From 573cd2f12c7549ebe323366f0dcd8642614f9abb Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Sat, 12 Oct 2024 01:30:20 -0400 Subject: [PATCH 01/60] g4.14pre --- src/version.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/version.h b/src/version.h index 21d2247e6..ca9cc3e59 100644 --- a/src/version.h +++ b/src/version.h @@ -41,20 +41,20 @@ const char *GetVersionString(); /** Lots of different version numbers **/ -#define VERSIONSTR "4.13pre" +#define VERSIONSTR "4.14pre" // The version as seen in the Windows resource -#define RC_FILEVERSION 4,12,9999,0 -#define RC_PRODUCTVERSION 4,12,9999,0 +#define RC_FILEVERSION 4,13,9999,0 +#define RC_PRODUCTVERSION 4,13,9999,0 #define RC_PRODUCTVERSION2 VERSIONSTR // These are for content versioning. #define VER_MAJOR 4 -#define VER_MINOR 13 +#define VER_MINOR 14 #define VER_REVISION 0 // This should always refer to the GZDoom version a derived port is based on and not reflect the derived port's version number! #define ENG_MAJOR 4 -#define ENG_MINOR 13 +#define ENG_MINOR 14 #define ENG_REVISION 0 // Version identifier for network games. From de64ffbf117e0c0e342398088a4bdb71adb7ca7a Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Sat, 12 Oct 2024 04:22:45 -0400 Subject: [PATCH 02/60] - define dither shader in a way that is compatible with Apple's GLSL-to-metal compiler --- wadsrc/static/shaders/glsl/main.fp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wadsrc/static/shaders/glsl/main.fp b/wadsrc/static/shaders/glsl/main.fp index 95f248d69..eb4685084 100644 --- a/wadsrc/static/shaders/glsl/main.fp +++ b/wadsrc/static/shaders/glsl/main.fp @@ -891,7 +891,7 @@ void main() #ifdef DITHERTRANS int index = (int(pixelpos.x) % 8) * 8 + int(pixelpos.y) % 8; const float DITHER_THRESHOLDS[64] = - { + float[64]( 1.0 / 65.0, 33.0 / 65.0, 9.0 / 65.0, 41.0 / 65.0, 3.0 / 65.0, 35.0 / 65.0, 11.0 / 65.0, 43.0 / 65.0, 49.0 / 65.0, 17.0 / 65.0, 57.0 / 65.0, 25.0 / 65.0, 51.0 / 65.0, 19.0 / 65.0, 59.0 / 65.0, 27.0 / 65.0, 13.0 / 65.0, 45.0 / 65.0, 5.0 / 65.0, 37.0 / 65.0, 15.0 / 65.0, 47.0 / 65.0, 7.0 / 65.0, 39.0 / 65.0, @@ -900,7 +900,7 @@ void main() 52.0 / 65.0, 20.0 / 65.0, 60.0 / 65.0, 28.0 / 65.0, 50.0 / 65.0, 18.0 / 65.0, 58.0 / 65.0, 26.0 / 65.0, 16.0 / 65.0, 48.0 / 65.0, 8.0 / 65.0, 40.0 / 65.0, 14.0 / 65.0, 46.0 / 65.0, 6.0 / 65.0, 38.0 / 65.0, 64.0 / 65.0, 32.0 / 65.0, 56.0 / 65.0, 24.0 / 65.0, 62.0 / 65.0, 30.0 / 65.0, 54.0 / 65.0, 22.0 /65.0 - }; + ); vec3 fragHSV = rgb2hsv(FragColor.rgb); float brightness = clamp(1.5*fragHSV.z, 0.1, 1.0); From 8e4080f8d16695b9c26475a1732feda2c7efe7f8 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 12 Oct 2024 11:52:07 +0200 Subject: [PATCH 03/60] Resolve compiler warning about destructor syntax gcc-14 warns: tarray.h:927:9: warning: template-id not allowed for destructor in C++20 [-Wtemplate-id-cdtor] 927 | ~TDeletingArray () --- src/common/utility/tarray.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/utility/tarray.h b/src/common/utility/tarray.h index 3445bd484..25d6e0e7f 100644 --- a/src/common/utility/tarray.h +++ b/src/common/utility/tarray.h @@ -924,7 +924,7 @@ public: return *this; } - ~TDeletingArray () + ~TDeletingArray() { for (unsigned int i = 0; i < TArray::Size(); ++i) { From 12d1afcc4eb027acb81af8babb9f78882c7d9643 Mon Sep 17 00:00:00 2001 From: inkoalawetrust <56005600+inkoalawetrust@users.noreply.github.com> Date: Wed, 2 Oct 2024 03:53:30 +0300 Subject: [PATCH 04/60] Fixed WalkStepTics & RunStepTics in terrain parser Fixed the discrepancy where WalkStepTics and RunStepTics were called, well, that. In the terrain struct in both C++ and ZScript. While the terrain parser looked for WALKINGSTEPTIME and RUNNINGSTEPTIME instead. Also made the parse not multiply these time values by the ticrate to treat them as seconds instead of tics. Added flags for P_HitWater(). Added optional overridable footsteps for players. Added an overridable MakeFootsteps() virtual in PlayerPawn. Which allows for adding totally custom footstep logic for players. By default, it comes with a basic footstep system that uses the footstep properties of whatever terrain the pawn is standing on. bMakeFootsteps must be enabled on the pawn for the virtual to run. Added generic StepSound TERRAIN property. Added a generic step sound TERRAIN property, for defining foot-agnostic step sounds. Used by the built-in footstep system over the individual foot ones. Simplified MakeFootsteps(). Also removed a leftover debug message. --- src/gamedata/p_terrain.cpp | 16 ++++--- src/gamedata/p_terrain.h | 1 + src/playsim/p_local.h | 2 +- src/playsim/p_mobj.cpp | 15 +++++-- wadsrc/static/zscript/actors/actor.zs | 2 +- wadsrc/static/zscript/actors/player/player.zs | 45 +++++++++++++++++++ wadsrc/static/zscript/constants.zs | 6 +++ wadsrc/static/zscript/doombase.zs | 1 + 8 files changed, 76 insertions(+), 12 deletions(-) diff --git a/src/gamedata/p_terrain.cpp b/src/gamedata/p_terrain.cpp index 4d0efcff9..7aa3f8a4f 100644 --- a/src/gamedata/p_terrain.cpp +++ b/src/gamedata/p_terrain.cpp @@ -77,13 +77,14 @@ enum ETerrainKeywords TR_DAMAGETIMEMASK, TR_FOOTCLIP, TR_STEPVOLUME, - TR_WALKINGSTEPTIME, - TR_RUNNINGSTEPTIME, + TR_WALKSTEPTICS, + TR_RUNSTEPTICS, TR_LEFTSTEPSOUNDS, TR_RIGHTSTEPSOUNDS, TR_LIQUID, TR_FRICTION, - TR_ALLOWPROTECTION + TR_ALLOWPROTECTION, + TR_STEPSOUNDS }; enum EGenericType @@ -179,14 +180,15 @@ static const char *TerrainKeywords[] = "damagetimemask", "footclip", "stepvolume", - "walkingsteptime", - "runningsteptime", + "walksteptics", + "runsteptics", "leftstepsounds", "rightstepsounds", "liquid", "friction", "allowprotection", "damageonland", + "stepsounds", NULL }; @@ -223,6 +225,7 @@ static FGenericParse TerrainParser[] = { GEN_Custom, {(size_t)ParseFriction} }, { GEN_Bool, {myoffsetof(FTerrainDef, AllowProtection)} }, { GEN_Bool, {myoffsetof(FTerrainDef, DamageOnLand)} }, + { GEN_Sound, {myoffsetof(FTerrainDef, StepSound)} }, }; @@ -599,7 +602,7 @@ static void GenericParse (FScanner &sc, FGenericParse *parser, const char **keyw case GEN_Time: sc.MustGetFloat (); - SET_FIELD (int, (int)(sc.Float * TICRATE)); + SET_FIELD (int, (int)(sc.Float)); break; case GEN_Bool: @@ -747,3 +750,4 @@ DEFINE_FIELD(FTerrainDef, AllowProtection) DEFINE_FIELD(FTerrainDef, DamageOnLand) DEFINE_FIELD(FTerrainDef, Friction) DEFINE_FIELD(FTerrainDef, MoveFactor) +DEFINE_FIELD(FTerrainDef, StepSound) \ No newline at end of file diff --git a/src/gamedata/p_terrain.h b/src/gamedata/p_terrain.h index a225b8a73..c581ca3fd 100644 --- a/src/gamedata/p_terrain.h +++ b/src/gamedata/p_terrain.h @@ -118,6 +118,7 @@ struct FTerrainDef bool DamageOnLand; double Friction; double MoveFactor; + FSoundID StepSound; }; extern TArray Splashes; diff --git a/src/playsim/p_local.h b/src/playsim/p_local.h index 6d02d2a56..584cfc43f 100644 --- a/src/playsim/p_local.h +++ b/src/playsim/p_local.h @@ -352,7 +352,7 @@ void P_TraceBleed (int damage, AActor *target, AActor *missile); // missile ver void P_TraceBleed(int damage, FTranslatedLineTarget *t, AActor *puff); // hitscan version void P_TraceBleed (int damage, AActor *target); // random direction version bool P_HitFloor (AActor *thing); -bool P_HitWater (AActor *thing, sector_t *sec, const DVector3 &pos, bool checkabove = false, bool alert = true, bool force = false); +bool P_HitWater (AActor *thing, sector_t *sec, const DVector3 &pos, bool checkabove = false, bool alert = true, bool force = false, int flags = 0); struct FRailParams diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index 5dff4a0be..275de6fe5 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -6631,7 +6631,13 @@ int P_GetThingFloorType (AActor *thing) // Returns true if hit liquid and splashed, false if not. //--------------------------------------------------------------------------- -bool P_HitWater (AActor * thing, sector_t * sec, const DVector3 &pos, bool checkabove, bool alert, bool force) +enum HitWaterFlags +{ + THW_SMALL = 1 << 0, + THW_NOVEL = 1 << 1, +}; + +bool P_HitWater (AActor * thing, sector_t * sec, const DVector3 &pos, bool checkabove, bool alert, bool force, int flags) { if (thing->player && (thing->player->cheats & CF_PREDICTING)) return false; @@ -6719,13 +6725,13 @@ foundone: // Don't splash for living things with small vertical velocities. // There are levels where the constant splashing from the monsters gets extremely annoying - if (((thing->flags3&MF3_ISMONSTER || thing->player) && thing->Vel.Z >= -6) && !force) + if (!(flags & THW_NOVEL) && ((thing->flags3 & MF3_ISMONSTER || thing->player) && thing->Vel.Z >= -6) && !force) return Terrains[terrainnum].IsLiquid; splash = &Splashes[splashnum]; // Small splash for small masses - if (thing->Mass < 10) + if (flags & THW_SMALL || thing->Mass < 10) smallsplash = true; if (!(thing->flags3 & MF3_DONTSPLASH)) @@ -6790,7 +6796,8 @@ DEFINE_ACTION_FUNCTION(AActor, HitWater) PARAM_BOOL(checkabove); PARAM_BOOL(alert); PARAM_BOOL(force); - ACTION_RETURN_BOOL(P_HitWater(self, sec, DVector3(x, y, z), checkabove, alert, force)); + PARAM_INT(flags); + ACTION_RETURN_BOOL(P_HitWater(self, sec, DVector3(x, y, z), checkabove, alert, force, flags)); } diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index 5c4dc376e..7d24c36fe 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -773,7 +773,7 @@ class Actor : Thinker native native Actor SpawnPuff(class pufftype, vector3 pos, double hitdir, double particledir, int updown, int flags = 0, Actor victim = null); native void SpawnBlood (Vector3 pos1, double dir, int damage); native void BloodSplatter (Vector3 pos, double hitangle, bool axe = false); - native bool HitWater (sector sec, Vector3 pos, bool checkabove = false, bool alert = true, bool force = false); + native bool HitWater (sector sec, Vector3 pos, bool checkabove = false, bool alert = true, bool force = false, int flags = 0); native void PlaySpawnSound(Actor missile); native clearscope bool CountsAsKill() const; diff --git a/wadsrc/static/zscript/actors/player/player.zs b/wadsrc/static/zscript/actors/player/player.zs index c2da5f46c..bba3d668c 100644 --- a/wadsrc/static/zscript/actors/player/player.zs +++ b/wadsrc/static/zscript/actors/player/player.zs @@ -87,6 +87,8 @@ class PlayerPawn : Actor flagdef CanSuperMorph: PlayerFlags, 1; flagdef CrouchableMorph: PlayerFlags, 2; flagdef WeaponLevel2Ended: PlayerFlags, 3; + //PF_VOODOO_ZOMBIE + flagdef MakeFootsteps: PlayerFlags, 5; //[inkoalawetrust] Use footstep system virtual. enum EPrivatePlayerFlags { @@ -1690,6 +1692,7 @@ class PlayerPawn : Actor CheckPitch(); HandleMovement(); CalcHeight (); + if (bMakeFootsteps) MakeFootsteps(); if (!(player.cheats & CF_PREDICTING)) { @@ -1718,6 +1721,48 @@ class PlayerPawn : Actor } } + //--------------------------------------------------------------------------- + // + // Handle player footstep sounds. + // Default footstep handling. + // + //--------------------------------------------------------------------------- + + virtual void MakeFootsteps() + { + if (pos.z > floorz) return; + + let Ground = GetFloorTerrain(); + let cmd = player.cmd; + + if (Ground && (cmd.forwardMove != 0 || cmd.sideMove != 0)) + { + bool Running = (cmd.buttons & BT_RUN); //Holding down run key, or it's toggled. + int Delay = !Running ? Ground.WalkStepTics : Ground.RunStepTics; + + if (Delay <= 0 || GetAge() % Delay != 0) return; + + Sound Step = Ground.StepSound; + + //Generic foot-agnostic sound takes precedence. + if (!Step) + { + //Apparently most people walk with their right foot first, so assume that here. + if (GetAge() % (Delay*2) == 0) + Step = Ground.LeftStepSound; + else + Step = Ground.RightStepSound; + } + + if (Step) + A_StartSound (Step,flags:CHANF_OVERLAP,volume:Ground.StepVolume); + + //Steps make splashes regardless. + bool Heavy = Mass >= 200 ? 0 : THW_SMALL; //Big player makes big splash. + HitWater (CurSector,(Pos.XY,CurSector.FloorPlane.ZatPoint(Pos.XY)),True,False,flags:Heavy|THW_NOVEL); + } + } + //--------------------------------------------------------------------------- // // PROC P_BringUpWeapon diff --git a/wadsrc/static/zscript/constants.zs b/wadsrc/static/zscript/constants.zs index 641d90a12..3650d8b5c 100644 --- a/wadsrc/static/zscript/constants.zs +++ b/wadsrc/static/zscript/constants.zs @@ -1466,6 +1466,12 @@ enum ECompatFlags COMPATF2_VOODOO_ZOMBIES = 1 << 15, // allow playerinfo, playerpawn, and voodoo health to all be different, and allow monster targetting of 'dead' players that have positive health }; +enum HitWaterFlags +{ + THW_SMALL = 1 << 0, + THW_NOVEL = 1 << 1, +}; + const M_E = 2.7182818284590452354; // e const M_LOG2E = 1.4426950408889634074; // log_2 e const M_LOG10E = 0.43429448190325182765; // log_10 e diff --git a/wadsrc/static/zscript/doombase.zs b/wadsrc/static/zscript/doombase.zs index 1ef97188c..2d88d01d0 100644 --- a/wadsrc/static/zscript/doombase.zs +++ b/wadsrc/static/zscript/doombase.zs @@ -613,6 +613,7 @@ struct TerrainDef native native bool DamageOnLand; native double Friction; native double MoveFactor; + native Sound StepSound; }; enum EPickStart From c60349405772f311f3b416ebb5430732e076d803 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Fri, 30 Aug 2024 16:02:32 +0600 Subject: [PATCH 05/60] Interpolate non-Burn screen wipes --- src/common/2d/wipe.cpp | 160 ++++++++++++++++++++++++++++++++++------- 1 file changed, 135 insertions(+), 25 deletions(-) diff --git a/src/common/2d/wipe.cpp b/src/common/2d/wipe.cpp index cc57ca29f..c829f7a8d 100644 --- a/src/common/2d/wipe.cpp +++ b/src/common/2d/wipe.cpp @@ -43,6 +43,8 @@ #include "s_soundinternal.h" #include "i_time.h" +EXTERN_CVAR(Bool, cl_capfps) + class FBurnTexture : public FTexture { TArray WorkBuffer; @@ -163,6 +165,8 @@ protected: public: virtual ~Wiper(); virtual bool Run(int ticks) = 0; + virtual bool RunInterpolated(double ticks) { return true; }; + virtual bool Interpolatable() { return false; } virtual void SetTextures(FGameTexture* startscreen, FGameTexture* endscreen) { startScreen = startscreen; @@ -177,9 +181,11 @@ class Wiper_Crossfade : public Wiper { public: bool Run(int ticks) override; + bool RunInterpolated(double ticks) override; + bool Interpolatable() override { return true; } private: - int Clock = 0; + float Clock = 0; }; class Wiper_Melt : public Wiper @@ -187,10 +193,12 @@ class Wiper_Melt : public Wiper public: Wiper_Melt(); bool Run(int ticks) override; + bool RunInterpolated(double ticks) override; + bool Interpolatable() override { return true; } private: enum { WIDTH = 320, HEIGHT = 200 }; - int y[WIDTH]; + double y[WIDTH]; }; class Wiper_Burn : public Wiper @@ -268,7 +276,23 @@ bool Wiper_Crossfade::Run(int ticks) Clock += ticks; DrawTexture(twod, startScreen, 0, 0, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_Masked, false, TAG_DONE); DrawTexture(twod, endScreen, 0, 0, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_Masked, false, DTA_Alpha, clamp(Clock / 32.f, 0.f, 1.f), TAG_DONE); - return Clock >= 32; + return Clock >= 32.; +} + +//========================================================================== +// +// OpenGLFrameBuffer :: Wiper_Crossfade :: Run +// +// Fades the old screen into the new one over 32 ticks. +// +//========================================================================== + +bool Wiper_Crossfade::RunInterpolated(double ticks) +{ + Clock += ticks; + DrawTexture(twod, startScreen, 0, 0, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_Masked, false, TAG_DONE); + DrawTexture(twod, endScreen, 0, 0, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_Masked, false, DTA_Alpha, clamp(Clock / 32.f, 0.f, 1.f), TAG_DONE); + return Clock >= 32.; } //========================================================================== @@ -282,7 +306,7 @@ Wiper_Melt::Wiper_Melt() y[0] = -(M_Random() & 15); for (int i = 1; i < WIDTH; ++i) { - y[i] = clamp(y[i-1] + (M_Random() % 3) - 1, -15, 0); + y[i] = clamp(y[i-1] + (double)(M_Random() % 3) - 1., -15., 0.); } } @@ -307,25 +331,25 @@ bool Wiper_Melt::Run(int ticks) { if (y[i] < HEIGHT) { - if (y[i] < 0) - y[i]++; - else if (y[i] < 16) - y[i] += y[i] + 1; + if (y[i] < 0.) + y[i] = y[i] + 1.; + else if (y[i] < 16.) + y[i] += y[i] + 1.; else - y[i] = min(y[i] + 8, HEIGHT); + y[i] = min(y[i] + 8., HEIGHT); done = false; } if (ticks == 0) { struct { int32_t x; - int32_t y; + double y; } dpt; struct { int32_t left; - int32_t top; + double top; int32_t right; - int32_t bottom; + double bottom; } rect; // Only draw for the final tick. @@ -333,7 +357,7 @@ bool Wiper_Melt::Run(int ticks) int w = startScreen->GetTexelWidth(); int h = startScreen->GetTexelHeight(); dpt.x = i * w / WIDTH; - dpt.y = max(0, y[i] * h / HEIGHT); + dpt.y = max(0., y[i] * (double)h / (double)HEIGHT); rect.left = dpt.x; rect.top = 0; rect.right = (i + 1) * w / WIDTH; @@ -348,6 +372,77 @@ bool Wiper_Melt::Run(int ticks) return done; } +//========================================================================== +// +// Wiper_Melt :: RunInterpolated +// +// Melts the old screen into the new one over 32 ticks (interpolated). +// +//========================================================================== + +bool Wiper_Melt::RunInterpolated(double ticks) +{ + bool done = false; + DrawTexture(twod, endScreen, 0, 0, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_Masked, false, TAG_DONE); + + // Copy the old screen in vertical strips on top of the new one. + while (ticks > 0.) + { + done = true; + for (int i = 0; i < WIDTH; i++) + { + if (y[i] < (double)HEIGHT) + { + if (ticks > 0. && ticks < 1.) + { + if (y[i] < 0) + y[i] += ticks; + else if (y[i] < 16) + y[i] += (y[i] + 1) * ticks; + else + y[i] = min(y[i] + (8 * ticks), (double)HEIGHT); + } + else if (y[i] < 0.) + y[i] = y[i] + 1.; + else if (y[i] < 16.) + y[i] += y[i] + 1.; + else + y[i] = min(y[i] + 8., HEIGHT); + done = false; + } + } + ticks -= 1.; + } + for (int i = 0; i < WIDTH; i++) + { + struct { + int32_t x; + double y; + } dpt; + struct { + int32_t left; + double top; + int32_t right; + double bottom; + } rect; + + // Only draw for the final tick. + int w = startScreen->GetTexelWidth(); + double h = startScreen->GetTexelHeight(); + dpt.x = i * w / WIDTH; + dpt.y = max(0., y[i] * (double)h / (double)HEIGHT); + rect.left = dpt.x; + rect.top = 0; + rect.right = (i + 1) * w / WIDTH; + rect.bottom = h - dpt.y; + if (rect.bottom > rect.top) + { + DrawTexture(twod, startScreen, 0, dpt.y, DTA_FlipY, screen->RenderTextureIsFlipped(), DTA_ClipLeft, rect.left, DTA_ClipRight, rect.right, DTA_Masked, false, TAG_DONE); + } + } + return done; +} + //========================================================================== // // OpenGLFrameBuffer :: Wiper_Burn Constructor @@ -423,6 +518,7 @@ void PerformWipe(FTexture* startimg, FTexture* endimg, int wipe_type, bool stops { // wipe update uint64_t wipestart, nowtime, diff; + double diff_frac; bool done; GSnd->SetSfxPaused(true, 1); @@ -438,20 +534,34 @@ void PerformWipe(FTexture* startimg, FTexture* endimg, int wipe_type, bool stops do { - do + if (wiper->Interpolatable() && !cl_capfps) { - I_WaitVBL(2); nowtime = I_msTime(); - diff = (nowtime - wipestart) * 40 / 1000; // Using 35 here feels too slow. - } while (diff < 1); - wipestart = nowtime; - twod->Begin(screen->GetWidth(), screen->GetHeight()); - done = wiper->Run(1); - if (overlaydrawer) overlaydrawer(); - twod->End(); - screen->Update(); - twod->OnFrameDone(); - + diff_frac = (nowtime - wipestart) * 40. / 1000.; // Using 35 here feels too slow. + wipestart = nowtime; + twod->Begin(screen->GetWidth(), screen->GetHeight()); + done = wiper->RunInterpolated(diff_frac); + if (overlaydrawer) overlaydrawer(); + twod->End(); + screen->Update(); + twod->OnFrameDone(); + } + else + { + do + { + I_WaitVBL(2); + nowtime = I_msTime(); + diff = (nowtime - wipestart) * 40 / 1000; // Using 35 here feels too slow. + } while (diff < 1); + wipestart = nowtime; + twod->Begin(screen->GetWidth(), screen->GetHeight()); + done = wiper->Run(1); + if (overlaydrawer) overlaydrawer(); + twod->End(); + screen->Update(); + twod->OnFrameDone(); + } } while (!done); delete wiper; I_FreezeTime(false); From 9df656a9cf32c8ed746367ceb12ced255cf3b7a7 Mon Sep 17 00:00:00 2001 From: inkoalawetrust <56005600+inkoalawetrust@users.noreply.github.com> Date: Mon, 14 Oct 2024 10:23:12 +0300 Subject: [PATCH 06/60] Added LookForEnemiesEx() for returning all enemies in an area. (#2753) * Compartmentalized the LookForEnemiesInBlock checks * Added LookForEnemiesEx(). This function allows for ZScript code to get an array with all enemies of the caller found in range. Using similar sight logic as functions like LookForEnemies(). * Added noPlayers parameter to LookForEnemiesEx(). This parameter allows the function to also find players around it. * Added VM abort to LookForEnemiesEx(). Prevent crashes by passing a null array by reference. --- src/playsim/p_enemy.cpp | 263 ++++++++++++++++---------- wadsrc/static/zscript/actors/actor.zs | 1 + 2 files changed, 160 insertions(+), 104 deletions(-) diff --git a/src/playsim/p_enemy.cpp b/src/playsim/p_enemy.cpp index 55f501488..120f37231 100644 --- a/src/playsim/p_enemy.cpp +++ b/src/playsim/p_enemy.cpp @@ -1309,6 +1309,161 @@ int P_IsVisible(AActor *lookee, AActor *other, INTBOOL allaround, FLookExParams return P_CheckSight(lookee, other, SF_SEEPASTSHOOTABLELINES); } +bool isTargetablePlayer(AActor *actor, player_t *player, INTBOOL allaround, void* lookparams) +{ + FLookExParams* params = (FLookExParams*)lookparams; + + if (!(player->mo->flags & MF_SHOOTABLE)) + return false; // not shootable (observer or dead) + + if (actor->IsFriend(player->mo)) + return false; // same +MF_FRIENDLY, ignore + + if (player->cheats & CF_NOTARGET) + return false; // no target + + if (player->health <= 0) + return false; // dead + + if (!P_IsVisible(actor, player->mo, allaround, params)) + return false; // out of sight + + // [RC] Well, let's let special monsters with this flag active be able to see + // the player then, eh? + if (!(actor->flags6 & MF6_SEEINVISIBLE)) + { + if ((player->mo->flags & MF_SHADOW && !(actor->Level->i_compatflags & COMPATF_INVISIBILITY)) || + player->mo->flags3 & MF3_GHOST) + { + if (player->mo->Distance2D(actor) > 128 && player->mo->Vel.XY().LengthSquared() < 5 * 5) + { // Player is sneaking - can't detect + return false; + } + if (pr_lookforplayers() < 225) + { // Player isn't sneaking, but still didn't detect + return false; + } + } + } + + return true; +} + +bool ValidEnemyInBlock(AActor* lookee, AActor* other, void* lookparams) +{ + FLookExParams* params = (FLookExParams*)lookparams; + + if (!(other->flags & MF_SHOOTABLE)) + return false; // not shootable (observer or dead) + + if (other == lookee) + return false; // is self + + if (other->health <= 0) + return false; // dead + + if (other->flags2 & MF2_DORMANT) + return false; // don't target dormant things + + if (!(other->flags3 & MF3_ISMONSTER)) + return false; // don't target it if it isn't a monster (could be a barrel) + + if (other->flags7 & MF7_NEVERTARGET) + return false; + + bool keepChecking = false; + if (lookee->flags & MF_FRIENDLY) + { + if (other->flags & MF_FRIENDLY) + { + if (!lookee->IsFriend(other)) + { + // This is somebody else's friend, so go after it + keepChecking = true; + } + else if (other->target != NULL && !(other->target->flags & MF_FRIENDLY)) + { + other = other->target; + if (!(other->flags & MF_SHOOTABLE) || + other->health <= 0 || + (other->flags2 & MF2_DORMANT)) + { + return false; + } + } + } + else + { + keepChecking = true; + } + } + else if (lookee->flags8 & MF8_SEEFRIENDLYMONSTERS && other->flags & MF_FRIENDLY) + { + keepChecking = true; + } + + // [MBF] If the monster is already engaged in a one-on-one attack + // with a healthy friend, don't attack around 60% the time. + + // [GrafZahl] This prevents friendlies from attacking all the same + // target. + + if (keepChecking) + { + AActor* targ = other->target; + if (targ && targ->target == other && pr_skiptarget() > 100 && lookee->IsFriend(targ) && + targ->health * 2 >= targ->SpawnHealth()) + { + return false; + } + } + + // [KS] Hey, shouldn't there be a check for MF3_NOSIGHTCHECK here? + + if (!keepChecking || !P_IsVisible(lookee, other, true, params)) + return false; // out of sight + + return true; +} + +//============================================================================ +// +// LookForEnemiesEx +// +// [inkoalawetrust] Return a script array of all valid enemies of the caller +// in range. For ZScript. +// +//============================================================================ + +DEFINE_ACTION_FUNCTION(AActor, LookForEnemiesEx) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OUTPOINTER(targets,TArray); + PARAM_FLOAT(range); + PARAM_BOOL(noPlayers); + PARAM_BOOL(allaround); + PARAM_POINTER(params, FLookExParams); + + if (targets == nullptr) + ThrowAbortException(X_WRITE_NIL,"No targets array passed"); + + if (range == -1) + range = self->friendlyseeblocks * FBlockmap::MAPBLOCKUNITS; + + FPortalGroupArray check(FPortalGroupArray::PGA_Full3d); + FMultiBlockThingsIterator it(check, self, range, false); + FMultiBlockThingsIterator::CheckResult cres; + + while (it.Next(&cres)) + { + if (cres.thing->player == nullptr && ValidEnemyInBlock(cres.thing, self, params) || + !noPlayers && cres.thing->player && isTargetablePlayer(self, cres.thing->player, allaround, params)) + targets->Push(cres.thing); + } + + ACTION_RETURN_INT(targets->Size()); +} + //--------------------------------------------------------------------------- // // FUNC P_LookForMonsters @@ -1552,80 +1707,10 @@ AActor *LookForEnemiesInBlock (AActor *lookee, int index, void *extparam) for (block = lookee->Level->blockmap.blocklinks[index]; block != NULL; block = block->NextActor) { - link = block->Me; - - if (!(link->flags & MF_SHOOTABLE)) - continue; // not shootable (observer or dead) - - if (link == lookee) + if (!ValidEnemyInBlock(lookee, block->Me, params)) continue; - if (link->health <= 0) - continue; // dead - - if (link->flags2 & MF2_DORMANT) - continue; // don't target dormant things - - if (!(link->flags3 & MF3_ISMONSTER)) - continue; // don't target it if it isn't a monster (could be a barrel) - - if (link->flags7 & MF7_NEVERTARGET) - continue; - - other = NULL; - if (lookee->flags & MF_FRIENDLY) - { - if (link->flags & MF_FRIENDLY) - { - if (!lookee->IsFriend(link)) - { - // This is somebody else's friend, so go after it - other = link; - } - else if (link->target != NULL && !(link->target->flags & MF_FRIENDLY)) - { - other = link->target; - if (!(other->flags & MF_SHOOTABLE) || - other->health <= 0 || - (other->flags2 & MF2_DORMANT)) - { - other = NULL;; - } - } - } - else - { - other = link; - } - } - else if (lookee->flags8 & MF8_SEEFRIENDLYMONSTERS && link->flags & MF_FRIENDLY) - { - other = link; - } - - // [MBF] If the monster is already engaged in a one-on-one attack - // with a healthy friend, don't attack around 60% the time. - - // [GrafZahl] This prevents friendlies from attacking all the same - // target. - - if (other) - { - AActor *targ = other->target; - if (targ && targ->target == other && pr_skiptarget() > 100 && lookee->IsFriend (targ) && - targ->health*2 >= targ->SpawnHealth()) - { - continue; - } - } - - // [KS] Hey, shouldn't there be a check for MF3_NOSIGHTCHECK here? - - if (other == NULL || !P_IsVisible (lookee, other, true, params)) - continue; // out of sight - - - return other; + return block->Me; } return NULL; } @@ -1825,38 +1910,8 @@ int P_LookForPlayers (AActor *actor, INTBOOL allaround, FLookExParams *params) player = actor->Level->Players[pnum]; - if (!(player->mo->flags & MF_SHOOTABLE)) - continue; // not shootable (observer or dead) - - if (actor->IsFriend(player->mo)) - continue; // same +MF_FRIENDLY, ignore - - if (player->cheats & CF_NOTARGET) - continue; // no target - - if (player->health <= 0) - continue; // dead - - if (!P_IsVisible (actor, player->mo, allaround, params)) - continue; // out of sight - - // [RC] Well, let's let special monsters with this flag active be able to see - // the player then, eh? - if(!(actor->flags6 & MF6_SEEINVISIBLE)) - { - if ((player->mo->flags & MF_SHADOW && !(actor->Level->i_compatflags & COMPATF_INVISIBILITY)) || - player->mo->flags3 & MF3_GHOST) - { - if (player->mo->Distance2D (actor) > 128 && player->mo->Vel.XY().LengthSquared() < 5*5) - { // Player is sneaking - can't detect - continue; - } - if (pr_lookforplayers() < 225) - { // Player isn't sneaking, but still didn't detect - continue; - } - } - } + if (!isTargetablePlayer(actor, player, allaround, params)) + continue; // [RH] Need to be sure the reactiontime is 0 if the monster is // leaving its goal to go after a player. diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index 7d24c36fe..970b23405 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -851,6 +851,7 @@ class Actor : Thinker native native bool LookForTid(bool allaround, LookExParams params = null); native bool LookForEnemies(bool allaround, LookExParams params = null); native bool LookForPlayers(bool allaround, LookExParams params = null); + native int LookForEnemiesEx(out Array targets, double range = -1, bool noPlayers = true, bool allaround = false, LookExParams params = null); native bool TeleportMove(Vector3 pos, bool telefrag, bool modifyactor = true); native clearscope double DistanceBySpeed(Actor other, double speed) const; native name GetSpecies(); From 3e33e31d1961f366229d5b4848fa29d2d797b8c3 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Mon, 14 Oct 2024 03:39:26 -0400 Subject: [PATCH 07/60] - simplify and deconstruct logic for applying sector damage - also fixes voodoo doll sector damage in TNT MAP30 --- src/playsim/p_mobj.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index 275de6fe5..4aa95ae83 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -4436,7 +4436,11 @@ 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. - if ((!(flags9 & MF9_NOSECTORDAMAGE) || flags9 & MF9_FORCESECTORDAMAGE) && (player || (player == nullptr && (Sector->MoreFlags & SECMF_HURTMONSTERS || flags9 & MF9_FORCESECTORDAMAGE)))) + 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); P_ActorInSpecialSector(this,Sector); From fa467073ebea5702d97ed60abaa7e3fd7c3b51e5 Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Mon, 14 Oct 2024 14:15:30 -0500 Subject: [PATCH 08/60] Added (SPF_)STRETCHPIXELS. This counteracts the squaring implied by rolling sprites. --- src/playsim/actor.h | 3 ++- src/playsim/p_effect.h | 1 + src/rendering/hwrenderer/scene/hw_sprites.cpp | 4 ++-- wadsrc/static/zscript/constants.zs | 1 + 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/playsim/actor.h b/src/playsim/actor.h index eba4011a2..708e06f4c 100644 --- a/src/playsim/actor.h +++ b/src/playsim/actor.h @@ -506,7 +506,8 @@ enum ActorRenderFlag2 RF2_CAMFOLLOWSPLAYER = 0x0040, // Matches the cam's base position and angles to the main viewpoint. RF2_NOMIPMAP = 0x0080, // [Nash] forces no mipmapping on sprites. Useful for tiny sprites that need to remain visually crisp RF2_ISOMETRICSPRITES = 0x0100, - RF2_SQUAREPIXELS = 0x0200, // apply +ROLLSPRITE scaling math so that non rolling sprites get the same scaling + RF2_SQUAREPIXELS = 0x0200, // apply +ROLLSPRITE scaling math so that non rolling sprites get the same scaling + RF2_STRETCHPIXELS = 0x0400, // don't apply SQUAREPIXELS for ROLLSPRITES }; // This translucency value produces the closest match to Heretic's TINTTAB. diff --git a/src/playsim/p_effect.h b/src/playsim/p_effect.h index 5eafdcd4b..4884739f2 100644 --- a/src/playsim/p_effect.h +++ b/src/playsim/p_effect.h @@ -70,6 +70,7 @@ enum EParticleFlags SPF_NOFACECAMERA = 1 << 12, SPF_ROLLCENTER = 1 << 13, SPF_NOMIPMAP = 1 << 14, + SPF_STRETCHPIXELS = 1 << 15, }; class DVisualThinker; diff --git a/src/rendering/hwrenderer/scene/hw_sprites.cpp b/src/rendering/hwrenderer/scene/hw_sprites.cpp index 61c120f31..91125b750 100644 --- a/src/rendering/hwrenderer/scene/hw_sprites.cpp +++ b/src/rendering/hwrenderer/scene/hw_sprites.cpp @@ -1038,7 +1038,7 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t r.Scale(sprscale.X, isSpriteShadow ? sprscale.Y * 0.15 * thing->isoscaleY : sprscale.Y * thing->isoscaleY); - if ((thing->renderflags & RF_ROLLSPRITE) || (thing->renderflags2 & RF2_SQUAREPIXELS)) + if (((thing->renderflags & RF_ROLLSPRITE) || (thing->renderflags2 & RF2_SQUAREPIXELS)) && !(thing->renderflags2 & RF2_STRETCHPIXELS)) { double ps = di->Level->pixelstretch; double mult = 1.0 / sqrt(ps); // shrink slightly @@ -1621,7 +1621,7 @@ void HWSprite::AdjustVisualThinker(HWDrawInfo* di, DVisualThinker* spr, sector_t auto r = spi.GetSpriteRect(); r.Scale(spr->Scale.X, spr->Scale.Y); - if (spr->PT.flags & SPF_ROLL) + if ((spr->PT.flags & SPF_ROLL) && !(spr->PT.flags & SPF_STRETCHPIXELS)) { double ps = di->Level->pixelstretch; double mult = 1.0 / sqrt(ps); // shrink slightly diff --git a/wadsrc/static/zscript/constants.zs b/wadsrc/static/zscript/constants.zs index 3650d8b5c..2e5ce524a 100644 --- a/wadsrc/static/zscript/constants.zs +++ b/wadsrc/static/zscript/constants.zs @@ -723,6 +723,7 @@ enum EParticleFlags SPF_NOFACECAMERA = 1 << 12, SPF_ROLLCENTER = 1 << 13, SPF_NOMIPMAP = 1 << 14, + SPF_STRETCHPIXELS = 1 << 15, SPF_RELATIVE = SPF_RELPOS|SPF_RELVEL|SPF_RELACCEL|SPF_RELANG }; From ee5442c06b200163811ad23287ac98330201ecf0 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Mon, 14 Oct 2024 17:30:59 -0400 Subject: [PATCH 09/60] - Actor.GetSpecies() is a non-destructive function --- src/rendering/hwrenderer/hw_entrypoint.cpp | 2 +- wadsrc/static/zscript/actors/actor.zs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rendering/hwrenderer/hw_entrypoint.cpp b/src/rendering/hwrenderer/hw_entrypoint.cpp index bfa0d8b1c..e55c041a6 100644 --- a/src/rendering/hwrenderer/hw_entrypoint.cpp +++ b/src/rendering/hwrenderer/hw_entrypoint.cpp @@ -362,7 +362,7 @@ sector_t* RenderView(player_t* player) // Draw all canvases that changed for (FCanvas* canvas : AllCanvases) { - if (canvas->Tex->CheckNeedsUpdate()) + if (canvas->Tex && canvas->Tex->CheckNeedsUpdate()) { screen->RenderTextureView(canvas->Tex, [=](IntRect& bounds) { diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index 970b23405..58a47afba 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -854,7 +854,7 @@ class Actor : Thinker native native int LookForEnemiesEx(out Array targets, double range = -1, bool noPlayers = true, bool allaround = false, LookExParams params = null); native bool TeleportMove(Vector3 pos, bool telefrag, bool modifyactor = true); native clearscope double DistanceBySpeed(Actor other, double speed) const; - native name GetSpecies(); + native clearscope name GetSpecies(); native void PlayActiveSound(); native void Howl(); native void DrawSplash (int count, double angle, int kind); From 70eb4b974dfc7381d1b72e7c66acdd83f69f7359 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Tue, 15 Oct 2024 10:50:04 -0400 Subject: [PATCH 10/60] - enable console subsystem processing for Windows, enable runtime detection --- src/CMakeLists.txt | 7 +++++ src/common/platform/win32/i_main.cpp | 41 +++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 789bea954..987f53dc0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1359,6 +1359,13 @@ else() endif() if( MSVC ) + option ( CONSOLE_MODE "Compile as a console application" OFF ) + if ( CONSOLE_MODE ) + set ( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:CONSOLE /ENTRY:wWinMainCRTStartup" ) + else() + set ( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:WINDOWS /ENTRY:wWinMainCRTStartup" ) + endif() + option( ZDOOM_GENERATE_MAPFILE "Generate .map file for debugging." OFF ) set( LINKERSTUFF "/MANIFEST:NO" ) diff --git a/src/common/platform/win32/i_main.cpp b/src/common/platform/win32/i_main.cpp index acadc2dc8..64c74e808 100644 --- a/src/common/platform/win32/i_main.cpp +++ b/src/common/platform/win32/i_main.cpp @@ -134,6 +134,28 @@ void I_SetIWADInfo() { } +//========================================================================== +// +// isConsoleApp() +// +// runtime detection to detect if this is a console subsystem app. +// +// the reason for doing this is because it is possible to edit a binary directly and change its subsystem +// type via hexedit so in order to gain flexibility it makes no sense to just compile out the unused code. +// +// we may plan to publish tools to allow users to do this manually on their own. +// +//========================================================================== + +bool isConsoleApp() +{ + DWORD pids[2]; + DWORD num_pids = GetConsoleProcessList(pids, 2); + bool win32con_is_exclusive = (num_pids <= 1); + + return GetConsoleWindow() != NULL && !win32con_is_exclusive; +} + //========================================================================== // // DoMain @@ -158,7 +180,24 @@ int DoMain (HINSTANCE hInstance) Args->AppendArg(FString(wargv[i])); } - if (Args->CheckParm("-stdout") || Args->CheckParm("-norun")) + if (isConsoleApp()) + { + StdOut = GetStdHandle(STD_OUTPUT_HANDLE); + BY_HANDLE_FILE_INFORMATION info; + + if (!GetFileInformationByHandle(StdOut, &info) && StdOut != nullptr) + { + SetConsoleCP(CP_UTF8); + SetConsoleOutputCP(CP_UTF8); + DWORD mode; + if (GetConsoleMode(StdOut, &mode)) + { + if (SetConsoleMode(StdOut, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING)) + FancyStdOut = IsWindows10OrGreater(); // Windows 8.1 and lower do not understand ANSI formatting. + } + } + } + else if (Args->CheckParm("-stdout") || Args->CheckParm("-norun")) { // As a GUI application, we don't normally get a console when we start. // If we were run from the shell and are on XP+, we can attach to its From 9d725276ac979b93fe55b97de2dce1a86bc80bba Mon Sep 17 00:00:00 2001 From: Kaelan Date: Tue, 15 Oct 2024 12:12:33 -0600 Subject: [PATCH 11/60] Add manual config saving to CVar struct Allows for calling to save custom cvars manually to ensure they're reliably stored. As is, the only way to ensure that cvars are saved is to safely/manually close out GZDoom, meaning if a crash occurs, that data is lost. THis is very detrimental to mods/standalone projects that rely on CVars for storing custom data, and or data that transcends save games. --- src/common/scripting/interface/vmnatives.cpp | 6 ++++++ wadsrc/static/zscript/engine/base.zs | 1 + 2 files changed, 7 insertions(+) diff --git a/src/common/scripting/interface/vmnatives.cpp b/src/common/scripting/interface/vmnatives.cpp index 2b57ceb25..1b2b749aa 100644 --- a/src/common/scripting/interface/vmnatives.cpp +++ b/src/common/scripting/interface/vmnatives.cpp @@ -41,6 +41,7 @@ #include "c_cvars.h" #include "c_bind.h" #include "c_dispatch.h" +#include "m_misc.h" #include "menu.h" #include "vm.h" @@ -1032,6 +1033,11 @@ DEFINE_ACTION_FUNCTION(_CVar, FindCVar) ACTION_RETURN_POINTER(FindCVar(name.GetChars(), nullptr)); } +DEFINE_ACTION_FUNCTION(_CVar, SaveConfig) +{ + ACTION_RETURN_BOOL(M_SaveDefaults(nullptr)); +} + //============================================================================= // // diff --git a/wadsrc/static/zscript/engine/base.zs b/wadsrc/static/zscript/engine/base.zs index 18fe1b363..69f5d66fe 100644 --- a/wadsrc/static/zscript/engine/base.zs +++ b/wadsrc/static/zscript/engine/base.zs @@ -689,6 +689,7 @@ struct CVar native }; native static CVar FindCVar(Name name); + native static bool SaveConfig(); bool GetBool() { return GetInt(); } native int GetInt(); native double GetFloat(); From b4d214a0cf137614cc582633969604e96127ed72 Mon Sep 17 00:00:00 2001 From: Kaelan Date: Tue, 15 Oct 2024 12:15:54 -0600 Subject: [PATCH 12/60] add PARAM_PROLOGUE --- src/common/scripting/interface/vmnatives.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/common/scripting/interface/vmnatives.cpp b/src/common/scripting/interface/vmnatives.cpp index 1b2b749aa..e7b51d063 100644 --- a/src/common/scripting/interface/vmnatives.cpp +++ b/src/common/scripting/interface/vmnatives.cpp @@ -1035,6 +1035,7 @@ DEFINE_ACTION_FUNCTION(_CVar, FindCVar) DEFINE_ACTION_FUNCTION(_CVar, SaveConfig) { + PARAM_PROLOGUE; ACTION_RETURN_BOOL(M_SaveDefaults(nullptr)); } From 81f2bef4ac868f5a52af0762e572c1ac16a0dab9 Mon Sep 17 00:00:00 2001 From: Kaelan Date: Tue, 15 Oct 2024 12:21:26 -0600 Subject: [PATCH 13/60] Further cleanup as per recommendations --- src/common/scripting/interface/vmnatives.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/common/scripting/interface/vmnatives.cpp b/src/common/scripting/interface/vmnatives.cpp index e7b51d063..c778364ed 100644 --- a/src/common/scripting/interface/vmnatives.cpp +++ b/src/common/scripting/interface/vmnatives.cpp @@ -1033,10 +1033,15 @@ DEFINE_ACTION_FUNCTION(_CVar, FindCVar) ACTION_RETURN_POINTER(FindCVar(name.GetChars(), nullptr)); } -DEFINE_ACTION_FUNCTION(_CVar, SaveConfig) +static int SaveConfig() +{ + return M_SaveDefaults(nullptr); +} + +DEFINE_ACTION_FUNCTION_NATIVE(_CVar, SaveConfig, SaveConfig) { PARAM_PROLOGUE; - ACTION_RETURN_BOOL(M_SaveDefaults(nullptr)); + ACTION_RETURN_INT(M_SaveDefaults(nullptr)); } //============================================================================= From 0a9eb474cd87ef10df6c497d724633892ff75c0f Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Wed, 16 Oct 2024 05:57:58 -0400 Subject: [PATCH 14/60] - fix isolated console mode (i.e. launching from explorer.exe) --- src/CMakeLists.txt | 2 +- src/common/platform/win32/i_main.cpp | 43 ++++++++++++++++---------- src/common/platform/win32/i_system.cpp | 2 ++ 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 987f53dc0..95b67a2d8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1361,7 +1361,7 @@ endif() if( MSVC ) option ( CONSOLE_MODE "Compile as a console application" OFF ) if ( CONSOLE_MODE ) - set ( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:CONSOLE /ENTRY:wWinMainCRTStartup" ) + set ( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:CONSOLE /ENTRY:wmainCRTStartup" ) else() set ( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:WINDOWS /ENTRY:wWinMainCRTStartup" ) endif() diff --git a/src/common/platform/win32/i_main.cpp b/src/common/platform/win32/i_main.cpp index 64c74e808..aa1f6271e 100644 --- a/src/common/platform/win32/i_main.cpp +++ b/src/common/platform/win32/i_main.cpp @@ -45,6 +45,11 @@ #include #include +#include +#include +#include +#include + #ifdef _MSC_VER #pragma warning(disable:4244) #endif @@ -149,11 +154,22 @@ void I_SetIWADInfo() bool isConsoleApp() { - DWORD pids[2]; - DWORD num_pids = GetConsoleProcessList(pids, 2); - bool win32con_is_exclusive = (num_pids <= 1); + static bool alreadychecked = false; + static bool returnvalue; - return GetConsoleWindow() != NULL && !win32con_is_exclusive; + if (!alreadychecked) + { + DWORD pids[2]; + DWORD num_pids = GetConsoleProcessList(pids, 2); + bool win32con_is_exclusive = (num_pids <= 1); + + returnvalue = ((GetConsoleWindow() != NULL && !win32con_is_exclusive) || (GetStdHandle(STD_OUTPUT_HANDLE) != NULL)); + alreadychecked = true; + } + + //printf("isConsoleApp is %i\n", returnvalue); + + return returnvalue; } //========================================================================== @@ -183,19 +199,7 @@ int DoMain (HINSTANCE hInstance) if (isConsoleApp()) { StdOut = GetStdHandle(STD_OUTPUT_HANDLE); - BY_HANDLE_FILE_INFORMATION info; - - if (!GetFileInformationByHandle(StdOut, &info) && StdOut != nullptr) - { - SetConsoleCP(CP_UTF8); - SetConsoleOutputCP(CP_UTF8); - DWORD mode; - if (GetConsoleMode(StdOut, &mode)) - { - if (SetConsoleMode(StdOut, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING)) - FancyStdOut = IsWindows10OrGreater(); // Windows 8.1 and lower do not understand ANSI formatting. - } - } + FancyStdOut = IsWindows10OrGreater(); // Windows 8.1 and lower do not understand ANSI formatting. } else if (Args->CheckParm("-stdout") || Args->CheckParm("-norun")) { @@ -514,6 +518,11 @@ CUSTOM_CVAR(Bool, disablecrashlog, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // //========================================================================== +int wmain() +{ + return wWinMain(GetModuleHandle(0), 0, GetCommandLineW(), SW_SHOW); +} + int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE nothing, LPWSTR cmdline, int nCmdShow) { g_hInst = hInstance; diff --git a/src/common/platform/win32/i_system.cpp b/src/common/platform/win32/i_system.cpp index 71a4ded12..caed820b0 100644 --- a/src/common/platform/win32/i_system.cpp +++ b/src/common/platform/win32/i_system.cpp @@ -102,6 +102,7 @@ // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- void DestroyCustomCursor(); +bool isConsoleApp(); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- @@ -306,6 +307,7 @@ static void PrintToStdOut(const char *cpt, HANDLE StdOut) else break; } } + DWORD bytes_written; WriteFile(StdOut, printData.GetChars(), (DWORD)printData.Len(), &bytes_written, NULL); if (terminal) From fcf65bee2700c09cd1aeef78a3c13cc6cac3cf01 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Wed, 16 Oct 2024 06:01:24 -0400 Subject: [PATCH 15/60] - we don't need these includes anymore --- src/common/platform/win32/i_main.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/common/platform/win32/i_main.cpp b/src/common/platform/win32/i_main.cpp index aa1f6271e..0f7bec82c 100644 --- a/src/common/platform/win32/i_main.cpp +++ b/src/common/platform/win32/i_main.cpp @@ -45,11 +45,6 @@ #include #include -#include -#include -#include -#include - #ifdef _MSC_VER #pragma warning(disable:4244) #endif From 2a8b629a129507acd5674d96ddbdc41cf589fb63 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Wed, 16 Oct 2024 06:03:26 -0400 Subject: [PATCH 16/60] - keep ENABLE_VIRTUAL_TERMINAL_PROCESSING mode in isolated console mode --- src/common/platform/win32/i_main.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/common/platform/win32/i_main.cpp b/src/common/platform/win32/i_main.cpp index 0f7bec82c..ce2fabe60 100644 --- a/src/common/platform/win32/i_main.cpp +++ b/src/common/platform/win32/i_main.cpp @@ -194,7 +194,13 @@ int DoMain (HINSTANCE hInstance) if (isConsoleApp()) { StdOut = GetStdHandle(STD_OUTPUT_HANDLE); - FancyStdOut = IsWindows10OrGreater(); // Windows 8.1 and lower do not understand ANSI formatting. + + SetConsoleCP(CP_UTF8); + SetConsoleOutputCP(CP_UTF8); + DWORD mode; + + if (SetConsoleMode(StdOut, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING)) + FancyStdOut = IsWindows10OrGreater(); // Windows 8.1 and lower do not understand ANSI formatting. } else if (Args->CheckParm("-stdout") || Args->CheckParm("-norun")) { From 261881e0d70cfd33bd757dc769f38b455a6f7e46 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 16 Oct 2024 16:54:15 +0200 Subject: [PATCH 17/60] do not set console mode from an uninitialized variable. --- src/common/platform/win32/i_main.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/common/platform/win32/i_main.cpp b/src/common/platform/win32/i_main.cpp index ce2fabe60..c68b5a7aa 100644 --- a/src/common/platform/win32/i_main.cpp +++ b/src/common/platform/win32/i_main.cpp @@ -197,10 +197,14 @@ int DoMain (HINSTANCE hInstance) SetConsoleCP(CP_UTF8); SetConsoleOutputCP(CP_UTF8); + DWORD mode; - if (SetConsoleMode(StdOut, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING)) - FancyStdOut = IsWindows10OrGreater(); // Windows 8.1 and lower do not understand ANSI formatting. + if (GetConsoleMode(StdOut, &mode)) + { + if (SetConsoleMode(StdOut, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING)) + FancyStdOut = IsWindows10OrGreater(); // Windows 8.1 and lower do not understand ANSI formatting. + } } else if (Args->CheckParm("-stdout") || Args->CheckParm("-norun")) { From 758c0dbc7eea9a9412ae7a13bbb76f78004d849d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Thu, 17 Oct 2024 16:25:47 -0300 Subject: [PATCH 18/60] allow getting checksum for current map --- src/g_dumpinfo.cpp | 62 +++++++++++++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 17 deletions(-) diff --git a/src/g_dumpinfo.cpp b/src/g_dumpinfo.cpp index 227b98f50..fcca4ed5b 100644 --- a/src/g_dumpinfo.cpp +++ b/src/g_dumpinfo.cpp @@ -141,30 +141,58 @@ CCMD (spray) CCMD (mapchecksum) { - MapData *map; - uint8_t cksum[16]; - - if (argv.argc() < 2) + if (argv.argc() == 1) + { //current map + const char *wadname = fileSystem.GetResourceFileName(fileSystem.GetFileContainer(level.lumpnum)); + + for (size_t i = 0; i < 16; ++i) + { + Printf("%02X", level.md5[i]); + } + + Printf(" // %s %s\n", wadname, level.MapName.GetChars()); + } + else if (argv.argc() < 2) { Printf("Usage: mapchecksum ...\n"); } - for (int i = 1; i < argv.argc(); ++i) + else { - map = P_OpenMapData(argv[i], true); - if (map == NULL) + MapData *map; + uint8_t cksum[16]; + + for (int i = 1; i < argv.argc(); ++i) { - Printf("Cannot load %s as a map\n", argv[i]); - } - else - { - map->GetChecksum(cksum); - const char *wadname = fileSystem.GetResourceFileName(fileSystem.GetFileContainer(map->lumpnum)); - delete map; - for (size_t j = 0; j < sizeof(cksum); ++j) + if(argv[i] == "*") { - Printf("%02X", cksum[j]); + const char *wadname = fileSystem.GetResourceFileName(fileSystem.GetFileContainer(level.lumpnum)); + + for (size_t i = 0; i < 16; ++i) + { + Printf("%02X", level.md5[i]); + } + + Printf(" // %s %s\n", wadname, level.MapName.GetChars()); + } + else + { + map = P_OpenMapData(argv[i], true); + if (map == NULL) + { + Printf("Cannot load %s as a map\n", argv[i]); + } + else + { + map->GetChecksum(cksum); + const char *wadname = fileSystem.GetResourceFileName(fileSystem.GetFileContainer(map->lumpnum)); + delete map; + for (size_t j = 0; j < sizeof(cksum); ++j) + { + Printf("%02X", cksum[j]); + } + Printf(" // %s %s\n", wadname, argv[i]); + } } - Printf(" // %s %s\n", wadname, argv[i]); } } } From c2fd99a24dc64cb397f66d0480bc74ede4d2712b Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Thu, 17 Oct 2024 21:28:52 -0400 Subject: [PATCH 19/60] Revert "- Actor.GetSpecies() is a non-destructive function" This reverts commit ee5442c06b200163811ad23287ac98330201ecf0. --- src/rendering/hwrenderer/hw_entrypoint.cpp | 2 +- wadsrc/static/zscript/actors/actor.zs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rendering/hwrenderer/hw_entrypoint.cpp b/src/rendering/hwrenderer/hw_entrypoint.cpp index e55c041a6..bfa0d8b1c 100644 --- a/src/rendering/hwrenderer/hw_entrypoint.cpp +++ b/src/rendering/hwrenderer/hw_entrypoint.cpp @@ -362,7 +362,7 @@ sector_t* RenderView(player_t* player) // Draw all canvases that changed for (FCanvas* canvas : AllCanvases) { - if (canvas->Tex && canvas->Tex->CheckNeedsUpdate()) + if (canvas->Tex->CheckNeedsUpdate()) { screen->RenderTextureView(canvas->Tex, [=](IntRect& bounds) { diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index 58a47afba..970b23405 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -854,7 +854,7 @@ class Actor : Thinker native native int LookForEnemiesEx(out Array targets, double range = -1, bool noPlayers = true, bool allaround = false, LookExParams params = null); native bool TeleportMove(Vector3 pos, bool telefrag, bool modifyactor = true); native clearscope double DistanceBySpeed(Actor other, double speed) const; - native clearscope name GetSpecies(); + native name GetSpecies(); native void PlayActiveSound(); native void Howl(); native void DrawSplash (int count, double angle, int kind); From 3bf3af9441d565458e053b5303c32217a9fe16f2 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Thu, 17 Oct 2024 23:45:09 -0400 Subject: [PATCH 20/60] - readd canvas check --- src/rendering/hwrenderer/hw_entrypoint.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rendering/hwrenderer/hw_entrypoint.cpp b/src/rendering/hwrenderer/hw_entrypoint.cpp index bfa0d8b1c..e55c041a6 100644 --- a/src/rendering/hwrenderer/hw_entrypoint.cpp +++ b/src/rendering/hwrenderer/hw_entrypoint.cpp @@ -362,7 +362,7 @@ sector_t* RenderView(player_t* player) // Draw all canvases that changed for (FCanvas* canvas : AllCanvases) { - if (canvas->Tex->CheckNeedsUpdate()) + if (canvas->Tex && canvas->Tex->CheckNeedsUpdate()) { screen->RenderTextureView(canvas->Tex, [=](IntRect& bounds) { From c38b11943567e6046945dd92c3e0d2765f333ad8 Mon Sep 17 00:00:00 2001 From: dileepvr Date: Tue, 15 Oct 2024 21:29:21 -0600 Subject: [PATCH 21/60] FOV scales ortho up to 180 degrees One line change in r_utility.cpp affecting a custom field. Orthographic projection sees "more" of the sceen as fov increases, but only up to 180 degrees, after which it will have no effect. Orthographic projection has no meaning for fov since there is no Frustum. But since this is fundamental to the engine, I am reinterpreting it. Cherno wanted this too. I'll update the wiki if this gets in. --- src/rendering/r_utility.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rendering/r_utility.cpp b/src/rendering/r_utility.cpp index 3e40c3a0c..b7b6b452b 100644 --- a/src/rendering/r_utility.cpp +++ b/src/rendering/r_utility.cpp @@ -704,7 +704,7 @@ void FRenderViewpoint::SetViewAngle(const FViewWindow& viewWindow) HWAngles.Yaw = FAngle::fromDeg(270.0 - Angles.Yaw.Degrees()); if (IsOrtho() && (camera->ViewPos->Offset.XY().Length() > 0.0)) - ScreenProj = 1.34396 / camera->ViewPos->Offset.Length(); // [DVR] Estimated. +/-1 should be top/bottom of screen. + ScreenProj = 1.34396 / camera->ViewPos->Offset.Length() / tan (FieldOfView.Radians()*0.5); // [DVR] Estimated. +/-1 should be top/bottom of screen. } From 6e7148b074188202be950599bd1119ede9a5be1a Mon Sep 17 00:00:00 2001 From: dileepvr Date: Wed, 16 Oct 2024 07:46:32 -0600 Subject: [PATCH 22/60] Missed a line in RenderOrthoNoFog Tying up the fov fix. --- src/rendering/hwrenderer/scene/hw_bsp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rendering/hwrenderer/scene/hw_bsp.cpp b/src/rendering/hwrenderer/scene/hw_bsp.cpp index 0904a0207..82f90a3ba 100644 --- a/src/rendering/hwrenderer/scene/hw_bsp.cpp +++ b/src/rendering/hwrenderer/scene/hw_bsp.cpp @@ -990,7 +990,7 @@ void HWDrawInfo::RenderOrthoNoFog() double vxdbl = Viewpoint.camera->X(); double vydbl = Viewpoint.camera->Y(); double ext = Viewpoint.camera->ViewPos->Offset.Length() ? - 3.0 * Viewpoint.camera->ViewPos->Offset.Length() : 100.0; + 3.0 * Viewpoint.camera->ViewPos->Offset.Length() * tan (Viewpoint.FieldOfView.Radians()*0.5) : 100.0; FBoundingBox viewbox(vxdbl, vydbl, ext); for (unsigned int kk = 0; kk < Level->subsectors.Size(); kk++) From c0bd024094c0d0f4eec1a0556fce91b31352cc50 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 19 Oct 2024 13:11:48 +0200 Subject: [PATCH 23/60] do not open resource files from non-open file readers. --- src/common/filesystem/source/resourcefile.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/common/filesystem/source/resourcefile.cpp b/src/common/filesystem/source/resourcefile.cpp index 81e2b7850..00a5234ca 100644 --- a/src/common/filesystem/source/resourcefile.cpp +++ b/src/common/filesystem/source/resourcefile.cpp @@ -162,6 +162,7 @@ static int nulPrintf(FSMessageLevel msg, const char* fmt, ...) FResourceFile *FResourceFile::DoOpenResourceFile(const char *filename, FileReader &file, bool containeronly, LumpFilterInfo* filter, FileSystemMessageFunc Printf, StringPool* sp) { + if (!file.isOpen()) return nullptr; if (Printf == nullptr) Printf = nulPrintf; for(auto func : funcs) { From c5308e4448c6f1b430feaa201278f98a869c3309 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 19 Oct 2024 13:13:11 +0200 Subject: [PATCH 24/60] fix bad string comparison. --- src/g_dumpinfo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_dumpinfo.cpp b/src/g_dumpinfo.cpp index fcca4ed5b..99c4b6adf 100644 --- a/src/g_dumpinfo.cpp +++ b/src/g_dumpinfo.cpp @@ -163,7 +163,7 @@ CCMD (mapchecksum) for (int i = 1; i < argv.argc(); ++i) { - if(argv[i] == "*") + if(!strcmp(argv[i], "*")) { const char *wadname = fileSystem.GetResourceFileName(fileSystem.GetFileContainer(level.lumpnum)); From e81d563cf4f4a32cee73019be6c84d610a4d4274 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 19 Oct 2024 13:22:30 +0200 Subject: [PATCH 25/60] made FCommandLine::operator[] return a const char * and fixed two places where this triggered a compile error. --- src/common/console/c_commandline.cpp | 2 +- src/common/console/c_commandline.h | 2 +- src/common/rendering/r_videoscale.cpp | 2 +- src/gamedata/keysections.cpp | 5 ++--- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/common/console/c_commandline.cpp b/src/common/console/c_commandline.cpp index 4f500ffe6..7fa9d1ff2 100644 --- a/src/common/console/c_commandline.cpp +++ b/src/common/console/c_commandline.cpp @@ -193,7 +193,7 @@ int FCommandLine::argc () return _argc; } -char *FCommandLine::operator[] (int i) +const char *FCommandLine::operator[] (int i) { if (_argv == NULL) { diff --git a/src/common/console/c_commandline.h b/src/common/console/c_commandline.h index dc5466df1..4886aa9c7 100644 --- a/src/common/console/c_commandline.h +++ b/src/common/console/c_commandline.h @@ -44,7 +44,7 @@ public: FCommandLine (const char *commandline, bool no_escapes = false); ~FCommandLine (); int argc (); - char *operator[] (int i); + const char *operator[] (int i); const char *args () { return cmd; } void Shift(); diff --git a/src/common/rendering/r_videoscale.cpp b/src/common/rendering/r_videoscale.cpp index 705fe905f..bfed3ec73 100644 --- a/src/common/rendering/r_videoscale.cpp +++ b/src/common/rendering/r_videoscale.cpp @@ -248,7 +248,7 @@ CCMD (vid_scaletoheight) } } -inline bool atob(char* I) +inline bool atob(const char* I) { if (stricmp (I, "true") == 0 || stricmp (I, "1") == 0) return true; diff --git a/src/gamedata/keysections.cpp b/src/gamedata/keysections.cpp index bcde05edd..25b71671b 100644 --- a/src/gamedata/keysections.cpp +++ b/src/gamedata/keysections.cpp @@ -100,12 +100,11 @@ CCMD (addkeysection) } // Limit the ini name to 32 chars - if (strlen (argv[2]) > 32) - argv[2][32] = 0; + FString name(argv[2], 32); for (unsigned i = 0; i < KeySections.Size(); i++) { - if (KeySections[i].mTitle.CompareNoCase(argv[2]) == 0) + if (KeySections[i].mTitle.CompareNoCase(name) == 0) { CurrentKeySection = i; return; From dd740b59e0d6af236ab087d507c8750ac5a95cb9 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Sat, 19 Oct 2024 10:17:01 -0400 Subject: [PATCH 26/60] Revert "- simplify and deconstruct logic for applying sector damage - also fixes voodoo doll sector damage in TNT MAP30" This reverts commit 3e33e31d1961f366229d5b4848fa29d2d797b8c3. Revert "Added MF9_FORCESECTORDAMAGE." This reverts commit 61bd3a739a0ca7509db46ddabbff1fc35bfd8908. --- src/playsim/actor.h | 1 - src/playsim/p_mobj.cpp | 6 +----- src/scripting/thingdef_data.cpp | 1 - 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/playsim/actor.h b/src/playsim/actor.h index 708e06f4c..759d9d262 100644 --- a/src/playsim/actor.h +++ b/src/playsim/actor.h @@ -445,7 +445,6 @@ enum ActorFlag9 MF9_DECOUPLEDANIMATIONS = 0x00000010, // [RL0] Decouple model animations from states MF9_NOSECTORDAMAGE = 0x00000020, // [inkoalawetrust] Actor ignores any sector-based damage (i.e damaging floors, NOT crushers) MF9_ISPUFF = 0x00000040, // [AA] Set on actors by P_SpawnPuff - MF9_FORCESECTORDAMAGE = 0x00000080, // [inkoalawetrust] Actor ALWAYS takes hurt floor damage if there's any. Even if the floor doesn't have SECMF_HURTMONSTERS. }; // --- mobj.renderflags --- diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index 4aa95ae83..eac012bb4 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -4436,11 +4436,7 @@ 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)) + if (!(flags9 & MF9_NOSECTORDAMAGE) && (player || (player == nullptr && Sector->MoreFlags & SECMF_HURTMONSTERS))) { P_ActorOnSpecial3DFloor(this); P_ActorInSpecialSector(this,Sector); diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 90ba65f00..129c06b78 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -353,7 +353,6 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG(MF9, DECOUPLEDANIMATIONS, AActor, flags9), DEFINE_FLAG(MF9, NOSECTORDAMAGE, AActor, flags9), DEFINE_PROTECTED_FLAG(MF9, ISPUFF, AActor, flags9), //[AA] was spawned by SpawnPuff - DEFINE_FLAG(MF9, FORCESECTORDAMAGE, AActor, flags9), // Effect flags DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects), From 4ba53e34e4ed1540f174d3c6ca33d17f5819b518 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Sat, 19 Oct 2024 10:25:03 -0400 Subject: [PATCH 27/60] Revert "Added SECMF_HURTMONSTERS, SECMF_HARMINAIR and NOSECTORDAMAGE." This reverts commit 391f4965128f2f5e2c07d764d42f363c67d9ed1c. --- specs/udmf_zdoom.txt | 2 - src/gamedata/r_defs.h | 2 - src/maploader/udmf.cpp | 8 ---- src/namedef_custom.h | 2 - src/playsim/actor.h | 3 +- src/playsim/p_3dfloors.cpp | 18 ++++----- src/playsim/p_3dfloors.h | 3 +- src/playsim/p_mobj.cpp | 8 ---- src/playsim/p_spec.cpp | 65 +++++++++++++++++--------------- src/playsim/p_spec.h | 4 +- src/playsim/p_user.cpp | 9 +++++ src/scripting/thingdef_data.cpp | 1 - wadsrc/static/zscript/mapdata.zs | 8 ---- 13 files changed, 58 insertions(+), 75 deletions(-) diff --git a/specs/udmf_zdoom.txt b/specs/udmf_zdoom.txt index 9e4df5472..4f73fa9bd 100644 --- a/specs/udmf_zdoom.txt +++ b/specs/udmf_zdoom.txt @@ -307,8 +307,6 @@ Note: All fields default to false unless mentioned otherwise. leakiness = ; // Probability of leaking through radiation suit (0 = never, 256 = always), default = 0. damageterraineffect = ; // Will spawn a terrain splash when damage is inflicted. Default = false. damagehazard = ; // Changes damage model to Strife's delayed damage for the given sector. Default = false. - hurtmonsters = ; // Non-players like monsters and decorations are hurt by this sector in the same manner as player. Doesn't work with damagehazard. - harminair = ; // Actors in this sector are harmed by the damage effects of the floor even if they aren't touching it. floorterrain = ; // Sets the terrain for the sector's floor. Default = 'use the flat texture's terrain definition.' ceilingterrain = ; // Sets the terrain for the sector's ceiling. Default = 'use the flat texture's terrain definition.' floor_reflect = ; // reflectiveness of floor (OpenGL only, not functional on sloped sectors) diff --git a/src/gamedata/r_defs.h b/src/gamedata/r_defs.h index d6453b6f8..943893c66 100644 --- a/src/gamedata/r_defs.h +++ b/src/gamedata/r_defs.h @@ -504,8 +504,6 @@ enum SECMF_OVERLAPPING = 512, // floor and ceiling overlap and require special renderer action. SECMF_NOSKYWALLS = 1024, // Do not draw "sky walls" SECMF_LIFT = 2048, // For MBF monster AI - SECMF_HURTMONSTERS = 4096, // Monsters in this sector are hurt like players. - SECMF_HARMINAIR = 8192, // Actors in this sector are also hurt mid-air. }; enum diff --git a/src/maploader/udmf.cpp b/src/maploader/udmf.cpp index 1fd9869c3..9748e082f 100644 --- a/src/maploader/udmf.cpp +++ b/src/maploader/udmf.cpp @@ -1979,14 +1979,6 @@ public: Flag(sec->Flags, SECF_HAZARD, key); break; - case NAME_hurtmonsters: - Flag(sec->MoreFlags, SECMF_HURTMONSTERS, key); - break; - - case NAME_harminair: - Flag(sec->MoreFlags, SECMF_HARMINAIR, key); - break; - case NAME_floorterrain: sec->terrainnum[sector_t::floor] = P_FindTerrain(CheckString(key)); break; diff --git a/src/namedef_custom.h b/src/namedef_custom.h index dbf94dbaf..dd2e0066d 100644 --- a/src/namedef_custom.h +++ b/src/namedef_custom.h @@ -810,8 +810,6 @@ xx(damageinterval) xx(leakiness) xx(damageterraineffect) xx(damagehazard) -xx(hurtmonsters) -xx(harminair) xx(floorterrain) xx(ceilingterrain) xx(floor_reflect) diff --git a/src/playsim/actor.h b/src/playsim/actor.h index 759d9d262..d472decad 100644 --- a/src/playsim/actor.h +++ b/src/playsim/actor.h @@ -442,8 +442,7 @@ enum ActorFlag9 MF9_DOSHADOWBLOCK = 0x00000002, // [inkoalawetrust] Should the monster look for SHADOWBLOCK actors ? MF9_SHADOWBLOCK = 0x00000004, // [inkoalawetrust] Actors in the line of fire with this flag trigger the MF_SHADOW aiming penalty. MF9_SHADOWAIMVERT = 0x00000008, // [inkoalawetrust] Monster aim is also offset vertically when aiming at shadow actors. - MF9_DECOUPLEDANIMATIONS = 0x00000010, // [RL0] Decouple model animations from states - MF9_NOSECTORDAMAGE = 0x00000020, // [inkoalawetrust] Actor ignores any sector-based damage (i.e damaging floors, NOT crushers) + MF9_DECOUPLEDANIMATIONS = 0x00000010, // [RL0] Decouple model animations from states MF9_ISPUFF = 0x00000040, // [AA] Set on actors by P_SpawnPuff }; diff --git a/src/playsim/p_3dfloors.cpp b/src/playsim/p_3dfloors.cpp index 505bfa794..dd5a2bb0a 100644 --- a/src/playsim/p_3dfloors.cpp +++ b/src/playsim/p_3dfloors.cpp @@ -198,15 +198,15 @@ void P_Add3DFloor(sector_t* sec, sector_t* sec2, line_t* master, int flags, int //========================================================================== // -// P_ActorOnSpecial3DFloor -// Checks to see if an actor is standing on or is inside a 3D floor (water) +// P_PlayerOnSpecial3DFloor +// Checks to see if a player is standing on or is inside a 3D floor (water) // and applies any specials.. // //========================================================================== -void P_ActorOnSpecial3DFloor(AActor* victim) +void P_PlayerOnSpecial3DFloor(player_t* player) { - for(auto rover : victim->Sector->e->XFloor.ffloors) + for(auto rover : player->mo->Sector->e->XFloor.ffloors) { if (!(rover->flags & FF_EXISTS)) continue; if (rover->flags & FF_FIX) continue; @@ -215,22 +215,22 @@ void P_ActorOnSpecial3DFloor(AActor* victim) 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(player->mo->Z() != rover->top.plane->ZatPoint(player->mo)) continue; } else { //Water and DEATH FOG!!! heh if ((rover->flags & FF_NODAMAGE) || - victim->Z() > rover->top.plane->ZatPoint(victim) || - victim->Top() < rover->bottom.plane->ZatPoint(victim)) + player->mo->Z() > rover->top.plane->ZatPoint(player->mo) || + player->mo->Top() < rover->bottom.plane->ZatPoint(player->mo)) continue; } // Apply sector specials - P_ActorInSpecialSector(victim, rover->model); + P_PlayerInSpecialSector(player, rover->model); // Apply flat specials (using the ceiling!) - P_ActorOnSpecialFlat(victim, rover->model->GetTerrain(rover->top.isceiling)); + P_PlayerOnSpecialFlat(player, rover->model->GetTerrain(rover->top.isceiling)); break; } diff --git a/src/playsim/p_3dfloors.h b/src/playsim/p_3dfloors.h index 2dba7f713..05d222137 100644 --- a/src/playsim/p_3dfloors.h +++ b/src/playsim/p_3dfloors.h @@ -113,7 +113,8 @@ struct lightlist_t -void P_ActorOnSpecial3DFloor(AActor* victim); +class player_t; +void P_PlayerOnSpecial3DFloor(player_t* player); bool P_CheckFor3DFloorHit(AActor * mo, double z, bool trigger); bool P_CheckFor3DCeilingHit(AActor * mo, double z, bool trigger); diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index eac012bb4..4bb0472a3 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -4435,14 +4435,6 @@ void AActor::Tick () // must have been removed 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. - if (!(flags9 & MF9_NOSECTORDAMAGE) && (player || (player == nullptr && Sector->MoreFlags & SECMF_HURTMONSTERS))) - { - 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)); - } if (tics != -1) { diff --git a/src/playsim/p_spec.cpp b/src/playsim/p_spec.cpp index 9c3fde6f4..ab52f285a 100644 --- a/src/playsim/p_spec.cpp +++ b/src/playsim/p_spec.cpp @@ -100,7 +100,7 @@ #include "c_console.h" #include "p_spec_thinkers.h" -static FRandom pr_actorinspecialsector ("ActorInSpecialSector"); +static FRandom pr_playerinspecialsector ("PlayerInSpecialSector"); EXTERN_CVAR(Bool, cl_predict_specials) EXTERN_CVAR(Bool, forcewater) @@ -419,18 +419,21 @@ bool P_PredictLine(line_t *line, AActor *mo, int side, int activationType) } // -// P_ActorInSpecialSector +// P_PlayerInSpecialSector // Called every tic frame -// that the actor origin is in a special sector +// that the player origin is in a special sector // -void P_ActorInSpecialSector (AActor *victim, sector_t * sector) +void P_PlayerInSpecialSector (player_t *player, sector_t * sector) { 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; + { + // Falling, not all the way down yet? + sector = player->mo->Sector; + if (!player->mo->isAtZ(sector->LowestFloorAt(player->mo)) + && !player->mo->waterlevel) + { + return; + } // Has hit ground. @@ -441,7 +444,7 @@ void P_ActorInSpecialSector (AActor *victim, sector_t * sector) if (sector->damageinterval <= 0) sector->damageinterval = 32; // repair invalid damageinterval values - if (victim->player && sector->Flags & (SECF_EXIT1 | SECF_EXIT2)) + if (sector->Flags & (SECF_EXIT1 | SECF_EXIT2)) { for (int i = 0; i < MAXPLAYERS; i++) if (playeringame[i]) @@ -460,7 +463,7 @@ void P_ActorInSpecialSector (AActor *victim, 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 = victim->Inventory; i != NULL; i = i->Inventory) + for (auto i = player->mo->Inventory; i != NULL; i = i->Inventory) { if (i->IsKindOf(NAME_PowerIronFeet)) { @@ -472,28 +475,28 @@ void P_ActorInSpecialSector (AActor *victim, sector_t * sector) } } - 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_ENDGODMODE) player->cheats &= ~CF_GODMODE; + if ((ironfeet == 0 || (ironfeet < 2 && pr_playerinspecialsector() < sector->leakydamage))) { - if (victim->player && sector->Flags & SECF_HAZARD) + if (sector->Flags & SECF_HAZARD) { - victim->player->hazardcount += sector->damageamount; - victim->player->hazardtype = sector->damagetype; - victim->player->hazardinterval = sector->damageinterval; + player->hazardcount += sector->damageamount; + player->hazardtype = sector->damagetype; + player->hazardinterval = sector->damageinterval; } else if (Level->time % sector->damageinterval == 0) { - if (!(victim->player && victim->player->cheats & (CF_GODMODE | CF_GODMODE2))) + if (!(player->cheats & (CF_GODMODE | CF_GODMODE2))) { - P_DamageMobj(victim, NULL, NULL, sector->damageamount, sector->damagetype); + P_DamageMobj(player->mo, NULL, NULL, sector->damageamount, sector->damagetype); } - if (victim->player && (sector->Flags & SECF_ENDLEVEL) && victim->player->health <= 10 && (!deathmatch || !(dmflags & DF_NO_EXIT))) + if ((sector->Flags & SECF_ENDLEVEL) && player->health <= 10 && (!deathmatch || !(dmflags & DF_NO_EXIT))) { Level->ExitLevel(0, false); } if (sector->Flags & SECF_DMGTERRAINFX) { - P_HitWater(victim, victim->Sector, victim->Pos(), false, true, true); + P_HitWater(player->mo, player->mo->Sector, player->mo->Pos(), false, true, true); } } } @@ -502,14 +505,14 @@ void P_ActorInSpecialSector (AActor *victim, sector_t * sector) { if (Level->time % sector->damageinterval == 0) { - P_GiveBody(victim, -sector->damageamount, 100); + P_GiveBody(player->mo, -sector->damageamount, 100); } } - if (victim->player && sector->isSecret()) + if (sector->isSecret()) { sector->ClearSecret(); - P_GiveSecret(Level, victim, true, true, sector->Index()); + P_GiveSecret(Level, player->mo, true, true, sector->Index()); } } @@ -648,13 +651,13 @@ DEFINE_ACTION_FUNCTION(FLevelLocals, GiveSecret) //============================================================================ // -// P_ActorOnSpecialFlat +// P_PlayerOnSpecialFlat // //============================================================================ -void P_ActorOnSpecialFlat (AActor *victim, int floorType) +void P_PlayerOnSpecialFlat (player_t *player, int floorType) { - auto Level = victim->Level; + auto Level = player->mo->Level; if (Terrains[floorType].DamageAmount && !(Level->time % (Terrains[floorType].DamageTimeMask+1))) @@ -664,7 +667,7 @@ void P_ActorOnSpecialFlat (AActor *victim, int floorType) if (Terrains[floorType].AllowProtection) { auto pitype = PClass::FindActor(NAME_PowerIronFeet); - for (ironfeet = victim->Inventory; ironfeet != NULL; ironfeet = ironfeet->Inventory) + for (ironfeet = player->mo->Inventory; ironfeet != NULL; ironfeet = ironfeet->Inventory) { if (ironfeet->IsKindOf (pitype)) break; @@ -674,18 +677,20 @@ void P_ActorOnSpecialFlat (AActor *victim, int floorType) int damage = 0; if (ironfeet == NULL) { - damage = P_DamageMobj (victim, NULL, NULL, Terrains[floorType].DamageAmount, + damage = P_DamageMobj (player->mo, NULL, NULL, Terrains[floorType].DamageAmount, Terrains[floorType].DamageMOD); } if (damage > 0 && Terrains[floorType].Splash != -1) { - S_Sound (victim, CHAN_AUTO, 0, + S_Sound (player->mo, CHAN_AUTO, 0, Splashes[Terrains[floorType].Splash].NormalSplashSound, 1, ATTN_IDLE); } } } + + // // P_UpdateSpecials // Animate planes, scroll walls, etc. diff --git a/src/playsim/p_spec.h b/src/playsim/p_spec.h index ebb5d93f9..cc7d990a9 100644 --- a/src/playsim/p_spec.h +++ b/src/playsim/p_spec.h @@ -90,8 +90,8 @@ 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_ActorOnSpecialFlat (AActor *victim, int floorType); +void P_PlayerInSpecialSector (player_t *player, sector_t * sector=NULL); +void P_PlayerOnSpecialFlat (player_t *player, 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); diff --git a/src/playsim/p_user.cpp b/src/playsim/p_user.cpp index a98a7c523..d3294ffd6 100644 --- a/src/playsim/p_user.cpp +++ b/src/playsim/p_user.cpp @@ -1204,6 +1204,15 @@ DEFINE_ACTION_FUNCTION(APlayerPawn, CheckMusicChange) void P_CheckEnvironment(player_t *player) { + P_PlayerOnSpecial3DFloor(player); + P_PlayerInSpecialSector(player); + + if (!player->mo->isAbove(player->mo->Sector->floorplane.ZatPoint(player->mo)) || + player->mo->waterlevel) + { + // Player must be touching the floor + P_PlayerOnSpecialFlat(player, P_GetThingFloorType(player->mo)); + } if (player->mo->Vel.Z <= -player->mo->FloatVar(NAME_FallingScreamMinSpeed) && player->mo->Vel.Z >= -player->mo->FloatVar(NAME_FallingScreamMaxSpeed) && player->mo->alternative == nullptr && player->mo->waterlevel == 0) diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 129c06b78..be7c299ed 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -351,7 +351,6 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG(MF9, SHADOWBLOCK, AActor, flags9), DEFINE_FLAG(MF9, SHADOWAIMVERT, AActor, flags9), DEFINE_FLAG(MF9, DECOUPLEDANIMATIONS, AActor, flags9), - DEFINE_FLAG(MF9, NOSECTORDAMAGE, AActor, flags9), DEFINE_PROTECTED_FLAG(MF9, ISPUFF, AActor, flags9), //[AA] was spawned by SpawnPuff // Effect flags diff --git a/wadsrc/static/zscript/mapdata.zs b/wadsrc/static/zscript/mapdata.zs index 06a7bf3ea..5d45563eb 100644 --- a/wadsrc/static/zscript/mapdata.zs +++ b/wadsrc/static/zscript/mapdata.zs @@ -435,11 +435,6 @@ struct Sector native play SECMF_UNDERWATERMASK = 32+64, SECMF_DRAWN = 128, // sector has been drawn at least once SECMF_HIDDEN = 256, // Do not draw on textured automap - SECMF_OVERLAPPING = 512, // floor and ceiling overlap and require special renderer action. - SECMF_NOSKYWALLS = 1024, // Do not draw "sky walls" - SECMF_LIFT = 2048, // For MBF monster AI - SECMF_HURTMONSTERS = 4096, // Monsters in this sector are hurt like players. - SECMF_HARMINAIR = 8192, // Actors in this sector are also hurt mid-air. } native uint16 MoreFlags; @@ -457,9 +452,6 @@ struct Sector native play SECF_ENDLEVEL = 512, // ends level when health goes below 10 SECF_HAZARD = 1024, // Change to Strife's delayed damage handling. SECF_NOATTACK = 2048, // monsters cannot start attacks in this sector. - SECF_EXIT1 = 4096, - SECF_EXIT2 = 8192, - SECF_KILLMONSTERS = 16384,// Monsters in this sector are instantly killed. SECF_WASSECRET = 1 << 30, // a secret that was discovered SECF_SECRET = 1 << 31, // a secret sector From c5da81763d41222dc91ea561f58b5a33851748bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Sat, 19 Oct 2024 11:30:04 -0300 Subject: [PATCH 28/60] Fully revert #2479 --- src/playsim/actor.h | 2 +- src/playsim/p_enemy.cpp | 6 ------ src/playsim/p_spec.cpp | 1 + 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/playsim/actor.h b/src/playsim/actor.h index d472decad..c6bd74e5b 100644 --- a/src/playsim/actor.h +++ b/src/playsim/actor.h @@ -442,7 +442,7 @@ enum ActorFlag9 MF9_DOSHADOWBLOCK = 0x00000002, // [inkoalawetrust] Should the monster look for SHADOWBLOCK actors ? MF9_SHADOWBLOCK = 0x00000004, // [inkoalawetrust] Actors in the line of fire with this flag trigger the MF_SHADOW aiming penalty. MF9_SHADOWAIMVERT = 0x00000008, // [inkoalawetrust] Monster aim is also offset vertically when aiming at shadow actors. - MF9_DECOUPLEDANIMATIONS = 0x00000010, // [RL0] Decouple model animations from states + MF9_DECOUPLEDANIMATIONS = 0x00000010, // [RL0] Decouple model animations from states MF9_ISPUFF = 0x00000040, // [AA] Set on actors by P_SpawnPuff }; diff --git a/src/playsim/p_enemy.cpp b/src/playsim/p_enemy.cpp index 120f37231..39d43d7b1 100644 --- a/src/playsim/p_enemy.cpp +++ b/src/playsim/p_enemy.cpp @@ -464,12 +464,6 @@ static int P_IsUnderDamage(AActor* actor) dir |= cl->getDirection(); } // Q: consider crushing 3D floors too? - // [inkoalawetrust] Check for sectors that can harm the actor. - if (!(actor->flags9 & MF9_NOSECTORDAMAGE) && seclist->m_sector->damageamount > 0) - { - if (seclist->m_sector->MoreFlags & SECMF_HARMINAIR || actor->isAtZ(seclist->m_sector->LowestFloorAt(actor)) || actor->waterlevel) - return (actor->player || (actor->player == nullptr && seclist->m_sector->MoreFlags & SECMF_HURTMONSTERS)) ? -1 : 0; - } } return dir; } diff --git a/src/playsim/p_spec.cpp b/src/playsim/p_spec.cpp index ab52f285a..6ffc2d9af 100644 --- a/src/playsim/p_spec.cpp +++ b/src/playsim/p_spec.cpp @@ -434,6 +434,7 @@ void P_PlayerInSpecialSector (player_t *player, sector_t * sector) { return; } + } // Has hit ground. From 12c6d1361adc6594f356ee5c99e0502574302240 Mon Sep 17 00:00:00 2001 From: nashmuhandes Date: Fri, 18 Oct 2024 21:36:16 +0800 Subject: [PATCH 29/60] Move no-mipmapping from actor renderflag/particle flag, to a material property in GLDEFS, where it makes more sense. The feature was introduced in the short-lived engine version of 4.13 which was deemed too broken and needed to be replaced with a newer version anyway, so might as well perform an API-breaking change at this point in time. Note that this currently only works for sprites (its primary targeted use case) -- walls, flats and models can be patched in later. --- src/common/textures/gametexture.h | 4 ++++ src/playsim/actor.h | 7 +++---- src/playsim/p_effect.h | 3 +-- src/r_data/gldefs.cpp | 14 ++++++++++++++ src/rendering/hwrenderer/scene/hw_drawstructs.h | 2 -- src/rendering/hwrenderer/scene/hw_sprites.cpp | 10 ++++++---- src/scripting/thingdef_data.cpp | 1 - wadsrc/static/zscript/constants.zs | 3 +-- 8 files changed, 29 insertions(+), 15 deletions(-) diff --git a/src/common/textures/gametexture.h b/src/common/textures/gametexture.h index 3eb3740a9..a55616e66 100644 --- a/src/common/textures/gametexture.h +++ b/src/common/textures/gametexture.h @@ -62,6 +62,7 @@ enum EGameTexFlags GTexf_OffsetsNotForFont = 512, // The offsets must be ignored when using this texture in a font. GTexf_NoTrim = 1024, // Don't perform trimming on this texture. GTexf_Seen = 2048, // Set to true when the texture is being used for rendering. Must be cleared manually if the check is needed. + GTexf_NoMipmap = 4096, // Disable mipmapping for this texture }; struct FMaterialLayers @@ -265,6 +266,9 @@ public: void SetGlowing(PalEntry color) { flags = (flags & ~GTexf_AutoGlowing) | GTexf_Glowing; GlowColor = color; } void SetDisableBrightmap() { flags |= GTexf_BrightmapChecked; Brightmap = nullptr; } + bool isNoMipmap() const { return !!(flags & GTexf_NoMipmap); } + void SetNoMipmap(bool set) { if (set) flags |= GTexf_NoMipmap; else flags &= ~GTexf_NoMipmap; } + bool isUserContent() const; int CheckRealHeight() { return xs_RoundToInt(Base->CheckRealHeight() / ScaleY); } void SetSize(int x, int y) diff --git a/src/playsim/actor.h b/src/playsim/actor.h index c6bd74e5b..98e4d88b7 100644 --- a/src/playsim/actor.h +++ b/src/playsim/actor.h @@ -502,10 +502,9 @@ enum ActorRenderFlag2 RF2_FLIPSPRITEOFFSETX = 0x0010, RF2_FLIPSPRITEOFFSETY = 0x0020, RF2_CAMFOLLOWSPLAYER = 0x0040, // Matches the cam's base position and angles to the main viewpoint. - RF2_NOMIPMAP = 0x0080, // [Nash] forces no mipmapping on sprites. Useful for tiny sprites that need to remain visually crisp - RF2_ISOMETRICSPRITES = 0x0100, - RF2_SQUAREPIXELS = 0x0200, // apply +ROLLSPRITE scaling math so that non rolling sprites get the same scaling - RF2_STRETCHPIXELS = 0x0400, // don't apply SQUAREPIXELS for ROLLSPRITES + RF2_ISOMETRICSPRITES = 0x0080, + RF2_SQUAREPIXELS = 0x0100, // apply +ROLLSPRITE scaling math so that non rolling sprites get the same scaling + RF2_STRETCHPIXELS = 0x0200, // don't apply SQUAREPIXELS for ROLLSPRITES }; // This translucency value produces the closest match to Heretic's TINTTAB. diff --git a/src/playsim/p_effect.h b/src/playsim/p_effect.h index 4884739f2..735a87e81 100644 --- a/src/playsim/p_effect.h +++ b/src/playsim/p_effect.h @@ -69,8 +69,7 @@ enum EParticleFlags SPF_FACECAMERA = 1 << 11, SPF_NOFACECAMERA = 1 << 12, SPF_ROLLCENTER = 1 << 13, - SPF_NOMIPMAP = 1 << 14, - SPF_STRETCHPIXELS = 1 << 15, + SPF_STRETCHPIXELS = 1 << 14, }; class DVisualThinker; diff --git a/src/r_data/gldefs.cpp b/src/r_data/gldefs.cpp index 9b5be0e25..d92b9daf6 100644 --- a/src/r_data/gldefs.cpp +++ b/src/r_data/gldefs.cpp @@ -1270,6 +1270,7 @@ class GLDefsParser bool disable_fullbright_specified = false; bool thiswad = false; bool iwad = false; + bool no_mipmap = false; UserShaderDesc usershader; TArray texNameList; @@ -1319,6 +1320,10 @@ class GLDefsParser // only affects textures defined in the IWAD. iwad = true; } + else if (sc.Compare("nomipmap")) + { + no_mipmap = true; + } else if (sc.Compare("glossiness")) { sc.MustGetFloat(); @@ -1422,6 +1427,8 @@ class GLDefsParser if (!useme) return; } + tex->SetNoMipmap(no_mipmap); + FGameTexture **bindings[6] = { &mlay.Brightmap, @@ -1681,6 +1688,7 @@ class GLDefsParser bool disable_fullbright = false; bool thiswad = false; bool iwad = false; + bool no_mipmap = false; int maplump = -1; UserShaderDesc desc; desc.shaderType = SHADER_Default; @@ -1723,6 +1731,10 @@ class GLDefsParser if (!found) sc.ScriptError("Unknown material type '%s' specified\n", sc.String); } + else if (sc.Compare("nomipmap")) + { + no_mipmap = true; + } else if (sc.Compare("speed")) { sc.MustGetFloat(); @@ -1784,6 +1796,8 @@ class GLDefsParser return; } + tex->SetNoMipmap(no_mipmap); + int firstUserTexture; switch (desc.shaderType) { diff --git a/src/rendering/hwrenderer/scene/hw_drawstructs.h b/src/rendering/hwrenderer/scene/hw_drawstructs.h index b364128de..903806c67 100644 --- a/src/rendering/hwrenderer/scene/hw_drawstructs.h +++ b/src/rendering/hwrenderer/scene/hw_drawstructs.h @@ -393,8 +393,6 @@ public: TArray *lightlist; DRotator Angles; - bool nomipmap; // force the sprite to have no mipmaps (ensures tiny sprites in the distance stay crisp) - void SplitSprite(HWDrawInfo *di, sector_t * frontsector, bool translucent); void PerformSpriteClipAdjustment(AActor *thing, const DVector2 &thingpos, float spriteheight); bool CalculateVertices(HWDrawInfo *di, FVector3 *v, DVector3 *vp); diff --git a/src/rendering/hwrenderer/scene/hw_sprites.cpp b/src/rendering/hwrenderer/scene/hw_sprites.cpp index 91125b750..cbca1a90d 100644 --- a/src/rendering/hwrenderer/scene/hw_sprites.cpp +++ b/src/rendering/hwrenderer/scene/hw_sprites.cpp @@ -224,7 +224,12 @@ void HWSprite::DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent) state.SetFog(0, 0); } - int clampmode = nomipmap ? CLAMP_XY_NOMIP : CLAMP_XY; + int clampmode = CLAMP_XY; + + if (texture && texture->isNoMipmap()) + { + clampmode = CLAMP_XY_NOMIP; + } uint32_t spritetype = actor? uint32_t(actor->renderflags & RF_SPRITETYPEMASK) : 0; if (texture) state.SetMaterial(texture, UF_Sprite, (spritetype == RF_FACESPRITE) ? CTF_Expand : 0, clampmode, translation, OverrideShader); @@ -786,8 +791,6 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t return; } - nomipmap = (thing->renderflags2 & RF2_NOMIPMAP); - // check renderrequired vs ~r_rendercaps, if anything matches we don't support that feature, // check renderhidden vs r_rendercaps, if anything matches we do support that feature and should hide it. if ((!r_debug_disable_vis_filter && !!(thing->RenderRequired & ~r_renderercaps)) || @@ -1420,7 +1423,6 @@ void HWSprite::ProcessParticle(HWDrawInfo *di, particle_t *particle, sector_t *s actor = nullptr; this->particle = particle; fullbright = particle->flags & SPF_FULLBRIGHT; - nomipmap = particle->flags & SPF_NOMIPMAP; if (di->isFullbrightScene()) { diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index be7c299ed..dc7fcacc3 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -383,7 +383,6 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG(RF2, FLIPSPRITEOFFSETX, AActor, renderflags2), DEFINE_FLAG(RF2, FLIPSPRITEOFFSETY, AActor, renderflags2), DEFINE_FLAG(RF2, CAMFOLLOWSPLAYER, AActor, renderflags2), - DEFINE_FLAG(RF2, NOMIPMAP, AActor, renderflags2), DEFINE_FLAG(RF2, ISOMETRICSPRITES, AActor, renderflags2), DEFINE_FLAG(RF2, SQUAREPIXELS, AActor, renderflags2), diff --git a/wadsrc/static/zscript/constants.zs b/wadsrc/static/zscript/constants.zs index 2e5ce524a..ae57f7a4d 100644 --- a/wadsrc/static/zscript/constants.zs +++ b/wadsrc/static/zscript/constants.zs @@ -722,8 +722,7 @@ enum EParticleFlags SPF_FACECAMERA = 1 << 11, SPF_NOFACECAMERA = 1 << 12, SPF_ROLLCENTER = 1 << 13, - SPF_NOMIPMAP = 1 << 14, - SPF_STRETCHPIXELS = 1 << 15, + SPF_STRETCHPIXELS = 1 << 14, SPF_RELATIVE = SPF_RELPOS|SPF_RELVEL|SPF_RELACCEL|SPF_RELANG }; From 34dc204517a21dd4eab3a627435fca4b8397f9fb Mon Sep 17 00:00:00 2001 From: inkoalawetrust <56005600+inkoalawetrust@users.noreply.github.com> Date: Sun, 20 Oct 2024 14:51:36 +0300 Subject: [PATCH 30/60] 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. --- specs/udmf_zdoom.txt | 2 + src/gamedata/r_defs.h | 2 + src/maploader/udmf.cpp | 8 ++++ src/namedef_custom.h | 2 + src/playsim/actor.h | 2 + src/playsim/p_3dfloors.cpp | 21 ++++----- src/playsim/p_3dfloors.h | 3 +- src/playsim/p_enemy.cpp | 6 +++ src/playsim/p_mobj.cpp | 8 ++++ src/playsim/p_spec.cpp | 74 ++++++++++++++++---------------- src/playsim/p_spec.h | 14 +++++- src/playsim/p_user.cpp | 9 ---- src/scripting/thingdef_data.cpp | 2 + wadsrc/static/zscript/mapdata.zs | 8 ++++ 14 files changed, 102 insertions(+), 59 deletions(-) diff --git a/specs/udmf_zdoom.txt b/specs/udmf_zdoom.txt index 4f73fa9bd..9e4df5472 100644 --- a/specs/udmf_zdoom.txt +++ b/specs/udmf_zdoom.txt @@ -307,6 +307,8 @@ Note: All fields default to false unless mentioned otherwise. leakiness = ; // Probability of leaking through radiation suit (0 = never, 256 = always), default = 0. damageterraineffect = ; // Will spawn a terrain splash when damage is inflicted. Default = false. damagehazard = ; // Changes damage model to Strife's delayed damage for the given sector. Default = false. + hurtmonsters = ; // Non-players like monsters and decorations are hurt by this sector in the same manner as player. Doesn't work with damagehazard. + harminair = ; // Actors in this sector are harmed by the damage effects of the floor even if they aren't touching it. floorterrain = ; // Sets the terrain for the sector's floor. Default = 'use the flat texture's terrain definition.' ceilingterrain = ; // Sets the terrain for the sector's ceiling. Default = 'use the flat texture's terrain definition.' floor_reflect = ; // reflectiveness of floor (OpenGL only, not functional on sloped sectors) diff --git a/src/gamedata/r_defs.h b/src/gamedata/r_defs.h index 943893c66..d6453b6f8 100644 --- a/src/gamedata/r_defs.h +++ b/src/gamedata/r_defs.h @@ -504,6 +504,8 @@ enum SECMF_OVERLAPPING = 512, // floor and ceiling overlap and require special renderer action. SECMF_NOSKYWALLS = 1024, // Do not draw "sky walls" SECMF_LIFT = 2048, // For MBF monster AI + SECMF_HURTMONSTERS = 4096, // Monsters in this sector are hurt like players. + SECMF_HARMINAIR = 8192, // Actors in this sector are also hurt mid-air. }; enum diff --git a/src/maploader/udmf.cpp b/src/maploader/udmf.cpp index 9748e082f..1fd9869c3 100644 --- a/src/maploader/udmf.cpp +++ b/src/maploader/udmf.cpp @@ -1979,6 +1979,14 @@ public: Flag(sec->Flags, SECF_HAZARD, key); break; + case NAME_hurtmonsters: + Flag(sec->MoreFlags, SECMF_HURTMONSTERS, key); + break; + + case NAME_harminair: + Flag(sec->MoreFlags, SECMF_HARMINAIR, key); + break; + case NAME_floorterrain: sec->terrainnum[sector_t::floor] = P_FindTerrain(CheckString(key)); break; diff --git a/src/namedef_custom.h b/src/namedef_custom.h index dd2e0066d..dbf94dbaf 100644 --- a/src/namedef_custom.h +++ b/src/namedef_custom.h @@ -810,6 +810,8 @@ xx(damageinterval) xx(leakiness) xx(damageterraineffect) xx(damagehazard) +xx(hurtmonsters) +xx(harminair) xx(floorterrain) xx(ceilingterrain) xx(floor_reflect) diff --git a/src/playsim/actor.h b/src/playsim/actor.h index 98e4d88b7..326a6f186 100644 --- a/src/playsim/actor.h +++ b/src/playsim/actor.h @@ -443,7 +443,9 @@ enum ActorFlag9 MF9_SHADOWBLOCK = 0x00000004, // [inkoalawetrust] Actors in the line of fire with this flag trigger the MF_SHADOW aiming penalty. MF9_SHADOWAIMVERT = 0x00000008, // [inkoalawetrust] Monster aim is also offset vertically when aiming at shadow actors. MF9_DECOUPLEDANIMATIONS = 0x00000010, // [RL0] Decouple model animations from states + MF9_NOSECTORDAMAGE = 0x00000020, // [inkoalawetrust] Actor ignores any sector-based damage (i.e damaging floors, NOT crushers) MF9_ISPUFF = 0x00000040, // [AA] Set on actors by P_SpawnPuff + MF9_FORCESECTORDAMAGE = 0x00000080, // [inkoalawetrust] Actor ALWAYS takes hurt floor damage if there's any. Even if the floor doesn't have SECMF_HURTMONSTERS. }; // --- mobj.renderflags --- diff --git a/src/playsim/p_3dfloors.cpp b/src/playsim/p_3dfloors.cpp index dd5a2bb0a..cce58326c 100644 --- a/src/playsim/p_3dfloors.cpp +++ b/src/playsim/p_3dfloors.cpp @@ -198,39 +198,40 @@ void P_Add3DFloor(sector_t* sec, sector_t* sec2, line_t* master, int flags, int //========================================================================== // -// P_PlayerOnSpecial3DFloor -// Checks to see if a player is standing on or is inside a 3D floor (water) +// P_ActorOnSpecial3DFloor +// Checks to see if an actor is standing on or is inside a 3D floor (water) // and applies any specials.. // //========================================================================== -void P_PlayerOnSpecial3DFloor(player_t* player) +void P_ActorOnSpecial3DFloor(AActor* victim) { - for(auto rover : player->mo->Sector->e->XFloor.ffloors) + for(auto rover : victim->Sector->e->XFloor.ffloors) { 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(player->mo->Z() != rover->top.plane->ZatPoint(player->mo)) continue; + if (victim->Z() != rover->top.plane->ZatPoint(victim)) continue; } else { //Water and DEATH FOG!!! heh if ((rover->flags & FF_NODAMAGE) || - player->mo->Z() > rover->top.plane->ZatPoint(player->mo) || - player->mo->Top() < rover->bottom.plane->ZatPoint(player->mo)) + victim->Z() > rover->top.plane->ZatPoint(victim) || + victim->Top() < rover->bottom.plane->ZatPoint(victim)) continue; } // Apply sector specials - P_PlayerInSpecialSector(player, rover->model); + P_ActorInSpecialSector(victim, rover->model,rover); // Apply flat specials (using the ceiling!) - P_PlayerOnSpecialFlat(player, rover->model->GetTerrain(rover->top.isceiling)); + P_ActorOnSpecialFlat(victim, rover->model->GetTerrain(rover->top.isceiling)); break; } diff --git a/src/playsim/p_3dfloors.h b/src/playsim/p_3dfloors.h index 05d222137..2dba7f713 100644 --- a/src/playsim/p_3dfloors.h +++ b/src/playsim/p_3dfloors.h @@ -113,8 +113,7 @@ struct lightlist_t -class player_t; -void P_PlayerOnSpecial3DFloor(player_t* player); +void P_ActorOnSpecial3DFloor(AActor* victim); bool P_CheckFor3DFloorHit(AActor * mo, double z, bool trigger); bool P_CheckFor3DCeilingHit(AActor * mo, double z, bool trigger); diff --git a/src/playsim/p_enemy.cpp b/src/playsim/p_enemy.cpp index 39d43d7b1..120f37231 100644 --- a/src/playsim/p_enemy.cpp +++ b/src/playsim/p_enemy.cpp @@ -464,6 +464,12 @@ static int P_IsUnderDamage(AActor* actor) dir |= cl->getDirection(); } // Q: consider crushing 3D floors too? + // [inkoalawetrust] Check for sectors that can harm the actor. + if (!(actor->flags9 & MF9_NOSECTORDAMAGE) && seclist->m_sector->damageamount > 0) + { + if (seclist->m_sector->MoreFlags & SECMF_HARMINAIR || actor->isAtZ(seclist->m_sector->LowestFloorAt(actor)) || actor->waterlevel) + return (actor->player || (actor->player == nullptr && seclist->m_sector->MoreFlags & SECMF_HURTMONSTERS)) ? -1 : 0; + } } return dir; } diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index 4bb0472a3..0f9a91803 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -4435,6 +4435,14 @@ void AActor::Tick () // must have been removed 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. + P_ActorOnSpecial3DFloor(this); //3D floors must be checked separately to see if their control sector allows non-player damage + if (checkForSpecialSector(this,Sector)) + { + 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)); + } if (tics != -1) { diff --git a/src/playsim/p_spec.cpp b/src/playsim/p_spec.cpp index 6ffc2d9af..c78dd1145 100644 --- a/src/playsim/p_spec.cpp +++ b/src/playsim/p_spec.cpp @@ -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. diff --git a/src/playsim/p_spec.h b/src/playsim/p_spec.h index cc7d990a9..3ef1aef9e 100644 --- a/src/playsim/p_spec.h +++ b/src/playsim/p_spec.h @@ -35,6 +35,7 @@ #include "dsectoreffect.h" #include "doomdata.h" #include "r_state.h" +#include "d_player.h" class FScanner; struct level_info_t; @@ -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_PlayerInSpecialSector (player_t *player, sector_t * sector=NULL); -void P_PlayerOnSpecialFlat (player_t *player, int floorType); +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. diff --git a/src/playsim/p_user.cpp b/src/playsim/p_user.cpp index d3294ffd6..a98a7c523 100644 --- a/src/playsim/p_user.cpp +++ b/src/playsim/p_user.cpp @@ -1204,15 +1204,6 @@ DEFINE_ACTION_FUNCTION(APlayerPawn, CheckMusicChange) void P_CheckEnvironment(player_t *player) { - P_PlayerOnSpecial3DFloor(player); - P_PlayerInSpecialSector(player); - - if (!player->mo->isAbove(player->mo->Sector->floorplane.ZatPoint(player->mo)) || - player->mo->waterlevel) - { - // Player must be touching the floor - P_PlayerOnSpecialFlat(player, P_GetThingFloorType(player->mo)); - } if (player->mo->Vel.Z <= -player->mo->FloatVar(NAME_FallingScreamMinSpeed) && player->mo->Vel.Z >= -player->mo->FloatVar(NAME_FallingScreamMaxSpeed) && player->mo->alternative == nullptr && player->mo->waterlevel == 0) diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index dc7fcacc3..3d6bfb4fd 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -351,7 +351,9 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG(MF9, SHADOWBLOCK, AActor, flags9), DEFINE_FLAG(MF9, SHADOWAIMVERT, AActor, flags9), DEFINE_FLAG(MF9, DECOUPLEDANIMATIONS, AActor, flags9), + DEFINE_FLAG(MF9, NOSECTORDAMAGE, AActor, flags9), DEFINE_PROTECTED_FLAG(MF9, ISPUFF, AActor, flags9), //[AA] was spawned by SpawnPuff + DEFINE_FLAG(MF9, FORCESECTORDAMAGE, AActor, flags9), // Effect flags DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects), diff --git a/wadsrc/static/zscript/mapdata.zs b/wadsrc/static/zscript/mapdata.zs index 5d45563eb..06a7bf3ea 100644 --- a/wadsrc/static/zscript/mapdata.zs +++ b/wadsrc/static/zscript/mapdata.zs @@ -435,6 +435,11 @@ struct Sector native play SECMF_UNDERWATERMASK = 32+64, SECMF_DRAWN = 128, // sector has been drawn at least once SECMF_HIDDEN = 256, // Do not draw on textured automap + SECMF_OVERLAPPING = 512, // floor and ceiling overlap and require special renderer action. + SECMF_NOSKYWALLS = 1024, // Do not draw "sky walls" + SECMF_LIFT = 2048, // For MBF monster AI + SECMF_HURTMONSTERS = 4096, // Monsters in this sector are hurt like players. + SECMF_HARMINAIR = 8192, // Actors in this sector are also hurt mid-air. } native uint16 MoreFlags; @@ -452,6 +457,9 @@ struct Sector native play SECF_ENDLEVEL = 512, // ends level when health goes below 10 SECF_HAZARD = 1024, // Change to Strife's delayed damage handling. SECF_NOATTACK = 2048, // monsters cannot start attacks in this sector. + SECF_EXIT1 = 4096, + SECF_EXIT2 = 8192, + SECF_KILLMONSTERS = 16384,// Monsters in this sector are instantly killed. SECF_WASSECRET = 1 << 30, // a secret that was discovered SECF_SECRET = 1 << 31, // a secret sector From 40546420b0d93f2e4c72c59d4efd865d7ecc0838 Mon Sep 17 00:00:00 2001 From: Professor Hastig Date: Mon, 21 Oct 2024 10:27:35 +0200 Subject: [PATCH 31/60] fixed UMAPINFO's label field to allow 'clear' as argument. --- src/gamedata/umapinfo.cpp | 18 ++++++++++++++++-- src/scripting/vmthunks.cpp | 3 ++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/gamedata/umapinfo.cpp b/src/gamedata/umapinfo.cpp index 9ba72e61b..d574bdcb9 100644 --- a/src/gamedata/umapinfo.cpp +++ b/src/gamedata/umapinfo.cpp @@ -148,8 +148,22 @@ static int ParseStandardProperty(FScanner &scanner, UMapEntry *mape, int *id24_l } else if (!pname.CompareNoCase("label")) { - scanner.MustGetToken(TK_StringConst); - mape->label = scanner.String; + if (scanner.CheckToken(TK_Identifier)) + { + if (!stricmp(scanner.String, "clear")) + { + mape->label = "*"; + } + else + { + scanner.ScriptError("Either 'clear' or string constant expected"); + } + } + else + { + scanner.MustGetToken(TK_StringConst); + mape->label = scanner.String; + } } else if (!pname.CompareNoCase("next")) { diff --git a/src/scripting/vmthunks.cpp b/src/scripting/vmthunks.cpp index 3153a4eab..a0e1b22a1 100644 --- a/src/scripting/vmthunks.cpp +++ b/src/scripting/vmthunks.cpp @@ -2266,7 +2266,8 @@ void FormatMapName(FLevelLocals *self, int cr, FString *result) // If a label is specified, use it uncontitionally here. if (self->info->MapLabel.IsNotEmpty()) { - *result << self->info->MapLabel << ": "; + if (self->info->MapLabel.Compare("*")) + *result << self->info->MapLabel << ": "; } else if (am_showmaplabel == 1 || (am_showmaplabel == 2 && !ishub)) { From 3a88281c10e9f81b70c33e704a4689d021643b6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Sun, 20 Oct 2024 18:57:00 -0300 Subject: [PATCH 32/60] time footsteps with duration of movement, not with actor age --- wadsrc/static/zscript/actors/player/player.zs | 58 ++++++++++++------- 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/wadsrc/static/zscript/actors/player/player.zs b/wadsrc/static/zscript/actors/player/player.zs index bba3d668c..c7da5e634 100644 --- a/wadsrc/static/zscript/actors/player/player.zs +++ b/wadsrc/static/zscript/actors/player/player.zs @@ -1728,39 +1728,55 @@ class PlayerPawn : Actor // //--------------------------------------------------------------------------- + int footstepCounter; + virtual void MakeFootsteps() { - if (pos.z > floorz) return; + if(pos.z > floorz) return; let Ground = GetFloorTerrain(); - let cmd = player.cmd; - if (Ground && (cmd.forwardMove != 0 || cmd.sideMove != 0)) + if(Ground && (player.cmd.forwardMove != 0 || player.cmd.sideMove != 0)) { - bool Running = (cmd.buttons & BT_RUN); //Holding down run key, or it's toggled. - int Delay = !Running ? Ground.WalkStepTics : Ground.RunStepTics; + int Delay = (player.cmd.buttons & BT_RUN) ? Ground.RunStepTics : Ground.WalkStepTics; - if (Delay <= 0 || GetAge() % Delay != 0) return; + if((player.cmd.buttons ^ player.oldbuttons) & BT_RUN) footstepCounter = 0; // zero out counter when starting/stopping a run - Sound Step = Ground.StepSound; - - //Generic foot-agnostic sound takes precedence. - if (!Step) + if(Delay > 0 && (footstepCounter % Delay == 0)) { - //Apparently most people walk with their right foot first, so assume that here. - if (GetAge() % (Delay*2) == 0) - Step = Ground.LeftStepSound; - else - Step = Ground.RightStepSound; + Sound Step = Ground.StepSound; + + //Generic foot-agnostic sound takes precedence. + if(!Step) + { + //Apparently most people walk with their right foot first, so assume that here. + if (footstepCounter == 0) + { + Step = Ground.LeftStepSound; + } + else + { + Step = Ground.RightStepSound; + } + } + + if(Step) + { + A_StartSound(Step, flags: CHANF_OVERLAP, volume: Ground.StepVolume); + } + + //Steps make splashes regardless. + bool Heavy = (Mass >= 200) ? 0 : THW_SMALL; //Big player makes big splash. + HitWater(CurSector, (Pos.XY, CurSector.FloorPlane.ZatPoint(Pos.XY)), true, false, flags: Heavy | THW_NOVEL); } - if (Step) - A_StartSound (Step,flags:CHANF_OVERLAP,volume:Ground.StepVolume); - - //Steps make splashes regardless. - bool Heavy = Mass >= 200 ? 0 : THW_SMALL; //Big player makes big splash. - HitWater (CurSector,(Pos.XY,CurSector.FloorPlane.ZatPoint(Pos.XY)),True,False,flags:Heavy|THW_NOVEL); + footstepCounter = (footstepCounter + 1) % (Delay * 2); } + else + { + footstepCounter = 0; + } + } //--------------------------------------------------------------------------- From 7b59642844080da8eb3a77ab63b16e5fa69b3644 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Sun, 20 Oct 2024 21:42:17 -0300 Subject: [PATCH 33/60] make sure WalkStepTics and RunStepTics read ints, not floats --- src/gamedata/p_terrain.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/gamedata/p_terrain.cpp b/src/gamedata/p_terrain.cpp index 7aa3f8a4f..dfdb6e801 100644 --- a/src/gamedata/p_terrain.cpp +++ b/src/gamedata/p_terrain.cpp @@ -96,7 +96,6 @@ enum EGenericType GEN_Splash, GEN_Float, GEN_Double, - GEN_Time, GEN_Bool, GEN_Int, GEN_Custom, @@ -217,8 +216,8 @@ static FGenericParse TerrainParser[] = { GEN_Int, {myoffsetof(FTerrainDef, DamageTimeMask)} }, { GEN_Double, {myoffsetof(FTerrainDef, FootClip)} }, { GEN_Float, {myoffsetof(FTerrainDef, StepVolume)} }, - { GEN_Time, {myoffsetof(FTerrainDef, WalkStepTics)} }, - { GEN_Time, {myoffsetof(FTerrainDef, RunStepTics)} }, + { GEN_Int, {myoffsetof(FTerrainDef, WalkStepTics)} }, + { GEN_Int, {myoffsetof(FTerrainDef, RunStepTics)} }, { GEN_Sound, {myoffsetof(FTerrainDef, LeftStepSound)} }, { GEN_Sound, {myoffsetof(FTerrainDef, RightStepSound)} }, { GEN_Bool, {myoffsetof(FTerrainDef, IsLiquid)} }, @@ -600,11 +599,6 @@ static void GenericParse (FScanner &sc, FGenericParse *parser, const char **keyw SET_FIELD(double, sc.Float); break; - case GEN_Time: - sc.MustGetFloat (); - SET_FIELD (int, (int)(sc.Float)); - break; - case GEN_Bool: SET_FIELD (bool, true); break; From d07d08ce9f280954880cce0610a9728370931847 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Sun, 20 Oct 2024 22:16:46 -0300 Subject: [PATCH 34/60] Add velocity/distance based footsteps --- src/gamedata/p_terrain.cpp | 8 +- src/gamedata/p_terrain.h | 2 + wadsrc/static/zscript/actors/player/player.zs | 100 +++++++++++++----- wadsrc/static/zscript/doombase.zs | 2 + 4 files changed, 82 insertions(+), 30 deletions(-) diff --git a/src/gamedata/p_terrain.cpp b/src/gamedata/p_terrain.cpp index dfdb6e801..0bb11237f 100644 --- a/src/gamedata/p_terrain.cpp +++ b/src/gamedata/p_terrain.cpp @@ -188,6 +188,8 @@ static const char *TerrainKeywords[] = "allowprotection", "damageonland", "stepsounds", + "stepdistance", + "stepdistanceminvel", NULL }; @@ -225,6 +227,8 @@ static FGenericParse TerrainParser[] = { GEN_Bool, {myoffsetof(FTerrainDef, AllowProtection)} }, { GEN_Bool, {myoffsetof(FTerrainDef, DamageOnLand)} }, { GEN_Sound, {myoffsetof(FTerrainDef, StepSound)} }, + { GEN_Double, {myoffsetof(FTerrainDef, StepDistance)} }, + { GEN_Double, {myoffsetof(FTerrainDef, StepDistanceMinVel)} }, }; @@ -744,4 +748,6 @@ DEFINE_FIELD(FTerrainDef, AllowProtection) DEFINE_FIELD(FTerrainDef, DamageOnLand) DEFINE_FIELD(FTerrainDef, Friction) DEFINE_FIELD(FTerrainDef, MoveFactor) -DEFINE_FIELD(FTerrainDef, StepSound) \ No newline at end of file +DEFINE_FIELD(FTerrainDef, StepSound) +DEFINE_FIELD(FTerrainDef, StepDistance) +DEFINE_FIELD(FTerrainDef, StepDistanceMinVel) \ No newline at end of file diff --git a/src/gamedata/p_terrain.h b/src/gamedata/p_terrain.h index c581ca3fd..6890a38cf 100644 --- a/src/gamedata/p_terrain.h +++ b/src/gamedata/p_terrain.h @@ -119,6 +119,8 @@ struct FTerrainDef double Friction; double MoveFactor; FSoundID StepSound; + double StepDistance; + double StepDistanceMinVel; }; extern TArray Splashes; diff --git a/wadsrc/static/zscript/actors/player/player.zs b/wadsrc/static/zscript/actors/player/player.zs index c7da5e634..746ad806a 100644 --- a/wadsrc/static/zscript/actors/player/player.zs +++ b/wadsrc/static/zscript/actors/player/player.zs @@ -1729,6 +1729,38 @@ class PlayerPawn : Actor //--------------------------------------------------------------------------- int footstepCounter; + double footstepLength; + bool footstepFoot; + + void DoFootstep(TerrainDef Ground) + { + Sound Step = Ground.StepSound; + + //Generic foot-agnostic sound takes precedence. + if(!Step) + { + //Apparently most people walk with their right foot first, so assume that here. + if (!footstepFoot) + { + Step = Ground.LeftStepSound; + } + else + { + Step = Ground.RightStepSound; + } + + footstepFoot = !footstepFoot; + } + + if(Step) + { + A_StartSound(Step, flags: CHANF_OVERLAP, volume: Ground.StepVolume); + } + + //Steps make splashes regardless. + bool Heavy = (Mass >= 200) ? 0 : THW_SMALL; //Big player makes big splash. + HitWater(CurSector, (Pos.XY, CurSector.FloorPlane.ZatPoint(Pos.XY)), true, false, flags: Heavy | THW_NOVEL); + } virtual void MakeFootsteps() { @@ -1740,41 +1772,51 @@ class PlayerPawn : Actor { int Delay = (player.cmd.buttons & BT_RUN) ? Ground.RunStepTics : Ground.WalkStepTics; - if((player.cmd.buttons ^ player.oldbuttons) & BT_RUN) footstepCounter = 0; // zero out counter when starting/stopping a run - - if(Delay > 0 && (footstepCounter % Delay == 0)) - { - Sound Step = Ground.StepSound; - - //Generic foot-agnostic sound takes precedence. - if(!Step) - { - //Apparently most people walk with their right foot first, so assume that here. - if (footstepCounter == 0) - { - Step = Ground.LeftStepSound; - } - else - { - Step = Ground.RightStepSound; - } - } - - if(Step) - { - A_StartSound(Step, flags: CHANF_OVERLAP, volume: Ground.StepVolume); - } - - //Steps make splashes regardless. - bool Heavy = (Mass >= 200) ? 0 : THW_SMALL; //Big player makes big splash. - HitWater(CurSector, (Pos.XY, CurSector.FloorPlane.ZatPoint(Pos.XY)), true, false, flags: Heavy | THW_NOVEL); + if((player.cmd.buttons ^ player.oldbuttons) & BT_RUN) + { // zero out counters when starting/stopping a run + footstepCounter = 0; + footstepLength = Ground.StepDistance; } - footstepCounter = (footstepCounter + 1) % (Delay * 2); + if(Ground.StepDistance > 0) + { // distance-based terrain + footstepCounter = 0; + + double moveVel = vel.xy.length(); + + if(moveVel > Ground.StepDistanceMinVel) + { + footstepLength += moveVel; + + while(footstepLength > Ground.StepDistance) + { + footstepLength -= Ground.StepDistance; + DoFootstep(Ground); + } + } + else + { + footstepLength = Ground.StepDistance; + } + + } + else if(Delay > 0) + { // delay-based terrain + footstepLength = 0; + + if(footstepCounter % Delay == 0) + { + DoFootstep(Ground); + } + + footstepCounter = (footstepCounter + 1) % Delay; + } } else { footstepCounter = 0; + footstepLength = Ground.StepDistance; + footstepFoot = false; } } diff --git a/wadsrc/static/zscript/doombase.zs b/wadsrc/static/zscript/doombase.zs index 2d88d01d0..7751e76cf 100644 --- a/wadsrc/static/zscript/doombase.zs +++ b/wadsrc/static/zscript/doombase.zs @@ -614,6 +614,8 @@ struct TerrainDef native native double Friction; native double MoveFactor; native Sound StepSound; + native double StepDistance; + native double StepDistanceMinVel; }; enum EPickStart From d0e6bce4e675464cadd8c56471358caeebb97a49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Sun, 20 Oct 2024 22:17:16 -0300 Subject: [PATCH 35/60] add CVar to control footstep volume --- src/common/audio/sound/i_sound.cpp | 3 +++ wadsrc/static/zscript/actors/player/player.zs | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/common/audio/sound/i_sound.cpp b/src/common/audio/sound/i_sound.cpp index dda757e8d..4ca119b0b 100644 --- a/src/common/audio/sound/i_sound.cpp +++ b/src/common/audio/sound/i_sound.cpp @@ -62,6 +62,9 @@ CUSTOM_CVAR(Int, snd_samplerate, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CVAR(Int, snd_buffersize, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CVAR(Int, snd_hrtf, -1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +CVAR(Float, snd_footstepvolume, 1.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) + + #if !defined(NO_OPENAL) #define DEF_BACKEND "openal" #else diff --git a/wadsrc/static/zscript/actors/player/player.zs b/wadsrc/static/zscript/actors/player/player.zs index 746ad806a..b320b6253 100644 --- a/wadsrc/static/zscript/actors/player/player.zs +++ b/wadsrc/static/zscript/actors/player/player.zs @@ -1754,7 +1754,7 @@ class PlayerPawn : Actor if(Step) { - A_StartSound(Step, flags: CHANF_OVERLAP, volume: Ground.StepVolume); + A_StartSound(Step, flags: CHANF_OVERLAP, volume: Ground.StepVolume * snd_footstepvolume); } //Steps make splashes regardless. From 6ed8aa6d695ad63028f5b1bc2d28697c30de8722 Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Mon, 21 Oct 2024 21:33:22 -0500 Subject: [PATCH 36/60] Removed debug line --- src/playsim/p_spec.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/playsim/p_spec.cpp b/src/playsim/p_spec.cpp index c78dd1145..3851bd748 100644 --- a/src/playsim/p_spec.cpp +++ b/src/playsim/p_spec.cpp @@ -429,7 +429,6 @@ void P_ActorInSpecialSector (AActor *victim, sector_t * sector, F3DFloor* Ffloor 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) From a0b0db6f648e6b79c7b03ad86dbf51374de3bc87 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Tue, 22 Oct 2024 00:50:13 -0400 Subject: [PATCH 37/60] - change order for Kex edition wads to appear last since they were most recent --- wadsrc_extra/static/iwadinfo.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wadsrc_extra/static/iwadinfo.txt b/wadsrc_extra/static/iwadinfo.txt index 985df8b5d..98cf868f6 100644 --- a/wadsrc_extra/static/iwadinfo.txt +++ b/wadsrc_extra/static/iwadinfo.txt @@ -709,15 +709,15 @@ Order // Order in the IWAD selection box "DOOM 2: L'Enfer sur Terre" "DOOM 2: BFG Edition" "DOOM 2: XBox Edition" - "DOOM 2: KEX Edition" "DOOM 2: Unity Edition" + "DOOM 2: KEX Edition" "The Ultimate DOOM" "DOOM Registered" "DOOM Shareware" "DOOM: BFG Edition" "DOOM: XBox Edition" - "DOOM: KEX Edition" "DOOM: Unity Edition" + "DOOM: KEX Edition" "Final Doom: Plutonia Experiment" "Final Doom: Plutonia Experiment: Unity Edition" "Final Doom: Plutonia Experiment: KEX Edition" From 8e16822ef9814f2d157851cfebce3cc7191544df Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Tue, 22 Oct 2024 18:05:06 -0400 Subject: [PATCH 38/60] - error out if destroying a canvas object --- src/common/2d/v_2ddrawer.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/common/2d/v_2ddrawer.h b/src/common/2d/v_2ddrawer.h index c2be564dc..200510aa1 100644 --- a/src/common/2d/v_2ddrawer.h +++ b/src/common/2d/v_2ddrawer.h @@ -8,6 +8,7 @@ #include "renderstyle.h" #include "dobject.h" #include "refcounted.h" +#include "printf.h" struct DrawParms; struct FColormap; @@ -279,6 +280,7 @@ public: class FCanvas : public DObject { DECLARE_CLASS(FCanvas, DObject) + void OnDestroy() override { I_Error("Calling Destroy on a canvas object is not allowed."); } public: F2DDrawer Drawer; FCanvasTexture* Tex = nullptr; From 59dab4438037cb9acbe43ce2b4b9d19c88727764 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Wed, 23 Oct 2024 22:58:33 -0300 Subject: [PATCH 39/60] Clarify default value for useowncolors --- specs/udmf_zdoom.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/specs/udmf_zdoom.txt b/specs/udmf_zdoom.txt index 9e4df5472..575b881ed 100644 --- a/specs/udmf_zdoom.txt +++ b/specs/udmf_zdoom.txt @@ -203,21 +203,21 @@ Note: All fields default to false unless mentioned otherwise. nogradient_top = ; // disables color gradient on upper tier. (Hardware rendering only.) flipgradient_top = ; // flips gradient colors on upper tier. (Hardware rendering only.) clampgradient_top = ; // clamps gradient on upper tier to actual bounds (default is the entire front sector height, hardware rendering only.) - useowncolors_top = ; // Set to 1 to use the colors set in the sidedef. Default is using the colors from the owning sector. + useowncolors_top = ; // Set to 1 to use the colors set in the sidedef. Default is true if uppercolor or lowercolor are set, otherwise it's false uppercolor_top = ; // Material color of the top of the upper tier. lowercolor_top = ; // Material color of the bottom of the upper tier. (Hardware rendering only.) nogradient_mid = ; // disables color gradient on middle tier. (Hardware rendering only.) flipgradient_mid = ; // flips gradient colors on middle tier. (Hardware rendering only.) clampgradient_mid = ; // clamps gradient on middle tier to actual bounds (default is the entire front sector height, hardware rendering only.) - useowncolors_mid = ; // Set to 1 to use the colors set in the sidedef. Default is using the colors from the owning sector. + useowncolors_mid = ; // Set to 1 to use the colors set in the sidedef. Default is true if uppercolor or lowercolor are set, otherwise it's false uppercolor_mid = ; // Material color of the top of the middle tier. lowercolor_mid = ; // Material color of the bottom of the middle tier. (Hardware rendering only.) nogradient_bottom = ; // disables color gradient on lower tier. (Hardware rendering only.) flipgradient_bottom = ; // flips gradient colors on lower tier. (Hardware rendering only.) clampgradient_bottom = ;// clamps gradient on lower tier to actual bounds (default is the entire front sector height, hardware rendering only.) - useowncolors_bottom = ; // Set to 1 to use the colors set in the sidedef. Default is using the colors from the owning sector. + useowncolors_bottom = ; // Set to 1 to use the colors set in the sidedef. Default is true if uppercolor or lowercolor are set, otherwise it's false uppercolor_bottom = ; // Material color of the top of the lower tier. lowercolor_bottom = ; // Material color of the bottom of the lower tier. (Hardware rendering only.) From ee6991e6d899f0023ee3437c8922d03854ccc523 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 25 Oct 2024 07:54:49 +0200 Subject: [PATCH 40/60] Do a check if a local variable exceeds the available stack space. Windows stack is 1 MB so play it safe and allow 512 kb as max. stack space for a single function. --- src/common/scripting/backend/codegen.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/common/scripting/backend/codegen.cpp b/src/common/scripting/backend/codegen.cpp index b14fb267c..df1c48c22 100644 --- a/src/common/scripting/backend/codegen.cpp +++ b/src/common/scripting/backend/codegen.cpp @@ -12640,6 +12640,15 @@ FxExpression *FxLocalVariableDeclaration::Resolve(FCompileContext &ctx) if (ValueType->RegType == REGT_NIL && ValueType != TypeAuto) { auto sfunc = static_cast(ctx.Function->Variants[0].Implementation); + + const unsigned MAX_STACK_ALLOC = 512 * 1024; // Windows stack is 1 MB, but we cannot go up there without problems + if (uint64_t(ValueType->Size) + uint64_t(sfunc->ExtraSpace) > MAX_STACK_ALLOC) + { + ScriptPosition.Message(MSG_ERROR, "%s exceeds max. allowed size of 512kb for local variables at variable %s", sfunc->Name.GetChars(), Name.GetChars()); + delete this; + return nullptr; + } + StackOffset = sfunc->AllocExtraStack(ValueType); if (Init != nullptr) From a14bba3561e59fff86e4a3a04c829c6bbdeb189a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 25 Oct 2024 08:47:19 +0200 Subject: [PATCH 41/60] Check array size for overflow. Since ZScript is a 32 bit VM, the largest safe value for an array's physical size is 2GB. Any larger value will be destroyed by the compiler which relies on signed 32 bit values too much. --- src/common/scripting/frontend/zcc_compile.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/common/scripting/frontend/zcc_compile.cpp b/src/common/scripting/frontend/zcc_compile.cpp index d109717a3..faef50959 100644 --- a/src/common/scripting/frontend/zcc_compile.cpp +++ b/src/common/scripting/frontend/zcc_compile.cpp @@ -2286,6 +2286,11 @@ PType *ZCCCompiler::ResolveArraySize(PType *baseType, ZCC_Expression *arraysize, Error(arraysize, "Array size must be positive"); return TypeError; } + if (uint64_t(size) * baseType->Size > 0x7fffffff) + { + Error(arraysize, "Array size overflow. Total size must be less than 2GB"); + return TypeError; + } baseType = NewArray(baseType, size); } From fe28defeca2ded10882d10df016dce28fd70bad3 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Fri, 25 Oct 2024 19:14:58 -0400 Subject: [PATCH 42/60] - cap the size of the string copy calls in LevelStatEntry() --- src/gamedata/statistics.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/gamedata/statistics.cpp b/src/gamedata/statistics.cpp index 95d8165ae..d374f2e8a 100644 --- a/src/gamedata/statistics.cpp +++ b/src/gamedata/statistics.cpp @@ -343,8 +343,12 @@ static void LevelStatEntry(FSessionStatistics *es, const char *level, const char time (&clock); lt = localtime (&clock); - strcpy(s.name, level); - strcpy(s.info, text); + strncpy(s.name, level, sizeof(s.name) - 1); + s.name[sizeof(s.name) - 1] = '\0'; + + strncpy(s.info, text, sizeof(s.info) - 1); + s.info[sizeof(s.info) - 1] = '\0'; + s.timeneeded=playtime; es->levelstats.Push(s); } From 275635adc56aba67d6d0230a9ae0b51585cf65aa Mon Sep 17 00:00:00 2001 From: Kaelan Date: Tue, 15 Oct 2024 18:51:05 -0600 Subject: [PATCH 43/60] add set/get plane reflectivity --- src/gamedata/r_defs.h | 10 ++++++++++ src/scripting/vmthunks.cpp | 26 ++++++++++++++++++++++++++ wadsrc/static/zscript/mapdata.zs | 2 ++ 3 files changed, 38 insertions(+) diff --git a/src/gamedata/r_defs.h b/src/gamedata/r_defs.h index d6453b6f8..bf0f6be4b 100644 --- a/src/gamedata/r_defs.h +++ b/src/gamedata/r_defs.h @@ -1029,6 +1029,16 @@ public: return pos == floor? floorplane:ceilingplane; } + void SetPlaneReflectivity(int pos, double val) + { + reflect[pos] = val; + } + + double GetPlaneReflectivity(int pos) + { + return reflect[pos]; + } + bool isSecret() const { return !!(Flags & SECF_SECRET); diff --git a/src/scripting/vmthunks.cpp b/src/scripting/vmthunks.cpp index a0e1b22a1..b8241fc11 100644 --- a/src/scripting/vmthunks.cpp +++ b/src/scripting/vmthunks.cpp @@ -869,6 +869,32 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Sector, SetXOffset, SetXOffset) ACTION_RETURN_INT(self->GetLightLevel()); } + static void SetPlaneReflectivity(sector_t* self, int pos, double val) + { + self->SetPlaneReflectivity(pos, val); + } + + DEFINE_ACTION_FUNCTION_NATIVE(_Sector, SetPlaneReflectivity, SetPlaneReflectivity) + { + PARAM_SELF_STRUCT_PROLOGUE(sector_t); + PARAM_INT(pos); + PARAM_FLOAT(val) + self->SetPlaneReflectivity(pos, val); + return 0; + } + + static double GetPlaneReflectivity(sector_t* self, int pos) + { + return self->GetPlaneReflectivity(pos); + } + + DEFINE_ACTION_FUNCTION_NATIVE(_Sector, GetPlaneReflectivity, GetPlaneReflectivity) + { + PARAM_SELF_STRUCT_PROLOGUE(sector_t); + PARAM_INT(pos); + ACTION_RETURN_FLOAT(self->GetPlaneReflectivity(pos)); + } + static int PortalBlocksView(sector_t *self, int pos) { return self->PortalBlocksView(pos); diff --git a/wadsrc/static/zscript/mapdata.zs b/wadsrc/static/zscript/mapdata.zs index 06a7bf3ea..9031b3158 100644 --- a/wadsrc/static/zscript/mapdata.zs +++ b/wadsrc/static/zscript/mapdata.zs @@ -553,6 +553,8 @@ struct Sector native play native void ChangeLightLevel(int newval); native void SetLightLevel(int newval); native clearscope int GetLightLevel() const; + native void SetPlaneReflectivity(int pos, double val); + native clearscope double GetPlaneReflectivity(int pos); native void AdjustFloorClip(); native clearscope bool IsLinked(Sector other, bool ceiling) const; From 4b3273b2292be5d2b2c795a9196a5ddd83958406 Mon Sep 17 00:00:00 2001 From: Kaelan Date: Tue, 15 Oct 2024 19:37:16 -0600 Subject: [PATCH 44/60] Add bounds check --- src/gamedata/r_defs.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gamedata/r_defs.h b/src/gamedata/r_defs.h index bf0f6be4b..e940d80ab 100644 --- a/src/gamedata/r_defs.h +++ b/src/gamedata/r_defs.h @@ -40,6 +40,7 @@ #include "r_sky.h" #include "p_terrain.h" #include "p_effect.h" +#include "vm.h" #include "hwrenderer/data/buffers.h" @@ -1031,11 +1032,13 @@ public: void SetPlaneReflectivity(int pos, double val) { + if (pos < 0 || pos > 1) ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "pos must be either 0 or 1"); reflect[pos] = val; } double GetPlaneReflectivity(int pos) { + if (pos < 0 || pos > 1) ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "pos must be either 0 or 1"); return reflect[pos]; } From d9fa7c38946d18a9573ae5d1658d220e83db7cf3 Mon Sep 17 00:00:00 2001 From: Kaelan Date: Wed, 16 Oct 2024 16:31:40 -0600 Subject: [PATCH 45/60] Re-move bounds checks out of core engine per request --- src/gamedata/r_defs.h | 3 --- src/scripting/vmthunks.cpp | 2 ++ 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/gamedata/r_defs.h b/src/gamedata/r_defs.h index e940d80ab..bf0f6be4b 100644 --- a/src/gamedata/r_defs.h +++ b/src/gamedata/r_defs.h @@ -40,7 +40,6 @@ #include "r_sky.h" #include "p_terrain.h" #include "p_effect.h" -#include "vm.h" #include "hwrenderer/data/buffers.h" @@ -1032,13 +1031,11 @@ public: void SetPlaneReflectivity(int pos, double val) { - if (pos < 0 || pos > 1) ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "pos must be either 0 or 1"); reflect[pos] = val; } double GetPlaneReflectivity(int pos) { - if (pos < 0 || pos > 1) ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "pos must be either 0 or 1"); return reflect[pos]; } diff --git a/src/scripting/vmthunks.cpp b/src/scripting/vmthunks.cpp index b8241fc11..0c738a424 100644 --- a/src/scripting/vmthunks.cpp +++ b/src/scripting/vmthunks.cpp @@ -871,6 +871,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Sector, SetXOffset, SetXOffset) static void SetPlaneReflectivity(sector_t* self, int pos, double val) { + if (pos < 0 || pos > 1) ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "pos must be either 0 or 1"); self->SetPlaneReflectivity(pos, val); } @@ -885,6 +886,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Sector, SetXOffset, SetXOffset) static double GetPlaneReflectivity(sector_t* self, int pos) { + if (pos < 0 || pos > 1) ThrowAbortException(X_ARRAY_OUT_OF_BOUNDS, "pos must be either 0 or 1"); return self->GetPlaneReflectivity(pos); } From 8b733323660d1fad4125fdcea031087498ef7cd7 Mon Sep 17 00:00:00 2001 From: Kaelan Date: Wed, 16 Oct 2024 16:41:44 -0600 Subject: [PATCH 46/60] Proper static function use --- src/scripting/vmthunks.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/scripting/vmthunks.cpp b/src/scripting/vmthunks.cpp index 0c738a424..856098469 100644 --- a/src/scripting/vmthunks.cpp +++ b/src/scripting/vmthunks.cpp @@ -880,7 +880,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Sector, SetXOffset, SetXOffset) PARAM_SELF_STRUCT_PROLOGUE(sector_t); PARAM_INT(pos); PARAM_FLOAT(val) - self->SetPlaneReflectivity(pos, val); + SetPlaneReflectivity(self, pos, val); return 0; } @@ -894,7 +894,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(_Sector, SetXOffset, SetXOffset) { PARAM_SELF_STRUCT_PROLOGUE(sector_t); PARAM_INT(pos); - ACTION_RETURN_FLOAT(self->GetPlaneReflectivity(pos)); + ACTION_RETURN_FLOAT(GetPlaneReflectivity(self, pos)); } static int PortalBlocksView(sector_t *self, int pos) From 2ba57b50680da2331975cedbe366d687eb16922a Mon Sep 17 00:00:00 2001 From: "Dileep V. Reddy" Date: Sat, 26 Oct 2024 08:22:43 -0600 Subject: [PATCH 47/60] Reduce number of multiply ops per frame and increase x-axis clipper range for orthographic projection. --- src/rendering/hwrenderer/scene/hw_clipper.cpp | 4 ++-- src/rendering/r_utility.cpp | 4 ++++ src/rendering/r_utility.h | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/rendering/hwrenderer/scene/hw_clipper.cpp b/src/rendering/hwrenderer/scene/hw_clipper.cpp index cef7b06b1..059a39981 100644 --- a/src/rendering/hwrenderer/scene/hw_clipper.cpp +++ b/src/rendering/hwrenderer/scene/hw_clipper.cpp @@ -476,8 +476,8 @@ angle_t Clipper::PointToPseudoOrthoAngle(double x, double y) { angle_t af = viewpoint->FrustAngle; double xproj = disp.XY().Length() * deltaangle(disp.Angle(), viewpoint->Angles.Yaw).Sin(); - xproj *= viewpoint->ScreenProj; - if (fabs(xproj) < r_viewwindow.WidescreenRatio*1.13) // 2.0) + xproj *= viewpoint->ScreenProjX; + if (fabs(xproj) < 1.13) { return AngleToPseudo( viewpoint->Angles.Yaw.BAMs() - xproj * 0.5 * af ); } diff --git a/src/rendering/r_utility.cpp b/src/rendering/r_utility.cpp index b7b6b452b..5313f738c 100644 --- a/src/rendering/r_utility.cpp +++ b/src/rendering/r_utility.cpp @@ -167,6 +167,7 @@ FRenderViewpoint::FRenderViewpoint() sector = nullptr; FieldOfView = DAngle::fromDeg(90.); // Angles in the SCREENWIDTH wide window ScreenProj = 0.0; + ScreenProjX = 0.0; TicFrac = 0.0; FrameTime = 0; extralight = 0; @@ -704,7 +705,10 @@ void FRenderViewpoint::SetViewAngle(const FViewWindow& viewWindow) HWAngles.Yaw = FAngle::fromDeg(270.0 - Angles.Yaw.Degrees()); if (IsOrtho() && (camera->ViewPos->Offset.XY().Length() > 0.0)) + { ScreenProj = 1.34396 / camera->ViewPos->Offset.Length() / tan (FieldOfView.Radians()*0.5); // [DVR] Estimated. +/-1 should be top/bottom of screen. + ScreenProjX = ScreenProj * 0.5 / viewWindow.WidescreenRatio; + } } diff --git a/src/rendering/r_utility.h b/src/rendering/r_utility.h index ca6d84b8c..f7e4a1e1d 100644 --- a/src/rendering/r_utility.h +++ b/src/rendering/r_utility.h @@ -43,6 +43,7 @@ struct FRenderViewpoint sector_t *sector; // [RH] keep track of sector viewing from DAngle FieldOfView; // current field of view double ScreenProj; // Screen projection factor for orthographic projection + double ScreenProjX; // Same for X-axis (screenspace) double TicFrac; // fraction of tic for interpolation uint32_t FrameTime; // current frame's time in tics. From 7b95977e2afdb0e8eff514d0406d609a2856b973 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Fri, 25 Oct 2024 21:32:52 -0300 Subject: [PATCH 48/60] Allow using `Self` as the class name in the default block to refer to the current class --- src/scripting/zscript/zcc_compile_doom.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/scripting/zscript/zcc_compile_doom.cpp b/src/scripting/zscript/zcc_compile_doom.cpp index 3563967e5..a86ea9a0e 100644 --- a/src/scripting/zscript/zcc_compile_doom.cpp +++ b/src/scripting/zscript/zcc_compile_doom.cpp @@ -724,8 +724,15 @@ void ZCCDoomCompiler::ProcessDefaultProperty(PClassActor *cls, ZCC_PropertyStmt } else if (namenode->SiblingNext->SiblingNext == namenode) { + FName name(namenode->Id); + + if(name == NAME_self) + { + name = cls->TypeName; + } + // a two-name property - propname << FName(namenode->Id).GetChars() << "." << FName(static_cast(namenode->SiblingNext)->Id).GetChars(); + propname << name.GetChars() << "." << FName(static_cast(namenode->SiblingNext)->Id).GetChars(); } else { @@ -784,6 +791,13 @@ void ZCCDoomCompiler::ProcessDefaultFlag(PClassActor *cls, ZCC_FlagStmt *flg) else if (namenode->SiblingNext->SiblingNext == namenode) { // a two-name flag + + if(namenode->Id == NAME_self) + { + n1 = cls->TypeName.GetChars(); + } + + n2 = FName(static_cast(namenode->SiblingNext)->Id).GetChars(); } else From 9ca5bef4ea2dd0442a1db889ad7d9ed89280262d Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Wed, 30 Oct 2024 16:22:33 -0500 Subject: [PATCH 49/60] Fixed STRETCHPIXELS flag not being exposed. --- src/scripting/thingdef_data.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 3d6bfb4fd..fa8d66674 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -387,6 +387,7 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG(RF2, CAMFOLLOWSPLAYER, AActor, renderflags2), DEFINE_FLAG(RF2, ISOMETRICSPRITES, AActor, renderflags2), DEFINE_FLAG(RF2, SQUAREPIXELS, AActor, renderflags2), + DEFINE_FLAG(RF2, STRETCHPIXELS, AActor, renderflags2), // Bounce flags DEFINE_FLAG2(BOUNCE_Walls, BOUNCEONWALLS, AActor, BounceFlags), From f5ceaafbbc1eea3d5c85389d68ed8c6d50fba9d4 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Wed, 30 Oct 2024 18:59:25 -0400 Subject: [PATCH 50/60] Added net id functions for ACS Includes net id getter and activator setter functionality. Essentially acts as a pseudo pointer system for Actors within ACS. --- src/g_levellocals.h | 17 +++++++++++++++++ src/playsim/p_acs.cpp | 21 +++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/g_levellocals.h b/src/g_levellocals.h index cf63f81b2..86476d1a7 100644 --- a/src/g_levellocals.h +++ b/src/g_levellocals.h @@ -316,6 +316,23 @@ public: { return tid == 0 ? defactor : GetActorIterator(tid).Next(); } + AActor* SelectActorFromTID(int tid, size_t index, AActor *defactor) + { + if (tid == 0) + return defactor; + + AActor* actor = nullptr; + size_t cur = 0u; + auto it = GetActorIterator(tid); + while ((actor = it.Next()) != nullptr) + { + if (cur == index) + return actor; + ++cur; + } + + return nullptr; + } bool SectorHasTags(sector_t *sector) { diff --git a/src/playsim/p_acs.cpp b/src/playsim/p_acs.cpp index d05f5dae3..89aee643d 100644 --- a/src/playsim/p_acs.cpp +++ b/src/playsim/p_acs.cpp @@ -4806,6 +4806,8 @@ enum EACSFunctions ACSF_GetSectorHealth, ACSF_GetLineHealth, ACSF_SetSubtitleNumber, + ACSF_GetNetID, + ACSF_SetActivatorByNetID, // Eternity's ACSF_GetLineX = 300, @@ -5380,6 +5382,13 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args, int & actor = Level->SingleActorFromTID(args[0], activator); return actor != NULL? DoubleToACS(actor->Vel.Z) : 0; + case ACSF_GetNetID: + MIN_ARG_COUNT(2); + actor = Level->SelectActorFromTID(args[0], args[1], activator); + if (argCount > 2) + actor = COPY_AAPTREX(Level, actor, args[2]); + return actor != nullptr ? actor->GetNetworkID() : NetworkEntityManager::WorldNetID; + case ACSF_SetPointer: MIN_ARG_COUNT(2); if (activator) @@ -5431,6 +5440,18 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args, int & } return 0; + case ACSF_SetActivatorByNetID: + MIN_ARG_COUNT(1); + actor = dyn_cast(NetworkEntityManager::GetNetworkEntity(args[0])); + if (argCount > 1) + actor = COPY_AAPTREX(Level, actor, args[1]); + if (actor != nullptr) + { + activator = actor; + return 1; + } + return 0; + case ACSF_GetActorViewHeight: MIN_ARG_COUNT(1); actor = Level->SingleActorFromTID(args[0], activator); From de8d839885da1f792535a9a4ece9c20e9e18707b Mon Sep 17 00:00:00 2001 From: Boondorl Date: Thu, 31 Oct 2024 13:42:52 -0400 Subject: [PATCH 51/60] Moved Actor TID selector out of header --- src/g_level.cpp | 18 ++++++++++++++++++ src/g_levellocals.h | 18 +----------------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/g_level.cpp b/src/g_level.cpp index 1278494b2..d82c68358 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -2400,6 +2400,24 @@ void FLevelLocals::ApplyCompatibility2() i_compatflags2 = GetCompatibility2(compatflags2) | ii_compatflags2; } +AActor* FLevelLocals::SelectActorFromTID(int tid, size_t index, AActor* defactor) +{ + if (tid == 0) + return defactor; + + AActor* actor = nullptr; + size_t cur = 0u; + auto it = GetActorIterator(tid); + while ((actor = it.Next()) != nullptr) + { + if (cur == index) + return actor; + ++cur; + } + + return nullptr; +} + //========================================================================== // IsPointInMap // diff --git a/src/g_levellocals.h b/src/g_levellocals.h index 86476d1a7..bb975e0eb 100644 --- a/src/g_levellocals.h +++ b/src/g_levellocals.h @@ -149,6 +149,7 @@ struct FLevelLocals int GetCompatibility2(int mask); void ApplyCompatibility(); void ApplyCompatibility2(); + AActor* SelectActorFromTID(int tid, size_t index, AActor* defactor); void Init(); @@ -316,23 +317,6 @@ public: { return tid == 0 ? defactor : GetActorIterator(tid).Next(); } - AActor* SelectActorFromTID(int tid, size_t index, AActor *defactor) - { - if (tid == 0) - return defactor; - - AActor* actor = nullptr; - size_t cur = 0u; - auto it = GetActorIterator(tid); - while ((actor = it.Next()) != nullptr) - { - if (cur == index) - return actor; - ++cur; - } - - return nullptr; - } bool SectorHasTags(sector_t *sector) { From 6fc256709c01fc7f08031b1ff14d86ccc24c1695 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 1 Nov 2024 08:46:02 +0100 Subject: [PATCH 52/60] fixed the particle replacement code. OldestParticle was not properly tracked which could result in circular lists. To make maintenance easier, the replacement code and the free particle part were merged into one to only have one place where the linked list is modified. --- src/playsim/p_effect.cpp | 83 ++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 50 deletions(-) diff --git a/src/playsim/p_effect.cpp b/src/playsim/p_effect.cpp index 459d267be..bdceae149 100644 --- a/src/playsim/p_effect.cpp +++ b/src/playsim/p_effect.cpp @@ -106,50 +106,45 @@ static const struct ColorList { {NULL, 0, 0, 0 } }; -inline particle_t *NewParticle (FLevelLocals *Level, bool replace = false) +static void FreeParticle(FLevelLocals* Level, particle_t* particle) { - particle_t *result = nullptr; - // [MC] Thanks to RaveYard and randi for helping me with this addition. - // Array's filled up - if (Level->InactiveParticles == NO_PARTICLE) + auto prev = particle->tprev == NO_PARTICLE? nullptr : &Level->Particles[particle->tprev]; + int pindex = (int)(particle - Level->Particles.Data()); + auto tnext = particle->tnext; + assert(!prev || (prev->tnext == pindex)); + if (prev) + prev->tnext = tnext; + else + Level->ActiveParticles = tnext; + + if (tnext != NO_PARTICLE) { - if (replace) - { - result = &Level->Particles[Level->OldestParticle]; + particle_t* next = &Level->Particles[tnext]; + assert(next->tprev == pindex); + next->tprev = particle->tprev; + } + if (Level->OldestParticle == pindex) + { + assert(tnext == NO_PARTICLE); + Level->OldestParticle = particle->tprev; + } + memset(particle, 0, sizeof(particle_t)); + particle->tnext = Level->InactiveParticles; + Level->InactiveParticles = pindex; +} - // There should be NO_PARTICLE for the oldest's tnext - if (result->tprev != NO_PARTICLE) - { - // tnext: youngest to oldest - // tprev: oldest to youngest - - // 2nd oldest -> oldest - particle_t *nbottom = &Level->Particles[result->tprev]; - nbottom->tnext = NO_PARTICLE; - - // now oldest becomes youngest - Level->OldestParticle = result->tprev; - result->tnext = Level->ActiveParticles; - result->tprev = NO_PARTICLE; - Level->ActiveParticles = uint32_t(result - Level->Particles.Data()); - - // youngest -> 2nd youngest - particle_t* ntop = &Level->Particles[result->tnext]; - ntop->tprev = Level->ActiveParticles; - } - // [MC] Future proof this by resetting everything when replacing a particle. - auto tnext = result->tnext; - auto tprev = result->tprev; - *result = {}; - result->tnext = tnext; - result->tprev = tprev; - } - return result; +static particle_t *NewParticle (FLevelLocals *Level, bool replace = false) +{ + // Array's filled up + if (Level->InactiveParticles == NO_PARTICLE && Level->OldestParticle != NO_PARTICLE) + { + if (!replace) return nullptr; + FreeParticle(Level, &Level->Particles[Level->OldestParticle]); } // Array isn't full. uint32_t current = Level->ActiveParticles; - result = &Level->Particles[Level->InactiveParticles]; + auto result = &Level->Particles[Level->InactiveParticles]; Level->InactiveParticles = result->tnext; result->tnext = current; result->tprev = NO_PARTICLE; @@ -310,19 +305,7 @@ void P_ThinkParticles (FLevelLocals *Level) particle->size += particle->sizestep; if (particle->alpha <= 0 || --particle->ttl <= 0 || (particle->size <= 0)) { // The particle has expired, so free it - *particle = {}; - if (prev) - prev->tnext = i; - else - Level->ActiveParticles = i; - - if (i != NO_PARTICLE) - { - particle_t *next = &Level->Particles[i]; - next->tprev = particle->tprev; - } - particle->tnext = Level->InactiveParticles; - Level->InactiveParticles = (int)(particle - Level->Particles.Data()); + FreeParticle(Level, particle); continue; } From a899571d8c104ac2d267a4544487d73bbd2a9d21 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 2 Nov 2024 09:07:07 +0100 Subject: [PATCH 53/60] got rid of strlwr. The 3 remaining uses were completely redundant. --- src/common/platform/posix/i_system.h | 11 ----------- src/scripting/decorate/thingdef_parse.cpp | 6 ------ src/scripting/decorate/thingdef_states.cpp | 8 +------- 3 files changed, 1 insertion(+), 24 deletions(-) diff --git a/src/common/platform/posix/i_system.h b/src/common/platform/posix/i_system.h index 4d800d53b..5573e26d3 100644 --- a/src/common/platform/posix/i_system.h +++ b/src/common/platform/posix/i_system.h @@ -54,17 +54,6 @@ bool I_WriteIniFailed (const char* filename); class FGameTexture; bool I_SetCursor(FGameTexture *); -static inline char *strlwr(char *str) -{ - char *ptr = str; - while(*ptr) - { - *ptr = tolower(*ptr); - ++ptr; - } - return str; -} - inline int I_GetNumaNodeCount() { return 1; } inline int I_GetNumaNodeThreadCount(int numaNode) { return std::max(std::thread::hardware_concurrency(), 1); } inline void I_SetThreadNumaNode(std::thread &thread, int numaNode) { } diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index 19c8f38ab..03a249814 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -49,9 +49,6 @@ #include "v_text.h" #include "m_argv.h" #include "v_video.h" -#ifndef _MSC_VER -#include "i_system.h" // for strlwr() -#endif // !_MSC_VER void ParseOldDecoration(FScanner &sc, EDefinitionType def, PNamespace *ns); EXTERN_CVAR(Bool, strictdecorate); @@ -945,15 +942,12 @@ static void ParseActorProperty(FScanner &sc, Baggage &bag) "Spawn", "See", "Melee", "Missile", "Pain", "Death", "XDeath", "Burn", "Ice", "Raise", "Crash", "Crush", "Wound", "Disintegrate", "Heal", NULL }; - strlwr (sc.String); - FString propname = sc.String; if (sc.CheckString (".")) { sc.MustGetString (); propname += '.'; - strlwr (sc.String); propname += sc.String; } else diff --git a/src/scripting/decorate/thingdef_states.cpp b/src/scripting/decorate/thingdef_states.cpp index 570905741..d518d6769 100644 --- a/src/scripting/decorate/thingdef_states.cpp +++ b/src/scripting/decorate/thingdef_states.cpp @@ -45,9 +45,6 @@ #include "thingdef.h" #include "codegen.h" #include "backend/codegen_doom.h" -#ifndef _MSC_VER -#include "i_system.h" // for strlwr() -#endif // !_MSC_VER //========================================================================== //*** @@ -562,11 +559,8 @@ FxExpression *ParseActions(FScanner &sc, FState state, FString statestring, Bagg FxExpression* ParseAction(FScanner &sc, FState state, FString statestring, Baggage &bag) { - // Make the action name lowercase - strlwr (sc.String); - FxExpression *call = DoActionSpecials(sc, state, bag); - if (call != NULL) + if (call != nullptr) { return call; } From 714eb8910c2f3360f1997304bb94d469c76f5c49 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Sun, 3 Nov 2024 16:15:41 -0500 Subject: [PATCH 54/60] Reworked player loading Resolves a host of issues related to playing loading, both in singleplayer and multiplayer. Name-based player data selection now works meaning join order no longer has to be preserved. --- src/g_levellocals.h | 4 +- src/p_saveg.cpp | 215 ++++++++++++++++++++------------------------ 2 files changed, 97 insertions(+), 122 deletions(-) diff --git a/src/g_levellocals.h b/src/g_levellocals.h index bb975e0eb..1b6c82d1b 100644 --- a/src/g_levellocals.h +++ b/src/g_levellocals.h @@ -167,8 +167,8 @@ private: void SerializePlayers(FSerializer &arc, bool skipload); void CopyPlayer(player_t *dst, player_t *src, const char *name); - void ReadOnePlayer(FSerializer &arc, bool skipload); - void ReadMultiplePlayers(FSerializer &arc, int numPlayers, int numPlayersNow, bool skipload); + void ReadOnePlayer(FSerializer &arc, bool fromHub); + void ReadMultiplePlayers(FSerializer &arc, int numPlayers, bool fromHub); void SerializeSounds(FSerializer &arc); void PlayerSpawnPickClass (int playernum); diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index 970cc9aa5..3a267c816 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -627,8 +627,8 @@ void FLevelLocals::SerializePlayers(FSerializer &arc, bool skipload) { if (arc.BeginObject(nullptr)) { - const char *n = Players[i]->userinfo.GetName(); - arc.StringPtr("playername", n); + FString name = Players[i]->userinfo.GetName(); + arc("playername", name); Players[i]->Serialize(arc); arc.EndObject(); } @@ -651,7 +651,7 @@ void FLevelLocals::SerializePlayers(FSerializer &arc, bool skipload) } else { - ReadMultiplePlayers(arc, numPlayers, numPlayersNow, skipload); + ReadMultiplePlayers(arc, numPlayers, skipload); } arc.EndArray(); @@ -680,53 +680,41 @@ void FLevelLocals::SerializePlayers(FSerializer &arc, bool skipload) // //========================================================================== -void FLevelLocals::ReadOnePlayer(FSerializer &arc, bool skipload) +void FLevelLocals::ReadOnePlayer(FSerializer &arc, bool fromHub) { - int i; - const char *name = NULL; - bool didIt = false; + if (!arc.BeginObject(nullptr)) + return; - if (arc.BeginObject(nullptr)) + FString name = {}; + arc("playername", name); + player_t temp = {}; + temp.Serialize(arc); + + for (int i = 0; i < MAXPLAYERS; ++i) { - arc.StringPtr("playername", name); + if (!PlayerInGame(i)) + continue; - for (i = 0; i < MAXPLAYERS; ++i) + if (!fromHub) { - if (playeringame[i]) - { - if (!didIt) - { - didIt = true; - player_t playerTemp; - playerTemp.Serialize(arc); - if (!skipload) - { - // This temp player has undefined pitch limits, so set them to something - // that should leave the pitch stored in the savegame intact when - // rendering. The real pitch limits will be set by P_SerializePlayers() - // via a net command, but that won't be processed in time for a screen - // wipe, so we need something here. - playerTemp.MaxPitch = playerTemp.MinPitch = playerTemp.mo->Angles.Pitch; - CopyPlayer(Players[i], &playerTemp, name); - } - else - { - // we need the player actor, so that G_FinishTravel can destroy it later. - Players[i]->mo = playerTemp.mo; - } - } - else - { - if (Players[i]->mo != NULL) - { - Players[i]->mo->Destroy(); - Players[i]->mo = NULL; - } - } - } + // This temp player has undefined pitch limits, so set them to something + // that should leave the pitch stored in the savegame intact when + // rendering. The real pitch limits will be set by P_SerializePlayers() + // via a net command, but that won't be processed in time for a screen + // wipe, so we need something here. + temp.MaxPitch = temp.MinPitch = temp.mo->Angles.Pitch; + CopyPlayer(Players[i], &temp, name.GetChars()); } - arc.EndObject(); + else + { + // we need the player actor, so that G_FinishTravel can destroy it later. + Players[i]->mo = temp.mo; + } + + break; } + + arc.EndObject(); } //========================================================================== @@ -735,109 +723,96 @@ void FLevelLocals::ReadOnePlayer(FSerializer &arc, bool skipload) // //========================================================================== -void FLevelLocals::ReadMultiplePlayers(FSerializer &arc, int numPlayers, int numPlayersNow, bool skipload) +struct NetworkPlayerInfo { - // For two or more players, read each player into a temporary array. - int i, j; - const char **nametemp = new const char *[numPlayers]; - player_t *playertemp = new player_t[numPlayers]; - uint8_t *tempPlayerUsed = new uint8_t[numPlayers]; - uint8_t playerUsed[MAXPLAYERS]; + FString Name = {}; + player_t Info = {}; + bool bUsed = false; +}; - for (i = 0; i < numPlayers; ++i) +void FLevelLocals::ReadMultiplePlayers(FSerializer &arc, int numPlayers, bool fromHub) +{ + TArray tempPlayers = {}; + tempPlayers.Reserve(numPlayers); + TArray assignedPlayers = {}; + assignedPlayers.Reserve(MAXPLAYERS); + + // Read all the save game players into a temporary array + for (auto& p : tempPlayers) { - nametemp[i] = NULL; if (arc.BeginObject(nullptr)) { - arc.StringPtr("playername", nametemp[i]); - playertemp[i].Serialize(arc); + arc("playername", p.Name); + p.Info.Serialize(arc); arc.EndObject(); } - tempPlayerUsed[i] = 0; - } - for (i = 0; i < MAXPLAYERS; ++i) - { - playerUsed[i] = playeringame[i] ? 0 : 2; } - if (!skipload) + // Now try to match players from the savegame with players present + // based on their names. If two players in the savegame have the + // same name, then they are assigned to players in the current game + // on a first-come, first-served basis. + for (int i = 0; i < MAXPLAYERS; ++i) { - // Now try to match players from the savegame with players present - // based on their names. If two players in the savegame have the - // same name, then they are assigned to players in the current game - // on a first-come, first-served basis. - for (i = 0; i < numPlayers; ++i) - { - for (j = 0; j < MAXPLAYERS; ++j) - { - if (playerUsed[j] == 0 && stricmp(players[j].userinfo.GetName(), nametemp[i]) == 0) - { // Found a match, so copy our temp player to the real player - Printf("Found player %d (%s) at %d\n", i, nametemp[i], j); - CopyPlayer(Players[j], &playertemp[i], nametemp[i]); - playerUsed[j] = 1; - tempPlayerUsed[i] = 1; - break; - } - } - } + if (!PlayerInGame(i)) + continue; - // Any players that didn't have matching names are assigned to existing - // players on a first-come, first-served basis. - for (i = 0; i < numPlayers; ++i) + for (auto& p : tempPlayers) { - if (tempPlayerUsed[i] == 0) + if (!p.bUsed && !p.Name.Compare(Players[i]->userinfo.GetName())) { - for (j = 0; j < MAXPLAYERS; ++j) + // Found a match, so copy our temp player to the real player + if (!fromHub) { - if (playerUsed[j] == 0) - { - Printf("Assigned player %d (%s) to %d (%s)\n", i, nametemp[i], j, players[j].userinfo.GetName()); - CopyPlayer(&players[j], &playertemp[i], nametemp[i]); - playerUsed[j] = 1; - tempPlayerUsed[i] = 1; - break; - } + Printf("Found %s's (%d) data\n", Players[i]->userinfo.GetName(), i); + CopyPlayer(Players[i], &p.Info, p.Name.GetChars()); } - } - } - - // Make sure any extra players don't have actors spawned yet. Happens if the players - // present now got the same slots as they had in the save, but there are not as many - // as there were in the save. - for (j = 0; j < MAXPLAYERS; ++j) - { - if (playerUsed[j] == 0) - { - if (players[j].mo != NULL) + else { - players[j].mo->Destroy(); - players[j].mo = NULL; + Players[i]->mo = p.Info.mo; } - } - } - // Remove any temp players that were not used. Happens if there are fewer players - // than there were in the save, and they got shuffled. - for (i = 0; i < numPlayers; ++i) - { - if (tempPlayerUsed[i] == 0) - { - playertemp[i].mo->Destroy(); - playertemp[i].mo = NULL; + p.bUsed = true; + assignedPlayers[i] = true; + break; } } } - else + + // Any players that didn't have matching names are assigned to existing + // players on a first-come, first-served basis. + for (int i = 0; i < MAXPLAYERS; ++i) { - for (i = 0; i < numPlayers; ++i) + if (!PlayerInGame(i) || assignedPlayers[i]) + continue; + + for (auto& p : tempPlayers) { - players[i].mo = playertemp[i].mo; + if (!p.bUsed) + { + if (!fromHub) + { + Printf("Assigned %s (%d) to %s's data\n", Players[i]->userinfo.GetName(), i, p.Name.GetChars()); + CopyPlayer(Players[i], &p.Info, p.Name.GetChars()); + } + else + { + Players[i]->mo = p.Info.mo; + } + + p.bUsed = true; + break; + } } } - delete[] tempPlayerUsed; - delete[] playertemp; - delete[] nametemp; + // Remove any temp players that were not used. Happens if there are now + // less players in the game than there were in the save + for (auto& p : tempPlayers) + { + if (!p.bUsed) + p.Info.mo->Destroy(); + } } //========================================================================== From 85cefd8516bc616c82b7f8cdc55341668d7aaf88 Mon Sep 17 00:00:00 2001 From: "Dileep V. Reddy" Date: Sun, 3 Nov 2024 07:35:18 -0700 Subject: [PATCH 55/60] Limiting r_radarclipper effect to Out-of-Bounds viewpoints only. Opens the possibility of leaving it true by default in the future. --- src/rendering/hwrenderer/scene/hw_bsp.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rendering/hwrenderer/scene/hw_bsp.cpp b/src/rendering/hwrenderer/scene/hw_bsp.cpp index 82f90a3ba..c36f86e83 100644 --- a/src/rendering/hwrenderer/scene/hw_bsp.cpp +++ b/src/rendering/hwrenderer/scene/hw_bsp.cpp @@ -286,12 +286,12 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip) angle_t startAngleR = clipperr.PointToPseudoAngle(seg->v2->fX(), seg->v2->fY()); angle_t endAngleR = clipperr.PointToPseudoAngle(seg->v1->fX(), seg->v1->fY()); - if(r_radarclipper && !(Level->flags3 & LEVEL3_NOFOGOFWAR) && (startAngleR - endAngleR >= ANGLE_180)) + if(Viewpoint.IsAllowedOoB() && r_radarclipper && !(Level->flags3 & LEVEL3_NOFOGOFWAR) && (startAngleR - endAngleR >= ANGLE_180)) { if (!seg->backsector) clipperr.SafeAddClipRange(startAngleR, endAngleR); else if((seg->sidedef != nullptr) && !uint8_t(seg->sidedef->Flags & WALLF_POLYOBJ) && (currentsector->sectornum != seg->backsector->sectornum)) { - if (in_area == area_default) in_area = hw_CheckViewArea(seg->v2, seg->v1, seg->frontsector, seg->backsector); + if (in_area == area_default) in_area = hw_CheckViewArea(seg->v1, seg->v2, seg->frontsector, seg->backsector); backsector = hw_FakeFlat(seg->backsector, in_area, true); if (hw_CheckClip(seg->sidedef, currentsector, backsector)) clipperr.SafeAddClipRange(startAngleR, endAngleR); } @@ -1011,7 +1011,7 @@ void HWDrawInfo::RenderBSP(void *node, bool drawpsprites) // Give the DrawInfo the viewpoint in fixed point because that's what the nodes are. viewx = FLOAT2FIXED(Viewpoint.Pos.X); viewy = FLOAT2FIXED(Viewpoint.Pos.Y); - if (r_radarclipper && !(Level->flags3 & LEVEL3_NOFOGOFWAR) && Viewpoint.IsAllowedOoB() && (Viewpoint.camera->ViewPos->Flags & VPSF_ABSOLUTEOFFSET)) + if (r_radarclipper && !(Level->flags3 & LEVEL3_NOFOGOFWAR) && Viewpoint.IsAllowedOoB()) { if (Viewpoint.camera->tracer != NULL) { From 0fe2d72b75086ce735b1c86d7e12dea2cb729c44 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Sun, 3 Nov 2024 20:40:37 -0500 Subject: [PATCH 56/60] Fixed startpos not saving Will now load properly from a save game preventing respawning at the wrong player starts. --- src/g_game.cpp | 10 +++++++++- src/g_level.cpp | 14 +++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/g_game.cpp b/src/g_game.cpp index e80a5cfd2..42ce6e99a 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -96,6 +96,8 @@ static FRandom pr_dmspawn ("DMSpawn"); static FRandom pr_pspawn ("PlayerSpawn"); +extern int startpos, laststartpos; + bool WriteZip(const char* filename, const FileSys::FCompressedBuffer* content, size_t contentcount); bool G_CheckDemoStatus (void); void G_ReadDemoTiccmd (ticcmd_t *cmd, int player); @@ -2146,7 +2148,9 @@ void G_DoLoadGame () arc("ticrate", time[0]) ("leveltime", time[1]) - ("globalfreeze", globalfreeze); + ("globalfreeze", globalfreeze) + ("startpos", startpos) + ("laststartpos", laststartpos); // dearchive all the modifications level.time = Scale(time[1], TICRATE, time[0]); @@ -2434,6 +2438,10 @@ void G_DoSaveGame (bool okForQuicksave, bool forceQuicksave, FString filename, c savegameglobals("leveltime", level.time); } + savegameglobals("globalfreeze", globalfreeze) + ("startpos", startpos) + ("laststartpos", laststartpos); + STAT_Serialize(savegameglobals); FRandom::StaticWriteRNGState(savegameglobals); P_WriteACSDefereds(savegameglobals); diff --git a/src/g_level.cpp b/src/g_level.cpp index d82c68358..bc0cd378a 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -111,6 +111,8 @@ EXTERN_CVAR (Int, disableautosave) EXTERN_CVAR (String, playerclass) extern uint8_t globalfreeze, globalchangefreeze; +int startpos = 0; // [RH] Support for multiple starts per level +int laststartpos = 0; #define SNAP_ID MAKE_ID('s','n','A','p') #define DSNP_ID MAKE_ID('d','s','N','p') @@ -652,7 +654,9 @@ void G_InitNew (const char *mapname, bool bTitleLevel) gamestate = GS_LEVEL; } - G_DoLoadLevel (mapname, 0, false, !savegamerestore); + if (!savegamerestore) + startpos = laststartpos = 0; + G_DoLoadLevel (mapname, startpos, false, !savegamerestore); if (!savegamerestore && (gameinfo.gametype == GAME_Strife || (SBarInfoScript[SCRIPT_CUSTOM] != nullptr && SBarInfoScript[SCRIPT_CUSTOM]->GetGameType() == GAME_Strife))) { @@ -669,7 +673,6 @@ void G_InitNew (const char *mapname, bool bTitleLevel) // G_DoCompleted // static FString nextlevel; -static int startpos; // [RH] Support for multiple starts per level extern int NoWipe; // [RH] Don't wipe when travelling in hubs static int changeflags; static bool unloading; @@ -1100,7 +1103,6 @@ void G_DoCompleted (void) if (gamestate == GS_TITLELEVEL) { G_DoLoadLevel (nextlevel, startpos, false, false); - startpos = 0; viewactive = true; return; } @@ -1373,7 +1375,6 @@ void G_DoLoadLevel(const FString &nextmapname, int position, bool autosave, bool void FLevelLocals::DoLoadLevel(const FString &nextmapname, int position, bool autosave, bool newGame) { MapName = nextmapname; - static int lastposition = 0; int i; if (NextSkill >= 0) @@ -1385,9 +1386,9 @@ void FLevelLocals::DoLoadLevel(const FString &nextmapname, int position, bool au } if (position == -1) - position = lastposition; + position = laststartpos; else - lastposition = position; + laststartpos = position; Init(); StatusBar->DetachAllMessages (); @@ -1575,7 +1576,6 @@ void G_DoWorldDone (void) } primaryLevel->StartTravel (); G_DoLoadLevel (nextlevel, startpos, true, false); - startpos = 0; gameaction = ga_nothing; viewactive = true; } From 1620d405c6054cf6673521e3ca4fa3d487b9db76 Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Sat, 26 Oct 2024 21:50:18 -0500 Subject: [PATCH 57/60] Added OrthographicCamera actor. Arguments are: - 0: Offset. This pushes the camera further away, going behind the camera. Default is 1.0 (converted to negative - the value cannot go lower than that). --- wadsrc/static/mapinfo/common.txt | 1 + wadsrc/static/zscript/actors/shared/camera.zs | 32 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/wadsrc/static/mapinfo/common.txt b/wadsrc/static/mapinfo/common.txt index f079ee6e6..d61578102 100644 --- a/wadsrc/static/mapinfo/common.txt +++ b/wadsrc/static/mapinfo/common.txt @@ -78,6 +78,7 @@ DoomEdNums 9081 = SkyPicker 9082 = SectorSilencer 9083 = SkyCamCompat + 9084 = OrthographicCamera 9200 = Decal 9300 = "$PolyAnchor" 9301 = "$PolySpawn" diff --git a/wadsrc/static/zscript/actors/shared/camera.zs b/wadsrc/static/zscript/actors/shared/camera.zs index 463ad6178..40972fa82 100644 --- a/wadsrc/static/zscript/actors/shared/camera.zs +++ b/wadsrc/static/zscript/actors/shared/camera.zs @@ -212,3 +212,35 @@ class SpectatorCamera : Actor } } } + +Class OrthographicCamera : Actor +{ + Default + { + +NOBLOCKMAP + +NOINTERACTION + CameraHeight 0; + RenderStyle "None"; + } + + override void PostBeginPlay() + { + Super.PostBeginPlay(); + UpdateViewPos(); + } + + override void Tick() + { + if (current != args[0]) + UpdateViewPos(); + + Super.Tick(); + } + + private int current; + private void UpdateViewPos() + { + current = args[0]; + SetViewPos((-abs(max(1.0, double(current))), 0, 0), VPSF_ORTHOGRAPHIC|VPSF_ALLOWOUTOFBOUNDS); + } +} From ceb2de36d37e2e64438037e7cffc25c6d31efa1e Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Mon, 28 Oct 2024 22:31:40 -0500 Subject: [PATCH 58/60] Change function from private to protected by request. --- wadsrc/static/zscript/actors/shared/camera.zs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/zscript/actors/shared/camera.zs b/wadsrc/static/zscript/actors/shared/camera.zs index 40972fa82..21f72dd6c 100644 --- a/wadsrc/static/zscript/actors/shared/camera.zs +++ b/wadsrc/static/zscript/actors/shared/camera.zs @@ -238,7 +238,7 @@ Class OrthographicCamera : Actor } private int current; - private void UpdateViewPos() + protected void UpdateViewPos() { current = args[0]; SetViewPos((-abs(max(1.0, double(current))), 0, 0), VPSF_ORTHOGRAPHIC|VPSF_ALLOWOUTOFBOUNDS); From 3d4dccd650b4829dd57910150795204bea81c404 Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Mon, 28 Oct 2024 22:33:34 -0500 Subject: [PATCH 59/60] And the variable. --- wadsrc/static/zscript/actors/shared/camera.zs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/zscript/actors/shared/camera.zs b/wadsrc/static/zscript/actors/shared/camera.zs index 21f72dd6c..11b036162 100644 --- a/wadsrc/static/zscript/actors/shared/camera.zs +++ b/wadsrc/static/zscript/actors/shared/camera.zs @@ -237,7 +237,7 @@ Class OrthographicCamera : Actor Super.Tick(); } - private int current; + protected int current; protected void UpdateViewPos() { current = args[0]; From d85d04f4217817d815bbf3542449f81f1c506a6d Mon Sep 17 00:00:00 2001 From: Boondorl Date: Mon, 4 Nov 2024 23:54:31 -0500 Subject: [PATCH 60/60] Fixed crash on functions with missing return values --- src/common/scripting/backend/vmbuilder.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/common/scripting/backend/vmbuilder.cpp b/src/common/scripting/backend/vmbuilder.cpp index 71a766d9a..5437ca848 100644 --- a/src/common/scripting/backend/vmbuilder.cpp +++ b/src/common/scripting/backend/vmbuilder.cpp @@ -879,10 +879,18 @@ void FFunctionBuildList::Build() { if (!item.Code->CheckReturn()) { - auto newcmpd = new FxCompoundStatement(item.Code->ScriptPosition); - newcmpd->Add(item.Code); - newcmpd->Add(new FxReturnStatement(nullptr, item.Code->ScriptPosition)); - item.Code = newcmpd->Resolve(ctx); + if (ctx.ReturnProto == nullptr || !ctx.ReturnProto->ReturnTypes.Size()) + { + auto newcmpd = new FxCompoundStatement(item.Code->ScriptPosition); + newcmpd->Add(item.Code); + newcmpd->Add(new FxReturnStatement(nullptr, item.Code->ScriptPosition)); + item.Code = newcmpd->Resolve(ctx); + } + else + { + item.Code->ScriptPosition.Message(MSG_ERROR, "Missing return statement in %s", item.PrintableName.GetChars()); + continue; + } } item.Proto = ctx.ReturnProto;