From 44434a64d1e92b82d02bab4bd354c49dceb782e0 Mon Sep 17 00:00:00 2001 From: MascaraSnake <jonassauer27@gmail.com> Date: Thu, 9 Dec 2021 07:10:16 +0100 Subject: [PATCH] Refactor P_RunTriggerLinedef --- src/p_spec.c | 414 +++++++++++++++++++++++++-------------------------- 1 file changed, 202 insertions(+), 212 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 265cba2b53..ed2f9eb977 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1501,108 +1501,215 @@ static boolean P_CheckNightsTriggerLine(line_t *triggerline, mobj_t *actor) return true; } -/** Used by P_LinedefExecute to check a trigger linedef's conditions - * The linedef executor specials in the trigger linedef's sector are run if all conditions are met. - * Return false cancels P_LinedefExecute, this happens if a condition is not met. - * - * \param triggerline Trigger linedef to check conditions for; should NEVER be NULL. - * \param actor Object initiating the action; should not be NULL. - * \param caller Sector in which the action was started. May be NULL. - * \sa P_ProcessLineSpecial, P_LinedefExecute - */ -boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller) +static boolean P_CheckPlayerMare(line_t *triggerline, INT32 targetmare) { - sector_t *ctlsector; - fixed_t dist = P_AproxDistance(triggerline->dx, triggerline->dy)>>FRACBITS; - size_t i, linecnt, sectori; - INT16 specialtype = triggerline->special; + UINT8 mare; - ///////////////////////////////////////////////// - // Distance-checking/sector trigger conditions // - ///////////////////////////////////////////////// + if (!(maptol & TOL_NIGHTS)) + return false; - // Linetypes 303 and 304 require a specific - // number, or minimum or maximum, of rings. - if (specialtype == 303 || specialtype == 304) - { - fixed_t rings = 0; + mare = P_FindLowestMare(); - // With the passuse flag, count all player's - // rings. - if (triggerline->flags & ML_EFFECT4) - { - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator) - continue; + if (triggerline->flags & ML_NOCLIMB) + return mare <= targetmare; - if (!players[i].mo || ((maptol & TOL_NIGHTS) ? players[i].spheres : players[i].rings) <= 0) - continue; + if (triggerline->flags & ML_BLOCKMONSTERS) + return mare >= targetmare; - rings += (maptol & TOL_NIGHTS) ? players[i].spheres : players[i].rings; - } - } - else - { - if (!(actor && actor->player)) - return false; // no player to count rings from here, sorry + return mare == targetmare; +} - rings = (maptol & TOL_NIGHTS) ? actor->player->spheres : actor->player->rings; - } +static boolean P_CheckPlayerRings(line_t *triggerline, mobj_t *actor, INT32 targetrings) +{ + INT32 rings = 0; + size_t i; - if (triggerline->flags & ML_NOCLIMB) - { - if (rings > dist) - return false; - } - else if (triggerline->flags & ML_BLOCKMONSTERS) - { - if (rings < dist) - return false; - } - else + // With the passuse flag, count all player's + // rings. + if (triggerline->flags & ML_EFFECT4) + { + for (i = 0; i < MAXPLAYERS; i++) { - if (rings != dist) - return false; + if (!playeringame[i] || players[i].spectator) + continue; + + if (!players[i].mo || ((maptol & TOL_NIGHTS) ? players[i].spheres : players[i].rings) <= 0) + continue; + + rings += (maptol & TOL_NIGHTS) ? players[i].spheres : players[i].rings; } } - else if (specialtype >= 314 && specialtype <= 315) + else { - msecnode_t *node; - mobj_t *mo; - INT32 numpush = 0; - INT32 numneeded = dist; + if (!(actor && actor->player)) + return false; // no player to count rings from here, sorry + + rings = (maptol & TOL_NIGHTS) ? actor->player->spheres : actor->player->rings; + } - if (!caller) - return false; // we need a calling sector to find pushables in, silly! + if (triggerline->flags & ML_NOCLIMB) + return rings <= targetrings; - // Count the pushables in this sector - node = caller->touching_thinglist; // things touching this sector - while (node) - { - mo = node->m_thing; - if ((mo->flags & MF_PUSHABLE) || ((mo->info->flags & MF_PUSHABLE) && mo->fuse)) - numpush++; - node = node->m_thinglist_next; - } + if (triggerline->flags & ML_BLOCKMONSTERS) + return rings >= targetrings; - if (triggerline->flags & ML_NOCLIMB) // Need at least or more - { - if (numpush < numneeded) - return false; - } - else if (triggerline->flags & ML_EFFECT4) // Need less than + return rings == targetrings; +} + +static boolean P_CheckPushables(line_t *triggerline, sector_t *caller, INT32 targetpushables) +{ + msecnode_t *node; + mobj_t *mo; + INT32 numpushables = 0; + + if (!caller) + return false; // we need a calling sector to find pushables in, silly! + + // Count the pushables in this sector + for (node = caller->touching_thinglist; node; node = node->m_thinglist_next) + { + mo = node->m_thing; + if ((mo->flags & MF_PUSHABLE) || ((mo->info->flags & MF_PUSHABLE) && mo->fuse)) + numpushables++; + } + + if (triggerline->flags & ML_NOCLIMB) + return numpushables >= targetpushables; + + if (triggerline->flags & ML_EFFECT4) + return numpushables <= targetpushables; + + return numpushables == targetpushables; +} + +static void P_ActivateLinedefExecutor(line_t *line, mobj_t *actor, sector_t *caller) +{ + if (line->special < 400 || line->special >= 500) + return; + + if (line->executordelay) + P_AddExecutorDelay(line, actor, caller); + else + P_ProcessLineSpecial(line, actor, caller); +} + +static boolean P_ActivateLinedefExecutorsInSector(line_t *triggerline, mobj_t *actor, sector_t *caller) +{ + sector_t *ctlsector = triggerline->frontsector; + size_t sectori = (size_t)(ctlsector - sectors); + size_t linecnt = ctlsector->linecount; + size_t i; + + if (triggerline->flags & ML_EFFECT5) // disregard order for efficiency + { + for (i = 0; i < linecnt; i++) + P_ActivateLinedefExecutor(ctlsector->lines[i], actor, caller); + } + else // walk around the sector in a defined order + { + boolean backwards = false; + size_t j, masterlineindex = (size_t)-1; + + for (i = 0; i < linecnt; i++) + if (ctlsector->lines[i] == triggerline) + { + masterlineindex = i; + break; + } + +#ifdef PARANOIA + if (masterlineindex == (size_t)-1) { - if (numpush >= numneeded) - return false; + const size_t li = (size_t)(ctlsector->lines[i] - lines); + I_Error("Line %s isn't linked into its front sector", sizeu1(li)); } - else // Need exact +#endif + + // i == masterlineindex + for (;;) { - if (numpush != numneeded) - return false; + if (backwards) // v2 to v1 + { + for (j = 0; j < linecnt; j++) + { + if (i == j) + continue; + if (ctlsector->lines[i]->v1 == ctlsector->lines[j]->v2) + { + i = j; + break; + } + if (ctlsector->lines[i]->v1 == ctlsector->lines[j]->v1) + { + i = j; + backwards = false; + break; + } + } + if (j == linecnt) + { + const size_t vertexei = (size_t)(ctlsector->lines[i]->v1 - vertexes); + CONS_Debug(DBG_GAMELOGIC, "Warning: Sector %s is not closed at vertex %s (%d, %d)\n", + sizeu1(sectori), sizeu2(vertexei), ctlsector->lines[i]->v1->x, ctlsector->lines[i]->v1->y); + return false; // abort + } + } + else // v1 to v2 + { + for (j = 0; j < linecnt; j++) + { + if (i == j) + continue; + if (ctlsector->lines[i]->v2 == ctlsector->lines[j]->v1) + { + i = j; + break; + } + if (ctlsector->lines[i]->v2 == ctlsector->lines[j]->v2) + { + i = j; + backwards = true; + break; + } + } + if (j == linecnt) + { + const size_t vertexei = (size_t)(ctlsector->lines[i]->v1 - vertexes); + CONS_Debug(DBG_GAMELOGIC, "Warning: Sector %s is not closed at vertex %s (%d, %d)\n", + sizeu1(sectori), sizeu2(vertexei), ctlsector->lines[i]->v2->x, ctlsector->lines[i]->v2->y); + return false; // abort + } + } + + if (i == masterlineindex) + break; + + P_ActivateLinedefExecutor(ctlsector->lines[i], actor, caller); } } - else if (caller) + + return true; +} + +/** Used by P_LinedefExecute to check a trigger linedef's conditions + * The linedef executor specials in the trigger linedef's sector are run if all conditions are met. + * Return false cancels P_LinedefExecute, this happens if a condition is not met. + * + * \param triggerline Trigger linedef to check conditions for; should NEVER be NULL. + * \param actor Object initiating the action; should not be NULL. + * \param caller Sector in which the action was started. May be NULL. + * \sa P_ProcessLineSpecial, P_LinedefExecute + */ +boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller) +{ + fixed_t dist = P_AproxDistance(triggerline->dx, triggerline->dy)>>FRACBITS; + INT16 specialtype = triggerline->special; + + //////////////////////// + // Trigger conditions // + //////////////////////// + + if (caller) { if (GETSECSPECIAL(caller->special, 2) == 6) { @@ -1611,28 +1718,8 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller } else if (GETSECSPECIAL(caller->special, 2) == 7) { - UINT8 mare; - - if (!(maptol & TOL_NIGHTS)) + if (!P_CheckPlayerMare(triggerline, dist)) return false; - - mare = P_FindLowestMare(); - - if (triggerline->flags & ML_NOCLIMB) - { - if (!(mare <= dist)) - return false; - } - else if (triggerline->flags & ML_BLOCKMONSTERS) - { - if (!(mare >= dist)) - return false; - } - else - { - if (!(mare == dist)) - return false; - } } // If we were not triggered by a sector type especially for the purpose, // a Linedef Executor linedef trigger is not handling sector triggers properly, return. @@ -1646,12 +1733,13 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller } } - ////////////////////////////////////// - // Miscellaneous trigger conditions // - ////////////////////////////////////// - switch (specialtype) { + case 303: // continuous + case 304: // once + if (!P_CheckPlayerRings(triggerline, actor, dist)) + return false; + break; case 305: // continuous case 306: // each time case 307: // once @@ -1670,6 +1758,11 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller if (!(actor && actor->player && actor->player->ctfteam == 2)) return false; break; + case 314: // continuous + case 315: // once + if (!P_CheckPushables(triggerline, caller, dist)) + return false; + break; case 317: // continuous case 318: // once { // Unlockable triggers required @@ -1743,111 +1836,8 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller // Processing linedef specials // ///////////////////////////////// - ctlsector = triggerline->frontsector; - sectori = (size_t)(ctlsector - sectors); - linecnt = ctlsector->linecount; - - if (triggerline->flags & ML_EFFECT5) // disregard order for efficiency - { - for (i = 0; i < linecnt; i++) - if (ctlsector->lines[i]->special >= 400 - && ctlsector->lines[i]->special < 500) - { - if (ctlsector->lines[i]->executordelay) - P_AddExecutorDelay(ctlsector->lines[i], actor, caller); - else - P_ProcessLineSpecial(ctlsector->lines[i], actor, caller); - } - } - else // walk around the sector in a defined order - { - boolean backwards = false; - size_t j, masterlineindex = (size_t)-1; - - for (i = 0; i < linecnt; i++) - if (ctlsector->lines[i] == triggerline) - { - masterlineindex = i; - break; - } - -#ifdef PARANOIA - if (masterlineindex == (size_t)-1) - { - const size_t li = (size_t)(ctlsector->lines[i] - lines); - I_Error("Line %s isn't linked into its front sector", sizeu1(li)); - } -#endif - - // i == masterlineindex - for (;;) - { - if (backwards) // v2 to v1 - { - for (j = 0; j < linecnt; j++) - { - if (i == j) - continue; - if (ctlsector->lines[i]->v1 == ctlsector->lines[j]->v2) - { - i = j; - break; - } - if (ctlsector->lines[i]->v1 == ctlsector->lines[j]->v1) - { - i = j; - backwards = false; - break; - } - } - if (j == linecnt) - { - const size_t vertexei = (size_t)(ctlsector->lines[i]->v1 - vertexes); - CONS_Debug(DBG_GAMELOGIC, "Warning: Sector %s is not closed at vertex %s (%d, %d)\n", - sizeu1(sectori), sizeu2(vertexei), ctlsector->lines[i]->v1->x, ctlsector->lines[i]->v1->y); - return false; // abort - } - } - else // v1 to v2 - { - for (j = 0; j < linecnt; j++) - { - if (i == j) - continue; - if (ctlsector->lines[i]->v2 == ctlsector->lines[j]->v1) - { - i = j; - break; - } - if (ctlsector->lines[i]->v2 == ctlsector->lines[j]->v2) - { - i = j; - backwards = true; - break; - } - } - if (j == linecnt) - { - const size_t vertexei = (size_t)(ctlsector->lines[i]->v1 - vertexes); - CONS_Debug(DBG_GAMELOGIC, "Warning: Sector %s is not closed at vertex %s (%d, %d)\n", - sizeu1(sectori), sizeu2(vertexei), ctlsector->lines[i]->v2->x, ctlsector->lines[i]->v2->y); - return false; // abort - } - } - - if (i == masterlineindex) - break; - - if (ctlsector->lines[i]->special >= 400 - && ctlsector->lines[i]->special < 500) - { - if (ctlsector->lines[i]->executordelay) - P_AddExecutorDelay(ctlsector->lines[i], actor, caller); - else - P_ProcessLineSpecial(ctlsector->lines[i], actor, caller); - } - } - } + if (!P_ActivateLinedefExecutorsInSector(triggerline, actor, caller)) + return false; // "Trigger on X calls" linedefs reset if noclimb is set if ((specialtype == 321 || specialtype == 322) && triggerline->flags & ML_NOCLIMB) -- GitLab