From b561ee792192aa9b8adb28971587ef69a897e34c Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 13 May 2020 14:40:07 +0200 Subject: [PATCH 1/9] Remove diffx/y/z from polywaypoint_t, since they're always 0 anyway --- src/p_polyobj.c | 37 +++++++++++++++---------------------- src/p_polyobj.h | 5 ----- src/p_saveg.c | 6 ------ 3 files changed, 15 insertions(+), 33 deletions(-) diff --git a/src/p_polyobj.c b/src/p_polyobj.c index b1da51462..e2c4ff519 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -1573,7 +1573,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th) { mobj_t *target = NULL; mobj_t *waypoint = NULL; - fixed_t adjustx, adjusty, adjustz; + fixed_t pox, poy, poz; fixed_t momx, momy, momz, dist; INT32 start; polyobj_t *po = Polyobj_GetForNum(th->polyObjNum); @@ -1602,32 +1602,31 @@ void T_PolyObjWaypoint(polywaypoint_t *th) return; } - // Compensate for position offset - adjustx = po->centerPt.x + th->diffx; - adjusty = po->centerPt.y + th->diffy; - adjustz = po->lines[0]->backsector->floorheight + (po->lines[0]->backsector->ceilingheight - po->lines[0]->backsector->floorheight)/2 + th->diffz; + pox = po->centerPt.x; + poy = po->centerPt.y; + poz = (po->lines[0]->backsector->floorheight + po->lines[0]->backsector->ceilingheight)/2; - dist = P_AproxDistance(P_AproxDistance(target->x - adjustx, target->y - adjusty), target->z - adjustz); + dist = P_AproxDistance(P_AproxDistance(target->x - pox, target->y - poy), target->z - poz); if (dist < 1) dist = 1; - momx = FixedMul(FixedDiv(target->x - adjustx, dist), (th->speed)); - momy = FixedMul(FixedDiv(target->y - adjusty, dist), (th->speed)); - momz = FixedMul(FixedDiv(target->z - adjustz, dist), (th->speed)); + momx = FixedMul(FixedDiv(target->x - pox, dist), th->speed); + momy = FixedMul(FixedDiv(target->y - poy, dist), th->speed); + momz = FixedMul(FixedDiv(target->z - poz, dist), th->speed); // Calculate the distance between the polyobject and the waypoint // 'dist' already equals this. // Will the polyobject be FURTHER away if the momx/momy/momz is added to // its current coordinates, or closer? (shift down to fracunits to avoid approximation errors) - if (dist>>FRACBITS <= P_AproxDistance(P_AproxDistance(target->x - adjustx - momx, target->y - adjusty - momy), target->z - adjustz - momz)>>FRACBITS) + if (dist>>FRACBITS <= P_AproxDistance(P_AproxDistance(target->x - pox - momx, target->y - poy - momy), target->z - poz - momz)>>FRACBITS) { // If further away, set XYZ of polyobject to waypoint location fixed_t amtx, amty, amtz; fixed_t diffz; - amtx = (target->x - th->diffx) - po->centerPt.x; - amty = (target->y - th->diffy) - po->centerPt.y; + amtx = target->x - po->centerPt.x; + amty = target->y - po->centerPt.y; Polyobj_moveXY(po, amtx, amty, true); // TODO: use T_MovePlane amtz = (po->lines[0]->backsector->ceilingheight - po->lines[0]->backsector->floorheight)/2; @@ -1694,14 +1693,14 @@ void T_PolyObjWaypoint(polywaypoint_t *th) // calculate MOMX/MOMY/MOMZ for next waypoint // change slope - dist = P_AproxDistance(P_AproxDistance(target->x - adjustx, target->y - adjusty), target->z - adjustz); + dist = P_AproxDistance(P_AproxDistance(target->x - pox, target->y - poy), target->z - poz); if (dist < 1) dist = 1; - momx = FixedMul(FixedDiv(target->x - adjustx, dist), (th->speed)); - momy = FixedMul(FixedDiv(target->y - adjusty, dist), (th->speed)); - momz = FixedMul(FixedDiv(target->z - adjustz, dist), (th->speed)); + momx = FixedMul(FixedDiv(target->x - pox, dist), th->speed); + momy = FixedMul(FixedDiv(target->y - poy, dist), th->speed); + momz = FixedMul(FixedDiv(target->z - poz, dist), th->speed); } else { @@ -2215,12 +2214,6 @@ boolean EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata) if (!last) last = first; - // Set diffx, diffy, diffz - // Put these at 0 for now...might not be needed after all. - th->diffx = 0;//first->x - po->centerPt.x; - th->diffy = 0;//first->y - po->centerPt.y; - th->diffz = 0;//first->z - (po->lines[0]->backsector->floorheight + (po->lines[0]->backsector->ceilingheight - po->lines[0]->backsector->floorheight)/2); - if (last->x == po->centerPt.x && last->y == po->centerPt.y && last->z == (po->lines[0]->backsector->floorheight + (po->lines[0]->backsector->ceilingheight - po->lines[0]->backsector->floorheight)/2)) diff --git a/src/p_polyobj.h b/src/p_polyobj.h index 68aff4bf1..b2331449f 100644 --- a/src/p_polyobj.h +++ b/src/p_polyobj.h @@ -154,11 +154,6 @@ typedef struct polywaypoint_s UINT8 continuous; // continuously move - used with COMEBACK or WRAP UINT8 stophere; // Will stop after it reaches the next waypoint - // Difference between location of PO and location of waypoint (offset) - fixed_t diffx; - fixed_t diffy; - fixed_t diffz; - mobj_t *target; // next waypoint mobj } polywaypoint_t; diff --git a/src/p_saveg.c b/src/p_saveg.c index 34bd3724b..5e5e82453 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2023,9 +2023,6 @@ static void SavePolywaypointThinker(const thinker_t *th, UINT8 type) WRITEUINT8(save_p, ht->wrap); WRITEUINT8(save_p, ht->continuous); WRITEUINT8(save_p, ht->stophere); - WRITEFIXED(save_p, ht->diffx); - WRITEFIXED(save_p, ht->diffy); - WRITEFIXED(save_p, ht->diffz); WRITEUINT32(save_p, SaveMobjnum(ht->target)); } @@ -3168,9 +3165,6 @@ static inline thinker_t* LoadPolywaypointThinker(actionf_p1 thinker) ht->wrap = READUINT8(save_p); ht->continuous = READUINT8(save_p); ht->stophere = READUINT8(save_p); - ht->diffx = READFIXED(save_p); - ht->diffy = READFIXED(save_p); - ht->diffz = READFIXED(save_p); ht->target = LoadMobj(READUINT32(save_p)); return &ht->thinker; } From 7413da918b1d4a7b4b196eb74a1832657c51897c Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 13 May 2020 16:21:47 +0200 Subject: [PATCH 2/9] Store PolyObject waypoint return behavior in an enum --- src/p_polyobj.c | 17 +++++++---------- src/p_polyobj.h | 38 ++++++++++++++++++++++---------------- src/p_saveg.c | 6 ++---- src/p_spec.c | 13 ++++++++++--- 4 files changed, 41 insertions(+), 33 deletions(-) diff --git a/src/p_polyobj.c b/src/p_polyobj.c index e2c4ff519..8ba5fadac 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -1606,6 +1606,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th) poy = po->centerPt.y; poz = (po->lines[0]->backsector->floorheight + po->lines[0]->backsector->ceilingheight)/2; + // Calculate the distance between the polyobject and the waypoint dist = P_AproxDistance(P_AproxDistance(target->x - pox, target->y - poy), target->z - poz); if (dist < 1) @@ -1615,9 +1616,6 @@ void T_PolyObjWaypoint(polywaypoint_t *th) momy = FixedMul(FixedDiv(target->y - poy, dist), th->speed); momz = FixedMul(FixedDiv(target->z - poz, dist), th->speed); - // Calculate the distance between the polyobject and the waypoint - // 'dist' already equals this. - // Will the polyobject be FURTHER away if the momx/momy/momz is added to // its current coordinates, or closer? (shift down to fracunits to avoid approximation errors) if (dist>>FRACBITS <= P_AproxDistance(P_AproxDistance(target->x - pox - momx, target->y - poy - momy), target->z - poz - momz)>>FRACBITS) @@ -1661,22 +1659,22 @@ void T_PolyObjWaypoint(polywaypoint_t *th) CONS_Debug(DBG_POLYOBJ, "Looking for next waypoint...\n"); waypoint = (th->direction == -1) ? P_GetPreviousWaypoint(target, false) : P_GetNextWaypoint(target, false); - if (!waypoint && th->wrap) // If specified, wrap waypoints + if (!waypoint && th->returnbehavior == PWR_WRAP) // If specified, wrap waypoints { if (!th->continuous) { - th->wrap = 0; + th->returnbehavior = PWR_STOP; th->stophere = true; } waypoint = (th->direction == -1) ? P_GetLastWaypoint(th->sequence) : P_GetFirstWaypoint(th->sequence); } - else if (!waypoint && th->comeback) // Come back to the start + else if (!waypoint && th->returnbehavior == PWR_COMEBACK) // Come back to the start { th->direction = -th->direction; if (!th->continuous) - th->comeback = false; + th->returnbehavior = PWR_STOP; waypoint = (th->direction == -1) ? P_GetPreviousWaypoint(target, false) : P_GetNextWaypoint(target, false); } @@ -2193,9 +2191,8 @@ boolean EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata) th->sequence = pwdata->sequence; // Used to specify sequence # th->direction = pwdata->reverse ? -1 : 1; - th->comeback = pwdata->comeback; + th->returnbehavior = pwdata->returnbehavior; th->continuous = pwdata->continuous; - th->wrap = pwdata->wrap; th->stophere = false; // Find the first waypoint we need to use @@ -2219,7 +2216,7 @@ boolean EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata) && last->z == (po->lines[0]->backsector->floorheight + (po->lines[0]->backsector->ceilingheight - po->lines[0]->backsector->floorheight)/2)) { // Already at the destination point... - if (!th->wrap) + if (th->returnbehavior != PWR_WRAP) { po->thinker = NULL; P_RemoveThinker(&th->thinker); diff --git a/src/p_polyobj.h b/src/p_polyobj.h index b2331449f..6b0016195 100644 --- a/src/p_polyobj.h +++ b/src/p_polyobj.h @@ -140,19 +140,26 @@ typedef struct polymove_s UINT32 angle; // angle along which to move } polymove_t; +// PolyObject waypoint movement return behavior +typedef enum +{ + PWR_STOP, // Stop after reaching last waypoint + PWR_WRAP, // Wrap back to first waypoint + PWR_COMEBACK, // Repeat sequence in reverse +} polywaypointreturn_e; + typedef struct polywaypoint_s { thinker_t thinker; // must be first - INT32 polyObjNum; // numeric id of polyobject - INT32 speed; // resultant velocity - INT32 sequence; // waypoint sequence # - INT32 pointnum; // waypoint # - INT32 direction; // 1 for normal, -1 for backwards - UINT8 comeback; // reverses and comes back when the end is reached - UINT8 wrap; // Wrap around waypoints - UINT8 continuous; // continuously move - used with COMEBACK or WRAP - UINT8 stophere; // Will stop after it reaches the next waypoint + INT32 polyObjNum; // numeric id of polyobject + INT32 speed; // resultant velocity + INT32 sequence; // waypoint sequence # + INT32 pointnum; // waypoint # + INT32 direction; // 1 for normal, -1 for backwards + UINT8 returnbehavior; // behavior after reaching the last waypoint + UINT8 continuous; // continuously move - used with PWR_WRAP or PWR_COMEBACK + UINT8 stophere; // Will stop after it reaches the next waypoint mobj_t *target; // next waypoint mobj } polywaypoint_t; @@ -251,13 +258,12 @@ typedef struct polymovedata_s typedef struct polywaypointdata_s { - INT32 polyObjNum; // numeric id of polyobject to affect - INT32 sequence; // waypoint sequence # - fixed_t speed; // linear speed - UINT8 reverse; // if true, will go in reverse waypoint order - UINT8 comeback; // reverses and comes back when the end is reached - UINT8 wrap; // Wrap around waypoints - UINT8 continuous; // continuously move - used with COMEBACK or WRAP + INT32 polyObjNum; // numeric id of polyobject to affect + INT32 sequence; // waypoint sequence # + fixed_t speed; // linear speed + UINT8 reverse; // if true, will go in reverse waypoint order + UINT8 returnbehavior; // behavior after reaching the last waypoint + UINT8 continuous; // continuously move - used with PWR_WRAP or PWR_COMEBACK } polywaypointdata_t; // polyobject door types diff --git a/src/p_saveg.c b/src/p_saveg.c index 5e5e82453..e4393826d 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2019,8 +2019,7 @@ static void SavePolywaypointThinker(const thinker_t *th, UINT8 type) WRITEINT32(save_p, ht->sequence); WRITEINT32(save_p, ht->pointnum); WRITEINT32(save_p, ht->direction); - WRITEUINT8(save_p, ht->comeback); - WRITEUINT8(save_p, ht->wrap); + WRITEUINT8(save_p, ht->returnbehavior); WRITEUINT8(save_p, ht->continuous); WRITEUINT8(save_p, ht->stophere); WRITEUINT32(save_p, SaveMobjnum(ht->target)); @@ -3161,8 +3160,7 @@ static inline thinker_t* LoadPolywaypointThinker(actionf_p1 thinker) ht->sequence = READINT32(save_p); ht->pointnum = READINT32(save_p); ht->direction = READINT32(save_p); - ht->comeback = READUINT8(save_p); - ht->wrap = READUINT8(save_p); + ht->returnbehavior = READUINT8(save_p); ht->continuous = READUINT8(save_p); ht->stophere = READUINT8(save_p); ht->target = LoadMobj(READUINT32(save_p)); diff --git a/src/p_spec.c b/src/p_spec.c index ae525441c..99657aab9 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1277,9 +1277,16 @@ static boolean PolyWaypoint(line_t *line) pwd.speed = sides[line->sidenum[0]].textureoffset / 8; pwd.sequence = sides[line->sidenum[0]].rowoffset >> FRACBITS; // Sequence # pwd.reverse = (line->flags & ML_EFFECT1) == ML_EFFECT1; // Reverse? - pwd.comeback = (line->flags & ML_EFFECT2) == ML_EFFECT2; // Return when reaching end? - pwd.wrap = (line->flags & ML_EFFECT3) == ML_EFFECT3; // Wrap around waypoints - pwd.continuous = (line->flags & ML_EFFECT4) == ML_EFFECT4; // Continuously move - used with COMEBACK or WRAP + + // Behavior after reaching the last waypoint? + if (line->flags & ML_EFFECT3) + pwd.returnbehavior = PWR_WRAP; // Wrap back to first waypoint + else if (line->flags & ML_EFFECT2) + pwd.returnbehavior = PWR_COMEBACK; // Go through sequence in reverse + else + pwd.returnbehavior = PWR_STOP; // Stop + + pwd.continuous = (line->flags & ML_EFFECT4) == ML_EFFECT4; // Continuously move - used with PWR_WRAP or PWR_COMEBACK return EV_DoPolyObjWaypoint(&pwd); } From 0508f99419dbb7065c016d9e05b76f7366223359 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Fri, 15 May 2020 17:35:07 +0200 Subject: [PATCH 3/9] T_PolyObjWaypoint: Move duplicated movement code into its own function --- src/p_polyobj.c | 97 ++++++++++++++++++------------------------------- 1 file changed, 36 insertions(+), 61 deletions(-) diff --git a/src/p_polyobj.c b/src/p_polyobj.c index 8ba5fadac..ea8a3d5cb 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -1569,15 +1569,42 @@ void T_PolyObjMove(polymove_t *th) } } +static void T_MovePolyObj(polyobj_t *po, fixed_t distx, fixed_t disty, fixed_t distz) +{ + polyobj_t *child; + INT32 start; + + Polyobj_moveXY(po, distx, disty, true); + // TODO: use T_MovePlane + po->lines[0]->backsector->floorheight += distz; + po->lines[0]->backsector->ceilingheight += distz; + // Sal: Remember to check your sectors! + // Monster Iestyn: we only need to bother with the back sector, now that P_CheckSector automatically checks the blockmap + // updating objects in the front one too just added teleporting to ground bugs + P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage)); + // Apply action to mirroring polyobjects as well + start = 0; + while ((child = Polyobj_GetChild(po, &start))) + { + if (child->isBad) + continue; + + Polyobj_moveXY(child, distx, disty, true); + // TODO: use T_MovePlane + child->lines[0]->backsector->floorheight += distz; + child->lines[0]->backsector->ceilingheight += distz; + P_CheckSector(child->lines[0]->backsector, (boolean)(child->damage)); + } +} + void T_PolyObjWaypoint(polywaypoint_t *th) { mobj_t *target = NULL; mobj_t *waypoint = NULL; fixed_t pox, poy, poz; - fixed_t momx, momy, momz, dist; - INT32 start; + fixed_t distx, disty, distz, dist; + fixed_t momx, momy, momz; polyobj_t *po = Polyobj_GetForNum(th->polyObjNum); - polyobj_t *oldpo = po; if (!po) #ifdef RANGECHECK @@ -1607,7 +1634,10 @@ void T_PolyObjWaypoint(polywaypoint_t *th) poz = (po->lines[0]->backsector->floorheight + po->lines[0]->backsector->ceilingheight)/2; // Calculate the distance between the polyobject and the waypoint - dist = P_AproxDistance(P_AproxDistance(target->x - pox, target->y - poy), target->z - poz); + distx = target->x - pox; + disty = target->y - poy; + distz = target->z - poz; + dist = P_AproxDistance(P_AproxDistance(distx, disty), distz); if (dist < 1) dist = 1; @@ -1621,38 +1651,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th) if (dist>>FRACBITS <= P_AproxDistance(P_AproxDistance(target->x - pox - momx, target->y - poy - momy), target->z - poz - momz)>>FRACBITS) { // If further away, set XYZ of polyobject to waypoint location - fixed_t amtx, amty, amtz; - fixed_t diffz; - amtx = target->x - po->centerPt.x; - amty = target->y - po->centerPt.y; - Polyobj_moveXY(po, amtx, amty, true); - // TODO: use T_MovePlane - amtz = (po->lines[0]->backsector->ceilingheight - po->lines[0]->backsector->floorheight)/2; - diffz = po->lines[0]->backsector->floorheight - (target->z - amtz); - po->lines[0]->backsector->floorheight = target->z - amtz; - po->lines[0]->backsector->ceilingheight = target->z + amtz; - // Sal: Remember to check your sectors! - // Monster Iestyn: we only need to bother with the back sector, now that P_CheckSector automatically checks the blockmap - // updating objects in the front one too just added teleporting to ground bugs - P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage)); - // Apply action to mirroring polyobjects as well - start = 0; - while ((po = Polyobj_GetChild(oldpo, &start))) - { - if (po->isBad) - continue; - - Polyobj_moveXY(po, amtx, amty, true); - // TODO: use T_MovePlane - po->lines[0]->backsector->floorheight += diffz; // move up/down by same amount as the parent did - po->lines[0]->backsector->ceilingheight += diffz; - // Sal: Remember to check your sectors! - // Monster Iestyn: we only need to bother with the back sector, now that P_CheckSector automatically checks the blockmap - // updating objects in the front one too just added teleporting to ground bugs - P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage)); - } - - po = oldpo; + T_MovePolyObj(po, distx, disty, distz); if (!th->stophere) { @@ -1720,31 +1719,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th) } // Move the polyobject - Polyobj_moveXY(po, momx, momy, true); - // TODO: use T_MovePlane - po->lines[0]->backsector->floorheight += momz; - po->lines[0]->backsector->ceilingheight += momz; - // Sal: Remember to check your sectors! - // Monster Iestyn: we only need to bother with the back sector, now that P_CheckSector automatically checks the blockmap - // updating objects in the front one too just added teleporting to ground bugs - P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage)); - - // Apply action to mirroring polyobjects as well - start = 0; - while ((po = Polyobj_GetChild(oldpo, &start))) - { - if (po->isBad) - continue; - - Polyobj_moveXY(po, momx, momy, true); - // TODO: use T_MovePlane - po->lines[0]->backsector->floorheight += momz; - po->lines[0]->backsector->ceilingheight += momz; - // Sal: Remember to check your sectors! - // Monster Iestyn: we only need to bother with the back sector, now that P_CheckSector automatically checks the blockmap - // updating objects in the front one too just added teleporting to ground bugs - P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage)); - } + T_MovePolyObj(po, momx, momy, momz); } void T_PolyDoorSlide(polyslidedoor_t *th) From e422d1fa1df8bf2e758d7bc9cb1534a8b8f88ec3 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 16 May 2020 08:45:06 +0200 Subject: [PATCH 4/9] Rewrite T_PolyObjWaypoint to move more smoothly --- src/p_polyobj.c | 159 +++++++++++++++++++++++------------------------- 1 file changed, 77 insertions(+), 82 deletions(-) diff --git a/src/p_polyobj.c b/src/p_polyobj.c index ea8a3d5cb..b81346ec3 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -1600,11 +1600,8 @@ static void T_MovePolyObj(polyobj_t *po, fixed_t distx, fixed_t disty, fixed_t d void T_PolyObjWaypoint(polywaypoint_t *th) { mobj_t *target = NULL; - mobj_t *waypoint = NULL; - fixed_t pox, poy, poz; - fixed_t distx, disty, distz, dist; - fixed_t momx, momy, momz; polyobj_t *po = Polyobj_GetForNum(th->polyObjNum); + fixed_t speed = th->speed; if (!po) #ifdef RANGECHECK @@ -1629,97 +1626,95 @@ void T_PolyObjWaypoint(polywaypoint_t *th) return; } - pox = po->centerPt.x; - poy = po->centerPt.y; - poz = (po->lines[0]->backsector->floorheight + po->lines[0]->backsector->ceilingheight)/2; - - // Calculate the distance between the polyobject and the waypoint - distx = target->x - pox; - disty = target->y - poy; - distz = target->z - poz; - dist = P_AproxDistance(P_AproxDistance(distx, disty), distz); - - if (dist < 1) - dist = 1; - - momx = FixedMul(FixedDiv(target->x - pox, dist), th->speed); - momy = FixedMul(FixedDiv(target->y - poy, dist), th->speed); - momz = FixedMul(FixedDiv(target->z - poz, dist), th->speed); - - // Will the polyobject be FURTHER away if the momx/momy/momz is added to - // its current coordinates, or closer? (shift down to fracunits to avoid approximation errors) - if (dist>>FRACBITS <= P_AproxDistance(P_AproxDistance(target->x - pox - momx, target->y - poy - momy), target->z - poz - momz)>>FRACBITS) + // Move along the waypoint sequence until speed for the current tic is exhausted + while (speed > 0) { - // If further away, set XYZ of polyobject to waypoint location - T_MovePolyObj(po, distx, disty, distz); + mobj_t *waypoint = NULL; + fixed_t pox, poy, poz; + fixed_t distx, disty, distz, dist; - if (!th->stophere) + // Current position of polyobject + pox = po->centerPt.x; + poy = po->centerPt.y; + poz = (po->lines[0]->backsector->floorheight + po->lines[0]->backsector->ceilingheight)/2; + + // Calculate the distance between the polyobject and the waypoint + distx = target->x - pox; + disty = target->y - poy; + distz = target->z - poz; + dist = P_AproxDistance(P_AproxDistance(distx, disty), distz); + + if (dist < 1) + dist = 1; + + // Will the polyobject overshoot its target? + if (speed <= dist) { - CONS_Debug(DBG_POLYOBJ, "Looking for next waypoint...\n"); - waypoint = (th->direction == -1) ? P_GetPreviousWaypoint(target, false) : P_GetNextWaypoint(target, false); + // No. Move towards waypoint + fixed_t momx, momy, momz; - if (!waypoint && th->returnbehavior == PWR_WRAP) // If specified, wrap waypoints - { - if (!th->continuous) - { - th->returnbehavior = PWR_STOP; - th->stophere = true; - } - - waypoint = (th->direction == -1) ? P_GetLastWaypoint(th->sequence) : P_GetFirstWaypoint(th->sequence); - } - else if (!waypoint && th->returnbehavior == PWR_COMEBACK) // Come back to the start - { - th->direction = -th->direction; - - if (!th->continuous) - th->returnbehavior = PWR_STOP; - - waypoint = (th->direction == -1) ? P_GetPreviousWaypoint(target, false) : P_GetNextWaypoint(target, false); - } - } - - if (waypoint) - { - CONS_Debug(DBG_POLYOBJ, "Found waypoint (sequence %d, number %d).\n", waypoint->threshold, waypoint->health); - - target = waypoint; - th->pointnum = target->health; - // Set the mobj as your target! -- Monster Iestyn 27/12/19 - P_SetTarget(&th->target, target); - - // calculate MOMX/MOMY/MOMZ for next waypoint - // change slope - dist = P_AproxDistance(P_AproxDistance(target->x - pox, target->y - poy), target->z - poz); - - if (dist < 1) - dist = 1; - - momx = FixedMul(FixedDiv(target->x - pox, dist), th->speed); - momy = FixedMul(FixedDiv(target->y - poy, dist), th->speed); - momz = FixedMul(FixedDiv(target->z - poz, dist), th->speed); + momx = FixedMul(FixedDiv(target->x - pox, dist), speed); + momy = FixedMul(FixedDiv(target->y - poy, dist), speed); + momz = FixedMul(FixedDiv(target->z - poz, dist), speed); + T_MovePolyObj(po, momx, momy, momz); + return; } else { - momx = momy = momz = 0; + // Yes. Teleport to waypoint and look for the next one + T_MovePolyObj(po, distx, disty, distz); if (!th->stophere) - CONS_Debug(DBG_POLYOBJ, "Next waypoint not found!\n"); + { + CONS_Debug(DBG_POLYOBJ, "Looking for next waypoint...\n"); + waypoint = (th->direction == -1) ? P_GetPreviousWaypoint(target, false) : P_GetNextWaypoint(target, false); - if (po->thinker == &th->thinker) - po->thinker = NULL; + if (!waypoint && th->returnbehavior == PWR_WRAP) // If specified, wrap waypoints + { + if (!th->continuous) + { + th->returnbehavior = PWR_STOP; + th->stophere = true; + } - P_RemoveThinker(&th->thinker); - return; + waypoint = (th->direction == -1) ? P_GetLastWaypoint(th->sequence) : P_GetFirstWaypoint(th->sequence); + } + else if (!waypoint && th->returnbehavior == PWR_COMEBACK) // Come back to the start + { + th->direction = -th->direction; + + if (!th->continuous) + th->returnbehavior = PWR_STOP; + + waypoint = (th->direction == -1) ? P_GetPreviousWaypoint(target, false) : P_GetNextWaypoint(target, false); + } + } + + if (waypoint) + { + CONS_Debug(DBG_POLYOBJ, "Found waypoint (sequence %d, number %d).\n", waypoint->threshold, waypoint->health); + + target = waypoint; + th->pointnum = target->health; + // Set the mobj as your target! -- Monster Iestyn 27/12/19 + P_SetTarget(&th->target, target); + + // Calculate remaining speed + speed -= dist; + } + else + { + if (!th->stophere) + CONS_Debug(DBG_POLYOBJ, "Next waypoint not found!\n"); + + if (po->thinker == &th->thinker) + po->thinker = NULL; + + P_RemoveThinker(&th->thinker); + return; + } } } - else - { - // momx/momy/momz already equals the right speed - } - - // Move the polyobject - T_MovePolyObj(po, momx, momy, momz); } void T_PolyDoorSlide(polyslidedoor_t *th) From 1057c0f7c1ce884d28ee1a516142abcb165f3edc Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 16 May 2020 08:49:03 +0200 Subject: [PATCH 5/9] T_PolyObjWaypoint: If the polyobject reaches its target exactly, find next waypoint in the same tic --- src/p_polyobj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_polyobj.c b/src/p_polyobj.c index b81346ec3..00c4a051a 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -1648,7 +1648,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th) dist = 1; // Will the polyobject overshoot its target? - if (speed <= dist) + if (speed < dist) { // No. Move towards waypoint fixed_t momx, momy, momz; From 3680b246c90f7989f0f3396e2b29c194f2931975 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 16 May 2020 09:03:02 +0200 Subject: [PATCH 6/9] T_PolyObjWaypoint: We can find waypoints in constant time now, so no need to store the waypoint mobj in the thinker anymore --- src/p_polyobj.c | 7 +------ src/p_polyobj.h | 2 -- src/p_saveg.c | 13 ------------- 3 files changed, 1 insertion(+), 21 deletions(-) diff --git a/src/p_polyobj.c b/src/p_polyobj.c index 00c4a051a..43a292655 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -1618,7 +1618,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th) if (!po->thinker) po->thinker = &th->thinker; - target = th->target; + target = waypoints[th->sequence][th->pointnum]; if (!target) { @@ -1696,8 +1696,6 @@ void T_PolyObjWaypoint(polywaypoint_t *th) target = waypoint; th->pointnum = target->health; - // Set the mobj as your target! -- Monster Iestyn 27/12/19 - P_SetTarget(&th->target, target); // Calculate remaining speed speed -= dist; @@ -2206,9 +2204,6 @@ boolean EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata) // Set pointnum th->pointnum = target->health; - th->target = NULL; // set to NULL first so the below doesn't go wrong - // Set the mobj as your target! -- Monster Iestyn 27/12/19 - P_SetTarget(&th->target, target); // We don't deal with the mirror crap here, we'll // handle that in the T_Thinker function. diff --git a/src/p_polyobj.h b/src/p_polyobj.h index 6b0016195..cfed15ffe 100644 --- a/src/p_polyobj.h +++ b/src/p_polyobj.h @@ -160,8 +160,6 @@ typedef struct polywaypoint_s UINT8 returnbehavior; // behavior after reaching the last waypoint UINT8 continuous; // continuously move - used with PWR_WRAP or PWR_COMEBACK UINT8 stophere; // Will stop after it reaches the next waypoint - - mobj_t *target; // next waypoint mobj } polywaypoint_t; typedef struct polyslidedoor_s diff --git a/src/p_saveg.c b/src/p_saveg.c index e4393826d..f18c14d73 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2022,7 +2022,6 @@ static void SavePolywaypointThinker(const thinker_t *th, UINT8 type) WRITEUINT8(save_p, ht->returnbehavior); WRITEUINT8(save_p, ht->continuous); WRITEUINT8(save_p, ht->stophere); - WRITEUINT32(save_p, SaveMobjnum(ht->target)); } static void SavePolyslidedoorThinker(const thinker_t *th, const UINT8 type) @@ -3163,7 +3162,6 @@ static inline thinker_t* LoadPolywaypointThinker(actionf_p1 thinker) ht->returnbehavior = READUINT8(save_p); ht->continuous = READUINT8(save_p); ht->stophere = READUINT8(save_p); - ht->target = LoadMobj(READUINT32(save_p)); return &ht->thinker; } @@ -3410,7 +3408,6 @@ static void P_NetUnArchiveThinkers(void) case tc_polywaypoint: th = LoadPolywaypointThinker((actionf_p1)T_PolyObjWaypoint); - restoreNum = true; break; case tc_polyslidedoor: @@ -3470,7 +3467,6 @@ static void P_NetUnArchiveThinkers(void) if (restoreNum) { executor_t *delay = NULL; - polywaypoint_t *polywp = NULL; UINT32 mobjnum; for (currentthinker = thlist[THINK_MAIN].next; currentthinker != &thlist[THINK_MAIN]; currentthinker = currentthinker->next) { @@ -3481,15 +3477,6 @@ static void P_NetUnArchiveThinkers(void) continue; delay->caller = P_FindNewPosition(mobjnum); } - for (currentthinker = thlist[THINK_POLYOBJ].next; currentthinker != &thlist[THINK_POLYOBJ]; currentthinker = currentthinker->next) - { - if (currentthinker->function.acp1 != (actionf_p1)T_PolyObjWaypoint) - continue; - polywp = (void *)currentthinker; - if (!(mobjnum = (UINT32)(size_t)polywp->target)) - continue; - polywp->target = P_FindNewPosition(mobjnum); - } } } From 06dda9c69d516e05b81061fe5c12deb7475fbc7c Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 16 May 2020 09:09:26 +0200 Subject: [PATCH 7/9] EV_DoPolyObjWaypoint: Don't discard movement if you start at the last waypoint --- src/p_polyobj.c | 32 +------------------------------- 1 file changed, 1 insertion(+), 31 deletions(-) diff --git a/src/p_polyobj.c b/src/p_polyobj.c index 43a292655..557055c92 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -2131,8 +2131,6 @@ boolean EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata) polyobj_t *po; polywaypoint_t *th; mobj_t *first = NULL; - mobj_t *last = NULL; - mobj_t *target = NULL; if (!(po = Polyobj_GetForNum(pwdata->polyObjNum))) { @@ -2165,7 +2163,6 @@ boolean EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata) // Find the first waypoint we need to use first = (th->direction == -1) ? P_GetLastWaypoint(th->sequence) : P_GetFirstWaypoint(th->sequence); - last = (th->direction == -1) ? P_GetFirstWaypoint(th->sequence) : P_GetLastWaypoint(th->sequence); if (!first) { @@ -2175,35 +2172,8 @@ boolean EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata) return false; } - // Hotfix to not crash on single-waypoint sequences -Red - if (!last) - last = first; - - if (last->x == po->centerPt.x - && last->y == po->centerPt.y - && last->z == (po->lines[0]->backsector->floorheight + (po->lines[0]->backsector->ceilingheight - po->lines[0]->backsector->floorheight)/2)) - { - // Already at the destination point... - if (th->returnbehavior != PWR_WRAP) - { - po->thinker = NULL; - P_RemoveThinker(&th->thinker); - } - } - - // Find the actual target movement waypoint - target = first; - - if (!target) - { - CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjWaypoint: Missing target waypoint!\n"); - po->thinker = NULL; - P_RemoveThinker(&th->thinker); - return false; - } - // Set pointnum - th->pointnum = target->health; + th->pointnum = first->health; // We don't deal with the mirror crap here, we'll // handle that in the T_Thinker function. From 536e355cdf9242daf5cffc566a36763546d47fa5 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 16 May 2020 09:49:30 +0200 Subject: [PATCH 8/9] polywaypointdata_t: Turn reverse and continuous into flags --- src/p_polyobj.c | 10 ++++------ src/p_polyobj.h | 9 +++++++-- src/p_spec.c | 8 ++++++-- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/p_polyobj.c b/src/p_polyobj.c index 557055c92..9958b19c9 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -2154,11 +2154,12 @@ boolean EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata) // set fields th->polyObjNum = pwdata->polyObjNum; th->speed = pwdata->speed; - th->sequence = pwdata->sequence; // Used to specify sequence # - th->direction = pwdata->reverse ? -1 : 1; + th->sequence = pwdata->sequence; + th->direction = (pwdata->flags & PWF_REVERSE) ? -1 : 1; th->returnbehavior = pwdata->returnbehavior; - th->continuous = pwdata->continuous; + if (pwdata->flags & PWF_LOOP) + th->continuous = true; th->stophere = false; // Find the first waypoint we need to use @@ -2172,11 +2173,8 @@ boolean EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata) return false; } - // Set pointnum th->pointnum = first->health; - // We don't deal with the mirror crap here, we'll - // handle that in the T_Thinker function. return true; } diff --git a/src/p_polyobj.h b/src/p_polyobj.h index cfed15ffe..8037c545f 100644 --- a/src/p_polyobj.h +++ b/src/p_polyobj.h @@ -254,14 +254,19 @@ typedef struct polymovedata_s UINT8 overRide; // if true, will override any action on the object } polymovedata_t; +typedef enum +{ + PWF_REVERSE = 1, // Move through waypoints in reverse order + PWF_LOOP = 1<<1, // Loop movement (used with PWR_WRAP or PWR_COMEBACK) +} polywaypointflags_e; + typedef struct polywaypointdata_s { INT32 polyObjNum; // numeric id of polyobject to affect INT32 sequence; // waypoint sequence # fixed_t speed; // linear speed - UINT8 reverse; // if true, will go in reverse waypoint order UINT8 returnbehavior; // behavior after reaching the last waypoint - UINT8 continuous; // continuously move - used with PWR_WRAP or PWR_COMEBACK + UINT8 flags; // PWF_ flags } polywaypointdata_t; // polyobject door types diff --git a/src/p_spec.c b/src/p_spec.c index 99657aab9..f592e8edd 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1276,7 +1276,6 @@ static boolean PolyWaypoint(line_t *line) pwd.polyObjNum = line->tag; pwd.speed = sides[line->sidenum[0]].textureoffset / 8; pwd.sequence = sides[line->sidenum[0]].rowoffset >> FRACBITS; // Sequence # - pwd.reverse = (line->flags & ML_EFFECT1) == ML_EFFECT1; // Reverse? // Behavior after reaching the last waypoint? if (line->flags & ML_EFFECT3) @@ -1286,7 +1285,12 @@ static boolean PolyWaypoint(line_t *line) else pwd.returnbehavior = PWR_STOP; // Stop - pwd.continuous = (line->flags & ML_EFFECT4) == ML_EFFECT4; // Continuously move - used with PWR_WRAP or PWR_COMEBACK + // Flags + pwd.flags = 0; + if (line->flags & ML_EFFECT1) + pwd.flags |= PWF_REVERSE; + if (line->flags & ML_EFFECT4) + pwd.flags |= PWF_LOOP; return EV_DoPolyObjWaypoint(&pwd); } From 371a1851e334ea96fc4b84847602a2878c5aa439 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Sat, 16 May 2020 10:24:06 +0200 Subject: [PATCH 9/9] Polyobject waypoint movement: Prevent infinite loop if all waypoints are in the same location --- src/doomstat.h | 1 + src/p_polyobj.c | 8 ++++++++ src/p_setup.c | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/src/doomstat.h b/src/doomstat.h index c283c5674..57ea3e049 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -631,6 +631,7 @@ mobj_t *P_GetLastWaypoint(UINT8 sequence); mobj_t *P_GetPreviousWaypoint(mobj_t *current, boolean wrap); mobj_t *P_GetNextWaypoint(mobj_t *current, boolean wrap); mobj_t *P_GetClosestWaypoint(UINT8 sequence, mobj_t *mo); +boolean P_IsDegeneratedWaypointSequence(UINT8 sequence); // ===================================== // Internal parameters, used for engine. diff --git a/src/p_polyobj.c b/src/p_polyobj.c index 9958b19c9..3b6195285 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -2173,6 +2173,14 @@ boolean EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata) return false; } + // Sanity check: If all waypoints are in the same location, + // don't allow the movement to be continuous so we don't get stuck in an infinite loop. + if (th->continuous && P_IsDegeneratedWaypointSequence(th->sequence)) + { + CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjWaypoint: All waypoints are in the same location!\n"); + th->continuous = false; + } + th->pointnum = first->health; return true; diff --git a/src/p_setup.c b/src/p_setup.c index f454bc1fd..84e89d746 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -239,6 +239,38 @@ mobj_t *P_GetClosestWaypoint(UINT8 sequence, mobj_t *mo) return result; } +// Return true if all waypoints are in the same location +boolean P_IsDegeneratedWaypointSequence(UINT8 sequence) +{ + mobj_t *first, *waypoint; + UINT8 wp; + + if (numwaypoints[sequence] <= 1) + return true; + + first = waypoints[sequence][0]; + + for (wp = 1; wp < numwaypoints[sequence]; wp++) + { + waypoint = waypoints[sequence][wp]; + + if (!waypoint) + continue; + + if (waypoint->x != first->x) + return false; + + if (waypoint->y != first->y) + return false; + + if (waypoint->z != first->z) + return false; + } + + return true; +} + + /** Logs an error about a map being corrupt, then terminate. * This allows reporting highly technical errors for usefulness, without * confusing a novice map designer who simply needs to run ZenNode.