From 486c8972436a1509e91f0ebbcb760781f2598067 Mon Sep 17 00:00:00 2001 From: NovaRain Date: Fri, 19 Jul 2024 19:51:04 +0800 Subject: [PATCH] Added new HOOK_BUILDSFXWEAPON * Hook for gsnd_build_weapon_sfx_name * Fixed long name ACM crash in AutoSearchSFX * Updated documents --- artifacts/scripting/headers/sfall.h | 2 + artifacts/scripting/hookscripts.md | 20 ++++++++ sfall/Modules/HookScripts.cpp | 21 ++++++-- sfall/Modules/HookScripts.h | 2 + sfall/Modules/HookScripts/SoundHs.cpp | 74 +++++++++++++++++++++++++++ sfall/Modules/HookScripts/SoundHs.h | 10 ++++ sfall/Modules/Sound.cpp | 1 + sfall/ddraw.vcxproj | 2 + sfall/ddraw.vcxproj.filters | 6 +++ 9 files changed, 135 insertions(+), 3 deletions(-) create mode 100644 sfall/Modules/HookScripts/SoundHs.cpp create mode 100644 sfall/Modules/HookScripts/SoundHs.h diff --git a/artifacts/scripting/headers/sfall.h b/artifacts/scripting/headers/sfall.h index ed3ec52f..3bf00b4d 100644 --- a/artifacts/scripting/headers/sfall.h +++ b/artifacts/scripting/headers/sfall.h @@ -76,6 +76,8 @@ #define HOOK_ROLLCHECK (46) #define HOOK_BESTWEAPON (47) #define HOOK_CANUSEWEAPON (48) +// RESERVED 49..60 +#define HOOK_BUILDSFXWEAPON (61) // Valid arguments to list_begin #define LIST_CRITTERS (0) diff --git a/artifacts/scripting/hookscripts.md b/artifacts/scripting/hookscripts.md index 819fd060..2aa2dfd4 100644 --- a/artifacts/scripting/hookscripts.md +++ b/artifacts/scripting/hookscripts.md @@ -878,3 +878,23 @@ int arg3 - original result of engine function: 1 - can use, 0 - cannot use int ret0 - overrides the result of engine function. Any non-zero value allows using the weapon ``` + +------------------------------------------- + +#### `HOOK_BUILDSFXWEAPON (hs_buildsfxweapon.int)` + +Runs before each weapon sound effect is played or added to the animation queue to determine the name of the sound effect file based on the weapon, target, and action being performed. + +``` +int arg0 - weapon sound effect type: + 0 - ready/reload + 1 - attack + 2 - out of ammo + 3 - flying (for projectiles from weapons) + 4 - hit +Item arg1 - the weapon being used +int arg2 - attack type (see ATKTYPE_* constants) +Obj arg3 - the target of the attack (can be 0) + +String ret0 - the filename of the new sound effect to use, without extension (relative to the sound\sfx\ directory) +``` diff --git a/sfall/Modules/HookScripts.cpp b/sfall/Modules/HookScripts.cpp index 4e9a6ef0..81e16dd0 100644 --- a/sfall/Modules/HookScripts.cpp +++ b/sfall/Modules/HookScripts.cpp @@ -30,6 +30,7 @@ #include "HookScripts\InventoryHs.h" #include "HookScripts\ObjectHs.h" #include "HookScripts\MiscHs.h" +#include "HookScripts\SoundHs.h" #include "HookScripts.h" @@ -99,18 +100,31 @@ static HooksInjectInfo injectHooks[] = { {HOOK_DESCRIPTIONOBJ, Inject_DescriptionObjHook, false}, {HOOK_USESKILLON, Inject_UseSkillOnHook, false}, {HOOK_ONEXPLOSION, Inject_OnExplosionHook, false}, - {-1, nullptr, false}, // dummy + {-1}, // unimplemented {HOOK_SETLIGHTING, Inject_SetLightingHook, false}, {HOOK_SNEAK, Inject_SneakCheckHook, false}, {HOOK_STDPROCEDURE, Inject_ScriptProcedureHook, false}, {HOOK_STDPROCEDURE_END, Inject_ScriptProcedureHook2, false}, {HOOK_TARGETOBJECT, Inject_TargetObjectHook, false}, {HOOK_ENCOUNTER, Inject_EncounterHook, false}, - {-1, nullptr, false}, // dummy - {-1, nullptr, false}, // dummy + {-1}, // unimplemented + {-1}, // unimplemented {HOOK_ROLLCHECK, Inject_RollCheckHook, false}, {HOOK_BESTWEAPON, Inject_BestWeaponHook, false}, {HOOK_CANUSEWEAPON, Inject_CanUseWeaponHook, false}, + {-1}, // RESERVED + {-1}, // RESERVED + {-1}, // HOOK_MOUSEWHEEL + {-1}, // RESERVED + {-1}, // RESERVED + {-1}, // RESERVED + {-1}, // HOOK_COMBATATTACK + {-1}, // RESERVED + {-1}, // RESERVED + {-1}, // RESERVED + {-1}, // RESERVED + {-1}, // RESERVED + {HOOK_BUILDSFXWEAPON, Inject_BuildSfxWeaponHook, false}, }; void HookScripts::InjectingHook(int hookId) { @@ -217,6 +231,7 @@ void HookScripts::LoadHookScripts() { InitInventoryHookScripts(); InitObjectHookScripts(); InitMiscHookScripts(); + InitSoundHookScripts(); HookScripts::LoadHookScript("hs_keypress", HOOK_KEYPRESS); HookScripts::LoadHookScript("hs_mouseclick", HOOK_MOUSECLICK); diff --git a/sfall/Modules/HookScripts.h b/sfall/Modules/HookScripts.h index 02f014a7..ec2329d0 100644 --- a/sfall/Modules/HookScripts.h +++ b/sfall/Modules/HookScripts.h @@ -75,6 +75,8 @@ enum HookType HOOK_ROLLCHECK = 46, HOOK_BESTWEAPON = 47, HOOK_CANUSEWEAPON = 48, + // RESERVED 49 to 60 + HOOK_BUILDSFXWEAPON = 61, HOOK_COUNT }; diff --git a/sfall/Modules/HookScripts/SoundHs.cpp b/sfall/Modules/HookScripts/SoundHs.cpp new file mode 100644 index 00000000..6e086918 --- /dev/null +++ b/sfall/Modules/HookScripts/SoundHs.cpp @@ -0,0 +1,74 @@ +#include "..\..\FalloutEngine\Fallout2.h" +#include "..\..\SafeWrite.h" +#include "..\HookScripts.h" +#include "Common.h" + +#include "SoundHs.h" + +using namespace sfall::script; + +namespace sfall +{ + +static DWORD __fastcall BuildSfxWeaponHook_Script(long effectType, fo::GameObject* weapon, long hitMode, fo::GameObject* target) { + BeginHook(); + allowNonIntReturn = true; + argCount = 4; + + args[0] = effectType; + args[1] = (DWORD)weapon; + args[2] = (DWORD)hitMode; + args[3] = (DWORD)target; + + RunHookScript(HOOK_BUILDSFXWEAPON); + + DWORD textPtr = cRet > 0 && retTypes[0] == DATATYPE_STR + ? rets[0] + : 0; + EndHook(); + + return textPtr; // -1 - default handler +} + +static __declspec(naked) void gsnd_build_weapon_sfx_name_hook() { + __asm { + pushadc; // save state + push ebx; + push ecx; // target + push ebx; // hitMode + mov ecx, eax; // effectType + call BuildSfxWeaponHook_Script; // edx - weapon + test eax, eax; // pointer to text + pop ebx; // restore state + pop ecx; + pop edx; + jnz skip; + pop eax; + jmp fo::funcoffs::gsnd_build_weapon_sfx_name_; +skip: + add esp, 4; + retn; + } +} + + +void Inject_BuildSfxWeaponHook() { + const DWORD weaponSfxNameHkAddr[] = { + 0x410DB3, // show_damage_to_object_ + 0x411397, 0x411538, // action_melee_ + 0x411787, 0x41196C, 0x411A96, 0x411B82, // action_ranged_ + 0x4268F5, // combat_attack_this_ + 0x42A9B4, 0x42AA92, 0x42AAF0, // ai_try_attack_ + 0x42AF4C, // cai_attempt_w_reload_ + 0x45BD31, // op_sfx_build_weapon_name_ + 0x460B87, // intface_item_reload_ + 0x476629, // drop_ammo_into_weapon_ + }; + HookCalls(gsnd_build_weapon_sfx_name_hook, weaponSfxNameHkAddr); +} + +void InitSoundHookScripts() { + HookScripts::LoadHookScript("hs_buildsfxweapon", HOOK_BUILDSFXWEAPON); +} + +} diff --git a/sfall/Modules/HookScripts/SoundHs.h b/sfall/Modules/HookScripts/SoundHs.h new file mode 100644 index 00000000..27aa0b7f --- /dev/null +++ b/sfall/Modules/HookScripts/SoundHs.h @@ -0,0 +1,10 @@ +#pragma once + +namespace sfall +{ + +void InitSoundHookScripts(); + +void Inject_BuildSfxWeaponHook(); + +} diff --git a/sfall/Modules/Sound.cpp b/sfall/Modules/Sound.cpp index b0df0b17..620fff32 100644 --- a/sfall/Modules/Sound.cpp +++ b/sfall/Modules/Sound.cpp @@ -1069,6 +1069,7 @@ void Sound::init() { const DWORD sfxlInitAddr[] = {0x4A9999, 0x4A9B34}; HookCalls(sfxl_init_hook, sfxlInitAddr); SafeWrite8(0x4A9B3F, 0xA9); // jz 0x4A9BEC (skip error message) + SafeWrite8(0x4AA060, 127); // fix crash when ACM file has name longer than 12 characters } if (IniReader::GetConfigString("Sound", "MainMenuMusic", "", mainMenuMusic, 9)) { diff --git a/sfall/ddraw.vcxproj b/sfall/ddraw.vcxproj index ebec11d7..80b36906 100644 --- a/sfall/ddraw.vcxproj +++ b/sfall/ddraw.vcxproj @@ -289,6 +289,7 @@ + @@ -406,6 +407,7 @@ + diff --git a/sfall/ddraw.vcxproj.filters b/sfall/ddraw.vcxproj.filters index 58e8a929..c1945522 100644 --- a/sfall/ddraw.vcxproj.filters +++ b/sfall/ddraw.vcxproj.filters @@ -371,6 +371,9 @@ Modules + + Modules\HookScripts + @@ -675,6 +678,9 @@ Modules + + Modules\HookScripts +