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:
Use = 0x00000800, // object can be used
HealingItem = 0x04000000, // sfall healing drug flag
HiddenItem = 0x08000000 // item is hidden
};
+21 -26
View File
@@ -18,32 +18,14 @@ namespace game
namespace sf = sfall;
static const long aiUseItemAPCost = 2;
// 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 result = fo::func::ai_can_use_weapon(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;
void __stdcall CombatAI::ai_check_drugs(fo::GameObject* source) {
@@ -95,8 +77,8 @@ void __stdcall CombatAI::ai_check_drugs(fo::GameObject* source) {
break;
}
if (CheckHealingItems(itemFind) && !fo::func::item_remove_mult(source, itemFind, 1)) {
if (!UseItemDrugFunc(source, itemFind)) {
if (game::Items::IsHealingItem(itemFind) && !fo::func::item_remove_mult(source, itemFind, 1)) {
if (!game::Items::UseDrugItemFunc(source, itemFind)) {
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 (counter < 3) {
// if the item is NOT a healing drug
if (!CheckHealingItems(item) && !fo::func::item_remove_mult(source, item, 1)) {
if (!UseItemDrugFunc(source, item)) {
if (!game::Items::IsHealingItem(item) && !fo::func::item_remove_mult(source, item, 1)) {
if (!game::Items::UseDrugItemFunc(source, item)) {
drugWasUsed = true;
usedCount++;
}
@@ -179,7 +161,7 @@ void __stdcall CombatAI::ai_check_drugs(fo::GameObject* source) {
// [FIX] Prevent the use of healing drugs when not necessary
// 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);
if (10 + source->critter.health >= maxHP) { // quick check current HP
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 (!UseItemDrugFunc(source, lastItem)) lastItem = nullptr;
if (!game::Items::UseDrugItemFunc(source, lastItem)) lastItem = nullptr;
if (source->critter.movePoints < aiUseItemAPCost) {
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() {
// Replace ai_check_drugs_ function
sf::MakeJump(fo::funcoffs::ai_check_drugs_, ai_check_drugs_hack); // 0x428480
drugUsePerfFixMode = sf::IniReader::GetConfigInt("Misc", "AIDrugUsePerfFix", 0);
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 "..\FalloutEngine\Fallout2.h"
@@ -22,6 +24,34 @@ namespace sf = sfall;
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
long Items::item_d_take_drug(fo::GameObject* source, fo::GameObject* item) {
if (sf::UseObjOnHook_Invoke(source, item, source) == -1) return -1;
+7
View File
@@ -13,6 +13,13 @@ class Items {
public:
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
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 {
call fo::funcoffs::stat_level_; // current hp
mov edx, dword ptr [esp + 0x34 - 0x1C + 4]; // ai cap
@@ -169,7 +169,7 @@ dontUse:
xor eax, eax;
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
static void __declspec(naked) ai_check_drugs_hack_break() {
@@ -2082,7 +2082,7 @@ skip:
add esp, 4;
jmp ai_check_drugs_hack_Loop; // goto begin loop, search next item
}
}
}*/
static void __declspec(naked) cai_cap_save_hook() {
__asm {