From b4b169834507fc2b990f7dd0a4dd4ef06c716f7b Mon Sep 17 00:00:00 2001 From: "Mr.Stalin" <21695363+FakelsHub@users.noreply.github.com> Date: Tue, 10 Jul 2018 01:00:04 +0300 Subject: [PATCH] Added new HOOK_EXPLOSIVETIMER (#175) --- .../ExplosionTimer/hs_explosivetimer.ssl | 35 ++++++++++++ artifacts/scripting/headers/sfall.h | 1 + sfall/Modules/HookScripts.cpp | 1 + sfall/Modules/HookScripts.h | 1 + sfall/Modules/HookScripts/MiscHs.cpp | 54 +++++++++++++++++++ sfall/Modules/HookScripts/MiscHs.h | 2 +- 6 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 artifacts/example_mods/ExplosionTimer/hs_explosivetimer.ssl diff --git a/artifacts/example_mods/ExplosionTimer/hs_explosivetimer.ssl b/artifacts/example_mods/ExplosionTimer/hs_explosivetimer.ssl new file mode 100644 index 00000000..41689f50 --- /dev/null +++ b/artifacts/example_mods/ExplosionTimer/hs_explosivetimer.ssl @@ -0,0 +1,35 @@ +/* + Example implementation of the algorithm of the game engine setting the timer of explosives. +*/ + +#include "..\..\scripting_docs\headers\define_lite.h" + +procedure start; + +procedure start begin + if (init_hook == 0) then begin + variable + time := get_sfall_arg, + result := ROLL_CRITICAL_FAILURE; + + if has_trait(TRAIT_PERK, dude_obj, PERK_demolition_expert_perk) then + result := ROLL_SUCCESS; + else begin + result := roll_vs_skill(dude_obj, SKILL_TRAPS, 0); + end + + if (result) then begin + if (result == ROLL_FAILURE) then + time /= 2; + else begin // success or critical success + result := ROLL_SUCCESS; + end + end else begin // critical failure + time := 0; + result := ROLL_FAILURE; + end + + set_sfall_return(time); + set_sfall_return(result); // failure/success + end +end diff --git a/artifacts/scripting/headers/sfall.h b/artifacts/scripting/headers/sfall.h index 30da3bfd..3bb31111 100644 --- a/artifacts/scripting/headers/sfall.h +++ b/artifacts/scripting/headers/sfall.h @@ -53,6 +53,7 @@ #define HOOK_RESTTIMER (30) #define HOOK_GAMEMODECHANGE (31) #define HOOK_USEANIMOBJ (32) +#define HOOK_EXPLOSIVETIMER (33) //Valid arguments to list_begin #define LIST_CRITTERS (0) diff --git a/sfall/Modules/HookScripts.cpp b/sfall/Modules/HookScripts.cpp index 72305f7e..d2677421 100644 --- a/sfall/Modules/HookScripts.cpp +++ b/sfall/Modules/HookScripts.cpp @@ -77,6 +77,7 @@ static HooksInjectInfo injectHooks[] = { {HOOK_RESTTIMER, Inject_RestTimerHook, false}, {HOOK_GAMEMODECHANGE, nullptr, true}, // always embedded to the engine {HOOK_USEANIMOBJ, Inject_UseAnimateObjHook, false}, + {HOOK_EXPLOSIVETIMER, Inject_ExplosiveTimerHook, false}, }; bool HookScripts::injectAllHooks; diff --git a/sfall/Modules/HookScripts.h b/sfall/Modules/HookScripts.h index c2eafd8a..19d60289 100644 --- a/sfall/Modules/HookScripts.h +++ b/sfall/Modules/HookScripts.h @@ -59,6 +59,7 @@ enum HookType HOOK_RESTTIMER = 30, HOOK_GAMEMODECHANGE = 31, HOOK_USEANIMOBJ = 32, + HOOK_EXPLOSIVETIMER = 33, HOOK_COUNT }; diff --git a/sfall/Modules/HookScripts/MiscHs.cpp b/sfall/Modules/HookScripts/MiscHs.cpp index cbd50f94..c3ef67c2 100644 --- a/sfall/Modules/HookScripts/MiscHs.cpp +++ b/sfall/Modules/HookScripts/MiscHs.cpp @@ -281,6 +281,55 @@ skip: } } +static int __fastcall ExplosiveTimerHook_Script(DWORD type, DWORD item, DWORD time) { + + BeginHook(); + argCount = 3; + + args[0] = time; + args[1] = item; + args[2] = (type == 11) ? fo::ROLL_FAILURE : fo::ROLL_SUCCESS; + + RunHookScript(HOOK_EXPLOSIVETIMER); + EndHook(); + + int result = 0; + if (cRet > 0 && rets[0] >= 0) { + if (rets[0] > 18000) rets[0] = 18000; // max 30 minutes + if (cRet < 2) { + result--; // use vanilla type + } else { + result++; // use returned type + } + } + return result; +} + +static void _declspec(naked) ExplosiveTimerHook() { + __asm { + push eax; + push edx; + push ecx; + //------- + push edi; // time in ticks + call ExplosiveTimerHook_Script; // ecx - type, edx - item + cmp eax, 0; + pop ecx; + pop edx; + pop eax; + jz end; + mov eax, rets[0]; // time in ticks + jl end; + mov ecx, 8; // type SUCCESS + cmp rets[4], 1; + jg end; + add ecx, 3; // type FAILURE (11) +end: + call fo::funcoffs::queue_add_; + retn; + } +} + void Inject_BarterPriceHook() { HookCalls(BarterPriceHook, { 0x474D4C, @@ -323,6 +372,10 @@ void Inject_RestTimerHook() { MakeCalls(RestTimerEscapeHook, { 0x499B63, 0x499CA1 }); } +void Inject_ExplosiveTimerHook() { + HookCall(0x49BDC4, ExplosiveTimerHook); +} + void InitMiscHookScripts() { LoadHookScript("hs_barterprice", HOOK_BARTERPRICE); @@ -332,6 +385,7 @@ void InitMiscHookScripts() { LoadHookScript("hs_cartravel", HOOK_CARTRAVEL); LoadHookScript("hs_setglobalvar", HOOK_SETGLOBALVAR); LoadHookScript("hs_resttimer", HOOK_RESTTIMER); + LoadHookScript("hs_explosivetimer", HOOK_EXPLOSIVETIMER); } } diff --git a/sfall/Modules/HookScripts/MiscHs.h b/sfall/Modules/HookScripts/MiscHs.h index 201b35dc..cbeead4b 100644 --- a/sfall/Modules/HookScripts/MiscHs.h +++ b/sfall/Modules/HookScripts/MiscHs.h @@ -11,5 +11,5 @@ namespace sfall void Inject_CarTravelHook(); void Inject_SetGlobalVarHook(); void Inject_RestTimerHook(); - + void Inject_ExplosiveTimerHook(); }