diff --git a/artifacts/scripting/headers/define_extra.h b/artifacts/scripting/headers/define_extra.h index 2de1909c..88e5c9d5 100644 --- a/artifacts/scripting/headers/define_extra.h +++ b/artifacts/scripting/headers/define_extra.h @@ -87,7 +87,6 @@ #define FLAG_SEEN (0x40000000) #define FLAG_SHOOTTHRU (0x80000000) - /* Critter Flags */ #define CFLG_BARTER 2 // 0x00000002 - Barter (can trade with) #define CFLG_NOSTEAL 32 // 0x00000020 - Steal (cannot steal from) @@ -101,6 +100,13 @@ #define CFLG_RANGED 8192 // 0x00002000 - Range (melee attack is possible at a distance) #define CFLG_NOKNOCKDOWN 16384 // 0x00004000 - Knock (cannot be knocked down) +/* Window Flags */ +#define WIN_FLAG_MOVEONTOP (0x4) +#define WIN_FLAG_HIDDEN (0x8) +#define WIN_FLAG_EXCLUSIVE (0x10) +#define WIN_FLAG_TRANSPARENT (0x20) + + //remove inven obj defines #define RMOBJ_CONSUME_DRUG 4666772 #define RMOBJ_CONTAINER 4683293 // same as RMOBJ_TRADE diff --git a/artifacts/scripting/headers/sfall.h b/artifacts/scripting/headers/sfall.h index fa3dff18..d616f8c1 100644 --- a/artifacts/scripting/headers/sfall.h +++ b/artifacts/scripting/headers/sfall.h @@ -277,9 +277,11 @@ #define get_object_ai_data(obj, aiParam) sfall_func2("get_object_ai_data", obj, aiParam) #define get_object_data(obj, offset) sfall_func2("get_object_data", obj, offset) #define get_outline(obj) sfall_func1("get_outline", obj) +#define get_sfall_arg_at(argNum) sfall_func1("get_sfall_arg_at", argNum) #define get_string_pointer(text) sfall_func1("get_string_pointer", text) #define has_fake_perk_npc(npc, perk) sfall_func2("has_fake_perk_npc", npc, perk) #define has_fake_trait_npc(npc, trait) sfall_func2("has_fake_trait_npc", npc, trait) +#define hide_window(winName) sfall_func1("hide_window", winName) #define intface_hide sfall_func0("intface_hide") #define intface_is_hidden sfall_func0("intface_is_hidden") #define intface_redraw sfall_func0("intface_redraw") @@ -312,6 +314,8 @@ #define set_unique_id(obj) sfall_func1("set_unique_id", obj) #define unset_unique_id(obj) sfall_func2("set_unique_id", obj, -1) #define set_unjam_locks_time(time) sfall_func1("set_unjam_locks_time", time) +#define set_window_flag(winID, flag, value) sfall_func3("set_window_flag", winID, flag, value) +#define show_window(winName) sfall_func1("show_window", winName) #define spatial_radius(obj) sfall_func1("spatial_radius", obj) #define tile_refresh_display sfall_func0("tile_refresh_display") #define unjam_lock(obj) sfall_func1("unjam_lock", obj) diff --git a/artifacts/scripting/hookscripts.txt b/artifacts/scripting/hookscripts.txt index 9e601a0d..8fdf0500 100644 --- a/artifacts/scripting/hookscripts.txt +++ b/artifacts/scripting/hookscripts.txt @@ -30,6 +30,7 @@ The hook script equivalent of game_loaded; it returns 2 when the script is first > mixed get_sfall_arg() Gets the next argument from sfall. Each time it's called it returns the next argument, or otherwise it returns 0 if there are no more arguments left. +You can arbitrarily get the value of any argument using the sfall_func1("get_sfall_arg_at", argNum) function. > array get_sfall_args() Returns all hook arguments as a new temp array. @@ -37,8 +38,8 @@ Returns all hook arguments as a new temp array. > void set_sfall_return(int value) Used to return the new values from the script. Each time it's called it sets the next value, or if you've already set all return values it does nothing. -> void set_sfall_arg(int argnum, int value) -Changes argument value. The argument number (argnum) is 0-indexed. This is useful if you have several hook scripts attached to one hook point (see below). +> void set_sfall_arg(int argNum, int value) +Changes argument value. The argument number (argNum) is 0-indexed. This is useful if you have several hook scripts attached to one hook point (see below). > void register_hook(int hooktype) Used from a normal global script if you want to run it at the same point a full hook script would normally run. In case of this function, "start" proc will be executed in a current global script. You can use all above functions like normal. diff --git a/artifacts/scripting/sfall function notes.txt b/artifacts/scripting/sfall function notes.txt index bfcfcba5..ea82897d 100644 --- a/artifacts/scripting/sfall function notes.txt +++ b/artifacts/scripting/sfall function notes.txt @@ -517,9 +517,10 @@ Some utility/math functions are available: - adds one custom box to the current boxes, and returns the number of the added tag (-1 if the tags limit is exceeded) - The maximum number of boxes is limited to 126 tags +> void sfall_func0("inventory_redraw") > void sfall_func1("inventory_redraw", int invSide) - 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) +- invSide specifies which side needs to be redrawn: 0 - the player, 1 - target (container/NPC in loot/barter screens), -1 - both sides > void sfall_func3("item_make_explosive", int pid, int activePid, int damage) > void sfall_func4("item_make_explosive", int pid, int activePid, int min, int max) @@ -647,6 +648,26 @@ optional argument: > void sfall_func1("remove_timer_event", int param) - removes all timer events with the specified 'param' value for the current global script +> mixed sfall_func1("get_sfall_arg_at", int argNum) +- gets the value of hook argument with the specified argument number (argNum, first argument starts from 0) + +> void sfall_func0("hide_window") +> void sfall_func1("hide_window", string winName) +- hides the specified or currently selected/active script window +- winName: the window name, assigned to the window by the CreateWin/create_win function + +> void sfall_func0("show_window") +> void sfall_func1("show_window", string winName) +- displays the specified hidden script window or the one previously hidden with the sfall_func0("hide_window") function +- winName: the window name, assigned to the window by the CreateWin/create_win function + +> void sfall_func3("set_window_flag", string/int winName/winID, int flag, bool value) +- changes the specified flag for the created script or game interface window +- winName: the window name, assigned to the window by the CreateWin/create_win function +- winID: the ID number of the interface or script window obtained with the get_window_under_mouse function +- flag: the flag to change (see WIN_FLAG_* constants in define_extra.h) +- value: true - set the flag, false - unset the flag + ------------------------ ------ MORE INFO ------- ------------------------ diff --git a/sfall/FalloutEngine/Structs.h b/sfall/FalloutEngine/Structs.h index 2ec0339f..e7153248 100644 --- a/sfall/FalloutEngine/Structs.h +++ b/sfall/FalloutEngine/Structs.h @@ -713,6 +713,25 @@ struct Window { long *drawFunc; }; +struct sWindow { + char name[32]; + long wID; + long width; + long height; + long unknown1; + long unknown2; + long unknown3; + long unknown4; + long *buttons; + long numButtons; + long unknown5; + long unknown6; + long clearColour; + long flags; + long unknown7; + long unknown8; +}; + #pragma pack(1) struct LSData { char signature[24]; diff --git a/sfall/FalloutEngine/VariableOffsets.h b/sfall/FalloutEngine/VariableOffsets.h index e71bbc8a..3cd61264 100644 --- a/sfall/FalloutEngine/VariableOffsets.h +++ b/sfall/FalloutEngine/VariableOffsets.h @@ -212,6 +212,7 @@ #define FO_VAR_stack_offset 0x59E844 #define FO_VAR_stat_data 0x51D53C #define FO_VAR_stat_flag 0x66452A +#define FO_VAR_sWindows 0x6727B0 #define FO_VAR_Tag_ 0x5708B0 #define FO_VAR_tag_skill 0x668070 #define FO_VAR_target_curr_stack 0x59E948 diff --git a/sfall/FalloutEngine/Variables_def.h b/sfall/FalloutEngine/Variables_def.h index 34d02728..c06edc8d 100644 --- a/sfall/FalloutEngine/Variables_def.h +++ b/sfall/FalloutEngine/Variables_def.h @@ -158,7 +158,7 @@ VAR_(pipmesg, DWORD) VAR_(preload_list_index, DWORD) VARA(procTableStrs, const char*, (int)ScriptProc::count) // table of procId (from define.h) => procName map VARA(proto_msg_files, MessageList, 6) // array of 6 elements -VAR_(proto_main_msg_file, MessageList) +VAR_(proto_main_msg_file, MessageList) VAR_(ptable, DWORD) VAR_(pud, DWORD) VAR_(queue, DWORD) @@ -181,6 +181,7 @@ VARA(stack, DWORD, 10) VARA(stack_offset, DWORD, 10) VARA(stat_data, StatInfo, STAT_real_max_stat) // dynamic array VAR_(stat_flag, DWORD) +VARA(sWindows, fo::sWindow, 16) VAR_(Tag_, DWORD) VAR_(tag_skill, DWORD) VAR_(target_curr_stack, DWORD) diff --git a/sfall/Modules/HookScripts.cpp b/sfall/Modules/HookScripts.cpp index 7ea07aaa..bad7d618 100644 --- a/sfall/Modules/HookScripts.cpp +++ b/sfall/Modules/HookScripts.cpp @@ -133,23 +133,27 @@ void HookScripts::GameModeChangeHook(DWORD exit) { } // END HOOKS -DWORD _stdcall GetHSArgCount() { +DWORD HookScripts::GetHSArgCount() { return argCount; } -DWORD _stdcall GetHSArg() { +DWORD HookScripts::GetHSArg() { return (cArg == argCount) ? 0 : args[cArg++]; } -void SetHSArg(DWORD id, DWORD value) { +void HookScripts::SetHSArg(DWORD id, DWORD value) { if (id < argCount) args[id] = value; } -DWORD* GetHSArgs() { +DWORD* HookScripts::GetHSArgs() { return args; } -void _stdcall SetHSReturn(DWORD value) { +DWORD HookScripts::GetHSArgAt(DWORD id) { + return args[id]; +} + +void __stdcall HookScripts::SetHSReturn(DWORD value) { if (cRetTmp < maxRets) { rets[cRetTmp++] = value; } diff --git a/sfall/Modules/HookScripts.h b/sfall/Modules/HookScripts.h index 75c0f8f1..2f5910ad 100644 --- a/sfall/Modules/HookScripts.h +++ b/sfall/Modules/HookScripts.h @@ -84,13 +84,14 @@ public: static void GameModeChangeHook(DWORD exit); static void KeyPressHook(DWORD* dxKey, bool pressed, DWORD vKey); -}; -DWORD _stdcall GetHSArgCount(); -DWORD _stdcall GetHSArg(); -DWORD* GetHSArgs(); -void SetHSArg(DWORD id, DWORD value); -void _stdcall SetHSReturn(DWORD d); + static DWORD GetHSArgCount(); + static DWORD GetHSArg(); + static DWORD GetHSArgAt(DWORD id); + static DWORD* GetHSArgs(); + static void SetHSArg(DWORD id, DWORD value); + static void __stdcall SetHSReturn(DWORD d); +}; // register hook by proc num (special values: -1 - use default (start) procedure, 0 - unregister) void RegisterHook(fo::Program* script, int id, int procNum, bool specReg); diff --git a/sfall/Modules/HookScripts/InventoryHs.cpp b/sfall/Modules/HookScripts/InventoryHs.cpp index febe5bac..4720c1db 100644 --- a/sfall/Modules/HookScripts/InventoryHs.cpp +++ b/sfall/Modules/HookScripts/InventoryHs.cpp @@ -80,7 +80,7 @@ static int __fastcall SwitchHandHook_Script(fo::GameObject* item, fo::GameObject int result = PartyControl::SwitchHandHook(item); if (result != -1) { cRetTmp = 0; - SetHSReturn(result); + HookScripts::SetHSReturn(result); } result = (cRet > 0) ? rets[0] : -1; EndHook(); diff --git a/sfall/Modules/Scripting/Handlers/Core.cpp b/sfall/Modules/Scripting/Handlers/Core.cpp index 750957fb..f77e396f 100644 --- a/sfall/Modules/Scripting/Handlers/Core.cpp +++ b/sfall/Modules/Scripting/Handlers/Core.cpp @@ -109,7 +109,7 @@ void __declspec(naked) op_get_sfall_arg() { __asm { push ecx; push eax; - call GetHSArg; + call HookScripts::GetHSArg; mov edx, eax; pop eax; _RET_VAL_INT(ecx); @@ -118,10 +118,21 @@ void __declspec(naked) op_get_sfall_arg() { } } +void sf_get_sfall_arg_at(OpcodeContext& ctx) { + long argVal = 0; + long id = ctx.arg(0).rawValue(); + if (id >= static_cast(HookScripts::GetHSArgCount()) || id < 0) { + ctx.printOpcodeError("%s() - invalid value for argument.", ctx.getMetaruleName()); + } else { + argVal = HookScripts::GetHSArgAt(id); + } + ctx.setReturn(argVal); +} + void sf_get_sfall_args(OpcodeContext& ctx) { - DWORD argCount = GetHSArgCount(); + DWORD argCount = HookScripts::GetHSArgCount(); DWORD id = TempArray(argCount, 0); - DWORD* args = GetHSArgs(); + DWORD* args = HookScripts::GetHSArgs(); for (DWORD i = 0; i < argCount; i++) { arrays[id].val[i].set(*(long*)&args[i]); } @@ -129,7 +140,7 @@ void sf_get_sfall_args(OpcodeContext& ctx) { } void sf_set_sfall_arg(OpcodeContext& ctx) { - SetHSArg(ctx.arg(0).rawValue(), ctx.arg(1).rawValue()); + HookScripts::SetHSArg(ctx.arg(0).rawValue(), ctx.arg(1).rawValue()); } void __declspec(naked) op_set_sfall_return() { @@ -137,7 +148,7 @@ void __declspec(naked) op_set_sfall_return() { push ecx; _GET_ARG_INT(end); push eax; - call SetHSReturn; + call HookScripts::SetHSReturn; end: pop ecx; retn; diff --git a/sfall/Modules/Scripting/Handlers/Core.h b/sfall/Modules/Scripting/Handlers/Core.h index c6682b2c..4289138a 100644 --- a/sfall/Modules/Scripting/Handlers/Core.h +++ b/sfall/Modules/Scripting/Handlers/Core.h @@ -41,6 +41,8 @@ void sf_get_sfall_global_float(OpcodeContext&); void __declspec() op_get_sfall_arg(); +void sf_get_sfall_arg_at(OpcodeContext&); + void sf_get_sfall_args(OpcodeContext&); void sf_set_sfall_arg(OpcodeContext&); diff --git a/sfall/Modules/Scripting/Handlers/Interface.cpp b/sfall/Modules/Scripting/Handlers/Interface.cpp index 8af61eaa..b8c4663c 100644 --- a/sfall/Modules/Scripting/Handlers/Interface.cpp +++ b/sfall/Modules/Scripting/Handlers/Interface.cpp @@ -318,10 +318,12 @@ void sf_inventory_redraw(OpcodeContext& ctx) { default: return; } - if (!ctx.arg(0).asBool()) { + long redrawSide = (ctx.numArgs() > 0) ? ctx.arg(0).rawValue() : -1; // -1 - both + if (redrawSide <= 0) { fo::var::stack_offset[fo::var::curr_stack] = 0; fo::func::display_inventory(0, -1, mode); - } else if (mode >= 2) { + } + if (redrawSide && mode >= 2) { fo::var::target_stack_offset[fo::var::target_curr_stack] = 0; fo::func::display_target_inventory(0, -1, fo::var::target_pud, mode); fo::func::win_draw(fo::var::i_wid); @@ -350,6 +352,76 @@ void sf_create_win(OpcodeContext& ctx) { } } +void sf_show_window(OpcodeContext& ctx) { + if (ctx.numArgs() > 0) { + const char* name = ctx.arg(0).strValue(); + for (size_t i = 0; i < 16; i++) { + if (_stricmp(name, fo::var::sWindows[i].name) == 0) { + fo::func::win_show(fo::var::sWindows[i].wID); + return; + } + } + ctx.printOpcodeError("%s() - window '%s' is not found.", ctx.getMetaruleName(), name); + } else { + __asm call fo::funcoffs::windowShow_; + } +} + +void sf_hide_window(OpcodeContext& ctx) { + if (ctx.numArgs() > 0) { + const char* name = ctx.arg(0).strValue(); + for (size_t i = 0; i < 16; i++) { + if (_stricmp(name, fo::var::sWindows[i].name) == 0) { + fo::func::win_hide(fo::var::sWindows[i].wID); + return; + } + } + ctx.printOpcodeError("%s() - window '%s' is not found.", ctx.getMetaruleName(), name); + } else { + __asm call fo::funcoffs::windowHide_; + } +} + +void sf_set_window_flag(OpcodeContext& ctx) { + long bitFlag = ctx.arg(1).rawValue(); + switch (bitFlag) { + case fo::WinFlags::MoveOnTop: + case fo::WinFlags::Hidden: + case fo::WinFlags::Exclusive: + case fo::WinFlags::Transparent: + break; + default: + return; // unsupported set flag + } + bool mode = ctx.arg(2).asBool(); + if (ctx.arg(0).isString()) { + const char* name = ctx.arg(0).strValue(); + for (size_t i = 0; i < 16; i++) { + if (_stricmp(name, fo::var::sWindows[i].name) == 0) { + fo::Window* win =fo::func::GNW_find(fo::var::sWindows[i].wID); + if (mode) { + fo::var::sWindows[i].flags |= bitFlag; + win->flags |= bitFlag; + } else { + fo::var::sWindows[i].flags &= ~bitFlag; + win->flags &= ~bitFlag; + } + return; + } + } + ctx.printOpcodeError("%s() - window '%s' is not found.", ctx.getMetaruleName(), name); + } else { + long wid = ctx.arg(0).rawValue(); + fo::Window* win = fo::func::GNW_find((wid > 0) ? wid : fo::var::i_wid); // i_wid - set flag to current game interface window + if (win == nullptr) return; + if (mode) { + win->flags |= bitFlag; + } else { + win->flags &= ~bitFlag; + } + } +} + static void DrawImage(OpcodeContext& ctx, bool isScaled) { if (*(DWORD*)FO_VAR_currentWindow == -1) { ctx.printOpcodeError("%s() - no created/selected window for the image.", ctx.getMetaruleName()); diff --git a/sfall/Modules/Scripting/Handlers/Interface.h b/sfall/Modules/Scripting/Handlers/Interface.h index f1bfd5ac..5623608b 100644 --- a/sfall/Modules/Scripting/Handlers/Interface.h +++ b/sfall/Modules/Scripting/Handlers/Interface.h @@ -99,6 +99,12 @@ void sf_dialog_message(OpcodeContext&); void sf_create_win(OpcodeContext&); +void sf_show_window(OpcodeContext&); + +void sf_hide_window(OpcodeContext&); + +void sf_set_window_flag(OpcodeContext&); + void sf_draw_image(OpcodeContext&); void sf_draw_image_scaled(OpcodeContext&); diff --git a/sfall/Modules/Scripting/Handlers/Metarule.cpp b/sfall/Modules/Scripting/Handlers/Metarule.cpp index 7f41beb2..8a55a855 100644 --- a/sfall/Modules/Scripting/Handlers/Metarule.cpp +++ b/sfall/Modules/Scripting/Handlers/Metarule.cpp @@ -88,14 +88,16 @@ static const SfallMetarule metarules[] = { {"get_object_ai_data", sf_get_object_ai_data, 2, 2, {ARG_OBJECT, ARG_INT}}, {"get_object_data", sf_get_object_data, 2, 2, {ARG_OBJECT, ARG_INT}}, {"get_outline", sf_get_outline, 1, 1, {ARG_OBJECT}}, + {"get_sfall_arg_at", sf_get_sfall_arg_at, 1, 1, {ARG_INT}}, {"get_string_pointer", sf_get_string_pointer, 1, 1, {ARG_STRING}}, {"has_fake_perk_npc", sf_has_fake_perk_npc, 2, 2, {ARG_OBJECT, ARG_STRING}}, {"has_fake_trait_npc", sf_has_fake_trait_npc, 2, 2, {ARG_OBJECT, ARG_STRING}}, + {"hide_window", sf_hide_window, 0, 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}, {"intface_show", sf_intface_show, 0, 0}, - {"inventory_redraw", sf_inventory_redraw, 1, 1, {ARG_INT}}, + {"inventory_redraw", sf_inventory_redraw, 0, 1, {ARG_INT}}, {"item_make_explosive", sf_item_make_explosive, 3, 4, {ARG_INT, ARG_INT, ARG_INT, ARG_INT}}, {"item_weight", sf_item_weight, 1, 1, {ARG_OBJECT}}, {"lock_is_jammed", sf_lock_is_jammed, 1, 1, {ARG_OBJECT}}, @@ -124,6 +126,8 @@ static const SfallMetarule metarules[] = { {"set_selectable_perk_npc", sf_set_selectable_perk_npc, 5, 5, {ARG_OBJECT, ARG_STRING, ARG_INT, ARG_INT, ARG_STRING}}, {"set_unique_id", sf_set_unique_id, 1, 2, {ARG_OBJECT, ARG_INT}}, {"set_unjam_locks_time", sf_set_unjam_locks_time, 1, 1, {ARG_INT}}, + {"set_window_flag", sf_set_window_flag, 3, 3, {ARG_INTSTR, ARG_INT, ARG_INT}}, + {"show_window", sf_show_window, 0, 1, {ARG_STRING}}, {"spatial_radius", sf_spatial_radius, 1, 1, {ARG_OBJECT}}, {"tile_refresh_display", sf_tile_refresh_display, 0, 0}, {"unjam_lock", sf_unjam_lock, 1, 1, {ARG_OBJECT}}, @@ -132,7 +136,7 @@ static const SfallMetarule metarules[] = { {"validate_test", sf_test, 2, 5, {ARG_INT, ARG_NUMBER, ARG_STRING, ARG_OBJECT, ARG_ANY}}, #endif }; - +// // returns current contents of metarule table static void sf_get_metarule_table(OpcodeContext& ctx) { DWORD arrId = TempArray(metaruleTable.size(), 0);