From 3f4513c5713939e09ab7d9d817f692be98717bee Mon Sep 17 00:00:00 2001 From: Boondorl Date: Tue, 5 Nov 2024 15:29:57 -0500 Subject: [PATCH 01/10] 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 02/10] 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 03/10] 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 04/10] 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 05/10] 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 06/10] 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 07/10] 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 08/10] 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 09/10] 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 10/10] 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;