From 2059a3da8cb2832ae8fb783e3f2413b98341b1c8 Mon Sep 17 00:00:00 2001 From: NovaRain Date: Wed, 8 May 2019 21:04:18 +0800 Subject: [PATCH] Backported 3 script functions from 4.1: * dialog_obj, loot_obj, and npc_engine_level_up. --- artifacts/scripting/headers/sfall.h | 3 +++ artifacts/scripting/sfall function notes.txt | 10 +++++++ sfall/LoadGameHook.cpp | 8 ++++++ sfall/LoadGameHook.h | 3 +++ sfall/PartyControl.cpp | 28 +++++++++++++------- sfall/PartyControl.h | 2 ++ sfall/ScriptOps/MetaruleOp.hpp | 3 +++ sfall/ScriptOps/MiscOps.hpp | 10 +++++++ sfall/ScriptOps/ObjectsOps.hpp | 8 ++++++ 9 files changed, 65 insertions(+), 10 deletions(-) diff --git a/artifacts/scripting/headers/sfall.h b/artifacts/scripting/headers/sfall.h index dd658429..c326a6b0 100644 --- a/artifacts/scripting/headers/sfall.h +++ b/artifacts/scripting/headers/sfall.h @@ -219,6 +219,7 @@ #define create_win(winName, x, y, w, h) sfall_func5("create_win", winName, x, y, w, h) #define create_win_flag(winName, x, y, w, h, flag) sfall_func6("create_win", winName, x, y, w, h, flag) #define critter_inven_obj2(obj, type) sfall_func2("critter_inven_obj2", obj, type) +#define dialog_obj sfall_func0("dialog_obj") #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) @@ -235,6 +236,8 @@ #define inventory_redraw(invSide) sfall_func1("inventory_redraw", invSide) #define item_weight(obj) sfall_func1("item_weight", obj) #define lock_is_jammed(obj) sfall_func1("lock_is_jammed", obj) +#define loot_obj sfall_func0("loot_obj") +#define npc_engine_level_up(toggle) sfall_func1("npc_engine_level_up", toggle) #define obj_under_cursor(crSwitch, inclDude) sfall_func2("obj_under_cursor", crSwitch, inclDude) #define outlined_object sfall_func0("outlined_object") #define set_cursor_mode(mode) sfall_func1("set_cursor_mode", mode) diff --git a/artifacts/scripting/sfall function notes.txt b/artifacts/scripting/sfall function notes.txt index c65c562f..76dbf302 100644 --- a/artifacts/scripting/sfall function notes.txt +++ b/artifacts/scripting/sfall function notes.txt @@ -458,11 +458,17 @@ Some utility/math functions are available: - works just like vanilla CreateWin function, but creates a window with MoveOnTop flag if the flags argument is not specified, and allows to set additional flags for the created window - MoveOnTop flag allows the created window to be placed on top of the game interface +> object sfall_func0("dialog_obj") +- returns a pointer to the object (critter) the player is having a conversation or bartering with + > object sfall_func2("obj_under_cursor", bool crSwitch, bool inclDude) - returns the object under the cursor on the main game screen - crSwitch: True - only checks critters and ignores their cover (roof tiles, walls, scenery, etc.), False - checks all objects (can't check critters under objects) - passing False to the inclDude argument will ignore dude_obj +> object sfall_func0("loot_obj") +- returns a pointer to the target object (container or critter) of the loot screen + > int sfall_func2("get_object_data", object, int offset) - returns the data at the specified offset of an object (see OBJ_DATA_* constants in define_extra.h for offsets) @@ -472,6 +478,10 @@ Some utility/math functions are available: > void sfall_func0("art_cache_clear") - clears the cache of FRM image files loaded into memory +> void sfall_func1("npc_engine_level_up", bool toggle) +- enables/disables the engine function that increases the level of party members in the player leveling process +- if the engine function is disabled, the process of leveling up party members should be performed by script functions + > int sfall_func1("set_unique_id", object) > int sfall_func2("set_unique_id", object, int flag) - assigns a unique ID number to the object and returns it. If a unique ID number has already been assigned to an object, then ID number is returned without reassignment diff --git a/sfall/LoadGameHook.cpp b/sfall/LoadGameHook.cpp index 237da25e..1ca7006a 100644 --- a/sfall/LoadGameHook.cpp +++ b/sfall/LoadGameHook.cpp @@ -48,6 +48,8 @@ #define MAX_GLOBAL_SIZE (MaxGlobalVars * 12 + 4) +DWORD LoadGameHook_LootTarget = 0; + static DWORD InLoop = 0; static DWORD SaveInCombatFix; static bool mapLoaded = false; @@ -64,6 +66,10 @@ DWORD InCombat() { return (InLoop & COMBAT) ? 1 : 0; } +DWORD InDialog() { + return (InLoop & DIALOG) ? 1 : 0; +} + DWORD GetCurrentLoops() { return InLoop; } @@ -85,6 +91,7 @@ static void _stdcall ResetState(DWORD onLoad) { ClearSavPrototypes(); ResetExplosionRadius(); PartyControlReset(); + NpcEngineLevelUpReset(); } void GetSavePath(char* buf, char* ftype) { @@ -489,6 +496,7 @@ static void __declspec(naked) UseInventoryOnHook() { static void __declspec(naked) LootContainerHook() { __asm { + mov LoadGameHook_LootTarget, edx; or InLoop, INTFACELOOT; call loot_container_; and InLoop, (-1 ^ INTFACELOOT); diff --git a/sfall/LoadGameHook.h b/sfall/LoadGameHook.h index 1d35cfd5..41c5ad02 100644 --- a/sfall/LoadGameHook.h +++ b/sfall/LoadGameHook.h @@ -18,11 +18,14 @@ #pragma once +extern DWORD LoadGameHook_LootTarget; + void LoadGameHookInit(); bool IsMapLoaded(); DWORD InWorldMap(); DWORD InCombat(); +DWORD InDialog(); #define WORLDMAP (1<<0) // 0x1 #define LOCALMAP (1<<1) // 0x2 No point hooking this: would always be 1 at any point at which scripts are running diff --git a/sfall/PartyControl.cpp b/sfall/PartyControl.cpp index d640cb7c..b0ec7684 100644 --- a/sfall/PartyControl.cpp +++ b/sfall/PartyControl.cpp @@ -32,6 +32,7 @@ #include "PartyControl.h" bool npcAutoLevelEnabled; +bool npcEngineLevelUp = true; static DWORD Mode; static int IsControllingNPC = 0; @@ -356,6 +357,16 @@ end: } } +void __stdcall PartyControlReset() { + if (real_dude != nullptr && IsControllingNPC > 0) { + RestoreRealDudeState(); + } +} + +bool IsNpcControlled() { + return IsControllingNPC != 0; +} + static char levelMsg[12], armorClassMsg[12], addictMsg[16]; static void __fastcall PartyMemberPrintStat(BYTE* surface, DWORD toWidth) { const char* fmt = "%s %d"; @@ -404,6 +415,13 @@ static void NpcAutoLevelPatch() { } } +void NpcEngineLevelUpReset() { + if (!npcEngineLevelUp) { + npcEngineLevelUp = true; + SafeWrite16(0x4AFC1C, 0x840F); + } +} + void PartyControlInit() { Mode = GetPrivateProfileIntA("Misc", "ControlCombat", 0, ini); if (Mode > 2) @@ -454,13 +472,3 @@ void PartyControlInit() { dlogr(" Done", DL_INIT); } } - -void __stdcall PartyControlReset() { - if (real_dude != nullptr && IsControllingNPC > 0) { - RestoreRealDudeState(); - } -} - -bool IsNpcControlled() { - return IsControllingNPC != 0; -} diff --git a/sfall/PartyControl.h b/sfall/PartyControl.h index 8c717d70..8adca1f1 100644 --- a/sfall/PartyControl.h +++ b/sfall/PartyControl.h @@ -19,8 +19,10 @@ #pragma once extern bool npcAutoLevelEnabled; +extern bool npcEngineLevelUp; void PartyControlInit(); void __stdcall PartyControlReset(); int __stdcall PartyControl_SwitchHandHook(TGameObj* item); bool IsNpcControlled(); +void NpcEngineLevelUpReset(); diff --git a/sfall/ScriptOps/MetaruleOp.hpp b/sfall/ScriptOps/MetaruleOp.hpp index 329d5219..c21984e5 100644 --- a/sfall/ScriptOps/MetaruleOp.hpp +++ b/sfall/ScriptOps/MetaruleOp.hpp @@ -108,6 +108,7 @@ static const SfallMetarule metaruleArray[] = { {"attack_is_aimed", sf_attack_is_aimed, 0, 0}, {"critter_inven_obj2", sf_critter_inven_obj2, 2, 2}, {"create_win", sf_create_win, 5, 6}, + {"dialog_obj", sf_get_dialog_object, 0, 0}, {"display_stats", sf_display_stats, 0, 0}, {"exec_map_update_scripts", sf_exec_map_update_scripts, 0, 0}, {"floor2", sf_floor2, 1, 1}, @@ -125,6 +126,8 @@ static const SfallMetarule metaruleArray[] = { {"inventory_redraw", sf_inventory_redraw, 1, 1}, {"item_weight", sf_item_weight, 1, 1}, {"lock_is_jammed", sf_lock_is_jammed, 1, 1}, + {"loot_obj", sf_get_loot_object, 0, 0}, + {"npc_engine_level_up", sf_npc_engine_level_up, 1, 1}, {"obj_under_cursor", sf_get_obj_under_cursor, 2, 2}, {"outlined_object", sf_outlined_object, 0, 0}, {"set_cursor_mode", sf_set_cursor_mode, 1, 1}, diff --git a/sfall/ScriptOps/MiscOps.hpp b/sfall/ScriptOps/MiscOps.hpp index 92a52c7e..e129ef61 100644 --- a/sfall/ScriptOps/MiscOps.hpp +++ b/sfall/ScriptOps/MiscOps.hpp @@ -1488,3 +1488,13 @@ static void sf_set_ini_setting() { break; } } + +static void sf_npc_engine_level_up() { + if (opHandler.arg(0).asBool()) { + if (!npcEngineLevelUp) SafeWrite16(0x4AFC1C, 0x840F); // enable + npcEngineLevelUp = true; + } else { + if (npcEngineLevelUp) SafeWrite16(0x4AFC1C, 0xE990); + npcEngineLevelUp = false; + } +} diff --git a/sfall/ScriptOps/ObjectsOps.hpp b/sfall/ScriptOps/ObjectsOps.hpp index e05bc983..6ade71f8 100644 --- a/sfall/ScriptOps/ObjectsOps.hpp +++ b/sfall/ScriptOps/ObjectsOps.hpp @@ -619,6 +619,10 @@ static void sf_get_current_inven_size() { opHandler.setReturn(sf_item_total_size(opHandler.arg(0).asObject()), DATATYPE_INT); } +static void sf_get_dialog_object() { + opHandler.setReturn(InDialog() ? *ptr_dialog_target : 0, DATATYPE_INT); +} + static void sf_get_obj_under_cursor() { int crSwitch = opHandler.arg(0).asBool() ? 1 : -1, inclDude = opHandler.arg(1).rawValue(), @@ -634,6 +638,10 @@ static void sf_get_obj_under_cursor() { opHandler.setReturn(obj); } +static void sf_get_loot_object() { + opHandler.setReturn((GetCurrentLoops() & INTFACELOOT) ? LoadGameHook_LootTarget : 0, DATATYPE_INT); +} + static void sf_get_object_data() { BYTE* object_ptr = (BYTE*)opHandler.arg(0).asObject(); opHandler.setReturn(*(long*)(object_ptr + opHandler.arg(1).asInt()), DATATYPE_INT);