diff --git a/artifacts/scripting/headers/sfall.h b/artifacts/scripting/headers/sfall.h index e124717b..43f57d67 100644 --- a/artifacts/scripting/headers/sfall.h +++ b/artifacts/scripting/headers/sfall.h @@ -259,84 +259,84 @@ /* sfall_funcX macros */ -#define add_global_timer_event(time, fixedParam) sfall_func2("add_g_timer_event", time, fixedParam) -#define add_iface_tag sfall_func0("add_iface_tag") -#define add_trait(traitID) sfall_func1("add_trait", traitID) -#define art_cache_clear sfall_func0("art_cache_clear") -#define attack_is_aimed sfall_func0("attack_is_aimed") -#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 draw_image(artFile, frame, x, y, noTrans) sfall_func5("draw_image", artFile, frame, x, y, noTrans) -#define draw_image_scaled(artFile, frame, x, y, w, h) sfall_func6("draw_image_scaled", artFile, frame, x, y, w, h) -#define exec_map_update_scripts sfall_func0("exec_map_update_scripts") -#define floor2(value) sfall_func1("floor2", value) -#define get_current_inven_size(obj) sfall_func1("get_current_inven_size", obj) -#define get_cursor_mode sfall_func0("get_cursor_mode") -#define get_flags(obj) sfall_func1("get_flags", obj) -#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") -#define get_object_data(obj, offset) sfall_func2("get_object_data", obj, offset) -#define get_outline(obj) sfall_func1("get_outline", obj) -#define get_pc_stat_max(stat) sfall_func1("get_stat_max", stat) -#define get_pc_stat_min(stat) sfall_func1("get_stat_min", stat) -#define get_npc_stat_max(stat) sfall_func2("get_stat_max", stat, 1) -#define get_npc_stat_min(stat) sfall_func2("get_stat_min", stat, 1) -#define get_sfall_arg_at(argNum) sfall_func1("get_sfall_arg_at", argNum) -#define get_text_width(text) sfall_func1("get_text_width", text) -#define hide_window(winName) sfall_func1("hide_window", winName) -#define interface_art_draw(winID, artFile, x, y) sfall_func4("interface_art_draw", winID, artFile, x, y) -#define interface_art_draw_frame(wID, art, x, y, frame) sfall_func5("interface_art_draw", wID, art, x, y, frame) -#define interface_art_draw_ex(wID, art, x, y, frm, prm) sfall_func6("interface_art_draw", wID, art, x, y, frm, prm) -#define interface_redraw_all sfall_func1("intface_redraw", 1) -#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) -#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 message_box(text) sfall_func1("message_box", text) -#define metarule_exist(metaruleName) sfall_func1("metarule_exist", metaruleName) -#define npc_engine_level_up(toggle) sfall_func1("npc_engine_level_up", toggle) -#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) -#define set_cursor_mode(mode) sfall_func1("set_cursor_mode", mode) -#define set_flags(obj, flags) sfall_func2("set_flags", obj, flags) -#define set_iface_tag_text(tag, text, color) sfall_func3("set_iface_tag_text", tag, text, color) -#define set_ini_setting(setting, value) sfall_func2("set_ini_setting", setting, value) -#define set_map_enter_position(tile, elev, rot) sfall_func3("set_map_enter_position", tile, elev, rot) -#define set_object_data(obj, offset, value) sfall_func3("set_object_data", obj, offset, value) -#define set_outline(obj, color) sfall_func2("set_outline", obj, color) -#define set_terrain_name(x, y, name) sfall_func3("set_terrain_name", x, y, name) -#define set_town_title(areaID, title) sfall_func2("set_town_title", areaID, title) -#define set_unique_id(obj) sfall_func1("set_unique_id", obj) -#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 string_compare(str1, str2) sfall_func2("string_compare", str1, str2) -#define string_compare_locale(str1, str2, codePage) sfall_func3("string_compare", str1, str2, codePage) -#define string_format(format, a1, a2) sfall_func3("string_format", format, a1, a2) -#define string_tolower(text) sfall_func2("string_to_case", text, 0) -#define string_toupper(text) sfall_func2("string_to_case", text, 1) -#define tile_by_position(x, y) sfall_func2("tile_by_position", x, y) -#define tile_refresh_display sfall_func0("tile_refresh_display") -#define unjam_lock(obj) sfall_func1("unjam_lock", obj) -#define unset_unique_id(obj) sfall_func2("set_unique_id", obj, -1) -#define unwield_slot(critter, slot) sfall_func2("unwield_slot", critter, slot) +#define add_global_timer_event(time, fixedParam) sfall_func2("add_g_timer_event", time, fixedParam) +#define add_iface_tag sfall_func0("add_iface_tag") +#define add_trait(traitID) sfall_func1("add_trait", traitID) +#define art_cache_clear sfall_func0("art_cache_clear") +#define attack_is_aimed sfall_func0("attack_is_aimed") +#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 draw_image(artFile, frame, x, y, noTrans) sfall_func5("draw_image", artFile, frame, x, y, noTrans) +#define draw_image_scaled(artFile, frame, x, y, w, h) sfall_func6("draw_image_scaled", artFile, frame, x, y, w, h) +#define exec_map_update_scripts sfall_func0("exec_map_update_scripts") +#define floor2(value) sfall_func1("floor2", value) +#define get_current_inven_size(obj) sfall_func1("get_current_inven_size", obj) +#define get_cursor_mode sfall_func0("get_cursor_mode") +#define get_flags(obj) sfall_func1("get_flags", obj) +#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") +#define get_object_data(obj, offset) sfall_func2("get_object_data", obj, offset) +#define get_outline(obj) sfall_func1("get_outline", obj) +#define get_pc_stat_max(stat) sfall_func1("get_stat_max", stat) +#define get_pc_stat_min(stat) sfall_func1("get_stat_min", stat) +#define get_npc_stat_max(stat) sfall_func2("get_stat_max", stat, 1) +#define get_npc_stat_min(stat) sfall_func2("get_stat_min", stat, 1) +#define get_sfall_arg_at(argNum) sfall_func1("get_sfall_arg_at", argNum) +#define get_text_width(text) sfall_func1("get_text_width", text) +#define hide_window(winName) sfall_func1("hide_window", winName) +#define interface_art_draw(winID, artFile, x, y) sfall_func4("interface_art_draw", winID, artFile, x, y) +#define interface_art_draw_frame(winID, artID, x, y, frame) sfall_func5("interface_art_draw", winID, artID, x, y, frame) +#define interface_art_draw_ex(winID, artID, x, y, frame, param) sfall_func6("interface_art_draw", winID, artID, x, y, frame, param) +#define interface_print(text, winType, x, y, color) sfall_func5("interface_print", text, winType, x, y, color) +#define interface_print_width(text, winType, x, y, color, w) sfall_func6("interface_print", text, winType, x, y, color, w) +#define interface_redraw_all sfall_func1("intface_redraw", 1) +#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) +#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 message_box(text) sfall_func1("message_box", text) +#define metarule_exist(metaruleName) sfall_func1("metarule_exist", metaruleName) +#define npc_engine_level_up(toggle) sfall_func1("npc_engine_level_up", toggle) +#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 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) +#define set_cursor_mode(mode) sfall_func1("set_cursor_mode", mode) +#define set_flags(obj, flags) sfall_func2("set_flags", obj, flags) +#define set_iface_tag_text(tag, text, color) sfall_func3("set_iface_tag_text", tag, text, color) +#define set_ini_setting(setting, value) sfall_func2("set_ini_setting", setting, value) +#define set_map_enter_position(tile, elev, rot) sfall_func3("set_map_enter_position", tile, elev, rot) +#define set_object_data(obj, offset, value) sfall_func3("set_object_data", obj, offset, value) +#define set_outline(obj, color) sfall_func2("set_outline", obj, color) +#define set_terrain_name(x, y, name) sfall_func3("set_terrain_name", x, y, name) +#define set_town_title(areaID, title) sfall_func2("set_town_title", areaID, title) +#define set_unique_id(obj) sfall_func1("set_unique_id", obj) +#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 string_compare(str1, str2) sfall_func2("string_compare", str1, str2) +#define string_compare_locale(str1, str2, codePage) sfall_func3("string_compare", str1, str2, codePage) +#define string_format(format, a1, a2) sfall_func3("string_format", format, a1, a2) +#define string_tolower(text) sfall_func2("string_to_case", text, 0) +#define string_toupper(text) sfall_func2("string_to_case", text, 1) +#define tile_by_position(x, y) sfall_func2("tile_by_position", x, y) +#define tile_refresh_display sfall_func0("tile_refresh_display") +#define unjam_lock(obj) sfall_func1("unjam_lock", obj) +#define unset_unique_id(obj) sfall_func2("set_unique_id", obj, -1) +#define unwield_slot(critter, slot) sfall_func2("unwield_slot", critter, slot) #endif diff --git a/artifacts/scripting/sfall function notes.txt b/artifacts/scripting/sfall function notes.txt index 692d96fb..570ca41f 100644 --- a/artifacts/scripting/sfall function notes.txt +++ b/artifacts/scripting/sfall function notes.txt @@ -635,7 +635,7 @@ optional arguments: > int sfall_func4("message_box", string message, int flags, int color1, int color2) - creates a dialog box with text and returns the result of pressing the button: 0 - No (Escape), 1 - Yes/Done (Enter) - returns -1 if for some reason the dialog box cannot be created -- message: the text in the dialog box. Use the \n control character to move text to a new line (example: "Hello\nWorld!") +- message: the text in the dialog box. Use the '\n' control character to move text to a new line (example: "Hello\nWorld!") 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) @@ -650,9 +650,9 @@ optional arguments: > 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 +- draws the specified PCX or FRM image in the game interface window, returns -1 on 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 + this also takes the value of the flag (0x1000000) to prevent immediate redrawing of the interface window - artFile/artId: path to the PCX/FRM file (e.g. "art\\inven\\5mmap.frm"), or its FRM ID number (e.g. 0x7000026, see specification of the FID format) - x/y: offset relative to the top-left corner of the window optional arguments: @@ -661,17 +661,19 @@ 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) +> int sfall_func5("interface_print", string text, int winType, int x, int y, int color) +> int sfall_func6("interface_print", 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!") +- returns the count of lines printed, or -1 on any error +- 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 + 0x1000000 - prevents immediate redrawing of the interface window, the 'textdirect' compiler constant (works the other way around) 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 +- width (optional): the maximum width of the text. The text will be wrapped to fit within the specified width ------------------------ ------ MORE INFO ------- diff --git a/sfall/AI.cpp b/sfall/AI.cpp index fa777a8c..48aa70f6 100644 --- a/sfall/AI.cpp +++ b/sfall/AI.cpp @@ -415,6 +415,10 @@ void AIInit() { dlogr(" Done", DL_INIT); } + #ifndef NDEBUG + if (iniGetInt("Debugging", "AIBugFixes", 1, ddrawIniDef) == 0) return; + #endif + // Fix for NPCs not fully reloading a weapon if it has more ammo capacity than a box of ammo const DWORD itemWReloadAddr[] = { 0x42AF15, // cai_attempt_w_reload_ @@ -436,10 +440,6 @@ void AIInit() { MakeCall(0x428EB5, ai_find_attackers_hack_target3); MakeCall(0x428EE5, ai_find_attackers_hack_target4, 1); - #ifndef NDEBUG - if (iniGetInt("Debugging", "AIBugFixes", 1, ddrawIniDef) == 0) return; - #endif - // Tweak for finding new targets for party members // Save the current target in the "target1" variable and find other potential targets MakeCall(0x429074, ai_danger_source_hack_pm_newfind); diff --git a/sfall/BugFixes.cpp b/sfall/BugFixes.cpp index ae6b6930..20ff1265 100644 --- a/sfall/BugFixes.cpp +++ b/sfall/BugFixes.cpp @@ -3231,7 +3231,7 @@ void BugFixesInit() MakeCall(0x456B63, op_obj_can_see_obj_hack); SafeWrite16(0x456B76, 0x23EB); // jmp loc_456B9B (skip unused engine code) - // Fix broken op_obj_can_hear_obj_ function + // Fix broken obj_can_hear_obj function if (GetConfigInt("Misc", "ObjCanHearObjFix", 0)) { dlog("Applying obj_can_hear_obj fix.", DL_INIT); SafeWrite8(0x4583D8, 0x3B); // jz loc_458414 @@ -3565,4 +3565,7 @@ void BugFixesInit() const DWORD isShotBlockedAddr[] = {0x426D46, 0x426D4E}; SafeWriteBatch(0x41, isShotBlockedAddr); // edi > ecx (replace target with object critter) SafeWrite8(0x426D48, DAM_DEAD | DAM_KNOCKED_DOWN | DAM_KNOCKED_OUT); + + // Fix broken Print() script function + HookCall(0x461AD4, (void*)windowOutput_); } diff --git a/sfall/FalloutEngine.cpp b/sfall/FalloutEngine.cpp index ad732023..80f53472 100644 --- a/sfall/FalloutEngine.cpp +++ b/sfall/FalloutEngine.cpp @@ -799,6 +799,7 @@ const DWORD windowDisplayTransBuf_ = 0x4B8F64; const DWORD windowGetBuffer_ = 0x4B82DC; const DWORD windowGetTextColor_ = 0x4B6174; const DWORD windowHide_ = 0x4B7610; +const DWORD windowOutput_ = 0x4B80A4; const DWORD windowShow_ = 0x4B7648; const DWORD windowWidth_ = 0x4B7734; const DWORD windowWrapLineWithSpacing_ = 0x4B8854; diff --git a/sfall/FalloutEngine.h b/sfall/FalloutEngine.h index 96a372e2..6acaeb10 100644 --- a/sfall/FalloutEngine.h +++ b/sfall/FalloutEngine.h @@ -1093,6 +1093,7 @@ extern const DWORD windowDisplayTransBuf_; extern const DWORD windowGetBuffer_; extern const DWORD windowGetTextColor_; extern const DWORD windowHide_; +extern const DWORD windowOutput_; extern const DWORD windowShow_; extern const DWORD windowWidth_; extern const DWORD windowWrapLineWithSpacing_; diff --git a/sfall/Interface.cpp b/sfall/Interface.cpp index ad1cd2b7..ab243b3f 100644 --- a/sfall/Interface.cpp +++ b/sfall/Interface.cpp @@ -566,6 +566,26 @@ static void __declspec(naked) main_death_scene_hook() { } } +static void __declspec(naked) display_body_hook() { + static const DWORD display_body_hook_Ret = 0x47098D; + __asm { + mov ebx, [esp + 0x60 - 0x28 + 8]; + cmp ebx, 1; // check mode 0 or 1 + jbe fix; + add esp, 8; + mov dword ptr [esp + 0x60 - 0x40], 0; // frm_ptr + jmp display_body_hook_Ret; +fix: + dec edx; // USE.FRM + mov ecx, 48; // INVBOX.FRM + test ebx, ebx; + cmovz edx, ecx; + xor ebx, ebx; + xor ecx, ecx; + jmp art_id_; + } +} + void InterfaceGmouseHandleHook() { if (hrpVersionValid) IFACE_BAR_MODE = *(BYTE*)HRPAddress(0x1006EB0C) != 0; HookCall(0x44C018, gmouse_handle_event_hook); // replaces hack function from HRP @@ -584,7 +604,7 @@ void InterfaceInit() { // Transparent/Hidden - will not toggle the mouse cursor when the cursor hovers over a transparent/hidden window // ScriptWindow - prevents the player from moving when clicking on the window if the 'Transparent' flag is not set HookCall(0x44B737, gmouse_bk_process_hook); - // InterfaceGmouseHandleHook will be run before game initialization + // InterfaceGmouseHandleHook will be executed before game initialization // Set the normal font for death screen subtitles if (GetConfigInt("Misc", "DeathScreenFontPatch", 0)) { @@ -597,6 +617,16 @@ void InterfaceInit() { if (hrpIsEnabled == false) SafeWrite32(0x48134D, 38 - (640 * 3)); // main_death_scene_ (shift y-offset 2px up, w/o HRP) if (hrpIsEnabled == false || hrpVersionValid) SafeWrite8(0x481345, 4); // main_death_scene_ if (hrpVersionValid) SafeWrite8(HRPAddress(0x10011738), 10); + + // Cosmetic fix for the background image of the character portrait on the inventory and character screens + HookCall(0x47093C, display_body_hook); + BYTE code[11] = { + 0x8B, 0xD3, // mov edx, ebx + 0x66, 0x8B, 0x58, 0xF4, // mov bx, [eax - 12] [sizeof(frame)] + 0x0F, 0xAF, 0xD3, // imul edx, ebx (y * frame width) + 0x53, 0x90 // push ebx (frame width) + }; + SafeWriteBytes(0x470971, code, 11); } void InterfaceExit() { diff --git a/sfall/ScriptExtender.cpp b/sfall/ScriptExtender.cpp index 999af5f7..289f2696 100644 --- a/sfall/ScriptExtender.cpp +++ b/sfall/ScriptExtender.cpp @@ -858,9 +858,9 @@ static const SfallOpcodeMetadata opcodeMetaArray[] = { {mf_get_window_attribute, "get_window_attribute", {DATATYPE_MASK_INT, DATATYPE_MASK_INT}}, {mf_hide_window, "hide_window", {DATATYPE_MASK_STR}}, {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_interface_print, "interface_print", {DATATYPE_MASK_STR, DATATYPE_MASK_INT, 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 9d93cf7e..c19f2bbe 100644 --- a/sfall/ScriptOps/InterfaceOps.hpp +++ b/sfall/ScriptOps/InterfaceOps.hpp @@ -729,7 +729,7 @@ static void mf_interface_art_draw() { interfaceWin->surface + (y * interfaceWin->width) + x, width, height, interfaceWin->width ); - if (!(opHandler.arg(0).rawValue() & 0x10000)) { + if (!(opHandler.arg(0).rawValue() & 0x1000000)) { GNWWinRefresh(interfaceWin, &interfaceWin->rect, 0); } MemFree(frmPtr); @@ -804,8 +804,7 @@ static void mf_unwield_slot() { } static void mf_get_window_attribute() { - long attr = 0; - if (opHandler.numArgs() > 1) attr = opHandler.arg(1).rawValue(); + long attr = (opHandler.numArgs() > 1) ? opHandler.arg(1).rawValue() : 0; WINinfo* win = Interface_GetWindow(opHandler.arg(0).rawValue()); if (win == nullptr) { @@ -835,16 +834,20 @@ static void mf_get_window_attribute() { opHandler.setReturn(result); } -static void mf_print_text() { // same as vanilla PrintRect +static void mf_interface_print() { // 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.printOpcodeError("interface_print() - 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(); + if (x < 0) x = 0; long y = opHandler.arg(3).rawValue(); + if (y < 0) y = 0; + long color = opHandler.arg(4).rawValue(); long width = (opHandler.numArgs() > 5) ? opHandler.arg(5).rawValue() : 0; @@ -856,15 +859,17 @@ static void mf_print_text() { // same as vanilla PrintRect width = maxWidth; } - color ^= 0x2000000; // fills background with black color if the flag is set + color ^= 0x2000000; // fills background with black color if the flag is set (textnofill) if ((color & 0xFF) == 0) { __asm call windowGetTextColor_; // set from SetTextColor __asm mov byte ptr color, al; } - if (color & 0x10000) { // shadow + if (color & 0x10000) { // shadow (textshadow) 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); + opHandler.setReturn(WindowWrapLineWithSpacing(win->wID, text, width, maxHeight, x, y, color, 0, 0)); // returns count of lines printed + + // no redraw (textdirect) + if (!(color & 0x1000000)) GNWWinRefresh(win, &win->rect, 0); } diff --git a/sfall/ScriptOps/MetaruleOps.hpp b/sfall/ScriptOps/MetaruleOps.hpp index 8b4d0fd3..79925996 100644 --- a/sfall/ScriptOps/MetaruleOps.hpp +++ b/sfall/ScriptOps/MetaruleOps.hpp @@ -143,6 +143,7 @@ static const SfallMetarule metaruleArray[] = { {"get_window_attribute", mf_get_window_attribute, 1, 2}, {"hide_window", mf_hide_window, 0, 1}, {"interface_art_draw", mf_interface_art_draw, 4, 6}, + {"interface_print", mf_interface_print, 5, 6}, {"intface_hide", mf_intface_hide, 0, 0}, {"intface_is_hidden", mf_intface_is_hidden, 0, 0}, {"intface_redraw", mf_intface_redraw, 0, 1}, @@ -157,7 +158,6 @@ 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},