From d6486008f42e36c0039e0f259bc6a25187b6fac1 Mon Sep 17 00:00:00 2001 From: NovaRain Date: Tue, 21 Jan 2020 21:40:36 +0800 Subject: [PATCH] Expanded the functionality of Fallout1Behavior * calling endgame_movie now plays Movie11 or Movie12 depending on the player's gender before the credits. Added new flags to force_encounter_with_flags function. --- artifacts/ddraw.ini | 1 + artifacts/scripting/headers/sfall.h | 8 +++++--- sfall/FalloutEngine.cpp | 3 +++ sfall/FalloutEngine.h | 3 +++ sfall/ScriptOps/WorldmapOps.hpp | 20 +++++++++++++++----- sfall/main.cpp | 24 +++++++++++++++++++++--- 6 files changed, 48 insertions(+), 11 deletions(-) diff --git a/artifacts/ddraw.ini b/artifacts/ddraw.ini index e6ced501..157d4a84 100644 --- a/artifacts/ddraw.ini +++ b/artifacts/ddraw.ini @@ -188,6 +188,7 @@ DebugEditorKey=0 ;Changes some of Fallout 2 engine functions to Fallout 1 behavior: ;- disables playing the final movie/credits after the endgame slideshow ;- disables halving the weight for power armor items +;- endgame_movie script function plays movie 10 or 11 based on the player's gender before the credits Fallout1Behavior=0 ;Time limit in years. Must be between -3 and 13 diff --git a/artifacts/scripting/headers/sfall.h b/artifacts/scripting/headers/sfall.h index 0fb65cdc..1cda8e42 100644 --- a/artifacts/scripting/headers/sfall.h +++ b/artifacts/scripting/headers/sfall.h @@ -59,9 +59,11 @@ #define LIST_ALL (9) //Valid flags for force_encounter_with_flags -#define ENCOUNTER_FLAG_NO_CAR (1) -#define ENCOUNTER_FLAG_LOCK (2) // block new forced encounter by the next function call until the current specified encounter occurs -#define ENCOUNTER_FLAG_SPECIAL (4) // special blinking icon +#define ENCOUNTER_FLAG_NO_CAR (0x1) +#define ENCOUNTER_FLAG_LOCK (0x2) // block new forced encounter by the next function call until the current specified encounter occurs +#define ENCOUNTER_FLAG_NO_ICON (0x4) // disable displaying the flashing icon +#define ENCOUNTER_FLAG_ICON_SP (0x8) // use special encounter icon +#define ENCOUNTER_FLAG_FADEOUT (0x10) // fade out the screen on encounter (Note: you yourself should restore the fade screen when entering the encounter) //The attack types returned by get_attack_type #define ATKTYPE_LWEP1 (0) diff --git a/sfall/FalloutEngine.cpp b/sfall/FalloutEngine.cpp index b3e0109c..0fdf8a84 100644 --- a/sfall/FalloutEngine.cpp +++ b/sfall/FalloutEngine.cpp @@ -394,6 +394,7 @@ const DWORD gmouse_3d_get_mode_ = 0x44CB6C; const DWORD gmouse_3d_set_mode_ = 0x44CA18; const DWORD gmouse_is_scrolling_ = 0x44B54C; const DWORD gmouse_set_cursor_ = 0x44C840; +const DWORD gmovie_play_ = 0x44E690; const DWORD GNW_find_ = 0x4D7888; const DWORD GNW95_process_message_ = 0x4C9CF0; const DWORD gsnd_build_weapon_sfx_name_ = 0x451760; @@ -557,6 +558,7 @@ const DWORD obj_use_book_ = 0x49B9F0; const DWORD obj_use_power_on_car_ = 0x49BDE8; const DWORD object_under_mouse_ = 0x44CEC4; const DWORD OptionWindow_ = 0x437C08; +const DWORD palette_fade_to_ = 0x493AD4; const DWORD palette_init_ = 0x493A00; const DWORD palette_set_to_ = 0x493B48; const DWORD partyMemberCopyLevelInfo_ = 0x495EA8; @@ -567,6 +569,7 @@ const DWORD partyMemberPrepItemSaveAll_ = 0x495140; const DWORD partyMemberPrepLoad_ = 0x4947AC; const DWORD partyMemberRemove_ = 0x4944DC; const DWORD partyMemberSaveProtos_ = 0x495870; +const DWORD pause_for_tocks_ = 0x4C937C; const DWORD pc_flag_off_ = 0x42E220; const DWORD pc_flag_on_ = 0x42E26C; const DWORD pc_flag_toggle_ = 0x42E2B0; diff --git a/sfall/FalloutEngine.h b/sfall/FalloutEngine.h index c1f6e905..cf5f2587 100644 --- a/sfall/FalloutEngine.h +++ b/sfall/FalloutEngine.h @@ -636,6 +636,7 @@ extern const DWORD gmouse_3d_get_mode_; extern const DWORD gmouse_3d_set_mode_; extern const DWORD gmouse_is_scrolling_; extern const DWORD gmouse_set_cursor_; +extern const DWORD gmovie_play_; extern const DWORD GNW_find_; extern const DWORD GNW95_process_message_; extern const DWORD gsnd_build_weapon_sfx_name_; @@ -808,6 +809,7 @@ extern const DWORD obj_use_book_; extern const DWORD obj_use_power_on_car_; extern const DWORD object_under_mouse_; extern const DWORD OptionWindow_; +extern const DWORD palette_fade_to_; extern const DWORD palette_init_; extern const DWORD palette_set_to_; extern const DWORD partyMemberCopyLevelInfo_; @@ -818,6 +820,7 @@ extern const DWORD partyMemberPrepItemSaveAll_; extern const DWORD partyMemberPrepLoad_; extern const DWORD partyMemberRemove_; extern const DWORD partyMemberSaveProtos_; +extern const DWORD pause_for_tocks_; extern const DWORD pc_flag_off_; extern const DWORD pc_flag_on_; extern const DWORD pc_flag_toggle_; diff --git a/sfall/ScriptOps/WorldmapOps.hpp b/sfall/ScriptOps/WorldmapOps.hpp index 9eeabeae..a6b46d70 100644 --- a/sfall/ScriptOps/WorldmapOps.hpp +++ b/sfall/ScriptOps/WorldmapOps.hpp @@ -27,6 +27,7 @@ static DWORD ForceEncounterMapID = -1; static DWORD ForceEncounterFlags; DWORD ForceEncounterRestore() { + if (ForceEncounterMapID == -1) return 0; long long data = 0x672E043D83; // cmp ds:_Meet_Frank_Horrigan, 0 SafeWriteBytes(0x4C06D1, (BYTE*)&data, 5); ForceEncounterFlags = 0; @@ -35,12 +36,21 @@ DWORD ForceEncounterRestore() { return mapID; } -// implements a blinking encounter icon -static void ForceEncounterIcon() { - long iconType = (ForceEncounterFlags & 4) ? 3 : 1; // icon type flag (special: 0-3, normal: 0-1) +static void ForceEncounterEffects() { + if (ForceEncounterFlags & 0x10) { // _FadeOut flag + __asm mov eax, _black_palette; + __asm call palette_fade_to_; + return; + }; + + // implements a flashing encounter icon + if (ForceEncounterFlags & 4) return; // _NoIcon flag + long iconType = (ForceEncounterFlags & 8) ? 3 : 1; // icon type flag (special: 0-3, normal: 0-1) + *(DWORD*)_wmEncounterIconShow = 1; *(DWORD*)_wmRndCursorFid = 0; - for (size_t n = 0; n < 7; ++n) { + + for (size_t n = 8; n > 0; --n) { long iconFidIndex = iconType - *(DWORD*)_wmRndCursorFid; *(DWORD*)_wmRndCursorFid = iconFidIndex; __asm call wmInterfaceRefresh_; @@ -59,7 +69,7 @@ static void __declspec(naked) wmRndEncounterOccurred_hack() { mov eax, ForceEncounterMapID; call wmMatchAreaContainingMapIdx_; noCar: - call ForceEncounterIcon; + call ForceEncounterEffects; call ForceEncounterRestore; push 0x4C0721; // return addr jmp map_load_idx_; // eax - mapID diff --git a/sfall/main.cpp b/sfall/main.cpp index 0aa3bea8..549e0258 100644 --- a/sfall/main.cpp +++ b/sfall/main.cpp @@ -218,9 +218,9 @@ end: } } -static const DWORD ScannerHookRet = 0x41BC1D; +static const DWORD ScannerHookRet = 0x41BC1D; static const DWORD ScannerHookFail = 0x41BC65; -static void __declspec(naked) ScannerAutomapHook() { +static void __declspec(naked) automap_hack() { __asm { mov eax, ds:[_obj_dude]; mov edx, PID_MOTION_SENSOR; @@ -306,6 +306,23 @@ static void __declspec(naked) display_stats_hook() { } } +static void __declspec(naked) endgame_movie_hook() { + __asm { + cmp [esp + 16], 0x45C563; // call from op_endgame_movie_ + je playWalkMovie; + retn; +playWalkMovie: + call stat_level_; + xor edx, edx; + add eax, 10; + mov ecx, eax; + mov eax, 1500; + call pause_for_tocks_; + mov eax, ecx; + jmp gmovie_play_; + } +} + static void DllMain2() { long tmp; dlogr("In DllMain2", DL_MAIN); @@ -503,6 +520,7 @@ static void DllMain2() { dlog("Applying Fallout 1 engine behavior patch.", DL_INIT); BlockCall(0x4A4343); // disable playing the final movie/credits after the endgame slideshow SafeWrite8(0x477C71, 0xEB); // disable halving the weight for power armor items + HookCall(0x43F872, endgame_movie_hook); // play movie 10 or 11 based on the player's gender before the credits dlogr(" Done", DL_INIT); } @@ -599,7 +617,7 @@ static void DllMain2() { if (tmp = GetConfigInt("Misc", "MotionScannerFlags", 1)) { dlog("Applying MotionScannerFlags patch.", DL_INIT); - if (tmp & 1) MakeJump(0x41BBE9, ScannerAutomapHook); + if (tmp & 1) MakeJump(0x41BBE9, automap_hack); if (tmp & 2) { // automap_ SafeWrite16(0x41BC24, 0x9090);