diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 3667d0505..9bff85433 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -97,13 +97,6 @@ FRandom pr_acs ("ACS"); #define NOT_FLOOR 8 #define NOT_CEILING 16 -// Flags for SectorDamage - -#define DAMAGE_PLAYERS 1 -#define DAMAGE_NONPLAYERS 2 -#define DAMAGE_IN_AIR 4 -#define DAMAGE_SUBCLASSES_PROTECT 8 - struct CallReturn { CallReturn(int pc, ScriptFunction *func, FBehavior *module, SDWORD *locals, bool discard, FString &str) @@ -6970,53 +6963,7 @@ int DLevelScript::RunScript () int flags = STACK(1); sp -= 5; - int secnum = -1; - - while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0) - { - AActor *actor, *next; - sector_t *sec = §ors[secnum]; - - for (actor = sec->thinglist; actor != NULL; actor = next) - { - next = actor->snext; - - if (!(actor->flags & MF_SHOOTABLE)) - continue; - - if (!(flags & DAMAGE_NONPLAYERS) && actor->player == NULL) - continue; - - if (!(flags & DAMAGE_PLAYERS) && actor->player != NULL) - continue; - - if (!(flags & DAMAGE_IN_AIR) && actor->z != sec->floorplane.ZatPoint (actor->x, actor->y) && !actor->waterlevel) - continue; - - if (protectClass != NULL) - { - if (!(flags & DAMAGE_SUBCLASSES_PROTECT)) - { - if (actor->FindInventory (protectClass)) - continue; - } - else - { - AInventory *item; - - for (item = actor->Inventory; item != NULL; item = item->Inventory) - { - if (item->IsKindOf (protectClass)) - break; - } - if (item != NULL) - continue; - } - } - - P_DamageMobj (actor, NULL, NULL, amount, type); - } - } + P_SectorDamage(tag, amount, type, protectClass, flags); } break; diff --git a/src/p_spec.cpp b/src/p_spec.cpp index a41fa2cad..e3a27201f 100644 --- a/src/p_spec.cpp +++ b/src/p_spec.cpp @@ -585,6 +585,77 @@ void P_PlayerInSpecialSector (player_t *player, sector_t * sector) } } +//============================================================================ +// +// P_SectorDamage +// +//============================================================================ + +static void DoSectorDamage(AActor *actor, sector_t *sec, int amount, FName type, const PClass *protectClass, int flags) +{ + if (!(actor->flags & MF_SHOOTABLE)) + return; + + if (!(flags & DAMAGE_NONPLAYERS) && actor->player == NULL) + return; + + if (!(flags & DAMAGE_PLAYERS) && actor->player != NULL) + return; + + if (!(flags & DAMAGE_IN_AIR) && actor->z != sec->floorplane.ZatPoint(actor->x, actor->y) && !actor->waterlevel) + return; + + if (protectClass != NULL) + { + if (actor->FindInventory(protectClass, !!(flags & DAMAGE_SUBCLASSES_PROTECT))) + return; + } + + P_DamageMobj (actor, NULL, NULL, amount, type); +} + +void P_SectorDamage(int tag, int amount, FName type, const PClass *protectClass, int flags) +{ + int secnum = -1; + + while ((secnum = P_FindSectorFromTag (tag, secnum)) >= 0) + { + AActor *actor, *next; + sector_t *sec = §ors[secnum]; + + // Do for actors in this sector. + for (actor = sec->thinglist; actor != NULL; actor = next) + { + next = actor->snext; + DoSectorDamage(actor, sec, amount, type, protectClass, flags); + } + // If this is a 3D floor control sector, also do for anything in/on + // those 3D floors. + for (unsigned i = 0; i < sec->e->XFloor.attached.Size(); ++i) + { + sector_t *sec2 = sec->e->XFloor.attached[i]; + + for (actor = sec2->thinglist; actor != NULL; actor = next) + { + next = actor->snext; + // Only affect actors touching the 3D floor + if (actor->z + actor->height > sec->floorplane.ZatPoint(actor->x, actor->y)) + { + // If DAMAGE_IN_AIR is used, anything not beneath the 3D floor will be + // damaged (so, anything touching it or above it). Other 3D floors between + // the actor and this one will not stop this effect. + if ((flags & DAMAGE_IN_AIR) || actor->z <= sec->ceilingplane.ZatPoint(actor->x, actor->y)) + { + // Here we pass the DAMAGE_IN_AIR flag to disable the floor check, since it + // only works with the real sector's floor. We did the appropriate height checks + // for 3D floors already. + DoSectorDamage(actor, NULL, amount, type, protectClass, flags | DAMAGE_IN_AIR); + } + } + } + } + } +} //============================================================================ // diff --git a/src/p_spec.h b/src/p_spec.h index d30fb4f83..81051eb8e 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -145,6 +145,12 @@ bool PIT_PushThing (AActor *thing); // Define values for map objects #define MO_TELEPORTMAN 14 +// Flags for P_SectorDamage +#define DAMAGE_PLAYERS 1 +#define DAMAGE_NONPLAYERS 2 +#define DAMAGE_IN_AIR 4 +#define DAMAGE_SUBCLASSES_PROTECT 8 + // [RH] If a deathmatch game, checks to see if noexit is enabled. // If so, it kills the player and returns false. Otherwise, @@ -163,7 +169,7 @@ bool P_TestActivateLine (line_t *ld, AActor *mo, int side, int activationType); void P_PlayerInSpecialSector (player_t *player, sector_t * sector=NULL); void P_PlayerOnSpecialFlat (player_t *player, int floorType); - +void P_SectorDamage(int tag, int amount, FName type, const PClass *protectClass, int flags); void P_SetSectorFriction (int tag, int amount, bool alterFlag); void P_GiveSecret(AActor *actor, bool printmessage, bool playsound);