diff --git a/src/actionspecials.h b/src/actionspecials.h index de2d86bfb..392efecb4 100644 --- a/src/actionspecials.h +++ b/src/actionspecials.h @@ -85,6 +85,9 @@ DEFINE_SPECIAL(ACS_LockedExecute, 83, 5, 5, 5) DEFINE_SPECIAL(ACS_ExecuteWithResult, 84, 1, 4, 4) DEFINE_SPECIAL(ACS_LockedExecuteDoor, 85, 5, 5, 5) +DEFINE_SPECIAL(Polyobj_Stop, 87, 1, 1, 1) +DEFINE_SPECIAL(Polyobj_MoveTo, 88, 4, 4, 4) +DEFINE_SPECIAL(Polyobj_OR_MoveTo, 89, 4, 4, 4) DEFINE_SPECIAL(Polyobj_OR_RotateLeft, 90, 3, 3, 3) DEFINE_SPECIAL(Polyobj_OR_RotateRight, 91, 3, 3, 3) DEFINE_SPECIAL(Polyobj_OR_Move, 92, 4, 4, 4) diff --git a/src/nodebuild.cpp b/src/nodebuild.cpp index 804190fee..8298e9017 100644 --- a/src/nodebuild.cpp +++ b/src/nodebuild.cpp @@ -228,7 +228,7 @@ void FNodeBuilder::CreateSubsectorsForReal () set = ptr.SegPtr->next; } sub.numlines = (DWORD)(SegList.Size() - firstline); - sub.firstline = (seg_t *)firstline; + sub.firstline = (seg_t *)(size_t)firstline; // Sort segs by linedef for special effects qsort (&SegList[firstline], sub.numlines, sizeof(USegPtr), SortSegs); @@ -1107,12 +1107,12 @@ int ClassifyLineBackpatchC (node_t &node, const FSimpleVert *v1, const FSimpleVe if (CPU.bSSE2) { func = ClassifyLineSSE2; - diff = (char *)ClassifyLineSSE2 - (char *)calleroffset; + diff = int((char *)ClassifyLineSSE2 - (char *)calleroffset); } else { func = ClassifyLine2; - diff = (char *)ClassifyLine2 - (char *)calleroffset; + diff = int((char *)ClassifyLine2 - (char *)calleroffset); } calleroffset--; diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index fb0bd31ab..61df5806d 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -121,6 +121,12 @@ FUNC(LS_Polyobj_MoveTimes8) return EV_MovePoly (ln, arg0, SPEED(arg1), BYTEANGLE(arg2), arg3 * FRACUNIT * 8, false); } +FUNC(LS_Polyobj_MoveTo) +// Polyobj_MoveTo (po, speed, x, y) +{ + return EV_MovePolyTo (ln, arg0, SPEED(arg1), arg2, arg3, false); +} + FUNC(LS_Polyobj_DoorSwing) // Polyobj_DoorSwing (po, speed, angle, delay) { @@ -157,6 +163,18 @@ FUNC(LS_Polyobj_OR_MoveTimes8) return EV_MovePoly (ln, arg0, SPEED(arg1), BYTEANGLE(arg2), arg3 * FRACUNIT * 8, true); } +FUNC(LS_Polyobj_OR_MoveTo) +// Polyobj_OR_MoveTo (po, speed, x, y) +{ + return EV_MovePolyTo (ln, arg0, SPEED(arg1), arg2, arg3, true); +} + +FUNC(LS_Polyobj_Stop) +// Polyobj_Stop (po) +{ + return EV_StopPoly (arg0); +} + FUNC(LS_Door_Close) // Door_Close (tag, speed, lighttag) { @@ -3060,9 +3078,9 @@ lnSpecFunc LineSpecials[256] = /* 84 */ LS_ACS_ExecuteWithResult, /* 85 */ LS_ACS_LockedExecuteDoor, /* 86 */ LS_NOP, - /* 87 */ LS_NOP, - /* 88 */ LS_NOP, - /* 89 */ LS_NOP, + /* 87 */ LS_Polyobj_Stop, + /* 88 */ LS_Polyobj_MoveTo, + /* 89 */ LS_Polyobj_OR_MoveTo, /* 90 */ LS_Polyobj_OR_RotateLeft, /* 91 */ LS_Polyobj_OR_RotateRight, /* 92 */ LS_Polyobj_OR_Move, diff --git a/src/p_local.h b/src/p_local.h index eb69a23c7..6978be19d 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -506,8 +506,9 @@ typedef enum bool EV_RotatePoly (line_t *line, int polyNum, int speed, int byteAngle, int direction, bool overRide); bool EV_MovePoly (line_t *line, int polyNum, int speed, angle_t angle, fixed_t dist, bool overRide); +bool EV_MovePolyTo (line_t *line, int polyNum, int speed, int x, int y, bool overRide); bool EV_OpenPolyDoor (line_t *line, int polyNum, int speed, angle_t angle, int delay, int distance, podoortype_t type); - +bool EV_StopPoly (int polyNum); // [RH] Data structure for P_SpawnMapThing() to keep track diff --git a/src/po_man.cpp b/src/po_man.cpp index 93662f64e..535d1f2dc 100644 --- a/src/po_man.cpp +++ b/src/po_man.cpp @@ -28,6 +28,7 @@ #include "g_level.h" #include "po_man.h" #include "p_setup.h" +#include "vectors.h" // MACROS ------------------------------------------------------------------ @@ -62,6 +63,7 @@ public: DPolyAction (int polyNum); void Serialize (FArchive &arc); void Destroy(); + void Stop(); int GetSpeed() const { return m_Speed; } void StopInterpolation (); @@ -104,6 +106,23 @@ protected: friend bool EV_MovePoly (line_t *line, int polyNum, int speed, angle_t angle, fixed_t dist, bool overRide); }; +class DMovePolyTo : public DPolyAction +{ + DECLARE_CLASS(DMovePolyTo, DPolyAction) +public: + DMovePolyTo(int polyNum); + void Serialize(FArchive &arc); + void Tick(); +protected: + DMovePolyTo(); + fixed_t m_xSpeed; + fixed_t m_ySpeed; + fixed_t m_xTarget; + fixed_t m_yTarget; + + friend bool EV_MovePolyTo(line_t *line, int polyNum, int speed, int x, int y, bool overRide); +}; + class DPolyDoor : public DMovePoly { @@ -199,7 +218,7 @@ void DPolyAction::Destroy() { FPolyObj *poly = PO_GetPolyobj (m_PolyObj); - if (poly->specialdata == NULL || poly->specialdata == this) + if (poly->specialdata == this) { poly->specialdata = NULL; } @@ -208,6 +227,13 @@ void DPolyAction::Destroy() Super::Destroy(); } +void DPolyAction::Stop() +{ + FPolyObj *poly = PO_GetPolyobj(m_PolyObj); + SN_StopSequence(poly); + Destroy(); +} + void DPolyAction::SetInterpolation () { FPolyObj *poly = PO_GetPolyobj (m_PolyObj); @@ -266,6 +292,34 @@ DMovePoly::DMovePoly (int polyNum) m_ySpeed = 0; } +//========================================================================== +// +// +// +// +//========================================================================== + +IMPLEMENT_CLASS(DMovePolyTo) + +DMovePolyTo::DMovePolyTo() +{ +} + +void DMovePolyTo::Serialize(FArchive &arc) +{ + Super::Serialize(arc); + arc << m_xSpeed << m_ySpeed << m_xTarget << m_yTarget; +} + +DMovePolyTo::DMovePolyTo(int polyNum) + : Super(polyNum) +{ + m_xSpeed = 0; + m_ySpeed = 0; + m_xTarget = 0; + m_yTarget = 0; +} + //========================================================================== // // @@ -318,10 +372,6 @@ void DRotatePoly::Tick () m_Dist -= absSpeed; if (m_Dist == 0) { - if (poly->specialdata == this) - { - poly->specialdata = NULL; - } SN_StopSequence (poly); Destroy (); } @@ -433,10 +483,6 @@ void DMovePoly::Tick () m_Dist -= absSpeed; if (m_Dist <= 0) { - if (poly->specialdata == this) - { - poly->specialdata = NULL; - } SN_StopSequence (poly); Destroy (); } @@ -522,6 +568,111 @@ bool EV_MovePoly (line_t *line, int polyNum, int speed, angle_t angle, return true; } +//========================================================================== +// +// DMovePolyTo :: Tick +// +//========================================================================== + +void DMovePolyTo::Tick () +{ + FPolyObj *poly = PO_GetPolyobj (m_PolyObj); + + if (poly != NULL) + { + if (poly->MovePolyobj (m_xSpeed, m_ySpeed)) + { + int absSpeed = abs (m_Speed); + m_Dist -= absSpeed; + if (m_Dist <= 0) + { + SN_StopSequence (poly); + Destroy (); + } + else if (m_Dist < absSpeed) + { + m_Speed = m_Dist * (m_Speed < 0 ? -1 : 1); + m_xSpeed = m_xTarget - poly->StartSpot.x; + m_ySpeed = m_yTarget - poly->StartSpot.y; + } + } + } +} + +//========================================================================== +// +// EV_MovePolyTo +// +//========================================================================== + +bool EV_MovePolyTo(line_t *line, int polyNum, int speed, int ix, int iy, bool overRide) +{ + fixed_t targx = ix << FRACBITS; + fixed_t targy = iy << FRACBITS; + int mirror; + DMovePolyTo *pe; + FPolyObj *poly; + TVector2 dist; + double distlen; + bool nointerp; + + if ( (poly = PO_GetPolyobj(polyNum)) ) + { + if (poly->specialdata && !overRide) + { // poly is already moving + return false; + } + } + else + { + Printf("EV_MovePolyTo: Invalid polyobj num: %d\n", polyNum); + return false; + } + dist.X = targx - poly->StartSpot.x; + dist.Y = targy - poly->StartSpot.y; + pe = new DMovePolyTo(polyNum); + poly->specialdata = pe; + pe->m_Dist = xs_RoundToInt(distlen = dist.MakeUnit()); + pe->m_Speed = speed; + pe->m_xSpeed = xs_RoundToInt(speed * dist.X); + pe->m_ySpeed = xs_RoundToInt(speed * dist.Y); + pe->m_xTarget = targx; + pe->m_yTarget = targy; + + nointerp = (pe->m_Dist / pe->m_Speed) <= 2; + if (nointerp) + { + pe->StopInterpolation(); + } + + while ( (mirror = poly->GetMirror()) ) + { + poly = PO_GetPolyobj(mirror); + if (poly && poly->specialdata && !overRide) + { // mirroring poly is already in motion + break; + } + // reverse the direction + dist.X = -dist.X; + dist.Y = -dist.Y; + pe = new DMovePolyTo(mirror); + poly->specialdata = pe; + pe->m_Dist = xs_RoundToInt(distlen); + pe->m_Speed = speed; + pe->m_xSpeed = xs_RoundToInt(speed * dist.X); + pe->m_ySpeed = xs_RoundToInt(speed * dist.Y); + pe->m_xTarget = xs_RoundToInt(poly->StartSpot.x + distlen * dist.X); + pe->m_yTarget = xs_RoundToInt(poly->StartSpot.y + distlen * dist.Y); + polyNum = mirror; + SN_StartSequence(poly, poly->seqType, SEQ_DOOR, 0); + if (nointerp) + { + pe->StopInterpolation(); + } + } + return true; +} + //========================================================================== // // T_PolyDoor @@ -564,10 +715,6 @@ void DPolyDoor::Tick () } else { - if (poly->specialdata == this) - { - poly->specialdata = NULL; - } Destroy (); } } @@ -612,10 +759,6 @@ void DPolyDoor::Tick () } else { - if (poly->specialdata == this) - { - poly->specialdata = NULL; - } Destroy (); } } @@ -719,7 +862,28 @@ bool EV_OpenPolyDoor (line_t *line, int polyNum, int speed, angle_t angle, } return true; } - + +//========================================================================== +// +// EV_StopPoly +// +//========================================================================== + +bool EV_StopPoly(int polynum) +{ + FPolyObj *poly; + + if (NULL != (poly = PO_GetPolyobj(polynum))) + { + if (poly->specialdata != NULL) + { + poly->specialdata->Stop(); + } + return true; + } + return false; +} + // ===== Higher Level Poly Interface code ===== //========================================================================== diff --git a/src/po_man.h b/src/po_man.h index 3d963f33b..d76dff55f 100644 --- a/src/po_man.h +++ b/src/po_man.h @@ -63,7 +63,7 @@ struct FPolyObj int seqType; fixed_t size; // polyobj size (area of POLY_AREAUNIT == size of FRACUNIT) FPolyNode *subsectorlinks; - DThinker *specialdata; // pointer to a thinker, if the poly is moving + DPolyAction *specialdata; // pointer to a thinker, if the poly is moving TObjPtr interpolation; FPolyObj(); diff --git a/src/vectors.h b/src/vectors.h index 013077042..c0783e250 100644 --- a/src/vectors.h +++ b/src/vectors.h @@ -242,12 +242,14 @@ struct TVector2 return *this * len; } - // Scales this vector into a unit vector - void MakeUnit() + // Scales this vector into a unit vector. Returns the old length + double MakeUnit() { - double len = Length(); - if (len != 0) len = 1 / len; - *this *= len; + double len, ilen; + len = ilen = Length(); + if (ilen != 0) ilen = 1 / ilen; + *this *= ilen; + return len; } // Dot product