forked from Mirrors/openclonk
fix and improve grabbing onto ropeladders
parent
fe0440f881
commit
9bb2de333a
|
@ -6,7 +6,7 @@
|
|||
|
||||
#include Library_Ladder
|
||||
|
||||
local master, index;
|
||||
local index;
|
||||
local angle;
|
||||
|
||||
public func SetAngle(int new_angle)
|
||||
|
@ -17,8 +17,10 @@ public func SetAngle(int new_angle)
|
|||
// Called from the ladder object to set a master and the segment index.
|
||||
public func SetMaster(object new_master, int new_index)
|
||||
{
|
||||
master = new_master;
|
||||
index = new_index;
|
||||
// First perform setting the master in the library function.
|
||||
_inherited(new_master, new_index, ...);
|
||||
index = new_index;
|
||||
return;
|
||||
}
|
||||
|
||||
// Returns whether the ladder can be climbed.
|
||||
|
|
|
@ -1,20 +1,16 @@
|
|||
/**
|
||||
Ladder Climbing
|
||||
Gives the ability to clonks climb on ladders.
|
||||
Gives the ability to clonks climb on ladders, to be included by the clonk.
|
||||
|
||||
@author Randrian
|
||||
*/
|
||||
|
||||
local jump_startcall;
|
||||
local no_ladder_counter;
|
||||
|
||||
public func GetTurnPhase() { return _inherited(...); }
|
||||
|
||||
public func Definition(proplist def)
|
||||
{
|
||||
// Only add action if included by clonk.
|
||||
if (!def.ActMap)
|
||||
return _inherited(def);
|
||||
// Add actions for climbing and overload jumping actions to search for ladders.
|
||||
def.ActMap = {
|
||||
Prototype = def.ActMap,
|
||||
Climb = {
|
||||
|
@ -30,24 +26,27 @@ public func Definition(proplist def)
|
|||
Jump = {
|
||||
Prototype = def.ActMap.Jump,
|
||||
StartCall = "StartSearchLadder",
|
||||
// save old phasecall of jump
|
||||
// Save the old phasecall of the jump.
|
||||
StartCallLadderOverloaded = def.ActMap.Jump.StartCall
|
||||
},
|
||||
WallJump = {
|
||||
Prototype = def.ActMap.WallJump,
|
||||
StartCall = "StartSearchLadder",
|
||||
// save old phasecall of jump
|
||||
// Save the old phasecall of the wall jump.
|
||||
StartCallLadderOverloaded = def.ActMap.WallJump.StartCall
|
||||
}
|
||||
};
|
||||
_inherited(def);
|
||||
return _inherited(def);
|
||||
}
|
||||
|
||||
public func StartScale()
|
||||
{
|
||||
// Should be overloaded, and add a climb animation here
|
||||
return _inherited(...);
|
||||
}
|
||||
public func GetTurnPhase() { return _inherited(...); }
|
||||
public func SetTurnType() { return _inherited(...); }
|
||||
public func SetHandAction() { return _inherited(...); }
|
||||
// Should be overloaded, and add a climb animation here
|
||||
public func StartScale() { return _inherited(...); }
|
||||
|
||||
|
||||
/*-- Ladder Searching --*/
|
||||
|
||||
public func StartSearchLadder()
|
||||
{
|
||||
|
@ -56,8 +55,9 @@ public func StartSearchLadder()
|
|||
Call(this.ActMap.Jump.StartCallLadderOverloaded);
|
||||
if (GetAction() == "WallJump" && this.ActMap.WallJump.StartCallLadderOverloaded)
|
||||
Call(this.ActMap.WallJump.StartCallLadderOverloaded);
|
||||
// Add an effect to search for ladders.
|
||||
if (!GetEffect("InSearchLadder", this))
|
||||
AddEffect("IntSearchLadder", this, 1, 5, this);
|
||||
AddEffect("IntSearchLadder", this, 1, 2, this);
|
||||
FxIntSearchLadderTimer();
|
||||
return;
|
||||
}
|
||||
|
@ -76,25 +76,19 @@ public func FxIntSearchLadderTimer(object target, proplist effect, int time)
|
|||
if (GetAction() != "Jump" && GetAction() != "WallJump")
|
||||
return FX_Execute_Kill;
|
||||
|
||||
// Don't search for ladders if the counter is non-zero.
|
||||
if (no_ladder_counter > 0)
|
||||
{
|
||||
no_ladder_counter--;
|
||||
return FX_OK;
|
||||
}
|
||||
|
||||
// Find a ladder.
|
||||
// Find a ladder which can be climbed.
|
||||
var ladder;
|
||||
for (ladder in FindObjects(Find_AtRect(-5, -10, 10, 8), Find_Func("IsLadder"), Find_NoContainer(), Find_Layer(GetObjectLayer())))
|
||||
{
|
||||
if (!ladder->~CanNotBeClimbed())
|
||||
{
|
||||
SetAction("Climb");
|
||||
ladder->~OnLadderGrab(this);
|
||||
PlayAnimation(GetLadderScaleAnimation(), CLONK_ANIM_SLOT_Movement, Anim_Y(0, GetAnimationLength(GetLadderScaleAnimation()), 0, 15), Anim_Linear(0, 0, 1000, 5, ANIM_Remove));
|
||||
AddEffect("IntClimbControl", this, 1, 1, this, nil, ladder);
|
||||
return FX_Execute_Kill;
|
||||
}
|
||||
// Don't climb ladders that are blocked.
|
||||
if (ladder->~CanNotBeClimbed() || IsBlockedLadder(ladder))
|
||||
continue;
|
||||
|
||||
SetAction("Climb");
|
||||
ladder->~OnLadderGrab(this);
|
||||
PlayAnimation(GetLadderScaleAnimation(), CLONK_ANIM_SLOT_Movement, Anim_Y(0, GetAnimationLength(GetLadderScaleAnimation()), 0, 15), Anim_Linear(0, 0, 1000, 5, ANIM_Remove));
|
||||
AddEffect("IntClimbControl", this, 1, 1, this, nil, ladder);
|
||||
return FX_Execute_Kill;
|
||||
}
|
||||
return FX_OK;
|
||||
}
|
||||
|
@ -103,123 +97,140 @@ public func FxIntSearchLadderStop(object target, proplist effect, reason, tmp)
|
|||
{
|
||||
if (tmp)
|
||||
return FX_OK;
|
||||
no_ladder_counter = 0;
|
||||
return FX_OK;
|
||||
}
|
||||
|
||||
public func FxIntClimbControlStart(object target, proplist effect, tmp, object ladder)
|
||||
|
||||
/*-- Ladder Block --*/
|
||||
|
||||
private func AddLadderBlock(object ladder, int duration)
|
||||
{
|
||||
AddEffect("IntBlockLadder", this, 100, duration, this, nil, ladder);
|
||||
return;
|
||||
}
|
||||
|
||||
private func IsBlockedLadder(object ladder)
|
||||
{
|
||||
var index = 0;
|
||||
var fx;
|
||||
while (fx = GetEffect("IntBlockLadder", this, index++))
|
||||
if (fx.ladder->IsSameLadder(ladder))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public func FxIntBlockLadderStart(object target, effect fx, int tmp, object to_ladder)
|
||||
{
|
||||
if (tmp)
|
||||
return FX_OK;
|
||||
fx.ladder = to_ladder;
|
||||
return FX_OK;
|
||||
}
|
||||
|
||||
public func FxIntBlockLadderTimer(object target, effect fx, int time)
|
||||
{
|
||||
return FX_Execute_Kill;
|
||||
}
|
||||
|
||||
|
||||
/*-- Ladder Control --*/
|
||||
|
||||
public func FxIntClimbControlStart(object target, effect fx, int tmp, object ladder)
|
||||
{
|
||||
if (tmp)
|
||||
return FX_OK;
|
||||
effect.ladder = ladder;
|
||||
fx.ladder = ladder;
|
||||
SetXDir(0);
|
||||
SetYDir(0);
|
||||
SetComDir(COMD_Stop);
|
||||
effect.odd = 0; // odd or even segment?
|
||||
// Start on an even segment.
|
||||
fx.odd = 0;
|
||||
// Correctly initalize the relative y-position of the clonk to the segment.
|
||||
var data = fx.ladder->GetLadderData();
|
||||
var sy = data[1], ey = data[3];
|
||||
var cy = GetY(1000);
|
||||
var posy = 0;
|
||||
if (ey - sy != 0)
|
||||
posy = 100 * (cy - sy) / (ey - sy);
|
||||
fx.pos = BoundBy(posy, 0, 100);
|
||||
// Set some stuff for the clonk.
|
||||
SetHandAction(1);
|
||||
SetTurnType(1);
|
||||
return FX_OK;
|
||||
}
|
||||
|
||||
public func SetTurnType() { return _inherited(...); }
|
||||
public func SetHandAction() { return _inherited(...); }
|
||||
|
||||
public func LadderStep(target, effect, fUp)
|
||||
public func LadderStep(object target, effect fx, int climb_direction)
|
||||
{
|
||||
if (fUp == 1)
|
||||
if (climb_direction != 1 && climb_direction != -1)
|
||||
return fx.ladder != nil;
|
||||
// Store old segment to forward to blocking.
|
||||
var old_ladder_segment = fx.ladder;
|
||||
// Increase position depending on direction and move to new segment if needed.
|
||||
fx.pos += 10 * climb_direction;
|
||||
if (fx.pos > 100)
|
||||
{
|
||||
effect.pos += 10;
|
||||
if (effect.pos > 100)
|
||||
fx.pos = 0;
|
||||
fx.ladder = fx.ladder->GetNextLadder();
|
||||
fx.odd = !fx.odd;
|
||||
}
|
||||
if (fx.pos < 0)
|
||||
{
|
||||
fx.pos = 100;
|
||||
fx.ladder = fx.ladder->GetPreviousLadder();
|
||||
fx.odd = !fx.odd;
|
||||
}
|
||||
// If no ladder has been found scale or jump off.
|
||||
if (fx.ladder == nil)
|
||||
{
|
||||
var contact = GetContact(-1);
|
||||
if (contact & CNAT_Left || contact & CNAT_Right)
|
||||
{
|
||||
effect.pos = 0;
|
||||
effect.ladder = effect.ladder->GetNextLadder();
|
||||
effect.odd = !effect.odd;
|
||||
SetAction("Scale");
|
||||
old_ladder_segment->~OnLadderReleased(this);
|
||||
return false;
|
||||
}
|
||||
if (effect.ladder == nil)
|
||||
AddLadderBlock(old_ladder_segment, 10);
|
||||
SetAction("Jump");
|
||||
// Increase speed if moving up.
|
||||
if (climb_direction == 1)
|
||||
{
|
||||
var contact = GetContact(-1);
|
||||
if (contact & CNAT_Left || contact & CNAT_Right)
|
||||
{
|
||||
SetAction("Scale");
|
||||
return false;
|
||||
}
|
||||
no_ladder_counter = 5;
|
||||
SetAction("Jump");
|
||||
SetXDir(-5+10*GetDir());
|
||||
SetXDir(-5 + 10 * GetDir());
|
||||
SetYDir(-5);
|
||||
return false;
|
||||
}
|
||||
old_ladder_segment->~OnLadderReleased(this);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
effect.pos -= 10;
|
||||
if(effect.pos < 0)
|
||||
{
|
||||
effect.pos = 100;
|
||||
effect.ladder = effect.ladder->GetPreviousLadder();
|
||||
effect.odd = !effect.odd;
|
||||
}
|
||||
if (effect.ladder == nil)
|
||||
{
|
||||
var contact = GetContact(-1);
|
||||
if (contact & CNAT_Left || contact & CNAT_Right)
|
||||
{
|
||||
SetAction("Scale");
|
||||
return false;
|
||||
}
|
||||
no_ladder_counter = 5;
|
||||
SetAction("Jump");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (effect.ladder == nil) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public func FxIntClimbControlTimer(object target, proplist effect, int time)
|
||||
public func FxIntClimbControlTimer(object target, effect fx, int time)
|
||||
{
|
||||
if (GetAction() != "Climb" || Contained())
|
||||
return FX_Execute_Kill;
|
||||
if (effect.ladder && effect.ladder->~CanNotBeClimbed(true))
|
||||
effect.ladder = nil;
|
||||
if (!effect.ladder)
|
||||
if (!fx.ladder || fx.ladder->~CanNotBeClimbed(true))
|
||||
{
|
||||
no_ladder_counter = 5;
|
||||
AddLadderBlock(fx.ladder, 5);
|
||||
SetAction("Jump");
|
||||
SetXDir(-5 + 10 * GetDir());
|
||||
SetYDir(-5);
|
||||
return FX_Execute_Kill;
|
||||
}
|
||||
|
||||
// Progress
|
||||
var step = 0;
|
||||
|
||||
// Progress movement in the controlled direction.
|
||||
var climb_direction = 0;
|
||||
if (GetComDir() == COMD_Down)
|
||||
step = -1;
|
||||
climb_direction = -1;
|
||||
if (GetComDir() == COMD_Up)
|
||||
step = 1;
|
||||
|
||||
if (step && !LadderStep(target, effect, step))
|
||||
{
|
||||
var contact = GetContact(-1);
|
||||
if (contact & CNAT_Left || contact & CNAT_Right)
|
||||
SetAction("Scale");
|
||||
else
|
||||
{
|
||||
no_ladder_counter = 5;
|
||||
SetAction("Jump");
|
||||
if (step == 1) // For Up add some speed
|
||||
{
|
||||
SetXDir(-5 + 10 * GetDir());
|
||||
SetYDir(-5);
|
||||
no_ladder_counter = 10;
|
||||
}
|
||||
}
|
||||
climb_direction = 1;
|
||||
// LadderStep advances the ladder segment or the ladder position.
|
||||
if (climb_direction && !LadderStep(target, fx, climb_direction))
|
||||
return FX_Execute_Kill;
|
||||
}
|
||||
var data = effect.ladder->GetLadderData();
|
||||
|
||||
// Move the clonk along the ladder according to the new pos/segment.
|
||||
var data = fx.ladder->GetLadderData();
|
||||
var startx = data[0], starty = data[1], endx = data[2], endy = data[3], angle = data[4];
|
||||
var x = startx + (endx-startx) * effect.pos / 100 + 5000 - 100 * GetTurnPhase();
|
||||
var y = starty + (endy-starty) * effect.pos / 100;
|
||||
var x = startx + (endx - startx) * fx.pos / 100 + 5000 - 100 * GetTurnPhase();
|
||||
var y = starty + (endy - starty) * fx.pos / 100;
|
||||
var lx = LadderToLandscapeCoordinates(x);
|
||||
var ly = LadderToLandscapeCoordinates(y);
|
||||
var old_x = GetX(), old_y = GetY();
|
||||
|
@ -229,6 +240,8 @@ public func FxIntClimbControlTimer(object target, proplist effect, int time)
|
|||
SetXDir(0);
|
||||
SetYDir(0);
|
||||
SetLadderRotation(-angle, x - GetX() * 1000, y - GetY() * 1000);
|
||||
|
||||
// Handle if the clonk gets stuck.
|
||||
if (Stuck())
|
||||
{
|
||||
var dir = -1;
|
||||
|
@ -237,40 +250,47 @@ public func FxIntClimbControlTimer(object target, proplist effect, int time)
|
|||
for (var i = 1; i <= 5; i++)
|
||||
{
|
||||
SetPosition(LadderToLandscapeCoordinates(x) + i * dir, LadderToLandscapeCoordinates(y));
|
||||
if (!Stuck()) break;
|
||||
if (!Stuck())
|
||||
break;
|
||||
}
|
||||
if (Stuck()) SetPosition(LadderToLandscapeCoordinates(x) + 5 * dir, LadderToLandscapeCoordinates(y));
|
||||
if (Stuck())
|
||||
SetPosition(LadderToLandscapeCoordinates(x) + 5 * dir, LadderToLandscapeCoordinates(y));
|
||||
}
|
||||
if (Stuck())
|
||||
{
|
||||
// Revert Position and step
|
||||
// Revert Position and step.
|
||||
SetPosition(old_x, old_y);
|
||||
if (step)
|
||||
LadderStep(target, effect, -step);
|
||||
// if we are to far left or right try to turn
|
||||
if (climb_direction)
|
||||
LadderStep(target, fx, -climb_direction);
|
||||
// If we are too far left or right try to turn.
|
||||
if (GetDir() == DIR_Left && LadderToLandscapeCoordinates(x) - 2 > GetX())
|
||||
{
|
||||
SetComDir(COMD_Right);
|
||||
SetDir(DIR_Right);
|
||||
}
|
||||
else if (GetDir() == DIR_Right && LadderToLandscapeCoordinates(x)+2 < GetX())
|
||||
else if (GetDir() == DIR_Right && LadderToLandscapeCoordinates(x) + 2 < GetX())
|
||||
{
|
||||
SetComDir(COMD_Left);
|
||||
SetDir(DIR_Left);
|
||||
}
|
||||
}
|
||||
else effect.ladder->~OnLadderClimb(this);
|
||||
// Make the animation synchron with movement TODO: this only makes the feet synchronous for the arms the animation has to be adapted
|
||||
else
|
||||
{
|
||||
fx.ladder->~OnLadderClimb(this);
|
||||
}
|
||||
// Make the animation synchron with movement.
|
||||
// TODO: this only makes the feet synchronous for the arms the animation has to be adapted.
|
||||
var animation = GetRootAnimation(5);
|
||||
if (animation != nil)
|
||||
{
|
||||
if (GetAnimationName(animation) != nil)
|
||||
{
|
||||
var length = GetAnimationLength(GetAnimationName(animation));
|
||||
var pos = effect.pos * length / 200 + length / 2 * effect.odd;
|
||||
var pos = fx.pos * length / 200 + length / 2 * fx.odd;
|
||||
SetAnimationPosition(animation, Anim_Const(pos));
|
||||
}
|
||||
}
|
||||
// Start walking or hangling if the clonk makes contact with the floor or ceiling.
|
||||
var contact = GetContact(-1);
|
||||
if (contact)
|
||||
{
|
||||
|
@ -287,14 +307,15 @@ public func FxIntClimbControlTimer(object target, proplist effect, int time)
|
|||
SetComDir(COMD_Left);
|
||||
SetDir(0);
|
||||
}
|
||||
return -1;
|
||||
return FX_Execute_Kill;
|
||||
}
|
||||
if (contact & CNAT_Bottom && GetComDir() == COMD_Down)
|
||||
{
|
||||
SetAction("Walk");
|
||||
return -1;
|
||||
return FX_Execute_Kill;
|
||||
}
|
||||
}
|
||||
return FX_OK;
|
||||
}
|
||||
|
||||
private func LadderToLandscapeCoordinates(int x)
|
||||
|
@ -303,15 +324,20 @@ private func LadderToLandscapeCoordinates(int x)
|
|||
return (x + 500) / 1000;
|
||||
}
|
||||
|
||||
public func FxIntClimbControlStop(target, effect)
|
||||
public func FxIntClimbControlStop(object target, effect fx, int reason, bool tmp)
|
||||
{
|
||||
if (tmp)
|
||||
return FX_OK;
|
||||
if (GetAction() == "Climb")
|
||||
SetAction("Walk");
|
||||
if (fx.ladder)
|
||||
fx.ladder->~OnLadderReleased(this);
|
||||
SetLadderRotation(0);
|
||||
SetHandAction(0);
|
||||
return FX_OK;
|
||||
}
|
||||
|
||||
public func FxIntClimbControlControl(object target, proplist effect, int ctrl, int x, int y, int strength, bool repeat, bool release)
|
||||
public func FxIntClimbControlControl(object target, effect fx, int ctrl, int x, int y, int strength, bool repeat, bool release)
|
||||
{
|
||||
// Only handle movement controls.
|
||||
if (ctrl != CON_Up && ctrl != CON_Down && ctrl != CON_Right && ctrl != CON_Left)
|
||||
|
@ -319,16 +345,24 @@ public func FxIntClimbControlControl(object target, proplist effect, int ctrl, i
|
|||
// Perform actions on key down and not on release.
|
||||
if (release)
|
||||
return false;
|
||||
|
||||
// Move up and down by setting com dir.
|
||||
if (ctrl == CON_Up)
|
||||
{
|
||||
SetComDir(COMD_Up);
|
||||
else if (ctrl == CON_Down)
|
||||
return true;
|
||||
}
|
||||
if (ctrl == CON_Down)
|
||||
{
|
||||
SetComDir(COMD_Down);
|
||||
return true;
|
||||
}
|
||||
|
||||
else if (ctrl == CON_Left)
|
||||
// Handle left and right controls.
|
||||
if (ctrl == CON_Left)
|
||||
{
|
||||
if (GetDir() == DIR_Left)
|
||||
{
|
||||
// Switch to the other side of the ladder.
|
||||
if (GetComDir() == COMD_Stop)
|
||||
{
|
||||
SetPosition(GetX() - 10, GetY());
|
||||
|
@ -343,17 +377,22 @@ public func FxIntClimbControlControl(object target, proplist effect, int ctrl, i
|
|||
}
|
||||
else
|
||||
{
|
||||
no_ladder_counter = 5;
|
||||
// Let go of the ladder and remove the effect.
|
||||
AddLadderBlock(fx.ladder, 5);
|
||||
if (GetComDir() == COMD_Up)
|
||||
this->ObjectCommand("Jump");
|
||||
else
|
||||
this->ObjectComLetGo(-10);
|
||||
RemoveEffect(nil, target, fx);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if (ctrl == CON_Right)
|
||||
|
||||
if (ctrl == CON_Right)
|
||||
{
|
||||
if (GetDir() == DIR_Right)
|
||||
{
|
||||
// Switch to the other side of the ladder.
|
||||
if (GetComDir() == COMD_Stop)
|
||||
{
|
||||
SetPosition(GetX() + 10, GetY());
|
||||
|
@ -368,12 +407,15 @@ public func FxIntClimbControlControl(object target, proplist effect, int ctrl, i
|
|||
}
|
||||
else
|
||||
{
|
||||
no_ladder_counter = 5;
|
||||
// Let go of the ladder and remove the effect.
|
||||
AddLadderBlock(fx.ladder, 5);
|
||||
if (GetComDir() == COMD_Up)
|
||||
this->ObjectCommand("Jump");
|
||||
else
|
||||
this->ObjectComLetGo(10);
|
||||
RemoveEffect(nil, target, fx);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,24 +1,43 @@
|
|||
/**
|
||||
Ladder Control
|
||||
Containes the basic functionality for ladders.
|
||||
Containes the basic functionality for ladder segments.
|
||||
|
||||
@author Randrian
|
||||
*/
|
||||
|
||||
local master;
|
||||
local next_segment;
|
||||
local prev_segment;
|
||||
|
||||
public func IsLadder() { return true; }
|
||||
|
||||
public func SetMaster(object new_master)
|
||||
{
|
||||
master = new_master;
|
||||
return;
|
||||
}
|
||||
|
||||
public func GetMaster()
|
||||
{
|
||||
return master;
|
||||
}
|
||||
|
||||
// Returns whether this segment and the other one are from the same ladder.
|
||||
public func IsSameLadder(object other_segment)
|
||||
{
|
||||
return GetMaster() == other_segment->GetMaster();
|
||||
}
|
||||
|
||||
// Returns the segment (start x, start y, end x, end y, angle) on which the clonk can climb.
|
||||
// The coordinate value must be specified with a precision of a 1000.
|
||||
public func GetLadderData()
|
||||
{
|
||||
// Normally (if not overloaded) interpret the first vertex as start and the second as end.
|
||||
return [
|
||||
GetX() + GetVertex(0, 0),
|
||||
GetY() + GetVertex(0, 1),
|
||||
GetX() + GetVertex(1, 0),
|
||||
GetY() + GetVertex(1, 1),
|
||||
GetX(1000) + 1000 * GetVertex(0, 0),
|
||||
GetY(1000) + 1000 * GetVertex(0, 1),
|
||||
GetX(1000) + 1000 * GetVertex(1, 0),
|
||||
GetY(1000) + 1000 * GetVertex(1, 1),
|
||||
0
|
||||
];
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue