diff --git a/artifacts/scripting/headers/sfall.h b/artifacts/scripting/headers/sfall.h index 88ec8dae..14af4bd2 100644 --- a/artifacts/scripting/headers/sfall.h +++ b/artifacts/scripting/headers/sfall.h @@ -287,102 +287,102 @@ /* sfall_funcX macros */ -#define add_extra_msg_file(name) sfall_func1("add_extra_msg_file", name) -#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 car_gas_amount sfall_func0("car_gas_amount") -#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_message(text) sfall_func1("dialog_message", text) -#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_can_rest_on_map(map, elev) sfall_func2("get_can_rest_on_map", map, elev) -#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_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, 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_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_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_string_pointer(text) sfall_func1("get_string_pointer", text) -#define get_text_width(text) sfall_func1("get_text_width", 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 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_make_explosive(pid, activePid, min, max) sfall_func4("item_make_explosive", pid, activePid, min, max) -#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_can_rest_on_map(map, elev, value) sfall_func3("set_can_rest_on_map", map, elev, value) -#define set_car_intface_art(artIndex) sfall_func1("set_car_intface_art", artIndex) -#define set_cursor_mode(mode) sfall_func1("set_cursor_mode", mode) -#define set_drugs_data(type, pid, value) sfall_func3("set_drugs_data", type, pid, value) -#define set_dude_obj(critter) sfall_func1("set_dude_obj", critter) -#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_rest_heal_time(time) sfall_func1("set_rest_heal_time", time) -#define set_rest_mode(mode) sfall_func1("set_rest_mode", mode) -#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_extra_msg_file(name) sfall_func1("add_extra_msg_file", name) +#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 car_gas_amount sfall_func0("car_gas_amount") +#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_message(text) sfall_func1("dialog_message", text) +#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_can_rest_on_map(map, elev) sfall_func2("get_can_rest_on_map", map, elev) +#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_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, 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_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_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_string_pointer(text) sfall_func1("get_string_pointer", text) +#define get_text_width(text) sfall_func1("get_text_width", 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 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_make_explosive(pid, activePid, min, max) sfall_func4("item_make_explosive", pid, activePid, min, max) +#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_can_rest_on_map(map, elev, value) sfall_func3("set_can_rest_on_map", map, elev, value) +#define set_car_intface_art(artIndex) sfall_func1("set_car_intface_art", artIndex) +#define set_cursor_mode(mode) sfall_func1("set_cursor_mode", mode) +#define set_drugs_data(type, pid, value) sfall_func3("set_drugs_data", type, pid, value) +#define set_dude_obj(critter) sfall_func1("set_dude_obj", critter) +#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_rest_heal_time(time) sfall_func1("set_rest_heal_time", time) +#define set_rest_mode(mode) sfall_func1("set_rest_mode", mode) +#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 set_fake_perk_npc(npc, perk, level, image, desc) sfall_func5("set_fake_perk_npc", npc, perk, level, image, desc) #define set_fake_trait_npc(npc, trait, active, image, desc) sfall_func5("set_fake_trait_npc", npc, trait, active, image, desc) diff --git a/artifacts/scripting/sfall function notes.txt b/artifacts/scripting/sfall function notes.txt index 098222a0..0d13e395 100644 --- a/artifacts/scripting/sfall function notes.txt +++ b/artifacts/scripting/sfall function notes.txt @@ -729,7 +729,7 @@ optional argument: > 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) @@ -744,9 +744,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: @@ -755,17 +755,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/Modules/AI.cpp b/sfall/Modules/AI.cpp index 9b69e755..bd01ed15 100644 --- a/sfall/Modules/AI.cpp +++ b/sfall/Modules/AI.cpp @@ -416,6 +416,10 @@ void AI::init() { dlogr(" Done", DL_INIT); } + #ifndef NDEBUG + if (iniGetInt("Debugging", "AIBugFixes", 1, ::sfall::ddrawIni) == 0) return; + #endif + // Fix for NPCs not fully reloading a weapon if it has more ammo capacity than a box of ammo HookCalls(item_w_reload_hook, { 0x42AF15, // cai_attempt_w_reload_ @@ -436,10 +440,6 @@ void AI::init() { MakeCall(0x428EB5, ai_find_attackers_hack_target3); MakeCall(0x428EE5, ai_find_attackers_hack_target4, 1); - #ifndef NDEBUG - if (iniGetInt("Debugging", "AIBugFixes", 1, ::sfall::ddrawIni) == 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/Modules/BugFixes.cpp b/sfall/Modules/BugFixes.cpp index 2c9a08dc..60c6d630 100644 --- a/sfall/Modules/BugFixes.cpp +++ b/sfall/Modules/BugFixes.cpp @@ -3243,7 +3243,7 @@ void BugFixes::init() 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 @@ -3570,6 +3570,9 @@ void BugFixes::init() // when calculating the hit chance penalty of ranged attacks in determine_to_hit_func_ engine function SafeWriteBatch(0x41, {0x426D46, 0x426D4E}); // edi > ecx (replace target with object critter) SafeWrite8(0x426D48, fo::DAM_DEAD | fo::DAM_KNOCKED_DOWN | fo::DAM_KNOCKED_OUT); + + // Fix broken Print() script function + HookCall(0x461AD4, (void*)fo::funcoffs::windowOutput_); } } diff --git a/sfall/Modules/Interface.cpp b/sfall/Modules/Interface.cpp index 735a85cd..6ee14fa0 100644 --- a/sfall/Modules/Interface.cpp +++ b/sfall/Modules/Interface.cpp @@ -938,6 +938,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 fo::funcoffs::art_id_; + } +} + void Interface::init() { if (GetConfigInt("Interface", "ActionPointsBar", 0)) { ActionPointsBarPatch(); @@ -966,6 +986,16 @@ void Interface::init() { 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 Interface::exit() { diff --git a/sfall/Modules/Scripting/Handlers/Interface.cpp b/sfall/Modules/Scripting/Handlers/Interface.cpp index bd6a68d0..b8e2ed51 100644 --- a/sfall/Modules/Scripting/Handlers/Interface.cpp +++ b/sfall/Modules/Scripting/Handlers/Interface.cpp @@ -599,7 +599,7 @@ static long InterfaceDrawImage(OpcodeContext& ctx, fo::Window* interfaceWin) { interfaceWin->surface + (y * interfaceWin->width) + x, width, height, interfaceWin->width ); - if (!(ctx.arg(0).rawValue() & 0x10000)) { + if (!(ctx.arg(0).rawValue() & 0x1000000)) { fo::func::GNW_win_refresh(interfaceWin, &interfaceWin->rect, 0); } fo::func::mem_free(frmPtr); @@ -708,7 +708,7 @@ void mf_get_window_attribute(OpcodeContext& ctx) { ctx.setReturn(result); } -void mf_print_text(OpcodeContext& ctx) { // same as vanilla PrintRect +void mf_interface_print(OpcodeContext& ctx) { // same as vanilla PrintRect fo::Window* win = Interface::GetWindow(ctx.arg(1).rawValue()); if (win == nullptr || (int)win == -1) { ctx.printOpcodeError("%s() - the game interface window is not created or invalid value for the interface.", ctx.getMetaruleName()); @@ -716,8 +716,12 @@ void mf_print_text(OpcodeContext& ctx) { // same as vanilla PrintRect return; } const char* text = ctx.arg(0).strValue(); + long x = ctx.arg(2).rawValue(); + if (x < 0) x = 0; long y = ctx.arg(3).rawValue(); + if (y < 0) y = 0; + long color = ctx.arg(4).rawValue(); long width = ctx.arg(5).rawValue(); @@ -729,17 +733,19 @@ void mf_print_text(OpcodeContext& ctx) { // 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 fo::funcoffs::windowGetTextColor_; // set from SetTextColor __asm mov byte ptr color, al; } - if (color & 0x10000) { // shadow + if (color & 0x10000) { // shadow (textshadow) fo::func::windowWrapLineWithSpacing(win->wID, text, width, maxHeight, x, y, 0x201000F, 0, 0); color ^= 0x10000; } - ctx.setReturn(fo::func::windowWrapLineWithSpacing(win->wID, text, width, maxHeight, x, y, color, 0, 0)); - fo::func::GNW_win_refresh(win, &win->rect, 0); + ctx.setReturn(fo::func::windowWrapLineWithSpacing(win->wID, text, width, maxHeight, x, y, color, 0, 0)); // returns count of lines printed + + // no redraw (textdirect) + if (!(color & 0x1000000)) fo::func::GNW_win_refresh(win, &win->rect, 0); } } diff --git a/sfall/Modules/Scripting/Handlers/Interface.h b/sfall/Modules/Scripting/Handlers/Interface.h index 148cefbc..332f50f4 100644 --- a/sfall/Modules/Scripting/Handlers/Interface.h +++ b/sfall/Modules/Scripting/Handlers/Interface.h @@ -117,7 +117,7 @@ void mf_unwield_slot(OpcodeContext&); void mf_get_window_attribute(OpcodeContext&); -void mf_print_text(OpcodeContext& ctx); +void mf_interface_print(OpcodeContext&); } } diff --git a/sfall/Modules/Scripting/Handlers/Metarule.cpp b/sfall/Modules/Scripting/Handlers/Metarule.cpp index cad974d3..3097f402 100644 --- a/sfall/Modules/Scripting/Handlers/Metarule.cpp +++ b/sfall/Modules/Scripting/Handlers/Metarule.cpp @@ -101,6 +101,7 @@ static const SfallMetarule metarules[] = { {"has_fake_trait_npc", mf_has_fake_trait_npc, 2, 2, 0, {ARG_OBJECT, ARG_STRING}}, {"hide_window", mf_hide_window, 0, 1, -1, {ARG_STRING}}, {"interface_art_draw", mf_interface_art_draw, 4, 6, -1, {ARG_INT, ARG_INTSTR, ARG_INT, ARG_INT, ARG_INT, ARG_INT}}, + {"interface_print", mf_interface_print, 5, 6, -1, {ARG_STRING, ARG_INT, ARG_INT, ARG_INT, ARG_INT, ARG_INT}}, {"intface_hide", mf_intface_hide, 0, 0}, {"intface_is_hidden", mf_intface_is_hidden, 0, 0}, {"intface_redraw", mf_intface_redraw, 0, 1}, @@ -116,7 +117,6 @@ static const SfallMetarule metarules[] = { {"obj_under_cursor", mf_obj_under_cursor, 2, 2, 0, {ARG_INT, ARG_INT}}, {"objects_in_radius", mf_objects_in_radius, 3, 4, 0, {ARG_INT, ARG_INT, ARG_INT, ARG_INT}}, {"outlined_object", mf_outlined_object, 0, 0}, - {"print_text", mf_print_text, 5, 6, -1, {ARG_STRING, ARG_INT, ARG_INT, ARG_INT, ARG_INT, ARG_INT}}, {"real_dude_obj", mf_real_dude_obj, 0, 0}, {"remove_timer_event", mf_remove_timer_event, 0, 1, -1, {ARG_INT}}, {"set_can_rest_on_map", mf_set_rest_on_map, 3, 3, -1, {ARG_INT, ARG_INT, ARG_INT}},