From d8120590305c4faa4313aca683db15070e90809c Mon Sep 17 00:00:00 2001 From: NovaRain Date: Mon, 27 Jan 2020 20:41:21 +0800 Subject: [PATCH] Added "dialog_box" script function Added a new attrType value to "get_window_attribute" function. --- artifacts/scripting/headers/sfall.h | 8 ++-- artifacts/scripting/sfall function notes.txt | 14 +++++- sfall/FalloutEngine/EngineUtils.cpp | 2 +- sfall/FalloutEngine/Enums.h | 10 +++++ sfall/FalloutEngine/Functions.cpp | 23 ++++++++-- sfall/FalloutEngine/Functions.h | 2 + .../Modules/Scripting/Handlers/Interface.cpp | 45 +++++++++++++++---- sfall/Modules/Scripting/Handlers/Interface.h | 2 + sfall/Modules/Scripting/Handlers/Metarule.cpp | 3 +- 9 files changed, 90 insertions(+), 19 deletions(-) diff --git a/artifacts/scripting/headers/sfall.h b/artifacts/scripting/headers/sfall.h index f6f84a59..7f205b29 100644 --- a/artifacts/scripting/headers/sfall.h +++ b/artifacts/scripting/headers/sfall.h @@ -78,7 +78,7 @@ #define LIST_ALL (9) //Valid window types for get_window_attribute -#define WINTYPE_INVENTORY (0) // any inventory window +#define WINTYPE_INVENTORY (0) // any inventory window (player/loot/use/barter) #define WINTYPE_DIALOG (1) #define WINTYPE_PIPBOY (2) #define WINTYPE_WORLDMAP (3) @@ -274,6 +274,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_box(text) sfall_func1("dialog_box", text) #define dialog_message(text) sfall_func1("dialog_message", text) #define dialog_obj sfall_func0("dialog_obj") #define display_stats sfall_func0("display_stats") @@ -287,8 +288,8 @@ #define get_flags(obj) sfall_func1("get_flags", obj) #define get_ini_section(file, sect) sfall_func2("get_ini_section", file, sect) #define get_ini_sections(file) sfall_func1("get_ini_sections", file) -#define get_interface_x(winType) sfall_func2("get_window_attribute", winType, 0) -#define get_interface_y(winType) sfall_func2("get_window_attribute", winType, 1) +#define get_interface_x(winType) sfall_func2("get_window_attribute", winType, 1) +#define get_interface_y(winType) sfall_func2("get_window_attribute", winType, 2) #define get_inven_ap_cost sfall_func0("get_inven_ap_cost") #define get_map_enter_position sfall_func0("get_map_enter_position") #define get_metarule_table sfall_func0("get_metarule_table") @@ -303,6 +304,7 @@ #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_is_shown(winType) sfall_func1("get_window_attribute", winType) #define intface_redraw sfall_func0("intface_redraw") #define intface_show sfall_func0("intface_show") #define inventory_redraw(invSide) sfall_func1("inventory_redraw", invSide) diff --git a/artifacts/scripting/sfall function notes.txt b/artifacts/scripting/sfall function notes.txt index 13554d3b..ff1aa05d 100644 --- a/artifacts/scripting/sfall function notes.txt +++ b/artifacts/scripting/sfall function notes.txt @@ -705,15 +705,25 @@ optional argument: > void sfall_func3("set_terrain_name", int x, int y, string name) - overrides the terrain type name for the sub-tile on the world map by the specified coordinates -int sfall_func2("get_window_attribute", int winType, int attrType) +> int sfall_func1("get_window_attribute", int winType) +> int sfall_func2("get_window_attribute", int winType, int attrType) - returns the attribute of the specified interface window by the attrType argument - winType: the type number of the interface window (see WINTYPE_* constants in sfall.h) -- attrType: 0 - X position, 1 - Y position (relative to the top-left corner of the game screen) +- attrType: 0 - returns a value of 1 if the specified interface window is created by the game (same as without the argument) + 1 - X position, 2 - Y position (relative to the top-left corner of the game screen) +- returns -1 if the specified attribute cannot be obtained > void sfall_func2("set_town_title", int areaID, string title) - sets a floating text for a town on the world map when hovering the cursor over the player's marker - areaID: the ID number of the town from city.txt +> int sfall_func1("dialog_box", string text1) +> int sfall_func2("dialog_box", string text1, string text2) +> int sfall_func3("dialog_box", string text1, string text2, string text3) +- creates a dialog box with text and returns the result of pressing the button: 0 - No, 1 - Yes +- text1/text2/text3: corresponding text in the dialog box for the first, second, and third lines +- returns -1 if for some reason the dialog box cannot be created + ------------------------ ------ MORE INFO ------- ------------------------ diff --git a/sfall/FalloutEngine/EngineUtils.cpp b/sfall/FalloutEngine/EngineUtils.cpp index 25e799be..e9a9fd4d 100644 --- a/sfall/FalloutEngine/EngineUtils.cpp +++ b/sfall/FalloutEngine/EngineUtils.cpp @@ -196,7 +196,7 @@ long __fastcall GetTopWindowID(long xPos, long yPos) { } enum WinNameType { - Inventory = 0, // any inventory window + Inventory = 0, // any inventory window (player/loot/use/barter) Dialog = 1, PipBoy = 2, WorldMap = 3, diff --git a/sfall/FalloutEngine/Enums.h b/sfall/FalloutEngine/Enums.h index 72faf5dc..a0c2d0e7 100644 --- a/sfall/FalloutEngine/Enums.h +++ b/sfall/FalloutEngine/Enums.h @@ -789,4 +789,14 @@ enum QueueType : long gsound_sfx_event = 13 // no object }; +enum DialogOutFlags : long +{ + DIALOGOUT_NORMAL = 0x01, // uses regular graphic + DIALOGOUT_SMALL = 0x02, // uses smaller graphic + DIALOGOUT_ALIGN_LEFT = 0x04, // text aligned to left + DIALOGOUT_ALIGN_TOP = 0x08, // text aligned to top + DIALOGOUT_YESNO = 0x10, // DONE button replaced by YES/NO buttons - WIP: currently useless in scripts + DIALOGOUT_CLEAN = 0x20 // no buttons +}; + } diff --git a/sfall/FalloutEngine/Functions.cpp b/sfall/FalloutEngine/Functions.cpp index 075f82f8..401443f7 100644 --- a/sfall/FalloutEngine/Functions.cpp +++ b/sfall/FalloutEngine/Functions.cpp @@ -404,21 +404,36 @@ long __stdcall win_register_button(DWORD winRef, long xPos, long yPos, long widt void __stdcall DialogOut(const char* text) { __asm { - push 1; // flag + push 1; // DIALOGOUT_NORMAL flag xor eax, eax; push eax; // ColorMsg - push eax; // DisplayMsg + push eax; // DisplayMsg (unknown) mov al, byte ptr ds:[0x6AB718]; push eax; // ColorIndex push 116; // y mov ecx, 192; // x mov eax, text; // DisplayText - xor ebx, ebx; // ? - xor edx, edx; // ? + xor ebx, ebx; + xor edx, edx; call fo::funcoffs::dialog_out_; } } +long __fastcall DialogOutEx(const char* text, const char** textEx, long count, long flags) { + __asm { + mov eax, 145; // Color index + push flags; // flag + push eax; // ColorMsg2 + push 0; // DisplayMsg (unknown) + push eax; // ColorMsg1 + mov eax, ecx; // DisplayText first line + push 116; // y + mov ecx, 192; // x + mov ebx, count; // count text lines 0-2 + call fo::funcoffs::dialog_out_; // edx - DisplayText second/third line + } +} + void __fastcall DrawWinLine(int winRef, DWORD startXPos, DWORD endXPos, DWORD startYPos, DWORD endYPos, BYTE colour) { __asm { xor eax, eax; diff --git a/sfall/FalloutEngine/Functions.h b/sfall/FalloutEngine/Functions.h index 3e30f2b0..3b432f86 100644 --- a/sfall/FalloutEngine/Functions.h +++ b/sfall/FalloutEngine/Functions.h @@ -208,6 +208,8 @@ long __stdcall win_register_button(DWORD winRef, long xPos, long yPos, long widt void __stdcall DialogOut(const char* text); +long __fastcall DialogOutEx(const char* text, const char** textEx, long count, long flags); + // draws an image to the buffer without scaling and with transparency display toggle void __fastcall windowDisplayBuf(long x, long width, long y, long height, void* data, long noTrans); diff --git a/sfall/Modules/Scripting/Handlers/Interface.cpp b/sfall/Modules/Scripting/Handlers/Interface.cpp index c8fc127a..855a8f4d 100644 --- a/sfall/Modules/Scripting/Handlers/Interface.cpp +++ b/sfall/Modules/Scripting/Handlers/Interface.cpp @@ -127,16 +127,38 @@ void __declspec(naked) op_resume_game() { } } -static bool dialogShow = false; void sf_create_message_window(OpcodeContext &ctx) { + static bool dialogShow = false; if (dialogShow) return; + const char* str = ctx.arg(0).strValue(); if (!str || str[0] == 0) return; + dialogShow = true; fo::func::DialogOut(str); dialogShow = false; } +void sf_dialog_box(OpcodeContext &ctx) { + const char* str = ctx.arg(0).strValue(); + if (!str || str[0] == 0) return; + + const char* str2[2]; + long lines = 0; + if (ctx.numArgs() > 1) { + ++lines; + str2[0] = ctx.arg(1).strValue(); + } + if (ctx.numArgs() > 2) { + ++lines; + str2[1] = ctx.arg(2).strValue(); + } + *(DWORD*)FO_VAR_script_engine_running = 0; + long result = fo::func::DialogOutEx(str, str2, lines, fo::DIALOGOUT_NORMAL | fo::DIALOGOUT_YESNO); + *(DWORD*)FO_VAR_script_engine_running = 1; + ctx.setReturn(result); +} + void __declspec(naked) op_get_viewport_x() { __asm { mov edx, ds:[FO_VAR_wmWorldOffsetX]; @@ -544,23 +566,30 @@ void sf_unwield_slot(OpcodeContext& ctx) { void sf_get_window_attribute(OpcodeContext& ctx) { fo::Window* win = fo::GetWindow(ctx.arg(0).rawValue()); if (win == nullptr) { - ctx.printOpcodeError("%s() - failed to get the interface window.", ctx.getMetaruleName()); + if (ctx.arg(1).rawValue() != 0) { + ctx.printOpcodeError("%s() - failed to get the interface window.", ctx.getMetaruleName()); + ctx.setReturn(-1); + } return; } if ((long)win == -1) { ctx.printOpcodeError("%s() - invalid window type number.", ctx.getMetaruleName()); + ctx.setReturn(-1); return; } - long pos = 0; + long result = 0; switch (ctx.arg(1).rawValue()) { - case 0: // x - pos = win->wRect.left; + case 0: // check if window exists + result = 1; break; - case 1: // y - pos = win->wRect.top; + case 1: // x + result = win->wRect.left; + break; + case 2: // y + result = win->wRect.top; break; } - ctx.setReturn(pos); + ctx.setReturn(result); } } diff --git a/sfall/Modules/Scripting/Handlers/Interface.h b/sfall/Modules/Scripting/Handlers/Interface.h index 8dd78c25..c2f86798 100644 --- a/sfall/Modules/Scripting/Handlers/Interface.h +++ b/sfall/Modules/Scripting/Handlers/Interface.h @@ -59,6 +59,8 @@ void __declspec() op_resume_game(); //Create a message window with given string void sf_create_message_window(OpcodeContext&); +void sf_dialog_box(OpcodeContext&); + void __declspec() op_get_viewport_x(); void __declspec() op_get_viewport_y(); diff --git a/sfall/Modules/Scripting/Handlers/Metarule.cpp b/sfall/Modules/Scripting/Handlers/Metarule.cpp index acda7f8f..0efc6851 100644 --- a/sfall/Modules/Scripting/Handlers/Metarule.cpp +++ b/sfall/Modules/Scripting/Handlers/Metarule.cpp @@ -70,6 +70,7 @@ static const SfallMetarule metarules[] = { {"car_gas_amount", sf_car_gas_amount, 0, 0}, {"create_win", sf_create_win, 5, 6, -1, {ARG_STRING, ARG_INT, ARG_INT, ARG_INT, ARG_INT, ARG_INT}}, {"critter_inven_obj2", sf_critter_inven_obj2, 2, 2, 0, {ARG_OBJECT, ARG_INT}}, + {"dialog_box", sf_dialog_box, 1, 3, -1, {ARG_STRING, ARG_STRING, ARG_STRING}}, {"dialog_message", sf_dialog_message, 1, 1, -1, {ARG_STRING}}, {"dialog_obj", sf_get_dialog_object, 0, 0}, {"display_stats", sf_display_stats, 0, 0}, // refresh @@ -92,7 +93,7 @@ static const SfallMetarule metarules[] = { {"get_sfall_arg_at", sf_get_sfall_arg_at, 1, 1, 0, {ARG_INT}}, {"get_string_pointer", sf_get_string_pointer, 1, 1, 0, {ARG_STRING}}, {"get_text_width", sf_get_text_width, 1, 1, 0, {ARG_STRING}}, - {"get_window_attribute", sf_get_window_attribute, 2, 2, 0, {ARG_INT, ARG_INT}}, + {"get_window_attribute", sf_get_window_attribute, 1, 2, 0, {ARG_INT, ARG_INT}}, {"has_fake_perk_npc", sf_has_fake_perk_npc, 2, 2, 0, {ARG_OBJECT, ARG_STRING}}, {"has_fake_trait_npc", sf_has_fake_trait_npc, 2, 2, 0, {ARG_OBJECT, ARG_STRING}}, {"hide_window", sf_hide_window, 0, 1, -1, {ARG_STRING}},