Re-added sector damage for non-players. (#2773)
* Re-add non-player sector damage. Reimplements SECMF_HURTMONSTERS and SECMF_HARMINAIR. * Fixed 3D floor handling for sector damage. Fixes sector damage to either monsters or players not working on (non-)solid 3D floors.
This commit is contained in:
parent
12c6d1361a
commit
34dc204517
14 changed files with 100 additions and 57 deletions
|
|
@ -100,7 +100,7 @@
|
|||
#include "c_console.h"
|
||||
#include "p_spec_thinkers.h"
|
||||
|
||||
static FRandom pr_playerinspecialsector ("PlayerInSpecialSector");
|
||||
static FRandom pr_actorinspecialsector ("ActorInSpecialSector");
|
||||
|
||||
EXTERN_CVAR(Bool, cl_predict_specials)
|
||||
EXTERN_CVAR(Bool, forcewater)
|
||||
|
|
@ -419,23 +419,27 @@ bool P_PredictLine(line_t *line, AActor *mo, int side, int activationType)
|
|||
}
|
||||
|
||||
//
|
||||
// P_PlayerInSpecialSector
|
||||
// P_ActorInSpecialSector
|
||||
// Called every tic frame
|
||||
// that the player origin is in a special sector
|
||||
// that the actor origin is in a special sector
|
||||
//
|
||||
void P_PlayerInSpecialSector (player_t *player, sector_t * sector)
|
||||
void P_ActorInSpecialSector (AActor *victim, sector_t * sector, F3DFloor* Ffloor)
|
||||
{
|
||||
if (sector == NULL)
|
||||
{
|
||||
// Falling, not all the way down yet?
|
||||
sector = player->mo->Sector;
|
||||
if (!player->mo->isAtZ(sector->LowestFloorAt(player->mo))
|
||||
&& !player->mo->waterlevel)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
sector = victim->Sector;
|
||||
|
||||
// Falling, not all the way down yet?
|
||||
if (Ffloor != nullptr && !(Ffloor->flags & FF_SOLID)) Printf("this 3d floor is not solid\n");
|
||||
bool evilAir = (sector->MoreFlags & SECMF_HARMINAIR);
|
||||
bool SolidFfloor = Ffloor != nullptr && (Ffloor->flags & FF_SOLID);
|
||||
if ((!evilAir && !(Ffloor != nullptr && !SolidFfloor)) && !victim->waterlevel)
|
||||
{
|
||||
// [inkoalawetrust] Check for 3D floors differently, because non-FF_INVERTSECTOR ffloors have their floor plane as the 3D floor BOTTOM.
|
||||
double theZ = Ffloor == nullptr ? sector->LowestFloorAt(victim) : Ffloor->top.plane->ZatPoint(victim);
|
||||
if (!victim->isAtZ(theZ))
|
||||
return;
|
||||
}
|
||||
|
||||
// Has hit ground.
|
||||
|
||||
auto Level = sector->Level;
|
||||
|
|
@ -445,7 +449,7 @@ void P_PlayerInSpecialSector (player_t *player, sector_t * sector)
|
|||
if (sector->damageinterval <= 0)
|
||||
sector->damageinterval = 32; // repair invalid damageinterval values
|
||||
|
||||
if (sector->Flags & (SECF_EXIT1 | SECF_EXIT2))
|
||||
if (victim->player && sector->Flags & (SECF_EXIT1 | SECF_EXIT2))
|
||||
{
|
||||
for (int i = 0; i < MAXPLAYERS; i++)
|
||||
if (playeringame[i])
|
||||
|
|
@ -464,7 +468,7 @@ void P_PlayerInSpecialSector (player_t *player, sector_t * sector)
|
|||
// different damage types yet, so that's not happening for now.
|
||||
// [MK] account for subclasses that may have "Full" protection (i.e.: prevent leaky damage)
|
||||
int ironfeet = 0;
|
||||
for (auto i = player->mo->Inventory; i != NULL; i = i->Inventory)
|
||||
for (auto i = victim->Inventory; i != NULL; i = i->Inventory)
|
||||
{
|
||||
if (i->IsKindOf(NAME_PowerIronFeet))
|
||||
{
|
||||
|
|
@ -476,28 +480,28 @@ void P_PlayerInSpecialSector (player_t *player, sector_t * sector)
|
|||
}
|
||||
}
|
||||
|
||||
if (sector->Flags & SECF_ENDGODMODE) player->cheats &= ~CF_GODMODE;
|
||||
if ((ironfeet == 0 || (ironfeet < 2 && pr_playerinspecialsector() < sector->leakydamage)))
|
||||
if (victim->player && sector->Flags & SECF_ENDGODMODE) victim->player->cheats &= ~CF_GODMODE;
|
||||
if ((ironfeet == 0 || (ironfeet < 2 && pr_actorinspecialsector() < sector->leakydamage)))
|
||||
{
|
||||
if (sector->Flags & SECF_HAZARD)
|
||||
if (victim->player && sector->Flags & SECF_HAZARD)
|
||||
{
|
||||
player->hazardcount += sector->damageamount;
|
||||
player->hazardtype = sector->damagetype;
|
||||
player->hazardinterval = sector->damageinterval;
|
||||
victim->player->hazardcount += sector->damageamount;
|
||||
victim->player->hazardtype = sector->damagetype;
|
||||
victim->player->hazardinterval = sector->damageinterval;
|
||||
}
|
||||
else if (Level->time % sector->damageinterval == 0)
|
||||
{
|
||||
if (!(player->cheats & (CF_GODMODE | CF_GODMODE2)))
|
||||
if (!(victim->player && victim->player->cheats & (CF_GODMODE | CF_GODMODE2)))
|
||||
{
|
||||
P_DamageMobj(player->mo, NULL, NULL, sector->damageamount, sector->damagetype);
|
||||
P_DamageMobj(victim, NULL, NULL, sector->damageamount, sector->damagetype);
|
||||
}
|
||||
if ((sector->Flags & SECF_ENDLEVEL) && player->health <= 10 && (!deathmatch || !(dmflags & DF_NO_EXIT)))
|
||||
if (victim->player && (sector->Flags & SECF_ENDLEVEL) && victim->player->health <= 10 && (!deathmatch || !(dmflags & DF_NO_EXIT)))
|
||||
{
|
||||
Level->ExitLevel(0, false);
|
||||
}
|
||||
if (sector->Flags & SECF_DMGTERRAINFX)
|
||||
{
|
||||
P_HitWater(player->mo, player->mo->Sector, player->mo->Pos(), false, true, true);
|
||||
P_HitWater(victim, victim->Sector, victim->Pos(), false, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -506,14 +510,14 @@ void P_PlayerInSpecialSector (player_t *player, sector_t * sector)
|
|||
{
|
||||
if (Level->time % sector->damageinterval == 0)
|
||||
{
|
||||
P_GiveBody(player->mo, -sector->damageamount, 100);
|
||||
P_GiveBody(victim, -sector->damageamount, 100);
|
||||
}
|
||||
}
|
||||
|
||||
if (sector->isSecret())
|
||||
if (victim->player && sector->isSecret())
|
||||
{
|
||||
sector->ClearSecret();
|
||||
P_GiveSecret(Level, player->mo, true, true, sector->Index());
|
||||
P_GiveSecret(Level, victim, true, true, sector->Index());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -652,13 +656,13 @@ DEFINE_ACTION_FUNCTION(FLevelLocals, GiveSecret)
|
|||
|
||||
//============================================================================
|
||||
//
|
||||
// P_PlayerOnSpecialFlat
|
||||
// P_ActorOnSpecialFlat
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
void P_PlayerOnSpecialFlat (player_t *player, int floorType)
|
||||
void P_ActorOnSpecialFlat (AActor *victim, int floorType)
|
||||
{
|
||||
auto Level = player->mo->Level;
|
||||
auto Level = victim->Level;
|
||||
|
||||
if (Terrains[floorType].DamageAmount &&
|
||||
!(Level->time % (Terrains[floorType].DamageTimeMask+1)))
|
||||
|
|
@ -668,7 +672,7 @@ void P_PlayerOnSpecialFlat (player_t *player, int floorType)
|
|||
if (Terrains[floorType].AllowProtection)
|
||||
{
|
||||
auto pitype = PClass::FindActor(NAME_PowerIronFeet);
|
||||
for (ironfeet = player->mo->Inventory; ironfeet != NULL; ironfeet = ironfeet->Inventory)
|
||||
for (ironfeet = victim->Inventory; ironfeet != NULL; ironfeet = ironfeet->Inventory)
|
||||
{
|
||||
if (ironfeet->IsKindOf (pitype))
|
||||
break;
|
||||
|
|
@ -678,20 +682,18 @@ void P_PlayerOnSpecialFlat (player_t *player, int floorType)
|
|||
int damage = 0;
|
||||
if (ironfeet == NULL)
|
||||
{
|
||||
damage = P_DamageMobj (player->mo, NULL, NULL, Terrains[floorType].DamageAmount,
|
||||
damage = P_DamageMobj (victim, NULL, NULL, Terrains[floorType].DamageAmount,
|
||||
Terrains[floorType].DamageMOD);
|
||||
}
|
||||
if (damage > 0 && Terrains[floorType].Splash != -1)
|
||||
{
|
||||
S_Sound (player->mo, CHAN_AUTO, 0,
|
||||
S_Sound (victim, CHAN_AUTO, 0,
|
||||
Splashes[Terrains[floorType].Splash].NormalSplashSound, 1,
|
||||
ATTN_IDLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// P_UpdateSpecials
|
||||
// Animate planes, scroll walls, etc.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue