- changed AInventory::HandlePickup to work iteratively instead of recursively.

Two reasons for this:

1. if this has to be routed through the VM each recursion will cost 1000 bytes of stack space which simply is not good.
2. having the virtual function only care about the item itself but not the entire inventory chain is a lot less error prone for scripting.

Since the scripting interface needs a separate caller function anyway this seemed like a good time to change it. The same will be done for the other chained inventory handlers as well.
This commit is contained in:
Christoph Oelckers 2016-11-27 10:40:43 +01:00
parent 6eff1cb8be
commit 096c51d546
18 changed files with 55 additions and 72 deletions

View file

@ -855,7 +855,6 @@ set( NOT_COMPILED_SOURCE_FILES
${OTHER_SYSTEM_SOURCES}
sc_man_scanner.h
sc_man_scanner.re
g_hexen/a_flechette.cpp
g_hexen/a_flies.cpp
g_hexen/a_heresiarch.cpp
g_hexen/a_hexenspecialdecs.cpp

View file

@ -45,6 +45,7 @@
#include "autosegs.h"
#include "v_text.h"
#include "a_pickups.h"
#include "a_artifacts.h"
#include "a_weaponpiece.h"
#include "d_player.h"
#include "doomerrors.h"

View file

@ -478,15 +478,15 @@ CCMD (useflechette)
{ // Select from one of arti_poisonbag1-3, whichever the player has
static const ENamedName bagnames[3] =
{
NAME_ArtiPoisonBag3, // use type 3 first because that's the default when the player has none specified.
NAME_ArtiPoisonBag1,
NAME_ArtiPoisonBag2,
NAME_ArtiPoisonBag3
NAME_ArtiPoisonBag2
};
if (who == NULL)
return;
PClassActor *type = GetFlechetteType(who);
PClassActor *type = who->FlechetteType;
if (type != NULL)
{
AInventory *item;
@ -497,7 +497,7 @@ CCMD (useflechette)
}
}
// The default flechette could not be found. Try all 3 types then.
// The default flechette could not be found, or the player had no default. Try all 3 types then.
for (int j = 0; j < 3; ++j)
{
AInventory *item;

View file

@ -1,15 +0,0 @@
#ifndef __A_HEXENGLOBAL_H__
#define __A_HEXENGLOBAL_H__
#include "d_player.h"
class AArtiPoisonBag : public AInventory
{
DECLARE_CLASS (AArtiPoisonBag, AInventory)
public:
bool HandlePickup (AInventory *item);
AInventory *CreateCopy (AActor *other);
void BeginPlay ();
};
#endif //__A_HEXENGLOBAL_H__

View file

@ -115,10 +115,6 @@ bool ABasicArmor::HandlePickup (AInventory *item)
armor->SaveAmount = int(armor->SaveAmount * G_SkillProperty(SKILLP_ArmorFactor));
}
if (Inventory != NULL)
{
return Inventory->HandlePickup (item);
}
return false;
}
@ -474,10 +470,6 @@ bool AHexenArmor::HandlePickup (AInventory *item)
}
return true;
}
else if (Inventory != NULL)
{
return Inventory->HandlePickup (item);
}
return false;
}

View file

@ -309,10 +309,6 @@ bool APowerup::HandlePickup (AInventory *item)
power->ItemFlags |= IF_PICKUPGOOD;
return true;
}
if (Inventory != NULL)
{
return Inventory->HandlePickup (item);
}
return false;
}

View file

@ -487,10 +487,6 @@ bool AKey::HandlePickup (AInventory *item)
item->ItemFlags |= IF_PICKUPGOOD;
return true;
}
if (Inventory != NULL)
{
return Inventory->HandlePickup (item);
}
return false;
}

View file

@ -183,10 +183,6 @@ bool AAmmo::HandlePickup (AInventory *item)
}
return true;
}
if (Inventory != NULL)
{
return Inventory->HandlePickup (item);
}
return false;
}
@ -718,13 +714,39 @@ bool AInventory::HandlePickup (AInventory *item)
}
return true;
}
if (Inventory != NULL)
return false;
}
DEFINE_ACTION_FUNCTION(AInventory, HandlePickup)
{
PARAM_SELF_PROLOGUE(AInventory);
PARAM_OBJECT(item, AInventory);
ACTION_RETURN_BOOL(self->HandlePickup(item));
}
bool AInventory::CallHandlePickup(AInventory *item)
{
auto self = this;
while (self != nullptr)
{
return Inventory->HandlePickup (item);
IFVIRTUAL(AActor, HandlePickup)
{
// Without the type cast this picks the 'void *' assignment...
VMValue params[2] = { (DObject*)self, (DObject*)item };
VMReturn ret;
VMFrameStack stack;
int retval;
ret.IntAt(&retval);
stack.Call(func, params, 2, &ret, 1, nullptr);
if (retval) return true;
}
else if (self->HandlePickup(item)) return true;
self = self->Inventory;
}
return false;
}
//===========================================================================
//
// AInventory :: GoAway
@ -1480,7 +1502,7 @@ bool AInventory::TryPickup (AActor *&toucher)
// picked up, then it leaves the flag cleared.
ItemFlags &= ~IF_PICKUPGOOD;
if (toucher->Inventory != NULL && toucher->Inventory->HandlePickup (this))
if (toucher->Inventory != NULL && toucher->Inventory->CallHandlePickup (this))
{
// Let something else the player is holding intercept the pickup.
if (!(ItemFlags & IF_PICKUPGOOD))
@ -1892,10 +1914,6 @@ bool AHealthPickup::HandlePickup (AInventory *item)
{
return Super::HandlePickup (item);
}
if (Inventory != NULL)
{
return Inventory->HandlePickup (item);
}
return false;
}
@ -2044,14 +2062,7 @@ bool ABackpackItem::HandlePickup (AInventory *item)
item->ItemFlags |= IF_PICKUPGOOD;
return true;
}
else if (Inventory != NULL)
{
return Inventory->HandlePickup (item);
}
else
{
return false;
}
return false;
}
//===========================================================================

