diff --git a/src/g_inventory/a_artifacts.cpp b/src/g_inventory/a_artifacts.cpp index 6e5b03cc3..fbceba95c 100644 --- a/src/g_inventory/a_artifacts.cpp +++ b/src/g_inventory/a_artifacts.cpp @@ -60,46 +60,6 @@ DEFINE_FIELD(APowerupGiver, BlendColor) DEFINE_FIELD(APowerupGiver, Mode) DEFINE_FIELD(APowerupGiver, Strength) -//=========================================================================== -// -// APowerupGiver :: Use -// -//=========================================================================== - -bool APowerupGiver::Use (bool pickup) -{ - if (PowerupType == NULL) return true; // item is useless - if (Owner == nullptr) return true; - - APowerup *power = static_cast (Spawn (PowerupType)); - - if (EffectTics != 0) - { - power->EffectTics = EffectTics; - } - if (BlendColor != 0) - { - if (BlendColor != MakeSpecialColormap(65535)) power->BlendColor = BlendColor; - else power->BlendColor = 0; - } - if (Mode != NAME_None) - { - power->Mode = Mode; - } - if (Strength != 0) - { - power->Strength = Strength; - } - - power->ItemFlags |= ItemFlags & (IF_ALWAYSPICKUP|IF_ADDITIVETIME|IF_NOTELEPORTFREEZE); - if (power->CallTryPickup (Owner)) - { - return true; - } - power->GoAwayAndDie (); - return false; -} - //=========================================================================== // // APowerupGiver :: Serialize @@ -142,49 +102,3 @@ void APowerup::Serialize(FSerializer &arc) ("colormap", Colormap, def->Colormap); } -//=========================================================================== -// -// APowerup :: OwnerDied -// -// Powerups don't last beyond death. -// -//=========================================================================== - -void APowerup::OwnerDied () -{ - Destroy (); -} - -// Morph powerup ------------------------------------------------------ - -IMPLEMENT_CLASS(APowerMorph, false, true) - -IMPLEMENT_POINTERS_START(APowerMorph) - IMPLEMENT_POINTER(PlayerClass) - IMPLEMENT_POINTER(MorphFlash) - IMPLEMENT_POINTER(UnMorphFlash) -IMPLEMENT_POINTERS_END - - -DEFINE_FIELD(APowerMorph, PlayerClass) -DEFINE_FIELD(APowerMorph, MorphFlash) -DEFINE_FIELD(APowerMorph, UnMorphFlash) -DEFINE_FIELD(APowerMorph, MorphStyle) -DEFINE_FIELD(APowerMorph, MorphedPlayer) - -//=========================================================================== -// -// APowerMorph :: Serialize -// -//=========================================================================== - -void APowerMorph::Serialize(FSerializer &arc) -{ - Super::Serialize (arc); - arc("playerclass", PlayerClass) - ("morphstyle", MorphStyle) - ("morphflash", MorphFlash) - ("unmorphflash", UnMorphFlash) - ("morphedplayer", MorphedPlayer); -} - diff --git a/src/g_inventory/a_artifacts.h b/src/g_inventory/a_artifacts.h index f17299d46..db9429858 100644 --- a/src/g_inventory/a_artifacts.h +++ b/src/g_inventory/a_artifacts.h @@ -12,7 +12,6 @@ class APowerup : public AInventory DECLARE_CLASS (APowerup, AInventory) public: virtual void Serialize(FSerializer &arc) override; - virtual void OwnerDied () override; int EffectTics; PalEntry BlendColor; @@ -31,7 +30,6 @@ class APowerupGiver : public AInventory DECLARE_CLASS (APowerupGiver, AInventory) HAS_OBJECT_POINTERS public: - virtual bool Use (bool pickup) override; virtual void Serialize(FSerializer &arc) override; @@ -42,19 +40,5 @@ public: double Strength; // Meaning depends on powerup - currently used only by Invisibility }; -class APowerMorph : public APowerup -{ - DECLARE_CLASS( APowerMorph, APowerup ) - HAS_OBJECT_POINTERS -public: - - virtual void Serialize(FSerializer &arc) override; - - // Variables - PClassPlayerPawn *PlayerClass; - PClassActor *MorphFlash, *UnMorphFlash; - int MorphStyle; - player_t *MorphedPlayer; -}; #endif //__A_ARTIFACTS_H__ diff --git a/src/g_inventory/a_pickups.cpp b/src/g_inventory/a_pickups.cpp index 13842d359..7b3756f52 100644 --- a/src/g_inventory/a_pickups.cpp +++ b/src/g_inventory/a_pickups.cpp @@ -368,18 +368,6 @@ void AInventory::CallDoEffect() } -//=========================================================================== -// -// AInventory :: OwnerDied -// -// Items receive this message when their owners die. -// -//=========================================================================== - -void AInventory::OwnerDied () -{ -} - //=========================================================================== // // AInventory :: HandlePickup @@ -1348,7 +1336,7 @@ bool AInventory::TryPickup (AActor *&toucher) } // The item is placed in the inventory just long enough to be used. toucher->AddInventory (this); - bool usegood = Use (true); + bool usegood = CallUse (true); toucher->RemoveInventory (this); if (usegood) diff --git a/src/g_inventory/a_pickups.h b/src/g_inventory/a_pickups.h index 9f85e482b..0d2c43fc5 100644 --- a/src/g_inventory/a_pickups.h +++ b/src/g_inventory/a_pickups.h @@ -138,8 +138,6 @@ public: // virtual on the script side only. double GetSpeedFactor(); bool GetNoTeleportFreeze(); - // Stuff for later when more features are exported. - virtual void OwnerDied(); bool GoAway(); diff --git a/src/namedef.h b/src/namedef.h index c37ee5577..366676a13 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -706,6 +706,10 @@ xx(WBobSpeed) xx(PlayerClass) xx(Wi_NoAutostartMap) +xx(MorphStyle) +xx(MorphFlash) +xx(UnMorphFlash) + // Decorate compatibility functions xx(BuiltinTypeCheck) xx(BuiltinRandom) diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index a73e3d8b3..0320b0feb 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -357,15 +357,19 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags) static int dieticks[MAXPLAYERS]; // [ZzZombo] not used? Except if for peeking in debugger... int pnum = int(this->player-players); dieticks[pnum] = gametic; - fprintf (debugfile, "died (%d) on tic %d (%s)\n", pnum, gametic, - this->player->cheats&CF_PREDICTING?"predicting":"real"); + fprintf(debugfile, "died (%d) on tic %d (%s)\n", pnum, gametic, + this->player->cheats&CF_PREDICTING ? "predicting" : "real"); } // [RH] Notify this actor's items. for (AInventory *item = Inventory; item != NULL; ) { AInventory *next = item->Inventory; - item->OwnerDied(); + IFVIRTUALPTR(item, AInventory, OwnerDied) + { + VMValue params[1] = { item }; + GlobalVMStack.Call(func, params, 1, nullptr, 0); + } item = next; } diff --git a/src/scripting/decorate/thingdef_parse.cpp b/src/scripting/decorate/thingdef_parse.cpp index c839a2dc0..7dceceb32 100644 --- a/src/scripting/decorate/thingdef_parse.cpp +++ b/src/scripting/decorate/thingdef_parse.cpp @@ -913,13 +913,14 @@ static void ParseActorProperty(FScanner &sc, Baggage &bag) if (prop != NULL) { - if (bag.Info->IsDescendantOf(*prop->cls)) + auto pcls = PClass::FindActor(prop->clsname); + if (bag.Info->IsDescendantOf(pcls)) { ParsePropertyParams(sc, prop, (AActor *)bag.Info->Defaults, bag); } else { - sc.ScriptMessage("'%s' requires an actor of type '%s'\n", propname.GetChars(), (*prop->cls)->TypeName.GetChars()); + sc.ScriptMessage("'%s' requires an actor of type '%s'\n", propname.GetChars(), pcls->TypeName.GetChars()); FScriptPosition::ErrorCounter++; } } diff --git a/src/scripting/thingdef.h b/src/scripting/thingdef.h index 20d25dd8e..76a209722 100644 --- a/src/scripting/thingdef.h +++ b/src/scripting/thingdef.h @@ -230,7 +230,7 @@ struct FPropertyInfo { const char *name; const char *params; - const PClass * const *cls; + const char *clsname; PropHandler Handler; int category; }; @@ -242,17 +242,24 @@ int MatchString (const char *in, const char **strings); #define DEFINE_PROPERTY_BASE(name, paramlist, clas, cat) \ static void Handler_##name##_##paramlist##_##clas(A##clas *defaults, PClassActor *info, Baggage &bag, FPropParam *params); \ static FPropertyInfo Prop_##name##_##paramlist##_##clas = \ - { #name, #paramlist, &RUNTIME_CLASS_CASTLESS(A##clas), (PropHandler)Handler_##name##_##paramlist##_##clas, cat }; \ + { #name, #paramlist, #clas, (PropHandler)Handler_##name##_##paramlist##_##clas, cat }; \ MSVC_PSEG FPropertyInfo *infoptr_##name##_##paramlist##_##clas GCC_PSEG = &Prop_##name##_##paramlist##_##clas; \ static void Handler_##name##_##paramlist##_##clas(A##clas *defaults, PClassActor *info, Baggage &bag, FPropParam *params) #define DEFINE_PREFIXED_PROPERTY_BASE(prefix, name, paramlist, clas, cat) \ static void Handler_##name##_##paramlist##_##clas(A##clas *defaults, PClassActor *info, Baggage &bag, FPropParam *params); \ static FPropertyInfo Prop_##name##_##paramlist##_##clas = \ -{ #prefix"."#name, #paramlist, &RUNTIME_CLASS_CASTLESS(A##clas), (PropHandler)Handler_##name##_##paramlist##_##clas, cat }; \ +{ #prefix"."#name, #paramlist, #clas, (PropHandler)Handler_##name##_##paramlist##_##clas, cat }; \ MSVC_PSEG FPropertyInfo *infoptr_##name##_##paramlist##_##clas GCC_PSEG = &Prop_##name##_##paramlist##_##clas; \ static void Handler_##name##_##paramlist##_##clas(A##clas *defaults, PClassActor *info, Baggage &bag, FPropParam *params) +#define DEFINE_PREFIXED_SCRIPTED_PROPERTY_BASE(prefix, name, paramlist, clas, cat) \ + static void Handler_##name##_##paramlist##_##clas(AActor *defaults, PClassActor *info, Baggage &bag, FPropParam *params); \ + static FPropertyInfo Prop_##name##_##paramlist##_##clas = \ +{ #prefix"."#name, #paramlist, #clas, (PropHandler)Handler_##name##_##paramlist##_##clas, cat }; \ + MSVC_PSEG FPropertyInfo *infoptr_##name##_##paramlist##_##clas GCC_PSEG = &Prop_##name##_##paramlist##_##clas; \ + static void Handler_##name##_##paramlist##_##clas(AActor *defaults, PClassActor *info, Baggage &bag, FPropParam *params) + #define DEFINE_PROPERTY(name, paramlist, clas) DEFINE_PROPERTY_BASE(name, paramlist, clas, CAT_PROPERTY) #define DEFINE_INFO_PROPERTY(name, paramlist, clas) DEFINE_PROPERTY_BASE(name, paramlist, clas, CAT_INFO) @@ -260,6 +267,9 @@ int MatchString (const char *in, const char **strings); #define DEFINE_CLASS_PROPERTY(name, paramlist, clas) DEFINE_PREFIXED_PROPERTY_BASE(clas, name, paramlist, clas, CAT_PROPERTY) #define DEFINE_CLASS_PROPERTY_PREFIX(prefix, name, paramlist, clas) DEFINE_PREFIXED_PROPERTY_BASE(prefix, name, paramlist, clas, CAT_PROPERTY) +#define DEFINE_SCRIPTED_PROPERTY(name, paramlist, clas) DEFINE_PREFIXED_SCRIPTED_PROPERTY_BASE(clas, name, paramlist, clas, CAT_PROPERTY) +#define DEFINE_SCRIPTED_PROPERTY_PREFIX(prefix, name, paramlist, clas) DEFINE_PREFIXED_SCRIPTED_PROPERTY_BASE(prefix, name, paramlist, clas, CAT_PROPERTY) + #define PROP_PARM_COUNT (params[0].i) #define PROP_STRING_PARM(var, no) \ diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index 487763d9a..170b5c49a 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -456,12 +456,38 @@ int MatchString (const char *in, const char **strings) return -1; } +//========================================================================== +// +// 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. +// +//========================================================================== + +static void *ScriptVar(DObject *obj, PClass *cls, FName field, PType *type) +{ + auto sym = dyn_cast(cls->Symbols.FindSymbol(field, true)); + if (sym && sym->Type == type) + { + return (((char*)obj) + sym->Offset); + } + I_Error("Variable %s of type %s not found in %s\n", field.GetChars(), type->DescriptiveName(), cls->TypeName.GetChars()); + return nullptr; +} + +template +T &TypedScriptVar(DObject *obj, PClass *cls, FName field, PType *type) +{ + return *(T*)ScriptVar(obj, cls, field, type); +} + //========================================================================== // // Info Property handlers // //========================================================================== + //========================================================================== // //========================================================================== @@ -3026,37 +3052,37 @@ DEFINE_CLASS_PROPERTY(unmorphflash, S, MorphProjectile) //========================================================================== // (non-fatal with non-existent types only in DECORATE) //========================================================================== -DEFINE_CLASS_PROPERTY(playerclass, S, PowerMorph) +DEFINE_SCRIPTED_PROPERTY(playerclass, S, PowerMorph) { PROP_STRING_PARM(str, 0); - defaults->PlayerClass = FindClassTentativePlayerPawn(str, bag.fromDecorate); + TypedScriptVar(defaults, bag.Info, NAME_PlayerClass, NewClassPointer(RUNTIME_CLASS(APlayerPawn))) = FindClassTentativePlayerPawn(str, bag.fromDecorate); } //========================================================================== // //========================================================================== -DEFINE_CLASS_PROPERTY(morphstyle, M, PowerMorph) +DEFINE_SCRIPTED_PROPERTY(morphstyle, M, PowerMorph) { PROP_INT_PARM(i, 0); - defaults->MorphStyle = i; + TypedScriptVar(defaults, bag.Info, NAME_MorphStyle, TypeSInt32) = i; } //========================================================================== // (non-fatal with non-existent types only in DECORATE) //========================================================================== -DEFINE_CLASS_PROPERTY(morphflash, S, PowerMorph) +DEFINE_SCRIPTED_PROPERTY(morphflash, S, PowerMorph) { PROP_STRING_PARM(str, 0); - defaults->MorphFlash = FindClassTentative(str, RUNTIME_CLASS(AActor), bag.fromDecorate); + TypedScriptVar(defaults, bag.Info, NAME_MorphFlash, NewClassPointer(RUNTIME_CLASS(AActor))) = FindClassTentative(str, RUNTIME_CLASS(AActor), bag.fromDecorate); } //========================================================================== // (non-fatal with non-existent types only in DECORATE) //========================================================================== -DEFINE_CLASS_PROPERTY(unmorphflash, S, PowerMorph) +DEFINE_SCRIPTED_PROPERTY(unmorphflash, S, PowerMorph) { PROP_STRING_PARM(str, 0); - defaults->UnMorphFlash = FindClassTentative(str, RUNTIME_CLASS(AActor), bag.fromDecorate); + TypedScriptVar(defaults, bag.Info, NAME_UnMorphFlash, NewClassPointer(RUNTIME_CLASS(AActor))) = FindClassTentative(str, RUNTIME_CLASS(AActor), bag.fromDecorate); } diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 1687983f2..c1cd274f0 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2022,13 +2022,14 @@ void ZCCCompiler::ProcessDefaultProperty(PClassActor *cls, ZCC_PropertyStmt *pro if (property != nullptr && property->category != CAT_INFO) { - if (cls->IsDescendantOf(*property->cls)) + auto pcls = PClass::FindActor(property->clsname); + if (cls->IsDescendantOf(pcls)) { DispatchProperty(property, prop, (AActor *)bag.Info->Defaults, bag); } else { - Error(prop, "'%s' requires an actor of type '%s'\n", propname.GetChars(), (*property->cls)->TypeName.GetChars()); + Error(prop, "'%s' requires an actor of type '%s'\n", propname.GetChars(), pcls->TypeName.GetChars()); } } else diff --git a/wadsrc/static/zscript/inventory/inventory.txt b/wadsrc/static/zscript/inventory/inventory.txt index 90ed458d0..a27240eb7 100644 --- a/wadsrc/static/zscript/inventory/inventory.txt +++ b/wadsrc/static/zscript/inventory/inventory.txt @@ -64,6 +64,7 @@ class Inventory : Actor native virtual bool GetNoTeleportFreeze() { return false; } virtual void ModifyDamage(int damage, Name damageType, out int newdamage, bool passive) {} virtual void AlterWeaponSprite(VisStyle vis, in out int changed) {} + virtual void OwnerDied() {} native bool GoAway(); native void GoAwayAndDie(); diff --git a/wadsrc/static/zscript/inventory/powerups.txt b/wadsrc/static/zscript/inventory/powerups.txt index af20ed628..00639ce9e 100644 --- a/wadsrc/static/zscript/inventory/powerups.txt +++ b/wadsrc/static/zscript/inventory/powerups.txt @@ -14,6 +14,50 @@ class PowerupGiver : Inventory native +INVENTORY.FANCYPICKUPSOUND Inventory.PickupSound "misc/p_pkup"; } + + //=========================================================================== + // + // APowerupGiver :: Use + // + //=========================================================================== + + override bool Use (bool pickup) + { + if (PowerupType == NULL) return true; // item is useless + if (Owner == null) return true; + + let power = Powerup(Spawn (PowerupType)); + + if (EffectTics != 0) + { + power.EffectTics = EffectTics; + } + if (BlendColor != 0) + { + if (BlendColor != Powerup.SPECIALCOLORMAP_MASK | 65535) power.BlendColor = BlendColor; + else power.BlendColor = 0; + } + if (Mode != 'None') + { + power.Mode = Mode; + } + if (Strength != 0) + { + power.Strength = Strength; + } + + power.bAlwaysPickup |= bAlwaysPickup; + power.bAdditiveTime |= bAdditiveTime; + power.bNoTeleportFreeze |= bNoTeleportFreeze; + if (power.CallTryPickup (Owner)) + { + return true; + } + power.GoAwayAndDie (); + return false; + } + + } class Powerup : Inventory native @@ -248,6 +292,19 @@ class Powerup : Inventory native return (EffectTics <= BLINKTHRESHOLD && (EffectTics & 8) && !bNoScreenBlink); } + //=========================================================================== + // + // APowerup :: OwnerDied + // + // Powerups don't last beyond death. + // + //=========================================================================== + + override void OwnerDied () + { + Destroy (); + } + } @@ -1890,12 +1947,12 @@ class PowerInfiniteAmmo : Powerup // //=========================================================================== -class PowerMorph : Powerup native +class PowerMorph : Powerup { - native Class PlayerClass; - native Class MorphFlash, UnMorphFlash; - native int MorphStyle; - native PlayerInfo MorphedPlayer; + Class PlayerClass; + Class MorphFlash, UnMorphFlash; + int MorphStyle; + PlayerInfo MorphedPlayer; Default {