From 573cd2f12c7549ebe323366f0dcd8642614f9abb Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Sat, 12 Oct 2024 01:30:20 -0400 Subject: [PATCH 01/93] 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/93] - 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/93] 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/93] 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/93] 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/93] 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/93] - 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/93] 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/93] - 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/93] - 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/93] 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/93] 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/93] 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/93] - 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/93] - 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/93] - 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/93] 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/93] 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/93] 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/93] - 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/93] 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/93] 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/93] 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/93] 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/93] 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/93] 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/93] 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/93] 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/93] 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/93] 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/93] 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/93] 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/93] 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/93] 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/93] 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/93] 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/93] - 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/93] - 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/93] 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/93] 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/93] 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/93] - 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/93] 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/93] 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/93] 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/93] 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/93] 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/93] 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/93] 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/93] 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/93] 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/93] 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/93] 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/93] 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/93] 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/93] 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/93] 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/93] 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/93] 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/93] 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; From e02b3565d0166a3f3e6eb7e4f217f378a8c970a2 Mon Sep 17 00:00:00 2001 From: nashmuhandes Date: Tue, 5 Nov 2024 21:52:10 +0800 Subject: [PATCH 61/93] Bump VKDoom's ZScript version --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index da6ab9cde..dee38c893 100644 --- a/src/version.h +++ b/src/version.h @@ -55,7 +55,7 @@ const char *GetVersionString(); // These are for zscript versioning. #define ZSCRIPT_VER_MAJOR 4 -#define ZSCRIPT_VER_MINOR 13 +#define ZSCRIPT_VER_MINOR 14 #define ZSCRIPT_VER_REVISION 0 // This should always refer to the VkDoom version a derived port is based on and not reflect the derived port's version number! From 220200d83643a02e9521232ecfaff0bc09795317 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Fri, 8 Nov 2024 14:26:51 -0500 Subject: [PATCH 62/93] Revert "- error out if destroying a canvas object" This reverts commit 8e16822ef9814f2d157851cfebce3cc7191544df. --- src/common/2d/v_2ddrawer.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/common/2d/v_2ddrawer.h b/src/common/2d/v_2ddrawer.h index 200510aa1..c2be564dc 100644 --- a/src/common/2d/v_2ddrawer.h +++ b/src/common/2d/v_2ddrawer.h @@ -8,7 +8,6 @@ #include "renderstyle.h" #include "dobject.h" #include "refcounted.h" -#include "printf.h" struct DrawParms; struct FColormap; @@ -280,7 +279,6 @@ 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 04cdbd1898f8e7240c4f02e4bd5da54217bd4758 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Fri, 8 Nov 2024 17:34:26 -0500 Subject: [PATCH 63/93] Fixed CreateCopy being broken on HexenArmor --- wadsrc/static/zscript/actors/inventory/armor.zs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/wadsrc/static/zscript/actors/inventory/armor.zs b/wadsrc/static/zscript/actors/inventory/armor.zs index 8509c5bf2..29c82a1fc 100644 --- a/wadsrc/static/zscript/actors/inventory/armor.zs +++ b/wadsrc/static/zscript/actors/inventory/armor.zs @@ -468,11 +468,12 @@ class HexenArmor : Armor override Inventory CreateCopy (Actor other) { - // Like BasicArmor, HexenArmor is used in the inventory but not the map. - // health is the slot this armor occupies. + // Unlike BasicArmor, Hexen's armor pieces directly inherit from this class. + // Health is the slot this armor occupies. // Amount is the quantity to give (0 = normal max). - let copy = HexenArmor(Spawn(GetHexenArmorClass())); - copy.AddArmorToSlot (health, Amount); + let copy = HexenArmor(Spawn(GetClass())); + copy.Health = Health; + copy.Amount = Amount; GoAwayAndDie (); return copy; } From 2bc561d135bd58e102f7bfe0156a6c134d3af26f Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Mon, 11 Nov 2024 06:50:59 -0500 Subject: [PATCH 64/93] - add automap default markers for all games (can be overridden) --- wadsrc/static/graphics/AMMNUM0.png | Bin 0 -> 89 bytes wadsrc/static/graphics/AMMNUM1.png | Bin 0 -> 88 bytes wadsrc/static/graphics/AMMNUM2.png | Bin 0 -> 86 bytes wadsrc/static/graphics/AMMNUM3.png | Bin 0 -> 84 bytes wadsrc/static/graphics/AMMNUM4.png | Bin 0 -> 89 bytes wadsrc/static/graphics/AMMNUM5.png | Bin 0 -> 87 bytes wadsrc/static/graphics/AMMNUM6.png | Bin 0 -> 89 bytes wadsrc/static/graphics/AMMNUM7.png | Bin 0 -> 87 bytes wadsrc/static/graphics/AMMNUM8.png | Bin 0 -> 86 bytes wadsrc/static/graphics/AMMNUM9.png | Bin 0 -> 89 bytes 10 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 wadsrc/static/graphics/AMMNUM0.png create mode 100644 wadsrc/static/graphics/AMMNUM1.png create mode 100644 wadsrc/static/graphics/AMMNUM2.png create mode 100644 wadsrc/static/graphics/AMMNUM3.png create mode 100644 wadsrc/static/graphics/AMMNUM4.png create mode 100644 wadsrc/static/graphics/AMMNUM5.png create mode 100644 wadsrc/static/graphics/AMMNUM6.png create mode 100644 wadsrc/static/graphics/AMMNUM7.png create mode 100644 wadsrc/static/graphics/AMMNUM8.png create mode 100644 wadsrc/static/graphics/AMMNUM9.png diff --git a/wadsrc/static/graphics/AMMNUM0.png b/wadsrc/static/graphics/AMMNUM0.png new file mode 100644 index 0000000000000000000000000000000000000000..6924f3956f24e24996bd6968d0575a6eb5fd6a1d GIT binary patch literal 89 zcmeAS@N?(olHy`uVBq!ia0y~yU|?ooU|{87VPIg;s+gzAz`&s3>Eakt5vSX^k(Ysi tqj^JnWsUsh3@&EoFLRj0JJe4`PtN7A*jX78%)r3F;OXk;vd$@?2>=xd6^{S_ literal 0 HcmV?d00001 diff --git a/wadsrc/static/graphics/AMMNUM1.png b/wadsrc/static/graphics/AMMNUM1.png new file mode 100644 index 0000000000000000000000000000000000000000..14dab57fe8ed3743552cc1fdaac1a624ce8b1850 GIT binary patch literal 88 zcmeAS@N?(olHy`uVBq!ia0y~yU|?ooU|{87VPIg;s+gzAz`!8y>Eakt5ode+ASVL@ sN9zUm=B@w3j@pYfX;iJ~*!_M(#wPaSW4@B?3=9kmp00i_>zopr08?uh@Bjb+ literal 0 HcmV?d00001 diff --git a/wadsrc/static/graphics/AMMNUM2.png b/wadsrc/static/graphics/AMMNUM2.png new file mode 100644 index 0000000000000000000000000000000000000000..4c6514893b7e7b10c7c5fd635169f8aa95a6a5fe GIT binary patch literal 86 zcmeAS@N?(olHy`uVBq!ia0y~yU|?ooU|{87VPIg;s+gzAz`!8u>Eakt5og=6QILT_ qz}aZ#-|eU7EBU*waC`BpUG7y3?*f|?Z3_kl1_n=8KbLh*2~7Y5WEM35 literal 0 HcmV?d00001 diff --git a/wadsrc/static/graphics/AMMNUM3.png b/wadsrc/static/graphics/AMMNUM3.png new file mode 100644 index 0000000000000000000000000000000000000000..bcd495a680c77795f63c17fa4d13699b0d7a5329 GIT binary patch literal 84 zcmeAS@N?(olHy`uVBq!ia0y~yU|?ooU|{87VPIg;s+gzAz`!8w>Eakt5trL;DagRU o(BzT!Kg@2oL4ksQTaEtH4BiE&C+bXRU|?YIboFyt=akR{0Ih)(bpQYW literal 0 HcmV?d00001 diff --git a/wadsrc/static/graphics/AMMNUM4.png b/wadsrc/static/graphics/AMMNUM4.png new file mode 100644 index 0000000000000000000000000000000000000000..6d373156cfd4ca7b8a6504719478834905ccd96d GIT binary patch literal 89 zcmeAS@N?(olHy`uVBq!ia0y~yU|?ooU|{87VPIg;s+gzAz`&s3>Eakt5$D>mk&}Ue ur+G>H)Bo#lS*bb-oczS&_c`h@Eakt5og=Jk(Ysi rr)kHU|Mgd=9qHgZu;#ITm1*g#7~Taz{2kd03=9mOu6{1-oD!MEakt5og=Jk(Ysi tqxr(&sy+RgzC8z+UWul^6Vm#}_F@yS#=*@YH4F?444$rjF6*2UngC@w7Eakt5f|EaP>_Lv rqiF|Q@&C16zd89Gq&aUrd@0j^jpcXYq1~Eakt5tn;>BQFC3 r3&Vz@8INt<-dtLl<#*}eZr0l^JR78cOtfQQU|{fc^>bP0l+XkKDmoYE literal 0 HcmV?d00001 diff --git a/wadsrc/static/graphics/AMMNUM9.png b/wadsrc/static/graphics/AMMNUM9.png new file mode 100644 index 0000000000000000000000000000000000000000..fa9232fa46b5d757703a725d27db56784e038f2f GIT binary patch literal 89 zcmeAS@N?(olHy`uVBq!ia0y~yU|?ooU|{87VPIg;s+gzAz`&s3>Eakt5vP0nATI+0 u3&TdE84q>cREp-Wo~8ZrLF?`7On3EoH5N|}=wV=BVDNPHb6Mw<&;$TakQeg+ literal 0 HcmV?d00001 From a145eac056233caaeeb702f2a15eabdcb6b40dd9 Mon Sep 17 00:00:00 2001 From: Blue Shadow Date: Mon, 11 Nov 2024 14:25:20 +0300 Subject: [PATCH 65/93] added constants for the most recently added level flags --- wadsrc/static/zscript/constants.zs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wadsrc/static/zscript/constants.zs b/wadsrc/static/zscript/constants.zs index ae57f7a4d..b39573bd9 100644 --- a/wadsrc/static/zscript/constants.zs +++ b/wadsrc/static/zscript/constants.zs @@ -1409,6 +1409,8 @@ enum ELevelFlags LEVEL3_AVOIDMELEE = 0x00020000, // global flag needed for proper MBF support. LEVEL3_NOJUMPDOWN = 0x00040000, // only for MBF21. Inverse of MBF's dog_jumping flag. LEVEL3_LIGHTCREATED = 0x00080000, // a light had been created in the last frame + LEVEL3_NOFOGOFWAR = 0x00100000, // disables effect of r_radarclipper CVAR on this map + LEVEL3_SECRET = 0x00200000, // level is a secret level }; // [RH] Compatibility flags. From ea7ea182edd9d8e5674b42fedf43b2db123aa0c1 Mon Sep 17 00:00:00 2001 From: nashmuhandes Date: Tue, 12 Nov 2024 09:34:46 +0800 Subject: [PATCH 66/93] Add missing CHANF_ constants and fix the styling of the comments for better readability --- wadsrc/static/zscript/engine/base.zs | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/wadsrc/static/zscript/engine/base.zs b/wadsrc/static/zscript/engine/base.zs index 69f5d66fe..e25c82229 100644 --- a/wadsrc/static/zscript/engine/base.zs +++ b/wadsrc/static/zscript/engine/base.zs @@ -15,27 +15,29 @@ enum ESoundFlags // modifier flags CHAN_LISTENERZ = 8, CHAN_MAYBE_LOCAL = 16, - CHAN_UI = 32, - CHAN_NOPAUSE = 64, + CHAN_UI = 32, // Do not record sound in savegames. + CHAN_NOPAUSE = 64, // Do not pause this sound in menus. CHAN_LOOP = 256, CHAN_PICKUP = (CHAN_ITEM|CHAN_MAYBE_LOCAL), // Do not use this with A_StartSound! It would not do what is expected. - CHAN_NOSTOP = 4096, - CHAN_OVERLAP = 8192, + CHAN_NOSTOP = 4096, // only for A_PlaySound. Does not start if channel is playing something. + CHAN_OVERLAP = 8192, // [MK] Does not stop any sounds in the channel and instead plays over them. // Same as above, with an F appended to allow better distinction of channel and channel flags. - CHANF_DEFAULT = 0, // just to make the code look better and avoid literal 0's. + CHANF_DEFAULT = 0, // just to make the code look better and avoid literal 0's. CHANF_LISTENERZ = 8, CHANF_MAYBE_LOCAL = 16, - CHANF_UI = 32, - CHANF_NOPAUSE = 64, + CHANF_UI = 32, // Do not record sound in savegames. + CHANF_NOPAUSE = 64, // Do not pause this sound in menus. CHANF_LOOP = 256, - CHANF_NOSTOP = 4096, - CHANF_OVERLAP = 8192, - CHANF_LOCAL = 16384, + CHANF_NOSTOP = 4096, // only for A_PlaySound. Does not start if channel is playing something. + CHANF_OVERLAP = 8192, // [MK] Does not stop any sounds in the channel and instead plays over them. + CHANF_LOCAL = 16384, // only plays locally for the calling actor + CHANF_TRANSIENT = 32768, // Do not record in savegames - used for sounds that get restarted outside the sound system (e.g. ambients in SW and Blood) + CHANF_FORCE = 65536, // Start, even if sound is paused. + CHANF_SINGULAR = 0x20000, // Only start if no sound of this name is already playing. CHANF_LOOPING = CHANF_LOOP | CHANF_NOSTOP, // convenience value for replicating the old 'looping' boolean. - }; // sound attenuation values From bb5c8d8124181180f505e34093fc133616f9cd17 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Thu, 13 Jun 2024 04:59:14 -0400 Subject: [PATCH 67/93] - don't fudge light position out of the floor for +NOINTERACTION actors --- src/playsim/a_dynlight.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/playsim/a_dynlight.cpp b/src/playsim/a_dynlight.cpp index 6d67d4e1b..3dc653898 100644 --- a/src/playsim/a_dynlight.cpp +++ b/src/playsim/a_dynlight.cpp @@ -383,10 +383,14 @@ void FDynamicLight::UpdateLocation() Pos = target->Vec3Offset(m_off.X * c + m_off.Y * s, m_off.X * s - m_off.Y * c, m_off.Z + target->GetBobOffset()); Sector = target->subsector->sector; // Get the render sector. target->Sector is the sector according to play logic. - // Some z-coordinate fudging to prevent the light from getting too close to the floor or ceiling planes. With proper attenuation this would render them invisible. - // A distance of 5 is needed so that the light's effect doesn't become too small. - if (Z() < target->floorz + 5.) Pos.Z = target->floorz + 5.; - else if (Z() > target->ceilingz - 5.) Pos.Z = target->ceilingz - 5.; + if (!(target->flags5 & MF5_NOINTERACTION)) + { + // Some z-coordinate fudging to prevent the light from getting too close to the floor or ceiling planes. With proper attenuation this would render them invisible. + // A distance of 5 is needed so that the light's effect doesn't become too small. + // [SP] don't do this if +NOINTERACTION is set, since the object can fly right through floors and ceilings with that flag + if (Z() < target->floorz + 5.) Pos.Z = target->floorz + 5.; + else if (Z() > target->ceilingz - 5.) Pos.Z = target->ceilingz - 5.; + } // The radius being used here is always the maximum possible with the // current settings. This avoids constant relinking of flickering lights From 1e4f17639556daed8ff44a4d85e7753fafd538c0 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Tue, 12 Nov 2024 06:34:26 -0500 Subject: [PATCH 68/93] - move appimage workflow to unused/ --- {.github/workflows => unused}/appimage.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {.github/workflows => unused}/appimage.yml (100%) diff --git a/.github/workflows/appimage.yml b/unused/appimage.yml similarity index 100% rename from .github/workflows/appimage.yml rename to unused/appimage.yml From 3a83762c5119061ec5e4cbd28305c20e6ac054c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Sat, 28 Oct 2023 16:38:12 -0300 Subject: [PATCH 69/93] Allow property-less flagdefs for non-actors --- src/scripting/zscript/zcc_compile_doom.cpp | 43 +++++++++++----------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/src/scripting/zscript/zcc_compile_doom.cpp b/src/scripting/zscript/zcc_compile_doom.cpp index a86ea9a0e..bd7ba9048 100644 --- a/src/scripting/zscript/zcc_compile_doom.cpp +++ b/src/scripting/zscript/zcc_compile_doom.cpp @@ -161,17 +161,14 @@ bool ZCCDoomCompiler::CompileProperties(PClass *type, TArray &Pr bool ZCCDoomCompiler::CompileFlagDefs(PClass *type, TArray &Properties, FName prefix) { - if (!type->IsDescendantOf(RUNTIME_CLASS(AActor))) - { - Error(Properties[0], "Flags can only be defined for actors"); - return false; - } + //[RL0] allow property-less flagdefs for non-actors + bool isActor = type->IsDescendantOf(RUNTIME_CLASS(AActor)); for (auto p : Properties) { PField *field; FName referenced = FName(p->RefName); - if (FName(p->NodeName) == FName("prefix") && fileSystem.GetFileContainer(Lump) == 0) + if (isActor && FName(p->NodeName) == FName("prefix") && fileSystem.GetFileContainer(Lump) == 0) { // only for internal definitions: Allow setting a prefix. This is only for compatiblity with the old DECORATE property parser, but not for general use. prefix = referenced; @@ -191,24 +188,28 @@ bool ZCCDoomCompiler::CompileFlagDefs(PClass *type, TArray &Prope } } else field = nullptr; - - - FString qualifiedname; - // Store the full qualified name and prepend some 'garbage' to the name so that no conflicts with other symbol types can happen. - // All these will be removed from the symbol table after the compiler finishes to free up the allocated space. + FName name = FName(p->NodeName); - for (int i = 0; i < 2; i++) - { - if (i == 0) qualifiedname.Format("@flagdef@%s", name.GetChars()); - else - { - if (prefix == NAME_None) continue; - qualifiedname.Format("@flagdef@%s.%s", prefix.GetChars(), name.GetChars()); - } - if (!type->VMType->Symbols.AddSymbol(Create(qualifiedname, field, p->BitValue, i == 0 && prefix != NAME_None))) + if(isActor) + { + FString qualifiedname; + // Store the full qualified name and prepend some 'garbage' to the name so that no conflicts with other symbol types can happen. + // All these will be removed from the symbol table after the compiler finishes to free up the allocated space. + + for (int i = 0; i < 2; i++) { - Error(p, "Unable to add flag definition %s to class %s", FName(p->NodeName).GetChars(), type->TypeName.GetChars()); + if (i == 0) qualifiedname.Format("@flagdef@%s", name.GetChars()); + else + { + if (prefix == NAME_None) continue; + qualifiedname.Format("@flagdef@%s.%s", prefix.GetChars(), name.GetChars()); + } + + if (!type->VMType->Symbols.AddSymbol(Create(qualifiedname, field, p->BitValue, i == 0 && prefix != NAME_None))) + { + Error(p, "Unable to add flag definition %s to class %s", FName(p->NodeName).GetChars(), type->TypeName.GetChars()); + } } } From 3622e2bb2a7d17ede6443c6bbb39011b923fd467 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Tue, 12 Nov 2024 16:00:41 -0300 Subject: [PATCH 70/93] Compress visualthinker bools into a flags field --- src/playsim/p_effect.cpp | 32 +++++++------------ src/playsim/p_effect.h | 18 +++++++---- src/rendering/hwrenderer/scene/hw_sprites.cpp | 7 ++-- wadsrc/static/zscript/constants.zs | 10 ++++++ wadsrc/static/zscript/visualthinker.zs | 21 +++++++----- 5 files changed, 49 insertions(+), 39 deletions(-) diff --git a/src/playsim/p_effect.cpp b/src/playsim/p_effect.cpp index bdceae149..2e5b3d342 100644 --- a/src/playsim/p_effect.cpp +++ b/src/playsim/p_effect.cpp @@ -364,9 +364,9 @@ void P_SpawnParticle(FLevelLocals *Level, const DVector3 &pos, const DVector3 &v particle->sizestep = sizestep; particle->texture = texture; particle->style = style; - particle->Roll = startroll; - particle->RollVel = rollvel; - particle->RollAcc = rollacc; + particle->Roll = (float)startroll; + particle->RollVel = (float)rollvel; + particle->RollAcc = (float)rollacc; particle->flags = flags; if(flags & SPF_LOCAL_ANIM) { @@ -1125,7 +1125,7 @@ int DVisualThinker::GetLightLevel(sector_t* rendersector) const { int lightlevel = rendersector->GetSpriteLight(); - if (bAddLightLevel) + if (flags & VTF_AddLightLevel) { lightlevel += LightLevel; } @@ -1138,7 +1138,7 @@ int DVisualThinker::GetLightLevel(sector_t* rendersector) const FVector3 DVisualThinker::InterpolatedPosition(double ticFrac) const { - if (bDontInterpolate) return FVector3(PT.Pos); + if (flags & VTF_DontInterpolate) return FVector3(PT.Pos); DVector3 proc = Prev + (ticFrac * (PT.Pos - Prev)); return FVector3(proc); @@ -1147,7 +1147,7 @@ FVector3 DVisualThinker::InterpolatedPosition(double ticFrac) const float DVisualThinker::InterpolatedRoll(double ticFrac) const { - if (bDontInterpolate) return PT.Roll; + if (flags & VTF_DontInterpolate) return PT.Roll; return float(PrevRoll + (PT.Roll - PrevRoll) * ticFrac); } @@ -1227,9 +1227,9 @@ int DVisualThinker::GetRenderStyle() float DVisualThinker::GetOffset(bool y) const // Needed for the renderer. { if (y) - return (float)(bFlipOffsetY ? Offset.Y : -Offset.Y); + return (float)((flags & VTF_FlipOffsetY) ? Offset.Y : -Offset.Y); else - return (float)(bFlipOffsetX ? Offset.X : -Offset.X); + return (float)((flags & VTF_FlipOffsetX) ? Offset.X : -Offset.X); } void DVisualThinker::Serialize(FSerializer& arc) @@ -1250,14 +1250,9 @@ void DVisualThinker::Serialize(FSerializer& arc) ("translation", Translation) ("cursector", cursector) ("scolor", PT.color) - ("flipx", bXFlip) - ("flipy", bYFlip) - ("dontinterpolate", bDontInterpolate) - ("addlightlevel", bAddLightLevel) - ("flipoffsetx", bFlipOffsetX) - ("flipoffsetY", bFlipOffsetY) ("lightlevel", LightLevel) - ("flags", PT.flags); + ("flags", PT.flags) + ("visualThinkerFlags", flags); } @@ -1269,6 +1264,7 @@ DEFINE_FIELD_NAMED(DVisualThinker, PT.Roll, Roll); DEFINE_FIELD_NAMED(DVisualThinker, PT.alpha, Alpha); DEFINE_FIELD_NAMED(DVisualThinker, PT.texture, Texture); DEFINE_FIELD_NAMED(DVisualThinker, PT.flags, Flags); +DEFINE_FIELD_NAMED(DVisualThinker, flags, VisualThinkerFlags); DEFINE_FIELD(DVisualThinker, Prev); DEFINE_FIELD(DVisualThinker, Scale); @@ -1277,9 +1273,3 @@ DEFINE_FIELD(DVisualThinker, PrevRoll); DEFINE_FIELD(DVisualThinker, Translation); DEFINE_FIELD(DVisualThinker, LightLevel); DEFINE_FIELD(DVisualThinker, cursector); -DEFINE_FIELD(DVisualThinker, bXFlip); -DEFINE_FIELD(DVisualThinker, bYFlip); -DEFINE_FIELD(DVisualThinker, bDontInterpolate); -DEFINE_FIELD(DVisualThinker, bAddLightLevel); -DEFINE_FIELD(DVisualThinker, bFlipOffsetX); -DEFINE_FIELD(DVisualThinker, bFlipOffsetY); diff --git a/src/playsim/p_effect.h b/src/playsim/p_effect.h index 735a87e81..fdb72c296 100644 --- a/src/playsim/p_effect.h +++ b/src/playsim/p_effect.h @@ -158,6 +158,17 @@ void P_DisconnectEffect (AActor *actor); //=========================================================================== class HWSprite; struct FTranslationID; + +enum EVisualThinkerFlags +{ + VTF_FlipOffsetX = 1 << 0, + VTF_FlipOffsetY = 1 << 1, + VTF_FlipX = 1 << 2, + VTF_FlipY = 1 << 3, // flip the sprite on the x/y axis. + VTF_DontInterpolate = 1 << 4, // disable all interpolation + VTF_AddLightLevel = 1 << 5, // adds sector light level to 'LightLevel' +}; + class DVisualThinker : public DThinker { DECLARE_CLASS(DVisualThinker, DThinker); @@ -171,12 +182,7 @@ public: FTextureID AnimatedTexture; sector_t *cursector; - bool bFlipOffsetX, - bFlipOffsetY, - bXFlip, - bYFlip, // flip the sprite on the x/y axis. - bDontInterpolate, // disable all interpolation - bAddLightLevel; // adds sector light level to 'LightLevel' + int flags; // internal only variables particle_t PT; diff --git a/src/rendering/hwrenderer/scene/hw_sprites.cpp b/src/rendering/hwrenderer/scene/hw_sprites.cpp index cbca1a90d..a8a9502fd 100644 --- a/src/rendering/hwrenderer/scene/hw_sprites.cpp +++ b/src/rendering/hwrenderer/scene/hw_sprites.cpp @@ -1599,7 +1599,7 @@ void HWSprite::AdjustVisualThinker(HWDrawInfo* di, DVisualThinker* spr, sector_t ? TexAnim.UpdateStandaloneAnimation(spr->PT.animData, di->Level->maptime + timefrac) : spr->PT.texture, !custom_anim); - if (spr->bDontInterpolate) + if (spr->flags & VTF_DontInterpolate) timefrac = 0.; FVector3 interp = spr->InterpolatedPosition(timefrac); @@ -1629,13 +1629,12 @@ void HWSprite::AdjustVisualThinker(HWDrawInfo* di, DVisualThinker* spr, sector_t double mult = 1.0 / sqrt(ps); // shrink slightly r.Scale(mult * ps, mult); } - - if (spr->bXFlip) + if (spr->flags & VTF_FlipX) { std::swap(ul,ur); r.left = -r.width - r.left; // mirror the sprite's x-offset } - if (spr->bYFlip) std::swap(vt,vb); + if (spr->flags & VTF_FlipY) std::swap(vt,vb); float viewvecX = vp.ViewVector.X; float viewvecY = vp.ViewVector.Y; diff --git a/wadsrc/static/zscript/constants.zs b/wadsrc/static/zscript/constants.zs index b39573bd9..5421c188e 100644 --- a/wadsrc/static/zscript/constants.zs +++ b/wadsrc/static/zscript/constants.zs @@ -1516,3 +1516,13 @@ enum EModelFlags MDL_CORRECTPIXELSTRETCH = 1<<13, // ensure model does not distort with pixel stretch when pitch/roll is applied MDL_FORCECULLBACKFACES = 1<<14, }; + +enum EVisualThinkerFlags +{ + VTF_FlipOffsetX = 1 << 0, + VTF_FlipOffsetY = 1 << 1, + VTF_FlipX = 1 << 2, + VTF_FlipY = 1 << 3, // flip the sprite on the x/y axis. + VTF_DontInterpolate = 1 << 4, // disable all interpolation + VTF_AddLightLevel = 1 << 5, // adds sector light level to 'LightLevel' +}; diff --git a/wadsrc/static/zscript/visualthinker.zs b/wadsrc/static/zscript/visualthinker.zs index 12a8c41d6..fad1d458c 100644 --- a/wadsrc/static/zscript/visualthinker.zs +++ b/wadsrc/static/zscript/visualthinker.zs @@ -10,14 +10,18 @@ Class VisualThinker : Thinker native Alpha; native TextureID Texture; native TranslationID Translation; - native uint16 Flags; native int16 LightLevel; - native bool bFlipOffsetX, - bFlipOffsetY, - bXFlip, - bYFlip, - bDontInterpolate, - bAddLightLevel; + + native uint16 Flags; + native int VisualThinkerFlags; + + FlagDef FlipOffsetX : VisualThinkerFlags, 0; + FlagDef FlipOffsetY : VisualThinkerFlags, 1; + FlagDef XFlip : VisualThinkerFlags, 2; + FlagDef YFlip : VisualThinkerFlags, 3; + FlagDef DontInterpolate : VisualThinkerFlags, 4; + FlagDef AddLightLevel : VisualThinkerFlags, 5; + native Color scolor; native Sector CurSector; // can be null! @@ -27,7 +31,7 @@ Class VisualThinker : Thinker native native bool IsFrozen(); static VisualThinker Spawn(Class type, TextureID tex, Vector3 pos, Vector3 vel, double alpha = 1.0, int flags = 0, - double roll = 0.0, Vector2 scale = (1,1), Vector2 offset = (0,0), int style = STYLE_Normal, TranslationID trans = 0) + double roll = 0.0, Vector2 scale = (1,1), Vector2 offset = (0,0), int style = STYLE_Normal, TranslationID trans = 0, int VisualThinkerFlags = 0) { if (!Level) return null; @@ -44,6 +48,7 @@ Class VisualThinker : Thinker native p.SetRenderStyle(style); p.Translation = trans; p.Flags = flags; + p.VisualThinkerFlags = VisualThinkerFlags; } return p; } From 174344ddf1490db83226b16997b8f70d10c68e4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Tue, 12 Nov 2024 16:03:28 -0300 Subject: [PATCH 71/93] move visual thinker definition into its own header --- src/common/objects/dobjtype.cpp | 10 ++- src/common/objects/dobjtype.h | 2 +- src/g_levellocals.h | 4 +- src/playsim/dthinker.cpp | 2 + src/playsim/p_effect.cpp | 1 + src/playsim/p_effect.h | 60 +----------------- src/playsim/p_visualthinker.h | 61 +++++++++++++++++++ src/rendering/hwrenderer/scene/hw_bsp.cpp | 2 + src/rendering/hwrenderer/scene/hw_sprites.cpp | 2 + 9 files changed, 80 insertions(+), 64 deletions(-) create mode 100644 src/playsim/p_visualthinker.h diff --git a/src/common/objects/dobjtype.cpp b/src/common/objects/dobjtype.cpp index 0d1bfdf9a..a3172c5e5 100644 --- a/src/common/objects/dobjtype.cpp +++ b/src/common/objects/dobjtype.cpp @@ -46,6 +46,8 @@ #include "symbols.h" #include "types.h" +#include "p_visualthinker.h" + // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- @@ -421,7 +423,7 @@ PClass *PClass::FindClass (FName zaname) // //========================================================================== -DObject *PClass::CreateNew() +DObject *PClass::CreateNew(int *statnum) { uint8_t *mem = (uint8_t *)M_Malloc (Size); assert (mem != nullptr); @@ -444,6 +446,12 @@ DObject *PClass::CreateNew() ((DObject *)mem)->SetClass (const_cast(this)); InitializeSpecials(mem, Defaults, &PClass::SpecialInits); + + if(statnum && ((DObject *)mem)->IsKindOf(RUNTIME_CLASS(DVisualThinker))) + { + *statnum = STAT_VISUALTHINKER; + } + return (DObject *)mem; } diff --git a/src/common/objects/dobjtype.h b/src/common/objects/dobjtype.h index 62e6f5ccc..17ad29862 100644 --- a/src/common/objects/dobjtype.h +++ b/src/common/objects/dobjtype.h @@ -90,7 +90,7 @@ public: PClass(); ~PClass(); void InsertIntoHash(bool native); - DObject *CreateNew(); + DObject *CreateNew(int *statnum = nullptr); PClass *CreateDerivedClass(FName name, unsigned int size, bool *newlycreated = nullptr, int fileno = 0); void InitializeActorInfo(); diff --git a/src/g_levellocals.h b/src/g_levellocals.h index 1b6c82d1b..719427d26 100644 --- a/src/g_levellocals.h +++ b/src/g_levellocals.h @@ -425,11 +425,9 @@ public: DThinker *CreateThinker(PClass *cls, int statnum = STAT_DEFAULT) { - DThinker *thinker = static_cast(cls->CreateNew()); + DThinker *thinker = static_cast(cls->CreateNew(&statnum)); assert(thinker->IsKindOf(RUNTIME_CLASS(DThinker))); thinker->ObjectFlags |= OF_JustSpawned; - if (thinker->IsKindOf(RUNTIME_CLASS(DVisualThinker))) // [MC] This absolutely must happen for this class! - statnum = STAT_VISUALTHINKER; Thinkers.Link(thinker, statnum); thinker->Level = this; return thinker; diff --git a/src/playsim/dthinker.cpp b/src/playsim/dthinker.cpp index 4229de792..e84384752 100644 --- a/src/playsim/dthinker.cpp +++ b/src/playsim/dthinker.cpp @@ -46,6 +46,8 @@ #include "g_cvars.h" #include "d_main.h" +#include "p_visualthinker.h" + static int ThinkCount; static cycle_t ThinkCycles; extern cycle_t BotSupportCycles; diff --git a/src/playsim/p_effect.cpp b/src/playsim/p_effect.cpp index 2e5b3d342..bc9e88163 100644 --- a/src/playsim/p_effect.cpp +++ b/src/playsim/p_effect.cpp @@ -50,6 +50,7 @@ #include "actorinlines.h" #include "g_game.h" #include "serializer_doom.h" +#include "p_visualthinker.h" #include "hwrenderer/scene/hw_drawstructs.h" diff --git a/src/playsim/p_effect.h b/src/playsim/p_effect.h index fdb72c296..1e5ba2705 100644 --- a/src/playsim/p_effect.h +++ b/src/playsim/p_effect.h @@ -147,62 +147,4 @@ struct SPortalHit void P_DrawRailTrail(AActor *source, TArray &portalhits, int color1, int color2, double maxdiff = 0, int flags = 0, PClassActor *spawnclass = NULL, DAngle angle = nullAngle, int duration = TICRATE, double sparsity = 1.0, double drift = 1.0, int SpiralOffset = 270, DAngle pitch = nullAngle); void P_DrawSplash (FLevelLocals *Level, int count, const DVector3 &pos, DAngle angle, int kind); void P_DrawSplash2 (FLevelLocals *Level, int count, const DVector3 &pos, DAngle angle, int updown, int kind); -void P_DisconnectEffect (AActor *actor); - -//=========================================================================== -// -// VisualThinkers -// by Major Cooke -// Credit to phantombeta, RicardoLuis0 & RaveYard for aid -// -//=========================================================================== -class HWSprite; -struct FTranslationID; - -enum EVisualThinkerFlags -{ - VTF_FlipOffsetX = 1 << 0, - VTF_FlipOffsetY = 1 << 1, - VTF_FlipX = 1 << 2, - VTF_FlipY = 1 << 3, // flip the sprite on the x/y axis. - VTF_DontInterpolate = 1 << 4, // disable all interpolation - VTF_AddLightLevel = 1 << 5, // adds sector light level to 'LightLevel' -}; - -class DVisualThinker : public DThinker -{ - DECLARE_CLASS(DVisualThinker, DThinker); -public: - DVector3 Prev; - DVector2 Scale, - Offset; - float PrevRoll; - int16_t LightLevel; - FTranslationID Translation; - FTextureID AnimatedTexture; - sector_t *cursector; - - int flags; - - // internal only variables - particle_t PT; - HWSprite *spr; //in an effort to cache the result. - - DVisualThinker(); - void Construct(); - void OnDestroy() override; - - static DVisualThinker* NewVisualThinker(FLevelLocals* Level, PClass* type); - void SetTranslation(FName trname); - int GetRenderStyle(); - bool isFrozen(); - int GetLightLevel(sector_t *rendersector) const; - FVector3 InterpolatedPosition(double ticFrac) const; - float InterpolatedRoll(double ticFrac) const; - - void Tick() override; - void UpdateSpriteInfo(); - void Serialize(FSerializer& arc) override; - - float GetOffset(bool y) const; -}; \ No newline at end of file +void P_DisconnectEffect (AActor *actor); \ No newline at end of file diff --git a/src/playsim/p_visualthinker.h b/src/playsim/p_visualthinker.h new file mode 100644 index 000000000..c52cc1cd4 --- /dev/null +++ b/src/playsim/p_visualthinker.h @@ -0,0 +1,61 @@ +#pragma once + +#include "palettecontainer.h" +#include "hwrenderer/scene/hw_drawstructs.h" + + +//=========================================================================== +// +// VisualThinkers +// by Major Cooke +// Credit to phantombeta, RicardoLuis0 & RaveYard for aid +// +//=========================================================================== + +enum EVisualThinkerFlags +{ + VTF_FlipOffsetX = 1 << 0, + VTF_FlipOffsetY = 1 << 1, + VTF_FlipX = 1 << 2, + VTF_FlipY = 1 << 3, // flip the sprite on the x/y axis. + VTF_DontInterpolate = 1 << 4, // disable all interpolation + VTF_AddLightLevel = 1 << 5, // adds sector light level to 'LightLevel' +}; + +class DVisualThinker : public DThinker +{ + DECLARE_CLASS(DVisualThinker, DThinker); +public: + DVector3 Prev; + DVector2 Scale, + Offset; + float PrevRoll; + int16_t LightLevel; + FTranslationID Translation; + FTextureID AnimatedTexture; + sector_t *cursector; + + int flags; + + // internal only variables + particle_t PT; + HWSprite *spr; //in an effort to cache the result. + + DVisualThinker(); + void Construct(); + void OnDestroy() override; + + static DVisualThinker* NewVisualThinker(FLevelLocals* Level, PClass* type); + void SetTranslation(FName trname); + int GetRenderStyle(); + bool isFrozen(); + int GetLightLevel(sector_t *rendersector) const; + FVector3 InterpolatedPosition(double ticFrac) const; + float InterpolatedRoll(double ticFrac) const; + + void Tick() override; + void UpdateSpriteInfo(); + void Serialize(FSerializer& arc) override; + + float GetOffset(bool y) const; +}; \ No newline at end of file diff --git a/src/rendering/hwrenderer/scene/hw_bsp.cpp b/src/rendering/hwrenderer/scene/hw_bsp.cpp index c36f86e83..ef4c89cb1 100644 --- a/src/rendering/hwrenderer/scene/hw_bsp.cpp +++ b/src/rendering/hwrenderer/scene/hw_bsp.cpp @@ -44,6 +44,8 @@ #include "hw_vertexbuilder.h" #include "hw_walldispatcher.h" +#include "p_visualthinker.h" + #ifdef ARCH_IA32 #include #endif // ARCH_IA32 diff --git a/src/rendering/hwrenderer/scene/hw_sprites.cpp b/src/rendering/hwrenderer/scene/hw_sprites.cpp index a8a9502fd..b7e1f20fe 100644 --- a/src/rendering/hwrenderer/scene/hw_sprites.cpp +++ b/src/rendering/hwrenderer/scene/hw_sprites.cpp @@ -60,6 +60,8 @@ #include "hw_renderstate.h" #include "quaternion.h" +#include "p_visualthinker.h" + extern TArray sprites; extern TArray SpriteFrames; extern uint32_t r_renderercaps; From 9466c2d13880aa81360cee26086adf0497fc9f2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Tue, 12 Nov 2024 16:05:24 -0300 Subject: [PATCH 72/93] remove unecessary allocations --- src/playsim/p_effect.cpp | 6 ------ src/playsim/p_visualthinker.h | 1 - src/rendering/hwrenderer/scene/hw_bsp.cpp | 5 ++--- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/playsim/p_effect.cpp b/src/playsim/p_effect.cpp index bc9e88163..86b9ac1bf 100644 --- a/src/playsim/p_effect.cpp +++ b/src/playsim/p_effect.cpp @@ -1006,7 +1006,6 @@ void DVisualThinker::Construct() PT.subsector = nullptr; cursector = nullptr; PT.color = 0xffffff; - spr = new HWSprite(); AnimatedTexture.SetNull(); } @@ -1018,11 +1017,6 @@ DVisualThinker::DVisualThinker() void DVisualThinker::OnDestroy() { PT.alpha = 0.0; // stops all rendering. - if(spr) - { - delete spr; - spr = nullptr; - } Super::OnDestroy(); } diff --git a/src/playsim/p_visualthinker.h b/src/playsim/p_visualthinker.h index c52cc1cd4..953f2f0ff 100644 --- a/src/playsim/p_visualthinker.h +++ b/src/playsim/p_visualthinker.h @@ -39,7 +39,6 @@ public: // internal only variables particle_t PT; - HWSprite *spr; //in an effort to cache the result. DVisualThinker(); void Construct(); diff --git a/src/rendering/hwrenderer/scene/hw_bsp.cpp b/src/rendering/hwrenderer/scene/hw_bsp.cpp index ef4c89cb1..2c1abdf7c 100644 --- a/src/rendering/hwrenderer/scene/hw_bsp.cpp +++ b/src/rendering/hwrenderer/scene/hw_bsp.cpp @@ -669,10 +669,9 @@ void HWDrawInfo::RenderParticles(subsector_t *sub, sector_t *front) int clipres = mClipPortal->ClipPoint(sp->PT.Pos.XY()); if (clipres == PClip_InFront) continue; } - - assert(sp->spr); - sp->spr->ProcessParticle(this, &sp->PT, front, sp); + HWSprite sprite; + sprite.ProcessParticle(this, &sp->PT, front, sp); } for (int i = Level->ParticlesInSubsec[sub->Index()]; i != NO_PARTICLE; i = Level->Particles[i].snext) { From d94a596bc2b6c401cf794072cc906ede6eeba7d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Tue, 12 Nov 2024 16:21:26 -0300 Subject: [PATCH 73/93] move crucial functions out of Tick, so that light custom tick overrides can be done without calling super.Tick for non-moving visualthinkers --- src/playsim/p_effect.cpp | 51 ++++++++++++++++++++------ src/playsim/p_visualthinker.h | 2 + wadsrc/static/zscript/visualthinker.zs | 5 +++ 3 files changed, 46 insertions(+), 12 deletions(-) diff --git a/src/playsim/p_effect.cpp b/src/playsim/p_effect.cpp index 86b9ac1bf..5abf899eb 100644 --- a/src/playsim/p_effect.cpp +++ b/src/playsim/p_effect.cpp @@ -1045,6 +1045,33 @@ static DVisualThinker* SpawnVisualThinker(FLevelLocals* Level, PClass* type) return DVisualThinker::NewVisualThinker(Level, type); } +void DVisualThinker::UpdateSector(subsector_t * newSubsector) +{ + assert(newSubsector); + if(PT.subsector != newSubsector) + { + PT.subsector = newSubsector; + cursector = newSubsector->sector; + } +} + +void DVisualThinker::UpdateSector() +{ + UpdateSector(Level->PointInRenderSubsector(PT.Pos)); +} + +static void UpdateSector(DVisualThinker * self) +{ + self->UpdateSector(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DVisualThinker, UpdateSector, UpdateSector) +{ + PARAM_SELF_PROLOGUE(DVisualThinker); + self->UpdateSector(); + return 0; +} + DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, SpawnVisualThinker, SpawnVisualThinker) { PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals); @@ -1092,27 +1119,27 @@ void DVisualThinker::Tick() PT.Pos.Y = newxy.Y; PT.Pos.Z += PT.Vel.Z; - PT.subsector = Level->PointInRenderSubsector(PT.Pos); - cursector = PT.subsector->sector; + subsector_t * ss = Level->PointInRenderSubsector(PT.Pos); + // Handle crossing a sector portal. - if (!cursector->PortalBlocksMovement(sector_t::ceiling)) + if (!ss->sector->PortalBlocksMovement(sector_t::ceiling)) { - if (PT.Pos.Z > cursector->GetPortalPlaneZ(sector_t::ceiling)) + if (PT.Pos.Z > ss->sector->GetPortalPlaneZ(sector_t::ceiling)) { - PT.Pos += cursector->GetPortalDisplacement(sector_t::ceiling); - PT.subsector = Level->PointInRenderSubsector(PT.Pos); - cursector = PT.subsector->sector; + PT.Pos += ss->sector->GetPortalDisplacement(sector_t::ceiling); + ss = Level->PointInRenderSubsector(PT.Pos); } } - else if (!cursector->PortalBlocksMovement(sector_t::floor)) + else if (!ss->sector->PortalBlocksMovement(sector_t::floor)) { - if (PT.Pos.Z < cursector->GetPortalPlaneZ(sector_t::floor)) + if (PT.Pos.Z < ss->sector->GetPortalPlaneZ(sector_t::floor)) { - PT.Pos += cursector->GetPortalDisplacement(sector_t::floor); - PT.subsector = Level->PointInRenderSubsector(PT.Pos); - cursector = PT.subsector->sector; + PT.Pos += ss->sector->GetPortalDisplacement(sector_t::floor); + ss = Level->PointInRenderSubsector(PT.Pos); } } + + UpdateSector(ss); UpdateSpriteInfo(); } diff --git a/src/playsim/p_visualthinker.h b/src/playsim/p_visualthinker.h index 953f2f0ff..d4b1e262d 100644 --- a/src/playsim/p_visualthinker.h +++ b/src/playsim/p_visualthinker.h @@ -25,6 +25,7 @@ enum EVisualThinkerFlags class DVisualThinker : public DThinker { DECLARE_CLASS(DVisualThinker, DThinker); + void UpdateSector(subsector_t * newSubsector); public: DVector3 Prev; DVector2 Scale, @@ -54,6 +55,7 @@ public: void Tick() override; void UpdateSpriteInfo(); + void UpdateSector(); void Serialize(FSerializer& arc) override; float GetOffset(bool y) const; diff --git a/wadsrc/static/zscript/visualthinker.zs b/wadsrc/static/zscript/visualthinker.zs index fad1d458c..45b32865c 100644 --- a/wadsrc/static/zscript/visualthinker.zs +++ b/wadsrc/static/zscript/visualthinker.zs @@ -30,6 +30,9 @@ Class VisualThinker : Thinker native native void SetRenderStyle(int mode); // see ERenderStyle native bool IsFrozen(); + native protected void UpdateSector(); // needs to be called if the thinker is set to a non-ticking statnum and the position is modified (or if Tick is overriden and doesn't call Super.Tick()) + native protected void UpdateSpriteInfo(); // needs to be called every time the texture is updated if the thinker uses SPF_LOCAL_ANIM and is set to a non-ticking statnum (or if Tick is overriden and doesn't call Super.Tick()) + static VisualThinker Spawn(Class type, TextureID tex, Vector3 pos, Vector3 vel, double alpha = 1.0, int flags = 0, double roll = 0.0, Vector2 scale = (1,1), Vector2 offset = (0,0), int style = STYLE_Normal, TranslationID trans = 0, int VisualThinkerFlags = 0) { @@ -49,6 +52,8 @@ Class VisualThinker : Thinker native p.Translation = trans; p.Flags = flags; p.VisualThinkerFlags = VisualThinkerFlags; + p.UpdateSector(); + p.UpdateSpriteInfo(); } return p; } From 925b62b8c579c33b3221906837fa243617ca032b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Tue, 12 Nov 2024 16:57:04 -0300 Subject: [PATCH 74/93] serialize animData, update subsector on deserialize --- src/common/engine/serializer.h | 3 ++- src/playsim/p_effect.cpp | 23 ++++++++++++++++++++--- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/common/engine/serializer.h b/src/common/engine/serializer.h index 40b6ab706..902d4226c 100644 --- a/src/common/engine/serializer.h +++ b/src/common/engine/serializer.h @@ -252,7 +252,8 @@ FSerializer &Serialize(FSerializer &arc, const char *key, struct ModelOverride & FSerializer &Serialize(FSerializer &arc, const char *key, struct AnimModelOverride &mo, struct AnimModelOverride *def); FSerializer &Serialize(FSerializer &arc, const char *key, ModelAnim &ao, ModelAnim *def); FSerializer &Serialize(FSerializer &arc, const char *key, ModelAnimFrame &ao, ModelAnimFrame *def); -FSerializer& Serialize(FSerializer& arc, const char* key, FTranslationID& value, FTranslationID* defval); +FSerializer &Serialize(FSerializer& arc, const char* key, FTranslationID& value, FTranslationID* defval); +FSerializer &Serialize(FSerializer& arc, const char* key, struct FStandaloneAnimation& value, struct FStandaloneAnimation* defval); void SerializeFunctionPointer(FSerializer &arc, const char *key, FunctionPointerValue *&p); diff --git a/src/playsim/p_effect.cpp b/src/playsim/p_effect.cpp index 5abf899eb..c48cafb85 100644 --- a/src/playsim/p_effect.cpp +++ b/src/playsim/p_effect.cpp @@ -1254,12 +1254,24 @@ float DVisualThinker::GetOffset(bool y) const // Needed for the renderer. return (float)((flags & VTF_FlipOffsetX) ? Offset.X : -Offset.X); } + +FSerializer& Serialize(FSerializer& arc, const char* key, FStandaloneAnimation& value, FStandaloneAnimation* defval) +{ + arc.BeginObject(key); + arc("SwitchTic", value.SwitchTic); + arc("AnimIndex", value.AnimIndex); + arc("CurFrame", value.CurFrame); + arc("Ok", value.ok); + arc("AnimType", value.AnimType); + arc.EndObject(); + return arc; +} + void DVisualThinker::Serialize(FSerializer& arc) { Super::Serialize(arc); - arc - ("pos", PT.Pos) + arc ("pos", PT.Pos) ("vel", PT.Vel) ("prev", Prev) ("scale", Scale) @@ -1273,9 +1285,14 @@ void DVisualThinker::Serialize(FSerializer& arc) ("cursector", cursector) ("scolor", PT.color) ("lightlevel", LightLevel) + ("animData", PT.animData) ("flags", PT.flags) ("visualThinkerFlags", flags); - + + if(arc.isReading()) + { + UpdateSector(); + } } IMPLEMENT_CLASS(DVisualThinker, false, false); From 6a067a76305dd4c5b7f90feab1b09289e414c299 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Tue, 12 Nov 2024 18:14:18 -0300 Subject: [PATCH 75/93] export UpdateSpriteInfo --- src/playsim/p_effect.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/playsim/p_effect.cpp b/src/playsim/p_effect.cpp index c48cafb85..f96ec1301 100644 --- a/src/playsim/p_effect.cpp +++ b/src/playsim/p_effect.cpp @@ -1090,6 +1090,19 @@ void DVisualThinker::UpdateSpriteInfo() } } +static void UpdateSpriteInfo(DVisualThinker * self) +{ + self->UpdateSpriteInfo(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DVisualThinker, UpdateSpriteInfo, UpdateSpriteInfo) +{ + PARAM_SELF_PROLOGUE(DVisualThinker); + self->UpdateSpriteInfo(); + return 0; +} + + // This runs just like Actor's, make sure to call Super.Tick() in ZScript. void DVisualThinker::Tick() { From ad40299da4faeca8e971e062b45764ae5bbfc9e6 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Tue, 22 Oct 2024 18:22:43 -0400 Subject: [PATCH 76/93] - add sprite/frame support for VisualThinkers --- src/playsim/p_effect.cpp | 5 ++++- src/playsim/p_effect.h | 2 +- src/rendering/hwrenderer/scene/hw_sprites.cpp | 21 ++++++++++++++++--- wadsrc/static/zscript/visualthinker.zs | 3 +++ 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/playsim/p_effect.cpp b/src/playsim/p_effect.cpp index f96ec1301..c3bdaa6fc 100644 --- a/src/playsim/p_effect.cpp +++ b/src/playsim/p_effect.cpp @@ -1006,6 +1006,7 @@ void DVisualThinker::Construct() PT.subsector = nullptr; cursector = nullptr; PT.color = 0xffffff; + sprite = -1; AnimatedTexture.SetNull(); } @@ -1110,7 +1111,7 @@ void DVisualThinker::Tick() return; // There won't be a standard particle for this, it's only for graphics. - if (!PT.texture.isValid()) + if (!PT.texture.isValid() && (sprite == -1)) { Printf("No valid texture, destroyed"); Destroy(); @@ -1325,3 +1326,5 @@ DEFINE_FIELD(DVisualThinker, PrevRoll); DEFINE_FIELD(DVisualThinker, Translation); DEFINE_FIELD(DVisualThinker, LightLevel); DEFINE_FIELD(DVisualThinker, cursector); +DEFINE_FIELD(DVisualThinker, sprite); +DEFINE_FIELD(DVisualThinker, frame); diff --git a/src/playsim/p_effect.h b/src/playsim/p_effect.h index 1e5ba2705..d0a38f44c 100644 --- a/src/playsim/p_effect.h +++ b/src/playsim/p_effect.h @@ -147,4 +147,4 @@ struct SPortalHit void P_DrawRailTrail(AActor *source, TArray &portalhits, int color1, int color2, double maxdiff = 0, int flags = 0, PClassActor *spawnclass = NULL, DAngle angle = nullAngle, int duration = TICRATE, double sparsity = 1.0, double drift = 1.0, int SpiralOffset = 270, DAngle pitch = nullAngle); void P_DrawSplash (FLevelLocals *Level, int count, const DVector3 &pos, DAngle angle, int kind); void P_DrawSplash2 (FLevelLocals *Level, int count, const DVector3 &pos, DAngle angle, int updown, int kind); -void P_DisconnectEffect (AActor *actor); \ No newline at end of file +void P_DisconnectEffect (AActor *actor); diff --git a/src/rendering/hwrenderer/scene/hw_sprites.cpp b/src/rendering/hwrenderer/scene/hw_sprites.cpp index b7e1f20fe..326749c16 100644 --- a/src/rendering/hwrenderer/scene/hw_sprites.cpp +++ b/src/rendering/hwrenderer/scene/hw_sprites.cpp @@ -414,7 +414,7 @@ bool HWSprite::CalculateVertices(HWDrawInfo* di, FVector3* v, DVector3* vp) const bool drawBillboardFacingCamera = hw_force_cambbpref ? gl_billboard_faces_camera : gl_billboard_faces_camera || ((actor && (!(actor->renderflags2 & RF2_BILLBOARDNOFACECAMERA) && (actor->renderflags2 & RF2_BILLBOARDFACECAMERA))) - || (particle && particle->texture.isValid() && (!(particle->flags & SPF_NOFACECAMERA) && (particle->flags & SPF_FACECAMERA)))); + || ((!(particle->flags & SPF_NOFACECAMERA) && (particle->flags & SPF_FACECAMERA)))); // [Nash] has +ROLLSPRITE const bool drawRollSpriteActor = (actor != nullptr && actor->renderflags & RF_ROLLSPRITE); @@ -1409,8 +1409,10 @@ void HWSprite::ProcessParticle(HWDrawInfo *di, particle_t *particle, sector_t *s if (!particle || particle->alpha <= 0) return; - if (spr && spr->PT.texture.isNull()) + if (spr && spr->PT.texture.isNull() && (spr->sprite == -1)) + { return; + } lightlevel = hw_ClampLight(spr ? spr->GetLightLevel(sector) : sector->GetSpriteLight()); foglevel = (uint8_t)clamp(sector->lightlevel, 0, 255); @@ -1483,7 +1485,7 @@ void HWSprite::ProcessParticle(HWDrawInfo *di, particle_t *particle, sector_t *s } else { - bool has_texture = particle->texture.isValid(); + bool has_texture = particle->texture.isValid() || !!spr; bool custom_animated_texture = (particle->flags & SPF_LOCAL_ANIM) && particle->animData.ok; int particle_style = has_texture ? 2 : gl_particles_style; // Treat custom texture the same as smooth particles @@ -1505,6 +1507,19 @@ void HWSprite::ProcessParticle(HWDrawInfo *di, particle_t *particle, sector_t *s else if(has_texture) { lump = particle->texture; + if (spr && !lump.isValid()) + { + bool mirror = false; + DVector3 thingpos = (DVector3)spr->InterpolatedPosition(vp.TicFrac); + DAngle ang = (thingpos - vp.Pos).Angle(); + if (di->Viewpoint.IsOrtho()) ang = vp.Angles.Yaw; + + bool spriteflip = false; // !!(thing->renderflags & RF_SPRITEFLIP) + + int rot; + rot = -1; + lump = sprites[spr->sprite].GetSpriteFrame(spr->frame, rot, ang, &mirror, spriteflip); + } } else { diff --git a/wadsrc/static/zscript/visualthinker.zs b/wadsrc/static/zscript/visualthinker.zs index 45b32865c..46f9bb7d7 100644 --- a/wadsrc/static/zscript/visualthinker.zs +++ b/wadsrc/static/zscript/visualthinker.zs @@ -30,6 +30,9 @@ Class VisualThinker : Thinker native native void SetRenderStyle(int mode); // see ERenderStyle native bool IsFrozen(); + native SpriteID sprite; + native uint8 frame; + native protected void UpdateSector(); // needs to be called if the thinker is set to a non-ticking statnum and the position is modified (or if Tick is overriden and doesn't call Super.Tick()) native protected void UpdateSpriteInfo(); // needs to be called every time the texture is updated if the thinker uses SPF_LOCAL_ANIM and is set to a non-ticking statnum (or if Tick is overriden and doesn't call Super.Tick()) From a0c1f5b1b74f4aaf1f8e3259341745684b5fde1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Wed, 13 Nov 2024 17:02:50 -0300 Subject: [PATCH 77/93] fix compilation --- src/playsim/p_visualthinker.h | 2 ++ src/rendering/hwrenderer/scene/hw_sprites.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/playsim/p_visualthinker.h b/src/playsim/p_visualthinker.h index d4b1e262d..988119b2e 100644 --- a/src/playsim/p_visualthinker.h +++ b/src/playsim/p_visualthinker.h @@ -37,6 +37,8 @@ public: sector_t *cursector; int flags; + int sprite; // used to find patch_t and flip value + uint8_t frame; // sprite frame to draw // internal only variables particle_t PT; diff --git a/src/rendering/hwrenderer/scene/hw_sprites.cpp b/src/rendering/hwrenderer/scene/hw_sprites.cpp index 326749c16..7940affc1 100644 --- a/src/rendering/hwrenderer/scene/hw_sprites.cpp +++ b/src/rendering/hwrenderer/scene/hw_sprites.cpp @@ -414,7 +414,7 @@ bool HWSprite::CalculateVertices(HWDrawInfo* di, FVector3* v, DVector3* vp) const bool drawBillboardFacingCamera = hw_force_cambbpref ? gl_billboard_faces_camera : gl_billboard_faces_camera || ((actor && (!(actor->renderflags2 & RF2_BILLBOARDNOFACECAMERA) && (actor->renderflags2 & RF2_BILLBOARDFACECAMERA))) - || ((!(particle->flags & SPF_NOFACECAMERA) && (particle->flags & SPF_FACECAMERA)))); + || (particle && (!(particle->flags & SPF_NOFACECAMERA) && (particle->flags & SPF_FACECAMERA)))); // [Nash] has +ROLLSPRITE const bool drawRollSpriteActor = (actor != nullptr && actor->renderflags & RF_ROLLSPRITE); From ccd38afbcb403df4218cf1bf9992974317a542bb Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Wed, 13 Nov 2024 16:16:36 -0500 Subject: [PATCH 78/93] - revert adding in the sprite/frame support for visual thinkers --- src/playsim/p_effect.cpp | 5 +---- src/playsim/p_effect.h | 2 +- src/playsim/p_visualthinker.h | 2 -- src/rendering/hwrenderer/scene/hw_sprites.cpp | 21 +++---------------- wadsrc/static/zscript/visualthinker.zs | 3 --- 5 files changed, 5 insertions(+), 28 deletions(-) diff --git a/src/playsim/p_effect.cpp b/src/playsim/p_effect.cpp index c3bdaa6fc..f96ec1301 100644 --- a/src/playsim/p_effect.cpp +++ b/src/playsim/p_effect.cpp @@ -1006,7 +1006,6 @@ void DVisualThinker::Construct() PT.subsector = nullptr; cursector = nullptr; PT.color = 0xffffff; - sprite = -1; AnimatedTexture.SetNull(); } @@ -1111,7 +1110,7 @@ void DVisualThinker::Tick() return; // There won't be a standard particle for this, it's only for graphics. - if (!PT.texture.isValid() && (sprite == -1)) + if (!PT.texture.isValid()) { Printf("No valid texture, destroyed"); Destroy(); @@ -1326,5 +1325,3 @@ DEFINE_FIELD(DVisualThinker, PrevRoll); DEFINE_FIELD(DVisualThinker, Translation); DEFINE_FIELD(DVisualThinker, LightLevel); DEFINE_FIELD(DVisualThinker, cursector); -DEFINE_FIELD(DVisualThinker, sprite); -DEFINE_FIELD(DVisualThinker, frame); diff --git a/src/playsim/p_effect.h b/src/playsim/p_effect.h index d0a38f44c..1e5ba2705 100644 --- a/src/playsim/p_effect.h +++ b/src/playsim/p_effect.h @@ -147,4 +147,4 @@ struct SPortalHit void P_DrawRailTrail(AActor *source, TArray &portalhits, int color1, int color2, double maxdiff = 0, int flags = 0, PClassActor *spawnclass = NULL, DAngle angle = nullAngle, int duration = TICRATE, double sparsity = 1.0, double drift = 1.0, int SpiralOffset = 270, DAngle pitch = nullAngle); void P_DrawSplash (FLevelLocals *Level, int count, const DVector3 &pos, DAngle angle, int kind); void P_DrawSplash2 (FLevelLocals *Level, int count, const DVector3 &pos, DAngle angle, int updown, int kind); -void P_DisconnectEffect (AActor *actor); +void P_DisconnectEffect (AActor *actor); \ No newline at end of file diff --git a/src/playsim/p_visualthinker.h b/src/playsim/p_visualthinker.h index 988119b2e..d4b1e262d 100644 --- a/src/playsim/p_visualthinker.h +++ b/src/playsim/p_visualthinker.h @@ -37,8 +37,6 @@ public: sector_t *cursector; int flags; - int sprite; // used to find patch_t and flip value - uint8_t frame; // sprite frame to draw // internal only variables particle_t PT; diff --git a/src/rendering/hwrenderer/scene/hw_sprites.cpp b/src/rendering/hwrenderer/scene/hw_sprites.cpp index 7940affc1..b7e1f20fe 100644 --- a/src/rendering/hwrenderer/scene/hw_sprites.cpp +++ b/src/rendering/hwrenderer/scene/hw_sprites.cpp @@ -414,7 +414,7 @@ bool HWSprite::CalculateVertices(HWDrawInfo* di, FVector3* v, DVector3* vp) const bool drawBillboardFacingCamera = hw_force_cambbpref ? gl_billboard_faces_camera : gl_billboard_faces_camera || ((actor && (!(actor->renderflags2 & RF2_BILLBOARDNOFACECAMERA) && (actor->renderflags2 & RF2_BILLBOARDFACECAMERA))) - || (particle && (!(particle->flags & SPF_NOFACECAMERA) && (particle->flags & SPF_FACECAMERA)))); + || (particle && particle->texture.isValid() && (!(particle->flags & SPF_NOFACECAMERA) && (particle->flags & SPF_FACECAMERA)))); // [Nash] has +ROLLSPRITE const bool drawRollSpriteActor = (actor != nullptr && actor->renderflags & RF_ROLLSPRITE); @@ -1409,10 +1409,8 @@ void HWSprite::ProcessParticle(HWDrawInfo *di, particle_t *particle, sector_t *s if (!particle || particle->alpha <= 0) return; - if (spr && spr->PT.texture.isNull() && (spr->sprite == -1)) - { + if (spr && spr->PT.texture.isNull()) return; - } lightlevel = hw_ClampLight(spr ? spr->GetLightLevel(sector) : sector->GetSpriteLight()); foglevel = (uint8_t)clamp(sector->lightlevel, 0, 255); @@ -1485,7 +1483,7 @@ void HWSprite::ProcessParticle(HWDrawInfo *di, particle_t *particle, sector_t *s } else { - bool has_texture = particle->texture.isValid() || !!spr; + bool has_texture = particle->texture.isValid(); bool custom_animated_texture = (particle->flags & SPF_LOCAL_ANIM) && particle->animData.ok; int particle_style = has_texture ? 2 : gl_particles_style; // Treat custom texture the same as smooth particles @@ -1507,19 +1505,6 @@ void HWSprite::ProcessParticle(HWDrawInfo *di, particle_t *particle, sector_t *s else if(has_texture) { lump = particle->texture; - if (spr && !lump.isValid()) - { - bool mirror = false; - DVector3 thingpos = (DVector3)spr->InterpolatedPosition(vp.TicFrac); - DAngle ang = (thingpos - vp.Pos).Angle(); - if (di->Viewpoint.IsOrtho()) ang = vp.Angles.Yaw; - - bool spriteflip = false; // !!(thing->renderflags & RF_SPRITEFLIP) - - int rot; - rot = -1; - lump = sprites[spr->sprite].GetSpriteFrame(spr->frame, rot, ang, &mirror, spriteflip); - } } else { diff --git a/wadsrc/static/zscript/visualthinker.zs b/wadsrc/static/zscript/visualthinker.zs index 46f9bb7d7..45b32865c 100644 --- a/wadsrc/static/zscript/visualthinker.zs +++ b/wadsrc/static/zscript/visualthinker.zs @@ -30,9 +30,6 @@ Class VisualThinker : Thinker native native void SetRenderStyle(int mode); // see ERenderStyle native bool IsFrozen(); - native SpriteID sprite; - native uint8 frame; - native protected void UpdateSector(); // needs to be called if the thinker is set to a non-ticking statnum and the position is modified (or if Tick is overriden and doesn't call Super.Tick()) native protected void UpdateSpriteInfo(); // needs to be called every time the texture is updated if the thinker uses SPF_LOCAL_ANIM and is set to a non-ticking statnum (or if Tick is overriden and doesn't call Super.Tick()) From 3f4513c5713939e09ab7d9d817f692be98717bee Mon Sep 17 00:00:00 2001 From: Boondorl Date: Tue, 5 Nov 2024 15:29:57 -0500 Subject: [PATCH 79/93] Updated packet handling Added "game in progress" message for players trying to join late. Improved "unknown host" packet logging to only log when truly unknown. Correctly abort network window so game can process fatal errors instead of hanging on waiting to connect. Unexpected disconnects in lobby now correctly update the state of the game. --- src/common/engine/i_net.cpp | 54 +++++++++++++++++----- src/common/engine/i_net.h | 1 + src/common/engine/st_start.h | 2 + src/common/platform/win32/i_mainwindow.cpp | 5 ++ src/common/platform/win32/i_mainwindow.h | 1 + src/common/platform/win32/st_start.cpp | 5 ++ src/common/widgets/netstartwindow.cpp | 6 +++ src/common/widgets/netstartwindow.h | 1 + 8 files changed, 64 insertions(+), 11 deletions(-) diff --git a/src/common/engine/i_net.cpp b/src/common/engine/i_net.cpp index 33b4c1267..27dbfe0a7 100644 --- a/src/common/engine/i_net.cpp +++ b/src/common/engine/i_net.cpp @@ -132,7 +132,8 @@ enum PRE_CONACK, // Sent from host to guest to acknowledge PRE_CONNECT receipt PRE_ALLFULL, // Sent from host to an unwanted guest PRE_ALLHEREACK, // Sent from guest to host to acknowledge PRE_ALLHEREACK receipt - PRE_GO // Sent from host to guest to continue game startup + PRE_GO, // Sent from host to guest to continue game startup + PRE_IN_PROGRESS, // Sent from host to guest if the game has already started }; // Set PreGamePacket.fake to this so that the game rejects any pregame packets @@ -269,6 +270,8 @@ void PacketSend (void) // I_Error ("SendPacket error: %s",strerror(errno)); } +void PreSend(const void* buffer, int bufferlen, const sockaddr_in* to); +void SendConAck(int num_connected, int num_needed); // // PacketGet @@ -303,7 +306,7 @@ void PacketGet (void) GetPlayerName(node).GetChars()); } - doomcom.data[0] = 0x80; // NCMD_EXIT + doomcom.data[0] = NCMD_EXIT; c = 1; } else if (err != WSAEWOULDBLOCK) @@ -342,9 +345,13 @@ void PacketGet (void) else if (c > 0) { //The packet is not from any in-game node, so we might as well discard it. // Don't show the message for disconnect notifications. - if (c != 2 || TransmitBuffer[0] != PRE_FAKE || TransmitBuffer[1] != PRE_DISCONNECT) + if (TransmitBuffer[0] != NCMD_EXIT) { - DPrintf(DMSG_WARNING, "Dropped packet: Unknown host (%s:%d)\n", inet_ntoa(fromaddress.sin_addr), fromaddress.sin_port); + if (TransmitBuffer[0] != PRE_FAKE) + DPrintf(DMSG_WARNING, "Dropped packet: Unknown host (%s:%d)\n", inet_ntoa(fromaddress.sin_addr), fromaddress.sin_port); + // If it's someone waiting in the lobby, let them know the game already started + uint8_t msg[] = { PRE_FAKE, PRE_IN_PROGRESS }; + PreSend(msg, 2, &fromaddress); } doomcom.remotenode = -1; return; @@ -369,7 +376,22 @@ sockaddr_in *PreGet (void *buffer, int bufferlen, bool noabort) int err = WSAGetLastError(); if (err == WSAEWOULDBLOCK || (noabort && err == WSAECONNRESET)) return NULL; // no packet - I_Error ("PreGet: %s", neterror ()); + + if (doomcom.consoleplayer == 0) + { + int node = FindNode(&fromaddress); + I_NetMessage("Got unexpected disconnect."); + doomcom.numnodes--; + for (; node < doomcom.numnodes; ++node) + sendaddress[node] = sendaddress[node + 1]; + + // Let remaining guests know that somebody left. + SendConAck(doomcom.numnodes, doomcom.numplayers); + } + else + { + I_NetError("The host disbanded the game unexpectedly"); + } } return &fromaddress; } @@ -708,7 +730,7 @@ bool HostGame (int i) doomcom.numnodes = 1; - I_NetInit ("Waiting for players", numplayers); + I_NetInit ("Hosting game", numplayers); // Wait for numplayers-1 different connections if (!I_NetLoop (Host_CheckForConnects, (void *)(intptr_t)numplayers)) @@ -783,13 +805,15 @@ bool Guest_ContactHost (void *userdata) } else if (packet.Message == PRE_DISCONNECT) { - doomcom.numnodes = 0; - I_FatalError ("The host cancelled the game."); + I_NetError("The host cancelled the game."); } else if (packet.Message == PRE_ALLFULL) { - doomcom.numnodes = 0; - I_FatalError ("The game is full."); + I_NetError("The game is full."); + } + else if (packet.Message == PRE_IN_PROGRESS) + { + I_NetError("The game was already started."); } } } @@ -850,7 +874,7 @@ bool Guest_WaitForOthers (void *userdata) return true; case PRE_DISCONNECT: - I_FatalError ("The host cancelled the game."); + I_NetError("The host cancelled the game."); break; } } @@ -875,6 +899,7 @@ bool JoinGame (int i) BuildAddress (&sendaddress[1], Args->GetArg(i+1)); sendplayer[1] = 0; doomcom.numnodes = 2; + doomcom.consoleplayer = -1; // Let host know we are here @@ -1046,6 +1071,13 @@ void I_NetMessage(const char* text, ...) #endif } +void I_NetError(const char* error) +{ + doomcom.numnodes = 0; + StartWindow->NetClose(); + I_FatalError(error); +} + // todo: later these must be dispatched by the main menu, not the start screen. void I_NetProgress(int val) { diff --git a/src/common/engine/i_net.h b/src/common/engine/i_net.h index c52072c86..15720374d 100644 --- a/src/common/engine/i_net.h +++ b/src/common/engine/i_net.h @@ -7,6 +7,7 @@ int I_InitNetwork (void); void I_NetCmd (void); void I_NetMessage(const char*, ...); +void I_NetError(const char* error); void I_NetProgress(int val); void I_NetInit(const char* msg, int num); bool I_NetLoop(bool (*timer_callback)(void*), void* userdata); diff --git a/src/common/engine/st_start.h b/src/common/engine/st_start.h index a8b78aaa8..b09991d04 100644 --- a/src/common/engine/st_start.h +++ b/src/common/engine/st_start.h @@ -55,6 +55,7 @@ public: virtual void NetInit(const char *message, int num_players) {} virtual void NetProgress(int count) {} virtual void NetDone() {} + virtual void NetClose() {} virtual bool NetLoop(bool (*timer_callback)(void *), void *userdata) { return false; } virtual void AppendStatusLine(const char* status) {} virtual void LoadingStatus(const char* message, int colors) {} @@ -74,6 +75,7 @@ public: void NetProgress(int count); void NetMessage(const char* format, ...); // cover for printf void NetDone(); + void NetClose(); bool NetLoop(bool (*timer_callback)(void*), void* userdata); protected: int NetMaxPos, NetCurPos; diff --git a/src/common/platform/win32/i_mainwindow.cpp b/src/common/platform/win32/i_mainwindow.cpp index 95dda5031..5bdd3569c 100644 --- a/src/common/platform/win32/i_mainwindow.cpp +++ b/src/common/platform/win32/i_mainwindow.cpp @@ -128,6 +128,11 @@ void MainWindow::HideNetStartPane() NetStartWindow::HideNetStartPane(); } +void MainWindow::CloseNetStartPane() +{ + NetStartWindow::NetClose(); +} + void MainWindow::SetNetStartProgress(int pos) { NetStartWindow::SetNetStartProgress(pos); diff --git a/src/common/platform/win32/i_mainwindow.h b/src/common/platform/win32/i_mainwindow.h index 3c0c7e55d..83567135c 100644 --- a/src/common/platform/win32/i_mainwindow.h +++ b/src/common/platform/win32/i_mainwindow.h @@ -29,6 +29,7 @@ public: void SetNetStartProgress(int pos); bool RunMessageLoop(bool (*timer_callback)(void*), void* userdata); void HideNetStartPane(); + void CloseNetStartPane(); void SetWindowTitle(const char* caption); diff --git a/src/common/platform/win32/st_start.cpp b/src/common/platform/win32/st_start.cpp index 8bc48d26e..fceeb3ced 100644 --- a/src/common/platform/win32/st_start.cpp +++ b/src/common/platform/win32/st_start.cpp @@ -201,3 +201,8 @@ bool FBasicStartupScreen::NetLoop(bool (*timer_callback)(void *), void *userdata { return mainwindow.RunMessageLoop(timer_callback, userdata); } + +void FBasicStartupScreen::NetClose() +{ + mainwindow.CloseNetStartPane(); +} diff --git a/src/common/widgets/netstartwindow.cpp b/src/common/widgets/netstartwindow.cpp index 69c83e565..887f9cc31 100644 --- a/src/common/widgets/netstartwindow.cpp +++ b/src/common/widgets/netstartwindow.cpp @@ -64,6 +64,12 @@ bool NetStartWindow::RunMessageLoop(bool (*newtimer_callback)(void*), void* newu return Instance->exitreason; } +void NetStartWindow::NetClose() +{ + if (Instance != nullptr) + Instance->OnClose(); +} + NetStartWindow::NetStartWindow() : Widget(nullptr, WidgetType::Window) { SetWindowBackground(Colorf::fromRgba8(51, 51, 51)); diff --git a/src/common/widgets/netstartwindow.h b/src/common/widgets/netstartwindow.h index 5d27b8ebf..dcc9d688e 100644 --- a/src/common/widgets/netstartwindow.h +++ b/src/common/widgets/netstartwindow.h @@ -14,6 +14,7 @@ public: static void HideNetStartPane(); static void SetNetStartProgress(int pos); static bool RunMessageLoop(bool (*timer_callback)(void*), void* userdata); + static void NetClose(); private: NetStartWindow(); From e898139690d9effdc5309fc4f91753aad3577a09 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Tue, 5 Nov 2024 15:41:31 -0500 Subject: [PATCH 80/93] Fixed static error for SendConAck --- src/common/engine/i_net.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/engine/i_net.cpp b/src/common/engine/i_net.cpp index 27dbfe0a7..d0f70eb99 100644 --- a/src/common/engine/i_net.cpp +++ b/src/common/engine/i_net.cpp @@ -521,7 +521,7 @@ void SendAbort (void) } } -static void SendConAck (int num_connected, int num_needed) +void SendConAck (int num_connected, int num_needed) { PreGamePacket packet; From b6fd65988bc4ca7ae4870a2532c99c46b90985cc Mon Sep 17 00:00:00 2001 From: Boondorl Date: Tue, 5 Nov 2024 16:24:10 -0500 Subject: [PATCH 81/93] Added stubs for NetClose on other platforms These will need someone with much better experience to implement correctly to abort the net window --- src/common/platform/posix/cocoa/st_console.h | 1 + src/common/platform/posix/cocoa/st_console.mm | 5 +++++ src/common/platform/posix/cocoa/st_start.mm | 5 +++++ src/common/platform/posix/sdl/st_start.cpp | 6 ++++++ 4 files changed, 17 insertions(+) diff --git a/src/common/platform/posix/cocoa/st_console.h b/src/common/platform/posix/cocoa/st_console.h index b2af7bade..91f77d124 100644 --- a/src/common/platform/posix/cocoa/st_console.h +++ b/src/common/platform/posix/cocoa/st_console.h @@ -66,6 +66,7 @@ public: void NetInit(const char* message, int playerCount); void NetProgress(int count); void NetDone(); + void NetClose(); private: NSWindow* m_window; diff --git a/src/common/platform/posix/cocoa/st_console.mm b/src/common/platform/posix/cocoa/st_console.mm index 1c45776e6..95d0ee11e 100644 --- a/src/common/platform/posix/cocoa/st_console.mm +++ b/src/common/platform/posix/cocoa/st_console.mm @@ -531,3 +531,8 @@ void FConsoleWindow::NetDone() m_netAbortButton = nil; } } + +void FConsoleWindow::NetClose() +{ + // TODO: Implement this +} diff --git a/src/common/platform/posix/cocoa/st_start.mm b/src/common/platform/posix/cocoa/st_start.mm index ee6ea2627..2cd73104d 100644 --- a/src/common/platform/posix/cocoa/st_start.mm +++ b/src/common/platform/posix/cocoa/st_start.mm @@ -110,6 +110,11 @@ void FBasicStartupScreen::NetDone() FConsoleWindow::GetInstance().NetDone(); } +void FBasicStartupScreen::NetClose() +{ + FConsoleWindow::GetInstance().NetClose(); +} + bool FBasicStartupScreen::NetLoop(bool (*timerCallback)(void*), void* const userData) { while (true) diff --git a/src/common/platform/posix/sdl/st_start.cpp b/src/common/platform/posix/sdl/st_start.cpp index 019a66122..5bd88684b 100644 --- a/src/common/platform/posix/sdl/st_start.cpp +++ b/src/common/platform/posix/sdl/st_start.cpp @@ -57,6 +57,7 @@ class FTTYStartupScreen : public FStartupScreen void NetInit(const char *message, int num_players); void NetProgress(int count); void NetDone(); + void NetClose(); bool NetLoop(bool (*timer_callback)(void *), void *userdata); protected: bool DidNetInit; @@ -237,6 +238,11 @@ void FTTYStartupScreen::NetProgress(int count) } } +void FTTYStartupScreen::NetClose() +{ + // TODO: Implement this +} + //=========================================================================== // // FTTYStartupScreen :: NetLoop From 8a14497d8c3658fbcce84e5aee462297977434a2 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Tue, 5 Nov 2024 18:03:08 -0500 Subject: [PATCH 82/93] Port NCMD_EXIT to i_net file --- src/common/engine/i_net.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/common/engine/i_net.cpp b/src/common/engine/i_net.cpp index d0f70eb99..2d717b02b 100644 --- a/src/common/engine/i_net.cpp +++ b/src/common/engine/i_net.cpp @@ -117,6 +117,8 @@ static SOCKET mysocket = INVALID_SOCKET; static sockaddr_in sendaddress[MAXNETNODES]; static uint8_t sendplayer[MAXNETNODES]; +constexpr int NET_EXIT = 0x80; + #ifdef __WIN32__ const char *neterror (void); #else @@ -306,7 +308,7 @@ void PacketGet (void) GetPlayerName(node).GetChars()); } - doomcom.data[0] = NCMD_EXIT; + doomcom.data[0] = NET_EXIT; c = 1; } else if (err != WSAEWOULDBLOCK) @@ -345,7 +347,7 @@ void PacketGet (void) else if (c > 0) { //The packet is not from any in-game node, so we might as well discard it. // Don't show the message for disconnect notifications. - if (TransmitBuffer[0] != NCMD_EXIT) + if (TransmitBuffer[0] != NET_EXIT) { if (TransmitBuffer[0] != PRE_FAKE) DPrintf(DMSG_WARNING, "Dropped packet: Unknown host (%s:%d)\n", inet_ntoa(fromaddress.sin_addr), fromaddress.sin_port); From 4c140224a25816884e23e68fd98ef1806895dc00 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Wed, 6 Nov 2024 20:02:44 -0500 Subject: [PATCH 83/93] Removed network message entirely Header needs to include more data to properly filter someone trying to connect --- src/common/engine/i_net.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/common/engine/i_net.cpp b/src/common/engine/i_net.cpp index 2d717b02b..ad106bbc4 100644 --- a/src/common/engine/i_net.cpp +++ b/src/common/engine/i_net.cpp @@ -117,8 +117,6 @@ static SOCKET mysocket = INVALID_SOCKET; static sockaddr_in sendaddress[MAXNETNODES]; static uint8_t sendplayer[MAXNETNODES]; -constexpr int NET_EXIT = 0x80; - #ifdef __WIN32__ const char *neterror (void); #else @@ -308,7 +306,7 @@ void PacketGet (void) GetPlayerName(node).GetChars()); } - doomcom.data[0] = NET_EXIT; + doomcom.data[0] = NCMD_EXIT; c = 1; } else if (err != WSAEWOULDBLOCK) @@ -346,11 +344,8 @@ void PacketGet (void) } else if (c > 0) { //The packet is not from any in-game node, so we might as well discard it. - // Don't show the message for disconnect notifications. - if (TransmitBuffer[0] != NET_EXIT) + if (TransmitBuffer[0] == PRE_FAKE) { - if (TransmitBuffer[0] != PRE_FAKE) - DPrintf(DMSG_WARNING, "Dropped packet: Unknown host (%s:%d)\n", inet_ntoa(fromaddress.sin_addr), fromaddress.sin_port); // If it's someone waiting in the lobby, let them know the game already started uint8_t msg[] = { PRE_FAKE, PRE_IN_PROGRESS }; PreSend(msg, 2, &fromaddress); From 597b06ae52f82a7d38b7887721dd998d0e443401 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Sat, 4 May 2024 20:35:44 -0400 Subject: [PATCH 84/93] Added CRandom functions Unique RNG namespace for client-side effects and HUDs. Identifiers for these cannot clash with identifiers that affect the playsim making them completely safe to use in HUD elements. They also won't be saved. --- src/bbannouncer.cpp | 2 +- src/common/audio/sound/s_sound.cpp | 2 +- src/common/engine/m_random.cpp | 50 ++++++++++++------- src/common/engine/m_random.h | 11 ++-- src/common/engine/namedef.h | 6 +++ src/common/scripting/backend/codegen.cpp | 38 +++++++++++--- src/d_netinfo.cpp | 2 +- src/g_game.cpp | 4 +- src/g_level.cpp | 2 +- src/g_statusbar/sbarinfo_commands.cpp | 2 +- src/gamedata/decallib.cpp | 4 +- src/gamedata/info.cpp | 2 +- src/gamedata/textures/animations.cpp | 2 +- src/p_conversation.cpp | 2 +- src/playsim/a_dynlight.cpp | 2 +- src/playsim/a_specialspot.cpp | 2 +- src/playsim/bots/b_func.cpp | 2 +- src/playsim/bots/b_game.cpp | 2 +- src/playsim/bots/b_move.cpp | 6 +-- src/playsim/bots/b_think.cpp | 2 +- src/playsim/fragglescript/t_func.cpp | 2 +- src/playsim/mapthinkers/a_lightning.cpp | 2 +- src/playsim/mapthinkers/a_lights.cpp | 8 +-- src/playsim/mapthinkers/a_plats.cpp | 2 +- src/playsim/mapthinkers/a_quake.cpp | 2 +- src/playsim/p_acs.cpp | 2 +- src/playsim/p_actionfunctions.cpp | 28 +++++------ src/playsim/p_effect.cpp | 2 +- src/playsim/p_enemy.cpp | 38 +++++++------- src/playsim/p_interaction.cpp | 12 ++--- src/playsim/p_lnspec.cpp | 2 +- src/playsim/p_map.cpp | 8 +-- src/playsim/p_mobj.cpp | 42 ++++++++-------- src/playsim/p_sight.cpp | 4 +- src/playsim/p_spec.cpp | 2 +- src/playsim/p_switch.cpp | 2 +- src/playsim/p_teleport.cpp | 3 +- src/playsim/p_things.cpp | 2 +- src/playsim/p_user.cpp | 2 +- src/playsim/shadowinlines.h | 2 +- src/rendering/r_utility.cpp | 4 +- src/scripting/decorate/thingdef_exp.cpp | 35 +++++++------ src/sound/s_doomsound.cpp | 2 +- src/sound/s_sndseq.cpp | 2 +- wadsrc/static/zscript/engine/base.zs | 4 +- .../zscript/ui/menu/conversationmenu.zs | 6 +-- .../zscript/ui/statusbar/heretic_sbar.zs | 2 +- 47 files changed, 213 insertions(+), 154 deletions(-) diff --git a/src/bbannouncer.cpp b/src/bbannouncer.cpp index 07bc2305e..caf9f9f42 100644 --- a/src/bbannouncer.cpp +++ b/src/bbannouncer.cpp @@ -169,7 +169,7 @@ static const char *TelefragSounds[] = #endif static int LastAnnounceTime; -static FRandom pr_bbannounce ("BBAnnounce"); +static FRandom pr_bbannounce ("BBAnnounce", true); // CODE -------------------------------------------------------------------- diff --git a/src/common/audio/sound/s_sound.cpp b/src/common/audio/sound/s_sound.cpp index 852d389f5..b9084692d 100644 --- a/src/common/audio/sound/s_sound.cpp +++ b/src/common/audio/sound/s_sound.cpp @@ -61,7 +61,7 @@ enum { DEFAULT_PITCH = 128, }; -static FRandom pr_soundpitch ("SoundPitch"); +static FRandom pr_soundpitch ("SoundPitch", true); SoundEngine* soundEngine; //========================================================================== diff --git a/src/common/engine/m_random.cpp b/src/common/engine/m_random.cpp index 3af14526b..df4d53217 100644 --- a/src/common/engine/m_random.cpp +++ b/src/common/engine/m_random.cpp @@ -79,11 +79,11 @@ // EXTERNAL DATA DECLARATIONS ---------------------------------------------- -FRandom pr_exrandom("EX_Random"); +FRandom pr_exrandom("EX_Random", false); // PUBLIC DATA DEFINITIONS ------------------------------------------------- -FRandom M_Random; +FRandom M_Random(true); // Global seed. This is modified predictably to initialize every RNG. uint32_t rngseed; @@ -126,8 +126,8 @@ CCMD(rngseed) // PRIVATE DATA DEFINITIONS ------------------------------------------------ -FRandom *FRandom::RNGList; -static TDeletingArray NewRNGs; +FRandom *FRandom::RNGList, *FRandom::CRNGList; +static TDeletingArray NewRNGs, NewCRNGs; // CODE -------------------------------------------------------------------- @@ -139,14 +139,22 @@ static TDeletingArray NewRNGs; // //========================================================================== -FRandom::FRandom () -: NameCRC (0) +FRandom::FRandom (bool client) +: NameCRC (0), bClient(client) { #ifndef NDEBUG Name = NULL; #endif - Next = RNGList; - RNGList = this; + if (client) + { + Next = CRNGList; + CRNGList = this; + } + else + { + Next = RNGList; + RNGList = this; + } Init(0); } @@ -158,7 +166,7 @@ FRandom::FRandom () // //========================================================================== -FRandom::FRandom (const char *name) +FRandom::FRandom (const char *name, bool client) : bClient(client) { NameCRC = CalcCRC32 ((const uint8_t *)name, (unsigned int)strlen (name)); #ifndef NDEBUG @@ -170,7 +178,7 @@ FRandom::FRandom (const char *name) #endif // Insert the RNG in the list, sorted by CRC - FRandom **prev = &RNGList, *probe = RNGList; + FRandom **prev = (client ? &CRNGList : &RNGList), * probe = (client ? CRNGList : RNGList); while (probe != NULL && probe->NameCRC < NameCRC) { @@ -205,8 +213,8 @@ FRandom::~FRandom () FRandom *last = NULL; - prev = &RNGList; - rng = RNGList; + prev = bClient ? &CRNGList : &RNGList; + rng = bClient ? CRNGList : RNGList; while (rng != NULL && rng != this) { @@ -237,6 +245,11 @@ void FRandom::StaticClearRandom () { rng->Init(rngseed); } + + for (FRandom* rng = FRandom::CRNGList; rng != NULL; rng = rng->Next) + { + rng->Init(rngseed); + } } //========================================================================== @@ -345,15 +358,15 @@ void FRandom::StaticReadRNGState(FSerializer &arc) // //========================================================================== -FRandom *FRandom::StaticFindRNG (const char *name) +FRandom *FRandom::StaticFindRNG (const char *name, bool client) { uint32_t NameCRC = CalcCRC32 ((const uint8_t *)name, (unsigned int)strlen (name)); // Use the default RNG if this one happens to have a CRC of 0. - if (NameCRC == 0) return &pr_exrandom; + if (NameCRC == 0) return client ? &M_Random : &pr_exrandom; // Find the RNG in the list, sorted by CRC - FRandom **prev = &RNGList, *probe = RNGList; + FRandom **prev = (client ? &CRNGList : &RNGList), *probe = (client ? CRNGList : RNGList); while (probe != NULL && probe->NameCRC < NameCRC) { @@ -364,10 +377,13 @@ FRandom *FRandom::StaticFindRNG (const char *name) if (probe == NULL || probe->NameCRC != NameCRC) { // A matching RNG doesn't exist yet so create it. - probe = new FRandom(name); + probe = new FRandom(name, client); // Store the new RNG for destruction when ZDoom quits. - NewRNGs.Push(probe); + if (client) + NewCRNGs.Push(probe); + else + NewRNGs.Push(probe); } return probe; } diff --git a/src/common/engine/m_random.h b/src/common/engine/m_random.h index d9eec6c44..991d812db 100644 --- a/src/common/engine/m_random.h +++ b/src/common/engine/m_random.h @@ -44,8 +44,8 @@ class FSerializer; class FRandom : public SFMTObj { public: - FRandom (); - FRandom (const char *name); + FRandom (bool client); + FRandom (const char *name, bool client); ~FRandom (); int Seed() const @@ -170,7 +170,9 @@ public: static void StaticClearRandom (); static void StaticReadRNGState (FSerializer &arc); static void StaticWriteRNGState (FSerializer &file); - static FRandom *StaticFindRNG(const char *name); + static FRandom *StaticFindRNG(const char *name, bool client); + static void SaveRNGState(TArray& backups); + static void RestoreRNGState(TArray& backups); #ifndef NDEBUG static void StaticPrintSeeds (); @@ -182,8 +184,9 @@ private: #endif FRandom *Next; uint32_t NameCRC; + bool bClient; - static FRandom *RNGList; + static FRandom *RNGList, *CRNGList; }; extern uint32_t rngseed; // The starting seed (not part of state) diff --git a/src/common/engine/namedef.h b/src/common/engine/namedef.h index 13827382c..be0c47649 100644 --- a/src/common/engine/namedef.h +++ b/src/common/engine/namedef.h @@ -41,6 +41,12 @@ xx(Random2) xx(RandomPick) xx(FRandomPick) xx(SetRandomSeed) +xx(CRandom) +xx(CFRandom) +xx(CRandom2) +xx(CRandomPick) +xx(CFRandomPick) +xx(CSetRandomSeed) xx(BuiltinRandomSeed) xx(BuiltinNew) xx(GetClass) diff --git a/src/common/scripting/backend/codegen.cpp b/src/common/scripting/backend/codegen.cpp index df1c48c22..86bd606f9 100644 --- a/src/common/scripting/backend/codegen.cpp +++ b/src/common/scripting/backend/codegen.cpp @@ -8268,8 +8268,12 @@ static bool CheckFunctionCompatiblity(FScriptPosition &ScriptPosition, PFunction FxFunctionCall::FxFunctionCall(FName methodname, FName rngname, FArgumentList &&args, const FScriptPosition &pos) : FxExpression(EFX_FunctionCall, pos) { + const bool isClient = methodname == NAME_CRandom || methodname == NAME_CFRandom + || methodname == NAME_CRandomPick || methodname == NAME_CFRandomPick + || methodname == NAME_CRandom2 || methodname == NAME_CSetRandomSeed; + MethodName = methodname; - RNG = &pr_exrandom; + RNG = isClient ? &M_Random : &pr_exrandom; ArgList = std::move(args); if (rngname != NAME_None) { @@ -8281,7 +8285,16 @@ FxFunctionCall::FxFunctionCall(FName methodname, FName rngname, FArgumentList && case NAME_FRandomPick: case NAME_Random2: case NAME_SetRandomSeed: - RNG = FRandom::StaticFindRNG(rngname.GetChars()); + RNG = FRandom::StaticFindRNG(rngname.GetChars(), false); + break; + + case NAME_CRandom: + case NAME_CFRandom: + case NAME_CRandomPick: + case NAME_CFRandomPick: + case NAME_CRandom2: + case NAME_CSetRandomSeed: + RNG = FRandom::StaticFindRNG(rngname.GetChars(), true); break; default: @@ -8547,13 +8560,22 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) } break; + case NAME_CSetRandomSeed: + if (CheckArgSize(NAME_CRandom, ArgList, 1, 1, ScriptPosition)) + { + func = new FxRandomSeed(RNG, ArgList[0], ScriptPosition, ctx.FromDecorate); + ArgList[0] = nullptr; + } + break; + case NAME_Random: + case NAME_CRandom: // allow calling Random without arguments to default to (0, 255) if (ArgList.Size() == 0) { func = new FxRandom(RNG, new FxConstant(0, ScriptPosition), new FxConstant(255, ScriptPosition), ScriptPosition, ctx.FromDecorate); } - else if (CheckArgSize(NAME_Random, ArgList, 2, 2, ScriptPosition)) + else if (CheckArgSize(MethodName, ArgList, 2, 2, ScriptPosition)) { func = new FxRandom(RNG, ArgList[0], ArgList[1], ScriptPosition, ctx.FromDecorate); ArgList[0] = ArgList[1] = nullptr; @@ -8561,7 +8583,8 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) break; case NAME_FRandom: - if (CheckArgSize(NAME_FRandom, ArgList, 2, 2, ScriptPosition)) + case NAME_CFRandom: + if (CheckArgSize(MethodName, ArgList, 2, 2, ScriptPosition)) { func = new FxFRandom(RNG, ArgList[0], ArgList[1], ScriptPosition); ArgList[0] = ArgList[1] = nullptr; @@ -8570,14 +8593,17 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) case NAME_RandomPick: case NAME_FRandomPick: + case NAME_CRandomPick: + case NAME_CFRandomPick: if (CheckArgSize(MethodName, ArgList, 1, -1, ScriptPosition)) { - func = new FxRandomPick(RNG, ArgList, MethodName == NAME_FRandomPick, ScriptPosition, ctx.FromDecorate); + func = new FxRandomPick(RNG, ArgList, MethodName == NAME_FRandomPick || MethodName == NAME_CFRandomPick, ScriptPosition, ctx.FromDecorate); } break; case NAME_Random2: - if (CheckArgSize(NAME_Random2, ArgList, 0, 1, ScriptPosition)) + case NAME_CRandom2: + if (CheckArgSize(MethodName, ArgList, 0, 1, ScriptPosition)) { func = new FxRandom2(RNG, ArgList.Size() == 0? nullptr : ArgList[0], ScriptPosition, ctx.FromDecorate); if (ArgList.Size() > 0) ArgList[0] = nullptr; diff --git a/src/d_netinfo.cpp b/src/d_netinfo.cpp index bac6eddfe..369abcca3 100644 --- a/src/d_netinfo.cpp +++ b/src/d_netinfo.cpp @@ -52,7 +52,7 @@ #include "gstrings.h" #include "g_game.h" -static FRandom pr_pickteam ("PickRandomTeam"); +static FRandom pr_pickteam ("PickRandomTeam", false); CVAR (Float, autoaim, 35.f, CVAR_USERINFO | CVAR_ARCHIVE); CVAR (String, name, "Player", CVAR_USERINFO | CVAR_ARCHIVE); diff --git a/src/g_game.cpp b/src/g_game.cpp index 42ce6e99a..774c7b5b2 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -93,8 +93,8 @@ #include "fs_findfile.h" -static FRandom pr_dmspawn ("DMSpawn"); -static FRandom pr_pspawn ("PlayerSpawn"); +static FRandom pr_dmspawn ("DMSpawn", false); +static FRandom pr_pspawn ("PlayerSpawn", false); extern int startpos, laststartpos; diff --git a/src/g_level.cpp b/src/g_level.cpp index bc0cd378a..0cf5ddb21 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -175,7 +175,7 @@ ELightMode getRealLightmode(FLevelLocals* Level, bool for3d) CVAR(Int, sv_alwaystally, 0, CVAR_SERVERINFO) -static FRandom pr_classchoice ("RandomPlayerClassChoice"); +static FRandom pr_classchoice ("RandomPlayerClassChoice", false); extern level_info_t TheDefaultLevelInfo; extern bool timingdemo; diff --git a/src/g_statusbar/sbarinfo_commands.cpp b/src/g_statusbar/sbarinfo_commands.cpp index 749294adc..85944b647 100644 --- a/src/g_statusbar/sbarinfo_commands.cpp +++ b/src/g_statusbar/sbarinfo_commands.cpp @@ -3227,7 +3227,7 @@ class CommandDrawGem : public SBarInfoCommand int chainWiggle; static FRandom pr_chainwiggle; }; -FRandom CommandDrawGem::pr_chainwiggle; //use the same method of chain wiggling as heretic. +FRandom CommandDrawGem::pr_chainwiggle(true); //use the same method of chain wiggling as heretic. //////////////////////////////////////////////////////////////////////////////// diff --git a/src/gamedata/decallib.cpp b/src/gamedata/decallib.cpp index 6243502f8..2babc3b45 100644 --- a/src/gamedata/decallib.cpp +++ b/src/gamedata/decallib.cpp @@ -60,8 +60,8 @@ static TArray DecalTranslations; // Sometimes two machines in a game will disagree on the state of // decals. I do not know why. -static FRandom pr_decalchoice ("DecalChoice"); -static FRandom pr_decal ("Decal"); +static FRandom pr_decalchoice ("DecalChoice", true); +static FRandom pr_decal ("Decal", true); class FDecalGroup : public FDecalBase { diff --git a/src/gamedata/info.cpp b/src/gamedata/info.cpp index 67fb87f67..6cff5943e 100644 --- a/src/gamedata/info.cpp +++ b/src/gamedata/info.cpp @@ -61,7 +61,7 @@ extern void InitBotStuff(); extern void ClearStrifeTypes(); TArray PClassActor::AllActorClasses; -FRandom FState::pr_statetics("StateTics"); +FRandom FState::pr_statetics("StateTics", false); cycle_t ActionCycles; diff --git a/src/gamedata/textures/animations.cpp b/src/gamedata/textures/animations.cpp index b0dce0a55..5cd072b14 100644 --- a/src/gamedata/textures/animations.cpp +++ b/src/gamedata/textures/animations.cpp @@ -56,7 +56,7 @@ FTextureAnimator TexAnim; // PRIVATE DATA DEFINITIONS ------------------------------------------------ -static FRandom pr_animatepictures ("AnimatePics"); +static FRandom pr_animatepictures ("AnimatePics", true); // CODE -------------------------------------------------------------------- diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index f8ee0a8e5..f897db759 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -62,7 +62,7 @@ #include "doommenu.h" #include "g_game.h" -static FRandom pr_randomspeech("RandomSpeech"); +static FRandom pr_randomspeech("RandomSpeech", true); static int ConversationMenuY; diff --git a/src/playsim/a_dynlight.cpp b/src/playsim/a_dynlight.cpp index 3dc653898..1470b0796 100644 --- a/src/playsim/a_dynlight.cpp +++ b/src/playsim/a_dynlight.cpp @@ -67,7 +67,7 @@ static FMemArena DynLightArena(sizeof(FDynamicLight) * 200); static TArray FreeList; -static FRandom randLight; +static FRandom randLight(true); extern TArray StateLights; diff --git a/src/playsim/a_specialspot.cpp b/src/playsim/a_specialspot.cpp index b658c1830..b332b7800 100644 --- a/src/playsim/a_specialspot.cpp +++ b/src/playsim/a_specialspot.cpp @@ -39,7 +39,7 @@ #include "a_pickups.h" #include "vm.h" -static FRandom pr_spot ("SpecialSpot"); +static FRandom pr_spot ("SpecialSpot", false); IMPLEMENT_CLASS(DSpotState, false, false) diff --git a/src/playsim/bots/b_func.cpp b/src/playsim/bots/b_func.cpp index e537bf9f7..fa9f2c80d 100644 --- a/src/playsim/bots/b_func.cpp +++ b/src/playsim/bots/b_func.cpp @@ -54,7 +54,7 @@ #include "p_checkposition.h" #include "actorinlines.h" -static FRandom pr_botdofire ("BotDoFire"); +static FRandom pr_botdofire ("BotDoFire", false); //Checks TRUE reachability from bot to a looker. diff --git a/src/playsim/bots/b_game.cpp b/src/playsim/bots/b_game.cpp index 3863ac923..eb8eb5d1a 100644 --- a/src/playsim/bots/b_game.cpp +++ b/src/playsim/bots/b_game.cpp @@ -98,7 +98,7 @@ Everything that is changed is marked (maybe commented) with "Added by MC" #include "i_system.h" // for SHARE_DIR #endif // !_WIN32 && !__APPLE__ -static FRandom pr_botspawn ("BotSpawn"); +static FRandom pr_botspawn ("BotSpawn", false); cycle_t BotThinkCycles, BotSupportCycles; int BotWTG; diff --git a/src/playsim/bots/b_move.cpp b/src/playsim/bots/b_move.cpp index 4d91839d8..092261832 100644 --- a/src/playsim/bots/b_move.cpp +++ b/src/playsim/bots/b_move.cpp @@ -53,9 +53,9 @@ #include "p_checkposition.h" #include "actorinlines.h" -static FRandom pr_botopendoor ("BotOpenDoor"); -static FRandom pr_bottrywalk ("BotTryWalk"); -static FRandom pr_botnewchasedir ("BotNewChaseDir"); +static FRandom pr_botopendoor ("BotOpenDoor", false); +static FRandom pr_bottrywalk ("BotTryWalk", false); +static FRandom pr_botnewchasedir ("BotNewChaseDir", false); // borrow some tables from p_enemy.cpp extern dirtype_t opposite[9]; diff --git a/src/playsim/bots/b_think.cpp b/src/playsim/bots/b_think.cpp index 9fba192d5..deef49aa1 100644 --- a/src/playsim/bots/b_think.cpp +++ b/src/playsim/bots/b_think.cpp @@ -52,7 +52,7 @@ #include "d_player.h" #include "actorinlines.h" -static FRandom pr_botmove ("BotMove"); +static FRandom pr_botmove ("BotMove", false); //This function is called each tic for each bot, //so this is what the bot does. diff --git a/src/playsim/fragglescript/t_func.cpp b/src/playsim/fragglescript/t_func.cpp index f9fff1b9e..3a463c3a2 100644 --- a/src/playsim/fragglescript/t_func.cpp +++ b/src/playsim/fragglescript/t_func.cpp @@ -56,7 +56,7 @@ using namespace FileSys; -static FRandom pr_script("FScript"); +static FRandom pr_script("FScript", false); // functions. FParser::SF_ means Script Function not, well.. heh, me diff --git a/src/playsim/mapthinkers/a_lightning.cpp b/src/playsim/mapthinkers/a_lightning.cpp index f6e0f713d..47f6623b1 100644 --- a/src/playsim/mapthinkers/a_lightning.cpp +++ b/src/playsim/mapthinkers/a_lightning.cpp @@ -38,7 +38,7 @@ #include "gi.h" #include -static FRandom pr_lightning ("Lightning"); +static FRandom pr_lightning ("Lightning", false); IMPLEMENT_CLASS(DLightningThinker, false, false) diff --git a/src/playsim/mapthinkers/a_lights.cpp b/src/playsim/mapthinkers/a_lights.cpp index 9cd7fb20f..48acdcd76 100644 --- a/src/playsim/mapthinkers/a_lights.cpp +++ b/src/playsim/mapthinkers/a_lights.cpp @@ -43,10 +43,10 @@ // State. #include "serializer.h" -static FRandom pr_flicker ("Flicker"); -static FRandom pr_lightflash ("LightFlash"); -static FRandom pr_strobeflash ("StrobeFlash"); -static FRandom pr_fireflicker ("FireFlicker"); +static FRandom pr_flicker ("Flicker", true); +static FRandom pr_lightflash ("LightFlash", true); +static FRandom pr_strobeflash ("StrobeFlash", true); +static FRandom pr_fireflicker ("FireFlicker", true); //----------------------------------------------------------------------------- diff --git a/src/playsim/mapthinkers/a_plats.cpp b/src/playsim/mapthinkers/a_plats.cpp index c688295e4..0f6fa9ce9 100644 --- a/src/playsim/mapthinkers/a_plats.cpp +++ b/src/playsim/mapthinkers/a_plats.cpp @@ -37,7 +37,7 @@ #include "p_spec.h" #include "g_levellocals.h" -static FRandom pr_doplat ("DoPlat"); +static FRandom pr_doplat ("DoPlat", false); IMPLEMENT_CLASS(DPlat, false, false) diff --git a/src/playsim/mapthinkers/a_quake.cpp b/src/playsim/mapthinkers/a_quake.cpp index b21951562..e6fb687fa 100644 --- a/src/playsim/mapthinkers/a_quake.cpp +++ b/src/playsim/mapthinkers/a_quake.cpp @@ -36,7 +36,7 @@ #include "actorinlines.h" #include -static FRandom pr_quake ("Quake"); +static FRandom pr_quake ("Quake", true); IMPLEMENT_CLASS(DEarthquake, false, true) diff --git a/src/playsim/p_acs.cpp b/src/playsim/p_acs.cpp index 89aee643d..211b155c2 100644 --- a/src/playsim/p_acs.cpp +++ b/src/playsim/p_acs.cpp @@ -540,7 +540,7 @@ -FRandom pr_acs ("ACS"); +FRandom pr_acs ("ACS", false); // I imagine this much stack space is probably overkill, but it could // potentially get used with recursive functions. diff --git a/src/playsim/p_actionfunctions.cpp b/src/playsim/p_actionfunctions.cpp index ea7090c1d..91bff0bc2 100644 --- a/src/playsim/p_actionfunctions.cpp +++ b/src/playsim/p_actionfunctions.cpp @@ -73,19 +73,19 @@ #include "shadowinlines.h" #include "i_time.h" -static FRandom pr_camissile ("CustomActorfire"); -static FRandom pr_cabullet ("CustomBullet"); -static FRandom pr_cwjump ("CustomWpJump"); -static FRandom pr_cwpunch ("CustomWpPunch"); -static FRandom pr_grenade ("ThrowGrenade"); - FRandom pr_crailgun ("CustomRailgun"); -static FRandom pr_spawndebris ("SpawnDebris"); -static FRandom pr_spawnitemex ("SpawnItemEx"); -static FRandom pr_burst ("Burst"); -static FRandom pr_monsterrefire ("MonsterRefire"); -static FRandom pr_teleport("A_Teleport"); -static FRandom pr_bfgselfdamage("BFGSelfDamage"); - FRandom pr_cajump("CustomJump"); +static FRandom pr_camissile ("CustomActorfire", false); +static FRandom pr_cabullet ("CustomBullet", false); +static FRandom pr_cwjump ("CustomWpJump", false); +static FRandom pr_cwpunch ("CustomWpPunch", false); +static FRandom pr_grenade ("ThrowGrenade", false); + FRandom pr_crailgun ("CustomRailgun", false); +static FRandom pr_spawndebris ("SpawnDebris", false); +static FRandom pr_spawnitemex ("SpawnItemEx", false); +static FRandom pr_burst ("Burst", false); +static FRandom pr_monsterrefire ("MonsterRefire", false); +static FRandom pr_teleport("A_Teleport", false); +static FRandom pr_bfgselfdamage("BFGSelfDamage", false); + FRandom pr_cajump("CustomJump", false); //========================================================================== // @@ -746,7 +746,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_StopSoundEx) // Generic seeker missile function // //========================================================================== -static FRandom pr_seekermissile ("SeekerMissile"); +static FRandom pr_seekermissile ("SeekerMissile", false); enum { SMF_LOOK = 1, diff --git a/src/playsim/p_effect.cpp b/src/playsim/p_effect.cpp index f96ec1301..31b3e3128 100644 --- a/src/playsim/p_effect.cpp +++ b/src/playsim/p_effect.cpp @@ -65,7 +65,7 @@ CVAR (Int, r_rail_trailsparsity, 1, CVAR_ARCHIVE); CVAR (Bool, r_particles, true, 0); EXTERN_CVAR(Int, r_maxparticles); -FRandom pr_railtrail("RailTrail"); +FRandom pr_railtrail("RailTrail", true); #define FADEFROMTTL(a) (1.f/(a)) diff --git a/src/playsim/p_enemy.cpp b/src/playsim/p_enemy.cpp index 120f37231..d3a5a66b2 100644 --- a/src/playsim/p_enemy.cpp +++ b/src/playsim/p_enemy.cpp @@ -54,26 +54,26 @@ #include "gi.h" -static FRandom pr_checkmissilerange ("CheckMissileRange"); -static FRandom pr_opendoor ("OpenDoor"); -static FRandom pr_trywalk ("TryWalk"); -static FRandom pr_newchasedir ("NewChaseDir"); -static FRandom pr_lookformonsters ("LookForMonsters"); -static FRandom pr_lookforplayers ("LookForPlayers"); -static FRandom pr_scaredycat ("Anubis"); - FRandom pr_chase ("Chase"); - FRandom pr_facetarget ("FaceTarget"); - FRandom pr_railface ("RailFace"); -static FRandom pr_look2 ("LookyLooky"); -static FRandom pr_look3 ("IGotHooky"); -static FRandom pr_slook ("SlooK"); -static FRandom pr_dropoff ("Dropoff"); -static FRandom pr_defect ("Defect"); -static FRandom pr_avoidcrush("AvoidCrush"); -static FRandom pr_stayonlift("StayOnLift"); +static FRandom pr_checkmissilerange ("CheckMissileRange", false); +static FRandom pr_opendoor ("OpenDoor", false); +static FRandom pr_trywalk ("TryWalk", false); +static FRandom pr_newchasedir ("NewChaseDir", false); +static FRandom pr_lookformonsters ("LookForMonsters", false); +static FRandom pr_lookforplayers ("LookForPlayers", false); +static FRandom pr_scaredycat ("Anubis", false); + FRandom pr_chase ("Chase", false); + FRandom pr_facetarget ("FaceTarget", false); + FRandom pr_railface ("RailFace", false); +static FRandom pr_look2 ("LookyLooky", false); +static FRandom pr_look3 ("IGotHooky", false); +static FRandom pr_slook ("SlooK", false); +static FRandom pr_dropoff ("Dropoff", false); +static FRandom pr_defect ("Defect", false); +static FRandom pr_avoidcrush("AvoidCrush", false); +static FRandom pr_stayonlift("StayOnLift", false); -static FRandom pr_skiptarget("SkipTarget"); -static FRandom pr_enemystrafe("EnemyStrafe"); +static FRandom pr_skiptarget("SkipTarget", false); +static FRandom pr_enemystrafe("EnemyStrafe", false); // movement interpolation is fine for objects that are moved by their own // velocity. But for monsters it is problematic. diff --git a/src/playsim/p_interaction.cpp b/src/playsim/p_interaction.cpp index 0ae77e914..eed16b87f 100644 --- a/src/playsim/p_interaction.cpp +++ b/src/playsim/p_interaction.cpp @@ -63,12 +63,12 @@ #include "actorinlines.h" #include "d_main.h" -static FRandom pr_botrespawn ("BotRespawn"); -static FRandom pr_killmobj ("ActorDie"); -FRandom pr_damagemobj ("ActorTakeDamage"); -static FRandom pr_lightning ("LightningDamage"); -static FRandom pr_poison ("PoisonDamage"); -static FRandom pr_switcher ("SwitchTarget"); +static FRandom pr_botrespawn ("BotRespawn", false); +static FRandom pr_killmobj ("ActorDie", false); +FRandom pr_damagemobj ("ActorTakeDamage", false); +static FRandom pr_lightning ("LightningDamage", false); +static FRandom pr_poison ("PoisonDamage", false); +static FRandom pr_switcher ("SwitchTarget", false); CVAR (Bool, cl_showsprees, true, CVAR_ARCHIVE) CVAR (Bool, cl_showmultikills, true, CVAR_ARCHIVE) diff --git a/src/playsim/p_lnspec.cpp b/src/playsim/p_lnspec.cpp index 00318dfbb..c0a399785 100644 --- a/src/playsim/p_lnspec.cpp +++ b/src/playsim/p_lnspec.cpp @@ -95,7 +95,7 @@ static DCeiling::ECrushMode CRUSHTYPE(int a, bool withslowdown) return withslowdown? DCeiling::ECrushMode::crushSlowdown : DCeiling::ECrushMode::crushDoom; } -static FRandom pr_glass ("GlassBreak"); +static FRandom pr_glass ("GlassBreak", false); // There are aliases for the ACS specials that take names instead of numbers. // This table maps them onto the real number-based specials. diff --git a/src/playsim/p_map.cpp b/src/playsim/p_map.cpp index 589204993..197ab55f1 100644 --- a/src/playsim/p_map.cpp +++ b/src/playsim/p_map.cpp @@ -103,10 +103,10 @@ static void CheckForPushSpecial(line_t *line, int side, AActor *mobj, DVector2 * static void SpawnShootDecal(AActor *t1, AActor *defaults, const FTraceResults &trace); static void SpawnDeepSplash(AActor *t1, const FTraceResults &trace, AActor *puff); -static FRandom pr_tracebleed("TraceBleed"); -static FRandom pr_checkthing("CheckThing"); -static FRandom pr_lineattack("LineAttack"); -static FRandom pr_crunch("DoCrunch"); +static FRandom pr_tracebleed("TraceBleed", false); +static FRandom pr_checkthing("CheckThing", false); +static FRandom pr_lineattack("LineAttack", false); +static FRandom pr_crunch("DoCrunch", false); // keep track of special lines as they are hit, // but don't process them until the move is proven valid diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index 0f9a91803..bb8d3be1a 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -122,29 +122,29 @@ EXTERN_CVAR (Int, cl_rockettrails) // PRIVATE DATA DEFINITIONS ------------------------------------------------ -static FRandom pr_explodemissile ("ExplodeMissile"); -static FRandom pr_reflect ("Reflect"); -static FRandom pr_nightmarerespawn ("NightmareRespawn"); -static FRandom pr_botspawnmobj ("BotSpawnActor"); -static FRandom pr_spawnmapthing ("SpawnMapThing"); -static FRandom pr_spawnpuff ("SpawnPuff"); -static FRandom pr_spawnblood ("SpawnBlood"); -static FRandom pr_splatter ("BloodSplatter"); -static FRandom pr_takedamage ("TakeDamage"); -static FRandom pr_splat ("FAxeSplatter"); -static FRandom pr_ripperblood ("RipperBlood"); -static FRandom pr_chunk ("Chunk"); -static FRandom pr_checkmissilespawn ("CheckMissileSpawn"); -static FRandom pr_missiledamage ("MissileDamage"); -static FRandom pr_multiclasschoice ("MultiClassChoice"); -static FRandom pr_rockettrail("RocketTrail"); -static FRandom pr_uniquetid("UniqueTID"); +static FRandom pr_explodemissile ("ExplodeMissile", false); +static FRandom pr_reflect ("Reflect", false); +static FRandom pr_nightmarerespawn ("NightmareRespawn", false); +static FRandom pr_botspawnmobj ("BotSpawnActor", false); +static FRandom pr_spawnmapthing ("SpawnMapThing", false); +static FRandom pr_spawnpuff ("SpawnPuff", false); +static FRandom pr_spawnblood ("SpawnBlood", false); +static FRandom pr_splatter ("BloodSplatter", false); +static FRandom pr_takedamage ("TakeDamage", false); +static FRandom pr_splat ("FAxeSplatter", false); +static FRandom pr_ripperblood ("RipperBlood", false); +static FRandom pr_chunk ("Chunk", false); +static FRandom pr_checkmissilespawn ("CheckMissileSpawn", false); +static FRandom pr_missiledamage ("MissileDamage", false); +static FRandom pr_multiclasschoice ("MultiClassChoice", false); +static FRandom pr_rockettrail("RocketTrail", false); +static FRandom pr_uniquetid("UniqueTID", false); // PUBLIC DATA DEFINITIONS ------------------------------------------------- -FRandom pr_spawnmobj ("SpawnActor"); -FRandom pr_bounce("Bounce"); -FRandom pr_spawnmissile("SpawnMissile"); +FRandom pr_spawnmobj ("SpawnActor", false); +FRandom pr_bounce("Bounce", false); +FRandom pr_spawnmissile("SpawnMissile", false); CUSTOM_CVAR (Float, sv_gravity, 800.f, CVAR_SERVERINFO|CVAR_NOSAVE|CVAR_NOINITCALL) { @@ -7956,7 +7956,7 @@ void AActor::SetTranslation(FName trname) // PROP A_RestoreSpecialPosition // //--------------------------------------------------------------------------- -static FRandom pr_restore("RestorePos"); +static FRandom pr_restore("RestorePos", false); void AActor::RestoreSpecialPosition() { diff --git a/src/playsim/p_sight.cpp b/src/playsim/p_sight.cpp index 2cf957c8c..a2fc76c46 100644 --- a/src/playsim/p_sight.cpp +++ b/src/playsim/p_sight.cpp @@ -37,8 +37,8 @@ #include "g_levellocals.h" #include "actorinlines.h" -static FRandom pr_botchecksight ("BotCheckSight"); -static FRandom pr_checksight ("CheckSight"); +static FRandom pr_botchecksight ("BotCheckSight", false); +static FRandom pr_checksight ("CheckSight", false); /* ============================================================================== diff --git a/src/playsim/p_spec.cpp b/src/playsim/p_spec.cpp index 3851bd748..385d17f92 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_actorinspecialsector ("ActorInSpecialSector", false); EXTERN_CVAR(Bool, cl_predict_specials) EXTERN_CVAR(Bool, forcewater) diff --git a/src/playsim/p_switch.cpp b/src/playsim/p_switch.cpp index e89f03011..2af3054d3 100644 --- a/src/playsim/p_switch.cpp +++ b/src/playsim/p_switch.cpp @@ -49,7 +49,7 @@ #include "actorinlines.h" #include "animations.h" -static FRandom pr_switchanim ("AnimSwitch"); +static FRandom pr_switchanim ("AnimSwitch", true); class DActiveButton : public DThinker { diff --git a/src/playsim/p_teleport.cpp b/src/playsim/p_teleport.cpp index a69d3654c..c39c6df1d 100644 --- a/src/playsim/p_teleport.cpp +++ b/src/playsim/p_teleport.cpp @@ -36,7 +36,8 @@ #define FUDGEFACTOR 10 -static FRandom pr_teleport ("Teleport"); +static FRandom pr_teleport ("Teleport", false); +static FRandom pr_playerteleport("PlayerTeleport", false); CVAR (Bool, telezoom, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG); diff --git a/src/playsim/p_things.cpp b/src/playsim/p_things.cpp index 3391030aa..878366d7b 100644 --- a/src/playsim/p_things.cpp +++ b/src/playsim/p_things.cpp @@ -47,7 +47,7 @@ #include "actorinlines.h" #include "vm.h" -static FRandom pr_leadtarget ("LeadTarget"); +static FRandom pr_leadtarget ("LeadTarget", false); bool FLevelLocals::EV_Thing_Spawn (int tid, AActor *source, int type, DAngle angle, bool fog, int newtid) { diff --git a/src/playsim/p_user.cpp b/src/playsim/p_user.cpp index a98a7c523..463d8f6e3 100644 --- a/src/playsim/p_user.cpp +++ b/src/playsim/p_user.cpp @@ -95,7 +95,7 @@ #include "s_music.h" #include "d_main.h" -static FRandom pr_skullpop ("SkullPop"); +static FRandom pr_skullpop ("SkullPop", false); // [SP] Allows respawn in single player CVAR(Bool, sv_singleplayerrespawn, false, CVAR_SERVERINFO | CVAR_CHEAT) diff --git a/src/playsim/shadowinlines.h b/src/playsim/shadowinlines.h index b36b051ac..6c0e9176f 100644 --- a/src/playsim/shadowinlines.h +++ b/src/playsim/shadowinlines.h @@ -17,7 +17,7 @@ extern FRandom pr_spawnmissile; extern FRandom pr_facetarget; extern FRandom pr_railface; extern FRandom pr_crailgun; -inline FRandom pr_shadowaimz("VerticalShadowAim"); +inline FRandom pr_shadowaimz("VerticalShadowAim", false); //========================================================================== // diff --git a/src/rendering/r_utility.cpp b/src/rendering/r_utility.cpp index 5313f738c..7311341e6 100644 --- a/src/rendering/r_utility.cpp +++ b/src/rendering/r_utility.cpp @@ -94,8 +94,8 @@ struct InterpolationViewer // PRIVATE DATA DECLARATIONS ----------------------------------------------- static TArray PastViewers; -static FRandom pr_torchflicker ("TorchFlicker"); -static FRandom pr_hom; +static FRandom pr_torchflicker ("TorchFlicker", true); +static FRandom pr_hom(true); bool NoInterpolateView; // GL needs access to this. static TArray InterpolationPath; diff --git a/src/scripting/decorate/thingdef_exp.cpp b/src/scripting/decorate/thingdef_exp.cpp index 1b27342be..831fcf0c6 100644 --- a/src/scripting/decorate/thingdef_exp.cpp +++ b/src/scripting/decorate/thingdef_exp.cpp @@ -47,9 +47,9 @@ extern FRandom pr_exrandom; -static FxExpression *ParseRandom(FScanner &sc, FName identifier, PClassActor *cls); -static FxExpression *ParseRandomPick(FScanner &sc, FName identifier, PClassActor *cls); -static FxExpression *ParseRandom2(FScanner &sc, PClassActor *cls); +static FxExpression *ParseRandom(FScanner &sc, FName identifier, PClassActor *cls, bool client); +static FxExpression *ParseRandomPick(FScanner &sc, FName identifier, PClassActor *cls, bool client); +static FxExpression *ParseRandom2(FScanner &sc, PClassActor *cls, bool client); static FxExpression *ParseAbs(FScanner &sc, PClassActor *cls); static FxExpression *ParseAtan2(FScanner &sc, FName identifier, PClassActor *cls); static FxExpression *ParseMinMax(FScanner &sc, FName identifier, PClassActor *cls); @@ -491,12 +491,17 @@ static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls) { case NAME_Random: case NAME_FRandom: - return ParseRandom(sc, identifier, cls); + case NAME_CRandom: + case NAME_CFRandom: + return ParseRandom(sc, identifier, cls, identifier == NAME_CRandom || identifier == NAME_CFRandom); case NAME_RandomPick: case NAME_FRandomPick: - return ParseRandomPick(sc, identifier, cls); + case NAME_CRandomPick: + case NAME_CFRandomPick: + return ParseRandomPick(sc, identifier, cls, identifier == NAME_CRandomPick || identifier == NAME_CFRandomPick); case NAME_Random2: - return ParseRandom2(sc, cls); + case NAME_CRandom2: + return ParseRandom2(sc, cls, identifier == NAME_CRandom2); default: if (cls != nullptr) { @@ -559,14 +564,14 @@ static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls) return NULL; } -static FRandom *ParseRNG(FScanner &sc) +static FRandom *ParseRNG(FScanner &sc, bool client) { FRandom *rng; if (sc.CheckToken('[')) { sc.MustGetToken(TK_Identifier); - rng = FRandom::StaticFindRNG(sc.String); + rng = FRandom::StaticFindRNG(sc.String, client); sc.MustGetToken(']'); } else @@ -576,9 +581,9 @@ static FRandom *ParseRNG(FScanner &sc) return rng; } -static FxExpression *ParseRandom(FScanner &sc, FName identifier, PClassActor *cls) +static FxExpression *ParseRandom(FScanner &sc, FName identifier, PClassActor *cls, bool client) { - FRandom *rng = ParseRNG(sc); + FRandom *rng = ParseRNG(sc, client); sc.MustGetToken('('); FxExpression *min = ParseExpressionM (sc, cls); @@ -586,7 +591,7 @@ static FxExpression *ParseRandom(FScanner &sc, FName identifier, PClassActor *cl FxExpression *max = ParseExpressionM (sc, cls); sc.MustGetToken(')'); - if (identifier == NAME_Random) + if (identifier == NAME_Random || identifier == NAME_CRandom) { return new FxRandom(rng, min, max, sc, true); } @@ -596,7 +601,7 @@ static FxExpression *ParseRandom(FScanner &sc, FName identifier, PClassActor *cl } } -static FxExpression *ParseRandomPick(FScanner &sc, FName identifier, PClassActor *cls) +static FxExpression *ParseRandomPick(FScanner &sc, FName identifier, PClassActor *cls, bool client) { bool floaty = identifier == NAME_FRandomPick; FRandom *rng; @@ -604,7 +609,7 @@ static FxExpression *ParseRandomPick(FScanner &sc, FName identifier, PClassActor list.Clear(); int index = 0; - rng = ParseRNG(sc); + rng = ParseRNG(sc, client); sc.MustGetToken('('); for (;;) @@ -618,9 +623,9 @@ static FxExpression *ParseRandomPick(FScanner &sc, FName identifier, PClassActor return new FxRandomPick(rng, list, floaty, sc, true); } -static FxExpression *ParseRandom2(FScanner &sc, PClassActor *cls) +static FxExpression *ParseRandom2(FScanner &sc, PClassActor *cls, bool client) { - FRandom *rng = ParseRNG(sc); + FRandom *rng = ParseRNG(sc, client); FxExpression *mask = NULL; sc.MustGetToken('('); diff --git a/src/sound/s_doomsound.cpp b/src/sound/s_doomsound.cpp index 33604ce61..4b2d597bc 100644 --- a/src/sound/s_doomsound.cpp +++ b/src/sound/s_doomsound.cpp @@ -1163,7 +1163,7 @@ TArray DoomSoundEngine::ReadSound(int lumpnum) // This is overridden to use a synchronized RNG. // //========================================================================== -static FRandom pr_randsound("RandSound"); +static FRandom pr_randsound("RandSound", true); FSoundID DoomSoundEngine::PickReplacement(FSoundID refid) { diff --git a/src/sound/s_sndseq.cpp b/src/sound/s_sndseq.cpp index 99b58a8f9..cfe8ed9c1 100644 --- a/src/sound/s_sndseq.cpp +++ b/src/sound/s_sndseq.cpp @@ -288,7 +288,7 @@ static const hexenseq_t HexenSequences[] = { static int SeqTrans[MAX_SNDSEQS*3]; -static FRandom pr_sndseq ("SndSeq"); +static FRandom pr_sndseq ("SndSeq", true); // CODE -------------------------------------------------------------------- diff --git a/wadsrc/static/zscript/engine/base.zs b/wadsrc/static/zscript/engine/base.zs index e25c82229..8abd04ee3 100644 --- a/wadsrc/static/zscript/engine/base.zs +++ b/wadsrc/static/zscript/engine/base.zs @@ -788,7 +788,9 @@ class Object native // // Intrinsic random number generation functions. Note that the square // bracket syntax for specifying an RNG ID is only available for these - // functions. + // functions. If the function is prefixed with a C, this is a client-side RNG + // call that isn't backed up while predicting and has a unique name space from + // regular RNG calls. This should be used for things like HUD elements. // clearscope void SetRandomSeed[Name rngId = 'None'](int seed); // Set the seed for the given RNG. // clearscope int Random[Name rngId = 'None'](int min, int max); // Use the given RNG to generate a random integer number in the range (min, max) inclusive. // clearscope int Random2[Name rngId = 'None'](int mask); // Use the given RNG to generate a random integer number, and do a "union" (bitwise AND, AKA &) operation with the bits in the mask integer. diff --git a/wadsrc/static/zscript/ui/menu/conversationmenu.zs b/wadsrc/static/zscript/ui/menu/conversationmenu.zs index 1b1d3c011..4e8210b1a 100644 --- a/wadsrc/static/zscript/ui/menu/conversationmenu.zs +++ b/wadsrc/static/zscript/ui/menu/conversationmenu.zs @@ -216,11 +216,11 @@ class ConversationMenu : Menu let goodbyestr = mCurNode.Goodbye; if (goodbyestr.Length() == 0) { - goodbyestr = String.Format("$TXT_RANDOMGOODBYE_%d", Random[RandomSpeech](1, NUM_RANDOM_GOODBYES)); + goodbyestr = String.Format("$TXT_RANDOMGOODBYE_%d", CRandom[RandomSpeech](1, NUM_RANDOM_GOODBYES)); } else if (goodbyestr.Left(7) == "RANDOM_") { - goodbyestr = String.Format("$TXT_%s_%02d", goodbyestr, Random[RandomSpeech](1, NUM_RANDOM_LINES)); + goodbyestr = String.Format("$TXT_%s_%02d", goodbyestr, CRandom[RandomSpeech](1, NUM_RANDOM_LINES)); } goodbyestr = Stringtable.Localize(goodbyestr); if (goodbyestr.Length() == 0 || goodbyestr.Left(1) == "$") goodbyestr = "Bye."; @@ -254,7 +254,7 @@ class ConversationMenu : Menu String toSay = mCurNode.Dialogue; if (toSay.Left(7) == "RANDOM_") { - let dlgtext = String.Format("$TXT_%s_%02d", toSay, random[RandomSpeech](1, NUM_RANDOM_LINES)); + let dlgtext = String.Format("$TXT_%s_%02d", toSay, crandom[RandomSpeech](1, NUM_RANDOM_LINES)); toSay = Stringtable.Localize(dlgtext); if (toSay.Left(1) == "$") toSay = Stringtable.Localize("$TXT_GOAWAY"); } diff --git a/wadsrc/static/zscript/ui/statusbar/heretic_sbar.zs b/wadsrc/static/zscript/ui/statusbar/heretic_sbar.zs index 62cc27efa..135b711c2 100644 --- a/wadsrc/static/zscript/ui/statusbar/heretic_sbar.zs +++ b/wadsrc/static/zscript/ui/statusbar/heretic_sbar.zs @@ -45,7 +45,7 @@ class HereticStatusBar : BaseStatusBar // wiggle the chain if it moves if (Level.time & 1) { - wiggle = (mHealthInterpolator.GetValue() != CPlayer.health) && Random[ChainWiggle](0, 1); + wiggle = (mHealthInterpolator.GetValue() != CPlayer.health) && CRandom[ChainWiggle](0, 1); } } From a1a4a97dcd2715ee4a1a062a0557d3d1790a1c66 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Mon, 4 Nov 2024 13:15:47 -0500 Subject: [PATCH 85/93] Added RNG snapshotting for predicting Allows RNG seeds to be played back in a predictive way paving the road for predictive behaviors that rely on RNG. --- src/common/engine/m_random.cpp | 15 +++++++++++++++ src/g_levellocals.h | 2 +- src/playsim/p_teleport.cpp | 7 ++++--- src/playsim/p_user.cpp | 6 ++++++ 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/common/engine/m_random.cpp b/src/common/engine/m_random.cpp index df4d53217..ee29a8055 100644 --- a/src/common/engine/m_random.cpp +++ b/src/common/engine/m_random.cpp @@ -388,6 +388,21 @@ FRandom *FRandom::StaticFindRNG (const char *name, bool client) return probe; } +void FRandom::SaveRNGState(TArray& backups) +{ + for (auto cur = RNGList; cur != nullptr; cur = cur->Next) + backups.Push(*cur); +} + +void FRandom::RestoreRNGState(TArray& backups) +{ + unsigned int i = 0u; + for (auto cur = RNGList; cur != nullptr; cur = cur->Next) + *cur = backups[i++]; + + backups.Clear(); +} + //========================================================================== // // FRandom :: StaticPrintSeeds diff --git a/src/g_levellocals.h b/src/g_levellocals.h index 719427d26..c02a6bd01 100644 --- a/src/g_levellocals.h +++ b/src/g_levellocals.h @@ -199,7 +199,7 @@ public: void ClearDynamic3DFloorData(); void WorldDone(void); void AirControlChanged(); - AActor *SelectTeleDest(int tid, int tag, bool norandom); + AActor *SelectTeleDest(int tid, int tag, bool norandom, bool isPlayer); bool AlignFlat(int linenum, int side, int fc); void ReplaceTextures(const char *fromname, const char *toname, int flags); diff --git a/src/playsim/p_teleport.cpp b/src/playsim/p_teleport.cpp index c39c6df1d..be398205c 100644 --- a/src/playsim/p_teleport.cpp +++ b/src/playsim/p_teleport.cpp @@ -272,7 +272,7 @@ DEFINE_ACTION_FUNCTION(AActor, Teleport) // //----------------------------------------------------------------------------- -AActor *FLevelLocals::SelectTeleDest (int tid, int tag, bool norandom) +AActor *FLevelLocals::SelectTeleDest (int tid, int tag, bool norandom, bool isPlayer) { AActor *searcher; @@ -324,7 +324,8 @@ AActor *FLevelLocals::SelectTeleDest (int tid, int tag, bool norandom) { if (count != 1 && !norandom) { - count = 1 + (pr_teleport() % count); + // Players get their own RNG seed to reduce likelihood of breaking prediction. + count = 1 + ((isPlayer ? pr_playerteleport() : pr_teleport()) % count); } searcher = NULL; while (count > 0) @@ -395,7 +396,7 @@ bool FLevelLocals::EV_Teleport (int tid, int tag, line_t *line, int side, AActor { // Don't teleport if hit back of line, so you can get out of teleporter. return 0; } - searcher = SelectTeleDest(tid, tag, predicting); + searcher = SelectTeleDest(tid, tag, false, thing->player != nullptr && thing->player->mo == thing); if (searcher == NULL) { return false; diff --git a/src/playsim/p_user.cpp b/src/playsim/p_user.cpp index 463d8f6e3..bdc9e9caa 100644 --- a/src/playsim/p_user.cpp +++ b/src/playsim/p_user.cpp @@ -144,6 +144,8 @@ static DVector3 LastPredictedPosition; static int LastPredictedPortalGroup; static int LastPredictedTic; +static TArray PredictionRNG; + static player_t PredictionPlayerBackup; static AActor *PredictionActor; static TArray PredictionActorBackupArray; @@ -1461,6 +1463,8 @@ void P_PredictPlayer (player_t *player) return; } + FRandom::SaveRNGState(PredictionRNG); + // Save original values for restoration later PredictionPlayerBackup.CopyFrom(*player, false); @@ -1600,6 +1604,8 @@ void P_UnPredictPlayer () // Q: Can this happen? If yes, can we continue? } + FRandom::RestoreRNGState(PredictionRNG); + AActor *savedcamera = player->camera; auto &actInvSel = act->PointerVar(NAME_InvSel); From 3ea5be1ea7674e7945355cf4fb3caa95ca7bea8e Mon Sep 17 00:00:00 2001 From: Boondorl Date: Wed, 6 Nov 2024 22:41:26 -0500 Subject: [PATCH 86/93] Reworked FRandom constructors Removes ambiguity while keeping old constructor syntax in check for better overall portability. --- src/bbannouncer.cpp | 2 +- src/common/audio/sound/s_sound.cpp | 2 +- src/common/engine/m_random.cpp | 8 ++--- src/common/engine/m_random.h | 19 ++++++++--- src/d_netinfo.cpp | 2 +- src/g_game.cpp | 4 +-- src/g_level.cpp | 2 +- src/g_statusbar/sbarinfo_commands.cpp | 4 +-- src/gamedata/decallib.cpp | 4 +-- src/gamedata/info.cpp | 2 +- src/gamedata/textures/animations.cpp | 2 +- src/p_conversation.cpp | 2 +- src/playsim/a_dynlight.cpp | 2 +- src/playsim/a_specialspot.cpp | 2 +- src/playsim/bots/b_func.cpp | 2 +- src/playsim/bots/b_game.cpp | 2 +- src/playsim/bots/b_move.cpp | 6 ++-- src/playsim/bots/b_think.cpp | 2 +- src/playsim/fragglescript/t_func.cpp | 2 +- src/playsim/mapthinkers/a_lightning.cpp | 2 +- src/playsim/mapthinkers/a_lights.cpp | 8 ++--- src/playsim/mapthinkers/a_plats.cpp | 2 +- src/playsim/mapthinkers/a_quake.cpp | 2 +- src/playsim/p_acs.cpp | 2 +- src/playsim/p_actionfunctions.cpp | 28 ++++++++--------- src/playsim/p_effect.cpp | 2 +- src/playsim/p_enemy.cpp | 38 +++++++++++----------- src/playsim/p_interaction.cpp | 12 +++---- src/playsim/p_lnspec.cpp | 2 +- src/playsim/p_map.cpp | 8 ++--- src/playsim/p_mobj.cpp | 42 ++++++++++++------------- src/playsim/p_sight.cpp | 4 +-- src/playsim/p_spec.cpp | 2 +- src/playsim/p_switch.cpp | 2 +- src/playsim/p_teleport.cpp | 4 +-- src/playsim/p_things.cpp | 2 +- src/playsim/p_user.cpp | 2 +- src/playsim/shadowinlines.h | 2 +- src/rendering/r_utility.cpp | 4 +-- src/scripting/decorate/thingdef_exp.cpp | 2 +- src/sound/s_doomsound.cpp | 2 +- src/sound/s_sndseq.cpp | 2 +- 42 files changed, 129 insertions(+), 118 deletions(-) diff --git a/src/bbannouncer.cpp b/src/bbannouncer.cpp index caf9f9f42..f52b5344b 100644 --- a/src/bbannouncer.cpp +++ b/src/bbannouncer.cpp @@ -169,7 +169,7 @@ static const char *TelefragSounds[] = #endif static int LastAnnounceTime; -static FRandom pr_bbannounce ("BBAnnounce", true); +static FCRandom pr_bbannounce ("BBAnnounce"); // CODE -------------------------------------------------------------------- diff --git a/src/common/audio/sound/s_sound.cpp b/src/common/audio/sound/s_sound.cpp index b9084692d..d8ae7fe00 100644 --- a/src/common/audio/sound/s_sound.cpp +++ b/src/common/audio/sound/s_sound.cpp @@ -61,7 +61,7 @@ enum { DEFAULT_PITCH = 128, }; -static FRandom pr_soundpitch ("SoundPitch", true); +static FCRandom pr_soundpitch ("SoundPitch"); SoundEngine* soundEngine; //========================================================================== diff --git a/src/common/engine/m_random.cpp b/src/common/engine/m_random.cpp index ee29a8055..11c4350b7 100644 --- a/src/common/engine/m_random.cpp +++ b/src/common/engine/m_random.cpp @@ -79,11 +79,11 @@ // EXTERNAL DATA DECLARATIONS ---------------------------------------------- -FRandom pr_exrandom("EX_Random", false); +FRandom pr_exrandom("EX_Random"); // PUBLIC DATA DEFINITIONS ------------------------------------------------- -FRandom M_Random(true); +FCRandom M_Random; // Global seed. This is modified predictably to initialize every RNG. uint32_t rngseed; @@ -145,7 +145,7 @@ FRandom::FRandom (bool client) #ifndef NDEBUG Name = NULL; #endif - if (client) + if (bClient) { Next = CRNGList; CRNGList = this; @@ -178,7 +178,7 @@ FRandom::FRandom (const char *name, bool client) : bClient(client) #endif // Insert the RNG in the list, sorted by CRC - FRandom **prev = (client ? &CRNGList : &RNGList), * probe = (client ? CRNGList : RNGList); + FRandom **prev = (bClient ? &CRNGList : &RNGList), * probe = (bClient ? CRNGList : RNGList); while (probe != NULL && probe->NameCRC < NameCRC) { diff --git a/src/common/engine/m_random.h b/src/common/engine/m_random.h index 991d812db..ba0bcaf62 100644 --- a/src/common/engine/m_random.h +++ b/src/common/engine/m_random.h @@ -44,9 +44,9 @@ class FSerializer; class FRandom : public SFMTObj { public: - FRandom (bool client); - FRandom (const char *name, bool client); - ~FRandom (); + FRandom() : FRandom(false) {} + FRandom(const char* name) : FRandom(name, false) {} + ~FRandom(); int Seed() const { @@ -178,6 +178,10 @@ public: static void StaticPrintSeeds (); #endif +protected: + FRandom(bool client); + FRandom(const char* name, bool client); + private: #ifndef NDEBUG const char *Name; @@ -189,6 +193,13 @@ private: static FRandom *RNGList, *CRNGList; }; +class FCRandom : public FRandom +{ +public: + FCRandom() : FRandom(true) {} + FCRandom(const char* name) : FRandom(name, true) {} +}; + extern uint32_t rngseed; // The starting seed (not part of state) extern uint32_t staticrngseed; // Static rngseed that can be set by the user @@ -196,6 +207,6 @@ extern bool use_staticrng; // M_Random can be used for numbers that do not affect gameplay -extern FRandom M_Random; +extern FCRandom M_Random; #endif diff --git a/src/d_netinfo.cpp b/src/d_netinfo.cpp index 369abcca3..bac6eddfe 100644 --- a/src/d_netinfo.cpp +++ b/src/d_netinfo.cpp @@ -52,7 +52,7 @@ #include "gstrings.h" #include "g_game.h" -static FRandom pr_pickteam ("PickRandomTeam", false); +static FRandom pr_pickteam ("PickRandomTeam"); CVAR (Float, autoaim, 35.f, CVAR_USERINFO | CVAR_ARCHIVE); CVAR (String, name, "Player", CVAR_USERINFO | CVAR_ARCHIVE); diff --git a/src/g_game.cpp b/src/g_game.cpp index 774c7b5b2..42ce6e99a 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -93,8 +93,8 @@ #include "fs_findfile.h" -static FRandom pr_dmspawn ("DMSpawn", false); -static FRandom pr_pspawn ("PlayerSpawn", false); +static FRandom pr_dmspawn ("DMSpawn"); +static FRandom pr_pspawn ("PlayerSpawn"); extern int startpos, laststartpos; diff --git a/src/g_level.cpp b/src/g_level.cpp index 0cf5ddb21..bc0cd378a 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -175,7 +175,7 @@ ELightMode getRealLightmode(FLevelLocals* Level, bool for3d) CVAR(Int, sv_alwaystally, 0, CVAR_SERVERINFO) -static FRandom pr_classchoice ("RandomPlayerClassChoice", false); +static FRandom pr_classchoice ("RandomPlayerClassChoice"); extern level_info_t TheDefaultLevelInfo; extern bool timingdemo; diff --git a/src/g_statusbar/sbarinfo_commands.cpp b/src/g_statusbar/sbarinfo_commands.cpp index 85944b647..a28d43e19 100644 --- a/src/g_statusbar/sbarinfo_commands.cpp +++ b/src/g_statusbar/sbarinfo_commands.cpp @@ -3225,9 +3225,9 @@ class CommandDrawGem : public SBarInfoCommand int goalValue; private: int chainWiggle; - static FRandom pr_chainwiggle; + static FCRandom pr_chainwiggle; }; -FRandom CommandDrawGem::pr_chainwiggle(true); //use the same method of chain wiggling as heretic. +FCRandom CommandDrawGem::pr_chainwiggle; //use the same method of chain wiggling as heretic. //////////////////////////////////////////////////////////////////////////////// diff --git a/src/gamedata/decallib.cpp b/src/gamedata/decallib.cpp index 2babc3b45..0f6e656b5 100644 --- a/src/gamedata/decallib.cpp +++ b/src/gamedata/decallib.cpp @@ -60,8 +60,8 @@ static TArray DecalTranslations; // Sometimes two machines in a game will disagree on the state of // decals. I do not know why. -static FRandom pr_decalchoice ("DecalChoice", true); -static FRandom pr_decal ("Decal", true); +static FCRandom pr_decalchoice ("DecalChoice"); +static FCRandom pr_decal ("Decal"); class FDecalGroup : public FDecalBase { diff --git a/src/gamedata/info.cpp b/src/gamedata/info.cpp index 6cff5943e..67fb87f67 100644 --- a/src/gamedata/info.cpp +++ b/src/gamedata/info.cpp @@ -61,7 +61,7 @@ extern void InitBotStuff(); extern void ClearStrifeTypes(); TArray PClassActor::AllActorClasses; -FRandom FState::pr_statetics("StateTics", false); +FRandom FState::pr_statetics("StateTics"); cycle_t ActionCycles; diff --git a/src/gamedata/textures/animations.cpp b/src/gamedata/textures/animations.cpp index 5cd072b14..619375c46 100644 --- a/src/gamedata/textures/animations.cpp +++ b/src/gamedata/textures/animations.cpp @@ -56,7 +56,7 @@ FTextureAnimator TexAnim; // PRIVATE DATA DEFINITIONS ------------------------------------------------ -static FRandom pr_animatepictures ("AnimatePics", true); +static FCRandom pr_animatepictures ("AnimatePics"); // CODE -------------------------------------------------------------------- diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index f897db759..356192ae6 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -62,7 +62,7 @@ #include "doommenu.h" #include "g_game.h" -static FRandom pr_randomspeech("RandomSpeech", true); +static FCRandom pr_randomspeech("RandomSpeech"); static int ConversationMenuY; diff --git a/src/playsim/a_dynlight.cpp b/src/playsim/a_dynlight.cpp index 1470b0796..79d8fe768 100644 --- a/src/playsim/a_dynlight.cpp +++ b/src/playsim/a_dynlight.cpp @@ -67,7 +67,7 @@ static FMemArena DynLightArena(sizeof(FDynamicLight) * 200); static TArray FreeList; -static FRandom randLight(true); +static FCRandom randLight; extern TArray StateLights; diff --git a/src/playsim/a_specialspot.cpp b/src/playsim/a_specialspot.cpp index b332b7800..b658c1830 100644 --- a/src/playsim/a_specialspot.cpp +++ b/src/playsim/a_specialspot.cpp @@ -39,7 +39,7 @@ #include "a_pickups.h" #include "vm.h" -static FRandom pr_spot ("SpecialSpot", false); +static FRandom pr_spot ("SpecialSpot"); IMPLEMENT_CLASS(DSpotState, false, false) diff --git a/src/playsim/bots/b_func.cpp b/src/playsim/bots/b_func.cpp index fa9f2c80d..e537bf9f7 100644 --- a/src/playsim/bots/b_func.cpp +++ b/src/playsim/bots/b_func.cpp @@ -54,7 +54,7 @@ #include "p_checkposition.h" #include "actorinlines.h" -static FRandom pr_botdofire ("BotDoFire", false); +static FRandom pr_botdofire ("BotDoFire"); //Checks TRUE reachability from bot to a looker. diff --git a/src/playsim/bots/b_game.cpp b/src/playsim/bots/b_game.cpp index eb8eb5d1a..3863ac923 100644 --- a/src/playsim/bots/b_game.cpp +++ b/src/playsim/bots/b_game.cpp @@ -98,7 +98,7 @@ Everything that is changed is marked (maybe commented) with "Added by MC" #include "i_system.h" // for SHARE_DIR #endif // !_WIN32 && !__APPLE__ -static FRandom pr_botspawn ("BotSpawn", false); +static FRandom pr_botspawn ("BotSpawn"); cycle_t BotThinkCycles, BotSupportCycles; int BotWTG; diff --git a/src/playsim/bots/b_move.cpp b/src/playsim/bots/b_move.cpp index 092261832..4d91839d8 100644 --- a/src/playsim/bots/b_move.cpp +++ b/src/playsim/bots/b_move.cpp @@ -53,9 +53,9 @@ #include "p_checkposition.h" #include "actorinlines.h" -static FRandom pr_botopendoor ("BotOpenDoor", false); -static FRandom pr_bottrywalk ("BotTryWalk", false); -static FRandom pr_botnewchasedir ("BotNewChaseDir", false); +static FRandom pr_botopendoor ("BotOpenDoor"); +static FRandom pr_bottrywalk ("BotTryWalk"); +static FRandom pr_botnewchasedir ("BotNewChaseDir"); // borrow some tables from p_enemy.cpp extern dirtype_t opposite[9]; diff --git a/src/playsim/bots/b_think.cpp b/src/playsim/bots/b_think.cpp index deef49aa1..9fba192d5 100644 --- a/src/playsim/bots/b_think.cpp +++ b/src/playsim/bots/b_think.cpp @@ -52,7 +52,7 @@ #include "d_player.h" #include "actorinlines.h" -static FRandom pr_botmove ("BotMove", false); +static FRandom pr_botmove ("BotMove"); //This function is called each tic for each bot, //so this is what the bot does. diff --git a/src/playsim/fragglescript/t_func.cpp b/src/playsim/fragglescript/t_func.cpp index 3a463c3a2..f9fff1b9e 100644 --- a/src/playsim/fragglescript/t_func.cpp +++ b/src/playsim/fragglescript/t_func.cpp @@ -56,7 +56,7 @@ using namespace FileSys; -static FRandom pr_script("FScript", false); +static FRandom pr_script("FScript"); // functions. FParser::SF_ means Script Function not, well.. heh, me diff --git a/src/playsim/mapthinkers/a_lightning.cpp b/src/playsim/mapthinkers/a_lightning.cpp index 47f6623b1..f6e0f713d 100644 --- a/src/playsim/mapthinkers/a_lightning.cpp +++ b/src/playsim/mapthinkers/a_lightning.cpp @@ -38,7 +38,7 @@ #include "gi.h" #include -static FRandom pr_lightning ("Lightning", false); +static FRandom pr_lightning ("Lightning"); IMPLEMENT_CLASS(DLightningThinker, false, false) diff --git a/src/playsim/mapthinkers/a_lights.cpp b/src/playsim/mapthinkers/a_lights.cpp index 48acdcd76..06b040304 100644 --- a/src/playsim/mapthinkers/a_lights.cpp +++ b/src/playsim/mapthinkers/a_lights.cpp @@ -43,10 +43,10 @@ // State. #include "serializer.h" -static FRandom pr_flicker ("Flicker", true); -static FRandom pr_lightflash ("LightFlash", true); -static FRandom pr_strobeflash ("StrobeFlash", true); -static FRandom pr_fireflicker ("FireFlicker", true); +static FCRandom pr_flicker ("Flicker"); +static FCRandom pr_lightflash ("LightFlash"); +static FCRandom pr_strobeflash ("StrobeFlash"); +static FCRandom pr_fireflicker ("FireFlicker"); //----------------------------------------------------------------------------- diff --git a/src/playsim/mapthinkers/a_plats.cpp b/src/playsim/mapthinkers/a_plats.cpp index 0f6fa9ce9..c688295e4 100644 --- a/src/playsim/mapthinkers/a_plats.cpp +++ b/src/playsim/mapthinkers/a_plats.cpp @@ -37,7 +37,7 @@ #include "p_spec.h" #include "g_levellocals.h" -static FRandom pr_doplat ("DoPlat", false); +static FRandom pr_doplat ("DoPlat"); IMPLEMENT_CLASS(DPlat, false, false) diff --git a/src/playsim/mapthinkers/a_quake.cpp b/src/playsim/mapthinkers/a_quake.cpp index e6fb687fa..d2529a5f8 100644 --- a/src/playsim/mapthinkers/a_quake.cpp +++ b/src/playsim/mapthinkers/a_quake.cpp @@ -36,7 +36,7 @@ #include "actorinlines.h" #include -static FRandom pr_quake ("Quake", true); +static FCRandom pr_quake ("Quake"); IMPLEMENT_CLASS(DEarthquake, false, true) diff --git a/src/playsim/p_acs.cpp b/src/playsim/p_acs.cpp index 211b155c2..89aee643d 100644 --- a/src/playsim/p_acs.cpp +++ b/src/playsim/p_acs.cpp @@ -540,7 +540,7 @@ -FRandom pr_acs ("ACS", false); +FRandom pr_acs ("ACS"); // I imagine this much stack space is probably overkill, but it could // potentially get used with recursive functions. diff --git a/src/playsim/p_actionfunctions.cpp b/src/playsim/p_actionfunctions.cpp index 91bff0bc2..ea7090c1d 100644 --- a/src/playsim/p_actionfunctions.cpp +++ b/src/playsim/p_actionfunctions.cpp @@ -73,19 +73,19 @@ #include "shadowinlines.h" #include "i_time.h" -static FRandom pr_camissile ("CustomActorfire", false); -static FRandom pr_cabullet ("CustomBullet", false); -static FRandom pr_cwjump ("CustomWpJump", false); -static FRandom pr_cwpunch ("CustomWpPunch", false); -static FRandom pr_grenade ("ThrowGrenade", false); - FRandom pr_crailgun ("CustomRailgun", false); -static FRandom pr_spawndebris ("SpawnDebris", false); -static FRandom pr_spawnitemex ("SpawnItemEx", false); -static FRandom pr_burst ("Burst", false); -static FRandom pr_monsterrefire ("MonsterRefire", false); -static FRandom pr_teleport("A_Teleport", false); -static FRandom pr_bfgselfdamage("BFGSelfDamage", false); - FRandom pr_cajump("CustomJump", false); +static FRandom pr_camissile ("CustomActorfire"); +static FRandom pr_cabullet ("CustomBullet"); +static FRandom pr_cwjump ("CustomWpJump"); +static FRandom pr_cwpunch ("CustomWpPunch"); +static FRandom pr_grenade ("ThrowGrenade"); + FRandom pr_crailgun ("CustomRailgun"); +static FRandom pr_spawndebris ("SpawnDebris"); +static FRandom pr_spawnitemex ("SpawnItemEx"); +static FRandom pr_burst ("Burst"); +static FRandom pr_monsterrefire ("MonsterRefire"); +static FRandom pr_teleport("A_Teleport"); +static FRandom pr_bfgselfdamage("BFGSelfDamage"); + FRandom pr_cajump("CustomJump"); //========================================================================== // @@ -746,7 +746,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_StopSoundEx) // Generic seeker missile function // //========================================================================== -static FRandom pr_seekermissile ("SeekerMissile", false); +static FRandom pr_seekermissile ("SeekerMissile"); enum { SMF_LOOK = 1, diff --git a/src/playsim/p_effect.cpp b/src/playsim/p_effect.cpp index 31b3e3128..a2d42f7c5 100644 --- a/src/playsim/p_effect.cpp +++ b/src/playsim/p_effect.cpp @@ -65,7 +65,7 @@ CVAR (Int, r_rail_trailsparsity, 1, CVAR_ARCHIVE); CVAR (Bool, r_particles, true, 0); EXTERN_CVAR(Int, r_maxparticles); -FRandom pr_railtrail("RailTrail", true); +FCRandom pr_railtrail("RailTrail"); #define FADEFROMTTL(a) (1.f/(a)) diff --git a/src/playsim/p_enemy.cpp b/src/playsim/p_enemy.cpp index d3a5a66b2..120f37231 100644 --- a/src/playsim/p_enemy.cpp +++ b/src/playsim/p_enemy.cpp @@ -54,26 +54,26 @@ #include "gi.h" -static FRandom pr_checkmissilerange ("CheckMissileRange", false); -static FRandom pr_opendoor ("OpenDoor", false); -static FRandom pr_trywalk ("TryWalk", false); -static FRandom pr_newchasedir ("NewChaseDir", false); -static FRandom pr_lookformonsters ("LookForMonsters", false); -static FRandom pr_lookforplayers ("LookForPlayers", false); -static FRandom pr_scaredycat ("Anubis", false); - FRandom pr_chase ("Chase", false); - FRandom pr_facetarget ("FaceTarget", false); - FRandom pr_railface ("RailFace", false); -static FRandom pr_look2 ("LookyLooky", false); -static FRandom pr_look3 ("IGotHooky", false); -static FRandom pr_slook ("SlooK", false); -static FRandom pr_dropoff ("Dropoff", false); -static FRandom pr_defect ("Defect", false); -static FRandom pr_avoidcrush("AvoidCrush", false); -static FRandom pr_stayonlift("StayOnLift", false); +static FRandom pr_checkmissilerange ("CheckMissileRange"); +static FRandom pr_opendoor ("OpenDoor"); +static FRandom pr_trywalk ("TryWalk"); +static FRandom pr_newchasedir ("NewChaseDir"); +static FRandom pr_lookformonsters ("LookForMonsters"); +static FRandom pr_lookforplayers ("LookForPlayers"); +static FRandom pr_scaredycat ("Anubis"); + FRandom pr_chase ("Chase"); + FRandom pr_facetarget ("FaceTarget"); + FRandom pr_railface ("RailFace"); +static FRandom pr_look2 ("LookyLooky"); +static FRandom pr_look3 ("IGotHooky"); +static FRandom pr_slook ("SlooK"); +static FRandom pr_dropoff ("Dropoff"); +static FRandom pr_defect ("Defect"); +static FRandom pr_avoidcrush("AvoidCrush"); +static FRandom pr_stayonlift("StayOnLift"); -static FRandom pr_skiptarget("SkipTarget", false); -static FRandom pr_enemystrafe("EnemyStrafe", false); +static FRandom pr_skiptarget("SkipTarget"); +static FRandom pr_enemystrafe("EnemyStrafe"); // movement interpolation is fine for objects that are moved by their own // velocity. But for monsters it is problematic. diff --git a/src/playsim/p_interaction.cpp b/src/playsim/p_interaction.cpp index eed16b87f..0ae77e914 100644 --- a/src/playsim/p_interaction.cpp +++ b/src/playsim/p_interaction.cpp @@ -63,12 +63,12 @@ #include "actorinlines.h" #include "d_main.h" -static FRandom pr_botrespawn ("BotRespawn", false); -static FRandom pr_killmobj ("ActorDie", false); -FRandom pr_damagemobj ("ActorTakeDamage", false); -static FRandom pr_lightning ("LightningDamage", false); -static FRandom pr_poison ("PoisonDamage", false); -static FRandom pr_switcher ("SwitchTarget", false); +static FRandom pr_botrespawn ("BotRespawn"); +static FRandom pr_killmobj ("ActorDie"); +FRandom pr_damagemobj ("ActorTakeDamage"); +static FRandom pr_lightning ("LightningDamage"); +static FRandom pr_poison ("PoisonDamage"); +static FRandom pr_switcher ("SwitchTarget"); CVAR (Bool, cl_showsprees, true, CVAR_ARCHIVE) CVAR (Bool, cl_showmultikills, true, CVAR_ARCHIVE) diff --git a/src/playsim/p_lnspec.cpp b/src/playsim/p_lnspec.cpp index c0a399785..00318dfbb 100644 --- a/src/playsim/p_lnspec.cpp +++ b/src/playsim/p_lnspec.cpp @@ -95,7 +95,7 @@ static DCeiling::ECrushMode CRUSHTYPE(int a, bool withslowdown) return withslowdown? DCeiling::ECrushMode::crushSlowdown : DCeiling::ECrushMode::crushDoom; } -static FRandom pr_glass ("GlassBreak", false); +static FRandom pr_glass ("GlassBreak"); // There are aliases for the ACS specials that take names instead of numbers. // This table maps them onto the real number-based specials. diff --git a/src/playsim/p_map.cpp b/src/playsim/p_map.cpp index 197ab55f1..589204993 100644 --- a/src/playsim/p_map.cpp +++ b/src/playsim/p_map.cpp @@ -103,10 +103,10 @@ static void CheckForPushSpecial(line_t *line, int side, AActor *mobj, DVector2 * static void SpawnShootDecal(AActor *t1, AActor *defaults, const FTraceResults &trace); static void SpawnDeepSplash(AActor *t1, const FTraceResults &trace, AActor *puff); -static FRandom pr_tracebleed("TraceBleed", false); -static FRandom pr_checkthing("CheckThing", false); -static FRandom pr_lineattack("LineAttack", false); -static FRandom pr_crunch("DoCrunch", false); +static FRandom pr_tracebleed("TraceBleed"); +static FRandom pr_checkthing("CheckThing"); +static FRandom pr_lineattack("LineAttack"); +static FRandom pr_crunch("DoCrunch"); // keep track of special lines as they are hit, // but don't process them until the move is proven valid diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index bb8d3be1a..0f9a91803 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -122,29 +122,29 @@ EXTERN_CVAR (Int, cl_rockettrails) // PRIVATE DATA DEFINITIONS ------------------------------------------------ -static FRandom pr_explodemissile ("ExplodeMissile", false); -static FRandom pr_reflect ("Reflect", false); -static FRandom pr_nightmarerespawn ("NightmareRespawn", false); -static FRandom pr_botspawnmobj ("BotSpawnActor", false); -static FRandom pr_spawnmapthing ("SpawnMapThing", false); -static FRandom pr_spawnpuff ("SpawnPuff", false); -static FRandom pr_spawnblood ("SpawnBlood", false); -static FRandom pr_splatter ("BloodSplatter", false); -static FRandom pr_takedamage ("TakeDamage", false); -static FRandom pr_splat ("FAxeSplatter", false); -static FRandom pr_ripperblood ("RipperBlood", false); -static FRandom pr_chunk ("Chunk", false); -static FRandom pr_checkmissilespawn ("CheckMissileSpawn", false); -static FRandom pr_missiledamage ("MissileDamage", false); -static FRandom pr_multiclasschoice ("MultiClassChoice", false); -static FRandom pr_rockettrail("RocketTrail", false); -static FRandom pr_uniquetid("UniqueTID", false); +static FRandom pr_explodemissile ("ExplodeMissile"); +static FRandom pr_reflect ("Reflect"); +static FRandom pr_nightmarerespawn ("NightmareRespawn"); +static FRandom pr_botspawnmobj ("BotSpawnActor"); +static FRandom pr_spawnmapthing ("SpawnMapThing"); +static FRandom pr_spawnpuff ("SpawnPuff"); +static FRandom pr_spawnblood ("SpawnBlood"); +static FRandom pr_splatter ("BloodSplatter"); +static FRandom pr_takedamage ("TakeDamage"); +static FRandom pr_splat ("FAxeSplatter"); +static FRandom pr_ripperblood ("RipperBlood"); +static FRandom pr_chunk ("Chunk"); +static FRandom pr_checkmissilespawn ("CheckMissileSpawn"); +static FRandom pr_missiledamage ("MissileDamage"); +static FRandom pr_multiclasschoice ("MultiClassChoice"); +static FRandom pr_rockettrail("RocketTrail"); +static FRandom pr_uniquetid("UniqueTID"); // PUBLIC DATA DEFINITIONS ------------------------------------------------- -FRandom pr_spawnmobj ("SpawnActor", false); -FRandom pr_bounce("Bounce", false); -FRandom pr_spawnmissile("SpawnMissile", false); +FRandom pr_spawnmobj ("SpawnActor"); +FRandom pr_bounce("Bounce"); +FRandom pr_spawnmissile("SpawnMissile"); CUSTOM_CVAR (Float, sv_gravity, 800.f, CVAR_SERVERINFO|CVAR_NOSAVE|CVAR_NOINITCALL) { @@ -7956,7 +7956,7 @@ void AActor::SetTranslation(FName trname) // PROP A_RestoreSpecialPosition // //--------------------------------------------------------------------------- -static FRandom pr_restore("RestorePos", false); +static FRandom pr_restore("RestorePos"); void AActor::RestoreSpecialPosition() { diff --git a/src/playsim/p_sight.cpp b/src/playsim/p_sight.cpp index a2fc76c46..2cf957c8c 100644 --- a/src/playsim/p_sight.cpp +++ b/src/playsim/p_sight.cpp @@ -37,8 +37,8 @@ #include "g_levellocals.h" #include "actorinlines.h" -static FRandom pr_botchecksight ("BotCheckSight", false); -static FRandom pr_checksight ("CheckSight", false); +static FRandom pr_botchecksight ("BotCheckSight"); +static FRandom pr_checksight ("CheckSight"); /* ============================================================================== diff --git a/src/playsim/p_spec.cpp b/src/playsim/p_spec.cpp index 385d17f92..3851bd748 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", false); +static FRandom pr_actorinspecialsector ("ActorInSpecialSector"); EXTERN_CVAR(Bool, cl_predict_specials) EXTERN_CVAR(Bool, forcewater) diff --git a/src/playsim/p_switch.cpp b/src/playsim/p_switch.cpp index 2af3054d3..59b70ec83 100644 --- a/src/playsim/p_switch.cpp +++ b/src/playsim/p_switch.cpp @@ -49,7 +49,7 @@ #include "actorinlines.h" #include "animations.h" -static FRandom pr_switchanim ("AnimSwitch", true); +static FCRandom pr_switchanim ("AnimSwitch"); class DActiveButton : public DThinker { diff --git a/src/playsim/p_teleport.cpp b/src/playsim/p_teleport.cpp index be398205c..a198f2b27 100644 --- a/src/playsim/p_teleport.cpp +++ b/src/playsim/p_teleport.cpp @@ -36,8 +36,8 @@ #define FUDGEFACTOR 10 -static FRandom pr_teleport ("Teleport", false); -static FRandom pr_playerteleport("PlayerTeleport", false); +static FRandom pr_teleport ("Teleport"); +static FRandom pr_playerteleport("PlayerTeleport"); CVAR (Bool, telezoom, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG); diff --git a/src/playsim/p_things.cpp b/src/playsim/p_things.cpp index 878366d7b..3391030aa 100644 --- a/src/playsim/p_things.cpp +++ b/src/playsim/p_things.cpp @@ -47,7 +47,7 @@ #include "actorinlines.h" #include "vm.h" -static FRandom pr_leadtarget ("LeadTarget", false); +static FRandom pr_leadtarget ("LeadTarget"); bool FLevelLocals::EV_Thing_Spawn (int tid, AActor *source, int type, DAngle angle, bool fog, int newtid) { diff --git a/src/playsim/p_user.cpp b/src/playsim/p_user.cpp index bdc9e9caa..4ed0c0bfd 100644 --- a/src/playsim/p_user.cpp +++ b/src/playsim/p_user.cpp @@ -95,7 +95,7 @@ #include "s_music.h" #include "d_main.h" -static FRandom pr_skullpop ("SkullPop", false); +static FRandom pr_skullpop ("SkullPop"); // [SP] Allows respawn in single player CVAR(Bool, sv_singleplayerrespawn, false, CVAR_SERVERINFO | CVAR_CHEAT) diff --git a/src/playsim/shadowinlines.h b/src/playsim/shadowinlines.h index 6c0e9176f..b36b051ac 100644 --- a/src/playsim/shadowinlines.h +++ b/src/playsim/shadowinlines.h @@ -17,7 +17,7 @@ extern FRandom pr_spawnmissile; extern FRandom pr_facetarget; extern FRandom pr_railface; extern FRandom pr_crailgun; -inline FRandom pr_shadowaimz("VerticalShadowAim", false); +inline FRandom pr_shadowaimz("VerticalShadowAim"); //========================================================================== // diff --git a/src/rendering/r_utility.cpp b/src/rendering/r_utility.cpp index 7311341e6..390e575c5 100644 --- a/src/rendering/r_utility.cpp +++ b/src/rendering/r_utility.cpp @@ -94,8 +94,8 @@ struct InterpolationViewer // PRIVATE DATA DECLARATIONS ----------------------------------------------- static TArray PastViewers; -static FRandom pr_torchflicker ("TorchFlicker", true); -static FRandom pr_hom(true); +static FCRandom pr_torchflicker ("TorchFlicker"); +static FCRandom pr_hom; bool NoInterpolateView; // GL needs access to this. static TArray InterpolationPath; diff --git a/src/scripting/decorate/thingdef_exp.cpp b/src/scripting/decorate/thingdef_exp.cpp index 831fcf0c6..f8ac9e91a 100644 --- a/src/scripting/decorate/thingdef_exp.cpp +++ b/src/scripting/decorate/thingdef_exp.cpp @@ -576,7 +576,7 @@ static FRandom *ParseRNG(FScanner &sc, bool client) } else { - rng = &pr_exrandom; + rng = client ? &M_Random : &pr_exrandom; } return rng; } diff --git a/src/sound/s_doomsound.cpp b/src/sound/s_doomsound.cpp index 4b2d597bc..749b1f5e7 100644 --- a/src/sound/s_doomsound.cpp +++ b/src/sound/s_doomsound.cpp @@ -1163,7 +1163,7 @@ TArray DoomSoundEngine::ReadSound(int lumpnum) // This is overridden to use a synchronized RNG. // //========================================================================== -static FRandom pr_randsound("RandSound", true); +static FCRandom pr_randsound("RandSound"); FSoundID DoomSoundEngine::PickReplacement(FSoundID refid) { diff --git a/src/sound/s_sndseq.cpp b/src/sound/s_sndseq.cpp index cfe8ed9c1..266447773 100644 --- a/src/sound/s_sndseq.cpp +++ b/src/sound/s_sndseq.cpp @@ -288,7 +288,7 @@ static const hexenseq_t HexenSequences[] = { static int SeqTrans[MAX_SNDSEQS*3]; -static FRandom pr_sndseq ("SndSeq", true); +static FCRandom pr_sndseq ("SndSeq"); // CODE -------------------------------------------------------------------- From 268dad18f75f7cce125dfe4c31d65951f9dd1b56 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Fri, 8 Nov 2024 21:58:45 -0500 Subject: [PATCH 87/93] Discs no longer blast players with collision disabled --- src/playsim/p_map.cpp | 9 ++++++++- wadsrc/static/zscript/actors/actor.zs | 1 + wadsrc/static/zscript/actors/hexen/blastradius.zs | 5 +++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/playsim/p_map.cpp b/src/playsim/p_map.cpp index 589204993..0f40a0937 100644 --- a/src/playsim/p_map.cpp +++ b/src/playsim/p_map.cpp @@ -121,13 +121,20 @@ TArray portalhit; // //========================================================================== -bool P_ShouldPassThroughPlayer(AActor *self, AActor *other) +static int P_ShouldPassThroughPlayer(AActor *self, AActor *other) { return (dmflags3 & DF3_NO_PLAYER_CLIP) && other->player && other->player->mo == other && self->IsFriend(other); } +DEFINE_ACTION_FUNCTION_NATIVE(AActor, ShouldPassThroughPlayer, P_ShouldPassThroughPlayer) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT_NOT_NULL(other, AActor); + ACTION_RETURN_BOOL(P_ShouldPassThroughPlayer(self, other)); +} + //========================================================================== // // CanCollideWith diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index 970b23405..37b36e9e7 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -844,6 +844,7 @@ class Actor : Thinker native native void Thrust(double speed = 1e37, double angle = 1e37); native clearscope bool isFriend(Actor other) const; native clearscope bool isHostile(Actor other) const; + native clearscope bool ShouldPassThroughPlayer(Actor other) const; native void AdjustFloorClip(); native clearscope DropItem GetDropItems() const; native void CopyFriendliness (Actor other, bool changeTarget, bool resetHealth = true); diff --git a/wadsrc/static/zscript/actors/hexen/blastradius.zs b/wadsrc/static/zscript/actors/hexen/blastradius.zs index 271f2bcfc..b66ca1418 100644 --- a/wadsrc/static/zscript/actors/hexen/blastradius.zs +++ b/wadsrc/static/zscript/actors/hexen/blastradius.zs @@ -139,6 +139,11 @@ extend class Actor { // Must be monster, player, missile, touchy or vulnerable continue; } + if (player && ShouldPassThroughPlayer(mo)) + { + // Don't blast friendly players if collision is disabled. + continue; + } if (Distance2D(mo) > radius) { // Out of range continue; From ab9b6320cb67843980d4c4e6f81323e8b5b04959 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Thu, 7 Nov 2024 18:54:23 -0500 Subject: [PATCH 88/93] Allow easier piece weapon replacing Checks for replacements on weapons instead of using the given weapon class as is (also verifies said replacement is a weapon). --- .../zscript/actors/inventory/weaponpiece.zs | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/wadsrc/static/zscript/actors/inventory/weaponpiece.zs b/wadsrc/static/zscript/actors/inventory/weaponpiece.zs index 2f2434d6c..2a2cd9fe6 100644 --- a/wadsrc/static/zscript/actors/inventory/weaponpiece.zs +++ b/wadsrc/static/zscript/actors/inventory/weaponpiece.zs @@ -59,6 +59,13 @@ class WeaponPiece : Inventory property number: PieceValue; property weapon: WeaponClass; + + // Account for weapon replacers, but make sure it's still a Weapon + clearscope class GetWeaponClass() const + { + class type = WeaponClass ? (class)(GetReplacement(WeaponClass)) : null; + return type ? type : WeaponClass; + } //========================================================================== // @@ -74,7 +81,11 @@ class WeaponPiece : Inventory return false; } - let Defaults = GetDefaultByType(WeaponClass); + class type = GetWeaponClass(); + if (!type) + return false; + + let Defaults = GetDefaultByType(type); bool gaveSome = !!(toucher.GiveAmmo (Defaults.AmmoType1, Defaults.AmmoGive1) + toucher.GiveAmmo (Defaults.AmmoType2, Defaults.AmmoGive2)); @@ -94,11 +105,15 @@ class WeaponPiece : Inventory override bool TryPickup (in out Actor toucher) { + class type = GetWeaponClass(); + if (!type) + return false; + Inventory item; WeaponHolder hold = NULL; bool shouldStay = ShouldStay (); int gaveAmmo; - let Defaults = GetDefaultByType(WeaponClass); + let Defaults = GetDefaultByType(type); FullWeapon = NULL; for(item=toucher.Inv; item; item=item.Inv) @@ -106,6 +121,7 @@ class WeaponPiece : Inventory hold = WeaponHolder(item); if (hold != null) { + // Intentionally check against the unreplaced class if (hold.PieceWeapon == WeaponClass) { break; @@ -153,9 +169,9 @@ class WeaponPiece : Inventory // Check if weapon assembled if (hold.PieceMask == (1 << Defaults.health) - 1) { - if (!toucher.FindInventory (WeaponClass)) + if (!toucher.FindInventory (type)) { - FullWeapon= Weapon(Spawn(WeaponClass)); + FullWeapon= Weapon(Spawn(type)); // The weapon itself should not give more ammo to the player. FullWeapon.AmmoGive1 = 0; From 702ef493f0147fd01f29874bfd6fa7d705f34f8d Mon Sep 17 00:00:00 2001 From: RaveYard <29225776+MrRaveYard@users.noreply.github.com> Date: Fri, 14 Jun 2024 20:53:46 +0200 Subject: [PATCH 89/93] Fix and restrict level postprocessor instance --- src/maploader/postprocessor.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/maploader/postprocessor.cpp b/src/maploader/postprocessor.cpp index e94e7d4d7..c430ce6a5 100644 --- a/src/maploader/postprocessor.cpp +++ b/src/maploader/postprocessor.cpp @@ -56,19 +56,16 @@ class DLevelPostProcessor : public DObject { - DECLARE_ABSTRACT_CLASS(DLevelPostProcessor, DObject) + DECLARE_CLASS(DLevelPostProcessor, DObject) public: MapLoader *loader; FLevelLocals *Level; }; -IMPLEMENT_CLASS(DLevelPostProcessor, true, false); +IMPLEMENT_CLASS(DLevelPostProcessor, false, false); void MapLoader::PostProcessLevel(FName checksum) { - auto lc = Create(); - lc->loader = this; - lc->Level = Level; for(auto cls : PClass::AllClasses) { if (cls->IsDescendantOf(RUNTIME_CLASS(DLevelPostProcessor))) @@ -87,8 +84,14 @@ void MapLoader::PostProcessLevel(FName checksum) continue; } + auto lc = static_cast(cls->CreateNew()); + lc->loader = this; + lc->Level = Level; + VMValue param[] = { lc, checksum.GetIndex(), &Level->MapName }; VMCall(func->Variants[0].Implementation, param, 3, nullptr, 0); + + lc->Destroy(); } } } From c31f45c6533e0ffb3acaff6543dacc07d287e1ae Mon Sep 17 00:00:00 2001 From: Boondorl Date: Tue, 19 Nov 2024 07:01:24 -0500 Subject: [PATCH 90/93] Fixed view for frozen players Will no longer try and extrapolate mouse input that's bound to mispredict. --- src/rendering/r_utility.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/rendering/r_utility.cpp b/src/rendering/r_utility.cpp index 390e575c5..3a3fdd70e 100644 --- a/src/rendering/r_utility.cpp +++ b/src/rendering/r_utility.cpp @@ -464,7 +464,8 @@ bool P_NoInterpolation(player_t const *player, AActor const *actor) && player->mo->reactiontime == 0 && !NoInterpolateView && !paused - && !LocalKeyboardTurner; + && !LocalKeyboardTurner + && !player->mo->isFrozen(); } //========================================================================== From 99c058d168d0e840ed51eca8d06a2266796a38c5 Mon Sep 17 00:00:00 2001 From: jekyllgrim <42670463+jekyllgrim@users.noreply.github.com> Date: Wed, 20 Nov 2024 18:26:00 +0300 Subject: [PATCH 91/93] Added WorldHitscanFired and WorldHitscanPreFired (#2432) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Added WorldHitscan events * DVector3 → const DVector3& --- src/events.cpp | 84 ++++++++++++++++++++++++++++++++- src/events.h | 14 ++++++ src/playsim/p_map.cpp | 52 ++++++++++++++------ wadsrc/static/zscript/events.zs | 10 ++++ 4 files changed, 145 insertions(+), 15 deletions(-) mode change 100755 => 100644 src/events.h diff --git a/src/events.cpp b/src/events.cpp index a4773d133..2f7b12091 100755 --- a/src/events.cpp +++ b/src/events.cpp @@ -701,6 +701,36 @@ void EventManager::WorldThingDied(AActor* actor, AActor* inflictor) handler->WorldThingDied(actor, inflictor); } +bool EventManager::WorldHitscanPreFired(AActor* actor, DAngle angle, double distance, DAngle pitch, int damage, FName damageType, PClassActor *pufftype, int flags, double sz, double offsetforward, double offsetside) +{ + // don't call anything if actor was destroyed on PostBeginPlay/BeginPlay/whatever. + if (actor->ObjectFlags & OF_EuthanizeMe) + return false; + + bool ret = false; + if (ShouldCallStatic(true)) ret = staticEventManager.WorldHitscanPreFired(actor, angle, distance, pitch, damage, damageType, pufftype, flags, sz, offsetforward, offsetside); + + if (!ret) + { + for (DStaticEventHandler* handler = FirstEventHandler; handler && ret == false; handler = handler->next) + ret = handler->WorldHitscanPreFired(actor, angle, distance, pitch, damage, damageType, pufftype, flags, sz, offsetforward, offsetside); + } + + return ret; +} + +void EventManager::WorldHitscanFired(AActor* actor, const DVector3& AttackPos, const DVector3& DamagePosition, AActor* Inflictor, int flags) +{ + // don't call anything if actor was destroyed on PostBeginPlay/BeginPlay/whatever. + if (actor->ObjectFlags & OF_EuthanizeMe) + return; + + if (ShouldCallStatic(true)) staticEventManager.WorldHitscanFired(actor, AttackPos, DamagePosition, Inflictor, flags); + + for (DStaticEventHandler* handler = FirstEventHandler; handler; handler = handler->next) + handler->WorldHitscanFired(actor, AttackPos, DamagePosition, Inflictor, flags); +} + void EventManager::WorldThingGround(AActor* actor, FState* st) { // don't call anything if actor was destroyed on PostBeginPlay/BeginPlay/whatever. @@ -1026,6 +1056,14 @@ DEFINE_FIELD_X(WorldEvent, FWorldEvent, DamagePosition); DEFINE_FIELD_X(WorldEvent, FWorldEvent, DamageIsRadius); DEFINE_FIELD_X(WorldEvent, FWorldEvent, NewDamage); DEFINE_FIELD_X(WorldEvent, FWorldEvent, CrushedState); +DEFINE_FIELD_X(WorldEvent, FWorldEvent, AttackPos); +DEFINE_FIELD_X(WorldEvent, FWorldEvent, AttackAngle); +DEFINE_FIELD_X(WorldEvent, FWorldEvent, AttackPitch); +DEFINE_FIELD_X(WorldEvent, FWorldEvent, AttackDistance); +DEFINE_FIELD_X(WorldEvent, FWorldEvent, AttackOffsetForward); +DEFINE_FIELD_X(WorldEvent, FWorldEvent, AttackOffsetSide); +DEFINE_FIELD_X(WorldEvent, FWorldEvent, AttackZ); +DEFINE_FIELD_X(WorldEvent, FWorldEvent, AttackPuffType); DEFINE_FIELD_X(PlayerEvent, FPlayerEvent, PlayerNumber); DEFINE_FIELD_X(PlayerEvent, FPlayerEvent, IsReturn); @@ -1729,6 +1767,51 @@ void DStaticEventHandler::WorldThingDied(AActor* actor, AActor* inflictor) } } +bool DStaticEventHandler::WorldHitscanPreFired(AActor* actor, DAngle angle, double distance, DAngle pitch, int damage, FName damageType, PClassActor *pufftype, int flags, double sz, double offsetforward, double offsetside) +{ + IFVIRTUAL(DStaticEventHandler, WorldHitscanPreFired) + { + // don't create excessive DObjects if not going to be processed anyway + if (isEmpty(func)) return false; + FWorldEvent e = owner->SetupWorldEvent(); + e.Thing = actor; + e.AttackAngle = angle; + e.AttackPitch = pitch; + e.AttackDistance = distance; + e.Damage = damage; + e.DamageType = damageType; + e.AttackPuffType = pufftype; + e.AttackOffsetForward = offsetforward; + e.AttackOffsetSide = offsetside; + e.AttackZ = sz; + e.DamageFlags = flags; + int processed; + VMReturn results[1] = { &processed }; + VMValue params[2] = { (DStaticEventHandler*)this, &e }; + VMCall(func, params, 2, results, 1); + return !!processed; + } + + return false; +} + +void DStaticEventHandler::WorldHitscanFired(AActor* actor, const DVector3& AttackPos, const DVector3& DamagePosition, AActor* Inflictor, int flags) +{ + IFVIRTUAL(DStaticEventHandler, WorldHitscanFired) + { + // don't create excessive DObjects if not going to be processed anyway + if (isEmpty(func)) return; + FWorldEvent e = owner->SetupWorldEvent(); + e.Thing = actor; + e.AttackPos = AttackPos; + e.DamagePosition = DamagePosition; + e.Inflictor = Inflictor; + e.DamageFlags = flags; + VMValue params[2] = { (DStaticEventHandler*)this, &e }; + VMCall(func, params, 2, nullptr, 0); + } +} + void DStaticEventHandler::WorldThingGround(AActor* actor, FState* st) { IFVIRTUAL(DStaticEventHandler, WorldThingGround) @@ -1743,7 +1826,6 @@ void DStaticEventHandler::WorldThingGround(AActor* actor, FState* st) } } - void DStaticEventHandler::WorldThingRevived(AActor* actor) { IFVIRTUAL(DStaticEventHandler, WorldThingRevived) diff --git a/src/events.h b/src/events.h old mode 100755 new mode 100644 index d71922b9a..c3d05d485 --- a/src/events.h +++ b/src/events.h @@ -311,6 +311,8 @@ public: void WorldThingRevived(AActor* actor); void WorldThingDamaged(AActor* actor, AActor* inflictor, AActor* source, int damage, FName mod, int flags, DAngle angle); void WorldThingDestroyed(AActor* actor); + bool WorldHitscanPreFired(AActor* actor, DAngle angle, double distance, DAngle pitch, int damage, FName damageType, PClassActor *pufftype, int flags, double sz, double offsetforward, double offsetside); + void WorldHitscanFired(AActor* actor, const DVector3& AttackPos, const DVector3& DamagePosition, AActor* Inflictor, int flags); void WorldLinePreActivated(line_t* line, AActor* actor, int activationType, bool* shouldactivate); void WorldLineActivated(line_t* line, AActor* actor, int activationType); int WorldSectorDamaged(sector_t* sector, AActor* source, int damage, FName damagetype, int part, DVector3 position, bool isradius); @@ -393,6 +395,14 @@ struct FWorldEvent bool DamageIsRadius; // radius damage yes/no int NewDamage = 0; // sector/line damaged. allows modifying damage FState* CrushedState = nullptr; // custom crush state set in thingground + DVector3 AttackPos; //hitscan point of origin + DAngle AttackAngle; + DAngle AttackPitch; + double AttackDistance = 0; + double AttackOffsetForward = 0; + double AttackOffsetSide = 0; + double AttackZ = 0; + PClassActor* AttackPuffType = nullptr; }; struct FPlayerEvent @@ -467,6 +477,10 @@ struct EventManager void WorldThingSpawned(AActor* actor); // called after AActor::Die of each actor. void WorldThingDied(AActor* actor, AActor* inflictor); + // called when a hitscan attack is fired (can be overridden to block it) + bool WorldHitscanPreFired(AActor* actor, DAngle angle, double distance, DAngle pitch, int damage, FName damageType, PClassActor *pufftype, int flags, double sz, double offsetforward, double offsetside); + // called when a hitscan attack has been fired + void WorldHitscanFired(AActor* actor, const DVector3& AttackPos, const DVector3& DamagePosition, AActor* Inflictor, int flags); // called inside AActor::Grind just before the corpse is destroyed void WorldThingGround(AActor* actor, FState* st); // called after AActor::Revive. diff --git a/src/playsim/p_map.cpp b/src/playsim/p_map.cpp index 0f40a0937..7da6ba515 100644 --- a/src/playsim/p_map.cpp +++ b/src/playsim/p_map.cpp @@ -81,6 +81,7 @@ #include "r_utility.h" #include "p_blockmap.h" #include "p_3dmidtex.h" +#include "events.h" #include "vm.h" #include "d_main.h" @@ -4627,6 +4628,12 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, DAngle pitch, int damage, FName damageType, PClassActor *pufftype, int flags, FTranslatedLineTarget*victim, int *actualdamage, double sz, double offsetforward, double offsetside) { + if (t1->Level->localEventManager->WorldHitscanPreFired(t1, angle, distance, pitch, damage, damageType, pufftype, flags, sz, offsetforward, offsetside)) + { + return nullptr; + } + + bool nointeract = !!(flags & LAF_NOINTERACT); DVector3 direction; double shootz; @@ -4641,6 +4648,7 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, if (flags & LAF_NORANDOMPUFFZ) puffFlags |= PF_NORANDOMZ; + if (victim != NULL) { memset(victim, 0, sizeof(*victim)); @@ -4731,6 +4739,7 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, // LAF_ABSOFFSET: Ignore the angle. DVector3 tempos; + DVector3 puffpos; if (flags & LAF_ABSPOSITION) { @@ -4766,7 +4775,8 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, if (nointeract || (puffDefaults && puffDefaults->flags3 & MF3_ALWAYSPUFF)) { // Spawn the puff anyway - puff = P_SpawnPuff(t1, pufftype, trace.HitPos, trace.SrcAngleFromTarget, trace.SrcAngleFromTarget, 2, puffFlags); + puffpos = trace.HitPos; + puff = P_SpawnPuff(t1, pufftype, puffpos, trace.SrcAngleFromTarget, trace.SrcAngleFromTarget, 2, puffFlags); if (nointeract) { @@ -4796,7 +4806,8 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, if (nointeract || trace.HitType != TRACE_HitWall || ((trace.Line->special != Line_Horizon) || spawnSky)) { DVector2 pos = t1->Level->GetPortalOffsetPosition(trace.HitPos.X, trace.HitPos.Y, -trace.HitVector.X * 4, -trace.HitVector.Y * 4); - puff = P_SpawnPuff(t1, pufftype, DVector3(pos, trace.HitPos.Z - trace.HitVector.Z * 4), trace.SrcAngleFromTarget, + puffpos = DVector3(pos, trace.HitPos.Z - trace.HitVector.Z * 4); + puff = P_SpawnPuff(t1, pufftype, puffpos, trace.SrcAngleFromTarget, trace.SrcAngleFromTarget - DAngle::fromDeg(90), 0, puffFlags); puff->radius = 1/65536.; @@ -4843,6 +4854,7 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, { // Hit a thing, so it could be either a puff or blood DVector3 bleedpos = trace.HitPos; + puffpos = bleedpos; // position a bit closer for puffs/blood if using compatibility mode. if (trace.Actor->Level->i_compatflags & COMPATF_HITSCAN) { @@ -4935,6 +4947,9 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance, SpawnDeepSplash(t1, trace, puff); } } + + t1->Level->localEventManager->WorldHitscanFired(t1, tempos, puffpos, puff, flags); + if (killPuff && puff != NULL) { puff->Destroy(); @@ -5385,16 +5400,30 @@ static ETraceStatus ProcessRailHit(FTraceResults &res, void *userdata) //========================================================================== void P_RailAttack(FRailParams *p) { - DVector3 start; - FTraceResults trace; + AActor *source = p->source; PClassActor *puffclass = p->puff; if (puffclass == NULL) { puffclass = PClass::FindActor(NAME_BulletPuff); } + assert(puffclass != NULL); // Because we set it to a default above + AActor *puffDefaults = GetDefaultByType(puffclass->GetReplacement(source->Level)); //Contains all the flags such as FOILINVUL, etc. + FName damagetype = (puffDefaults == NULL || puffDefaults->DamageType == NAME_None) ? FName(NAME_Railgun) : puffDefaults->DamageType; + + int flags; + + // disabled because not complete yet. + flags = (puffDefaults->flags6 & MF6_NOTRIGGER) ? TRACE_ReportPortals : TRACE_PCross | TRACE_Impact | TRACE_ReportPortals; + + if (source->Level->localEventManager->WorldHitscanPreFired(source, source->Angles.Yaw + p->angleoffset, p->distance, source->Angles.Pitch + p->pitchoffset, p->damage, damagetype, puffclass, flags, p->offset_z, 0, p->offset_xy)) + { + return; + } + + DVector3 start; + FTraceResults trace; - AActor *source = p->source; DAngle pitch = source->Angles.Pitch + p->pitchoffset; DAngle angle = source->Angles.Yaw + p->angleoffset; @@ -5423,13 +5452,6 @@ void P_RailAttack(FRailParams *p) start.Y = xy.Y; start.Z = shootz; - int flags; - - assert(puffclass != NULL); // Because we set it to a default above - AActor *puffDefaults = GetDefaultByType(puffclass->GetReplacement(source->Level)); //Contains all the flags such as FOILINVUL, etc. - - // disabled because not complete yet. - flags = (puffDefaults->flags6 & MF6_NOTRIGGER) ? TRACE_ReportPortals : TRACE_PCross | TRACE_Impact | TRACE_ReportPortals; rail_data.StopAtInvul = (puffDefaults->flags3 & MF3_FOILINVUL) ? false : true; rail_data.MThruSpecies = ((puffDefaults->flags6 & MF6_MTHRUSPECIES)) ? true : false; @@ -5466,8 +5488,7 @@ void P_RailAttack(FRailParams *p) // Hurt anything the trace hit unsigned int i; - FName damagetype = (puffDefaults == NULL || puffDefaults->DamageType == NAME_None) ? FName(NAME_Railgun) : puffDefaults->DamageType; - + for (i = 0; i < rail_data.RailHits.Size(); i++) { bool spawnpuff; @@ -5555,6 +5576,9 @@ void P_RailAttack(FRailParams *p) } } } + + source->Level->localEventManager->WorldHitscanFired(source, start, trace.HitPos, thepuff, flags); + if (thepuff != NULL) { if (trace.Crossed3DWater || trace.CrossedWater) diff --git a/wadsrc/static/zscript/events.zs b/wadsrc/static/zscript/events.zs index 52cf3a7eb..72cf23a51 100644 --- a/wadsrc/static/zscript/events.zs +++ b/wadsrc/static/zscript/events.zs @@ -97,6 +97,14 @@ struct WorldEvent native play version("2.4") native readonly bool DamageIsRadius; native int NewDamage; native readonly State CrushedState; + native readonly double AttackAngle; + native readonly double AttackPitch; + native readonly double AttackDistance; + native readonly vector3 AttackPos; + native readonly double AttackOffsetForward; + native readonly double AttackOffsetSide; + native readonly double AttackZ; + native readonly class AttackPuffType; } struct PlayerEvent native play version("2.4") @@ -155,6 +163,8 @@ class StaticEventHandler : Object native play version("2.4") virtual void WorldThingRevived(WorldEvent e) {} virtual void WorldThingDamaged(WorldEvent e) {} virtual void WorldThingDestroyed(WorldEvent e) {} + virtual bool WorldHitscanPreFired(WorldEvent e) { return false; } + virtual void WorldHitscanFired(WorldEvent e) {} virtual void WorldLinePreActivated(WorldEvent e) {} virtual void WorldLineActivated(WorldEvent e) {} virtual void WorldSectorDamaged(WorldEvent e) {} From 1825c8ba77f660bb98c14f49238d5c7555593b50 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Thu, 21 Nov 2024 04:27:02 -0500 Subject: [PATCH 92/93] Fixed poison not clearing on revive --- src/playsim/p_mobj.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index 0f9a91803..d896db678 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -7806,6 +7806,19 @@ void AActor::Revive() target = nullptr; lastenemy = nullptr; + // Make sure to clear poison damage. + PoisonDamageReceived = 0; + PoisonDamageTypeReceived = NAME_None; + PoisonDurationReceived = 0; + PoisonPeriodReceived = 0; + Poisoner = nullptr; + if (player != nullptr) + { + player->poisoncount = 0; + player->poisoner = nullptr; + player->poisontype = player->poisonpaintype = NAME_None; + } + // [RH] If it's a monster, it gets to count as another kill if (CountsAsKill()) { From 878c5f08575279171dbeb8403d2638660e3dace1 Mon Sep 17 00:00:00 2001 From: Boondorl <59555366+Boondorl@users.noreply.github.com> Date: Fri, 22 Nov 2024 06:23:53 -0500 Subject: [PATCH 93/93] Fixed missing checks in P_TestMobjZ (#2827) Adds in missing missile checks and fixes ordering to match P_CheckPosition to give more consistency. --- src/playsim/p_map.cpp | 99 +++++++++++++++++++++++++++++++++---------- 1 file changed, 76 insertions(+), 23 deletions(-) diff --git a/src/playsim/p_map.cpp b/src/playsim/p_map.cpp index 7da6ba515..f8b23a811 100644 --- a/src/playsim/p_map.cpp +++ b/src/playsim/p_map.cpp @@ -2108,10 +2108,13 @@ int P_TestMobjZ(AActor *actor, bool quick, AActor **pOnmobj) while (it.Next(&cres)) { AActor *thing = cres.thing; + if (!quick && onmobj != NULL && thing->Top() < onmobj->Top()) + { // something higher is in the way + continue; + } - double blockdist = thing->radius + actor->radius; - if (fabs(thing->X() - cres.Position.X) >= blockdist || fabs(thing->Y() - cres.Position.Y) >= blockdist) - { + if (thing == actor) + { // Don't clip against self. continue; } if (thing->flags2 & MF2_THRUACTORS) @@ -2122,19 +2125,24 @@ int P_TestMobjZ(AActor *actor, bool quick, AActor **pOnmobj) { continue; } - if ((actor->flags6 & MF6_THRUSPECIES) && (thing->GetSpecies() == actor->GetSpecies())) - { - continue; - } if (!(thing->flags & MF_SOLID)) { // Can't hit thing continue; } - if (thing->flags & (MF_SPECIAL | MF_NOCLIP)) + if ((thing->flags & (MF_SPECIAL | MF_NOCLIP)) || (thing->flags6 & MF6_TOUCHY)) { // [RH] Specials and noclippers don't block moves continue; } - if (thing->flags & (MF_CORPSE)) + const double blockdist = thing->radius + actor->radius; + if (fabs(thing->X() - cres.Position.X) >= blockdist || fabs(thing->Y() - cres.Position.Y) >= blockdist) + { + continue; + } + if ((actor->flags6 & MF6_THRUSPECIES) && thing->GetSpecies() == actor->GetSpecies()) + { + continue; + } + if (thing->flags & MF_CORPSE) { // Corpses need a few more checks if (!(actor->flags & MF_ICECORPSE)) continue; @@ -2143,33 +2151,78 @@ int P_TestMobjZ(AActor *actor, bool quick, AActor **pOnmobj) { // [RH] Only bridges block pickup items continue; } - if (thing == actor) - { // Don't clip against self - continue; - } - if ((actor->flags & MF_MISSILE) && (thing == actor->target)) - { // Don't clip against whoever shot the missile. + if (actor->player != nullptr && P_ShouldPassThroughPlayer(actor, thing)) + { continue; } if (actor->Z() > thing->Top()) { // over thing continue; } - else if (actor->Top() <= thing->Z()) + if (actor->Top() <= thing->Z()) { // under thing continue; } - else if (!quick && onmobj != NULL && thing->Top() < onmobj->Top()) - { // something higher is in the way - continue; - } - else if (!P_CanCollideWith(actor, thing)) + if (!P_CanCollideWith(actor, thing)) { // If they cannot collide, they cannot block each other. continue; } - if (actor->player && P_ShouldPassThroughPlayer(actor, thing)) + if ((actor->flags & MF_MISSILE) || ((actor->BounceFlags & BOUNCE_MBF) && !(actor->flags & MF_SOLID))) { - continue; + if (thing->flags2 & MF2_NONSHOOTABLE) + { + continue; + } + if ((thing->flags3 & MF3_GHOST) && (actor->flags2 & MF2_THRUGHOST)) + { + continue; + } + if ((thing->flags4 & MF4_SPECTRAL) && !(actor->flags4 & MF4_SPECTRAL)) + { + continue; + } + if (actor->target != nullptr) + { + if ((actor->flags6 & MF6_MTHRUSPECIES) && actor->target->GetSpecies() == thing->GetSpecies()) + { + continue; + } + if (actor->target == thing) + { + if (!(actor->flags8 & MF8_HITOWNER)) + { + continue; + } + } + else if (actor->target->player != nullptr && P_ShouldPassThroughPlayer(actor->target, thing)) + { + continue; + } + } + if ((thing->flags7 & MF7_THRUREFLECT) && (thing->flags2 & MF2_REFLECTIVE) && (actor->flags & MF_MISSILE)) + { + continue; + } + + double clipheight = thing->Height; + if (thing->projectilepassheight > 0) + { + clipheight = thing->projectilepassheight; + } + else if (thing->projectilepassheight < 0 && (thing->Level->i_compatflags & COMPATF_MISSILECLIP)) + { + clipheight = -thing->projectilepassheight; + } + if (actor->Z() > thing->Z() + clipheight) + { // Over thing + continue; + } + if ((actor->flags2 & MF2_RIP) && !(thing->flags5 & MF5_DONTRIP) + && (!(actor->flags6 & MF6_NOBOSSRIP) || !(thing->flags2 & MF2_BOSS)) + && CheckRipLevel(thing, actor)) + { + continue; + } } onmobj = thing;