- scriptified UseInventory and several functions using the already scriptified ones,

This commit is contained in:
Christoph Oelckers 2018-12-01 17:17:08 +01:00
parent 588ddd185b
commit 09129e0113
14 changed files with 384 additions and 436 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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