diff --git a/libraries/ZWidget/src/window/win32/win32displaywindow.cpp b/libraries/ZWidget/src/window/win32/win32displaywindow.cpp index eafc4f527..d8e9a7f1c 100644 --- a/libraries/ZWidget/src/window/win32/win32displaywindow.cpp +++ b/libraries/ZWidget/src/window/win32/win32displaywindow.cpp @@ -61,7 +61,7 @@ Win32DisplayWindow::Win32DisplayWindow(DisplayWindowHost* windowHost, bool popup 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; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 315a02798..457201a09 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/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/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 fdcb93a9b..8e6cf8633 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1807,7 +1807,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; @@ -3442,7 +3442,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. @@ -3459,13 +3459,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/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/d_dehacked.cpp b/src/gamedata/d_dehacked.cpp index 029878176..77e9d1320 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); @@ -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 @@ -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/src/gamedata/g_mapinfo.h b/src/gamedata/g_mapinfo.h index 1e9419739..1ee37ec0e 100644 --- a/src/gamedata/g_mapinfo.h +++ b/src/gamedata/g_mapinfo.h @@ -517,6 +517,7 @@ enum ESkillProperty SKILLP_PlayerRespawn, SKILLP_SpawnMulti, SKILLP_InstantReaction, + SKILLP_SpawnMultiCoopOnly, }; enum EFSkillProperty // floating point properties { @@ -562,6 +563,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/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/actor.h b/src/playsim/actor.h index 1adccf81c..38c2b47a0 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/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/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index e84783c33..6e47a7f33 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/src/rendering/hwrenderer/scene/hw_bsp.cpp b/src/rendering/hwrenderer/scene/hw_bsp.cpp index 5dd103ab3..45aa185c2 100644 --- a/src/rendering/hwrenderer/scene/hw_bsp.cpp +++ b/src/rendering/hwrenderer/scene/hw_bsp.cpp @@ -327,25 +327,28 @@ void HWDrawInfo::AddLine (seg_t *seg, bool portalclip, FRenderState& state) 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)) @@ -737,7 +740,7 @@ void HWDrawInfo::DoSubsector(subsector_t * sub, FRenderState& state) 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; @@ -754,15 +757,21 @@ void HWDrawInfo::DoSubsector(subsector_t * sub, FRenderState& state) 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_drawinfo.cpp b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp index 78bae4534..9d929a962 100644 --- a/src/rendering/hwrenderer/scene/hw_drawinfo.cpp +++ b/src/rendering/hwrenderer/scene/hw_drawinfo.cpp @@ -321,9 +321,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; diff --git a/src/rendering/hwrenderer/scene/hw_sprites.cpp b/src/rendering/hwrenderer/scene/hw_sprites.cpp index 9304e09c3..2c673f6b6 100644 --- a/src/rendering/hwrenderer/scene/hw_sprites.cpp +++ b/src/rendering/hwrenderer/scene/hw_sprites.cpp @@ -1099,7 +1099,7 @@ void HWSprite::Process(HWDrawInfo *di, FRenderState& state, AActor* thing, secto 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), 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", diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index 6984bcd20..333c26e89 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 = 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. @@ -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/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/inventory.zs b/wadsrc/static/zscript/actors/inventory/inventory.zs index 2e6544093..52009f2e1 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)) @@ -646,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)) { @@ -695,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)) @@ -847,6 +849,8 @@ class Inventory : Actor return; localPickUp = give != self; + if (localPickUp) + give.ClearCounters(); } bool res; @@ -1124,6 +1128,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 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/constants.zs b/wadsrc/static/zscript/constants.zs index d99daa9e2..80a4f11fc 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 { diff --git a/wadsrc/static/zscript/doombase.zs b/wadsrc/static/zscript/doombase.zs index daaf143bf..403763066 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)); 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