From 2e383073e84f364b8aa157adc1adc0b1f9451623 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 2 Dec 2018 19:45:45 +0100 Subject: [PATCH] - 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. --- src/p_interaction.cpp | 121 +-------------- .../zscript/shared/player_inventory.txt | 144 ++++++++++++++++++ 2 files changed, 150 insertions(+), 115 deletions(-) diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index f36ccd512..d03a6d187 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -757,89 +757,14 @@ void AActor::CallDie(AActor *source, AActor *inflictor, int dmgflags, FName Mean // PROC P_AutoUseHealth // //--------------------------------------------------------------------------- -static int CountHealth(TArray &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 &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 NormalHealthItems; - TArray 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 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); } } diff --git a/wadsrc/static/zscript/shared/player_inventory.txt b/wadsrc/static/zscript/shared/player_inventory.txt index af3e15267..228e2bbf8 100644 --- a/wadsrc/static/zscript/shared/player_inventory.txt +++ b/wadsrc/static/zscript/shared/player_inventory.txt @@ -1,3 +1,56 @@ + +struct AutoUseHealthInfo play +{ + Array 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 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); + } + } + } + + } \ No newline at end of file