From 1750ded7c45ca2bc199bc59d7be51ad19bc3ed98 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 19 Jan 2017 20:56:31 +0100 Subject: [PATCH] - more exporting of AInventory. --- src/b_bot.cpp | 2 + src/d_dehacked.cpp | 3 +- src/g_inventory/a_pickups.cpp | 367 ++---------------- src/g_inventory/a_pickups.h | 29 +- src/g_inventory/a_weapons.cpp | 2 - src/p_actionfunctions.cpp | 6 +- src/p_enemy.cpp | 17 +- src/p_local.h | 2 - src/p_mobj.cpp | 23 +- src/scripting/decorate/olddecorations.cpp | 2 +- src/scripting/thingdef_properties.cpp | 2 +- wadsrc/static/zscript/inventory/inventory.txt | 225 ++++++++++- .../zscript/inventory/stateprovider.txt | 5 +- wadsrc/static/zscript/shared/botstuff.txt | 3 +- 14 files changed, 291 insertions(+), 397 deletions(-) diff --git a/src/b_bot.cpp b/src/b_bot.cpp index 3f4d0c592..54d154a3e 100644 --- a/src/b_bot.cpp +++ b/src/b_bot.cpp @@ -26,6 +26,8 @@ IMPLEMENT_POINTERS_START(DBot) IMPLEMENT_POINTER(last_mate) IMPLEMENT_POINTERS_END +DEFINE_FIELD(DBot, dest) + DBot::DBot () : DThinker(STAT_BOT) { diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 85d10de02..eda79f744 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -3158,9 +3158,10 @@ bool ADehackedPickup::TryPickup (AActor *&toucher) FString ADehackedPickup::PickupMessage () { + /* if (RealPickup != nullptr) return RealPickup->PickupMessage (); - else return ""; + else*/ return ""; } bool ADehackedPickup::ShouldStay () diff --git a/src/g_inventory/a_pickups.cpp b/src/g_inventory/a_pickups.cpp index c65961de1..b3826d46f 100644 --- a/src/g_inventory/a_pickups.cpp +++ b/src/g_inventory/a_pickups.cpp @@ -39,7 +39,7 @@ void PClassInventory::DeriveData(PClass *newclass) Super::DeriveData(newclass); PClassInventory *newc = static_cast(newclass); - newc->PickupMessage = PickupMessage; + newc->PickupMsg = PickupMsg; newc->GiveQuest = GiveQuest; newc->AltHUDIcon = AltHUDIcon; newc->ForbiddenToPlayerClass = ForbiddenToPlayerClass; @@ -79,19 +79,16 @@ void PClassInventory::Finalize(FStateDefinitions &statedef) ((AActor*)Defaults)->flags |= MF_SPECIAL; } -int AInventory::StaticLastMessageTic; -FString AInventory::StaticLastMessage; - IMPLEMENT_CLASS(AInventory, false, true) IMPLEMENT_POINTERS_START(AInventory) - IMPLEMENT_POINTER(Owner) +IMPLEMENT_POINTER(Owner) IMPLEMENT_POINTERS_END DEFINE_FIELD_BIT(AInventory, ItemFlags, bPickupGood, IF_PICKUPGOOD) DEFINE_FIELD_BIT(AInventory, ItemFlags, bCreateCopyMoved, IF_CREATECOPYMOVED) DEFINE_FIELD_BIT(AInventory, ItemFlags, bInitEffectFailed, IF_INITEFFECTFAILED) -DEFINE_FIELD(AInventory, Owner) +DEFINE_FIELD(AInventory, Owner) DEFINE_FIELD(AInventory, Amount) DEFINE_FIELD(AInventory, MaxAmount) DEFINE_FIELD(AInventory, InterHubAmount) @@ -101,6 +98,7 @@ DEFINE_FIELD(AInventory, DropTime) DEFINE_FIELD(AInventory, SpawnPointClass) DEFINE_FIELD(AInventory, PickupFlash) DEFINE_FIELD(AInventory, PickupSound) +DEFINE_FIELD(PClassInventory, PickupMsg) //=========================================================================== // @@ -179,42 +177,6 @@ void AInventory::MarkPrecacheSounds() const PickupSound.MarkUsed(); } -//=========================================================================== -// -// AInventory :: SpecialDropAction -// -// Called by P_DropItem. Return true to prevent the standard drop tossing. -// A few Strife items that are meant to trigger actions rather than be -// picked up use this. Normal items shouldn't need it. -// -//=========================================================================== - -bool AInventory::SpecialDropAction (AActor *dropper) -{ - return false; -} - -DEFINE_ACTION_FUNCTION(AInventory, SpecialDropAction) -{ - PARAM_SELF_PROLOGUE(AInventory); - PARAM_OBJECT_NOT_NULL(dropper, AActor); - ACTION_RETURN_BOOL(self->SpecialDropAction(dropper)); -} - -bool AInventory::CallSpecialDropAction(AActor *dropper) -{ - IFVIRTUAL(AInventory, SpecialDropAction) - { - VMValue params[2] = { (DObject*)this, (DObject*)dropper }; - VMReturn ret; - int retval; - ret.IntAt(&retval); - GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr); - return !!retval; - } - return SpecialDropAction(dropper); -} - //=========================================================================== // // AInventory :: ShouldRespawn @@ -231,18 +193,6 @@ bool AInventory::ShouldRespawn () return !!((dmflags & DF_ITEMS_RESPAWN) || (ItemFlags & IF_ALWAYSRESPAWN)); } -//=========================================================================== -// -// AInventory :: BeginPlay -// -//=========================================================================== - -void AInventory::BeginPlay () -{ - Super::BeginPlay (); - flags |= MF_DROPPED; // [RH] Items are dropped by default -} - //=========================================================================== // // AInventory :: Grind @@ -270,68 +220,6 @@ bool AInventory::Grind(bool items) return Super::Grind(items); } -//=========================================================================== -// -// AInventory :: DoEffect -// -// Handles any effect an item might apply to its owner -// Normally only used by subclasses of Powerup -// -//=========================================================================== - -void AInventory::DoEffect() -{ - IFVIRTUAL(AInventory, DoEffect) - { - VMValue params[1] = { (DObject*)this }; - VMFrameStack stack; - GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr); - } -} - - -//=========================================================================== -// -// AInventory :: HandlePickup -// -// Returns true if the pickup was handled (or should not happen at all), -// false if not. -// -//=========================================================================== - -bool AInventory::HandlePickup (AInventory *item) -{ - if (item->GetClass() == GetClass()) - { - if (Amount < MaxAmount || (sv_unlimited_pickup && !item->CallShouldStay())) - { - if (Amount > 0 && Amount + item->Amount < 0) - { - Amount = 0x7fffffff; - } - else - { - Amount += item->Amount; - } - - if (Amount > MaxAmount && !sv_unlimited_pickup) - { - Amount = MaxAmount; - } - item->ItemFlags |= IF_PICKUPGOOD; - } - return true; - } - return false; -} - -DEFINE_ACTION_FUNCTION(AInventory, HandlePickup) -{ - PARAM_SELF_PROLOGUE(AInventory); - PARAM_OBJECT_NOT_NULL(item, AInventory); - ACTION_RETURN_BOOL(self->HandlePickup(item)); -} - //=========================================================================== // // AInventory :: GoAway @@ -392,67 +280,6 @@ DEFINE_ACTION_FUNCTION(AInventory, GoAwayAndDie) return 0; } - -//=========================================================================== -// -// AInventory :: CreateCopy -// -// Returns an actor suitable for placing in an inventory, either itself or -// a copy based on whether it needs to respawn or not. Returning NULL -// indicates the item should not be picked up. -// -//=========================================================================== - -AInventory *AInventory::CreateCopy (AActor *other) -{ - AInventory *copy; - - Amount = MIN(Amount, MaxAmount); - if (GoAway ()) - { - copy = static_cast(Spawn (GetClass())); - copy->Amount = Amount; - copy->MaxAmount = MaxAmount; - } - else - { - copy = this; - } - return copy; -} - -DEFINE_ACTION_FUNCTION(AInventory, CreateCopy) -{ - PARAM_SELF_PROLOGUE(AInventory); - PARAM_OBJECT(other, AActor); - ACTION_RETURN_OBJECT(self->CreateCopy(other)); -} - - -//=========================================================================== -// -// AInventory::CreateTossable -// -// Creates a copy of the item suitable for dropping. If this actor embodies -// only one item, then it is tossed out itself. Otherwise, the count drops -// by one and a new item with an amount of 1 is spawned. -// -//=========================================================================== - -AInventory *AInventory::CreateTossable() -{ - IFVIRTUAL(AInventory, CreateTossable) - { - VMValue params[1] = { (DObject*)this }; - VMReturn ret; - AInventory *retval; - ret.PointerAt((void**)&retval); - GlobalVMStack.Call(func, params, 1, &ret, 1, nullptr); - return retval; - } - else return CreateTossable(); -} - //=========================================================================== // // AInventory :: BecomeItem @@ -518,30 +345,6 @@ DEFINE_ACTION_FUNCTION(AInventory, BecomePickup) return 0; } -//=========================================================================== -// -// AInventory :: ModifyDamage -// -// Allows inventory items to manipulate the amount of damage -// inflicted. Damage is the amount of damage that would be done without manipulation, -// and newdamage is the amount that should be done after the item has changed -// it. -// 'active' means it is called by the inflictor, 'passive' by the target. -// It may seem that this is redundant and AbsorbDamage is the same. However, -// AbsorbDamage is called only for players and also depends on other settings -// which are undesirable for a protection artifact. -// -//=========================================================================== - -void AInventory::ModifyDamage (int damage, FName damageType, int &newdamage, bool passive) -{ - IFVIRTUAL(AInventory, ModifyDamage) - { - VMValue params[5] = { (DObject*)this, damage, int(damageType), &newdamage, passive }; - GlobalVMStack.Call(func, params, 5, nullptr, 0, nullptr); - } -} - //=========================================================================== // // AInventory :: GetSpeedFactor @@ -556,10 +359,9 @@ double AInventory::GetSpeedFactor() { IFVIRTUALPTR(self, AInventory, GetSpeedFactor) { - VMValue params[2] = { (DObject*)self }; - VMReturn ret; + VMValue params[1] = { (DObject*)self }; double retval; - ret.FloatAt(&retval); + VMReturn ret(&retval); GlobalVMStack.Call(func, params, 1, &ret, 1, nullptr); factor *= retval; } @@ -581,10 +383,9 @@ bool AInventory::GetNoTeleportFreeze () { IFVIRTUALPTR(self, AInventory, GetNoTeleportFreeze) { - VMValue params[2] = { (DObject*)self }; - VMReturn ret; + VMValue params[1] = { (DObject*)self }; int retval; - ret.IntAt(&retval); + VMReturn ret(&retval); GlobalVMStack.Call(func, params, 1, &ret, 1, nullptr); if (retval) return true; } @@ -610,6 +411,7 @@ bool AInventory::CallUse(bool pickup) GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr); return !!retval; } + return false; } @@ -669,100 +471,25 @@ void AInventory::Hide () // // //=========================================================================== +static int StaticLastMessageTic; +static FString StaticLastMessage; -static void PrintPickupMessage (const char *str) +DEFINE_ACTION_FUNCTION(AInventory, PrintPickupMessage) { - if (str != NULL) + PARAM_PROLOGUE; + PARAM_BOOL(localview); + PARAM_STRING(str); + if (str.IsNotEmpty() && localview && (StaticLastMessageTic != gametic || StaticLastMessage.Compare(str))) { - if (str[0]=='$') - { - str=GStrings(str+1); - } - if (str[0] != 0) Printf (PRINT_LOW, "%s\n", str); - } -} - -//=========================================================================== -// -// AInventory :: Touch -// -// Handles collisions from another actor, possible adding itself to the -// collider's inventory. -// -//=========================================================================== - -void AInventory::Touch (AActor *toucher) -{ - player_t *player = toucher->player; - - // If a voodoo doll touches something, pretend the real player touched it instead. - if (player != NULL) - { - toucher = player->mo; - } - - bool localview = toucher->CheckLocalView(consoleplayer); - - if (!CallTryPickup (toucher, &toucher)) return; - - // This is the only situation when a pickup flash should ever play. - if (PickupFlash != NULL && !CallShouldStay()) - { - Spawn(PickupFlash, Pos(), ALLOW_REPLACE); - } - - if (!(ItemFlags & IF_QUIET)) - { - FString message = GetPickupMessage (); - - if (message.IsNotEmpty() && localview - && (StaticLastMessageTic != gametic || StaticLastMessage.Compare(message))) - { - StaticLastMessageTic = gametic; - StaticLastMessage = message; - PrintPickupMessage (message); - StatusBar->FlashCrosshair (); - } - - // Special check so voodoo dolls picking up items cause the - // real player to make noise. - if (player != NULL) - { - CallPlayPickupSound (player->mo); - if (!(ItemFlags & IF_NOSCREENFLASH)) - { - player->bonuscount = BONUSADD; - } - } - else - { - CallPlayPickupSound (toucher); - } - } - - // [RH] Execute an attached special (if any) - DoPickupSpecial (toucher); - - if (flags & MF_COUNTITEM) - { - if (player != NULL) - { - player->itemcount++; - } - level.found_items++; - } - - if (flags5 & MF5_COUNTSECRET) - { - P_GiveSecret(player != NULL? (AActor*)player->mo : toucher, true, true, -1); - } - - //Added by MC: Check if item taken was the roam destination of any bot - for (int i = 0; i < MAXPLAYERS; i++) - { - if (players[i].Bot != NULL && this == players[i].Bot->dest) - players[i].Bot->dest = NULL; + StaticLastMessageTic = gametic; + StaticLastMessage = str; + const char *pstr = str.GetChars(); + + if (pstr[0] == '$') pstr = GStrings(pstr + 1); + if (pstr[0] != 0) Printf(PRINT_LOW, "%s\n", pstr); + StatusBar->FlashCrosshair(); } + return 0; } //=========================================================================== @@ -783,37 +510,12 @@ void AInventory::DoPickupSpecial (AActor *toucher) } } -//=========================================================================== -// -// AInventory :: PickupMessage -// -// Returns the message to print when this actor is picked up. -// -//=========================================================================== - -FString AInventory::PickupMessage () -{ - return GetClass()->PickupMessage; -} - -DEFINE_ACTION_FUNCTION(AInventory, PickupMessage) +DEFINE_ACTION_FUNCTION(AInventory, DoPickupSpecial) { PARAM_SELF_PROLOGUE(AInventory); - ACTION_RETURN_STRING(self->PickupMessage()); -} - -FString AInventory::GetPickupMessage() -{ - IFVIRTUAL(AInventory, PickupMessage) - { - VMValue params[1] = { (DObject*)this }; - VMReturn ret; - FString retval; - ret.StringAt(&retval); - GlobalVMStack.Call(func, params, 1, &ret, 1, nullptr); - return retval; - } - else return PickupMessage(); + PARAM_OBJECT(toucher, AActor); + self->DoPickupSpecial(toucher); + return 0; } //=========================================================================== @@ -881,17 +583,6 @@ void AInventory::CallPlayPickupSound(AActor *other) // //=========================================================================== -bool AInventory::ShouldStay () -{ - return false; -} - -DEFINE_ACTION_FUNCTION(AInventory, ShouldStay) -{ - PARAM_SELF_PROLOGUE(AInventory); - ACTION_RETURN_BOOL(self->ShouldStay()); -} - bool AInventory::CallShouldStay() { IFVIRTUAL(AInventory, ShouldStay) @@ -903,7 +594,7 @@ bool AInventory::CallShouldStay() GlobalVMStack.Call(func, params, 1, &ret, 1, nullptr); return !!retval; } - else return ShouldStay(); + return false; } diff --git a/src/g_inventory/a_pickups.h b/src/g_inventory/a_pickups.h index 4701d60e6..4c5094ca6 100644 --- a/src/g_inventory/a_pickups.h +++ b/src/g_inventory/a_pickups.h @@ -59,7 +59,7 @@ public: virtual size_t PointerSubstitution(DObject *oldclass, DObject *newclass); void Finalize(FStateDefinitions &statedef); - FString PickupMessage; + FString PickupMsg; int GiveQuest; // Optionally give one of the quest items. FTextureID AltHUDIcon; TArray RestrictedToPlayerClass; @@ -72,10 +72,8 @@ class AInventory : public AActor HAS_OBJECT_POINTERS public: - virtual void Touch (AActor *toucher) override; virtual void Serialize(FSerializer &arc) override; virtual void MarkPrecacheSounds() const override; - virtual void BeginPlay () override; virtual void OnDestroy() override; virtual void Tick() override; virtual bool Grind(bool items) override; @@ -86,39 +84,20 @@ public: virtual bool ShouldRespawn (); virtual void DoPickupSpecial (AActor *toucher); - // methods that can be overridden by scripts, plus their callers. - virtual bool SpecialDropAction (AActor *dropper); - bool CallSpecialDropAction(AActor *dropper); - bool CallTryPickup(AActor *toucher, AActor **toucher_return = NULL); // This wraps both virtual methods plus a few more checks. - virtual AInventory *CreateCopy(AActor *other); - - AInventory *CreateTossable(); - - virtual FString PickupMessage(); - FString GetPickupMessage(); - - virtual bool HandlePickup(AInventory *item); - bool CallUse(bool pickup); virtual PalEntry GetBlend(); PalEntry CallGetBlend(); - virtual bool ShouldStay(); bool CallShouldStay(); - void DoEffect(); - virtual void PlayPickupSound(AActor *toucher); void CallPlayPickupSound(AActor *toucher); void CallAttachToOwner(AActor *other); - // still need to be done. - void ModifyDamage(int damage, FName damageType, int &newdamage, bool passive); - // virtual on the script side only. double GetSpeedFactor(); bool GetNoTeleportFreeze(); @@ -136,8 +115,6 @@ public: AInventory *PrevInv(); // Returns the previous item with IF_INVBAR set. AInventory *NextInv(); // Returns the next item with IF_INVBAR set. - bool CallStateChain(AActor *actor, FState *state); - TObjPtr Owner; // Who owns this item? NULL if it's still a pickup. int Amount; // Amount of item this instance has int MaxAmount; // Max amount of item this instance can have @@ -158,13 +135,13 @@ protected: void GiveQuest(AActor * toucher); private: - static int StaticLastMessageTic; - static FString StaticLastMessage; }; class AStateProvider : public AInventory { DECLARE_CLASS (AStateProvider, AInventory) +public: + bool CallStateChain(AActor *actor, FState *state); }; extern PClassActor *QuestItemClasses[31]; diff --git a/src/g_inventory/a_weapons.cpp b/src/g_inventory/a_weapons.cpp index bf7f04928..24661dfd1 100644 --- a/src/g_inventory/a_weapons.cpp +++ b/src/g_inventory/a_weapons.cpp @@ -56,8 +56,6 @@ #include "virtual.h" -#define BONUSADD 6 - extern FFlagDef WeaponFlagDefs[]; IMPLEMENT_CLASS(AWeapon, false, true) diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index f3e1a0c8d..65f7be9a1 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -108,7 +108,7 @@ static FRandom pr_bfgselfdamage("BFGSelfDamage"); // //========================================================================== -bool AInventory::CallStateChain (AActor *actor, FState *state) +bool AStateProvider::CallStateChain (AActor *actor, FState *state) { INTBOOL result = false; int counter = 0; @@ -223,9 +223,9 @@ bool AInventory::CallStateChain (AActor *actor, FState *state) return !!result; } -DEFINE_ACTION_FUNCTION(AInventory, CallStateChain) +DEFINE_ACTION_FUNCTION(ACustomInventory, CallStateChain) { - PARAM_SELF_PROLOGUE(AInventory); + PARAM_SELF_PROLOGUE(AStateProvider); PARAM_OBJECT(affectee, AActor); PARAM_STATE(state); ACTION_RETURN_BOOL(self->CallStateChain(affectee, state)); diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index bb90e976f..e42f9d08f 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -52,6 +52,7 @@ #include "p_checkposition.h" #include "math/cmath.h" #include "g_levellocals.h" +#include "virtual.h" #include "gi.h" @@ -3312,11 +3313,19 @@ AInventory *P_DropItem (AActor *source, PClassActor *type, int dropamount, int c AInventory *inv = static_cast(mo); ModifyDropAmount(inv, dropamount); inv->ItemFlags |= IF_TOSSED; - if (inv->CallSpecialDropAction (source)) + + IFVIRTUALPTR(inv, AInventory, SpecialDropAction) { - // The special action indicates that the item should not spawn - inv->Destroy(); - return NULL; + VMValue params[2] = { inv, source }; + int retval; + VMReturn ret(&retval); + GlobalVMStack.Call(func, params, 2, &ret, 1, nullptr); + if (retval) + { + // The special action indicates that the item should not spawn + inv->Destroy(); + return NULL; + } } return inv; } diff --git a/src/p_local.h b/src/p_local.h index 8ebdf9fae..d50d2be52 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -48,8 +48,6 @@ struct FLinePortal; #define STEEPSLOPE (46342/65536.) // [RH] Minimum floorplane.c value for walking -#define BONUSADD 6 - // Inspired by Maes extern int bmapnegx; extern int bmapnegy; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 6691a1d0e..c3bbcf076 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1038,12 +1038,14 @@ DEFINE_ACTION_FUNCTION(AActor, UseInventory) AInventory *AActor::DropInventory (AInventory *item) { - AInventory *drop = item->CreateTossable (); - - if (drop == NULL) + AInventory *drop = nullptr; + IFVIRTUALPTR(item, AInventory, CreateTossable) { - return NULL; + VMValue params[1] = { (DObject*)this }; + VMReturn ret((void**)&drop); + GlobalVMStack.Call(func, params, 1, &ret, 1, nullptr); } + if (drop == nullptr) return NULL; drop->SetOrigin(PosPlusZ(10.), false); drop->Angles.Yaw = Angles.Yaw; drop->VelFromAngle(5.); @@ -3945,7 +3947,11 @@ void AActor::Tick () // by the order in the inventory, not the order in the thinker table while (item != NULL && item->Owner == this) { - item->DoEffect(); + IFVIRTUALPTR(item, AInventory, DoEffect) + { + VMValue params[1] = { item }; + GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr); + } item = item->Inventory; } @@ -7592,10 +7598,13 @@ int AActor::GetModifiedDamage(FName damagetype, int damage, bool passive) auto inv = Inventory; while (inv != nullptr) { - inv->ModifyDamage(damage, damagetype, damage, passive); + IFVIRTUALPTR(inv, AInventory, ModifyDamage) + { + VMValue params[5] = { (DObject*)inv, damage, int(damagetype), &damage, passive }; + GlobalVMStack.Call(func, params, 5, nullptr, 0, nullptr); + } inv = inv->Inventory; } - return damage; } diff --git a/src/scripting/decorate/olddecorations.cpp b/src/scripting/decorate/olddecorations.cpp index 400444340..754d6deef 100644 --- a/src/scripting/decorate/olddecorations.cpp +++ b/src/scripting/decorate/olddecorations.cpp @@ -584,7 +584,7 @@ static void ParseInsideDecoration (Baggage &bag, AActor *defaults, else if (def == DEF_Pickup && sc.Compare ("PickupMessage")) { sc.MustGetString (); - static_cast(bag.Info)->PickupMessage = sc.String; + static_cast(bag.Info)->PickupMsg = sc.String; } else if (def == DEF_Pickup && sc.Compare ("Respawns")) { diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index 6cb482ed8..11e5dc96d 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -1802,7 +1802,7 @@ DEFINE_CLASS_PROPERTY(pickupmessage, T, Inventory) { PROP_STRING_PARM(str, 0); assert(info->IsKindOf(RUNTIME_CLASS(PClassInventory))); - static_cast(info)->PickupMessage = str; + static_cast(info)->PickupMsg = str; } //========================================================================== diff --git a/wadsrc/static/zscript/inventory/inventory.txt b/wadsrc/static/zscript/inventory/inventory.txt index d798dba26..fced80e24 100644 --- a/wadsrc/static/zscript/inventory/inventory.txt +++ b/wadsrc/static/zscript/inventory/inventory.txt @@ -8,6 +8,7 @@ struct VisStyle class Inventory : Actor native { const BLINKTHRESHOLD = (4*32); + const BONUSADD = 6; native Actor Owner; // Who owns self item? NULL if it's still a pickup. native int Amount; // Amount of item self instance has @@ -22,6 +23,7 @@ class Inventory : Actor native native bool bPickupGood; native bool bCreateCopyMoved; native bool bInitEffectFailed; + native meta String PickupMsg; Default { @@ -34,12 +36,8 @@ class Inventory : Actor native } virtual native color GetBlend (); - virtual native bool HandlePickup(Inventory item); - virtual native Inventory CreateCopy(Actor other); - virtual native bool SpecialDropAction (Actor dropper); - virtual native String PickupMessage(); - virtual native bool ShouldStay(); virtual native void PlayPickupSound(Actor user); + virtual native void DoPickupSpecial (Actor toucher); native bool DoRespawn(); native bool GoAway(); @@ -50,7 +48,7 @@ class Inventory : Actor native // In this case the caller function is more than a simple wrapper around the virtual method and // is what must be actually called to pick up an item. native bool, Actor CallTryPickup(Actor toucher); - native bool CallStateChain (Actor actor, State state); + native static void PrintPickupMessage (bool localview, String str); States(Actor, Overlay, Weapon, Item) { @@ -74,8 +72,18 @@ class Inventory : Actor native Stop; } - // These are regular functions for the item itself. - + //=========================================================================== + // + // AInventory :: BeginPlay + // + //=========================================================================== + + override void BeginPlay () + { + Super.BeginPlay (); + bDropped = true; // [RH] Items are dropped by default + } + //--------------------------------------------------------------------------- // // PROC A_RestoreSpecialThing1 @@ -132,6 +140,69 @@ class Inventory : Actor native } + //=========================================================================== + // + // AInventory :: CreateCopy + // + // Returns an actor suitable for placing in an inventory, either itself or + // a copy based on whether it needs to respawn or not. Returning NULL + // indicates the item should not be picked up. + // + //=========================================================================== + + virtual Inventory CreateCopy (Actor other) + { + Inventory copy; + + Amount = MIN(Amount, MaxAmount); + if (GoAway ()) + { + copy = Inventory(Spawn (GetClass())); + copy.Amount = Amount; + copy.MaxAmount = MaxAmount; + } + else + { + copy = self; + } + return copy; + } + + //=========================================================================== + // + // AInventory :: HandlePickup + // + // Returns true if the pickup was handled (or should not happen at all), + // false if not. + // + //=========================================================================== + + virtual bool HandlePickup (Inventory item) + { + if (item.GetClass() == GetClass()) + { + if (Amount < MaxAmount || (sv_unlimited_pickup && !item.ShouldStay())) + { + if (Amount > 0 && Amount + item.Amount < 0) + { + Amount = 0x7fffffff; + } + else + { + Amount += item.Amount; + } + + if (Amount > MaxAmount && !sv_unlimited_pickup) + { + Amount = MaxAmount; + } + item.bPickupGood = true; + } + return true; + } + return false; + } + //=========================================================================== // // AInventory :: CallHandlePickup @@ -236,6 +307,19 @@ class Inventory : Actor native return true; } + //=========================================================================== + // + // AInventory :: ShouldStay + // + // Returns true if the item should not disappear, even temporarily. + // + //=========================================================================== + + virtual bool ShouldStay () + { + return false; + } + //=========================================================================== // // AInventory :: TryPickupRestricted @@ -313,6 +397,97 @@ class Inventory : Actor native return copy; } + + //=========================================================================== + // + // AInventory :: PickupMessage + // + // Returns the message to print when this actor is picked up. + // + //=========================================================================== + + virtual String PickupMessage () + { + return PickupMsg; + } + + //=========================================================================== + // + // AInventory :: Touch + // + // Handles collisions from another actor, possible adding itself to the + // collider's inventory. + // + //=========================================================================== + + override void Touch (Actor toucher) + { + let player = toucher.player; + + // If a voodoo doll touches something, pretend the real player touched it instead. + if (player != NULL) + { + toucher = player.mo; + } + + bool localview = toucher.CheckLocalView(consoleplayer); + + bool res; + [res, toucher] = CallTryPickup(toucher); + if (!res) return; + + // This is the only situation when a pickup flash should ever play. + if (PickupFlash != NULL && !ShouldStay()) + { + Spawn(PickupFlash, Pos, ALLOW_REPLACE); + } + + if (!bQuiet) + { + PrintPickupMessage(localview, PickupMessage ()); + + // Special check so voodoo dolls picking up items cause the + // real player to make noise. + if (player != NULL) + { + PlayPickupSound (player.mo); + if (!bNoScreenFlash) + { + player.bonuscount = BONUSADD; + } + } + else + { + PlayPickupSound (toucher); + } + } + + // [RH] Execute an attached special (if any) + DoPickupSpecial (toucher); + + if (bCountItem) + { + if (player != NULL) + { + player.itemcount++; + } + level.found_items++; + } + + if (bCountSecret) + { + Actor ac = player != NULL? Actor(player.mo) : toucher; + ac.GiveSecret(true, true); + } + + //Added by MC: Check if item taken was the roam destination of any bot + for (int i = 0; i < MAXPLAYERS; i++) + { + if (players[i].Bot != NULL && self == players[i].Bot.dest) + players[i].Bot.dest = NULL; + } + } + //=========================================================================== // // AInventory :: DepleteOrDestroy @@ -361,11 +536,27 @@ class Inventory : Actor native virtual void DoEffect() {} + //=========================================================================== + // + // AInventory :: ModifyDamage + // + // Allows inventory items to manipulate the amount of damage + // inflicted. Damage is the amount of damage that would be done without manipulation, + // and newdamage is the amount that should be done after the item has changed + // it. + // 'active' means it is called by the inflictor, 'passive' by the target. + // It may seem that this is redundant and AbsorbDamage is the same. However, + // AbsorbDamage is called only for players and also depends on other settings + // which are undesirable for a protection artifact. + // + //=========================================================================== + + virtual void ModifyDamage(int damage, Name damageType, out int newdamage, bool passive) {} + virtual bool Use (bool pickup) { return false; } virtual double GetSpeedFactor() { return 1; } 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() {} @@ -393,6 +584,22 @@ class Inventory : Actor native virtual void AbsorbDamage (int damage, Name damageType, out int newdamage) {} + //=========================================================================== + // + // AInventory :: SpecialDropAction + // + // Called by P_DropItem. Return true to prevent the standard drop tossing. + // A few Strife items that are meant to trigger actions rather than be + // picked up use this. Normal items shouldn't need it. + // + //=========================================================================== + + virtual bool SpecialDropAction (Actor dropper) + { + return false; + } + + } class DehackedPickup : Inventory native diff --git a/wadsrc/static/zscript/inventory/stateprovider.txt b/wadsrc/static/zscript/inventory/stateprovider.txt index 8f5571629..3f4f1fcda 100644 --- a/wadsrc/static/zscript/inventory/stateprovider.txt +++ b/wadsrc/static/zscript/inventory/stateprovider.txt @@ -13,7 +13,7 @@ class StateProvider : Inventory native action native void A_ResetReloadCounter(); } -class CustomInventory : StateProvider native +class CustomInventory : StateProvider { Default { @@ -36,7 +36,8 @@ class CustomInventory : StateProvider native deprecated action void A_Lower() {} deprecated action void A_Raise() {} deprecated action void A_CheckReload() {} - + native bool CallStateChain (Actor actor, State state); + //=========================================================================== // // ACustomInventory :: SpecialDropAction diff --git a/wadsrc/static/zscript/shared/botstuff.txt b/wadsrc/static/zscript/shared/botstuff.txt index 3ae2d1889..991e4876e 100644 --- a/wadsrc/static/zscript/shared/botstuff.txt +++ b/wadsrc/static/zscript/shared/botstuff.txt @@ -24,6 +24,7 @@ class CajunTrace : Actor } } -struct Bot native +class Bot native { + native Actor dest; }