From 42ded7e6e532a18b656574cb9ce09b6e8cc531cb Mon Sep 17 00:00:00 2001 From: BobTheBob Date: Wed, 22 Feb 2023 14:51:22 +0000 Subject: commit for branch change --- NorthstarDLL/mods/modmanager.cpp | 1 + NorthstarDLL/mods/modmanager.h | 8 +- NorthstarDLL/mods/reload/reloadmodweapons.cpp | 108 ++++++++++++++++++++++++++ 3 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 NorthstarDLL/mods/reload/reloadmodweapons.cpp (limited to 'NorthstarDLL/mods') diff --git a/NorthstarDLL/mods/modmanager.cpp b/NorthstarDLL/mods/modmanager.cpp index 06e32e29..10c351ba 100644 --- a/NorthstarDLL/mods/modmanager.cpp +++ b/NorthstarDLL/mods/modmanager.cpp @@ -896,6 +896,7 @@ void ModManager::CheckModFilesForChanges() { // TODO: need to check whether any ui scripts have changed + // need to do this by calling LoadScriptsRson (client.dll+3177D0) and getting the list of scripts loaded from that maybe if (!pChangedFile->m_Path.parent_path().compare("resource/ui/")) { diff --git a/NorthstarDLL/mods/modmanager.h b/NorthstarDLL/mods/modmanager.h index 253b7812..940f1967 100644 --- a/NorthstarDLL/mods/modmanager.h +++ b/NorthstarDLL/mods/modmanager.h @@ -126,6 +126,9 @@ struct ModOverrideFile fs::file_time_type m_tLastWriteTime; }; +// defined in reloadmodweapons.cpp +extern struct SidedWeaponReloadPointers; + class ModManager { private: @@ -165,7 +168,6 @@ class ModManager bool bPlaylists = false; bool bAimAssistSettings = false; bool bMaterials = false; // vmts - bool bWeaponSettings = false; bool bPlayerSettings = false; bool bAiSettings = false; bool bDamageDefs = false; // damagedefs @@ -177,6 +179,7 @@ class ModManager bool bRPaks = false; // assets that we can reload individually + std::unordered_set setsWeaponSettings; //std::vector vAudioOverrides } m_AssetTypesToReload; @@ -224,6 +227,9 @@ class ModManager void TryBuildKeyValues(const char* filename); void BuildKBActionsList(); + // asset reloading funcs + bool TryReloadWeapon(const char* pWeaponName, const SidedWeaponReloadPointers* pReloadPointers); + // for std::views::filter, e.g. for (Mod& mod : g_pModManager::GetMods() | ModManager::FilterEnabled) static inline constexpr auto FilterEnabled = std::views::filter([](Mod& mod) { return mod.m_bEnabled; }); static inline constexpr auto FilterRemote = std::views::filter([](Mod& mod) { return mod.m_bRemote; }); diff --git a/NorthstarDLL/mods/reload/reloadmodweapons.cpp b/NorthstarDLL/mods/reload/reloadmodweapons.cpp new file mode 100644 index 00000000..297c3d48 --- /dev/null +++ b/NorthstarDLL/mods/reload/reloadmodweapons.cpp @@ -0,0 +1,108 @@ +#include "mods/modmanager.h" + +AUTOHOOK_INIT() + +OFFSET_STRUCT(WeaponDefinition) +{ + FIELD(5, bool bUnk); // this controls whether we reload script funcs + FIELD(6, char pWeaponName[]); // this probably has a max length but i do not know what it is +}; + +OFFSET_STRUCT(GlobalWeaponDefs) +{ + // each entry is 24 bytes, but no clue what the bytes after the def are, so just ignore atm + // need the full struct so we iterate properly + OFFSET_STRUCT(WeaponDefContainer) + { + STRUCT_SIZE(24); + WeaponDefinition* pWeaponDef; + }; + + FIELD(16, WeaponDefContainer m_Weapons[]); +}; + +uint16_t* g_pnClientWeaponsLoaded; +GlobalWeaponDefs** g_ppClientWeaponDefs; + +void (*ClientReparseWeapon)(WeaponDefinition* pWeapon); +void (*ClientReloadWeaponCallbacks)(int nWeaponIndex); +int (*ClientWeaponIndexByName)(const char* pWeaponName); + +uint16_t* g_pnServerWeaponsLoaded; +GlobalWeaponDefs** g_ppServerWeaponDefs; + +void (*ServerReparseWeapon)(WeaponDefinition* pWeapon); +void (*ServerReloadWeaponCallbacks)(int nWeaponIndex); +int (*ServerWeaponIndexByName)(const char* pWeaponName); + +// used for passing client/server funcs/data/pointers to TryReloadWeapon +struct SidedWeaponReloadPointers +{ + // data pointers + uint16_t* m_pnWeaponsLoaded; + GlobalWeaponDefs** m_ppWeaponDefs; + + // funcs + void (*m_fnReparseWeapon)(WeaponDefinition* pWeapon); + void (*m_fnReloadWeaponCallbacks)(int nWeaponIndex); + int (*m_fnWeaponIndexByName)(const char* pWeaponName); + + SidedWeaponReloadPointers( + uint16_t* pnWeaponsLoaded, + GlobalWeaponDefs** ppWeaponDefs, + void (*fnReparseWeapon)(WeaponDefinition*), + void (*fnReloadWeaponCallbacks)(int), + int (*fnWeaponIndexByName)(const char*)) + { + m_pnWeaponsLoaded = pnWeaponsLoaded; + m_ppWeaponDefs = ppWeaponDefs; + m_fnReparseWeapon = fnReparseWeapon; + m_fnReloadWeaponCallbacks = fnReloadWeaponCallbacks; + m_fnWeaponIndexByName = fnWeaponIndexByName; + } +}; + +bool ModManager::TryReloadWeapon(const char* pWeaponName, const SidedWeaponReloadPointers* pReloadPointers) +{ + if (!m_AssetTypesToReload.setsWeaponSettings.contains(pWeaponName)) + return false; // don't reload + + int nWeaponIndex = pReloadPointers->m_fnWeaponIndexByName(pWeaponName); + if (nWeaponIndex == -1) // weapon isn't loaded at all, no need to reload! + return false; + + spdlog::info("ModManager::TryReloadWeapon reloading weapon {}", pWeaponName); + + WeaponDefinition* pWeapon = (*pReloadPointers->m_ppWeaponDefs)->m_Weapons->pWeaponDef; + pReloadPointers->m_fnReparseWeapon(pWeapon); + if (pWeapon->bUnk) + pReloadPointers->m_fnReloadWeaponCallbacks(nWeaponIndex); + + m_AssetTypesToReload.setsWeaponSettings.erase(pWeaponName); + return true; +} + +// TODO: server implementation for this? +AUTOHOOK(ClientPrecacheWeaponFromStringtable, client.dll + 0x195A60, +bool, __fastcall, (void* a1, void* a2, void* a3, const char* pWeaponName)) +{ + static SidedWeaponReloadPointers clientReloadPointers( + g_pnClientWeaponsLoaded, g_ppClientWeaponDefs, ClientReparseWeapon, ClientReloadWeaponCallbacks, ClientWeaponIndexByName); + + if (g_pModManager->TryReloadWeapon(pWeaponName, &clientReloadPointers)) + return true; + + spdlog::info("PrecacheWeaponFromStringtable: {}", pWeaponName); + return ClientPrecacheWeaponFromStringtable(a1, a2, a3, pWeaponName); +} + +ON_DLL_LOAD_CLIENT("client.dll", ModReloadWeaponsClient, (CModule module)) +{ + AUTOHOOK_DISPATCH() + + g_pnClientWeaponsLoaded = module.Offset(0xB33A02).As(); + g_ppClientWeaponDefs = module.Offset(0xB339E8).As(); + + ClientReparseWeapon = module.Offset(0x3D2FB0).As(); + ClientReloadWeaponCallbacks = module.Offset(0x3CE270).As(); +} -- cgit v1.2.3