diff --git a/src/actor.h b/src/actor.h index b2f011919..599ff767b 100644 --- a/src/actor.h +++ b/src/actor.h @@ -745,10 +745,6 @@ public: // APlayerPawn for some specific handling for players. None of this // should ever be overridden by custom classes. - // Give an item to the actor and pick it up. - // Returns true if the item pickup succeeded. - bool GiveInventory (PClassActor *type, int amount, bool givecheat = false); - // Removes the item from the inventory list. virtual void RemoveInventory (AInventory *item); diff --git a/src/fragglescript/t_func.cpp b/src/fragglescript/t_func.cpp index 6ecbeb441..b9fd08d2f 100644 --- a/src/fragglescript/t_func.cpp +++ b/src/fragglescript/t_func.cpp @@ -2416,34 +2416,6 @@ void FParser::SF_IsPlayerObj(void) //============================================================================ -//============================================================================ -// -// DoGiveInv -// -// Gives an item to a single actor. -// -//============================================================================ - -static void FS_GiveInventory (AActor *actor, const char * type, int amount) -{ - if (amount <= 0) - { - return; - } - if (strcmp (type, "Armor") == 0) - { - type = "BasicArmorPickup"; - } - auto info = PClass::FindActor (type); - if (info == NULL || !info->IsDescendantOf(RUNTIME_CLASS(AInventory))) - { - Printf ("Unknown inventory item: %s\n", type); - return; - } - - actor->GiveInventory(info, amount); -} - //============================================================================ // // DoTakeInv @@ -2520,9 +2492,9 @@ static int FS_CheckInventory (AActor *activator, const char *type) void FParser::SF_PlayerKeys(void) { - static const char * const DoomKeys[]={"BlueCard", "YellowCard", "RedCard", "BlueSkull", "YellowSkull", "RedSkull"}; + static const ENamedName DoomKeys[]={NAME_BlueCard, NAME_YellowCard, NAME_RedCard, NAME_BlueSkull, NAME_YellowSkull, NAME_RedSkull}; int playernum, keynum, givetake; - const char * keyname; + FName keyname; if (CheckArgs(2)) { @@ -2546,7 +2518,7 @@ void FParser::SF_PlayerKeys(void) else { givetake = intvalue(t_argv[2]); - if(givetake) FS_GiveInventory(players[playernum].mo, keyname, 1); + if(givetake) ScriptUtil::Exec(NAME_GiveInventory, players[playernum].mo, keyname.GetIndex(), 1); else FS_TakeInventory(players[playernum].mo, keyname, 1); t_return.type = svt_int; t_return.value.i = 0; @@ -2756,7 +2728,7 @@ void FParser::SF_GiveInventory(void) if(t_argc == 2) count=1; else count=intvalue(t_argv[2]); - FS_GiveInventory(players[playernum].mo, stringvalue(t_argv[1]), count); + ScriptUtil::Exec(NAME_GiveInventory, ScriptUtil::Pointer, players[playernum].mo, FName(stringvalue(t_argv[1])).GetIndex(), count); t_return.type = svt_int; t_return.value.i = 0; } diff --git a/src/namedef.h b/src/namedef.h index 7c366610b..0573c5715 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -992,6 +992,7 @@ xx(snd_resampler) xx(ScriptUtil) xx(SetMarineWeapon) xx(SetMarineSprite) +xx(GiveInventory) // Weapon member fields that need direct access xx(Ammo1) @@ -1009,4 +1010,11 @@ xx(bDehAmmo) xx(FOVScale) xx(YAdjust) xx(Crosshair) -xx(WeaponFlags) \ No newline at end of file +xx(WeaponFlags) + +xx(BlueCard) +xx(YellowCard) +xx(RedCard) +xx(BlueSkull) +xx(YellowSkull) +xx(RedSkull) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 11091d56f..2a00cc404 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -1762,49 +1762,6 @@ static void ClearInventory (AActor *activator) } } -//============================================================================ -// -// GiveInventory -// -// Gives an item to one or more actors. -// -//============================================================================ - -static void GiveInventory (AActor *activator, const char *type, int amount) -{ - PClassActor *info; - - if (amount <= 0 || type == NULL) - { - return; - } - if (stricmp (type, "Armor") == 0) - { - type = "BasicArmorPickup"; - } - info = PClass::FindActor(type); - if (info == NULL) - { - Printf ("ACS: I don't know what %s is.\n", type); - } - else if (!info->IsDescendantOf (RUNTIME_CLASS(AInventory))) - { - Printf ("ACS: %s is not an inventory item.\n", type); - } - else if (activator == NULL) - { - for (int i = 0; i < MAXPLAYERS; ++i) - { - if (playeringame[i]) - players[i].mo->GiveInventory(info, amount); - } - } - else - { - activator->GiveInventory(info, amount); - } -} - //============================================================================ // // TakeInventory @@ -9340,34 +9297,41 @@ scriptwait: break; case PCD_GIVEINVENTORY: - GiveInventory (activator, FBehavior::StaticLookupString (STACK(2)), STACK(1)); + { + int typeindex = FName(FBehavior::StaticLookupString(STACK(2))).GetIndex(); + ScriptUtil::Exec(NAME_GiveInventory, ScriptUtil::Pointer, activator, ScriptUtil::Int, typeindex, ScriptUtil::Int, STACK(1), ScriptUtil::End); sp -= 2; break; + } case PCD_GIVEACTORINVENTORY: + { + int typeindex = FName(FBehavior::StaticLookupString(STACK(2))).GetIndex(); + FName type = FName(FBehavior::StaticLookupString(STACK(2))); + if (STACK(3) == 0) { - const char *type = FBehavior::StaticLookupString(STACK(2)); - if (STACK(3) == 0) - { - GiveInventory(NULL, FBehavior::StaticLookupString(STACK(2)), STACK(1)); - } - else - { - FActorIterator it(STACK(3)); - AActor *actor; - for (actor = it.Next(); actor != NULL; actor = it.Next()) - { - GiveInventory(actor, type, STACK(1)); - } - } - sp -= 3; + ScriptUtil::Exec(NAME_GiveInventory, ScriptUtil::Pointer, nullptr, ScriptUtil::Int, typeindex, ScriptUtil::Int, STACK(1), ScriptUtil::End); } + else + { + FActorIterator it(STACK(3)); + AActor *actor; + for (actor = it.Next(); actor != NULL; actor = it.Next()) + { + ScriptUtil::Exec(NAME_GiveInventory, ScriptUtil::Pointer, actor, ScriptUtil::Int, typeindex, ScriptUtil::Int, STACK(1), ScriptUtil::End); + } + } + sp -= 3; break; + } case PCD_GIVEINVENTORYDIRECT: - GiveInventory (activator, FBehavior::StaticLookupString (TAGSTR(uallong(pc[0]))), uallong(pc[1])); + { + int typeindex = FName(FBehavior::StaticLookupString(TAGSTR(uallong(pc[0])))).GetIndex(); + ScriptUtil::Exec(NAME_GiveInventory, ScriptUtil::Pointer, activator, ScriptUtil::Int, typeindex, ScriptUtil::Int, uallong(pc[1]), ScriptUtil::End); pc += 2; break; + } case PCD_TAKEINVENTORY: TakeInventory (activator, FBehavior::StaticLookupString (STACK(2)), STACK(1)); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 221e6dce6..66fee58db 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -767,81 +767,6 @@ DEFINE_ACTION_FUNCTION(AActor, SetState) ACTION_RETURN_BOOL(self->SetState(state, nofunction)); }; -//============================================================================ -// -// AActor :: GiveInventory -// -//============================================================================ - -bool AActor::GiveInventory(PClassActor *type, int amount, bool givecheat) -{ - bool result = true; - - if (type == nullptr || !type->IsDescendantOf(RUNTIME_CLASS(AInventory))) return false; - - auto savedPendingWeap = player != NULL ? player->PendingWeapon : NULL; - bool hadweap = player != NULL ? player->ReadyWeapon != NULL : true; - - AInventory *item; - if (!givecheat) - { - item = static_cast(Spawn (type)); - } - else - { - item = static_cast(Spawn (type, Pos(), NO_REPLACE)); - if (item == NULL) return false; - } - - // This shouldn't count for the item statistics! - item->ClearCounters(); - if (!givecheat || amount > 0) - { - if (type->IsDescendantOf(NAME_BasicArmorPickup) || type->IsDescendantOf(NAME_BasicArmorBonus)) - { - item->IntVar(NAME_SaveAmount) *= amount; - } - else - { - if (givecheat) - { - const AInventory *const haveitem = FindInventory(type); - - item->Amount = MIN(amount, nullptr == haveitem - ? static_cast(GetDefaultByType(type))->MaxAmount - : haveitem->MaxAmount); - } - else - { - item->Amount = amount; - } - } - } - if (!item->CallTryPickup (this)) - { - item->Destroy (); - result = false; - } - // If the item was a weapon, don't bring it up automatically - // unless the player was not already using a weapon. - // Don't bring it up automatically if this is called by the give cheat. - if (!givecheat && player != NULL && savedPendingWeap != NULL && hadweap) - { - player->PendingWeapon = savedPendingWeap; - } - return result; -} - -DEFINE_ACTION_FUNCTION(AActor, GiveInventory) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_CLASS(type, AInventory); - PARAM_INT(amount); - PARAM_BOOL(givecheat); - ACTION_RETURN_BOOL(self->GiveInventory(type, amount, givecheat)); -} - - //============================================================================ // // AActor :: RemoveInventory diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index acba81024..752ad50aa 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -742,7 +742,6 @@ class Actor : Thinker native native void RemoveInventory(Inventory inv); native void ClearInventory(); protected native void DestroyAllInventory(); // This is not supposed to be called by user code! - native bool GiveInventory(class type, int amount, bool givecheat = false); native bool SetInventory(class itemclass, int amount, bool beyondMax = false); native bool TakeInventory(class itemclass, int amount, bool fromdecorate = false, bool notakeinfinite = false); native clearscope Inventory FindInventory(class itemtype, bool subclass = false) const; diff --git a/wadsrc/static/zscript/actor_inventory.txt b/wadsrc/static/zscript/actor_inventory.txt index 052e1f21f..d28d75654 100644 --- a/wadsrc/static/zscript/actor_inventory.txt +++ b/wadsrc/static/zscript/actor_inventory.txt @@ -31,4 +31,53 @@ extend class Actor Inv.InventoryID = InventoryID++; } + //============================================================================ + // + // AActor :: GiveInventory + // + //============================================================================ + + bool GiveInventory(Class type, int amount, bool givecheat = false) + { + bool result = true; + let player = self.player; + + // This can be called from places which do not check the given item's type. + if (type == null || !(type is 'Inventory')) return false; + + Weapon savedPendingWeap = player != NULL ? player.PendingWeapon : NULL; + bool hadweap = player != NULL ? player.ReadyWeapon != NULL : true; + + Inventory item; + if (!givecheat) + { + item = Inventory(Spawn (type)); + } + else + { + item = Inventory(Spawn (type, Pos, NO_REPLACE)); + if (item == NULL) return false; + } + + // This shouldn't count for the item statistics. + item.ClearCounters(); + if (!givecheat || amount > 0) + { + item.SetGiveAmount(self, amount, givecheat); + } + if (!item.CallTryPickup (self)) + { + item.Destroy (); + result = false; + } + // If the item was a weapon, don't bring it up automatically + // unless the player was not already using a weapon. + // Don't bring it up automatically if this is called by the give cheat. + if (!givecheat && player != NULL && savedPendingWeap != NULL && hadweap) + { + player.PendingWeapon = savedPendingWeap; + } + return result; + } + } \ No newline at end of file diff --git a/wadsrc/static/zscript/inventory/armor.txt b/wadsrc/static/zscript/inventory/armor.txt index 1ffe70e79..96d355e19 100644 --- a/wadsrc/static/zscript/inventory/armor.txt +++ b/wadsrc/static/zscript/inventory/armor.txt @@ -340,6 +340,10 @@ class BasicArmorBonus : Armor } + override void SetGiveAmount(Actor receiver, int amount, bool bycheat) + { + SaveAmount *= amount; + } } //=========================================================================== @@ -440,6 +444,12 @@ class BasicArmorPickup : Armor armor.ActualSaveAmount = SaveAmount; return true; } + + override void SetGiveAmount(Actor receiver, int amount, bool bycheat) + { + SaveAmount *= amount; + } + } //=========================================================================== diff --git a/wadsrc/static/zscript/inventory/inventory.txt b/wadsrc/static/zscript/inventory/inventory.txt index da2e70555..7672bf1c8 100644 --- a/wadsrc/static/zscript/inventory/inventory.txt +++ b/wadsrc/static/zscript/inventory/inventory.txt @@ -1016,6 +1016,27 @@ class Inventory : Actor native } } + //--------------------------------------------------------------------------- + // + // Modifies the amount based on what an item should contain if given + // + //--------------------------------------------------------------------------- + + virtual void SetGiveAmount(Actor receiver, int amount, bool givecheat) + { + if (givecheat) + { + let haveitem = receiver.FindInventory(GetClass()); + self.Amount = MIN(amount, haveitem == null? self.Default.MaxAmount : haveitem.MaxAmount); + } + else + { + self.Amount = amount; + } + } + + + } //=========================================================================== diff --git a/wadsrc/static/zscript/scriptutil/scriptutil.txt b/wadsrc/static/zscript/scriptutil/scriptutil.txt index d29fb3f34..d36ff3640 100644 --- a/wadsrc/static/zscript/scriptutil/scriptutil.txt +++ b/wadsrc/static/zscript/scriptutil/scriptutil.txt @@ -4,6 +4,47 @@ class ScriptUtil play { + //============================================================================ + // + // GiveInventory + // + // Gives an item to one or more actors. + // + //============================================================================ + + static void GiveInventory (Actor activator, Name type, int amount) + { + if (amount <= 0 || type == 'none') + { + return; + } + if (type == 'Armor') + { + type = "BasicArmorPickup"; + } + Class info = type; + if (info == NULL) + { + Console.Printf ("GiveInventory: Unknown item type %s.\n", type); + } + else if (!(info is 'Inventory')) + { + Console.Printf ("GiveInventory: %s is not an inventory item.\n", type); + } + else if (activator == NULL) + { + for (int i = 0; i < MAXPLAYERS; ++i) + { + if (playeringame[i]) + players[i].mo.GiveInventory((class)(info), amount); + } + } + else + { + activator.GiveInventory((class)(info), amount); + } + } + //========================================================================== // //