mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Fixed AI not checking min HP properly for using stims.
Edited the code of InventoryApCost in Inventory.cpp. Minor edits to some other code.
This commit is contained in:
@@ -72,6 +72,17 @@ tryHeal:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __declspec(naked) ai_check_drugs_hook() {
|
||||||
|
__asm {
|
||||||
|
call stat_level_; // current hp
|
||||||
|
mov edx, dword ptr [esp + 0x34 - 0x1C + 4]; // ai cap
|
||||||
|
mov edx, [edx + 0x10]; // min_hp
|
||||||
|
cmp eax, edx; // curr_hp < cap.min_hp
|
||||||
|
cmovl edi, edx;
|
||||||
|
retn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static DWORD RetryCombatLastAP;
|
static DWORD RetryCombatLastAP;
|
||||||
@@ -190,6 +201,9 @@ void AIInit() {
|
|||||||
|
|
||||||
// Fix to allow fleeing NPC to use drugs
|
// Fix to allow fleeing NPC to use drugs
|
||||||
MakeCall(0x42B1DC, combat_ai_hack);
|
MakeCall(0x42B1DC, combat_ai_hack);
|
||||||
|
// Fix for AI not checking minimum hp properly for using stimpaks (prevents premature fleeing)
|
||||||
|
HookCall(0x428579, ai_check_drugs_hook);
|
||||||
|
|
||||||
// Fix for NPC stuck in fleeing mode when the hit chance of a target was too low
|
// Fix for NPC stuck in fleeing mode when the hit chance of a target was too low
|
||||||
HookCall(0x42B1E3, combat_ai_hook_FleeFix);
|
HookCall(0x42B1E3, combat_ai_hook_FleeFix);
|
||||||
HookCall(0x42ABA8, ai_try_attack_hook_FleeFix);
|
HookCall(0x42ABA8, ai_try_attack_hook_FleeFix);
|
||||||
|
|||||||
+7
-7
@@ -791,19 +791,19 @@ static void __declspec(naked) PipStatus_AddHotLines_hook() {
|
|||||||
|
|
||||||
static void __declspec(naked) perform_withdrawal_start_display_print_hook() {
|
static void __declspec(naked) perform_withdrawal_start_display_print_hook() {
|
||||||
__asm {
|
__asm {
|
||||||
test eax, eax
|
test eax, eax;
|
||||||
jz end
|
jz end;
|
||||||
jmp display_print_
|
jmp display_print_;
|
||||||
end:
|
end:
|
||||||
retn
|
retn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __declspec(naked) op_wield_obj_critter_adjust_ac_hook() {
|
static void __declspec(naked) op_wield_obj_critter_adjust_ac_hook() {
|
||||||
__asm {
|
__asm {
|
||||||
call adjust_ac_
|
call adjust_ac_;
|
||||||
xor eax, eax // not animated
|
xor eax, eax; // not animated
|
||||||
jmp intface_update_ac_
|
jmp intface_update_ac_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -33,10 +33,10 @@ static void _stdcall ConsoleFilePrint(const char* msg) {
|
|||||||
static const DWORD ConsoleHookRet = 0x431871;
|
static const DWORD ConsoleHookRet = 0x431871;
|
||||||
static void __declspec(naked) ConsoleHook() {
|
static void __declspec(naked) ConsoleHook() {
|
||||||
__asm {
|
__asm {
|
||||||
pushad;
|
pushadc;
|
||||||
push eax;
|
push eax;
|
||||||
call ConsoleFilePrint;
|
call ConsoleFilePrint;
|
||||||
popad;
|
popadc;
|
||||||
push ebx;
|
push ebx;
|
||||||
push ecx;
|
push ecx;
|
||||||
push edx;
|
push edx;
|
||||||
|
|||||||
@@ -337,6 +337,8 @@ enum AttackType : long
|
|||||||
ATKTYPE_PIERCINGKICK = 19
|
ATKTYPE_PIERCINGKICK = 19
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define PLAYER_ID (18000)
|
||||||
|
|
||||||
#define OBJFLAG_CAN_WEAR_ITEMS (0xF000000)
|
#define OBJFLAG_CAN_WEAR_ITEMS (0xF000000)
|
||||||
|
|
||||||
#define OBJFLAG_HELD_IN_RIGHT (0x10000)
|
#define OBJFLAG_HELD_IN_RIGHT (0x10000)
|
||||||
|
|||||||
+62
-64
@@ -29,9 +29,9 @@
|
|||||||
|
|
||||||
static DWORD sizeLimitMode;
|
static DWORD sizeLimitMode;
|
||||||
static DWORD invSizeMaxLimit;
|
static DWORD invSizeMaxLimit;
|
||||||
static DWORD ReloadWeaponKey = 0;
|
static DWORD reloadWeaponKey = 0;
|
||||||
static DWORD ItemFastMoveKey = 0;
|
static DWORD itemFastMoveKey = 0;
|
||||||
static DWORD SkipFromContainer = 0;
|
static DWORD skipFromContainer = 0;
|
||||||
|
|
||||||
struct sMessage {
|
struct sMessage {
|
||||||
DWORD number;
|
DWORD number;
|
||||||
@@ -59,7 +59,7 @@ TGameObj* GetActiveItem() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void InventoryKeyPressedHook(DWORD dxKey, bool pressed, DWORD vKey) {
|
void InventoryKeyPressedHook(DWORD dxKey, bool pressed, DWORD vKey) {
|
||||||
if (pressed && ReloadWeaponKey && dxKey == ReloadWeaponKey && IsMapLoaded() && (GetCurrentLoops() & ~(COMBAT | PCOMBAT)) == 0) {
|
if (pressed && reloadWeaponKey && dxKey == reloadWeaponKey && IsMapLoaded() && (GetCurrentLoops() & ~(COMBAT | PCOMBAT)) == 0) {
|
||||||
DWORD maxAmmo, curAmmo;
|
DWORD maxAmmo, curAmmo;
|
||||||
TGameObj* item = GetActiveItem();
|
TGameObj* item = GetActiveItem();
|
||||||
__asm {
|
__asm {
|
||||||
@@ -91,6 +91,7 @@ void InventoryKeyPressedHook(DWORD dxKey, bool pressed, DWORD vKey) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
DWORD __stdcall sf_item_total_size(TGameObj* critter) {
|
DWORD __stdcall sf_item_total_size(TGameObj* critter) {
|
||||||
int totalSize;
|
int totalSize;
|
||||||
__asm {
|
__asm {
|
||||||
@@ -118,20 +119,6 @@ DWORD __stdcall sf_item_total_size(TGameObj* critter) {
|
|||||||
return totalSize;
|
return totalSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*static const DWORD ObjPickupFail=0x49B70D;
|
|
||||||
static const DWORD ObjPickupEnd=0x49B6F8;
|
|
||||||
static const DWORD size_limit;
|
|
||||||
static __declspec(naked) void ObjPickupHook() {
|
|
||||||
__asm {
|
|
||||||
cmp edi, ds:[_obj_dude];
|
|
||||||
jnz end;
|
|
||||||
end:
|
|
||||||
lea edx, [esp+0x10];
|
|
||||||
mov eax, ecx;
|
|
||||||
jmp ObjPickupEnd;
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
static int __stdcall CritterGetMaxSize(TGameObj* critter) {
|
static int __stdcall CritterGetMaxSize(TGameObj* critter) {
|
||||||
if (critter == *ptr_obj_dude) return invSizeMaxLimit;
|
if (critter == *ptr_obj_dude) return invSizeMaxLimit;
|
||||||
|
|
||||||
@@ -232,8 +219,8 @@ static __declspec(naked) void barter_attempt_transaction_hack_pc() {
|
|||||||
/* cmp eax, edx */
|
/* cmp eax, edx */
|
||||||
jg fail; // if there's no available weight
|
jg fail; // if there's no available weight
|
||||||
//------
|
//------
|
||||||
mov ecx, edi; // source (pc)
|
mov ecx, edi; // source (pc)
|
||||||
mov edx, ebp; // npc table
|
mov edx, ebp; // npc table
|
||||||
call BarterAttemptTransaction;
|
call BarterAttemptTransaction;
|
||||||
test eax, eax;
|
test eax, eax;
|
||||||
jz fail;
|
jz fail;
|
||||||
@@ -372,51 +359,33 @@ static void __declspec(naked) gdControlUpdateInfo_hack() {
|
|||||||
/////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static char SuperStimMsg[128];
|
static char SuperStimMsg[128];
|
||||||
static int __fastcall SuperStimFix2(TGameObj* item, TGameObj* target) {
|
static int __fastcall SuperStimFix(TGameObj* item, TGameObj* target) {
|
||||||
if (item->pid != PID_SUPER_STIMPAK || !target || (target->pid & 0xFF000000) != (OBJ_TYPE_CRITTER << 24)) { // 0x01000000
|
if (item->pid != PID_SUPER_STIMPAK || !target || (target->pid & 0xFF000000) != (OBJ_TYPE_CRITTER << 24)) { // 0x01000000
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
long curr_hp, max_hp;
|
long curr_hp = StatLevel(target, STAT_current_hp);
|
||||||
curr_hp = StatLevel(target, STAT_current_hp);
|
long max_hp = StatLevel(target, STAT_max_hit_points);
|
||||||
max_hp = StatLevel(target, STAT_max_hit_points);
|
|
||||||
if (curr_hp < max_hp) return 0;
|
if (curr_hp < max_hp) return 0;
|
||||||
|
|
||||||
DisplayConsoleMessage(SuperStimMsg);
|
DisplayConsoleMessage(SuperStimMsg);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const DWORD UseItemHookRet = 0x49C5F4;
|
static const DWORD protinst_use_item_on_Ret = 0x49C5F4;
|
||||||
static void __declspec(naked) SuperStimFix() {
|
static void __declspec(naked) protinst_use_item_on_hack() {
|
||||||
__asm {
|
__asm {
|
||||||
push ecx;
|
push ecx;
|
||||||
mov ecx, ebx; // ecx - item
|
mov ecx, ebx; // ecx - item
|
||||||
call SuperStimFix2; // edx - target
|
call SuperStimFix; // edx - target
|
||||||
pop ecx;
|
pop ecx;
|
||||||
test eax, eax;
|
test eax, eax;
|
||||||
jnz end;
|
jnz end;
|
||||||
mov ebp, -1; // overwritten engine code
|
mov ebp, -1; // overwritten engine code
|
||||||
retn;
|
retn;
|
||||||
end:
|
end:
|
||||||
add esp, 4; // destroy ret
|
add esp, 4; // destroy ret
|
||||||
jmp UseItemHookRet; // exit
|
jmp protinst_use_item_on_Ret; // exit
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int invenApCost, invenApCostDef;
|
|
||||||
static char invenApQPReduction;
|
|
||||||
void _stdcall SetInvenApCost(int cost) {
|
|
||||||
invenApCost = cost;
|
|
||||||
}
|
|
||||||
static const DWORD inven_ap_cost_hack_ret = 0x46E816;
|
|
||||||
static void __declspec(naked) inven_ap_cost_hack() {
|
|
||||||
_asm {
|
|
||||||
movzx ebx, byte ptr invenApQPReduction;
|
|
||||||
mul bl;
|
|
||||||
mov edx, invenApCost;
|
|
||||||
sub edx, eax;
|
|
||||||
mov eax, edx;
|
|
||||||
jmp inven_ap_cost_hack_ret;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -690,10 +659,10 @@ static void __declspec(naked) do_move_timer_hook() {
|
|||||||
pushadc;
|
pushadc;
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyDown(ItemFastMoveKey); // check pressed
|
KeyDown(itemFastMoveKey); // check pressed
|
||||||
|
|
||||||
__asm {
|
__asm {
|
||||||
cmp SkipFromContainer, 0;
|
cmp skipFromContainer, 0;
|
||||||
jz noSkip;
|
jz noSkip;
|
||||||
cmp dword ptr [esp + 0x14 + 16], 0x474A43;
|
cmp dword ptr [esp + 0x14 + 16], 0x474A43;
|
||||||
jnz noSkip;
|
jnz noSkip;
|
||||||
@@ -710,6 +679,37 @@ end:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int invenApCost, invenApCostDef;
|
||||||
|
static char invenApQPReduction;
|
||||||
|
static const DWORD inven_ap_cost_Ret = 0x46E812;
|
||||||
|
static void __declspec(naked) inven_ap_cost_hack() {
|
||||||
|
_asm {
|
||||||
|
mul byte ptr invenApQPReduction;
|
||||||
|
mov edx, invenApCost;
|
||||||
|
jmp inven_ap_cost_Ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool onlyOnceAP = false;
|
||||||
|
inline static void ApplyInvenApCostPatch() {
|
||||||
|
MakeJump(0x46E80B, inven_ap_cost_hack);
|
||||||
|
onlyOnceAP = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _stdcall SetInvenApCost(int cost) {
|
||||||
|
invenApCost = cost;
|
||||||
|
if (!onlyOnceAP) ApplyInvenApCostPatch();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Make GetInvenApCost() function
|
||||||
|
/*long GetInvenApCost() {
|
||||||
|
long plevel = PerkLevel(*ptr_obj_dude, PERK_quick_pockets);
|
||||||
|
return invenApCost - (invenApQPReduction * plevel);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
void InventoryReset() {
|
||||||
|
invenApCost = invenApCostDef;
|
||||||
|
}
|
||||||
|
|
||||||
void InventoryInit() {
|
void InventoryInit() {
|
||||||
sizeLimitMode = GetPrivateProfileInt("Misc", "CritterInvSizeLimitMode", 0, ini);
|
sizeLimitMode = GetPrivateProfileInt("Misc", "CritterInvSizeLimitMode", 0, ini);
|
||||||
@@ -762,13 +762,17 @@ void InventoryInit() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
invenApCost = invenApCostDef = GetPrivateProfileInt("Misc", "InventoryApCost", 4, ini);
|
|
||||||
invenApQPReduction = GetPrivateProfileInt("Misc", "QuickPocketsApCostReduction", 2, ini);
|
|
||||||
MakeJump(0x46E80B, inven_ap_cost_hack);
|
|
||||||
|
|
||||||
if(GetPrivateProfileInt("Misc", "SuperStimExploitFix", 0, ini)) {
|
if(GetPrivateProfileInt("Misc", "SuperStimExploitFix", 0, ini)) {
|
||||||
GetPrivateProfileString("sfall", "SuperStimExploitMsg", "You cannot use a super stim on someone who is not injured!", SuperStimMsg, 128, translationIni);
|
GetPrivateProfileString("sfall", "SuperStimExploitMsg", "You cannot use a super stim on someone who is not injured!", SuperStimMsg, 128, translationIni);
|
||||||
MakeCall(0x49C3D9, SuperStimFix);
|
MakeCall(0x49C3D9, protinst_use_item_on_hack);
|
||||||
|
}
|
||||||
|
|
||||||
|
reloadWeaponKey = GetPrivateProfileInt("Input", "ReloadWeaponKey", 0, ini);
|
||||||
|
|
||||||
|
invenApCost = invenApCostDef = GetPrivateProfileInt("Misc", "InventoryApCost", 4, ini);
|
||||||
|
invenApQPReduction = GetPrivateProfileInt("Misc", "QuickPocketsApCostReduction", 2, ini);
|
||||||
|
if (invenApCostDef != 4 || invenApQPReduction != 2) {
|
||||||
|
ApplyInvenApCostPatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(GetPrivateProfileInt("Misc", "CheckWeaponAmmoCost", 0, ini)) {
|
if(GetPrivateProfileInt("Misc", "CheckWeaponAmmoCost", 0, ini)) {
|
||||||
@@ -778,8 +782,6 @@ void InventoryInit() {
|
|||||||
MakeCall(0x4234B3, compute_spray_hack, 1);
|
MakeCall(0x4234B3, compute_spray_hack, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReloadWeaponKey = GetPrivateProfileInt("Input", "ReloadWeaponKey", 0, ini);
|
|
||||||
|
|
||||||
if (GetPrivateProfileIntA("Misc", "StackEmptyWeapons", 0, ini)) {
|
if (GetPrivateProfileIntA("Misc", "StackEmptyWeapons", 0, ini)) {
|
||||||
MakeCall(0x4736C6, inven_action_cursor_hack);
|
MakeCall(0x4736C6, inven_action_cursor_hack);
|
||||||
HookCall(0x4772AA, item_add_mult_hook);
|
HookCall(0x4772AA, item_add_mult_hook);
|
||||||
@@ -794,11 +796,11 @@ void InventoryInit() {
|
|||||||
SafeWrite8(0x476569, 0x91); // xchg ecx, eax
|
SafeWrite8(0x476569, 0x91); // xchg ecx, eax
|
||||||
};
|
};
|
||||||
|
|
||||||
ItemFastMoveKey = GetPrivateProfileIntA("Input", "ItemFastMoveKey", DIK_LCONTROL, ini);
|
itemFastMoveKey = GetPrivateProfileIntA("Input", "ItemFastMoveKey", DIK_LCONTROL, ini);
|
||||||
if (ItemFastMoveKey > 0) {
|
if (itemFastMoveKey > 0) {
|
||||||
HookCall(0x476897, do_move_timer_hook);
|
HookCall(0x476897, do_move_timer_hook);
|
||||||
// Do not call the 'Move Items' window when taking items from containers or corpses
|
// Do not call the 'Move Items' window when taking items from containers or corpses
|
||||||
SkipFromContainer = GetPrivateProfileIntA("Input", "FastMoveFromContainer", 0, ini);
|
skipFromContainer = GetPrivateProfileIntA("Input", "FastMoveFromContainer", 0, ini);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetPrivateProfileIntA("Misc", "ItemCounterDefaultMax", 0, ini)) {
|
if (GetPrivateProfileIntA("Misc", "ItemCounterDefaultMax", 0, ini)) {
|
||||||
@@ -818,7 +820,3 @@ void InventoryInit() {
|
|||||||
*((DWORD*)_max) = 100;
|
*((DWORD*)_max) = 100;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void InventoryReset() {
|
|
||||||
invenApCost = invenApCostDef;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1224,7 +1224,7 @@ long objUniqueID = UID_START; // saving to sfallgv.sav
|
|||||||
// player ID = 18000, all party members have ID = 18000 + its pid (file number of prototype)
|
// player ID = 18000, all party members have ID = 18000 + its pid (file number of prototype)
|
||||||
long SetObjectUniqueID(TGameObj* obj) {
|
long SetObjectUniqueID(TGameObj* obj) {
|
||||||
long id = obj->ID;
|
long id = obj->ID;
|
||||||
if (id > UID_START || obj == *ptr_obj_dude || (id >= 18000 && id < 83536)) return id; // 65535 maximum possible number of prototypes
|
if (id > UID_START || obj == *ptr_obj_dude || (id >= PLAYER_ID && id < 83536)) return id; // 65535 maximum possible number of prototypes
|
||||||
|
|
||||||
if ((DWORD)objUniqueID >= UID_END) objUniqueID = UID_START;
|
if ((DWORD)objUniqueID >= UID_END) objUniqueID = UID_START;
|
||||||
obj->ID = ++objUniqueID;
|
obj->ID = ++objUniqueID;
|
||||||
|
|||||||
Reference in New Issue
Block a user