mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Improved the implementation of HOOK_INVENWIELD
* it now runs for the player and NPCs when removing equipped items. * added an additional argument. Fixed drop_obj script function not removing the equipped armor properly for the player and party members.
This commit is contained in:
@@ -431,7 +431,7 @@ int ret1 - Override setting (-1 - use engine handler, any other value - prev
|
||||
|
||||
HOOK_INVENWIELD (hs_invenwield.int)
|
||||
|
||||
Runs before wielding or unwielding an armor or a weapon by a critter (except when using inventory by PC).
|
||||
Runs before causing a critter or the player to wield/unwield an armor or a weapon (except when using the inventory by PC).
|
||||
An example usage would be to change critter art depending on armor being used or to dynamically customize weapon animations.
|
||||
NOTE: when replacing a previously wielded armor or weapon, the unwielding hook will not be executed.
|
||||
If you need to rely on this, try checking if armor/weapon is already equipped when wielding hook is executed.
|
||||
@@ -440,5 +440,6 @@ Critter arg1 - critter
|
||||
Obj arg2 - item being wielded or unwielded (weapon/armor)
|
||||
int arg3 - slot (INVEN_TYPE_*)
|
||||
int arg4 - 1 when wielding, 0 when unwielding
|
||||
int arg5 - 1 when removing an equipped item from inventory, 0 otherwise
|
||||
|
||||
int ret1 - overrides hard-coded handler (-1 - use engine handler, any other value - override) - NOT RECOMMENDED
|
||||
|
||||
+34
-4
@@ -3,6 +3,7 @@
|
||||
#include "BugFixes.h"
|
||||
#include "Define.h"
|
||||
#include "FalloutEngine.h"
|
||||
#include "HookScripts.h"
|
||||
#include "LoadGameHook.h"
|
||||
#include "ScriptExtender.h"
|
||||
|
||||
@@ -382,7 +383,7 @@ nextArmor:
|
||||
call inven_worn_;
|
||||
test eax, eax;
|
||||
jz noArmor;
|
||||
and byte ptr [eax + 0x27], 0xFB; // Unset the flag of equipped armor
|
||||
and byte ptr [eax + 0x27], 0xFB; // Unset flag of equipped armor (~Worn >> 24)
|
||||
jmp nextArmor;
|
||||
noArmor:
|
||||
mov eax, esi;
|
||||
@@ -398,7 +399,7 @@ nextArmor:
|
||||
call inven_worn_;
|
||||
test eax, eax;
|
||||
jz end;
|
||||
and byte ptr [eax + 0x27], 0xFB; // Unset flag of equipped armor
|
||||
and byte ptr [eax + 0x27], 0xFB; // Unset flag of equipped armor (~Worn >> 24)
|
||||
jmp nextArmor;
|
||||
end:
|
||||
retn;
|
||||
@@ -420,11 +421,15 @@ skip:
|
||||
jz dudeFix;
|
||||
test eax, eax;
|
||||
jz end;
|
||||
// fix for party member
|
||||
call InvenUnwield_HookMove; // run HOOK_INVENWIELD before moving item
|
||||
push ebx;
|
||||
mov ecx, edx;
|
||||
xor ebx, ebx; // new armor
|
||||
xchg eax, edx; // set: eax - source, edx - removed armor
|
||||
call adjust_ac_; // fix for party member
|
||||
call adjust_ac_;
|
||||
mov edx, ecx;
|
||||
pop ebx;
|
||||
xor eax, eax;
|
||||
end:
|
||||
retn; // must be eax = 0
|
||||
@@ -432,7 +437,7 @@ dudeFix:
|
||||
test eax, eax;
|
||||
jz equipped; // no armor
|
||||
// additionally check flag of equipped armor for dude
|
||||
test byte ptr [eax + 0x27], 0x4;
|
||||
test byte ptr [eax + 0x27], 0x4; // Worn >> 24
|
||||
jnz equipped;
|
||||
xor eax, eax;
|
||||
equipped:
|
||||
@@ -441,6 +446,29 @@ equipped:
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) obj_drop_hook() {
|
||||
__asm {
|
||||
test byte ptr [edx + 0x27], 0x7; // (Worn | Right_Hand | Left_Hand) >> 24
|
||||
jz skipHook;
|
||||
call InvenUnwield_HookDrop; // run HOOK_INVENWIELD before dropping item
|
||||
skipHook:
|
||||
test byte ptr [edx + 0x27], 0x4; // Worn >> 24
|
||||
jnz fixArmorStat;
|
||||
jmp obj_remove_from_inven_;
|
||||
fixArmorStat:
|
||||
call isPartyMember_; // and dude
|
||||
test eax, eax;
|
||||
jz skip;
|
||||
mov eax, ecx;
|
||||
xor ebx, ebx; // new armor
|
||||
call adjust_ac_; // eax - source, edx - removed armor
|
||||
mov edx, esi;
|
||||
skip:
|
||||
mov eax, ecx;
|
||||
jmp obj_remove_from_inven_;
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) partyMemberIncLevels_hook() {
|
||||
__asm {
|
||||
mov ebx, eax; // party member pointer
|
||||
@@ -2422,6 +2450,8 @@ void BugFixesInit()
|
||||
HookCall(0x45C49A, op_move_obj_inven_to_obj_hook);
|
||||
SafeWrite16(0x45C496, 0x9090);
|
||||
SafeWrite8(0x45C4A3, 0x75); // jmp > jnz
|
||||
// Fix for drop_obj function
|
||||
HookCall(0x49B965, obj_drop_hook);
|
||||
dlogr(" Done", DL_INIT);
|
||||
//}
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ DWORD* ptr_inven_scroll_dn_bid = reinterpret_cast<DWORD*>(_inven_scroll_d
|
||||
DWORD* ptr_inven_scroll_up_bid = reinterpret_cast<DWORD*>(_inven_scroll_up_bid);
|
||||
DWORD* ptr_inventry_message_file = reinterpret_cast<DWORD*>(_inventry_message_file);
|
||||
DWORD* ptr_itemButtonItems = reinterpret_cast<DWORD*>(_itemButtonItems);
|
||||
DWORD* ptr_itemCurrentItem = reinterpret_cast<DWORD*>(_itemCurrentItem); // 0 - left, 1 - right
|
||||
long* ptr_itemCurrentItem = reinterpret_cast<long*>(_itemCurrentItem); // 0 - left, 1 - right
|
||||
DWORD* ptr_kb_lock_flags = reinterpret_cast<DWORD*>(_kb_lock_flags);
|
||||
DWORD* ptr_last_buttons = reinterpret_cast<DWORD*>(_last_buttons);
|
||||
DWORD* ptr_last_button_winID = reinterpret_cast<DWORD*>(_last_button_winID);
|
||||
@@ -524,6 +524,7 @@ const DWORD obj_lock_is_jammed_ = 0x49D410;
|
||||
const DWORD obj_new_sid_inst_ = 0x49AAC0;
|
||||
const DWORD obj_outline_object_ = 0x48C2B4;
|
||||
const DWORD obj_pid_new_ = 0x489C9C;
|
||||
const DWORD obj_remove_from_inven_ = 0x49B73C;
|
||||
const DWORD obj_remove_outline_ = 0x48C2F0;
|
||||
const DWORD obj_save_dude_ = 0x48D59C;
|
||||
const DWORD obj_scroll_blocking_at_ = 0x48BB44;
|
||||
|
||||
@@ -341,7 +341,7 @@ extern DWORD* ptr_inven_scroll_dn_bid;
|
||||
extern DWORD* ptr_inven_scroll_up_bid;
|
||||
extern DWORD* ptr_inventry_message_file;
|
||||
extern DWORD* ptr_itemButtonItems;
|
||||
extern DWORD* ptr_itemCurrentItem; // 0 - left, 1 - right
|
||||
extern long* ptr_itemCurrentItem; // 0 - left, 1 - right
|
||||
extern DWORD* ptr_kb_lock_flags;
|
||||
extern DWORD* ptr_last_buttons;
|
||||
extern DWORD* ptr_last_button_winID;
|
||||
@@ -756,6 +756,7 @@ extern const DWORD obj_new_; // int aObj*<eax>, int aPid<ebx>
|
||||
extern const DWORD obj_new_sid_inst_;
|
||||
extern const DWORD obj_outline_object_;
|
||||
extern const DWORD obj_pid_new_;
|
||||
extern const DWORD obj_remove_from_inven_;
|
||||
extern const DWORD obj_remove_outline_;
|
||||
extern const DWORD obj_save_dude_;
|
||||
extern const DWORD obj_scroll_blocking_at_;
|
||||
|
||||
+144
-20
@@ -1254,17 +1254,45 @@ skip:
|
||||
}
|
||||
}
|
||||
|
||||
/* Common InvenWield hook */
|
||||
static bool InvenWieldHook_Script(int flag) {
|
||||
argCount = 4;
|
||||
args[3] = flag; // invenwield flag
|
||||
/* Common InvenWield script hooks */
|
||||
static long __fastcall InvenWieldHook_Script(TGameObj* critter, TGameObj* item, long slot, long isWield, long isRemove) {
|
||||
if (!isWield) {
|
||||
// for the critter, the right slot is always the active slot
|
||||
if (slot == INVEN_TYPE_LEFT_HAND && critter != *ptr_obj_dude) return 1;
|
||||
// check the current active slot for the player
|
||||
if (slot != INVEN_TYPE_WORN && critter == *ptr_obj_dude) {
|
||||
long _slot = (slot != INVEN_TYPE_LEFT_HAND);
|
||||
if (_slot != *ptr_itemCurrentItem) return 1; // item in non-active slot
|
||||
}
|
||||
}
|
||||
BeginHook();
|
||||
|
||||
args[0] = (DWORD)critter;
|
||||
args[1] = (DWORD)item;
|
||||
args[2] = slot;
|
||||
args[3] = isWield; // unwield/wield event
|
||||
args[4] = isRemove;
|
||||
|
||||
argCount = 5;
|
||||
RunHookScript(HOOK_INVENWIELD);
|
||||
|
||||
long result = (cRet == 0 || rets[0] == -1);
|
||||
EndHook();
|
||||
|
||||
return result; // 1 - use engine handler
|
||||
}
|
||||
|
||||
static __declspec(noinline) bool InvenWieldHook_ScriptPart(long isWield, long isRemove = 0) {
|
||||
args[3] = isWield; // unwield/wield event
|
||||
args[4] = isRemove;
|
||||
|
||||
argCount = 5;
|
||||
RunHookScript(HOOK_INVENWIELD);
|
||||
|
||||
bool result = (cRet == 0 || rets[0] == -1);
|
||||
EndHook();
|
||||
|
||||
return result; // True - use engine handler
|
||||
return result; // true - use engine handler
|
||||
}
|
||||
|
||||
static void __declspec(naked) InvenWieldFuncHook() {
|
||||
@@ -1275,13 +1303,11 @@ static void __declspec(naked) InvenWieldFuncHook() {
|
||||
mov args[8], ebx; // slot
|
||||
pushad;
|
||||
}
|
||||
|
||||
// right hand slot?
|
||||
if (args[2] != INVEN_TYPE_RIGHT_HAND && ItemGetType((TGameObj*)args[1]) != item_type_armor) {
|
||||
args[2] = INVEN_TYPE_LEFT_HAND;
|
||||
}
|
||||
|
||||
InvenWieldHook_Script(1); // wield flag
|
||||
InvenWieldHook_ScriptPart(1); // wield event
|
||||
|
||||
__asm {
|
||||
test al, al;
|
||||
@@ -1302,14 +1328,14 @@ static void __declspec(naked) InvenUnwieldFuncHook() {
|
||||
mov args[8], edx; // slot
|
||||
pushad;
|
||||
}
|
||||
|
||||
// set slot
|
||||
if (args[2] == 0) { // left hand slot?
|
||||
args[2] = INVEN_TYPE_LEFT_HAND;
|
||||
}
|
||||
args[1] = (DWORD)GetItemPtrSlot((TGameObj*)args[0], args[2]); // get item
|
||||
// get item
|
||||
args[1] = (DWORD)GetItemPtrSlot((TGameObj*)args[0], args[2]);
|
||||
|
||||
InvenWieldHook_Script(0); // unwield flag
|
||||
InvenWieldHook_ScriptPart(0); // unwield event
|
||||
|
||||
__asm {
|
||||
test al, al;
|
||||
@@ -1328,9 +1354,8 @@ static void __declspec(naked) CorrectFidForRemovedItemHook() {
|
||||
mov args[0], eax; // critter
|
||||
mov args[4], edx; // item
|
||||
mov args[8], ebx; // item flag
|
||||
pushad;
|
||||
pushadc;
|
||||
}
|
||||
|
||||
// set slot
|
||||
if (args[2] & 0x2000000) { // right hand slot
|
||||
args[2] = INVEN_TYPE_RIGHT_HAND;
|
||||
@@ -1339,20 +1364,117 @@ static void __declspec(naked) CorrectFidForRemovedItemHook() {
|
||||
} else {
|
||||
args[2] = INVEN_TYPE_WORN; // armor slot
|
||||
}
|
||||
|
||||
InvenWieldHook_Script(0); // unwield flag (armor by default)
|
||||
|
||||
InvenWieldHook_ScriptPart(0, 1); // unwield event (armor by default)
|
||||
// engine handler is not overridden
|
||||
__asm {
|
||||
test al, al;
|
||||
popad;
|
||||
jz skip;
|
||||
popadc;
|
||||
jmp correctFidForRemovedItem_;
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) item_drop_all_hack() {
|
||||
__asm {
|
||||
push eax;
|
||||
push 1; // remove event
|
||||
push 0; // unwield event
|
||||
mov ecx, INVEN_TYPE_LEFT_HAND;
|
||||
test ah, 0x1; // Left_Hand >> 24
|
||||
jnz skip;
|
||||
test ah, 0x4; // Worn >> 24
|
||||
setz cl; // set INVEN_TYPE_WORN or INVEN_TYPE_RIGHT_HAND
|
||||
skip:
|
||||
mov eax, -1;
|
||||
push ecx; // slot
|
||||
mov edx, esi; // item
|
||||
mov ecx, edi; // critter
|
||||
call InvenWieldHook_Script;
|
||||
mov [esp + 0x40 - 0x2C + 8], eax; // itemIsEquipped (hook return result)
|
||||
pop eax;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
// called from bugfixes for obj_drop_
|
||||
void __declspec(naked) InvenUnwield_HookDrop() { // ecx - critter, edx - item
|
||||
__asm {
|
||||
pushadc;
|
||||
mov eax, INVEN_TYPE_LEFT_HAND;
|
||||
test byte ptr [edx + 0x27], 0x1; // Left_Hand >> 24
|
||||
jnz isLeft;
|
||||
test byte ptr [edx + 0x27], 0x4; // Worn >> 24
|
||||
setz al; // set INVEN_TYPE_WORN or INVEN_TYPE_RIGHT_HAND
|
||||
isLeft:
|
||||
push 1; // remove event
|
||||
push 0; // unwield event
|
||||
push eax; // slot
|
||||
call InvenWieldHook_Script; // ecx - critter, edx - item
|
||||
// engine handler is not overridden
|
||||
popadc;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
// called from bugfixes for op_move_obj_inven_to_obj_
|
||||
void __declspec(naked) InvenUnwield_HookMove() { // eax - item, edx - critter
|
||||
__asm {
|
||||
pushadc;
|
||||
mov ecx, edx;
|
||||
mov edx, eax;
|
||||
push 1; // remove event
|
||||
xor eax, eax;
|
||||
push eax; // unwield event
|
||||
push eax; // slot
|
||||
call InvenWieldHook_Script; // ecx - critter, edx - item
|
||||
// engine handler is not overridden
|
||||
popadc;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
// called when unwelding dude weapon and armor
|
||||
static void __declspec(naked) op_move_obj_inven_to_obj_hook() {
|
||||
__asm {
|
||||
cmp eax, ds:[_obj_dude];
|
||||
je runHook;
|
||||
jmp item_move_all_;
|
||||
runHook:
|
||||
push eax;
|
||||
push edx;
|
||||
mov ecx, eax; // keep source
|
||||
mov edx, ds:[_itemCurrentItem]; // get player's active slot
|
||||
test edx, edx;
|
||||
jz left;
|
||||
call inven_right_hand_;
|
||||
jmp skip;
|
||||
left:
|
||||
call inven_left_hand_;
|
||||
skip:
|
||||
test eax, eax;
|
||||
jz noWeapon;
|
||||
push 1; // remove event
|
||||
push 0; // unwield event
|
||||
mov ebx, INVEN_TYPE_LEFT_HAND;
|
||||
sub ebx, edx;
|
||||
push ebx; // slot: INVEN_TYPE_LEFT_HAND or INVEN_TYPE_RIGHT_HAND
|
||||
mov edx, eax; // weapon
|
||||
call InvenWieldHook_Script; // ecx - source
|
||||
// engine handler is not overridden
|
||||
noWeapon:
|
||||
mov edx, [esp + 0x30 - 0x20 + 12]; // armor
|
||||
test edx, edx;
|
||||
jz noArmor;
|
||||
xor eax, eax;
|
||||
push 1; // remove event
|
||||
push eax; // unwield event
|
||||
push eax; // slot: INVEN_TYPE_WORN
|
||||
call InvenWieldHook_Script; // ecx - source
|
||||
// engine handler is not overridden
|
||||
noArmor:
|
||||
pop edx;
|
||||
pop eax;
|
||||
jmp item_move_all_;
|
||||
}
|
||||
}
|
||||
|
||||
DWORD _stdcall GetHSArgCount() {
|
||||
return argCount;
|
||||
}
|
||||
@@ -1605,6 +1727,8 @@ static void HookScriptInit2() {
|
||||
HookCall(0x495F0B, InvenUnwieldFuncHook); // partyMemberCopyLevelInfo_
|
||||
HookCall(0x45680C, CorrectFidForRemovedItemHook); // op_rm_obj_from_inven_
|
||||
HookCall(0x45C4EA, CorrectFidForRemovedItemHook); // op_move_obj_inven_to_obj_
|
||||
HookCall(0x45C4F6, op_move_obj_inven_to_obj_hook);
|
||||
MakeCall(0x4778AF, item_drop_all_hack, 3);
|
||||
|
||||
__asm {
|
||||
xor edx, edx
|
||||
|
||||
+6
-2
@@ -63,6 +63,10 @@ void HookScriptClear();
|
||||
|
||||
extern DWORD InitingHookScripts;
|
||||
extern int __fastcall AmmoCostHook_Script(DWORD hookType, TGameObj* weapon, DWORD &rounds);
|
||||
void _stdcall MouseClickHook(DWORD button, bool pressed);
|
||||
DWORD _stdcall KeyPressHook(DWORD dxKey, bool pressed, DWORD vKey);
|
||||
void _stdcall RunHookScriptsAtProc(DWORD procId);
|
||||
|
||||
DWORD _stdcall KeyPressHook(DWORD dxKey, bool pressed, DWORD vKey);
|
||||
void _stdcall MouseClickHook(DWORD button, bool pressed);
|
||||
|
||||
void InvenUnwield_HookDrop();
|
||||
void InvenUnwield_HookMove();
|
||||
|
||||
Reference in New Issue
Block a user