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

366 lines
8.1 KiB
C
Raw Normal View History

/*--
Ladder climbing
Authors: Randrian
Gives the ability to climb on ladders
--*/
local jump_startcall;
local no_ladder_counter;
func GetTurnPhase() { return _inherited(...); }
func Definition(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
}
};
_inherited(def);
}
func StartScale()
{
// Should be overloaded, and add a climb animation here
return _inherited(...);
}
func StartSearchLadder()
{
// call overwriten old phase call
if (GetProperty("StartCallLadderOverloaded", GetProperty("Jump", GetProperty("ActMap"))))
Call(GetProperty("StartCallLadderOverloaded", GetProperty("Jump", GetProperty("ActMap"))));
if (!GetEffect("InSearchLadder", this))
{
AddEffect("IntSearchLadder", this, 1, 5, this);
}
FxIntSearchLadderTimer();
}
func GetLadderScaleAnimation()
{
var animation = _inherited(...);
if(animation) return animation;
return "Scale";
}
func FxIntSearchLadderTimer(target, effect, time)
{
if (GetAction() != "Jump") return -1;
var ladder;
if (!no_ladder_counter)
{
2010-09-20 22:53:16 +00:00
for(ladder in FindObjects(Find_AtRect(-5,-5,10,10), Find_Func("IsLadder"),
Find_NoContainer(), Find_Layer(GetObjectLayer())))
{
if(ladder->~CanNotBeClimbed()) continue;
else break;
}
if(ladder && ladder->~CanNotBeClimbed()) ladder = nil;
}
else
no_ladder_counter--;
// Found ladder?
if (ladder != nil)
{
SetAction("Climb");
ladder->~OnLadderGrab(this);
PlayAnimation(GetLadderScaleAnimation(), 5, Anim_Y(0, GetAnimationLength(GetLadderScaleAnimation()), 0, 15), Anim_Linear(0, 0, 1000, 5, ANIM_Remove));
AddEffect("IntClimbControl", this, 1, 1, this, 0, ladder);
return -1;
}
}
func FxIntSearchLadderStop(target, effect, reason, tmp)
{
if (tmp) return;
no_ladder_counter = 0;
}
func FxIntClimbControlStart(target, effect, tmp, ladder)
{
if (tmp) return;
effect.var0 = ladder;
SetXDir(0);
SetYDir(0);
SetComDir(COMD_Stop);
effect.var2 = 0; // odd or even segment?
SetHandAction(1);
SetTurnType(1);
}
func SetTurnType() { return _inherited(...); }
func SetHandAction() { return _inherited(...); }
func LadderStep(target, effect, fUp)
{
if (fUp == 1)
{
effect.var1 += 10;
if (effect.var1 > 100)
{
effect.var1 = 0;
effect.var0 = effect.var0->GetNextLadder();
effect.var2 = !effect.var2;
}
if (effect.var0 == nil)
{
var contact = GetContact(-1);
if (contact & CNAT_Left || contact & CNAT_Right)
{
SetAction("Scale");
return 0;
}
no_ladder_counter = 5;
SetAction("Jump");
SetXDir(-5+10*GetDir());
SetYDir(-5);
return 0;
}
}
else
{
effect.var1 -= 10;
if(effect.var1 < 0)
{
effect.var1 = 100;
effect.var0 = effect.var0->GetPreviousLadder();
effect.var2 = !effect.var2;
}
if (effect.var0 == nil)
{
var contact = GetContact(-1);
if (contact & CNAT_Left || contact & CNAT_Right)
{
SetAction("Scale");
return 0;
}
no_ladder_counter = 5;
SetAction("Jump");
return 0;
}
}
if (effect.var0 == nil) return 0;
return true;
}
func FxIntClimbControlTimer(target, effect, time)
{
if (GetAction() != "Climb" || Contained()) return -1;
if(effect.var0 && effect.var0->CanNotBeClimbed(1)) effect.var0 = 0;
if(!effect.var0)
2010-07-08 21:31:30 +00:00
{
no_ladder_counter = 5;
2010-07-08 21:31:30 +00:00
SetAction("Jump");
SetXDir(-5+10*GetDir());
SetYDir(-5);
return -1;
}
// Progress
var step = 0;
if (GetComDir() == COMD_Down) step = -1;
if (GetComDir() == COMD_Up) step = 1;
if (step && LadderStep(target, effect, step) == 0)
{
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);
2010-03-12 14:28:27 +00:00
no_ladder_counter = 10;
}
}
return -1;
}
var data = effect.var0->GetLadderData();
var startx = data[0], starty = data[1], endx = data[2], endy = data[3], angle = data[4];
var x = startx + (endx-startx)*effect.var1/100+5000-100*GetTurnPhase();
var y = starty + (endy-starty)*effect.var1/100;
var lx = LadderToLandscapeCoordinates(x);
var ly = LadderToLandscapeCoordinates(y);
var old_x = GetX(), old_y = GetY();
if(Abs(old_x-lx)+Abs(old_y-ly) > 10 && time > 1)
return -1;
SetPosition(lx, ly);
SetXDir(0); SetYDir(0);
SetLadderRotation(-angle, x-GetX()*1000, y-GetY()*1000);//effect.var2);
if (Stuck())
2010-03-12 14:28:27 +00:00
{
var dir = -1;
if (GetDir() == 0) dir = 1;
for (var i = 1; i <= 5; i++)
2010-03-12 14:28:27 +00:00
{
SetPosition(LadderToLandscapeCoordinates(x)+i*dir, LadderToLandscapeCoordinates(y));
if (!Stuck()) break;
2010-03-12 14:28:27 +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);
if (step) LadderStep(target, effect, -step);
// if we are to far left or right try to turn
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.var0->~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.var1*length/200+length/2*effect.var2;
//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;
}
/* if(contact & CNAT_Left || contact & CNAT_Right)
{
SetAction("Scale");
return -1;
}*/
}
}
func LadderToLandscapeCoordinates(int x)
{
return (x+500)/1000; // round to the next thousand
}
func FxIntClimbControlStop(target, effect)
{
if(GetAction() == "Climb") SetAction("Walk");
SetLadderRotation(0);
SetHandAction(0);
}
func FxIntClimbControlControl(target, number, ctrl, x,y,strength, repeat, release)
{
if (ctrl != CON_Up && ctrl != CON_Down && ctrl != CON_Right && ctrl != CON_Left) return;
if (release == 1) return;
if (ctrl == CON_Up) SetComDir(COMD_Up);
else if (ctrl == CON_Down) SetComDir(COMD_Down);
else if (ctrl == CON_Left)
{
if (GetDir() == 0)
{
if (GetComDir() == COMD_Stop)
{
SetPosition(GetX()-10, GetY());
if (!Stuck())
{
SetComDir(COMD_Right);
SetDir(1);
}
SetPosition(GetX()+10, GetY());
}
SetComDir(COMD_Stop);
}
else
{
no_ladder_counter = 5;
SetAction("Jump");
SetXDir(-15);
}
}
else if (ctrl == CON_Right)
{
if (GetDir() == 1)
{
if (GetComDir() == COMD_Stop)
{
SetPosition(GetX()+10, GetY());
if (!Stuck())
{
SetComDir(COMD_Left);
SetDir(0);
}
SetPosition(GetX()-10, GetY());
}
SetComDir(COMD_Stop);
}
else
{
no_ladder_counter = 5;
SetAction("Jump");
SetXDir(+15);
}
}
return 1;
}
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)), 1);
// SetProperty("MeshTransformation", Trans_Mul(Trans_Translate(0, -10000), Trans_Rotate(-r,0,0,1), Trans_Translate(xoff, 10000+yoff)));
return;
// var fsin=Sin(r, 1000), fcos=Cos(r, 1000);
// // set matrix values
// SetObjDrawTransform (
// +fcos, +fsin, xoff, //(1000-fcos)*xoff - fsin*yoff,
// -fsin, +fcos, yoff, //(1000-fcos)*yoff + fsin*xoff,
// );
}
2010-10-15 16:40:00 +00:00
// Defined to prevent an error.
func SetMeshTransformation() { return _inherited(...); }