diff --git a/artifacts/scripting/headers/sfall.h b/artifacts/scripting/headers/sfall.h index 5abf5517..e124717b 100644 --- a/artifacts/scripting/headers/sfall.h +++ b/artifacts/scripting/headers/sfall.h @@ -309,6 +309,8 @@ #define obj_under_cursor(onlyCritter, includeDude) sfall_func2("obj_under_cursor", onlyCritter, includeDude) #define objects_in_radius(tile, radius, elev, type) sfall_func4("objects_in_radius", tile, radius, elev, type) #define outlined_object sfall_func0("outlined_object") +#define print_text(text, winType, x, y, color) sfall_func5("print_text", text, winType, x, y, color) +#define print_text_width(text, winType, x, y, color, w) sfall_func6("print_text", text, winType, x, y, color, w) #define real_dude_obj sfall_func0("real_dude_obj") #define remove_all_timer_events sfall_func0("remove_timer_event") #define remove_timer_event(fixedParam) sfall_func1("remove_timer_event", fixedParam) diff --git a/artifacts/scripting/sfall function notes.txt b/artifacts/scripting/sfall function notes.txt index 16633e02..692d96fb 100644 --- a/artifacts/scripting/sfall function notes.txt +++ b/artifacts/scripting/sfall function notes.txt @@ -582,7 +582,7 @@ optional arguments: - 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) +> void sfall_func3("set_window_flag", string winName/int 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, or 0 for the current game interface @@ -640,16 +640,16 @@ optional arguments: - flags: mode flags (see MSGBOX_* constants in define_extra.h). Pass -1 to skip setting the flags (default flags are NORMAL and YESNO) - color1/color2: the color index in Fallout palette. color1 sets the text color for the first line, and color2 for all subsequent lines of text (default color is 145) -> int sfall_func1("get_stat_min", stat) -> int sfall_func1("get_stat_max", stat) -> int sfall_func2("get_stat_min", stat, bool who) -> int sfall_func2("get_stat_max", stat, bool who) +> int sfall_func1("get_stat_min", int stat) +> int sfall_func1("get_stat_max", int stat) +> int sfall_func2("get_stat_min", int stat, bool who) +> int sfall_func2("get_stat_max", int stat, bool who) - returns the maximum or minimum set value of the specified stat (see set_stat_max/min functions) - who: 0 (false) or omitting the argument - returns the value of the player, 1 (true) - returns the value set for other critters -> int sfall_func4("interface_art_draw", int winType, string/int artFile/artId, int x, int y) -> int sfall_func5("interface_art_draw", int winType, string/int artFile/artId, int x, int y, int frame) -> int sfall_func6("interface_art_draw", int winType, string/int artFile/artId, int x, int y, int frame, array param) +> int sfall_func4("interface_art_draw", int winType, string artFile/int artID, int x, int y) +> int sfall_func5("interface_art_draw", int winType, string artFile/int artID, int x, int y, int frame) +> int sfall_func6("interface_art_draw", int winType, string artFile/int artID, int x, int y, int frame, array param) - draws the specified PCX or FRM image in the game interface window, returns -1 in case of any error - winType: the type number of the interface window (see WINTYPE_* constants in sfall.h) this also takes the value of the flag (0x10000) to prevent immediate redrawing of the interface window @@ -661,6 +661,18 @@ optional arguments: index 0 - sprite direction for multi-directional FRM index 1/index 2 - the new width/height to scale the image to. Pass -1 to use the original width/height +> int sfall_func5("print_text", string text, int winType, int x, int y, int color) +> int sfall_func6("print_text", string text, int winType, int x, int y, int color, int width) +- displays the text in the specified interface window with the current font. Use vanilla SetFont function to set the font +- text: the text to be printed. Use the \n control character to move text to a new line (example: "Hello\nWorld!") +- winType: the type number of the interface window (see WINTYPE_* constants in sfall.h) +- x/y: offset relative to the top-left corner of the window +- color: the color index in Fallout palette. Pass 0 if the text color was previously set by vanilla SetTextColor function + it can also take additional flags (via bwor) for displaying text: + 0x0010000 - adds a shadow to the text, the 'textshadow' compiler constant + 0x2000000 - fills the background of the text with black color, the 'textnofill' compiler constant (works the other way around) +- width: the maximum width of the text. The text will be wrapped to fit within the specified width + ------------------------ ------ MORE INFO ------- ------------------------ diff --git a/sfall/FalloutEngine.cpp b/sfall/FalloutEngine.cpp index 400a7fb9..ad732023 100644 --- a/sfall/FalloutEngine.cpp +++ b/sfall/FalloutEngine.cpp @@ -797,9 +797,11 @@ const DWORD win_width_ = 0x4D7918; const DWORD windowDisplayBuf_ = 0x4B8EF0; const DWORD windowDisplayTransBuf_ = 0x4B8F64; const DWORD windowGetBuffer_ = 0x4B82DC; +const DWORD windowGetTextColor_ = 0x4B6174; const DWORD windowHide_ = 0x4B7610; const DWORD windowShow_ = 0x4B7648; const DWORD windowWidth_ = 0x4B7734; +const DWORD windowWrapLineWithSpacing_ = 0x4B8854; const DWORD wmDrawCursorStopped_ = 0x4C41EC; const DWORD wmFindCurSubTileFromPos_ = 0x4C0C00; const DWORD wmInterfaceInit_ = 0x4C2324; @@ -913,6 +915,10 @@ void DevPrintf(...) {} __asm push arg8 \ WRAP_WATCOM_FCALL7(offs, arg1, arg2, arg3, arg4, arg5, arg6, arg7) +#define WRAP_WATCOM_FCALL9(offs, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) \ + __asm push arg9 \ + WRAP_WATCOM_FCALL8(offs, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) + // prints message to debug.log file void __declspec(naked) DebugPrintf(const char* fmt, ...) { __asm jmp debug_printf_; @@ -1059,10 +1065,10 @@ void __fastcall WindowTransCscale(long i_width, long i_height, long s_width, lon push w_width; push s_height; push s_width; - mov ebx, edx; // i_height - mov edx, ecx; // i_width call windowGetBuffer_; add eax, xy_shift; + mov ebx, edx; // i_height + mov edx, ecx; // i_width push eax; // to_buff mov eax, data; call trans_cscale_; // *from_buff, i_width, i_height, i_width2, to_buff, width, height, to_width @@ -1274,6 +1280,11 @@ long __fastcall GetGameConfigString(const char* outValue, const char* section, c WRAP_WATCOM_FCALL8(funcoff, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \ } +#define WRAP_WATCOM_FFUNC9(retType, name, funcoff, arg1t, arg1, arg2t, arg2, arg3t, arg3, arg4t, arg4, arg5t, arg5, arg6t, arg6, arg7t, arg7, arg8t, arg8, arg9t, arg9) \ + retType __fastcall name(arg1t arg1, arg2t arg2, arg3t arg3, arg4t arg4, arg5t arg5, arg6t arg6, arg7t arg7, arg8t arg8, arg9t arg9) { \ + WRAP_WATCOM_FCALL9(funcoff, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) \ + } + #include "FalloutFuncs_def.h" ///////////////////////////////// ENGINE UTILS ///////////////////////////////// diff --git a/sfall/FalloutEngine.h b/sfall/FalloutEngine.h index 4e2deef9..96a372e2 100644 --- a/sfall/FalloutEngine.h +++ b/sfall/FalloutEngine.h @@ -1091,9 +1091,11 @@ extern const DWORD win_width_; extern const DWORD windowDisplayBuf_; extern const DWORD windowDisplayTransBuf_; extern const DWORD windowGetBuffer_; +extern const DWORD windowGetTextColor_; extern const DWORD windowHide_; extern const DWORD windowShow_; extern const DWORD windowWidth_; +extern const DWORD windowWrapLineWithSpacing_; extern const DWORD wmDrawCursorStopped_; extern const DWORD wmFindCurSubTileFromPos_; extern const DWORD wmInterfaceInit_; @@ -1239,6 +1241,9 @@ long __fastcall GetGameConfigString(const char* outValue, const char* section, c #define WRAP_WATCOM_FFUNC8(retType, name, funcoff, arg1t, arg1, arg2t, arg2, arg3t, arg3, arg4t, arg4, arg5t, arg5, arg6t, arg6, arg7t, arg7, arg8t, arg8) \ retType __fastcall name(arg1t arg1, arg2t arg2, arg3t arg3, arg4t arg4, arg5t arg5, arg6t arg6, arg7t arg7, arg8t arg8); +#define WRAP_WATCOM_FFUNC9(retType, name, funcoff, arg1t, arg1, arg2t, arg2, arg3t, arg3, arg4t, arg4, arg5t, arg5, arg6t, arg6, arg7t, arg7, arg8t, arg8, arg9t, arg9) \ + retType __fastcall name(arg1t arg1, arg2t arg2, arg3t arg3, arg4t arg4, arg5t arg5, arg6t arg6, arg7t arg7, arg8t arg8, arg9t arg9); + #include "FalloutFuncs_def.h" #undef WRAP_WATCOM_FUNC0 @@ -1258,6 +1263,7 @@ long __fastcall GetGameConfigString(const char* outValue, const char* section, c #undef WRAP_WATCOM_FFUNC6 #undef WRAP_WATCOM_FFUNC7 #undef WRAP_WATCOM_FFUNC8 +#undef WRAP_WATCOM_FFUNC9 ///////////////////////////////// ENGINE UTILS ///////////////////////////////// diff --git a/sfall/FalloutFuncs_def.h b/sfall/FalloutFuncs_def.h index e9591cc7..d875b543 100644 --- a/sfall/FalloutFuncs_def.h +++ b/sfall/FalloutFuncs_def.h @@ -45,6 +45,7 @@ WRAP_WATCOM_FFUNC3(long, ScrSetLocalVar, scr_set_local_var_, long, sid, long, va WRAP_WATCOM_FFUNC3(long, TileNumInDirection, tile_num_in_direction_, long, tile, long, rotation, long, distance) WRAP_WATCOM_FFUNC8(void, TransCscale, trans_cscale_, void*, fromBuff, long, width, long, height, long, pitch, void*, toBuff, long, toWidth, long, toHeight, long, toPitch) WRAP_WATCOM_FFUNC3(void, WinClip, win_clip_, WINinfo*, window, RectList**, rects, void*, buffer) +WRAP_WATCOM_FFUNC9(long, WindowWrapLineWithSpacing, windowWrapLineWithSpacing_, long, winID, const char*, text, long, width, long, height, long, x, long, y, long, color, long, alignment, long, unknown) WRAP_WATCOM_FFUNC3(const char*, InterpretGetString, interpretGetString_, TProgram*, scriptPtr, DWORD, dataType, DWORD, strId) diff --git a/sfall/ScriptExtender.cpp b/sfall/ScriptExtender.cpp index a1ce3722..999af5f7 100644 --- a/sfall/ScriptExtender.cpp +++ b/sfall/ScriptExtender.cpp @@ -860,6 +860,7 @@ static const SfallOpcodeMetadata opcodeMetaArray[] = { {mf_interface_art_draw, "interface_art_draw", {DATATYPE_MASK_INT, DATATYPE_MASK_INT | DATATYPE_MASK_STR, DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT}}, {mf_inventory_redraw, "inventory_redraw", {DATATYPE_MASK_INT}}, {mf_message_box, "message_box", {DATATYPE_MASK_STR, DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT}}, + {mf_print_text, "print_text", {DATATYPE_MASK_STR, DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT, DATATYPE_MASK_INT}}, {mf_remove_timer_event, "remove_timer_event", {DATATYPE_MASK_INT}}, {mf_set_cursor_mode, "set_cursor_mode", {DATATYPE_MASK_INT}}, {mf_set_flags, "set_flags", {DATATYPE_MASK_VALID_OBJ, DATATYPE_MASK_INT}}, diff --git a/sfall/ScriptOps/InterfaceOps.hpp b/sfall/ScriptOps/InterfaceOps.hpp index c006bcfa..9d93cf7e 100644 --- a/sfall/ScriptOps/InterfaceOps.hpp +++ b/sfall/ScriptOps/InterfaceOps.hpp @@ -344,7 +344,7 @@ static void mf_intface_redraw() { if (flag == 0) { IntfaceRedraw(); } else { - RefreshGNW(1); // redraw all interfaces + RefreshGNW(2); // fake redraw all interfaces (TODO: need a real redraw of interfaces) } } @@ -491,6 +491,7 @@ static void mf_hide_window() { static void mf_set_window_flag() { long bitFlag = opHandler.arg(1).rawValue(); switch (bitFlag) { + case WinFlags::DontMoveTop: case WinFlags::MoveOnTop: case WinFlags::Hidden: case WinFlags::Exclusive: @@ -833,3 +834,37 @@ static void mf_get_window_attribute() { } opHandler.setReturn(result); } + +static void mf_print_text() { // same as vanilla PrintRect + WINinfo* win = Interface_GetWindow(opHandler.arg(1).rawValue()); + if (win == nullptr || (int)win == -1) { + opHandler.printOpcodeError("print_text() - the game interface window is not created or invalid value for the interface."); + opHandler.setReturn(-1); + return; + } + const char* text = opHandler.arg(0).strValue(); + long x = opHandler.arg(2).rawValue(); + long y = opHandler.arg(3).rawValue(); + long color = opHandler.arg(4).rawValue(); + long width = (opHandler.numArgs() > 5) ? opHandler.arg(5).rawValue() : 0; + + int maxHeight = win->height - y; + int maxWidth = win->width - x; + if (width <= 0) { + width = maxWidth; + } else if (width > maxWidth) { + width = maxWidth; + } + + color ^= 0x2000000; // fills background with black color if the flag is set + if ((color & 0xFF) == 0) { + __asm call windowGetTextColor_; // set from SetTextColor + __asm mov byte ptr color, al; + } + if (color & 0x10000) { // shadow + WindowWrapLineWithSpacing(win->wID, text, width, maxHeight, x, y, 0x201000F, 0, 0); + color ^= 0x10000; + } + opHandler.setReturn(WindowWrapLineWithSpacing(win->wID, text, width, maxHeight, x, y, color, 0, 0)); + GNWWinRefresh(win, &win->rect, 0); +} diff --git a/sfall/ScriptOps/MetaruleOps.hpp b/sfall/ScriptOps/MetaruleOps.hpp index 127b78f1..8b4d0fd3 100644 --- a/sfall/ScriptOps/MetaruleOps.hpp +++ b/sfall/ScriptOps/MetaruleOps.hpp @@ -157,6 +157,7 @@ static const SfallMetarule metaruleArray[] = { {"obj_under_cursor", mf_obj_under_cursor, 2, 2}, {"objects_in_radius", mf_objects_in_radius, 3, 4}, {"outlined_object", mf_outlined_object, 0, 0}, + {"print_text", mf_print_text, 5, 6}, {"real_dude_obj", mf_real_dude_obj, 0, 0}, {"remove_timer_event", mf_remove_timer_event, 0, 1}, {"set_cursor_mode", mf_set_cursor_mode, 1, 1},