mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-24 13:01:47 +00:00
- scriptified UseInventory and several functions using the already scriptified ones,
This commit is contained in:
parent
588ddd185b
commit
09129e0113
14 changed files with 384 additions and 436 deletions
|
@ -746,15 +746,8 @@ public:
|
|||
// APlayerPawn for some specific handling for players. None of this
|
||||
// should ever be overridden by custom classes.
|
||||
|
||||
// Take the amount value of an item from the inventory list.
|
||||
// If nothing is left, the item may be destroyed.
|
||||
// Returns true if the initial item count is positive.
|
||||
virtual bool TakeInventory (PClassActor *itemclass, int amount, bool fromdecorate = false, bool notakeinfinite = false);
|
||||
|
||||
bool SetInventory(PClassActor *itemclass, int amount, bool beyondMax);
|
||||
|
||||
// Uses an item and removes it from the inventory.
|
||||
virtual bool UseInventory (AInventory *item);
|
||||
bool UseInventory (AInventory *item);
|
||||
|
||||
// Tosses an item out of the inventory.
|
||||
AInventory *DropInventory (AInventory *item, int amt = -1);
|
||||
|
|
|
@ -89,7 +89,6 @@ public:
|
|||
|
||||
virtual void PostBeginPlay() override;
|
||||
virtual void Tick() override;
|
||||
virtual bool UseInventory (AInventory *item) override;
|
||||
virtual void BeginPlay () override;
|
||||
virtual bool UpdateWaterLevel (bool splash) override;
|
||||
|
||||
|
|
|
@ -424,7 +424,6 @@ public:
|
|||
void CallDraw(EHudState state, double ticFrac);
|
||||
void DrawBottomStuff (EHudState state);
|
||||
void DrawTopStuff (EHudState state);
|
||||
void FlashItem (const PClass *itemtype);
|
||||
void AttachToPlayer(player_t *player);
|
||||
DVector2 GetHUDScale() const;
|
||||
virtual void FlashCrosshair ();
|
||||
|
|
|
@ -1190,15 +1190,6 @@ void DBaseStatusBar::DrawWaiting () const
|
|||
}
|
||||
}
|
||||
|
||||
void DBaseStatusBar::FlashItem (const PClass *itemtype)
|
||||
{
|
||||
IFVIRTUAL(DBaseStatusBar, FlashItem)
|
||||
{
|
||||
VMValue params[] = { (DObject*)this, (PClass*)itemtype };
|
||||
VMCall(func, params, countof(params), nullptr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void DBaseStatusBar::NewGame ()
|
||||
{
|
||||
IFVIRTUAL(DBaseStatusBar, NewGame)
|
||||
|
@ -1232,7 +1223,7 @@ void DBaseStatusBar::ScreenSizeChanged ()
|
|||
|
||||
for (size_t i = 0; i < countof(Messages); ++i)
|
||||
{
|
||||
DHUDMessageBase *message = Messages[i];
|
||||
DHUDMessageBase *message = Messages[i];
|
||||
while (message != NULL)
|
||||
{
|
||||
message->CallScreenSizeChanged ();
|
||||
|
|
|
@ -549,25 +549,11 @@ FString cht_Morph(player_t *player, PClassActor *morphclass, bool quickundo)
|
|||
|
||||
void cht_SetInv(player_t *player, const char *string, int amount, bool beyond)
|
||||
{
|
||||
if (!stricmp(string, "health"))
|
||||
IFVIRTUALPTR(player->mo, APlayerPawn, CheatSetInv)
|
||||
{
|
||||
if (amount <= 0)
|
||||
{
|
||||
cht_Suicide(player);
|
||||
return;
|
||||
}
|
||||
if (!beyond) amount = MIN(amount, player->mo->GetMaxHealth(true));
|
||||
player->health = player->mo->health = amount;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto item = PClass::FindActor(string);
|
||||
if (item != nullptr && item->IsDescendantOf(RUNTIME_CLASS(AInventory)))
|
||||
{
|
||||
player->mo->SetInventory(item, amount, beyond);
|
||||
return;
|
||||
}
|
||||
Printf("Unknown item \"%s\"\n", string);
|
||||
FString message = string;
|
||||
VMValue params[] = { player->mo, &message, amount, beyond };
|
||||
VMCall(func, params, 4, nullptr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1588,238 +1588,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_CustomRailgun)
|
|||
return 0;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// DoGiveInventory
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
static bool DoGiveInventory(AActor *receiver, bool orresult, VM_ARGS)
|
||||
{
|
||||
int paramnum = 0;
|
||||
PARAM_CLASS (mi, AInventory);
|
||||
PARAM_INT (amount)
|
||||
|
||||
if (!orresult)
|
||||
{
|
||||
PARAM_INT(setreceiver)
|
||||
receiver = COPY_AAPTR(receiver, setreceiver);
|
||||
}
|
||||
if (receiver == NULL)
|
||||
{ // If there's nothing to receive it, it's obviously a fail, right?
|
||||
return false;
|
||||
}
|
||||
// Owned inventory items cannot own anything because their Inventory pointer is repurposed for the owner's linked list.
|
||||
if (receiver->IsKindOf(RUNTIME_CLASS(AInventory)) && static_cast<AInventory*>(receiver)->Owner != nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (amount <= 0)
|
||||
{
|
||||
amount = 1;
|
||||
}
|
||||
if (mi)
|
||||
{
|
||||
AInventory *item = static_cast<AInventory *>(Spawn(mi));
|
||||
if (item == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (item->IsKindOf(NAME_Health))
|
||||
{
|
||||
item->Amount *= amount;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->Amount = amount;
|
||||
}
|
||||
item->flags |= MF_DROPPED;
|
||||
item->ClearCounters();
|
||||
if (!item->CallTryPickup(receiver))
|
||||
{
|
||||
item->Destroy();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_GiveInventory)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
ACTION_RETURN_BOOL(DoGiveInventory(self, false, VM_ARGS_NAMES));
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_GiveToTarget)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
ACTION_RETURN_BOOL(DoGiveInventory(self->target, false, VM_ARGS_NAMES));
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_GiveToChildren)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
TThinkerIterator<AActor> it;
|
||||
AActor *mo;
|
||||
int count = 0;
|
||||
|
||||
while ((mo = it.Next()))
|
||||
{
|
||||
if (mo->master == self)
|
||||
{
|
||||
count += DoGiveInventory(mo, true, VM_ARGS_NAMES);
|
||||
}
|
||||
}
|
||||
ACTION_RETURN_INT(count);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_GiveToSiblings)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
TThinkerIterator<AActor> it;
|
||||
AActor *mo;
|
||||
int count = 0;
|
||||
|
||||
if (self->master != NULL)
|
||||
{
|
||||
while ((mo = it.Next()))
|
||||
{
|
||||
if (mo->master == self->master && mo != self)
|
||||
{
|
||||
count += DoGiveInventory(mo, true, VM_ARGS_NAMES);
|
||||
}
|
||||
}
|
||||
}
|
||||
ACTION_RETURN_INT(count);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_SetInventory
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_SetInventory)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_CLASS(itemtype, AInventory);
|
||||
PARAM_INT(amount);
|
||||
PARAM_INT(ptr);
|
||||
PARAM_BOOL(beyondMax);
|
||||
|
||||
bool res = false;
|
||||
|
||||
if (itemtype == nullptr)
|
||||
{
|
||||
ACTION_RETURN_BOOL(false);
|
||||
}
|
||||
|
||||
AActor *mobj = COPY_AAPTR(self, ptr);
|
||||
|
||||
if (mobj == nullptr)
|
||||
{
|
||||
ACTION_RETURN_BOOL(false);
|
||||
}
|
||||
|
||||
// Do not run this function on voodoo dolls because the way they transfer the inventory to the player will not work with the code below.
|
||||
if (mobj->player != nullptr)
|
||||
{
|
||||
mobj = mobj->player->mo;
|
||||
}
|
||||
ACTION_RETURN_BOOL(mobj->SetInventory(itemtype, amount, beyondMax));
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_TakeInventory
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
enum
|
||||
{
|
||||
TIF_NOTAKEINFINITE = 1,
|
||||
};
|
||||
|
||||
bool DoTakeInventory(AActor *receiver, bool orresult, VM_ARGS)
|
||||
{
|
||||
int paramnum = 0;
|
||||
PARAM_CLASS (itemtype, AInventory);
|
||||
PARAM_INT (amount);
|
||||
PARAM_INT (flags);
|
||||
|
||||
if (itemtype == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!orresult)
|
||||
{
|
||||
PARAM_INT(setreceiver);
|
||||
receiver = COPY_AAPTR(receiver, setreceiver);
|
||||
}
|
||||
if (receiver == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return receiver->TakeInventory(itemtype, amount, true, (flags & TIF_NOTAKEINFINITE) != 0);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_TakeInventory)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
ACTION_RETURN_BOOL(DoTakeInventory(self, false, VM_ARGS_NAMES));
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_TakeFromTarget)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
ACTION_RETURN_BOOL(DoTakeInventory(self->target, false, VM_ARGS_NAMES));
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_TakeFromChildren)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
TThinkerIterator<AActor> it;
|
||||
AActor *mo;
|
||||
int count = 0;
|
||||
|
||||
while ((mo = it.Next()))
|
||||
{
|
||||
if (mo->master == self)
|
||||
{
|
||||
count += DoTakeInventory(mo, true, VM_ARGS_NAMES);
|
||||
}
|
||||
}
|
||||
ACTION_RETURN_INT(count);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_TakeFromSiblings)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
TThinkerIterator<AActor> it;
|
||||
AActor *mo;
|
||||
int count = 0;
|
||||
|
||||
if (self->master != NULL)
|
||||
{
|
||||
while ((mo = it.Next()))
|
||||
{
|
||||
if (mo->master == self->master && mo != self)
|
||||
{
|
||||
count += DoTakeInventory(mo, true, VM_ARGS_NAMES);
|
||||
}
|
||||
}
|
||||
}
|
||||
ACTION_RETURN_INT(count);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_Recoil
|
||||
|
|
|
@ -641,7 +641,11 @@ static void TakeStrifeItem (player_t *player, PClassActor *itemtype, int amount)
|
|||
if (itemtype->TypeName == NAME_Sigil)
|
||||
return;
|
||||
|
||||
player->mo->TakeInventory(itemtype, amount);
|
||||
IFVM(Actor, TakeInventory)
|
||||
{
|
||||
VMValue params[] = { player->mo, itemtype, amount, false, false };
|
||||
VMCall(func, params, 5, nullptr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
CUSTOM_CVAR(Float, dlg_musicvolume, 1.0f, CVAR_ARCHIVE)
|
||||
|
|
120
src/p_mobj.cpp
120
src/p_mobj.cpp
|
@ -753,91 +753,6 @@ DEFINE_ACTION_FUNCTION(AActor, SetState)
|
|||
ACTION_RETURN_BOOL(self->SetState(state, nofunction));
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// AActor :: TakeInventory
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
bool AActor::TakeInventory(PClassActor *itemclass, int amount, bool fromdecorate, bool notakeinfinite)
|
||||
{
|
||||
IFVM(Actor, TakeInventory)
|
||||
{
|
||||
VMValue params[] = { this, itemclass, amount, fromdecorate, notakeinfinite };
|
||||
int retval = 0;
|
||||
VMReturn ret(&retval);
|
||||
VMCall(func, params, 5, &ret, 1);
|
||||
return !!retval;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool AActor::SetInventory(PClassActor *itemtype, int amount, bool beyondMax)
|
||||
{
|
||||
AInventory *item = FindInventory(itemtype);
|
||||
|
||||
if (item != nullptr)
|
||||
{
|
||||
// A_SetInventory sets the absolute amount.
|
||||
// Subtract or set the appropriate amount as necessary.
|
||||
|
||||
if (amount == item->Amount)
|
||||
{
|
||||
// Nothing was changed.
|
||||
return false;
|
||||
}
|
||||
else if (amount <= 0)
|
||||
{
|
||||
//Remove it all.
|
||||
return TakeInventory(itemtype, item->Amount, true, false);
|
||||
}
|
||||
else if (amount < item->Amount)
|
||||
{
|
||||
int amt = abs(item->Amount - amount);
|
||||
return TakeInventory(itemtype, amt, true, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
item->Amount = (beyondMax ? amount : clamp(amount, 0, item->MaxAmount));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (amount <= 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
item = static_cast<AInventory *>(Spawn(itemtype));
|
||||
if (item == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->Amount = amount;
|
||||
item->flags |= MF_DROPPED;
|
||||
item->ItemFlags |= IF_IGNORESKILL;
|
||||
item->ClearCounters();
|
||||
if (!item->CallTryPickup(this))
|
||||
{
|
||||
item->Destroy();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, SetInventory)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_CLASS_NOT_NULL(item, AInventory);
|
||||
PARAM_INT(amount);
|
||||
PARAM_BOOL(beyondMax);
|
||||
ACTION_RETURN_BOOL(self->SetInventory(item, amount, beyondMax));
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
|
@ -919,41 +834,14 @@ DEFINE_ACTION_FUNCTION(AActor, FirstInv)
|
|||
|
||||
bool AActor::UseInventory (AInventory *item)
|
||||
{
|
||||
// No using items if you're dead.
|
||||
if (health <= 0)
|
||||
IFVIRTUAL(AActor, UseInventory)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Don't use it if you don't actually have any of it.
|
||||
if (item->Amount <= 0 || (item->ObjectFlags & OF_EuthanizeMe))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
IFVIRTUALPTR(item, AInventory, Use)
|
||||
{
|
||||
VMValue params[2] = { item, false };
|
||||
int retval;
|
||||
VMValue params[] = { this, item };
|
||||
int retval = 0;
|
||||
VMReturn ret(&retval);
|
||||
VMCall(func, params, 2, &ret, 1);
|
||||
if (!retval) return false;
|
||||
return !!retval;
|
||||
}
|
||||
|
||||
if (dmflags2 & DF2_INFINITE_INVENTORY)
|
||||
return true;
|
||||
|
||||
if (--item->Amount <= 0)
|
||||
{
|
||||
item->DepleteOrDestroy ();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, UseInventory)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
PARAM_OBJECT_NOT_NULL(item, AInventory);
|
||||
ACTION_RETURN_BOOL(self->UseInventory(item));
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
|
|
@ -938,40 +938,6 @@ void APlayerPawn::PostBeginPlay()
|
|||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// APlayerPawn :: UseInventory
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
bool APlayerPawn::UseInventory (AInventory *item)
|
||||
{
|
||||
const PClass *itemtype = item->GetClass();
|
||||
|
||||
if (player->cheats & CF_TOTALLYFROZEN)
|
||||
{ // You can't use items if you're totally frozen
|
||||
return false;
|
||||
}
|
||||
if ((level.flags2 & LEVEL2_FROZEN) && (player == NULL || player->timefreezer == 0))
|
||||
{
|
||||
// Time frozen
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Super::UseInventory (item))
|
||||
{
|
||||
// Heretic and Hexen advance the inventory cursor if the use failed.
|
||||
// Should this behavior be retained?
|
||||
return false;
|
||||
}
|
||||
if (player == &players[consoleplayer])
|
||||
{
|
||||
S_Sound (this, CHAN_ITEM, item->UseSound, 1, ATTN_NORM);
|
||||
StatusBar->FlashItem (itemtype);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// APlayerPawn :: PickNewWeapon
|
||||
|
|
|
@ -743,11 +743,9 @@ class Actor : Thinker native
|
|||
native bool CheckClass(class<Actor> 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 bool SetInventory(class<Inventory> itemclass, int amount, bool beyondMax = 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);
|
||||
native bool UseInventory(Inventory item);
|
||||
native void ObtainInventory(Actor other);
|
||||
native bool GiveAmmo (Class<Ammo> type, int amount);
|
||||
native bool UsePuzzleItem(int PuzzleItemType);
|
||||
|
@ -1013,9 +1011,6 @@ class Actor : Thinker native
|
|||
native action state A_Jump(int chance, statelabel label, ...);
|
||||
native Actor A_SpawnProjectile(class<Actor> missiletype, double spawnheight = 32, double spawnofs_xy = 0, double angle = 0, int flags = 0, double pitch = 0, int ptr = AAPTR_TARGET);
|
||||
native void A_CustomRailgun(int damage, int spawnofs_xy = 0, color color1 = 0, color color2 = 0, int flags = 0, int aim = 0, double maxdiff = 0, class<Actor> pufftype = "BulletPuff", double spread_xy = 0, double spread_z = 0, double range = 0, int duration = 0, double sparsity = 1.0, double driftspeed = 1.0, class<Actor> spawnclass = null, double spawnofs_z = 0, int spiraloffset = 270, int limit = 0, double veleffect = 3);
|
||||
native bool A_SetInventory(class<Inventory> itemtype, int amount, int ptr = AAPTR_DEFAULT, bool beyondMax = false);
|
||||
native bool A_GiveInventory(class<Inventory> itemtype, int amount = 0, int giveto = AAPTR_DEFAULT);
|
||||
native bool A_TakeInventory(class<Inventory> itemtype, int amount = 0, int flags = 0, int giveto = AAPTR_DEFAULT);
|
||||
native void A_Print(string whattoprint, double time = 0, name fontname = "none");
|
||||
native void A_PrintBold(string whattoprint, double time = 0, name fontname = "none");
|
||||
native void A_Log(string whattoprint, bool local = false);
|
||||
|
@ -1049,8 +1044,6 @@ class Actor : Thinker native
|
|||
native void A_LookEx(int flags = 0, double minseedist = 0, double maxseedist = 0, double maxheardist = 0, double fov = 0, statelabel label = null);
|
||||
|
||||
native void A_Recoil(double xyvel);
|
||||
native bool A_GiveToTarget(class<Inventory> itemtype, int amount = 0, int forward_ptr = AAPTR_DEFAULT);
|
||||
native bool A_TakeFromTarget(class<Inventory> itemtype, int amount = 0, int flags = 0, int forward_ptr = AAPTR_DEFAULT);
|
||||
native int A_RadiusGive(class<Inventory> itemtype, double distance, int flags, int amount = 0, class<Actor> filter = null, name species = "None", double mindist = 0, int limit = 0);
|
||||
native void A_CustomMeleeAttack(int damage = 0, sound meleesound = "", sound misssound = "", name damagetype = "none", bool bleed = true);
|
||||
native void A_CustomComboAttack(class<Actor> missiletype, double spawnheight, int damage, sound meleesound = "", name damagetype = "none", bool bleed = true);
|
||||
|
@ -1097,10 +1090,6 @@ class Actor : Thinker native
|
|||
native void A_RemoveChildren(bool removeall = false, int flags = 0, class<Actor> filter = null, name species = "None");
|
||||
native void A_RemoveSiblings(bool removeall = false, int flags = 0, class<Actor> filter = null, name species = "None");
|
||||
native void A_Remove(int removee, int flags = 0, class<Actor> filter = null, name species = "None");
|
||||
native int A_GiveToChildren(class<Inventory> itemtype, int amount = 0);
|
||||
native int A_GiveToSiblings(class<Inventory> itemtype, int amount = 0);
|
||||
native int A_TakeFromChildren(class<Inventory> itemtype, int amount = 0);
|
||||
native int A_TakeFromSiblings(class<Inventory> itemtype, int amount = 0);
|
||||
native void A_SetTeleFog(class<Actor> oldpos, class<Actor> newpos);
|
||||
native void A_SwapTeleFog();
|
||||
native void A_SetHealth(int health, int ptr = AAPTR_DEFAULT);
|
||||
|
|
|
@ -159,4 +159,311 @@ extend class Actor
|
|||
}
|
||||
|
||||
|
||||
}
|
||||
//============================================================================
|
||||
//
|
||||
// AActor :: SetInventory
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
bool SetInventory(class<Inventory> itemclass, int amount, bool beyondMax = false)
|
||||
{
|
||||
let item = FindInventory(itemclass);
|
||||
|
||||
if (item != null)
|
||||
{
|
||||
// A_SetInventory sets the absolute amount.
|
||||
// Subtract or set the appropriate amount as necessary.
|
||||
|
||||
if (amount == item.Amount)
|
||||
{
|
||||
// Nothing was changed.
|
||||
return false;
|
||||
}
|
||||
else if (amount <= 0)
|
||||
{
|
||||
//Remove it all.
|
||||
return TakeInventory(itemclass, item.Amount, true, false);
|
||||
}
|
||||
else if (amount < item.Amount)
|
||||
{
|
||||
int amt = abs(item.Amount - amount);
|
||||
return TakeInventory(itemclass, amt, true, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
item.Amount = (beyondMax ? amount : clamp(amount, 0, item.MaxAmount));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (amount <= 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
item = Inventory(Spawn(itemclass));
|
||||
if (item == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
item.Amount = amount;
|
||||
item.bDropped = true;
|
||||
item.bIgnoreSkill = true;
|
||||
item.ClearCounters();
|
||||
if (!item.CallTryPickup(self))
|
||||
{
|
||||
item.Destroy();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// AActor :: UseInventory
|
||||
//
|
||||
// Attempts to use an item. If the use succeeds, one copy of the item is
|
||||
// removed from the inventory. If all copies are removed, then the item is
|
||||
// destroyed.
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
virtual bool UseInventory (Inventory item)
|
||||
{
|
||||
// No using items if you're dead or you don't have them.
|
||||
if (health <= 0 || item.Amount <= 0 || item.bDestroyed)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!item.Use(false))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sv_infiniteinventory)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (--item.Amount <= 0)
|
||||
{
|
||||
item.DepleteOrDestroy ();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// DoGiveInventory
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
static bool DoGiveInventory(Actor receiver, bool orresult, class<Inventory> mi, int amount, int setreceiver)
|
||||
{
|
||||
int paramnum = 0;
|
||||
|
||||
if (!orresult)
|
||||
{
|
||||
receiver = receiver.GetPointer(setreceiver);
|
||||
}
|
||||
if (receiver == NULL)
|
||||
{ // If there's nothing to receive it, it's obviously a fail, right?
|
||||
return false;
|
||||
}
|
||||
// Owned inventory items cannot own anything because their Inventory pointer is repurposed for the owner's linked list.
|
||||
if (receiver is 'Inventory' && Inventory(receiver).Owner != null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (amount <= 0)
|
||||
{
|
||||
amount = 1;
|
||||
}
|
||||
if (mi)
|
||||
{
|
||||
let item = Inventory(Spawn(mi));
|
||||
if (item == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (item is 'Health')
|
||||
{
|
||||
item.Amount *= amount;
|
||||
}
|
||||
else
|
||||
{
|
||||
item.Amount = amount;
|
||||
}
|
||||
item.bDropped = true;
|
||||
item.ClearCounters();
|
||||
if (!item.CallTryPickup(receiver))
|
||||
{
|
||||
item.Destroy();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool A_GiveInventory(class<Inventory> itemtype, int amount = 0, int giveto = AAPTR_DEFAULT)
|
||||
{
|
||||
return DoGiveInventory(self, false, itemtype, amount, giveto);
|
||||
}
|
||||
|
||||
bool A_GiveToTarget(class<Inventory> itemtype, int amount = 0, int giveto = AAPTR_DEFAULT)
|
||||
{
|
||||
return DoGiveInventory(target, false, itemtype, amount, giveto);
|
||||
}
|
||||
|
||||
int A_GiveToChildren(class<Inventory> itemtype, int amount = 0)
|
||||
{
|
||||
let it = ThinkerIterator.Create('Actor');
|
||||
Actor mo;
|
||||
int count = 0;
|
||||
|
||||
while ((mo = Actor(it.Next())))
|
||||
{
|
||||
if (mo.master == self)
|
||||
{
|
||||
count += DoGiveInventory(mo, true, itemtype, amount, AAPTR_DEFAULT);
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int A_GiveToSiblings(class<Inventory> itemtype, int amount = 0)
|
||||
{
|
||||
let it = ThinkerIterator.Create('Actor');
|
||||
Actor mo;
|
||||
int count = 0;
|
||||
|
||||
if (self.master != NULL)
|
||||
{
|
||||
while ((mo = Actor(it.Next())))
|
||||
{
|
||||
if (mo.master == self.master && mo != self)
|
||||
{
|
||||
count += DoGiveInventory(mo, true, itemtype, amount, AAPTR_DEFAULT);
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_TakeInventory
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
bool DoTakeInventory(Actor receiver, bool orresult, class<Inventory> itemtype, int amount, int flags, int setreceiver = AAPTR_DEFAULT)
|
||||
{
|
||||
int paramnum = 0;
|
||||
|
||||
if (itemtype == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!orresult)
|
||||
{
|
||||
receiver = receiver.GetPointer(setreceiver);
|
||||
}
|
||||
if (receiver == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return receiver.TakeInventory(itemtype, amount, true, (flags & TIF_NOTAKEINFINITE) != 0);
|
||||
}
|
||||
|
||||
bool A_TakeInventory(class<Inventory> itemtype, int amount = 0, int flags = 0, int giveto = AAPTR_DEFAULT)
|
||||
{
|
||||
return DoTakeInventory(self, false, itemtype, amount, flags, giveto);
|
||||
}
|
||||
|
||||
bool A_TakeFromTarget(class<Inventory> itemtype, int amount = 0, int flags = 0, int giveto = AAPTR_DEFAULT)
|
||||
{
|
||||
return DoTakeInventory(target, false, itemtype, amount, flags, giveto);
|
||||
}
|
||||
|
||||
int A_TakeFromChildren(class<Inventory> itemtype, int amount = 0)
|
||||
{
|
||||
let it = ThinkerIterator.Create('Actor');
|
||||
Actor mo;
|
||||
int count = 0;
|
||||
|
||||
while ((mo = Actor(it.Next())))
|
||||
{
|
||||
if (mo.master == self)
|
||||
{
|
||||
count += DoTakeInventory(mo, true, itemtype, amount, 0, AAPTR_DEFAULT);
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int A_TakeFromSiblings(class<Inventory> itemtype, int amount = 0)
|
||||
{
|
||||
let it = ThinkerIterator.Create('Actor');
|
||||
Actor mo;
|
||||
int count = 0;
|
||||
|
||||
if (self.master != NULL)
|
||||
{
|
||||
while ((mo = Actor(it.Next())))
|
||||
{
|
||||
if (mo.master == self.master && mo != self)
|
||||
{
|
||||
count += DoTakeInventory(mo, true, itemtype, amount, 0, AAPTR_DEFAULT);
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_SetInventory
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
bool A_SetInventory(class<Inventory> itemtype, int amount, int ptr = AAPTR_DEFAULT, bool beyondMax = false)
|
||||
{
|
||||
bool res = false;
|
||||
|
||||
if (itemtype == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Actor mobj = GetPointer(ptr);
|
||||
|
||||
if (mobj == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Do not run this function on voodoo dolls because the way they transfer the inventory to the player will not work with the code below.
|
||||
if (mobj.player != null)
|
||||
{
|
||||
mobj = mobj.player.mo;
|
||||
}
|
||||
return mobj.SetInventory(itemtype, amount, beyondMax);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -399,6 +399,31 @@ extend class PlayerPawn
|
|||
}
|
||||
return;
|
||||
}
|
||||
|
||||
virtual void CheatSetInv(String strng, int amount, bool beyond)
|
||||
{
|
||||
if (!(strng ~== "health"))
|
||||
{
|
||||
if (amount <= 0)
|
||||
{
|
||||
CheatSuicide();
|
||||
return;
|
||||
}
|
||||
if (!beyond) amount = MIN(amount, player.mo.GetMaxHealth(true));
|
||||
player.health = player.mo.health = amount;
|
||||
}
|
||||
else
|
||||
{
|
||||
class<Inventory> item = strng;
|
||||
if (item != null)
|
||||
{
|
||||
player.mo.SetInventory(item, amount, beyond);
|
||||
return;
|
||||
}
|
||||
Console.Printf("Unknown item \"%s\"\n", strng);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
virtual String CheatMorph(class<PlayerPawn> morphClass, bool quickundo)
|
||||
{
|
||||
|
|
|
@ -75,4 +75,37 @@ extend class PlayerPawn
|
|||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// APlayerPawn :: UseInventory
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
override bool UseInventory (Inventory item)
|
||||
{
|
||||
let itemtype = item.GetClass();
|
||||
|
||||
if (player.cheats & CF_TOTALLYFROZEN)
|
||||
{ // You can't use items if you're totally frozen
|
||||
return false;
|
||||
}
|
||||
if ((level.FROZEN) && (player == NULL || player.timefreezer == 0))
|
||||
{
|
||||
// Time frozen
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Super.UseInventory (item))
|
||||
{
|
||||
// Heretic and Hexen advance the inventory cursor if the use failed.
|
||||
// Should this behavior be retained?
|
||||
return false;
|
||||
}
|
||||
if (player == players[consoleplayer])
|
||||
{
|
||||
A_PlaySound(item.UseSound, CHAN_ITEM);
|
||||
StatusBar.FlashItem (itemtype); // Fixme: This shouldn't be called from here, because it is in the UI.
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -297,8 +297,8 @@ class BaseStatusBar native ui
|
|||
native PlayerInfo CPlayer;
|
||||
native bool ShowLog;
|
||||
native Vector2 defaultScale; // factor for fully scaled fullscreen display.
|
||||
native int artiflashTick;
|
||||
native double itemflashFade;
|
||||
clearscope native int artiflashTick;
|
||||
clearscope native double itemflashFade;
|
||||
|
||||
// These are block properties for the drawers. A child class can set them to have a block of items use the same settings.
|
||||
native double Alpha;
|
||||
|
@ -331,7 +331,7 @@ class BaseStatusBar native ui
|
|||
native virtual clearscope void ReceivedWeapon (Weapon weapn);
|
||||
native virtual clearscope void SetMugShotState (String state_name, bool wait_till_done=false, bool reset=false);
|
||||
|
||||
virtual void FlashItem (class<Inventory> itemtype) { artiflashTick = 4; itemflashFade = 0.75; }
|
||||
clearscope virtual void FlashItem (class<Inventory> itemtype) { artiflashTick = 4; itemflashFade = 0.75; }
|
||||
virtual void AttachToPlayer (PlayerInfo player) { CPlayer = player; UpdateScreenGeometry(); }
|
||||
virtual void FlashCrosshair () { CrosshairSize = XHAIRPICKUPSIZE; }
|
||||
virtual void NewGame () { if (CPlayer != null) AttachToPlayer(CPlayer); }
|
||||
|
|
Loading…
Reference in a new issue