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.
This commit is contained in:
NovaRain
2019-08-27 22:31:10 +08:00
parent 071581effc
commit 20cb24b385
5 changed files with 55 additions and 51 deletions
+4 -2
View File
@@ -248,13 +248,14 @@ Obj arg1 - the owner that the object is being removed from
item arg2 - the item that is being removed item arg2 - the item that is being removed
int arg3 - the number of items to remove int arg3 - the number of items to remove
int arg4 - The reason the object is being removed (see RMOBJ_* constants) 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) HOOK_BARTERPRICE (hs_barterprice.int)
Runs whenever the value of goods being purchased is calculated 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 arg1 - the critter doing the bartering (either dude_obj or inven_dude)
critter arg2 - the critter being bartered with 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 int arg6 - the value of all goods being traded before skill modifications
critter arg7 - table of offered goods (being sold to NPC) critter arg7 - table of offered goods (being sold to NPC)
int arg8 - the total cost of the goods offered by the player 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 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 int ret2 - the modified value of all offered goods
+7
View File
@@ -1169,3 +1169,10 @@ long __stdcall ItemTotalCost(TGameObj* object) {
call item_total_cost_; call item_total_cost_;
} }
} }
long __stdcall ItemTotalWeight(TGameObj* object) {
__asm {
mov eax, object;
call item_total_weight_;
}
}
+1
View File
@@ -1083,3 +1083,4 @@ long __stdcall ItemWRounds(TGameObj* item);
long __stdcall BarterComputeValue(TGameObj* source, TGameObj* target); long __stdcall BarterComputeValue(TGameObj* source, TGameObj* target);
long __stdcall ItemCapsTotal(TGameObj* object); long __stdcall ItemCapsTotal(TGameObj* object);
long __stdcall ItemTotalCost(TGameObj* object); long __stdcall ItemTotalCost(TGameObj* object);
long __stdcall ItemTotalWeight(TGameObj* object);
+22 -20
View File
@@ -575,15 +575,17 @@ static void __declspec(naked) RemoveObjHook() {
} }
// 4.x backport // 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) { 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); int computeCost = BarterComputeValue(source, target);
BeginHook(); BeginHook();
argCount = 9; argCount = 10;
args[0] = (DWORD)source; args[0] = (DWORD)source;
args[1] = (DWORD)target; args[1] = (DWORD)target;
args[2] = computeCost; args[2] = !barterIsParty ? computeCost : 0;
TGameObj* bTable = (TGameObj*)*ptr_btable; TGameObj* bTable = (TGameObj*)*ptr_btable;
args[3] = (DWORD)bTable; args[3] = (DWORD)bTable;
@@ -592,24 +594,24 @@ static DWORD __fastcall BarterPriceHook_Script(register TGameObj* source, regist
TGameObj* pTable = (TGameObj*)*ptr_ptable; TGameObj* pTable = (TGameObj*)*ptr_ptable;
args[6] = (DWORD)pTable; args[6] = (DWORD)pTable;
int pcCost = ItemTotalCost(pTable); int pcCost = !barterIsParty ? ItemTotalCost(pTable) : ItemTotalWeight(pTable);
args[7] = pcCost; 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); RunHookScript(HOOK_BARTERPRICE);
bool isPCHook = (callAddr == 0x47551F); bool isPCHook = (callAddr == -1);
int cost = isPCHook ? pcCost : computeCost; int cost = isPCHook ? pcCost : computeCost;
if (cRet > 0) { if (!barterIsParty && cRet > 0) {
if (isPCHook) { if (isPCHook) {
if (cRet > 1) cost = rets[1]; // new cost for pc if (cRet > 1) cost = rets[1]; // new cost for pc
} else if ((int)rets[0] > -1) { } else if ((int)rets[0] > -1) {
cost = rets[0]; // new cost for trader cost = rets[0]; // new cost for npc
} }
} }
EndHook(); EndHook();
return cost; 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() { static void __declspec(naked) PC_BarterPriceHook() {
__asm { __asm {
push edx; push edx;
push ecx; push ecx;
//------- //-------
push [esp + 8]; // address on call stack push -1; // address on call stack
mov ecx, dword ptr ds:[_obj_dude]; // source mov ecx, dword ptr ds:[_obj_dude]; // source
mov edx, dword ptr ds:[_target_stack]; // target mov edx, dword ptr ds:[_target_stack]; // target
call BarterPriceHook_Script; call BarterPriceHook_Script;
@@ -644,11 +646,10 @@ static void __declspec(naked) PC_BarterPriceHook() {
} }
} }
static const DWORD OverrideCostRet = 0x474D44; static void __declspec(naked) OverrideCost_BarterPriceHook() {
static void __declspec(naked) OverrideCost_BarterPriceHack() {
__asm { __asm {
mov eax, offersGoodsCost; mov eax, offersGoodsCost;
jmp OverrideCostRet; retn;
} }
} }
@@ -1377,7 +1378,7 @@ void _stdcall RegisterHook(DWORD script, DWORD id, DWORD procNum) {
sScriptProgram *prog = GetGlobalScriptProgram(script); sScriptProgram *prog = GetGlobalScriptProgram(script);
if (prog) { 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; sHookScript hook;
hook.prog = *prog; hook.prog = *prog;
hook.callback = procNum; hook.callback = procNum;
@@ -1503,11 +1504,12 @@ static void HookScriptInit2() {
MakeJump(0x477492, RemoveObjHook); // old 0x477490 MakeJump(0x477492, RemoveObjHook); // old 0x477490
LoadHookScript("hs_barterprice", HOOK_BARTERPRICE); LoadHookScript("hs_barterprice", HOOK_BARTERPRICE);
HookCall(0x474D4C, BarterPriceHook); HookCall(0x474D4C, BarterPriceHook); // barter_attempt_transaction_ (offers button)
HookCall(0x475735, BarterPriceHook); HookCall(0x475735, BarterPriceHook); // display_table_inventories_ (for party members)
HookCall(0x475762, BarterPriceHook); HookCall(0x475762, BarterPriceHook); // display_table_inventories_
HookCall(0X47551A, PC_BarterPriceHook); HookCall(0x4754F4, PC_BarterPriceHook); // display_table_inventories_
MakeJump(0x474D3F, OverrideCost_BarterPriceHack); // just overrides cost of offered goods 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); LoadHookScript("hs_movecost", HOOK_MOVECOST);
HookCall(0x417665, &MoveCostHook); HookCall(0x417665, &MoveCostHook);
+21 -29
View File
@@ -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() { static void __declspec(naked) register_hook() {
__asm { _WRAP_OPCODE(register_hook2, 1, 0)
pushad; }
mov ebp, eax;
call interpretPopShort_; static void _stdcall register_hook_proc2() {
mov edi, eax; const ScriptValue &idArg = opHandler.arg(0);
mov eax, ebp;
call interpretPopLong_; if (idArg.isInt()) {
cmp di, VAR_TYPE_INT; RegisterHook((DWORD)opHandler.program(), idArg.rawValue(), opHandler.arg(1).rawValue());
jnz end; } else {
push -1; OpcodeInvalidArgs("register_hook_proc");
push eax;
push ebp;
call RegisterHook;
end:
popad;
retn;
} }
} }
static void __declspec(naked) register_hook_proc() { static void __declspec(naked) register_hook_proc() {
_OP_BEGIN(ebp) _WRAP_OPCODE(register_hook_proc2, 2, 0)
_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
} }
static void __declspec(naked) sfall_ver_major() { static void __declspec(naked) sfall_ver_major() {