diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 966d2d4da..b157b4a63 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -11,26 +11,17 @@ body: ## Please fill out forms as cleanly as possible. #### Make sure that you have * properly edited & filled in the title of this bug report - - type: dropdown + - type: input id: version attributes: label: GZDoom version description: | What version are you using? - Run `gzdoom --version` + Run `gzdoom --version` or check in the console in game. Make sure to update to latest [release](https://github.com/coelckers/gzdoom/releases) version and test again before continuing. - multiple: false - options: - - 4.6.1 - - 4.6.0 - - 4.5.0 - - 4.4.2 - - 4.4.1 - - 4.4.0 - - Git - - Other + placeholder: "ex: GZDoom 4.0.0, Git version, Branch, other" validations: - required: true + required: false - type: dropdown id: gameid attributes: diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index 6bf1d971a..60c7440fe 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -11,26 +11,17 @@ body: ## Please fill out forms as cleanly as possible. #### Make sure that you have * properly edited & filled in the title of this bug report - - type: dropdown + - type: input id: version attributes: label: GZDoom version description: | What version are you using? - Run `gzdoom --version` + Run `gzdoom --version` or check in the console in game. Make sure to update to latest [release](https://github.com/coelckers/gzdoom/releases) version and test again before continuing. - multiple: false - options: - - 4.6.1 - - 4.6.0 - - 4.5.0 - - 4.4.2 - - 4.4.1 - - 4.4.0 - - Git - - Other + placeholder: "ex: GZDoom 4.0.0, Git version, Branch, other" validations: - required: true + required: false - type: dropdown id: gameid attributes: diff --git a/src/common/2d/v_2ddrawer.h b/src/common/2d/v_2ddrawer.h index ebcef6142..74d5935a6 100644 --- a/src/common/2d/v_2ddrawer.h +++ b/src/common/2d/v_2ddrawer.h @@ -243,7 +243,7 @@ public: bool mIsFirstPass = true; }; -struct DShape2DBufferInfo : NoVirtualRefCountedBase +struct DShape2DBufferInfo : RefCountedBase { TArray buffers; bool needsVertexUpload = true; diff --git a/src/common/fonts/v_font.cpp b/src/common/fonts/v_font.cpp index 1305fc413..0042f48c3 100644 --- a/src/common/fonts/v_font.cpp +++ b/src/common/fonts/v_font.cpp @@ -94,6 +94,7 @@ FFont *V_GetFont(const char *name, const char *fontlumpname) { if (!stricmp(name, "DBIGFONT")) name = "BigFont"; else if (!stricmp(name, "CONFONT")) name = "ConsoleFont"; // several mods have used the name CONFONT directly and effectively duplicated the font. + else if (!stricmp(name, "INDEXFON")) name = "IndexFont"; // Same here - for whatever reason some people had to use its 8 character name... FFont *font = FFont::FindFont (name); if (font == nullptr) { @@ -873,6 +874,7 @@ void V_InitFonts() NewSmallFont = CreateHexLumpFont2("NewSmallFont", lump); CurrentConsoleFont = NewConsoleFont; ConFont = V_GetFont("ConsoleFont", "CONFONT"); + V_GetFont("IndexFont", "INDEXFON"); // detect potential replacements for this one. } void V_LoadTranslations() diff --git a/src/common/menu/menudef.cpp b/src/common/menu/menudef.cpp index 280349781..ef3397df0 100644 --- a/src/common/menu/menudef.cpp +++ b/src/common/menu/menudef.cpp @@ -910,7 +910,7 @@ static void ParseOptionSettings(FScanner &sc) else if (sc.Compare("Linespacing")) { sc.MustGetNumber(); - OptionSettings.mLinespacing = sc.Number; + // ignored } else if (sc.Compare("LabelOffset")) { @@ -1402,6 +1402,7 @@ void M_ParseMenuDefs() DefaultOptionMenuSettings = Create(); DefaultListMenuSettings->Reset(); DefaultOptionMenuSettings->Reset(); + OptionSettings.mLinespacing = 17; int IWADMenu = fileSystem.CheckNumForName("MENUDEF", ns_global, fileSystem.GetIwadNum()); diff --git a/src/common/objects/dobject.cpp b/src/common/objects/dobject.cpp index 9f4a164e4..8516229de 100644 --- a/src/common/objects/dobject.cpp +++ b/src/common/objects/dobject.cpp @@ -229,6 +229,7 @@ DObject::DObject () ObjNext = GC::Root; GCNext = nullptr; GC::Root = this; + GC::AllocCount++; } DObject::DObject (PClass *inClass) @@ -238,6 +239,7 @@ DObject::DObject (PClass *inClass) ObjNext = GC::Root; GCNext = nullptr; GC::Root = this; + GC::AllocCount++; } //========================================================================== @@ -275,6 +277,7 @@ DObject::~DObject () void DObject::Release() { + if (GC::AllocCount > 0) GC::AllocCount--; DObject **probe; // Unlink this object from the GC list. diff --git a/src/common/objects/dobjgc.cpp b/src/common/objects/dobjgc.cpp index 9afa0b0af..58b27c4b7 100644 --- a/src/common/objects/dobjgc.cpp +++ b/src/common/objects/dobjgc.cpp @@ -108,6 +108,7 @@ namespace GC size_t AllocBytes; size_t Threshold; size_t Estimate; +size_t AllocCount; DObject *Gray; DObject *Root; DObject *SoftRoots; diff --git a/src/common/objects/dobjgc.h b/src/common/objects/dobjgc.h index e3f8b85b1..d01e52cf6 100644 --- a/src/common/objects/dobjgc.h +++ b/src/common/objects/dobjgc.h @@ -43,6 +43,9 @@ namespace GC // Number of bytes currently allocated through M_Malloc/M_Realloc. extern size_t AllocBytes; + // Number of allocated objects since last CheckGC call. + extern size_t AllocCount; + // Amount of memory to allocate before triggering a collection. extern size_t Threshold; @@ -105,10 +108,15 @@ namespace GC } // Check if it's time to collect, and do a collection step if it is. - static inline void CheckGC() + static inline bool CheckGC() { + AllocCount = 0; if (AllocBytes >= Threshold) + { Step(); + return true; + } + return false; } // Forces a collection to start now. diff --git a/src/events.cpp b/src/events.cpp index 623d22203..a9362e03b 100755 --- a/src/events.cpp +++ b/src/events.cpp @@ -294,11 +294,11 @@ void EventManager::WorldLoaded() } } -void EventManager::WorldUnloaded() +void EventManager::WorldUnloaded(const FString& nextmap) { for (DStaticEventHandler* handler = LastEventHandler; handler; handler = handler->prev) { - handler->WorldUnloaded(); + handler->WorldUnloaded(nextmap); } } @@ -629,6 +629,7 @@ DEFINE_FIELD_X(RenderEvent, FRenderEvent, Camera); DEFINE_FIELD_X(WorldEvent, FWorldEvent, IsSaveGame); DEFINE_FIELD_X(WorldEvent, FWorldEvent, IsReopen); +DEFINE_FIELD_X(WorldEvent, FWorldEvent, NextMap); DEFINE_FIELD_X(WorldEvent, FWorldEvent, Thing); DEFINE_FIELD_X(WorldEvent, FWorldEvent, Inflictor); DEFINE_FIELD_X(WorldEvent, FWorldEvent, Damage); @@ -769,13 +770,14 @@ void DStaticEventHandler::WorldLoaded() } } -void DStaticEventHandler::WorldUnloaded() +void DStaticEventHandler::WorldUnloaded(const FString& nextmap) { IFVIRTUAL(DStaticEventHandler, WorldUnloaded) { // don't create excessive DObjects if not going to be processed anyway if (isEmpty(func)) return; FWorldEvent e = owner->SetupWorldEvent(); + e.NextMap = nextmap; VMValue params[2] = { (DStaticEventHandler*)this, &e }; VMCall(func, params, 2, nullptr, 0); } diff --git a/src/events.h b/src/events.h index 86e8e941e..f5ad75d88 100755 --- a/src/events.h +++ b/src/events.h @@ -78,7 +78,7 @@ public: // void WorldLoaded(); - void WorldUnloaded(); + void WorldUnloaded(const FString& nextmap); void WorldThingSpawned(AActor* actor); void WorldThingDied(AActor* actor, AActor* inflictor); void WorldThingGround(AActor* actor, FState* st); @@ -144,6 +144,7 @@ struct FWorldEvent // for loaded/unloaded bool IsSaveGame = false; bool IsReopen = false; + FString NextMap; // for thingspawned, thingdied, thingdestroyed AActor* Thing = nullptr; // for thingdied AActor* Inflictor = nullptr; // can be null - for damagemobj @@ -232,7 +233,7 @@ struct EventManager // called right after the map has loaded (approximately same time as OPEN ACS scripts) void WorldLoaded(); // called when the map is about to unload (approximately same time as UNLOADING ACS scripts) - void WorldUnloaded(); + void WorldUnloaded(const FString& nextmap); // called around PostBeginPlay of each actor. void WorldThingSpawned(AActor* actor); // called after AActor::Die of each actor. diff --git a/src/g_game.cpp b/src/g_game.cpp index fdbc18aa8..f394d1a85 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1316,6 +1316,15 @@ void G_Ticker () default: break; } + // Do some more aggressive GC maintenance when the game ticker is inactive. + if ((gamestate != GS_LEVEL && gamestate != GS_TITLELEVEL) || paused || P_CheckTickerPaused()) + { + size_t ac = std::max(10, GC::AllocCount); + for (size_t i = 0; i < ac; i++) + { + if (!GC::CheckGC()) break; + } + } // [MK] Additional ticker for UI events right after all others primaryLevel->localEventManager->PostUiTick(); diff --git a/src/g_level.cpp b/src/g_level.cpp index 358e567e0..6139e1c04 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -468,7 +468,7 @@ void G_InitNew (const char *mapname, bool bTitleLevel) // did we have any level before? if (primaryLevel->info != nullptr) - staticEventManager.WorldUnloaded(); + staticEventManager.WorldUnloaded(FString()); // [MK] don't pass the new map, as it's not a level transition if (!savegamerestore) { @@ -701,10 +701,10 @@ void FLevelLocals::ChangeLevel(const char *levelname, int position, int inflags, for (auto Level : AllLevels()) { // Todo: This must be exolicitly sandboxed! - Level->localEventManager->WorldUnloaded(); + Level->localEventManager->WorldUnloaded(nextlevel); } // [ZZ] unsafe world unload (changemap != map) - staticEventManager.WorldUnloaded(); + staticEventManager.WorldUnloaded(nextlevel); unloading = false; STAT_ChangeLevel(nextlevel, this); diff --git a/src/gamedata/d_dehacked.cpp b/src/gamedata/d_dehacked.cpp index 85c167fe0..a82146ad5 100644 --- a/src/gamedata/d_dehacked.cpp +++ b/src/gamedata/d_dehacked.cpp @@ -764,22 +764,6 @@ static void CreateLineEffectFunc(FunctionCallEmitter &emitters, int value1, int emitters.AddParameterIntConst(value2); // tag } -// No misc, but it's basically A_Explode with an added effect -static void CreateNailBombFunc(FunctionCallEmitter &emitters, int value1, int value2, MBFParamState* state) -{ // A_Explode - // This one does not actually have MBF-style parameters. But since - // we're aliasing it to an extension of A_Explode... - emitters.AddParameterIntConst(-1); // damage - emitters.AddParameterIntConst(-1); // distance - emitters.AddParameterIntConst(1); // flags (1=XF_HURTSOURCE) - emitters.AddParameterIntConst(0); // alert - emitters.AddParameterIntConst(0); // fulldamagedistance - emitters.AddParameterIntConst(30); // nails - emitters.AddParameterIntConst(10); // naildamage - emitters.AddParameterPointerConst(PClass::FindClass(NAME_BulletPuff)); // itemtype - emitters.AddParameterIntConst(NAME_None); // damage type -} - static void CreateSpawnObjectFunc(FunctionCallEmitter& emitters, int value1, int value2, MBFParamState* state) { state->ValidateArgCount(8, "A_SpawnObject"); @@ -936,7 +920,6 @@ static void (*MBFCodePointerFactories[])(FunctionCallEmitter&, int, int, MBFPara { // Die and Detonate are not in this list because these codepointers have // no dehacked arguments and therefore do not need special handling. - // NailBomb has no argument but is implemented as new parameters for A_Explode. CreateMushroomFunc, CreateSpawnFunc, CreateTurnFunc, @@ -945,7 +928,6 @@ static void (*MBFCodePointerFactories[])(FunctionCallEmitter&, int, int, MBFPara CreatePlaySoundFunc, CreateRandomJumpFunc, CreateLineEffectFunc, - CreateNailBombFunc, CreateSpawnObjectFunc, CreateMonsterProjectileFunc, CreateMonsterBulletAttackFunc, diff --git a/src/maploader/udmf.cpp b/src/maploader/udmf.cpp index 8cdfe3d3d..f11774157 100644 --- a/src/maploader/udmf.cpp +++ b/src/maploader/udmf.cpp @@ -109,21 +109,22 @@ static inline bool P_IsThingSpecial(int specnum) return (specnum >= Thing_Projectile && specnum <= Thing_SpawnNoFog) || specnum == Thing_SpawnFacing || specnum == Thing_ProjectileIntercept || specnum == Thing_ProjectileAimed; } - -enum +namespace { - Dm=1, - Ht=2, - Hx=4, - St=8, - Zd=16, - Zdt=32, - Va=64, - - // will be extended later. Unknown namespaces will always be treated like the base - // namespace for each game -}; + enum + { + Dm=1, // Doom + Ht=2, // Heretic + Hx=4, // Hexen + St=8, // Strife + Zd=16, // ZDoom + Zdt=32, // ZDoom Translated + Va=64, // Vavoom + // will be extended later. Unknown namespaces will always be treated like the base + // namespace for each game + }; +} #define CHECK_N(f) if (!(namespace_bits&(f))) break; //=========================================================================== diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index 8ca386766..741622127 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -584,7 +584,7 @@ bool AActor::SetState (FState *newstate, bool nofunction) newstate = newstate->GetNextState(); } while (tics == 0); - if (GetInfo()->LightAssociations.Size() || (newstate && newstate->Light > 0)) + if (GetInfo()->LightAssociations.Size() || (state && state->Light > 0)) { flags8 |= MF8_RECREATELIGHTS; Level->flags3 |= LEVEL3_LIGHTCREATED; diff --git a/wadsrc/static/dehsupp.txt b/wadsrc/static/dehsupp.txt index 744e65dc0..8525d1164 100644 --- a/wadsrc/static/dehsupp.txt +++ b/wadsrc/static/dehsupp.txt @@ -1193,12 +1193,11 @@ Aliases A_PlaySound, A_PlaySound, A_RandomJump, A_Jump, A_LineEffect, A_LineEffect, - A_NailBomb, A_Explode, A_SpawnObject, MBF21_SpawnObject, A_MonsterProjectile, MBF21_MonsterProjectile, A_MonsterBulletAttack, MBF21_MonsterBulletAttack, A_MonsterMeleeAttack, MBF21_MonsterMeleeAttack, - A_RadiusDamage, A_Explode, + A_RadiusDamage, A_RadiusDamage, A_HealChase, MBF21_HealChase, A_SeekTracer, A_SeekerMissile, A_FindTracer, A_FindTracer, diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 8e7a316db..a5878a3c6 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -344,18 +344,6 @@ OptionValue AutoOffOn 1, "$OPTVAL_ON" } -OptionMenuSettings -{ - // These can be overridden if a different menu fonts requires it. - Linespacing 17 - /* - IfGame(Heretic, Hexen) - { - Linespacing 9 - } - */ -} - DefaultOptionMenu { Position -15 diff --git a/wadsrc/static/zscript/actors/attacks.zs b/wadsrc/static/zscript/actors/attacks.zs index 102451abd..edefdd24f 100644 --- a/wadsrc/static/zscript/actors/attacks.zs +++ b/wadsrc/static/zscript/actors/attacks.zs @@ -616,6 +616,18 @@ extend class Actor return count; } + deprecated("2.3", "For Dehacked use only") + void A_NailBomb() + { + A_Explode(nails:30); + } + + deprecated("2.3", "For Dehacked use only") + void A_RadiusDamage(int dam, int dist) + { + A_Explode(dam, dist); + } + //========================================================================== // // A_RadiusThrust diff --git a/wadsrc/static/zscript/actors/doom/weaponfist.zs b/wadsrc/static/zscript/actors/doom/weaponfist.zs index c1535f8c7..711ca97d9 100644 --- a/wadsrc/static/zscript/actors/doom/weaponfist.zs +++ b/wadsrc/static/zscript/actors/doom/weaponfist.zs @@ -66,9 +66,10 @@ extend class Actor damage *= 10; double ang = angle + Random2[Punch]() * (5.625 / 256); - double pitch = AimLineAttack (ang, MeleeRange + MELEEDELTA, null, 0., ALF_CHECK3D); + double range = MeleeRange + MELEEDELTA; + double pitch = AimLineAttack (ang, range, null, 0., ALF_CHECK3D); - LineAttack (ang, MeleeRange, pitch, damage, 'Melee', "BulletPuff", LAF_ISMELEEATTACK, t); + LineAttack (ang, range, pitch, damage, 'Melee', "BulletPuff", LAF_ISMELEEATTACK, t); // turn to face target if (t.linetarget) diff --git a/wadsrc/static/zscript/actors/player/player.zs b/wadsrc/static/zscript/actors/player/player.zs index a3f94408f..c5795537a 100644 --- a/wadsrc/static/zscript/actors/player/player.zs +++ b/wadsrc/static/zscript/actors/player/player.zs @@ -2084,7 +2084,7 @@ class PlayerPawn : Actor me.GiveDefaultInventory(); } } - + //=========================================================================== // // FWeaponSlot :: PickWeapon diff --git a/wadsrc/static/zscript/events.zs b/wadsrc/static/zscript/events.zs index 6db6fb1e2..7492ea2b0 100644 --- a/wadsrc/static/zscript/events.zs +++ b/wadsrc/static/zscript/events.zs @@ -15,6 +15,8 @@ struct WorldEvent native play version("2.4") native readonly bool IsSaveGame; // this will be true if we are re-entering the hub level. native readonly bool IsReopen; + // for unloaded, name of next map (if any) + native readonly String NextMap; // for thingspawned/thingdied/thingdestroyed/thingground native readonly Actor Thing; // for thingdied. can be null