mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-10 23:01:50 +00:00
- scriptified the AutoUseHealth feature.
This again is a piece of code that reads and even writes to inventory items' properties, so better have it on the script side.
This commit is contained in:
parent
3182569fb8
commit
2e383073e8
2 changed files with 150 additions and 115 deletions
|
@ -757,89 +757,14 @@ void AActor::CallDie(AActor *source, AActor *inflictor, int dmgflags, FName Mean
|
|||
// PROC P_AutoUseHealth
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
static int CountHealth(TArray<AInventory *> &Items)
|
||||
{
|
||||
int counted = 0;
|
||||
for(unsigned i = 0; i < Items.Size(); i++)
|
||||
{
|
||||
counted += Items[i]->Amount * Items[i]->health;
|
||||
}
|
||||
return counted;
|
||||
}
|
||||
|
||||
static int UseHealthItems(TArray<AInventory *> &Items, int &saveHealth)
|
||||
{
|
||||
int saved = 0;
|
||||
|
||||
while (Items.Size() > 0 && saveHealth > 0)
|
||||
{
|
||||
int maxhealth = 0;
|
||||
int index = -1;
|
||||
|
||||
// Find the largest item in the list
|
||||
for(unsigned i = 0; i < Items.Size(); i++)
|
||||
{
|
||||
if (Items[i]->health > maxhealth)
|
||||
{
|
||||
index = i;
|
||||
maxhealth = Items[i]->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;
|
||||
if (--Items[index]->Amount == 0)
|
||||
{
|
||||
DepleteOrDestroy (Items[index]);
|
||||
Items.Delete(index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return saved;
|
||||
}
|
||||
|
||||
void P_AutoUseHealth(player_t *player, int saveHealth)
|
||||
{
|
||||
TArray<AInventory *> NormalHealthItems;
|
||||
TArray<AInventory *> LargeHealthItems;
|
||||
|
||||
auto hptype = PClass::FindActor(NAME_HealthPickup);
|
||||
for(AInventory *inv = player->mo->Inventory; inv != NULL; inv = inv->Inventory)
|
||||
IFVM(PlayerPawn, AutoUseHealth)
|
||||
{
|
||||
if (inv->Amount > 0 && inv->IsKindOf(hptype))
|
||||
{
|
||||
int mode = inv->IntVar(NAME_autousemode);
|
||||
|
||||
if (mode == 1) NormalHealthItems.Push(inv);
|
||||
else if (mode == 2) LargeHealthItems.Push(inv);
|
||||
}
|
||||
VMValue params[] = { player->mo, saveHealth };
|
||||
VMCall(func, params, 2, nullptr, 0);
|
||||
}
|
||||
|
||||
int normalhealth = CountHealth(NormalHealthItems);
|
||||
int largehealth = CountHealth(LargeHealthItems);
|
||||
|
||||
bool skilluse = !!G_SkillProperty(SKILLP_AutoUseHealth);
|
||||
|
||||
if (skilluse && normalhealth >= saveHealth)
|
||||
{ // Use quartz flasks
|
||||
player->health += UseHealthItems(NormalHealthItems, saveHealth);
|
||||
}
|
||||
else if (largehealth >= saveHealth)
|
||||
{
|
||||
// Use mystic urns
|
||||
player->health += UseHealthItems(LargeHealthItems, saveHealth);
|
||||
}
|
||||
else if (skilluse && normalhealth + largehealth >= saveHealth)
|
||||
{ // Use mystic urns and quartz flasks
|
||||
player->health += UseHealthItems(NormalHealthItems, saveHealth);
|
||||
if (saveHealth > 0) player->health += UseHealthItems(LargeHealthItems, saveHealth);
|
||||
}
|
||||
player->mo->health = player->health;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
@ -851,44 +776,10 @@ CVAR(Bool, sv_disableautohealth, false, CVAR_ARCHIVE|CVAR_SERVERINFO)
|
|||
|
||||
void P_AutoUseStrifeHealth (player_t *player)
|
||||
{
|
||||
TArray<AInventory *> Items;
|
||||
|
||||
auto hptype = PClass::FindActor(NAME_HealthPickup);
|
||||
for(AInventory *inv = player->mo->Inventory; inv != NULL; inv = inv->Inventory)
|
||||
IFVM(PlayerPawn, AutoUseStrifeHealth)
|
||||
{
|
||||
if (inv->Amount > 0 && inv->IsKindOf(hptype))
|
||||
{
|
||||
int mode = inv->IntVar(NAME_autousemode);
|
||||
if (mode == 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(unsigned i = 0; i < Items.Size(); i++)
|
||||
{
|
||||
if (Items[i]->health > maxhealth)
|
||||
{
|
||||
index = i;
|
||||
maxhealth = Items[i]->Amount;
|
||||
}
|
||||
}
|
||||
|
||||
while (player->health < 50)
|
||||
{
|
||||
if (!player->mo->UseInventory (Items[index]))
|
||||
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);
|
||||
}
|
||||
VMValue params[] = { player->mo };
|
||||
VMCall(func, params, 1, nullptr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,56 @@
|
|||
|
||||
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
|
||||
{
|
||||
|
||||
|
@ -176,4 +229,95 @@ extend class PlayerPawn
|
|||
}
|
||||
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)
|
||||
{
|
||||
if (!UseInventory (Items[index]))
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
Reference in a new issue