From cd180d29c7d7a7ad29024bb148acc25975e150a5 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 14 Apr 2017 13:31:58 +0200 Subject: [PATCH 01/18] - block direct use of 'new' for DObjects. This is to ensure that the Class pointer can be set right on creation. ZDoom had always depended on handling this lazily which poses some problems for the VM. So now there is a variadic Create function taking care of that, but to ensure that it gets used, direct access to the new operator has been blocked. This also neccessitated making DArgs a regular object because they get created before the type system is up. Since the few uses of DArgs are easily controllable this wasn't a big issue. - did a bit of optimization on the bots' decision making whether to pick up a health item or not. --- src/actor.h | 2 +- src/b_game.cpp | 2 +- src/b_think.cpp | 20 ++++-- src/c_console.cpp | 4 +- src/c_dispatch.cpp | 4 +- src/d_main.cpp | 15 ++-- src/decallib.cpp | 8 +-- src/dobject.h | 43 ++++++++---- src/dobjgc.cpp | 5 +- src/dobjtype.cpp | 2 +- src/dthinker.cpp | 4 +- src/dthinker.h | 3 +- src/fragglescript/t_func.cpp | 6 +- src/fragglescript/t_load.cpp | 2 +- src/fragglescript/t_prepro.cpp | 2 +- src/fragglescript/t_script.cpp | 8 +-- src/fragglescript/t_spec.cpp | 2 +- src/fragglescript/t_variable.cpp | 2 +- src/g_game.cpp | 8 +-- src/g_level.cpp | 2 +- src/g_shared/a_action.cpp | 2 +- src/g_shared/a_decals.cpp | 8 +-- src/g_shared/a_lightning.cpp | 4 +- src/g_shared/a_quake.cpp | 4 +- src/g_shared/a_specialspot.cpp | 2 +- src/g_statusbar/shared_sbar.cpp | 4 +- src/gameconfigfile.cpp | 2 +- src/gameconfigfile.h | 4 +- src/intermission/intermission.cpp | 2 +- src/m_argv.cpp | 86 +++++++++++------------ src/m_argv.h | 17 +++-- src/m_cheat.cpp | 2 +- src/m_misc.cpp | 3 +- src/menu/menudef.cpp | 14 ++-- src/namedef.h | 6 +- src/p_acs.cpp | 20 +++--- src/p_actionfunctions.cpp | 4 +- src/p_ceiling.cpp | 2 +- src/p_conversation.cpp | 4 +- src/p_doors.cpp | 8 +-- src/p_floor.cpp | 16 ++--- src/p_interaction.cpp | 8 +-- src/p_lights.cpp | 42 +++++------ src/p_maputl.cpp | 8 +-- src/p_mobj.cpp | 79 +++++++++++++-------- src/p_pillar.cpp | 2 +- src/p_plats.cpp | 2 +- src/p_pspr.cpp | 4 +- src/p_pusher.cpp | 10 +-- src/p_scroll.cpp | 32 ++++----- src/p_spec.cpp | 10 +-- src/p_spec.h | 2 +- src/p_switch.cpp | 2 +- src/p_tags.cpp | 4 +- src/po_man.cpp | 8 +-- src/posix/cocoa/i_main.mm | 4 +- src/posix/sdl/i_main.cpp | 4 +- src/r_data/r_interpolate.cpp | 12 ++-- src/s_sndseq.cpp | 6 +- src/scripting/backend/codegen.cpp | 20 +++--- src/scripting/decorate/thingdef_parse.cpp | 6 +- src/scripting/symbols.cpp | 4 +- src/scripting/thingdef.cpp | 2 +- src/scripting/types.cpp | 50 ++++++------- src/scripting/zscript/zcc_compile.cpp | 38 +++++----- src/v_text.cpp | 2 +- src/wi_stuff.cpp | 2 +- src/win32/i_main.cpp | 4 +- 68 files changed, 384 insertions(+), 341 deletions(-) diff --git a/src/actor.h b/src/actor.h index 666ca67f8..1eda53028 100644 --- a/src/actor.h +++ b/src/actor.h @@ -613,7 +613,7 @@ public: FActorInfo *GetInfo() const { - return ((PClassActor*)GetClass())->ActorInfo(); + return static_cast(GetClass())->ActorInfo(); } diff --git a/src/b_game.cpp b/src/b_game.cpp index ea80030ff..9a7811095 100644 --- a/src/b_game.cpp +++ b/src/b_game.cpp @@ -375,7 +375,7 @@ bool FCajunMaster::DoAddBot (uint8_t *info, botskill_t skill) D_ReadUserInfoStrings (bnum, &info, false); multiplayer = true; //Prevents cheating and so on; emulates real netgame (almost). - players[bnum].Bot = new DBot; + players[bnum].Bot = Create(); players[bnum].Bot->player = &players[bnum]; players[bnum].Bot->skill = skill; playeringame[bnum] = true; diff --git a/src/b_think.cpp b/src/b_think.cpp index 25932f390..116e70c4f 100644 --- a/src/b_think.cpp +++ b/src/b_think.cpp @@ -313,12 +313,13 @@ void DBot::ThinkForMove (ticcmd_t *cmd) old = player->mo->Pos(); } +int P_GetRealMaxHealth(APlayerPawn *actor, int max); + //BOT_WhatToGet // //Determines if the bot will roam after an item or not. void DBot::WhatToGet (AActor *item) { -#define typeis(x) item->IsKindOf (PClass::FindClass (#x)) if ((item->renderflags & RF_INVISIBLE) //Under respawn and away. || item == prev) { @@ -350,17 +351,24 @@ void DBot::WhatToGet (AActor *item) { auto ac = PClass::FindActor(NAME_Ammo); auto parent = item->GetClass(); - while (parent->ParentClass != ac) parent = (PClassActor*)(parent->ParentClass); + while (parent->ParentClass != ac) parent = static_cast(parent->ParentClass); AInventory *holdingammo = player->mo->FindInventory(parent); if (holdingammo != NULL && holdingammo->Amount >= holdingammo->MaxAmount) { return; } } - else if ((typeis (Megasphere) || typeis (Soulsphere) || typeis (HealthBonus)) && player->mo->health >= deh.MaxSoulsphere) - return; - else if (item->IsKindOf (PClass::FindActor(NAME_Health)) && player->mo->health >= player->mo->GetMaxHealth(true)) - return; + else if (item->GetClass()->TypeName == NAME_Megasphere || item->IsKindOf(NAME_Health)) + { + // do the test with the health item that's actually given. + if (item->GetClass()->TypeName == NAME_Megasphere) item = GetDefaultByName("MegasphereHealth"); + if (item != nullptr) + { + int maxhealth = P_GetRealMaxHealth(player->mo, item->IntVar(NAME_MaxAmount)); + if (player->mo->health >= maxhealth) + return; + } + } if ((dest == NULL || !(dest->flags & MF_SPECIAL)/* || diff --git a/src/c_console.cpp b/src/c_console.cpp index f401ed0e5..ff3f86b20 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -1822,7 +1822,7 @@ void C_MidPrint (FFont *font, const char *msg) AddToConsole (-1, msg); AddToConsole (-1, bar3); - StatusBar->AttachMessage (new DHUDMessage (font, msg, 1.5f, 0.375f, 0, 0, + StatusBar->AttachMessage (Create(font, msg, 1.5f, 0.375f, 0, 0, (EColorRange)PrintColors[PRINTLEVELS], con_midtime), MAKE_ID('C','N','T','R')); } else @@ -1839,7 +1839,7 @@ void C_MidPrintBold (FFont *font, const char *msg) AddToConsole (-1, msg); AddToConsole (-1, bar3); - StatusBar->AttachMessage (new DHUDMessage (font, msg, 1.5f, 0.375f, 0, 0, + StatusBar->AttachMessage (Create (font, msg, 1.5f, 0.375f, 0, 0, (EColorRange)PrintColors[PRINTLEVELS+1], con_midtime), MAKE_ID('C','N','T','R')); } else diff --git a/src/c_dispatch.cpp b/src/c_dispatch.cpp index 464ed4495..996872a66 100644 --- a/src/c_dispatch.cpp +++ b/src/c_dispatch.cpp @@ -636,7 +636,7 @@ void C_DoCommand (const char *cmd, int keynum) } else { - new DStoredCommand (com, beg); + Create (com, beg); } } } @@ -730,7 +730,7 @@ void AddCommandString (char *cmd, int keynum) // Note that deferred commands lose track of which key // (if any) they were pressed from. *brkpt = ';'; - new DWaitingCommand (brkpt, tics); + Create (brkpt, tics); } return; } diff --git a/src/d_main.cpp b/src/d_main.cpp index b03ca3e50..b6a67c06b 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1770,7 +1770,7 @@ bool ConsiderPatches (const char *arg) // //========================================================================== -FExecList *D_MultiExec (DArgs *list, FExecList *exec) +FExecList *D_MultiExec (FArgs *list, FExecList *exec) { for (int i = 0; i < list->NumArgs(); ++i) { @@ -1980,7 +1980,8 @@ static void SetMapxxFlag() static void FinalGC() { - Args = NULL; + delete Args; + Args = nullptr; GC::FinalGC = true; GC::FullGC(); GC::DelSoftRootHead(); // the soft root head will not be collected by a GC so we have to do it explicitly @@ -2264,7 +2265,6 @@ void D_DoomMain (void) int p; const char *v; const char *wad; - DArgs *execFiles; TArray pwads; FString *args; int argcount; @@ -2372,13 +2372,15 @@ void D_DoomMain (void) // Process automatically executed files FExecList *exec; - execFiles = new DArgs; + FArgs *execFiles = new FArgs; GameConfig->AddAutoexec(execFiles, gameinfo.ConfigName); exec = D_MultiExec(execFiles, NULL); + delete execFiles; // Process .cfg files at the start of the command line. execFiles = Args->GatherFiles ("-exec"); exec = D_MultiExec(execFiles, exec); + delete execFiles; // [RH] process all + commands on the command line exec = C_ParseCmdLineParams(exec); @@ -2747,10 +2749,7 @@ void D_DoomMain (void) GC::FullGC(); // perform one final garbage collection after shutdown - for (DObject *obj = GC::Root; obj; obj = obj->ObjNext) - { - obj->ClearClass(); // Delete the Class pointer because the data it points to has been deleted. This will automatically be reset if needed. - } + assert(GC::Root == nullptr); restart++; PClass::bShutdown = false; diff --git a/src/decallib.cpp b/src/decallib.cpp index d9f22499e..aa6fa38b4 100644 --- a/src/decallib.cpp +++ b/src/decallib.cpp @@ -1201,7 +1201,7 @@ void DDecalFader::Tick () DThinker *FDecalFaderAnim::CreateThinker (DBaseDecal *actor, side_t *wall) const { - DDecalFader *fader = new DDecalFader (actor); + DDecalFader *fader = Create (actor); fader->TimeToStartDecay = level.maptime + DecayStart; fader->TimeToEndDecay = fader->TimeToStartDecay + DecayTime; @@ -1227,7 +1227,7 @@ void DDecalStretcher::Serialize(FSerializer &arc) DThinker *FDecalStretcherAnim::CreateThinker (DBaseDecal *actor, side_t *wall) const { - DDecalStretcher *thinker = new DDecalStretcher (actor); + DDecalStretcher *thinker = Create (actor); thinker->TimeToStart = level.maptime + StretchStart; thinker->TimeToStop = thinker->TimeToStart + StretchTime; @@ -1313,7 +1313,7 @@ void DDecalSlider::Serialize(FSerializer &arc) DThinker *FDecalSliderAnim::CreateThinker (DBaseDecal *actor, side_t *wall) const { - DDecalSlider *thinker = new DDecalSlider (actor); + DDecalSlider *thinker = Create (actor); thinker->TimeToStart = level.maptime + SlideStart; thinker->TimeToStop = thinker->TimeToStart + SlideTime; @@ -1432,7 +1432,7 @@ void DDecalColorer::Tick () DThinker *FDecalColorerAnim::CreateThinker (DBaseDecal *actor, side_t *wall) const { - DDecalColorer *Colorer = new DDecalColorer (actor); + DDecalColorer *Colorer = Create(actor); Colorer->TimeToStartDecay = level.maptime + DecayStart; Colorer->TimeToEndDecay = Colorer->TimeToStartDecay + DecayTime; diff --git a/src/dobject.h b/src/dobject.h index 0108e1378..55a05c955 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -35,6 +35,7 @@ #define __DOBJECT_H__ #include +#include #include "doomtype.h" #include "i_system.h" @@ -45,8 +46,6 @@ class FSoundID; class DObject; /* -class DArgs; -class DCanvas; class DConsoleCommand; class DConsoleAlias; class DSeqNode; @@ -231,11 +230,6 @@ public: void SerializeUserVars(FSerializer &arc); virtual void Serialize(FSerializer &arc); - void ClearClass() - { - Class = NULL; - } - // Releases the object from the GC, letting the caller care of any maintenance. void Release(); @@ -264,12 +258,7 @@ public: PClass *GetClass() const { - if (Class == NULL) - { - // Save a little time the next time somebody wants this object's type - // by recording it now. - const_cast(this)->Class = StaticType(); - } + assert(Class != nullptr); return Class; } @@ -278,10 +267,21 @@ public: Class = inClass; } - void *operator new(size_t len) +private: + struct nonew + { + }; + + void *operator new(size_t len, nonew&) { return M_Malloc(len); } +public: + + void operator delete (void *mem, nonew&) + { + M_Free(mem); + } void operator delete (void *mem) { @@ -354,8 +354,23 @@ protected: { M_Free (mem); } + + template + friend T* Create(Args&&... args); + }; +template +T* Create(Args&&... args) +{ + DObject::nonew nono; + T *object = new(nono) T(std::forward(args)...); + object->SetClass(RUNTIME_CLASS(T)); + assert(object->GetClass() != nullptr); // beware of object that get created before the type system is up. + return object; +} + + class AInventory;// // When you write to a pointer to an Object, you must call this for diff --git a/src/dobjgc.cpp b/src/dobjgc.cpp index 03a715329..3631c36ed 100644 --- a/src/dobjgc.cpp +++ b/src/dobjgc.cpp @@ -323,7 +323,6 @@ static void MarkRoot() int i; Gray = NULL; - Mark(Args); Mark(StatusBar); M_MarkMenus(); Mark(DIntermissionController::CurrentIntermission); @@ -351,7 +350,7 @@ static void MarkRoot() // Mark sectors. if (SectorMarker == nullptr && level.sectors.Size() > 0) { - SectorMarker = new DSectorMarker; + SectorMarker = Create(); } else if (level.sectors.Size() == 0) { @@ -592,7 +591,7 @@ void AddSoftRoot(DObject *obj) // Create a new object to root the soft roots off of, and stick // it at the end of the object list, so we know that anything // before it is not a soft root. - SoftRoots = new DObject; + SoftRoots = Create(); SoftRoots->ObjectFlags |= OF_Fixed; probe = &Root; while (*probe != NULL) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 3d27b3a0d..2bd1a8a0f 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -226,7 +226,7 @@ void PClass::StaticInit () // WP_NOCHANGE must point to a valid object, although it does not need to be a weapon. // A simple DObject is enough to give the GC the ability to deal with it, if subjected to it. - WP_NOCHANGE = (AWeapon*)new DObject; + WP_NOCHANGE = (AWeapon*)Create(); WP_NOCHANGE->Release(); } diff --git a/src/dthinker.cpp b/src/dthinker.cpp index 35dd6505c..d68939665 100644 --- a/src/dthinker.cpp +++ b/src/dthinker.cpp @@ -69,7 +69,7 @@ void FThinkerList::AddTail(DThinker *thinker) assert(!(thinker->ObjectFlags & OF_EuthanizeMe)); if (Sentinel == NULL) { - Sentinel = new DThinker(DThinker::NO_LINK); + Sentinel = Create(DThinker::NO_LINK); Sentinel->ObjectFlags |= OF_Sentinel; Sentinel->NextThinker = Sentinel; Sentinel->PrevThinker = Sentinel; @@ -727,7 +727,7 @@ DEFINE_ACTION_FUNCTION(DThinkerIterator, Create) PARAM_PROLOGUE; PARAM_CLASS_DEF(type, DThinker); PARAM_INT_DEF(statnum); - ACTION_RETURN_OBJECT(new DThinkerIterator(type, statnum)); + ACTION_RETURN_OBJECT(Create(type, statnum)); } DEFINE_ACTION_FUNCTION(DThinkerIterator, Next) diff --git a/src/dthinker.h b/src/dthinker.h index a8c374bb7..c7a768ae3 100644 --- a/src/dthinker.h +++ b/src/dthinker.h @@ -91,9 +91,10 @@ public: static DThinker *FirstThinker (int statnum); static bool bSerialOverride; -private: + // only used internally but Create needs access. enum no_link_type { NO_LINK }; DThinker(no_link_type) throw(); +private: static void DestroyThinkersInList (FThinkerList &list); static int TickThinkers (FThinkerList *list, FThinkerList *dest); // Returns: # of thinkers ticked static void SaveList(FSerializer &arc, DThinker *node); diff --git a/src/fragglescript/t_func.cpp b/src/fragglescript/t_func.cpp index 9e1d95ffd..181d20d30 100644 --- a/src/fragglescript/t_func.cpp +++ b/src/fragglescript/t_func.cpp @@ -1873,7 +1873,7 @@ void FParser::SF_FadeLight(void) FSectorTagIterator it(sectag); while ((i = it.Next()) >= 0) { - if (!level.sectors[i].lightingdata) new DLightLevel(&level.sectors[i],destlevel,speed); + if (!level.sectors[i].lightingdata) Create(&level.sectors[i],destlevel,speed); } } } @@ -4036,7 +4036,7 @@ DRunningScript *FParser::SaveCurrentScript() DFraggleThinker *th = DFraggleThinker::ActiveThinker; if (th) { - DRunningScript *runscr = new DRunningScript(Script->trigger, Script, Script->MakeIndex(Rover)); + DRunningScript *runscr = Create(Script->trigger, Script, Script->MakeIndex(Rover)); // hook into chain at start th->AddRunningScript(runscr); @@ -4170,7 +4170,7 @@ void FParser::SF_StartScript() script_error("script %i not defined\n", snum); } - DRunningScript *runscr = new DRunningScript(Script->trigger, script, 0); + DRunningScript *runscr = Create(Script->trigger, script, 0); // hook into chain at start th->AddRunningScript(runscr); } diff --git a/src/fragglescript/t_load.cpp b/src/fragglescript/t_load.cpp index 99818a53d..e27735425 100644 --- a/src/fragglescript/t_load.cpp +++ b/src/fragglescript/t_load.cpp @@ -315,7 +315,7 @@ bool FScriptLoader::ParseInfo(MapData * map) } if (HasScripts) { - new DFraggleThinker; + Create(); DFraggleThinker::ActiveThinker->LevelScript->data = copystring(scriptsrc.GetChars()); if (drownflag==-1) drownflag = (level.maptype != MAPTYPE_DOOM || fsglobal); diff --git a/src/fragglescript/t_prepro.cpp b/src/fragglescript/t_prepro.cpp index 4128e6661..c770e94af 100644 --- a/src/fragglescript/t_prepro.cpp +++ b/src/fragglescript/t_prepro.cpp @@ -156,7 +156,7 @@ void DFsScript::ClearSections() DFsSection *DFsScript::NewSection(const char *brace) { int n = section_hash(brace); - DFsSection *newsec = new DFsSection; + DFsSection *newsec = Create(); newsec->start_index = MakeIndex(brace); newsec->next = sections[n]; diff --git a/src/fragglescript/t_script.cpp b/src/fragglescript/t_script.cpp index 9dc153310..47447d988 100644 --- a/src/fragglescript/t_script.cpp +++ b/src/fragglescript/t_script.cpp @@ -406,8 +406,8 @@ DFraggleThinker::DFraggleThinker() else { ActiveThinker = this; - RunningScripts = new DRunningScript; - LevelScript = new DFsScript; + RunningScripts = Create(); + LevelScript = Create(); LevelScript->parent = global_script; GC::WriteBarrier(this, RunningScripts); GC::WriteBarrier(this, LevelScript); @@ -669,7 +669,7 @@ bool T_RunScript(int snum, AActor * t_trigger) DFsScript *script = th->LevelScript->children[snum]; if(!script) return false; - DRunningScript *runscr = new DRunningScript(t_trigger, script, 0); + DRunningScript *runscr = Create(t_trigger, script, 0); // hook into chain at start th->AddRunningScript(runscr); return true; @@ -699,7 +699,7 @@ void T_Init() if (global_script == NULL) { - global_script = new DFsScript; + global_script = Create(); GC::AddSoftRoot(global_script); init_functions(); } diff --git a/src/fragglescript/t_spec.cpp b/src/fragglescript/t_spec.cpp index d2f0922e2..7703398ed 100644 --- a/src/fragglescript/t_spec.cpp +++ b/src/fragglescript/t_spec.cpp @@ -417,7 +417,7 @@ void FParser::spec_script() return; } - newscript = new DFsScript; + newscript = Create(); // add to scripts list of parent Script->children[scriptnum] = newscript; diff --git a/src/fragglescript/t_variable.cpp b/src/fragglescript/t_variable.cpp index a87d2c1e6..d0a0c8b9f 100644 --- a/src/fragglescript/t_variable.cpp +++ b/src/fragglescript/t_variable.cpp @@ -334,7 +334,7 @@ void DFsVariable::Serialize(FSerializer & ar) DFsVariable *DFsScript::NewVariable(const char *name, int vtype) { - DFsVariable *newvar = new DFsVariable(name); + DFsVariable *newvar = Create(name); newvar->type = vtype; int n = variable_hash(name); diff --git a/src/g_game.cpp b/src/g_game.cpp index 16b818ba7..a32672de7 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -343,7 +343,7 @@ CCMD (weapnext) // [BC] Option to display the name of the weapon being cycled to. if ((displaynametags & 2) && StatusBar && SmallFont && SendItemUse) { - StatusBar->AttachMessage(new DHUDMessageFadeOut(SmallFont, SendItemUse->GetTag(), + StatusBar->AttachMessage(Create(SmallFont, SendItemUse->GetTag(), 1.5f, 0.90f, 0, 0, (EColorRange)*nametagcolor, 2.f, 0.35f), MAKE_ID( 'W', 'E', 'P', 'N' )); } if (SendItemUse != players[consoleplayer].ReadyWeapon) @@ -358,7 +358,7 @@ CCMD (weapprev) // [BC] Option to display the name of the weapon being cycled to. if ((displaynametags & 2) && StatusBar && SmallFont && SendItemUse) { - StatusBar->AttachMessage(new DHUDMessageFadeOut(SmallFont, SendItemUse->GetTag(), + StatusBar->AttachMessage(Create(SmallFont, SendItemUse->GetTag(), 1.5f, 0.90f, 0, 0, (EColorRange)*nametagcolor, 2.f, 0.35f), MAKE_ID( 'W', 'E', 'P', 'N' )); } if (SendItemUse != players[consoleplayer].ReadyWeapon) @@ -394,7 +394,7 @@ CCMD (invnext) } } if ((displaynametags & 1) && StatusBar && SmallFont && who->InvSel) - StatusBar->AttachMessage (new DHUDMessageFadeOut (SmallFont, who->InvSel->GetTag(), + StatusBar->AttachMessage (Create (SmallFont, who->InvSel->GetTag(), 1.5f, 0.80f, 0, 0, (EColorRange)*nametagcolor, 2.f, 0.35f), MAKE_ID('S','I','N','V')); } who->player->inventorytics = 5*TICRATE; @@ -429,7 +429,7 @@ CCMD (invprev) who->InvSel = item; } if ((displaynametags & 1) && StatusBar && SmallFont && who->InvSel) - StatusBar->AttachMessage (new DHUDMessageFadeOut (SmallFont, who->InvSel->GetTag(), + StatusBar->AttachMessage (Create (SmallFont, who->InvSel->GetTag(), 1.5f, 0.80f, 0, 0, (EColorRange)*nametagcolor, 2.f, 0.35f), MAKE_ID('S','I','N','V')); } who->player->inventorytics = 5*TICRATE; diff --git a/src/g_level.cpp b/src/g_level.cpp index 46248deca..ad83a2a05 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1059,7 +1059,7 @@ void G_DoLoadLevel (int position, bool autosave) // [RH] Always save the game when entering a new level. if (autosave && !savegamerestore && disableautosave < 1) { - DAutosaver GCCNOWARN *dummy = new DAutosaver; + DAutosaver GCCNOWARN *dummy = Create(); } } diff --git a/src/g_shared/a_action.cpp b/src/g_shared/a_action.cpp index 71f796a89..627c7323d 100644 --- a/src/g_shared/a_action.cpp +++ b/src/g_shared/a_action.cpp @@ -181,7 +181,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_QueueCorpse) if (sv_corpsequeuesize > 0) { - new DCorpsePointer (self); + Create (self); } return 0; } diff --git a/src/g_shared/a_decals.cpp b/src/g_shared/a_decals.cpp index 9c31256ec..3840a9af9 100644 --- a/src/g_shared/a_decals.cpp +++ b/src/g_shared/a_decals.cpp @@ -522,7 +522,7 @@ void DBaseDecal::Spread (const FDecalTemplate *tpl, side_t *wall, double x, doub DBaseDecal *DBaseDecal::CloneSelf (const FDecalTemplate *tpl, double ix, double iy, double iz, side_t *wall, F3DFloor * ffloor) const { - DBaseDecal *decal = new DBaseDecal(iz); + DBaseDecal *decal = Create(iz); if (decal != NULL) { if (decal->StickToWall (wall, ix, iy, ffloor).isValid()) @@ -615,7 +615,7 @@ DImpactDecal *DImpactDecal::StaticCreate (const FDecalTemplate *tpl, const DVect StaticCreate (tpl_low, pos, wall, ffloor, lowercolor); } DImpactDecal::CheckMax(); - decal = new DImpactDecal (pos.Z); + decal = Create(pos.Z); if (decal == NULL) { return NULL; @@ -651,7 +651,7 @@ DBaseDecal *DImpactDecal::CloneSelf (const FDecalTemplate *tpl, double ix, doubl } DImpactDecal::CheckMax(); - DImpactDecal *decal = new DImpactDecal(iz); + DImpactDecal *decal = Create(iz); if (decal != NULL) { if (decal->StickToWall (wall, ix, iy, ffloor).isValid()) @@ -739,7 +739,7 @@ DBaseDecal *ShootDecal(const FDecalTemplate *tpl, AActor *basisactor, sector_t * { if (permanent) { - decal = new DBaseDecal(trace.HitPos.Z); + decal = Create(trace.HitPos.Z); wall = trace.Line->sidedef[trace.Side]; decal->StickToWall(wall, trace.HitPos.X, trace.HitPos.Y, trace.ffloor); tpl->ApplyToDecal(decal, wall); diff --git a/src/g_shared/a_lightning.cpp b/src/g_shared/a_lightning.cpp index cec7c1800..28cdeceea 100644 --- a/src/g_shared/a_lightning.cpp +++ b/src/g_shared/a_lightning.cpp @@ -184,7 +184,7 @@ void P_StartLightning () DLightningThinker *lightning = LocateLightning (); if (lightning == NULL) { - new DLightningThinker (); + Create(); } } @@ -193,7 +193,7 @@ void P_ForceLightning (int mode) DLightningThinker *lightning = LocateLightning (); if (lightning == NULL) { - lightning = new DLightningThinker (); + lightning = Create(); } if (lightning != NULL) { diff --git a/src/g_shared/a_quake.cpp b/src/g_shared/a_quake.cpp index feb7e6256..6c8e0f2da 100644 --- a/src/g_shared/a_quake.cpp +++ b/src/g_shared/a_quake.cpp @@ -374,7 +374,7 @@ bool P_StartQuakeXYZ(AActor *activator, int tid, int intensityX, int intensityY, { if (activator != NULL) { - new DEarthquake(activator, intensityX, intensityY, intensityZ, duration, damrad, tremrad, + Create(activator, intensityX, intensityY, intensityZ, duration, damrad, tremrad, quakesfx, flags, waveSpeedX, waveSpeedY, waveSpeedZ, falloff, highpoint, rollIntensity, rollWave); return true; } @@ -385,7 +385,7 @@ bool P_StartQuakeXYZ(AActor *activator, int tid, int intensityX, int intensityY, while ( (center = iterator.Next ()) ) { res = true; - new DEarthquake(center, intensityX, intensityY, intensityZ, duration, damrad, tremrad, + Create(center, intensityX, intensityY, intensityZ, duration, damrad, tremrad, quakesfx, flags, waveSpeedX, waveSpeedY, waveSpeedZ, falloff, highpoint, rollIntensity, rollWave); } } diff --git a/src/g_shared/a_specialspot.cpp b/src/g_shared/a_specialspot.cpp index 5c0919820..dc6829d2d 100644 --- a/src/g_shared/a_specialspot.cpp +++ b/src/g_shared/a_specialspot.cpp @@ -248,7 +248,7 @@ void DSpotState::Tick () DSpotState *DSpotState::GetSpotState(bool create) { - if (SpotState == NULL && create) SpotState = new DSpotState; + if (SpotState == NULL && create) SpotState = Create(); return SpotState; } diff --git a/src/g_statusbar/shared_sbar.cpp b/src/g_statusbar/shared_sbar.cpp index 1afe8d46d..4b2b1e727 100644 --- a/src/g_statusbar/shared_sbar.cpp +++ b/src/g_statusbar/shared_sbar.cpp @@ -771,7 +771,7 @@ void DBaseStatusBar::ShowPlayerName () EColorRange color; color = (CPlayer == &players[consoleplayer]) ? CR_GOLD : CR_GREEN; - AttachMessage (new DHUDMessageFadeOut (SmallFont, CPlayer->userinfo.GetName(), + AttachMessage (Create (SmallFont, CPlayer->userinfo.GetName(), 1.5f, 0.92f, 0, 0, color, 2.f, 0.35f), MAKE_ID('P','N','A','M')); } @@ -1664,7 +1664,7 @@ DEFINE_ACTION_FUNCTION(DHUDFont, Create) PARAM_BOOL_DEF(mono); PARAM_INT_DEF(sx); PARAM_INT_DEF(sy); - ACTION_RETURN_POINTER(new DHUDFont(fnt, spac, mono, sy, sy)); + ACTION_RETURN_POINTER(Create(fnt, spac, mono, sy, sy)); } DEFINE_FIELD(DHUDFont, mFont); diff --git a/src/gameconfigfile.cpp b/src/gameconfigfile.cpp index b3fc0b712..ad9a87b20 100644 --- a/src/gameconfigfile.cpp +++ b/src/gameconfigfile.cpp @@ -643,7 +643,7 @@ void FGameConfigFile::CreateStandardAutoExec(const char *section, bool start) } } -void FGameConfigFile::AddAutoexec (DArgs *list, const char *game) +void FGameConfigFile::AddAutoexec (FArgs *list, const char *game) { char section[64]; const char *key; diff --git a/src/gameconfigfile.h b/src/gameconfigfile.h index faeec2e51..1ba066d05 100644 --- a/src/gameconfigfile.h +++ b/src/gameconfigfile.h @@ -37,7 +37,7 @@ #include "doomtype.h" #include "configfile.h" -class DArgs; +class FArgs; class FIWadManager; class FGameConfigFile : public FConfigFile @@ -53,7 +53,7 @@ public: void DoModSetup (const char *gamename); void ArchiveGlobalData (); void ArchiveGameData (const char *gamename); - void AddAutoexec (DArgs *list, const char *gamename); + void AddAutoexec (FArgs *list, const char *gamename); FString GetConfigPath (bool tryProg); void ReadNetVars (); diff --git a/src/intermission/intermission.cpp b/src/intermission/intermission.cpp index 916d1c24d..650f03f87 100644 --- a/src/intermission/intermission.cpp +++ b/src/intermission/intermission.cpp @@ -897,7 +897,7 @@ void F_StartIntermission(FIntermissionDescriptor *desc, bool deleteme, uint8_t s if (state == FSTATE_InLevel) wipegamestate = GS_FINALE; // don't wipe when within a level. viewactive = false; automapactive = false; - DIntermissionController::CurrentIntermission = new DIntermissionController(desc, deleteme, state); + DIntermissionController::CurrentIntermission = Create(desc, deleteme, state); GC::WriteBarrier(DIntermissionController::CurrentIntermission); } diff --git a/src/m_argv.cpp b/src/m_argv.cpp index 395885986..aac5771d6 100644 --- a/src/m_argv.cpp +++ b/src/m_argv.cpp @@ -37,47 +37,45 @@ #include "cmdlib.h" #include "i_system.h" -IMPLEMENT_CLASS(DArgs, false, false) - //=========================================================================== // -// DArgs Default Constructor +// FArgs Default Constructor // //=========================================================================== -DArgs::DArgs() +FArgs::FArgs() { } //=========================================================================== // -// DArgs Copy Constructor +// FArgs Copy Constructor // //=========================================================================== -DArgs::DArgs(const DArgs &other) -: DObject(), Argv(other.Argv) +FArgs::FArgs(const FArgs &other) +: Argv(other.Argv) { } //=========================================================================== // -// DArgs Argv Constructor +// FArgs Argv Constructor // //=========================================================================== -DArgs::DArgs(int argc, char **argv) +FArgs::FArgs(int argc, char **argv) { SetArgs(argc, argv); } //=========================================================================== // -// DArgs String Argv Constructor +// FArgs String Argv Constructor // //=========================================================================== -DArgs::DArgs(int argc, FString *argv) +FArgs::FArgs(int argc, FString *argv) { AppendArgs(argc, argv); } @@ -86,11 +84,11 @@ DArgs::DArgs(int argc, FString *argv) //=========================================================================== // -// DArgs Copy Operator +// FArgs Copy Operator // //=========================================================================== -DArgs &DArgs::operator=(const DArgs &other) +FArgs &FArgs::operator=(const FArgs &other) { Argv = other.Argv; return *this; @@ -98,11 +96,11 @@ DArgs &DArgs::operator=(const DArgs &other) //=========================================================================== // -// DArgs :: SetArgs +// FArgs :: SetArgs // //=========================================================================== -void DArgs::SetArgs(int argc, char **argv) +void FArgs::SetArgs(int argc, char **argv) { Argv.Resize(argc); for (int i = 0; i < argc; ++i) @@ -113,25 +111,25 @@ void DArgs::SetArgs(int argc, char **argv) //=========================================================================== // -// DArgs :: FlushArgs +// FArgs :: FlushArgs // //=========================================================================== -void DArgs::FlushArgs() +void FArgs::FlushArgs() { Argv.Clear(); } //=========================================================================== // -// DArgs :: CheckParm +// FArgs :: CheckParm // // Checks for the given parameter in the program's command line arguments. // Returns the argument number (1 to argc-1) or 0 if not present // //=========================================================================== -int DArgs::CheckParm(const char *check, int start) const +int FArgs::CheckParm(const char *check, int start) const { for (unsigned i = start; i < Argv.Size(); ++i) { @@ -145,14 +143,14 @@ int DArgs::CheckParm(const char *check, int start) const //=========================================================================== // -// DArgs :: CheckParmList +// FArgs :: CheckParmList // // Returns the number of arguments after the parameter (if found) and also // returns a pointer to the first argument. // //=========================================================================== -int DArgs::CheckParmList(const char *check, FString **strings, int start) const +int FArgs::CheckParmList(const char *check, FString **strings, int start) const { unsigned int i, parmat = CheckParm(check, start); @@ -180,14 +178,14 @@ int DArgs::CheckParmList(const char *check, FString **strings, int start) const //=========================================================================== // -// DArgs :: CheckValue +// FArgs :: CheckValue // // Like CheckParm, but it also checks that the parameter has a value after // it and returns that or NULL if not present. // //=========================================================================== -const char *DArgs::CheckValue(const char *check) const +const char *FArgs::CheckValue(const char *check) const { int i = CheckParm(check); @@ -204,14 +202,14 @@ const char *DArgs::CheckValue(const char *check) const //=========================================================================== // -// DArgs :: TakeValue +// FArgs :: TakeValue // // Like CheckValue, except it also removes the parameter and its argument // (if present) from argv. // //=========================================================================== -FString DArgs::TakeValue(const char *check) +FString FArgs::TakeValue(const char *check) { int i = CheckParm(check); FString out; @@ -233,11 +231,11 @@ FString DArgs::TakeValue(const char *check) //=========================================================================== // -// DArgs :: RemoveArg +// FArgs :: RemoveArg // //=========================================================================== -void DArgs::RemoveArgs(const char *check) +void FArgs::RemoveArgs(const char *check) { int i = CheckParm(check); @@ -253,64 +251,64 @@ void DArgs::RemoveArgs(const char *check) //=========================================================================== // -// DArgs :: GetArg +// FArgs :: GetArg // // Gets the argument at a particular position. // //=========================================================================== -const char *DArgs::GetArg(int arg) const +const char *FArgs::GetArg(int arg) const { return ((unsigned)arg < Argv.Size()) ? Argv[arg].GetChars() : NULL; } //=========================================================================== // -// DArgs :: GetArgList +// FArgs :: GetArgList // // Returns a pointer to the FString at a particular position. // //=========================================================================== -FString *DArgs::GetArgList(int arg) const +FString *FArgs::GetArgList(int arg) const { return ((unsigned)arg < Argv.Size()) ? &Argv[arg] : NULL; } //=========================================================================== // -// DArgs :: NumArgs +// FArgs :: NumArgs // //=========================================================================== -int DArgs::NumArgs() const +int FArgs::NumArgs() const { return (int)Argv.Size(); } //=========================================================================== // -// DArgs :: AppendArg +// FArgs :: AppendArg // // Adds another argument to argv. Invalidates any previous results from // GetArgList(). // //=========================================================================== -void DArgs::AppendArg(FString arg) +void FArgs::AppendArg(FString arg) { Argv.Push(arg); } //=========================================================================== // -// DArgs :: AppendArgs +// FArgs :: AppendArgs // // Adds an array of FStrings to argv. // //=========================================================================== -void DArgs::AppendArgs(int argc, const FString *argv) +void FArgs::AppendArgs(int argc, const FString *argv) { if (argv != NULL && argc > 0) { @@ -324,20 +322,20 @@ void DArgs::AppendArgs(int argc, const FString *argv) //=========================================================================== // -// DArgs :: RemoveArg +// FArgs :: RemoveArg // // Removes a single argument from argv. // //=========================================================================== -void DArgs::RemoveArg(int argindex) +void FArgs::RemoveArg(int argindex) { Argv.Delete(argindex); } //=========================================================================== // -// DArgs :: CollectFiles +// FArgs :: CollectFiles // // Takes all arguments after any instance of -param and any arguments before // all switches that end in .extension and combines them into a single @@ -346,7 +344,7 @@ void DArgs::RemoveArg(int argindex) // //=========================================================================== -void DArgs::CollectFiles(const char *param, const char *extension) +void FArgs::CollectFiles(const char *param, const char *extension) { TArray work; unsigned int i; @@ -407,7 +405,7 @@ void DArgs::CollectFiles(const char *param, const char *extension) //=========================================================================== // -// DArgs :: GatherFiles +// FArgs :: GatherFiles // // Returns all the arguments after the first instance of -param. If you want // to combine more than one or get switchless stuff included, you need to @@ -415,11 +413,11 @@ void DArgs::CollectFiles(const char *param, const char *extension) // //=========================================================================== -DArgs *DArgs::GatherFiles(const char *param) const +FArgs *FArgs::GatherFiles(const char *param) const { FString *files; int filecount; filecount = CheckParmList(param, &files); - return new DArgs(filecount, files); + return new FArgs(filecount, files); } diff --git a/src/m_argv.h b/src/m_argv.h index c317256f7..31df56ad8 100644 --- a/src/m_argv.h +++ b/src/m_argv.h @@ -40,16 +40,15 @@ // // MISC // -class DArgs : public DObject +class FArgs { - DECLARE_CLASS(DArgs, DObject) public: - DArgs(); - DArgs(const DArgs &args); - DArgs(int argc, char **argv); - DArgs(int argc, FString *argv); + FArgs(); + FArgs(const FArgs &args); + FArgs(int argc, char **argv); + FArgs(int argc, FString *argv); - DArgs &operator=(const DArgs &other); + FArgs &operator=(const FArgs &other); void AppendArg(FString arg); void AppendArgs(int argc, const FString *argv); @@ -57,7 +56,7 @@ public: void RemoveArgs(const char *check); void SetArgs(int argc, char **argv); void CollectFiles(const char *param, const char *extension); - DArgs *GatherFiles(const char *param) const; + FArgs *GatherFiles(const char *param) const; void SetArg(int argnum, const char *arg); int CheckParm(const char *check, int start=1) const; // Returns the position of the given parameter in the arg list (0 if not found). @@ -73,6 +72,6 @@ private: TArray Argv; }; -extern DArgs *Args; +extern FArgs *Args; #endif //__M_ARGV_H__ diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index b667415a8..cba490a0c 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -666,7 +666,7 @@ void cht_Suicide (player_t *plyr) // the initial tick. if (plyr->mo != NULL) { - DSuicider *suicide = new DSuicider; + DSuicider *suicide = Create(); suicide->Pawn = plyr->mo; GC::WriteBarrier(suicide, suicide->Pawn); } diff --git a/src/m_misc.cpp b/src/m_misc.cpp index 229835405..a118638aa 100644 --- a/src/m_misc.cpp +++ b/src/m_misc.cpp @@ -231,7 +231,7 @@ void M_FindResponseFile (void) ParseCommandLine (file, NULL, argv); // Create a new argument vector - DArgs *newargs = new DArgs; + FArgs *newargs = new FArgs; // Copy parameters before response file. for (index = 0; index < i; ++index) @@ -246,6 +246,7 @@ void M_FindResponseFile (void) newargs->AppendArg(Args->GetArg(index)); // Use the new argument vector as the global Args object. + delete Args; Args = newargs; if (++added_stuff == limit) { diff --git a/src/menu/menudef.cpp b/src/menu/menudef.cpp index 8c80325c0..a14ac25b3 100644 --- a/src/menu/menudef.cpp +++ b/src/menu/menudef.cpp @@ -543,7 +543,7 @@ static void ParseListMenu(FScanner &sc) { sc.MustGetString(); - DListMenuDescriptor *desc = new DListMenuDescriptor; + DListMenuDescriptor *desc = Create(); desc->mMenuName = sc.String; desc->mSelectedItem = -1; desc->mAutoselect = -1; @@ -867,7 +867,7 @@ static void ParseOptionMenu(FScanner &sc) { sc.MustGetString(); - DOptionMenuDescriptor *desc = new DOptionMenuDescriptor; + DOptionMenuDescriptor *desc = Create(); desc->mMenuName = sc.String; desc->mSelectedItem = -1; desc->mScrollPos = 0; @@ -919,8 +919,8 @@ void M_ParseMenuDefs() OptionSettings.mFontColorHighlight = V_FindFontColor(gameinfo.mFontColorHighlight); OptionSettings.mFontColorSelection = V_FindFontColor(gameinfo.mFontColorSelection); // these are supposed to get GC'd after parsing is complete. - DefaultListMenuSettings = new DListMenuDescriptor; - DefaultOptionMenuSettings = new DOptionMenuDescriptor; + DefaultListMenuSettings = Create(); + DefaultOptionMenuSettings = Create(); DefaultListMenuSettings->Reset(); DefaultOptionMenuSettings->Reset(); @@ -1066,7 +1066,7 @@ static void BuildEpisodeMenu() { // Couldn't create the episode menu, either because there's too many episodes or some error occured // Create an option menu for episode selection instead. - DOptionMenuDescriptor *od = new DOptionMenuDescriptor; + DOptionMenuDescriptor *od = Create(); MenuDescriptors[NAME_Episodemenu] = od; od->mMenuName = NAME_Episodemenu; od->mTitle = "$MNU_EPISODE"; @@ -1199,7 +1199,7 @@ static void BuildPlayerclassMenu() { // Couldn't create the playerclass menu, either because there's too many episodes or some error occured // Create an option menu for class selection instead. - DOptionMenuDescriptor *od = new DOptionMenuDescriptor; + DOptionMenuDescriptor *od = Create(); MenuDescriptors[NAME_Playerclassmenu] = od; od->mMenuName = NAME_Playerclassmenu; od->mTitle = "$MNU_CHOOSECLASS"; @@ -1505,7 +1505,7 @@ fail: DOptionMenuDescriptor *od; if (desc == nullptr) { - od = new DOptionMenuDescriptor; + od = Create(); MenuDescriptors[NAME_Skillmenu] = od; od->mMenuName = NAME_Skillmenu; od->mTitle = "$MNU_CHOOSESKILL"; diff --git a/src/namedef.h b/src/namedef.h index 18075976d..ae0a17afd 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -111,10 +111,8 @@ xx(Ironlich) xx(Minotaur) xx(Sorcerer2) -// P_SpawnMapThing checks for these as health items (I smell a FIXME) -xx(Berserk) -xx(Soulsphere) -xx(Megasphere) // also counts as armor for P_SpawnMapThing +// Bots check this +xx(Megasphere) // Standard player classes xx(DoomPlayer) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index dd75f9069..58288d9e1 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -3659,7 +3659,7 @@ DLevelScript::DLevelScript () { next = prev = NULL; if (DACSThinker::ActiveThinker == NULL) - new DACSThinker; + Create(); activefont = SmallFont; } @@ -4071,7 +4071,7 @@ showme: fa1 = viewer->BlendA; } } - new DFlashFader (fr1, fg1, fb1, fa1, fr2, fg2, fb2, fa2, ftime, viewer->mo); + Create (fr1, fg1, fb1, fa1, fr2, fg2, fb2, fa2, ftime, viewer->mo); } } } @@ -8819,13 +8819,13 @@ scriptwait: { default: // normal alpha = (optstart < sp) ? ACSToFloat(Stack[optstart]) : 1.f; - msg = new DHUDMessage (activefont, work, x, y, hudwidth, hudheight, color, holdTime); + msg = Create (activefont, work, x, y, hudwidth, hudheight, color, holdTime); break; case 1: // fade out { float fadeTime = (optstart < sp) ? ACSToFloat(Stack[optstart]) : 0.5f; alpha = (optstart < sp-1) ? ACSToFloat(Stack[optstart+1]) : 1.f; - msg = new DHUDMessageFadeOut (activefont, work, x, y, hudwidth, hudheight, color, holdTime, fadeTime); + msg = Create (activefont, work, x, y, hudwidth, hudheight, color, holdTime, fadeTime); } break; case 2: // type on, then fade out @@ -8833,7 +8833,7 @@ scriptwait: float typeTime = (optstart < sp) ? ACSToFloat(Stack[optstart]) : 0.05f; float fadeTime = (optstart < sp-1) ? ACSToFloat(Stack[optstart+1]) : 0.5f; alpha = (optstart < sp-2) ? ACSToFloat(Stack[optstart+2]) : 1.f; - msg = new DHUDMessageTypeOnFadeOut (activefont, work, x, y, hudwidth, hudheight, color, typeTime, holdTime, fadeTime); + msg = Create (activefont, work, x, y, hudwidth, hudheight, color, typeTime, holdTime, fadeTime); } break; case 3: // fade in, then fade out @@ -8841,7 +8841,7 @@ scriptwait: float inTime = (optstart < sp) ? ACSToFloat(Stack[optstart]) : 0.5f; float outTime = (optstart < sp-1) ? ACSToFloat(Stack[optstart+1]) : 0.5f; alpha = (optstart < sp-2) ? ACSToFloat(Stack[optstart + 2]) : 1.f; - msg = new DHUDMessageFadeInOut (activefont, work, x, y, hudwidth, hudheight, color, holdTime, inTime, outTime); + msg = Create (activefont, work, x, y, hudwidth, hudheight, color, holdTime, inTime, outTime); } break; } @@ -9630,13 +9630,13 @@ scriptwait: break; case PCD_SETFLOORTRIGGER: - new DPlaneWatcher (activator, activationline, backSide, false, STACK(8), + Create (activator, activationline, backSide, false, STACK(8), STACK(7), STACK(6), STACK(5), STACK(4), STACK(3), STACK(2), STACK(1)); sp -= 8; break; case PCD_SETCEILINGTRIGGER: - new DPlaneWatcher (activator, activationline, backSide, true, STACK(8), + Create (activator, activationline, backSide, true, STACK(8), STACK(7), STACK(6), STACK(5), STACK(4), STACK(3), STACK(2), STACK(1)); sp -= 8; break; @@ -10513,7 +10513,7 @@ static DLevelScript *P_GetScriptGoing (AActor *who, line_t *where, int num, cons return NULL; } - return new DLevelScript (who, where, num, code, module, args, argcount, flags); + return Create (who, where, num, code, module, args, argcount, flags); } DLevelScript::DLevelScript (AActor *who, line_t *where, int num, const ScriptPtr *code, FBehavior *module, @@ -10521,7 +10521,7 @@ DLevelScript::DLevelScript (AActor *who, line_t *where, int num, const ScriptPtr : activeBehavior (module) { if (DACSThinker::ActiveThinker == NULL) - new DACSThinker; + Create(); script = num; assert(code->VarCount >= code->ArgCount); diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 19cafed23..0387bfd52 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -3574,8 +3574,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_SetBlend) if (color2.a == 0) color2 = color; - new DFlashFader(color.r/255.f, color.g/255.f, color.b/255.f, float(alpha), - color2.r/255.f, color2.g/255.f, color2.b/255.f, 0, + Create(color.r/255.f, color.g/255.f, color.b/255.f, float(alpha), + color2.r/255.f, color2.g/255.f, color2.b/255.f, 0.f, float(tics)/TICRATE, self); return 0; } diff --git a/src/p_ceiling.cpp b/src/p_ceiling.cpp index c7bc715f2..40b0094ab 100644 --- a/src/p_ceiling.cpp +++ b/src/p_ceiling.cpp @@ -244,7 +244,7 @@ bool P_CreateCeiling(sector_t *sec, DCeiling::ECeiling type, line_t *line, int t } // new door thinker - DCeiling *ceiling = new DCeiling (sec, speed, speed2, silent & ~4); + DCeiling *ceiling = Create (sec, speed, speed2, silent & ~4); vertex_t *spot = sec->Lines[0]->v1; switch (type) diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index bbd9281b7..a715f6a49 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -1170,9 +1170,9 @@ static void TerminalResponse (const char *str) // merchants can tell you something like this but continue to show // their dialogue screen. I think most other conversations use this // only as a response for terminating the dialogue. - StatusBar->AttachMessage(new DHUDMessageFadeOut(SmallFont, str, + StatusBar->AttachMessage(Create(SmallFont, str, float(CleanWidth/2) + 0.4f, float(ConversationMenuY - 110 + CleanHeight/2), CleanWidth, -CleanHeight, - CR_UNTRANSLATED, 3, 1), MAKE_ID('T','A','L','K')); + CR_UNTRANSLATED, 3.f, 1.f), MAKE_ID('T','A','L','K')); } else { diff --git a/src/p_doors.cpp b/src/p_doors.cpp index f09fd7f9b..13c5447f1 100644 --- a/src/p_doors.cpp +++ b/src/p_doors.cpp @@ -485,7 +485,7 @@ bool EV_DoDoor (DDoor::EVlDoor type, line_t *line, AActor *thing, } return false; } - if (new DDoor (sec, type, speed, delay, lightTag, topcountdown)) + if (Create (sec, type, speed, delay, lightTag, topcountdown)) rtn = true; } else @@ -499,7 +499,7 @@ bool EV_DoDoor (DDoor::EVlDoor type, line_t *line, AActor *thing, if (sec->PlaneMoving(sector_t::ceiling)) continue; - if (new DDoor (sec, type, speed, delay, lightTag, topcountdown)) + if (Create(sec, type, speed, delay, lightTag, topcountdown)) rtn = true; } @@ -779,7 +779,7 @@ bool EV_SlidingDoor (line_t *line, AActor *actor, int tag, int speed, int delay, FDoorAnimation *anim = TexMan.FindAnimatedDoor (line->sidedef[0]->GetTexture(side_t::top)); if (anim != NULL) { - new DAnimatedDoor (sec, line, speed, delay, anim, type); + Create(sec, line, speed, delay, anim, type); return true; } return false; @@ -804,7 +804,7 @@ bool EV_SlidingDoor (line_t *line, AActor *actor, int tag, int speed, int delay, if (anim != NULL) { rtn = true; - new DAnimatedDoor (sec, line, speed, delay, anim, type); + Create(sec, line, speed, delay, anim, type); break; } } diff --git a/src/p_floor.cpp b/src/p_floor.cpp index 918419fbe..580726155 100644 --- a/src/p_floor.cpp +++ b/src/p_floor.cpp @@ -282,7 +282,7 @@ bool P_CreateFloor(sector_t *sec, DFloor::EFloor floortype, line_t *line, // new floor thinker rtn = true; - floor = new DFloor(sec); + floor = Create(sec); floor->m_Type = floortype; floor->m_Crush = crush; floor->m_Hexencrush = hexencrush; @@ -631,7 +631,7 @@ bool EV_BuildStairs (int tag, DFloor::EStair type, line_t *line, // new floor thinker rtn = true; - floor = new DFloor (sec); + floor = Create (sec); floor->m_Direction = (type == DFloor::buildUp) ? 1 : -1; stairstep = stairsize * floor->m_Direction; floor->m_Type = DFloor::buildStair; //jff 3/31/98 do not leave uninited @@ -734,7 +734,7 @@ bool EV_BuildStairs (int tag, DFloor::EStair type, line_t *line, secnum = newsecnum; // create and initialize a thinker for the next step - floor = new DFloor (sec); + floor = Create (sec); floor->StartFloorSound (); floor->m_Direction = (type == DFloor::buildUp) ? 1 : -1; floor->m_FloorDestDist = sec->floorplane.PointToDist (DVector2(0, 0), height); @@ -813,7 +813,7 @@ bool EV_DoDonut (int tag, line_t *line, double pillarspeed, double slimespeed) s3 = ln->backsector; // Spawn rising slime - floor = new DFloor (s2); + floor = Create (s2); floor->m_Type = DFloor::donutRaise; floor->m_Crush = -1; floor->m_Hexencrush = false; @@ -828,7 +828,7 @@ bool EV_DoDonut (int tag, line_t *line, double pillarspeed, double slimespeed) floor->StartFloorSound (); // Spawn lowering donut-hole - floor = new DFloor (s1); + floor = Create (s1); floor->m_Type = DFloor::floorLowerToNearest; floor->m_Crush = -1; floor->m_Hexencrush = false; @@ -1017,7 +1017,7 @@ bool EV_DoElevator (line_t *line, DElevator::EElevator elevtype, // create and initialize new elevator thinker rtn = true; - elevator = new DElevator (sec); + elevator = Create (sec); elevator->m_Type = elevtype; elevator->m_Speed = speed; elevator->StartFloorSound (); @@ -1327,12 +1327,12 @@ bool EV_StartWaggle (int tag, line_t *line, int height, int speed, int offset, retCode = true; if (ceiling) { - waggle = new DCeilingWaggle (sector); + waggle = Create (sector); waggle->m_OriginalDist = sector->ceilingplane.fD(); } else { - waggle = new DFloorWaggle (sector); + waggle = Create (sector); waggle->m_OriginalDist = sector->floorplane.fD(); } waggle->m_Accumulator = offset; diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 6de00eb37..7df05653e 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -408,7 +408,7 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags) SexMessage (GStrings("SPREEKILLSELF"), buff, player->userinfo.GetGender(), player->userinfo.GetName(), player->userinfo.GetName()); - StatusBar->AttachMessage (new DHUDMessageFadeOut (SmallFont, buff, + StatusBar->AttachMessage (Create(SmallFont, buff, 1.5f, 0.2f, 0, 0, CR_WHITE, 3.f, 0.5f), MAKE_ID('K','S','P','R')); } } @@ -465,7 +465,7 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags) { SexMessage (GStrings("SPREEOVER"), buff, player->userinfo.GetGender(), player->userinfo.GetName(), source->player->userinfo.GetName()); - StatusBar->AttachMessage (new DHUDMessageFadeOut (SmallFont, buff, + StatusBar->AttachMessage (Create (SmallFont, buff, 1.5f, 0.2f, 0, 0, CR_WHITE, 3.f, 0.5f), MAKE_ID('K','S','P','R')); } } @@ -475,7 +475,7 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags) { SexMessage (spreemsg, buff, player->userinfo.GetGender(), player->userinfo.GetName(), source->player->userinfo.GetName()); - StatusBar->AttachMessage (new DHUDMessageFadeOut (SmallFont, buff, + StatusBar->AttachMessage (Create (SmallFont, buff, 1.5f, 0.2f, 0, 0, CR_WHITE, 3.f, 0.5f), MAKE_ID('K','S','P','R')); } } @@ -525,7 +525,7 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags) { SexMessage (multimsg, buff, player->userinfo.GetGender(), player->userinfo.GetName(), source->player->userinfo.GetName()); - StatusBar->AttachMessage (new DHUDMessageFadeOut (SmallFont, buff, + StatusBar->AttachMessage (Create (SmallFont, buff, 1.5f, 0.8f, 0, 0, CR_RED, 3.f, 0.5f), MAKE_ID('M','K','I','L')); } } diff --git a/src/p_lights.cpp b/src/p_lights.cpp index d680bfc46..c3a69f052 100644 --- a/src/p_lights.cpp +++ b/src/p_lights.cpp @@ -152,14 +152,16 @@ class DPhased : public DLighting public: DPhased(sector_t *sector); DPhased(sector_t *sector, int baselevel, int phase); + // These are for internal use only but the Create template needs access to them. + DPhased(); + DPhased(sector_t *sector, int baselevel); + void Serialize(FSerializer &arc); void Tick(); protected: uint8_t m_BaseLevel; uint8_t m_Phase; private: - DPhased(); - DPhased(sector_t *sector, int baselevel); int PhaseHelper(sector_t *sector, int index, int light, sector_t *prev); }; @@ -325,7 +327,7 @@ void EV_StartLightFlickering (int tag, int upper, int lower) FSectorTagIterator it(tag); while ((secnum = it.Next()) >= 0) { - new DFlicker (&level.sectors[secnum], upper, lower); + Create (&level.sectors[secnum], upper, lower); } } @@ -506,7 +508,7 @@ void EV_StartLightStrobing (int tag, int upper, int lower, int utics, int ltics) if (sec->lightingdata) continue; - new DStrobe (sec, upper, lower, utics, ltics); + Create (sec, upper, lower, utics, ltics); } } @@ -520,7 +522,7 @@ void EV_StartLightStrobing (int tag, int utics, int ltics) if (sec->lightingdata) continue; - new DStrobe (sec, utics, ltics, false); + Create (sec, utics, ltics, false); } } @@ -826,7 +828,7 @@ void EV_StartLightGlowing (int tag, int upper, int lower, int tics) if (sec->lightingdata) continue; - new DGlow2 (sec, upper, lower, tics, false); + Create (sec, upper, lower, tics, false); } } @@ -856,7 +858,7 @@ void EV_StartLightFading (int tag, int value, int tics) if (sec->lightlevel == value) continue; - new DGlow2 (sec, sec->lightlevel, value, tics, true); + Create (sec, sec->lightlevel, value, tics, true); } } } @@ -930,7 +932,7 @@ int DPhased::PhaseHelper (sector_t *sector, int index, int light, sector_t *prev m_BaseLevel = baselevel; } else - l = new DPhased (sector, baselevel); + l = Create (sector, baselevel); int numsteps = PhaseHelper (sector->NextSpecialSector ( sector->special == LightSequenceSpecial1 ? @@ -998,52 +1000,52 @@ void P_SpawnLights(sector_t *sector) switch (sector->special) { case Light_Phased: - new DPhased(sector, 48, 63 - (sector->lightlevel & 63)); + Create(sector, 48, 63 - (sector->lightlevel & 63)); break; // [RH] Hexen-like phased lighting case LightSequenceStart: - new DPhased(sector); + Create(sector); break; case dLight_Flicker: - new DLightFlash(sector); + Create(sector); break; case dLight_StrobeFast: - new DStrobe(sector, STROBEBRIGHT, FASTDARK, false); + Create(sector, STROBEBRIGHT, FASTDARK, false); break; case dLight_StrobeSlow: - new DStrobe(sector, STROBEBRIGHT, SLOWDARK, false); + Create(sector, STROBEBRIGHT, SLOWDARK, false); break; case dLight_Strobe_Hurt: - new DStrobe(sector, STROBEBRIGHT, FASTDARK, false); + Create(sector, STROBEBRIGHT, FASTDARK, false); break; case dLight_Glow: - new DGlow(sector); + Create(sector); break; case dLight_StrobeSlowSync: - new DStrobe(sector, STROBEBRIGHT, SLOWDARK, true); + Create(sector, STROBEBRIGHT, SLOWDARK, true); break; case dLight_StrobeFastSync: - new DStrobe(sector, STROBEBRIGHT, FASTDARK, true); + Create(sector, STROBEBRIGHT, FASTDARK, true); break; case dLight_FireFlicker: - new DFireFlicker(sector); + Create(sector); break; case dScroll_EastLavaDamage: - new DStrobe(sector, STROBEBRIGHT, FASTDARK, false); + Create(sector, STROBEBRIGHT, FASTDARK, false); break; case sLight_Strobe_Hurt: - new DStrobe(sector, STROBEBRIGHT, FASTDARK, false); + Create(sector, STROBEBRIGHT, FASTDARK, false); break; default: diff --git a/src/p_maputl.cpp b/src/p_maputl.cpp index 21ed99c61..5e7dfa218 100644 --- a/src/p_maputl.cpp +++ b/src/p_maputl.cpp @@ -938,7 +938,7 @@ DEFINE_ACTION_FUNCTION(DBlockLinesIterator, Create) PARAM_PROLOGUE; PARAM_OBJECT_NOT_NULL(origin, AActor); PARAM_FLOAT_DEF(radius); - ACTION_RETURN_OBJECT(new DBlockLinesIterator(origin, radius)); + ACTION_RETURN_OBJECT(Create(origin, radius)); } DEFINE_ACTION_FUNCTION(DBlockLinesIterator, CreateFromPos) @@ -950,7 +950,7 @@ DEFINE_ACTION_FUNCTION(DBlockLinesIterator, CreateFromPos) PARAM_FLOAT(h); PARAM_FLOAT(radius); PARAM_POINTER_DEF(sec, sector_t); - ACTION_RETURN_OBJECT(new DBlockLinesIterator(x, y, z, h, radius, sec)); + ACTION_RETURN_OBJECT(Create(x, y, z, h, radius, sec)); } DEFINE_ACTION_FUNCTION(DBlockLinesIterator, Next) @@ -1277,7 +1277,7 @@ DEFINE_ACTION_FUNCTION(DBlockThingsIterator, Create) PARAM_OBJECT_NOT_NULL(origin, AActor); PARAM_FLOAT_DEF(radius); PARAM_BOOL_DEF(ignore); - ACTION_RETURN_OBJECT(new DBlockThingsIterator(origin, radius, ignore)); + ACTION_RETURN_OBJECT(Create(origin, radius, ignore)); } DEFINE_ACTION_FUNCTION(DBlockThingsIterator, CreateFromPos) @@ -1289,7 +1289,7 @@ DEFINE_ACTION_FUNCTION(DBlockThingsIterator, CreateFromPos) PARAM_FLOAT(h); PARAM_FLOAT(radius); PARAM_BOOL(ignore); - ACTION_RETURN_OBJECT(new DBlockThingsIterator(x, y, z, h, radius, ignore, nullptr)); + ACTION_RETURN_OBJECT(Create(x, y, z, h, radius, ignore, nullptr)); } DEFINE_ACTION_FUNCTION(DBlockThingsIterator, Next) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 066396cd0..e0a10946a 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1380,6 +1380,54 @@ DEFINE_ACTION_FUNCTION(AActor, ObtainInventory) return 0; } +//--------------------------------------------------------------------------- +// +// FUNC P_GetRealMaxHealth +// +// Taken out of P_GiveBody so that the bot code can also use it to decide +// whether to pick up an item or not. +// +//--------------------------------------------------------------------------- + +int P_GetRealMaxHealth(APlayerPawn *actor, int max) +{ + // Max is 0 by default, preserving default behavior for P_GiveBody() + // calls while supporting health pickups. + auto player = actor->player; + if (max <= 0) + { + max = actor->GetMaxHealth(true); + // [MH] First step in predictable generic morph effects + if (player->morphTics) + { + if (player->MorphStyle & MORPH_FULLHEALTH) + { + if (!(player->MorphStyle & MORPH_ADDSTAMINA)) + { + max -= actor->stamina + actor->BonusHealth; + } + } + else // old health behaviour + { + max = MAXMORPHHEALTH; + if (player->MorphStyle & MORPH_ADDSTAMINA) + { + max += actor->stamina + actor->BonusHealth; + } + } + } + } + else + { + // Bonus health should be added on top of the item's limit. + if (player->morphTics == 0 || (player->MorphStyle & MORPH_ADDSTAMINA)) + { + max += actor->BonusHealth; + } + } + return max; +} + //--------------------------------------------------------------------------- // // FUNC P_GiveBody @@ -1400,33 +1448,8 @@ bool P_GiveBody(AActor *actor, int num, int max) num = clamp(num, -65536, 65536); // prevent overflows for bad values if (player != NULL) { - // Max is 0 by default, preserving default behavior for P_GiveBody() - // calls while supporting health pickups. - if (max <= 0) - { - max = static_cast(actor)->GetMaxHealth(true); - // [MH] First step in predictable generic morph effects - if (player->morphTics) - { - if (player->MorphStyle & MORPH_FULLHEALTH) - { - if (!(player->MorphStyle & MORPH_ADDSTAMINA)) - { - max -= player->mo->stamina + player->mo->BonusHealth; - } - } - else // old health behaviour - { - max = MAXMORPHHEALTH; - if (player->MorphStyle & MORPH_ADDSTAMINA) - { - max += player->mo->stamina + player->mo->BonusHealth; - } - } - } - } - // [RH] For Strife: A negative body sets you up with a percentage - // of your full health. + max = P_GetRealMaxHealth(player->mo, max); // do not pass voodoo dolls in here. + // [RH] For Strife: A negative value sets you up with a percentage of your full health. if (num < 0) { num = max * -num / 100; @@ -7949,7 +7972,7 @@ DEFINE_ACTION_FUNCTION(DActorIterator, Create) PARAM_PROLOGUE; PARAM_INT(tid); PARAM_CLASS_DEF(type, AActor); - ACTION_RETURN_OBJECT(new DActorIterator(type, tid)); + ACTION_RETURN_OBJECT(Create(type, tid)); } DEFINE_ACTION_FUNCTION(DActorIterator, Next) diff --git a/src/p_pillar.cpp b/src/p_pillar.cpp index 77316ad2c..0f383b43f 100644 --- a/src/p_pillar.cpp +++ b/src/p_pillar.cpp @@ -238,7 +238,7 @@ bool EV_DoPillar (DPillar::EPillar type, line_t *line, int tag, continue; rtn = true; - new DPillar (sec, type, speed, height, height2, crush, hexencrush); + Create (sec, type, speed, height, height2, crush, hexencrush); } return rtn; } diff --git a/src/p_plats.cpp b/src/p_plats.cpp index 8dd82c024..320597ddc 100644 --- a/src/p_plats.cpp +++ b/src/p_plats.cpp @@ -253,7 +253,7 @@ bool EV_DoPlat (int tag, line_t *line, DPlat::EPlatType type, double height, // Find lowest & highest floors around sector rtn = true; - plat = new DPlat (sec); + plat = Create (sec); plat->m_Type = type; plat->m_Crush = -1; diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index 45c4d36d7..cb89305d8 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -255,7 +255,7 @@ DPSprite *player_t::GetPSprite(PSPLayers layer) DPSprite *pspr = FindPSprite(layer); if (pspr == nullptr) { - pspr = new DPSprite(this, newcaller, layer); + pspr = Create(this, newcaller, layer); } else { @@ -1263,7 +1263,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Overlay) } DPSprite *pspr; - pspr = new DPSprite(player, stateowner, layer); + pspr = Create(player, stateowner, layer); pspr->SetState(state); ACTION_RETURN_BOOL(true); } diff --git a/src/p_pusher.cpp b/src/p_pusher.cpp index 0b08b4f65..c4b38c582 100644 --- a/src/p_pusher.cpp +++ b/src/p_pusher.cpp @@ -371,7 +371,7 @@ void P_SpawnPushers () { FSectorTagIterator itr(l->args[0]); while ((s = itr.Next()) >= 0) - new DPusher(DPusher::p_wind, l->args[3] ? l : NULL, l->args[1], l->args[2], NULL, s); + Create(DPusher::p_wind, l->args[3] ? l : nullptr, l->args[1], l->args[2], nullptr, s); l->special = 0; break; } @@ -380,7 +380,7 @@ void P_SpawnPushers () { FSectorTagIterator itr(l->args[0]); while ((s = itr.Next()) >= 0) - new DPusher(DPusher::p_current, l->args[3] ? l : NULL, l->args[1], l->args[2], NULL, s); + Create(DPusher::p_current, l->args[3] ? l : nullptr, l->args[1], l->args[2], nullptr, s); l->special = 0; break; } @@ -394,7 +394,7 @@ void P_SpawnPushers () if (thing) { // No MT_P* means no effect // [RH] Allow narrowing it down by tid if (!l->args[1] || l->args[1] == thing->tid) - new DPusher (DPusher::p_push, l->args[3] ? l : NULL, l->args[2], + Create (DPusher::p_push, l->args[3] ? l : NULL, l->args[2], 0, thing, s); } } @@ -407,7 +407,7 @@ void P_SpawnPushers () if (thing->GetClass()->TypeName == NAME_PointPusher || thing->GetClass()->TypeName == NAME_PointPuller) { - new DPusher (DPusher::p_push, l->args[3] ? l : NULL, l->args[2], 0, thing, thing->Sector->Index()); + Create (DPusher::p_push, l->args[3] ? l : NULL, l->args[2], 0, thing, thing->Sector->Index()); } } } @@ -452,7 +452,7 @@ void AdjustPusher (int tag, int magnitude, int angle, bool wind) } if (i == numcollected) { - new DPusher (type, NULL, magnitude, angle, NULL, secnum); + Create (type, nullptr, magnitude, angle, nullptr, secnum); } } } diff --git a/src/p_scroll.cpp b/src/p_scroll.cpp index d74c6273f..59b18f1ce 100644 --- a/src/p_scroll.cpp +++ b/src/p_scroll.cpp @@ -470,7 +470,7 @@ void P_SpawnScrollers(void) FSectorTagIterator itr(l->args[0]); while ((s = itr.Next()) >= 0) { - new DScroller(EScroll::sc_ceiling, -dx, dy, control, s, accel); + Create(EScroll::sc_ceiling, -dx, dy, control, s, accel); } for (unsigned j = 0; j < copyscrollers.Size(); j++) { @@ -478,7 +478,7 @@ void P_SpawnScrollers(void) if (line->args[0] == l->args[0] && (line->args[1] & 1)) { - new DScroller(EScroll::sc_ceiling, -dx, dy, control, line->frontsector->Index(), accel); + Create(EScroll::sc_ceiling, -dx, dy, control, line->frontsector->Index(), accel); } } break; @@ -490,7 +490,7 @@ void P_SpawnScrollers(void) FSectorTagIterator itr(l->args[0]); while ((s = itr.Next()) >= 0) { - new DScroller (EScroll::sc_floor, -dx, dy, control, s, accel); + Create (EScroll::sc_floor, -dx, dy, control, s, accel); } for(unsigned j = 0;j < copyscrollers.Size(); j++) { @@ -498,7 +498,7 @@ void P_SpawnScrollers(void) if (line->args[0] == l->args[0] && (line->args[1] & 2)) { - new DScroller(EScroll::sc_floor, -dx, dy, control, line->frontsector->Index(), accel); + Create(EScroll::sc_floor, -dx, dy, control, line->frontsector->Index(), accel); } } } @@ -508,7 +508,7 @@ void P_SpawnScrollers(void) FSectorTagIterator itr(l->args[0]); while ((s = itr.Next()) >= 0) { - new DScroller (EScroll::sc_carry, dx, dy, control, s, accel); + Create (EScroll::sc_carry, dx, dy, control, s, accel); } for(unsigned j = 0;j < copyscrollers.Size(); j++) { @@ -516,7 +516,7 @@ void P_SpawnScrollers(void) if (line->args[0] == l->args[0] && (line->args[1] & 4)) { - new DScroller (EScroll::sc_carry, dx, dy, control, line->frontsector->Index(), accel); + Create (EScroll::sc_carry, dx, dy, control, line->frontsector->Index(), accel); } } } @@ -530,7 +530,7 @@ void P_SpawnScrollers(void) while ((s = itr.Next()) >= 0) { if (s != (int)i) - new DScroller(dx, dy, &level.lines[s], control, accel); + Create(dx, dy, &level.lines[s], control, accel); } break; } @@ -538,35 +538,35 @@ void P_SpawnScrollers(void) case Scroll_Texture_Offsets: // killough 3/2/98: scroll according to sidedef offsets s = level.lines[i].sidedef[0]->Index(); - new DScroller (EScroll::sc_side, -level.sides[s].GetTextureXOffset(side_t::mid), + Create (EScroll::sc_side, -level.sides[s].GetTextureXOffset(side_t::mid), level.sides[s].GetTextureYOffset(side_t::mid), -1, s, accel, SCROLLTYPE(l->args[0])); break; case Scroll_Texture_Left: l->special = special; // Restore the special, for compat_useblocking's benefit. s = level.lines[i].sidedef[0]->Index(); - new DScroller (EScroll::sc_side, l->args[0] / 64., 0, + Create (EScroll::sc_side, l->args[0] / 64., 0, -1, s, accel, SCROLLTYPE(l->args[1])); break; case Scroll_Texture_Right: l->special = special; s = level.lines[i].sidedef[0]->Index(); - new DScroller (EScroll::sc_side, -l->args[0] / 64., 0, + Create (EScroll::sc_side, -l->args[0] / 64., 0, -1, s, accel, SCROLLTYPE(l->args[1])); break; case Scroll_Texture_Up: l->special = special; s = level.lines[i].sidedef[0]->Index(); - new DScroller (EScroll::sc_side, 0, l->args[0] / 64., + Create (EScroll::sc_side, 0, l->args[0] / 64., -1, s, accel, SCROLLTYPE(l->args[1])); break; case Scroll_Texture_Down: l->special = special; s = level.lines[i].sidedef[0]->Index(); - new DScroller (EScroll::sc_side, 0, -l->args[0] / 64., + Create (EScroll::sc_side, 0, -l->args[0] / 64., -1, s, accel, SCROLLTYPE(l->args[1])); break; @@ -575,7 +575,7 @@ void P_SpawnScrollers(void) if (l->args[0] == 0) { dx = (l->args[1] - l->args[2]) / 64.; dy = (l->args[4] - l->args[3]) / 64.; - new DScroller (EScroll::sc_side, dx, dy, -1, s, accel); + Create (EScroll::sc_side, dx, dy, -1, s, accel); } break; @@ -656,7 +656,7 @@ void SetWallScroller (int id, int sidechoice, double dx, double dy, EScrollPos W } if (i == numcollected) { - new DScroller (EScroll::sc_side, dx, dy, -1, sidenum, 0, Where); + Create (EScroll::sc_side, dx, dy, -1, sidenum, 0, Where); } } } @@ -696,11 +696,11 @@ void SetScroller (int tag, EScroll type, double dx, double dy) FSectorTagIterator itr(tag); while ((i = itr.Next()) >= 0) { - new DScroller (type, dx, dy, -1, i, 0); + Create (type, dx, dy, -1, i, 0); } } void P_CreateScroller(EScroll type, double dx, double dy, int control, int affectee, int accel, EScrollPos scrollpos) { - new DScroller(type, dx, dy, control, affectee, accel, scrollpos); + Create(type, dx, dy, control, affectee, accel, scrollpos); } diff --git a/src/p_spec.cpp b/src/p_spec.cpp index 43c094e25..7c128eb1d 100644 --- a/src/p_spec.cpp +++ b/src/p_spec.cpp @@ -1133,7 +1133,7 @@ void P_InitSectorSpecial(sector_t *sector, int special) break; case dSector_DoorCloseIn30: - new DDoor(sector, DDoor::doorWaitClose, 2, 0, 0, 30 * TICRATE); + Create(sector, DDoor::doorWaitClose, 2, 0, 0, 30 * TICRATE); break; case dDamage_End: @@ -1141,7 +1141,7 @@ void P_InitSectorSpecial(sector_t *sector, int special) break; case dSector_DoorRaiseIn5Mins: - new DDoor (sector, DDoor::doorWaitRaise, 2, TICRATE*30/7, 0, 5*60*TICRATE); + Create (sector, DDoor::doorWaitRaise, 2, TICRATE*30/7, 0, 5*60*TICRATE); break; case dFriction_Low: @@ -1322,19 +1322,19 @@ void P_SpawnSpecials (void) // killough 3/16/98: Add support for setting // floor lighting independently (e.g. lava) case Transfer_FloorLight: - new DLightTransfer (line.frontsector, line.args[0], true); + Create (line.frontsector, line.args[0], true); break; // killough 4/11/98: Add support for setting // ceiling lighting independently case Transfer_CeilingLight: - new DLightTransfer (line.frontsector, line.args[0], false); + Create (line.frontsector, line.args[0], false); break; // [Graf Zahl] Add support for setting lighting // per wall independently case Transfer_WallLight: - new DWallLightTransfer (line.frontsector, line.args[0], line.args[1]); + Create (line.frontsector, line.args[0], line.args[1]); break; case Sector_Attach3dMidtex: diff --git a/src/p_spec.h b/src/p_spec.h index 48535d0b0..5c8130a53 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -190,9 +190,9 @@ public: void Tick (); bool IsLift() const { return m_Type == platDownWaitUpStay || m_Type == platDownWaitUpStayStone; } + DPlat(sector_t *sector); protected: - DPlat (sector_t *sector); double m_Speed; double m_Low; diff --git a/src/p_switch.cpp b/src/p_switch.cpp index d23e30ea2..3563f96b8 100644 --- a/src/p_switch.cpp +++ b/src/p_switch.cpp @@ -103,7 +103,7 @@ static bool P_StartButton (side_t *side, int Where, FSwitchDef *Switch, const DV } } - new DActiveButton (side, Where, Switch, pos, useagain); + Create (side, Where, Switch, pos, useagain); return true; } diff --git a/src/p_tags.cpp b/src/p_tags.cpp index 6fe06ed0f..74bcafbd7 100644 --- a/src/p_tags.cpp +++ b/src/p_tags.cpp @@ -382,7 +382,7 @@ DEFINE_ACTION_FUNCTION(DSectorTagIterator, Create) PARAM_PROLOGUE; PARAM_INT(tag); PARAM_POINTER_DEF(line, line_t); - ACTION_RETURN_POINTER(new DSectorTagIterator(tag, line)); + ACTION_RETURN_POINTER(Create(tag, line)); } DEFINE_ACTION_FUNCTION(DSectorTagIterator, Next) @@ -416,7 +416,7 @@ DEFINE_ACTION_FUNCTION(DLineIdIterator, Create) { PARAM_PROLOGUE; PARAM_INT(tag); - ACTION_RETURN_POINTER(new DLineIdIterator(tag)); + ACTION_RETURN_POINTER(Create(tag)); } DEFINE_ACTION_FUNCTION(DLineIdIterator, Next) diff --git a/src/po_man.cpp b/src/po_man.cpp index 0a8948b23..50a50d0da 100644 --- a/src/po_man.cpp +++ b/src/po_man.cpp @@ -390,7 +390,7 @@ bool EV_RotatePoly (line_t *line, int polyNum, int speed, int byteAngle, // cannot do rotations on linked polyportals. break; } - pe = new DRotatePoly(poly->tag); + pe = Create(poly->tag); poly->specialdata = pe; poly->bBlocked = false; if (byteAngle != 0) @@ -472,7 +472,7 @@ bool EV_MovePoly (line_t *line, int polyNum, double speed, DAngle angle, { // poly is already in motion break; } - pe = new DMovePoly(poly->tag); + pe = Create(poly->tag); poly->specialdata = pe; poly->bBlocked = false; pe->m_Dist = dist; // Distance @@ -554,7 +554,7 @@ bool EV_MovePolyTo(line_t *line, int polyNum, double speed, const DVector2 &targ { // poly is already in motion break; } - pe = new DMovePolyTo(poly->tag); + pe = Create(poly->tag); poly->specialdata = pe; poly->bBlocked = false; pe->m_Dist = distlen; @@ -709,7 +709,7 @@ bool EV_OpenPolyDoor(line_t *line, int polyNum, double speed, DAngle angle, int break; } - pd = new DPolyDoor(poly->tag, type); + pd = Create(poly->tag, type); poly->specialdata = pd; if (type == PODOOR_SLIDE) { diff --git a/src/posix/cocoa/i_main.mm b/src/posix/cocoa/i_main.mm index 0d426caaa..d8fef4932 100644 --- a/src/posix/cocoa/i_main.mm +++ b/src/posix/cocoa/i_main.mm @@ -179,7 +179,7 @@ static void I_DetectOS() } -DArgs* Args; // command line arguments +FArgs* Args; // command line arguments // Newer versions of GCC than 4.2 have a bug with C++ exceptions in Objective-C++ code. @@ -188,7 +188,7 @@ DArgs* Args; // command line arguments void OriginalMainExcept(int argc, char** argv); void OriginalMainTry(int argc, char** argv) { - Args = new DArgs(argc, argv); + Args = new FArgs(argc, argv); /* killough 1/98: diff --git a/src/posix/sdl/i_main.cpp b/src/posix/sdl/i_main.cpp index 7fe5aeb08..21f58e71e 100644 --- a/src/posix/sdl/i_main.cpp +++ b/src/posix/sdl/i_main.cpp @@ -82,7 +82,7 @@ void Mac_I_FatalError(const char* errortext); // PUBLIC DATA DEFINITIONS ------------------------------------------------- // The command line arguments. -DArgs *Args; +FArgs *Args; // PRIVATE DATA DEFINITIONS ------------------------------------------------ @@ -218,7 +218,7 @@ int main (int argc, char **argv) try { - Args = new DArgs(argc, argv); + Args = new FArgs(argc, argv); /* killough 1/98: diff --git a/src/r_data/r_interpolate.cpp b/src/r_data/r_interpolate.cpp index 2c7197a44..8f8fc3f80 100644 --- a/src/r_data/r_interpolate.cpp +++ b/src/r_data/r_interpolate.cpp @@ -907,7 +907,7 @@ DInterpolation *side_t::SetInterpolation(int position) { if (textures[position].interpolation == NULL) { - textures[position].interpolation = new DWallScrollInterpolation(this, position); + textures[position].interpolation = Create(this, position); } textures[position].interpolation->AddRef(); GC::WriteBarrier(textures[position].interpolation); @@ -942,19 +942,19 @@ DInterpolation *sector_t::SetInterpolation(int position, bool attach) switch (position) { case sector_t::CeilingMove: - interp = new DSectorPlaneInterpolation(this, true, attach); + interp = Create(this, true, attach); break; case sector_t::FloorMove: - interp = new DSectorPlaneInterpolation(this, false, attach); + interp = Create(this, false, attach); break; case sector_t::CeilingScroll: - interp = new DSectorScrollInterpolation(this, true); + interp = Create(this, true); break; case sector_t::FloorScroll: - interp = new DSectorScrollInterpolation(this, false); + interp = Create(this, false); break; default: @@ -981,7 +981,7 @@ DInterpolation *FPolyObj::SetInterpolation() } else { - interpolation = new DPolyobjInterpolation(this); + interpolation = Create(this); interpolation->AddRef(); } GC::WriteBarrier(interpolation); diff --git a/src/s_sndseq.cpp b/src/s_sndseq.cpp index 8d4652d2b..589dcc053 100644 --- a/src/s_sndseq.cpp +++ b/src/s_sndseq.cpp @@ -881,7 +881,7 @@ DSeqNode *SN_StartSequence (AActor *actor, int sequence, seqtype_t type, int mod } if (TwiddleSeqNum (sequence, type)) { - return new DSeqActorNode (actor, sequence, modenum); + return Create (actor, sequence, modenum); } return NULL; } @@ -904,7 +904,7 @@ DSeqNode *SN_StartSequence (sector_t *sector, int chan, int sequence, seqtype_t } if (TwiddleSeqNum (sequence, type)) { - return new DSeqSectorNode (sector, chan, sequence, modenum); + return Create(sector, chan, sequence, modenum); } return NULL; } @@ -928,7 +928,7 @@ DSeqNode *SN_StartSequence (FPolyObj *poly, int sequence, seqtype_t type, int mo } if (TwiddleSeqNum (sequence, type)) { - return new DSeqPolyNode (poly, sequence, modenum); + return Create(poly, sequence, modenum); } return NULL; } diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index 5b7fcddc9..76ab83358 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -274,7 +274,7 @@ static PSymbol *FindBuiltinFunction(FName funcname, VMNativeFunction::NativeCall PSymbol *sym = Namespaces.GlobalNamespace->Symbols.FindSymbol(funcname, false); if (sym == nullptr) { - PSymbolVMFunction *symfunc = new PSymbolVMFunction(funcname); + PSymbolVMFunction *symfunc = Create(funcname); VMNativeFunction *calldec = new VMNativeFunction(func, funcname); calldec->PrintableName = funcname.GetChars(); symfunc->Function = calldec; @@ -6809,7 +6809,7 @@ ExpEmit FxCVar::Emit(VMFunctionBuilder *build) //========================================================================== FxStackVariable::FxStackVariable(PType *type, int offset, const FScriptPosition &pos) - : FxMemberBase(EFX_StackVariable, new PField(NAME_None, type, 0, offset), pos) + : FxMemberBase(EFX_StackVariable, Create(NAME_None, type, 0, offset), pos) { } @@ -7030,13 +7030,13 @@ FxExpression *FxStructMember::Resolve(FCompileContext &ctx) } else if (classx->ValueType->isStruct()) { - // if this is a struct within a class or another struct we can simplify the expression by creating a new PField with a cumulative offset. + // if this is a struct within a class or another struct we can simplify the expression by creating a Create with a cumulative offset. if (classx->ExprType == EFX_ClassMember || classx->ExprType == EFX_StructMember || classx->ExprType == EFX_GlobalVariable || classx->ExprType == EFX_StackVariable) { auto parentfield = static_cast(classx)->membervar; // PFields are garbage collected so this will be automatically taken care of later. // [ZZ] call ChangeSideInFlags to ensure that we don't get ui+play - auto newfield = new PField(NAME_None, membervar->Type, FScopeBarrier::ChangeSideInFlags(membervar->Flags | parentfield->Flags, BarrierSide), membervar->Offset + parentfield->Offset); + auto newfield = Create(NAME_None, membervar->Type, FScopeBarrier::ChangeSideInFlags(membervar->Flags | parentfield->Flags, BarrierSide), membervar->Offset + parentfield->Offset); newfield->BitValue = membervar->BitValue; static_cast(classx)->membervar = newfield; classx->isresolved = false; // re-resolve the parent so it can also check if it can be optimized away. @@ -7259,7 +7259,7 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx) if (Array->isStaticArray()) { - // if this is an array within a class or another struct we can simplify the expression by creating a new PField with a cumulative offset. + // if this is an array within a class or another struct we can simplify the expression by creating a Create with a cumulative offset. if (Array->ExprType == EFX_ClassMember || Array->ExprType == EFX_StructMember || Array->ExprType == EFX_GlobalVariable || Array->ExprType == EFX_StackVariable) { auto parentfield = static_cast(Array)->membervar; @@ -7283,12 +7283,12 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx) return nullptr; } - // if this is an array within a class or another struct we can simplify the expression by creating a new PField with a cumulative offset. + // if this is an array within a class or another struct we can simplify the expression by creating a Create with a cumulative offset. if (Array->ExprType == EFX_ClassMember || Array->ExprType == EFX_StructMember || Array->ExprType == EFX_GlobalVariable || Array->ExprType == EFX_StackVariable) { auto parentfield = static_cast(Array)->membervar; // PFields are garbage collected so this will be automatically taken care of later. - auto newfield = new PField(NAME_None, elementtype, parentfield->Flags, indexval * arraytype->ElementSize + parentfield->Offset); + auto newfield = Create(NAME_None, elementtype, parentfield->Flags, indexval * arraytype->ElementSize + parentfield->Offset); static_cast(Array)->membervar = newfield; Array->isresolved = false; // re-resolve the parent so it can also check if it can be optimized away. auto x = Array->Resolve(ctx); @@ -7337,7 +7337,7 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) start = ExpEmit(build, REGT_POINTER); build->Emit(OP_LP, start.RegNum, arrayvar.RegNum, build->GetConstantInt(0)); - auto f = new PField(NAME_None, TypeUInt32, ismeta? VARF_Meta : 0, SizeAddr); + auto f = Create(NAME_None, TypeUInt32, ismeta? VARF_Meta : 0, SizeAddr); static_cast(Array)->membervar = f; static_cast(Array)->AddressRequested = false; Array->ValueType = TypeUInt32; @@ -8149,7 +8149,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) if (Self->ExprType == EFX_StructMember || Self->ExprType == EFX_ClassMember || Self->ExprType == EFX_StackVariable) { auto member = static_cast(Self); - auto newfield = new PField(NAME_None, backingtype, 0, member->membervar->Offset); + auto newfield = Create(NAME_None, backingtype, 0, member->membervar->Offset); member->membervar = newfield; } } @@ -8193,7 +8193,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) if (Self->ExprType == EFX_StructMember || Self->ExprType == EFX_ClassMember || Self->ExprType == EFX_GlobalVariable) { auto member = static_cast(Self); - auto newfield = new PField(NAME_None, TypeUInt32, VARF_ReadOnly, member->membervar->Offset + sizeof(void*)); // the size is stored right behind the pointer. + auto newfield = Create(NAME_None, TypeUInt32, VARF_ReadOnly, member->membervar->Offset + sizeof(void*)); // the size is stored right behind the pointer. member->membervar = newfield; Self = nullptr; delete this; diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index 0a0b2fa3d..c2cc3ecbe 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -255,12 +255,12 @@ static void ParseConstant (FScanner &sc, PSymbolTable *symt, PClassActor *cls, P PSymbolConstNumeric *sym; if (type == TK_Int) { - sym = new PSymbolConstNumeric(symname, TypeSInt32); + sym = Create(symname, TypeSInt32); sym->Value = val.GetInt(); } else { - sym = new PSymbolConstNumeric(symname, TypeFloat64); + sym = Create(symname, TypeFloat64); sym->Float = val.GetFloat(); } if (symt->AddSymbol (sym) == NULL) @@ -318,7 +318,7 @@ static void ParseEnum (FScanner &sc, PSymbolTable *symt, PClassActor *cls, PName FScriptPosition::ErrorCounter++; } } - PSymbolConstNumeric *sym = new PSymbolConstNumeric(symname, TypeSInt32); + PSymbolConstNumeric *sym = Create(symname, TypeSInt32); sym->Value = currvalue; if (symt->AddSymbol (sym) == NULL) { diff --git a/src/scripting/symbols.cpp b/src/scripting/symbols.cpp index 057b6ef29..1d25d11fe 100644 --- a/src/scripting/symbols.cpp +++ b/src/scripting/symbols.cpp @@ -311,7 +311,7 @@ PSymbol *PSymbolTable::AddSymbol (PSymbol *sym) PField *PSymbolTable::AddField(FName name, PType *type, uint32_t flags, unsigned &Size, unsigned *Align) { - PField *field = new PField(name, type, flags); + PField *field = Create(name, type, flags); // The new field is added to the end of this struct, alignment permitting. field->Offset = (Size + (type->Align - 1)) & ~(type->Align - 1); @@ -345,7 +345,7 @@ PField *PSymbolTable::AddField(FName name, PType *type, uint32_t flags, unsigned PField *PSymbolTable::AddNativeField(FName name, PType *type, size_t address, uint32_t flags, int bitvalue) { - PField *field = new PField(name, type, flags | VARF_Native | VARF_Transient, address, bitvalue); + PField *field = Create(name, type, flags | VARF_Native | VARF_Transient, address, bitvalue); if (AddSymbol(field) == nullptr) { // name is already in use diff --git a/src/scripting/thingdef.cpp b/src/scripting/thingdef.cpp index a76fdd5fb..aa8db34fd 100644 --- a/src/scripting/thingdef.cpp +++ b/src/scripting/thingdef.cpp @@ -171,7 +171,7 @@ PFunction *CreateAnonymousFunction(PContainerType *containingclass, PType *retur rets[0] = returntype != nullptr? returntype : TypeError; // Use TypeError as placeholder if we do not know the return type yet. SetImplicitArgs(&args, &argflags, &argnames, containingclass, fflags, flags); - PFunction *sym = new PFunction(containingclass, NAME_None); // anonymous functions do not have names. + PFunction *sym = Create(containingclass, NAME_None); // anonymous functions do not have names. sym->AddVariant(NewPrototype(rets, args), argflags, argnames, nullptr, fflags, flags); return sym; } diff --git a/src/scripting/types.cpp b/src/scripting/types.cpp index 4649777af..5a8581812 100644 --- a/src/scripting/types.cpp +++ b/src/scripting/types.cpp @@ -337,7 +337,7 @@ void PType::StaticInit() TypeVector3->AddField(NAME_Y, TypeFloat64); TypeVector3->AddField(NAME_Z, TypeFloat64); // allow accessing xy as a vector2. This is not supposed to be serialized so it's marked transient - TypeVector3->Symbols.AddSymbol(new PField(NAME_XY, TypeVector2, VARF_Transient, 0)); + TypeVector3->Symbols.AddSymbol(Create(NAME_XY, TypeVector2, VARF_Transient, 0)); TypeTable.AddType(TypeVector3, NAME_Struct); TypeVector3->loadOp = OP_LV3; TypeVector3->storeOp = OP_SV3; @@ -347,24 +347,24 @@ void PType::StaticInit() - Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_sByte, TypeSInt8)); - Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Byte, TypeUInt8)); - Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Short, TypeSInt16)); - Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_uShort, TypeUInt16)); - Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Int, TypeSInt32)); - Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_uInt, TypeUInt32)); - Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Bool, TypeBool)); - Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Float, TypeFloat64)); - Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Double, TypeFloat64)); - Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Float32, TypeFloat32)); - Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Float64, TypeFloat64)); - Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_String, TypeString)); - Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Name, TypeName)); - Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Sound, TypeSound)); - Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Color, TypeColor)); - Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_State, TypeState)); - Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Vector2, TypeVector2)); - Namespaces.GlobalNamespace->Symbols.AddSymbol(new PSymbolType(NAME_Vector3, TypeVector3)); + Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_sByte, TypeSInt8)); + Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_Byte, TypeUInt8)); + Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_Short, TypeSInt16)); + Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_uShort, TypeUInt16)); + Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_Int, TypeSInt32)); + Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_uInt, TypeUInt32)); + Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_Bool, TypeBool)); + Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_Float, TypeFloat64)); + Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_Double, TypeFloat64)); + Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_Float32, TypeFloat32)); + Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_Float64, TypeFloat64)); + Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_String, TypeString)); + Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_Name, TypeName)); + Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_Sound, TypeSound)); + Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_Color, TypeColor)); + Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_State, TypeState)); + Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_Vector2, TypeVector2)); + Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_Vector3, TypeVector3)); } @@ -444,13 +444,13 @@ PInt::PInt(unsigned int size, bool unsign, bool compatible) { int maxval = (1u << ((8 * size) - 1)) - 1; // compute as unsigned to prevent overflow before -1 int minval = -maxval - 1; - Symbols.AddSymbol(new PSymbolConstNumeric(NAME_Min, this, minval)); - Symbols.AddSymbol(new PSymbolConstNumeric(NAME_Max, this, maxval)); + Symbols.AddSymbol(Create(NAME_Min, this, minval)); + Symbols.AddSymbol(Create(NAME_Max, this, maxval)); } else { - Symbols.AddSymbol(new PSymbolConstNumeric(NAME_Min, this, 0u)); - Symbols.AddSymbol(new PSymbolConstNumeric(NAME_Max, this, (1u << ((8 * size) - 1)))); + Symbols.AddSymbol(Create(NAME_Min, this, 0u)); + Symbols.AddSymbol(Create(NAME_Max, this, (1u << ((8 * size) - 1)))); } SetOps(); } @@ -799,7 +799,7 @@ void PFloat::SetSymbols(const PFloat::SymbolInitF *sym, size_t count) { for (size_t i = 0; i < count; ++i) { - Symbols.AddSymbol(new PSymbolConstNumeric(sym[i].Name, this, sym[i].Value)); + Symbols.AddSymbol(Create(sym[i].Name, this, sym[i].Value)); } } @@ -807,7 +807,7 @@ void PFloat::SetSymbols(const PFloat::SymbolInitI *sym, size_t count) { for (size_t i = 0; i < count; ++i) { - Symbols.AddSymbol(new PSymbolConstNumeric(sym[i].Name, this, sym[i].Value)); + Symbols.AddSymbol(Create(sym[i].Name, this, sym[i].Value)); } } diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index c6f65dc98..9f6c1fdce 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -329,7 +329,7 @@ ZCCCompiler::ZCCCompiler(ZCC_AST &ast, DObject *_outer, PSymbolTable &_symbols, case AST_Enum: zenumType = static_cast(node); enumType = NewEnum(zenumType->NodeName, OutNamespace); - OutNamespace->Symbols.AddSymbol(new PSymbolType(zenumType->NodeName, enumType)); + OutNamespace->Symbols.AddSymbol(Create(zenumType->NodeName, enumType)); break; case AST_Class: @@ -399,7 +399,7 @@ PSymbolTreeNode *ZCCCompiler::AddTreeNode(FName name, ZCC_TreeNode *node, PSymbo } else { - auto sy = new PSymbolTreeNode(name, node); + auto sy = Create(name, node); FString name; treenodes->AddSymbol(sy); return sy; @@ -549,13 +549,13 @@ void ZCCCompiler::CreateStructTypes() // old versions force 'play'. sf = FScopeBarrier::ChangeSideInObjectFlags(sf, FScopeBarrier::Side_Play); } - s->strct->Symbol = new PSymbolType(s->NodeName(), s->Type()); + s->strct->Symbol = Create(s->NodeName(), s->Type()); syms->AddSymbol(s->strct->Symbol); for (auto e : s->Enums) { auto etype = NewEnum(e->NodeName, s->Type()); - s->Type()->Symbols.AddSymbol(new PSymbolType(e->NodeName, etype)); + s->Type()->Symbols.AddSymbol(Create(e->NodeName, etype)); } } } @@ -701,7 +701,7 @@ void ZCCCompiler::CreateClassTypes() c->Type()->ScopeFlags = FScopeBarrier::ChangeSideInObjectFlags(c->Type()->ScopeFlags, FScopeBarrier::Side_Play); } - c->cls->Symbol = new PSymbolType(c->NodeName(), c->Type()); + c->cls->Symbol = Create(c->NodeName(), c->Type()); OutNamespace->Symbols.AddSymbol(c->cls->Symbol); Classes.Push(c); OrigClasses.Delete(i--); @@ -725,7 +725,7 @@ void ZCCCompiler::CreateClassTypes() Error(c->cls, "Class %s has unknown base class %s", c->NodeName().GetChars(), FName(c->cls->ParentName->Id).GetChars()); // create a placeholder so that the compiler can continue looking for errors. c->cls->Type = NewClassType(RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName())); - c->cls->Symbol = new PSymbolType(c->NodeName(), c->Type()); + c->cls->Symbol = Create(c->NodeName(), c->Type()); OutNamespace->Symbols.AddSymbol(c->cls->Symbol); Classes.Push(c); OrigClasses.Delete(i--); @@ -741,7 +741,7 @@ void ZCCCompiler::CreateClassTypes() { Error(c->cls, "Class %s has circular inheritance", FName(c->NodeName()).GetChars()); c->cls->Type = NewClassType(RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName())); - c->cls->Symbol = new PSymbolType(c->NodeName(), c->Type()); + c->cls->Symbol = Create(c->NodeName(), c->Type()); OutNamespace->Symbols.AddSymbol(c->cls->Symbol); Classes.Push(c); } @@ -752,7 +752,7 @@ void ZCCCompiler::CreateClassTypes() for (auto e : cd->Enums) { auto etype = NewEnum(e->NodeName, cd->Type()); - cd->Type()->Symbols.AddSymbol(new PSymbolType(e->NodeName, etype)); + cd->Type()->Symbols.AddSymbol(Create(e->NodeName, etype)); } // Link the tree node tables. We only can do this after we know the class relations. for (auto cc : Classes) @@ -872,13 +872,13 @@ void ZCCCompiler::AddConstant(ZCC_ConstantWork &constant) ZCC_ExprConstant *cval = static_cast(val); if (cval->Type == TypeString) { - def->Symbol = new PSymbolConstString(def->NodeName, *(cval->StringVal)); + def->Symbol = Create(def->NodeName, *(cval->StringVal)); } else if (cval->Type->isInt()) { // How do we get an Enum type in here without screwing everything up??? //auto type = def->Type != nullptr ? def->Type : cval->Type; - def->Symbol = new PSymbolConstNumeric(def->NodeName, cval->Type, cval->IntVal); + def->Symbol = Create(def->NodeName, cval->Type, cval->IntVal); } else if (cval->Type->isFloat()) { @@ -886,7 +886,7 @@ void ZCCCompiler::AddConstant(ZCC_ConstantWork &constant) { Error(def, "Enum members must be integer values"); } - def->Symbol = new PSymbolConstNumeric(def->NodeName, cval->Type, cval->DoubleVal); + def->Symbol = Create(def->NodeName, cval->Type, cval->DoubleVal); } else { @@ -898,13 +898,13 @@ void ZCCCompiler::AddConstant(ZCC_ConstantWork &constant) { if (c.Type == TypeString) { - def->Symbol = new PSymbolConstString(def->NodeName, c.GetString()); + def->Symbol = Create(def->NodeName, c.GetString()); } else if (c.Type->isInt()) { // How do we get an Enum type in here without screwing everything up??? //auto type = def->Type != nullptr ? def->Type : cval->Type; - def->Symbol = new PSymbolConstNumeric(def->NodeName, c.Type, c.GetInt()); + def->Symbol = Create(def->NodeName, c.Type, c.GetInt()); } else if (c.Type->isFloat()) { @@ -912,7 +912,7 @@ void ZCCCompiler::AddConstant(ZCC_ConstantWork &constant) { Error(def, "Enum members must be integer values"); } - def->Symbol = new PSymbolConstNumeric(def->NodeName, c.Type, c.GetFloat()); + def->Symbol = Create(def->NodeName, c.Type, c.GetFloat()); } else { @@ -924,7 +924,7 @@ void ZCCCompiler::AddConstant(ZCC_ConstantWork &constant) if (def->Symbol == nullptr) { // Create a dummy constant so we don't make any undefined value warnings. - def->Symbol = new PSymbolConstNumeric(def->NodeName, TypeError, 0); + def->Symbol = Create(def->NodeName, TypeError, 0); } constant.Outputtable->ReplaceSymbol(def->Symbol); } @@ -1025,7 +1025,7 @@ void ZCCCompiler::CompileArrays(ZCC_StructWork *work) copyp += ztype->Align; } } - work->Type()->Symbols.AddSymbol(new PField(sas->Id, NewArray(ztype, values.Size()), VARF_Static | VARF_ReadOnly, (size_t)destmem)); + work->Type()->Symbols.AddSymbol(Create(sas->Id, NewArray(ztype, values.Size()), VARF_Static | VARF_ReadOnly, (size_t)destmem)); } } @@ -1337,7 +1337,7 @@ bool ZCCCompiler::CompileFields(PContainerType *type, TArrayBitValue != 0) thisfieldtype = fd->FieldSize == 1 ? TypeUInt8 : fd->FieldSize == 2 ? TypeUInt16 : TypeUInt32; - PField *field = new PField(name->Name, thisfieldtype, varflags | VARF_Native | VARF_Static, fd->FieldOffset, fd->BitValue); + PField *field = Create(name->Name, thisfieldtype, varflags | VARF_Native | VARF_Static, fd->FieldOffset, fd->BitValue); if (OutNamespace->Symbols.AddSymbol(field) == nullptr) { // name is already in use @@ -1428,7 +1428,7 @@ bool ZCCCompiler::CompileProperties(PClass *type, TArray &Proper else qualifiedname.Format("@property@%s.%s", prefix.GetChars(), name.GetChars()); fields.ShrinkToFit(); - if (!type->VMType->Symbols.AddSymbol(new PProperty(qualifiedname, fields))) + if (!type->VMType->Symbols.AddSymbol(Create(qualifiedname, fields))) { Error(id, "Unable to add property %s to class %s", FName(p->NodeName).GetChars(), type->TypeName.GetChars()); } @@ -2607,7 +2607,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool } while (p != f->Params); } - PFunction *sym = new PFunction(c->Type(), f->Name); + PFunction *sym = Create(c->Type(), f->Name); sym->AddVariant(NewPrototype(rets, args), argflags, argnames, afd == nullptr ? nullptr : *(afd->VMPointer), varflags, useflags); c->Type()->Symbols.ReplaceSymbol(sym); diff --git a/src/v_text.cpp b/src/v_text.cpp index 3c31312b3..cf8ce8cc7 100644 --- a/src/v_text.cpp +++ b/src/v_text.cpp @@ -454,5 +454,5 @@ DEFINE_ACTION_FUNCTION(FFont, BreakLines) unsigned int count; FBrokenLines *broken = V_BreakLines(self, maxwidth, text, true, &count); - ACTION_RETURN_OBJECT(new DBrokenLines(broken, count)); + ACTION_RETURN_OBJECT(Create(broken, count)); } diff --git a/src/wi_stuff.cpp b/src/wi_stuff.cpp index dc915a011..113253f95 100644 --- a/src/wi_stuff.cpp +++ b/src/wi_stuff.cpp @@ -251,7 +251,7 @@ DEFINE_ACTION_FUNCTION(DInterBackground, Create) { PARAM_PROLOGUE; PARAM_POINTER(wbst, wbstartstruct_t); - ACTION_RETURN_POINTER(new DInterBackground(wbst)); + ACTION_RETURN_POINTER(Create(wbst)); } //==================================================================== diff --git a/src/win32/i_main.cpp b/src/win32/i_main.cpp index 99706c9a9..bf16a8708 100644 --- a/src/win32/i_main.cpp +++ b/src/win32/i_main.cpp @@ -124,7 +124,7 @@ extern UINT TimerPeriod; // PUBLIC DATA DEFINITIONS ------------------------------------------------- // The command line arguments. -DArgs *Args; +FArgs *Args; HINSTANCE g_hInst; DWORD SessionID; @@ -840,7 +840,7 @@ void DoMain (HINSTANCE hInstance) _set_new_handler (NewFailure); #endif - Args = new DArgs(__argc, __argv); + Args = new FArgs(__argc, __argv); // Load Win32 modules Kernel32Module.Load({"kernel32.dll"}); From 33145610b1c3a7f1f1572127fd11faac06c9407b Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 14 Apr 2017 13:48:00 +0200 Subject: [PATCH 02/18] - let's better add a null check to Create<> in case allocation or construction fails. Although unlikely it's not impossible. --- src/dobject.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/dobject.h b/src/dobject.h index 55a05c955..ee2bfb5af 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -360,13 +360,18 @@ protected: }; +// This is the only method aside from calling CreateNew that should be used for creating DObjects +// to ensure that the Class pointer is always set. template T* Create(Args&&... args) { DObject::nonew nono; T *object = new(nono) T(std::forward(args)...); - object->SetClass(RUNTIME_CLASS(T)); - assert(object->GetClass() != nullptr); // beware of object that get created before the type system is up. + if (object != nullptr) + { + object->SetClass(RUNTIME_CLASS(T)); + assert(object->GetClass() != nullptr); // beware of objects that get created before the type system is up. + } return object; } From fd07b56ae914e2026f3e2fed993168ae321e685b Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Fri, 14 Apr 2017 16:13:51 +0300 Subject: [PATCH 03/18] Fixed link error for MSVC x64 build with modern Windows SDK win32video.obj : error LNK2001: unresolved external symbol IID_IDirectDraw2 --- src/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a6dcfd766..da79cd408 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -111,6 +111,7 @@ if( WIN32 ) ( MSVC15 AND NOT CMAKE_GENERATOR_TOOLSET STREQUAL "v150_xp" ) ) # For VS 2017. # for modern Windows SDKs the DirectX headers should be available by default. set( DX_dinput8_LIBRARY dinput8 ) + set( DX_dxguid_LIBRARY dxguid ) else() find_path( D3D_INCLUDE_DIR d3d9.h From 7983f6ea4fa9e28e414ded7f16bed215aa7b71ae Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 14 Apr 2017 15:20:02 +0200 Subject: [PATCH 04/18] - fixed incorrect return variable. --- src/scripting/backend/scopebarrier.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripting/backend/scopebarrier.cpp b/src/scripting/backend/scopebarrier.cpp index 65740ec18..4fe0f646d 100644 --- a/src/scripting/backend/scopebarrier.cpp +++ b/src/scripting/backend/scopebarrier.cpp @@ -93,7 +93,7 @@ EScopeFlags FScopeBarrier::ChangeSideInObjectFlags(EScopeFlags flags, int side) int f = int(flags); f &= ~(Scope_UI | Scope_Play); f |= ObjectFlagsFromSide(side); - return (EScopeFlags)flags; + return (EScopeFlags)f; } FScopeBarrier::FScopeBarrier() From 47bb29bac6b32af32b31db82e33242e69a87287a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 14 Apr 2017 15:32:04 +0200 Subject: [PATCH 05/18] - check the return value of ogl_LoadFunctions and abort if it indicates failure. If this happens there is normally something very wrong on the system side so continuing is not advised. --- src/gl/system/gl_framebuffer.cpp | 5 ++++- src/posix/cocoa/i_video.mm | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/gl/system/gl_framebuffer.cpp b/src/gl/system/gl_framebuffer.cpp index 24e6ee626..a684f4c4c 100644 --- a/src/gl/system/gl_framebuffer.cpp +++ b/src/gl/system/gl_framebuffer.cpp @@ -120,7 +120,10 @@ void OpenGLFrameBuffer::InitializeState() if (first) { - ogl_LoadFunctions(); + if (ogl_LoadFunctions() == ogl_LOAD_FAILED) + { + I_FatalError("Failed to load OpenGL functions."); + } } gl_LoadExtensions(); diff --git a/src/posix/cocoa/i_video.mm b/src/posix/cocoa/i_video.mm index 34cb4bb8b..e74161559 100644 --- a/src/posix/cocoa/i_video.mm +++ b/src/posix/cocoa/i_video.mm @@ -888,7 +888,10 @@ CocoaFrameBuffer::CocoaFrameBuffer(int width, int height, bool bgra, bool fullsc if (!isOpenGLInitialized) { - ogl_LoadFunctions(); + if (ogl_LoadFunctions() == ogl_LOAD_FAILED) + { + I_FatalError("Failed to load OpenGL functions."); + } isOpenGLInitialized = true; } From 1135f154b7eb490bf34e6309c619ba4e84afc701 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 14 Apr 2017 15:41:36 +0200 Subject: [PATCH 06/18] - fixed: For Screen.SetClipRect, -1 is a valid value for width and height so it must not be clamped away. --- src/v_draw.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/v_draw.cpp b/src/v_draw.cpp index 314a0fb9a..ea589cbfc 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -186,9 +186,9 @@ void DCanvas::DrawTextureParms(FTexture *img, DrawParms &parms) void DCanvas::SetClipRect(int x, int y, int w, int h) { clipleft = clamp(x, 0, GetWidth()); - clipwidth = clamp(w, 0, GetWidth() - x); + clipwidth = clamp(w, -1, GetWidth() - x); cliptop = clamp(y, 0, GetHeight()); - clipheight = clamp(h, 0, GetHeight() - y); + clipheight = clamp(h, -1, GetHeight() - y); } DEFINE_ACTION_FUNCTION(_Screen, SetClipRect) From 92acbdc6256aba4630b5c79db597b8ad58185810 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 14 Apr 2017 16:14:27 +0200 Subject: [PATCH 07/18] - made GetClassName an intrinsic and expanded it to also work on class types. --- src/dobject.cpp | 6 --- src/namedef.h | 1 + src/scripting/backend/codegen.cpp | 75 +++++++++++++++++++++++++++---- src/scripting/backend/codegen.h | 19 ++++++++ wadsrc/static/zscript/base.txt | 1 - 5 files changed, 87 insertions(+), 15 deletions(-) diff --git a/src/dobject.cpp b/src/dobject.cpp index 687e76f85..39c55f2b5 100644 --- a/src/dobject.cpp +++ b/src/dobject.cpp @@ -612,12 +612,6 @@ void DObject::CheckIfSerialized () const } -DEFINE_ACTION_FUNCTION(DObject, GetClassName) -{ - PARAM_SELF_PROLOGUE(DObject); - ACTION_RETURN_INT(self->GetClass()->TypeName); -} - DEFINE_ACTION_FUNCTION(DObject, MSTime) { ACTION_RETURN_INT(I_MSTime()); diff --git a/src/namedef.h b/src/namedef.h index ae0a17afd..fec4093fd 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -335,6 +335,7 @@ xx(RandomPick) xx(FRandomPick) xx(GetClass) xx(GetParentClass) +xx(GetClassName) xx(GetDefaultByType) xx(Exp) xx(Log10) diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index 76ab83358..09d85f726 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -7775,6 +7775,13 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) } break; + case NAME_GetClassName: + if (CheckArgSize(NAME_GetClassName, ArgList, 0, 0, ScriptPosition)) + { + func = new FxGetClassName(new FxSelf(ScriptPosition)); + } + break; + case NAME_GetDefaultByType: if (CheckArgSize(NAME_GetDefaultByType, ArgList, 1, 1, ScriptPosition)) { @@ -8215,14 +8222,20 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) if (MethodName == NAME_GetParentClass && (Self->IsObject() || Self->ValueType->isClassPointer())) { - if (ArgList.Size() > 0) + if (CheckArgSize(NAME_GetParentClass, ArgList, 0, 0, ScriptPosition)) { - ScriptPosition.Message(MSG_ERROR, "too many parameters in call to %s", MethodName.GetChars()); - delete this; - return nullptr; + auto x = new FxGetParentClass(Self); + return x->Resolve(ctx); + } + } + if (MethodName == NAME_GetClassName && + (Self->IsObject() || Self->ValueType->isClassPointer())) + { + if (CheckArgSize(NAME_GetClassName, ArgList, 0, 0, ScriptPosition)) + { + auto x = new FxGetClassName(Self); + return x->Resolve(ctx); } - auto x = new FxGetParentClass(Self); - return x->Resolve(ctx); } if (Self->ValueType->isRealPointer()) @@ -9336,11 +9349,11 @@ FxExpression *FxGetParentClass::Resolve(FCompileContext &ctx) if (!Self->ValueType->isClassPointer() && !Self->IsObject()) { - ScriptPosition.Message(MSG_ERROR, "GetClass() requires an object"); + ScriptPosition.Message(MSG_ERROR, "GetParentClass() requires an object"); delete this; return nullptr; } - ValueType = NewClassPointer(RUNTIME_CLASS(DObject)); // + ValueType = NewClassPointer(RUNTIME_CLASS(DObject)); return this; } @@ -9365,6 +9378,52 @@ ExpEmit FxGetParentClass::Emit(VMFunctionBuilder *build) // //========================================================================== +FxGetClassName::FxGetClassName(FxExpression *self) + :FxExpression(EFX_GetClassName, self->ScriptPosition) +{ + Self = self; +} + +FxGetClassName::~FxGetClassName() +{ + SAFE_DELETE(Self); +} + +FxExpression *FxGetClassName::Resolve(FCompileContext &ctx) +{ + SAFE_RESOLVE(Self, ctx); + + if (!Self->ValueType->isClassPointer() && !Self->IsObject()) + { + ScriptPosition.Message(MSG_ERROR, "GetClassName() requires an object"); + delete this; + return nullptr; + } + ValueType = TypeName; + return this; +} + +ExpEmit FxGetClassName::Emit(VMFunctionBuilder *build) +{ + ExpEmit op = Self->Emit(build); + op.Free(build); + if (Self->IsObject()) + { + ExpEmit to(build, REGT_POINTER); + build->Emit(OP_CLSS, to.RegNum, op.RegNum); + op = to; + op.Free(build); + } + ExpEmit to(build, REGT_INT); + build->Emit(OP_LW, to.RegNum, op.RegNum, build->GetConstantInt(myoffsetof(PClass, TypeName))); + return to; +} + +//========================================================================== +// +// +//========================================================================== + FxGetDefaultByType::FxGetDefaultByType(FxExpression *self) :FxExpression(EFX_GetDefaultByType, self->ScriptPosition) { diff --git a/src/scripting/backend/codegen.h b/src/scripting/backend/codegen.h index aa2e06910..004b1f228 100644 --- a/src/scripting/backend/codegen.h +++ b/src/scripting/backend/codegen.h @@ -296,6 +296,7 @@ enum EFxType EFX_NamedNode, EFX_GetClass, EFX_GetParentClass, + EFX_GetClassName, EFX_StrLen, EFX_ColorLiteral, EFX_GetDefaultByType, @@ -1660,6 +1661,24 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +//========================================================================== +// +// FxGetClass +// +//========================================================================== + +class FxGetClassName : public FxExpression +{ + FxExpression *Self; + +public: + + FxGetClassName(FxExpression *self); + ~FxGetClassName(); + FxExpression *Resolve(FCompileContext&); + ExpEmit Emit(VMFunctionBuilder *build); +}; + //========================================================================== // // FxGetDefaultByType diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index c834dff94..7d0e54213 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -342,7 +342,6 @@ class Object native native static uint MSTime(); native vararg static void ThrowAbortException(String fmt, ...); - native Name GetClassName(); native virtualscope void Destroy(); // This does not call into the native method of the same name to avoid problems with objects that get garbage collected late on shutdown. From 329c168cc204854f2101fd08d806eb8f923b786c Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 14 Apr 2017 16:28:54 +0200 Subject: [PATCH 08/18] - added a distance parameter to A_SprayDecal. --- src/g_shared/a_decals.cpp | 4 ++-- src/g_shared/a_sharedglobal.h | 2 +- src/p_actionfunctions.cpp | 3 ++- wadsrc/static/zscript/actor.txt | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/g_shared/a_decals.cpp b/src/g_shared/a_decals.cpp index 3840a9af9..edc170294 100644 --- a/src/g_shared/a_decals.cpp +++ b/src/g_shared/a_decals.cpp @@ -704,7 +704,7 @@ CCMD (spray) Net_WriteString (argv[1]); } -void SprayDecal(AActor *shooter, const char *name) +void SprayDecal(AActor *shooter, const char *name, double distance) { FTraceResults trace; @@ -713,7 +713,7 @@ void SprayDecal(AActor *shooter, const char *name) double c = pitch.Cos(); DVector3 vec(c * ang.Cos(), c * ang.Sin(), -pitch.Sin()); - if (Trace(shooter->PosPlusZ(shooter->Height / 2), shooter->Sector, vec, 172., 0, ML_BLOCKEVERYTHING, shooter, trace, TRACE_NoSky)) + if (Trace(shooter->PosPlusZ(shooter->Height / 2), shooter->Sector, vec, distance, 0, ML_BLOCKEVERYTHING, shooter, trace, TRACE_NoSky)) { if (trace.HitType == TRACE_HitWall) { diff --git a/src/g_shared/a_sharedglobal.h b/src/g_shared/a_sharedglobal.h index f45cd9d0e..626985f93 100644 --- a/src/g_shared/a_sharedglobal.h +++ b/src/g_shared/a_sharedglobal.h @@ -11,7 +11,7 @@ struct F3DFloor; class DBaseDecal; class DBaseDecal *ShootDecal(const FDecalTemplate *tpl, AActor *basisactor, sector_t *sec, double x, double y, double z, DAngle angle, double tracedist, bool permanent); -void SprayDecal(AActor *shooter, const char *name); +void SprayDecal(AActor *shooter, const char *name,double distance = 172.); class DBaseDecal : public DThinker { diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 0387bfd52..838c885e6 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -6813,7 +6813,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_SprayDecal) { PARAM_SELF_PROLOGUE(AActor); PARAM_STRING(name); - SprayDecal(self, name); + PARAM_FLOAT_DEF(dist); + SprayDecal(self, name, dist); return 0; } diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index fb883f846..9b7836d17 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -1092,7 +1092,7 @@ class Actor : Thinker native native bool A_SetVisibleRotation(double anglestart = 0, double angleend = 0, double pitchstart = 0, double pitchend = 0, int flags = 0, int ptr = AAPTR_DEFAULT); native void A_SetTranslation(name transname); native bool A_SetSize(double newradius, double newheight = -1, bool testpos = false); - native void A_SprayDecal(String name); + native void A_SprayDecal(String name, double dist = 172); native void A_SetMugshotState(String name); native void A_RearrangePointers(int newtarget, int newmaster = AAPTR_DEFAULT, int newtracer = AAPTR_DEFAULT, int flags=0); From cde450dd8a8735bc7444d795353b65ef15178659 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 14 Apr 2017 16:51:11 +0200 Subject: [PATCH 09/18] - some enhancements for PowerReflection. --- src/namedef.h | 1 + src/p_interaction.cpp | 13 ++++++++++--- wadsrc/static/zscript/inventory/powerups.txt | 4 ++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/namedef.h b/src/namedef.h index fec4093fd..bfbf26362 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -911,3 +911,4 @@ xx(Enum) xx(StaticArray) xx(DynArray) xx(Struct) +xx(ReflectType) diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 7df05653e..59a22fa76 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1122,20 +1122,27 @@ static int DamageMobj (AActor *target, AActor *inflictor, AActor *source, int da { int reflectdamage = 0; + bool reflecttype = false; for (auto p = target->player->mo->Inventory; p != nullptr; p = p->Inventory) { // This picks the reflection item with the maximum efficiency for the given damage type. if (p->IsKindOf(NAME_PowerReflection)) { - int mydamage = p->ApplyDamageFactor(mod, damage); - if (mydamage > reflectdamage) reflectdamage = mydamage; + double alwaysreflect = p->FloatVar(NAME_Strength); + int alwaysdamage = clamp(int(damage * alwaysreflect), 0, damage); + int mydamage = alwaysdamage + p->ApplyDamageFactor(mod, damage - alwaysdamage); + if (mydamage > reflectdamage) + { + reflectdamage = mydamage; + reflecttype = p->BoolVar(NAME_ReflectType); + } } } if (reflectdamage > 0) { // use the reflect item's damage factors to get the final value here. - P_DamageMobj(source, nullptr, target, reflectdamage, NAME_Reflection ); + P_DamageMobj(source, nullptr, target, reflectdamage, reflecttype? mod : NAME_Reflection ); // Reset means of death flag. MeansOfDeath = mod; diff --git a/wadsrc/static/zscript/inventory/powerups.txt b/wadsrc/static/zscript/inventory/powerups.txt index 045331672..8402588c5 100644 --- a/wadsrc/static/zscript/inventory/powerups.txt +++ b/wadsrc/static/zscript/inventory/powerups.txt @@ -1861,6 +1861,10 @@ class PowerInfiniteAmmo : Powerup class PowerReflection : Powerup { + // if 1, reflects the damage type as well. + bool ReflectType; + property ReflectType : ReflectType; + Default { Powerup.Duration -60; From 2add60a4c4092fd5e429afe885ace09ea87c3653 Mon Sep 17 00:00:00 2001 From: "alexey.lysiuk" Date: Fri, 14 Apr 2017 17:54:01 +0300 Subject: [PATCH 10/18] Single RUNTIME_CLASS() macro for classes and templates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The main purpose of this is to fix compilation errors with GCC/Clang src/dobject.h:87:48: error: expected primary-expression before ‘)’ token --- src/actor.h | 8 ++++---- src/dobject.h | 3 +-- src/dthinker.h | 4 ++-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/actor.h b/src/actor.h index 1eda53028..bc65144da 100644 --- a/src/actor.h +++ b/src/actor.h @@ -739,7 +739,7 @@ public: AInventory *FindInventory (FName type, bool subclass = false); template T *FindInventory () { - return static_cast (FindInventory (RUNTIME_TEMPLATE_CLASS(T))); + return static_cast (FindInventory (RUNTIME_CLASS(T))); } // Adds one item of a particular type. Returns NULL if it could not be added. @@ -1512,7 +1512,7 @@ public: do { actor = FActorIterator::Next (); - } while (actor && !actor->IsKindOf (RUNTIME_TEMPLATE_CLASS(T))); + } while (actor && !actor->IsKindOf (RUNTIME_CLASS(T))); return static_cast(actor); } }; @@ -1563,12 +1563,12 @@ inline AActor *Spawn(FName type, const DVector3 &pos, replace_t allowreplacement template inline T *Spawn(const DVector3 &pos, replace_t allowreplacement) { - return static_cast(AActor::StaticSpawn(RUNTIME_TEMPLATE_CLASS(T), pos, allowreplacement)); + return static_cast(AActor::StaticSpawn(RUNTIME_CLASS(T), pos, allowreplacement)); } template inline T *Spawn() // for inventory items we do not need coordinates and replacement info. { - return static_cast(AActor::StaticSpawn(RUNTIME_TEMPLATE_CLASS(T), DVector3(0, 0, 0), NO_REPLACE)); + return static_cast(AActor::StaticSpawn(RUNTIME_CLASS(T), DVector3(0, 0, 0), NO_REPLACE)); } inline PClassActor *PClass::FindActor(FName name) diff --git a/src/dobject.h b/src/dobject.h index ee2bfb5af..d043dfada 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -84,8 +84,7 @@ class DPillar; class PClassActor; #define RUNTIME_CLASS_CASTLESS(cls) (cls::RegistrationInfo.MyClass) // Passed a native class name, returns a PClass representing that class -#define RUNTIME_CLASS(cls) ((cls::MetaClass *)RUNTIME_CLASS_CASTLESS(cls)) // Like above, but returns the true type of the meta object -#define RUNTIME_TEMPLATE_CLASS(cls) ((typename cls::MetaClass *)RUNTIME_CLASS_CASTLESS(cls)) // RUNTIME_CLASS, but works with templated parameters on GCC +#define RUNTIME_CLASS(cls) ((typename cls::MetaClass *)RUNTIME_CLASS_CASTLESS(cls)) // Like above, but returns the true type of the meta object #define NATIVE_TYPE(object) (object->StaticType()) // Passed an object, returns the type of the C++ class representing the object // Enumerations for the meta classes created by ClassReg::RegisterClass() diff --git a/src/dthinker.h b/src/dthinker.h index c7a768ae3..da7eced7d 100644 --- a/src/dthinker.h +++ b/src/dthinker.h @@ -134,10 +134,10 @@ protected: template class TThinkerIterator : public FThinkerIterator { public: - TThinkerIterator (int statnum=MAX_STATNUM+1) : FThinkerIterator (RUNTIME_TEMPLATE_CLASS(T), statnum) + TThinkerIterator (int statnum=MAX_STATNUM+1) : FThinkerIterator (RUNTIME_CLASS(T), statnum) { } - TThinkerIterator (int statnum, DThinker *prev) : FThinkerIterator (RUNTIME_TEMPLATE_CLASS(T), statnum, prev) + TThinkerIterator (int statnum, DThinker *prev) : FThinkerIterator (RUNTIME_CLASS(T), statnum, prev) { } TThinkerIterator (const PClass *subclass, int statnum=MAX_STATNUM+1) : FThinkerIterator(subclass, statnum) From d03c33f39330121a7e42c1d70c750a4d94410f65 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 14 Apr 2017 17:40:05 +0200 Subject: [PATCH 11/18] - added Translation.GetID. --- src/r_data/r_translate.cpp | 7 +++++++ wadsrc/static/zscript/base.txt | 1 + 2 files changed, 8 insertions(+) diff --git a/src/r_data/r_translate.cpp b/src/r_data/r_translate.cpp index 3c61ec4ac..b069aa9f3 100644 --- a/src/r_data/r_translate.cpp +++ b/src/r_data/r_translate.cpp @@ -1356,6 +1356,13 @@ int R_FindCustomTranslation(FName name) return (t != nullptr)? *t : -1; } +DEFINE_ACTION_FUNCTION(_Translation, GetID) +{ + PARAM_PROLOGUE; + PARAM_NAME(t); + ACTION_RETURN_INT(R_FindCustomTranslation(t)); +} + //---------------------------------------------------------------------------- // // diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 7d0e54213..bb941b414 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -258,6 +258,7 @@ struct Translation version("2.4") native int AddTranslation(); native static bool SetPlayerTranslation(int group, int num, int plrnum, PlayerClass pclass); + native static int GetID(Name transname); static int MakeID(int group, int num) { return (group << 16) + num; From 71863422210d5d792dda28d232e8f33a95a4ab2f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 14 Apr 2017 19:25:47 +0200 Subject: [PATCH 12/18] - do not try to serialize static arrays. --- src/scripting/symbols.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scripting/symbols.cpp b/src/scripting/symbols.cpp index 1d25d11fe..76afe8d2a 100644 --- a/src/scripting/symbols.cpp +++ b/src/scripting/symbols.cpp @@ -370,7 +370,7 @@ void PSymbolTable::WriteFields(FSerializer &ar, const void *addr, const void *de { const PField *field = dyn_cast(pair->Value); // Skip fields without or with native serialization - if (field && !(field->Flags & (VARF_Transient | VARF_Meta))) + if (field && !(field->Flags & (VARF_Transient | VARF_Meta | VARF_Static))) { // todo: handle defaults in WriteValue //auto defp = def == nullptr ? nullptr : (const uint8_t *)def + field->Offset; From d014395daea89ccbaf91809010e691fee6a0b6e8 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 14 Apr 2017 19:40:50 +0200 Subject: [PATCH 13/18] - do not delete the namespaces when removing compiler symbols. They still get referenced by some types and must remain until the engine shuts down. --- src/dobjtype.cpp | 2 +- src/scripting/symbols.cpp | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 2bd1a8a0f..bf41d3cde 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -267,6 +267,7 @@ void PClass::StaticShutdown () { p.PendingWeapon = nullptr; } + Namespaces.ReleaseSymbols(); // This must be done in two steps because the native classes are not ordered by inheritance, // so all meta data must be gone before deleting the actual class objects. @@ -275,7 +276,6 @@ void PClass::StaticShutdown () // Unless something went wrong, anything left here should be class and type objects only, which do not own any scripts. bShutdown = true; TypeTable.Clear(); - Namespaces.ReleaseSymbols(); ClassDataAllocator.FreeAllBlocks(); AllClasses.Clear(); PClassActor::AllActorClasses.Clear(); diff --git a/src/scripting/symbols.cpp b/src/scripting/symbols.cpp index 76afe8d2a..9fcefd603 100644 --- a/src/scripting/symbols.cpp +++ b/src/scripting/symbols.cpp @@ -512,13 +512,16 @@ PNamespace *FNamespaceManager::NewNamespace(int filenum) //========================================================================== // -// +// Deallocate the entire namespace manager. // //========================================================================== void FNamespaceManager::ReleaseSymbols() { - RemoveSymbols(); + for (auto ns : AllNamespaces) + { + delete ns; + } GlobalNamespace = nullptr; AllNamespaces.Clear(); } @@ -537,7 +540,7 @@ int FNamespaceManager::RemoveSymbols() for (auto ns : AllNamespaces) { count += ns->Symbols.Symbols.CountUsed(); - delete ns; + ns->Symbols.ReleaseSymbols(); } return count; } @@ -550,7 +553,6 @@ int FNamespaceManager::RemoveSymbols() void RemoveUnusedSymbols() { - // Global symbols are not needed anymore after running the compiler. int count = Namespaces.RemoveSymbols(); // We do not need any non-field and non-function symbols in structs and classes anymore. From 3d8821ee822f68887f421af4790fa06fed8d41b0 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 14 Apr 2017 20:27:46 +0200 Subject: [PATCH 14/18] - make polyobject setup errors not abort the map. --- src/po_man.cpp | 49 +++++++++++++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/src/po_man.cpp b/src/po_man.cpp index 50a50d0da..09c42211c 100644 --- a/src/po_man.cpp +++ b/src/po_man.cpp @@ -34,6 +34,7 @@ #include "p_blockmap.h" #include "g_levellocals.h" #include "actorinlines.h" +#include "v_text.h" // MACROS ------------------------------------------------------------------ @@ -1536,19 +1537,23 @@ static void SpawnPolyobj (int index, int tag, int type) { if (po->Sidedefs.Size() > 0) { - I_Error ("SpawnPolyobj: Polyobj %d already spawned.\n", tag); + Printf (TEXTCOLOR_RED "SpawnPolyobj: Polyobj %d already spawned.\n", tag); + return; } - sd->linedef->special = 0; - sd->linedef->args[0] = 0; - IterFindPolySides(&polyobjs[index], sd); - po->MirrorNum = sd->linedef->args[1]; - po->crush = (type != SMT_PolySpawn) ? 3 : 0; - po->bHurtOnTouch = (type == SMT_PolySpawnHurt); - po->tag = tag; - po->seqType = sd->linedef->args[2]; - if (po->seqType < 0 || po->seqType > 63) + else { - po->seqType = 0; + sd->linedef->special = 0; + sd->linedef->args[0] = 0; + IterFindPolySides(&polyobjs[index], sd); + po->MirrorNum = sd->linedef->args[1]; + po->crush = (type != SMT_PolySpawn) ? 3 : 0; + po->bHurtOnTouch = (type == SMT_PolySpawnHurt); + po->tag = tag; + po->seqType = sd->linedef->args[2]; + if (po->seqType < 0 || po->seqType > 63) + { + po->seqType = 0; + } } break; } @@ -1570,9 +1575,13 @@ static void SpawnPolyobj (int index, int tag, int type) { if (!level.sides[i].linedef->args[1]) { - I_Error("SpawnPolyobj: Explicit line missing order number in poly %d, linedef %d.\n", tag, level.sides[i].linedef->Index()); + Printf(TEXTCOLOR_RED "SpawnPolyobj: Explicit line missing order number in poly %d, linedef %d.\n", tag, level.sides[i].linedef->Index()); + return; + } + else + { + po->Sidedefs.Push(&level.sides[i]); } - po->Sidedefs.Push (&level.sides[i]); } } qsort(&po->Sidedefs[0], po->Sidedefs.Size(), sizeof(po->Sidedefs[0]), posicmp); @@ -1585,7 +1594,10 @@ static void SpawnPolyobj (int index, int tag, int type) po->MirrorNum = po->Sidedefs[0]->linedef->args[2]; } else - I_Error ("SpawnPolyobj: Poly %d does not exist\n", tag); + { + Printf(TEXTCOLOR_RED "SpawnPolyobj: Poly %d does not exist\n", tag); + return; + } } validcount++; @@ -1648,11 +1660,13 @@ static void TranslateToStartSpot (int tag, const DVector2 &origin) } if (po == NULL) { // didn't match the tag with a polyobj tag - I_Error("TranslateToStartSpot: Unable to match polyobj tag: %d\n", tag); + Printf(TEXTCOLOR_RED "TranslateToStartSpot: Unable to match polyobj tag: %d\n", tag); + return; } if (po->Sidedefs.Size() == 0) { - I_Error ("TranslateToStartSpot: Anchor point located without a StartSpot point: %d\n", tag); + Printf(TEXTCOLOR_RED "TranslateToStartSpot: Anchor point located without a StartSpot point: %d\n", tag); + return; } po->OriginalPts.Resize(po->Sidedefs.Size()); po->PrevPts.Resize(po->Sidedefs.Size()); @@ -1738,8 +1752,7 @@ void PO_Init (void) { if (polyobjs[polyIndex].OriginalPts.Size() == 0) { - I_Error ("PO_Init: StartSpot located without an Anchor point: %d\n", - polyobjs[polyIndex].tag); + Printf (TEXTCOLOR_RED "PO_Init: StartSpot located without an Anchor point: %d\n", polyobjs[polyIndex].tag); } } InitBlockMap(); From c73b71807b53a9bfe1037fd45c1e02f0b91a0ed3 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 14 Apr 2017 22:06:29 +0200 Subject: [PATCH 15/18] - fixed: During hub travel, static thinkers may not be deserialized. Since they are static, the version that got carried over from the last level will still be there and the more current version. --- src/dthinker.cpp | 56 ++++++++++++++++++++++++++---------------------- src/p_saveg.cpp | 2 +- 2 files changed, 31 insertions(+), 27 deletions(-) diff --git a/src/dthinker.cpp b/src/dthinker.cpp index d68939665..5e5360651 100644 --- a/src/dthinker.cpp +++ b/src/dthinker.cpp @@ -179,37 +179,41 @@ void DThinker::SerializeThinkers(FSerializer &arc, bool hubLoad) { for (i = 0; i <= MAX_STATNUM; i++) { + if (arc.BeginArray(nullptr)) { - int size = arc.ArraySize(); - for (int j = 0; j < size; j++) + if (!hubLoad || i != STAT_STATIC) // do not load static thinkers in a hub transition because they'd just duplicate the active ones. { - DThinker *thinker = nullptr; - arc(nullptr, thinker); - if (thinker != nullptr) + int size = arc.ArraySize(); + for (int j = 0; j < size; j++) { - // This may be a player stored in their ancillary list. Remove - // them first before inserting them into the new list. - if (thinker->NextThinker != nullptr) + DThinker *thinker = nullptr; + arc(nullptr, thinker); + if (thinker != nullptr) { - thinker->Remove(); - } - // Thinkers with the OF_JustSpawned flag set go in the FreshThinkers - // list. Anything else goes in the regular Thinkers list. - if (thinker->ObjectFlags & OF_EuthanizeMe) - { - // This thinker was destroyed during the loading process. Do - // not link it into any list. - } - else if (thinker->ObjectFlags & OF_JustSpawned) - { - FreshThinkers[i].AddTail(thinker); - thinker->PostSerialize(); - } - else - { - Thinkers[i].AddTail(thinker); - thinker->PostSerialize(); + // This may be a player stored in their ancillary list. Remove + // them first before inserting them into the new list. + if (thinker->NextThinker != nullptr) + { + thinker->Remove(); + } + // Thinkers with the OF_JustSpawned flag set go in the FreshThinkers + // list. Anything else goes in the regular Thinkers list. + if (thinker->ObjectFlags & OF_EuthanizeMe) + { + // This thinker was destroyed during the loading process. Do + // not link it into any list. + } + else if (thinker->ObjectFlags & OF_JustSpawned) + { + FreshThinkers[i].AddTail(thinker); + thinker->PostSerialize(); + } + else + { + Thinkers[i].AddTail(thinker); + thinker->PostSerialize(); + } } } } diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index b20e9af09..6c8d29973 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -996,7 +996,7 @@ void G_SerializeLevel(FSerializer &arc, bool hubload) // [ZZ] serialize events E_SerializeEvents(arc); - DThinker::SerializeThinkers(arc, !hubload); + DThinker::SerializeThinkers(arc, hubload); arc.Array("polyobjs", polyobjs, po_NumPolyobjs); SerializeSubsectors(arc, "subsectors"); StatusBar->SerializeMessages(arc); From ca1981c52fcfe4a41d2e2389d0226f2732037060 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 14 Apr 2017 23:06:12 +0200 Subject: [PATCH 16/18] - fixed missing null pointer check in BuiltinNameToClass. --- src/scripting/backend/codegen.cpp | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/src/scripting/backend/codegen.cpp b/src/scripting/backend/codegen.cpp index 09d85f726..737bb3c31 100644 --- a/src/scripting/backend/codegen.cpp +++ b/src/scripting/backend/codegen.cpp @@ -10739,27 +10739,21 @@ FxExpression *FxClassTypeCast::Resolve(FCompileContext &ctx) int BuiltinNameToClass(VMValue *param, TArray &defaultparam, int numparam, VMReturn *ret, int numret) { - assert(numparam == 2); - assert(numret == 1); - assert(param[0].Type == REGT_INT); - assert(param[1].Type == REGT_POINTER); - assert(ret->RegType == REGT_POINTER); + PARAM_PROLOGUE; + PARAM_NAME(clsname); + PARAM_CLASS(desttype, DObject); - FName clsname = ENamedName(param[0].i); + PClass *cls = nullptr; if (clsname != NAME_None) { - const PClass *cls = PClass::FindClass(clsname); - const PClass *desttype = reinterpret_cast(param[1].a); - - if (cls->VMType == nullptr || !cls->IsDescendantOf(desttype)) + cls = PClass::FindClass(clsname); + if (cls != nullptr && (cls->VMType == nullptr || !cls->IsDescendantOf(desttype))) { - // Let the caller check this. Making this an error with a message is only taking away options from the user. + // does not match required parameters or is invalid. cls = nullptr; } - ret->SetPointer(const_cast(cls)); } - else ret->SetPointer(nullptr); - return 1; + ACTION_RETURN_POINTER(cls); } ExpEmit FxClassTypeCast::Emit(VMFunctionBuilder *build) From edebea4f8dd99cffe79639abb62e1e3cab3fa8db Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 14 Apr 2017 23:28:54 +0200 Subject: [PATCH 17/18] - allow specifying a custom class for message box display. --- src/gi.cpp | 1 + src/gi.h | 1 + src/menu/messagebox.cpp | 14 +++++++++----- src/namedef.h | 1 + wadsrc/static/mapinfo/chex.txt | 1 + wadsrc/static/mapinfo/doomcommon.txt | 1 + wadsrc/static/mapinfo/heretic.txt | 1 + wadsrc/static/mapinfo/hexen.txt | 1 + wadsrc/static/mapinfo/mindefaults.txt | 1 + wadsrc/static/mapinfo/strife.txt | 1 + wadsrc/static/zscript/menu/messagebox.txt | 2 +- 11 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/gi.cpp b/src/gi.cpp index 8dea1e577..85335554c 100644 --- a/src/gi.cpp +++ b/src/gi.cpp @@ -371,6 +371,7 @@ void FMapInfoParser::ParseGameInfo() GAMEINFOKEY_STRING_STAMPED(statusbarclass, "statusbarclass", statusbarclassfile) GAMEINFOKEY_MUSIC(intermissionMusic, intermissionOrder, "intermissionMusic") GAMEINFOKEY_STRING(CursorPic, "CursorPic") + GAMEINFOKEY_STRING(MessageBoxClass, "MessageBoxClass") GAMEINFOKEY_BOOL(noloopfinalemusic, "noloopfinalemusic") GAMEINFOKEY_BOOL(drawreadthis, "drawreadthis") GAMEINFOKEY_BOOL(swapmenu, "swapmenu") diff --git a/src/gi.h b/src/gi.h index d656e80bf..5c9dc1ae5 100644 --- a/src/gi.h +++ b/src/gi.h @@ -152,6 +152,7 @@ struct gameinfo_t int statusbarfile = -1; FName statusbarclass; int statusbarclassfile = -1; + FName MessageBoxClass; FName backpacktype; FString intermissionMusic; int intermissionOrder; diff --git a/src/menu/messagebox.cpp b/src/menu/messagebox.cpp index 368420964..3531cf2f6 100644 --- a/src/menu/messagebox.cpp +++ b/src/menu/messagebox.cpp @@ -66,14 +66,18 @@ DEFINE_ACTION_FUNCTION(DMessageBoxMenu, CallHandler) DMenu *CreateMessageBoxMenu(DMenu *parent, const char *message, int messagemode, bool playsound, FName action = NAME_None, hfunc handler = nullptr) { - auto c = PClass::FindClass("MessageBoxMenu"); + auto c = PClass::FindClass(gameinfo.MessageBoxClass); + if (!c->IsDescendantOf(NAME_MessageBoxMenu)) c = PClass::FindClass(NAME_MessageBoxMenu); auto p = c->CreateNew(); FString namestr = message; - VMValue params[] = { p, parent, &namestr, messagemode, playsound, action.GetIndex(), reinterpret_cast(handler) }; - auto f = dyn_cast(c->FindSymbol("Init", false)); - VMCall(f->Variants[0].Implementation, params, countof(params), nullptr, 0); - return (DMenu*)p; + IFVIRTUALPTRNAME(p, NAME_MessageBoxMenu, Init) + { + VMValue params[] = { p, parent, &namestr, messagemode, playsound, action.GetIndex(), reinterpret_cast(handler) }; + VMCall(func, params, countof(params), nullptr, 0); + return (DMenu*)p; + } + return nullptr; } //============================================================================= diff --git a/src/namedef.h b/src/namedef.h index bfbf26362..ad29da9ba 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -912,3 +912,4 @@ xx(StaticArray) xx(DynArray) xx(Struct) xx(ReflectType) +xx(MessageBoxMenu) diff --git a/wadsrc/static/mapinfo/chex.txt b/wadsrc/static/mapinfo/chex.txt index 4bff1283e..fe852542f 100644 --- a/wadsrc/static/mapinfo/chex.txt +++ b/wadsrc/static/mapinfo/chex.txt @@ -68,6 +68,7 @@ gameinfo statscreen_coop = "CoopStatusScreen" statscreen_dm = "DeathmatchStatusScreen" statscreen_single = "DoomStatusScreen" + messageboxclass = "MessageBoxMenu" } DoomEdNums diff --git a/wadsrc/static/mapinfo/doomcommon.txt b/wadsrc/static/mapinfo/doomcommon.txt index c033ce09c..82eb14d22 100644 --- a/wadsrc/static/mapinfo/doomcommon.txt +++ b/wadsrc/static/mapinfo/doomcommon.txt @@ -69,6 +69,7 @@ gameinfo statscreen_coop = "CoopStatusScreen" statscreen_dm = "DeathmatchStatusScreen" statscreen_single = "DoomStatusScreen" + messageboxclass = "MessageBoxMenu" } spawnnums diff --git a/wadsrc/static/mapinfo/heretic.txt b/wadsrc/static/mapinfo/heretic.txt index af0295ef3..73310ad47 100644 --- a/wadsrc/static/mapinfo/heretic.txt +++ b/wadsrc/static/mapinfo/heretic.txt @@ -67,6 +67,7 @@ gameinfo statscreen_coop = "CoopStatusScreen" statscreen_dm = "DeathmatchStatusScreen" statscreen_single = "RavenStatusScreen" + messageboxclass = "MessageBoxMenu" } DoomEdNums diff --git a/wadsrc/static/mapinfo/hexen.txt b/wadsrc/static/mapinfo/hexen.txt index 37afe7336..618fd4be7 100644 --- a/wadsrc/static/mapinfo/hexen.txt +++ b/wadsrc/static/mapinfo/hexen.txt @@ -65,6 +65,7 @@ gameinfo statscreen_coop = "CoopStatusScreen" statscreen_dm = "DeathmatchStatusScreen" statscreen_single = "RavenStatusScreen" + messageboxclass = "MessageBoxMenu" } DoomEdNums diff --git a/wadsrc/static/mapinfo/mindefaults.txt b/wadsrc/static/mapinfo/mindefaults.txt index 885587281..26ab0d939 100644 --- a/wadsrc/static/mapinfo/mindefaults.txt +++ b/wadsrc/static/mapinfo/mindefaults.txt @@ -53,6 +53,7 @@ gameinfo statscreen_mapnamefont = "BigFont" statscreen_finishedpatch = "WIF" statscreen_enteringpatch = "WIENTER" + messageboxclass = "MessageBoxMenu" } DoomEdNums diff --git a/wadsrc/static/mapinfo/strife.txt b/wadsrc/static/mapinfo/strife.txt index 419c8c13f..0b52b213e 100644 --- a/wadsrc/static/mapinfo/strife.txt +++ b/wadsrc/static/mapinfo/strife.txt @@ -67,6 +67,7 @@ gameinfo statscreen_dm = "DeathmatchStatusScreen" statscreen_single = "RavenStatusScreen" statusbarclass = "StrifeStatusBar" + messageboxclass = "MessageBoxMenu" } DoomEdNums diff --git a/wadsrc/static/zscript/menu/messagebox.txt b/wadsrc/static/zscript/menu/messagebox.txt index 48d9949a3..86796d301 100644 --- a/wadsrc/static/zscript/menu/messagebox.txt +++ b/wadsrc/static/zscript/menu/messagebox.txt @@ -50,7 +50,7 @@ class MessageBoxMenu : Menu // //============================================================================= - void Init(Menu parent, String message, int messagemode, bool playsound = false, Name cmd = 'None', voidptr native_handler = null) + virtual void Init(Menu parent, String message, int messagemode, bool playsound = false, Name cmd = 'None', voidptr native_handler = null) { Super.Init(parent); mAction = cmd; From 0ebf4958b93b418fa467546184c23e6cc6eba8e7 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 15 Apr 2017 00:48:22 +0200 Subject: [PATCH 18/18] - fixed pitch calculation for camera actors. For compatibility with Hexen format they need to treat the pitch arg as a signed byte. --- wadsrc/static/zscript/shared/camera.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wadsrc/static/zscript/shared/camera.txt b/wadsrc/static/zscript/shared/camera.txt index abb394745..f19d90d25 100644 --- a/wadsrc/static/zscript/shared/camera.txt +++ b/wadsrc/static/zscript/shared/camera.txt @@ -36,7 +36,8 @@ class SecurityCamera : Actor if (args[1]) Delta /= 2; Acc = 0.; - Pitch = clamp(args[0], -89, 89); + int arg = (args[0] << 24) >> 24; // make sure the value has the intended sign. + Pitch = clamp(arg, -89, 89); Range = args[1]; }