mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-12-01 16:41:22 +00:00
9521b6cd1f
Unlike the other classes, the places where variables from this class were accessed were quite scattered so there isn't much scriptified code. Instead, most of these places are now using the script variable access methods. This was the last remaining subclass of AActor, meaning that class Actor can now be opened for user-side extensions.
359 lines
No EOL
8.3 KiB
Text
359 lines
No EOL
8.3 KiB
Text
|
|
struct AutoUseHealthInfo play
|
|
{
|
|
Array<Inventory> collectedItems[2];
|
|
int collectedHealth[2];
|
|
|
|
void AddItemToList(Inventory item, int list)
|
|
{
|
|
collectedItems[list].Push(item);
|
|
collectedHealth[list] += Item.Amount * Item.health;
|
|
}
|
|
|
|
int UseHealthItems(int list, in out int saveHealth)
|
|
{
|
|
int saved = 0;
|
|
|
|
while (collectedItems[list].Size() > 0 && saveHealth > 0)
|
|
{
|
|
int maxhealth = 0;
|
|
int index = -1;
|
|
|
|
// Find the largest item in the list
|
|
for(int i = 0; i < collectedItems[list].Size(); i++)
|
|
{
|
|
// Workaround for a deficiency in the expression resolver.
|
|
let item = list == 0? collectedItems[0][i] : collectedItems[1][i];
|
|
if (Item.health > maxhealth)
|
|
{
|
|
index = i;
|
|
maxhealth = Item.health;
|
|
}
|
|
}
|
|
|
|
// Now apply the health items, using the same logic as Heretic and Hexen.
|
|
int count = (saveHealth + maxhealth-1) / maxhealth;
|
|
for(int i = 0; i < count; i++)
|
|
{
|
|
saved += maxhealth;
|
|
saveHealth -= maxhealth;
|
|
let item = list == 0? collectedItems[0][index] : collectedItems[1][index];
|
|
if (--item.Amount == 0)
|
|
{
|
|
item.DepleteOrDestroy ();
|
|
collectedItems[list].Delete(index);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return saved;
|
|
}
|
|
|
|
}
|
|
|
|
extend class PlayerPawn
|
|
{
|
|
|
|
//===========================================================================
|
|
//
|
|
//
|
|
//
|
|
//===========================================================================
|
|
|
|
ui void InvNext()
|
|
{
|
|
Inventory next;
|
|
|
|
let old = InvSel;
|
|
if (InvSel != NULL)
|
|
{
|
|
if ((next = InvSel.NextInv()) != NULL)
|
|
{
|
|
InvSel = next;
|
|
}
|
|
else
|
|
{
|
|
// Select the first item in the inventory
|
|
InvSel = FirstInv();
|
|
}
|
|
if (InvSel) InvSel.DisplayNameTag();
|
|
}
|
|
player.inventorytics = 5*TICRATE;
|
|
if (old != InvSel)
|
|
{
|
|
A_PlaySound("misc/invchange", CHAN_AUTO, 1.0, false, ATTN_NONE);
|
|
}
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// PlayerPawn :: InvPrev
|
|
//
|
|
//===========================================================================
|
|
|
|
ui void InvPrev()
|
|
{
|
|
Inventory item, newitem;
|
|
|
|
let old = InvSel;
|
|
if (InvSel != NULL)
|
|
{
|
|
if ((item = InvSel.PrevInv()) != NULL)
|
|
{
|
|
InvSel = item;
|
|
}
|
|
else
|
|
{
|
|
// Select the last item in the inventory
|
|
item = InvSel;
|
|
while ((newitem = item.NextInv()) != NULL)
|
|
{
|
|
item = newitem;
|
|
}
|
|
InvSel = item;
|
|
}
|
|
if (InvSel) InvSel.DisplayNameTag();
|
|
}
|
|
player.inventorytics = 5*TICRATE;
|
|
if (old != InvSel)
|
|
{
|
|
A_PlaySound("misc/invchange", CHAN_AUTO, 1.0, false, ATTN_NONE);
|
|
}
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// PlayerPawn :: AddInventory
|
|
//
|
|
//===========================================================================
|
|
|
|
override void AddInventory (Inventory item)
|
|
{
|
|
// Adding inventory to a voodoo doll should add it to the real player instead.
|
|
if (player != NULL && player.mo != self && player.mo != NULL)
|
|
{
|
|
player.mo.AddInventory (item);
|
|
return;
|
|
}
|
|
Super.AddInventory (item);
|
|
|
|
// If nothing is selected, select this item.
|
|
if (InvSel == NULL && item.bInvBar)
|
|
{
|
|
InvSel = item;
|
|
}
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// PlayerPawn :: RemoveInventory
|
|
//
|
|
//===========================================================================
|
|
|
|
override void RemoveInventory (Inventory item)
|
|
{
|
|
bool pickWeap = false;
|
|
|
|
// Since voodoo dolls aren't supposed to have an inventory, there should be
|
|
// no need to redirect them to the real player here as there is with AddInventory.
|
|
|
|
// If the item removed is the selected one, select something else, either the next
|
|
// item, if there is one, or the previous item.
|
|
if (player != NULL)
|
|
{
|
|
if (InvSel == item)
|
|
{
|
|
InvSel = item.NextInv ();
|
|
if (InvSel == NULL)
|
|
{
|
|
InvSel = item.PrevInv ();
|
|
}
|
|
}
|
|
if (InvFirst == item)
|
|
{
|
|
InvFirst = item.NextInv ();
|
|
if (InvFirst == NULL)
|
|
{
|
|
InvFirst = item.PrevInv ();
|
|
}
|
|
}
|
|
if (item == player.PendingWeapon)
|
|
{
|
|
player.PendingWeapon = WP_NOCHANGE;
|
|
}
|
|
if (item == player.ReadyWeapon)
|
|
{
|
|
// If the current weapon is removed, clear the refire counter and pick a new one.
|
|
pickWeap = true;
|
|
player.ReadyWeapon = NULL;
|
|
player.refire = 0;
|
|
}
|
|
}
|
|
Super.RemoveInventory (item);
|
|
if (pickWeap && player.mo == self && player.PendingWeapon == WP_NOCHANGE)
|
|
{
|
|
PickNewWeapon (NULL);
|
|
}
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// PlayerPawn :: 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;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// PROC P_AutoUseHealth
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
void AutoUseHealth(int saveHealth)
|
|
{
|
|
AutoUseHealthInfo collector;
|
|
|
|
for(Inventory inv = self.Inv; inv != NULL; inv = inv.Inv)
|
|
{
|
|
let hp = HealthPickup(inv);
|
|
if (hp && hp.Amount > 0)
|
|
{
|
|
int mode = hp.autousemode;
|
|
if (mode == 1 || mode == 2) collector.AddItemToList(inv, mode-1);
|
|
}
|
|
}
|
|
|
|
bool skilluse = !!G_SkillPropertyInt(SKILLP_AutoUseHealth);
|
|
|
|
if (skilluse && collector.collectedHealth[0] >= saveHealth)
|
|
{
|
|
// Use quartz flasks
|
|
player.health += collector.UseHealthItems(0, saveHealth);
|
|
}
|
|
else if (collector.collectedHealth[1] >= saveHealth)
|
|
{
|
|
// Use mystic urns
|
|
player.health += collector.UseHealthItems(1, saveHealth);
|
|
}
|
|
else if (skilluse && collector.collectedHealth[0] + collector.collectedHealth[1] >= saveHealth)
|
|
{
|
|
// Use mystic urns and quartz flasks
|
|
player.health += collector.UseHealthItems(0, saveHealth);
|
|
if (saveHealth > 0) player.health += collector.UseHealthItems(1, saveHealth);
|
|
}
|
|
health = player.health;
|
|
}
|
|
|
|
//============================================================================
|
|
//
|
|
// P_AutoUseStrifeHealth
|
|
//
|
|
//============================================================================
|
|
|
|
void AutoUseStrifeHealth ()
|
|
{
|
|
Array<Inventory> Items;
|
|
|
|
for(Inventory inv = self.Inv; inv != NULL; inv = inv.Inv)
|
|
{
|
|
let hp = HealthPickup(inv);
|
|
if (hp && hp.Amount > 0)
|
|
{
|
|
if (hp.autousemode == 3) Items.Push(inv);
|
|
}
|
|
}
|
|
|
|
if (!sv_disableautohealth)
|
|
{
|
|
while (Items.Size() > 0)
|
|
{
|
|
int maxhealth = 0;
|
|
int index = -1;
|
|
|
|
// Find the largest item in the list
|
|
for(int i = 0; i < Items.Size(); i++)
|
|
{
|
|
if (Items[i].health > maxhealth)
|
|
{
|
|
index = i;
|
|
maxhealth = Items[i].Amount;
|
|
}
|
|
}
|
|
|
|
while (player.health < 50)
|
|
{
|
|
let item = Items[index];
|
|
if (item == null || !UseInventory (item))
|
|
break;
|
|
}
|
|
if (player.health >= 50) return;
|
|
// Using all of this item was not enough so delete it and restart with the next best one
|
|
Items.Delete(index);
|
|
}
|
|
}
|
|
}
|
|
|
|
//============================================================================
|
|
//
|
|
// Helper for 'useflechette' CCMD.
|
|
//
|
|
//============================================================================
|
|
|
|
protected virtual Inventory GetFlechetteItem()
|
|
{
|
|
// Select from one of arti_poisonbag1-3, whichever the player has
|
|
static const Class<Inventory> bagtypes[] = {
|
|
"ArtiPoisonBag3", // use type 3 first because that's the default when the player has none specified.
|
|
"ArtiPoisonBag1",
|
|
"ArtiPoisonBag2"
|
|
};
|
|
|
|
if (FlechetteType != NULL)
|
|
{
|
|
let item = FindInventory(FlechetteType);
|
|
if (item != null)
|
|
{
|
|
return item;
|
|
}
|
|
}
|
|
|
|
// 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)
|
|
{
|
|
let item = FindInventory(bagtypes[j]);
|
|
if (item != null)
|
|
{
|
|
return item;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
} |