From 112c931ea3496828a7f987e28d02b4e862720716 Mon Sep 17 00:00:00 2001 From: NovaRain Date: Wed, 5 Aug 2020 16:18:19 +0800 Subject: [PATCH] Added a patch to allow setting custom colors for object outlines Added a tweak to ObjCanSeeObj_ShootThru_Fix to allow critters to see through other critters. Fixed the internal variable for Horrigan encounter always being reset if DisableHorrigan=0 (commit 74d3cb9) Corrected some code. --- artifacts/ddraw.ini | 7 +-- artifacts/scripting/sfall function notes.txt | 5 ++- sfall/HeroAppearance.cpp | 4 +- sfall/LoadGameHook.cpp | 13 +++--- sfall/LoadOrder.cpp | 12 +++-- sfall/MiscPatches.cpp | 47 +++++++++++++++++--- 6 files changed, 59 insertions(+), 29 deletions(-) diff --git a/artifacts/ddraw.ini b/artifacts/ddraw.ini index d778bf0f..06f4f884 100644 --- a/artifacts/ddraw.ini +++ b/artifacts/ddraw.ini @@ -106,7 +106,7 @@ AllowSoundForFloats=0 AllowDShowSound=0 ;Set to 1 to override the default music path with data\sound\music\ if music_path is not present in the cfg -;Set to 2 to overwrite all occurances of the music path +;Set to 2 to overwrite all occurrences of the music path OverrideMusicDir=1 ;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX @@ -184,6 +184,7 @@ HighlightCorpses=1 ;16 - bright yellow ;32 - dark yellow ;64 - purple +;You can set a custom color from the game palette by multiplying the color index value by 256 (available since sfall 3.8.27) OutlineColor=16 ;A key to press to reload your currently equipped weapon or use the active item @@ -560,8 +561,8 @@ SuperStimExploitFix=0 InventoryApCost=4 QuickPocketsApCostReduction=2 -;Set to 1 to allow objects seeing through other objects that have their ShootThru flag set -;Note that enabling this option can cause unexpected NPC behavior in some situations +;Set to 1 to fix obj_can_see_obj script function to allow critters to see through other critters and objects with 'ShootThru' flag set +;Note that enabling this option can cause unexpected NPC behavior in some situations, e.g. able to attack or enter into a dialogue with the player behind some objects ObjCanSeeObj_ShootThru_Fix=0 ;Set to 1 to fix the broken obj_can_hear_obj script function diff --git a/artifacts/scripting/sfall function notes.txt b/artifacts/scripting/sfall function notes.txt index 3b0eee11..be27e703 100644 --- a/artifacts/scripting/sfall function notes.txt +++ b/artifacts/scripting/sfall function notes.txt @@ -417,8 +417,9 @@ Some utility/math functions are available: - gets the current outline color for an object > void sfall_func2("set_outline", object, int color) -- sets the outline color of an object -- 0 means or any value above 0x00FFFFFF disables the outline +- sets the outline color of an object (see OUTLINE_* constants in sfall.h) +- can also set a custom color from the game palette by shifting the color index value 8 bits left: 0xCC00 where CC is the palette index (available since sfall 4.2.7/3.8.27) +- passing 0 will disable the outline - call "tile_refresh_display" after changing outline of objects to properly redraw the scene > int sfall_func1("get_flags", object) diff --git a/sfall/HeroAppearance.cpp b/sfall/HeroAppearance.cpp index 08fd0ed0..d5443843 100644 --- a/sfall/HeroAppearance.cpp +++ b/sfall/HeroAppearance.cpp @@ -246,8 +246,8 @@ checkArt: call db_access_; // check art file exists test eax, eax; jz notExists; - //mov eax, _art_name; - jmp LoadOrder_art_get_name_hack; //retn; Not sure if we need a jump to: art_get_name_hack + mov eax, _art_name; + retn; notExists: // if file not found load regular critter art instead sub esi, critterArraySize; add esp, 4; // drop func ret address diff --git a/sfall/LoadGameHook.cpp b/sfall/LoadGameHook.cpp index d0fa7c33..d19fdb11 100644 --- a/sfall/LoadGameHook.cpp +++ b/sfall/LoadGameHook.cpp @@ -50,13 +50,11 @@ #include "version.h" #include "Worldmap.h" -#define MAX_GLOBAL_SIZE (MaxGlobalVars * 12 + 4) - static DWORD inLoop = 0; static DWORD saveInCombatFix; +static bool gameLoaded = false; static bool disableHorrigan = false; static bool pipBoyAvailableAtGameStart = false; -static bool gameLoaded = false; // True if game was started, false when on the main menu bool IsGameLoaded() { @@ -239,7 +237,7 @@ errorLoad: static void __stdcall LoadGame_After() { CritLoad(); - *ptr_Meet_Frank_Horrigan = disableHorrigan; + if (disableHorrigan) *ptr_Meet_Frank_Horrigan = true; LoadGlobalScripts(); gameLoaded = true; } @@ -321,7 +319,7 @@ static void NewGame2() { CritLoad(); SetNewCharAppearanceGlobals(); LoadHeroAppearance(); - *ptr_Meet_Frank_Horrigan = disableHorrigan; + if (disableHorrigan) *ptr_Meet_Frank_Horrigan = true; LoadGlobalScripts(); dlogr("New Game started.", DL_MAIN); @@ -339,8 +337,7 @@ static void __declspec(naked) NewGame() { } static void ReadExtraGameMsgFilesIfNeeded() { - if (gExtraGameMsgLists.empty()) - ReadExtraGameMsgFiles(); + if (gExtraGameMsgLists.empty()) ReadExtraGameMsgFiles(); } static void __declspec(naked) MainMenuHook() { @@ -349,7 +346,7 @@ static void __declspec(naked) MainMenuHook() { push 0; call ResetState; mov al, pipBoyAvailableAtGameStart; - mov byte ptr ds:[_gmovie_played_list + 0x3], al; + mov byte ptr ds:[_gmovie_played_list + 3], al; call ReadExtraGameMsgFilesIfNeeded; popad; jmp main_menu_loop_; diff --git a/sfall/LoadOrder.cpp b/sfall/LoadOrder.cpp index 820203eb..9a37978c 100644 --- a/sfall/LoadOrder.cpp +++ b/sfall/LoadOrder.cpp @@ -269,16 +269,14 @@ void __declspec(naked) LoadOrder_art_get_name_hack() { jne artHasAlias; retn; artHasAlias: - sub esp, 4; - mov edx, esp; - call db_dir_entry_; - add esp, 4; - cmp eax, -1; - je artNotExist; + call db_access_; + test eax, eax; + jz artNotExist; mov aliasFID, -1; mov eax, _art_name; retn; artNotExist: + dec eax; // -1 xchg eax, aliasFID add esp, 4; jmp art_get_name_Alias; // get name of art alias @@ -304,7 +302,7 @@ void LoadOrderInit() { HookCall(0x44436D, game_init_databases_hook1); } - // Predefined behavior for replacing art aliases for critters + // Redefined behavior for replacing art aliases for critters // first check the existence of the art file of the current critter and then replace the art alias if file not found HookCall(0x419440, art_get_name_hook); SafeWrite16(0x419521, 0x003B); // jmp 0x419560 diff --git a/sfall/MiscPatches.cpp b/sfall/MiscPatches.cpp index cf90b7e4..466a018f 100644 --- a/sfall/MiscPatches.cpp +++ b/sfall/MiscPatches.cpp @@ -125,13 +125,31 @@ fail: } static void __declspec(naked) op_obj_can_see_obj_hook() { + using namespace Fields; __asm { - push obj_shoot_blocking_at_; // check hex objects func pointer - push 0x20; // flags, 0x20 = check ShootThru - mov ecx, dword ptr [esp + 0x0C]; // buf **ret_objStruct - push ecx; - xor ecx, ecx; - call make_straight_path_func_; // (EAX *objStruct, EDX hexNum1, EBX hexNum2, ECX 0, stack1 **ret_objStruct, stack2 flags, stack3 *check_hex_objs_func) + mov edi, [esp + 4]; // buf **ret_objStruct + push obj_shoot_blocking_at_; // check hex objects func pointer + push 0x20; // flags, 0x20 = check ShootThru + push edi; + call make_straight_path_func_; + // fix: see through critters + mov edx, [esp + 4]; + mov ebx, [edx]; + test ebx, ebx; + jz skip; + cmp ebx, [edx - 8]; // target + jne noTarget; +skip: + retn 8; +noTarget: + mov eax, [ebx + protoId]; + shr eax, 24; + cmp eax, OBJ_TYPE_CRITTER; + je isCritter; + retn 8; +isCritter: + mov [edx - 4], ebx; // replace source + mov dword ptr [esp], 0x456BAB; // continue retn 8; } } @@ -198,6 +216,18 @@ skip: } } +static void __declspec(naked) obj_render_outline_hack() { + __asm { + test eax, 0xFF00; + jnz palColor; + mov al, ds:[_GoodColor]; + retn; +palColor: + mov al, ah; + retn; + } +} + static void AdditionalWeaponAnimsPatch() { if (GetConfigInt("Misc", "AdditionalWeaponAnims", 0)) { dlog("Applying additional weapon animations patch.", DL_INIT); @@ -352,7 +382,7 @@ static void DisablePipboyAlarmPatch() { static void ObjCanSeeShootThroughPatch() { if (GetConfigInt("Misc", "ObjCanSeeObj_ShootThru_Fix", 0)) { - dlog("Applying ObjCanSeeObj ShootThru Fix.", DL_INIT); + dlog("Applying obj_can_see_obj fix for critters and ShootThru objects.", DL_INIT); HookCall(0x456BC6, op_obj_can_see_obj_hook); dlogr(" Done", DL_INIT); } @@ -593,6 +623,9 @@ void MiscPatchesInit() { const DWORD drawCardAddr[] = {0x43ACD5, 0x43DD37}; // 136, 133 SafeWriteBatch(145, drawCardAddr); + // Allow setting custom colors from the game palette for object outlines + MakeCall(0x48EE00, obj_render_outline_hack); + F1EngineBehaviorPatch(); DialogueFix(); AdditionalWeaponAnimsPatch();