mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
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:
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user