diff --git a/artifacts/ddraw.ini b/artifacts/ddraw.ini index 92a193fe..601587cb 100644 --- a/artifacts/ddraw.ini +++ b/artifacts/ddraw.ini @@ -649,8 +649,7 @@ DialogPanelAnimDelay=33 PipboyTimeAnimDelay=50 ;Set to 1 to let you use the command cursor to specify targets for party members to attack in combat -;Note: The old built-in ControlCombat option is removed in 3.8.40 -;See the example mods in the modders pack for a script-based NPC combat control mod +;The 'Attack Who' preference in the combat control panel of party members must be set to 'Whomever you want' PartyOrderToAttack=0 ;Changes the way weapon reloading works when you drag ammo onto a weapon in the inventory diff --git a/artifacts/scripting/hookscripts.md b/artifacts/scripting/hookscripts.md index 75bf3861..aab2df9d 100644 --- a/artifacts/scripting/hookscripts.md +++ b/artifacts/scripting/hookscripts.md @@ -322,7 +322,7 @@ Critter arg0 - the critter doing the bartering (either dude_obj or inven_dude) Critter arg1 - the critter being bartered with int arg2 - the default value of the goods Critter arg3 - table of requested goods (being bought from NPC) -int arg4 - the amount of actual caps in the barter stack (as opposed to goods) +int arg4 - the number of actual caps in the barter stack (as opposed to goods) int arg5 - the value of all goods being traded before skill modifications Critter arg6 - table of offered goods (being sold to NPC) int arg7 - the total cost of the goods offered by the player @@ -476,10 +476,12 @@ Example message (vanilla behavior):\ ``` Critter arg0 - Thief Obj arg1 - The target -Item arg2 - Item being stolen/planted +Item arg2 - The item being stolen/planted int arg3 - 0 when stealing, 1 when planting +int arg4 - quantity of the item being stolen/planted -int ret0 - overrides hard-coded handler (1 - force success, 0 - force fail, -1 - use engine handler) +int ret0 - overrides hard-coded handler (2 - force fail without closing window, 1 - force success, 0 - force fail, -1 - use engine handler) +int ret1 - overrides experience points gained for stealing this item (must be greater than or equal to 0) ``` ------------------------------------------- diff --git a/sfall/Modules/HookScripts/MiscHs.cpp b/sfall/Modules/HookScripts/MiscHs.cpp index 363dba25..ac92594d 100644 --- a/sfall/Modules/HookScripts/MiscHs.cpp +++ b/sfall/Modules/HookScripts/MiscHs.cpp @@ -202,31 +202,66 @@ defaultHandler: } } +static long stealExpOverride; + +static void __declspec(naked) StealHook_ExpOverrideHack() { + __asm { + mov ecx, [esp + 0x150 - 0x18 + 4]; // total exp + cmp stealExpOverride, -1; + jle vanillaExp; + add ecx, stealExpOverride; // add overridden exp value + jmp end; +vanillaExp: + add ecx, edi; // add vanilla exp value +end: + add edi, 10; // vanilla exp increment for next success + mov [esp + 0x150 - 0x18 + 4], ecx; // set total exp + mov ecx, [esp]; + add ecx, 14; // shift return address + mov [esp], ecx; + retn; + } +} + static void __declspec(naked) StealCheckHook() { + static const DWORD StealSkipRet = 0x474B18; __asm { HookBegin; mov args[0], eax; // thief mov args[4], edx; // target mov args[8], ebx; // item mov args[12], ecx; // is planting + mov args[16], esi; // quantity pushadc; } - argCount = 4; + argCount = 5; RunHookScript(HOOK_STEAL); __asm { popadc; - cmp cRet, 1; - jl defaultHandler; - cmp rets[0], -1; - je defaultHandler; - mov eax, rets[0]; + cmp cRet, 1; + jl defaultHandler; // no return values, use vanilla path + cmp cRet, 2; + push eax; + mov eax, -1; + cmovge eax, rets[4]; // override experience points for steal + mov stealExpOverride, eax; + pop eax; + cmp rets[0], -1; // if <= -1, use vanilla path + jle defaultHandler; + cmp rets[0], 2; // 2 - steal failed but didn't get cought + jnz normalReturn; + HookEnd; + add esp, 4; + jmp StealSkipRet; +normalReturn: + mov eax, rets[0]; HookEnd; retn; defaultHandler: HookEnd; - jmp fo::funcoffs::skill_check_stealing_; + jmp fo::funcoffs::skill_check_stealing_; } } @@ -711,6 +746,8 @@ void Inject_UseSkillHook() { void Inject_StealCheckHook() { const DWORD stealCheckHkAddr[] = {0x4749A2, 0x474A69}; HookCalls(StealCheckHook, stealCheckHkAddr); + const DWORD stealExpHkAddr[] = {0x4742C5, 0x4743E1}; + MakeCalls(StealHook_ExpOverrideHack, stealExpHkAddr); } void Inject_SneakCheckHook() {