From 98f9219334a619d495bd3a4139c97792b4307b6f Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 17 Jan 2017 20:30:17 +0100 Subject: [PATCH] - scriptified the remaining functions in a_artifacts.cpp. - added some helpers to set scripted member variables through the native property parser. Unfortunately some classes, e.g. PowerMorph, MorphProjectile and the powerup contain some that cannot be handled through the 'property' definition on the script side so they need to be done from the native side. --- src/g_inventory/a_artifacts.cpp | 86 ------------------- src/g_inventory/a_artifacts.h | 16 ---- src/g_inventory/a_pickups.cpp | 14 +-- src/g_inventory/a_pickups.h | 2 - src/namedef.h | 4 + src/p_interaction.cpp | 10 ++- src/scripting/decorate/thingdef_parse.cpp | 5 +- src/scripting/thingdef.h | 16 +++- src/scripting/thingdef_properties.cpp | 42 +++++++-- src/scripting/zscript/zcc_compile.cpp | 5 +- wadsrc/static/zscript/inventory/inventory.txt | 1 + wadsrc/static/zscript/inventory/powerups.txt | 67 +++++++++++++-- 12 files changed, 128 insertions(+), 140 deletions(-) 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 {