From 227a062fa605c63cbe90d6c1ce3ee3fca7d749c7 Mon Sep 17 00:00:00 2001 From: NovaRain Date: Sun, 10 Nov 2019 18:09:12 +0800 Subject: [PATCH] Added a fix for scripted interface windows (#25) * prevents player's movement when clicking on the window. * the mouse cursor will not be toggled when the cursor hovers over a hidden window. Updated version number. --- artifacts/ddraw.ini | 2 +- artifacts/mods/gl_partycontrol.ssl | 8 ++--- sfall/FalloutEngine/Enums.h | 2 +- sfall/FalloutEngine/Functions_def.h | 1 + sfall/FalloutEngine/Structs.h | 14 ++++---- sfall/FalloutEngine/VariableOffsets.h | 6 ++++ sfall/FalloutEngine/Variables_def.h | 6 +++- sfall/Modules/Interface.cpp | 51 +++++++++++++++++++++++++-- sfall/Modules/Objects.cpp | 5 ++- sfall/Modules/Tiles.cpp | 4 +-- sfall/main.cpp | 6 ++-- sfall/main.h | 2 +- sfall/version.h | 4 +-- 13 files changed, 82 insertions(+), 29 deletions(-) diff --git a/artifacts/ddraw.ini b/artifacts/ddraw.ini index 0decda1d..d50af44c 100644 --- a/artifacts/ddraw.ini +++ b/artifacts/ddraw.ini @@ -1,5 +1,5 @@ ;sfall configuration settings -;v4.2.1 +;v4.2.2 [Main] ;Change to 1 if you want to use command line args to tell sfall to use another ini file. diff --git a/artifacts/mods/gl_partycontrol.ssl b/artifacts/mods/gl_partycontrol.ssl index 2e9d0f63..40d77521 100644 --- a/artifacts/mods/gl_partycontrol.ssl +++ b/artifacts/mods/gl_partycontrol.ssl @@ -54,9 +54,7 @@ procedure combatturn_handler begin // set perks (only work with 4.1.8+) foreach (perkID in perksList) begin level := has_trait(TRAIT_PERK, real_dude_obj, perkID); - if (level) then begin - critter_add_trait(critter, TRAIT_PERK, perkID, level); - end + if (level) then critter_add_trait(critter, TRAIT_PERK, perkID, level); end intface_redraw; lightDist := get_object_data(critter, OBJ_DATA_LIGHT_DISTANCE); @@ -83,9 +81,7 @@ procedure combatturn_handler begin if (dude_obj != real_dude_obj) then begin foreach (perkID in perksList) begin level := has_trait(TRAIT_PERK, real_dude_obj, perkID); - if (level) then begin - critter_rm_trait(critter, TRAIT_PERK, perkID, level); - end + if (level) then critter_rm_trait(critter, TRAIT_PERK, perkID, level); end end if isShowTag then begin diff --git a/sfall/FalloutEngine/Enums.h b/sfall/FalloutEngine/Enums.h index 5eb62138..3b6adea2 100644 --- a/sfall/FalloutEngine/Enums.h +++ b/sfall/FalloutEngine/Enums.h @@ -739,7 +739,7 @@ namespace WinFlags { Transparent = 0x20, UnknownFlag40 = 0x40, UnknownFlag80 = 0x80, - scriptWindow = 0x100, + ScriptWindow = 0x100, itsButton = 0x10000, }; } diff --git a/sfall/FalloutEngine/Functions_def.h b/sfall/FalloutEngine/Functions_def.h index 68c22576..439c1ce0 100644 --- a/sfall/FalloutEngine/Functions_def.h +++ b/sfall/FalloutEngine/Functions_def.h @@ -25,6 +25,7 @@ WRAP_WATCOM_FFUNC3(FrmFrameData*, frame_ptr, FrmHeaderData*, frm, long, frame, l WRAP_WATCOM_FFUNC3(void, intface_update_items, long, animate, long, modeLeft,long, modeRight) WRAP_WATCOM_FFUNC3(long, item_add_force, GameObject*, critter, GameObject*, item, long, count) WRAP_WATCOM_FFUNC7(void, make_straight_path_func, GameObject*, objFrom, DWORD, tileFrom, DWORD, tileTo, void*, rotationPtr, DWORD*, result, long, flags, void*, func) +WRAP_WATCOM_FFUNC4(long, mouse_click_in, long, x, long, y, long, x_end, long, y_end) WRAP_WATCOM_FFUNC3(GameObject*, obj_blocking_at, GameObject*, object, long, tile, long, elevation) WRAP_WATCOM_FFUNC3(long, object_under_mouse, long, crSwitch, long, inclDude, long, elevation) WRAP_WATCOM_FFUNC3(long, scr_get_local_var, long, sid, long, varId, long*, value) diff --git a/sfall/FalloutEngine/Structs.h b/sfall/FalloutEngine/Structs.h index 0fec931c..2ec0339f 100644 --- a/sfall/FalloutEngine/Structs.h +++ b/sfall/FalloutEngine/Structs.h @@ -697,20 +697,20 @@ struct ScriptListInfoItem { //for holding window info #pragma pack(1) struct Window { - long ref; + long wID; long flags; RECT wRect; long width; long height; long clearColour; - long unknown2; - long unknown3; + long rand1; + long rand2; BYTE *surface; // bytes frame data ref to palette - long buttonListP; - long unknown5;//buttonptr? + long *buttonsList; + long unknown5; // buttonptr? long unknown6; - long unknown7; - long drawFuncP; + long *menuBar; + long *drawFunc; }; #pragma pack(1) diff --git a/sfall/FalloutEngine/VariableOffsets.h b/sfall/FalloutEngine/VariableOffsets.h index d8b9237b..e71bbc8a 100644 --- a/sfall/FalloutEngine/VariableOffsets.h +++ b/sfall/FalloutEngine/VariableOffsets.h @@ -51,6 +51,7 @@ #define FO_VAR_dialogue_switch_mode 0x518718 #define FO_VAR_dialog_target 0x518848 #define FO_VAR_dialog_target_is_party 0x51884C +#define FO_VAR_display_win 0x631E4C #define FO_VAR_displayMapList 0x41B560 #define FO_VAR_dropped_explosive 0x5190E0 #define FO_VAR_drugInfoList 0x5191CC @@ -148,6 +149,7 @@ #define FO_VAR_name_sort_list 0x56FCB0 #define FO_VAR_num_game_global_vars 0x5186C4 #define FO_VAR_num_map_global_vars 0x519574 +#define FO_VAR_num_windows 0x6ADF24 #define FO_VAR_card_old_fid1 0x5709EC #define FO_VAR_obj_dude 0x6610B8 #define FO_VAR_obj_seen 0x662445 @@ -232,6 +234,7 @@ #define FO_VAR_trait_data 0x51DB84 #define FO_VAR_view_page 0x664520 #define FO_VAR_wd_obj 0x59E98C +#define FO_VAR_window 0x6ADE58 #define FO_VAR_wmAreaInfoList 0x51DDF8 #define FO_VAR_wmLastRndTime 0x51DEA0 #define FO_VAR_wmMaxMapNum 0x51DE10 @@ -248,10 +251,13 @@ // colors #define FO_VAR_BlueColor 0x6A38EF +#define FO_VAR_DARK_GREY_Color 0x6A59D8 #define FO_VAR_DarkGreenColor 0x6A3A90 +#define FO_VAR_DarkGreenGreyColor 0x6A3DF1 #define FO_VAR_DullPinkColor 0x6AB718 #define FO_VAR_GoodColor 0x6AB4EF #define FO_VAR_GreenColor 0x6A3CB0 +#define FO_VAR_LIGHT_GREY_Color 0x6A76BF #define FO_VAR_PeanutButter 0x6A82F3 #define FO_VAR_RedColor 0x6AB4D0 #define FO_VAR_WhiteColor 0x6AB8CF diff --git a/sfall/FalloutEngine/Variables_def.h b/sfall/FalloutEngine/Variables_def.h index 6de8226d..34d02728 100644 --- a/sfall/FalloutEngine/Variables_def.h +++ b/sfall/FalloutEngine/Variables_def.h @@ -34,7 +34,9 @@ VAR_(curr_font_num, DWORD) VARA(curr_pc_stat, long, PCSTAT_max_pc_stat) VAR_(curr_stack, DWORD) VAR_(cursor_line, DWORD) -VAR_(DarkGreenColor, BYTE) +VAR_(DARK_GREY_Color, BYTE) +VAR_(DarkGreenColor, BYTE) +VAR_(DarkGreenGreyColor, BYTE) VAR_(dialogue_state, DWORD) VAR_(dialogue_switch_mode, DWORD) VAR_(dialog_target, DWORD) @@ -95,6 +97,7 @@ VAR_(last_button_winID, DWORD) VAR_(last_level, DWORD) VAR_(Level_, DWORD) VAR_(Lifegiver, DWORD) +VAR_(LIGHT_GREY_Color, BYTE) VAR_(lipsFID, DWORD) VAR_(list_com, DWORD) VAR_(list_total, DWORD) @@ -200,6 +203,7 @@ VAR_(title_font, DWORD) VARA(trait_data, TraitInfo, TRAIT_count) VAR_(view_page, DWORD) VAR_(wd_obj, DWORD) +VARA(window, fo::Window*, 50) VAR_(WhiteColor, BYTE) VAR_(wmAreaInfoList, DWORD) VAR_(wmLastRndTime, DWORD) diff --git a/sfall/Modules/Interface.cpp b/sfall/Modules/Interface.cpp index 01fdc574..9f6a2db4 100644 --- a/sfall/Modules/Interface.cpp +++ b/sfall/Modules/Interface.cpp @@ -81,8 +81,8 @@ static void ActionPointsBarPatch() { dlog("Applying expanded action points bar patch.", DL_INIT); if (hrpIsEnabled) { // check valid data - if (hrpVersionValid && !_stricmp((const char*)HRPAddressOffset(0x39358), "HR_IFACE_%i.frm")) { - SafeWriteStr(HRPAddressOffset(0x39363), "E.frm"); // patching HRP + if (hrpVersionValid && !_stricmp((const char*)HRPAddress(0x10039358), "HR_IFACE_%i.frm")) { + SafeWriteStr(HRPAddress(0x10039363), "E.frm"); // patching HRP } else { dlogr(" Incorrect HRP version!", DL_INIT); return; @@ -561,6 +561,44 @@ static void SpeedInterfaceCounterAnimsPatch() { } } +static bool IFACE_BAR_MODE = false; +static long gmouse_handle_event_hook() { + long countWin = *(DWORD*)FO_VAR_num_windows; + long ifaceWin = fo::var::interfaceWindow; + fo::Window* win = nullptr; + + for (int n = 1; n < countWin; n++) { + win = fo::var::window[n]; + if ((win->wID == ifaceWin || (win->flags & fo::WinFlags::ScriptWindow && !(win->flags & fo::WinFlags::Transparent))) // also check the script windows + && !(win->flags & fo::WinFlags::Hidden)) { + RECT *rect = &win->wRect; + if (fo::func::mouse_click_in(rect->left, rect->top, rect->right, rect->bottom)) return 0; // 0 - block clicking in the window area + } + } + if (IFACE_BAR_MODE) return 1; + // if IFACE_BAR_MODE is not enabled, check the display_win window area + win = fo::func::GNW_find(*(DWORD*)FO_VAR_display_win); + RECT *rect = &win->wRect; + return fo::func::mouse_click_in(rect->left, rect->top, rect->right, rect->bottom); // 1 - click in the display_win area +} + +static void __declspec(naked) gmouse_bk_process_hook() { + using namespace fo::WinFlags; + __asm { + call fo::funcoffs::win_get_top_win_; + cmp eax, ds:[FO_VAR_display_win]; + jnz checkFlag; + retn; +checkFlag: + call fo::funcoffs::GNW_find_; + cmp [eax + 4], Hidden; // window flags + jnz skip; + mov eax, ds:[FO_VAR_display_win]; // window is hidden, so return the number of the display_win +skip: + retn; + } +} + void Interface::init() { if (GetConfigInt("Interface", "ActionPointsBar", 0)) { ActionPointsBarPatch(); @@ -568,6 +606,15 @@ void Interface::init() { DrawActionPointsNumber(); WorldMapInterfacePatch(); SpeedInterfaceCounterAnimsPatch(); + + // Fix for interface windows with 'Hidden' and 'ScriptWindow' flags + // Hidden - will not toggle the mouse cursor when the cursor hovers over a hidden window + // ScriptWindow - prevents player's movement when clicking on the window if the 'Transparent' flag is not set + HookCall(0x44B737, gmouse_bk_process_hook); + LoadGameHook::OnBeforeGameInit() += []() { + if (hrpVersionValid) IFACE_BAR_MODE = *(BYTE*)HRPAddress(0x1006EB0C) != 0; + HookCall(0x44C018, gmouse_handle_event_hook); // replaces hack function from HRP + }; } void Interface::exit() { diff --git a/sfall/Modules/Objects.cpp b/sfall/Modules/Objects.cpp index 7bfe3f68..27e09039 100644 --- a/sfall/Modules/Objects.cpp +++ b/sfall/Modules/Objects.cpp @@ -120,6 +120,7 @@ static void __declspec(naked) queue_add_hack() { __asm { mov [edx + 8], edi; // queue.object mov [edx], esi; // queue.time + // test edi, edi; jnz fix; retn; @@ -152,9 +153,7 @@ end: } void Objects::SetAutoUnjamLockTime(DWORD time) { - if (!unjamTimeState) { - BlockCall(0x4A364A); // disable auto unjam at midnight - } + if (!unjamTimeState) BlockCall(0x4A364A); // disable auto unjam at midnight if (time > 0) { SafeWrite8(0x4831D9, (BYTE)time); diff --git a/sfall/Modules/Tiles.cpp b/sfall/Modules/Tiles.cpp index 26707387..3fe647f9 100644 --- a/sfall/Modules/Tiles.cpp +++ b/sfall/Modules/Tiles.cpp @@ -274,8 +274,8 @@ void Tiles::init() { SafeWriteBatch(0x40, Tiles_40); SafeWriteBatch(0xC0, Tiles_C0); if (hrpVersionValid) { // Check HRP 4.1.8 - SafeWrite8(HRPAddressOffset(0xE1C0), 0x40); - SafeWrite8(HRPAddressOffset(0xE1DA), 0x3F); + SafeWrite8(HRPAddress(0x1000E1C0), 0x40); + SafeWrite8(HRPAddress(0x1000E1DA), 0x3F); } dlogr(" Done", DL_INIT); } diff --git a/sfall/main.cpp b/sfall/main.cpp index 0ff293ee..e55d34f6 100644 --- a/sfall/main.cpp +++ b/sfall/main.cpp @@ -98,8 +98,8 @@ static char translationIni[65]; DWORD modifiedIni; DWORD hrpDLLBaseAddr = 0x10000000; -DWORD HRPAddressOffset(DWORD offset) { - return (hrpDLLBaseAddr + offset); +DWORD HRPAddress(DWORD addr) { + return (hrpDLLBaseAddr + (addr & 0xFFFFF)); } int iniGetInt(const char* section, const char* setting, int defaultValue, const char* iniFile) { @@ -323,7 +323,7 @@ defaultIni: hrpIsEnabled = (*(DWORD*)0x4E4480 != 0x278805C7); // check if HRP is enabled if (hrpIsEnabled) { LoadHRPModule(); - if (strncmp((const char*)HRPAddressOffset(0x39940), "4.1.8", 5) == 0) hrpVersionValid = true; + if (strncmp((const char*)HRPAddress(0x10039940), "4.1.8", 5) == 0) hrpVersionValid = true; } InitModules(); diff --git a/sfall/main.h b/sfall/main.h index 43ca9509..81ac2f03 100644 --- a/sfall/main.h +++ b/sfall/main.h @@ -106,7 +106,7 @@ std::string Translate(const char* section, const char* setting, const char* defa // Translates given string using Sfall translation INI file and puts the result into given buffer. size_t Translate(const char* section, const char* setting, const char* defaultValue, char* buffer, size_t bufSize = 128); -DWORD HRPAddressOffset(DWORD offset); +DWORD HRPAddress(DWORD addr); extern const char ddrawIni[]; extern DWORD modifiedIni; diff --git a/sfall/version.h b/sfall/version.h index e48dc61a..1a9d0c4e 100644 --- a/sfall/version.h +++ b/sfall/version.h @@ -24,7 +24,7 @@ #define VERSION_MAJOR 4 #define VERSION_MINOR 2 -#define VERSION_BUILD 1 +#define VERSION_BUILD 2 #define VERSION_REV 0 -#define VERSION_STRING "4.2.1" +#define VERSION_STRING "4.2.2"