From 7d5a8ac14b62378ed56b5e6e643ac3ecdb576d6d Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 15 Jan 2020 19:13:41 -0800 Subject: [PATCH 01/25] Allow G_BuildMapName outside of levels --- src/lua_baselib.c | 21 +++++++++++++++++++-- src/lua_script.h | 5 ++++- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 2a82ec512..d4d6e1a6d 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2772,11 +2772,28 @@ static int lib_gAddGametype(lua_State *L) return 0; } +static int Lcheckmapnumber (lua_State *L, int idx) +{ + if (ISINLEVEL) + return luaL_optinteger(L, idx, gamemap); + else + { + if (lua_isnoneornil(L, idx)) + { + return luaL_error(L, + "G_BuildMapName can only be used " + "without a parameter while in a level." + ); + } + else + return luaL_checkinteger(L, idx); + } +} + static int lib_gBuildMapName(lua_State *L) { - INT32 map = luaL_optinteger(L, 1, gamemap); + INT32 map = Lcheckmapnumber(L, 1); //HUDSAFE - INLEVEL lua_pushstring(L, G_BuildMapName(map)); return 1; } diff --git a/src/lua_script.h b/src/lua_script.h index 8f27dcb4c..7d8aaa282 100644 --- a/src/lua_script.h +++ b/src/lua_script.h @@ -100,7 +100,10 @@ void COM_Lua_f(void); // uncomment if you want seg_t/node_t in Lua // #define HAVE_LUA_SEGS -#define INLEVEL if (gamestate != GS_LEVEL && !titlemapinaction)\ +#define ISINLEVEL \ + (gamestate == GS_LEVEL || titlemapinaction) + +#define INLEVEL if (! ISINLEVEL)\ return luaL_error(L, "This can only be used in a level!"); #endif From 50b18acd3f08012d313ced34e946f7c30a2ea313 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 15 Jan 2020 20:04:50 -0800 Subject: [PATCH 02/25] Expose G_BuildMapTitle to Lua --- src/lua_baselib.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index d4d6e1a6d..106fcb761 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2772,7 +2772,7 @@ static int lib_gAddGametype(lua_State *L) return 0; } -static int Lcheckmapnumber (lua_State *L, int idx) +static int Lcheckmapnumber (lua_State *L, int idx, const char *fun) { if (ISINLEVEL) return luaL_optinteger(L, idx, gamemap); @@ -2781,8 +2781,8 @@ static int Lcheckmapnumber (lua_State *L, int idx) if (lua_isnoneornil(L, idx)) { return luaL_error(L, - "G_BuildMapName can only be used " - "without a parameter while in a level." + "%s can only be used without a parameter while in a level.", + fun ); } else @@ -2792,12 +2792,30 @@ static int Lcheckmapnumber (lua_State *L, int idx) static int lib_gBuildMapName(lua_State *L) { - INT32 map = Lcheckmapnumber(L, 1); + INT32 map = Lcheckmapnumber(L, 1, "G_BuildMapName"); //HUDSAFE lua_pushstring(L, G_BuildMapName(map)); return 1; } +static int lib_gBuildMapTitle(lua_State *L) +{ + INT32 map = Lcheckmapnumber(L, 1, "G_BuoldMapTitle"); + char *name; + if (map < 1 || map > NUMMAPS) + { + return luaL_error(L, + "map number %d out of range (1 - %d)", + map, + NUMMAPS + ); + } + name = G_BuildMapTitle(map); + lua_pushstring(L, name); + Z_Free(name); + return 1; +} + static int lib_gDoReborn(lua_State *L) { INT32 playernum = luaL_checkinteger(L, 1); @@ -3174,6 +3192,7 @@ static luaL_Reg lib[] = { // g_game {"G_AddGametype", lib_gAddGametype}, {"G_BuildMapName",lib_gBuildMapName}, + {"G_BuildMapTitle",lib_gBuildMapTitle}, {"G_DoReborn",lib_gDoReborn}, {"G_SetCustomExitVars",lib_gSetCustomExitVars}, {"G_EnoughPlayersFinished",lib_gEnoughPlayersFinished}, From b7b24eb5d70bd738b27767fceb11514cddf519c8 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 18 Jan 2020 15:56:03 -0800 Subject: [PATCH 03/25] Buold. --- src/lua_baselib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 106fcb761..35ea6db0c 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2800,7 +2800,7 @@ static int lib_gBuildMapName(lua_State *L) static int lib_gBuildMapTitle(lua_State *L) { - INT32 map = Lcheckmapnumber(L, 1, "G_BuoldMapTitle"); + INT32 map = Lcheckmapnumber(L, 1, "G_BuildMapTitle"); char *name; if (map < 1 || map > NUMMAPS) { From 435e6c9812c03657be0da01d0150c7d777c8e592 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 12 May 2020 14:53:10 +0200 Subject: [PATCH 04/25] Rename variables for Fang waypoints, in preparation for new global waypoint data structure --- src/p_enemy.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 2341be6d3..813ae1fc8 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8794,19 +8794,19 @@ void A_Dye(mobj_t *actor) #endif if (color >= MAXTRANSLATIONS) return; - + if (!color) target->colorized = false; else target->colorized = true; - + // What if it's a player? if (target->player) { target->player->powers[pw_dye] = color; return; } - + target->color = color; } @@ -12642,8 +12642,8 @@ void A_Boss5FindWaypoint(mobj_t *actor) else // locvar1 == 0 { fixed_t hackoffset = P_MobjFlip(actor)*56*FRACUNIT; - INT32 numwaypoints = 0; - mobj_t **waypoints; + INT32 numfangwaypoints = 0; + mobj_t **fangwaypoints; INT32 key; actor->z += hackoffset; @@ -12668,7 +12668,7 @@ void A_Boss5FindWaypoint(mobj_t *actor) continue; if (!P_CheckSight(actor, mapthings[i].mobj)) continue; - numwaypoints++; + numfangwaypoints++; } // players also count as waypoints apparently @@ -12690,11 +12690,11 @@ void A_Boss5FindWaypoint(mobj_t *actor) continue; if (!P_CheckSight(actor, players[i].mo)) continue; - numwaypoints++; + numfangwaypoints++; } } - if (!numwaypoints) + if (!numfangwaypoints) { // restore z position actor->z -= hackoffset; @@ -12702,8 +12702,8 @@ void A_Boss5FindWaypoint(mobj_t *actor) } // allocate the table and reset count to zero - waypoints = Z_Calloc(sizeof(*waypoints)*numwaypoints, PU_STATIC, NULL); - numwaypoints = 0; + fangwaypoints = Z_Calloc(sizeof(*waypoints)*numfangwaypoints, PU_STATIC, NULL); + numfangwaypoints = 0; // now find them again and add them to the table! for (i = 0; i < nummapthings; i++) @@ -12728,7 +12728,7 @@ void A_Boss5FindWaypoint(mobj_t *actor) } if (!P_CheckSight(actor, mapthings[i].mobj)) continue; - waypoints[numwaypoints++] = mapthings[i].mobj; + fangwaypoints[numfangwaypoints++] = mapthings[i].mobj; } if (actor->extravalue2 > 1) @@ -12749,25 +12749,25 @@ void A_Boss5FindWaypoint(mobj_t *actor) continue; if (!P_CheckSight(actor, players[i].mo)) continue; - waypoints[numwaypoints++] = players[i].mo; + fangwaypoints[numfangwaypoints++] = players[i].mo; } } // restore z position actor->z -= hackoffset; - if (!numwaypoints) + if (!numfangwaypoints) { - Z_Free(waypoints); // free table + Z_Free(fangwaypoints); // free table goto nowaypoints; // ??? } - key = P_RandomKey(numwaypoints); + key = P_RandomKey(numfangwaypoints); - P_SetTarget(&actor->tracer, waypoints[key]); + P_SetTarget(&actor->tracer, fangwaypoints[key]); if (actor->tracer->type == MT_FANGWAYPOINT) - actor->tracer->reactiontime = numwaypoints/4; // Monster Iestyn: is this how it should be? I count center waypoints as waypoints unlike the original Lua script - Z_Free(waypoints); // free table + actor->tracer->reactiontime = numfangwaypoints/4; // Monster Iestyn: is this how it should be? I count center waypoints as waypoints unlike the original Lua script + Z_Free(fangwaypoints); // free table } // now face the tracer you just set! From d708789c3a61ada6e5af9c39dc0194fa476cda66 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 12 May 2020 23:50:30 +0200 Subject: [PATCH 05/25] Store waypoints (for zoom tubes, rope hangs, polyobjects) explicitly --- src/doomstat.h | 12 +++ src/p_mobj.c | 9 ++- src/p_polyobj.c | 196 ++---------------------------------------------- src/p_setup.c | 97 ++++++++++++++++++++++++ src/p_spec.c | 140 ++-------------------------------- src/p_user.c | 70 +---------------- 6 files changed, 134 insertions(+), 390 deletions(-) diff --git a/src/doomstat.h b/src/doomstat.h index 1ec03a86c..ab67706a7 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -620,6 +620,18 @@ extern mapthing_t *playerstarts[MAXPLAYERS]; // Cooperative extern mapthing_t *bluectfstarts[MAXPLAYERS]; // CTF extern mapthing_t *redctfstarts[MAXPLAYERS]; // CTF +#define WAYPOINTSEQUENCESIZE 256 +#define NUMWAYPOINTSEQUENCES 256 +extern mobj_t *waypoints[NUMWAYPOINTSEQUENCES][WAYPOINTSEQUENCESIZE]; +extern UINT16 numwaypoints[NUMWAYPOINTSEQUENCES]; + +void P_AddWaypoint(UINT8 sequence, UINT8 id, mobj_t *waypoint); +mobj_t *P_GetFirstWaypoint(UINT8 sequence); +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); + // ===================================== // Internal parameters, used for engine. // ===================================== diff --git a/src/p_mobj.c b/src/p_mobj.c index c78ec4a53..be0828464 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12728,9 +12728,14 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean mobj->threshold = min(mthing->extrainfo, 7); break; case MT_TUBEWAYPOINT: - mobj->health = mthing->angle & 255; - mobj->threshold = mthing->angle >> 8; + { + UINT8 sequence = mthing->angle >> 8; + UINT8 id = mthing->angle & 255; + mobj->health = id; + mobj->threshold = sequence; + P_AddWaypoint(sequence, id, mobj); break; + } case MT_IDEYAANCHOR: mobj->health = mthing->extrainfo; break; diff --git a/src/p_polyobj.c b/src/p_polyobj.c index cd63f4509..4b9538951 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -1571,10 +1571,8 @@ void T_PolyObjMove(polymove_t *th) void T_PolyObjWaypoint(polywaypoint_t *th) { - mobj_t *mo2; mobj_t *target = NULL; mobj_t *waypoint = NULL; - thinker_t *wp; fixed_t adjustx, adjusty, adjustz; fixed_t momx, momy, momz, dist; INT32 start; @@ -1593,30 +1591,9 @@ void T_PolyObjWaypoint(polywaypoint_t *th) #endif // check for displacement due to override and reattach when possible - if (po->thinker == NULL) + if (!po->thinker) po->thinker = &th->thinker; -/* - // Find out target first. - // We redo this each tic to make savegame compatibility easier. - for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) - { - if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) - continue; - - mo2 = (mobj_t *)wp; - - if (mo2->type != MT_TUBEWAYPOINT) - continue; - - if (mo2->threshold == th->sequence && mo2->health == th->pointnum) - { - target = mo2; - break; - } - } -*/ - target = th->target; if (!target) @@ -1683,38 +1660,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th) if (!th->stophere) { CONS_Debug(DBG_POLYOBJ, "Looking for next waypoint...\n"); - - // Find next waypoint - for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) - { - if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) - continue; - - mo2 = (mobj_t *)wp; - - if (mo2->type != MT_TUBEWAYPOINT) - continue; - - if (mo2->threshold != th->sequence) - continue; - - if (th->direction == -1) - { - if (mo2->health == target->health - 1) - { - waypoint = mo2; - break; - } - } - else - { - if (mo2->health == target->health + 1) - { - waypoint = mo2; - break; - } - } - } + waypoint = (th->direction == -1) ? P_GetPreviousWaypoint(target, false) : P_GetNextWaypoint(target, false); if (!waypoint && th->wrap) // If specified, wrap waypoints { @@ -1724,35 +1670,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th) th->stophere = true; } - for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) - { - if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) - continue; - - mo2 = (mobj_t *)wp; - - if (mo2->type != MT_TUBEWAYPOINT) - continue; - - if (mo2->threshold != th->sequence) - continue; - - if (th->direction == -1) - { - if (waypoint == NULL) - waypoint = mo2; - else if (mo2->health > waypoint->health) - waypoint = mo2; - } - else - { - if (mo2->health == 0) - { - waypoint = mo2; - break; - } - } - } + waypoint = (th->direction == -1) ? P_GetFirstWaypoint(th->sequence) : P_GetLastWaypoint(th->sequence); } else if (!waypoint && th->comeback) // Come back to the start { @@ -1761,36 +1679,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th) if (!th->continuous) th->comeback = false; - for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) - { - if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) - continue; - - mo2 = (mobj_t *)wp; - - if (mo2->type != MT_TUBEWAYPOINT) - continue; - - if (mo2->threshold != th->sequence) - continue; - - if (th->direction == -1) - { - if (mo2->health == target->health - 1) - { - waypoint = mo2; - break; - } - } - else - { - if (mo2->health == target->health + 1) - { - waypoint = mo2; - break; - } - } - } + waypoint = (th->direction == -1) ? P_GetPreviousWaypoint(target, false) : P_GetNextWaypoint(target, false); } } @@ -2276,11 +2165,9 @@ boolean EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata) { polyobj_t *po; polywaypoint_t *th; - mobj_t *mo2; mobj_t *first = NULL; mobj_t *last = NULL; mobj_t *target = NULL; - thinker_t *wp; if (!(po = Polyobj_GetForNum(pwdata->polyObjNum))) { @@ -2305,10 +2192,7 @@ boolean EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata) th->polyObjNum = pwdata->polyObjNum; th->speed = pwdata->speed; th->sequence = pwdata->sequence; // Used to specify sequence # - if (pwdata->reverse) - th->direction = -1; - else - th->direction = 1; + th->direction = pwdata->reverse ? -1 : 1; th->comeback = pwdata->comeback; th->continuous = pwdata->continuous; @@ -2316,44 +2200,8 @@ boolean EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata) th->stophere = false; // Find the first waypoint we need to use - for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) - { - if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) - continue; - - mo2 = (mobj_t *)wp; - - if (mo2->type != MT_TUBEWAYPOINT) - continue; - - if (mo2->threshold != th->sequence) - continue; - - if (th->direction == -1) // highest waypoint # - { - if (mo2->health == 0) - last = mo2; - else - { - if (first == NULL) - first = mo2; - else if (mo2->health > first->health) - first = mo2; - } - } - else // waypoint 0 - { - if (mo2->health == 0) - first = mo2; - else - { - if (last == NULL) - last = mo2; - else if (mo2->health > last->health) - last = mo2; - } - } - } + 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) { @@ -2387,36 +2235,6 @@ boolean EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata) // Find the actual target movement waypoint target = first; - /*for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) - { - if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) - continue; - - mo2 = (mobj_t *)wp; - - if (mo2->type != MT_TUBEWAYPOINT) - continue; - - if (mo2->threshold != th->sequence) - continue; - - if (th->direction == -1) // highest waypoint # - { - if (mo2->health == first->health - 1) - { - target = mo2; - break; - } - } - else // waypoint 0 - { - if (mo2->health == first->health + 1) - { - target = mo2; - break; - } - } - }*/ if (!target) { diff --git a/src/p_setup.c b/src/p_setup.c index b4a5f2c3c..f454bc1fd 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -144,6 +144,101 @@ mapthing_t *playerstarts[MAXPLAYERS]; mapthing_t *bluectfstarts[MAXPLAYERS]; mapthing_t *redctfstarts[MAXPLAYERS]; +// Maintain waypoints +mobj_t *waypoints[NUMWAYPOINTSEQUENCES][WAYPOINTSEQUENCESIZE]; +UINT16 numwaypoints[NUMWAYPOINTSEQUENCES]; + +void P_AddWaypoint(UINT8 sequence, UINT8 id, mobj_t *waypoint) +{ + waypoints[sequence][id] = waypoint; + if (id >= numwaypoints[sequence]) + numwaypoints[sequence] = id + 1; +} + +static void P_ResetWaypoints(void) +{ + UINT16 sequence, id; + for (sequence = 0; sequence < NUMWAYPOINTSEQUENCES; sequence++) + { + for (id = 0; id < numwaypoints[sequence]; id++) + waypoints[sequence][id] = NULL; + + numwaypoints[sequence] = 0; + } +} + +mobj_t *P_GetFirstWaypoint(UINT8 sequence) +{ + return waypoints[sequence][0]; +} + +mobj_t *P_GetLastWaypoint(UINT8 sequence) +{ + return waypoints[sequence][numwaypoints[sequence] - 1]; +} + +mobj_t *P_GetPreviousWaypoint(mobj_t *current, boolean wrap) +{ + UINT8 sequence = current->threshold; + UINT8 id = current->health; + + if (id == 0) + { + if (!wrap) + return NULL; + + id = numwaypoints[sequence] - 1; + } + else + id--; + + return waypoints[sequence][id]; +} + +mobj_t *P_GetNextWaypoint(mobj_t *current, boolean wrap) +{ + UINT8 sequence = current->threshold; + UINT8 id = current->health; + + if (id == numwaypoints[sequence] - 1) + { + if (!wrap) + return NULL; + + id = 0; + } + else + id++; + + return waypoints[sequence][id]; +} + +mobj_t *P_GetClosestWaypoint(UINT8 sequence, mobj_t *mo) +{ + UINT8 wp; + mobj_t *mo2, *result = NULL; + fixed_t bestdist = 0; + fixed_t curdist; + + for (wp = 0; wp < numwaypoints[sequence]; wp++) + { + mo2 = waypoints[sequence][wp]; + + if (!mo2) + continue; + + curdist = P_AproxDistance(P_AproxDistance(mo->x - mo2->x, mo->y - mo2->y), mo->z - mo2->z); + + if (result && curdist > bestdist) + continue; + + result = mo2; + bestdist = curdist; + } + + return result; +} + /** 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. @@ -3545,6 +3640,8 @@ boolean P_LoadLevel(boolean fromnetsave) P_ResetSpawnpoints(); + P_ResetWaypoints(); + P_MapStart(); if (!P_LoadMapFromFile()) diff --git a/src/p_spec.c b/src/p_spec.c index ac72eec15..6c8d7be2a 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4799,9 +4799,7 @@ DoneSection2: INT32 sequence; fixed_t speed; INT32 lineindex; - thinker_t *th; mobj_t *waypoint = NULL; - mobj_t *mo2; angle_t an; if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ZOOMTUBE) @@ -4826,25 +4824,7 @@ DoneSection2: break; } - // scan the thinkers - // to find the first waypoint - for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) - { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) - continue; - - mo2 = (mobj_t *)th; - - if (mo2->type != MT_TUBEWAYPOINT) - continue; - if (mo2->threshold != sequence) - continue; - if (mo2->health != 0) - continue; - - waypoint = mo2; - break; - } + waypoint = P_GetFirstWaypoint(sequence); if (!waypoint) { @@ -4881,9 +4861,7 @@ DoneSection2: INT32 sequence; fixed_t speed; INT32 lineindex; - thinker_t *th; mobj_t *waypoint = NULL; - mobj_t *mo2; angle_t an; if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ZOOMTUBE) @@ -4908,25 +4886,7 @@ DoneSection2: break; } - // scan the thinkers - // to find the last waypoint - for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) - { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) - continue; - - mo2 = (mobj_t *)th; - - if (mo2->type != MT_TUBEWAYPOINT) - continue; - if (mo2->threshold != sequence) - continue; - - if (!waypoint) - waypoint = mo2; - else if (mo2->health > waypoint->health) - waypoint = mo2; - } + waypoint = P_GetLastWaypoint(sequence); if (!waypoint) { @@ -5008,14 +4968,11 @@ DoneSection2: INT32 sequence; fixed_t speed; INT32 lineindex; - thinker_t *th; mobj_t *waypointmid = NULL; mobj_t *waypointhigh = NULL; mobj_t *waypointlow = NULL; - mobj_t *mo2; mobj_t *closest = NULL; vector3_t p, line[2], resulthigh, resultlow; - mobj_t *highest = NULL; if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ROPEHANG) break; @@ -5061,98 +5018,16 @@ DoneSection2: // Determine the closest spot on the line between the three waypoints // Put player at that location. - // scan the thinkers - // to find the first waypoint - for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) - { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) - continue; + waypointmid = P_GetClosestWaypoint(sequence, player->mo); - mo2 = (mobj_t *)th; - - if (mo2->type != MT_TUBEWAYPOINT) - continue; - - if (mo2->threshold != sequence) - continue; - - if (!highest) - highest = mo2; - else if (mo2->health > highest->health) // Find the highest waypoint # in case we wrap - highest = mo2; - - if (closest && P_AproxDistance(P_AproxDistance(player->mo->x-mo2->x, player->mo->y-mo2->y), - player->mo->z-mo2->z) > P_AproxDistance(P_AproxDistance(player->mo->x-closest->x, - player->mo->y-closest->y), player->mo->z-closest->z)) - continue; - - // Found a target - closest = mo2; - } - - waypointmid = closest; - - closest = NULL; - - if (waypointmid == NULL) + if (!waypointmid) { CONS_Debug(DBG_GAMELOGIC, "ERROR: WAYPOINT(S) IN SEQUENCE %d NOT FOUND.\n", sequence); break; } - // Find waypoint before this one (waypointlow) - for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) - { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) - continue; - - mo2 = (mobj_t *)th; - - if (mo2->type != MT_TUBEWAYPOINT) - continue; - - if (mo2->threshold != sequence) - continue; - - if (waypointmid->health == 0) - { - if (mo2->health != highest->health) - continue; - } - else if (mo2->health != waypointmid->health - 1) - continue; - - // Found a target - waypointlow = mo2; - break; - } - - // Find waypoint after this one (waypointhigh) - for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) - { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) - continue; - - mo2 = (mobj_t *)th; - - if (mo2->type != MT_TUBEWAYPOINT) - continue; - - if (mo2->threshold != sequence) - continue; - - if (waypointmid->health == highest->health) - { - if (mo2->health != 0) - continue; - } - else if (mo2->health != waypointmid->health + 1) - continue; - - // Found a target - waypointhigh = mo2; - break; - } + waypointlow = P_GetPreviousWaypoint(waypointmid, true); + waypointhigh = P_GetNextWaypoint(waypointmid, true); CONS_Debug(DBG_GAMELOGIC, "WaypointMid: %d; WaypointLow: %d; WaypointHigh: %d\n", waypointmid->health, waypointlow ? waypointlow->health : -1, waypointhigh ? waypointhigh->health : -1); @@ -5199,6 +5074,7 @@ DoneSection2: if (lines[lineindex].flags & ML_EFFECT1) // Don't wrap { + mobj_t *highest = P_GetLastWaypoint(sequence); highest->flags |= MF_SLIDEME; } @@ -5210,7 +5086,7 @@ DoneSection2: player->mo->y = resulthigh.y; player->mo->z = resulthigh.z - P_GetPlayerHeight(player); } - else if ((lines[lineindex].flags & ML_EFFECT1) && waypointmid->health == highest->health) + else if ((lines[lineindex].flags & ML_EFFECT1) && waypointmid->health == numwaypoints[sequence] - 1) { closest = waypointmid; player->mo->x = resultlow.x; diff --git a/src/p_user.c b/src/p_user.c index 9df71587d..2c120593a 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8727,10 +8727,7 @@ static void P_MovePlayer(player_t *player) static void P_DoZoomTube(player_t *player) { - INT32 sequence; fixed_t speed; - thinker_t *th; - mobj_t *mo2; mobj_t *waypoint = NULL; fixed_t dist; boolean reverse; @@ -8746,8 +8743,6 @@ static void P_DoZoomTube(player_t *player) speed = abs(player->speed); - sequence = player->mo->tracer->threshold; - // change slope dist = P_AproxDistance(P_AproxDistance(player->mo->tracer->x - player->mo->x, player->mo->tracer->y - player->mo->y), player->mo->tracer->z - player->mo->z); @@ -8779,28 +8774,7 @@ static void P_DoZoomTube(player_t *player) CONS_Debug(DBG_GAMELOGIC, "Looking for next waypoint...\n"); // Find next waypoint - for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) - { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) - continue; - - mo2 = (mobj_t *)th; - - if (mo2->type != MT_TUBEWAYPOINT) - continue; - - if (mo2->threshold != sequence) - continue; - - if (reverse && mo2->health != player->mo->tracer->health - 1) - continue; - - if (!reverse && mo2->health != player->mo->tracer->health + 1) - continue; - - waypoint = mo2; - break; - } + waypoint = reverse ? P_GetPreviousWaypoint(player->mo->tracer, false) : P_GetNextWaypoint(player->mo->tracer, false); if (waypoint) { @@ -8851,8 +8825,6 @@ static void P_DoRopeHang(player_t *player) { INT32 sequence; fixed_t speed; - thinker_t *th; - mobj_t *mo2; mobj_t *waypoint = NULL; fixed_t dist; fixed_t playerz; @@ -8915,50 +8887,14 @@ static void P_DoRopeHang(player_t *player) CONS_Debug(DBG_GAMELOGIC, "Looking for next waypoint...\n"); // Find next waypoint - for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) - { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) - continue; - - mo2 = (mobj_t *)th; - - if (mo2->type != MT_TUBEWAYPOINT) - continue; - - if (mo2->threshold != sequence) - continue; - - if (mo2->health != player->mo->tracer->health + 1) - continue; - - waypoint = mo2; - break; - } + waypoint = P_GetNextWaypoint(player->mo->tracer, false); if (!(player->mo->tracer->flags & MF_SLIDEME) && !waypoint) { CONS_Debug(DBG_GAMELOGIC, "Next waypoint not found, wrapping to start...\n"); // Wrap around back to first waypoint - for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) - { - if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) - continue; - - mo2 = (mobj_t *)th; - - if (mo2->type != MT_TUBEWAYPOINT) - continue; - - if (mo2->threshold != sequence) - continue; - - if (mo2->health != 0) - continue; - - waypoint = mo2; - break; - } + waypoint = P_GetFirstWaypoint(sequence); } if (waypoint) From aa16bd22f97ceb60aa935467b5fe3804a276ae57 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 13 May 2020 09:32:00 +0200 Subject: [PATCH 06/25] Fix accidental swap of first and last waypoint --- 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 4b9538951..b1da51462 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -1670,7 +1670,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th) th->stophere = true; } - waypoint = (th->direction == -1) ? P_GetFirstWaypoint(th->sequence) : P_GetLastWaypoint(th->sequence); + waypoint = (th->direction == -1) ? P_GetLastWaypoint(th->sequence) : P_GetFirstWaypoint(th->sequence); } else if (!waypoint && th->comeback) // Come back to the start { From b561ee792192aa9b8adb28971587ef69a897e34c Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 13 May 2020 14:40:07 +0200 Subject: [PATCH 07/25] 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 08/25] 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 09/25] 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 10/25] 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 11/25] 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 12/25] 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 13/25] 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 14/25] 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 15/25] 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. From dd42682791ce98d4c8b418ecc065130ae9faed55 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 19 May 2020 16:48:50 +0100 Subject: [PATCH 16/25] remove gxt and gyt, as they are unnecessary also add a few comments to explain what tx/tz are --- src/r_things.c | 40 +++++++++------------------------------- 1 file changed, 9 insertions(+), 31 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 8a3c2e35f..febb5b6dc 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1346,7 +1346,6 @@ static void R_ProjectSprite(mobj_t *thing) { mobj_t *oldthing = thing; fixed_t tr_x, tr_y; - fixed_t gxt, gyt; fixed_t tx, tz; fixed_t xscale, yscale, sortscale; //added : 02-02-98 : aaargll..if I were a math-guy!!! @@ -1399,18 +1398,13 @@ static void R_ProjectSprite(mobj_t *thing) tr_x = thing->x - viewx; tr_y = thing->y - viewy; - gxt = FixedMul(tr_x, viewcos); - gyt = -FixedMul(tr_y, viewsin); - - tz = gxt-gyt; + tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); // near/far distance // thing is behind view plane? if (!papersprite && (tz < FixedMul(MINZ, this_scale))) // papersprite clipping is handled later return; - gxt = -FixedMul(tr_x, viewsin); - gyt = FixedMul(tr_y, viewcos); - basetx = tx = -(gyt + gxt); + basetx = tx = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos); // sideways distance // too far off the side? if (!papersprite && abs(tx) > tz<<2) // papersprite clipping is handled later @@ -1561,15 +1555,11 @@ static void R_ProjectSprite(mobj_t *thing) tr_x += FixedMul(offset, cosmul); tr_y += FixedMul(offset, sinmul); - gxt = FixedMul(tr_x, viewcos); - gyt = -FixedMul(tr_y, viewsin); - tz = gxt-gyt; + tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); yscale = FixedDiv(projectiony, tz); //if (yscale < 64) return; // Fix some funky visuals - gxt = -FixedMul(tr_x, viewsin); - gyt = FixedMul(tr_y, viewcos); - tx = -(gyt + gxt); + tx = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos); xscale = FixedDiv(projection, tz); x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS; @@ -1585,15 +1575,11 @@ static void R_ProjectSprite(mobj_t *thing) tr_x += FixedMul(offset2, cosmul); tr_y += FixedMul(offset2, sinmul); - gxt = FixedMul(tr_x, viewcos); - gyt = -FixedMul(tr_y, viewsin); - tz2 = gxt-gyt; + tz2 = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); yscale2 = FixedDiv(projectiony, tz2); //if (yscale2 < 64) return; // ditto - gxt = -FixedMul(tr_x, viewsin); - gyt = FixedMul(tr_y, viewcos); - tx2 = -(gyt + gxt); + tx2 = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos); xscale2 = FixedDiv(projection, tz2); x2 = ((centerxfrac + FixedMul(tx2,xscale2))>>FRACBITS); @@ -1670,9 +1656,7 @@ static void R_ProjectSprite(mobj_t *thing) tr_x = thing->x - viewx; tr_y = thing->y - viewy; - gxt = FixedMul(tr_x, viewcos); - gyt = -FixedMul(tr_y, viewsin); - tz = gxt-gyt; + tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); linkscale = FixedDiv(projectiony, tz); if (tz < FixedMul(MINZ, this_scale)) @@ -1872,7 +1856,6 @@ static void R_ProjectSprite(mobj_t *thing) static void R_ProjectPrecipitationSprite(precipmobj_t *thing) { fixed_t tr_x, tr_y; - fixed_t gxt, gyt; fixed_t tx, tz; fixed_t xscale, yscale; //added : 02-02-98 : aaargll..if I were a math-guy!!! @@ -1893,18 +1876,13 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) tr_x = thing->x - viewx; tr_y = thing->y - viewy; - gxt = FixedMul(tr_x, viewcos); - gyt = -FixedMul(tr_y, viewsin); - - tz = gxt - gyt; + tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); // near/far distance // thing is behind view plane? if (tz < MINZ) return; - gxt = -FixedMul(tr_x, viewsin); - gyt = FixedMul(tr_y, viewcos); - tx = -(gyt + gxt); + tx = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos); // sideways distance // too far off the side? if (abs(tx) > tz<<2) From c8320b6c9dad1996a96557858c00e1f5f9f9a4c9 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 19 May 2020 16:58:53 +0100 Subject: [PATCH 17/25] split "rot" into two variables: frame and rot, for frame number and rotation angle it always bothered me that "rot" was used for both of the above, since it confused me as to what it was for every time I look at this function --- src/r_things.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index febb5b6dc..cd19dfa90 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1358,7 +1358,7 @@ static void R_ProjectSprite(mobj_t *thing) #endif size_t lump; - size_t rot; + size_t frame, rot; UINT16 flip; boolean vflip = (!(thing->eflags & MFE_VERTICALFLIP) != !(thing->frame & FF_VERTICALFLIP)); @@ -1420,7 +1420,7 @@ static void R_ProjectSprite(mobj_t *thing) I_Error("R_ProjectSprite: invalid sprite number %d ", thing->sprite); #endif - rot = thing->frame&FF_FRAMEMASK; + frame = thing->frame&FF_FRAMEMASK; //Fab : 02-08-98: 'skin' override spritedef currently used for skin if (thing->skin && thing->sprite == SPR_PLAY) @@ -1429,15 +1429,15 @@ static void R_ProjectSprite(mobj_t *thing) #ifdef ROTSPRITE sprinfo = &((skin_t *)thing->skin)->sprinfo[thing->sprite2]; #endif - if (rot >= sprdef->numframes) { - CONS_Alert(CONS_ERROR, M_GetText("R_ProjectSprite: invalid skins[\"%s\"].sprites[%sSPR2_%s] frame %s\n"), ((skin_t *)thing->skin)->name, ((thing->sprite2 & FF_SPR2SUPER) ? "FF_SPR2SUPER|": ""), spr2names[(thing->sprite2 & ~FF_SPR2SUPER)], sizeu5(rot)); + if (frame >= sprdef->numframes) { + CONS_Alert(CONS_ERROR, M_GetText("R_ProjectSprite: invalid skins[\"%s\"].sprites[%sSPR2_%s] frame %s\n"), ((skin_t *)thing->skin)->name, ((thing->sprite2 & FF_SPR2SUPER) ? "FF_SPR2SUPER|": ""), spr2names[(thing->sprite2 & ~FF_SPR2SUPER)], sizeu5(frame)); thing->sprite = states[S_UNKNOWN].sprite; thing->frame = states[S_UNKNOWN].frame; sprdef = &sprites[thing->sprite]; #ifdef ROTSPRITE sprinfo = NULL; #endif - rot = thing->frame&FF_FRAMEMASK; + frame = thing->frame&FF_FRAMEMASK; } } else @@ -1447,10 +1447,10 @@ static void R_ProjectSprite(mobj_t *thing) sprinfo = NULL; #endif - if (rot >= sprdef->numframes) + if (frame >= sprdef->numframes) { CONS_Alert(CONS_ERROR, M_GetText("R_ProjectSprite: invalid sprite frame %s/%s for %s\n"), - sizeu1(rot), sizeu2(sprdef->numframes), sprnames[thing->sprite]); + sizeu1(frame), sizeu2(sprdef->numframes), sprnames[thing->sprite]); if (thing->sprite == thing->state->sprite && thing->frame == thing->state->frame) { thing->state->sprite = states[S_UNKNOWN].sprite; @@ -1459,11 +1459,11 @@ static void R_ProjectSprite(mobj_t *thing) thing->sprite = states[S_UNKNOWN].sprite; thing->frame = states[S_UNKNOWN].frame; sprdef = &sprites[thing->sprite]; - rot = thing->frame&FF_FRAMEMASK; + frame = thing->frame&FF_FRAMEMASK; } } - sprframe = &sprdef->spriteframes[rot]; + sprframe = &sprdef->spriteframes[frame]; #ifdef PARANOIA if (!sprframe) @@ -1517,7 +1517,7 @@ static void R_ProjectSprite(mobj_t *thing) { rollangle = R_GetRollAngle(thing->rollangle); if (!(sprframe->rotsprite.cached & (1<sprite, (thing->frame & FF_FRAMEMASK), sprinfo, sprframe, rot, flip); + R_CacheRotSprite(thing->sprite, frame, sprinfo, sprframe, rot, flip); rotsprite = sprframe->rotsprite.patch[rot][rollangle]; if (rotsprite != NULL) { From 1a790235c69833f31e915586b6358c501ef87c20 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 19 May 2020 17:19:44 +0100 Subject: [PATCH 18/25] added basic culling of papersprites if tx for either is too large, proper clamping to be added later also removed some commented out old code --- src/r_things.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index cd19dfa90..27a7c0bb6 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1557,7 +1557,6 @@ static void R_ProjectSprite(mobj_t *thing) tr_y += FixedMul(offset, sinmul); tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); yscale = FixedDiv(projectiony, tz); - //if (yscale < 64) return; // Fix some funky visuals tx = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos); xscale = FixedDiv(projection, tz); @@ -1577,7 +1576,6 @@ static void R_ProjectSprite(mobj_t *thing) tr_y += FixedMul(offset2, sinmul); tz2 = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); yscale2 = FixedDiv(projectiony, tz2); - //if (yscale2 < 64) return; // ditto tx2 = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos); xscale2 = FixedDiv(projection, tz2); @@ -1586,6 +1584,9 @@ static void R_ProjectSprite(mobj_t *thing) if (max(tz, tz2) < FixedMul(MINZ, this_scale)) // non-papersprite clipping is handled earlier return; + if (tx2 < -(tz2<<2) || tx > tz<<2) // too far off the side? + return; + // Needs partially clipped if (tz < FixedMul(MINZ, this_scale)) { @@ -1606,6 +1607,8 @@ static void R_ProjectSprite(mobj_t *thing) x2 = (centerxfrac + FixedMul(tx2,xscale2))>>FRACBITS; } + // TODO: tx clamping + // off the right side? if (x1 > viewwidth) return; From 12e109414384ab80c702382a7fa2549c6eec26a1 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 19 May 2020 17:23:22 +0100 Subject: [PATCH 19/25] We don't actually need x1 or x2 until these points in the function, at least for papersprites --- src/r_things.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 27a7c0bb6..a4bd19627 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1560,7 +1560,6 @@ static void R_ProjectSprite(mobj_t *thing) tx = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos); xscale = FixedDiv(projection, tz); - x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS; // Get paperoffset (offset) and paperoffset (distance) paperoffset = -FixedMul(tr_x, cosmul) - FixedMul(tr_y, sinmul); @@ -1579,7 +1578,6 @@ static void R_ProjectSprite(mobj_t *thing) tx2 = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos); xscale2 = FixedDiv(projection, tz2); - x2 = ((centerxfrac + FixedMul(tx2,xscale2))>>FRACBITS); if (max(tz, tz2) < FixedMul(MINZ, this_scale)) // non-papersprite clipping is handled earlier return; @@ -1595,7 +1593,6 @@ static void R_ProjectSprite(mobj_t *thing) tz = FixedMul(MINZ, this_scale); yscale = FixedDiv(projectiony, tz); xscale = FixedDiv(projection, tz); - x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS; } else if (tz2 < FixedMul(MINZ, this_scale)) { @@ -1604,15 +1601,18 @@ static void R_ProjectSprite(mobj_t *thing) tz2 = FixedMul(MINZ, this_scale); yscale2 = FixedDiv(projectiony, tz2); xscale2 = FixedDiv(projection, tz2); - x2 = (centerxfrac + FixedMul(tx2,xscale2))>>FRACBITS; } // TODO: tx clamping + x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS; + // off the right side? if (x1 > viewwidth) return; + x2 = (centerxfrac + FixedMul(tx2,xscale2))>>FRACBITS; + // off the left side if (x2 < 0) return; From 35e5d673e08485e685a0f7660397348f81e2982d Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 19 May 2020 18:43:33 +0100 Subject: [PATCH 20/25] do tx checking after tz clamping, not before --- src/r_things.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index a4bd19627..6bdb7cae8 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1582,9 +1582,6 @@ static void R_ProjectSprite(mobj_t *thing) if (max(tz, tz2) < FixedMul(MINZ, this_scale)) // non-papersprite clipping is handled earlier return; - if (tx2 < -(tz2<<2) || tx > tz<<2) // too far off the side? - return; - // Needs partially clipped if (tz < FixedMul(MINZ, this_scale)) { @@ -1603,6 +1600,9 @@ static void R_ProjectSprite(mobj_t *thing) xscale2 = FixedDiv(projection, tz2); } + if (tx2 < -(tz2<<2) || tx > tz<<2) // too far off the side? + return; + // TODO: tx clamping x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS; From 65d6b04fd283a76bc505b1aab81abe3583038ea3 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 19 May 2020 18:54:39 +0100 Subject: [PATCH 21/25] change limits for tx based on fov, by multiplying by fovtan this makes it so that higher fov values can actually let you see all the sprites that should be in the view --- src/r_things.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 6bdb7cae8..a29fb6cb7 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1407,7 +1407,7 @@ static void R_ProjectSprite(mobj_t *thing) basetx = tx = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos); // sideways distance // too far off the side? - if (!papersprite && abs(tx) > tz<<2) // papersprite clipping is handled later + if (!papersprite && abs(tx) > FixedMul(tz, fovtan)<<2) // papersprite clipping is handled later return; // aspect ratio stuff @@ -1600,7 +1600,7 @@ static void R_ProjectSprite(mobj_t *thing) xscale2 = FixedDiv(projection, tz2); } - if (tx2 < -(tz2<<2) || tx > tz<<2) // too far off the side? + if (tx2 < -(FixedMul(tz2, fovtan)<<2) || tx > FixedMul(tz, fovtan)<<2) // too far off the side? return; // TODO: tx clamping From c3d576058a2f59833026a3ef6fd1a9c35524c5ab Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 19 May 2020 22:00:34 +0100 Subject: [PATCH 22/25] on second thought maybe we don't need extra tx clamping, it turns out to be more effort than it's worth (at least for now) meanwhile, let's move x/yscale calculations down since we don't actually need them until later on --- src/r_things.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index a29fb6cb7..a40c61058 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1556,10 +1556,8 @@ static void R_ProjectSprite(mobj_t *thing) tr_x += FixedMul(offset, cosmul); tr_y += FixedMul(offset, sinmul); tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); - yscale = FixedDiv(projectiony, tz); tx = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos); - xscale = FixedDiv(projection, tz); // Get paperoffset (offset) and paperoffset (distance) paperoffset = -FixedMul(tr_x, cosmul) - FixedMul(tr_y, sinmul); @@ -1574,10 +1572,8 @@ static void R_ProjectSprite(mobj_t *thing) tr_x += FixedMul(offset2, cosmul); tr_y += FixedMul(offset2, sinmul); tz2 = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); - yscale2 = FixedDiv(projectiony, tz2); tx2 = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos); - xscale2 = FixedDiv(projection, tz2); if (max(tz, tz2) < FixedMul(MINZ, this_scale)) // non-papersprite clipping is handled earlier return; @@ -1588,22 +1584,19 @@ static void R_ProjectSprite(mobj_t *thing) fixed_t div = FixedDiv(tz2-tz, FixedMul(MINZ, this_scale)-tz); tx += FixedDiv(tx2-tx, div); tz = FixedMul(MINZ, this_scale); - yscale = FixedDiv(projectiony, tz); - xscale = FixedDiv(projection, tz); } else if (tz2 < FixedMul(MINZ, this_scale)) { fixed_t div = FixedDiv(tz-tz2, FixedMul(MINZ, this_scale)-tz2); tx2 += FixedDiv(tx-tx2, div); tz2 = FixedMul(MINZ, this_scale); - yscale2 = FixedDiv(projectiony, tz2); - xscale2 = FixedDiv(projection, tz2); } if (tx2 < -(FixedMul(tz2, fovtan)<<2) || tx > FixedMul(tz, fovtan)<<2) // too far off the side? return; - // TODO: tx clamping + yscale = FixedDiv(projectiony, tz); + xscale = FixedDiv(projection, tz); x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS; @@ -1611,6 +1604,9 @@ static void R_ProjectSprite(mobj_t *thing) if (x1 > viewwidth) return; + yscale2 = FixedDiv(projectiony, tz2); + xscale2 = FixedDiv(projection, tz2); + x2 = (centerxfrac + FixedMul(tx2,xscale2))>>FRACBITS; // off the left side From 702a7041d4e7f3274e6c05347e72c8bc0952cf1d Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Wed, 20 May 2020 19:34:18 +0100 Subject: [PATCH 23/25] also do the fovtan multiplication thing with precip sprites --- src/r_things.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/r_things.c b/src/r_things.c index a40c61058..14782d0c2 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1884,7 +1884,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) tx = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos); // sideways distance // too far off the side? - if (abs(tx) > tz<<2) + if (abs(tx) > FixedMul(tz, fovtan)<<2) return; // aspect ratio stuff : From c9c7327011487ec9925e81c9d322af72c93e9487 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 21 May 2020 19:42:48 +0100 Subject: [PATCH 24/25] A_SplitShot fix: don't even attempt to A_FaceTarget (or anything beyond) if there is no target to face to begin with --- src/p_enemy.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/p_enemy.c b/src/p_enemy.c index 061d4d366..bd8a2b054 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -9707,6 +9707,9 @@ void A_SplitShot(mobj_t *actor) if (LUA_CallAction("A_SplitShot", actor)) return; + if (!actor->target) + return; + A_FaceTarget(actor); { const angle_t an = (actor->angle + ANGLE_90) >> ANGLETOFINESHIFT; From 4b7f0f49f18e709fcb7d223940a0f0afd489fc2e Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Fri, 22 May 2020 18:32:34 +0100 Subject: [PATCH 25/25] added the ability to get the # of a mapthing_t in Lua --- src/lua_mobjlib.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 81729b788..ac1432b4c 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -829,6 +829,15 @@ static int mapthing_set(lua_State *L) return 0; } +static int mapthing_num(lua_State *L) +{ + mapthing_t *mt = *((mapthing_t **)luaL_checkudata(L, 1, META_MAPTHING)); + if (!mt) + return luaL_error(L, "accessed mapthing_t doesn't exist anymore."); + lua_pushinteger(L, mt-mapthings); + return 1; +} + static int lib_iterateMapthings(lua_State *L) { size_t i = 0; @@ -893,6 +902,9 @@ int LUA_MobjLib(lua_State *L) lua_pushcfunction(L, mapthing_set); lua_setfield(L, -2, "__newindex"); + + lua_pushcfunction(L, mapthing_num); + lua_setfield(L, -2, "__len"); lua_pop(L,1); lua_newuserdata(L, 0);