From a938e9c66ce38ab30234534a496c14252ec577d1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 21 Apr 2024 18:30:19 +0200 Subject: [PATCH 01/84] moved the NetworkEntityManager into the backend code. --- src/common/objects/dobject.cpp | 161 ++++++++++++++++++++++++++++++++ src/common/objects/dobject.h | 21 +++++ src/d_main.cpp | 2 + src/d_net.cpp | 162 --------------------------------- src/d_net.h | 19 ---- src/g_game.cpp | 2 +- src/p_saveg.cpp | 2 +- 7 files changed, 186 insertions(+), 183 deletions(-) diff --git a/src/common/objects/dobject.cpp b/src/common/objects/dobject.cpp index b66029a53..e3d2b9240 100644 --- a/src/common/objects/dobject.cpp +++ b/src/common/objects/dobject.cpp @@ -622,3 +622,164 @@ void *DObject::ScriptVar(FName field, PType *type) // This is only for internal use so I_Error is fine. I_Error("Variable %s not found in %s\n", field.GetChars(), cls->TypeName.GetChars()); } + + +//========================================================================== +// +// +// +//========================================================================== + +void NetworkEntityManager::InitializeNetworkEntities() +{ + if (!s_netEntities.Size()) + s_netEntities.AppendFill(nullptr, NetIDStart); // Allocate the first 0-8 slots for the world and clients. +} + +// Clients need special handling since they always go in slots 1 - MAXPLAYERS. +void NetworkEntityManager::SetClientNetworkEntity(DObject* mo, const uint32_t id) +{ + // If resurrecting, we need to swap the corpse's position with the new pawn's + // position so it's no longer considered the client's body. + DObject* const oldBody = s_netEntities[id]; + if (oldBody != nullptr) + { + if (oldBody == mo) + return; + + const uint32_t curID = mo->GetNetworkID(); + + s_netEntities[curID] = oldBody; + oldBody->ClearNetworkID(); + oldBody->SetNetworkID(curID); + + mo->ClearNetworkID(); + } + else + { + RemoveNetworkEntity(mo); // Free up its current id. + } + + s_netEntities[id] = mo; + mo->SetNetworkID(ClientNetIDStart + id); +} + +void NetworkEntityManager::AddNetworkEntity(DObject* const ent) +{ + if (ent->IsNetworked()) + return; + + // Slot 0 is reserved for the world. + // Clients go in the first 1 - MAXPLAYERS slots + // Everything else is first come first serve. + uint32_t id = WorldNetID; + if (s_openNetIDs.Size()) + { + s_openNetIDs.Pop(id); + s_netEntities[id] = ent; + } + else + { + id = s_netEntities.Push(ent); + } + + ent->SetNetworkID(id); +} + +void NetworkEntityManager::RemoveNetworkEntity(DObject* const ent) +{ + if (!ent->IsNetworked()) + return; + + const uint32_t id = ent->GetNetworkID(); + if (id == WorldNetID) + return; + + assert(s_netEntities[id] == ent); + if (id >= NetIDStart) + s_openNetIDs.Push(id); + s_netEntities[id] = nullptr; + ent->ClearNetworkID(); +} + +DObject* NetworkEntityManager::GetNetworkEntity(const uint32_t id) +{ + if (id == WorldNetID || id >= s_netEntities.Size()) + return nullptr; + + return s_netEntities[id]; +} + +//========================================================================== +// +// +// +//========================================================================== + +void DObject::SetNetworkID(const uint32_t id) +{ + if (!IsNetworked()) + { + ObjectFlags |= OF_Networked; + _networkID = id; + } +} + +void DObject::ClearNetworkID() +{ + ObjectFlags &= ~OF_Networked; + _networkID = NetworkEntityManager::WorldNetID; +} + +void DObject::EnableNetworking(const bool enable) +{ + if (enable) + NetworkEntityManager::AddNetworkEntity(this); + else + NetworkEntityManager::RemoveNetworkEntity(this); +} + +void DObject::RemoveFromNetwork() +{ + NetworkEntityManager::RemoveNetworkEntity(this); +} + +static unsigned int GetNetworkID(DObject* const self) +{ + return self->GetNetworkID(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DObject, GetNetworkID, GetNetworkID) +{ + PARAM_SELF_PROLOGUE(DObject); + + ACTION_RETURN_INT(self->GetNetworkID()); +} + +static void EnableNetworking(DObject* const self, const bool enable) +{ + self->EnableNetworking(enable); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DObject, EnableNetworking, EnableNetworking) +{ + PARAM_SELF_PROLOGUE(DObject); + PARAM_BOOL(enable); + + self->EnableNetworking(enable); + return 0; +} + +static DObject* GetNetworkEntity(const unsigned int id) +{ + return NetworkEntityManager::GetNetworkEntity(id); +} + +DEFINE_ACTION_FUNCTION_NATIVE(DObject, GetNetworkEntity, GetNetworkEntity) +{ + PARAM_PROLOGUE; + PARAM_UINT(id); + + ACTION_RETURN_OBJECT(NetworkEntityManager::GetNetworkEntity(id)); +} + diff --git a/src/common/objects/dobject.h b/src/common/objects/dobject.h index f193379c1..f7f1e195d 100644 --- a/src/common/objects/dobject.h +++ b/src/common/objects/dobject.h @@ -487,4 +487,25 @@ inline T *&DObject::PointerVar(FName field) return *(T**)ScriptVar(field, nullptr); // pointer check is more tricky and for the handful of uses in the DECORATE parser not worth the hassle. } + +class NetworkEntityManager +{ +private: + inline static TArray s_netEntities = {}; + inline static TArray s_openNetIDs = {}; + +public: + NetworkEntityManager() = delete; + + static constexpr uint32_t WorldNetID = 0u; + static constexpr uint32_t ClientNetIDStart = 1u; + inline static uint32_t NetIDStart;// = MAXPLAYERS + 1u; + + static void InitializeNetworkEntities(); + static void SetClientNetworkEntity(DObject* mo, const uint32_t id); + static void AddNetworkEntity(DObject* const ent); + static void RemoveNetworkEntity(DObject* const ent); + static DObject* GetNetworkEntity(const uint32_t id); +}; + #endif //__DOBJECT_H__ diff --git a/src/d_main.cpp b/src/d_main.cpp index 723fff388..a4e8f5eb9 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1,4 +1,5 @@ //----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- // Copyright 1993-1996 id Software // Copyright 1999-2016 Randy Heit // Copyright 2002-2016 Christoph Oelckers @@ -3617,6 +3618,7 @@ static int D_DoomMain_Internal (void) const char *wad; FIWadManager *iwad_man; + NetworkEntityManager::NetIDStart = MAXPLAYERS + 1; GC::AddMarkerFunc(GC_MarkGameRoots); VM_CastSpriteIDToString = Doom_CastSpriteIDToString; diff --git a/src/d_net.cpp b/src/d_net.cpp index 656b07e0b..d70425f76 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -2971,168 +2971,6 @@ int Net_GetLatency(int *ld, int *ad) // //========================================================================== -void NetworkEntityManager::InitializeNetworkEntities() -{ - if (!s_netEntities.Size()) - s_netEntities.AppendFill(nullptr, NetIDStart); // Allocate the first 0-8 slots for the world and clients. -} - -// Clients need special handling since they always go in slots 1 - MAXPLAYERS. -void NetworkEntityManager::SetClientNetworkEntity(player_t* const client) -{ - AActor* const mo = client->mo; - const uint32_t id = ClientNetIDStart + mo->Level->PlayerNum(client); - - // If resurrecting, we need to swap the corpse's position with the new pawn's - // position so it's no longer considered the client's body. - DObject* const oldBody = s_netEntities[id]; - if (oldBody != nullptr) - { - if (oldBody == mo) - return; - - const uint32_t curID = mo->GetNetworkID(); - - s_netEntities[curID] = oldBody; - oldBody->ClearNetworkID(); - oldBody->SetNetworkID(curID); - - mo->ClearNetworkID(); - } - else - { - RemoveNetworkEntity(mo); // Free up its current id. - } - - s_netEntities[id] = mo; - mo->SetNetworkID(id); -} - -void NetworkEntityManager::AddNetworkEntity(DObject* const ent) -{ - if (ent->IsNetworked()) - return; - - // Slot 0 is reserved for the world. - // Clients go in the first 1 - MAXPLAYERS slots - // Everything else is first come first serve. - uint32_t id = WorldNetID; - if (s_openNetIDs.Size()) - { - s_openNetIDs.Pop(id); - s_netEntities[id] = ent; - } - else - { - id = s_netEntities.Push(ent); - } - - ent->SetNetworkID(id); -} - -void NetworkEntityManager::RemoveNetworkEntity(DObject* const ent) -{ - if (!ent->IsNetworked()) - return; - - const uint32_t id = ent->GetNetworkID(); - if (id == WorldNetID) - return; - - assert(s_netEntities[id] == ent); - if (id >= NetIDStart) - s_openNetIDs.Push(id); - s_netEntities[id] = nullptr; - ent->ClearNetworkID(); -} - -DObject* NetworkEntityManager::GetNetworkEntity(const uint32_t id) -{ - if (id == WorldNetID || id >= s_netEntities.Size()) - return nullptr; - - return s_netEntities[id]; -} - -//========================================================================== -// -// -// -//========================================================================== - -void DObject::SetNetworkID(const uint32_t id) -{ - if (!IsNetworked()) - { - ObjectFlags |= OF_Networked; - _networkID = id; - } -} - -void DObject::ClearNetworkID() -{ - ObjectFlags &= ~OF_Networked; - _networkID = NetworkEntityManager::WorldNetID; -} - -void DObject::EnableNetworking(const bool enable) -{ - if (enable) - NetworkEntityManager::AddNetworkEntity(this); - else - NetworkEntityManager::RemoveNetworkEntity(this); -} - -void DObject::RemoveFromNetwork() -{ - NetworkEntityManager::RemoveNetworkEntity(this); -} - -static unsigned int GetNetworkID(DObject* const self) -{ - return self->GetNetworkID(); -} - -DEFINE_ACTION_FUNCTION_NATIVE(DObject, GetNetworkID, GetNetworkID) -{ - PARAM_SELF_PROLOGUE(DObject); - - ACTION_RETURN_INT(self->GetNetworkID()); -} - -static void EnableNetworking(DObject* const self, const bool enable) -{ - self->EnableNetworking(enable); -} - -DEFINE_ACTION_FUNCTION_NATIVE(DObject, EnableNetworking, EnableNetworking) -{ - PARAM_SELF_PROLOGUE(DObject); - PARAM_BOOL(enable); - - self->EnableNetworking(enable); - return 0; -} - -static DObject* GetNetworkEntity(const unsigned int id) -{ - return NetworkEntityManager::GetNetworkEntity(id); -} - -DEFINE_ACTION_FUNCTION_NATIVE(DObject, GetNetworkEntity, GetNetworkEntity) -{ - PARAM_PROLOGUE; - PARAM_UINT(id); - - ACTION_RETURN_OBJECT(NetworkEntityManager::GetNetworkEntity(id)); -} - -//========================================================================== -// -// -// -//========================================================================== - // [RH] List "ping" times CCMD (pings) { diff --git a/src/d_net.h b/src/d_net.h index e4029bd66..e6a6a32b9 100644 --- a/src/d_net.h +++ b/src/d_net.h @@ -98,25 +98,6 @@ extern int ticdup; class player_t; class DObject; -class NetworkEntityManager -{ -private: - inline static TArray s_netEntities = {}; - inline static TArray s_openNetIDs = {}; - -public: - NetworkEntityManager() = delete; - - inline static uint32_t WorldNetID = 0u; - inline static uint32_t ClientNetIDStart = 1u; - inline static uint32_t NetIDStart = MAXPLAYERS + 1u; - - static void InitializeNetworkEntities(); - static void SetClientNetworkEntity(player_t* const client); - static void AddNetworkEntity(DObject* const ent); - static void RemoveNetworkEntity(DObject* const ent); - static DObject* GetNetworkEntity(const uint32_t id); -}; // [RH] // New generic packet structure: diff --git a/src/g_game.cpp b/src/g_game.cpp index ac09977d8..56a84d482 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1425,7 +1425,7 @@ void FLevelLocals::PlayerReborn (int player) p->oldbuttons = ~0, p->attackdown = true; p->usedown = true; // don't do anything immediately p->original_oldbuttons = ~0; p->playerstate = PST_LIVE; - NetworkEntityManager::SetClientNetworkEntity(p); + NetworkEntityManager::SetClientNetworkEntity(p->mo, p - players); if (gamestate != GS_TITLELEVEL) { diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index de4f7c1c1..e58124759 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -660,7 +660,7 @@ void FLevelLocals::SerializePlayers(FSerializer &arc, bool skipload) for (unsigned int i = 0u; i < MAXPLAYERS; ++i) { if (PlayerInGame(i) && Players[i]->mo != nullptr) - NetworkEntityManager::SetClientNetworkEntity(Players[i]); + NetworkEntityManager::SetClientNetworkEntity(Players[i]->mo, i); } } } From d45a4f18d46f482847f8d54300c87d9dafd7cadc Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 22 Apr 2024 07:14:04 +0200 Subject: [PATCH 02/84] fix lifetime of skyinfo variable in HWWall::SkyPlane. --- src/rendering/hwrenderer/scene/hw_sky.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rendering/hwrenderer/scene/hw_sky.cpp b/src/rendering/hwrenderer/scene/hw_sky.cpp index dfa954530..45ff8c5e7 100644 --- a/src/rendering/hwrenderer/scene/hw_sky.cpp +++ b/src/rendering/hwrenderer/scene/hw_sky.cpp @@ -137,9 +137,9 @@ void HWWall::SkyPlane(HWWallDispatcher *di, sector_t *sector, int plane, bool al // Either a regular sky or a skybox with skyboxes disabled if ((sportal == nullptr && sector->GetTexture(plane) == skyflatnum) || (gl_noskyboxes && sportal != nullptr && sportal->mType == PORTS_SKYVIEWPOINT)) { + HWSkyInfo skyinfo; if (di->di) { - HWSkyInfo skyinfo; skyinfo.init(di->di, sector, plane, sector->skytransfer, Colormap.FadeColor); ptype = PORTALTYPE_SKY; sky = &skyinfo; From 29e103363e960d6bc9af6bedf2c90153b808f541 Mon Sep 17 00:00:00 2001 From: nashmuhandes Date: Mon, 22 Apr 2024 22:09:32 +0800 Subject: [PATCH 03/84] ZDRay specs fix --- specs/udmf_zdoom.txt | 2 +- src/namedef_custom.h | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/specs/udmf_zdoom.txt b/specs/udmf_zdoom.txt index e3c73df4d..402f3d6e8 100644 --- a/specs/udmf_zdoom.txt +++ b/specs/udmf_zdoom.txt @@ -424,7 +424,7 @@ Note: All fields default to false unless mentioned otherwise. lm_sampledist = ; // ZDRay lightmap sample distance for the entire map. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 8 lm_suncolor = ; // ZDRay lightmap sun color in hex. Default = "FFFFFF" - sourceradius = ; // ZDRay lightmap light soft shadow amount. Higher values produce softer shadows. Default = 5.0 + SourceRadius = ; // ZDRay lightmap light and raytraced dynamic light soft shadow amount. Higher values produce softer shadows. Default = 5.0 friendlyseeblocks = ; // How far (in block units) a friendly monster can see other monsters. Default 10 diff --git a/src/namedef_custom.h b/src/namedef_custom.h index 7d6d095f2..e04dc3795 100644 --- a/src/namedef_custom.h +++ b/src/namedef_custom.h @@ -863,7 +863,9 @@ xx(lm_sampledist_ceiling) xx(lm_dynamic) xx(lm_suncolor) xx(lm_sampledist) -xx(sourceradius) + +// Light keywords +xx(SourceRadius) xx(skew_bottom_type) xx(skew_middle_type) From a3e61ce33ba454cdc0e41def2ef3fa969c6f5793 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Mon, 22 Apr 2024 16:53:12 -0400 Subject: [PATCH 04/84] - `-norun` now implies `-stdout` on Windows as it's useless without it --- src/common/platform/win32/i_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/platform/win32/i_main.cpp b/src/common/platform/win32/i_main.cpp index 6977055b7..acadc2dc8 100644 --- a/src/common/platform/win32/i_main.cpp +++ b/src/common/platform/win32/i_main.cpp @@ -158,7 +158,7 @@ int DoMain (HINSTANCE hInstance) Args->AppendArg(FString(wargv[i])); } - if (Args->CheckParm("-stdout")) + if (Args->CheckParm("-stdout") || Args->CheckParm("-norun")) { // As a GUI application, we don't normally get a console when we start. // If we were run from the shell and are on XP+, we can attach to its From 586e89954a6d706efd184adb04079b998de12535 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Tue, 23 Apr 2024 20:30:44 -0400 Subject: [PATCH 05/84] - fixed: rollsprites now 'unstretch' properly in regular y-billboarding --- src/rendering/hwrenderer/scene/hw_sprites.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/rendering/hwrenderer/scene/hw_sprites.cpp b/src/rendering/hwrenderer/scene/hw_sprites.cpp index 8ada22c8b..341bb2001 100644 --- a/src/rendering/hwrenderer/scene/hw_sprites.cpp +++ b/src/rendering/hwrenderer/scene/hw_sprites.cpp @@ -355,6 +355,12 @@ void HandleSpriteOffsets(Matrix3x4 *mat, const FRotator *HW, FVector2 *offset, b bool HWSprite::CalculateVertices(HWDrawInfo* di, FVector3* v, DVector3* vp) { + float pixelstretch = 1.2; + if (actor && actor->Level) + pixelstretch = actor->Level->pixelstretch; + else if (particle && particle->subsector && particle->subsector->sector && particle->subsector->sector->Level) + pixelstretch = particle->subsector->sector->Level->pixelstretch; + FVector3 center = FVector3((x1 + x2) * 0.5, (y1 + y2) * 0.5, (z1 + z2) * 0.5); const auto& HWAngles = di->Viewpoint.HWAngles; Matrix3x4 mat; @@ -421,12 +427,6 @@ bool HWSprite::CalculateVertices(HWDrawInfo* di, FVector3* v, DVector3* vp) // [Nash] check for special sprite drawing modes if (drawWithXYBillboard || isWallSprite) { - float pixelstretch = 1.2; - if (actor && actor->Level) - pixelstretch = actor->Level->pixelstretch; - else if (particle && particle->subsector && particle->subsector->sector && particle->subsector->sector->Level) - pixelstretch = particle->subsector->sector->Level->pixelstretch; - mat.MakeIdentity(); mat.Translate(center.X, center.Z, center.Y); // move to sprite center mat.Scale(1.0, 1.0/pixelstretch, 1.0); // unstretch sprite by level aspect ratio @@ -509,9 +509,11 @@ bool HWSprite::CalculateVertices(HWDrawInfo* di, FVector3* v, DVector3* vp) float rollDegrees = Angles.Roll.Degrees(); mat.Translate(center.X, center.Z, center.Y); + mat.Scale(1.0, 1.0/pixelstretch, 1.0); // unstretch sprite by level aspect ratio if (useOffsets) mat.Translate(xx, zz, yy); mat.Rotate(cos(angleRad), 0, sin(angleRad), rollDegrees); if (useOffsets) mat.Translate(-xx, -zz, -yy); + mat.Scale(1.0, pixelstretch, 1.0); // stretch sprite by level aspect ratio mat.Translate(-center.X, -center.Z, -center.Y); } From 83d751af72b51223ccee97c32fda3b363ccbcd10 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Wed, 24 Apr 2024 06:52:01 -0400 Subject: [PATCH 06/84] - demote SDL_Wait errors to console printouts --- libraries/ZWidget/src/window/sdl2/sdl2displaywindow.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libraries/ZWidget/src/window/sdl2/sdl2displaywindow.cpp b/libraries/ZWidget/src/window/sdl2/sdl2displaywindow.cpp index 2cb52e2b5..808244a22 100644 --- a/libraries/ZWidget/src/window/sdl2/sdl2displaywindow.cpp +++ b/libraries/ZWidget/src/window/sdl2/sdl2displaywindow.cpp @@ -289,7 +289,11 @@ void SDL2DisplayWindow::RunLoop() SDL_Event event; int result = SDL_WaitEvent(&event); if (result == 0) - throw std::runtime_error(std::string("SDL_WaitEvent failed:") + SDL_GetError()); + { + fprintf(stderr, "SDL_WaitEvent failed: "); + fprintf(stderr, SDL_GetError()); + fprintf(stderr, "\n"); + } DispatchEvent(event); } } From eba90361646fba61a0f0b809df3e58c77ff5d97c Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Wed, 24 Apr 2024 07:17:09 -0400 Subject: [PATCH 07/84] - shorten sdl_waitevent error message --- libraries/ZWidget/src/window/sdl2/sdl2displaywindow.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/libraries/ZWidget/src/window/sdl2/sdl2displaywindow.cpp b/libraries/ZWidget/src/window/sdl2/sdl2displaywindow.cpp index 808244a22..9ccf859e0 100644 --- a/libraries/ZWidget/src/window/sdl2/sdl2displaywindow.cpp +++ b/libraries/ZWidget/src/window/sdl2/sdl2displaywindow.cpp @@ -289,11 +289,7 @@ void SDL2DisplayWindow::RunLoop() SDL_Event event; int result = SDL_WaitEvent(&event); if (result == 0) - { - fprintf(stderr, "SDL_WaitEvent failed: "); - fprintf(stderr, SDL_GetError()); - fprintf(stderr, "\n"); - } + fprintf(stderr, "SDL_WaitEvent failed: %s\n", SDL_GetError()); DispatchEvent(event); } } From d9f03863bfd80157c9d67c0c4b05d4d7e98cd90c Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Thu, 25 Apr 2024 02:27:20 -0400 Subject: [PATCH 08/84] - make gcc14 happy --- libraries/ZWidget/src/widgets/lineedit/lineedit.cpp | 2 +- src/common/filesystem/source/resourcefile.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/ZWidget/src/widgets/lineedit/lineedit.cpp b/libraries/ZWidget/src/widgets/lineedit/lineedit.cpp index 34391fd19..5c90e68e1 100644 --- a/libraries/ZWidget/src/widgets/lineedit/lineedit.cpp +++ b/libraries/ZWidget/src/widgets/lineedit/lineedit.cpp @@ -1,4 +1,4 @@ - +#include #include "widgets/lineedit/lineedit.h" #include "core/utf8reader.h" #include "core/colorf.h" diff --git a/src/common/filesystem/source/resourcefile.cpp b/src/common/filesystem/source/resourcefile.cpp index 7a6085d2f..81e2b7850 100644 --- a/src/common/filesystem/source/resourcefile.cpp +++ b/src/common/filesystem/source/resourcefile.cpp @@ -34,6 +34,7 @@ ** */ +#include #include #include "resourcefile.h" #include "md5.hpp" @@ -45,7 +46,7 @@ #include "wildcards.hpp" namespace FileSys { - + // this is for restricting shared file readers to the main thread. thread_local bool mainThread; void SetMainThread() From 2b697d6c4c29b84604c1ed30031eba642d96fea4 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Thu, 25 Apr 2024 07:52:44 -0400 Subject: [PATCH 09/84] Interpolation fix for network prediction This is a minor fix for interpolation when playing online as predicted movement was not properly having its prev data reset like a real tick would be. This resulted in jittery player sprites in third person. --- src/playsim/p_user.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/playsim/p_user.cpp b/src/playsim/p_user.cpp index 9751fc268..b67ed2bb9 100644 --- a/src/playsim/p_user.cpp +++ b/src/playsim/p_user.cpp @@ -1481,6 +1481,8 @@ void P_PredictPlayer (player_t *player) R_RebuildViewInterpolation(player); player->cmd = localcmds[i % LOCALCMDTICS]; + player->mo->ClearInterpolation(); + player->mo->ClearFOVInterpolation(); P_PlayerThink (player); player->mo->Tick (); From 7c9c7fa1f7886501515903eaa50fa41541382188 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 25 Apr 2024 18:14:39 +0200 Subject: [PATCH 10/84] fixed: AActor's members must all be native. The morph code added 4 scripted ones, but AActor's size must be known at compile time. --- src/playsim/actor.h | 7 ++++++- src/playsim/p_mobj.cpp | 8 +++++++- src/scripting/vmthunks_actors.cpp | 4 ++++ wadsrc/static/zscript/actors/morph.zs | 8 ++++---- 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/playsim/actor.h b/src/playsim/actor.h index 8e562f125..ece9be8e0 100644 --- a/src/playsim/actor.h +++ b/src/playsim/actor.h @@ -1362,18 +1362,23 @@ class AActor final : public DThinker DVector3 Prev; DRotator PrevAngles; DAngle PrevFOV; - int PrevPortalGroup; TArray AttachedLights; TDeletingArray UserLights; + int PrevPortalGroup; // When was this actor spawned? int SpawnTime; uint32_t SpawnOrder; + int UnmorphTime; + int MorphFlags; + int PremorphProperties; + PClassActor* MorphExitFlash; // landing speed from a jump with normal gravity (squats the player's view) // (note: this is put into AActor instead of the PlayerPawn because non-players also use the value) double LandingSpeed; + // ThingIDs void SetTID (int newTID); diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index 5e7a19f0c..185260505 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -393,7 +393,13 @@ void AActor::Serialize(FSerializer &arc) A("userlights", UserLights) A("WorldOffset", WorldOffset) ("modelData", modelData) - A("LandingSpeed", LandingSpeed); + A("LandingSpeed", LandingSpeed) + + ("unmorphtime", UnmorphTime) + ("morphflags", MorphFlags) + ("premorphproperties", PremorphProperties) + ("morphexitflash", MorphExitFlash); + SerializeTerrain(arc, "floorterrain", floorterrain, &def->floorterrain); SerializeArgs(arc, "args", args, def->args, special); diff --git a/src/scripting/vmthunks_actors.cpp b/src/scripting/vmthunks_actors.cpp index 7094212e0..acf253807 100644 --- a/src/scripting/vmthunks_actors.cpp +++ b/src/scripting/vmthunks_actors.cpp @@ -2126,6 +2126,10 @@ DEFINE_FIELD(AActor, ShadowAimFactor) DEFINE_FIELD(AActor, ShadowPenaltyFactor) DEFINE_FIELD(AActor, AutomapOffsets) DEFINE_FIELD(AActor, LandingSpeed) +DEFINE_FIELD(AActor, UnmorphTime) +DEFINE_FIELD(AActor, MorphFlags) +DEFINE_FIELD(AActor, PremorphProperties) +DEFINE_FIELD(AActor, MorphExitFlash) DEFINE_FIELD_X(FCheckPosition, FCheckPosition, thing); DEFINE_FIELD_X(FCheckPosition, FCheckPosition, pos); diff --git a/wadsrc/static/zscript/actors/morph.zs b/wadsrc/static/zscript/actors/morph.zs index b9fdbb101..9cd21287a 100644 --- a/wadsrc/static/zscript/actors/morph.zs +++ b/wadsrc/static/zscript/actors/morph.zs @@ -35,10 +35,10 @@ extend class Actor MPROP_INVIS = 1 << 6, } - int UnmorphTime; - EMorphFlags MorphFlags; - class MorphExitFlash; - EPremorphProperty PremorphProperties; + native int UnmorphTime; + native int MorphFlags; + native class MorphExitFlash; + native int PremorphProperties; // Players still track these separately for legacy reasons. void SetMorphStyle(EMorphFlags flags) From 566e03da60faccd0139829e25cc56d8fa7df6f72 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Thu, 25 Apr 2024 12:55:26 -0400 Subject: [PATCH 11/84] Fixed incorrect automap arrow position in multiplayer This caused the player arrows to update at only 35Hz and for the console player's arrow it would lag behind when following. --- src/am_map.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/am_map.cpp b/src/am_map.cpp index f08ce8909..48bc53823 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -2880,7 +2880,8 @@ void DAutomap::drawPlayers () if (p->mo != nullptr) { - DVector3 pos = p->mo->PosRelative(MapPortalGroup); + DVector2 pos = p->mo->InterpolatedPosition(r_viewpoint.TicFrac).XY(); + pos += Level->Displacements.getOffset(Level->PointInSector(pos)->PortalGroup, MapPortalGroup); pt.x = pos.X; pt.y = pos.Y; From cf6bad97e8d913dcd50df987172909dd6df28dcc Mon Sep 17 00:00:00 2001 From: Boondorl Date: Wed, 24 Apr 2024 12:46:30 -0400 Subject: [PATCH 12/84] Fixes for client network IDs Fixed an off-by-one error on client IDs (these need to start at 1 as 0 is an invalid network ID). Morphing will now swap the client body's ID so it remains in the first 1 - MAXPLAYERS slots. --- src/common/objects/dobject.cpp | 3 ++- src/common/objects/dobject.h | 2 +- src/playsim/p_mobj.cpp | 4 ++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/common/objects/dobject.cpp b/src/common/objects/dobject.cpp index e3d2b9240..dc0d9a579 100644 --- a/src/common/objects/dobject.cpp +++ b/src/common/objects/dobject.cpp @@ -637,10 +637,11 @@ void NetworkEntityManager::InitializeNetworkEntities() } // Clients need special handling since they always go in slots 1 - MAXPLAYERS. -void NetworkEntityManager::SetClientNetworkEntity(DObject* mo, const uint32_t id) +void NetworkEntityManager::SetClientNetworkEntity(DObject* mo, const unsigned int playNum) { // If resurrecting, we need to swap the corpse's position with the new pawn's // position so it's no longer considered the client's body. + const uint32_t id = ClientNetIDStart + playNum; DObject* const oldBody = s_netEntities[id]; if (oldBody != nullptr) { diff --git a/src/common/objects/dobject.h b/src/common/objects/dobject.h index f7f1e195d..c0b6aecb5 100644 --- a/src/common/objects/dobject.h +++ b/src/common/objects/dobject.h @@ -502,7 +502,7 @@ class NetworkEntityManager inline static uint32_t NetIDStart;// = MAXPLAYERS + 1u; static void InitializeNetworkEntities(); - static void SetClientNetworkEntity(DObject* mo, const uint32_t id); + static void SetClientNetworkEntity(DObject* mo, const unsigned int playNum); static void AddNetworkEntity(DObject* const ent); static void RemoveNetworkEntity(DObject* const ent); static DObject* GetNetworkEntity(const uint32_t id); diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index 185260505..3bc54c8d7 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -5390,6 +5390,10 @@ int MorphPointerSubstitution(AActor* from, AActor* to) { to->player = from->player; from->player = nullptr; + + // Swap the new body into the right network slot if it's a client (this doesn't + // really matter for regular Actors since they grab any ID they can get anyway). + NetworkEntityManager::SetClientNetworkEntity(to, to->player - players); } if (from->alternative != nullptr) From ca95e18742371730702e3d8785e9200b1adcf028 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Thu, 25 Apr 2024 16:10:00 -0400 Subject: [PATCH 13/84] View fixes when predicting View interpolation paths are now reset properly when predicting, fixing portals. Teleporters disabling view interpolation is now handled before every movement instead of only once at the start of predicting. Enabled FoV interpolation when playing online. --- src/playsim/p_mobj.cpp | 4 ---- src/playsim/p_user.cpp | 21 ++++++++++++--------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index 3bc54c8d7..671a65238 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -3662,10 +3662,6 @@ void AActor::SetViewAngle(DAngle ang, int fflags) double AActor::GetFOV(double ticFrac) { - // [B] Disable interpolation when playing online, otherwise it gets vomit inducing - if (netgame) - return player ? player->FOV : CameraFOV; - double fov; if (player) { diff --git a/src/playsim/p_user.cpp b/src/playsim/p_user.cpp index b67ed2bb9..055b347a1 100644 --- a/src/playsim/p_user.cpp +++ b/src/playsim/p_user.cpp @@ -1437,7 +1437,6 @@ void P_PredictPlayer (player_t *player) act->flags &= ~MF_PICKUP; act->flags2 &= ~MF2_PUSHWALL; - act->renderflags &= ~RF_NOINTERPOLATEVIEW; player->cheats |= CF_PREDICTING; BackupNodeList(act, act->touching_sectorlist, §or_t::touching_thinglist, PredictionTouchingSectors_sprev_Backup, PredictionTouchingSectorsBackup); @@ -1474,11 +1473,16 @@ void P_PredictPlayer (player_t *player) act->BlockNode = NULL; // Values too small to be usable for lerping can be considered "off". - bool CanLerp = (!(cl_predict_lerpscale < 0.01f) && (ticdup == 1)), DoLerp = false, NoInterpolateOld = R_GetViewInterpolationStatus(); + bool CanLerp = (!(cl_predict_lerpscale < 0.01f) && (ticdup == 1)), DoLerp = false; + // This essentially acts like a mini P_Ticker where only the stuff relevant to the client is actually + // called. Call order is preserved. for (int i = gametic; i < maxtic; ++i) { - if (!NoInterpolateOld) - R_RebuildViewInterpolation(player); + // Make sure any portal paths have been cleared from the previous movement. + R_ClearInterpolationPath(); + r_NoInterpolate = false; + // Because we're always predicting, this will get set by teleporters and then can never unset itself in the renderer properly. + player->mo->renderflags &= ~RF_NOINTERPOLATEVIEW; player->cmd = localcmds[i % LOCALCMDTICS]; player->mo->ClearInterpolation(); @@ -1486,7 +1490,7 @@ void P_PredictPlayer (player_t *player) P_PlayerThink (player); player->mo->Tick (); - if (CanLerp && PredictionLast.gametic > 0 && i == PredictionLast.gametic && !NoInterpolateOld) + if (CanLerp && PredictionLast.gametic > 0 && i == PredictionLast.gametic) { // Z is not compared as lifts will alter this with no apparent change // Make lerping less picky by only testing whole units @@ -1503,12 +1507,11 @@ void P_PredictPlayer (player_t *player) } } + // TODO: This should be changed to a proper rubberbanding solution in the near future (only rubberband if there was + // a mismatch between client's last predicted pos and current predicted pos). if (CanLerp) { - if (NoInterpolateOld) - P_PredictionLerpReset(); - - else if (DoLerp) + if (DoLerp) { // If lerping is already in effect, use the previous camera postion so the view doesn't suddenly snap PredictionLerpFrom = (PredictionLerptics == 0) ? PredictionLast : PredictionLerpResult; From f0aa0acf0849bd1f776f1263cec22a83c8f9c051 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Thu, 25 Apr 2024 18:09:53 -0400 Subject: [PATCH 14/84] Fixed changeskill being unnetworked --- src/console/c_cmds.cpp | 5 +++-- src/d_net.cpp | 5 +++++ src/d_protocol.h | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/console/c_cmds.cpp b/src/console/c_cmds.cpp index b4e9b8810..19c5c9d50 100644 --- a/src/console/c_cmds.cpp +++ b/src/console/c_cmds.cpp @@ -412,7 +412,7 @@ CCMD (changeskill) { if (!players[consoleplayer].mo || !usergame) { - Printf ("Use the skill command when not in a game.\n"); + Printf ("Cannot change skills while not in a game.\n"); return; } @@ -431,7 +431,8 @@ CCMD (changeskill) } else { - NextSkill = skill; + Net_WriteInt8(DEM_CHANGESKILL); + Net_WriteInt32(skill); Printf ("Skill %d will take effect on the next map.\n", skill); } } diff --git a/src/d_net.cpp b/src/d_net.cpp index d70425f76..b785b52e2 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -2753,6 +2753,10 @@ void Net_DoCommand (int type, uint8_t **stream, int player) primaryLevel->localEventManager->NetCommand(netCmd); } break; + + case DEM_CHANGESKILL: + NextSkill = ReadInt32(stream); + break; default: I_Error ("Unknown net command: %d", type); @@ -2848,6 +2852,7 @@ void Net_SkipCommand (int type, uint8_t **stream) case DEM_INVUSE: case DEM_FOV: case DEM_MYFOV: + case DEM_CHANGESKILL: skip = 4; break; diff --git a/src/d_protocol.h b/src/d_protocol.h index 33fa10966..f726a6ef2 100644 --- a/src/d_protocol.h +++ b/src/d_protocol.h @@ -164,6 +164,7 @@ enum EDemoCommand DEM_SETINV, // 72 SetInventory DEM_ENDSCREENJOB, DEM_ZSC_CMD, // 74 String: Command, Word: Byte size of command + DEM_CHANGESKILL, // 75 Int: Skill }; // The following are implemented by cht_DoCheat in m_cheat.cpp From 287277b1f8058f8d4ba7a92e24089ce7fb10f8ee Mon Sep 17 00:00:00 2001 From: Boondorl Date: Fri, 26 Apr 2024 13:10:49 -0400 Subject: [PATCH 15/84] Player spawn fix in co-op new games If there aren't enough player spawns present in co-op, the game will instead fail to spawn extra players, waiting for the ticker to automatically capture the fact they have PST_ENTER. This presents a problem in WorldLoaded() where it becomes unreliable whether or not a player has truly spawned. This also means those extra players had slightly different spawn behavior compared to regular pawns. --- src/g_level.cpp | 2 +- src/p_setup.cpp | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/g_level.cpp b/src/g_level.cpp index 686057d64..1278494b2 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1478,7 +1478,7 @@ void FLevelLocals::DoLoadLevel(const FString &nextmapname, int position, bool au for (int i = 0; imo != nullptr) - P_PlayerStartStomp(Players[i]->mo); + P_PlayerStartStomp(Players[i]->mo, !deathmatch); } } diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 02f89c860..23bf28e98 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -504,6 +504,18 @@ void P_SetupLevel(FLevelLocals *Level, int position, bool newGame) } } } + else if (newGame) + { + for (i = 0; i < MAXPLAYERS; ++i) + { + // Didn't have a player spawn available so spawn it now. + if (Level->PlayerInGame(i) && Level->Players[i]->playerstate == PST_ENTER && Level->Players[i]->mo == nullptr) + { + FPlayerStart* mthing = Level->PickPlayerStart(i); + Level->SpawnPlayer(mthing, i, (Level->flags2 & LEVEL2_PRERAISEWEAPON) ? SPF_WEAPONFULLYUP : 0); + } + } + } // [SP] move unfriendly players around // horribly hacky - yes, this needs rewritten. From 12d0c946f059759634d8744c7f5d084ec6089120 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Fri, 26 Apr 2024 15:12:47 -0400 Subject: [PATCH 16/84] Reworked clientside lerping Now acts as a rubberbanding effect. The result is that movement is now considered correct and adjusted towards the real position if not rather than cautiously moving towards the predicted position. --- src/playsim/p_user.cpp | 140 +++++++++++++++++++++-------------------- 1 file changed, 72 insertions(+), 68 deletions(-) diff --git a/src/playsim/p_user.cpp b/src/playsim/p_user.cpp index 055b347a1..d00f7571b 100644 --- a/src/playsim/p_user.cpp +++ b/src/playsim/p_user.cpp @@ -103,16 +103,26 @@ CVAR(Bool, sv_singleplayerrespawn, false, CVAR_SERVERINFO | CVAR_CHEAT) // Variables for prediction CVAR (Bool, cl_noprediction, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR(Bool, cl_predict_specials, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +// Deprecated +CVAR(Float, cl_predict_lerpscale, 0.05f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +CVAR(Float, cl_predict_lerpthreshold, 2.00f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) -CUSTOM_CVAR(Float, cl_predict_lerpscale, 0.05f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +CUSTOM_CVAR(Float, cl_rubberband_scale, 0.3f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) { - P_PredictionLerpReset(); + if (self < 0.0f) + self = 0.0f; + else if (self > 1.0f) + self = 1.0f; } -CUSTOM_CVAR(Float, cl_predict_lerpthreshold, 2.00f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +CUSTOM_CVAR(Float, cl_rubberband_threshold, 20.0f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (self < 0.1f) + self = 0.1f; +} +CUSTOM_CVAR(Float, cl_rubberband_minmove, 20.0f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) { if (self < 0.1f) self = 0.1f; - P_PredictionLerpReset(); } ColorSetList ColorSets; @@ -125,13 +135,9 @@ CUSTOM_CVAR(Float, fov, 90.f, CVAR_ARCHIVE | CVAR_USERINFO | CVAR_NOINITCALL) p->SetFOV(fov); } -struct PredictPos -{ - int gametic; - DVector3 pos; - DRotator angles; -} static PredictionLerpFrom, PredictionLerpResult, PredictionLast; -static int PredictionLerptics; +static DVector3 LastPredictedPosition; +static int LastPredictedPortalGroup; +static int LastPredictedTic; static player_t PredictionPlayerBackup; static AActor *PredictionActor; @@ -1290,23 +1296,25 @@ void P_PlayerThink (player_t *player) void P_PredictionLerpReset() { - PredictionLerptics = PredictionLast.gametic = PredictionLerpFrom.gametic = PredictionLerpResult.gametic = 0; + LastPredictedPosition = DVector3{}; + LastPredictedPortalGroup = 0; + LastPredictedTic = -1; } -bool P_LerpCalculate(AActor *pmo, PredictPos from, PredictPos to, PredictPos &result, float scale) +void P_LerpCalculate(AActor* pmo, const DVector3& from, DVector3 &result, float scale, float threshold, float minMove) { - DVector3 vecFrom = from.pos; - DVector3 vecTo = to.pos; - DVector3 vecResult; - vecResult = vecTo - vecFrom; - vecResult *= scale; - vecResult = vecResult + vecFrom; - DVector3 delta = vecResult - vecTo; - - result.pos = pmo->Vec3Offset(vecResult - to.pos); + DVector3 diff = pmo->Pos() - from; + diff.XY() += pmo->Level->Displacements.getOffset(pmo->Sector->PortalGroup, pmo->Level->PointInSector(from.XY())->PortalGroup); + double dist = diff.Length(); + if (dist <= max(threshold, minMove)) + { + result = pmo->Pos(); + return; + } - // As a fail safe, assume extrapolation is the threshold. - return (delta.LengthSquared() > cl_predict_lerpthreshold && scale <= 1.00f); + diff /= dist; + diff *= min(dist * (1.0f - scale), dist - minMove); + result = pmo->Vec3Offset(-diff.X, -diff.Y, -diff.Z); } template @@ -1472,10 +1480,12 @@ void P_PredictPlayer (player_t *player) } act->BlockNode = NULL; - // Values too small to be usable for lerping can be considered "off". - bool CanLerp = (!(cl_predict_lerpscale < 0.01f) && (ticdup == 1)), DoLerp = false; // This essentially acts like a mini P_Ticker where only the stuff relevant to the client is actually // called. Call order is preserved. + bool rubberband = false; + DVector3 rubberbandPos = {}; + const bool canRubberband = LastPredictedTic >= 0 && cl_rubberband_scale > 0.0f && cl_rubberband_scale < 1.0f; + const double rubberbandThreshold = max(cl_rubberband_minmove, cl_rubberband_threshold); for (int i = gametic; i < maxtic; ++i) { // Make sure any portal paths have been cleared from the previous movement. @@ -1484,58 +1494,52 @@ void P_PredictPlayer (player_t *player) // Because we're always predicting, this will get set by teleporters and then can never unset itself in the renderer properly. player->mo->renderflags &= ~RF_NOINTERPOLATEVIEW; + // Got snagged on something. Start correcting towards the player's final predicted position. We're + // being intentionally generous here by not really caring how the player got to that position, only + // that they ended up in the same spot on the same tick. + if (canRubberband && LastPredictedTic == i) + { + DVector3 diff = player->mo->Pos() - LastPredictedPosition; + diff += player->mo->Level->Displacements.getOffset(player->mo->Sector->PortalGroup, LastPredictedPortalGroup); + double dist = diff.LengthSquared(); + if (dist >= EQUAL_EPSILON * EQUAL_EPSILON && dist > rubberbandThreshold * rubberbandThreshold) + { + rubberband = true; + rubberbandPos = player->mo->Pos(); + } + } + player->cmd = localcmds[i % LOCALCMDTICS]; player->mo->ClearInterpolation(); player->mo->ClearFOVInterpolation(); P_PlayerThink (player); player->mo->Tick (); - - if (CanLerp && PredictionLast.gametic > 0 && i == PredictionLast.gametic) - { - // Z is not compared as lifts will alter this with no apparent change - // Make lerping less picky by only testing whole units - DoLerp = (int)PredictionLast.pos.X != (int)player->mo->X() || (int)PredictionLast.pos.Y != (int)player->mo->Y(); - - // Aditional Debug information - if (developer >= DMSG_NOTIFY && DoLerp) - { - DPrintf(DMSG_NOTIFY, "Lerp! Ltic (%d) && Ptic (%d) | Lx (%f) && Px (%f) | Ly (%f) && Py (%f)\n", - PredictionLast.gametic, i, - (PredictionLast.pos.X), (player->mo->X()), - (PredictionLast.pos.Y), (player->mo->Y())); - } - } } - // TODO: This should be changed to a proper rubberbanding solution in the near future (only rubberband if there was - // a mismatch between client's last predicted pos and current predicted pos). - if (CanLerp) + if (rubberband) { - if (DoLerp) - { - // If lerping is already in effect, use the previous camera postion so the view doesn't suddenly snap - PredictionLerpFrom = (PredictionLerptics == 0) ? PredictionLast : PredictionLerpResult; - PredictionLerptics = 1; - } - - PredictionLast.gametic = maxtic - 1; - PredictionLast.pos = player->mo->Pos(); - //PredictionLast.portalgroup = player->mo->Sector->PortalGroup; + R_ClearInterpolationPath(); + player->mo->renderflags &= ~RF_NOINTERPOLATEVIEW; - if (PredictionLerptics > 0) - { - if (PredictionLerpFrom.gametic > 0 && - P_LerpCalculate(player->mo, PredictionLerpFrom, PredictionLast, PredictionLerpResult, (float)PredictionLerptics * cl_predict_lerpscale)) - { - PredictionLerptics++; - player->mo->SetXYZ(PredictionLerpResult.pos); - } - else - { - PredictionLerptics = 0; - } - } + DPrintf(DMSG_NOTIFY, "Prediction mismatch at (%.3f, %.3f, %.3f)\nExpected: (%.3f, %.3f, %.3f)\nCorrecting to (%.3f, %.3f, %.3f)\n", + LastPredictedPosition.X, LastPredictedPosition.Y, LastPredictedPosition.Z, + rubberbandPos.X, rubberbandPos.Y, rubberbandPos.Z, + player->mo->X(), player->mo->Y(), player->mo->Z()); + + DVector3 snapPos = {}; + P_LerpCalculate(player->mo, LastPredictedPosition, snapPos, cl_rubberband_scale, cl_rubberband_threshold, cl_rubberband_minmove); + player->mo->PrevPortalGroup = LastPredictedPortalGroup; + player->mo->Prev = LastPredictedPosition; + const double zOfs = player->viewz - player->mo->Z(); + player->mo->SetXYZ(snapPos); + player->viewz = snapPos.Z + zOfs; } + + // This is intentionally done after rubberbanding starts since it'll automatically smooth itself towards + // the right spot until it reaches it. + LastPredictedTic = maxtic; + LastPredictedPosition = player->mo->Pos(); + LastPredictedPortalGroup = player->mo->Level->PointInSector(LastPredictedPosition)->PortalGroup; } void P_UnPredictPlayer () From b43c440552964578f35782714ca6765a4030ce37 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Mon, 22 Apr 2024 20:45:33 -0400 Subject: [PATCH 17/84] Added ShouldShareItem virtual Allows for easier customizing of whether or not an item should be shared with players upon pickup in co-op (e.g. it allows it to be expanded to weapons with custom cvars). --- wadsrc/static/zscript/actors/inventory/inv_misc.zs | 10 ++++++++++ wadsrc/static/zscript/actors/inventory/inventory.zs | 7 ++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/wadsrc/static/zscript/actors/inventory/inv_misc.zs b/wadsrc/static/zscript/actors/inventory/inv_misc.zs index 318d29491..7dd374932 100644 --- a/wadsrc/static/zscript/actors/inventory/inv_misc.zs +++ b/wadsrc/static/zscript/actors/inventory/inv_misc.zs @@ -43,6 +43,11 @@ class Key : Inventory static native clearscope Color GetMapColorForKey(Key key); static native clearscope int GetKeyTypeCount(); static native clearscope class GetKeyType(int index); + + override bool ShouldShareItem(Actor giver) + { + return sv_coopsharekeys; + } override bool HandlePickup (Inventory item) { @@ -113,6 +118,11 @@ class PuzzleItem : Inventory PuzzleItem.FailMessage("$TXT_USEPUZZLEFAILED"); PuzzleItem.FailSound "*puzzfail"; } + + override bool ShouldShareItem(Actor giver) + { + return sv_coopsharekeys; + } override bool HandlePickup (Inventory item) { diff --git a/wadsrc/static/zscript/actors/inventory/inventory.zs b/wadsrc/static/zscript/actors/inventory/inventory.zs index a2af10398..564989459 100644 --- a/wadsrc/static/zscript/actors/inventory/inventory.zs +++ b/wadsrc/static/zscript/actors/inventory/inventory.zs @@ -261,6 +261,11 @@ class Inventory : Actor } } + virtual bool ShouldShareItem(Actor giver) + { + return false; + } + protected void ShareItemWithPlayers(Actor giver) { if (bSharingItem) @@ -695,7 +700,7 @@ class Inventory : Actor toucher.HasReceived(self); // If the item can be shared, make sure every player gets a copy. - if (multiplayer && !deathmatch && sv_coopsharekeys && bIsKeyItem) + if (multiplayer && !deathmatch && ShouldShareItem(toucher)) ShareItemWithPlayers(toucher); } return res, toucher; From 861a557d9224b589a588c8ffda1a95750eea265a Mon Sep 17 00:00:00 2001 From: jekyllgrim Date: Sat, 6 Jan 2024 17:55:20 +0300 Subject: [PATCH 18/84] Add graycheckVal, expose hud_oldscale/hud_scalefactor to the menu Add graycheckVal to OptionMenu items Add menu elements for hud_oldscale and hud_scalefactor to menudef.txt --- wadsrc/static/menudef.txt | 8 ++-- .../zscript/engine/ui/menu/optionmenuitems.zs | 46 ++++++++++--------- 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 7c8359cd5..fe289c6c8 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -1078,9 +1078,11 @@ OptionMenu "ScalingOptions" protected StaticText "$SCALEMNU_OVERRIDE", 1 ScaleSlider "$SCALEMNU_MESSAGES", "con_scaletext", 0.0, 8.0, 1.0, "$SCALEMNU_USEUI" ScaleSlider "$SCALEMNU_CONSOLE", "con_scale", 0.0, 8.0, 1.0, "$SCALEMNU_USEUI" - ScaleSlider "$SCALEMNU_STATBAR", "st_scale", -1.0, 8.0, 1.0, "$SCALEMNU_USEUI", "$SCALEMNU_USEFS" - ScaleSlider "$SCALEMNU_HUD", "hud_scale", -1.0, 8.0, 1.0, "$SCALEMNU_USEUI", "$SCALEMNU_USEFS" - ScaleSlider "$SCALEMNU_ALTHUD", "hud_althudscale", 0.0, 8.0, 1.0, "$SCALEMNU_USEUI" + Option "$SCALEMNU_HUD_OLDSCALE", "hud_oldscale", "OnOff" + Slider "$SCALEMNU_HUD_SCALEFACTOR", "hud_scalefactor", 0.0, 1.0, 0.025, 3, "hud_oldscale", 1 + ScaleSlider "$SCALEMNU_STATBAR", "st_scale", -1.0, 8.0, 1.0, "$SCALEMNU_USEUI", "$SCALEMNU_USEFS", "hud_oldscale" + ScaleSlider "$SCALEMNU_HUD", "hud_scale", -1.0, 8.0, 1.0, "$SCALEMNU_USEUI", "$SCALEMNU_USEFS", "hud_oldscale" + ScaleSlider "$SCALEMNU_ALTHUD", "hud_althudscale", 0.0, 8.0, 1.0, "$SCALEMNU_USEUI", "", "hud_oldscale" StaticText " " Option "$SCALEMNU_HUDASPECT", "hud_aspectscale", "OnOff" StaticText " " diff --git a/wadsrc/static/zscript/engine/ui/menu/optionmenuitems.zs b/wadsrc/static/zscript/engine/ui/menu/optionmenuitems.zs index 8276dda3e..9fc0d66ff 100644 --- a/wadsrc/static/zscript/engine/ui/menu/optionmenuitems.zs +++ b/wadsrc/static/zscript/engine/ui/menu/optionmenuitems.zs @@ -37,13 +37,15 @@ class OptionMenuItem : MenuItemBase String mLabel; bool mCentered; CVar mGrayCheck; + int mGrayCheckVal; - protected void Init(String label, String command, bool center = false, CVar graycheck = null) + protected void Init(String label, String command, bool center = false, CVar graycheck = null, int graycheckVal = 0) { Super.Init(0, 0, command); mLabel = label; mCentered = center; mGrayCheck = graycheck; + mGrayCheckVal = graycheckVal; } protected void drawText(int x, int y, int color, String text, bool grayed = false) @@ -75,7 +77,7 @@ class OptionMenuItem : MenuItemBase virtual bool IsGrayed() { - return mGrayCheck != null && !mGrayCheck.GetInt(); + return mGrayCheck != null && mGrayCheck.GetInt() == mGrayCheckVal; } override bool Selectable() @@ -263,9 +265,9 @@ class OptionMenuItemOptionBase : OptionMenuItem const OP_VALUES = 0x11001; - protected void Init(String label, Name command, Name values, CVar graycheck, int center) + protected void Init(String label, Name command, Name values, CVar graycheck, int center, int graycheckVal = 0) { - Super.Init(label, command, false, graycheck); + Super.Init(label, command, false, graycheck, graycheckVal); mValues = values; mCenter = center; } @@ -361,9 +363,9 @@ class OptionMenuItemOption : OptionMenuItemOptionBase private static native void SetCVarDescription(CVar cv, String label); - OptionMenuItemOption Init(String label, Name command, Name values, CVar graycheck = null, int center = 0) + OptionMenuItemOption Init(String label, Name command, Name values, CVar graycheck = null, int center = 0, int graycheckVal = 0) { - Super.Init(label, command, values, graycheck, center); + Super.Init(label, command, values, graycheck, center, graycheckVal); mCVar = CVar.FindCVar(mAction); if (mCVar) SetCVarDescription(mCVar, label); return self; @@ -699,9 +701,9 @@ class OptionMenuSliderBase : OptionMenuItem int mDrawX; int mSliderShort; - protected void Init(String label, double min, double max, double step, int showval, Name command = 'none', CVar graycheck = NULL) + protected void Init(String label, double min, double max, double step, int showval, Name command = 'none', CVar graycheck = NULL, int graycheckVal = 0) { - Super.Init(label, command, false, graycheck); + Super.Init(label, command, false, graycheck, graycheckVal); mMin = min; mMax = max; mStep = step; @@ -855,9 +857,9 @@ class OptionMenuItemSlider : OptionMenuSliderBase { CVar mCVar; - OptionMenuItemSlider Init(String label, Name command, double min, double max, double step, int showval = 1, CVar graycheck = NULL) + OptionMenuItemSlider Init(String label, Name command, double min, double max, double step, int showval = 1, CVar graycheck = NULL, int graycheckVal = 0) { - Super.Init(label, min, max, step, showval, command, graycheck); + Super.Init(label, min, max, step, showval, command, graycheck, graycheckVal); mCVar =CVar.FindCVar(command); return self; } @@ -895,9 +897,9 @@ class OptionMenuItemColorPicker : OptionMenuItem const CPF_RESET = 0x20001; - OptionMenuItemColorPicker Init(String label, Name command, CVar graycheck = null) + OptionMenuItemColorPicker Init(String label, Name command, CVar graycheck = null, int graycheckVal = 0) { - Super.Init(label, command, false, graycheck); + Super.Init(label, command, false, graycheck, graycheckVal); CVar cv = CVar.FindCVar(command); if (cv != null && cv.GetRealType() != CVar.CVAR_Color) cv = null; mCVar = cv; @@ -974,9 +976,9 @@ class OptionMenuFieldBase : OptionMenuItem { CVar mCVar; - void Init (String label, Name command, CVar graycheck = null) + void Init (String label, Name command, CVar graycheck = null, int graycheckVal = 0) { - Super.Init(label, command, false, graycheck); + Super.Init(label, command, false, graycheck, graycheckVal); mCVar = CVar.FindCVar(mAction); } @@ -1037,9 +1039,9 @@ class OptionMenuItemTextField : OptionMenuFieldBase { TextEnterMenu mEnter; - OptionMenuItemTextField Init (String label, Name command, CVar graycheck = null) + OptionMenuItemTextField Init (String label, Name command, CVar graycheck = null, int graycheckVal = 0) { - Super.Init(label, command, graycheck); + Super.Init(label, command, graycheck, graycheckVal); mEnter = null; return self; } @@ -1109,9 +1111,9 @@ class OptionMenuItemTextField : OptionMenuFieldBase class OptionMenuItemNumberField : OptionMenuFieldBase { - OptionMenuItemNumberField Init (String label, Name command, float minimum = 0, float maximum = 100, float step = 1, CVar graycheck = null) + OptionMenuItemNumberField Init (String label, Name command, float minimum = 0, float maximum = 100, float step = 1, CVar graycheck = null, int graycheckVal = 0) { - Super.Init(label, command, graycheck); + Super.Init(label, command, graycheck, graycheckVal); mMinimum = min(minimum, maximum); mMaximum = max(minimum, maximum); mStep = max(1, step); @@ -1169,9 +1171,9 @@ class OptionMenuItemScaleSlider : OptionMenuItemSlider String TextNegOne; int mClickVal; - OptionMenuItemScaleSlider Init(String label, Name command, double min, double max, double step, String zero, String negone = "", CVar graycheck = null) + OptionMenuItemScaleSlider Init(String label, Name command, double min, double max, double step, String zero, String negone = "", CVar graycheck = null, int graycheckVal = 0) { - Super.Init(label, command, min, max, step, 0, graycheck); + Super.Init(label, command, min, max, step, 0, graycheck, graycheckVal); mCVar =CVar.FindCVar(command); TextZero = zero; TextNEgOne = negone; @@ -1237,9 +1239,9 @@ class OptionMenuItemFlagOption : OptionMenuItemOption { int mBitShift; - OptionMenuItemFlagOption Init(String label, Name command, Name values, int bitShift, CVar greycheck = null, int center = 0) + OptionMenuItemFlagOption Init(String label, Name command, Name values, int bitShift, CVar greycheck = null, int center = 0, int graycheckVal = 0) { - Super.Init(label, command, values, greycheck, center); + Super.Init(label, command, values, greycheck, center, graycheckVal); mBitShift = bitShift; return self; From f7a15bc5f9e995ff63298ccd46eef938e846306e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 27 Apr 2024 10:45:50 +0200 Subject: [PATCH 19/84] added emulation of Final Doom's teleporter z glitch and activate it for Saturnia MAP10 --- src/d_main.cpp | 2 ++ src/doomdef.h | 1 + src/maploader/compatibility.cpp | 1 + src/playsim/p_lnspec.cpp | 2 +- src/playsim/p_spec.h | 1 + src/playsim/p_teleport.cpp | 23 ++++++++++++++++++++--- wadsrc/static/compatibility.txt | 5 +++++ wadsrc/static/menudef.txt | 2 ++ 8 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index a4e8f5eb9..c570eddc4 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -713,6 +713,8 @@ CVAR (Flag, compat_railing, compatflags2, COMPATF2_RAILING); CVAR (Flag, compat_avoidhazard, compatflags2, COMPATF2_AVOID_HAZARDS); CVAR (Flag, compat_stayonlift, compatflags2, COMPATF2_STAYONLIFT); CVAR (Flag, compat_nombf21, compatflags2, COMPATF2_NOMBF21); +CVAR (Flag, compat_voodoozombies, compatflags2, COMPATF2_VOODOO_ZOMBIES); +CVAR (Flag, compat_fdteleport, compatflags2, COMPATF2_FDTELEPORT); CVAR(Bool, vid_activeinbackground, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) diff --git a/src/doomdef.h b/src/doomdef.h index 98fa88d93..811b4fa5e 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -241,6 +241,7 @@ enum : unsigned int COMPATF2_STAYONLIFT = 1 << 13, // yet another MBF thing. COMPATF2_NOMBF21 = 1 << 14, // disable MBF21 features that may clash with certain maps COMPATF2_VOODOO_ZOMBIES = 1 << 15, // [RL0] allow playerinfo, playerpawn, and voodoo health to all be different, and skip killing the player's mobj if a voodoo doll dies to allow voodoo zombies + COMPATF2_FDTELEPORT = 1 << 16, // Emulate Final Doom's teleporter z glitch. }; diff --git a/src/maploader/compatibility.cpp b/src/maploader/compatibility.cpp index 802ec3465..7caddc90a 100644 --- a/src/maploader/compatibility.cpp +++ b/src/maploader/compatibility.cpp @@ -173,6 +173,7 @@ static FCompatOption Options[] = { "scriptwait", COMPATF2_SCRIPTWAIT, SLOT_COMPAT2 }, { "nombf21", COMPATF2_NOMBF21, SLOT_COMPAT2 }, { "voodoozombies", COMPATF2_VOODOO_ZOMBIES, SLOT_COMPAT2 }, + { "fdteleport", COMPATF2_FDTELEPORT, SLOT_COMPAT2 }, { NULL, 0, 0 } }; diff --git a/src/playsim/p_lnspec.cpp b/src/playsim/p_lnspec.cpp index 73666d0c3..00318dfbb 100644 --- a/src/playsim/p_lnspec.cpp +++ b/src/playsim/p_lnspec.cpp @@ -1120,7 +1120,7 @@ FUNC(LS_Teleport_NewMap) FUNC(LS_Teleport) // Teleport (tid, sectortag, bNoSourceFog) { - int flags = TELF_DESTFOG; + int flags = TELF_DESTFOG | TELF_FDCOMPAT; if (!arg2) { flags |= TELF_SOURCEFOG; diff --git a/src/playsim/p_spec.h b/src/playsim/p_spec.h index 5d602eb1d..cc7d990a9 100644 --- a/src/playsim/p_spec.h +++ b/src/playsim/p_spec.h @@ -141,6 +141,7 @@ enum TELF_KEEPHEIGHT = 16, TELF_ROTATEBOOM = 32, TELF_ROTATEBOOMINVERSE = 64, + TELF_FDCOMPAT = 128, }; //Spawns teleport fog. Pass the actor to pluck TeleFogFromType and TeleFogToType. 'from' determines if this is the fog to spawn at the old position (true) or new (false). diff --git a/src/playsim/p_teleport.cpp b/src/playsim/p_teleport.cpp index 1643b1b76..a69d3654c 100644 --- a/src/playsim/p_teleport.cpp +++ b/src/playsim/p_teleport.cpp @@ -128,7 +128,15 @@ bool P_Teleport (AActor *thing, DVector3 pos, DAngle angle, int flags) } else { - pos.Z = floorheight; + if (!(thing->Level->i_compatflags2 & COMPATF2_FDTELEPORT) || !(flags & TELF_FDCOMPAT) || floorheight > thing->Z()) + { + pos.Z = floorheight; + } + else + { + pos.Z = thing->Z(); + } + if (!(flags & TELF_KEEPORIENTATION)) { resetpitch = false; @@ -145,7 +153,16 @@ bool P_Teleport (AActor *thing, DVector3 pos, DAngle angle, int flags) } else { - pos.Z = floorheight; + // emulation of Final Doom's teleport glitch. + // For walking monsters we still have to force them to the ground because the handling of off-ground monsters is different from vanilla. + if (!(thing->Level->i_compatflags2 & COMPATF2_FDTELEPORT) || !(flags & TELF_FDCOMPAT) || !(thing->flags & MF_NOGRAVITY) || floorheight > pos.Z) + { + pos.Z = floorheight; + } + else + { + pos.Z = thing->Z(); + } } } // [MK] notify thing of incoming teleport, check for an early cancel @@ -245,7 +262,7 @@ DEFINE_ACTION_FUNCTION(AActor, Teleport) PARAM_FLOAT(z); PARAM_ANGLE(an); PARAM_INT(flags); - ACTION_RETURN_BOOL(P_Teleport(self, DVector3(x, y, z), an, flags)); + ACTION_RETURN_BOOL(P_Teleport(self, DVector3(x, y, z), an, flags & ~TELF_FDCOMPAT)); } //----------------------------------------------------------------------------- diff --git a/wadsrc/static/compatibility.txt b/wadsrc/static/compatibility.txt index 2440ef55f..f8c3fe453 100644 --- a/wadsrc/static/compatibility.txt +++ b/wadsrc/static/compatibility.txt @@ -332,3 +332,8 @@ F1EB6927F53047F219A54997DAD9DC81 // mm2.wad map20 rebuildnodes trace } + +BA2247ED1465C8107192AC4215B2A5F3 // saturnia.wad map10 +{ + fdteleport +} diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index fe289c6c8..a213f593f 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -1760,6 +1760,7 @@ OptionMenu "CompatActorMenu" protected Option "$CMPTMNU_INVISIBILITY", "compat_INVISIBILITY", "YesNo" Option "$CMPTMNU_MINOTAUR", "compat_MINOTAUR", "YesNo" Option "$CMPTMNU_NOTOSSDROPS", "compat_NOTOSSDROPS", "YesNo" + Option "$CMPTMNU_VOODOOZOMBIES", "compat_voodoozombies", "YesNo" Class "CompatibilityMenu" } @@ -1786,6 +1787,7 @@ OptionMenu "CompatMapMenu" protected Option "$CMPTMNU_POINTONLINE", "compat_pointonline", "YesNo" Option "$CMPTMNU_MULTIEXIT", "compat_multiexit", "YesNo" Option "$CMPTMNU_TELEPORT", "compat_teleport", "YesNo" + Option "$CMPTMNU_FDTELEPORT", "compat_fdteleport", "YesNo" Option "$CMPTMNU_PUSHWINDOW", "compat_pushwindow", "YesNo" Option "$CMPTMNU_CHECKSWITCHRANGE", "compat_checkswitchrange", "YesNo" Option "$CMPTMNU_RAILINGHACK", "compat_railing", "YesNo" From 45cf72ff48ef21c145f248d90bd19a6caf51e655 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 27 Apr 2024 11:57:22 +0200 Subject: [PATCH 20/84] fixed bad network ID assignment. ClientNetIDStart was added twice here. This was asserting when loading a savegame. --- src/common/objects/dobject.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/objects/dobject.cpp b/src/common/objects/dobject.cpp index dc0d9a579..4ba504738 100644 --- a/src/common/objects/dobject.cpp +++ b/src/common/objects/dobject.cpp @@ -662,7 +662,7 @@ void NetworkEntityManager::SetClientNetworkEntity(DObject* mo, const unsigned in } s_netEntities[id] = mo; - mo->SetNetworkID(ClientNetIDStart + id); + mo->SetNetworkID(id); } void NetworkEntityManager::AddNetworkEntity(DObject* const ent) From a768d6c177f1e6f2be4b1047b789511c9924c7f0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 27 Apr 2024 12:36:10 +0200 Subject: [PATCH 21/84] text update --- wadsrc/static/language.csv | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/wadsrc/static/language.csv b/wadsrc/static/language.csv index 080a605b2..b588c7c66 100644 --- a/wadsrc/static/language.csv +++ b/wadsrc/static/language.csv @@ -3384,8 +3384,11 @@ Disallow override of camera facing mode,GLPREFMNU_SPRBILLFACECAMERAFORCE,,,,,Til Swap health and armor,ALTHUDMNU_SWAPHEALTHARMOR,,,,Prohodit zdraví a brnění,Byt om på helbred og rustning,Anzeige für Gesundheit und Panzerung tauschen,,Permuti sanon kaj kirason,,,,Échanger la santé et l'armure,,Scambio di salute e armatura,体力とアーマーをスワップ,,Verwissel gezondheid en pantser,Bytt helse og rustning,Zamień zdrowie i pancerz,Trocar saúde e armadura,,,Поменять отображение здоровья и брони местами,,Byt hälsa och rustning,Sağlık ve zırhı değiştir, Use classic HUD scaling,SCALEMNU_HUD_OLDSCALE,hud_oldscale,,,Pro HUD použít klasické škálování,Brug klassisk HUD-skalering,Klassische HUD-Skalierung,,Uzi klasikan skaladon de HUD,,,,Utiliser l'échelle classique du HUD,,Utilizzare la scalatura classica dell'HUD,旧式HUDスケーリングを使う,,Gebruik klassieke HUD-schaling,Bruk klassisk HUD-skalering,,Usar escala clássica do HUD,,,Классическое масштабирование интерфейса,,Använd klassisk HUD-skalning,Klasik HUD ölçeklendirmesini kullanın, HUD scale factor,SCALEMNU_HUD_SCALEFACTOR,hud_scalefactor,,,Faktor HUD škálování,HUD-skaleringsfaktor,HUD-Skalierungsfaktor,,Skalfaktoro de HUD,,,,Facteur d'échelle du HUD,,Fattore di scala dell'HUD,HUDスケール倍率,,HUD-schaalfactor,HUD-skaleringsfaktor,,Fator de escala do HUD,,,Значение масштабирования интерфейса,,Skalningsfaktor för HUD,HUD ölçek faktörü, -Spawn co-op only things in multiplayer,GMPLYMNU_COOPTHINGS,Any Actor that only appears in co-op is disabled,,,Co-op věci pouze v multiplayeru,,,,Ekaperigi nurajn kooperajn aĵojn en plurludanta reĝimo,,,,,,,マルチで協力モード限定thingsを出す,,,,,,,,Появление вещей из совместной игры в сетевой игре,,,, -Spawn co-op only items in multiplayer,GMPLYMNU_COOPITEMS,Items that only appear in co-op are disabled,,,Co-op předměty pouze v multiplayeru,,,,Ekaperigi nurajn kooperajn objektojn en plurludanta reĝimo,,,,,,,マルチで協力モード限定アイテムを出す,,,,,,,,Появление предметов из совместной игры в сетевой игре,,,, -Players pick up their own copy of items in multiplayer,GMPLYMNU_LOCALITEMS,Items are picked up client-side rather than fully taken by the client who picked it up,,,V multiplayeru hráči sbírají své vlastní kopie předmětů,,,,Ludantoj prenas sian propran kopion de objektoj en plurludanta reĝimo,,,,,,,マルチでプレイヤー達は複製アイテムを拾う,,,,,,,,Игроки подбирают собственные копии предметов в сетевой игре,,,, -Disable client-side pick ups on dropped items,GMPLYMNU_NOLOCALDROP,Drops from Actors aren't picked up locally,,,Zakázat sbírání odhozených předmětů na straně klientů,,,,Malvalidigi klientflankajn prenadojn de faligitaj objektoj,,,,,,,クライアント側で落としたアイテムを拾わせない,,,,,,,,Отключить подбирание выпавших предметов на стороне клиента,,,, -Restart on Death,MISCMNU_RESTARTONDEATH,Disables autoloading save on death,,,,,,,,,,,,,,,,,,,,,,Перезапуск после смерти,,,, \ No newline at end of file +Spawn co-op only things in multiplayer,GMPLYMNU_COOPTHINGS,Any Actor that only appears in co-op is disabled,,,Co-op věci pouze v multiplayeru,Skab kun co-op-objekter i multiplayer,Erzeuge Nur-Co-op Dinge in Multiplayer,,Ekaperigi nurajn kooperajn aĵojn en plurludanta reĝimo,,,,Faire apparaitre les acteurs Co-Op Seulement en Multijoueur,,Creare oggetti solo per la cooperativa in multigiocatore,マルチで協力モード限定thingsを出す,,Alleen co-op-voorwerpen maken in multiplayer,Opprett co-op-objekter i flerspillermodus,,,,,Появление вещей из совместной игры в сетевой игре,,Skapa co-op-objekt i flerspelarläget,Çok oyunculu modda ortak nesneler oluşturun, +Spawn co-op only pickup items in multiplayer,GMPLYMNU_COOPITEMS,Items that only appear in co-op are disabled,,,Co-op předměty pouze v multiplayeru,Skab kun co-op-genstande i multiplayer,Erzeuge Nur-Co-op Gegenstände in Multiplayer,,Ekaperigi nurajn kooperajn objektojn en plurludanta reĝimo,,,,Faire apparaitre les objets Co-Op Seulement en Multijoueur,,Creare pickup solo per la cooperativa in multigiocatore,マルチで協力モード限定アイテムを出す,,Alleen co-op pickups maken in multiplayer,Opprett co-op-pickuper i flerspillermodus,,,,,Появление предметов из совместной игры в сетевой игре,,Skapa co-op pickups i flerspelarläget,Çok oyunculu modda ortak pikaplar oluşturun, +Players pick up their own copy of items in multiplayer,GMPLYMNU_LOCALITEMS,Items are picked up client-side rather than fully taken by the client who picked it up,,,V multiplayeru hráči sbírají své vlastní kopie předmětů,Spillere samler deres egen kopi af genstande op i multiplayer,Spieler nehmen ihre eigene Kopie von Gegenständen im Mehrspielermodus auf,,Ludantoj prenas sian propran kopion de objektoj en plurludanta reĝimo,,,,Chaque joueur obtient sa copie de chaque objet en Multijoueur,,I giocatori raccolgono la propria copia di oggetti in multigiocatore,マルチでプレイヤー達は複製アイテムを拾う,,Spelers pikken hun eigen exemplaar van voorwerpen op in multiplayer,Spillere plukker opp sin egen kopi av gjenstander i flerspiller,,,,,Игроки подбирают собственные копии предметов в сетевой игре,,Spelare plockar upp sin egen kopia av föremål i flerspelarläget,Oyuncular çok oyunculu modda eşyaların kendi kopyalarını alırlar, +Disable client-side pick ups on dropped items,GMPLYMNU_NOLOCALDROP,Drops from Actors aren't picked up locally,,,Zakázat sbírání odhozených předmětů na straně klientů,Deaktiver opsamling på klientsiden af tabte genstande,Client-seitiges Aufnehmen von fallengelassenen Gegenständen deaktivieren,,Malvalidigi klientflankajn prenadojn de faligitaj objektoj,,,,Désactiver le ramassage des objets lâchés en clientside,,Disabilita il ritiro degli oggetti caduti dal lato client,クライアント側で落としたアイテムを拾わせない,,Client-side pick ups van gedropte items uitschakelen,Deaktiver opphenting på klientsiden av gjenstander som droppes,,,,,Отключить подбирание выпавших предметов на стороне клиента,,Inaktivera upphämtning av tappade föremål på klientsidan,Düşen öğeleri istemci tarafında almayı devre dışı bırakma, +Restart level on Death,MISCMNU_RESTARTONDEATH,Disables autoloading save on death,,,Restart po umření,Genstart niveau ved død,Level bei Tod neu starten,,,,,,Recharger après mort,,Riavvio del livello in caso di morte,,,Level herstarten bij dood,Start nivået på nytt ved død,,,,,Перезапуск уровня после смерти,,Starta om nivån vid död,Ölüm halinde seviyeyi yeniden başlat, +Pistol Start,GMPLYMNU_PISTOLSTART,Resets inventory on every map,,,Začít jen s pistolí,Start med pistol,Pistolenstart,,,,,,Démarrage du pistolet,,Avvio pistola,,,Start met pistool,Start med pistol,,,,,Пистолет в начале,,Starta med pistol,Tabanca ile başlayın, +Allow creation of zombie players,CMPTMNU_VOODOOZOMBIES,,,,,,Erlaube Zombieplayer,,,,,,,,,,,,,,,,,,,,, +ignore floor z when teleporting,CMPTMNU_FDTELEPORT,,,,,,Ignoriere Fußbodenhöhe bem Teleportieren,,,,,,,,,,,,,,,,,,,,, \ No newline at end of file From 620d689038bab84ffa5bead36c518ba6026c934c Mon Sep 17 00:00:00 2001 From: DyNaM1Kk <42520902+DyNaM1Kk@users.noreply.github.com> Date: Sat, 27 Apr 2024 17:38:45 +0400 Subject: [PATCH 22/84] Fixed "PrivateNetOf" function not checking for the entire B class private network range --- src/common/engine/i_net.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/engine/i_net.cpp b/src/common/engine/i_net.cpp index 65dc60cb1..33b4c1267 100644 --- a/src/common/engine/i_net.cpp +++ b/src/common/engine/i_net.cpp @@ -903,11 +903,11 @@ bool JoinGame (int i) static int PrivateNetOf(in_addr in) { int addr = ntohl(in.s_addr); - if ((addr & 0xFFFF0000) == 0xC0A80000) // 192.168.0.0 + if ((addr & 0xFFFF0000) == 0xC0A80000) // 192.168.0.0 { return 0xC0A80000; } - else if ((addr & 0xFFF00000) == 0xAC100000) // 172.16.0.0 + else if ((addr & 0xFFFF0000) >= 0xAC100000 && (addr & 0xFFFF0000) <= 0xAC1F0000) // 172.16.0.0 - 172.31.0.0 { return 0xAC100000; } From 4625d4ac34d34e3f08f16533da24a3f1e7cb5501 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Sun, 28 Apr 2024 03:35:09 -0400 Subject: [PATCH 23/84] - mirror changes with ZWidget, remove SDL_Wait failure message --- libraries/ZWidget/src/window/sdl2/sdl2displaywindow.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libraries/ZWidget/src/window/sdl2/sdl2displaywindow.cpp b/libraries/ZWidget/src/window/sdl2/sdl2displaywindow.cpp index 9ccf859e0..17db8a863 100644 --- a/libraries/ZWidget/src/window/sdl2/sdl2displaywindow.cpp +++ b/libraries/ZWidget/src/window/sdl2/sdl2displaywindow.cpp @@ -288,9 +288,8 @@ void SDL2DisplayWindow::RunLoop() { SDL_Event event; int result = SDL_WaitEvent(&event); - if (result == 0) - fprintf(stderr, "SDL_WaitEvent failed: %s\n", SDL_GetError()); - DispatchEvent(event); + if (result == 1) + DispatchEvent(event); } } From 929febdfb1fe4704c05d37eeb94e165992f684d8 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Sun, 28 Apr 2024 18:30:19 -0400 Subject: [PATCH 24/84] Fixed prediction not calling virtual Tick function --- src/playsim/p_user.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/playsim/p_user.cpp b/src/playsim/p_user.cpp index d00f7571b..806db50fc 100644 --- a/src/playsim/p_user.cpp +++ b/src/playsim/p_user.cpp @@ -1512,8 +1512,8 @@ void P_PredictPlayer (player_t *player) player->cmd = localcmds[i % LOCALCMDTICS]; player->mo->ClearInterpolation(); player->mo->ClearFOVInterpolation(); - P_PlayerThink (player); - player->mo->Tick (); + P_PlayerThink(player); + player->mo->CallTick(); } if (rubberband) From 2643a4a16772406ebc4eca53af48a74e898e006e Mon Sep 17 00:00:00 2001 From: Boondorl Date: Sun, 28 Apr 2024 19:18:55 -0400 Subject: [PATCH 25/84] Fixed desync in Heretic --- wadsrc/static/zscript/actors/player/player.zs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wadsrc/static/zscript/actors/player/player.zs b/wadsrc/static/zscript/actors/player/player.zs index 0cee7a7f3..f2d7213f4 100644 --- a/wadsrc/static/zscript/actors/player/player.zs +++ b/wadsrc/static/zscript/actors/player/player.zs @@ -154,7 +154,7 @@ class PlayerPawn : Actor if (health > 0) Height = FullHeight; } - if (player && bWeaponLevel2Ended) + if (player && bWeaponLevel2Ended && !(player.cheats & CF_PREDICTING)) { bWeaponLevel2Ended = false; if (player.ReadyWeapon != NULL && player.ReadyWeapon.bPowered_Up) From 48eb848433840761a1b129aa0e16853f10c59f14 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Sun, 28 Apr 2024 09:00:18 -0400 Subject: [PATCH 26/84] Fixed ViewPos not properly backing up when predicting Also now forcibly creates the object on players when they spawn so their pointer won't get lost when predicting. --- src/playsim/p_user.cpp | 20 +++++++++++++++++++ wadsrc/static/zscript/actors/player/player.zs | 3 +++ 2 files changed, 23 insertions(+) diff --git a/src/playsim/p_user.cpp b/src/playsim/p_user.cpp index 806db50fc..967ddb660 100644 --- a/src/playsim/p_user.cpp +++ b/src/playsim/p_user.cpp @@ -156,6 +156,12 @@ static TArray PredictionPortalSectors_sprev_Backup; static TArray PredictionPortalLinesBackup; static TArray PredictionPortalLines_sprev_Backup; +struct +{ + DVector3 Pos = {}; + int Flags = 0; +} static PredictionViewPosBackup; + // [GRB] Custom player classes TArray PlayerClasses; @@ -1443,6 +1449,14 @@ void P_PredictPlayer (player_t *player) PredictionActorBackupArray.Resize(act->GetClass()->Size); memcpy(PredictionActorBackupArray.Data(), &act->snext, act->GetClass()->Size - ((uint8_t *)&act->snext - (uint8_t *)act)); + // Since this is a DObject it needs to have its fields backed up manually for restore, otherwise any changes + // to it will be permanent while predicting. This is now auto-created on pawns to prevent creation spam. + if (act->ViewPos != nullptr) + { + PredictionViewPosBackup.Pos = act->ViewPos->Offset; + PredictionViewPosBackup.Flags = act->ViewPos->Flags; + } + act->flags &= ~MF_PICKUP; act->flags2 &= ~MF2_PUSHWALL; player->cheats |= CF_PREDICTING; @@ -1580,6 +1594,12 @@ void P_UnPredictPlayer () act->UnlinkFromWorld(&ctx); memcpy(&act->snext, PredictionActorBackupArray.Data(), PredictionActorBackupArray.Size() - ((uint8_t *)&act->snext - (uint8_t *)act)); + if (act->ViewPos != nullptr) + { + act->ViewPos->Offset = PredictionViewPosBackup.Pos; + act->ViewPos->Flags = PredictionViewPosBackup.Flags; + } + // The blockmap ordering needs to remain unchanged, too. // Restore sector links and refrences. // [ED850] This is somewhat of a duplicate of LinkToWorld(), but we need to keep every thing the same, diff --git a/wadsrc/static/zscript/actors/player/player.zs b/wadsrc/static/zscript/actors/player/player.zs index f2d7213f4..fe56805d7 100644 --- a/wadsrc/static/zscript/actors/player/player.zs +++ b/wadsrc/static/zscript/actors/player/player.zs @@ -179,6 +179,9 @@ class PlayerPawn : Actor override void BeginPlay() { + // Force create this since players can predict. + SetViewPos((0.0, 0.0, 0.0)); + Super.BeginPlay (); ChangeStatNum (STAT_PLAYER); FullHeight = Height; From 27eb78f4374a431e5181564fdec9f923c4e89bc1 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Sat, 27 Apr 2024 18:43:04 -0400 Subject: [PATCH 27/84] Fixed weapon slots not resetting on unmorph Important for any morphed pawns that set custom weapon slots. --- wadsrc/static/zscript/actors/player/player_morph.zs | 1 + 1 file changed, 1 insertion(+) diff --git a/wadsrc/static/zscript/actors/player/player_morph.zs b/wadsrc/static/zscript/actors/player/player_morph.zs index ff84246a1..25858dd7c 100644 --- a/wadsrc/static/zscript/actors/player/player_morph.zs +++ b/wadsrc/static/zscript/actors/player/player_morph.zs @@ -323,6 +323,7 @@ extend class PlayerPawn if (level2) level2.Destroy(); + WeaponSlots.SetupWeaponSlots(alt); let morphWeap = p.ReadyWeapon; if (premorphWeap) { From c03f7889bf071ddc8992320d153e90920d33d312 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Sun, 28 Apr 2024 11:20:31 -0300 Subject: [PATCH 28/84] restore old fadestep behavior if SPF_NEGATIVE_FADESTEP is not passed in --- src/playsim/p_effect.cpp | 2 +- src/playsim/p_effect.h | 1 + wadsrc/static/zscript/constants.zs | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/playsim/p_effect.cpp b/src/playsim/p_effect.cpp index 5ee7e9f3c..459d267be 100644 --- a/src/playsim/p_effect.cpp +++ b/src/playsim/p_effect.cpp @@ -374,7 +374,7 @@ void P_SpawnParticle(FLevelLocals *Level, const DVector3 &pos, const DVector3 &v particle->Acc = FVector3(accel); particle->color = ParticleColor(color); particle->alpha = float(startalpha); - if (fadestep <= -1.0) particle->fadestep = FADEFROMTTL(lifetime); + if ((fadestep < 0 && !(flags & SPF_NEGATIVE_FADESTEP)) || fadestep <= -1.0) particle->fadestep = FADEFROMTTL(lifetime); else particle->fadestep = float(fadestep); particle->ttl = lifetime; particle->size = size; diff --git a/src/playsim/p_effect.h b/src/playsim/p_effect.h index 0f439785c..374aeecfc 100644 --- a/src/playsim/p_effect.h +++ b/src/playsim/p_effect.h @@ -65,6 +65,7 @@ enum EParticleFlags SPF_REPLACE = 1 << 7, SPF_NO_XY_BILLBOARD = 1 << 8, SPF_LOCAL_ANIM = 1 << 9, + SPF_NEGATIVE_FADESTEP = 1 << 10, }; class DVisualThinker; diff --git a/wadsrc/static/zscript/constants.zs b/wadsrc/static/zscript/constants.zs index e1176c649..8e36a5516 100644 --- a/wadsrc/static/zscript/constants.zs +++ b/wadsrc/static/zscript/constants.zs @@ -714,6 +714,7 @@ enum EParticleFlags SPF_REPLACE = 1 << 7, SPF_NO_XY_BILLBOARD = 1 << 8, SPF_LOCAL_ANIM = 1 << 9, + SPF_NEGATIVE_FADESTEP = 1 << 10, SPF_RELATIVE = SPF_RELPOS|SPF_RELVEL|SPF_RELACCEL|SPF_RELANG }; From 3318e540b665c0ffffaa93ba1b8f993b34d2460e Mon Sep 17 00:00:00 2001 From: Ru5tK1ng Date: Mon, 29 Apr 2024 00:46:12 -0500 Subject: [PATCH 29/84] Added missing checking for LOOKALLAROUND. --- src/playsim/p_enemy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/playsim/p_enemy.cpp b/src/playsim/p_enemy.cpp index 50ed1a74d..cf15cbf38 100644 --- a/src/playsim/p_enemy.cpp +++ b/src/playsim/p_enemy.cpp @@ -2139,7 +2139,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LookEx) if (!(flags & LOF_NOSIGHTCHECK)) { - if (!P_LookForPlayers(self, true, ¶ms)) + if (!P_LookForPlayers(self, (self->flags4 & MF4_LOOKALLAROUND), ¶ms)) // [RK] Account for the flag being set. return 0; } else From 81dade9ed5fd80bed0fb0fcd4477bea0b160e915 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 1 May 2024 09:47:58 +0200 Subject: [PATCH 30/84] fixed: for deleting files and folders on Windows we have to call the Unicode variants of these functions. --- src/common/menu/savegamemanager.cpp | 7 +++---- src/common/utility/cmdlib.cpp | 20 ++++++++++++++++++++ src/common/utility/cmdlib.h | 2 ++ src/common/utility/writezip.cpp | 7 ++++--- src/g_game.cpp | 2 +- src/maploader/glnodes.cpp | 10 ++-------- 6 files changed, 32 insertions(+), 16 deletions(-) diff --git a/src/common/menu/savegamemanager.cpp b/src/common/menu/savegamemanager.cpp index 83865cd1d..06b014122 100644 --- a/src/common/menu/savegamemanager.cpp +++ b/src/common/menu/savegamemanager.cpp @@ -84,7 +84,7 @@ int FSavegameManagerBase::RemoveSaveSlot(int index) int listindex = SaveGames[0]->bNoDelete ? index - 1 : index; if (listindex < 0) return index; - remove(SaveGames[index]->Filename.GetChars()); + RemoveFile(SaveGames[index]->Filename.GetChars()); UnloadSaveData(); FSaveGameNode *file = SaveGames[index]; @@ -274,7 +274,7 @@ DEFINE_ACTION_FUNCTION(FSavegameManager, DoSave) unsigned FSavegameManagerBase::ExtractSaveData(int index) { - FResourceFile *resf; + std::unique_ptr resf; FSaveGameNode *node; if (index == -1) @@ -295,7 +295,7 @@ unsigned FSavegameManagerBase::ExtractSaveData(int index) (node = SaveGames[index]) && !node->Filename.IsEmpty() && !node->bOldVersion && - (resf = FResourceFile::OpenResourceFile(node->Filename.GetChars(), true)) != nullptr) + ( (resf.reset(FResourceFile::OpenResourceFile(node->Filename.GetChars(), true))), resf != nullptr)) { auto info = resf->FindEntry("info.json"); if (info < 0) @@ -329,7 +329,6 @@ unsigned FSavegameManagerBase::ExtractSaveData(int index) } } } - delete resf; } return index; } diff --git a/src/common/utility/cmdlib.cpp b/src/common/utility/cmdlib.cpp index 5933a91d5..3b8dc9981 100644 --- a/src/common/utility/cmdlib.cpp +++ b/src/common/utility/cmdlib.cpp @@ -593,6 +593,26 @@ void CreatePath(const char *fn) } #endif +void RemoveFile(const char* file) +{ +#ifndef _WIN32 + remove(file); +#else + auto wpath = WideString(file); + _wremove(wpath.c_str()); +#endif +} + +int RemoveDir(const char* file) +{ +#ifndef _WIN32 + return rmdir(file); +#else + auto wpath = WideString(file); + return _wrmdir(wpath.c_str()); +#endif +} + //========================================================================== // // strbin -- In-place version diff --git a/src/common/utility/cmdlib.h b/src/common/utility/cmdlib.h index df779a975..88027c156 100644 --- a/src/common/utility/cmdlib.h +++ b/src/common/utility/cmdlib.h @@ -71,6 +71,8 @@ int strbin (char *str); FString strbin1 (const char *start); void CreatePath(const char * fn); +void RemoveFile(const char* file); +int RemoveDir(const char* file); FString ExpandEnvVars(const char *searchpathstring); FString NicePath(const char *path); diff --git a/src/common/utility/writezip.cpp b/src/common/utility/writezip.cpp index 2f3507e6f..de89779c0 100644 --- a/src/common/utility/writezip.cpp +++ b/src/common/utility/writezip.cpp @@ -40,6 +40,7 @@ #include "m_swap.h" #include "w_zip.h" #include "fs_decompress.h" +#include "cmdlib.h" using FileSys::FCompressedBuffer; @@ -201,7 +202,7 @@ bool WriteZip(const char* filename, const FCompressedBuffer* content, size_t con if (pos == -1) { delete f; - remove(filename); + RemoveFile(filename); return false; } positions.Push(pos); @@ -213,7 +214,7 @@ bool WriteZip(const char* filename, const FCompressedBuffer* content, size_t con if (AppendCentralDirectory(f, content[i], dostime, positions[i]) < 0) { delete f; - remove(filename); + RemoveFile(filename); return false; } } @@ -230,7 +231,7 @@ bool WriteZip(const char* filename, const FCompressedBuffer* content, size_t con if (f->Write(&dirend, sizeof(dirend)) != sizeof(dirend)) { delete f; - remove(filename); + RemoveFile(filename); return false; } delete f; diff --git a/src/g_game.cpp b/src/g_game.cpp index 56a84d482..472b840a4 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -3079,7 +3079,7 @@ bool G_CheckDemoStatus (void) const size_t size = demo_p - demobuffer; saved = fw->Write(demobuffer, size) == size; delete fw; - if (!saved) remove(demoname.GetChars()); + if (!saved) RemoveFile(demoname.GetChars()); } M_Free (demobuffer); demorecording = false; diff --git a/src/maploader/glnodes.cpp b/src/maploader/glnodes.cpp index b41b22c0b..df569b1ae 100644 --- a/src/maploader/glnodes.cpp +++ b/src/maploader/glnodes.cpp @@ -34,12 +34,6 @@ #ifndef _WIN32 #include - -#else -#include - -#define rmdir _rmdir - #endif #include @@ -1215,11 +1209,11 @@ UNSAFE_CCMD(clearnodecache) { if (list[i].isDirectory) { - rmdir(list[i].FilePath.c_str()); + RemoveDir(list[i].FilePath.c_str()); } else { - remove(list[i].FilePath.c_str()); + RemoveFile(list[i].FilePath.c_str()); } } From f2d582f680b72eb50480e7c704f90b9bd38c7529 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 1 May 2024 09:49:45 +0200 Subject: [PATCH 31/84] fixed: The savegame's PNG loader must use a caching FileReader to avoid holding a handle to the containing file. This blocked savegame deletion. --- src/common/menu/savegamemanager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/common/menu/savegamemanager.cpp b/src/common/menu/savegamemanager.cpp index 06b014122..135093021 100644 --- a/src/common/menu/savegamemanager.cpp +++ b/src/common/menu/savegamemanager.cpp @@ -316,7 +316,8 @@ unsigned FSavegameManagerBase::ExtractSaveData(int index) auto pic = resf->FindEntry("savepic.png"); if (pic >= 0) { - FileReader picreader = resf->GetEntryReader(pic, FileSys::READER_NEW, FileSys::READERFLAG_SEEKABLE); + // This must use READER_CACHED or it will lock the savegame file. + FileReader picreader = resf->GetEntryReader(pic, FileSys::READER_CACHED, FileSys::READERFLAG_SEEKABLE); PNGHandle *png = M_VerifyPNG(picreader); if (png != nullptr) { From 6f2bc8379adbde57fbe38778e10e8c5ab4f97536 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 1 May 2024 11:58:30 +0200 Subject: [PATCH 32/84] strip spaces from language labels. --- src/common/engine/stringtable.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/common/engine/stringtable.cpp b/src/common/engine/stringtable.cpp index 707b59b69..d9d739b57 100644 --- a/src/common/engine/stringtable.cpp +++ b/src/common/engine/stringtable.cpp @@ -254,6 +254,7 @@ bool FStringTable::ParseLanguageCSV(int filenum, const char* buffer, size_t size } } + row[labelcol].StripLeftRight(); FName strName = row[labelcol].GetChars(); if (hasDefaultEntry) { From 3a5838c8f5a24bbe198faa41574736694848992e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 1 May 2024 12:20:06 +0200 Subject: [PATCH 33/84] don't abort when parsing the Steam config fails. --- src/win32/i_steam.cpp | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/src/win32/i_steam.cpp b/src/win32/i_steam.cpp index f8bd74bff..2cf536475 100644 --- a/src/win32/i_steam.cpp +++ b/src/win32/i_steam.cpp @@ -61,6 +61,7 @@ #include "printf.h" +#include "engineerrors.h" #include "version.h" #include "i_sound.h" #include "stats.h" @@ -307,23 +308,30 @@ TArray I_GetSteamPath() return result; } - TArray paths = ParseSteamRegistry((steamPath + "/config/libraryfolders.vdf").GetChars()); - - for(FString &path : paths) + try { - path.ReplaceChars('\\','/'); - path+="/"; - } + TArray paths = ParseSteamRegistry((steamPath + "/config/libraryfolders.vdf").GetChars()); - paths.Push(steamPath + "/steamapps/common/"); + for (FString& path : paths) + { + path.ReplaceChars('\\', '/'); + path += "/"; + } - for(unsigned int i = 0; i < countof(steam_dirs); ++i) - { - for(const FString &path : paths) + paths.Push(steamPath + "/steamapps/common/"); + + for (unsigned int i = 0; i < countof(steam_dirs); ++i) { - result.Push(path + steam_dirs[i]); + for (const FString& path : paths) + { + result.Push(path + steam_dirs[i]); + } } } + catch (const CRecoverableError& err) + { + // don't abort on errors in here. Just return an empty path. + } return result; } From 370bec6c559ec3b3be2552ae4cf829750599f915 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 1 May 2024 17:57:11 +0200 Subject: [PATCH 34/84] fixed GL nodes loader for maps loaded from mounted folders. Due to how the reader is created, READER_NEW will not work for it, it needs to force READER_CACHED. --- src/maploader/glnodes.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/maploader/glnodes.cpp b/src/maploader/glnodes.cpp index df569b1ae..33051b6c1 100644 --- a/src/maploader/glnodes.cpp +++ b/src/maploader/glnodes.cpp @@ -900,7 +900,8 @@ bool MapLoader::LoadGLNodes(MapData * map) break; } else - gwalumps[i] = f_gwa->GetEntryReader(li + i + 1, FileSys::READER_NEW, FileSys::READERFLAG_SEEKABLE); + // This is a special case. The container for the map WAD is not set up to create new file handles for itself so this needs to cache the content here. + gwalumps[i] = f_gwa->GetEntryReader(li + i + 1, FileSys::READER_CACHED, FileSys::READERFLAG_SEEKABLE); } if (result) result = DoLoadGLNodes(gwalumps); } From a6e1114d3cea82cf9aeaa74f36eea7f94a544e67 Mon Sep 17 00:00:00 2001 From: Xaser Acheron Date: Wed, 1 May 2024 15:46:07 -0500 Subject: [PATCH 35/84] add mbf21 and mbf21 (strict) compatibility presets --- src/d_main.cpp | 13 +++++++++++++ wadsrc/static/language.csv | 2 ++ wadsrc/static/menudef.txt | 2 ++ 3 files changed, 17 insertions(+) diff --git a/src/d_main.cpp b/src/d_main.cpp index c570eddc4..fbc67693c 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -662,6 +662,19 @@ CUSTOM_CVAR(Int, compatmode, 0, CVAR_ARCHIVE|CVAR_NOINITCALL) COMPATF_TRACE | COMPATF_HITSCAN | COMPATF_MISSILECLIP | COMPATF_MASKEDMIDTEX | COMPATF_SOUNDTARGET; w = COMPATF2_POINTONLINE | COMPATF2_EXPLODE1 | COMPATF2_EXPLODE2 | COMPATF2_AVOID_HAZARDS | COMPATF2_STAYONLIFT | COMPATF2_NOMBF21; break; + + case 8: // MBF21 compat mode + v = COMPATF_TRACE | COMPATF_SOUNDTARGET | COMPATF_BOOMSCROLL | COMPATF_MISSILECLIP | COMPATF_CROSSDROPOFF | + COMPATF_MUSHROOM | COMPATF_MBFMONSTERMOVE | COMPATF_NOBLOCKFRIENDS | COMPATF_MASKEDMIDTEX; + w = COMPATF2_EXPLODE1 | COMPATF2_AVOID_HAZARDS | COMPATF2_STAYONLIFT; + break; + + case 9: // Stricter MBF21 compatibility + v = COMPATF_NOBLOCKFRIENDS | COMPATF_MBFMONSTERMOVE | COMPATF_INVISIBILITY | + COMPATF_NOTOSSDROPS | COMPATF_MUSHROOM | COMPATF_NO_PASSMOBJ | COMPATF_BOOMSCROLL | COMPATF_WALLRUN | + COMPATF_TRACE | COMPATF_HITSCAN | COMPATF_MISSILECLIP | COMPATF_CROSSDROPOFF | COMPATF_MASKEDMIDTEX | COMPATF_SOUNDTARGET; + w = COMPATF2_POINTONLINE | COMPATF2_EXPLODE1 | COMPATF2_EXPLODE2 | COMPATF2_AVOID_HAZARDS | COMPATF2_STAYONLIFT; + break; } compatflags = v; compatflags2 = w; diff --git a/wadsrc/static/language.csv b/wadsrc/static/language.csv index b588c7c66..81a41967e 100644 --- a/wadsrc/static/language.csv +++ b/wadsrc/static/language.csv @@ -3146,6 +3146,8 @@ Boom,OPTVAL_BOOM,,,,,,,,,,,,,,,,붐,,,,,,,,,,, Boom (strict),OPTVAL_BOOMSTRICT,,,,Boom (striktní),Boom (streng),Boom (strikt),,Boom (severa),Boom (estricto),,Boom (tiukka),,Boom (szigorú),Boom (rigoroso),Boom(厳密),붐 (엄격하게),Boom (streng),Boom (streng),Boom (ścisły),Boom (estritamente),Boom (estrito),,Boom (строгий),Boom (строг),Boom (strikt),Boom (katı), MBF,OPTVAL_MBF,,,,,,,,,,,,,,,,마린의 절친한 친구,,,,,,,,,,, MBF (strict),OPTVAL_MBFSTRICT,,,,MBF (striktní),MBF (streng),MBF (strikt),,MBF (severa),MBF (estricto),,MBF (tiukka),,MBF (szigorú),MBF (rigoroso),MBF(厳密),마린의 절친한 친구 (엄격하게),MBF (streng),MBF (streng),MBF (ścisły),MBF (estritamente),MBF (estrito),,MBF (строгий),MBF (строг),MBF (strikt),MBF (katı), +MBF21,OPTVAL_MBF21,,,,,,,,,,,,,,,,,,,,,,,,,,, +MBF21 (strict),OPTVAL_MBF21STRICT,,,,MBF21 (striktní),MBF21 (streng),MBF21 (strikt),,MBF21 (severa),MBF21 (estricto),,MBF21 (tiukka),,MBF21 (szigorú),MBF21 (rigoroso),MBF21(厳密),MBF21 (엄격하게),MBF21 (streng),MBF21 (streng),MBF21 (ścisły),MBF21 (estritamente),MBF21 (estrito),,MBF21 (строгий),MBF21 (строг),MBF21 (strikt),MBF21 (katı), ZDoom 2.0.63,OPTVAL_ZDOOM2063,,,,,,,,,,,,,,,,Z둠 2.0.63,,,,,,,,,,, All unacknowledged,OPTVAL_ALLUNACKNOWLEDGED,,,,Všechny nepotrvzené,Alle ubekræftede,Alle unbestätigten,,Ĉiuj neagnoskitaj,Todos no reconocidos,,Kaikki kuittaamattomat,Tout non-acknowledged,Minden visszaigazolatlan,Tutti non riconosciuti,未確認全て,모두 미확인함,Allemaal onbekend,Alle ubekreftet,Wszystkie niepotwierdzone,Todos não-reconhecidos,,Toate necunoscute,Всё неопознанное,Све неусвојено,Alla obeaktade,Tüm onaylanmamış, Errors,OPTVAL_ERRORS,,,,Chyby,Fejl,Fehler,,Eraroj,Errores,,Virheet,Erreurs,Hibák,Errori,エラー,에러,Fouten,Feil,Błędy,Erros,,Erori,Ошибки,Грешка,Fel,Hatalar, diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index a213f593f..c9535ff0c 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -1729,6 +1729,8 @@ OptionValue CompatModes 6, "$OPTVAL_BOOMSTRICT" 5, "$OPTVAL_MBF" 7, "$OPTVAL_MBFSTRICT" + 8, "$OPTVAL_MBF21" + 9, "$OPTVAL_MBF21STRICT" 4, "$OPTVAL_ZDOOM2063" } From 4bf2fb0ef89582f54d87613253b48440b7e86b37 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Fri, 3 May 2024 02:03:58 -0400 Subject: [PATCH 36/84] - make particles square --- src/rendering/hwrenderer/scene/hw_sprites.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/rendering/hwrenderer/scene/hw_sprites.cpp b/src/rendering/hwrenderer/scene/hw_sprites.cpp index 341bb2001..8263a57fa 100644 --- a/src/rendering/hwrenderer/scene/hw_sprites.cpp +++ b/src/rendering/hwrenderer/scene/hw_sprites.cpp @@ -1447,7 +1447,11 @@ void HWSprite::ProcessParticle(HWDrawInfo *di, particle_t *particle, sector_t *s else factor = 1 / 7.f; float scalefac=particle->size * factor; - float viewvecX = vp.ViewVector.X * scalefac; + float ps = di->Level->pixelstretch; + + scalefac *= 2 * ps / (ps * ps + 1); // shrink it slightly to account for the stretch + + float viewvecX = vp.ViewVector.X * scalefac * ps; float viewvecY = vp.ViewVector.Y * scalefac; x1=x+viewvecY; From bcad040fd341e78f1f32c83d0ad8b0143dd4aa51 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Fri, 3 May 2024 09:45:20 -0400 Subject: [PATCH 37/84] - always show iwad picker, offer option for forks to hide picker by default. this commit was intentionally done in a way to cause merge conflicts so as to force fork maintainers to pay attention to the new option in version.h --- src/common/engine/i_interface.cpp | 3 ++- src/d_iwad.cpp | 4 ++-- src/version.h | 3 +++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/common/engine/i_interface.cpp b/src/common/engine/i_interface.cpp index 580dde407..7030194ea 100644 --- a/src/common/engine/i_interface.cpp +++ b/src/common/engine/i_interface.cpp @@ -4,6 +4,7 @@ #include "startupinfo.h" #include "c_cvars.h" #include "gstrings.h" +#include "version.h" static_assert(sizeof(void*) == 8, "32 builds are not supported"); @@ -23,7 +24,7 @@ bool pauseext; FStartupInfo GameStartupInfo; -CVAR(Bool, queryiwad, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); +CVAR(Bool, queryiwad, QUERYIWADDEFAULT, CVAR_ARCHIVE | CVAR_GLOBALCONFIG); CVAR(String, defaultiwad, "", CVAR_ARCHIVE | CVAR_GLOBALCONFIG); CVAR(Bool, vid_fps, false, 0) diff --git a/src/d_iwad.cpp b/src/d_iwad.cpp index f1495febc..99f5df02f 100644 --- a/src/d_iwad.cpp +++ b/src/d_iwad.cpp @@ -728,7 +728,7 @@ int FIWadManager::IdentifyVersion (std::vector&wadfiles, const char int pick = 0; // We got more than one so present the IWAD selection box. - if (picks.Size() > 1) + if (picks.Size() > 0) { // Locate the user's prefered IWAD, if it was found. if (defaultiwad[0] != '\0') @@ -743,7 +743,7 @@ int FIWadManager::IdentifyVersion (std::vector&wadfiles, const char } } } - if (picks.Size() > 1) + if (picks.Size() > 0) { if (!havepicked) { diff --git a/src/version.h b/src/version.h index 1d02a1f40..21d2247e6 100644 --- a/src/version.h +++ b/src/version.h @@ -101,8 +101,11 @@ const char *GetVersionString(); #define GAMENAME "GZDoom" #define WGAMENAME L"GZDoom" #define GAMENAMELOWERCASE "gzdoom" +#define QUERYIWADDEFAULT true #define FORUM_URL "http://forum.zdoom.org/" #define BUGS_FORUM_URL "http://forum.zdoom.org/viewforum.php?f=2" +// For QUERYIWADDEFAULT: Set to 'true' to always show dialog box on startup by default, 'false' to disable. +// Should set to 'false' for standalone games, and set to 'true' for regular source port forks that are meant to run any game. #if defined(__APPLE__) || defined(_WIN32) #define GAME_DIR GAMENAME From 7ef6fa97a776c0285334cd16daa9186524a92cb0 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Fri, 3 May 2024 14:32:20 -0400 Subject: [PATCH 38/84] - make roll and flat sprites square --- src/rendering/hwrenderer/scene/hw_sprites.cpp | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/rendering/hwrenderer/scene/hw_sprites.cpp b/src/rendering/hwrenderer/scene/hw_sprites.cpp index 8263a57fa..cd2100e3f 100644 --- a/src/rendering/hwrenderer/scene/hw_sprites.cpp +++ b/src/rendering/hwrenderer/scene/hw_sprites.cpp @@ -355,11 +355,7 @@ void HandleSpriteOffsets(Matrix3x4 *mat, const FRotator *HW, FVector2 *offset, b bool HWSprite::CalculateVertices(HWDrawInfo* di, FVector3* v, DVector3* vp) { - float pixelstretch = 1.2; - if (actor && actor->Level) - pixelstretch = actor->Level->pixelstretch; - else if (particle && particle->subsector && particle->subsector->sector && particle->subsector->sector->Level) - pixelstretch = particle->subsector->sector->Level->pixelstretch; + float pixelstretch = di->Level->pixelstretch; FVector3 center = FVector3((x1 + x2) * 0.5, (y1 + y2) * 0.5, (z1 + z2) * 0.5); const auto& HWAngles = di->Viewpoint.HWAngles; @@ -1005,6 +1001,13 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t r.Scale(sprscale.X, isSpriteShadow ? sprscale.Y * 0.15 : sprscale.Y); + if (thing->renderflags & (RF_ROLLSPRITE|RF_FLATSPRITE)) + { + double ps = di->Level->pixelstretch; + double mult = 2 * ps / (ps * ps + 1); // shrink slightly + r.Scale(mult * ps, mult); + } + float rightfac = -r.left; float leftfac = rightfac - r.width; z1 = z - r.top; @@ -1521,6 +1524,13 @@ void HWSprite::AdjustVisualThinker(HWDrawInfo* di, DVisualThinker* spr, sector_t auto r = spi.GetSpriteRect(); r.Scale(spr->Scale.X, spr->Scale.Y); + if (spr->PT.flags & SPF_ROLL) + { + double ps = di->Level->pixelstretch; + double mult = 2 * ps / (ps * ps + 1); // shrink slightly + r.Scale(mult * ps, mult); + } + if (spr->bXFlip) { std::swap(ul,ur); From 35f5e0498eda6871f30386d977953fe5d2e25abd Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Fri, 3 May 2024 14:45:25 -0400 Subject: [PATCH 39/84] - fix always show iwad box - don't show if queryiwad is false, or if -iwad parameter is used --- src/d_iwad.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/d_iwad.cpp b/src/d_iwad.cpp index 99f5df02f..0dd46db3b 100644 --- a/src/d_iwad.cpp +++ b/src/d_iwad.cpp @@ -727,8 +727,10 @@ int FIWadManager::IdentifyVersion (std::vector&wadfiles, const char } int pick = 0; - // We got more than one so present the IWAD selection box. - if (picks.Size() > 0) + // Present the IWAD selection box. + bool alwaysshow = (queryiwad && !Args->CheckParm("-iwad")); + + if (alwaysshow || picks.Size() > 1) { // Locate the user's prefered IWAD, if it was found. if (defaultiwad[0] != '\0') @@ -743,7 +745,7 @@ int FIWadManager::IdentifyVersion (std::vector&wadfiles, const char } } } - if (picks.Size() > 0) + if (alwaysshow || picks.Size() > 1) { if (!havepicked) { From 75c9b584ee89ea2c4dc35b7ae43404be1271121e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Sun, 21 Apr 2024 10:50:27 -0300 Subject: [PATCH 40/84] Revert "- hide the additional parameters for now, this needs to be added in later" This reverts commit fde6c863d171ab5b071d45dd47cb03861937d376. --- src/launcher/playgamepage.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/launcher/playgamepage.cpp b/src/launcher/playgamepage.cpp index 972e48d26..46bd16a92 100644 --- a/src/launcher/playgamepage.cpp +++ b/src/launcher/playgamepage.cpp @@ -85,7 +85,6 @@ void PlayGamePage::OnGeometryChanged() y = GetHeight() - 10.0; -#if 0 // NYI: Additional Parameters double editHeight = 24.0; y -= editHeight; ParametersEdit->SetFrameGeometry(0.0, y, GetWidth(), editHeight); @@ -95,7 +94,6 @@ void PlayGamePage::OnGeometryChanged() y -= labelHeight; ParametersLabel->SetFrameGeometry(0.0, y, GetWidth(), labelHeight); y -= 10.0; -#endif double listViewBottom = y - 10.0; GamesList->SetFrameGeometry(0.0, listViewTop, GetWidth(), std::max(listViewBottom - listViewTop, 0.0)); From c3ac4c9c38b1208e724fee1a0d4b2f794c11c535 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Sun, 21 Apr 2024 12:20:36 -0300 Subject: [PATCH 41/84] Handle Extra Args --- src/common/platform/posix/i_system.h | 2 +- src/common/platform/posix/sdl/i_system.cpp | 4 +- src/common/platform/win32/i_system.cpp | 4 +- src/common/platform/win32/i_system.h | 2 +- src/common/utility/m_argv.cpp | 108 +++++++++++++++++++++ src/common/utility/m_argv.h | 1 + src/common/utility/zstring.h | 1 + src/d_iwad.cpp | 11 ++- src/d_main.cpp | 7 +- src/launcher/launcherwindow.cpp | 10 +- src/launcher/launcherwindow.h | 2 +- 11 files changed, 136 insertions(+), 16 deletions(-) diff --git a/src/common/platform/posix/i_system.h b/src/common/platform/posix/i_system.h index 02acf0e3e..4d800d53b 100644 --- a/src/common/platform/posix/i_system.h +++ b/src/common/platform/posix/i_system.h @@ -38,7 +38,7 @@ void I_PrintStr (const char *str); void I_SetIWADInfo (); // Pick from multiple IWADs to use -int I_PickIWad (WadStuff *wads, int numwads, bool queryiwad, int defaultiwad, int&); +int I_PickIWad (WadStuff *wads, int numwads, bool queryiwad, int defaultiwad, int&, FString &); // [RH] Checks the registry for Steam's install path, so we can scan its // directories for IWADs if the user purchased any through Steam. diff --git a/src/common/platform/posix/sdl/i_system.cpp b/src/common/platform/posix/sdl/i_system.cpp index 7fa41b2bc..2c28368b0 100644 --- a/src/common/platform/posix/sdl/i_system.cpp +++ b/src/common/platform/posix/sdl/i_system.cpp @@ -298,7 +298,7 @@ void I_PrintStr(const char *cp) if (StartWindow) RedrawProgressBar(ProgressBarCurPos,ProgressBarMaxPos); } -int I_PickIWad (WadStuff *wads, int numwads, bool showwin, int defaultiwad, int& autoloadflags) +int I_PickIWad (WadStuff *wads, int numwads, bool showwin, int defaultiwad, int& autoloadflags, FString &extraArgs) { if (!showwin) { @@ -308,7 +308,7 @@ int I_PickIWad (WadStuff *wads, int numwads, bool showwin, int defaultiwad, int& #ifdef __APPLE__ return I_PickIWad_Cocoa (wads, numwads, showwin, defaultiwad); #else - return LauncherWindow::ExecModal(wads, numwads, defaultiwad, &autoloadflags); + return LauncherWindow::ExecModal(wads, numwads, defaultiwad, &autoloadflags, &extraArgs); #endif } diff --git a/src/common/platform/win32/i_system.cpp b/src/common/platform/win32/i_system.cpp index fe5fada53..71a4ded12 100644 --- a/src/common/platform/win32/i_system.cpp +++ b/src/common/platform/win32/i_system.cpp @@ -353,7 +353,7 @@ static void SetQueryIWad(HWND dialog) // //========================================================================== -int I_PickIWad(WadStuff *wads, int numwads, bool showwin, int defaultiwad, int& autoloadflags) +int I_PickIWad(WadStuff *wads, int numwads, bool showwin, int defaultiwad, int& autoloadflags, FString &extraArgs) { int vkey; if (stricmp(queryiwad_key, "shift") == 0) @@ -370,7 +370,7 @@ int I_PickIWad(WadStuff *wads, int numwads, bool showwin, int defaultiwad, int& } if (showwin || (vkey != 0 && GetAsyncKeyState(vkey))) { - return LauncherWindow::ExecModal(wads, numwads, defaultiwad, &autoloadflags); + return LauncherWindow::ExecModal(wads, numwads, defaultiwad, &autoloadflags, &extraArgs); } return defaultiwad; } diff --git a/src/common/platform/win32/i_system.h b/src/common/platform/win32/i_system.h index 9d360b55a..b70efb78b 100644 --- a/src/common/platform/win32/i_system.h +++ b/src/common/platform/win32/i_system.h @@ -38,7 +38,7 @@ void I_PrintStr (const char *cp); void I_SetIWADInfo (); // Pick from multiple IWADs to use -int I_PickIWad(WadStuff* wads, int numwads, bool queryiwad, int defaultiwad, int& autoloadflags); +int I_PickIWad(WadStuff* wads, int numwads, bool queryiwad, int defaultiwad, int& autoloadflags, FString &extraArgs); // The ini could not be saved at exit bool I_WriteIniFailed (const char* filename); diff --git a/src/common/utility/m_argv.cpp b/src/common/utility/m_argv.cpp index b9b05c3e9..05bc173ee 100644 --- a/src/common/utility/m_argv.cpp +++ b/src/common/utility/m_argv.cpp @@ -345,6 +345,114 @@ void FArgs::AppendArgs(int argc, const FString *argv) } } +//=========================================================================== +// +// FArgs :: AppendArgsString +// +// Adds extra args as a space-separated string, supporting simple quoting, and inserting -file args into the right place +// +//=========================================================================== + + +void FArgs::AppendArgsString(FString argv) +{ + auto file_index = Argv.Find("-file"); + auto files_end = file_index + 1; + + for (; files_end < Argv.Size() && Argv[files_end][0] != '-' && Argv[files_end][0] != '+'; ++files_end); + + if(file_index == Argv.Size()) + { + Argv.Push("-file"); + } + + bool inserting_file = true; + + argv.StripLeftRight(); + + size_t i = 0; + size_t lastSection = 0; + size_t lastStart = 0; + char lastQuoteType = 0; + + FString tmp; + bool has_tmp = false; + + for(i = 0; i < argv.Len(); i++) + { + if(argv[i] == ' ') + { + FString arg = tmp + argv.Mid(lastSection, i - lastSection); + + if(arg[0] == '-' || arg[0] == '+') inserting_file = false; + + if(inserting_file) + { + Argv.Insert(files_end++, arg); + } + else if(arg.Compare("-file") == 0) + { + inserting_file = true; + } + else + { + files_end++; + Argv.Insert(file_index++, arg); + } + + lastSection = i + 1; + tmp = ""; + has_tmp = false; + for(;(i + 1) < argv.Len() && argv[i + 1] == ' '; i++, lastSection++); + lastStart = i + 1; + } + else if(argv[i] == '\'' || argv[i] == '"') + { + lastQuoteType = argv[i]; + tmp += argv.Mid(lastSection, i - lastSection); + has_tmp = true; + bool wasSlash = false; + + for(i++; (argv[i] != lastQuoteType || wasSlash) && i < argv.Len(); i++) + { + if(i == '\\' && !wasSlash) + { + wasSlash = true; + } + else + { + tmp += argv[i]; + wasSlash = false; + } + } + lastSection = i + 1; + } + } + + if(lastSection != i) + { // ended on an unquoted section + FString arg = tmp + argv.Mid(lastSection); + if(inserting_file) + { + Argv.Insert(files_end, arg); + } + else if(arg.Compare("-file") != 0) + { + Argv.Insert(file_index, arg); + } + } + else if(has_tmp) + { // ended on a quote + if(inserting_file) + { + Argv.Insert(files_end, tmp); + } + else if(tmp.Compare("-file") != 0) + { + Argv.Insert(file_index, tmp); + } + } +} //=========================================================================== // // FArgs :: RemoveArg diff --git a/src/common/utility/m_argv.h b/src/common/utility/m_argv.h index 953769703..d12da9a5f 100644 --- a/src/common/utility/m_argv.h +++ b/src/common/utility/m_argv.h @@ -85,6 +85,7 @@ class FArgs void AppendArg(FString arg); void AppendArgs(int argc, const FString *argv); + void AppendArgsString(FString argv); void RemoveArg(int argindex); void RemoveArgs(const char *check); void SetArgs(int argc, char **argv); diff --git a/src/common/utility/zstring.h b/src/common/utility/zstring.h index 93d679021..284027712 100644 --- a/src/common/utility/zstring.h +++ b/src/common/utility/zstring.h @@ -128,6 +128,7 @@ class FString FString (FString &&other) noexcept : Chars(other.Chars) { other.ResetToNull(); } FString (const char *copyStr); FString (const char *copyStr, size_t copyLen); + FString (const std::string &s) : FString(s.c_str(), s.length()) {} FString (char oneChar); FString(const TArray & source) : FString(source.Data(), source.Size()) {} FString(const TArray & source) : FString((char*)source.Data(), source.Size()) {} diff --git a/src/d_iwad.cpp b/src/d_iwad.cpp index 0dd46db3b..4758064a3 100644 --- a/src/d_iwad.cpp +++ b/src/d_iwad.cpp @@ -764,9 +764,18 @@ int FIWadManager::IdentifyVersion (std::vector&wadfiles, const char if (autoloadbrightmaps) flags |= 4; if (autoloadwidescreen) flags |= 8; - pick = I_PickIWad(&wads[0], (int)wads.Size(), queryiwad, pick, flags); + FString extraArgs; + + pick = I_PickIWad(&wads[0], (int)wads.Size(), queryiwad, pick, flags, extraArgs); if (pick >= 0) { + extraArgs.StripLeftRight(); + + if(extraArgs.Len() > 0) + { + Args->AppendArgsString(extraArgs); + } + disableautoload = !!(flags & 1); autoloadlights = !!(flags & 2); autoloadbrightmaps = !!(flags & 4); diff --git a/src/d_main.cpp b/src/d_main.cpp index fbc67693c..2d7f20c48 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1809,7 +1809,9 @@ static void GetCmdLineFiles(std::vector& wadfiles) int i, argc; argc = Args->CheckParmList("-file", &args); - for (i = 0; i < argc; ++i) + + // [RL0] Check for array size to only add new wads + for (i = wadfiles.size(); i < argc; ++i) { D_AddWildFile(wadfiles, args[i].GetChars(), ".wad", GameConfig); } @@ -3764,6 +3766,9 @@ static int D_DoomMain_Internal (void) std::vector allwads; const FIWADInfo *iwad_info = iwad_man->FindIWAD(allwads, iwad.GetChars(), basewad.GetChars(), optionalwad.GetChars()); + + GetCmdLineFiles(pwads); // [RL0] Update with files passed on the launcher extra args + if (!iwad_info) return 0; // user exited the selection popup via cancel button. if ((iwad_info->flags & GI_SHAREWARE) && pwads.size() > 0) { diff --git a/src/launcher/launcherwindow.cpp b/src/launcher/launcherwindow.cpp index 37d0a236d..860d1a109 100644 --- a/src/launcher/launcherwindow.cpp +++ b/src/launcher/launcherwindow.cpp @@ -11,7 +11,7 @@ #include #include -int LauncherWindow::ExecModal(WadStuff* wads, int numwads, int defaultiwad, int* autoloadflags) +int LauncherWindow::ExecModal(WadStuff* wads, int numwads, int defaultiwad, int* autoloadflags, FString * extraArgs) { Size screenSize = GetScreenSize(); double windowWidth = 615.0; @@ -23,6 +23,8 @@ int LauncherWindow::ExecModal(WadStuff* wads, int numwads, int defaultiwad, int* DisplayWindow::RunLoop(); + if(extraArgs) *extraArgs = launcher->PlayGame->GetExtraArgs(); + return launcher->ExecResult; } @@ -54,12 +56,6 @@ void LauncherWindow::Start() { Settings->Save(); - std::string extraargs = PlayGame->GetExtraArgs(); - if (!extraargs.empty()) - { - // To do: restart the process like the cocoa backend is doing? - } - ExecResult = PlayGame->GetSelectedGame(); DisplayWindow::ExitLoop(); } diff --git a/src/launcher/launcherwindow.h b/src/launcher/launcherwindow.h index 8cdbc6ce7..8e7c8bbe6 100644 --- a/src/launcher/launcherwindow.h +++ b/src/launcher/launcherwindow.h @@ -14,7 +14,7 @@ struct WadStuff; class LauncherWindow : public Widget { public: - static int ExecModal(WadStuff* wads, int numwads, int defaultiwad, int* autoloadflags); + static int ExecModal(WadStuff* wads, int numwads, int defaultiwad, int* autoloadflags, FString * extraArgs = nullptr); LauncherWindow(WadStuff* wads, int numwads, int defaultiwad, int* autoloadflags); void UpdateLanguage(); From 1006d20c136b438985a6c0ae246aec59d2de0ec4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Sun, 21 Apr 2024 12:25:14 -0300 Subject: [PATCH 42/84] fix CheckParmList seems like it was checking the second char for '+' instead of the first --- src/common/utility/m_argv.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/utility/m_argv.cpp b/src/common/utility/m_argv.cpp index 05bc173ee..0e8946058 100644 --- a/src/common/utility/m_argv.cpp +++ b/src/common/utility/m_argv.cpp @@ -189,7 +189,7 @@ int FArgs::CheckParmList(const char *check, FString **strings, int start) const } for (i = ++parmat; i < Argv.Size(); ++i) { - if (Argv[i][0] == '-' || Argv[i][1] == '+') + if (Argv[i][0] == '-' || Argv[i][0] == '+') { break; } From 9129f0121b0b9facbcbee0eb5f82afbb0e67b022 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Sun, 21 Apr 2024 12:31:12 -0300 Subject: [PATCH 43/84] Fix MacOS Compilation --- src/common/platform/posix/cocoa/i_system.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/platform/posix/cocoa/i_system.mm b/src/common/platform/posix/cocoa/i_system.mm index cef2d177b..267bac31d 100644 --- a/src/common/platform/posix/cocoa/i_system.mm +++ b/src/common/platform/posix/cocoa/i_system.mm @@ -122,7 +122,7 @@ void I_ShowFatalError(const char *message) } -int I_PickIWad(WadStuff* const wads, const int numwads, const bool showwin, const int defaultiwad, int&) +int I_PickIWad(WadStuff* const wads, const int numwads, const bool showwin, const int defaultiwad, int&, FString&) { if (!showwin) { From da4752d7ec74534c4de3618894447f9fbcd58d06 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Fri, 10 May 2024 15:33:56 -0400 Subject: [PATCH 44/84] Fixed unmorphed Actors still ticking --- src/playsim/p_mobj.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index 671a65238..d5fdf8574 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -3810,8 +3810,11 @@ void AActor::Tick () // Check for Actor unmorphing, but only on the thing that is the morphed Actor. // Players do their own special checking for this. - if (alternative != nullptr && !(flags & MF_UNMORPHED) && player == nullptr) + if (alternative != nullptr && player == nullptr) { + if (flags & MF_UNMORPHED) + return; + int res = false; IFVIRTUAL(AActor, CheckUnmorph) { From 6d8bee9316223dee577239975168a7308afc454c Mon Sep 17 00:00:00 2001 From: Xaser Acheron Date: Mon, 10 Apr 2023 22:18:41 -0500 Subject: [PATCH 45/84] don't show secret-flagged linedefs with special color on am_cheat 4 and above --- src/am_map.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/am_map.cpp b/src/am_map.cpp index 48bc53823..6ee8165da 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -2624,7 +2624,7 @@ void DAutomap::drawWalls (bool allmap) } else if (line.flags & ML_SECRET) { // secret door - if (am_cheat != 0 && line.backsector != nullptr) + if (am_cheat != 0 && am_cheat < 4 && line.backsector != nullptr) drawMline(&l, AMColors.SecretWallColor); else drawMline(&l, AMColors.WallColor); From 1dedcee7391370f919b38ce2a5c95728ba1a9d4e Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sat, 18 May 2024 10:24:00 +0200 Subject: [PATCH 46/84] Provide a diagnostic message for the two 32-bit related static_asserts --- src/common/engine/i_interface.cpp | 8 +++++++- src/playsim/p_effect.h | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/common/engine/i_interface.cpp b/src/common/engine/i_interface.cpp index 7030194ea..dfedbe8ee 100644 --- a/src/common/engine/i_interface.cpp +++ b/src/common/engine/i_interface.cpp @@ -6,7 +6,13 @@ #include "gstrings.h" #include "version.h" -static_assert(sizeof(void*) == 8, "32 builds are not supported"); +static_assert(sizeof(void*) == 8, + "Only LP64/LLP64 builds are officially supported. " + "Please do not attempt to build for other platforms; " + "even if the program succeeds in a MAP01 smoke test, " + "there are e.g. known visual artifacts " + " " + "that lead to a bad user experience."); // Some global engine variables taken out of the backend code. FStartupScreen* StartWindow; diff --git a/src/playsim/p_effect.h b/src/playsim/p_effect.h index 374aeecfc..c87aa2c7d 100644 --- a/src/playsim/p_effect.h +++ b/src/playsim/p_effect.h @@ -88,7 +88,7 @@ struct particle_t FStandaloneAnimation animData; //+16 = 128 }; -static_assert(sizeof(particle_t) == 128); +static_assert(sizeof(particle_t) == 128, "Only LP64/LLP64 is supported"); const uint16_t NO_PARTICLE = 0xffff; From ffbbe0a4c6b155db91c0160ce47a63588b43a4ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Mon, 20 May 2024 16:08:13 -0300 Subject: [PATCH 47/84] partial fix for `FString::IsInt()` --- src/common/utility/zstring.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/common/utility/zstring.cpp b/src/common/utility/zstring.cpp index ecd0dc7e6..488c09eb6 100644 --- a/src/common/utility/zstring.cpp +++ b/src/common/utility/zstring.cpp @@ -1089,6 +1089,12 @@ octdigits = [0-7]; ("0" octdigits+ | "0" [xX] hexdigits+ | (digits \ '0') digits*) { return true; } [\000-\377] { return false; }*/ + + //FIX for "0" returning false, doesn't fix 0 with whitespace, but that isn't necessary for savegame loading, so it'll need to be fixed later + if(Len() == 1 && Chars[0] == '0') return true; + + + const char *YYCURSOR = Chars; char yych; From cf8a04c457988b4cf01626802fe6e6490931b7a6 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Tue, 21 May 2024 03:09:21 -0400 Subject: [PATCH 48/84] - simplify squishing to square pixels for particles and rollsprites --- src/rendering/hwrenderer/scene/hw_sprites.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rendering/hwrenderer/scene/hw_sprites.cpp b/src/rendering/hwrenderer/scene/hw_sprites.cpp index cd2100e3f..c06812858 100644 --- a/src/rendering/hwrenderer/scene/hw_sprites.cpp +++ b/src/rendering/hwrenderer/scene/hw_sprites.cpp @@ -1004,7 +1004,7 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t if (thing->renderflags & (RF_ROLLSPRITE|RF_FLATSPRITE)) { double ps = di->Level->pixelstretch; - double mult = 2 * ps / (ps * ps + 1); // shrink slightly + double mult = 1.0 / sqrt(ps); // shrink slightly r.Scale(mult * ps, mult); } @@ -1452,7 +1452,7 @@ void HWSprite::ProcessParticle(HWDrawInfo *di, particle_t *particle, sector_t *s float ps = di->Level->pixelstretch; - scalefac *= 2 * ps / (ps * ps + 1); // shrink it slightly to account for the stretch + scalefac /= sqrt(ps); // shrink it slightly to account for the stretch float viewvecX = vp.ViewVector.X * scalefac * ps; float viewvecY = vp.ViewVector.Y * scalefac; @@ -1527,7 +1527,7 @@ void HWSprite::AdjustVisualThinker(HWDrawInfo* di, DVisualThinker* spr, sector_t if (spr->PT.flags & SPF_ROLL) { double ps = di->Level->pixelstretch; - double mult = 2 * ps / (ps * ps + 1); // shrink slightly + double mult = 1.0 / sqrt(ps); // shrink slightly r.Scale(mult * ps, mult); } From 3bc54d3757dc866d1509f29dd4bc3e4614441d53 Mon Sep 17 00:00:00 2001 From: Kartinea Date: Mon, 6 May 2024 16:08:41 -0700 Subject: [PATCH 49/84] Fix invisibility affect on enemies When performing the ShadowBlock check, we previously would return a nullptr actor if nothing was between the monster and the player. This resulted in the monster aiming as if you didn't have invisibility. Fall back to returning the target actor if it is shadowed but nothing is in between the two. --- src/playsim/shadowinlines.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/playsim/shadowinlines.h b/src/playsim/shadowinlines.h index 60caa9506..574abd251 100644 --- a/src/playsim/shadowinlines.h +++ b/src/playsim/shadowinlines.h @@ -85,7 +85,12 @@ inline bool AffectedByShadows(AActor* self) inline AActor* CheckForShadows(AActor* self, AActor* other, DVector3 pos, double& penaltyFactor) { - return ((other && (other->flags & MF_SHADOW)) || (self->flags9 & MF9_DOSHADOWBLOCK)) ? P_CheckForShadowBlock(self, other, pos, penaltyFactor) : nullptr; + if ((other && (other->flags & MF_SHADOW)) || (self->flags9 & MF9_DOSHADOWBLOCK)) + { + AActor* shadowBlock = P_CheckForShadowBlock(self, other, pos, penaltyFactor); + return shadowBlock ? shadowBlock : other; + } + return nullptr; } inline AActor* PerformShadowChecks(AActor* self, AActor* other, DVector3 pos, double& penaltyFactor) From d02f79d4be457667000756496742b16f57625648 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Sun, 12 May 2024 18:32:36 -0400 Subject: [PATCH 50/84] Added subclassing for use commands Allows for finding subclasses when using the item commands that search the inventory. Can be either true/false or 0/1. --- src/g_game.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/g_game.cpp b/src/g_game.cpp index 472b840a4..105b16aa7 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -476,11 +476,17 @@ CCMD(invquery) } } +constexpr char True[] = "true"; + CCMD (use) { if (argv.argc() > 1 && players[consoleplayer].mo != NULL) { - SendItemUse = players[consoleplayer].mo->FindInventory(argv[1]); + bool subclass = false; + if (argv.argc() > 2) + subclass = !stricmp(argv[2], True) || atoi(argv[2]); + + SendItemUse = players[consoleplayer].mo->FindInventory(argv[1], subclass); } } @@ -503,7 +509,11 @@ CCMD (drop) { if (argv.argc() > 1 && players[consoleplayer].mo != NULL) { - SendItemDrop = players[consoleplayer].mo->FindInventory(argv[1]); + bool subclass = false; + if (argv.argc() > 3) + subclass = !stricmp(argv[3], True) || atoi(argv[3]); + + SendItemDrop = players[consoleplayer].mo->FindInventory(argv[1], subclass); SendItemDropAmount = argv.argc() > 2 ? atoi(argv[2]) : -1; } } @@ -528,7 +538,11 @@ CCMD (select) auto user = players[consoleplayer].mo; if (argv.argc() > 1) { - auto item = user->FindInventory(argv[1]); + bool subclass = false; + if (argv.argc() > 2) + subclass = !stricmp(argv[2], True) || atoi(argv[2]); + + auto item = user->FindInventory(argv[1], subclass); if (item != NULL) { user->PointerVar(NAME_InvSel) = item; From 4c191f4bf525cf8b0a36d5644266df57466bad5d Mon Sep 17 00:00:00 2001 From: Boondorl Date: Fri, 17 May 2024 20:03:44 -0400 Subject: [PATCH 51/84] Inventory item spawn fixes Default player items and shared items are no longer capable of being duplicated regardless of item flags. Shared items now give a true copy of the item. Fixed incorrect effects playing from item copies. Dropped items can no longer be shared. --- .../zscript/actors/inventory/inventory.zs | 22 +++++++++---------- wadsrc/static/zscript/actors/player/player.zs | 1 + 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/wadsrc/static/zscript/actors/inventory/inventory.zs b/wadsrc/static/zscript/actors/inventory/inventory.zs index 564989459..2e6544093 100644 --- a/wadsrc/static/zscript/actors/inventory/inventory.zs +++ b/wadsrc/static/zscript/actors/inventory/inventory.zs @@ -271,19 +271,18 @@ class Inventory : Actor if (bSharingItem) return; - class type = GetClass(); int skip = giver && giver.player ? giver.PlayerNumber() : -1; - for (int i; i < MAXPLAYERS; ++i) { if (!playerInGame[i] || i == skip) continue; - let item = Inventory(Spawn(type)); - if (!item) + let item = CreateLocalCopy(players[i].mo); + if (!item || item == self) continue; item.bSharingItem = true; + item.bDropped = item.bNeverLocal = true; if (!item.CallTryPickup(players[i].mo)) { item.Destroy(); @@ -293,14 +292,13 @@ class Inventory : Actor if (!bQuiet) { - PlayPickupSound(players[i].mo); + PrintPickupMessage(i == consoleplayer, item.PickupMessage()); + + item.PlayPickupSound(players[i].mo); if (!bNoScreenFlash && players[i].PlayerState != PST_DEAD) players[i].BonusCount = BONUSADD; } } - - if (!bQuiet && consoleplayer != skip) - PrintPickupMessage(true, PickupMessage()); } //=========================================================================== @@ -700,7 +698,7 @@ class Inventory : Actor toucher.HasReceived(self); // If the item can be shared, make sure every player gets a copy. - if (multiplayer && !deathmatch && ShouldShareItem(toucher)) + if (multiplayer && !deathmatch && !bDropped && ShouldShareItem(toucher)) ShareItemWithPlayers(toucher); } return res, toucher; @@ -869,13 +867,13 @@ class Inventory : Actor if (!bQuiet) { - PrintPickupMessage(localview, PickupMessage ()); + PrintPickupMessage(localview, give.PickupMessage ()); // Special check so voodoo dolls picking up items cause the // real player to make noise. if (player != NULL) { - PlayPickupSound (player.mo); + give.PlayPickupSound (player.mo); if (!bNoScreenFlash && player.playerstate != PST_DEAD) { player.bonuscount = BONUSADD; @@ -883,7 +881,7 @@ class Inventory : Actor } else { - PlayPickupSound (toucher); + give.PlayPickupSound (toucher); } } diff --git a/wadsrc/static/zscript/actors/player/player.zs b/wadsrc/static/zscript/actors/player/player.zs index fe56805d7..505d18d83 100644 --- a/wadsrc/static/zscript/actors/player/player.zs +++ b/wadsrc/static/zscript/actors/player/player.zs @@ -1945,6 +1945,7 @@ class PlayerPawn : Actor { item = Inventory(Spawn(ti)); item.bIgnoreSkill = true; // no skill multipliers here + item.bDropped = item.bNeverLocal = true; // Avoid possible copies. item.Amount = di.Amount; let weap = Weapon(item); if (weap) From 3d6e508d678b139646c185f7ff63e3ea502a6fa2 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Mon, 29 Apr 2024 07:43:14 -0400 Subject: [PATCH 52/84] Network messages will now show usernames instead of just numbers Gives more useful feedback as it's not obvious which node belongs to who. Added line breaks to network messages for cases where a large amount of players are desynced. --- src/g_statusbar/shared_sbar.cpp | 73 ++++++++----------- src/playsim/d_player.h | 20 ++++- src/playsim/p_user.cpp | 3 +- wadsrc/static/zscript/actors/player/player.zs | 2 +- 4 files changed, 51 insertions(+), 47 deletions(-) diff --git a/src/g_statusbar/shared_sbar.cpp b/src/g_statusbar/shared_sbar.cpp index bd75e4469..de125725b 100644 --- a/src/g_statusbar/shared_sbar.cpp +++ b/src/g_statusbar/shared_sbar.cpp @@ -1233,76 +1233,63 @@ void DBaseStatusBar::DrawTopStuff (EHudState state) void DBaseStatusBar::DrawConsistancy () const { - static bool firsttime = true; - int i; - char conbuff[64], *buff_p; - if (!netgame) return; - buff_p = NULL; - for (i = 0; i < MAXPLAYERS; i++) + bool desync = false; + FString text = "Out of sync with:"; + for (int i = 0; i < MAXPLAYERS; i++) { if (playeringame[i] && players[i].inconsistant) { - if (buff_p == NULL) - { - strcpy (conbuff, "Out of sync with:"); - buff_p = conbuff + 17; - } - *buff_p++ = ' '; - *buff_p++ = '1' + i; - *buff_p = 0; + desync = true; + text.AppendFormat(" %s (%d)", players[i].userinfo.GetName(10u), i + 1); } } - if (buff_p != NULL) + if (desync) { - if (firsttime) + auto lines = V_BreakLines(SmallFont, twod->GetWidth() / CleanXfac - 40, text.GetChars()); + const int height = SmallFont->GetHeight() * CleanYfac; + double y = 0.0; + for (auto& line : lines) { - firsttime = false; - if (debugfile) - { - fprintf (debugfile, "%s as of tic %d (%d)\n", conbuff, - players[1-consoleplayer].inconsistant, - players[1-consoleplayer].inconsistant/ticdup); - } + DrawText(twod, SmallFont, CR_GREEN, + (twod->GetWidth() - SmallFont->StringWidth(line.Text) * CleanXfac) * 0.5, + y, line.Text.GetChars(), DTA_CleanNoMove, true, TAG_DONE); + y += height; } - DrawText(twod, SmallFont, CR_GREEN, - (twod->GetWidth() - SmallFont->StringWidth (conbuff)*CleanXfac) / 2, - 0, conbuff, DTA_CleanNoMove, true, TAG_DONE); } } void DBaseStatusBar::DrawWaiting () const { - int i; - char conbuff[64], *buff_p; - if (!netgame) return; - buff_p = NULL; - for (i = 0; i < MAXPLAYERS; i++) + FString text = "Waiting for:"; + bool isWaiting = false; + for (int i = 0; i < MAXPLAYERS; i++) { if (playeringame[i] && players[i].waiting) { - if (buff_p == NULL) - { - strcpy (conbuff, "Waiting for:"); - buff_p = conbuff + 12; - } - *buff_p++ = ' '; - *buff_p++ = '1' + i; - *buff_p = 0; + isWaiting = true; + text.AppendFormat(" %s (%d)", players[i].userinfo.GetName(10u), i + 1); } } - if (buff_p != NULL) + if (isWaiting) { - DrawText(twod, SmallFont, CR_ORANGE, - (twod->GetWidth() - SmallFont->StringWidth (conbuff)*CleanXfac) / 2, - SmallFont->GetHeight()*CleanYfac, conbuff, DTA_CleanNoMove, true, TAG_DONE); + auto lines = V_BreakLines(SmallFont, twod->GetWidth() / CleanXfac - 40, text.GetChars()); + const int height = SmallFont->GetHeight() * CleanYfac; + double y = 0.0; + for (auto& line : lines) + { + DrawText(twod, SmallFont, CR_ORANGE, + (twod->GetWidth() - SmallFont->StringWidth(line.Text) * CleanXfac) * 0.5, + y, line.Text.GetChars(), DTA_CleanNoMove, true, TAG_DONE); + y += height; + } } } diff --git a/src/playsim/d_player.h b/src/playsim/d_player.h index 34ac55da6..a717bb42c 100644 --- a/src/playsim/d_player.h +++ b/src/playsim/d_player.h @@ -204,9 +204,25 @@ struct userinfo_t : TMap { return *static_cast(*CheckKey(NAME_Autoaim)); } - const char *GetName() const + const char *GetName(unsigned int charLimit = 0u) const { - return *static_cast(*CheckKey(NAME_Name)); + const char* name = *static_cast(*CheckKey(NAME_Name)); + if (charLimit) + { + FString temp = name; + if (temp.CharacterCount() > charLimit) + { + int next = 0; + for (unsigned int i = 0u; i < charLimit; ++i) + temp.GetNextCharacter(next); + + temp.Truncate(next); + temp += "..."; + name = temp.GetChars(); + } + } + + return name; } int GetTeam() const { diff --git a/src/playsim/p_user.cpp b/src/playsim/p_user.cpp index 967ddb660..924ad47a8 100644 --- a/src/playsim/p_user.cpp +++ b/src/playsim/p_user.cpp @@ -727,7 +727,8 @@ DEFINE_ACTION_FUNCTION(_PlayerInfo, Resurrect) DEFINE_ACTION_FUNCTION(_PlayerInfo, GetUserName) { PARAM_SELF_STRUCT_PROLOGUE(player_t); - ACTION_RETURN_STRING(self->userinfo.GetName()); + PARAM_UINT(charLimit); + ACTION_RETURN_STRING(self->userinfo.GetName(charLimit)); } DEFINE_ACTION_FUNCTION(_PlayerInfo, GetNeverSwitch) diff --git a/wadsrc/static/zscript/actors/player/player.zs b/wadsrc/static/zscript/actors/player/player.zs index 505d18d83..e9b25c9b2 100644 --- a/wadsrc/static/zscript/actors/player/player.zs +++ b/wadsrc/static/zscript/actors/player/player.zs @@ -2861,7 +2861,7 @@ struct PlayerInfo native play // self is what internally is known as player_t native void SetSubtitleNumber (int text, Sound sound_id = 0); native bool Resurrect(); - native clearscope String GetUserName() const; + native clearscope String GetUserName(uint charLimit = 0u) const; native clearscope Color GetColor() const; native clearscope Color GetDisplayColor() const; native clearscope int GetColorSet() const; From 53270f0bc809c330286ac3696434e10cfc0bd940 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Thu, 23 May 2024 12:16:34 -0400 Subject: [PATCH 53/84] Added ChangeTeam function for teamplay Also removes the TeamLibrary global since all it did was call what should've been static functions. --- src/d_main.cpp | 2 +- src/d_netinfo.cpp | 16 ++++----- src/gamedata/teaminfo.cpp | 34 ++++++++++++++++--- src/gamedata/teaminfo.h | 10 +++--- src/hu_scores.cpp | 4 +-- src/playsim/bots/b_game.cpp | 4 +-- wadsrc/static/zscript/actors/player/player.zs | 1 + 7 files changed, 49 insertions(+), 22 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index 2d7f20c48..b0d3d88f2 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -3359,7 +3359,7 @@ static int D_InitGame(const FIWADInfo* iwad_info, std::vector& allw // [CW] Parse any TEAMINFO lumps. if (!batchrun) Printf ("ParseTeamInfo: Load team definitions.\n"); - TeamLibrary.ParseTeamInfo (); + FTeam::ParseTeamInfo (); R_ParseTrnslate(); PClassActor::StaticInit (); diff --git a/src/d_netinfo.cpp b/src/d_netinfo.cpp index ee004505e..bac6eddfe 100644 --- a/src/d_netinfo.cpp +++ b/src/d_netinfo.cpp @@ -197,7 +197,7 @@ void D_GetPlayerColor (int player, float *h, float *s, float *v, FPlayerColorSet RGBtoHSV (RPART(color)/255.f, GPART(color)/255.f, BPART(color)/255.f, h, s, v); - if (teamplay && TeamLibrary.IsValidTeam((team = info->GetTeam())) && !Teams[team].GetAllowCustomPlayerColor()) + if (teamplay && FTeam::IsValid((team = info->GetTeam())) && !Teams[team].GetAllowCustomPlayerColor()) { // In team play, force the player to use the team's hue // and adjust the saturation and value so that the team @@ -264,7 +264,7 @@ int D_PickRandomTeam () if (playeringame[i]) { team = players[i].userinfo.GetTeam(); - if (TeamLibrary.IsValidTeam(team)) + if (FTeam::IsValid(team)) { if (Teams[team].m_iPresent++ == 0) { @@ -319,7 +319,7 @@ static void UpdateTeam (int pnum, int team, bool update) { userinfo_t *info = &players[pnum].userinfo; - if ((dmflags2 & DF2_NO_TEAM_SWITCH) && (alwaysapplydmflags || deathmatch) && TeamLibrary.IsValidTeam (info->GetTeam())) + if ((dmflags2 & DF2_NO_TEAM_SWITCH) && (alwaysapplydmflags || deathmatch) && FTeam::IsValid (info->GetTeam())) { Printf ("%s\n", GStrings.GetString("TXT_NO_TEAM_CHANGE")); return; @@ -327,7 +327,7 @@ static void UpdateTeam (int pnum, int team, bool update) int oldteam; - if (!TeamLibrary.IsValidTeam (team)) + if (!FTeam::IsValid (team)) { team = TEAM_NONE; } @@ -337,7 +337,7 @@ static void UpdateTeam (int pnum, int team, bool update) if (update && oldteam != team) { FString message; - if (TeamLibrary.IsValidTeam (team)) + if (FTeam::IsValid (team)) { message = GStrings.GetString("TXT_JOINED_TEAM"); message.Substitute("%t", Teams[team].GetName()); @@ -356,7 +356,7 @@ static void UpdateTeam (int pnum, int team, bool update) StatusBar->AttachToPlayer (&players[pnum]); } // Double-check - if (!TeamLibrary.IsValidTeam (team)) + if (!FTeam::IsValid (team)) { *static_cast((*info)[NAME_Team]) = TEAM_NONE; } @@ -365,7 +365,7 @@ static void UpdateTeam (int pnum, int team, bool update) int D_GetFragCount (player_t *player) { const int team = player->userinfo.GetTeam(); - if (!teamplay || !TeamLibrary.IsValidTeam(team)) + if (!teamplay || !FTeam::IsValid(team)) { return player->fragcount; } @@ -479,7 +479,7 @@ void userinfo_t::Reset(int pnum) int userinfo_t::TeamChanged(int team) { - if (teamplay && !TeamLibrary.IsValidTeam(team)) + if (teamplay && !FTeam::IsValid(team)) { // Force players onto teams in teamplay mode team = D_PickRandomTeam(); } diff --git a/src/gamedata/teaminfo.cpp b/src/gamedata/teaminfo.cpp index 1838d1b39..25ec9dd3b 100644 --- a/src/gamedata/teaminfo.cpp +++ b/src/gamedata/teaminfo.cpp @@ -43,6 +43,7 @@ #include "v_video.h" #include "filesystem.h" #include "vm.h" +#include "d_player.h" // MACROS ------------------------------------------------------------------ @@ -56,9 +57,11 @@ // EXTERNAL DATA DECLARATIONS ---------------------------------------------- +extern bool playeringame[MAXPLAYERS]; +extern player_t players[MAXPLAYERS]; + // PUBLIC DATA DEFINITIONS ------------------------------------------------- -FTeam TeamLibrary; TArray Teams; // PRIVATE DATA DEFINITIONS ------------------------------------------------ @@ -245,7 +248,7 @@ void FTeam::ClearTeams () // //========================================================================== -bool FTeam::IsValidTeam (unsigned int uiTeam) const +bool FTeam::IsValid (unsigned int uiTeam) { if (uiTeam >= Teams.Size ()) return false; @@ -253,6 +256,15 @@ bool FTeam::IsValidTeam (unsigned int uiTeam) const return true; } +bool FTeam::ChangeTeam(unsigned int pNum, unsigned int newTeam) +{ + if (!multiplayer || !teamplay || pNum >= MAXPLAYERS || !playeringame[pNum] || !FTeam::IsValid(newTeam) || players[pNum].userinfo.GetTeam() == newTeam) + return false; + + players[pNum].userinfo.TeamChanged(newTeam); + return true; +} + //========================================================================== // // FTeam :: GetName @@ -342,7 +354,7 @@ DEFINE_FIELD_NAMED(FTeam, m_Name, mName) static int IsValid(unsigned int id) { - return TeamLibrary.IsValidTeam(id); + return FTeam::IsValid(id); } DEFINE_ACTION_FUNCTION_NATIVE(FTeam, IsValid, IsValid) @@ -350,7 +362,21 @@ DEFINE_ACTION_FUNCTION_NATIVE(FTeam, IsValid, IsValid) PARAM_PROLOGUE; PARAM_UINT(id); - ACTION_RETURN_BOOL(TeamLibrary.IsValidTeam(id)); + ACTION_RETURN_BOOL(FTeam::IsValid(id)); +} + +static int ChangeTeam(unsigned int pNum, unsigned int newTeam) +{ + return FTeam::ChangeTeam(pNum, newTeam); +} + +DEFINE_ACTION_FUNCTION_NATIVE(FTeam, ChangeTeam, ChangeTeam) +{ + PARAM_PROLOGUE; + PARAM_UINT(pNum); + PARAM_UINT(newTeam); + + ACTION_RETURN_BOOL(FTeam::ChangeTeam(pNum, newTeam)); } static int GetPlayerColor(FTeam* self) diff --git a/src/gamedata/teaminfo.h b/src/gamedata/teaminfo.h index 1a3db705c..17be9dd46 100644 --- a/src/gamedata/teaminfo.h +++ b/src/gamedata/teaminfo.h @@ -45,8 +45,9 @@ class FTeam { public: FTeam (); - void ParseTeamInfo (); - bool IsValidTeam (unsigned int uiTeam) const; + static void ParseTeamInfo (); + static bool IsValid (unsigned int uiTeam); + static bool ChangeTeam(unsigned int pNum, unsigned int newTeam); const char *GetName () const; int GetPlayerColor () const; @@ -60,8 +61,8 @@ class FTeam int m_iTies; private: - void ParseTeamDefinition (FScanner &Scan); - void ClearTeams (); + static void ParseTeamDefinition (FScanner &Scan); + static void ClearTeams (); public: // needed for script access. FString m_Name; @@ -72,7 +73,6 @@ class FTeam bool m_bAllowCustomPlayerColor; }; -extern FTeam TeamLibrary; extern TArray Teams; #endif diff --git a/src/hu_scores.cpp b/src/hu_scores.cpp index 797e222ef..d7cde85fc 100644 --- a/src/hu_scores.cpp +++ b/src/hu_scores.cpp @@ -293,7 +293,7 @@ static void HU_DoDrawScores (player_t *player, player_t *sortedplayers[MAXPLAYER for (i = 0; i < MAXPLAYERS; ++i) { - if (playeringame[sortedplayers[i]-players] && TeamLibrary.IsValidTeam (sortedplayers[i]->userinfo.GetTeam())) + if (playeringame[sortedplayers[i]-players] && FTeam::IsValid (sortedplayers[i]->userinfo.GetTeam())) { if (Teams[sortedplayers[i]->userinfo.GetTeam()].m_iPlayerCount++ == 0) { @@ -485,7 +485,7 @@ int HU_GetRowColor(player_t *player, bool highlight) { if (teamplay && deathmatch) { - if (TeamLibrary.IsValidTeam (player->userinfo.GetTeam())) + if (FTeam::IsValid (player->userinfo.GetTeam())) return Teams[player->userinfo.GetTeam()].GetTextColor(); else return CR_GREY; diff --git a/src/playsim/bots/b_game.cpp b/src/playsim/bots/b_game.cpp index 198692c1f..3863ac923 100644 --- a/src/playsim/bots/b_game.cpp +++ b/src/playsim/bots/b_game.cpp @@ -305,7 +305,7 @@ bool FCajunMaster::SpawnBot (const char *name, int color) { concat << colors[bot_next_color]; } - if (TeamLibrary.IsValidTeam (thebot->lastteam)) + if (FTeam::IsValid (thebot->lastteam)) { // Keep the bot on the same team when switching levels concat.AppendFormat("\\team\\%d\n", thebot->lastteam); } @@ -587,7 +587,7 @@ bool FCajunMaster::LoadBots () if (IsNum (sc.String)) { teamnum = atoi (sc.String); - if (!TeamLibrary.IsValidTeam (teamnum)) + if (!FTeam::IsValid (teamnum)) { teamnum = TEAM_NONE; } diff --git a/wadsrc/static/zscript/actors/player/player.zs b/wadsrc/static/zscript/actors/player/player.zs index e9b25c9b2..05d9e1b1b 100644 --- a/wadsrc/static/zscript/actors/player/player.zs +++ b/wadsrc/static/zscript/actors/player/player.zs @@ -2989,6 +2989,7 @@ struct Team native native String mName; native static bool IsValid(uint teamIndex); + native static bool ChangeTeam(uint playerNumber, uint newTeamIndex); native Color GetPlayerColor() const; native int GetTextColor() const; From ab20b75c14b898aa551052e0f6e8be258757796d Mon Sep 17 00:00:00 2001 From: Boondorl Date: Sat, 25 May 2024 22:41:30 -0400 Subject: [PATCH 54/84] Added missing player retranslation Play-scoped team changing function. --- src/gamedata/teaminfo.cpp | 1 + wadsrc/static/zscript/actors/player/player.zs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gamedata/teaminfo.cpp b/src/gamedata/teaminfo.cpp index 25ec9dd3b..44e8c0e37 100644 --- a/src/gamedata/teaminfo.cpp +++ b/src/gamedata/teaminfo.cpp @@ -262,6 +262,7 @@ bool FTeam::ChangeTeam(unsigned int pNum, unsigned int newTeam) return false; players[pNum].userinfo.TeamChanged(newTeam); + R_BuildPlayerTranslation(pNum); return true; } diff --git a/wadsrc/static/zscript/actors/player/player.zs b/wadsrc/static/zscript/actors/player/player.zs index 05d9e1b1b..b2252c16e 100644 --- a/wadsrc/static/zscript/actors/player/player.zs +++ b/wadsrc/static/zscript/actors/player/player.zs @@ -2989,7 +2989,7 @@ struct Team native native String mName; native static bool IsValid(uint teamIndex); - native static bool ChangeTeam(uint playerNumber, uint newTeamIndex); + native play static bool ChangeTeam(uint playerNumber, uint newTeamIndex); native Color GetPlayerColor() const; native int GetTextColor() const; From ae28eeae94384dfebbe93c45ed95921c15fccd1f Mon Sep 17 00:00:00 2001 From: nashmuhandes Date: Tue, 14 May 2024 21:26:12 +0800 Subject: [PATCH 55/84] Scriptified the view squatting. --- src/playsim/p_mobj.cpp | 15 +++++++++------ wadsrc/static/zscript/actors/actor.zs | 11 +++++++++++ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index d5fdf8574..9c0b99c88 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -2811,15 +2811,18 @@ static void PlayerLandedMakeGruntSound(AActor* self, AActor *onmobj) } } -static void PlayerLandedOnThing (AActor *mo, AActor *onmobj) +static void PlayerSquatView(AActor *self, AActor *onmobj) { - if (!mo->player) - return; - - if (mo->player->mo == mo) + IFVIRTUALPTR(self, AActor, PlayerSquatView) { - mo->player->deltaviewheight = mo->Vel.Z / 8.; + VMValue params[2] = { self, onmobj }; + VMCall(func, params, 2, nullptr, 0); } +} + +static void PlayerLandedOnThing (AActor *mo, AActor *onmobj) +{ + PlayerSquatView(mo, onmobj); if (mo->player->cheats & CF_PREDICTING) return; diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index 7c52030da..694f8262e 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -1439,6 +1439,17 @@ class Actor : Thinker native } } + virtual void PlayerSquatView(Actor onmobj) + { + if (!self.player) + return; + + if (self.player.mo == self) + { + self.player.deltaviewheight = self.Vel.Z / 8.; + } + } + //---------------------------------------------------------------------------- // // PROC A_CheckSkullDone From c707b418efec4f27e8ba66cd008d66e36188f645 Mon Sep 17 00:00:00 2001 From: Acts 19 quiz Date: Mon, 6 May 2024 14:41:18 -0500 Subject: [PATCH 56/84] Narrow the Launcher check box clickable areas to stop overlap and fix #2558 --- src/launcher/settingspage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/launcher/settingspage.cpp b/src/launcher/settingspage.cpp index 9cd89bcd0..1bfe54d22 100644 --- a/src/launcher/settingspage.cpp +++ b/src/launcher/settingspage.cpp @@ -161,7 +161,7 @@ void SettingsPage::OnLanguageChanged(int i) void SettingsPage::OnGeometryChanged() { - double panelWidth = 200.0; + double panelWidth = 160.0; double y = 0.0; double w = GetWidth(); double h = GetHeight(); From 87463ef36b7a5a9ad691cd8eac664e791e9c9589 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Fri, 31 May 2024 03:02:50 -0300 Subject: [PATCH 57/84] Fix memory leak on TDeletingArray move assignment --- src/common/utility/tarray.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/common/utility/tarray.h b/src/common/utility/tarray.h index bce3ba3ea..3445bd484 100644 --- a/src/common/utility/tarray.h +++ b/src/common/utility/tarray.h @@ -919,6 +919,7 @@ class TDeletingArray : public TArray TDeletingArray(TDeletingArray &&other) : TArray(std::move(other)) {} TDeletingArray &operator=(TDeletingArray &&other) { + DeleteAndClear(); TArray::operator=(std::move(other)); return *this; } From 20cf8befbf55dd2e603a73e5215731267fdea980 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Fri, 31 May 2024 03:07:31 -0300 Subject: [PATCH 58/84] Rework named arguments Now allows arguments to be in any arbitrary position, and allows required arguments to be named --- src/common/scripting/backend/codegen.cpp | 210 ++++++++++++++--------- 1 file changed, 125 insertions(+), 85 deletions(-) diff --git a/src/common/scripting/backend/codegen.cpp b/src/common/scripting/backend/codegen.cpp index 8b3ee306a..077ca1654 100644 --- a/src/common/scripting/backend/codegen.cpp +++ b/src/common/scripting/backend/codegen.cpp @@ -9544,7 +9544,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) if(FnPtrCall) static_cast(ctx.Function->Variants[0].Implementation)->blockJit = true; - int implicit = Function->GetImplicitArgs(); + unsigned implicit = Function->GetImplicitArgs(); if (!CheckAccessibility(ctx.Version)) { @@ -9576,21 +9576,110 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) CallingFunction = ctx.Function; if (ArgList.Size() > 0) { - if (argtypes.Size() == 0) + if ((argtypes.Size() == 0) || (argtypes.Last() != nullptr && ArgList.Size() + implicit > argtypes.Size())) { ScriptPosition.Message(MSG_ERROR, "Too many arguments in call to %s", Function->SymbolName.GetChars()); delete this; return nullptr; } + bool isvararg = (argtypes.Last() == nullptr); + + { + TDeletingArray OrderedArgs; + const unsigned count = (argtypes.Size() - implicit) - isvararg; + + OrderedArgs.Resize(count); + memset(OrderedArgs.Data(), 0, sizeof(FxExpression*) * count); + + unsigned index = 0; + unsigned n = ArgList.Size(); + + for(unsigned i = 0; i < n; i++) + { + if(ArgList[i]->ExprType == EFX_NamedNode) + { + if(FnPtrCall) + { + ScriptPosition.Message(MSG_ERROR, "Named arguments not supported in function pointer calls"); + delete this; + return nullptr; + } + else if((index >= count) && isvararg) + { + ScriptPosition.Message(MSG_ERROR, "Cannot use a named argument in the varargs part of the parameter list."); + delete this; + return nullptr; + } + else + { + unsigned j; + FName name = static_cast(ArgList[i])->name; + for (j = 0; j < count; j++) + { + if (argnames[j + implicit] == name) + { + // i don't think this needs any further optimization? + // O(N^2) complexity technically but N isn't likely to be large, + // and the check itself is just an int comparison, so it should be fine + index = j; + break; + } + } + + if(j == count) + { + ScriptPosition.Message(MSG_ERROR, "Named argument %s not found.", name.GetChars()); + delete this; + return nullptr; + } + } + } + + if(index >= count) + { + if(isvararg) + { + OrderedArgs.Push(ArgList[i]); + ArgList[i] = nullptr; + index++; + } + else + { + ScriptPosition.Message(MSG_ERROR, "Too many arguments in call to %s", Function->SymbolName.GetChars()); + delete this; + return nullptr; + } + } + else + { + if(ArgList[i]->ExprType == EFX_NamedNode) + { + auto * node = static_cast(ArgList[i]); + OrderedArgs[index] = node->value; + node->value = nullptr; + } + else + { + OrderedArgs[index] = ArgList[i]; + } + ArgList[i] = nullptr; + index++; + } + } + + ArgList = std::move(OrderedArgs); + } + bool foundvarargs = false; PType * type = nullptr; int flag = 0; - if (argtypes.Size() > 0 && argtypes.Last() != nullptr && ArgList.Size() + implicit > argtypes.Size()) + + int defaults_index = 0; + + for(unsigned i = 0; i < implicit; i++) { - ScriptPosition.Message(MSG_ERROR, "Too many arguments in call to %s", Function->SymbolName.GetChars()); - delete this; - return nullptr; + defaults_index += argtypes[i]->GetRegCount(); } for (unsigned i = 0; i < ArgList.Size(); i++) @@ -9608,94 +9697,45 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) } assert(type != nullptr); - if (ArgList[i]->ExprType == EFX_NamedNode) + if(!foundvarargs) { - if(FnPtrCall) - { - ScriptPosition.Message(MSG_ERROR, "Named arguments not supported in function pointer calls"); - delete this; - return nullptr; - } - if (!(flag & VARF_Optional)) - { - ScriptPosition.Message(MSG_ERROR, "Cannot use a named argument here - not all required arguments have been passed."); - delete this; - return nullptr; - } - if (foundvarargs) - { - ScriptPosition.Message(MSG_ERROR, "Cannot use a named argument in the varargs part of the parameter list."); - delete this; - return nullptr; - } - unsigned j; - bool done = false; - FName name = static_cast(ArgList[i])->name; - for (j = 0; j < argnames.Size() - implicit; j++) + if(ArgList[i] == nullptr) { - if (argnames[j + implicit] == name) + if(!(flag & VARF_Optional)) { - if (j < i) - { - ScriptPosition.Message(MSG_ERROR, "Named argument %s comes before current position in argument list.", name.GetChars()); - delete this; - return nullptr; - } - // copy the original argument into the list - auto old = static_cast(ArgList[i]); - ArgList[i] = old->value; - old->value = nullptr; - delete old; - // now fill the gap with constants created from the default list so that we got a full list of arguments. - int insert = j - i; - int skipdefs = 0; - // Defaults contain multiple entries for pointers so we need to calculate how much additional defaults we need to skip - for (unsigned k = 0; k < i + implicit; k++) - { - skipdefs += argtypes[k]->GetRegCount() - 1; - } - for (int k = 0; k < insert; k++) + ScriptPosition.Message(MSG_ERROR, "Required argument %s has not been passed in call to %s", argnames[i + implicit].GetChars(), Function->SymbolName.GetChars()); + delete this; + return nullptr; + } + + auto ntype = argtypes[i + implicit]; + // If this is a reference argument, the pointer type must be undone because the code below expects the pointed type as value type. + if (argflags[i + implicit] & VARF_Ref) + { + assert(ntype->isPointer()); + ntype = TypeNullPtr; // the default of a reference type can only be a null pointer + } + if (ntype->GetRegCount() == 1) + { + ArgList[i] = new FxConstant(ntype, (*defaults)[defaults_index], ScriptPosition); + } + else + { + // Vectors need special treatment because they are not normal constants + FxConstant *cs[4] = { nullptr }; + for (int l = 0; l < ntype->GetRegCount(); l++) { - auto ntype = argtypes[i + k + implicit]; - // If this is a reference argument, the pointer type must be undone because the code below expects the pointed type as value type. - if (argflags[i + k + implicit] & VARF_Ref) - { - assert(ntype->isPointer()); - ntype = TypeNullPtr; // the default of a reference type can only be a null pointer - } - if (ntype->GetRegCount() == 1) - { - auto x = new FxConstant(ntype, (*defaults)[i + k + skipdefs + implicit], ScriptPosition); - ArgList.Insert(i + k, x); - } - else - { - // Vectors need special treatment because they are not normal constants - FxConstant *cs[4] = { nullptr }; - for (int l = 0; l < ntype->GetRegCount(); l++) - { - cs[l] = new FxConstant(TypeFloat64, (*defaults)[l + i + k + skipdefs + implicit], ScriptPosition); - } - FxExpression *x = new FxVectorValue(cs[0], cs[1], cs[2], cs[3], ScriptPosition); - ArgList.Insert(i + k, x); - skipdefs += ntype->GetRegCount() - 1; - } + cs[l] = new FxConstant(TypeFloat64, (*defaults)[l + defaults_index], ScriptPosition); } - done = true; - break; + ArgList[i] = new FxVectorValue(cs[0], cs[1], cs[2], cs[3], ScriptPosition); } } - if (!done) - { - ScriptPosition.Message(MSG_ERROR, "Named argument %s not found.", name.GetChars()); - delete this; - return nullptr; - } - // re-get the proper info for the inserted node. - type = argtypes[i + implicit]; - flag = argflags[i + implicit]; + + defaults_index += argtypes[i + implicit]->GetRegCount(); } + assert(ArgList[i]); + FxExpression *x = nullptr; if (foundvarargs && (Function->Variants[0].Flags & VARF_VarArg)) { From 461c2f77b7214f4cd556c9147c64c7279e29e725 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Sat, 1 Jun 2024 11:24:12 -0300 Subject: [PATCH 59/84] restrict new relaxed named arguments to zscript >= 4.13 --- src/common/scripting/backend/codegen.cpp | 46 +++++++++++++++++------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/src/common/scripting/backend/codegen.cpp b/src/common/scripting/backend/codegen.cpp index 077ca1654..5b1a975a6 100644 --- a/src/common/scripting/backend/codegen.cpp +++ b/src/common/scripting/backend/codegen.cpp @@ -9546,6 +9546,8 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) unsigned implicit = Function->GetImplicitArgs(); + bool relaxed_named_arugments = (ctx.Version >= MakeVersion(4, 13)); + if (!CheckAccessibility(ctx.Version)) { delete this; @@ -9613,25 +9615,43 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) } else { - unsigned j; FName name = static_cast(ArgList[i])->name; - for (j = 0; j < count; j++) + if(argnames[index + implicit] != name) { - if (argnames[j + implicit] == name) + unsigned j; + + for (j = 0; j < count; j++) { - // i don't think this needs any further optimization? - // O(N^2) complexity technically but N isn't likely to be large, - // and the check itself is just an int comparison, so it should be fine - index = j; - break; + if (argnames[j + implicit] == name) + { + if(!relaxed_named_arugments && !(argflags[j + implicit] & VARF_Optional)) + { + ScriptPosition.Message(MSG_ERROR, "Cannot use a named argument here - not all required arguments have been passed."); + } + else if(!relaxed_named_arugments && j < index) + { + ScriptPosition.Message(MSG_ERROR, "Named argument %s comes before current position in argument list.", name.GetChars()); + } + + // i don't think this needs any further optimization? + // O(N^2) complexity technically but N isn't likely to be large, + // and the check itself is just an int comparison, so it should be fine + index = j; + + break; + } } - } - if(j == count) + if(j == count) + { + ScriptPosition.Message(MSG_ERROR, "Named argument %s not found.", name.GetChars()); + delete this; + return nullptr; + } + } + else if(!relaxed_named_arugments && !(argflags[index + implicit] & VARF_Optional)) { - ScriptPosition.Message(MSG_ERROR, "Named argument %s not found.", name.GetChars()); - delete this; - return nullptr; + ScriptPosition.Message(MSG_ERROR, "Cannot use a named argument here - not all required arguments have been passed."); } } } From c693e3b0731707351cd166aa160aaa7803751d89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Wed, 5 Jun 2024 19:43:25 -0300 Subject: [PATCH 60/84] Fix A_SetAnimation --- wadsrc/static/zscript/actors/actor.zs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index 694f8262e..768837d59 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -1310,7 +1310,7 @@ class Actor : Thinker native native bool A_AttachLight(Name lightid, int type, Color lightcolor, int radius1, int radius2, int flags = 0, Vector3 ofs = (0,0,0), double param = 0, double spoti = 10, double spoto = 25, double spotp = 0); native bool A_RemoveLight(Name lightid); - native version("4.12") void SetAnimation(Name animName, double framerate = -1, int startFrame = -1, int loopFrame= -1, int endFrame = -1, int interpolateTics = -1, int flags = 0); + native version("4.12") void SetAnimation(Name animName, double framerate = -1, int startFrame = -1, int loopFrame = -1, int endFrame = -1, int interpolateTics = -1, int flags = 0); native version("4.12") ui void SetAnimationUI(Name animName, double framerate = -1, int startFrame = -1, int loopFrame = -1, int endFrame = -1, int interpolateTics = -1, int flags = 0); native version("4.12") void SetAnimationFrameRate(double framerate); @@ -1321,9 +1321,9 @@ class Actor : Thinker native native version("4.12") void ResetModelFlags(); - action version("4.12") void A_SetAnimation(Name animName, double framerate = -1, int startFrame = -1, int loopFrame= -1, int interpolateTics = -1, int flags = 0) + action version("4.12") void A_SetAnimation(Name animName, double framerate = -1, int startFrame = -1, int loopFrame = -1, int endFrame = -1, int interpolateTics = -1, int flags = 0) { - invoker.SetAnimation(animName, framerate, startFrame, loopFrame, interpolateTics, flags); + invoker.SetAnimation(animName, framerate, startFrame, loopFrame, endFrame, interpolateTics, flags); } action version("4.12") void A_SetAnimationFrameRate(double framerate) From 13b9ffd6c83ea4b3aa49b9ad4d2af3e4da2c620a Mon Sep 17 00:00:00 2001 From: nashmuhandes Date: Sat, 15 Jun 2024 18:14:10 +0800 Subject: [PATCH 61/84] Rename SourceRadius to SoftShadowRadius (to match VKDoom) --- specs/udmf_zdoom.txt | 2 +- src/namedef_custom.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/specs/udmf_zdoom.txt b/specs/udmf_zdoom.txt index 402f3d6e8..73e94ea8a 100644 --- a/specs/udmf_zdoom.txt +++ b/specs/udmf_zdoom.txt @@ -424,7 +424,7 @@ Note: All fields default to false unless mentioned otherwise. lm_sampledist = ; // ZDRay lightmap sample distance for the entire map. Defines the map units each lightmap texel covers. Must be in powers of two. Default = 8 lm_suncolor = ; // ZDRay lightmap sun color in hex. Default = "FFFFFF" - SourceRadius = ; // ZDRay lightmap light and raytraced dynamic light soft shadow amount. Higher values produce softer shadows. Default = 5.0 + SoftShadowRadius = ; // ZDRay lightmap light and raytraced dynamic light soft shadow amount. Higher values produce softer shadows. Default = 5.0 friendlyseeblocks = ; // How far (in block units) a friendly monster can see other monsters. Default 10 diff --git a/src/namedef_custom.h b/src/namedef_custom.h index e04dc3795..61bf9d261 100644 --- a/src/namedef_custom.h +++ b/src/namedef_custom.h @@ -865,7 +865,7 @@ xx(lm_suncolor) xx(lm_sampledist) // Light keywords -xx(SourceRadius) +xx(SoftShadowRadius) xx(skew_bottom_type) xx(skew_middle_type) From 2e4bf697b83871a269a6dddcee142115093284c9 Mon Sep 17 00:00:00 2001 From: nashmuhandes Date: Mon, 17 Jun 2024 01:19:58 +0800 Subject: [PATCH 62/84] Add X, Y and Z offsets for VOXELDEF. Needed for voxelized weapons which would typically be very large and take up the majority of the 256x256x256 canvas, therefore making precise positioning of the models relative to the screen pretty much impossible without tweakable offsets. --- src/common/models/voxels.h | 3 ++ src/r_data/models.cpp | 3 ++ src/r_data/voxeldef.cpp | 54 +++++++++++++++++++++ src/rendering/swrenderer/things/r_voxel.cpp | 3 ++ 4 files changed, 63 insertions(+) diff --git a/src/common/models/voxels.h b/src/common/models/voxels.h index 52299434a..fe583fd93 100644 --- a/src/common/models/voxels.h +++ b/src/common/models/voxels.h @@ -73,6 +73,9 @@ struct FVoxelDef int VoxeldefIndex; // Needed by GZDoom double Scale; DAngle AngleOffset;// added to actor's angle to compensate for wrong-facing voxels + double xoffset; + double yoffset; + double zoffset; bool PitchFromMomentum; bool UseActorPitch; bool UseActorRoll; diff --git a/src/r_data/models.cpp b/src/r_data/models.cpp index c2268cef8..f63a15ef6 100644 --- a/src/r_data/models.cpp +++ b/src/r_data/models.cpp @@ -616,6 +616,9 @@ void InitModels() smf.animationIDs[0] = -1; smf.xscale = smf.yscale = smf.zscale = VoxelDefs[i]->Scale; smf.angleoffset = VoxelDefs[i]->AngleOffset.Degrees(); + smf.xoffset = VoxelDefs[i]->xoffset; + smf.yoffset = VoxelDefs[i]->yoffset; + smf.zoffset = VoxelDefs[i]->zoffset; // this helps catching uninitialized data. assert(VoxelDefs[i]->PitchFromMomentum == true || VoxelDefs[i]->PitchFromMomentum == false); if (VoxelDefs[i]->PitchFromMomentum) smf.flags |= MDL_PITCHFROMMOMENTUM; diff --git a/src/r_data/voxeldef.cpp b/src/r_data/voxeldef.cpp index 35037158b..a2eee3c35 100644 --- a/src/r_data/voxeldef.cpp +++ b/src/r_data/voxeldef.cpp @@ -58,6 +58,9 @@ struct VoxelOptions int PlacedSpin = 0; double Scale = 1; DAngle AngleOffset = DAngle90; + double xoffset = 0.0; + double yoffset = 0.0; + double zoffset = 0.0; bool OverridePalette = false; bool PitchFromMomentum = false; bool UseActorPitch = false; @@ -177,6 +180,54 @@ static void VOX_ReadOptions(FScanner &sc, VoxelOptions &opts) } opts.AngleOffset = DAngle::fromDeg(mul * sc.Float + 90.); } + else if (sc.Compare("xoffset")) + { + int mul = 1; + sc.MustGetToken('='); + if (sc.CheckToken('-')) mul = -1; + sc.MustGetAnyToken(); + if (sc.TokenType == TK_IntConst) + { + sc.Float = sc.Number; + } + else + { + sc.TokenMustBe(TK_FloatConst); + } + opts.xoffset = sc.Float * mul; + } + else if (sc.Compare("yoffset")) + { + int mul = 1; + sc.MustGetToken('='); + if (sc.CheckToken('-')) mul = -1; + sc.MustGetAnyToken(); + if (sc.TokenType == TK_IntConst) + { + sc.Float = sc.Number; + } + else + { + sc.TokenMustBe(TK_FloatConst); + } + opts.yoffset = sc.Float * mul; + } + else if (sc.Compare("zoffset")) + { + int mul = 1; + sc.MustGetToken('='); + if (sc.CheckToken('-')) mul = -1; + sc.MustGetAnyToken(); + if (sc.TokenType == TK_IntConst) + { + sc.Float = sc.Number; + } + else + { + sc.TokenMustBe(TK_FloatConst); + } + opts.zoffset = sc.Float * mul; + } else if (sc.Compare("overridepalette")) { opts.OverridePalette = true; @@ -262,6 +313,9 @@ void R_InitVoxels() def->DroppedSpin = opts.DroppedSpin; def->PlacedSpin = opts.PlacedSpin; def->AngleOffset = opts.AngleOffset; + def->xoffset = opts.xoffset; + def->yoffset = opts.yoffset; + def->zoffset = opts.zoffset; def->PitchFromMomentum = opts.PitchFromMomentum; def->UseActorPitch = opts.UseActorPitch; def->UseActorRoll = opts.UseActorRoll; diff --git a/src/rendering/swrenderer/things/r_voxel.cpp b/src/rendering/swrenderer/things/r_voxel.cpp index 28d8921f0..a75b66e31 100644 --- a/src/rendering/swrenderer/things/r_voxel.cpp +++ b/src/rendering/swrenderer/things/r_voxel.cpp @@ -148,6 +148,9 @@ namespace swrenderer vis->depth = (float)tz; vis->gpos = { (float)pos.X, (float)pos.Y, (float)pos.Z }; + vis->gpos.X += (float)voxel->xoffset; + vis->gpos.Y += (float)voxel->yoffset; + vis->gpos.Z += (float)voxel->zoffset; vis->gzb = (float)gzb; // [RH] use gzb, not thing->z vis->gzt = (float)gzt; // killough 3/27/98 vis->deltax = float(pos.X - thread->Viewport->viewpoint.Pos.X); From c56d70f2b16dc7853049ae93e0910f8fa9e49c31 Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Sun, 23 Jun 2024 09:05:45 -0500 Subject: [PATCH 63/84] Added SPF_(NO)FACECAMERA flagst for specifying camera facing on particles and visual thinkers. - This also adds ensures facing camera is applied to these via the option menu. --- src/playsim/p_effect.h | 2 ++ src/rendering/hwrenderer/scene/hw_sprites.cpp | 5 +++-- wadsrc/static/zscript/constants.zs | 2 ++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/playsim/p_effect.h b/src/playsim/p_effect.h index c87aa2c7d..d22438f10 100644 --- a/src/playsim/p_effect.h +++ b/src/playsim/p_effect.h @@ -66,6 +66,8 @@ enum EParticleFlags SPF_NO_XY_BILLBOARD = 1 << 8, SPF_LOCAL_ANIM = 1 << 9, SPF_NEGATIVE_FADESTEP = 1 << 10, + SPF_FACECAMERA = 1 << 11, + SPF_NOFACECAMERA = 1 << 12, }; class DVisualThinker; diff --git a/src/rendering/hwrenderer/scene/hw_sprites.cpp b/src/rendering/hwrenderer/scene/hw_sprites.cpp index c06812858..41112a411 100644 --- a/src/rendering/hwrenderer/scene/hw_sprites.cpp +++ b/src/rendering/hwrenderer/scene/hw_sprites.cpp @@ -400,8 +400,9 @@ bool HWSprite::CalculateVertices(HWDrawInfo* di, FVector3* v, DVector3* vp) && (gl_billboard_mode == 1 || (actor && actor->renderflags & RF_FORCEXYBILLBOARD)))); const bool drawBillboardFacingCamera = hw_force_cambbpref ? gl_billboard_faces_camera : - (gl_billboard_faces_camera && (actor && !(actor->renderflags2 & RF2_BILLBOARDNOFACECAMERA))) - || !!(actor && actor->renderflags2 & RF2_BILLBOARDFACECAMERA); + gl_billboard_faces_camera + && ((actor && (!(actor->renderflags2 & RF2_BILLBOARDNOFACECAMERA) || (actor->renderflags2 & RF2_BILLBOARDFACECAMERA))) + || (particle && particle->texture.isValid() && (!(particle->flags & SPF_NOFACECAMERA) || (particle->flags & SPF_FACECAMERA)))); // [Nash] has +ROLLSPRITE const bool drawRollSpriteActor = (actor != nullptr && actor->renderflags & RF_ROLLSPRITE); diff --git a/wadsrc/static/zscript/constants.zs b/wadsrc/static/zscript/constants.zs index 8e36a5516..6f9d5027a 100644 --- a/wadsrc/static/zscript/constants.zs +++ b/wadsrc/static/zscript/constants.zs @@ -715,6 +715,8 @@ enum EParticleFlags SPF_NO_XY_BILLBOARD = 1 << 8, SPF_LOCAL_ANIM = 1 << 9, SPF_NEGATIVE_FADESTEP = 1 << 10, + SPF_FACECAMERA = 1 << 11, + SPF_NOFACECAMERA = 1 << 12, SPF_RELATIVE = SPF_RELPOS|SPF_RELVEL|SPF_RELACCEL|SPF_RELANG }; From 5fc3d44ba54f18d62ed1e2ef4fe6d3fc240ecfd2 Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Sun, 23 Jun 2024 09:44:13 -0500 Subject: [PATCH 64/84] Added SPF_ROLLCENTER for particles and visual thinkers. --- src/playsim/p_effect.h | 1 + src/rendering/hwrenderer/scene/hw_sprites.cpp | 2 +- wadsrc/static/zscript/constants.zs | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/playsim/p_effect.h b/src/playsim/p_effect.h index d22438f10..29f1cb720 100644 --- a/src/playsim/p_effect.h +++ b/src/playsim/p_effect.h @@ -68,6 +68,7 @@ enum EParticleFlags SPF_NEGATIVE_FADESTEP = 1 << 10, SPF_FACECAMERA = 1 << 11, SPF_NOFACECAMERA = 1 << 12, + SPF_ROLLCENTER = 1 << 13, }; class DVisualThinker; diff --git a/src/rendering/hwrenderer/scene/hw_sprites.cpp b/src/rendering/hwrenderer/scene/hw_sprites.cpp index 41112a411..9340839b9 100644 --- a/src/rendering/hwrenderer/scene/hw_sprites.cpp +++ b/src/rendering/hwrenderer/scene/hw_sprites.cpp @@ -415,7 +415,7 @@ bool HWSprite::CalculateVertices(HWDrawInfo* di, FVector3* v, DVector3* vp) // [Nash] is a flat sprite const bool isWallSprite = (actor != nullptr) && (spritetype == RF_WALLSPRITE); - const bool useOffsets = (actor != nullptr) && !(actor->renderflags & RF_ROLLCENTER); + const bool useOffsets = ((actor != nullptr) && !(actor->renderflags & RF_ROLLCENTER)) || (particle && !(particle->flags & SPF_ROLLCENTER)); FVector2 offset = FVector2( offx, offy ); float xx = -center.X + x; diff --git a/wadsrc/static/zscript/constants.zs b/wadsrc/static/zscript/constants.zs index 6f9d5027a..bd92db9b8 100644 --- a/wadsrc/static/zscript/constants.zs +++ b/wadsrc/static/zscript/constants.zs @@ -717,6 +717,7 @@ enum EParticleFlags SPF_NEGATIVE_FADESTEP = 1 << 10, SPF_FACECAMERA = 1 << 11, SPF_NOFACECAMERA = 1 << 12, + SPF_ROLLCENTER = 1 << 13, SPF_RELATIVE = SPF_RELPOS|SPF_RELVEL|SPF_RELACCEL|SPF_RELANG }; From 3e91d3858202012e07b75395d2b5367802d2a9b7 Mon Sep 17 00:00:00 2001 From: Major Cooke Date: Sun, 23 Jun 2024 18:18:05 -0500 Subject: [PATCH 65/84] Fixed Pre(Un)Morph being called out of order. - This had broken several mods that relied on the inventory being in place before the switch, which was the intended way to begin with. --- src/playsim/p_mobj.cpp | 36 +++++++++++++++++++ wadsrc/static/zscript/actors/morph.zs | 1 + .../zscript/actors/player/player_morph.zs | 6 ---- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index 9c0b99c88..728f1a56d 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -5345,6 +5345,42 @@ int MorphPointerSubstitution(AActor* from, AActor* to) return false; } + // [MC] Had to move this here since ObtainInventory was also moved as well. Should be called + // before any transference of items since that's what was intended when introduced. + if (!from->alternative) // Morphing into + { + { + IFVIRTUALPTR(from, AActor, PreMorph) + { + VMValue params[] = { from, to, false }; + VMCall(func, params, 3, nullptr, 0); + } + } + { + IFVIRTUALPTR(to, AActor, PreMorph) + { + VMValue params[] = { to, from, true }; + VMCall(func, params, 3, nullptr, 0); + } + } + } + else // Unmorphing back + { + { + IFVIRTUALPTR(from, AActor, PreUnmorph) + { + VMValue params[] = { from, to, false }; + VMCall(func, params, 3, nullptr, 0); + } + } + { + IFVIRTUALPTR(to, AActor, PreUnmorph) + { + VMValue params[] = { to, from, true }; + VMCall(func, params, 3, nullptr, 0); + } + } + } // Since the check is good, move the inventory items over. This should always be done when // morphing to emulate Heretic/Hexen's behavior since those stored the inventory in their // player structs. diff --git a/wadsrc/static/zscript/actors/morph.zs b/wadsrc/static/zscript/actors/morph.zs index 9cd21287a..5ebbb59f0 100644 --- a/wadsrc/static/zscript/actors/morph.zs +++ b/wadsrc/static/zscript/actors/morph.zs @@ -99,6 +99,7 @@ extend class Actor } // [MC] Called when an actor morphs, on both the previous form (!current) and present form (current). + // Due to recent changes, these are now called internally instead of within the virtuals. virtual void PreMorph(Actor mo, bool current) {} virtual void PostMorph(Actor mo, bool current) {} virtual void PreUnmorph(Actor mo, bool current) {} diff --git a/wadsrc/static/zscript/actors/player/player_morph.zs b/wadsrc/static/zscript/actors/player/player_morph.zs index 25858dd7c..435d61cdf 100644 --- a/wadsrc/static/zscript/actors/player/player_morph.zs +++ b/wadsrc/static/zscript/actors/player/player_morph.zs @@ -129,9 +129,6 @@ extend class PlayerPawn return false; } - PreMorph(morphed, false); - morphed.PreMorph(self, true); - morphed.EndAllPowerupEffects(); if ((style & MRF_TRANSFERTRANSLATION) && !morphed.bDontTranslate) @@ -259,9 +256,6 @@ extend class PlayerPawn if (!MorphInto(alt)) return false; - PreUnmorph(alt, false); // This body's about to be left. - alt.PreUnmorph(self, true); // This one's about to become current. - alt.EndAllPowerupEffects(); // Remove the morph power if the morph is being undone prematurely. From 02305f02b94da5767d620855a1deef72aac42c41 Mon Sep 17 00:00:00 2001 From: dpjudas Date: Fri, 15 Mar 2024 09:41:25 +0100 Subject: [PATCH 66/84] Turn on the output limiter --- src/common/audio/sound/oalsound.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/common/audio/sound/oalsound.cpp b/src/common/audio/sound/oalsound.cpp index 511a89fbd..8b20fb9c1 100644 --- a/src/common/audio/sound/oalsound.cpp +++ b/src/common/audio/sound/oalsound.cpp @@ -598,6 +598,7 @@ OpenALSoundRenderer::OpenALSoundRenderer() ALC.EXT_disconnect = !!alcIsExtensionPresent(Device, "ALC_EXT_disconnect"); ALC.SOFT_HRTF = !!alcIsExtensionPresent(Device, "ALC_SOFT_HRTF"); ALC.SOFT_pause_device = !!alcIsExtensionPresent(Device, "ALC_SOFT_pause_device"); + ALC.SOFT_output_limiter = !!alcIsExtensionPresent(Device, "ALC_SOFT_output_limiter"); const ALCchar *current = NULL; if(alcIsExtensionPresent(Device, "ALC_ENUMERATE_ALL_EXT")) @@ -634,6 +635,11 @@ OpenALSoundRenderer::OpenALSoundRenderer() else attribs.Push(ALC_DONT_CARE_SOFT); } + if(ALC.SOFT_output_limiter) + { + attribs.Push(ALC_OUTPUT_LIMITER_SOFT); + attribs.Push(ALC_TRUE); + } // Other attribs..? attribs.Push(0); From 35f66c5cc2082cdd01c4af1039fd4f8b6e179485 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Mon, 10 Jun 2024 16:54:38 -0300 Subject: [PATCH 67/84] add COMPATF2_NOACSARGCHECK to disable ACS function argument count checks --- src/doomdef.h | 1 + src/gamedata/g_mapinfo.cpp | 1 + src/maploader/compatibility.cpp | 1 + src/playsim/p_acs.cpp | 8 +++++++- 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/doomdef.h b/src/doomdef.h index 811b4fa5e..f1f4f352e 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -242,6 +242,7 @@ enum : unsigned int COMPATF2_NOMBF21 = 1 << 14, // disable MBF21 features that may clash with certain maps COMPATF2_VOODOO_ZOMBIES = 1 << 15, // [RL0] allow playerinfo, playerpawn, and voodoo health to all be different, and skip killing the player's mobj if a voodoo doll dies to allow voodoo zombies COMPATF2_FDTELEPORT = 1 << 16, // Emulate Final Doom's teleporter z glitch. + COMPATF2_NOACSARGCHECK = 1 << 17, // Disable arg count checking for ACS }; diff --git a/src/gamedata/g_mapinfo.cpp b/src/gamedata/g_mapinfo.cpp index 0e6a5fe6f..748d7cacd 100644 --- a/src/gamedata/g_mapinfo.cpp +++ b/src/gamedata/g_mapinfo.cpp @@ -1867,6 +1867,7 @@ MapFlagHandlers[] = { "compat_stayonlift", MITYPE_COMPATFLAG, 0, COMPATF2_STAYONLIFT }, { "compat_nombf21", MITYPE_COMPATFLAG, 0, COMPATF2_NOMBF21 }, { "compat_voodoozombies", MITYPE_COMPATFLAG, 0, COMPATF2_VOODOO_ZOMBIES }, + { "compat_noacsargcheck", MITYPE_COMPATFLAG, 0, COMPATF2_NOACSARGCHECK }, { "cd_start_track", MITYPE_EATNEXT, 0, 0 }, { "cd_end1_track", MITYPE_EATNEXT, 0, 0 }, { "cd_end2_track", MITYPE_EATNEXT, 0, 0 }, diff --git a/src/maploader/compatibility.cpp b/src/maploader/compatibility.cpp index 7caddc90a..1ba18d444 100644 --- a/src/maploader/compatibility.cpp +++ b/src/maploader/compatibility.cpp @@ -174,6 +174,7 @@ static FCompatOption Options[] = { "nombf21", COMPATF2_NOMBF21, SLOT_COMPAT2 }, { "voodoozombies", COMPATF2_VOODOO_ZOMBIES, SLOT_COMPAT2 }, { "fdteleport", COMPATF2_FDTELEPORT, SLOT_COMPAT2 }, + { "noacsargcheck", COMPATF2_NOACSARGCHECK, SLOT_COMPAT2 }, { NULL, 0, 0 } }; diff --git a/src/playsim/p_acs.cpp b/src/playsim/p_acs.cpp index b464ed2a5..1d4e90d1e 100644 --- a/src/playsim/p_acs.cpp +++ b/src/playsim/p_acs.cpp @@ -5323,7 +5323,13 @@ int DLevelScript::SwapActorTeleFog(AActor *activator, int tid) } // Macro for CallFunction. Checks passed number of arguments with minimum required. Sets needCount and returns if not enough. -#define MIN_ARG_COUNT(minCount) do { if (argCount < minCount) { needCount = minCount; return 0; } } while(0) +#define MIN_ARG_COUNT(minCount) \ + do { \ + if (argCount < minCount && !(Level->i_compatflags2 & COMPATF2_NOACSARGCHECK)) { \ + needCount = minCount; \ + return 0; \ + } \ + } while(0) int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args, int &needCount) { From ddbf90389b34c926aee11dea92f8cf0787198f74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Tue, 11 Jun 2024 00:28:19 -0300 Subject: [PATCH 68/84] add total chaos retro and full maps to compatibility.txt --- wadsrc/static/compatibility.txt | 47 +++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/wadsrc/static/compatibility.txt b/wadsrc/static/compatibility.txt index f8c3fe453..21946aa17 100644 --- a/wadsrc/static/compatibility.txt +++ b/wadsrc/static/compatibility.txt @@ -337,3 +337,50 @@ BA2247ED1465C8107192AC4215B2A5F3 // saturnia.wad map10 { fdteleport } + +// Total Chaos Directors Cut 1.40 +1C9D1306F76EA85558C4BD3BC4C7363C // TITLEMAP - retro & full +5138C10892976F7F8D58E73DF9BD1D35 // MADNESS - retro +EA96F1D692B354B2388F34CD9F0E4CDC // MADNESS - full +F7658930D904959FF43BE0A374E1E356 // MAP01 - retro & full +7C5508701E4AC3D1A00985409EC45EFD // NG1 - retro +C4C2CBACCF08F68AFC341557AEE6A727 // NG2 - retro +37853C2D108A56241E51C785CF0857D4 // NG3 - retro +0B14A4C8223F410816292E7EC578C625 // NG4 - retro +04F3D083D787DE15ACE8661163A6CA14 // NG5 - retro +F52D8B176EEFD374F342F3D9B3DEFC61 // NG6 - retro +A4D6321677AA6E7BA5CD93B39D1D063B // NG1 - full +3B4BAD71CFD7C9C1B860FB66363AEDF2 // NG2 - full +DD660C6E6E3F6F7A615D7234B7A56F59 // NG3 - full +74C68D18E6BD94B386163C4F672D3BFD // NG4 - full +835052B4078B33206675A4BB240333C8 // NG5 - full +0D3A15105CC16BCA0D06CA864AF0B58D // NG6 - full +0E186784223C02A19420BB49081FB734 // NG7 - retro & full +B57F6841E4E5C3989AA58ADDE9812762 // NGD1 - retro +A979225DED3F99E22B50FC6D9CE0355F // NGD2 - retro +95CE0EA31B85BA4D65A189B2D86D69A3 // NGD3 - retro +C1DB8E3B014A548383FDF95D999DF948 // NGD1 - full +6DB1AF715DA54226DC8D958B07FEC7DA // NGD2 - full +E6386D98F733E8D965865859E6056AFA // NGD3 - full +62958B31FB86C109B91BF2DDB9E93D2E // REGRESS - retro +84B499C6179E845265DF4BBF0D3AD361 // RESOLVE - retro +CC4D0C838C0EC5F710E220F3D77A1509 // SURFACE - retro +9FB4164A268007D7D1A630A4460C1CBB // ARRIVAL - retro +0F6AFE40771DCF448C77B6028CB53336 // REGRESS - full +B6E841EC4E5B45D90E3D4CFF805D192E // RESOLVE - full +80098CA75B3FCDE714E10832A8A08185 // SURFACE - full +EF8AA935168FED4393D68DAE04613106 // ARRIVAL - full +60C9D10D3FFDEF25E3131839FC50E1AD // CHAOS - retro +37325C08B6466A1760CA25D0D4176A64 // CROSS - retro +4F032EA6B61A5A42B1B6A7EDC8D5667B // CHAOS - full +D08C3FED35FE0489CFFAB6088FE79B3A // CROSS - full +859662ADA3A4CF634E8B7CE32B8ACB80 // CTEST - retro & full +1A3D2981D32783FED2BE7BA1587809E5 // DECAY - retro +2903FAAB2FBCD516F0559F5799EEEF14 // DECAY - full +A7898E72ED8D2C679DF18D6BC5DCC485 // FINALE - retro +EBD9BB5E7719F6E5042F12B3AE670104 // FORGOT - retro +A318D63145AA0A454475FBE426567896 // FINALE - full +C58AA89A5ACDC7F16BDA68428E31C555 // FORGOT - full +{ + noacsargcheck +} From a82e3b9dfe627b2981694f4c7ba33270c3c18d8d Mon Sep 17 00:00:00 2001 From: MrRaveYard <29225776+MrRaveYard@users.noreply.github.com> Date: Tue, 25 Jun 2024 21:51:48 +0200 Subject: [PATCH 69/84] Add missing GC write barrier --- src/common/objects/dobject.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/common/objects/dobject.cpp b/src/common/objects/dobject.cpp index 4ba504738..e124a975c 100644 --- a/src/common/objects/dobject.cpp +++ b/src/common/objects/dobject.cpp @@ -330,6 +330,7 @@ void DObject::Destroy () } OnDestroy(); ObjectFlags = (ObjectFlags & ~OF_Fixed) | OF_EuthanizeMe; + GC::WriteBarrier(this); } DEFINE_ACTION_FUNCTION(DObject, Destroy) From 10d0f94972a6da8b4482ab46b615d9f5b497420a Mon Sep 17 00:00:00 2001 From: Boondorl Date: Sun, 26 May 2024 17:21:58 -0400 Subject: [PATCH 70/84] Misc network fixes Fixed missing teleport specials when predicting. Added rubberband limit; if too far away from the predicted position, will instead instantly snap the player's view to their new spot. Deprecated cl_noprediction; this was pointless as you'd never not want to predict your position/angles. Fixed angle targets not being backed up. Fixed oldbuttons not being set. Updated menu --- src/playsim/p_spec.cpp | 4 +++- src/playsim/p_user.cpp | 43 +++++++++++++++++++++++++------------ src/rendering/r_utility.cpp | 2 -- wadsrc/static/menudef.txt | 5 ++--- 4 files changed, 34 insertions(+), 20 deletions(-) diff --git a/src/playsim/p_spec.cpp b/src/playsim/p_spec.cpp index c0bfca34a..ba2036971 100644 --- a/src/playsim/p_spec.cpp +++ b/src/playsim/p_spec.cpp @@ -384,7 +384,9 @@ bool P_PredictLine(line_t *line, AActor *mo, int side, int activationType) // Only predict a very specifc section of specials if (line->special != Teleport_Line && - line->special != Teleport) + line->special != Teleport && + line->special != Teleport_NoFog && + line->special != Teleport_NoStop) { return false; } diff --git a/src/playsim/p_user.cpp b/src/playsim/p_user.cpp index 924ad47a8..fefb0f943 100644 --- a/src/playsim/p_user.cpp +++ b/src/playsim/p_user.cpp @@ -101,9 +101,9 @@ static FRandom pr_skullpop ("SkullPop"); CVAR(Bool, sv_singleplayerrespawn, false, CVAR_SERVERINFO | CVAR_CHEAT) // Variables for prediction -CVAR (Bool, cl_noprediction, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR(Bool, cl_predict_specials, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) // Deprecated +CVAR(Bool, cl_noprediction, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CVAR(Float, cl_predict_lerpscale, 0.05f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CVAR(Float, cl_predict_lerpthreshold, 2.00f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) @@ -124,6 +124,11 @@ CUSTOM_CVAR(Float, cl_rubberband_minmove, 20.0f, CVAR_ARCHIVE | CVAR_GLOBALCONFI if (self < 0.1f) self = 0.1f; } +CUSTOM_CVAR(Float, cl_rubberband_limit, 756.0f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (self < 0.0f) + self = 0.0f; +} ColorSetList ColorSets; PainFlashList PainFlashes; @@ -353,6 +358,7 @@ void player_t::CopyFrom(player_t &p, bool copyPSP) MUSINFOactor = p.MUSINFOactor; MUSINFOtics = p.MUSINFOtics; SoundClass = p.SoundClass; + angleOffsetTargets = p.angleOffsetTargets; if (copyPSP) { // This needs to transfer ownership completely. @@ -1422,8 +1428,7 @@ void P_PredictPlayer (player_t *player) { int maxtic; - if (cl_noprediction || - singletics || + if (singletics || demoplayback || player->mo == NULL || player != player->mo->Level->GetConsolePlayer() || @@ -1497,7 +1502,7 @@ void P_PredictPlayer (player_t *player) // This essentially acts like a mini P_Ticker where only the stuff relevant to the client is actually // called. Call order is preserved. - bool rubberband = false; + bool rubberband = false, rubberbandLimit = false; DVector3 rubberbandPos = {}; const bool canRubberband = LastPredictedTic >= 0 && cl_rubberband_scale > 0.0f && cl_rubberband_scale < 1.0f; const double rubberbandThreshold = max(cl_rubberband_minmove, cl_rubberband_threshold); @@ -1521,9 +1526,11 @@ void P_PredictPlayer (player_t *player) { rubberband = true; rubberbandPos = player->mo->Pos(); + rubberbandLimit = cl_rubberband_limit > 0.0f && dist > cl_rubberband_limit * cl_rubberband_limit; } } + player->oldbuttons = player->cmd.ucmd.buttons; player->cmd = localcmds[i % LOCALCMDTICS]; player->mo->ClearInterpolation(); player->mo->ClearFOVInterpolation(); @@ -1533,21 +1540,29 @@ void P_PredictPlayer (player_t *player) if (rubberband) { - R_ClearInterpolationPath(); - player->mo->renderflags &= ~RF_NOINTERPOLATEVIEW; - DPrintf(DMSG_NOTIFY, "Prediction mismatch at (%.3f, %.3f, %.3f)\nExpected: (%.3f, %.3f, %.3f)\nCorrecting to (%.3f, %.3f, %.3f)\n", LastPredictedPosition.X, LastPredictedPosition.Y, LastPredictedPosition.Z, rubberbandPos.X, rubberbandPos.Y, rubberbandPos.Z, player->mo->X(), player->mo->Y(), player->mo->Z()); - DVector3 snapPos = {}; - P_LerpCalculate(player->mo, LastPredictedPosition, snapPos, cl_rubberband_scale, cl_rubberband_threshold, cl_rubberband_minmove); - player->mo->PrevPortalGroup = LastPredictedPortalGroup; - player->mo->Prev = LastPredictedPosition; - const double zOfs = player->viewz - player->mo->Z(); - player->mo->SetXYZ(snapPos); - player->viewz = snapPos.Z + zOfs; + if (rubberbandLimit) + { + // If too far away, instantly snap the player's view to their correct position. + player->mo->renderflags |= RF_NOINTERPOLATEVIEW; + } + else + { + R_ClearInterpolationPath(); + player->mo->renderflags &= ~RF_NOINTERPOLATEVIEW; + + DVector3 snapPos = {}; + P_LerpCalculate(player->mo, LastPredictedPosition, snapPos, cl_rubberband_scale, cl_rubberband_threshold, cl_rubberband_minmove); + player->mo->PrevPortalGroup = LastPredictedPortalGroup; + player->mo->Prev = LastPredictedPosition; + const double zOfs = player->viewz - player->mo->Z(); + player->mo->SetXYZ(snapPos); + player->viewz = snapPos.Z + zOfs; + } } // This is intentionally done after rubberbanding starts since it'll automatically smooth itself towards diff --git a/src/rendering/r_utility.cpp b/src/rendering/r_utility.cpp index b78cf955d..2a5d95586 100644 --- a/src/rendering/r_utility.cpp +++ b/src/rendering/r_utility.cpp @@ -441,7 +441,6 @@ void R_Shutdown () //========================================================================== //CVAR (Int, tf, 0, 0) -EXTERN_CVAR (Bool, cl_noprediction) bool P_NoInterpolation(player_t const *player, AActor const *actor) { @@ -455,7 +454,6 @@ bool P_NoInterpolation(player_t const *player, AActor const *actor) && player->mo->reactiontime == 0 && !NoInterpolateView && !paused - && (!netgame || !cl_noprediction) && !LocalKeyboardTurner; } diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index c9535ff0c..0d099afb6 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -2363,10 +2363,9 @@ OptionMenu NetworkOptions protected { Title "$NETMNU_TITLE" StaticText "$NETMNU_LOCALOPTIONS", 1 - Option "$NETMNU_MOVEPREDICTION", "cl_noprediction", "OffOn" Option "$NETMNU_LINESPECIALPREDICTION", "cl_predict_specials", "OnOff" - Slider "$NETMNU_PREDICTIONLERPSCALE", "cl_predict_lerpscale", 0.0, 0.5, 0.05, 2 - Slider "$NETMNU_LERPTHRESHOLD", "cl_predict_lerpthreshold", 0.1, 16.0, 0.1 + Slider "$NETMNU_PREDICTIONLERPSCALE", "cl_rubberband_scale", 0.0, 1.0, 0.05, 2 + Slider "$NETMNU_LERPTHRESHOLD", "cl_rubberband_threshold", 0.0, 256.0, 8.0 StaticText " " StaticText "$NETMNU_HOSTOPTIONS", 1 Option "$NETMNU_EXTRATICS", "net_extratic", "ExtraTicMode" From 7ddd4ec245c8aec08f5a219e015c0d590dc26f56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Sun, 7 Jul 2024 10:54:49 -0300 Subject: [PATCH 71/84] handle freeze in decoupled animations --- src/playsim/actor.h | 2 +- src/playsim/p_actionfunctions.cpp | 8 +++++--- src/playsim/p_mobj.cpp | 14 +++++++++++++- src/r_data/models.cpp | 4 ++-- 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/playsim/actor.h b/src/playsim/actor.h index ece9be8e0..4a0a3cf14 100644 --- a/src/playsim/actor.h +++ b/src/playsim/actor.h @@ -710,7 +710,7 @@ struct AnimOverride int flags = ANIMOVERRIDE_NONE; float framerate; double startTic; // when the current animation started (changing framerates counts as restarting) (or when animation starts if interpolating from previous animation) - double switchTic; // when the animation was changed -- where to interpolate the switch from + double switchOffset; // when the animation was changed -- where to interpolate the switch from }; struct ModelOverride diff --git a/src/playsim/p_actionfunctions.cpp b/src/playsim/p_actionfunctions.cpp index b6090213b..4a647af4e 100644 --- a/src/playsim/p_actionfunctions.cpp +++ b/src/playsim/p_actionfunctions.cpp @@ -5214,18 +5214,20 @@ void SetAnimationInternal(AActor * self, FName animName, double framerate, int s self->modelData->curAnim.startFrame = startFrame < 0 ? animStart : animStart + startFrame; self->modelData->curAnim.loopFrame = loopFrame < 0 ? animStart : animStart + loopFrame; self->modelData->curAnim.flags = (flags&SAF_LOOP) ? ANIMOVERRIDE_LOOP : 0; - self->modelData->curAnim.switchTic = tic; self->modelData->curAnim.framerate = (float)framerate; if(!(flags & SAF_INSTANT)) { self->modelData->prevAnim.startFrame = getCurrentFrame(self->modelData->prevAnim, tic); - self->modelData->curAnim.startTic = floor(tic) + interpolateTics; + int startTic = floor(tic) + interpolateTics; + self->modelData->curAnim.startTic = startTic; + self->modelData->curAnim.switchOffset = startTic - tic; } else { self->modelData->curAnim.startTic = tic; + self->modelData->curAnim.switchOffset = 0; } } @@ -5274,7 +5276,7 @@ void SetAnimationFrameRateInternal(AActor * self, double framerate, double ticFr self->modelData->curAnim.startFrame = frame; self->modelData->curAnim.startTic = tic; - self->modelData->curAnim.switchTic = tic; + self->modelData->curAnim.switchOffset = 0; self->modelData->curAnim.framerate = (float)framerate; } diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index 728f1a56d..3f08d3a39 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -1453,7 +1453,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, struct AnimOverride &a arc("flags", ao.flags); arc("framerate", ao.framerate); arc("startTic", ao.startTic); - arc("switchTic", ao.switchTic); + arc("switchOffset", ao.switchOffset); arc.EndObject(); return arc; } @@ -3861,6 +3861,12 @@ void AActor::Tick () { special2++; } + + if(flags9 & MF9_DECOUPLEDANIMATIONS && modelData && !(modelData->curAnim.flags & ANIMOVERRIDE_NONE)) + { + modelData->curAnim.startTic += 1; + } + return; } @@ -3908,6 +3914,12 @@ void AActor::Tick () { special2++; } + + if(flags9 & MF9_DECOUPLEDANIMATIONS && modelData && !(modelData->curAnim.flags & ANIMOVERRIDE_NONE)) + { + modelData->curAnim.startTic += 1; + } + return; } diff --git a/src/r_data/models.cpp b/src/r_data/models.cpp index f63a15ef6..abf1bf179 100644 --- a/src/r_data/models.cpp +++ b/src/r_data/models.cpp @@ -316,13 +316,13 @@ void RenderFrameModels(FModelRenderer *renderer, FLevelLocals *Level, const FSpr if(actor->modelData && !(actor->modelData->curAnim.flags & ANIMOVERRIDE_NONE)) { double tic = actor->Level->totaltime; - if ((ConsoleState == c_up || ConsoleState == c_rising) && (menuactive == MENU_Off || menuactive == MENU_OnNoPause) && !Level->isFrozen()) + if ((ConsoleState == c_up || ConsoleState == c_rising) && (menuactive == MENU_Off || menuactive == MENU_OnNoPause) && !actor->isFrozen()) { tic += I_GetTimeFrac(); } if(actor->modelData->curAnim.startTic > tic) { - inter = (tic - actor->modelData->curAnim.switchTic) / (actor->modelData->curAnim.startTic - actor->modelData->curAnim.switchTic); + inter = (tic - (actor->modelData->curAnim.startTic - actor->modelData->curAnim.switchOffset)) / actor->modelData->curAnim.switchOffset; double nextFrame = actor->modelData->curAnim.startFrame; From 0caa036a96a24f47964cddb57906d5b51f71ac1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Tue, 9 Jul 2024 11:51:31 -0300 Subject: [PATCH 72/84] fix compilation --- src/r_data/models.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/r_data/models.cpp b/src/r_data/models.cpp index abf1bf179..866e538c3 100644 --- a/src/r_data/models.cpp +++ b/src/r_data/models.cpp @@ -44,6 +44,7 @@ #include "texturemanager.h" #include "modelrenderer.h" #include "actor.h" +#include "actorinlines.h" #ifdef _MSC_VER From 566ad81cc097b8b5c4857976e81bcc7573f861c0 Mon Sep 17 00:00:00 2001 From: nashmuhandes Date: Fri, 12 Jul 2024 20:29:48 +0800 Subject: [PATCH 73/84] Rebalance default audio mix --- src/common/audio/music/i_music.cpp | 2 +- src/common/menu/menu.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/audio/music/i_music.cpp b/src/common/audio/music/i_music.cpp index b30a27f13..4570de82e 100644 --- a/src/common/audio/music/i_music.cpp +++ b/src/common/audio/music/i_music.cpp @@ -70,7 +70,7 @@ int nomusic = 0; // Maximum volume of MOD/stream music. //========================================================================== -CUSTOM_CVARD(Float, snd_musicvolume, 1.0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG, "controls music volume") +CUSTOM_CVARD(Float, snd_musicvolume, 0.65, CVAR_ARCHIVE|CVAR_GLOBALCONFIG, "controls music volume") { if (self < 0.f) self = 0.f; diff --git a/src/common/menu/menu.cpp b/src/common/menu/menu.cpp index ee9a1277e..1cff6a8b5 100644 --- a/src/common/menu/menu.cpp +++ b/src/common/menu/menu.cpp @@ -63,7 +63,7 @@ static ScaleOverrider *CurrentScaleOverrider; CVAR (Int, m_showinputgrid, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CVAR(Bool, m_blockcontrollers, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) -CVAR (Float, snd_menuvolume, 0.6f, CVAR_ARCHIVE) +CVAR (Float, snd_menuvolume, 0.8f, CVAR_ARCHIVE) CVAR(Int, m_use_mouse, 1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR(Int, m_show_backbutton, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR(Bool, m_cleanscale, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) From f5ab26a45b42c33e3b8f89a81a0e43d6e589b55c Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Fri, 12 Jul 2024 19:50:18 +0200 Subject: [PATCH 74/84] Fix directory crash for filenames that appear elsewhere in the path --- src/common/filesystem/source/file_directory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/filesystem/source/file_directory.cpp b/src/common/filesystem/source/file_directory.cpp index 3193e00b1..1999e9c4c 100644 --- a/src/common/filesystem/source/file_directory.cpp +++ b/src/common/filesystem/source/file_directory.cpp @@ -106,7 +106,7 @@ int FDirectory::AddDirectory(const char *dirpath, LumpFilterInfo* filter, FileSy if (mBasePath == nullptr) { // extract the base path from the first entry to cover changes made in ScanDirectory. - auto full = entry.FilePath.find(entry.FilePathRel); + auto full = entry.FilePath.rfind(entry.FilePathRel); std::string path(entry.FilePath, 0, full); mBasePath = stringpool->Strdup(path.c_str()); } From 9d78eb5aa0231197b3b7399ae13aaf6741384a02 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Fri, 12 Jul 2024 19:50:18 +0200 Subject: [PATCH 75/84] Fix directory crash for filenames that appear elsewhere in the path --- src/common/filesystem/source/file_directory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/filesystem/source/file_directory.cpp b/src/common/filesystem/source/file_directory.cpp index 0b9b7cd45..ca87fd9ea 100644 --- a/src/common/filesystem/source/file_directory.cpp +++ b/src/common/filesystem/source/file_directory.cpp @@ -106,7 +106,7 @@ int FDirectory::AddDirectory(const char *dirpath, LumpFilterInfo* filter, FileSy if (mBasePath == nullptr) { // extract the base path from the first entry to cover changes made in ScanDirectory. - auto full = entry.FilePath.find(entry.FilePathRel); + auto full = entry.FilePath.rfind(entry.FilePathRel); std::string path(entry.FilePath, 0, full); mBasePath = stringpool->Strdup(path.c_str()); } From 314ec1030c6c19e0fdc1adc8a0841feaa2cf2287 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Fri, 12 Jul 2024 20:04:50 +0200 Subject: [PATCH 76/84] Fix level mesh crash --- src/rendering/hwrenderer/doom_levelmesh.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/rendering/hwrenderer/doom_levelmesh.cpp b/src/rendering/hwrenderer/doom_levelmesh.cpp index 34b2952f7..59e9a8bfa 100644 --- a/src/rendering/hwrenderer/doom_levelmesh.cpp +++ b/src/rendering/hwrenderer/doom_levelmesh.cpp @@ -618,6 +618,10 @@ void DoomLevelMesh::CreateFlatSurface(HWFlatDispatcher& disp, MeshBuilder& state { for (HWFlat& flatpart : list) { + state.mSortedLists.clear(); + state.mVertices.Clear(); + state.mIndexes.Clear(); + if (isSky) { state.SetEffect(EFF_PORTAL); @@ -661,9 +665,6 @@ void DoomLevelMesh::CreateFlatSurface(HWFlatDispatcher& disp, MeshBuilder& state foundDraw = true; break; } - state.mSortedLists.clear(); - state.mVertices.Clear(); - state.mIndexes.Clear(); if (!foundDraw) continue; From 3ae77ef6c4d18338d5db0bae471ffea18b77ca1d Mon Sep 17 00:00:00 2001 From: dpjudas Date: Sat, 20 Jul 2024 05:45:28 +0200 Subject: [PATCH 77/84] Fix crash when loading maps with sectors with no subsectors --- src/rendering/hwrenderer/doom_levelmesh.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rendering/hwrenderer/doom_levelmesh.cpp b/src/rendering/hwrenderer/doom_levelmesh.cpp index 59e9a8bfa..a1e4fc0db 100644 --- a/src/rendering/hwrenderer/doom_levelmesh.cpp +++ b/src/rendering/hwrenderer/doom_levelmesh.cpp @@ -339,7 +339,7 @@ void DoomLevelMesh::CreateSurfaces(FLevelLocals& doomMap) for (unsigned int i = 0; i < doomMap.sectors.Size(); i++) { sector_t* sector = &doomMap.sectors[i]; - if (sector->subsectors[0]->flags & SSECF_POLYORG) + if (sector->subsectorcount == 0 || sector->subsectors[0]->flags & SSECF_POLYORG) continue; UpdateFlat(doomMap, i); } From f671018700e1e71ad2dda9ccdbf3fe62bb9efb49 Mon Sep 17 00:00:00 2001 From: nashmuhandes Date: Sun, 21 Jul 2024 00:26:58 +0800 Subject: [PATCH 78/84] Clean up lightmap stuff in the namedef --- src/maploader/udmf.cpp | 4 ++-- src/namedef_custom.h | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/maploader/udmf.cpp b/src/maploader/udmf.cpp index db34030de..725b95b91 100644 --- a/src/maploader/udmf.cpp +++ b/src/maploader/udmf.cpp @@ -1166,7 +1166,7 @@ class UDMFParser : public UDMFParserBase ld->healthgroup = CheckInt(key); break; - case NAME_lm_sampledist_line: + case NAME_lm_sampledist: case NAME_lm_sampledist_top: case NAME_lm_sampledist_mid: case NAME_lm_sampledist_bot: @@ -1516,7 +1516,7 @@ class UDMFParser : public UDMFParserBase sd->Flags |= WALLF_EXTCOLOR; break; - case NAME_lm_sampledist_line: + case NAME_lm_sampledist: case NAME_lm_sampledist_top: case NAME_lm_sampledist_mid: case NAME_lm_sampledist_bot: diff --git a/src/namedef_custom.h b/src/namedef_custom.h index 61bf9d261..59752245b 100644 --- a/src/namedef_custom.h +++ b/src/namedef_custom.h @@ -854,7 +854,7 @@ xx(Sky) xx(Pagename) // Lightmap/ZDRay keywords -xx(lm_sampledist_line) +xx(lm_sampledist) xx(lm_sampledist_top) xx(lm_sampledist_mid) xx(lm_sampledist_bot) @@ -862,7 +862,6 @@ xx(lm_sampledist_floor) xx(lm_sampledist_ceiling) xx(lm_dynamic) xx(lm_suncolor) -xx(lm_sampledist) // Light keywords xx(SoftShadowRadius) From 519dd16c9a2f351fd9e59d6a2f826680f9e80cbd Mon Sep 17 00:00:00 2001 From: Blue Shadow Date: Sun, 28 Jul 2024 08:07:43 +0300 Subject: [PATCH 79/84] - fixed alignment issue in SBARINFO's DrawString command --- src/g_statusbar/sbarinfo_commands.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/g_statusbar/sbarinfo_commands.cpp b/src/g_statusbar/sbarinfo_commands.cpp index bbb3bc90f..73462f384 100644 --- a/src/g_statusbar/sbarinfo_commands.cpp +++ b/src/g_statusbar/sbarinfo_commands.cpp @@ -924,6 +924,7 @@ class CommandDrawString : public SBarInfoCommand break; default: str = GStrings.localize(label.GetChars()); + RealignString(); break; } } From d697eafbe16d8f76e01759ac033451386dfa3bb8 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Mon, 29 Jul 2024 00:19:56 -0400 Subject: [PATCH 80/84] Fixed subnormal float viewpos values breaking rendering --- src/common/utility/vectors.h | 39 ++++++++++++++++++++++++++++++++++++ src/playsim/actor.h | 3 +++ 2 files changed, 42 insertions(+) diff --git a/src/common/utility/vectors.h b/src/common/utility/vectors.h index 77e41d2a9..47eb59793 100644 --- a/src/common/utility/vectors.h +++ b/src/common/utility/vectors.h @@ -1019,6 +1019,45 @@ struct TVector4 } }; +inline void ZeroSubnormalsF(double& num) +{ + if (fabs(num) < FLT_MIN) num = 0; +} + +inline void ZeroSubnormals(double& num) +{ + if (fabs(num) < DBL_MIN) num = 0; +} + +inline void ZeroSubnormals(float& num) +{ + if (fabsf(num) < FLT_MIN) num = 0; +} + +template +inline void ZeroSubnormals(TVector2& vec) +{ + ZeroSubnormals(vec.X); + ZeroSubnormals(vec.Y); +} + +template +inline void ZeroSubnormals(TVector3& vec) +{ + ZeroSubnormals(vec.X); + ZeroSubnormals(vec.Y); + ZeroSubnormals(vec.Z); +} + +template +inline void ZeroSubnormals(TVector4& vec) +{ + ZeroSubnormals(vec.X); + ZeroSubnormals(vec.Y); + ZeroSubnormals(vec.Z); + ZeroSubnormals(vec.W); +} + template struct TMatrix3x3 { diff --git a/src/playsim/actor.h b/src/playsim/actor.h index 4a0a3cf14..d0ea86cb6 100644 --- a/src/playsim/actor.h +++ b/src/playsim/actor.h @@ -774,6 +774,9 @@ class DViewPosition : public DObject void Set(DVector3 &off, int f = -1) { + ZeroSubnormalsF(off.X); + ZeroSubnormalsF(off.Y); + ZeroSubnormalsF(off.Z); Offset = off; if (f > -1) From 3d3cd8886843335a28d9c54a4876024948db867e Mon Sep 17 00:00:00 2001 From: Boondorl Date: Wed, 31 Jul 2024 01:01:37 -0400 Subject: [PATCH 81/84] Disable effects on Actors set not to render locally These are purely visual --- src/playsim/a_dynlight.cpp | 2 +- src/playsim/dthinker.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/playsim/a_dynlight.cpp b/src/playsim/a_dynlight.cpp index dddb9f54e..6d67d4e1b 100644 --- a/src/playsim/a_dynlight.cpp +++ b/src/playsim/a_dynlight.cpp @@ -255,7 +255,7 @@ void FDynamicLight::Tick() if (owned) { - if (!target->state) + if (!target->state || !target->ShouldRenderLocally()) { Deactivate(); return; diff --git a/src/playsim/dthinker.cpp b/src/playsim/dthinker.cpp index 3214decf3..4229de792 100644 --- a/src/playsim/dthinker.cpp +++ b/src/playsim/dthinker.cpp @@ -132,7 +132,7 @@ void FThinkerCollection::RunThinkers(FLevelLocals *Level) if (dolights) ac->SetDynamicLights(); } // This was merged from P_RunEffects to eliminate the costly duplicate ThinkerIterator loop. - if ((ac->effects || ac->fountaincolor) && !Level->isFrozen()) + if ((ac->effects || ac->fountaincolor) && ac->ShouldRenderLocally() && !Level->isFrozen()) { P_RunEffect(ac, ac->effects); } From 593e1c0225ff4127f80a506bb4631bcc5c842ef3 Mon Sep 17 00:00:00 2001 From: nashmuhandes Date: Wed, 31 Jul 2024 00:41:00 +0800 Subject: [PATCH 82/84] Add SPF_NOMIPMAP to force actor sprites or particles to have no mipmaps. This makes tiny sprites/particles look more crisp and legible in the distance. Mipmapping causes the sprites/particles to have an inconsistent look where they'd sometimes be clearly visible and sometimes less visible depending on camera distance and movement. --- src/playsim/actor.h | 1 + src/playsim/p_effect.h | 1 + src/rendering/hwrenderer/scene/hw_drawstructs.h | 1 + src/rendering/hwrenderer/scene/hw_sprites.cpp | 7 ++++++- src/scripting/thingdef_data.cpp | 1 + wadsrc/static/zscript/constants.zs | 1 + 6 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/playsim/actor.h b/src/playsim/actor.h index d0ea86cb6..fa0e23bf2 100644 --- a/src/playsim/actor.h +++ b/src/playsim/actor.h @@ -501,6 +501,7 @@ enum ActorRenderFlag2 RF2_FLIPSPRITEOFFSETX = 0x0010, RF2_FLIPSPRITEOFFSETY = 0x0020, RF2_CAMFOLLOWSPLAYER = 0x0040, // Matches the cam's base position and angles to the main viewpoint. + RF2_NOMIPMAP = 0x0080, // [Nash] forces no mipmapping on sprites. Useful for tiny sprites that need to remain visually crisp }; // This translucency value produces the closest match to Heretic's TINTTAB. diff --git a/src/playsim/p_effect.h b/src/playsim/p_effect.h index 29f1cb720..5eafdcd4b 100644 --- a/src/playsim/p_effect.h +++ b/src/playsim/p_effect.h @@ -69,6 +69,7 @@ enum EParticleFlags SPF_FACECAMERA = 1 << 11, SPF_NOFACECAMERA = 1 << 12, SPF_ROLLCENTER = 1 << 13, + SPF_NOMIPMAP = 1 << 14, }; class DVisualThinker; diff --git a/src/rendering/hwrenderer/scene/hw_drawstructs.h b/src/rendering/hwrenderer/scene/hw_drawstructs.h index a025c87c9..b364128de 100644 --- a/src/rendering/hwrenderer/scene/hw_drawstructs.h +++ b/src/rendering/hwrenderer/scene/hw_drawstructs.h @@ -393,6 +393,7 @@ class HWSprite TArray *lightlist; DRotator Angles; + bool nomipmap; // force the sprite to have no mipmaps (ensures tiny sprites in the distance stay crisp) void SplitSprite(HWDrawInfo *di, sector_t * frontsector, bool translucent); void PerformSpriteClipAdjustment(AActor *thing, const DVector2 &thingpos, float spriteheight); diff --git a/src/rendering/hwrenderer/scene/hw_sprites.cpp b/src/rendering/hwrenderer/scene/hw_sprites.cpp index 9340839b9..3f595d177 100644 --- a/src/rendering/hwrenderer/scene/hw_sprites.cpp +++ b/src/rendering/hwrenderer/scene/hw_sprites.cpp @@ -221,8 +221,10 @@ void HWSprite::DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent) state.SetFog(0, 0); } + int clampmode = nomipmap ? CLAMP_XY_NOMIP : CLAMP_XY; + uint32_t spritetype = actor? uint32_t(actor->renderflags & RF_SPRITETYPEMASK) : 0; - if (texture) state.SetMaterial(texture, UF_Sprite, (spritetype == RF_FACESPRITE) ? CTF_Expand : 0, CLAMP_XY, translation, OverrideShader); + if (texture) state.SetMaterial(texture, UF_Sprite, (spritetype == RF_FACESPRITE) ? CTF_Expand : 0, clampmode, translation, OverrideShader); else if (!modelframe) state.EnableTexture(false); //SetColor(lightlevel, rel, Colormap, trans); @@ -771,6 +773,8 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t return; } + nomipmap = (thing->renderflags2 & RF2_NOMIPMAP); + // check renderrequired vs ~r_rendercaps, if anything matches we don't support that feature, // check renderhidden vs r_rendercaps, if anything matches we do support that feature and should hide it. if ((!r_debug_disable_vis_filter && !!(thing->RenderRequired & ~r_renderercaps)) || @@ -1325,6 +1329,7 @@ void HWSprite::ProcessParticle(HWDrawInfo *di, particle_t *particle, sector_t *s actor = nullptr; this->particle = particle; fullbright = particle->flags & SPF_FULLBRIGHT; + nomipmap = particle->flags & SPF_NOMIPMAP; if (di->isFullbrightScene()) { diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 997ab78b1..570dd2a4e 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -384,6 +384,7 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG(RF2, FLIPSPRITEOFFSETX, AActor, renderflags2), DEFINE_FLAG(RF2, FLIPSPRITEOFFSETY, AActor, renderflags2), DEFINE_FLAG(RF2, CAMFOLLOWSPLAYER, AActor, renderflags2), + DEFINE_FLAG(RF2, NOMIPMAP, AActor, renderflags2), // Bounce flags DEFINE_FLAG2(BOUNCE_Walls, BOUNCEONWALLS, AActor, BounceFlags), diff --git a/wadsrc/static/zscript/constants.zs b/wadsrc/static/zscript/constants.zs index bd92db9b8..ad77dc8b2 100644 --- a/wadsrc/static/zscript/constants.zs +++ b/wadsrc/static/zscript/constants.zs @@ -718,6 +718,7 @@ enum EParticleFlags SPF_FACECAMERA = 1 << 11, SPF_NOFACECAMERA = 1 << 12, SPF_ROLLCENTER = 1 << 13, + SPF_NOMIPMAP = 1 << 14, SPF_RELATIVE = SPF_RELPOS|SPF_RELVEL|SPF_RELACCEL|SPF_RELANG }; From a0802d566f485c87a1ee430613d17f4cb34dd282 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Wed, 7 Aug 2024 11:11:46 -0400 Subject: [PATCH 83/84] - fix: check if bombsource exists when exploding a projectile with a XF_NOALLIES flag --- src/playsim/p_map.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/playsim/p_map.cpp b/src/playsim/p_map.cpp index 53329b96f..a79f912ae 100644 --- a/src/playsim/p_map.cpp +++ b/src/playsim/p_map.cpp @@ -6169,7 +6169,7 @@ int P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, double continue; //[inkoalawetrust] Don't harm actors friendly to the explosions' source. But do harm the source. - if ((flags & RADF_NOALLIES) && bombsource->IsFriend(thing) && !(thing == bombsource || thing == bombspot)) + if ((flags & RADF_NOALLIES) && bombsource && bombsource->IsFriend(thing) && !(thing == bombsource || thing == bombspot)) continue; if (bombsource && thing != bombsource && bombsource->player && P_ShouldPassThroughPlayer(bombsource, thing)) From 7930ee807d04421ba1033a832d1822b112c46ea4 Mon Sep 17 00:00:00 2001 From: Ashley Miller-Jelfs Date: Thu, 8 Aug 2024 15:03:54 +0930 Subject: [PATCH 84/84] Fix Specular not using Material definition for Glossiness and Level --- wadsrc/static/shaders/scene/lightmodel_specular.glsl | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/wadsrc/static/shaders/scene/lightmodel_specular.glsl b/wadsrc/static/shaders/scene/lightmodel_specular.glsl index b889034ab..a9d99c779 100644 --- a/wadsrc/static/shaders/scene/lightmodel_specular.glsl +++ b/wadsrc/static/shaders/scene/lightmodel_specular.glsl @@ -1,5 +1,5 @@ -vec2 lightAttenuation(int i, vec3 normal, vec3 viewdir, float lightcolorA) +vec2 lightAttenuation(int i, vec3 normal, vec3 viewdir, float lightcolorA, float glossiness, float specularLevel) { vec4 lightpos = lights[i]; vec4 lightspot1 = lights[i+2]; @@ -25,9 +25,6 @@ vec2 lightAttenuation(int i, vec3 normal, vec3 viewdir, float lightcolorA) if (attenuation <= 0.0) return vec2(0.0); - float glossiness = uSpecularMaterial.x; - float specularLevel = uSpecularMaterial.y; - vec3 halfdir = normalize(viewdir + lightdir); float specAngle = clamp(dot(halfdir, normal), 0.0f, 1.0f); float phExp = glossiness * 4.0f; @@ -51,7 +48,7 @@ vec3 ProcessMaterialLight(Material material, vec3 color) for(int i=lightRange.x; i