forked from Mirrors/openclonk
Tweak the "corner scale" behaviour
Instead of teleporting from sticking with the left/rightmost vertex to the want to standing on the lowest one at the same position, the Clonk can now climb using the lowest vertex alone. That means the teleport only needs to cover only one pixel each in x and y direction to go from sticking to the side of the landscape pixel to sticking on top of the same pixel. Also remove some unnecessary x/ydir resets and make comdir in the direction of the wall the Clonk is scaling keep the up/down direction instead of only going up.floating-point
parent
e68f83f02b
commit
944ca60910
|
@ -541,20 +541,11 @@ func StopScale()
|
|||
if(GetAction() != "Scale") RemoveEffect("IntScale", this);
|
||||
}
|
||||
|
||||
func CheckPosition(int off_x, int off_y)
|
||||
{
|
||||
var free = 1;
|
||||
SetPosition(GetX()+off_x, GetY()+off_y);
|
||||
if(Stuck()) free = 0;
|
||||
SetPosition(GetX()-off_x, GetY()-off_y);
|
||||
return free;
|
||||
}
|
||||
|
||||
func CheckScaleTop()
|
||||
{
|
||||
// Test whether the clonk has reached a top corner
|
||||
if(GBackSolid(-8+16*GetDir(),-8)) return false;
|
||||
if(!CheckPosition(-7*(-1+2*GetDir()),-17)) return false;
|
||||
// That is, the leg vertices are the only ones attached to the wall
|
||||
if(GBackSolid(-3+6*GetDir(),-3) || GBackSolid(-5+10*GetDir(),2)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -573,24 +564,20 @@ func FxIntScaleTimer(target, number, time)
|
|||
{
|
||||
// If the animation is not already set
|
||||
var dist = 0;
|
||||
while(!GBackSolid(-8+16*GetDir(),dist-8) && dist < 10) dist++;
|
||||
while(!(GBackSolid(-3+6*GetDir(),dist-3) || GBackSolid(-5+10*GetDir(),dist+2)) && dist < 8) dist++;
|
||||
dist *= 100;
|
||||
dist += GetY(100)-GetY()*100;
|
||||
// add the fractional part of the position (dist counts in the opposite direction of y)
|
||||
dist -= GetY(100)-GetY()*100;
|
||||
if(number.animation_mode != 1)
|
||||
{
|
||||
number.animation_id = PlayAnimation("ScaleTop", 5, Anim_Const(GetAnimationLength("ScaleTop")*dist/1000), Anim_Linear(0, 0, 1000, 5, ANIM_Remove));
|
||||
number.animation_id = PlayAnimation("ScaleTop", 5, Anim_Const(GetAnimationLength("ScaleTop")*dist/800), Anim_Linear(0, 0, 1000, 5, ANIM_Remove));
|
||||
number.animation_mode = 1;
|
||||
}
|
||||
this.dist = dist;
|
||||
SetAnimationPosition(number.animation_id, Anim_Const(GetAnimationLength("ScaleTop")*dist/1000));
|
||||
SetAnimationPosition(number.animation_id, Anim_Const(GetAnimationLength("ScaleTop")*dist/800));
|
||||
// The animation's graphics has to be shifet a bit to adjust to the clonk movement
|
||||
var pos = GetAnimationPosition(number.animation_id);
|
||||
//var percent = pos*1000/GetAnimationLength("ScaleTop");
|
||||
var offset_list = [[0,0], [0,-1], [-1,-2], [-2,-3], [-2,-5], [-2,-7], [-4,-8], [-6,-10], [-7,-9], [-8,-8]];
|
||||
var offset = offset_list[dist/100-1];
|
||||
var rot = 0;
|
||||
if(dist/100-1 > 5) rot = 5*dist/100-25;
|
||||
SetScaleRotation(0, -offset[0]*(-1+2*GetDir())*1000, offset[1]*1000, -rot*(-1+2*GetDir()), 0, 1);
|
||||
SetScaleRotation(0, 0, 0, 0, 0, 1);
|
||||
}
|
||||
else if(!GBackSolid(-10+20*GetDir(), 8))
|
||||
{
|
||||
|
@ -1367,4 +1354,4 @@ func StartEat()
|
|||
PlayAnimation("Eat", 10, Anim_Linear(0,0, GetAnimationLength("Eat"), 45, ANIM_Remove), Anim_Linear(0, 0, 1000, 5, ANIM_Remove));
|
||||
// Update carried items
|
||||
UpdateAttach();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,11 +5,11 @@ Category=C4D_Living
|
|||
Width=8
|
||||
Height=20
|
||||
Offset=-4,-10
|
||||
Vertices=7
|
||||
VertexX=0,0,0,-2,2,-4,4
|
||||
VertexY=2,-7,9,-3,-3,2,2
|
||||
VertexCNAT=0,4,8,1,2,1,2
|
||||
VertexFriction=300,300,100,300,300,300,300
|
||||
Vertices=9
|
||||
VertexX= 0, 0, 0, -2, 2, -4, 4, -2, 2
|
||||
VertexY= 2, -7, 9, -3, -3, 2, 2, 6, 6
|
||||
VertexCNAT= 0, 4, 11, 1, 2, 1, 2, 1, 2
|
||||
VertexFriction=300,300,100,300,300,300,300,300,300
|
||||
Value=25
|
||||
Mass=50
|
||||
Collection=-8,-10,16,27
|
||||
|
|
|
@ -317,37 +317,46 @@ void C4Object::DoMovement()
|
|||
// Move to target
|
||||
do
|
||||
{
|
||||
bool at_xovr = false, at_yovr = false;
|
||||
// Set next step target
|
||||
int step_x = 0, step_y = 0;
|
||||
if (Abs<C4Real>(fix_x - ctcox) > C4REAL10(5))
|
||||
step_x = Sign<C4Real>(new_x - fix_x);
|
||||
if (Abs<C4Real>(fix_y - ctcoy) > C4REAL10(5))
|
||||
step_y = Sign<C4Real>(new_y - fix_y);
|
||||
int32_t ctx = GetX() + step_x; int32_t cty = GetY() + step_y;
|
||||
if (ctcox != GetX())
|
||||
step_x = Sign(ctcox - GetX());
|
||||
else if (ctcoy != GetY())
|
||||
step_y = Sign(ctcoy - GetY());
|
||||
int32_t ctx = GetX() + step_x;
|
||||
int32_t cty = GetY() + step_y;
|
||||
// Attachment check
|
||||
if (!Shape.Attach(ctx,cty,Action.t_attach))
|
||||
fNoAttach=1;
|
||||
else
|
||||
{
|
||||
// Attachment change to ctx/cty overrides ctco target
|
||||
if (cty != GetY() + step_y) at_yovr = true;
|
||||
if (ctx != GetX() + step_x) at_xovr = true;
|
||||
if (ctx != GetX() + step_x)
|
||||
{
|
||||
ctcox = ctx; xdir = Fix0; new_x = itofix(ctx);
|
||||
}
|
||||
if (cty != GetY() + step_y)
|
||||
{
|
||||
ctcoy = cty; ydir = Fix0; new_y = itofix(cty);
|
||||
}
|
||||
}
|
||||
// Contact check & evaluation
|
||||
if ((iContact=ContactCheck(ctx,cty)))
|
||||
{
|
||||
fAnyContact=true; iContacts |= t_contact;
|
||||
// Abort movement
|
||||
ctcox=GetX(); new_x = fix_x;
|
||||
ctcoy=GetY(); new_y = fix_y;
|
||||
if (ctx != GetX())
|
||||
{
|
||||
ctx = ctcox = GetX(); new_x = fix_x;
|
||||
}
|
||||
if (cty != GetY())
|
||||
{
|
||||
cty = ctcoy = GetY(); new_y = fix_y;
|
||||
}
|
||||
}
|
||||
else // Continue free movement
|
||||
DoMotion(ctx-GetX(),cty-GetY());
|
||||
if (at_xovr) { ctcox=GetX(); xdir=Fix0; new_x = fix_x; }
|
||||
if (at_yovr) { ctcoy=GetY(); ydir=Fix0; new_y = fix_y; }
|
||||
DoMotion(ctx - GetX(), cty - GetY());
|
||||
}
|
||||
while (Abs<C4Real>(fix_x - ctcox) > C4REAL10(5) || Abs<C4Real>(fix_y - ctcoy) > C4REAL10(5));
|
||||
while (ctcox != GetX() || ctcoy != GetY());
|
||||
}
|
||||
|
||||
if(fix_x != new_x || fix_y != new_y)
|
||||
|
|
|
@ -3086,14 +3086,9 @@ void C4Object::NoAttachAction()
|
|||
}
|
||||
}
|
||||
|
||||
bool ContactVtxCNAT(C4Object *cobj, BYTE cnat_dir);
|
||||
|
||||
void C4Object::ContactAction()
|
||||
{
|
||||
// Take certain action on contact. Evaluate t_contact-CNAT and Procedure.
|
||||
C4Real last_xdir;
|
||||
|
||||
int32_t iDir;
|
||||
|
||||
// Determine Procedure
|
||||
C4PropList* pActionDef = GetAction();
|
||||
|
@ -3112,25 +3107,17 @@ void C4Object::ContactAction()
|
|||
if (ObjectActionFlat(this,Action.Dir)) return;
|
||||
if (OCF & OCF_HitSpeed3)
|
||||
if (ObjectActionKneel(this)) return;
|
||||
// Walk, but keep horizontal momentum (momentum is reset
|
||||
// by ObjectActionWalk) to avoid walk-jump-flipflop on
|
||||
// sideways corner hit if initial walk acceleration is
|
||||
// not enough to reach the next pixel for attachment.
|
||||
// Urks, all those special cases...
|
||||
last_xdir=xdir;
|
||||
ObjectActionWalk(this);
|
||||
xdir=last_xdir;
|
||||
ydir = 0;
|
||||
return;
|
||||
case DFA_SCALE:
|
||||
// Scale up: try corner scale
|
||||
if (!ComDirLike(Action.ComDir, COMD_Down))
|
||||
// Scale down: stand
|
||||
if (ComDirLike(Action.ComDir, COMD_Down))
|
||||
{
|
||||
if (ObjectActionCornerScale(this)) return;
|
||||
ObjectActionStand(this);
|
||||
return;
|
||||
}
|
||||
// Any other: Stand
|
||||
ObjectActionStand(this);
|
||||
return;
|
||||
break;
|
||||
case DFA_DIG:
|
||||
// no special action
|
||||
break;
|
||||
|
@ -3138,7 +3125,7 @@ void C4Object::ContactAction()
|
|||
// Try corner scale out
|
||||
if (!GBackLiquid(GetX(), GetY() - 1))
|
||||
if (ObjectActionCornerScale(this)) return;
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
//------------------------------- Hit Ceiling -----------------------------------------
|
||||
|
@ -3152,9 +3139,11 @@ void C4Object::ContactAction()
|
|||
// Scale: Try hangle, else stop if going upward
|
||||
if (ComDirLike(Action.ComDir, COMD_Up))
|
||||
{
|
||||
iDir=DIR_Left;
|
||||
if (Action.Dir==DIR_Left) { iDir=DIR_Right; }
|
||||
if (ObjectActionHangle(this,iDir)) return;
|
||||
if (ObjectActionHangle(this))
|
||||
{
|
||||
SetDir(Action.Dir == DIR_Left ? DIR_Right : DIR_Left);
|
||||
return;
|
||||
}
|
||||
Action.ComDir=COMD_Stop;
|
||||
}
|
||||
break;
|
||||
|
@ -3162,8 +3151,8 @@ void C4Object::ContactAction()
|
|||
// Jump: Try hangle, else bounce off
|
||||
// High Speed Flight: Tumble
|
||||
if ((OCF & OCF_HitSpeed3) || fDisabled)
|
||||
{ ObjectActionTumble(this,Action.Dir,Fix0,Fix0); break; }
|
||||
if (ObjectActionHangle(this,Action.Dir)) return;
|
||||
{ ObjectActionTumble(this,Action.Dir,xdir,ydir); break; }
|
||||
if (ObjectActionHangle(this)) return;
|
||||
break;
|
||||
case DFA_DIG:
|
||||
// No action
|
||||
|
@ -3186,12 +3175,14 @@ void C4Object::ContactAction()
|
|||
else if (ObjectActionScale(this,DIR_Left)) return;
|
||||
break;
|
||||
case DFA_WALK:
|
||||
// Walk: Try scale, else stop
|
||||
// Walk: Try scale
|
||||
if (ComDirLike(Action.ComDir, COMD_Left))
|
||||
{
|
||||
if (ObjectActionScale(this,DIR_Left)) return;
|
||||
// Else stop
|
||||
Action.ComDir=COMD_Stop;
|
||||
if (ObjectActionScale(this,DIR_Left))
|
||||
{
|
||||
ydir = C4REAL100(-1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Heading away from solid
|
||||
if (ComDirLike(Action.ComDir, COMD_Right))
|
||||
|
@ -3208,10 +3199,12 @@ void C4Object::ContactAction()
|
|||
if (ObjectActionCornerScale(this)) return;
|
||||
return;
|
||||
case DFA_HANGLE:
|
||||
// Hangle: Try scale, else stop
|
||||
// Hangle: Try scale
|
||||
if (ObjectActionScale(this,DIR_Left))
|
||||
{
|
||||
ydir = C4REAL100(1);
|
||||
return;
|
||||
Action.ComDir=COMD_Stop;
|
||||
}
|
||||
return;
|
||||
case DFA_DIG:
|
||||
// Dig: no action
|
||||
|
@ -3232,11 +3225,14 @@ void C4Object::ContactAction()
|
|||
else if (ObjectActionScale(this,DIR_Right)) return;
|
||||
break;
|
||||
case DFA_WALK:
|
||||
// Walk: Try scale, else stop
|
||||
// Walk: Try scale
|
||||
if (ComDirLike(Action.ComDir, COMD_Right))
|
||||
{
|
||||
if (ObjectActionScale(this,DIR_Right)) return;
|
||||
Action.ComDir=COMD_Stop;
|
||||
if (ObjectActionScale(this,DIR_Right))
|
||||
{
|
||||
ydir = C4REAL100(-1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Heading away from solid
|
||||
if (ComDirLike(Action.ComDir, COMD_Left))
|
||||
|
@ -3254,10 +3250,12 @@ void C4Object::ContactAction()
|
|||
// Skip to enable walk out
|
||||
return;
|
||||
case DFA_HANGLE:
|
||||
// Hangle: Try scale, else stop
|
||||
// Hangle: Try scale
|
||||
if (ObjectActionScale(this,DIR_Right))
|
||||
{
|
||||
ydir = C4REAL100(1);
|
||||
return;
|
||||
Action.ComDir=COMD_Stop;
|
||||
}
|
||||
return;
|
||||
case DFA_DIG:
|
||||
// Dig: no action
|
||||
|
@ -3540,10 +3538,13 @@ void C4Object::ExecAction()
|
|||
case DFA_SCALE:
|
||||
{
|
||||
int ComDir = Action.ComDir;
|
||||
if (Action.Dir == DIR_Left && ComDir == COMD_Left)
|
||||
ComDir = COMD_Up;
|
||||
else if (Action.Dir == DIR_Right && ComDir == COMD_Right)
|
||||
ComDir = COMD_Up;
|
||||
if ((Action.Dir == DIR_Left && ComDir == COMD_Left) || (Action.Dir == DIR_Right && ComDir == COMD_Right))
|
||||
{
|
||||
if (ydir > 0)
|
||||
ComDir = COMD_Down;
|
||||
else
|
||||
ComDir = COMD_Up;
|
||||
}
|
||||
switch (ComDir)
|
||||
{
|
||||
case COMD_Up: case COMD_UpRight: case COMD_UpLeft:
|
||||
|
|
|
@ -48,7 +48,6 @@ bool CreateConstructionSite(int32_t ctx, int32_t bty, C4ID strid, int32_t owner,
|
|||
bool ObjectActionWalk(C4Object *cObj)
|
||||
{
|
||||
if (!cObj->SetActionByName("Walk")) return false;
|
||||
cObj->xdir=cObj->ydir=0;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -104,14 +103,12 @@ bool ObjectActionGetPunched(C4Object *cObj, C4Real xdir, C4Real ydir)
|
|||
bool ObjectActionKneel(C4Object *cObj)
|
||||
{
|
||||
if (!cObj->SetActionByName("KneelDown")) return false;
|
||||
cObj->xdir=cObj->ydir=0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ObjectActionFlat(C4Object *cObj, int32_t dir)
|
||||
{
|
||||
if (!cObj->SetActionByName("FlatUp")) return false;
|
||||
cObj->xdir=cObj->ydir=0;
|
||||
cObj->SetDir(dir);
|
||||
return true;
|
||||
}
|
||||
|
@ -119,16 +116,13 @@ bool ObjectActionFlat(C4Object *cObj, int32_t dir)
|
|||
bool ObjectActionScale(C4Object *cObj, int32_t dir)
|
||||
{
|
||||
if (!cObj->SetActionByName("Scale")) return false;
|
||||
cObj->xdir=cObj->ydir=0;
|
||||
cObj->SetDir(dir);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ObjectActionHangle(C4Object *cObj, int32_t dir)
|
||||
bool ObjectActionHangle(C4Object *cObj)
|
||||
{
|
||||
if (!cObj->SetActionByName("Hangle")) return false;
|
||||
cObj->xdir=cObj->ydir=0;
|
||||
cObj->SetDir(dir);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -164,7 +158,7 @@ bool ObjectActionPush(C4Object *cObj, C4Object *target)
|
|||
return cObj->SetActionByName("Push",target);
|
||||
}
|
||||
|
||||
bool CornerScaleOkay(C4Object *cObj, int32_t iRangeX, int32_t iRangeY)
|
||||
static bool CornerScaleOkay(C4Object *cObj, int32_t iRangeX, int32_t iRangeY)
|
||||
{
|
||||
int32_t ctx,cty;
|
||||
cty=cObj->GetY()-iRangeY;
|
||||
|
@ -179,31 +173,10 @@ bool CornerScaleOkay(C4Object *cObj, int32_t iRangeX, int32_t iRangeY)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool CheckCornerScale(C4Object *cObj, int32_t &iRangeX, int32_t &iRangeY)
|
||||
{
|
||||
for (iRangeX=CornerRange; iRangeX>=1; iRangeX--)
|
||||
for (iRangeY=CornerRange; iRangeY>=1; iRangeY--)
|
||||
if (CornerScaleOkay(cObj,iRangeX,iRangeY))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ObjectActionCornerScale(C4Object *cObj)
|
||||
{
|
||||
int32_t iRangeX,iRangeY;
|
||||
// Scaling: check range max to min
|
||||
if (cObj->GetProcedure()==DFA_SCALE)
|
||||
{
|
||||
if (!CheckCornerScale(cObj,iRangeX,iRangeY)) return false;
|
||||
}
|
||||
// Swimming: check range min to max
|
||||
else
|
||||
{
|
||||
iRangeY=2;
|
||||
while (!CornerScaleOkay(cObj,iRangeY,iRangeY))
|
||||
{ iRangeY++; if (iRangeY>CornerRange) return false; }
|
||||
iRangeX=iRangeY;
|
||||
}
|
||||
int32_t iRangeX = 1, iRangeY = 1;
|
||||
if (!CornerScaleOkay(cObj,iRangeX,iRangeY)) return false;
|
||||
// Do corner scale
|
||||
if (!cObj->SetActionByName("KneelUp"))
|
||||
cObj->SetActionByName("Walk");
|
||||
|
@ -234,17 +207,6 @@ bool ObjectComMovement(C4Object *cObj, int32_t comdir)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ObjectComTurn(C4Object *cObj)
|
||||
{
|
||||
// turn around, if standing still
|
||||
if (!cObj->xdir && cObj->GetProcedure() == DFA_WALK)
|
||||
{
|
||||
cObj->SetDir(1-cObj->Action.Dir);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ObjectComStop(C4Object *cObj)
|
||||
{
|
||||
// Cease current action
|
||||
|
|
|
@ -43,7 +43,7 @@ bool ObjectActionGetPunched(C4Object *cObj, C4Real xdir, C4Real ydir);
|
|||
bool ObjectActionKneel(C4Object *cObj);
|
||||
bool ObjectActionFlat(C4Object *cObj, int32_t dir);
|
||||
bool ObjectActionScale(C4Object *cObj, int32_t dir);
|
||||
bool ObjectActionHangle(C4Object *cObj, int32_t dir);
|
||||
bool ObjectActionHangle(C4Object *cObj);
|
||||
bool ObjectActionThrow(C4Object *cObj, C4Object *pThing=NULL);
|
||||
bool ObjectActionDig(C4Object *cObj);
|
||||
bool ObjectActionPush(C4Object *cObj, C4Object *pTarget);
|
||||
|
|
Loading…
Reference in New Issue