forked from Mirrors/openclonk
Refactor movement code (#87)
Improve readability by adding appropriate parentheses and braces, and fixing misleading/confusing whitespace. Extract SolidMask removal to a function since it's used in several places.master
parent
765d9a24e9
commit
4a2048575f
|
@ -28,33 +28,43 @@
|
||||||
|
|
||||||
/* Some physical constants */
|
/* Some physical constants */
|
||||||
|
|
||||||
const C4Real FRedirect=C4REAL100(50);
|
const C4Real FRedirect = C4REAL100(50);
|
||||||
const C4Real FFriction=C4REAL100(30);
|
const C4Real FFriction = C4REAL100(30);
|
||||||
const C4Real FixFullCircle=itofix(360),FixHalfCircle=FixFullCircle/2;
|
const C4Real FixFullCircle = itofix(360);
|
||||||
const C4Real FloatFriction=C4REAL100(2);
|
const C4Real FixHalfCircle = FixFullCircle / 2;
|
||||||
const C4Real RotateAccel=C4REAL100(20);
|
const C4Real FloatFriction = C4REAL100(2);
|
||||||
const C4Real HitSpeed1=C4REAL100(150); // Hit Event
|
const C4Real RotateAccel = C4REAL100(20);
|
||||||
const C4Real HitSpeed2=itofix(2); // Cross Check Hit
|
const C4Real HitSpeed1 = C4REAL100(150); // Hit Event
|
||||||
const C4Real HitSpeed3=itofix(6); // Scale disable, kneel
|
const C4Real HitSpeed2 = itofix(2); // Cross Check Hit
|
||||||
const C4Real HitSpeed4=itofix(8); // Flat
|
const C4Real HitSpeed3 = itofix(6); // Scale disable, kneel
|
||||||
const C4Real DefaultGravAccel=C4REAL100(20);
|
const C4Real HitSpeed4 = itofix(8); // Flat
|
||||||
|
const C4Real DefaultGravAccel = C4REAL100(20);
|
||||||
|
|
||||||
/* Some helper functions */
|
/* Some helper functions */
|
||||||
|
|
||||||
void RedirectForce(C4Real &from, C4Real &to, int32_t tdir)
|
void RedirectForce(C4Real &from, C4Real &to, int32_t tdir)
|
||||||
{
|
{
|
||||||
C4Real fred;
|
C4Real fred;
|
||||||
fred=std::min(Abs(from), FRedirect);
|
fred = std::min(Abs(from), FRedirect);
|
||||||
from-=fred*Sign(from);
|
from -= fred * Sign(from);
|
||||||
to+=fred*tdir;
|
to += fred * tdir;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApplyFriction(C4Real &tval, int32_t percent)
|
void ApplyFriction(C4Real &tval, int32_t percent)
|
||||||
{
|
{
|
||||||
C4Real ffric=FFriction*percent/100;
|
C4Real ffric = FFriction * percent / 100;
|
||||||
if (tval>+ffric) { tval-=ffric; return; }
|
if (tval > +ffric)
|
||||||
if (tval<-ffric) { tval+=ffric; return; }
|
{
|
||||||
tval=0;
|
tval -= ffric;
|
||||||
|
}
|
||||||
|
else if (tval < -ffric)
|
||||||
|
{
|
||||||
|
tval += ffric;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tval = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compares all Shape.VtxContactCNAT[] CNAT flags to search flag.
|
// Compares all Shape.VtxContactCNAT[] CNAT flags to search flag.
|
||||||
|
@ -62,12 +72,14 @@ void ApplyFriction(C4Real &tval, int32_t percent)
|
||||||
|
|
||||||
bool ContactVtxCNAT(C4Object *cobj, BYTE cnat_dir)
|
bool ContactVtxCNAT(C4Object *cobj, BYTE cnat_dir)
|
||||||
{
|
{
|
||||||
int32_t cnt;
|
for (int32_t cnt = 0; cnt < cobj->Shape.VtxNum; cnt++)
|
||||||
bool fcontact=false;
|
{
|
||||||
for (cnt=0; cnt<cobj->Shape.VtxNum; cnt++)
|
|
||||||
if (cobj->Shape.VtxContactCNAT[cnt] & cnat_dir)
|
if (cobj->Shape.VtxContactCNAT[cnt] & cnat_dir)
|
||||||
fcontact=true;
|
{
|
||||||
return fcontact;
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finds first vertex with contact flag set.
|
// Finds first vertex with contact flag set.
|
||||||
|
@ -75,13 +87,20 @@ bool ContactVtxCNAT(C4Object *cobj, BYTE cnat_dir)
|
||||||
|
|
||||||
int32_t ContactVtxWeight(C4Object *cobj)
|
int32_t ContactVtxWeight(C4Object *cobj)
|
||||||
{
|
{
|
||||||
int32_t cnt;
|
for (int32_t cnt = 0; cnt < cobj->Shape.VtxNum; cnt++)
|
||||||
for (cnt=0; cnt<cobj->Shape.VtxNum; cnt++)
|
{
|
||||||
if (cobj->Shape.VtxContactCNAT[cnt])
|
if (cobj->Shape.VtxContactCNAT[cnt])
|
||||||
{
|
{
|
||||||
if (cobj->Shape.VtxX[cnt]<0) return -1;
|
if (cobj->Shape.VtxX[cnt] < 0)
|
||||||
if (cobj->Shape.VtxX[cnt]>0) return +1;
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (cobj->Shape.VtxX[cnt] > 0)
|
||||||
|
{
|
||||||
|
return +1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,10 +109,13 @@ int32_t ContactVtxWeight(C4Object *cobj)
|
||||||
|
|
||||||
int32_t ContactVtxFriction(C4Object *cobj)
|
int32_t ContactVtxFriction(C4Object *cobj)
|
||||||
{
|
{
|
||||||
int32_t cnt;
|
for (int32_t cnt = 0; cnt < cobj->Shape.VtxNum; cnt++)
|
||||||
for (cnt=0; cnt<cobj->Shape.VtxNum; cnt++)
|
{
|
||||||
if (cobj->Shape.VtxContactCNAT[cnt])
|
if (cobj->Shape.VtxContactCNAT[cnt])
|
||||||
|
{
|
||||||
return cobj->Shape.VtxFriction[cnt];
|
return cobj->Shape.VtxFriction[cnt];
|
||||||
|
}
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,8 +144,9 @@ bool C4Object::Contact(int32_t iCNAT)
|
||||||
|
|
||||||
void C4Object::DoMotion(int32_t mx, int32_t my)
|
void C4Object::DoMotion(int32_t mx, int32_t my)
|
||||||
{
|
{
|
||||||
if (pSolidMaskData) pSolidMaskData->Remove(true);
|
RemoveSolidMask(true);
|
||||||
fix_x += mx; fix_y += my;
|
fix_x += mx;
|
||||||
|
fix_y += my;
|
||||||
}
|
}
|
||||||
|
|
||||||
void C4Object::StopAndContact(C4Real & ctco, C4Real limit, C4Real & speed, int32_t cnat)
|
void C4Object::StopAndContact(C4Real & ctco, C4Real limit, C4Real & speed, int32_t cnat)
|
||||||
|
@ -136,17 +159,25 @@ void C4Object::StopAndContact(C4Real & ctco, C4Real limit, C4Real & speed, int32
|
||||||
int32_t C4Object::ContactCheck(int32_t iAtX, int32_t iAtY, uint32_t *border_hack_contacts, bool collide_halfvehic)
|
int32_t C4Object::ContactCheck(int32_t iAtX, int32_t iAtY, uint32_t *border_hack_contacts, bool collide_halfvehic)
|
||||||
{
|
{
|
||||||
// Check shape contact at given position
|
// Check shape contact at given position
|
||||||
Shape.ContactCheck(iAtX,iAtY,border_hack_contacts,collide_halfvehic);
|
Shape.ContactCheck(iAtX, iAtY, border_hack_contacts, collide_halfvehic);
|
||||||
|
|
||||||
// Store shape contact values in object t_contact
|
// Store shape contact values in object t_contact
|
||||||
t_contact=Shape.ContactCNAT;
|
t_contact = Shape.ContactCNAT;
|
||||||
|
|
||||||
// Contact script call for the first contacted cnat
|
// Contact script call for the first contacted cnat
|
||||||
if (Shape.ContactCNAT)
|
if (Shape.ContactCNAT)
|
||||||
for (int32_t ccnat=0; ccnat<4; ccnat++) // Left, right, top bottom
|
{
|
||||||
if (Shape.ContactCNAT & (1<<ccnat))
|
for (int32_t ccnat = 0; ccnat < 4; ccnat++) // Left, right, top bottom
|
||||||
if (Contact(1<<ccnat))
|
{
|
||||||
|
if (Shape.ContactCNAT & (1 << ccnat))
|
||||||
|
{
|
||||||
|
if (Contact(1 << ccnat))
|
||||||
|
{
|
||||||
break; // Will stop on first positive return contact call!
|
break; // Will stop on first positive return contact call!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Return shape contact count
|
// Return shape contact count
|
||||||
return Shape.ContactCount;
|
return Shape.ContactCount;
|
||||||
|
@ -156,80 +187,114 @@ int32_t C4Object::ContactCheck(int32_t iAtX, int32_t iAtY, uint32_t *border_hack
|
||||||
void C4Object::SideBounds(C4Real &ctcox)
|
void C4Object::SideBounds(C4Real &ctcox)
|
||||||
{
|
{
|
||||||
// layer bounds
|
// layer bounds
|
||||||
if (Layer && Layer->GetPropertyInt(P_BorderBound) & C4D_Border_Layer)
|
if (Layer && (Layer->GetPropertyInt(P_BorderBound) & C4D_Border_Layer))
|
||||||
{
|
{
|
||||||
C4PropList* pActionDef = GetAction();
|
C4PropList* pActionDef = GetAction();
|
||||||
if (!pActionDef || pActionDef->GetPropertyP(P_Procedure) != DFA_ATTACH)
|
if (!pActionDef || pActionDef->GetPropertyP(P_Procedure) != DFA_ATTACH)
|
||||||
{
|
{
|
||||||
C4Real lbound = itofix(Layer->GetX() + Layer->Shape.GetX() - Shape.GetX()),
|
C4Real lbound = itofix(Layer->GetX() + Layer->Shape.GetX() - Shape.GetX());
|
||||||
rbound = itofix(Layer->GetX() + Layer->Shape.GetX() + Layer->Shape.Wdt - (Shape.GetX() + Shape.Wdt));
|
C4Real rbound = itofix(Layer->GetX() + Layer->Shape.GetX() + Layer->Shape.Wdt - (Shape.GetX() + Shape.Wdt));
|
||||||
if (ctcox < lbound) StopAndContact(ctcox, lbound, xdir, CNAT_Left);
|
if (ctcox < lbound)
|
||||||
if (ctcox > rbound) StopAndContact(ctcox, rbound, xdir, CNAT_Right);
|
{
|
||||||
|
StopAndContact(ctcox, lbound, xdir, CNAT_Left);
|
||||||
|
}
|
||||||
|
if (ctcox > rbound)
|
||||||
|
{
|
||||||
|
StopAndContact(ctcox, rbound, xdir, CNAT_Right);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// landscape bounds
|
// landscape bounds
|
||||||
C4Real lbound = itofix(0 - Shape.GetX()),
|
C4Real lbound = itofix(0 - Shape.GetX());
|
||||||
rbound = itofix(::Landscape.GetWidth() - (Shape.GetX() + Shape.Wdt));
|
C4Real rbound = itofix(::Landscape.GetWidth() - (Shape.GetX() + Shape.Wdt));
|
||||||
if (ctcox < lbound && GetPropertyInt(P_BorderBound) & C4D_Border_Sides)
|
if (ctcox < lbound && (GetPropertyInt(P_BorderBound) & C4D_Border_Sides))
|
||||||
|
{
|
||||||
StopAndContact(ctcox, lbound, xdir, CNAT_Left);
|
StopAndContact(ctcox, lbound, xdir, CNAT_Left);
|
||||||
if (ctcox > rbound && GetPropertyInt(P_BorderBound) & C4D_Border_Sides)
|
}
|
||||||
|
if (ctcox > rbound && (GetPropertyInt(P_BorderBound) & C4D_Border_Sides))
|
||||||
|
{
|
||||||
StopAndContact(ctcox, rbound, xdir, CNAT_Right);
|
StopAndContact(ctcox, rbound, xdir, CNAT_Right);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void C4Object::VerticalBounds(C4Real &ctcoy)
|
void C4Object::VerticalBounds(C4Real &ctcoy)
|
||||||
{
|
{
|
||||||
// layer bounds
|
// layer bounds
|
||||||
if (Layer && Layer->GetPropertyInt(P_BorderBound) & C4D_Border_Layer)
|
if (Layer && (Layer->GetPropertyInt(P_BorderBound) & C4D_Border_Layer))
|
||||||
{
|
{
|
||||||
C4PropList* pActionDef = GetAction();
|
C4PropList* pActionDef = GetAction();
|
||||||
if (!pActionDef || pActionDef->GetPropertyP(P_Procedure) != DFA_ATTACH)
|
if (!pActionDef || pActionDef->GetPropertyP(P_Procedure) != DFA_ATTACH)
|
||||||
{
|
{
|
||||||
C4Real tbound = itofix(Layer->GetY() + Layer->Shape.GetY() - Shape.GetY()),
|
C4Real tbound = itofix(Layer->GetY() + Layer->Shape.GetY() - Shape.GetY());
|
||||||
bbound = itofix(Layer->GetY() + Layer->Shape.GetY() + Layer->Shape.Hgt - (Shape.GetY() + Shape.Hgt));
|
C4Real bbound = itofix(Layer->GetY() + Layer->Shape.GetY() + Layer->Shape.Hgt - (Shape.GetY() + Shape.Hgt));
|
||||||
if (ctcoy < tbound) StopAndContact(ctcoy, tbound, ydir, CNAT_Top);
|
if (ctcoy < tbound)
|
||||||
if (ctcoy > bbound) StopAndContact(ctcoy, bbound, ydir, CNAT_Bottom);
|
{
|
||||||
|
StopAndContact(ctcoy, tbound, ydir, CNAT_Top);
|
||||||
|
}
|
||||||
|
if (ctcoy > bbound)
|
||||||
|
{
|
||||||
|
StopAndContact(ctcoy, bbound, ydir, CNAT_Bottom);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// landscape bounds
|
// landscape bounds
|
||||||
C4Real tbound = itofix(0 - Shape.GetY()),
|
C4Real tbound = itofix(0 - Shape.GetY());
|
||||||
bbound = itofix(::Landscape.GetHeight() - (Shape.GetY() + Shape.Hgt));
|
C4Real bbound = itofix(::Landscape.GetHeight() - (Shape.GetY() + Shape.Hgt));
|
||||||
if (ctcoy < tbound && GetPropertyInt(P_BorderBound) & C4D_Border_Top)
|
if (ctcoy < tbound && (GetPropertyInt(P_BorderBound) & C4D_Border_Top))
|
||||||
|
{
|
||||||
StopAndContact(ctcoy, tbound, ydir, CNAT_Top);
|
StopAndContact(ctcoy, tbound, ydir, CNAT_Top);
|
||||||
if (ctcoy > bbound && GetPropertyInt(P_BorderBound) & C4D_Border_Bottom)
|
}
|
||||||
|
if (ctcoy > bbound && (GetPropertyInt(P_BorderBound) & C4D_Border_Bottom))
|
||||||
|
{
|
||||||
StopAndContact(ctcoy, bbound, ydir, CNAT_Bottom);
|
StopAndContact(ctcoy, bbound, ydir, CNAT_Bottom);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void C4Object::DoMovement()
|
void C4Object::DoMovement()
|
||||||
{
|
{
|
||||||
int32_t iContact=0;
|
int32_t iContact = 0;
|
||||||
bool fAnyContact=false; int iContacts = 0;
|
bool fAnyContact = false;
|
||||||
BYTE fTurned=0,fRedirectYR=0,fNoAttach=0;
|
int iContacts = 0;
|
||||||
|
BYTE fTurned = 0;
|
||||||
|
BYTE fRedirectYR = 0;
|
||||||
|
BYTE fNoAttach = 0;
|
||||||
// Restrictions
|
// Restrictions
|
||||||
if (Def->NoHorizontalMove) xdir=0;
|
if (Def->NoHorizontalMove)
|
||||||
|
{
|
||||||
|
xdir = 0;
|
||||||
|
}
|
||||||
// Dig free target area
|
// Dig free target area
|
||||||
C4PropList* pActionDef = GetAction();
|
C4PropList* pActionDef = GetAction();
|
||||||
if (pActionDef)
|
if (pActionDef)
|
||||||
|
{
|
||||||
if (pActionDef->GetPropertyInt(P_DigFree))
|
if (pActionDef->GetPropertyInt(P_DigFree))
|
||||||
{
|
{
|
||||||
int ctcox, ctcoy;
|
int ctcox, ctcoy;
|
||||||
// Shape size square
|
// Shape size square
|
||||||
if (pActionDef->GetPropertyInt(P_DigFree)==1)
|
if (pActionDef->GetPropertyInt(P_DigFree) == 1)
|
||||||
{
|
{
|
||||||
ctcox=fixtoi(fix_x+xdir); ctcoy=fixtoi(fix_y+ydir);
|
ctcox = fixtoi(fix_x + xdir);
|
||||||
::Landscape.DigFreeRect(ctcox+Shape.GetX(),ctcoy+Shape.GetY(),Shape.Wdt,Shape.Hgt,this);
|
ctcoy = fixtoi(fix_y + ydir);
|
||||||
|
::Landscape.DigFreeRect(ctcox + Shape.GetX(), ctcoy + Shape.GetY(), Shape.Wdt, Shape.Hgt, this);
|
||||||
}
|
}
|
||||||
// Free size round (variable size)
|
// Free size round (variable size)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ctcox=fixtoi(fix_x+xdir); ctcoy=fixtoi(fix_y+ydir);
|
ctcox = fixtoi(fix_x + xdir);
|
||||||
|
ctcoy = fixtoi(fix_y + ydir);
|
||||||
int32_t rad = pActionDef->GetPropertyInt(P_DigFree);
|
int32_t rad = pActionDef->GetPropertyInt(P_DigFree);
|
||||||
if (Con<FullCon) rad = rad*6*Con/5/FullCon;
|
if (Con < FullCon)
|
||||||
::Landscape.DigFree(ctcox,ctcoy-1,rad,this);
|
{
|
||||||
|
rad = rad * 6 * Con / 5 / FullCon;
|
||||||
|
}
|
||||||
|
::Landscape.DigFree(ctcox, ctcoy - 1, rad, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// store previous movement and ocf
|
// store previous movement and ocf
|
||||||
C4Real oldxdir(xdir), oldydir(ydir);
|
C4Real oldxdir(xdir);
|
||||||
|
C4Real oldydir(ydir);
|
||||||
uint32_t old_ocf = OCF;
|
uint32_t old_ocf = OCF;
|
||||||
|
|
||||||
bool fMoved = false;
|
bool fMoved = false;
|
||||||
|
@ -246,18 +311,19 @@ void C4Object::DoMovement()
|
||||||
// Next step
|
// Next step
|
||||||
int step = Sign(new_x - fix_x);
|
int step = Sign(new_x - fix_x);
|
||||||
uint32_t border_hack_contacts = 0;
|
uint32_t border_hack_contacts = 0;
|
||||||
iContact=ContactCheck(GetX() + step, GetY(), &border_hack_contacts);
|
iContact = ContactCheck(GetX() + step, GetY(), &border_hack_contacts);
|
||||||
if (iContact || border_hack_contacts)
|
if (iContact || border_hack_contacts)
|
||||||
{
|
{
|
||||||
fAnyContact=true; iContacts |= t_contact | border_hack_contacts;
|
fAnyContact = true;
|
||||||
|
iContacts |= t_contact | border_hack_contacts;
|
||||||
}
|
}
|
||||||
if (iContact)
|
if (iContact)
|
||||||
{
|
{
|
||||||
// Abort horizontal movement
|
// Abort horizontal movement
|
||||||
new_x = fix_x;
|
new_x = fix_x;
|
||||||
// Vertical redirection (always)
|
// Vertical redirection (always)
|
||||||
RedirectForce(xdir,ydir,-1);
|
RedirectForce(xdir, ydir, -1);
|
||||||
ApplyFriction(ydir,ContactVtxFriction(this));
|
ApplyFriction(ydir, ContactVtxFriction(this));
|
||||||
}
|
}
|
||||||
else // Free horizontal movement
|
else // Free horizontal movement
|
||||||
{
|
{
|
||||||
|
@ -275,31 +341,36 @@ void C4Object::DoMovement()
|
||||||
{
|
{
|
||||||
// Next step
|
// Next step
|
||||||
int step = Sign(new_y - fix_y);
|
int step = Sign(new_y - fix_y);
|
||||||
if ((iContact=ContactCheck(GetX(), GetY() + step, nullptr, ydir > 0)))
|
if ((iContact = ContactCheck(GetX(), GetY() + step, nullptr, ydir > 0)))
|
||||||
{
|
{
|
||||||
fAnyContact=true; iContacts |= t_contact;
|
fAnyContact = true;
|
||||||
|
iContacts |= t_contact;
|
||||||
new_y = fix_y;
|
new_y = fix_y;
|
||||||
// Vertical contact horizontal friction
|
// Vertical contact horizontal friction
|
||||||
ApplyFriction(xdir,ContactVtxFriction(this));
|
ApplyFriction(xdir, ContactVtxFriction(this));
|
||||||
// Redirection slide or rotate
|
// Redirection slide or rotate
|
||||||
if (!ContactVtxCNAT(this,CNAT_Left))
|
if (!ContactVtxCNAT(this, CNAT_Left))
|
||||||
RedirectForce(ydir,xdir,-1);
|
{
|
||||||
else if (!ContactVtxCNAT(this,CNAT_Right))
|
RedirectForce(ydir, xdir, -1);
|
||||||
RedirectForce(ydir,xdir,+1);
|
}
|
||||||
|
else if (!ContactVtxCNAT(this, CNAT_Right))
|
||||||
|
{
|
||||||
|
RedirectForce(ydir, xdir, +1);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// living things are always capable of keeping their rotation
|
// living things are always capable of keeping their rotation
|
||||||
if (OCF & OCF_Rotate) if (iContact==1) if (!Alive)
|
if ((OCF & OCF_Rotate) && iContact == 1 && !Alive)
|
||||||
{
|
{
|
||||||
RedirectForce(ydir,rdir,-ContactVtxWeight(this));
|
RedirectForce(ydir, rdir, -ContactVtxWeight(this));
|
||||||
fRedirectYR=1;
|
fRedirectYR = 1;
|
||||||
}
|
}
|
||||||
ydir=0;
|
ydir = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // Free vertical movement
|
else // Free vertical movement
|
||||||
{
|
{
|
||||||
DoMotion(0,step);
|
DoMotion(0, step);
|
||||||
fMoved = true;
|
fMoved = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -311,45 +382,57 @@ void C4Object::DoMovement()
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
// Set next step target
|
// Set next step target
|
||||||
int step_x = 0, step_y = 0;
|
int step_x = 0;
|
||||||
|
int step_y = 0;
|
||||||
if (fixtoi(new_x) != GetX())
|
if (fixtoi(new_x) != GetX())
|
||||||
|
{
|
||||||
step_x = Sign(fixtoi(new_x) - GetX());
|
step_x = Sign(fixtoi(new_x) - GetX());
|
||||||
|
}
|
||||||
else if (fixtoi(new_y) != GetY())
|
else if (fixtoi(new_y) != GetY())
|
||||||
|
{
|
||||||
step_y = Sign(fixtoi(new_y) - GetY());
|
step_y = Sign(fixtoi(new_y) - GetY());
|
||||||
|
}
|
||||||
int32_t ctx = GetX() + step_x;
|
int32_t ctx = GetX() + step_x;
|
||||||
int32_t cty = GetY() + step_y;
|
int32_t cty = GetY() + step_y;
|
||||||
// Attachment check
|
// Attachment check
|
||||||
if (!Shape.Attach(ctx,cty,Action.t_attach))
|
if (!Shape.Attach(ctx, cty, Action.t_attach))
|
||||||
fNoAttach=1;
|
{
|
||||||
|
fNoAttach = 1;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Attachment change to ctx/cty overrides target
|
// Attachment change to ctx/cty overrides target
|
||||||
if (ctx != GetX() + step_x)
|
if (ctx != GetX() + step_x)
|
||||||
{
|
{
|
||||||
xdir = Fix0; new_x = itofix(ctx);
|
xdir = Fix0;
|
||||||
|
new_x = itofix(ctx);
|
||||||
}
|
}
|
||||||
if (cty != GetY() + step_y)
|
if (cty != GetY() + step_y)
|
||||||
{
|
{
|
||||||
ydir = Fix0; new_y = itofix(cty);
|
ydir = Fix0;
|
||||||
|
new_y = itofix(cty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Contact check & evaluation
|
// Contact check & evaluation
|
||||||
uint32_t border_hack_contacts = 0;
|
uint32_t border_hack_contacts = 0;
|
||||||
iContact=ContactCheck(ctx,cty,&border_hack_contacts);
|
iContact = ContactCheck(ctx, cty, &border_hack_contacts);
|
||||||
if (iContact || border_hack_contacts)
|
if (iContact || border_hack_contacts)
|
||||||
{
|
{
|
||||||
fAnyContact=true; iContacts |= border_hack_contacts | t_contact;
|
fAnyContact = true;
|
||||||
|
iContacts |= border_hack_contacts | t_contact;
|
||||||
}
|
}
|
||||||
if (iContact)
|
if (iContact)
|
||||||
{
|
{
|
||||||
// Abort movement
|
// Abort movement
|
||||||
if (ctx != GetX())
|
if (ctx != GetX())
|
||||||
{
|
{
|
||||||
ctx = GetX(); new_x = fix_x;
|
ctx = GetX();
|
||||||
|
new_x = fix_x;
|
||||||
}
|
}
|
||||||
if (cty != GetY())
|
if (cty != GetY())
|
||||||
{
|
{
|
||||||
cty = GetY(); new_y = fix_y;
|
cty = GetY();
|
||||||
|
new_y = fix_y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DoMotion(ctx - GetX(), cty - GetY());
|
DoMotion(ctx - GetX(), cty - GetY());
|
||||||
|
@ -358,31 +441,39 @@ void C4Object::DoMovement()
|
||||||
while (fixtoi(new_x) != GetX() || fixtoi(new_y) != GetY());
|
while (fixtoi(new_x) != GetX() || fixtoi(new_y) != GetY());
|
||||||
}
|
}
|
||||||
|
|
||||||
if(fix_x != new_x || fix_y != new_y)
|
if (fix_x != new_x || fix_y != new_y)
|
||||||
{
|
{
|
||||||
fMoved = true;
|
fMoved = true;
|
||||||
if (pSolidMaskData) pSolidMaskData->Remove(true);
|
RemoveSolidMask(true);
|
||||||
fix_x = new_x;
|
fix_x = new_x;
|
||||||
fix_y = new_y;
|
fix_y = new_y;
|
||||||
}
|
}
|
||||||
// Rotation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// Rotation - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
if (OCF & OCF_Rotate && !!rdir)
|
if ((OCF & OCF_Rotate) && !!rdir)
|
||||||
{
|
{
|
||||||
C4Real target_r = fix_r + rdir * 5;
|
C4Real target_r = fix_r + rdir * 5;
|
||||||
// Rotation limit
|
// Rotation limit
|
||||||
if (Def->Rotateable>1)
|
if (Def->Rotateable>1)
|
||||||
{
|
{
|
||||||
if (target_r > itofix(Def->Rotateable))
|
if (target_r > itofix(Def->Rotateable))
|
||||||
{ target_r = itofix(Def->Rotateable); rdir=0; }
|
{
|
||||||
|
target_r = itofix(Def->Rotateable);
|
||||||
|
rdir = 0;
|
||||||
|
}
|
||||||
if (target_r < itofix(-Def->Rotateable))
|
if (target_r < itofix(-Def->Rotateable))
|
||||||
{ target_r = itofix(-Def->Rotateable); rdir=0; }
|
{
|
||||||
|
target_r = itofix(-Def->Rotateable);
|
||||||
|
rdir = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
int32_t ctx=GetX(); int32_t cty=GetY();
|
int32_t ctx = GetX();
|
||||||
|
int32_t cty = GetY();
|
||||||
// Move to target
|
// Move to target
|
||||||
while (fixtoi(fix_r) != fixtoi(target_r))
|
while (fixtoi(fix_r) != fixtoi(target_r))
|
||||||
{
|
{
|
||||||
// Save step undos
|
// Save step undos
|
||||||
C4Real lcobjr = fix_r; C4Shape lshape=Shape;
|
C4Real lcobjr = fix_r;
|
||||||
|
C4Shape lshape = Shape;
|
||||||
// Try next step
|
// Try next step
|
||||||
fix_r += Sign(target_r - fix_r);
|
fix_r += Sign(target_r - fix_r);
|
||||||
UpdateShape();
|
UpdateShape();
|
||||||
|
@ -392,59 +483,80 @@ void C4Object::DoMovement()
|
||||||
// more accurately, attachment should be evaluated by a rotation around the attachment vertex
|
// more accurately, attachment should be evaluated by a rotation around the attachment vertex
|
||||||
// however, as long as this code is only used for some surfaces adjustment for large vehicles,
|
// however, as long as this code is only used for some surfaces adjustment for large vehicles,
|
||||||
// it's enough to assume rotation around the center
|
// it's enough to assume rotation around the center
|
||||||
ctx=GetX(); cty=GetY();
|
ctx = GetX();
|
||||||
|
cty = GetY();
|
||||||
// evaluate attachment, but do not bother about attachment loss
|
// evaluate attachment, but do not bother about attachment loss
|
||||||
// that will then be done in next execution cycle
|
// that will then be done in next execution cycle
|
||||||
Shape.Attach(ctx,cty,Action.t_attach);
|
Shape.Attach(ctx, cty, Action.t_attach);
|
||||||
}
|
}
|
||||||
// check for contact
|
// check for contact
|
||||||
if ((iContact=ContactCheck(ctx,cty))) // Contact
|
if ((iContact = ContactCheck(ctx, cty))) // Contact
|
||||||
{
|
{
|
||||||
fAnyContact=true; iContacts |= t_contact;
|
fAnyContact = true;
|
||||||
|
iContacts |= t_contact;
|
||||||
// Undo step and abort movement
|
// Undo step and abort movement
|
||||||
Shape=lshape;
|
Shape = lshape;
|
||||||
target_r = fix_r = lcobjr;
|
target_r = fix_r = lcobjr;
|
||||||
// last UpdateShape-call might have changed sector lists!
|
// last UpdateShape-call might have changed sector lists!
|
||||||
UpdatePos();
|
UpdatePos();
|
||||||
// Redirect to GetY()
|
// Redirect to GetY()
|
||||||
if (iContact==1) if (!fRedirectYR)
|
if (iContact == 1 && !fRedirectYR)
|
||||||
RedirectForce(rdir,ydir,-1);
|
{
|
||||||
|
RedirectForce(rdir, ydir, -1);
|
||||||
|
}
|
||||||
// Stop rotation
|
// Stop rotation
|
||||||
rdir=0;
|
rdir = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fTurned=1;
|
fTurned = 1;
|
||||||
if (ctx != GetX() || cty != GetY())
|
if (ctx != GetX() || cty != GetY())
|
||||||
{
|
{
|
||||||
fix_x = itofix(ctx); fix_y = itofix(cty);
|
fix_x = itofix(ctx);
|
||||||
|
fix_y = itofix(cty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Circle bounds
|
// Circle bounds
|
||||||
if (target_r < -FixHalfCircle) { target_r += FixFullCircle; }
|
if (target_r < -FixHalfCircle)
|
||||||
if (target_r > +FixHalfCircle) { target_r -= FixFullCircle; }
|
{
|
||||||
|
target_r += FixFullCircle;
|
||||||
|
}
|
||||||
|
if (target_r > +FixHalfCircle)
|
||||||
|
{
|
||||||
|
target_r -= FixFullCircle;
|
||||||
|
}
|
||||||
fix_r = target_r;
|
fix_r = target_r;
|
||||||
}
|
}
|
||||||
// Reput solid mask if moved by motion
|
// Reput solid mask if moved by motion
|
||||||
if (fMoved || fTurned) UpdateSolidMask(true);
|
if (fMoved || fTurned)
|
||||||
|
{
|
||||||
|
UpdateSolidMask(true);
|
||||||
|
}
|
||||||
// Misc checks ===========================================================================================
|
// Misc checks ===========================================================================================
|
||||||
// InLiquid check
|
// InLiquid check
|
||||||
// this equals C4Object::UpdateLiquid, but the "fNoAttach=false;"-line
|
// this equals C4Object::UpdateLiquid, but the "fNoAttach = false;"-line
|
||||||
if (IsInLiquidCheck()) // In Liquid
|
if (IsInLiquidCheck()) // In Liquid
|
||||||
{
|
{
|
||||||
if (!InLiquid) // Enter liquid
|
if (!InLiquid) // Enter liquid
|
||||||
{
|
{
|
||||||
if (OCF & OCF_HitSpeed2)
|
if (OCF & OCF_HitSpeed2)
|
||||||
if (Mass>3) Splash();
|
{
|
||||||
fNoAttach=false;
|
if (Mass > 3)
|
||||||
InLiquid=true;
|
{
|
||||||
|
Splash();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fNoAttach = false;
|
||||||
|
InLiquid = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // Out of liquid
|
else // Out of liquid
|
||||||
{
|
{
|
||||||
if (InLiquid) // Leave liquid
|
if (InLiquid) // Leave liquid
|
||||||
InLiquid=false;
|
{
|
||||||
|
InLiquid = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Contact Action
|
// Contact Action
|
||||||
if (fAnyContact)
|
if (fAnyContact)
|
||||||
|
@ -454,50 +566,79 @@ void C4Object::DoMovement()
|
||||||
}
|
}
|
||||||
// Attachment Loss Action
|
// Attachment Loss Action
|
||||||
if (fNoAttach)
|
if (fNoAttach)
|
||||||
|
{
|
||||||
NoAttachAction();
|
NoAttachAction();
|
||||||
|
}
|
||||||
// Movement Script Execution
|
// Movement Script Execution
|
||||||
if (fAnyContact)
|
if (fAnyContact)
|
||||||
{
|
{
|
||||||
C4AulParSet pars(fixtoi(oldxdir, 100), fixtoi(oldydir, 100));
|
C4AulParSet pars(fixtoi(oldxdir, 100), fixtoi(oldydir, 100));
|
||||||
if (old_ocf & OCF_HitSpeed1) Call(PSF_Hit, &pars);
|
if (old_ocf & OCF_HitSpeed1)
|
||||||
if (old_ocf & OCF_HitSpeed2) Call(PSF_Hit2, &pars);
|
{
|
||||||
if (old_ocf & OCF_HitSpeed3) Call(PSF_Hit3, &pars);
|
Call(PSF_Hit, &pars);
|
||||||
|
}
|
||||||
|
if (old_ocf & OCF_HitSpeed2)
|
||||||
|
{
|
||||||
|
Call(PSF_Hit2, &pars);
|
||||||
|
}
|
||||||
|
if (old_ocf & OCF_HitSpeed3)
|
||||||
|
{
|
||||||
|
Call(PSF_Hit3, &pars);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Rotation gfx
|
// Rotation gfx
|
||||||
if (fTurned)
|
if (fTurned)
|
||||||
|
{
|
||||||
UpdateFace(true);
|
UpdateFace(true);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
// pos changed?
|
// pos changed?
|
||||||
if (fMoved) UpdatePos();
|
if (fMoved)
|
||||||
|
{
|
||||||
|
UpdatePos();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void C4Object::Stabilize()
|
void C4Object::Stabilize()
|
||||||
{
|
{
|
||||||
// def allows stabilization?
|
// def allows stabilization?
|
||||||
if (Def->NoStabilize) return;
|
if (Def->NoStabilize)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
// normalize angle
|
// normalize angle
|
||||||
C4Real nr = fix_r;
|
C4Real nr = fix_r;
|
||||||
while (nr < itofix(-180)) nr += 360;
|
while (nr < itofix(-180))
|
||||||
while (nr > itofix(180)) nr -= 360;
|
{
|
||||||
|
nr += 360;
|
||||||
|
}
|
||||||
|
while (nr > itofix(180))
|
||||||
|
{
|
||||||
|
nr -= 360;
|
||||||
|
}
|
||||||
if (nr != Fix0)
|
if (nr != Fix0)
|
||||||
if (Inside<C4Real>(nr,itofix(-StableRange),itofix(+StableRange)))
|
{
|
||||||
|
if (Inside<C4Real>(nr, itofix(-StableRange), itofix(+StableRange)))
|
||||||
{
|
{
|
||||||
// Save step undos
|
// Save step undos
|
||||||
C4Real lcobjr=fix_r;
|
C4Real lcobjr = fix_r;
|
||||||
C4Shape lshape=Shape;
|
C4Shape lshape = Shape;
|
||||||
// Try rotation
|
// Try rotation
|
||||||
fix_r=Fix0;
|
fix_r = Fix0;
|
||||||
UpdateShape();
|
UpdateShape();
|
||||||
if (ContactCheck(GetX(),GetY()))
|
if (ContactCheck(GetX(), GetY()))
|
||||||
{ // Undo rotation
|
{ // Undo rotation
|
||||||
Shape=lshape;
|
Shape = lshape;
|
||||||
fix_r=lcobjr;
|
fix_r = lcobjr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // Stabilization okay
|
{ // Stabilization okay
|
||||||
UpdateFace(true);
|
UpdateFace(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void C4Object::CopyMotion(C4Object *from)
|
void C4Object::CopyMotion(C4Object *from)
|
||||||
|
@ -505,16 +646,19 @@ void C4Object::CopyMotion(C4Object *from)
|
||||||
// Designed for contained objects, no static
|
// Designed for contained objects, no static
|
||||||
if (fix_x != from->fix_x || fix_y != from->fix_y)
|
if (fix_x != from->fix_x || fix_y != from->fix_y)
|
||||||
{
|
{
|
||||||
fix_x=from->fix_x; fix_y=from->fix_y;
|
fix_x = from->fix_x;
|
||||||
|
fix_y = from->fix_y;
|
||||||
// Resort into sectors
|
// Resort into sectors
|
||||||
UpdatePos();
|
UpdatePos();
|
||||||
}
|
}
|
||||||
xdir=from->xdir; ydir=from->ydir;
|
xdir = from->xdir;
|
||||||
|
ydir = from->ydir;
|
||||||
}
|
}
|
||||||
|
|
||||||
void C4Object::ForcePosition(C4Real tx, C4Real ty)
|
void C4Object::ForcePosition(C4Real tx, C4Real ty)
|
||||||
{
|
{
|
||||||
fix_x=tx; fix_y=ty;
|
fix_x = tx;
|
||||||
|
fix_y = ty;
|
||||||
UpdatePos();
|
UpdatePos();
|
||||||
UpdateSolidMask(false);
|
UpdateSolidMask(false);
|
||||||
}
|
}
|
||||||
|
@ -527,9 +671,9 @@ void C4Object::MovePosition(int32_t dx, int32_t dy)
|
||||||
void C4Object::MovePosition(C4Real dx, C4Real dy)
|
void C4Object::MovePosition(C4Real dx, C4Real dy)
|
||||||
{
|
{
|
||||||
// move object position; repositions SolidMask
|
// move object position; repositions SolidMask
|
||||||
if (pSolidMaskData) pSolidMaskData->Remove(true);
|
RemoveSolidMask(true);
|
||||||
fix_x+=dx;
|
fix_x += dx;
|
||||||
fix_y+=dy;
|
fix_y += dy;
|
||||||
UpdatePos();
|
UpdatePos();
|
||||||
UpdateSolidMask(true);
|
UpdateSolidMask(true);
|
||||||
}
|
}
|
||||||
|
@ -549,7 +693,10 @@ bool C4Object::ExecMovement() // Every Tick1 by Execute
|
||||||
}
|
}
|
||||||
|
|
||||||
// General mobility check
|
// General mobility check
|
||||||
if (Category & C4D_StaticBack) return false;
|
if (Category & C4D_StaticBack)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Movement execution
|
// Movement execution
|
||||||
if (Mobile) // Object is moving
|
if (Mobile) // Object is moving
|
||||||
|
@ -557,9 +704,15 @@ bool C4Object::ExecMovement() // Every Tick1 by Execute
|
||||||
// Move object
|
// Move object
|
||||||
DoMovement();
|
DoMovement();
|
||||||
// Demobilization check
|
// Demobilization check
|
||||||
if ((xdir==0) && (ydir==0) && (rdir==0)) Mobile=false;
|
if ((xdir == 0) && (ydir == 0) && (rdir == 0))
|
||||||
|
{
|
||||||
|
Mobile = false;
|
||||||
|
}
|
||||||
// Check for stabilization
|
// Check for stabilization
|
||||||
if (rdir==0) Stabilize();
|
if (rdir == 0)
|
||||||
|
{
|
||||||
|
Stabilize();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else // Object is static
|
else // Object is static
|
||||||
{
|
{
|
||||||
|
@ -569,13 +722,16 @@ bool C4Object::ExecMovement() // Every Tick1 by Execute
|
||||||
if (!::Game.iTick10)
|
if (!::Game.iTick10)
|
||||||
{
|
{
|
||||||
// Gravity mobilization
|
// Gravity mobilization
|
||||||
xdir=ydir=rdir=0;
|
xdir = ydir = rdir = 0;
|
||||||
Mobile=true;
|
Mobile = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enforce zero rotation
|
// Enforce zero rotation
|
||||||
if (!Def->Rotateable) fix_r=Fix0;
|
if (!Def->Rotateable)
|
||||||
|
{
|
||||||
|
fix_r = Fix0;
|
||||||
|
}
|
||||||
|
|
||||||
// Out of bounds check
|
// Out of bounds check
|
||||||
if ((!Inside<int32_t>(GetX() + Shape.GetX(), -Shape.Wdt, ::Landscape.GetWidth()) && !(GetPropertyInt(P_BorderBound) & C4D_Border_Sides))
|
if ((!Inside<int32_t>(GetX() + Shape.GetX(), -Shape.Wdt, ::Landscape.GetWidth()) && !(GetPropertyInt(P_BorderBound) & C4D_Border_Sides))
|
||||||
|
@ -593,9 +749,18 @@ bool C4Object::ExecMovement() // Every Tick1 by Execute
|
||||||
int parX, parY;
|
int parX, parY;
|
||||||
GetParallaxity(&parX, &parY);
|
GetParallaxity(&parX, &parY);
|
||||||
fRemove = false;
|
fRemove = false;
|
||||||
if (GetX()>::Landscape.GetWidth() || GetY()>::Landscape.GetHeight()) fRemove = true; // except if they are really out of the viewport to the right...
|
if (GetX() > ::Landscape.GetWidth() || GetY() > ::Landscape.GetHeight())
|
||||||
else if (GetX()<0 && !!parX) fRemove = true; // ...or it's not HUD horizontally and it's out to the left
|
{
|
||||||
else if (!parX && GetX()<-::Landscape.GetWidth()) fRemove = true; // ...or it's HUD horizontally and it's out to the left
|
fRemove = true; // except if they are really out of the viewport to the right...
|
||||||
|
}
|
||||||
|
else if (GetX() < 0 && !!parX)
|
||||||
|
{
|
||||||
|
fRemove = true; // ...or it's not HUD horizontally and it's out to the left
|
||||||
|
}
|
||||||
|
else if (!parX && GetX() < -::Landscape.GetWidth())
|
||||||
|
{
|
||||||
|
fRemove = true; // ...or it's HUD horizontally and it's out to the left
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (fRemove)
|
if (fRemove)
|
||||||
{
|
{
|
||||||
|
@ -611,41 +776,59 @@ bool SimFlight(C4Real &x, C4Real &y, C4Real &xdir, C4Real &ydir, int32_t iDensit
|
||||||
{
|
{
|
||||||
bool hitOnTime = true;
|
bool hitOnTime = true;
|
||||||
bool fBreak = false;
|
bool fBreak = false;
|
||||||
int32_t ctcox,ctcoy,cx,cy,i;
|
int32_t ctcox, ctcoy;
|
||||||
cx = fixtoi(x); cy = fixtoi(y);
|
int32_t cx = fixtoi(x);
|
||||||
i = iIter;
|
int32_t cy = fixtoi(y);
|
||||||
|
int32_t i = iIter;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (!--i) {hitOnTime = false; break;}
|
if (!--i)
|
||||||
|
{
|
||||||
|
hitOnTime = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
// If the object isn't moving and there is no gravity either, abort
|
// If the object isn't moving and there is no gravity either, abort
|
||||||
if (xdir == 0 && ydir == 0 && GravAccel == 0)
|
if (xdir == 0 && ydir == 0 && GravAccel == 0)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
// If the object is above the landscape flying upwards in no/negative gravity, abort
|
// If the object is above the landscape flying upwards in no/negative gravity, abort
|
||||||
if (ydir <= 0 && GravAccel <= 0 && cy < 0)
|
if (ydir <= 0 && GravAccel <= 0 && cy < 0)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
// Set target position by momentum
|
// Set target position by momentum
|
||||||
x+=xdir; y+=ydir;
|
x += xdir;
|
||||||
|
y += ydir;
|
||||||
// Movement to target
|
// Movement to target
|
||||||
ctcox=fixtoi(x); ctcoy=fixtoi(y);
|
ctcox = fixtoi(x);
|
||||||
|
ctcoy = fixtoi(y);
|
||||||
// Bounds
|
// Bounds
|
||||||
if (!Inside<int32_t>(ctcox,0,::Landscape.GetWidth()) || (ctcoy>=::Landscape.GetHeight()))
|
if (!Inside<int32_t>(ctcox, 0, ::Landscape.GetWidth()) || (ctcoy >= ::Landscape.GetHeight()))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
// Move to target
|
// Move to target
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
// Set next step target
|
// Set next step target
|
||||||
cx+=Sign(ctcox-cx); cy+=Sign(ctcoy-cy);
|
cx += Sign(ctcox - cx);
|
||||||
|
cy += Sign(ctcoy - cy);
|
||||||
// Contact check
|
// Contact check
|
||||||
if (Inside(GBackDensity(cx,cy), iDensityMin, iDensityMax))
|
if (Inside(GBackDensity(cx, cy), iDensityMin, iDensityMax))
|
||||||
{ fBreak = true; break; }
|
{
|
||||||
|
fBreak = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
while ((cx!=ctcox) || (cy!=ctcoy));
|
while ((cx != ctcox) || (cy != ctcoy));
|
||||||
// Adjust GravAccel once per frame
|
// Adjust GravAccel once per frame
|
||||||
ydir+=GravAccel;
|
ydir += GravAccel;
|
||||||
}
|
}
|
||||||
while (!fBreak);
|
while (!fBreak);
|
||||||
// write position back
|
// write position back
|
||||||
x = itofix(cx); y = itofix(cy);
|
x = itofix(cx);
|
||||||
|
y = itofix(cy);
|
||||||
|
|
||||||
// how many steps did it take to get here?
|
// how many steps did it take to get here?
|
||||||
iIter -= i;
|
iIter -= i;
|
||||||
|
@ -656,13 +839,20 @@ bool SimFlight(C4Real &x, C4Real &y, C4Real &xdir, C4Real &ydir, int32_t iDensit
|
||||||
bool SimFlightHitsLiquid(C4Real fcx, C4Real fcy, C4Real xdir, C4Real ydir)
|
bool SimFlightHitsLiquid(C4Real fcx, C4Real fcy, C4Real xdir, C4Real ydir)
|
||||||
{
|
{
|
||||||
// Start in water?
|
// Start in water?
|
||||||
int temp;
|
|
||||||
if (DensityLiquid(GBackDensity(fixtoi(fcx), fixtoi(fcy))))
|
if (DensityLiquid(GBackDensity(fixtoi(fcx), fixtoi(fcy))))
|
||||||
if (!SimFlight(fcx, fcy, xdir, ydir, 0, C4M_Liquid - 1, temp=10))
|
{
|
||||||
|
int temp = 10;
|
||||||
|
if (!SimFlight(fcx, fcy, xdir, ydir, 0, C4M_Liquid - 1, temp))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
// Hits liquid?
|
// Hits liquid?
|
||||||
if (!SimFlight(fcx, fcy, xdir, ydir, C4M_Liquid, 100, temp=-1))
|
int temp = -1;
|
||||||
|
if (!SimFlight(fcx, fcy, xdir, ydir, C4M_Liquid, 100, temp))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
// liquid & deep enough?
|
// liquid & deep enough?
|
||||||
return GBackLiquid(fixtoi(fcx), fixtoi(fcy)) && GBackLiquid(fixtoi(fcx), fixtoi(fcy) + 9);
|
return GBackLiquid(fixtoi(fcx), fixtoi(fcy)) && GBackLiquid(fixtoi(fcx), fixtoi(fcy) + 9);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4125,7 +4125,7 @@ void C4Object::SetRotation(int32_t nr)
|
||||||
while (nr<0) nr+=360;
|
while (nr<0) nr+=360;
|
||||||
nr%=360;
|
nr%=360;
|
||||||
// remove solid mask
|
// remove solid mask
|
||||||
if (pSolidMaskData) pSolidMaskData->Remove(false);
|
RemoveSolidMask(false);
|
||||||
// set rotation
|
// set rotation
|
||||||
fix_r=itofix(nr);
|
fix_r=itofix(nr);
|
||||||
// Update face
|
// Update face
|
||||||
|
@ -4156,6 +4156,14 @@ void C4Object::DrawSolidMask(C4TargetFacet &cgo) const
|
||||||
pSolidMaskData->Draw(cgo);
|
pSolidMaskData->Draw(cgo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void C4Object::RemoveSolidMask(bool fBackupAttachment)
|
||||||
|
{
|
||||||
|
if (pSolidMaskData)
|
||||||
|
{
|
||||||
|
pSolidMaskData->Remove(fBackupAttachment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void C4Object::UpdateSolidMask(bool fRestoreAttachedObjects)
|
void C4Object::UpdateSolidMask(bool fRestoreAttachedObjects)
|
||||||
{
|
{
|
||||||
// solidmask doesn't make sense with non-existant objects
|
// solidmask doesn't make sense with non-existant objects
|
||||||
|
@ -4172,7 +4180,9 @@ void C4Object::UpdateSolidMask(bool fRestoreAttachedObjects)
|
||||||
pSolidMaskData = new C4SolidMask(this);
|
pSolidMaskData = new C4SolidMask(this);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
pSolidMaskData->Remove(false);
|
pSolidMaskData->Remove(false);
|
||||||
|
}
|
||||||
pSolidMaskData->Put(true, nullptr, fRestoreAttachedObjects);
|
pSolidMaskData->Put(true, nullptr, fRestoreAttachedObjects);
|
||||||
SetHalfVehicleSolidMask(HalfVehicleSolidMask);
|
SetHalfVehicleSolidMask(HalfVehicleSolidMask);
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,6 +102,7 @@ class C4Object: public C4PropListNumbered
|
||||||
private:
|
private:
|
||||||
void UpdateInMat();
|
void UpdateInMat();
|
||||||
void Splash();
|
void Splash();
|
||||||
|
void RemoveSolidMask(bool fBackupAttachment); // Remove solid mask data, if existing
|
||||||
public:
|
public:
|
||||||
C4Object();
|
C4Object();
|
||||||
~C4Object() override;
|
~C4Object() override;
|
||||||
|
|
Loading…
Reference in New Issue