openclonk/planet/Objects.ocd/Libraries.ocd/LadderClimb.ocd/Script.c

393 lines
8.9 KiB
C
Raw Normal View History

2015-12-08 10:18:47 +00:00
/**
Ladder Climbing
Gives the ability to clonks climb on ladders.
2015-12-08 10:18:47 +00:00
@author Randrian
*/
local jump_startcall;
local no_ladder_counter;
2015-12-08 10:18:47 +00:00
public func GetTurnPhase() { return _inherited(...); }
2015-12-08 10:18:47 +00:00
public func Definition(proplist def)
{
// Only add action if included by clonk.
if (!def.ActMap)
return _inherited(def);
def.ActMap = {
Prototype = def.ActMap,
Climb = {
Prototype = Action,
Name = "Climb",
Directions = 2,
Length = 0,
Delay = 0,
Wdt = 8,
Hgt = 20,
Procedure = DFA_FLOAT,
},
Jump = {
Prototype = def.ActMap.Jump,
StartCall = "StartSearchLadder",
// save old phasecall of jump
StartCallLadderOverloaded = def.ActMap.Jump.StartCall
2015-12-08 10:18:47 +00:00
},
WallJump = {
Prototype = def.ActMap.WallJump,
StartCall = "StartSearchLadder",
// save old phasecall of jump
StartCallLadderOverloaded = def.ActMap.WallJump.StartCall
}
};
_inherited(def);
}
2015-12-08 10:18:47 +00:00
public func StartScale()
{
// Should be overloaded, and add a climb animation here
return _inherited(...);
}
2015-12-08 10:18:47 +00:00
public func StartSearchLadder()
{
2015-12-08 10:18:47 +00:00
// Call the overwriten old phase call.
if (GetAction() == "Jump" && this.ActMap.Jump.StartCallLadderOverloaded)
Call(this.ActMap.Jump.StartCallLadderOverloaded);
if (GetAction() == "WallJump" && this.ActMap.WallJump.StartCallLadderOverloaded)
Call(this.ActMap.WallJump.StartCallLadderOverloaded);
if (!GetEffect("InSearchLadder", this))
AddEffect("IntSearchLadder", this, 1, 5, this);
FxIntSearchLadderTimer();
2015-12-08 10:18:47 +00:00
return;
}
2015-12-08 10:18:47 +00:00
public func GetLadderScaleAnimation()
{
var animation = _inherited(...);
2015-12-08 10:18:47 +00:00
if (animation)
return animation;
return "Scale";
}
2015-12-08 10:18:47 +00:00
public func FxIntSearchLadderTimer(object target, proplist effect, int time)
{
2015-12-08 10:18:47 +00:00
if (GetAction() != "Jump" && GetAction() != "WallJump")
return FX_Execute_Kill;
var ladder;
if (!no_ladder_counter)
{
2015-12-08 10:18:47 +00:00
for (ladder in FindObjects(Find_AtRect(-5,-5,10,10), Find_Func("IsLadder"), Find_NoContainer(), Find_Layer(GetObjectLayer())))
{
2015-12-08 10:18:47 +00:00
if (ladder->~CanNotBeClimbed())
continue;
else
break;
}
2015-12-08 10:18:47 +00:00
if (ladder && ladder->~CanNotBeClimbed())
ladder = nil;
}
else
no_ladder_counter--;
// Found ladder?
if (ladder != nil)
{
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));
2015-12-08 10:18:47 +00:00
AddEffect("IntClimbControl", this, 1, 1, this, nil, ladder);
return FX_Execute_Kill;
}
}
2015-12-08 10:18:47 +00:00
public func FxIntSearchLadderStop(object target, proplist effect, reason, tmp)
{
2015-12-08 10:18:47 +00:00
if (tmp)
return FX_OK;
no_ladder_counter = 0;
2015-12-08 10:18:47 +00:00
return FX_OK;
}
2015-12-08 10:18:47 +00:00
public func FxIntClimbControlStart(object target, proplist effect, tmp, object ladder)
{
2015-12-08 10:18:47 +00:00
if (tmp)
return FX_OK;
effect.ladder = ladder;
SetXDir(0);
SetYDir(0);
SetComDir(COMD_Stop);
effect.odd = 0; // odd or even segment?
SetHandAction(1);
SetTurnType(1);
2015-12-08 10:18:47 +00:00
return FX_OK;
}
2015-12-08 10:18:47 +00:00
public func SetTurnType() { return _inherited(...); }
public func SetHandAction() { return _inherited(...); }
2015-12-08 10:18:47 +00:00
public func LadderStep(target, effect, fUp)
{
if (fUp == 1)
{
effect.pos += 10;
if (effect.pos > 100)
{
effect.pos = 0;
effect.ladder = effect.ladder->GetNextLadder();
effect.odd = !effect.odd;
}
if (effect.ladder == nil)
{
var contact = GetContact(-1);
if (contact & CNAT_Left || contact & CNAT_Right)
{
SetAction("Scale");
2015-12-08 10:18:47 +00:00
return false;
}
no_ladder_counter = 5;
SetAction("Jump");
SetXDir(-5+10*GetDir());
SetYDir(-5);
2015-12-08 10:18:47 +00:00
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");
2015-12-08 10:18:47 +00:00
return false;
}
no_ladder_counter = 5;
SetAction("Jump");
2015-12-08 10:18:47 +00:00
return false;
}
}
if (effect.ladder == nil) return false;
return true;
}
2015-12-08 10:18:47 +00:00
public func FxIntClimbControlTimer(object target, proplist effect, int time)
{
2015-12-08 10:18:47 +00:00
if (GetAction() != "Climb" || Contained())
return FX_Execute_Kill;
if (effect.ladder && effect.ladder->~CanNotBeClimbed(true))
2015-12-08 10:18:47 +00:00
effect.ladder = nil;
if (!effect.ladder)
2010-07-08 21:31:30 +00:00
{
no_ladder_counter = 5;
2010-07-08 21:31:30 +00:00
SetAction("Jump");
2015-12-08 10:18:47 +00:00
SetXDir(-5 + 10 * GetDir());
2010-07-08 21:31:30 +00:00
SetYDir(-5);
2015-12-08 10:18:47 +00:00
return FX_Execute_Kill;
2010-07-08 21:31:30 +00:00
}
// Progress
var step = 0;
2015-12-08 10:18:47 +00:00
if (GetComDir() == COMD_Down)
step = -1;
if (GetComDir() == COMD_Up)
step = 1;
if (step && !LadderStep(target, effect, step))
{
var contact = GetContact(-1);
if (contact & CNAT_Left || contact & CNAT_Right)
2015-12-08 10:18:47 +00:00
SetAction("Scale");
else
{
no_ladder_counter = 5;
SetAction("Jump");
if (step == 1) // For Up add some speed
{
2015-12-08 10:18:47 +00:00
SetXDir(-5 + 10 * GetDir());
SetYDir(-5);
2010-03-12 14:28:27 +00:00
no_ladder_counter = 10;
}
}
2015-12-08 10:18:47 +00:00
return FX_Execute_Kill;
}
var data = effect.ladder->GetLadderData();
var startx = data[0], starty = data[1], endx = data[2], endy = data[3], angle = data[4];
2015-12-08 10:18:47 +00:00
var x = startx + (endx-startx) * effect.pos / 100 + 5000 - 100 * GetTurnPhase();
var y = starty + (endy-starty) * effect.pos / 100;
var lx = LadderToLandscapeCoordinates(x);
var ly = LadderToLandscapeCoordinates(y);
var old_x = GetX(), old_y = GetY();
2015-12-08 10:18:47 +00:00
if (Abs(old_x - lx) + Abs(old_y - ly) > 10 && time > 1)
return FX_Execute_Kill;
SetPosition(lx, ly);
2015-12-08 10:18:47 +00:00
SetXDir(0);
SetYDir(0);
SetLadderRotation(-angle, x - GetX() * 1000, y - GetY() * 1000);
if (Stuck())
2010-03-12 14:28:27 +00:00
{
var dir = -1;
2015-12-08 10:18:47 +00:00
if (GetDir() == 0)
dir = 1;
for (var i = 1; i <= 5; i++)
2010-03-12 14:28:27 +00:00
{
2015-12-08 10:18:47 +00:00
SetPosition(LadderToLandscapeCoordinates(x) + i * dir, LadderToLandscapeCoordinates(y));
if (!Stuck()) break;
2010-03-12 14:28:27 +00:00
}
2015-12-08 10:18:47 +00:00
if (Stuck()) SetPosition(LadderToLandscapeCoordinates(x) + 5 * dir, LadderToLandscapeCoordinates(y));
2010-03-12 14:28:27 +00:00
}
if (Stuck())
{
// Revert Position and step
SetPosition(old_x, old_y);
2015-12-08 10:18:47 +00:00
if (step)
LadderStep(target, effect, -step);
// if we are to far left or right try to turn
2015-12-08 10:18:47 +00:00
if (GetDir() == 0 && LadderToLandscapeCoordinates(x) - 2 > GetX())
{
SetComDir(COMD_Right);
SetDir(1);
}
else if (GetDir() == 1 && LadderToLandscapeCoordinates(x)+2 < GetX())
{
SetComDir(COMD_Left);
SetDir(0);
}
}
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
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;
//pos = BoundBy(pos, 1, length-1);
SetAnimationPosition(animation, Anim_Const(pos));
}
}
var contact = GetContact(-1);
if (contact)
{
if (contact & CNAT_Top && GetComDir() == COMD_Up)
{
SetAction("Hangle");
if (GetDir() == 0)
{
SetComDir(COMD_Right);
SetDir(1);
}
else
{
SetComDir(COMD_Left);
SetDir(0);
}
return -1;
}
if (contact & CNAT_Bottom && GetComDir() == COMD_Down)
{
SetAction("Walk");
return -1;
}
}
}
2015-12-08 10:18:47 +00:00
private func LadderToLandscapeCoordinates(int x)
{
2015-12-08 10:18:47 +00:00
// Round to the next thousand.
return (x + 500) / 1000;
}
2015-12-08 10:18:47 +00:00
public func FxIntClimbControlStop(target, effect)
{
2015-12-08 10:18:47 +00:00
if (GetAction() == "Climb")
SetAction("Walk");
SetLadderRotation(0);
SetHandAction(0);
}
2015-12-08 10:18:47 +00:00
public func FxIntClimbControlControl(object target, proplist effect, int ctrl, int x, int y, int strength, bool repeat, bool release)
{
2015-12-08 10:18:47 +00:00
//Log("LIBLADDER: Control effect ctrl = %d, dir = %d", ctrl, GetDir());
// Only handle movement controls.
if (ctrl != CON_Up && ctrl != CON_Down && ctrl != CON_Right && ctrl != CON_Left)
return false;
// Perform actions on key down and not on release.
if (release)
return false;
if (ctrl == CON_Up)
SetComDir(COMD_Up);
else if (ctrl == CON_Down)
SetComDir(COMD_Down);
else if (ctrl == CON_Left)
{
2015-12-08 10:18:47 +00:00
if (GetDir() == DIR_Left)
{
if (GetComDir() == COMD_Stop)
{
2015-12-08 10:18:47 +00:00
SetPosition(GetX() - 10, GetY());
if (!Stuck())
{
SetComDir(COMD_Right);
2015-12-08 10:18:47 +00:00
SetDir(DIR_Right);
}
2015-12-08 10:18:47 +00:00
SetPosition(GetX() + 10, GetY());
}
SetComDir(COMD_Stop);
}
else
{
no_ladder_counter = 5;
2015-12-08 16:22:13 +00:00
if (GetComDir() == COMD_Up)
this->ObjectCommand("Jump");
else
this->ObjectComLetGo(-10);
}
}
else if (ctrl == CON_Right)
{
2015-12-08 10:18:47 +00:00
if (GetDir() == DIR_Right)
{
if (GetComDir() == COMD_Stop)
{
2015-12-08 10:18:47 +00:00
SetPosition(GetX() + 10, GetY());
if (!Stuck())
{
SetComDir(COMD_Left);
2015-12-08 10:18:47 +00:00
SetDir(DIR_Left);
}
2015-12-08 10:18:47 +00:00
SetPosition(GetX() - 10, GetY());
}
SetComDir(COMD_Stop);
}
else
{
no_ladder_counter = 5;
2015-12-08 16:22:13 +00:00
if (GetComDir() == COMD_Up)
this->ObjectCommand("Jump");
else
this->ObjectComLetGo(10);
}
}
2015-12-08 10:18:47 +00:00
return true;
}
2015-12-08 10:18:47 +00:00
public func SetLadderRotation (int r, int xoff, int yoff)
{
SetMeshTransformation(Trans_Mul(Trans_Translate(0, -10000), Trans_Rotate(-r, 0, 0, 1), Trans_Translate(xoff, 10000 + yoff)), 5);
return;
}
2010-10-15 16:40:00 +00:00
2015-12-08 10:18:47 +00:00
// Defined to prevent an error, because SetMeshTransformation is overloaded by the clonk.
2010-10-15 16:40:00 +00:00
func SetMeshTransformation() { return _inherited(...); }