Skip to content

Commit

Permalink
Fixed 3D floor handling for sector damage.
Browse files Browse the repository at this point in the history
Fixes sector damage to either monsters or players not working on (non-)solid 3D floors.
  • Loading branch information
inkoalawetrust committed Oct 20, 2024
1 parent 7ba3a70 commit a944f10
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 14 deletions.
7 changes: 4 additions & 3 deletions src/playsim/p_3dfloors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,12 +210,13 @@ void P_ActorOnSpecial3DFloor(AActor* victim)
{
if (!(rover->flags & FF_EXISTS)) continue;
if (rover->flags & FF_FIX) continue;

if (!checkForSpecialSector(victim, rover->model)) continue;

// Check the 3D floor's type...
if(rover->flags & FF_SOLID)
{
// Player must be on top of the floor to be affected...
if(victim->Z() != rover->top.plane->ZatPoint(victim)) continue;
if (victim->Z() != rover->top.plane->ZatPoint(victim)) continue;
}
else
{
Expand All @@ -227,7 +228,7 @@ void P_ActorOnSpecial3DFloor(AActor* victim)
}

// Apply sector specials
P_ActorInSpecialSector(victim, rover->model);
P_ActorInSpecialSector(victim, rover->model,rover);

// Apply flat specials (using the ceiling!)
P_ActorOnSpecialFlat(victim, rover->model->GetTerrain(rover->top.isceiling));
Expand Down
8 changes: 2 additions & 6 deletions src/playsim/p_mobj.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4436,13 +4436,9 @@ void AActor::Tick ()
if (ObjectFlags & OF_EuthanizeMe) return;
}
//[inkoalawetrust] Genericized level damage handling that makes sector, 3D floor, and TERRAIN flat damage affect monsters and other NPCs too.
bool afsdnope = !!(flags9 & MF9_NOSECTORDAMAGE);
bool afsdforce = !!(flags9 & MF9_FORCESECTORDAMAGE);
bool sfhurtmonsters = !!(Sector->MoreFlags & SECMF_HURTMONSTERS);
bool isplayer = (player != nullptr) && (this == player->mo);
if ((!afsdnope || afsdforce) && (isplayer || sfhurtmonsters || afsdforce))
P_ActorOnSpecial3DFloor(this); //3D floors must be checked separately to see if their control sector allows non-player damage
if (checkForSpecialSector(this,Sector))
{
P_ActorOnSpecial3DFloor(this);
P_ActorInSpecialSector(this,Sector);
if (!isAbove(Sector->floorplane.ZatPoint(this)) || waterlevel) // Actor must be touching the floor for TERRAIN flats.
P_ActorOnSpecialFlat(this, P_GetThingFloorType(this));
Expand Down
16 changes: 12 additions & 4 deletions src/playsim/p_spec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -423,15 +423,23 @@ bool P_PredictLine(line_t *line, AActor *mo, int side, int activationType)
// Called every tic frame
// that the actor origin is in a special sector
//
void P_ActorInSpecialSector (AActor *victim, sector_t * sector)
void P_ActorInSpecialSector (AActor *victim, sector_t * sector, F3DFloor* Ffloor)
{
if (sector == NULL)
sector = victim->Sector;

// Falling, not all the way down yet?
if (!(sector->MoreFlags & SECMF_HARMINAIR) && !victim->isAtZ(sector->LowestFloorAt(victim)) && !victim->waterlevel)
return;

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;
Expand Down
12 changes: 11 additions & 1 deletion src/playsim/p_spec.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "dsectoreffect.h"
#include "doomdata.h"
#include "r_state.h"
#include "d_player.h"

class FScanner;
struct level_info_t;
Expand Down Expand Up @@ -90,13 +91,22 @@ bool P_ActivateLine (line_t *ld, AActor *mo, int side, int activationType, DVect
bool P_TestActivateLine (line_t *ld, AActor *mo, int side, int activationType, DVector3 *optpos = NULL);
bool P_PredictLine (line_t *ld, AActor *mo, int side, int activationType);

void P_ActorInSpecialSector (AActor *victim, sector_t * sector=NULL);
void P_ActorInSpecialSector (AActor *victim, sector_t * sector = NULL, F3DFloor* Ffloor = NULL);
void P_ActorOnSpecialFlat (AActor *victim, int floorType);
void P_SectorDamage(FLevelLocals *Level, int tag, int amount, FName type, PClassActor *protectClass, int flags);
void P_SetSectorFriction (FLevelLocals *level, int tag, int amount, bool alterFlag);
double FrictionToMoveFactor(double friction);
void P_GiveSecret(FLevelLocals *Level, AActor *actor, bool printmessage, bool playsound, int sectornum);

inline bool checkForSpecialSector(AActor* mo, sector_t* sec)
{
bool afsdnope = !!(mo->flags9 & MF9_NOSECTORDAMAGE);
bool afsdforce = !!(mo->flags9 & MF9_FORCESECTORDAMAGE);
bool sfhurtmonsters = !!(sec->MoreFlags & SECMF_HURTMONSTERS);
bool isplayer = (mo->player != nullptr) && (mo == mo->player->mo);
return ((!afsdnope || afsdforce) && (isplayer || sfhurtmonsters || afsdforce));
}

//
// getNextSector()
// Return sector_t * of sector next to current.
Expand Down

0 comments on commit a944f10

Please sign in to comment.