From 588ddd185b8f62051e1407d660fb9b0e9fb102e6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 1 Dec 2018 17:11:09 +0100 Subject: [PATCH] - scriptified TakeInventory, including the ACS/FS interfaces. --- src/fragglescript/t_func.cpp | 43 +--------- src/namedef.h | 1 + src/p_acs.cpp | 84 ++++++------------- src/p_mobj.cpp | 53 ++---------- wadsrc/static/zscript/actor.txt | 1 - wadsrc/static/zscript/actor_inventory.txt | 49 +++++++++++ .../static/zscript/scriptutil/scriptutil.txt | 41 +++++++++ 7 files changed, 123 insertions(+), 149 deletions(-) diff --git a/src/fragglescript/t_func.cpp b/src/fragglescript/t_func.cpp index 521a718c7..472d525d5 100644 --- a/src/fragglescript/t_func.cpp +++ b/src/fragglescript/t_func.cpp @@ -2405,44 +2405,6 @@ void FParser::SF_IsPlayerObj(void) //============================================================================ -//============================================================================ -// -// DoTakeInv -// -// Takes an item from a single actor. -// -//============================================================================ - -static void FS_TakeInventory (AActor *actor, const char * type, int amount) -{ - if (strcmp (type, "Armor") == 0) - { - type = "BasicArmor"; - } - if (amount <= 0) - { - return; - } - PClassActor * info = PClass::FindActor (type); - if (info == NULL) - { - return; - } - - AInventory *item = actor->FindInventory (info); - if (item != NULL) - { - item->Amount -= amount; - if (item->Amount <= 0) - { - // If it's not ammo, destroy it. Ammo needs to stick around, even - // when it's zero for the benefit of the weapons that use it and - // to maintain the maximum ammo amounts a backpack might have given. - item->DepleteOrDestroy(); - } - } -} - //============================================================================ // // CheckInventory @@ -2507,8 +2469,7 @@ void FParser::SF_PlayerKeys(void) else { givetake = intvalue(t_argv[2]); - if(givetake) ScriptUtil::Exec(NAME_GiveInventory, players[playernum].mo, keyname.GetIndex(), 1); - else FS_TakeInventory(players[playernum].mo, keyname, 1); + ScriptUtil::Exec(givetake?NAME_GiveInventory : NAME_TakeInventory, players[playernum].mo, keyname.GetIndex(), 1); t_return.type = svt_int; t_return.value.i = 0; } @@ -2740,7 +2701,7 @@ void FParser::SF_TakeInventory(void) if(t_argc == 2) count=32767; else count=intvalue(t_argv[2]); - FS_TakeInventory(players[playernum].mo, stringvalue(t_argv[1]), count); + ScriptUtil::Exec(NAME_TakeInventory, 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 0573c5715..fd876a89b 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -993,6 +993,7 @@ xx(ScriptUtil) xx(SetMarineWeapon) xx(SetMarineSprite) xx(GiveInventory) +xx(TakeInventory) // Weapon member fields that need direct access xx(Ammo1) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 2c94459a3..40a739b39 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -1747,49 +1747,6 @@ static void ClearInventory (AActor *activator) } } -//============================================================================ -// -// TakeInventory -// -// Takes an item from one or more actors. -// -//============================================================================ - -static void TakeInventory (AActor *activator, const char *type, int amount) -{ - PClassActor *info; - - if (type == NULL) - { - return; - } - if (strcmp (type, "Armor") == 0) - { - type = "BasicArmor"; - } - if (amount <= 0) - { - return; - } - info = PClass::FindActor (type); - if (info == NULL) - { - return; - } - if (activator == NULL) - { - for (int i = 0; i < MAXPLAYERS; ++i) - { - if (playeringame[i]) - players[i].mo->TakeInventory(info, amount); - } - } - else - { - activator->TakeInventory(info, amount); - } -} - //============================================================================ // // DoUseInv @@ -9319,34 +9276,41 @@ scriptwait: } case PCD_TAKEINVENTORY: - TakeInventory (activator, FBehavior::StaticLookupString (STACK(2)), STACK(1)); + { + int typeindex = FName(FBehavior::StaticLookupString(STACK(2))).GetIndex(); + ScriptUtil::Exec(NAME_TakeInventory, ScriptUtil::Pointer, activator, ScriptUtil::Int, typeindex, ScriptUtil::Int, STACK(1), ScriptUtil::End); sp -= 2; break; + } case PCD_TAKEACTORINVENTORY: + { + 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) - { - TakeInventory(NULL, type, STACK(1)); - } - else - { - FActorIterator it(STACK(3)); - AActor *actor; - for (actor = it.Next(); actor != NULL; actor = it.Next()) - { - TakeInventory(actor, type, STACK(1)); - } - } - sp -= 3; + ScriptUtil::Exec(NAME_TakeInventory, 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_TakeInventory, ScriptUtil::Pointer, actor, ScriptUtil::Int, typeindex, ScriptUtil::Int, STACK(1), ScriptUtil::End); + } + } + sp -= 3; break; + } case PCD_TAKEINVENTORYDIRECT: - TakeInventory (activator, FBehavior::StaticLookupString (TAGSTR(uallong(pc[0]))), uallong(pc[1])); + { + int typeindex = FName(FBehavior::StaticLookupString(TAGSTR(uallong(pc[0])))).GetIndex(); + ScriptUtil::Exec(NAME_TakeInventory, ScriptUtil::Pointer, activator, ScriptUtil::Int, typeindex, ScriptUtil::Int, uallong(pc[1]), ScriptUtil::End); pc += 2; break; + } case PCD_CHECKINVENTORY: STACK(1) = CheckInventory (activator, FBehavior::StaticLookupString (STACK(1)), false); diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 2e9f109a6..3dc5d8868 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -761,57 +761,16 @@ DEFINE_ACTION_FUNCTION(AActor, SetState) bool AActor::TakeInventory(PClassActor *itemclass, int amount, bool fromdecorate, bool notakeinfinite) { - amount = abs(amount); - AInventory *item = FindInventory(itemclass); - - if (item == NULL) - return false; - - if (!fromdecorate) + IFVM(Actor, TakeInventory) { - item->Amount -= amount; - if (item->Amount <= 0) - { - item->DepleteOrDestroy(); - } - // It won't be used in non-decorate context, so return false here - return false; + VMValue params[] = { this, itemclass, amount, fromdecorate, notakeinfinite }; + int retval = 0; + VMReturn ret(&retval); + VMCall(func, params, 5, &ret, 1); + return !!retval; } - - bool result = false; - if (item->Amount > 0) - { - result = true; - } - - // Do not take ammo if the "no take infinite/take as ammo depletion" flag is set - // and infinite ammo is on - if (notakeinfinite && - ((dmflags & DF_INFINITE_AMMO) || (player && FindInventory(NAME_PowerInfiniteAmmo, true))) && item->IsKindOf(NAME_Ammo)) - { - // Nothing to do here, except maybe res = false;? Would it make sense? - result = false; - } - else if (!amount || amount>=item->Amount) - { - item->DepleteOrDestroy(); - } - else item->Amount-=amount; - - return result; } -DEFINE_ACTION_FUNCTION(AActor, TakeInventory) -{ - PARAM_SELF_PROLOGUE(AActor); - PARAM_CLASS_NOT_NULL(item, AInventory); - PARAM_INT(amount); - PARAM_BOOL(fromdecorate); - PARAM_BOOL(notakeinfinite); - ACTION_RETURN_BOOL(self->TakeInventory(item, amount, fromdecorate, notakeinfinite)); -} - - bool AActor::SetInventory(PClassActor *itemtype, int amount, bool beyondMax) { diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 43a5722d4..e1f5605ae 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -744,7 +744,6 @@ class Actor : Thinker native native void ClearInventory(); protected native void DestroyAllInventory(); // This is not supposed to be called by user code! 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; native Inventory GiveInventoryType(class itemtype); native Inventory DropInventory (Inventory item, int amt = -1); diff --git a/wadsrc/static/zscript/actor_inventory.txt b/wadsrc/static/zscript/actor_inventory.txt index 676fe7ba6..910c57589 100644 --- a/wadsrc/static/zscript/actor_inventory.txt +++ b/wadsrc/static/zscript/actor_inventory.txt @@ -110,4 +110,53 @@ extend class Actor } } + //============================================================================ + // + // AActor :: TakeInventory + // + //============================================================================ + + bool TakeInventory(class itemclass, int amount, bool fromdecorate = false, bool notakeinfinite = false) + { + amount = abs(amount); + let item = FindInventory(itemclass); + + if (item == NULL) + return false; + + if (!fromdecorate) + { + item.Amount -= amount; + if (item.Amount <= 0) + { + item.DepleteOrDestroy(); + } + // It won't be used in non-decorate context, so return false here + return false; + } + + bool result = false; + if (item.Amount > 0) + { + result = true; + } + + // Do not take ammo if the "no take infinite/take as ammo depletion" flag is set + // and infinite ammo is on + if (notakeinfinite && + (sv_infiniteammo || (player && FindInventory('PowerInfiniteAmmo', true))) && (item is 'Ammo')) + { + // Nothing to do here, except maybe res = false;? Would it make sense? + result = false; + } + else if (!amount || amount >= item.Amount) + { + item.DepleteOrDestroy(); + } + else item.Amount -= amount; + + return result; + } + + } \ No newline at end of file diff --git a/wadsrc/static/zscript/scriptutil/scriptutil.txt b/wadsrc/static/zscript/scriptutil/scriptutil.txt index d36ff3640..0f22e8423 100644 --- a/wadsrc/static/zscript/scriptutil/scriptutil.txt +++ b/wadsrc/static/zscript/scriptutil/scriptutil.txt @@ -45,6 +45,47 @@ class ScriptUtil play } } + //============================================================================ + // + // TakeInventory + // + // Takes an item from one or more actors. + // + //============================================================================ + + static void TakeInventory (Actor activator, Name type, int amount) + { + if (type == 'none') + { + return; + } + if (type == 'Armor') + { + type = "BasicArmor"; + } + if (amount <= 0) + { + return; + } + Class info = type; + if (info == NULL) + { + return; + } + if (activator == NULL) + { + for (int i = 0; i < MAXPLAYERS; ++i) + { + if (playeringame[i]) + players[i].mo.TakeInventory(info, amount); + } + } + else + { + activator.TakeInventory(info, amount); + } + } + //========================================================================== // //