View file

@ -203,6 +203,7 @@ public:
virtual bool GoAway ();
virtual void GoAwayAndDie ();
virtual bool HandlePickup (AInventory *item);
bool CallHandlePickup(AInventory *item);
virtual bool Use (bool pickup);
bool CallUse(bool pickup);
virtual void Travelled ();

View file

@ -1,3 +1,5 @@
#pragma once
#include "a_pickups.h"
//
class PClassWeaponPiece : public PClassInventory

View file

@ -346,10 +346,6 @@ bool AWeapon::HandlePickup (AInventory *item)
}
return true;
}
if (Inventory != NULL)
{
return Inventory->HandlePickup (item);
}
return false;
}

View file

@ -50,6 +50,7 @@
#include "sbarinfo.h"
#include "gi.h"
#include "r_data/r_translate.h"
#include "a_artifacts.h"
#include "a_weaponpiece.h"
#include "a_strifeglobal.h"
#include "g_level.h"

View file

@ -41,10 +41,6 @@ bool ACoin::HandlePickup (AInventory *item)
}
return true;
}
if (Inventory != NULL)
{
return Inventory->HandlePickup (item);
}
return false;
}

View file

@ -786,10 +786,6 @@ bool ASigil::HandlePickup (AInventory *item)
}
return true;
}
if (Inventory != NULL)
{
return Inventory->HandlePickup (item);
}
return false;
}

View file

@ -41,7 +41,6 @@
#include "c_dispatch.h"
#include "b_bot.h" //Added by MC:
#include "stats.h"
#include "a_hexenglobal.h"
#include "a_sharedglobal.h"
#include "gi.h"
#include "sbar.h"
@ -69,6 +68,7 @@
#include "serializer.h"
#include "r_utility.h"
#include "thingdef.h"
#include "d_player.h"
#include "virtual.h"
// MACROS ------------------------------------------------------------------
@ -7436,6 +7436,15 @@ DEFINE_ACTION_FUNCTION(AActor, SetFriendPlayer)
self->SetFriendPlayer(player);
return 0;
}
DEFINE_ACTION_FUNCTION(AActor, ClearBounce)
{
PARAM_SELF_PROLOGUE(AActor);
self->BounceFlags = 0;
return 0;
}
//----------------------------------------------------------------------------
//
// DropItem handling

View file

@ -57,6 +57,7 @@
#include "m_argv.h"
#include "p_local.h"
#include "doomerrors.h"
#include "a_artifacts.h"
#include "a_weaponpiece.h"
#include "p_conversation.h"
#include "v_text.h"

View file

@ -39,7 +39,7 @@
*/
#include "gi.h"
#include "actor.h"
#include "d_player.h"
#include "info.h"
#include "tarray.h"
#include "w_wad.h"
@ -57,8 +57,7 @@
#include "p_effect.h"
#include "v_palette.h"
#include "doomerrors.h"
#include "a_hexenglobal.h"
#include "a_weaponpiece.h"
#include "a_artifacts.h"
#include "p_conversation.h"
#include "v_text.h"
#include "thingdef.h"
@ -69,6 +68,7 @@
#include "teaminfo.h"
#include "v_video.h"
#include "r_data/colormaps.h"
#include "a_weaponpiece.h"
#include "vmbuilder.h"
extern TArray<PClassActor **> OptionalClassPtrs;
@ -2800,7 +2800,7 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, morphweapon, S, PlayerPawn)
DEFINE_CLASS_PROPERTY_PREFIX(player, flechettetype, S, PlayerPawn)
{
PROP_STRING_PARM(str, 0);
defaults->FlechetteType = FindClassTentative(str, RUNTIME_CLASS(AArtiPoisonBag));
defaults->FlechetteType = FindClassTentative(str, PClass::FindActor("ArtiPoisonBag"));
}
//==========================================================================

View file

@ -280,6 +280,7 @@ class Actor : Thinker native
native int PlayerNumber();
native void SetFriendPlayer(PlayerInfo player);
native void NoiseAlert(Actor emitter, bool splash = false, double maxdist = 0);
native void ClearBounce();
native void RestoreDamage();
native int SpawnHealth();