- Fixed: SectorDamage did not work with 3D floors.

SVN r3594 (trunk)
This commit is contained in:
Randy Heit 2012-04-26 02:35:02 +00:00
parent 142a15b9c6
commit 3523e4f24a
3 changed files with 79 additions and 55 deletions

View File

@ -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 = &sectors[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;

View File

@ -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 = &sectors[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);
}
}
}
}
}
}
//============================================================================
//

View File

@ -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);