mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-24 13:01:47 +00:00
- scriptified TakeInventory, including the ACS/FS interfaces.
This commit is contained in:
parent
e7d309cb96
commit
588ddd185b
7 changed files with 123 additions and 149 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -993,6 +993,7 @@ xx(ScriptUtil)
|
|||
xx(SetMarineWeapon)
|
||||
xx(SetMarineSprite)
|
||||
xx(GiveInventory)
|
||||
xx(TakeInventory)
|
||||
|
||||
// Weapon member fields that need direct access
|
||||
xx(Ammo1)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
|
Loading…
Reference in a new issue