From 93cd7a08ad42460eb1e3f084fe525a49ab6636d7 Mon Sep 17 00:00:00 2001 From: "Mr.Stalin" <21695363+FakelsHub@users.noreply.github.com> Date: Sat, 28 Jul 2018 17:14:38 +0300 Subject: [PATCH] Added new HOOK_DESCRIPTIONOBJ and dialog_message/get_string_pointer functions (#181) Added the second return value to HOOK_BARTERPRICE to modify the cost of the player's goods. Fixed missing AC/DR mod stats when examining ammo in barter screen. Added an option to display full item description for weapon/ammo in barter screen. --- artifacts/scripting/headers/sfall.h | 2 + artifacts/scripting/hookscripts.txt | 16 +- artifacts/scripting/sfall function notes.txt | 6 + sfall/FalloutEngine/Functions_def.h | 4 + sfall/Modules/BugFixes.cpp | 95 +++++++ sfall/Modules/HookScripts.cpp | 1 + sfall/Modules/HookScripts.h | 1 + sfall/Modules/HookScripts/MiscHs.cpp | 249 ++++++++++-------- sfall/Modules/HookScripts/ObjectHs.cpp | 30 +++ sfall/Modules/HookScripts/ObjectHs.h | 1 + .../Modules/Scripting/Handlers/Interface.cpp | 7 + sfall/Modules/Scripting/Handlers/Interface.h | 2 + sfall/Modules/Scripting/Handlers/Metarule.cpp | 2 + sfall/Modules/Scripting/Handlers/Utils.cpp | 4 + sfall/Modules/Scripting/Handlers/Utils.h | 2 + 15 files changed, 317 insertions(+), 105 deletions(-) diff --git a/artifacts/scripting/headers/sfall.h b/artifacts/scripting/headers/sfall.h index 3bb31111..2de78c5e 100644 --- a/artifacts/scripting/headers/sfall.h +++ b/artifacts/scripting/headers/sfall.h @@ -223,6 +223,7 @@ #define attack_is_aimed sfall_func0("attack_is_aimed") #define car_gas_amount sfall_func0("car_gas_amount") #define critter_inven_obj2(obj, type) sfall_func2("critter_inven_obj2", obj, type) +#define dialog_message(text) sfall_func1("dialog_message", text) #define display_stats sfall_func0("display_stats") #define exec_map_update_scripts sfall_func0("exec_map_update_scripts") #define floor2(value) sfall_func1("floor2", value) @@ -232,6 +233,7 @@ #define get_ini_sections(file) sfall_func1("get_ini_sections", file) #define get_map_enter_position sfall_func0("get_map_enter_position") #define get_outline(obj) sfall_func1("get_outline", obj) +#define get_string_pointer(text) sfall_func1("get_string_pointer", text) #define intface_hide sfall_func0("intface_hide") #define intface_is_hidden sfall_func0("intface_is_hidden") #define intface_redraw sfall_func0("intface_redraw") diff --git a/artifacts/scripting/hookscripts.txt b/artifacts/scripting/hookscripts.txt index 8873ea74..303a8eb0 100644 --- a/artifacts/scripting/hookscripts.txt +++ b/artifacts/scripting/hookscripts.txt @@ -265,7 +265,8 @@ 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 ret1 - the modified value of all of the goods +int ret1 - the modified value of all of the goods, pass -1 for modify only offered goods +int ret2 - the modified value of all offered goods ------------------------------------------- @@ -530,4 +531,15 @@ Obj arg2 - the explosive object int arg3 - the result of engine calculation of whether the timer was set successfully: 1 - failure, 2 - success (similar to ROLL_* in Condtion.h) int ret1 - overrides the time of the timer (maximum 18000 ticks) -int ret2 - overrides the result of engine calculation: 1 - failure, 2 - success, any other value - use engine handler +int ret2 - overrides the result of engine calculation: 0/1 - failure, 2/3 - success (similar to ROLL_*), any other value - use engine handler + +------------------------------------------- + +HOOK_DESCRIPTIONOBJ (hs_descriptionobj) + +Runs while using the item description icon in the player's inventory, or trade window. +Allows to override the description of the item (for example: add additional parameters to the description). + +Obj arg1 - the item + +int ret1 - a pointer to the new "text" received using the macro function 'get_string_pointer' from FuncX functions diff --git a/artifacts/scripting/sfall function notes.txt b/artifacts/scripting/sfall function notes.txt index 0641c5f5..fe8f9c24 100644 --- a/artifacts/scripting/sfall function notes.txt +++ b/artifacts/scripting/sfall function notes.txt @@ -491,6 +491,12 @@ Some utility/math functions are available: - redraws inventory list in the inventory/use inventory item on/loot/barter screens - invSide specifies which side needs to be redrawn: 0 - the player, 1 - target (container/NPC in loot/barter screens) +> int sfall_func1("get_string_pointer", string text) +- returns a pointer to a string variable or to a text + +> void sfall_func1("dialog_message", string text) +- displays a message in the NPC response window in dialog or trade mode + ------------------------ ------ MORE INFO ------- ------------------------ diff --git a/sfall/FalloutEngine/Functions_def.h b/sfall/FalloutEngine/Functions_def.h index 9816edc5..1f274e98 100644 --- a/sfall/FalloutEngine/Functions_def.h +++ b/sfall/FalloutEngine/Functions_def.h @@ -24,6 +24,7 @@ WRAP_WATCOM_FUNC2(FrmFrameData*, art_ptr_lock, long, frmId, DWORD*, lockPtr) WRAP_WATCOM_FUNC4(BYTE*, art_ptr_lock_data, long, frmId, long, frameNum, long, rotation, DWORD*, lockPtr) WRAP_WATCOM_FUNC4(BYTE*, art_lock, long, frmId, DWORD*, lockPtr, long*, widthOut, long*, heightOut) WRAP_WATCOM_FUNC1(long, art_ptr_unlock, DWORD, lockId) +WRAP_WATCOM_FUNC2(long, barter_compute_value, GameObject*, source, GameObject*, target) WRAP_WATCOM_FUNC1(void*, dbase_open, const char*, fileName) WRAP_WATCOM_FUNC1(void, dbase_close, void*, dbPtr) WRAP_WATCOM_FUNC3(long, db_freadShortCount, DbFile*, file, WORD*, dest, long, count) @@ -38,6 +39,7 @@ WRAP_WATCOM_FUNC2(long, combat_turn, GameObject*, critter, long, isDudeTurn) WRAP_WATCOM_FUNC1(long, critter_is_dead, GameObject*, critter) WRAP_WATCOM_FUNC1(void, EndLoad, DbFile*, file) WRAP_WATCOM_FUNC1(long, game_get_global_var, long, globalVar) +WRAP_WATCOM_FUNC1(void, gdialogDisplayMsg, const char*, message) WRAP_WATCOM_FUNC1(long, gmouse_3d_set_mode, long, mode) WRAP_WATCOM_FUNC1(long, gmouse_set_cursor, long, picNum) WRAP_WATCOM_FUNC1(Window*, GNW_find, long, winRef) @@ -45,6 +47,8 @@ WRAP_WATCOM_FUNC0(long, intface_is_item_right_hand) WRAP_WATCOM_FUNC0(void, intface_toggle_item_state) WRAP_WATCOM_FUNC0(void, intface_use_item) WRAP_WATCOM_FUNC0(long, is_pc_sneak_working) +WRAP_WATCOM_FUNC1(long, item_caps_total, GameObject*, object) +WRAP_WATCOM_FUNC1(long, item_total_cost, GameObject*, object) WRAP_WATCOM_FUNC1(long, item_w_anim_code, GameObject*, item) WRAP_WATCOM_FUNC2(long, item_w_anim_weap, GameObject*, item, DWORD, hitMode) WRAP_WATCOM_FUNC2(long, item_w_compute_ammo_cost, GameObject*, item, DWORD*, rounds) diff --git a/sfall/Modules/BugFixes.cpp b/sfall/Modules/BugFixes.cpp index 83b951be..85767b5f 100644 --- a/sfall/Modules/BugFixes.cpp +++ b/sfall/Modules/BugFixes.cpp @@ -1142,6 +1142,88 @@ static void __declspec(naked) compute_damage_hack() { } } +static int currDescLen = 0; +static char textBuf[355]; +static bool showItemDescription = false; +static void __stdcall AppendText(const char* text, const char* desc) { + if (showItemDescription && currDescLen == 0) { + strncpy_s(textBuf, desc, 161); + int len = strlen(textBuf); + if (len > 160) { + len = 158; + textBuf[len++] = '.'; + textBuf[len++] = '.'; + textBuf[len++] = '.'; + } + textBuf[len++] = ' '; + textBuf[len] = 0; + currDescLen = len; + } else if (currDescLen == 0) { + textBuf[0] = 0; + } + + strncat(textBuf, text, 64); + currDescLen += strlen(text); + if (currDescLen < 300) { + textBuf[currDescLen++] = '.'; + textBuf[currDescLen++] = ' '; + textBuf[currDescLen] = 0; + } +} + +static void __declspec(naked) obj_examine_func_hack_ammo0() { + __asm { + cmp dword ptr [esp + 0x1AC - 0x14 + 4], 0x445448; // gdialogDisplayMsg_ + jnz skip; + pushad; + push esi; + push eax; + call AppendText; + popad; + retn; +skip: + jmp dword ptr [esp + 0x1AC - 0x14 + 4]; + } +} + +static void __declspec(naked) obj_examine_func_hack_ammo1() { + __asm { + cmp dword ptr [esp + 0x1AC - 0x14 + 4], 0x445448; // gdialogDisplayMsg_ + jnz skip; + pushad; + push 0; + push eax; + call AppendText; + mov currDescLen, 0; + popad; + lea eax, [textBuf]; + jmp fo::funcoffs::gdialogDisplayMsg_; +skip: + jmp dword ptr [esp + 0x1AC - 0x14 + 4]; + } +} + +static void __declspec(naked) obj_examine_func_hack_weapon() { + __asm { + cmp dword ptr [esp + 0x1AC - 0x14], 0x445448; // gdialogDisplayMsg_ + jnz skip; + pushad; + push esi; + push eax; + call AppendText; + mov eax, currDescLen; + sub eax, 2; + mov byte ptr textBuf[eax], 0; // cutoff last character + mov currDescLen, 0; + popad; + lea eax, [textBuf]; +skip: + mov ecx, 0x49B63C; + jmp ecx; + } +} + + void BugFixes::init() { #ifndef NDEBUG @@ -1465,6 +1547,19 @@ void BugFixes::init() dlog("Applying instant death fix.", DL_INIT); MakeJump(0x424BA2, compute_damage_hack); dlogr(" Done", DL_INIT); + + // Fix descriptions info items weapon/ammo in barter + dlog("Applying barter item description fix.", DL_INIT); + MakeCalls(obj_examine_func_hack_ammo0, {0x49B4AD, 0x49B504}); + SafeWrite16(0x49B4B2, 0x9090); + SafeWrite16(0x49B509, 0x9090); + MakeCall(0x49B563, obj_examine_func_hack_ammo1); + SafeWrite16(0x49B568, 0x9090); + showItemDescription = (GetConfigInt("Misc", "BarterItemDescriptions", 1) != 0); + if (showItemDescription) { + HookCall(0x49B452, obj_examine_func_hack_weapon); // it's jump + } + dlogr(" Done", DL_INIT); } diff --git a/sfall/Modules/HookScripts.cpp b/sfall/Modules/HookScripts.cpp index d2677421..b3649a19 100644 --- a/sfall/Modules/HookScripts.cpp +++ b/sfall/Modules/HookScripts.cpp @@ -78,6 +78,7 @@ static HooksInjectInfo injectHooks[] = { {HOOK_GAMEMODECHANGE, nullptr, true}, // always embedded to the engine {HOOK_USEANIMOBJ, Inject_UseAnimateObjHook, false}, {HOOK_EXPLOSIVETIMER, Inject_ExplosiveTimerHook, false}, + {HOOK_DESCRIPTIONOBJ, Inject_DescriptionObjHook, false}, }; bool HookScripts::injectAllHooks; diff --git a/sfall/Modules/HookScripts.h b/sfall/Modules/HookScripts.h index 19d60289..bf45c30a 100644 --- a/sfall/Modules/HookScripts.h +++ b/sfall/Modules/HookScripts.h @@ -60,6 +60,7 @@ enum HookType HOOK_GAMEMODECHANGE = 31, HOOK_USEANIMOBJ = 32, HOOK_EXPLOSIVETIMER = 33, + HOOK_DESCRIPTIONOBJ = 34, HOOK_COUNT }; diff --git a/sfall/Modules/HookScripts/MiscHs.cpp b/sfall/Modules/HookScripts/MiscHs.cpp index c3ef67c2..1b0c3716 100644 --- a/sfall/Modules/HookScripts/MiscHs.cpp +++ b/sfall/Modules/HookScripts/MiscHs.cpp @@ -10,133 +10,173 @@ namespace sfall { +static DWORD __fastcall BarterPriceHook_Script(register fo::GameObject* source, register fo::GameObject* target, DWORD callAddr) { + + int computeCost = fo::func::barter_compute_value(source, target); + + BeginHook(); + argCount = 9; + + args[0] = (DWORD)source; + args[1] = (DWORD)target; + args[2] = computeCost; + + fo::GameObject* bTable = (fo::GameObject*)fo::var::btable; + args[3] = (DWORD)bTable; + args[4] = fo::func::item_caps_total(bTable); + args[5] = fo::func::item_total_cost(bTable); + + fo::GameObject* pTable = (fo::GameObject*)fo::var::ptable; + args[6] = (DWORD)pTable; + int pcCost = fo::func::item_total_cost(pTable); + args[7] = pcCost; + + args[8] = (DWORD)(callAddr == 0x474D51); // check offers button + + RunHookScript(HOOK_BARTERPRICE); + EndHook(); + + return (callAddr == 0x47551F) ? pcCost : computeCost; +} + static void __declspec(naked) BarterPriceHook() { __asm { - hookbegin(9); - mov args[0], eax; - mov args[4], edx; - call fo::funcoffs::barter_compute_value_; - mov edx, ds:[FO_VAR_btable]; - mov args[8], eax; - mov args[12], edx; - xchg eax, edx; - call fo::funcoffs::item_caps_total_; - mov args[16], eax; - mov eax, ds:[FO_VAR_btable]; - call fo::funcoffs::item_total_cost_; - mov args[20], eax; - mov eax, ds:[FO_VAR_ptable]; - mov args[24], eax; - call fo::funcoffs::item_total_cost_; - mov args[28], eax; - xor eax, eax; - mov edx, [esp]; // check offers button - cmp edx, 0x474D51; // last address on call stack - jne skip; - inc eax; + push edx; + push ecx; + //------- + push [esp + 8]; // address on call stack + mov ecx, eax; // source + call BarterPriceHook_Script; // edx - target + pop ecx; + pop edx; + cmp cRet, 1; + jb skip; + cmp rets[0], -1; + cmovg eax, rets[0]; skip: - mov args[32], eax; - mov eax, args[8]; - pushad; - push HOOK_BARTERPRICE; - call RunHookScript; - popad; - cmp cRet, 1; - jl end; - mov eax, rets[0]; -end: - hookend; retn; } } +static DWORD offersGoodsCost; // keep last cost +static void __declspec(naked) PC_BarterPriceHook() { + __asm { + push edx; + push ecx; + //------- + push [esp + 8]; // address on call stack + mov ecx, dword ptr ds:[FO_VAR_obj_dude]; // source + mov edx, dword ptr ds:[FO_VAR_target_stack]; // target + call BarterPriceHook_Script; + pop ecx; + pop edx; + cmp cRet, 2; + cmovnb eax, rets[4]; + mov offersGoodsCost, eax; + retn; + } +} + +static const DWORD OverrideCostRet = 0x474D44; +static void __declspec(naked) OverrideCost_BarterPriceHack() { + __asm { + mov eax, offersGoodsCost; + jmp OverrideCostRet; + } +} + static void __declspec(naked) UseSkillHook() { __asm { - hookbegin(4); - mov args[0], eax; // user - mov args[4], edx; // target - mov args[8], ebx; // skill id + HookBegin; + mov args[0], eax; // user + mov args[4], edx; // target + mov args[8], ebx; // skill id mov args[12], ecx; // skill bonus pushad; - push HOOK_USESKILL; - call RunHookScript; + } + + argCount = 4; + RunHookScript(HOOK_USESKILL); + EndHook(); + + __asm { popad; cmp cRet, 1; - jl defaulthandler; + jb defaultHandler; cmp rets[0], -1; - je defaulthandler; + je defaultHandler; mov eax, rets[0]; - jmp end; -defaulthandler: - call fo::funcoffs::skill_use_; -end: - hookend; retn; +defaultHandler: + jmp fo::funcoffs::skill_use_; } } static void __declspec(naked) StealCheckHook() { __asm { - hookbegin(4); - mov args[0], eax; // thief - mov args[4], edx; // target - mov args[8], ebx; // item + HookBegin; + mov args[0], eax; // thief + mov args[4], edx; // target + mov args[8], ebx; // item mov args[12], ecx; // is planting pushad; - push HOOK_STEAL; - call RunHookScript; + } + + argCount = 4; + RunHookScript(HOOK_STEAL); + EndHook(); + + __asm { popad; cmp cRet, 1; - jl defaulthandler; + jb defaultHandler; cmp rets[0], -1; - je defaulthandler; + je defaultHandler; mov eax, rets[0]; - jmp end; -defaulthandler: - call fo::funcoffs::skill_check_stealing_; -end: - hookend; retn; +defaultHandler: + jmp fo::funcoffs::skill_check_stealing_; } } static void __declspec(naked) PerceptionRangeHook() { __asm { - hookbegin(3); - mov args[0], eax; // watcher - mov args[4], edx; // target + HookBegin; + mov args[0], eax; // watcher + mov args[4], edx; // target call fo::funcoffs::is_within_perception_; - mov args[8], eax; // check result + mov args[8], eax; // check result pushad; - push HOOK_WITHINPERCEPTION; - call RunHookScript; + } + + argCount = 3; + RunHookScript(HOOK_WITHINPERCEPTION); + EndHook(); + + __asm { popad; cmp cRet, 1; - jl end; - mov eax, rets[0]; -end: - hookend; + cmovnb eax, rets[0]; retn; } } -// jmp here, not call static const DWORD PerceptionRangeBonusHack_back = 0x456BA7; -static const DWORD PerceptionRangeBonusHack_skip_blocking_check = 0x456BDC; +static const DWORD PerceptionRangeBonusHack_skip = 0x456BDC; static void __declspec(naked) PerceptionRangeBonusHack() { __asm { call PerceptionRangeHook; - cmp eax, 2; - jne nevermind; - mov dword ptr[esp + 16], 1; - jmp PerceptionRangeBonusHack_skip_blocking_check; + cmp eax, 2; + jne nevermind; // return + mov dword ptr[esp + 16], 1; + jmp PerceptionRangeBonusHack_skip; // skip blocking check nevermind: - jmp PerceptionRangeBonusHack_back; + jmp PerceptionRangeBonusHack_back; } } static constexpr long maxGasAmount = 80000; -static void CarTravelHookScript() { +static void CarTravelHook_Script() { BeginHook(); argCount = 2; // calculate vanilla speed @@ -184,13 +224,13 @@ static const DWORD CarTravelHack_back = 0x4BFF43; static void __declspec(naked) CarTravelHack() { __asm { pushad; - call CarTravelHookScript; + call CarTravelHook_Script; popad; jmp CarTravelHack_back; } } -static void __fastcall GlobalVarHookScript(DWORD number, int value) { +static void __fastcall GlobalVarHook_Script(DWORD number, int value) { int old = fo::var::game_global_vars[number]; BeginHook(); @@ -211,17 +251,17 @@ static void __fastcall GlobalVarHookScript(DWORD number, int value) { static void __declspec(naked) SetGlobalVarHook() { __asm { pushad; - mov ecx, eax; // number - call GlobalVarHookScript; // edx - value + mov ecx, eax; // number + call GlobalVarHook_Script; // edx - value popad; cmp cRet, 1; - cmovae edx, dword ptr rets[0]; + cmovnb edx, dword ptr rets[0]; jmp fo::funcoffs::game_set_global_var_; } } static int restTicks; -static void _stdcall RestTimerHookScript() { +static void _stdcall RestTimerHook_Script() { DWORD addrHook; __asm { mov addrHook, ebx; @@ -247,34 +287,34 @@ static void _stdcall RestTimerHookScript() { static void __declspec(naked) RestTimerLoopHook() { __asm { pushad; - mov ebx, [esp + 32]; - mov ecx, [esp + 36 + 0x40]; // hours_ - mov edx, [esp + 36 + 0x44]; // minutes_ - call RestTimerHookScript; + mov ebx, [esp + 32]; + mov ecx, [esp + 36 + 0x40]; // hours_ + mov edx, [esp + 36 + 0x44]; // minutes_ + call RestTimerHook_Script; popad; - cmp cRet, 1; - jl skip; - cmp rets[0], 1; + cmp cRet, 1; + jb skip; + cmp rets[0], 1; cmovz edi, rets[0]; skip: - jmp fo::funcoffs::set_game_time_; + jmp fo::funcoffs::set_game_time_; } } static void __declspec(naked) RestTimerEscapeHook() { __asm { - cmp eax, 0x1B; // ESC ASCII code - jnz skip; + cmp eax, 0x1B; // ESC ASCII code + jnz skip; pushad; - mov ebx, [esp + 32]; - mov ecx, [esp + 36 + 0x40]; // hours_ - mov edx, [esp + 36 + 0x44]; // minutes_ - call RestTimerHookScript; + mov ebx, [esp + 32]; + mov ecx, [esp + 36 + 0x40]; // hours_ + mov edx, [esp + 36 + 0x44]; // minutes_ + call RestTimerHook_Script; popad; - mov edi, 1; - cmp cRet, 1; - jl skip; - cmp rets[0], 0; + mov edi, 1; + cmp cRet, 1; + jb skip; + cmp rets[0], 0; cmovz edi, rets[0]; // ret 0 for cancel escape skip: retn; @@ -296,7 +336,7 @@ static int __fastcall ExplosiveTimerHook_Script(DWORD type, DWORD item, DWORD ti int result = 0; if (cRet > 0 && rets[0] >= 0) { if (rets[0] > 18000) rets[0] = 18000; // max 30 minutes - if (cRet < 2) { + if (cRet < 2 || (rets[1] < fo::ROLL_CRITICAL_FAILURE || rets[1] > fo::ROLL_CRITICAL_SUCCESS)) { result--; // use vanilla type } else { result++; // use returned type @@ -306,6 +346,7 @@ static int __fastcall ExplosiveTimerHook_Script(DWORD type, DWORD item, DWORD ti } static void _declspec(naked) ExplosiveTimerHook() { + using namespace fo; __asm { push eax; push edx; @@ -321,7 +362,7 @@ static void _declspec(naked) ExplosiveTimerHook() { mov eax, rets[0]; // time in ticks jl end; mov ecx, 8; // type SUCCESS - cmp rets[4], 1; + cmp rets[4], ROLL_FAILURE; jg end; add ecx, 3; // type FAILURE (11) end: @@ -336,6 +377,8 @@ void Inject_BarterPriceHook() { 0x475735, 0x475762 }); + HookCall(0X47551A, PC_BarterPriceHook); + MakeJump(0x474D3F, OverrideCost_BarterPriceHack); // just overrides cost of offered goods } void Inject_UseSkillHook() { diff --git a/sfall/Modules/HookScripts/ObjectHs.cpp b/sfall/Modules/HookScripts/ObjectHs.cpp index 991f6045..1a8a89f0 100644 --- a/sfall/Modules/HookScripts/ObjectHs.cpp +++ b/sfall/Modules/HookScripts/ObjectHs.cpp @@ -129,6 +129,31 @@ end: } } +static void __stdcall DescriptionObjHook_Script(DWORD object) { + BeginHook(); + argCount = 1; + + args[0] = object; + + RunHookScript(HOOK_DESCRIPTIONOBJ); + EndHook(); +} + +static void __declspec(naked) DescriptionObjHook() { + __asm { + pushad; + push eax; // object + call DescriptionObjHook_Script; + popad; + cmp cRet, 1; + jb skip; + mov eax, rets[0]; // pointer to text + retn; +skip: + jmp fo::funcoffs::item_description_; + } +} + void Inject_UseObjOnHook() { HookCalls(UseObjOnHook, { 0x49C606, 0x473619 }); @@ -149,11 +174,16 @@ void Inject_UseAnimateObjHook() { HookCalls(UseAnimateObjHook, { 0x4120C1, 0x412292 }); } +void Inject_DescriptionObjHook() { + HookCall(0x48C925, DescriptionObjHook); +} + void InitObjectHookScripts() { LoadHookScript("hs_useobjon", HOOK_USEOBJON); LoadHookScript("hs_useobj", HOOK_USEOBJ); LoadHookScript("hs_useanimobj", HOOK_USEANIMOBJ); + LoadHookScript("hs_descriptionobj", HOOK_DESCRIPTIONOBJ); } } diff --git a/sfall/Modules/HookScripts/ObjectHs.h b/sfall/Modules/HookScripts/ObjectHs.h index 36badff6..9bc5396a 100644 --- a/sfall/Modules/HookScripts/ObjectHs.h +++ b/sfall/Modules/HookScripts/ObjectHs.h @@ -7,4 +7,5 @@ namespace sfall void Inject_UseObjOnHook(); void Inject_UseObjHook(); void Inject_UseAnimateObjHook(); + void Inject_DescriptionObjHook(); } diff --git a/sfall/Modules/Scripting/Handlers/Interface.cpp b/sfall/Modules/Scripting/Handlers/Interface.cpp index 89dab2eb..28563c0d 100644 --- a/sfall/Modules/Scripting/Handlers/Interface.cpp +++ b/sfall/Modules/Scripting/Handlers/Interface.cpp @@ -434,5 +434,12 @@ void sf_inventory_redraw(OpcodeContext& ctx) { } } +void sf_dialog_message(OpcodeContext& ctx) { + if (GetLoopFlags() & DIALOG) { + const char* message = ctx.arg(0).asString(); + fo::func::gdialogDisplayMsg(message); + } +} + } } diff --git a/sfall/Modules/Scripting/Handlers/Interface.h b/sfall/Modules/Scripting/Handlers/Interface.h index c10710ea..d25f4820 100644 --- a/sfall/Modules/Scripting/Handlers/Interface.h +++ b/sfall/Modules/Scripting/Handlers/Interface.h @@ -93,5 +93,7 @@ void sf_set_iface_tag_text(OpcodeContext&); void sf_inventory_redraw(OpcodeContext&); +void sf_dialog_message(OpcodeContext&); + } } diff --git a/sfall/Modules/Scripting/Handlers/Metarule.cpp b/sfall/Modules/Scripting/Handlers/Metarule.cpp index d149ee9d..063ea876 100644 --- a/sfall/Modules/Scripting/Handlers/Metarule.cpp +++ b/sfall/Modules/Scripting/Handlers/Metarule.cpp @@ -80,6 +80,7 @@ static const SfallMetarule metarules[] = { {"attack_is_aimed", sf_attack_is_aimed, 0, 0}, {"car_gas_amount", sf_car_gas_amount, 0, 0}, {"critter_inven_obj2", sf_critter_inven_obj2, 2, 2, {ARG_OBJECT, ARG_INT}}, + {"dialog_message", sf_dialog_message, 1, 1, {ARG_STRING}}, {"display_stats", sf_display_stats, 0, 0}, {"exec_map_update_scripts", sf_exec_map_update_scripts, 0, 0}, {"floor2", sf_floor2, 1, 1, {ARG_NUMBER}}, @@ -90,6 +91,7 @@ static const SfallMetarule metarules[] = { {"get_map_enter_position", sf_get_map_enter_position, 0, 0}, {"get_metarule_table", sf_get_metarule_table, 0, 0}, {"get_outline", sf_get_outline, 1, 1, {ARG_OBJECT}}, + {"get_string_pointer", sf_get_string_pointer, 1, 1, {ARG_STRING}}, {"intface_hide", sf_intface_hide, 0, 0}, {"intface_is_hidden", sf_intface_is_hidden, 0, 0}, {"intface_redraw", sf_intface_redraw, 0, 0}, diff --git a/sfall/Modules/Scripting/Handlers/Utils.cpp b/sfall/Modules/Scripting/Handlers/Utils.cpp index b0faecb5..3854b8f5 100644 --- a/sfall/Modules/Scripting/Handlers/Utils.cpp +++ b/sfall/Modules/Scripting/Handlers/Utils.cpp @@ -349,5 +349,9 @@ void sf_floor2(OpcodeContext& ctx) { ctx.setReturn(static_cast(floor(ctx.arg(0).asFloat()))); } +void sf_get_string_pointer(OpcodeContext& ctx) { + ctx.setReturn(reinterpret_cast(ctx.arg(0).asString()), DataType::INT); +} + } } diff --git a/sfall/Modules/Scripting/Handlers/Utils.h b/sfall/Modules/Scripting/Handlers/Utils.h index dfd8be06..d9e8464e 100644 --- a/sfall/Modules/Scripting/Handlers/Utils.h +++ b/sfall/Modules/Scripting/Handlers/Utils.h @@ -69,6 +69,8 @@ void sf_message_str_game(OpcodeContext&); void sf_floor2(OpcodeContext&); +void sf_get_string_pointer(OpcodeContext&); + char* _stdcall Substring(const char* str, int pos, int length); }