diff --git a/src/p_floor.c b/src/p_floor.c index bef57014c..e46b0b4fb 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1281,21 +1281,37 @@ void T_ThwompSector(levelspecthink_t *thwomp) #undef ceilingwasheight } +static boolean T_SectorHasEnemies(sector_t *sec) +{ + msecnode_t *node = sec->touching_thinglist; // things touching this sector + mobj_t *mo; + while (node) + { + mo = node->m_thing; + + if ((mo->flags & (MF_ENEMY|MF_BOSS)) + && mo->health > 0 + && mo->z < sec->ceilingheight + && mo->z + mo->height > sec->floorheight) + return true; + + node = node->m_thinglist_next; + } + + return false; +} + // // T_NoEnemiesThinker // // Runs a linedef exec when no more MF_ENEMY/MF_BOSS objects with health are in the area // \sa P_AddNoEnemiesThinker // -void T_NoEnemiesSector(levelspecthink_t *nobaddies) +void T_NoEnemiesSector(noenemies_t *nobaddies) { size_t i; - fixed_t upperbound, lowerbound; sector_t *sec = NULL; - sector_t *targetsec = NULL; INT32 secnum = -1; - msecnode_t *node; - mobj_t *thing; boolean FOFsector = false; while ((secnum = P_FindSectorFromLineTag(nobaddies->sourceline, secnum)) >= 0) @@ -1316,40 +1332,13 @@ void T_NoEnemiesSector(levelspecthink_t *nobaddies) while ((targetsecnum = P_FindSectorFromLineTag(sec->lines[i], targetsecnum)) >= 0) { - targetsec = §ors[targetsecnum]; - - upperbound = targetsec->ceilingheight; - lowerbound = targetsec->floorheight; - node = targetsec->touching_thinglist; // things touching this sector - while (node) - { - thing = node->m_thing; - - if ((thing->flags & (MF_ENEMY|MF_BOSS)) && thing->health > 0 - && thing->z < upperbound && thing->z+thing->height > lowerbound) - return; - - node = node->m_thinglist_next; - } - } - } - - if (!FOFsector) - { - upperbound = sec->ceilingheight; - lowerbound = sec->floorheight; - node = sec->touching_thinglist; // things touching this sector - while (node) - { - thing = node->m_thing; - - if ((thing->flags & (MF_ENEMY|MF_BOSS)) && thing->health > 0 - && thing->z < upperbound && thing->z+thing->height > lowerbound) + if (T_SectorHasEnemies(§ors[targetsecnum])) return; - - node = node->m_thinglist_next; } } + + if (!FOFsector && T_SectorHasEnemies(sec)) + return; } CONS_Debug(DBG_GAMELOGIC, "Running no-more-enemies exec with tag of %d\n", nobaddies->sourceline->tag); diff --git a/src/p_saveg.c b/src/p_saveg.c index e9d2e0836..afcd9867e 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1658,6 +1658,18 @@ static void SaveSpecialLevelThinker(const thinker_t *th, const UINT8 type) WRITEUINT32(save_p, SaveSector(ht->sector)); } +// +// SaveNoEnemiesThinker +// +// Saves a noenemies_t thinker +// +static void SaveNoEnemiesThinker(const thinker_t *th, const UINT8 type) +{ + const noenemies_t *ht = (const void *)th; + WRITEUINT8(save_p, type); + WRITEUINT32(save_p, SaveLine(ht->sourceline)); +} + // // SaveContinuousFallThinker // @@ -2310,7 +2322,7 @@ static void P_NetArchiveThinkers(void) } else if (th->function.acp1 == (actionf_p1)T_NoEnemiesSector) { - SaveSpecialLevelThinker(th, tc_noenemies); + SaveNoEnemiesThinker(th, tc_noenemies); continue; } else if (th->function.acp1 == (actionf_p1)T_EachTimeThinker) @@ -2848,6 +2860,18 @@ static thinker_t* LoadSpecialLevelThinker(actionf_p1 thinker, UINT8 floorOrCeili return &ht->thinker; } +// LoadNoEnemiesThinker +// +// Loads a noenemies_t from a save game +// +static thinker_t* LoadNoEnemiesThinker(actionf_p1 thinker) +{ + noenemies_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + ht->sourceline = LoadLine(READUINT32(save_p)); + return &ht->thinker; +} + // LoadContinuousFallThinker // // Loads a continuousfall_t from a save game @@ -3604,7 +3628,7 @@ static void P_NetUnArchiveThinkers(void) break; case tc_noenemies: - th = LoadSpecialLevelThinker((actionf_p1)T_NoEnemiesSector, 0); + th = LoadNoEnemiesThinker((actionf_p1)T_NoEnemiesSector); break; case tc_eachtime: diff --git a/src/p_spec.c b/src/p_spec.c index 54a6d88d6..6bcac18f9 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6107,14 +6107,13 @@ static inline void P_AddThwompThinker(sector_t *sec, sector_t *actionsector, lin /** Adds a thinker which checks if any MF_ENEMY objects with health are in the defined area. * If not, a linedef executor is run once. * - * \param sec Control sector. * \param sourceline Control linedef. * \sa P_SpawnSpecials, T_NoEnemiesSector * \author SSNTails */ -static inline void P_AddNoEnemiesThinker(sector_t *sec, line_t *sourceline) +static inline void P_AddNoEnemiesThinker(line_t *sourceline) { - levelspecthink_t *nobaddies; + noenemies_t *nobaddies; // create and initialize new thinker nobaddies = Z_Calloc(sizeof (*nobaddies), PU_LEVSPEC, NULL); @@ -6122,7 +6121,6 @@ static inline void P_AddNoEnemiesThinker(sector_t *sec, line_t *sourceline) nobaddies->thinker.function.acp1 = (actionf_p1)T_NoEnemiesSector; - nobaddies->sector = sec; nobaddies->sourceline = sourceline; } @@ -7124,8 +7122,7 @@ void P_SpawnSpecials(boolean fromnetsave) // No More Enemies Linedef Exec case 313: - sec = sides[*lines[i].sidenum].sector - sectors; - P_AddNoEnemiesThinker(§ors[sec], &lines[i]); + P_AddNoEnemiesThinker(&lines[i]); break; // Pushable linedef executors (count # of pushables) diff --git a/src/p_spec.h b/src/p_spec.h index 946b01bcf..ef98be5c4 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -320,6 +320,12 @@ typedef struct sector_t *sector; // Sector the thinker is from } levelspecthink_t; +typedef struct +{ + thinker_t thinker; + line_t *sourceline; // Source line of the thinker +} noenemies_t; + typedef struct { thinker_t thinker; @@ -414,7 +420,7 @@ void T_MarioBlock(mariothink_t *block); void T_FloatSector(floatthink_t *floater); void T_MarioBlockChecker(levelspecthink_t *block); void T_ThwompSector(levelspecthink_t *thwomp); -void T_NoEnemiesSector(levelspecthink_t *nobaddies); +void T_NoEnemiesSector(noenemies_t *nobaddies); void T_EachTimeThinker(eachtime_t *eachtime); void T_CameraScanner(elevator_t *elevator); void T_RaiseSector(raise_t *raise);