- scriptified TakeInventory, including the ACS/FS interfaces.

This commit is contained in:
Christoph Oelckers 2018-12-01 17:11:09 +01:00
parent e7d309cb96
commit 588ddd185b
7 changed files with 123 additions and 149 deletions

View file

@ -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;
}

View file

@ -993,6 +993,7 @@ xx(ScriptUtil)
xx(SetMarineWeapon)
xx(SetMarineSprite)
xx(GiveInventory)
xx(TakeInventory)
// Weapon member fields that need direct access
xx(Ammo1)

View file

@ -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);

View file

@ -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)
{

View file

@ -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<Inventory> itemclass, int amount, bool beyondMax = false);
native bool TakeInventory(class<Inventory> itemclass, int amount, bool fromdecorate = false, bool notakeinfinite = false);
native clearscope Inventory FindInventory(class<Inventory> itemtype, bool subclass = false) const;
native Inventory GiveInventoryType(class<Inventory> itemtype);
native Inventory DropInventory (Inventory item, int amt = -1);

View file

@ -110,4 +110,53 @@ extend class Actor
}
}
//============================================================================
//
// AActor :: TakeInventory
//
//============================================================================
bool TakeInventory(class<Inventory> 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;
}
}

View file

@ -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<Inventory> 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);
}
}
//==========================================================================
//
//