diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index d803b3040..804397a05 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -925,54 +925,13 @@ DEFINE_ACTION_FUNCTION(AActor, GiveInventoryType) void AActor::ClearInventory() { - // In case destroying an inventory item causes another to be destroyed - // (e.g. Weapons destroy their sisters), keep track of the pointer to - // the next inventory item rather than the next inventory item itself. - // For example, if a weapon is immediately followed by its sister, the - // next weapon we had tracked would be to the sister, so it is now - // invalid and we won't be able to find the complete inventory by - // following it. - // - // When we destroy an item, we leave invp alone, since the destruction - // process will leave it pointing to the next item we want to check. If - // we don't destroy an item, then we move invp to point to its Inventory - // pointer. - // - // It should be safe to assume that an item being destroyed will only - // destroy items further down in the chain, because if it was going to - // destroy something we already processed, we've already destroyed it, - // so it won't have anything to destroy. - - AInventory **invp = &Inventory; - - while (*invp != NULL) + IFVIRTUAL(AActor, ClearInventory) { - AInventory *inv = *invp; - if (!(inv->ItemFlags & IF_UNDROPPABLE)) - { - DepleteOrDestroy(inv); - if (!(inv->ObjectFlags & OF_EuthanizeMe)) invp = &inv->Inventory; // was only depleted so advance the pointer manually. - } - else - { - invp = &inv->Inventory; - } - } - if (player != nullptr) - { - player->ReadyWeapon = nullptr; - player->PendingWeapon = WP_NOCHANGE; + VMValue params[] = { this }; + VMCall(func, params, 1, nullptr, 0); } } -DEFINE_ACTION_FUNCTION(AActor, ClearInventory) -{ - PARAM_SELF_PROLOGUE(AActor); - self->ClearInventory(); - return 0; -} - - //============================================================================ // // AActor :: CopyFriendliness diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index b065fde6b..da933dcf1 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -741,7 +741,6 @@ class Actor : Thinker native native clearscope int GetAge() const; native bool CheckClass(class checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false); - native void ClearInventory(); protected native void DestroyAllInventory(); // This is not supposed to be called by user code! native clearscope Inventory FindInventory(class itemtype, bool subclass = false) const; native Inventory GiveInventoryType(class itemtype); diff --git a/wadsrc/static/zscript/actor_inventory.txt b/wadsrc/static/zscript/actor_inventory.txt index 27816f041..18b0f4154 100644 --- a/wadsrc/static/zscript/actor_inventory.txt +++ b/wadsrc/static/zscript/actor_inventory.txt @@ -305,6 +305,57 @@ extend class Actor } + //============================================================================ + // + // AActor :: ClearInventory + // + // Clears the inventory of a single actor. + // + //============================================================================ + + virtual void ClearInventory() + { + // In case destroying an inventory item causes another to be destroyed + // (e.g. Weapons destroy their sisters), keep track of the pointer to + // the next inventory item rather than the next inventory item itself. + // For example, if a weapon is immediately followed by its sister, the + // next weapon we had tracked would be to the sister, so it is now + // invalid and we won't be able to find the complete inventory by + // following it. + // + // When we destroy an item, we leave last alone, since the destruction + // process will leave it pointing to the next item we want to check. If + // we don't destroy an item, then we move last to point to its Inventory + // pointer. + // + // It should be safe to assume that an item being destroyed will only + // destroy items further down in the chain, because if it was going to + // destroy something we already processed, we've already destroyed it, + // so it won't have anything to destroy. + + let last = self; + + while (last.inv != NULL) + { + let inv = last.inv; + if (!inv.bUndroppable) + { + inv.DepleteOrDestroy(); + if (!inv.bDestroyed) last = inv; // was only depleted so advance the pointer manually. + } + else + { + last = inv; + } + } + if (player != null) + { + player.ReadyWeapon = null; + player.PendingWeapon = WP_NOCHANGE; + } + } + + //============================================================================ // // AActor :: GiveAmmo