From b89663174ffe3df4d72540c16050a032f11e5dbc Mon Sep 17 00:00:00 2001 From: NovaRain Date: Sat, 29 Dec 2018 09:16:43 +0800 Subject: [PATCH] Added new HOOK_SETLIGHTING (from Mr.Stalin) (#215) --- artifacts/scripting/headers/sfall.h | 1 + artifacts/scripting/hookscripts.txt | 13 ++++ artifacts/scripting/sfall function notes.txt | 4 +- sfall/Modules/HookScripts.cpp | 1 + sfall/Modules/HookScripts.h | 1 + sfall/Modules/HookScripts/Common.cpp | 1 + sfall/Modules/HookScripts/ObjectHs.cpp | 72 ++++++++++++++++++++ sfall/Modules/HookScripts/ObjectHs.h | 1 + 8 files changed, 92 insertions(+), 2 deletions(-) diff --git a/artifacts/scripting/headers/sfall.h b/artifacts/scripting/headers/sfall.h index f112e6f1..d54aeec4 100644 --- a/artifacts/scripting/headers/sfall.h +++ b/artifacts/scripting/headers/sfall.h @@ -59,6 +59,7 @@ #define HOOK_USESKILLON (35) #define HOOK_ONEXPLOSION (36) #define HOOK_SUBCOMBATDAMAGE (37) +#define HOOK_SETLIGHTING (38) //Valid arguments to list_begin #define LIST_CRITTERS (0) diff --git a/artifacts/scripting/hookscripts.txt b/artifacts/scripting/hookscripts.txt index e6b54481..e60fcc1d 100644 --- a/artifacts/scripting/hookscripts.txt +++ b/artifacts/scripting/hookscripts.txt @@ -603,3 +603,16 @@ int arg11 - The calculated amount of damage (usually 0, required when using mixed arg12 - Computed attack results (see C_ATTACK_* for offsets and use get/set_object_data functions to get/set the data) int ret1 - The returned amount of damage + +------------------------------------------- + +HOOK_SETLIGHTING (hs_setlighting.int) + +Runs before setting the light level for an object or a map. You can override the result. + +Obj arg1 - the object being set, or -1 when setting the light level for a map +int arg2 - the light intensity +int arg3 - the light radius, or -1 when setting the light level for a map + +int ret1 - overrides the light intensity. Intensity range is from 0 to 65536 +int ret2 - overrides the light radius. Radius range is from 0 to 8 (works only for the object) diff --git a/artifacts/scripting/sfall function notes.txt b/artifacts/scripting/sfall function notes.txt index 43238f0d..23262aeb 100644 --- a/artifacts/scripting/sfall function notes.txt +++ b/artifacts/scripting/sfall function notes.txt @@ -141,7 +141,7 @@ array - array ID to be used with array-related functions (actually an integer) - In this case use force_encounter_with_flags with the ENCOUNTER_FLAG_NO_CAR flag set. > int get_light_level() -- ambient light level in range 0..65535 +- ambient light level in range 0..65536 - The value returned by get_light_level may not exactly match that set by set_light_level, as set_light_level applies modifiers from the night vision perk. > void set_map_time_multi(float multi) @@ -325,7 +325,7 @@ Some utility/math functions are available: - this calls an internal engine function which is used to determine the perception range of critters (which you can override using HOOK_WITHINPERCEPTION) > int tile_light(int elevation, int tileNum) -- returns light intensity at the given tile in range from 0 to 65535 +- returns light intensity at the given tile in range from 0 to 65536 > object obj_blocking_line(object objFrom, int tileTo, int blockingType) - returns first object which blocks direct linear path from objFrom to tileTo using selected blocking function (see BLOCKING_TYPE_* constants in sfall.h) diff --git a/sfall/Modules/HookScripts.cpp b/sfall/Modules/HookScripts.cpp index 98917380..6a098dbd 100644 --- a/sfall/Modules/HookScripts.cpp +++ b/sfall/Modules/HookScripts.cpp @@ -82,6 +82,7 @@ static HooksInjectInfo injectHooks[] = { {HOOK_USESKILLON, Inject_UseSkillOnHook, false}, {HOOK_ONEXPLOSION, Inject_OnExplosionHook, false}, {HOOK_SUBCOMBATDAMAGE, Inject_SubCombatDamageHook, false}, // replace the code logic + {HOOK_SETLIGHTING, Inject_SetLightingHook, false}, }; bool HookScripts::injectAllHooks; diff --git a/sfall/Modules/HookScripts.h b/sfall/Modules/HookScripts.h index 6e609789..e0eea7fd 100644 --- a/sfall/Modules/HookScripts.h +++ b/sfall/Modules/HookScripts.h @@ -64,6 +64,7 @@ enum HookType HOOK_USESKILLON = 35, HOOK_ONEXPLOSION = 36, HOOK_SUBCOMBATDAMAGE = 37, + HOOK_SETLIGHTING = 38, HOOK_COUNT }; diff --git a/sfall/Modules/HookScripts/Common.cpp b/sfall/Modules/HookScripts/Common.cpp index d53cdd99..efe1d543 100644 --- a/sfall/Modules/HookScripts/Common.cpp +++ b/sfall/Modules/HookScripts/Common.cpp @@ -65,6 +65,7 @@ static bool CheckRecursiveHooks(DWORD hook) { if (hook == currentRunHook) { switch (hook) { case HOOK_SETGLOBALVAR: + case HOOK_SETLIGHTING: return true; } } diff --git a/sfall/Modules/HookScripts/ObjectHs.cpp b/sfall/Modules/HookScripts/ObjectHs.cpp index b9e34eb4..d526b9d4 100644 --- a/sfall/Modules/HookScripts/ObjectHs.cpp +++ b/sfall/Modules/HookScripts/ObjectHs.cpp @@ -171,6 +171,72 @@ skip: } } +static bool __fastcall SetLightingHook_Script(DWORD* intensity, DWORD* radius, DWORD object) { + BeginHook(); + argCount = 3; + + args[0] = object; + args[1] = *intensity; + args[2] = *radius; + RunHookScript(HOOK_SETLIGHTING); + + bool result = false; + if (cRet > 0) { + int light = rets[0]; + if (light < 0) light = 0; + *intensity = light; + if (cRet > 1 && object != -1) { + int dist = rets[1]; + if (dist < 0) dist = 0; + *radius = dist; + } + result = true; + } + EndHook(); + return result; +} + +static void __declspec(naked) SetObjectLightHook() { + __asm { + pushadc; + push ebp; + mov edx, esp; // &radius + push ebx; + mov ecx, esp; // &intensity + push esi; // object + call SetLightingHook_Script; + test al, al; + jz skip; + pop ebx; // return intensity value + pop ebp; // return radius value + jmp end; +skip: + add esp, 8; +end: + popadc; + jmp fo::funcoffs::obj_turn_off_light_; + } +} + +static void __declspec(naked) SetMapLightHook() { + __asm { + push ecx; + push ebx; + mov ecx, esp; // &intensity + push -1; // no object (it's a map) + mov edx, esp; // no radius + call SetLightingHook_Script; + add esp, 4; + test al, al; + jz skip; + mov ebx, [esp - 4]; // return intensity value +skip: + pop ecx; + cmp ebx, dword ptr ds:[0x47A93D]; // get miminal ambient light intensity (16384) + retn; + } +} + void Inject_UseObjOnHook() { HookCalls(UseObjOnHook, { 0x49C606, 0x473619 }); @@ -195,12 +261,18 @@ void Inject_DescriptionObjHook() { HookCall(0x48C925, DescriptionObjHook); } +void Inject_SetLightingHook() { + HookCall(0x48ACA0, SetObjectLightHook); + MakeCall(0x47A934, SetMapLightHook, 1); +} + void InitObjectHookScripts() { LoadHookScript("hs_useobjon", HOOK_USEOBJON); LoadHookScript("hs_useobj", HOOK_USEOBJ); LoadHookScript("hs_useanimobj", HOOK_USEANIMOBJ); LoadHookScript("hs_descriptionobj", HOOK_DESCRIPTIONOBJ); + LoadHookScript("hs_setlighting", HOOK_SETLIGHTING); } } diff --git a/sfall/Modules/HookScripts/ObjectHs.h b/sfall/Modules/HookScripts/ObjectHs.h index 9bc5396a..020cc066 100644 --- a/sfall/Modules/HookScripts/ObjectHs.h +++ b/sfall/Modules/HookScripts/ObjectHs.h @@ -8,4 +8,5 @@ namespace sfall void Inject_UseObjHook(); void Inject_UseAnimateObjHook(); void Inject_DescriptionObjHook(); + void Inject_SetLightingHook(); }