Relocated some functions in the previous commit

Added an additional 'Healing Item' flag to ext flags for item protos.

* indicates the item is a healing drug when AI needs to heal itself.
This commit is contained in:
NovaRain
2021-08-18 12:03:58 +08:00
parent e55db2b4da
commit 94dd41f7ac
6 changed files with 63 additions and 30 deletions
+1
View File
@@ -139,6 +139,7 @@ enum ItemFlags : long
// Action Flags: // Action Flags:
Use = 0x00000800, // object can be used Use = 0x00000800, // object can be used
HealingItem = 0x04000000, // sfall healing drug flag
HiddenItem = 0x08000000 // item is hidden HiddenItem = 0x08000000 // item is hidden
}; };
+21 -26
View File
@@ -18,32 +18,14 @@ namespace game
namespace sf = sfall; namespace sf = sfall;
static const long aiUseItemAPCost = 2;
// Implementation of ai_can_use_weapon_ engine function with the HOOK_CANUSEWEAPON hook // Implementation of ai_can_use_weapon_ engine function with the HOOK_CANUSEWEAPON hook
bool CombatAI::ai_can_use_weapon(fo::GameObject* source, fo::GameObject* weapon, long hitMode) { bool CombatAI::ai_can_use_weapon(fo::GameObject* source, fo::GameObject* weapon, long hitMode) {
bool result = fo::func::ai_can_use_weapon(source, weapon, hitMode); bool result = fo::func::ai_can_use_weapon(source, weapon, hitMode);
return sf::CanUseWeaponHook_Invoke(result, source, weapon, hitMode); return sf::CanUseWeaponHook_Invoke(result, source, weapon, hitMode);
} }
static const long aiUseItemAPCost = 2;
static std::vector<long> healingItemPids = {fo::PID_STIMPAK, fo::PID_SUPER_STIMPAK, fo::PID_HEALING_POWDER};
static bool CheckHealingItems(fo::GameObject* item) {
return (std::find(healingItemPids.cbegin(), healingItemPids.cend(), item->protoId) != healingItemPids.cend());
}
// True - use failed
static bool UseItemDrugFunc(fo::GameObject* source, fo::GameObject* item) {
bool result = (game::Items::item_d_take_drug(source, item) == -1);
if (result) {
fo::func::item_add_force(source, item, 1);
} else {
fo::func::ai_magic_hands(source, item, 5000);
fo::func::obj_connect(item, source->tile, source->elevation, 0);
fo::func::obj_destroy(item);
}
return result;
}
static long drugUsePerfFixMode; static long drugUsePerfFixMode;
void __stdcall CombatAI::ai_check_drugs(fo::GameObject* source) { void __stdcall CombatAI::ai_check_drugs(fo::GameObject* source) {
@@ -95,8 +77,8 @@ void __stdcall CombatAI::ai_check_drugs(fo::GameObject* source) {
break; break;
} }
if (CheckHealingItems(itemFind) && !fo::func::item_remove_mult(source, itemFind, 1)) { if (game::Items::IsHealingItem(itemFind) && !fo::func::item_remove_mult(source, itemFind, 1)) {
if (!UseItemDrugFunc(source, itemFind)) { if (!game::Items::UseDrugItemFunc(source, itemFind)) {
drugWasUsed = true; drugWasUsed = true;
} }
@@ -146,8 +128,8 @@ void __stdcall CombatAI::ai_check_drugs(fo::GameObject* source) {
// if the preference counter is less than 3, then AI can use the drug // if the preference counter is less than 3, then AI can use the drug
if (counter < 3) { if (counter < 3) {
// if the item is NOT a healing drug // if the item is NOT a healing drug
if (!CheckHealingItems(item) && !fo::func::item_remove_mult(source, item, 1)) { if (!game::Items::IsHealingItem(item) && !fo::func::item_remove_mult(source, item, 1)) {
if (!UseItemDrugFunc(source, item)) { if (!game::Items::UseDrugItemFunc(source, item)) {
drugWasUsed = true; drugWasUsed = true;
usedCount++; usedCount++;
} }
@@ -179,7 +161,7 @@ void __stdcall CombatAI::ai_check_drugs(fo::GameObject* source) {
// [FIX] Prevent the use of healing drugs when not necessary // [FIX] Prevent the use of healing drugs when not necessary
// noInvenDrug: is set to 2 that healing is required // noInvenDrug: is set to 2 that healing is required
if (lastItem && noInvenDrug != 2 && CheckHealingItems(lastItem)) { if (lastItem && noInvenDrug != 2 && game::Items::IsHealingItem(lastItem)) {
long maxHP = fo::func::stat_level(source, fo::Stat::STAT_max_hit_points); long maxHP = fo::func::stat_level(source, fo::Stat::STAT_max_hit_points);
if (10 + source->critter.health >= maxHP) { // quick check current HP if (10 + source->critter.health >= maxHP) { // quick check current HP
return; // exit: don't use healing item return; // exit: don't use healing item
@@ -187,7 +169,7 @@ void __stdcall CombatAI::ai_check_drugs(fo::GameObject* source) {
} }
if (lastItem && !fo::func::item_remove_mult(source, lastItem, 1)) { if (lastItem && !fo::func::item_remove_mult(source, lastItem, 1)) {
if (!UseItemDrugFunc(source, lastItem)) lastItem = nullptr; if (!game::Items::UseDrugItemFunc(source, lastItem)) lastItem = nullptr;
if (source->critter.movePoints < aiUseItemAPCost) { if (source->critter.movePoints < aiUseItemAPCost) {
source->critter.movePoints = 0; source->critter.movePoints = 0;
@@ -199,7 +181,20 @@ void __stdcall CombatAI::ai_check_drugs(fo::GameObject* source) {
} }
} }
static void __declspec(naked) ai_check_drugs_hack() {
__asm {
push ecx;
push eax; // source
call CombatAI::ai_check_drugs;
pop ecx;
retn;
}
}
void CombatAI::init() { void CombatAI::init() {
// Replace ai_check_drugs_ function
sf::MakeJump(fo::funcoffs::ai_check_drugs_, ai_check_drugs_hack); // 0x428480
drugUsePerfFixMode = sf::IniReader::GetConfigInt("Misc", "AIDrugUsePerfFix", 0); drugUsePerfFixMode = sf::IniReader::GetConfigInt("Misc", "AIDrugUsePerfFix", 0);
if (drugUsePerfFixMode > 0) sf::dlogr("Applying AI drug use preference fix.", DL_FIX); if (drugUsePerfFixMode > 0) sf::dlogr("Applying AI drug use preference fix.", DL_FIX);
} }
+30
View File
@@ -4,6 +4,8 @@
* *
*/ */
#include <array>
#include "..\main.h" #include "..\main.h"
#include "..\FalloutEngine\Fallout2.h" #include "..\FalloutEngine\Fallout2.h"
@@ -22,6 +24,34 @@ namespace sf = sfall;
static constexpr int reloadCostAP = 2; // engine default reload AP cost static constexpr int reloadCostAP = 2; // engine default reload AP cost
static std::array<long, 3> healingItemPids = {fo::PID_STIMPAK, fo::PID_SUPER_STIMPAK, fo::PID_HEALING_POWDER};
void Items::SetHealingPID(long index, long pid) {
/*if (index >= 0 && index < 3)*/ healingItemPids[index] = pid;
}
bool Items::IsHealingItem(fo::GameObject* item) {
if (std::find(healingItemPids.cbegin(), healingItemPids.cend(), item->protoId) != healingItemPids.cend()) return true;
fo::Proto* proto;
if (fo::GetProto(item->protoId, &proto)) {
return ((proto->item.flagsExt & fo::ItemFlags::HealingItem) != 0); // TODO: check asm code
}
return false;
}
bool Items::UseDrugItemFunc(fo::GameObject* source, fo::GameObject* item) {
bool result = (game::Items::item_d_take_drug(source, item) == -1);
if (result) {
fo::func::item_add_force(source, item, 1);
} else {
fo::func::ai_magic_hands(source, item, 5000);
fo::func::obj_connect(item, source->tile, source->elevation, 0);
fo::func::obj_destroy(item);
}
return result;
}
// Implementation of item_d_take_ engine function with the HOOK_USEOBJON hook // Implementation of item_d_take_ engine function with the HOOK_USEOBJON hook
long Items::item_d_take_drug(fo::GameObject* source, fo::GameObject* item) { long Items::item_d_take_drug(fo::GameObject* source, fo::GameObject* item) {
if (sf::UseObjOnHook_Invoke(source, item, source) == -1) return -1; if (sf::UseObjOnHook_Invoke(source, item, source) == -1) return -1;
+7
View File
@@ -13,6 +13,13 @@ class Items {
public: public:
static void init(); static void init();
static void SetHealingPID(long index, long pid);
static bool IsHealingItem(fo::GameObject* item);
// True - use failed
static bool UseDrugItemFunc(fo::GameObject* source, fo::GameObject* item);
// Implementation of item_d_take_ engine function with the HOOK_USEOBJON hook // Implementation of item_d_take_ engine function with the HOOK_USEOBJON hook
static long item_d_take_drug(fo::GameObject* source, fo::GameObject* item); static long item_d_take_drug(fo::GameObject* source, fo::GameObject* item);
+2 -2
View File
@@ -123,7 +123,7 @@ tryHeal:
} }
} }
static void __declspec(naked) ai_check_drugs_hook() { /*static void __declspec(naked) ai_check_drugs_hook() {
__asm { __asm {
call fo::funcoffs::stat_level_; // current hp call fo::funcoffs::stat_level_; // current hp
mov edx, dword ptr [esp + 0x34 - 0x1C + 4]; // ai cap mov edx, dword ptr [esp + 0x34 - 0x1C + 4]; // ai cap
@@ -169,7 +169,7 @@ dontUse:
xor eax, eax; xor eax, eax;
retn; retn;
} }
} }*/
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
+2 -2
View File
@@ -2033,7 +2033,7 @@ skip:
} }
} }
static DWORD firstItemDrug = -1; /*static DWORD firstItemDrug = -1;
// when there are no more items in the inventory // when there are no more items in the inventory
static void __declspec(naked) ai_check_drugs_hack_break() { static void __declspec(naked) ai_check_drugs_hack_break() {
@@ -2082,7 +2082,7 @@ skip:
add esp, 4; add esp, 4;
jmp ai_check_drugs_hack_Loop; // goto begin loop, search next item jmp ai_check_drugs_hack_Loop; // goto begin loop, search next item
} }
} }*/
static void __declspec(naked) cai_cap_save_hook() { static void __declspec(naked) cai_cap_save_hook() {
__asm { __asm {