Fixed broken Print() script function

Fixed the background image of the character portrait on inv/char screens.
Renamed "print_text" to "interface_print".
This commit is contained in:
NovaRain
2020-10-06 11:46:13 +08:00
parent ac28d7293b
commit 2f750a8a4b
8 changed files with 157 additions and 116 deletions
+4 -4
View File
@@ -329,8 +329,10 @@
#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_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")
@@ -348,8 +350,6 @@
#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)
+9 -7
View File
@@ -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 -------
+4 -4
View File
@@ -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);
+4 -1
View File
@@ -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<BYTE>(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_);
}
}
+30
View File
@@ -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() {
+12 -6
View File
@@ -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);
}
}
+1 -1
View File
@@ -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&);
}
}
@@ -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}},