diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 633eb466b..1239d71bb 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -1928,7 +1928,7 @@ static int PatchMisc (int dummy) } else if (a > 0) { - static_cast(GetDefaultByName (types[i]))->BlendColor = PalEntry( + GetDefaultByName (types[i])->ColorVar(NAME_BlendColor) = PalEntry( BYTE(clamp(a,0.f,1.f)*255.f), clamp(r,0,255), clamp(g,0,255), @@ -1936,7 +1936,7 @@ static int PatchMisc (int dummy) } else { - static_cast(GetDefaultByName (types[i]))->BlendColor = 0; + GetDefaultByName (types[i])->ColorVar(NAME_BlendColor) = 0; } } } diff --git a/src/dobject.cpp b/src/dobject.cpp index 6c9afb884..e31a3dd23 100644 --- a/src/dobject.cpp +++ b/src/dobject.cpp @@ -275,6 +275,7 @@ DObject::DObject () { ObjectFlags = GC::CurrentWhite & OF_WhiteBits; ObjNext = GC::Root; + GCNext = nullptr; GC::Root = this; } @@ -283,6 +284,7 @@ DObject::DObject (PClass *inClass) { ObjectFlags = GC::CurrentWhite & OF_WhiteBits; ObjNext = GC::Root; + GCNext = nullptr; GC::Root = this; } diff --git a/src/dobject.h b/src/dobject.h index 3e8801d40..367350427 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -479,6 +479,8 @@ public: // Add other types as needed. int &IntVar(FName field); + PalEntry &ColorVar(FName field); + FName &NameVar(FName field); double &FloatVar(FName field); // If you need to replace one object with another and want to diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 75513c5b5..a041b4b9d 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -3347,7 +3347,7 @@ void PClass::InitializeDefaults() Defaults = (BYTE *)M_Malloc(Size); // run the constructor on the defaults to set the vtbl pointer which is needed to run class-aware functions on them. - // bSerialOverride prevents linking into the thinker chains. + // Temporarily setting bSerialOverride prevents linking into the thinker chains. auto s = DThinker::bSerialOverride; DThinker::bSerialOverride = true; ConstructNative(Defaults); @@ -3359,9 +3359,10 @@ void PClass::InitializeDefaults() optr->SetClass(this); + // Copy the defaults from the parent but leave the DObject part alone because it contains important data. if (ParentClass->Defaults != NULL) { - memcpy(Defaults, ParentClass->Defaults, ParentClass->Size); + memcpy(Defaults + sizeof(DObject), ParentClass->Defaults + sizeof(DObject), ParentClass->Size - sizeof(DObject)); if (Size > ParentClass->Size) { memset(Defaults + ParentClass->Size, 0, Size - ParentClass->Size); @@ -3369,7 +3370,7 @@ void PClass::InitializeDefaults() } else { - memset(Defaults, 0, Size); + memset(Defaults + sizeof(DObject), 0, Size - sizeof(DObject)); } if (bRuntimeClass) diff --git a/src/dobjtype.h b/src/dobjtype.h index a7ce429bb..ee5d0984e 100644 --- a/src/dobjtype.h +++ b/src/dobjtype.h @@ -1078,6 +1078,16 @@ inline int &DObject::IntVar(FName field) return *(int*)ScriptVar(field, TypeSInt32); } +inline PalEntry &DObject::ColorVar(FName field) +{ + return *(PalEntry*)ScriptVar(field, TypeColor); +} + +inline FName &DObject::NameVar(FName field) +{ + return *(FName*)ScriptVar(field, TypeName); +} + inline double &DObject::FloatVar(FName field) { return *(double*)ScriptVar(field, TypeFloat64); diff --git a/src/g_inventory/a_artifacts.cpp b/src/g_inventory/a_artifacts.cpp index 15895eaa4..e69de29bb 100644 --- a/src/g_inventory/a_artifacts.cpp +++ b/src/g_inventory/a_artifacts.cpp @@ -1,74 +0,0 @@ -#include "info.h" -#include "a_pickups.h" -#include "d_player.h" -#include "p_local.h" -#include "c_dispatch.h" -#include "gi.h" -#include "s_sound.h" -#include "p_local.h" -#include "p_spec.h" -#include "p_lnspec.h" -#include "p_effect.h" -#include "a_artifacts.h" -#include "sbar.h" -#include "d_player.h" -#include "m_random.h" -#include "v_video.h" -#include "templates.h" -#include "a_morph.h" -#include "g_level.h" -#include "doomstat.h" -#include "v_palette.h" -#include "serializer.h" -#include "r_utility.h" -#include "virtual.h" -#include "g_levellocals.h" - -#include "r_data/colormaps.h" - -static FRandom pr_torch ("Torch"); - -/* Those are no longer needed, except maybe as reference? - * They're not used anywhere in the code anymore, except - * MAULATORTICS as redefined in a_minotaur.cpp... -#define INVULNTICS (30*TICRATE) -#define INVISTICS (60*TICRATE) -#define INFRATICS (120*TICRATE) -#define IRONTICS (60*TICRATE) -#define WPNLEV2TICS (40*TICRATE) -#define FLIGHTTICS (60*TICRATE) -#define SPEEDTICS (45*TICRATE) -#define MAULATORTICS (25*TICRATE) -#define TIMEFREEZE_TICS ( 12 * TICRATE ) -*/ - - -IMPLEMENT_CLASS(APowerup, false, false) - -// Powerup-Giver ------------------------------------------------------------- - - -// Powerup ------------------------------------------------------------------- - -DEFINE_FIELD(APowerup, EffectTics) -DEFINE_FIELD(APowerup, BlendColor) -DEFINE_FIELD(APowerup, Mode) -DEFINE_FIELD(APowerup, Strength) -DEFINE_FIELD(APowerup, Colormap) - -//=========================================================================== -// -// APowerup :: Serialize -// -//=========================================================================== - -void APowerup::Serialize(FSerializer &arc) -{ - Super::Serialize (arc); - auto def = (APowerup*)GetDefault(); - arc("effecttics", EffectTics, def->EffectTics) - ("blendcolor", BlendColor, def->BlendColor) - ("mode", Mode, def->Mode) - ("strength", Strength, def->Strength) - ("colormap", Colormap, def->Colormap); -} diff --git a/src/g_inventory/a_artifacts.h b/src/g_inventory/a_artifacts.h index 84c18505b..5f5bd1e88 100644 --- a/src/g_inventory/a_artifacts.h +++ b/src/g_inventory/a_artifacts.h @@ -3,24 +3,4 @@ #include "a_pickups.h" -class player_t; - -// A powerup is a pseudo-inventory item that applies an effect to its -// owner while it is present. -class APowerup : public AInventory -{ - DECLARE_CLASS (APowerup, AInventory) -public: - virtual void Serialize(FSerializer &arc) override; - - int EffectTics; - PalEntry BlendColor; - FNameNoInit Mode; - double Strength; - int Colormap; - -public: - friend void EndAllPowerupEffects(AInventory *item); - friend void InitAllPowerupEffects(AInventory *item); -}; #endif //__A_ARTIFACTS_H__ diff --git a/src/g_inventory/a_pickups.cpp b/src/g_inventory/a_pickups.cpp index 7b3756f52..b19fcf1f2 100644 --- a/src/g_inventory/a_pickups.cpp +++ b/src/g_inventory/a_pickups.cpp @@ -341,22 +341,11 @@ bool AInventory::Grind(bool items) // AInventory :: DoEffect // // Handles any effect an item might apply to its owner -// Normally only used by subclasses of APowerup +// Normally only used by subclasses of Powerup // //=========================================================================== -void AInventory::DoEffect () -{ -} - -DEFINE_ACTION_FUNCTION(AInventory, DoEffect) -{ - PARAM_SELF_PROLOGUE(AInventory); - self->DoEffect(); - return 0; -} - -void AInventory::CallDoEffect() +void AInventory::DoEffect() { IFVIRTUAL(AInventory, DoEffect) { @@ -364,7 +353,6 @@ void AInventory::CallDoEffect() VMFrameStack stack; GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr); } - else DoEffect(); } diff --git a/src/g_inventory/a_pickups.h b/src/g_inventory/a_pickups.h index 0d2c43fc5..3ef2fd285 100644 --- a/src/g_inventory/a_pickups.h +++ b/src/g_inventory/a_pickups.h @@ -115,8 +115,7 @@ public: virtual bool ShouldStay(); bool CallShouldStay(); - virtual void DoEffect(); - void CallDoEffect(); + void DoEffect(); virtual void PlayPickupSound(AActor *toucher); void CallPlayPickupSound(AActor *toucher); diff --git a/src/p_acs.cpp b/src/p_acs.cpp index fb0de5932..8914ab788 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -5728,9 +5728,9 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound) AActor *actor = SingleActorFromTID(args[0], activator); if (actor != NULL) { - APowerup* powerup = (APowerup*)actor->FindInventory(powerupclass); + auto powerup = actor->FindInventory(powerupclass); if (powerup != NULL) - return powerup->EffectTics; + return powerup->IntVar(NAME_EffectTics); } return 0; } diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index f26f617a9..a09ad16cf 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -2868,10 +2868,10 @@ FUNC(LS_SetPlayerProperty) { // Give power to activator if (power != 4) { - APowerup *item = static_cast(it->GiveInventoryType(PClass::FindActor(powers[power]))); + auto item = it->GiveInventoryType(PClass::FindActor(powers[power])); if (item != NULL && power == 0 && arg1 == 1) { - item->BlendColor = MakeSpecialColormap(INVERSECOLORMAP); + item->ColorVar(NAME_BlendColor) = MakeSpecialColormap(INVERSECOLORMAP); } } else if (it->player - players == consoleplayer) @@ -2908,10 +2908,10 @@ FUNC(LS_SetPlayerProperty) { // Give power if (power != 4) { - APowerup *item = static_cast(players[i].mo->GiveInventoryType ((PClass::FindActor(powers[power])))); + auto item = players[i].mo->GiveInventoryType ((PClass::FindActor(powers[power]))); if (item != NULL && power == 0 && arg1 == 1) { - item->BlendColor = MakeSpecialColormap(INVERSECOLORMAP); + item->ColorVar(NAME_BlendColor) = MakeSpecialColormap(INVERSECOLORMAP); } } else if (i == consoleplayer) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index e52b10a8e..4bf890462 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -3954,7 +3954,7 @@ void AActor::Tick () // by the order in the inventory, not the order in the thinker table while (item != NULL && item->Owner == this) { - item->CallDoEffect(); + item->DoEffect(); item = item->Inventory; } diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index f441f8417..947ee1587 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -107,10 +107,6 @@ static AWeapon::MetaClass *FindClassTentativeWeapon(const char *name, bool optio { return static_cast(FindClassTentative(name, RUNTIME_CLASS(AWeapon), optional)); } -static APowerup::MetaClass *FindClassTentativePowerup(const char *name, bool optional = false) -{ - return static_cast(FindClassTentative(name, RUNTIME_CLASS(APowerup), optional)); -} static APlayerPawn::MetaClass *FindClassTentativePlayerPawn(const char *name, bool optional = false) { return static_cast(FindClassTentative(name, RUNTIME_CLASS(APlayerPawn), optional)); @@ -458,9 +454,8 @@ int MatchString (const char *in, const char **strings) //========================================================================== // -// Get access to scripted fields. -// Fortunately there's only a handful that cannot be done with a -// scripted property definition, most notably the powerup and morph stuff. +// Get access to scripted pointers. +// They need a bit more work than other variables. // //========================================================================== @@ -2289,7 +2284,7 @@ DEFINE_CLASS_PROPERTY_PREFIX(powerup, color, C_f, Inventory) if (info->IsDescendantOf(PClass::FindActor(NAME_Powerup)) || isgiver) { - pBlendColor = &TypedScriptVar(defaults, info, NAME_BlendColor, TypeColor); + pBlendColor = &defaults->ColorVar(NAME_BlendColor); } else { @@ -2335,13 +2330,9 @@ DEFINE_CLASS_PROPERTY_PREFIX(powerup, color, C_f, Inventory) //========================================================================== DEFINE_CLASS_PROPERTY_PREFIX(powerup, colormap, FFFfff, Inventory) { - PalEntry * pBlendColor; + PalEntry BlendColor; - if (info->IsDescendantOf(PClass::FindActor(NAME_Powerup)) || info->IsDescendantOf(PClass::FindActor(NAME_PowerupGiver))) - { - pBlendColor = &TypedScriptVar(defaults, info, NAME_BlendColor, TypeColor); - } - else + if (!info->IsDescendantOf(PClass::FindActor(NAME_Powerup)) && !info->IsDescendantOf(PClass::FindActor(NAME_PowerupGiver))) { I_Error("\"powerup.colormap\" requires an actor of type \"Powerup\"\n"); return; @@ -2352,7 +2343,7 @@ DEFINE_CLASS_PROPERTY_PREFIX(powerup, colormap, FFFfff, Inventory) PROP_FLOAT_PARM(r, 0); PROP_FLOAT_PARM(g, 1); PROP_FLOAT_PARM(b, 2); - *pBlendColor = MakeSpecialColormap(AddSpecialColormap(0, 0, 0, r, g, b)); + BlendColor = MakeSpecialColormap(AddSpecialColormap(0, 0, 0, r, g, b)); } else if (PROP_PARM_COUNT == 6) { @@ -2362,12 +2353,13 @@ DEFINE_CLASS_PROPERTY_PREFIX(powerup, colormap, FFFfff, Inventory) PROP_FLOAT_PARM(r2, 3); PROP_FLOAT_PARM(g2, 4); PROP_FLOAT_PARM(b2, 5); - *pBlendColor = MakeSpecialColormap(AddSpecialColormap(r1, g1, b1, r2, g2, b2)); + BlendColor = MakeSpecialColormap(AddSpecialColormap(r1, g1, b1, r2, g2, b2)); } else { I_Error("\"power.colormap\" must have either 3 or 6 parameters\n"); } + defaults->ColorVar(NAME_BlendColor) = BlendColor; } //========================================================================== @@ -2375,20 +2367,14 @@ DEFINE_CLASS_PROPERTY_PREFIX(powerup, colormap, FFFfff, Inventory) //========================================================================== DEFINE_CLASS_PROPERTY_PREFIX(powerup, duration, I, Inventory) { - int *pEffectTics; - - if (info->IsDescendantOf(PClass::FindActor(NAME_Powerup)) || info->IsDescendantOf(PClass::FindActor(NAME_PowerupGiver))) - { - pEffectTics = &TypedScriptVar(defaults, info, NAME_EffectTics, TypeSInt32); - } - else + if (!info->IsDescendantOf(PClass::FindActor(NAME_Powerup)) && !info->IsDescendantOf(PClass::FindActor(NAME_PowerupGiver))) { I_Error("\"powerup.duration\" requires an actor of type \"Powerup\"\n"); return; } PROP_INT_PARM(i, 0); - *pEffectTics = (i >= 0) ? i : -i * TICRATE; + defaults->IntVar(NAME_EffectTics) = (i >= 0) ? i : -i * TICRATE; } //========================================================================== @@ -2396,19 +2382,13 @@ DEFINE_CLASS_PROPERTY_PREFIX(powerup, duration, I, Inventory) //========================================================================== DEFINE_CLASS_PROPERTY_PREFIX(powerup, strength, F, Inventory) { - double *pStrength; - - if (info->IsDescendantOf(PClass::FindActor(NAME_Powerup)) || info->IsDescendantOf(PClass::FindActor(NAME_PowerupGiver))) - { - pStrength = &TypedScriptVar(defaults, info, NAME_Strength, TypeFloat64); - } - else + if (!info->IsDescendantOf(PClass::FindActor(NAME_Powerup)) && !info->IsDescendantOf(PClass::FindActor(NAME_PowerupGiver))) { I_Error("\"powerup.strength\" requires an actor of type \"Powerup\"\n"); return; } PROP_DOUBLE_PARM(f, 0); - *pStrength = f; + defaults->FloatVar(NAME_Strength) = f; } //========================================================================== @@ -2417,18 +2397,13 @@ DEFINE_CLASS_PROPERTY_PREFIX(powerup, strength, F, Inventory) DEFINE_CLASS_PROPERTY_PREFIX(powerup, mode, S, Inventory) { PROP_STRING_PARM(str, 0); - FName *pMode; - if (info->IsDescendantOf(PClass::FindActor(NAME_Powerup)) || info->IsDescendantOf(PClass::FindActor(NAME_PowerupGiver))) - { - pMode = &TypedScriptVar(defaults, info, NAME_Mode, TypeName); - } - else + if (!info->IsDescendantOf(PClass::FindActor(NAME_Powerup)) && !info->IsDescendantOf(PClass::FindActor(NAME_PowerupGiver))) { I_Error("\"powerup.mode\" requires an actor of type \"Powerup\"\n"); return; } - *pMode = (FName)str; + defaults->NameVar(NAME_Mode) = (FName)str; } //========================================================================== @@ -2441,13 +2416,14 @@ DEFINE_SCRIPTED_PROPERTY_PREFIX(powerup, type, S, PowerupGiver) // Yuck! What was I thinking when I decided to prepend "Power" to the name? // Now it's too late to change it... PClassActor *cls = PClass::FindActor(str); - if (cls == nullptr || !cls->IsDescendantOf(RUNTIME_CLASS(APowerup))) + auto pow = PClass::FindActor(NAME_Powerup); + if (cls == nullptr || !cls->IsDescendantOf(pow)) { if (bag.fromDecorate) { FString st; st.Format("%s%s", strnicmp(str, "power", 5) ? "Power" : "", str); - cls = FindClassTentativePowerup(st); + cls = FindClassTentative(st, pow); } else { diff --git a/wadsrc/static/zscript/inventory/inventory.txt b/wadsrc/static/zscript/inventory/inventory.txt index a27240eb7..3e01d059e 100644 --- a/wadsrc/static/zscript/inventory/inventory.txt +++ b/wadsrc/static/zscript/inventory/inventory.txt @@ -41,7 +41,6 @@ class Inventory : Actor native virtual native bool SpecialDropAction (Actor dropper); virtual native String PickupMessage(); virtual native bool ShouldStay(); - virtual native void DoEffect(); virtual native void PlayPickupSound(Actor user); virtual native void AttachToOwner(Actor user); virtual native void DetachFromOwner(); @@ -57,9 +56,19 @@ class Inventory : Actor native // //=========================================================================== - virtual void Travelled() - {} + virtual void Travelled() {} + //=========================================================================== + // + // AInventory :: DoEffect + // + // Handles any effect an item might apply to its owner + // Normally only used by subclasses of Powerup + // + //=========================================================================== + + virtual void DoEffect() {} + virtual double GetSpeedFactor() { return 1; } virtual bool GetNoTeleportFreeze() { return false; } virtual void ModifyDamage(int damage, Name damageType, out int newdamage, bool passive) {} diff --git a/wadsrc/static/zscript/inventory/powerups.txt b/wadsrc/static/zscript/inventory/powerups.txt index e9325c004..d355a5e14 100644 --- a/wadsrc/static/zscript/inventory/powerups.txt +++ b/wadsrc/static/zscript/inventory/powerups.txt @@ -58,13 +58,13 @@ class PowerupGiver : Inventory } } -class Powerup : Inventory native +class Powerup : Inventory { - native int EffectTics; - native color BlendColor; - native Name Mode; // Meaning depends on powerup - used for Invulnerability and Invisibility - native double Strength; // Meaning depends on powerup - currently used only by Invisibility - native int Colormap; + int EffectTics; + color BlendColor; + Name Mode; // Meaning depends on powerup - used for Invulnerability and Invisibility + double Strength; // Meaning depends on powerup - currently used only by Invisibility + int Colormap; const SPECIALCOLORMAP_MASK = 0x00b60000; // Note, that while this is an inventory flag, it only has meaning on an active powerup.