From f156abcff046609e7750327e4886912bfd128da6 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Sun, 21 Apr 2024 03:04:56 -0400 Subject: [PATCH 01/28] - version 4.12.0 --- src/version.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/version.h b/src/version.h index 722439183..2c772fbaf 100644 --- a/src/version.h +++ b/src/version.h @@ -41,11 +41,11 @@ const char *GetVersionString(); /** Lots of different version numbers **/ -#define VERSIONSTR "4.12pre" +#define VERSIONSTR "4.12.0" // The version as seen in the Windows resource -#define RC_FILEVERSION 4,11,9999,0 -#define RC_PRODUCTVERSION 4,11,9999,0 +#define RC_FILEVERSION 4,12,0,0 +#define RC_PRODUCTVERSION 4,12,0,0 #define RC_PRODUCTVERSION2 VERSIONSTR // These are for content versioning. #define VER_MAJOR 4 From 132a150aa140037d1342485c16454d408d50f522 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Thu, 18 Apr 2024 14:54:43 -0400 Subject: [PATCH 02/28] Added pistol start gameplay option Automatically resets the player's inventory and health when changing maps. --- src/d_main.cpp | 1 + src/doomdef.h | 1 + src/g_level.cpp | 5 +++-- wadsrc/static/menudef.txt | 1 + 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index c5b77942e..c5e83cf58 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -580,6 +580,7 @@ CVAR(Flag, sv_nolocaldrops, dmflags3, DF3_NO_LOCAL_DROPS); CVAR(Flag, sv_nocoopitems, dmflags3, DF3_NO_COOP_ONLY_ITEMS); CVAR(Flag, sv_nocoopthings, dmflags3, DF3_NO_COOP_ONLY_THINGS); CVAR(Flag, sv_rememberlastweapon, dmflags3, DF3_REMEMBER_LAST_WEAP); +CVAR(Flag, sv_pistolstart, dmflags3, DF3_PISTOL_START); //========================================================================== // diff --git a/src/doomdef.h b/src/doomdef.h index 70759a406..98fa88d93 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -186,6 +186,7 @@ enum : unsigned DF3_NO_COOP_ONLY_ITEMS = 1 << 4, // Items that only appear in co-op are disabled DF3_NO_COOP_ONLY_THINGS = 1 << 5, // Any Actor that only appears in co-op is disabled DF3_REMEMBER_LAST_WEAP = 1 << 6, // When respawning in co-op, keep the last used weapon out instead of switching to the best new one. + DF3_PISTOL_START = 1 << 7, // Take player inventory when exiting to the next level. }; // [RH] Compatibility flags. diff --git a/src/g_level.cpp b/src/g_level.cpp index 386df8d09..4fcef5f75 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -776,11 +776,12 @@ void FLevelLocals::ChangeLevel(const char *levelname, int position, int inflags, { if (thiscluster != nextcluster || (thiscluster && !(thiscluster->flags & CLUSTER_HUB))) { - if (nextinfo->flags2 & LEVEL2_RESETINVENTORY) + const bool doReset = dmflags3 & DF3_PISTOL_START; + if (doReset || (nextinfo->flags2 & LEVEL2_RESETINVENTORY)) { inflags |= CHANGELEVEL_RESETINVENTORY; } - if (nextinfo->flags2 & LEVEL2_RESETHEALTH) + if (doReset || (nextinfo->flags2 & LEVEL2_RESETHEALTH)) { inflags |= CHANGELEVEL_RESETHEALTH; } diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index ed0d727c5..7c8359cd5 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -1630,6 +1630,7 @@ OptionMenu GameplayOptions protected StaticText " " Option "$GMPLYMNU_SMARTAUTOAIM", "sv_smartaim", "SmartAim" StaticText " " + Option "$GMPLYMNU_PISTOLSTART", "sv_pistolstart", "YesNo" Option "$GMPLYMNU_FALLINGDAMAGE", "sv_fallingdamage", "FallingDM" Option "$GMPLYMNU_DROPWEAPON", "sv_weapondrop", "YesNo" Option "$GMPLYMNU_DOUBLEAMMO", "sv_doubleammo", "YesNo" From 7f3e01470704bab2aec7bc2d7b7b1fea3cac3313 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Fri, 19 Apr 2024 09:10:31 -0400 Subject: [PATCH 03/28] Exported FTeam getters --- src/gamedata/teaminfo.cpp | 77 ++++++++++++++++++- src/gamedata/teaminfo.h | 4 +- wadsrc/static/zscript/actors/player/player.zs | 13 +++- 3 files changed, 88 insertions(+), 6 deletions(-) diff --git a/src/gamedata/teaminfo.cpp b/src/gamedata/teaminfo.cpp index 3a28da984..1838d1b39 100644 --- a/src/gamedata/teaminfo.cpp +++ b/src/gamedata/teaminfo.cpp @@ -38,6 +38,7 @@ #include "gi.h" #include "teaminfo.h" +#include "texturemanager.h" #include "v_font.h" #include "v_video.h" #include "filesystem.h" @@ -244,7 +245,7 @@ void FTeam::ClearTeams () // //========================================================================== -bool FTeam::IsValidTeam (unsigned int uiTeam) +bool FTeam::IsValidTeam (unsigned int uiTeam) const { if (uiTeam >= Teams.Size ()) return false; @@ -303,7 +304,7 @@ int FTeam::GetTextColor () const // //========================================================================== -FString FTeam::GetLogo () const +const FString& FTeam::GetLogo () const { return m_Logo; } @@ -338,3 +339,75 @@ CCMD (teamlist) DEFINE_GLOBAL(Teams) DEFINE_FIELD_NAMED(FTeam, m_Name, mName) + +static int IsValid(unsigned int id) +{ + return TeamLibrary.IsValidTeam(id); +} + +DEFINE_ACTION_FUNCTION_NATIVE(FTeam, IsValid, IsValid) +{ + PARAM_PROLOGUE; + PARAM_UINT(id); + + ACTION_RETURN_BOOL(TeamLibrary.IsValidTeam(id)); +} + +static int GetPlayerColor(FTeam* self) +{ + return self->GetPlayerColor(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(FTeam, GetPlayerColor, GetPlayerColor) +{ + PARAM_SELF_STRUCT_PROLOGUE(FTeam); + ACTION_RETURN_INT(self->GetPlayerColor()); +} + +static int GetTextColor(FTeam* self) +{ + return self->GetTextColor(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(FTeam, GetTextColor, GetTextColor) +{ + PARAM_SELF_STRUCT_PROLOGUE(FTeam); + ACTION_RETURN_INT(self->GetTextColor()); +} + +static int GetLogo(FTeam* self) +{ + const FString& name = self->GetLogo(); + if (name.IsEmpty()) + return -1; + + return TexMan.CheckForTexture(name.GetChars(), ETextureType::Any).GetIndex(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(FTeam, GetLogo, GetLogo) +{ + PARAM_SELF_STRUCT_PROLOGUE(FTeam); + ACTION_RETURN_INT(GetLogo(self)); +} + +static void GetLogoName(FTeam* self, FString* res) +{ + *res = self->GetLogo(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(FTeam, GetLogoName, GetLogoName) +{ + PARAM_SELF_STRUCT_PROLOGUE(FTeam); + ACTION_RETURN_STRING(self->GetLogo()); +} + +static int AllowsCustomPlayerColor(FTeam* self) +{ + return self->GetAllowCustomPlayerColor(); +} + +DEFINE_ACTION_FUNCTION_NATIVE(FTeam, AllowsCustomPlayerColor, AllowsCustomPlayerColor) +{ + PARAM_SELF_STRUCT_PROLOGUE(FTeam); + ACTION_RETURN_BOOL(self->GetAllowCustomPlayerColor()); +} diff --git a/src/gamedata/teaminfo.h b/src/gamedata/teaminfo.h index 1c84d9b9b..1a3db705c 100644 --- a/src/gamedata/teaminfo.h +++ b/src/gamedata/teaminfo.h @@ -46,12 +46,12 @@ class FTeam public: FTeam (); void ParseTeamInfo (); - bool IsValidTeam (unsigned int uiTeam); + bool IsValidTeam (unsigned int uiTeam) const; const char *GetName () const; int GetPlayerColor () const; int GetTextColor () const; - FString GetLogo () const; + const FString& GetLogo () const; bool GetAllowCustomPlayerColor () const; int m_iPlayerCount; diff --git a/wadsrc/static/zscript/actors/player/player.zs b/wadsrc/static/zscript/actors/player/player.zs index e6c66fa44..65fc28943 100644 --- a/wadsrc/static/zscript/actors/player/player.zs +++ b/wadsrc/static/zscript/actors/player/player.zs @@ -2969,7 +2969,16 @@ struct PlayerSkin native struct Team native { - const NoTeam = 255; - const Max = 16; + const NOTEAM = 255; + const MAX = 16; + native String mName; + + native static bool IsValid(uint teamIndex); + + native Color GetPlayerColor() const; + native int GetTextColor() const; + native TextureID GetLogo() const; + native string GetLogoName() const; + native bool AllowsCustomPlayerColor() const; } From 661b1d128e30be7a16656ea30bf2275f1b9235a1 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Fri, 29 Mar 2024 11:02:46 -0400 Subject: [PATCH 04/28] Added PSpriteTick virtual --- wadsrc/static/zscript/actors/actor.zs | 5 +++++ wadsrc/static/zscript/actors/player/player.zs | 22 ++++++++++++++----- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index 72f441b10..7c52030da 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -509,6 +509,11 @@ class Actor : Thinker native native clearscope void DisableLocalRendering(uint playerNum, bool disable); native ui bool ShouldRenderLocally(); // Only clients get to check this, never the playsim. + // Called when the Actor is being used within a PSprite. This happens before potentially changing PSprite + // state so that any custom actions based on things like player input can be done before moving to the next + // state of something like a weapon. + virtual void PSpriteTick(PSprite psp) {} + // Called by inventory items to see if this actor is capable of touching them. // If true, the item will attempt to be picked up. Useful for things like // allowing morphs to pick up limited items such as keys while preventing diff --git a/wadsrc/static/zscript/actors/player/player.zs b/wadsrc/static/zscript/actors/player/player.zs index 65fc28943..0cee7a7f3 100644 --- a/wadsrc/static/zscript/actors/player/player.zs +++ b/wadsrc/static/zscript/actors/player/player.zs @@ -2708,13 +2708,23 @@ class PSprite : Object native play { if (processPending) { - // drop tic count and possibly change state - if (Tics != -1) // a -1 tic count never changes + if (Caller) { - Tics--; - // [BC] Apply double firing speed. - if (bPowDouble && Tics && (Owner.mo.FindInventory ("PowerDoubleFiringSpeed", true))) Tics--; - if (!Tics && Caller != null) SetState(CurState.NextState); + Caller.PSpriteTick(self); + if (bDestroyed) + return; + } + + if (processPending) + { + // drop tic count and possibly change state + if (Tics != -1) // a -1 tic count never changes + { + Tics--; + // [BC] Apply double firing speed. + if (bPowDouble && Tics && (Owner.mo.FindInventory ("PowerDoubleFiringSpeed", true))) Tics--; + if (!Tics && Caller != null) SetState(CurState.NextState); + } } } } From 38cff89a238e7ed005648b53b00221f681e24ac4 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 21 Apr 2024 12:12:21 +0200 Subject: [PATCH 05/28] ZWidgets: disabled SetClientFrame. On Win32 this function is unused, but it contains two API calls that only exist in Windows 10 or later. --- libraries/ZWidget/src/window/win32/win32window.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/ZWidget/src/window/win32/win32window.cpp b/libraries/ZWidget/src/window/win32/win32window.cpp index f279bcf3f..8a1fda50c 100644 --- a/libraries/ZWidget/src/window/win32/win32window.cpp +++ b/libraries/ZWidget/src/window/win32/win32window.cpp @@ -128,6 +128,8 @@ void Win32Window::SetWindowFrame(const Rect& box) void Win32Window::SetClientFrame(const Rect& box) { + // This function is currently unused but needs to be disabled because it contains Windows API calls that were only added in Windows 10. +#if 0 double dpiscale = GetDpiScale(); RECT rect = {}; @@ -141,6 +143,7 @@ void Win32Window::SetClientFrame(const Rect& box) AdjustWindowRectExForDpi(&rect, style, FALSE, exstyle, GetDpiForWindow(WindowHandle)); SetWindowPos(WindowHandle, nullptr, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOACTIVATE | SWP_NOZORDER); +#endif } void Win32Window::Show() From 51b3e4b33527615e685510af491b78cfd425a022 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Sun, 21 Apr 2024 07:09:00 -0400 Subject: [PATCH 06/28] - dynamically import GetDpiForWindow from USER32.dll, else return a default value --- libraries/ZWidget/src/window/win32/win32window.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/libraries/ZWidget/src/window/win32/win32window.cpp b/libraries/ZWidget/src/window/win32/win32window.cpp index 8a1fda50c..64d4701ed 100644 --- a/libraries/ZWidget/src/window/win32/win32window.cpp +++ b/libraries/ZWidget/src/window/win32/win32window.cpp @@ -271,9 +271,20 @@ int Win32Window::GetPixelHeight() const return box.bottom; } +typedef UINT(WINAPI* GetDpiForWindow_t)(HWND); double Win32Window::GetDpiScale() const { - return GetDpiForWindow(WindowHandle) / 96.0; + static GetDpiForWindow_t pGetDpiForWindow = nullptr; + if (!pGetDpiForWindow) + { + HMODULE hMod = LoadLibrary(TEXT("User32.dll")); + pGetDpiForWindow = reinterpret_cast(GetProcAddress(hMod, "GetDpiForWindow")); + } + + if (pGetDpiForWindow) + return pGetDpiForWindow(WindowHandle) / 96.0; + else + return 1.0; } std::string Win32Window::GetClipboardText() From 260c019301b7f32583576d13a3c2d64fa5969282 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 21 Apr 2024 14:30:26 +0200 Subject: [PATCH 07/28] optimized last commit to not retrieve the function repeatedly if it has already failed. --- libraries/ZWidget/src/window/win32/win32window.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libraries/ZWidget/src/window/win32/win32window.cpp b/libraries/ZWidget/src/window/win32/win32window.cpp index 64d4701ed..3ba21698a 100644 --- a/libraries/ZWidget/src/window/win32/win32window.cpp +++ b/libraries/ZWidget/src/window/win32/win32window.cpp @@ -275,10 +275,12 @@ typedef UINT(WINAPI* GetDpiForWindow_t)(HWND); double Win32Window::GetDpiScale() const { static GetDpiForWindow_t pGetDpiForWindow = nullptr; - if (!pGetDpiForWindow) + static bool done = false; + if (!done) { - HMODULE hMod = LoadLibrary(TEXT("User32.dll")); - pGetDpiForWindow = reinterpret_cast(GetProcAddress(hMod, "GetDpiForWindow")); + HMODULE hMod = GetModuleHandleA("User32.dll"); + if (hMod != nullptr) pGetDpiForWindow = reinterpret_cast(GetProcAddress(hMod, "GetDpiForWindow")); + done = true; } if (pGetDpiForWindow) From 0e1de064e31bff7c48e63f59b9eeb6babe15e461 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Sun, 21 Apr 2024 09:11:46 -0400 Subject: [PATCH 08/28] - hide the additional parameters for now, this needs to be added in later --- src/launcher/playgamepage.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/launcher/playgamepage.cpp b/src/launcher/playgamepage.cpp index 5c585c9e5..ce30930f8 100644 --- a/src/launcher/playgamepage.cpp +++ b/src/launcher/playgamepage.cpp @@ -85,6 +85,7 @@ 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); @@ -94,6 +95,7 @@ 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 c3b9dd7c8f6d99d8e15f3a31164ca60bb66f41fd Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Sun, 21 Apr 2024 09:37:01 -0400 Subject: [PATCH 09/28] - minor language update --- wadsrc/static/language.csv | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/wadsrc/static/language.csv b/wadsrc/static/language.csv index eb9e98808..080a605b2 100644 --- a/wadsrc/static/language.csv +++ b/wadsrc/static/language.csv @@ -1875,7 +1875,7 @@ Zorch Propulsor,TAG_ZORCHPROPULSOR,,,,Bzukový propulzor,,Zorch-Propeller,,Zorĉ Phasing Zorcher,TAG_PHASINGZORCHER,,,,Fázovací bzukr,,Phasenzorcher,,Fluktuantzorĉilo,Zorcher de Fase,,Vaiheiszorcheri,Zorcheur à Phase,Fokozatos Zorker,Zorcher di Fase,フェイシング ゾーチャー,전자 자쳐,Fasezorcher,,Fazowy Zorcher,Zorcher Fásico,,Zorcher Fazat,Фазерный зорчер,Фазни зорчер,Fasande Zorcher,Fazlama Zorcher,Фазовий Зорчер LAZ Device,TAG_LAZDEVICE,,,,Velkodosahový bzukr,LAZ-enhed,Flächenzorcher,,LAZ-Aparato,Dispositivo LAZ,,SAZ-laite,Zorcheur Zone Large,LAZ Készülék,Dispositivo LAZ,ラージエリアゾーキング デバイス,LAZ 장치,LAZ-aparaat,LAZ-enhet,Urządzenie LAZ,Dispositivo LAZ,,Dispozitiv LAZ,Устройство «ЗБР»,ЛАЗ уређај,LAZ-enhet,LAZ Cihazı,Пристрій LAZ %o was slimed by a flemoid.,OB_COMMONUS,,,,%o byl@[ao_cs] osliznut@[ao_cs] slizounem.,%o blev slimet af en flemoid.,%o wurde von einem Flemoiden vollgeschleimt.,,%o estas ŝlimiga de mukulo.,%o fue pegotead@[ao_esp] por un flemoide.,,%o joutui limatuksen limaamaksi.,%o à été gélifié par un flemoid.,%o el lett trutyizva egy Flemoid által.,%o è stato coperto di slime da un flemoid.,%o はフレモイドにベトベトにされた。,%o 은(는) 플레모이드에 의해 더러워졌습니다.,%o werd afgeslankt door een flemoid.,%o ble slimet av en flemoid.,"%o został@[ao_pl] oszlamion@[adj_pl] przez flemoida. -",%o foi melecad@[ao_ptb] por um flemóide.,%o foi suj@[ao_ptb] por um flemóide.,%o a fost transformat în mâzgă de un flemoid.,Игрока %o обслюнявил флемоид.,%o је унаказио љигавац.,%o blev slemmad av en flemoid.,%o bir flemoid tarafından sümüklendi., +",%o foi melecad@[ao_ptb] por um flemóide.,%o foi suj@[ao_ptb] por um flemóide.,%o a fost transformat în mâzgă de un flemoid.,Игрока %o обслюнявил флемоид.,%o је унаказио љигавац.,%o blev slemmad av en flemoid.,%o bir flemoid tarafından sümüklendi.,Виберіть рівень важкості: %o was slimed by a bipedicus.,OB_BIPEDICUS,,,,%o byl@[ao_cs] osliznut@[ao_cs] dvojnožkem.,%o blev slimet af en bipedicus.,%o wurde von einem Bipedicus vollgeschleimt.,,%o estas ŝlimiga de dupiedmukulo.,%o fue pegotead@[ao_esp] por un bipedicus.,,%o joutui bipedicuksen limaamaksi.,%o à été gélifié@[e_fr] par un bipedicus.,%o el lett trutyizva egy kétlábusz által.,%o è stato coperto di slime da un bipedicus.,%o はバイペディクスにベトベトにされた。,%o 은(는) 바이피디쿠스의 끈쩍한 시야에 걸렸습니다.,%o werd afgeslankt door een bipedicus.,%o ble slimet av en bipedicus.,%o został@[ao_pl] oszlamion@[adj_pl] przez bipedicusa.,%o foi melecad@[ao_ptb] por um bipedicus.,%o foi suj@[ao_ptb] por um bipedicus.,% a fost transformat în mâzgă de un biped.,Игрока %o обслюнявила двуножка.,%o је унаказио двоножни-љигавац.,%o blev slemmad av en bipedicus.,%o bir bipedicus tarafından sümüklendi., %o was slimed by an armored bipedicus.,OB_BIPEDICUS2,,,%o was slimed by an armoured bipedicus.,%o byl@[ao_cs] osliznut@[ao_cs] obrněným dvojnožkem.,%o blev slimet af en pansret bipedicus.,%o wurde von einem gepanzerten Bipedicus vollgeschleimt.,,%o estas ŝlimiga de kirasa dupiedmukulo.,%o fue pegotead@[ao_esp] por un bipedicus blindado.,,%o joutui panssaroidun bipedicuksen limaamaksi.,%o à été gélifié@[e_fr] par un bipedicus en armure.,%o el lett trutyizva egy páncélozott kétlábusz által.,%o è stato coperto di slime da un bipedicus corazzato.,%o はアーマードペディクスにベトベトにされた。,%o 은(는) 정예 바이피디쿠스의 찐득한 공격을 받았습니다.,%o werd afgeslankt door een gepantserde bipedicus.,%o ble slimet av en pansret bipedicus.,%o został@[ao_pl] oszlamion@[adj_pl] przez opancerzonego bipedicusa.,%o foi melecad@[ao_ptb] por um bipedicus de armadura.,%o foi suj@[ao_ptb] por um bipedicus de armadura.,"%o a fost transformat în mâzgă de un biped cu armură.",Игрока %o обслюнявила бронированная двуножка.,%o је унаказио оклопни-љигавац.,%o blev slemmad av en bepansrad bipedicus.,%o zırhlı bir bipedicus tarafından sümüklendi., @@ -3387,4 +3387,5 @@ HUD scale factor,SCALEMNU_HUD_SCALEFACTOR,hud_scalefactor,,,Faktor HUD škálov 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,,,,,,,クライアント側で落としたアイテムを拾わせない,,,,,,,,Отключить подбирание выпавших предметов на стороне клиента,,,, \ No newline at end of file +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 From 10a8a615cbaaa994ba9f6632c16ba3ce1a5c9430 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Wed, 17 Apr 2024 20:54:16 -0400 Subject: [PATCH 10/28] Fixed local copies of items not respecting their Amount value --- wadsrc/static/zscript/actors/inventory/inventory.zs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/wadsrc/static/zscript/actors/inventory/inventory.zs b/wadsrc/static/zscript/actors/inventory/inventory.zs index c9890c699..a2af10398 100644 --- a/wadsrc/static/zscript/actors/inventory/inventory.zs +++ b/wadsrc/static/zscript/actors/inventory/inventory.zs @@ -414,7 +414,10 @@ class Inventory : Actor { Inventory copy; - Amount = MIN(Amount, MaxAmount); + // Clamping this on local copy creation presents too many possible + // pitfalls (e.g. Health items). + if (!IsCreatingLocalCopy()) + Amount = MIN(Amount, MaxAmount); if (GoAway ()) { copy = Inventory(Spawn (GetClass())); @@ -1046,7 +1049,7 @@ class Inventory : Actor protected bool GoAway () { - if (bCreatingCopy) + if (IsCreatingLocalCopy()) return true; // Dropped items never stick around @@ -1130,6 +1133,11 @@ class Inventory : Actor return item; } + + protected clearscope bool IsCreatingLocalCopy() const + { + return bCreatingCopy; + } //=========================================================================== // From 36a4207a9879387bd756828569828d775ce8a015 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Thu, 25 Apr 2024 02:27:20 -0400 Subject: [PATCH 11/28] - 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 572ba9f515780530eb63c28fd9154ab0ce62e326 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Thu, 25 Apr 2024 07:52:44 -0400 Subject: [PATCH 12/28] 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 6839b412a..dad3a9870 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 347cb724e3c1681689158fcb39ac8523870f7bdc Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 25 Apr 2024 18:14:39 +0200 Subject: [PATCH 13/28] 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 @@ public: 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 e1a1fb6fb..daa19670f 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 503f716507bbc21492908f2cb2bd1d45a0606a2d Mon Sep 17 00:00:00 2001 From: Boondorl Date: Thu, 25 Apr 2024 12:55:26 -0400 Subject: [PATCH 14/28] 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 61f8a3366..41d60cb55 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 3f07d4e689a0db34128d7b1c2762c912bb905f80 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Thu, 25 Apr 2024 16:10:00 -0400 Subject: [PATCH 15/28] 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 daa19670f..a75925996 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 dad3a9870..e5f02b2fe 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 6040416caae48722474d76e646a4d33d18a10326 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Thu, 25 Apr 2024 18:09:53 -0400 Subject: [PATCH 16/28] 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 3871b47dd..0ec5cfe05 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 ca45da4ef..6dbbc2c5c 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 0e8325401d2e319a52fc5511acf501d91438908f Mon Sep 17 00:00:00 2001 From: Boondorl Date: Fri, 26 Apr 2024 13:10:49 -0400 Subject: [PATCH 17/28] 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 4fcef5f75..0f6484419 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 0049a00fe5fac37894fa59785aa5ed38679bbb13 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 27 Apr 2024 10:45:50 +0200 Subject: [PATCH 18/28] 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 c5e83cf58..ef7ff549f 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -712,6 +712,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 5fb7c026d..3eec35b2d 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 7c8359cd5..3c3fb1af0 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -1758,6 +1758,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" } @@ -1784,6 +1785,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 387e59cba7fa02d5891b4c7e22b2c55d7d20db1e Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 27 Apr 2024 12:36:10 +0200 Subject: [PATCH 19/28] 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 98a0b5f8d23d2d96baad4de14a0859895bd9b896 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 22 Apr 2024 07:14:04 +0200 Subject: [PATCH 20/28] 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 54ee0391d794d377d60e439160966c0937dcf3bb Mon Sep 17 00:00:00 2001 From: nashmuhandes Date: Mon, 22 Apr 2024 22:09:32 +0800 Subject: [PATCH 21/28] 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 5971d521d9f35ae34dadbd5705e9dcc5845bd670 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Mon, 22 Apr 2024 16:53:12 -0400 Subject: [PATCH 22/28] - `-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 25f791156f50212aa6a20a76c000de23e07bbc74 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Tue, 23 Apr 2024 20:30:44 -0400 Subject: [PATCH 23/28] - 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 9d460d3f46acb3b05834f6d5bf764a8b7f037b47 Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Wed, 24 Apr 2024 06:52:01 -0400 Subject: [PATCH 24/28] - 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 d00fc3b9b8f7224ff0bc6fcfdb8d6b0a623734bc Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Wed, 24 Apr 2024 07:17:09 -0400 Subject: [PATCH 25/28] - 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 92e509e771e016e257f789dc42abf569629b9d6d Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Sun, 28 Apr 2024 02:41:00 -0400 Subject: [PATCH 26/28] - this is 4.12.2 --- src/version.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/version.h b/src/version.h index 2c772fbaf..b0e6b4e14 100644 --- a/src/version.h +++ b/src/version.h @@ -41,21 +41,21 @@ const char *GetVersionString(); /** Lots of different version numbers **/ -#define VERSIONSTR "4.12.0" +#define VERSIONSTR "4.12.2" // The version as seen in the Windows resource -#define RC_FILEVERSION 4,12,0,0 -#define RC_PRODUCTVERSION 4,12,0,0 +#define RC_FILEVERSION 4,12,2,0 +#define RC_PRODUCTVERSION 4,12,2,0 #define RC_PRODUCTVERSION2 VERSIONSTR // These are for content versioning. #define VER_MAJOR 4 #define VER_MINOR 12 -#define VER_REVISION 0 +#define VER_REVISION 2 // This should always refer to the GZDoom version a derived port is based on and not reflect the derived port's version number! #define ENG_MAJOR 4 #define ENG_MINOR 12 -#define ENG_REVISION 0 +#define ENG_REVISION 2 // Version identifier for network games. // Bump it every time you do a release unless you're certain you From 22fd9b66ad9aed6aa9d036720bb482cbbbf9064f Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Sun, 28 Apr 2024 03:35:09 -0400 Subject: [PATCH 27/28] - 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 71c40432e5e893c629a1c9c76a523a0ab22bd56a Mon Sep 17 00:00:00 2001 From: Boondorl Date: Fri, 26 Apr 2024 15:12:47 -0400 Subject: [PATCH 28/28] 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 | 138 +++++++++++++++++++++-------------------- 1 file changed, 71 insertions(+), 67 deletions(-) diff --git a/src/playsim/p_user.cpp b/src/playsim/p_user.cpp index e5f02b2fe..dc48c783d 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; + 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; + } - result.pos = pmo->Vec3Offset(vecResult - to.pos); - - // 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; - } + R_ClearInterpolationPath(); + player->mo->renderflags &= ~RF_NOINTERPOLATEVIEW; - PredictionLast.gametic = maxtic - 1; - PredictionLast.pos = player->mo->Pos(); - //PredictionLast.portalgroup = player->mo->Sector->PortalGroup; + 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()); - 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; - } - } + 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 ()