From f5c86819abb67534fe80706b8ed2e5ed824ec8f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Farkas=20P=C3=A9ter?= Date: Fri, 16 Aug 2024 00:42:14 +0200 Subject: [PATCH 01/13] Added GOG path for Doom + Doom II --- src/win32/i_steam.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/win32/i_steam.cpp b/src/win32/i_steam.cpp index 07e7f2a02..2cc76ab66 100644 --- a/src/win32/i_steam.cpp +++ b/src/win32/i_steam.cpp @@ -183,7 +183,6 @@ static bool QueryPathKey(HKEY key, const wchar_t *keypath, const wchar_t *valnam TArray I_GetGogPaths() { - // TODO Does the 2024 Update affect GOG version? TArray result; FString path; std::wstring gamepath; @@ -226,6 +225,13 @@ TArray I_GetGogPaths() result.Push(path + "/DOOM II_Data/StreamingAssets"); // in a subdirectory } + // Look for Doom + Doom II + gamepath = gogregistrypath + L"\\1413291984"; + if (QueryPathKey(HKEY_LOCAL_MACHINE, gamepath.c_str(), L"Path", path)) + { + result.Push(path); // directly in install folder + } + // Look for Final Doom gamepath = gogregistrypath + L"\\1435848742"; if (QueryPathKey(HKEY_LOCAL_MACHINE, gamepath.c_str(), L"Path", path)) @@ -355,7 +361,6 @@ TArray I_GetBethesdaPath() TArray result; static const char* const bethesda_dirs[] = { - // TODO Does the 2024 Update affect Bethesda Launcher? "DOOM_Classic_2019/base", "DOOM_Classic_2019/rerelease/DOOM_Data/StreamingAssets", "DOOM_II_Classic_2019/base", From 5fa220219e2e00a65d72e05f883d470db5b01a26 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 16 Aug 2024 12:36:42 +0200 Subject: [PATCH 02/13] Reverted use of tchar.h which should be considered deprecated. GZDoom is Unicode only - as should be the norm for any Windows application - and will not work when compiled as ANSI so there's no good reason to use this wrapper. --- libraries/ZWidget/src/window/win32/win32window.cpp | 9 ++++----- src/CMakeLists.txt | 9 +-------- src/common/rendering/gl_load/gl_load.c | 3 +-- 3 files changed, 6 insertions(+), 15 deletions(-) diff --git a/libraries/ZWidget/src/window/win32/win32window.cpp b/libraries/ZWidget/src/window/win32/win32window.cpp index 48531372c..6ad09ef60 100644 --- a/libraries/ZWidget/src/window/win32/win32window.cpp +++ b/libraries/ZWidget/src/window/win32/win32window.cpp @@ -1,7 +1,6 @@ #include "win32window.h" #include -#include #include #include #include @@ -82,11 +81,11 @@ Win32Window::Win32Window(DisplayWindowHost* windowHost) : WindowHost(windowHost) Windows.push_front(this); WindowsIterator = Windows.begin(); - WNDCLASSEX classdesc = {}; + WNDCLASSEXW classdesc = {}; classdesc.cbSize = sizeof(WNDCLASSEX); classdesc.hInstance = GetModuleHandle(0); classdesc.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS; - classdesc.lpszClassName = _T( "ZWidgetWindow" ); + classdesc.lpszClassName = L"ZWidgetWindow"; classdesc.lpfnWndProc = &Win32Window::WndProc; RegisterClassEx(&classdesc); @@ -95,7 +94,7 @@ Win32Window::Win32Window(DisplayWindowHost* windowHost) : WindowHost(windowHost) // WS_CAPTION shows the caption (yay! actually a flag that does what it says it does!) // WS_SYSMENU shows the min/max/close buttons // WS_THICKFRAME makes the window resizable - CreateWindowEx(WS_EX_APPWINDOW | WS_EX_DLGMODALFRAME, _T( "ZWidgetWindow" ), _T( "" ), WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, 0, 0, 100, 100, 0, 0, GetModuleHandle(0), this); + CreateWindowExW(WS_EX_APPWINDOW | WS_EX_DLGMODALFRAME, L"ZWidgetWindow", L"", WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, 0, 0, 100, 100, 0, 0, GetModuleHandle(0), this); /* RAWINPUTDEVICE rid; @@ -299,7 +298,7 @@ double Win32Window::GetDpiScale() const static bool done = false; if (!done) { - HMODULE hMod = GetModuleHandle( _T( "User32.dll" )); + HMODULE hMod = GetModuleHandleA("User32.dll"); if (hMod != nullptr) pGetDpiForWindow = reinterpret_cast(GetProcAddress(hMod, "GetDpiForWindow")); done = true; } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e10d2cd1f..37d5d4839 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -69,20 +69,13 @@ if( WIN32 ) setupapi oleaut32 dbghelp - dxguid - dwmapi - ) - - if( NOT MINGW ) - list( APPEND PROJECT_LIBRARIES legacy_stdio_definitions ) - endif() + legacy_stdio_definitions ) if( DEM_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE ) if( DX_dxguid_LIBRARY ) list( APPEND PROJECT_LIBRARIES "${DX_dxguid_LIBRARY}" ) endif() endif() - else() if( APPLE ) set( NO_GTK ON ) diff --git a/src/common/rendering/gl_load/gl_load.c b/src/common/rendering/gl_load/gl_load.c index f50830528..d5ba4e49f 100644 --- a/src/common/rendering/gl_load/gl_load.c +++ b/src/common/rendering/gl_load/gl_load.c @@ -46,7 +46,6 @@ static void* PosixGetProcAddress (const GLubyte* name) #undef APIENTRY #endif #include -#include #ifdef _MSC_VER @@ -77,7 +76,7 @@ static void CheckOpenGL(void) { if (opengl32dll == 0) { - opengl32dll = LoadLibrary(_T("OpenGL32.DLL")); + opengl32dll = LoadLibraryA("OpenGL32.DLL"); if (opengl32dll != 0) { createcontext = (HGLRC(WINAPI*)(HDC)) GetProcAddress(opengl32dll, "wglCreateContext"); From 0d43272c8fdb6bd2d0fc8cc94564efcdffe3948e Mon Sep 17 00:00:00 2001 From: Boondorl Date: Fri, 29 Mar 2024 19:49:16 -0400 Subject: [PATCH 03/13] Allow for Basic and Hexen armor replacing --- src/ct_chat.cpp | 2 +- src/g_statusbar/sbarinfo.cpp | 2 +- src/g_statusbar/sbarinfo_commands.cpp | 8 ++++---- src/gamedata/gi.cpp | 4 ++++ src/gamedata/gi.h | 2 ++ src/playsim/p_acs.cpp | 6 +++--- wadsrc/static/zscript/actors/checks.zs | 2 +- wadsrc/static/zscript/actors/hexen/boostarmor.zs | 2 +- .../static/zscript/actors/hexen/healingradius.zs | 2 +- wadsrc/static/zscript/actors/inventory/armor.zs | 14 +++++++------- wadsrc/static/zscript/actors/inventory_util.zs | 14 ++++++++++++++ wadsrc/static/zscript/actors/player/player.zs | 6 +++--- .../static/zscript/actors/player/player_cheat.zs | 2 +- .../static/zscript/actors/player/player_morph.zs | 2 +- wadsrc/static/zscript/doombase.zs | 2 ++ wadsrc/static/zscript/scriptutil/scriptutil.zs | 2 +- wadsrc/static/zscript/ui/statusbar/alt_hud.zs | 2 +- wadsrc/static/zscript/ui/statusbar/doom_sbar.zs | 2 +- wadsrc/static/zscript/ui/statusbar/heretic_sbar.zs | 2 +- wadsrc/static/zscript/ui/statusbar/statusbar.zs | 8 ++++---- wadsrc/static/zscript/ui/statusbar/strife_sbar.zs | 4 ++-- 21 files changed, 56 insertions(+), 34 deletions(-) diff --git a/src/ct_chat.cpp b/src/ct_chat.cpp index e5368f83e..a12bb9f20 100644 --- a/src/ct_chat.cpp +++ b/src/ct_chat.cpp @@ -436,7 +436,7 @@ static bool DoSubstitution (FString &out, const char *in) { if (strnicmp(a, "armor", 5) == 0) { - auto armor = player->mo->FindInventory(NAME_BasicArmor); + auto armor = player->mo->FindInventory(NAME_BasicArmor, true); out.AppendFormat("%d", armor != NULL ? armor->IntVar(NAME_Amount) : 0); } } diff --git a/src/g_statusbar/sbarinfo.cpp b/src/g_statusbar/sbarinfo.cpp index 1d855cc23..6bb27d179 100644 --- a/src/g_statusbar/sbarinfo.cpp +++ b/src/g_statusbar/sbarinfo.cpp @@ -1036,7 +1036,7 @@ public: ammocount2 = ammo2 != nullptr ? ammo2->IntVar(NAME_Amount) : 0; //prepare ammo counts - armor = CPlayer->mo->FindInventory(NAME_BasicArmor); + armor = CPlayer->mo->FindInventory(NAME_BasicArmor, true); } void _Draw (EHudState state) diff --git a/src/g_statusbar/sbarinfo_commands.cpp b/src/g_statusbar/sbarinfo_commands.cpp index 73462f384..749294adc 100644 --- a/src/g_statusbar/sbarinfo_commands.cpp +++ b/src/g_statusbar/sbarinfo_commands.cpp @@ -276,7 +276,7 @@ class CommandDrawImage : public SBarInfoCommandFlowControl { int armorType = type - HEXENARMOR_ARMOR; - auto harmor = statusBar->CPlayer->mo->FindInventory(NAME_HexenArmor); + auto harmor = statusBar->CPlayer->mo->FindInventory(NAME_HexenArmor, true); if (harmor != NULL) { double *Slots = (double*)harmor->ScriptVar(NAME_Slots, nullptr); @@ -596,7 +596,7 @@ class CommandDrawSwitchableImage : public CommandDrawImage } else if(condition == ARMORTYPE) { - auto armor = statusBar->CPlayer->mo->FindInventory(NAME_BasicArmor); + auto armor = statusBar->CPlayer->mo->FindInventory(NAME_BasicArmor, true); if(armor != NULL) { auto n = armor->NameVar(NAME_ArmorType).GetIndex(); @@ -1413,7 +1413,7 @@ class CommandDrawNumber : public CommandDrawString case SAVEPERCENT: { double add = 0; - auto harmor = statusBar->CPlayer->mo->FindInventory(NAME_HexenArmor); + auto harmor = statusBar->CPlayer->mo->FindInventory(NAME_HexenArmor, true); if(harmor != NULL) { double *Slots = (double*)harmor->ScriptVar(NAME_Slots, nullptr); @@ -2775,7 +2775,7 @@ class CommandDrawBar : public SBarInfoCommand case SAVEPERCENT: { double add = 0; - auto harmor = statusBar->CPlayer->mo->FindInventory(NAME_HexenArmor); + auto harmor = statusBar->CPlayer->mo->FindInventory(NAME_HexenArmor, true); if (harmor != NULL) { double *Slots = (double*)harmor->ScriptVar(NAME_Slots, nullptr); diff --git a/src/gamedata/gi.cpp b/src/gamedata/gi.cpp index e907722e9..ed9b0bfa9 100644 --- a/src/gamedata/gi.cpp +++ b/src/gamedata/gi.cpp @@ -52,6 +52,8 @@ DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, backpacktype) DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, Armor2Percent) DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, ArmorIcon1) DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, ArmorIcon2) +DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, BasicArmorClass) +DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, HexenArmorClass) DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, gametype) DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, norandomplayerclass) DEFINE_FIELD_X(GameInfoStruct, gameinfo_t, infoPages) @@ -392,6 +394,8 @@ void FMapInfoParser::ParseGameInfo() GAMEINFOKEY_SOUNDARRAY(PrecachedSounds, "precachesounds", 0, false) GAMEINFOKEY_STRINGARRAY(EventHandlers, "addeventhandlers", 0, false) GAMEINFOKEY_STRINGARRAY(EventHandlers, "eventhandlers", 0, false) + GAMEINFOKEY_STRING(BasicArmorClass, "BasicArmorClass") + GAMEINFOKEY_STRING(HexenArmorClass, "HexenArmorClass") GAMEINFOKEY_STRING(PauseSign, "pausesign") GAMEINFOKEY_STRING(quitSound, "quitSound") GAMEINFOKEY_STRING(BorderFlat, "borderFlat") diff --git a/src/gamedata/gi.h b/src/gamedata/gi.h index 5e713628d..a8d4fa66c 100644 --- a/src/gamedata/gi.h +++ b/src/gamedata/gi.h @@ -148,6 +148,8 @@ struct gameinfo_t FString SkyFlatName; FString ArmorIcon1; FString ArmorIcon2; + FName BasicArmorClass; + FName HexenArmorClass; FString PauseSign; FString Endoom; double Armor2Percent; diff --git a/src/playsim/p_acs.cpp b/src/playsim/p_acs.cpp index 1d4e90d1e..d05f5dae3 100644 --- a/src/playsim/p_acs.cpp +++ b/src/playsim/p_acs.cpp @@ -5506,7 +5506,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args, int & else { FName p(Level->Behaviors.LookupString(args[0])); - auto armor = Level->Players[args[1]]->mo->FindInventory(NAME_BasicArmor); + auto armor = Level->Players[args[1]]->mo->FindInventory(NAME_BasicArmor, true); if (armor && armor->NameVar(NAME_ArmorType) == p) return armor->IntVar(NAME_Amount); } return 0; @@ -5517,7 +5517,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, int32_t *args, int & { if (activator == NULL || activator->player == NULL) return 0; - auto equippedarmor = activator->FindInventory(NAME_BasicArmor); + auto equippedarmor = activator->FindInventory(NAME_BasicArmor, true); if (equippedarmor && equippedarmor->IntVar(NAME_Amount) != 0) { @@ -8898,7 +8898,7 @@ scriptwait: case PCD_PLAYERARMORPOINTS: if (activator) { - auto armor = activator->FindInventory(NAME_BasicArmor); + auto armor = activator->FindInventory(NAME_BasicArmor, true); PushToStack (armor ? armor->IntVar(NAME_Amount) : 0); } else diff --git a/wadsrc/static/zscript/actors/checks.zs b/wadsrc/static/zscript/actors/checks.zs index 280abf4fe..018f2b552 100644 --- a/wadsrc/static/zscript/actors/checks.zs +++ b/wadsrc/static/zscript/actors/checks.zs @@ -110,7 +110,7 @@ extend class Actor bool CheckArmorType(name Type, int amount = 1) { - let myarmor = BasicArmor(FindInventory("BasicArmor")); + let myarmor = BasicArmor(FindInventory("BasicArmor", true)); return myarmor != null && myarmor.ArmorType == type && myarmor.Amount >= amount; } diff --git a/wadsrc/static/zscript/actors/hexen/boostarmor.zs b/wadsrc/static/zscript/actors/hexen/boostarmor.zs index 4ed7c7f80..0592a4e2d 100644 --- a/wadsrc/static/zscript/actors/hexen/boostarmor.zs +++ b/wadsrc/static/zscript/actors/hexen/boostarmor.zs @@ -32,7 +32,7 @@ class ArtiBoostArmor : Inventory for (int i = 0; i < 4; ++i) { - armor = HexenArmor(Spawn("HexenArmor")); + armor = HexenArmor(Spawn(GetHexenArmorClass())); armor.bDropped = true; armor.health = i; armor.Amount = 1; diff --git a/wadsrc/static/zscript/actors/hexen/healingradius.zs b/wadsrc/static/zscript/actors/hexen/healingradius.zs index 852bd642a..508595a30 100644 --- a/wadsrc/static/zscript/actors/hexen/healingradius.zs +++ b/wadsrc/static/zscript/actors/hexen/healingradius.zs @@ -51,7 +51,7 @@ class ArtiHealingRadius : Inventory case 'Armor': for (int j = 0; j < 4; ++j) { - HexenArmor armor = HexenArmor(Spawn("HexenArmor")); + HexenArmor armor = HexenArmor(Spawn(GetHexenArmorClass())); armor.health = j; armor.Amount = 1; if (!armor.CallTryPickup (mo)) diff --git a/wadsrc/static/zscript/actors/inventory/armor.zs b/wadsrc/static/zscript/actors/inventory/armor.zs index bc764fc2c..8509c5bf2 100644 --- a/wadsrc/static/zscript/actors/inventory/armor.zs +++ b/wadsrc/static/zscript/actors/inventory/armor.zs @@ -106,7 +106,7 @@ class BasicArmor : Armor { // BasicArmor that is in use is stored in the inventory as BasicArmor. // BasicArmor that is in reserve is not. - let copy = BasicArmor(Spawn("BasicArmor")); + let copy = BasicArmor(Spawn(GetBasicArmorClass())); copy.SavePercent = SavePercent != 0 ? SavePercent : 0.33335; // slightly more than 1/3 to avoid roundoff errors. copy.Amount = Amount; copy.MaxAmount = MaxAmount; @@ -127,7 +127,7 @@ class BasicArmor : Armor override bool HandlePickup (Inventory item) { - if (item.GetClass() == "BasicArmor") + if (item is "BasicArmor") { // You shouldn't be picking up BasicArmor anyway. return true; @@ -271,13 +271,13 @@ class BasicArmorBonus : Armor override bool Use (bool pickup) { - let armor = BasicArmor(Owner.FindInventory("BasicArmor")); + let armor = BasicArmor(Owner.FindInventory("BasicArmor", true)); bool result = false; // This should really never happen but let's be prepared for a broken inventory. if (armor == null) { - armor = BasicArmor(Spawn("BasicArmor")); + armor = BasicArmor(Spawn(GetBasicArmorClass())); armor.BecomeItem (); armor.Amount = 0; armor.MaxAmount = MaxSaveAmount; @@ -391,12 +391,12 @@ class BasicArmorPickup : Armor override bool Use (bool pickup) { int SaveAmount = GetSaveAmount(); - let armor = BasicArmor(Owner.FindInventory("BasicArmor")); + let armor = BasicArmor(Owner.FindInventory("BasicArmor", true)); // This should really never happen but let's be prepared for a broken inventory. if (armor == null) { - armor = BasicArmor(Spawn("BasicArmor")); + armor = BasicArmor(Spawn(GetBasicArmorClass())); armor.BecomeItem (); Owner.AddInventory (armor); } @@ -471,7 +471,7 @@ class HexenArmor : Armor // Like BasicArmor, HexenArmor is used in the inventory but not the map. // health is the slot this armor occupies. // Amount is the quantity to give (0 = normal max). - let copy = HexenArmor(Spawn("HexenArmor")); + let copy = HexenArmor(Spawn(GetHexenArmorClass())); copy.AddArmorToSlot (health, Amount); GoAwayAndDie (); return copy; diff --git a/wadsrc/static/zscript/actors/inventory_util.zs b/wadsrc/static/zscript/actors/inventory_util.zs index 1bb9be512..011ca134f 100644 --- a/wadsrc/static/zscript/actors/inventory_util.zs +++ b/wadsrc/static/zscript/actors/inventory_util.zs @@ -855,8 +855,22 @@ extend class Actor } } + clearscope static class GetBasicArmorClass() + { + class cls = (class)(GameInfo.BasicArmorClass); + if (cls) + return cls; + return "BasicArmor"; + } + clearscope static class GetHexenArmorClass() + { + class cls = (class)(GameInfo.HexenArmorClass); + if (cls) + return cls; + return "HexenArmor"; + } } diff --git a/wadsrc/static/zscript/actors/player/player.zs b/wadsrc/static/zscript/actors/player/player.zs index b2252c16e..69e534b70 100644 --- a/wadsrc/static/zscript/actors/player/player.zs +++ b/wadsrc/static/zscript/actors/player/player.zs @@ -1906,8 +1906,8 @@ class PlayerPawn : Actor // it provides player class based protection that should not affect // any other protection item. let myclass = GetClass(); - GiveInventoryType('HexenArmor'); - let harmor = HexenArmor(FindInventory('HexenArmor')); + GiveInventoryType(GetHexenArmorClass()); + let harmor = HexenArmor(FindInventory('HexenArmor', true)); harmor.Slots[4] = self.HexenArmor[0]; for (int i = 0; i < 4; ++i) @@ -1918,7 +1918,7 @@ class PlayerPawn : Actor // BasicArmor must come right after that. It should not affect any // other protection item as well but needs to process the damage // before the HexenArmor does. - GiveInventoryType('BasicArmor'); + GiveInventoryType(GetBasicArmorClass()); // Now add the items from the DECORATE definition let di = GetDropItems(); diff --git a/wadsrc/static/zscript/actors/player/player_cheat.zs b/wadsrc/static/zscript/actors/player/player_cheat.zs index c89832dca..3fbb5f30b 100644 --- a/wadsrc/static/zscript/actors/player/player_cheat.zs +++ b/wadsrc/static/zscript/actors/player/player_cheat.zs @@ -139,7 +139,7 @@ extend class PlayerPawn { for (i = 0; i < 4; ++i) { - let armoritem = Inventory(Spawn("HexenArmor")); + let armoritem = Inventory(Spawn(GetHexenArmorClass())); armoritem.health = i; armoritem.Amount = 0; if (!armoritem.CallTryPickup (self)) diff --git a/wadsrc/static/zscript/actors/player/player_morph.zs b/wadsrc/static/zscript/actors/player/player_morph.zs index 435d61cdf..85d21d250 100644 --- a/wadsrc/static/zscript/actors/player/player_morph.zs +++ b/wadsrc/static/zscript/actors/player/player_morph.zs @@ -347,7 +347,7 @@ extend class PlayerPawn } // Reset the base AC of the player's Hexen armor back to its default. - let hexArmor = HexenArmor(alt.FindInventory("HexenArmor")); + let hexArmor = HexenArmor(alt.FindInventory("HexenArmor", true)); if (hexArmor) hexArmor.Slots[4] = alt.HexenArmor[0]; diff --git a/wadsrc/static/zscript/doombase.zs b/wadsrc/static/zscript/doombase.zs index 829e75270..54c44f821 100644 --- a/wadsrc/static/zscript/doombase.zs +++ b/wadsrc/static/zscript/doombase.zs @@ -89,6 +89,8 @@ extend struct GameInfoStruct native double Armor2Percent; native String ArmorIcon1; native String ArmorIcon2; + native Name BasicArmorClass; + native Name HexenArmorClass; native bool norandomplayerclass; native Array infoPages; native GIFont mStatscreenMapNameFont; diff --git a/wadsrc/static/zscript/scriptutil/scriptutil.zs b/wadsrc/static/zscript/scriptutil/scriptutil.zs index 26f1a2b9d..b9d13e7b5 100644 --- a/wadsrc/static/zscript/scriptutil/scriptutil.zs +++ b/wadsrc/static/zscript/scriptutil/scriptutil.zs @@ -61,7 +61,7 @@ class ScriptUtil play } if (type == 'Armor') { - type = "BasicArmor"; + type = Actor.GetBasicArmorClass().GetClassName(); } if (amount <= 0) { diff --git a/wadsrc/static/zscript/ui/statusbar/alt_hud.zs b/wadsrc/static/zscript/ui/statusbar/alt_hud.zs index 203d55ec4..c1c6e7288 100644 --- a/wadsrc/static/zscript/ui/statusbar/alt_hud.zs +++ b/wadsrc/static/zscript/ui/statusbar/alt_hud.zs @@ -930,7 +930,7 @@ class AltHud ui int armory = hud_swaphealtharmor ? hudheight-45 : hudheight-20; int healthy = hud_swaphealtharmor ? hudheight-20 : hudheight-45; DrawHealth(CPlayer, 5, healthy); - DrawArmor(BasicArmor(CPlayer.mo.FindInventory('BasicArmor')), HexenArmor(CPlayer.mo.FindInventory('HexenArmor')), 5, armory); + DrawArmor(BasicArmor(CPlayer.mo.FindInventory('BasicArmor', true)), HexenArmor(CPlayer.mo.FindInventory('HexenArmor', true)), 5, armory); int y = DrawKeys(CPlayer, hudwidth-4, hudheight-10); y = DrawAmmo(CPlayer, hudwidth-5, y); diff --git a/wadsrc/static/zscript/ui/statusbar/doom_sbar.zs b/wadsrc/static/zscript/ui/statusbar/doom_sbar.zs index 39cad7adb..7e7496a41 100644 --- a/wadsrc/static/zscript/ui/statusbar/doom_sbar.zs +++ b/wadsrc/static/zscript/ui/statusbar/doom_sbar.zs @@ -146,7 +146,7 @@ class DoomStatusBar : BaseStatusBar DrawImage(berserk? "PSTRA0" : "MEDIA0", (20, -2)); DrawString(mHUDFont, FormatNumber(CPlayer.health, 3), (44, -20)); - let armor = CPlayer.mo.FindInventory("BasicArmor"); + let armor = CPlayer.mo.FindInventory("BasicArmor", true); if (armor != null && armor.Amount > 0) { DrawInventoryIcon(armor, (20, -22)); diff --git a/wadsrc/static/zscript/ui/statusbar/heretic_sbar.zs b/wadsrc/static/zscript/ui/statusbar/heretic_sbar.zs index 5c29e176f..62cc27efa 100644 --- a/wadsrc/static/zscript/ui/statusbar/heretic_sbar.zs +++ b/wadsrc/static/zscript/ui/statusbar/heretic_sbar.zs @@ -148,7 +148,7 @@ class HereticStatusBar : BaseStatusBar DrawString(mBigFont, FormatNumber(mHealthInterpolator.GetValue()), (41, -21), DI_TEXT_ALIGN_RIGHT); //armor - let armor = CPlayer.mo.FindInventory("BasicArmor"); + let armor = CPlayer.mo.FindInventory("BasicArmor", true); if (armor != null && armor.Amount > 0) { DrawInventoryIcon(armor, (58, -24)); diff --git a/wadsrc/static/zscript/ui/statusbar/statusbar.zs b/wadsrc/static/zscript/ui/statusbar/statusbar.zs index 58f2ecc3a..1cbaeae87 100644 --- a/wadsrc/static/zscript/ui/statusbar/statusbar.zs +++ b/wadsrc/static/zscript/ui/statusbar/statusbar.zs @@ -430,7 +430,7 @@ class BaseStatusBar : StatusBarCore native int GetArmorAmount() { - let armor = CPlayer.mo.FindInventory("BasicArmor"); + let armor = CPlayer.mo.FindInventory("BasicArmor", true); return armor? armor.Amount : 0; } @@ -451,13 +451,13 @@ class BaseStatusBar : StatusBarCore native int GetArmorSavePercent() { double add = 0; - let harmor = HexenArmor(CPlayer.mo.FindInventory("HexenArmor")); + let harmor = HexenArmor(CPlayer.mo.FindInventory("HexenArmor", true)); if(harmor != NULL) { add = harmor.Slots[0] + harmor.Slots[1] + harmor.Slots[2] + harmor.Slots[3] + harmor.Slots[4]; } //Hexen counts basic armor also so we should too. - let armor = BasicArmor(CPlayer.mo.FindInventory("BasicArmor")); + let armor = BasicArmor(CPlayer.mo.FindInventory("BasicArmor", true)); if(armor != NULL && armor.Amount > 0) { add += armor.SavePercent * 100; @@ -771,7 +771,7 @@ class BaseStatusBar : StatusBarCore native void DrawHexenArmor(int armortype, String image, Vector2 pos, int flags = 0, double alpha = 1.0, Vector2 boxsize = (-1, -1), Vector2 scale = (1.,1.)) { - let harmor = HexenArmor(statusBar.CPlayer.mo.FindInventory("HexenArmor")); + let harmor = HexenArmor(statusBar.CPlayer.mo.FindInventory("HexenArmor", true)); if (harmor != NULL) { let slotval = harmor.Slots[armorType]; diff --git a/wadsrc/static/zscript/ui/statusbar/strife_sbar.zs b/wadsrc/static/zscript/ui/statusbar/strife_sbar.zs index f52195be4..7186d46d4 100644 --- a/wadsrc/static/zscript/ui/statusbar/strife_sbar.zs +++ b/wadsrc/static/zscript/ui/statusbar/strife_sbar.zs @@ -287,7 +287,7 @@ class StrifeStatusBar : BaseStatusBar DrawHealthBar (points, 49, 175); // Armor - item = CPlayer.mo.FindInventory('BasicArmor'); + item = CPlayer.mo.FindInventory('BasicArmor', true); if (item != NULL && item.Amount > 0) { DrawInventoryIcon(item, (2, 177), DI_ITEM_OFFSETS); @@ -333,7 +333,7 @@ class StrifeStatusBar : BaseStatusBar DrawImage("I_MDKT", (14, -17)); // Draw armor - let armor = CPlayer.mo.FindInventory('BasicArmor'); + let armor = CPlayer.mo.FindInventory('BasicArmor', true); if (armor != NULL && armor.Amount != 0) { DrawString(mYelFont, FormatNumber(armor.Amount, 3), (35, -10)); From 1b20c92ca51b5b6ca21bf02b034d8e2ca4cc23e9 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Fri, 16 Aug 2024 18:26:11 -0400 Subject: [PATCH 04/13] Fixed counters not clearing when using shared/local pickups --- wadsrc/static/zscript/actors/inventory/inventory.zs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/wadsrc/static/zscript/actors/inventory/inventory.zs b/wadsrc/static/zscript/actors/inventory/inventory.zs index 2e6544093..0ca6faf3e 100644 --- a/wadsrc/static/zscript/actors/inventory/inventory.zs +++ b/wadsrc/static/zscript/actors/inventory/inventory.zs @@ -281,6 +281,7 @@ class Inventory : Actor if (!item || item == self) continue; + item.ClearCounters(); item.bSharingItem = true; item.bDropped = item.bNeverLocal = true; if (!item.CallTryPickup(players[i].mo)) @@ -847,6 +848,8 @@ class Inventory : Actor return; localPickUp = give != self; + if (localPickUp) + give.ClearCounters(); } bool res; @@ -1124,6 +1127,7 @@ class Inventory : Actor int pNum = client.PlayerNumber(); pickedUp[pNum] = true; DisableLocalRendering(pNum, true); + bCountItem = bCountSecret = false; } // Force spawn a new version of the item. This needs to use CreateCopy so that From 108ad7736a8af21ae2e0793303e1da408e38d5c6 Mon Sep 17 00:00:00 2001 From: jekyllgrim Date: Thu, 15 Aug 2024 17:02:17 +0300 Subject: [PATCH 05/13] Added itemcls to HasReceived CallTryPickup will cache the item's class and pass it to HasReceived, so the latter will know what item was received even if the item has been destroyed by the time it's called. --- wadsrc/static/zscript/actors/actor.zs | 6 ++++-- wadsrc/static/zscript/actors/inventory/inventory.zs | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index 2658a052f..7dd0cfc2b 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -534,7 +534,9 @@ class Actor : Thinker native // [AA] Called by inventory items at the end of CallTryPickup to let actors // do something with the items they've received. 'Item' might be null for // items that disappear on pickup. - virtual void HasReceived(Inventory item) {} + // 'itemcls' is passed unconditionally, so it can still be read even if + // 'item' is null due to being destroyed with GoAwayAndDie() on pickup. + virtual void HasReceived(Inventory item, class itemcls) {} // Called in TryMove if the mover ran into another Actor. This isn't called on players // if they're currently predicting. Guarantees collisions unlike CanCollideWith. @@ -705,7 +707,7 @@ class Actor : Thinker native native void SoundAlert(Actor target, bool splash = false, double maxdist = 0); native void ClearBounce(); native TerrainDef GetFloorTerrain(); - native bool CheckLocalView(int consoleplayer = -1 /* parameter is not used anymore but needed for backward compatibilityö. */); + native bool CheckLocalView(int consoleplayer = -1 /* parameter is not used anymore but needed for backward compatibility�. */); native bool CheckNoDelay(); native bool UpdateWaterLevel (bool splash = true); native bool IsZeroDamage(); diff --git a/wadsrc/static/zscript/actors/inventory/inventory.zs b/wadsrc/static/zscript/actors/inventory/inventory.zs index 0ca6faf3e..52009f2e1 100644 --- a/wadsrc/static/zscript/actors/inventory/inventory.zs +++ b/wadsrc/static/zscript/actors/inventory/inventory.zs @@ -647,9 +647,10 @@ class Inventory : Actor // unmorphed versions of a currently morphed actor cannot pick up anything. if (bUnmorphed) return false, null; - //[AA] starting with true, so that CanReceive can unset it, + // [AA] starting with true, so that CanReceive can unset it, // if necessary: bool res = true; + class cls = self.GetClass(); // [AA] CanReceive lets the actor receiving the item process it first. if (!toucher.CanReceive(self)) { @@ -696,7 +697,7 @@ class Inventory : Actor } } // [AA] Let the toucher do something with the item they've just received: - toucher.HasReceived(self); + toucher.HasReceived(self, cls); // If the item can be shared, make sure every player gets a copy. if (multiplayer && !deathmatch && !bDropped && ShouldShareItem(toucher)) From 4d18380956eaab3da9ccaf8a06043692b5d95cc5 Mon Sep 17 00:00:00 2001 From: jekyllgrim Date: Sat, 17 Aug 2024 18:58:03 +0300 Subject: [PATCH 06/13] Made itemcls optional And removed the invalid character on line 710 --- wadsrc/static/zscript/actors/actor.zs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index 7dd0cfc2b..584b466af 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -536,7 +536,7 @@ class Actor : Thinker native // items that disappear on pickup. // 'itemcls' is passed unconditionally, so it can still be read even if // 'item' is null due to being destroyed with GoAwayAndDie() on pickup. - virtual void HasReceived(Inventory item, class itemcls) {} + virtual void HasReceived(Inventory item, class itemcls = null) {} // Called in TryMove if the mover ran into another Actor. This isn't called on players // if they're currently predicting. Guarantees collisions unlike CanCollideWith. @@ -707,7 +707,7 @@ class Actor : Thinker native native void SoundAlert(Actor target, bool splash = false, double maxdist = 0); native void ClearBounce(); native TerrainDef GetFloorTerrain(); - native bool CheckLocalView(int consoleplayer = -1 /* parameter is not used anymore but needed for backward compatibility�. */); + native bool CheckLocalView(int consoleplayer = -1 /* parameter is not used anymore but needed for backward compatibility. */); native bool CheckNoDelay(); native bool UpdateWaterLevel (bool splash = true); native bool IsZeroDamage(); From 70cf707251c8eb527229278444d4ba2c0bf1cbb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Wed, 21 Aug 2024 00:08:57 -0300 Subject: [PATCH 07/13] Skip bex strings for freedoom if language lump is present (#2682) --- src/d_iwad.cpp | 4 + src/d_main.cpp | 8 +- src/d_main.h | 1 + src/gamedata/d_dehacked.cpp | 134 +++++++++++++++++-------------- src/gamedata/d_dehacked.h | 11 ++- wadsrc_extra/static/iwadinfo.txt | 4 + 6 files changed, 96 insertions(+), 66 deletions(-) diff --git a/src/d_iwad.cpp b/src/d_iwad.cpp index 4758064a3..7f9bc60fe 100644 --- a/src/d_iwad.cpp +++ b/src/d_iwad.cpp @@ -138,6 +138,10 @@ void FIWadManager::ParseIWadInfo(const char *fn, const char *data, int datasize, { iwad->nokeyboardcheats = true; } + else if (sc.Compare("SkipBexStringsIfLanguage")) + { + iwad->SkipBexStringsIfLanguage = true; + } else if (sc.Compare("Compatibility")) { sc.MustGetStringName("="); diff --git a/src/d_main.cpp b/src/d_main.cpp index b0d3d88f2..c14149196 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1782,7 +1782,7 @@ bool ConsiderPatches (const char *arg) if ( (f = BaseFileSearch(args[i].GetChars(), ".deh", false, GameConfig)) || (f = BaseFileSearch(args[i].GetChars(), ".bex", false, GameConfig)) ) { - D_LoadDehFile(f); + D_LoadDehFile(f, 0); } } return argc > 0; @@ -3396,7 +3396,7 @@ static int D_InitGame(const FIWADInfo* iwad_info, std::vector& allw auto numbasesounds = soundEngine->GetNumSounds(); // Load embedded Dehacked patches - D_LoadDehLumps(FromIWAD); + D_LoadDehLumps(FromIWAD, iwad_info->SkipBexStringsIfLanguage ? DEH_SKIP_BEX_STRINGS_IF_LANGUAGE : 0); // [RH] Add any .deh and .bex files on the command line. // If there are none, try adding any in the config file. @@ -3413,13 +3413,13 @@ static int D_InitGame(const FIWADInfo* iwad_info, std::vector& allw if (stricmp (key, "Path") == 0 && FileExists (value)) { if (!batchrun) Printf ("Applying patch %s\n", value); - D_LoadDehFile(value); + D_LoadDehFile(value, 0); } } } // Load embedded Dehacked patches - D_LoadDehLumps(FromPWADs); + D_LoadDehLumps(FromPWADs, 0); // Create replacements for dehacked pickups FinishDehPatch(); diff --git a/src/d_main.h b/src/d_main.h index 6f6c37458..49e9846be 100644 --- a/src/d_main.h +++ b/src/d_main.h @@ -86,6 +86,7 @@ struct FIWADInfo int StartupType = FStartupInfo::DefaultStartup; // alternate startup type FString MapInfo; // Base mapinfo to load bool nokeyboardcheats = false; // disable keyboard cheats + bool SkipBexStringsIfLanguage = false; TArray Load; // Wads to be loaded with this one. TArray Lumps; // Lump names for identification TArray DeleteLumps; // Lumps which must be deleted from the directory. diff --git a/src/gamedata/d_dehacked.cpp b/src/gamedata/d_dehacked.cpp index 029878176..26123b319 100644 --- a/src/gamedata/d_dehacked.cpp +++ b/src/gamedata/d_dehacked.cpp @@ -446,28 +446,28 @@ struct Key { ptrdiff_t offset; }; -static int PatchThing (int); -static int PatchSound (int); -static int PatchFrame (int); -static int PatchSprite (int); -static int PatchAmmo (int); -static int PatchWeapon (int); -static int PatchPointer (int); -static int PatchCheats (int); -static int PatchMisc (int); -static int PatchText (int); -static int PatchStrings (int); -static int PatchPars (int); -static int PatchCodePtrs (int); -static int PatchMusic (int); -static int DoInclude (int); -static int PatchSpriteNames(int); -static int PatchSoundNames(int); -static bool DoDehPatch(); +static int PatchThing (int, int); +static int PatchSound (int, int); +static int PatchFrame (int, int); +static int PatchSprite (int, int); +static int PatchAmmo (int, int); +static int PatchWeapon (int, int); +static int PatchPointer (int, int); +static int PatchCheats (int, int); +static int PatchMisc (int, int); +static int PatchText (int, int); +static int PatchStrings (int, int); +static int PatchPars (int, int); +static int PatchCodePtrs (int, int); +static int PatchMusic (int, int); +static int DoInclude (int, int); +static int PatchSpriteNames(int, int); +static int PatchSoundNames(int, int); +static bool DoDehPatch(int); static const struct { const char *name; - int (*func)(int); + int (*func)(int, int); } Modes[] = { // These appear in .deh and .bex files { "Thing", PatchThing }, @@ -491,7 +491,7 @@ static const struct { { NULL, NULL }, }; -static int HandleMode (const char *mode, int num); +static int HandleMode (const char *mode, int num, int flags); static bool HandleKey (const struct Key *keys, void *structure, const char *key, int value); static bool ReadChars (char **stuff, int size); static char *igets (void); @@ -509,14 +509,14 @@ static void PushTouchedActor(PClassActor *cls) } -static int HandleMode (const char *mode, int num) +static int HandleMode (const char *mode, int num, int flags) { int i = 0; while (Modes[i].name && stricmp (Modes[i].name, mode)) i++; if (Modes[i].name) - return Modes[i].func (num); + return Modes[i].func (num, flags); // Handle unknown or unimplemented data Printf ("Unknown chunk %s encountered. Skipping.\n", mode); @@ -1181,7 +1181,7 @@ static void ClearBits2Stuff(AActor* defaults) } -static int PatchThing (int thingy) +static int PatchThing (int thingy, int flags) { enum { @@ -1776,7 +1776,7 @@ static int PatchThing (int thingy) // real benefit to doing this, and it would be very difficult for // me to emulate it, I have disabled them entirely. -static int PatchSound (int soundNum) +static int PatchSound (int soundNum, int flags) { int result; @@ -1833,7 +1833,7 @@ DehBits sbits[] = { }; -static int PatchFrame (int frameNum) +static int PatchFrame (int frameNum, int flags) { MBFArgs args{}; int result; @@ -1983,7 +1983,7 @@ static int PatchFrame (int frameNum) return result; } -static int PatchSprite (int sprNum) +static int PatchSprite (int sprNum, int flags) { int result; int offset = 0; @@ -2025,7 +2025,7 @@ static int PatchSprite (int sprNum) return result; } -static int PatchAmmo (int ammoNum) +static int PatchAmmo (int ammoNum, int flags) { PClassActor *ammoType = NULL; AActor *defaultAmmo = NULL; @@ -2116,7 +2116,7 @@ DehBits wbits[] = { { "NOAUTOSWITCHTO", WIF_NOAUTOSWITCHTO } }; -static int PatchWeapon (int weapNum) +static int PatchWeapon (int weapNum, int flags) { int result; PClassActor *type = nullptr; @@ -2324,7 +2324,7 @@ static int SetPointer(FState *state, PFunction *sym, int frame = 0) return -1; } -static int PatchPointer (int ptrNum) +static int PatchPointer (int ptrNum, int flags) { int result; @@ -2386,7 +2386,7 @@ static int PatchPointer (int ptrNum) return result; } -static int PatchCheats (int dummy) +static int PatchCheats (int dummy, int flags) { int result; @@ -2398,7 +2398,7 @@ static int PatchCheats (int dummy) return result; } -static int PatchMisc (int dummy) +static int PatchMisc (int dummy, int flags) { static const struct Key keys[] = { { "Initial Health", static_cast(myoffsetof(struct DehInfo,StartHealth)) }, @@ -2592,7 +2592,7 @@ static int PatchMisc (int dummy) return result; } -static int PatchPars (int dummy) +static int PatchPars (int dummy, int flags) { char *space, mapname[8], *moredata; level_info_t *info; @@ -2658,7 +2658,7 @@ static int PatchPars (int dummy) } -static int PatchCodePtrs (int dummy) +static int PatchCodePtrs (int dummy, int flags) { int result; @@ -2733,7 +2733,7 @@ static int PatchCodePtrs (int dummy) return result; } -static int PatchMusic (int dummy) +static int PatchMusic (int dummy, int flags) { int result; @@ -2788,7 +2788,7 @@ static void ReplaceSpriteInData(const char* oldStr, const char* newStr) } } -static int PatchText (int oldSize) +static int PatchText (int oldSize, int flags) { int newSize; char *oldStr; @@ -2895,7 +2895,7 @@ donewithtext: return result; } -static int PatchStrings (int dummy) +static int PatchStrings (int dummy, int flags) { int result; @@ -2919,20 +2919,23 @@ static int PatchStrings (int dummy) } } while (Line2 && *Line2); - ReplaceSpecialChars (holdstring.LockBuffer()); - holdstring.UnlockBuffer(); - // Account for a discrepancy between Boom's and ZDoom's name for the red skull key pickup message - const char *ll = Line1; - if (!stricmp(ll, "GOTREDSKULL")) ll = "GOTREDSKUL"; - TableElement te = { LumpFileNum, { holdstring, holdstring, holdstring, holdstring } }; - DehStrings.Insert(ll, te); - DPrintf (DMSG_SPAMMY, "%s set to:\n%s\n", Line1, holdstring.GetChars()); + if(!(flags & DEH_SKIP_BEX_STRINGS_IF_LANGUAGE)) + { + ReplaceSpecialChars (holdstring.LockBuffer()); + holdstring.UnlockBuffer(); + // Account for a discrepancy between Boom's and ZDoom's name for the red skull key pickup message + const char *ll = Line1; + if (!stricmp(ll, "GOTREDSKULL")) ll = "GOTREDSKUL"; + TableElement te = { LumpFileNum, { holdstring, holdstring, holdstring, holdstring } }; + DehStrings.Insert(ll, te); + DPrintf (DMSG_SPAMMY, "%s set to:\n%s\n", Line1, holdstring.GetChars()); + } } return result; } -static int PatchSoundNames (int dummy) +static int PatchSoundNames (int dummy, int flags) { int result; @@ -2949,7 +2952,7 @@ static int PatchSoundNames (int dummy) return result; } -static int PatchSpriteNames (int dummy) +static int PatchSpriteNames (int dummy, int flags) { int result; @@ -2985,7 +2988,7 @@ static int PatchSpriteNames (int dummy) } -static int DoInclude (int dummy) +static int DoInclude (int dummy, int flags) { char *data; int savedversion, savepversion, savepatchsize; @@ -3047,7 +3050,7 @@ static int DoInclude (int dummy) } } - D_LoadDehFile(path); + D_LoadDehFile(path, flags); if (data != path) { @@ -3080,7 +3083,7 @@ static bool isDehFile(int lumpnum) && (0 == stricmp(extension, ".deh") || 0 == stricmp(extension, ".bex")); } -int D_LoadDehLumps(DehLumpSource source) +int D_LoadDehLumps(DehLumpSource source, int flags) { int lastlump = 0, lumpnum, count = 0; @@ -3099,7 +3102,20 @@ int D_LoadDehLumps(DehLumpSource source) continue; } - count += D_LoadDehLump(lumpnum); + int filtered_flags = flags & ~DEH_SKIP_BEX_STRINGS_IF_LANGUAGE; + + if((flags & DEH_SKIP_BEX_STRINGS_IF_LANGUAGE) && FromIWAD == source) + { + int iwadnum = fileSystem.GetIwadNum(); + int lastlump2 = fileSystem.GetFirstEntry(iwadnum); + int lumpnum2 = fileSystem.FindLump("LANGUAGE", &lastlump2); + + if(lumpnum2 >= 0 && fileSystem.GetFileContainer(lumpnum2) == iwadnum) + { + filtered_flags |= DEH_SKIP_BEX_STRINGS_IF_LANGUAGE; + } + } + count += D_LoadDehLump(lumpnum, filtered_flags); } if (FromPWADs == source && 0 == PatchSize && dehload > 0) @@ -3112,7 +3128,7 @@ int D_LoadDehLumps(DehLumpSource source) { if (isDehFile(lumpnum)) { - count += D_LoadDehLump(lumpnum); + count += D_LoadDehLump(lumpnum, 0); } } } @@ -3122,7 +3138,7 @@ int D_LoadDehLumps(DehLumpSource source) { if (isDehFile(lumpnum)) { - count += D_LoadDehLump(lumpnum); + count += D_LoadDehLump(lumpnum, 0); break; } } @@ -3132,7 +3148,7 @@ int D_LoadDehLumps(DehLumpSource source) return count; } -bool D_LoadDehLump(int lumpnum) +bool D_LoadDehLump(int lumpnum, int flags) { auto ls = LumpFileNum; LumpFileNum = fileSystem.GetFileContainer(lumpnum); @@ -3143,13 +3159,13 @@ bool D_LoadDehLump(int lumpnum) PatchFile = new char[PatchSize + 1]; fileSystem.ReadFile(lumpnum, PatchFile); PatchFile[PatchSize] = '\0'; // terminate with a '\0' character - auto res = DoDehPatch(); + auto res = DoDehPatch(flags); LumpFileNum = ls; return res; } -bool D_LoadDehFile(const char *patchfile) +bool D_LoadDehFile(const char *patchfile, int flags) { FileReader fr; @@ -3162,7 +3178,7 @@ bool D_LoadDehFile(const char *patchfile) fr.Read(PatchFile, PatchSize); fr.Close(); PatchFile[PatchSize] = '\0'; // terminate with a '\0' character - return DoDehPatch(); + return DoDehPatch(flags); } else { @@ -3178,14 +3194,14 @@ bool D_LoadDehFile(const char *patchfile) } if (lumpnum >= 0) { - return D_LoadDehLump(lumpnum); + return D_LoadDehLump(lumpnum, flags); } } Printf ("Could not open DeHackEd patch \"%s\"\n", patchfile); return false; } -static bool DoDehPatch() +static bool DoDehPatch(int flags) { if (!batchrun) Printf("Adding dehacked patch %s\n", PatchName.GetChars()); @@ -3276,7 +3292,7 @@ static bool DoDehPatch() } else if (cont == 2) { - cont = HandleMode (Line1, atoi (Line2)); + cont = HandleMode (Line1, atoi (Line2), flags); } } while (cont); diff --git a/src/gamedata/d_dehacked.h b/src/gamedata/d_dehacked.h index bb87993e9..449964943 100644 --- a/src/gamedata/d_dehacked.h +++ b/src/gamedata/d_dehacked.h @@ -40,9 +40,14 @@ enum DehLumpSource FromPWADs }; -int D_LoadDehLumps(DehLumpSource source); -bool D_LoadDehLump(int lumpnum); -bool D_LoadDehFile(const char *filename); +enum DehFlags +{ + DEH_SKIP_BEX_STRINGS_IF_LANGUAGE = 1, +}; + +int D_LoadDehLumps(DehLumpSource source, int flags); +bool D_LoadDehLump(int lumpnum, int flags); +bool D_LoadDehFile(const char *filename, int flags); void FinishDehPatch (); #endif //__D_DEHACK_H__ diff --git a/wadsrc_extra/static/iwadinfo.txt b/wadsrc_extra/static/iwadinfo.txt index 343b64431..8eb7f1522 100644 --- a/wadsrc_extra/static/iwadinfo.txt +++ b/wadsrc_extra/static/iwadinfo.txt @@ -282,6 +282,7 @@ IWad Mapinfo = "mapinfo/doom2.txt" MustContain = "MAP01", "FREEDM" BannerColors = "32 54 43", "c6 dc d1" + SkipBexStringsIfLanguage } IWad @@ -294,6 +295,7 @@ IWad Mapinfo = "mapinfo/doom2.txt" MustContain = "MAP01", "FREEDOOM" BannerColors = "32 54 43", "c6 dc d1" + SkipBexStringsIfLanguage } IWad @@ -306,6 +308,7 @@ IWad Mapinfo = "mapinfo/doom1.txt" MustContain = "E1M1", "E2M1", "E3M1", "FREEDOOM" BannerColors = "32 54 43", "c6 dc d1" + SkipBexStringsIfLanguage } IWad @@ -317,6 +320,7 @@ IWad Mapinfo = "mapinfo/doom1.txt" MustContain = "E1M1", "FREEDOOM" BannerColors = "32 54 43", "c6 dc d1" + SkipBexStringsIfLanguage } IWad From f0ff2736203506b4a0c1502ddbf95ba1766d28ef Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 18 Aug 2024 14:56:58 +0200 Subject: [PATCH 08/13] Stop grabbing mouse when game window doesn't have the focus --- src/common/platform/win32/i_mouse.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/common/platform/win32/i_mouse.cpp b/src/common/platform/win32/i_mouse.cpp index 72dc3f335..e0050cc3a 100644 --- a/src/common/platform/win32/i_mouse.cpp +++ b/src/common/platform/win32/i_mouse.cpp @@ -267,7 +267,7 @@ void I_CheckNativeMouse(bool preferNative, bool eventhandlerresult) } else { - if ((GetForegroundWindow() != mainwindow.GetHandle()) || preferNative || !use_mouse) + if (preferNative || !use_mouse) { want_native = true; } @@ -286,6 +286,10 @@ void I_CheckNativeMouse(bool preferNative, bool eventhandlerresult) if (!want_native && eventhandlerresult) want_native = true; + // The application should *never* grab the mouse cursor if its window doesn't have the focus. + if (GetForegroundWindow() != mainwindow.GetHandle()) + want_native = true; + //Printf ("%d %d %d\n", wantNative, preferNative, NativeMouse); if (want_native != NativeMouse) From b2976444c95455e11bfedbb08e94361034a35e74 Mon Sep 17 00:00:00 2001 From: "Dileep V. Reddy" Date: Sun, 25 Aug 2024 09:05:54 -0600 Subject: [PATCH 09/13] Smaller aspect ratio screens were getting clipped a bit too much. This is a brute-force if-else solution. Larger aspect ratios (wider screens) were always good. --- src/rendering/hwrenderer/scene/hw_drawinfo.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp index 19478c30c..b7c02a841 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp @@ -366,9 +366,16 @@ angle_t HWDrawInfo::FrustumAngle() { // If pitch is larger than this you can look all around at an FOV of 90 degrees if (fabs(Viewpoint.HWAngles.Pitch.Degrees()) > 89.0) return 0xffffffff; + int aspMult = AspectMultiplier(r_viewwindow.WidescreenRatio); // 48 == square window + double absPitch = fabs(Viewpoint.HWAngles.Pitch.Degrees()); + // Smaller aspect ratios still clip too much. Need a better solution + if (aspMult > 36 && absPitch > 30.0) return 0xffffffff; + else if (aspMult > 40 && absPitch > 25.0) return 0xffffffff; + else if (aspMult > 45 && absPitch > 20.0) return 0xffffffff; + else if (aspMult > 47 && absPitch > 10.0) return 0xffffffff; double xratio = r_viewwindow.FocalTangent / Viewpoint.PitchCos; - double floatangle = 0.035 + atan ( xratio ) * 48.0 / AspectMultiplier(r_viewwindow.WidescreenRatio); // this is radians + double floatangle = 0.05 + atan ( xratio ) * 48.0 / aspMult; // this is radians angle_t a1 = DAngle::fromRad(floatangle).BAMs(); if (a1 >= ANGLE_90) return 0xffffffff; From 76c8b6da5742562a8eece3037f90ab71de4b1d77 Mon Sep 17 00:00:00 2001 From: Xaser Acheron Date: Sat, 10 Aug 2024 02:53:52 -0500 Subject: [PATCH 10/13] fix A_PlaySound not working for DSDHACKED-defined sounds --- src/gamedata/d_dehacked.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gamedata/d_dehacked.cpp b/src/gamedata/d_dehacked.cpp index 26123b319..77e9d1320 100644 --- a/src/gamedata/d_dehacked.cpp +++ b/src/gamedata/d_dehacked.cpp @@ -843,7 +843,7 @@ static void CreateScratchFunc(FunctionCallEmitter &emitters, int value1, int val // misc1 = sound, misc2 = attenuation none (true) or normal (false) static void CreatePlaySoundFunc(FunctionCallEmitter &emitters, int value1, int value2, MBFParamState* state) { // A_PlaySound - emitters.AddParameterIntConst(DehFindSound(value1 - 1, true).index()); // soundid + emitters.AddParameterIntConst(DehFindSound(value1 - 1, false).index()); // soundid emitters.AddParameterIntConst(CHAN_BODY); // channel emitters.AddParameterFloatConst(1); // volume emitters.AddParameterIntConst(false); // looping From 5895f9b1b134445ad78949d544a96ab5828a12bf Mon Sep 17 00:00:00 2001 From: Rachael Alexanderson Date: Sat, 7 Sep 2024 23:09:18 -0400 Subject: [PATCH 11/13] - implement +SQUAREPIXELS flag --- src/playsim/actor.h | 1 + src/rendering/hwrenderer/scene/hw_sprites.cpp | 2 +- src/scripting/thingdef_data.cpp | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/playsim/actor.h b/src/playsim/actor.h index 30fdc55e8..5aa23b573 100644 --- a/src/playsim/actor.h +++ b/src/playsim/actor.h @@ -503,6 +503,7 @@ enum ActorRenderFlag2 RF2_CAMFOLLOWSPLAYER = 0x0040, // Matches the cam's base position and angles to the main viewpoint. RF2_NOMIPMAP = 0x0080, // [Nash] forces no mipmapping on sprites. Useful for tiny sprites that need to remain visually crisp RF2_ISOMETRICSPRITES = 0x0100, + RF2_SQUAREPIXELS = 0x0200, // apply +ROLLSPRITE scaling math so that non rolling sprites get the same scaling }; // This translucency value produces the closest match to Heretic's TINTTAB. diff --git a/src/rendering/hwrenderer/scene/hw_sprites.cpp b/src/rendering/hwrenderer/scene/hw_sprites.cpp index ba4b67983..05207f8c4 100644 --- a/src/rendering/hwrenderer/scene/hw_sprites.cpp +++ b/src/rendering/hwrenderer/scene/hw_sprites.cpp @@ -1036,7 +1036,7 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t r.Scale(sprscale.X, isSpriteShadow ? sprscale.Y * 0.15 * thing->isoscaleY : sprscale.Y * thing->isoscaleY); - if (thing->renderflags & (RF_ROLLSPRITE|RF_FLATSPRITE)) + if ((thing->renderflags & (RF_ROLLSPRITE|RF_FLATSPRITE)) || (thing->renderflags2 & RF2_SQUAREPIXELS)) { double ps = di->Level->pixelstretch; double mult = 1.0 / sqrt(ps); // shrink slightly diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 3993cd745..5bbb35fae 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -386,6 +386,7 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG(RF2, CAMFOLLOWSPLAYER, AActor, renderflags2), DEFINE_FLAG(RF2, NOMIPMAP, AActor, renderflags2), DEFINE_FLAG(RF2, ISOMETRICSPRITES, AActor, renderflags2), + DEFINE_FLAG(RF2, SQUAREPIXELS, AActor, renderflags2), // Bounce flags DEFINE_FLAG2(BOUNCE_Walls, BOUNCEONWALLS, AActor, BounceFlags), From afcd38907c07848a0ab3b7e710d91bea833a5305 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Sun, 8 Sep 2024 17:01:51 -0300 Subject: [PATCH 12/13] add SpawnMultiCoopOnly mapinfo flag to spawn **only** coop spawns in single-player --- src/gamedata/g_mapinfo.h | 2 ++ src/gamedata/g_skill.cpp | 12 +++++++++++- src/playsim/p_mobj.cpp | 5 +++-- wadsrc/static/zscript/constants.zs | 1 + 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/gamedata/g_mapinfo.h b/src/gamedata/g_mapinfo.h index 73b46d7e0..8f311f6a2 100644 --- a/src/gamedata/g_mapinfo.h +++ b/src/gamedata/g_mapinfo.h @@ -510,6 +510,7 @@ enum ESkillProperty SKILLP_PlayerRespawn, SKILLP_SpawnMulti, SKILLP_InstantReaction, + SKILLP_SpawnMultiCoopOnly, }; enum EFSkillProperty // floating point properties { @@ -555,6 +556,7 @@ struct FSkillInfo int SpawnFilter; bool SpawnMulti; bool InstantReaction; + bool SpawnMultiCoopOnly; int ACSReturn; FString MenuName; FString PicName; diff --git a/src/gamedata/g_skill.cpp b/src/gamedata/g_skill.cpp index 8a0f69fb3..e8d7849ba 100644 --- a/src/gamedata/g_skill.cpp +++ b/src/gamedata/g_skill.cpp @@ -77,6 +77,7 @@ void FMapInfoParser::ParseSkill () skill.Aggressiveness = 1.; skill.SpawnFilter = 0; skill.SpawnMulti = false; + skill.SpawnMultiCoopOnly = false; skill.InstantReaction = false; skill.ACSReturn = 0; skill.MustConfirm = false; @@ -198,6 +199,10 @@ void FMapInfoParser::ParseSkill () { skill.SpawnMulti = true; } + else if (sc.Compare ("spawnmulticooponly")) + { + skill.SpawnMultiCoopOnly = true; + } else if (sc.Compare ("InstantReaction")) { skill.InstantReaction = true; @@ -408,9 +413,13 @@ int G_SkillProperty(ESkillProperty prop) case SKILLP_SpawnMulti: return AllSkills[gameskill].SpawnMulti; - + case SKILLP_InstantReaction: return AllSkills[gameskill].InstantReaction; + + case SKILLP_SpawnMultiCoopOnly: + return AllSkills[gameskill].SpawnMultiCoopOnly; + } } return 0; @@ -550,6 +559,7 @@ FSkillInfo &FSkillInfo::operator=(const FSkillInfo &other) SpawnFilter = other.SpawnFilter; SpawnMulti = other.SpawnMulti; InstantReaction = other.InstantReaction; + SpawnMultiCoopOnly = other.SpawnMultiCoopOnly; ACSReturn = other.ACSReturn; MenuName = other.MenuName; PicName = other.PicName; diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index d216d30d8..442f101f5 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -5757,6 +5757,7 @@ AActor *FLevelLocals::SpawnMapThing (FMapThing *mthing, int position) AActor *mobj; bool spawnmulti = G_SkillProperty(SKILLP_SpawnMulti) || !!(dmflags2 & DF2_ALWAYS_SPAWN_MULTI); + bool spawnmulti_cooponly = G_SkillProperty(SKILLP_SpawnMultiCoopOnly); if (mthing->EdNum == 0 || mthing->EdNum == -1) return NULL; @@ -5837,9 +5838,9 @@ AActor *FLevelLocals::SpawnMapThing (FMapThing *mthing, int position) { mask = MTF_COOPERATIVE; } - else if (spawnmulti) + else if (spawnmulti || spawnmulti_cooponly) { - mask = MTF_COOPERATIVE|MTF_SINGLE; + mask = spawnmulti_cooponly ? MTF_COOPERATIVE : (MTF_COOPERATIVE|MTF_SINGLE); } else { diff --git a/wadsrc/static/zscript/constants.zs b/wadsrc/static/zscript/constants.zs index b4f2d85b7..f22204cbf 100644 --- a/wadsrc/static/zscript/constants.zs +++ b/wadsrc/static/zscript/constants.zs @@ -1024,6 +1024,7 @@ enum ESkillProperty SKILLP_PlayerRespawn, SKILLP_SpawnMulti, SKILLP_InstantReaction, + SKILLP_SpawnMultiCoopOnly, }; enum EFSkillProperty // floating point properties { From aacc4d7278a62ad226a4aa3556df84ee42d59fc6 Mon Sep 17 00:00:00 2001 From: "Dileep V. Reddy" Date: Mon, 9 Sep 2024 19:24:15 -0600 Subject: [PATCH 13/13] PointToPseudoPitch() was being called even when viewpoint was not allowed out of bounds. And its sqrt was slow even when it was necessary (thanks dpjudas for the speedup code). --- src/rendering/hwrenderer/scene/hw_bsp.cpp | 61 +++++++++++-------- src/rendering/hwrenderer/scene/hw_clipper.cpp | 15 +++++ 2 files changed, 50 insertions(+), 26 deletions(-) diff --git a/src/rendering/hwrenderer/scene/hw_bsp.cpp b/src/rendering/hwrenderer/scene/hw_bsp.cpp index fafa680d4..0904a0207 100644 --- a/src/rendering/hwrenderer/scene/hw_bsp.cpp +++ b/src/rendering/hwrenderer/scene/hw_bsp.cpp @@ -324,25 +324,28 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip) return; } - auto &clipperv = *vClipper; - angle_t startPitch = clipperv.PointToPseudoPitch(seg->v1->fX(), seg->v1->fY(), currentsector->floorplane.ZatPoint(seg->v1)); - angle_t endPitch = clipperv.PointToPseudoPitch(seg->v1->fX(), seg->v1->fY(), currentsector->ceilingplane.ZatPoint(seg->v1)); - angle_t startPitch2 = clipperv.PointToPseudoPitch(seg->v2->fX(), seg->v2->fY(), currentsector->floorplane.ZatPoint(seg->v2)); - angle_t endPitch2 = clipperv.PointToPseudoPitch(seg->v2->fX(), seg->v2->fY(), currentsector->ceilingplane.ZatPoint(seg->v2)); - angle_t temp; - // Wall can be tilted from viewpoint perspective. Find vertical extent on screen in psuedopitch units (0 to 2, bottom to top) - if(int(startPitch) > int(startPitch2)) // Handle zero crossing + if (Viewpoint.IsAllowedOoB()) // No need for vertical clipping if viewpoint not allowed out of bounds { - temp = startPitch; startPitch = startPitch2; startPitch2 = temp; // exchange - } - if(int(endPitch) > int(endPitch2)) // Handle zero crossing - { - temp = endPitch; endPitch = endPitch2; endPitch2 = temp; // exchange - } + auto &clipperv = *vClipper; + angle_t startPitch = clipperv.PointToPseudoPitch(seg->v1->fX(), seg->v1->fY(), currentsector->floorplane.ZatPoint(seg->v1)); + angle_t endPitch = clipperv.PointToPseudoPitch(seg->v1->fX(), seg->v1->fY(), currentsector->ceilingplane.ZatPoint(seg->v1)); + angle_t startPitch2 = clipperv.PointToPseudoPitch(seg->v2->fX(), seg->v2->fY(), currentsector->floorplane.ZatPoint(seg->v2)); + angle_t endPitch2 = clipperv.PointToPseudoPitch(seg->v2->fX(), seg->v2->fY(), currentsector->ceilingplane.ZatPoint(seg->v2)); + angle_t temp; + // Wall can be tilted from viewpoint perspective. Find vertical extent on screen in psuedopitch units (0 to 2, bottom to top) + if(int(startPitch) > int(startPitch2)) // Handle zero crossing + { + temp = startPitch; startPitch = startPitch2; startPitch2 = temp; // exchange + } + if(int(endPitch) > int(endPitch2)) // Handle zero crossing + { + temp = endPitch; endPitch = endPitch2; endPitch2 = temp; // exchange + } - if (!clipperv.SafeCheckRange(startPitch, endPitch2)) - { - return; + if (!clipperv.SafeCheckRange(startPitch, endPitch2)) + { + return; + } } if (!r_radarclipper || (Level->flags3 & LEVEL3_NOFOGOFWAR) || clipperr.SafeCheckRange(startAngleR, endAngleR)) @@ -734,7 +737,7 @@ void HWDrawInfo::DoSubsector(subsector_t * sub) int count = sub->numlines; seg_t * seg = sub->firstline; bool anglevisible = false; - bool pitchvisible = false; + bool pitchvisible = !(Viewpoint.IsAllowedOoB()); // No vertical clipping if viewpoint is not allowed out of bounds bool radarvisible = false; angle_t pitchtemp; angle_t pitchmin = ANGLE_90; @@ -751,15 +754,21 @@ void HWDrawInfo::DoSubsector(subsector_t * sub) angle_t endAngleR = clipperr.PointToPseudoAngle(seg->v1->fX(), seg->v1->fY()); if (startAngleR-endAngleR >= ANGLE_180) radarvisible |= (clipperr.SafeCheckRange(startAngleR, endAngleR) || (Level->flags3 & LEVEL3_NOFOGOFWAR) || ((sub->flags & SSECMF_DRAWN) && !deathmatch)); - pitchmin = clipperv.PointToPseudoPitch(seg->v1->fX(), seg->v1->fY(), sector->floorplane.ZatPoint(seg->v1)); - pitchmax = clipperv.PointToPseudoPitch(seg->v1->fX(), seg->v1->fY(), sector->ceilingplane.ZatPoint(seg->v1)); - pitchvisible |= clipperv.SafeCheckRange(pitchmin, pitchmax); + if (!pitchvisible) + { + pitchmin = clipperv.PointToPseudoPitch(seg->v1->fX(), seg->v1->fY(), sector->floorplane.ZatPoint(seg->v1)); + pitchmax = clipperv.PointToPseudoPitch(seg->v1->fX(), seg->v1->fY(), sector->ceilingplane.ZatPoint(seg->v1)); + pitchvisible |= clipperv.SafeCheckRange(pitchmin, pitchmax); + } if (pitchvisible && anglevisible && radarvisible) break; - pitchtemp = clipperv.PointToPseudoPitch(seg->v2->fX(), seg->v2->fY(), sector->floorplane.ZatPoint(seg->v2)); - if (int(pitchmin) > int(pitchtemp)) pitchmin = pitchtemp; - pitchtemp = clipperv.PointToPseudoPitch(seg->v2->fX(), seg->v2->fY(), sector->ceilingplane.ZatPoint(seg->v2)); - if (int(pitchmax) < int(pitchtemp)) pitchmax = pitchtemp; - pitchvisible |= clipperv.SafeCheckRange(pitchmin, pitchmax); + if (!pitchvisible) + { + pitchtemp = clipperv.PointToPseudoPitch(seg->v2->fX(), seg->v2->fY(), sector->floorplane.ZatPoint(seg->v2)); + if (int(pitchmin) > int(pitchtemp)) pitchmin = pitchtemp; + pitchtemp = clipperv.PointToPseudoPitch(seg->v2->fX(), seg->v2->fY(), sector->ceilingplane.ZatPoint(seg->v2)); + if (int(pitchmax) < int(pitchtemp)) pitchmax = pitchtemp; + pitchvisible |= clipperv.SafeCheckRange(pitchmin, pitchmax); + } if (pitchvisible && anglevisible && radarvisible) break; } seg++; diff --git a/src/rendering/hwrenderer/scene/hw_clipper.cpp b/src/rendering/hwrenderer/scene/hw_clipper.cpp index 94713f107..6b256851b 100644 --- a/src/rendering/hwrenderer/scene/hw_clipper.cpp +++ b/src/rendering/hwrenderer/scene/hw_clipper.cpp @@ -39,6 +39,11 @@ #include "g_levellocals.h" #include "basics.h" +#if defined(__SSE2__) || defined(_M_X64) +#include +#define USE_SSE2 +#endif + unsigned Clipper::starttime; Clipper::Clipper() @@ -440,7 +445,17 @@ angle_t Clipper::PointToPseudoPitch(double x, double y, double z) } else { +#ifdef USE_SSE2 + __m128 mvecx = _mm_set_ss(vecx); + __m128 mvecy = _mm_set_ss(vecy); + __m128 mvecz = _mm_set_ss(vecz); + __m128 dot = _mm_add_ss(_mm_mul_ss(mvecx, mvecx), _mm_mul_ss(mvecy, mvecy)); + __m128 notsignbit = _mm_castsi128_ps(_mm_cvtsi32_si128(~(1 << 31))); + __m128 fabsvecz = _mm_and_ps(mvecz, notsignbit); + double result = _mm_cvtss_f32((_mm_div_ss(mvecz, _mm_add_ss(_mm_sqrt_ss(dot), fabsvecz)))); +#else double result = vecz / (g_sqrt(vecx*vecx + vecy*vecy) + fabs(vecz)); // -ffast-math compile flag applies to this file, yes? +#endif if ((vecx * viewpoint->TanCos + vecy * viewpoint->TanSin) <= 0.0) // Point is behind viewpoint { result = 2.0 - result;