From 20cb24b385ae679e4fc628dc49cdae96a0b121f2 Mon Sep 17 00:00:00 2001 From: NovaRain Date: Tue, 27 Aug 2019 12:57:34 +0800 Subject: [PATCH] Fixed some args in HOOK_BARTERPRICE hook when trading with PM And added a new argument to indicate trading with a party member. Refactored register_hook/register_hook_proc with _WRAP_OPCODE. --- artifacts/scripting/hookscripts.txt | 6 ++-- sfall/FalloutEngine.cpp | 7 ++++ sfall/FalloutEngine.h | 1 + sfall/HookScripts.cpp | 42 ++++++++++++------------ sfall/ScriptExtender.cpp | 50 ++++++++++++----------------- 5 files changed, 55 insertions(+), 51 deletions(-) diff --git a/artifacts/scripting/hookscripts.txt b/artifacts/scripting/hookscripts.txt index f4b1a9ba..36fe8c30 100644 --- a/artifacts/scripting/hookscripts.txt +++ b/artifacts/scripting/hookscripts.txt @@ -248,13 +248,14 @@ Obj arg1 - the owner that the object is being removed from item arg2 - the item that is being removed int arg3 - the number of items to remove int arg4 - The reason the object is being removed (see RMOBJ_* constants) -Obj arg5 - The destination object when the item is moved to another object, otherwise 0 +Obj arg5 - The destination object when the item is moved to another object, 0 otherwise ------------------------------------------- HOOK_BARTERPRICE (hs_barterprice.int) Runs whenever the value of goods being purchased is calculated +NOTE: the hook is executed twice when entering the barter screen or after transaction: the first time is for the player and the second time is for NPC critter arg1 - the critter doing the bartering (either dude_obj or inven_dude) critter arg2 - the critter being bartered with @@ -264,7 +265,8 @@ int arg5 - the amount of actual caps in the barter stack (as opposed to good int arg6 - the value of all goods being traded before skill modifications critter arg7 - table of offered goods (being sold to NPC) int arg8 - the total cost of the goods offered by the player -int arg9 - set 1 if the "offers" button was pressed (not for a party member), otherwise 0 +int arg9 - 1 if the "offers" button was pressed (not for a party member), 0 otherwise +int arg10 - 1 if trading with a party member, 0 otherwise int ret1 - the modified value of all of the goods (pass -1 if you just want to modify offered goods) int ret2 - the modified value of all offered goods diff --git a/sfall/FalloutEngine.cpp b/sfall/FalloutEngine.cpp index 8ba0622b..6088266a 100644 --- a/sfall/FalloutEngine.cpp +++ b/sfall/FalloutEngine.cpp @@ -1169,3 +1169,10 @@ long __stdcall ItemTotalCost(TGameObj* object) { call item_total_cost_; } } + +long __stdcall ItemTotalWeight(TGameObj* object) { + __asm { + mov eax, object; + call item_total_weight_; + } +} diff --git a/sfall/FalloutEngine.h b/sfall/FalloutEngine.h index 416b0884..8ab48822 100644 --- a/sfall/FalloutEngine.h +++ b/sfall/FalloutEngine.h @@ -1083,3 +1083,4 @@ long __stdcall ItemWRounds(TGameObj* item); long __stdcall BarterComputeValue(TGameObj* source, TGameObj* target); long __stdcall ItemCapsTotal(TGameObj* object); long __stdcall ItemTotalCost(TGameObj* object); +long __stdcall ItemTotalWeight(TGameObj* object); diff --git a/sfall/HookScripts.cpp b/sfall/HookScripts.cpp index 0e0ac65b..dc34638e 100644 --- a/sfall/HookScripts.cpp +++ b/sfall/HookScripts.cpp @@ -575,15 +575,17 @@ static void __declspec(naked) RemoveObjHook() { } // 4.x backport +// The hook is executed twice when entering the barter screen or after transaction: the first time is for the player and the second time is for NPC static DWORD __fastcall BarterPriceHook_Script(register TGameObj* source, register TGameObj* target, DWORD callAddr) { + bool barterIsParty = (*ptr_dialog_target_is_party != 0); int computeCost = BarterComputeValue(source, target); BeginHook(); - argCount = 9; + argCount = 10; args[0] = (DWORD)source; args[1] = (DWORD)target; - args[2] = computeCost; + args[2] = !barterIsParty ? computeCost : 0; TGameObj* bTable = (TGameObj*)*ptr_btable; args[3] = (DWORD)bTable; @@ -592,24 +594,24 @@ static DWORD __fastcall BarterPriceHook_Script(register TGameObj* source, regist TGameObj* pTable = (TGameObj*)*ptr_ptable; args[6] = (DWORD)pTable; - int pcCost = ItemTotalCost(pTable); - args[7] = pcCost; + int pcCost = !barterIsParty ? ItemTotalCost(pTable) : ItemTotalWeight(pTable); + args[7] = !barterIsParty ? pcCost : 0; - args[8] = (DWORD)(callAddr == 0x474D51); // check offers button + args[8] = (DWORD)(callAddr == 0x474D51); // offers button is pressed + args[9] = (DWORD)barterIsParty; RunHookScript(HOOK_BARTERPRICE); - bool isPCHook = (callAddr == 0x47551F); + bool isPCHook = (callAddr == -1); int cost = isPCHook ? pcCost : computeCost; - if (cRet > 0) { + if (!barterIsParty && cRet > 0) { if (isPCHook) { if (cRet > 1) cost = rets[1]; // new cost for pc } else if ((int)rets[0] > -1) { - cost = rets[0]; // new cost for trader + cost = rets[0]; // new cost for npc } } EndHook(); - return cost; } @@ -627,13 +629,13 @@ static void __declspec(naked) BarterPriceHook() { } } -static DWORD offersGoodsCost; // keep last cost +static DWORD offersGoodsCost; // keep last cost for pc static void __declspec(naked) PC_BarterPriceHook() { __asm { push edx; push ecx; //------- - push [esp + 8]; // address on call stack + push -1; // address on call stack mov ecx, dword ptr ds:[_obj_dude]; // source mov edx, dword ptr ds:[_target_stack]; // target call BarterPriceHook_Script; @@ -644,11 +646,10 @@ static void __declspec(naked) PC_BarterPriceHook() { } } -static const DWORD OverrideCostRet = 0x474D44; -static void __declspec(naked) OverrideCost_BarterPriceHack() { +static void __declspec(naked) OverrideCost_BarterPriceHook() { __asm { mov eax, offersGoodsCost; - jmp OverrideCostRet; + retn; } } @@ -1377,7 +1378,7 @@ void _stdcall RegisterHook(DWORD script, DWORD id, DWORD procNum) { sScriptProgram *prog = GetGlobalScriptProgram(script); if (prog) { - dlog_f("Global script %08x registered as hook id %d\n", DL_HOOK, script, id); + dlog_f("Global script %08x registered as hook ID %d\n", DL_HOOK, script, id); sHookScript hook; hook.prog = *prog; hook.callback = procNum; @@ -1503,11 +1504,12 @@ static void HookScriptInit2() { MakeJump(0x477492, RemoveObjHook); // old 0x477490 LoadHookScript("hs_barterprice", HOOK_BARTERPRICE); - HookCall(0x474D4C, BarterPriceHook); - HookCall(0x475735, BarterPriceHook); - HookCall(0x475762, BarterPriceHook); - HookCall(0X47551A, PC_BarterPriceHook); - MakeJump(0x474D3F, OverrideCost_BarterPriceHack); // just overrides cost of offered goods + HookCall(0x474D4C, BarterPriceHook); // barter_attempt_transaction_ (offers button) + HookCall(0x475735, BarterPriceHook); // display_table_inventories_ (for party members) + HookCall(0x475762, BarterPriceHook); // display_table_inventories_ + HookCall(0x4754F4, PC_BarterPriceHook); // display_table_inventories_ + HookCall(0X47551A, PC_BarterPriceHook); // display_table_inventories_ + HookCall(0x474D3F, OverrideCost_BarterPriceHook); // barter_attempt_transaction_ (just overrides cost of offered goods) LoadHookScript("hs_movecost", HOOK_MOVECOST); HookCall(0x417665, &MoveCostHook); diff --git a/sfall/ScriptExtender.cpp b/sfall/ScriptExtender.cpp index 51c74418..6d52bfa8 100644 --- a/sfall/ScriptExtender.cpp +++ b/sfall/ScriptExtender.cpp @@ -805,40 +805,32 @@ end: } } +static void _stdcall register_hook2() { + const ScriptValue &idArg = opHandler.arg(0); + + if (idArg.isInt()) { + RegisterHook((DWORD)opHandler.program(), idArg.rawValue(), -1); + } else { + OpcodeInvalidArgs("register_hook"); + } +} + static void __declspec(naked) register_hook() { - __asm { - pushad; - mov ebp, eax; - call interpretPopShort_; - mov edi, eax; - mov eax, ebp; - call interpretPopLong_; - cmp di, VAR_TYPE_INT; - jnz end; - push -1; - push eax; - push ebp; - call RegisterHook; -end: - popad; - retn; + _WRAP_OPCODE(register_hook2, 1, 0) +} + +static void _stdcall register_hook_proc2() { + const ScriptValue &idArg = opHandler.arg(0); + + if (idArg.isInt()) { + RegisterHook((DWORD)opHandler.program(), idArg.rawValue(), opHandler.arg(1).rawValue()); + } else { + OpcodeInvalidArgs("register_hook_proc"); } } static void __declspec(naked) register_hook_proc() { - _OP_BEGIN(ebp) - _GET_ARG_R32(ebp, ecx, esi) - _GET_ARG_R32(ebp, ebx, edi) - _CHECK_ARG_INT(cx, fail) - _CHECK_ARG_INT(bx, fail) - __asm { - push esi; - push edi; - push ebp; - call RegisterHook; - fail: - } - _OP_END + _WRAP_OPCODE(register_hook_proc2, 2, 0) } static void __declspec(naked) sfall_ver_major() {