diff options
-rw-r--r-- | NorthstarDLL/config/profile.cpp | 2 | ||||
-rw-r--r-- | NorthstarDLL/core/filesystem/filesystem.cpp | 5 | ||||
-rw-r--r-- | NorthstarDLL/mods/modmanager.cpp | 38 | ||||
-rw-r--r-- | NorthstarDLL/mods/modmanager.h | 13 | ||||
-rw-r--r-- | NorthstarDLL/mods/reload/reloadmodweapons.cpp | 42 | ||||
-rw-r--r-- | NorthstarDLL/mods/reload/reloadmodweapons_misc.cpp | 72 | ||||
-rw-r--r-- | NorthstarDLL/scripts/client/scriptmodmenu.cpp | 7 |
7 files changed, 159 insertions, 20 deletions
diff --git a/NorthstarDLL/config/profile.cpp b/NorthstarDLL/config/profile.cpp index 80ddb59f..017735d0 100644 --- a/NorthstarDLL/config/profile.cpp +++ b/NorthstarDLL/config/profile.cpp @@ -39,5 +39,5 @@ void InitialiseNorthstarPrefix() // set the console title to show the current profile // dont do this on dedi as title contains useful information on dedi and setting title breaks it as well if (!IsDedicatedServer()) - SetConsoleTitleA((fs::path("NorthstarLauncher | ") / NORTHSTAR_FOLDER_PREFIX).string().c_str()); + SetConsoleTitleA((std::string("NorthstarLauncher | ") + NORTHSTAR_FOLDER_PREFIX.string()).c_str()); } diff --git a/NorthstarDLL/core/filesystem/filesystem.cpp b/NorthstarDLL/core/filesystem/filesystem.cpp index b06bd140..1646562c 100644 --- a/NorthstarDLL/core/filesystem/filesystem.cpp +++ b/NorthstarDLL/core/filesystem/filesystem.cpp @@ -12,7 +12,7 @@ using namespace R2; bool bReadingOriginalFile = false; std::string sCurrentModPath; -ConVar* Cvar_ns_fs_log_reads; +VAR_AT(filesystem_stdio.dll + 0xE5940, ConVar*, Cvar_fs_showAllReads); // use the R2 namespace for game funcs namespace R2 @@ -84,6 +84,9 @@ void SetNewModSearchPaths(Mod* mod) bool TryReplaceFile(const char* pPath, bool shouldCompile) { + if (Cvar_fs_showAllReads->GetBool()) + spdlog::info("filesystem open: {}", pPath); + if (bReadingOriginalFile) return false; diff --git a/NorthstarDLL/mods/modmanager.cpp b/NorthstarDLL/mods/modmanager.cpp index ab1ef791..6d36a975 100644 --- a/NorthstarDLL/mods/modmanager.cpp +++ b/NorthstarDLL/mods/modmanager.cpp @@ -294,7 +294,7 @@ ModManager::ModManager() m_LastModLoadState = nullptr; m_ModLoadState = new ModLoadState; - LoadMods(false); + LoadMods(false, false); } template <ScriptContext context> auto ModConCommandCallback_Internal(std::string name, const CCommand& command) @@ -352,7 +352,7 @@ auto ModConCommandCallback(const CCommand& command) -void ModManager::LoadMods(bool bDeferredAssetReload) +void ModManager::LoadMods(bool bReloadAssets, bool bDeferredAssetReload) { // reset state of all currently loaded mods, if we've loaded once already if (m_bHasLoadedMods) @@ -366,7 +366,7 @@ void ModManager::LoadMods(bool bDeferredAssetReload) LoadModDefinitions(); // install mods (load all files) - InstallMods(bDeferredAssetReload); + InstallMods(bReloadAssets, bDeferredAssetReload); // write json storing currently enabled mods SaveEnabledMods(); @@ -1043,6 +1043,21 @@ void ModManager::ReloadNecessaryModAssets(bool bDeferred, const ModAssetsToReloa } else { + if (pAssetsToReload->bAimAssistSettings) + TryImmediateReloadADSPulls(); + + if (pAssetsToReload->bAmmoSuckBehaviours) + TryImmediateReloadAmmoSuckBehaviours(); + + if (pAssetsToReload->bDamageDefs) + TryImmediateReloadDamageFlags(); + + if (pAssetsToReload->bWeaponSprings) + TryImmediateReloadWeaponSprings(); + + TryImmediateReloadWeapons(pAssetsToReload->setsWeaponSettings); + + // need to reimplement mat_reloadmaterials for this // if (m_AssetTypesToReload.bMaterials) // R2::Cbuf_AddText(R2::Cbuf_GetCurrentPlayer(), "mat_reloadmaterials", R2::cmd_source_t::kCommandSrcCode); @@ -1057,7 +1072,7 @@ void ModManager::ReloadNecessaryModAssets(bool bDeferred, const ModAssetsToReloa R2::Cbuf_Execute(); } -void ModManager::InstallMods(bool bDeferredAssetReload) +void ModManager::InstallMods(bool bReloadAssets, bool bDeferredAssetReload) { for (Mod& mod : GetMods() | FilterEnabled) { @@ -1075,7 +1090,7 @@ void ModManager::InstallMods(bool bDeferredAssetReload) InstallModFileOverrides(mod); } - if (m_bHasLoadedMods) // only reload assets after initial load + if (m_bHasLoadedMods && bReloadAssets) // only reload assets after initial load { ModAssetsToReload assetsToReload; @@ -1183,12 +1198,20 @@ void ModManager::CompileAssetsForFile(const char* filename) void ConCommand_mods_reload(const CCommand& args) { - g_pModManager->LoadMods(false); + // reload assets now + g_pModManager->LoadMods(true, false); } void ConCommand_mods_reload_deferred(const CCommand& args) { - g_pModManager->LoadMods(true); + // reload assets later + g_pModManager->LoadMods(true, true); +} + +void ConCommand_mods_no_asset_reload(const CCommand& args) +{ + // reload assets never + g_pModManager->LoadMods(false, false); } void ConCommand_mods_getfileowner(const CCommand& args) @@ -1232,5 +1255,6 @@ ON_DLL_LOAD_RELIESON("engine.dll", ModManager, (ConCommand, MasterServer), (CMod RegisterConCommand("reload_mods", ConCommand_mods_reload, "reloads mods", FCVAR_NONE); RegisterConCommand("mods_reload", ConCommand_mods_reload, "reloads mods", FCVAR_NONE); RegisterConCommand("mods_reload_deferred", ConCommand_mods_reload_deferred, "reloads mods, prefers reloading assets on level load rather than now", FCVAR_NONE); + RegisterConCommand("mods_reload_no_asset_reload", ConCommand_mods_no_asset_reload, "reloads mods without trying to reload assets", FCVAR_NONE); RegisterConCommand("mods_getfileowner", ConCommand_mods_getfileowner, "find the mod that owns a given file", FCVAR_NONE); } diff --git a/NorthstarDLL/mods/modmanager.h b/NorthstarDLL/mods/modmanager.h index 9b194ea9..9eccffc5 100644 --- a/NorthstarDLL/mods/modmanager.h +++ b/NorthstarDLL/mods/modmanager.h @@ -141,7 +141,7 @@ class ModManager void LoadModDefinitions(); void SaveEnabledMods(); void BuildPublicModList(); - void InstallMods(bool bDeferredAssetReload); + void InstallMods(bool bReloadAssets, bool bDeferredAssetReload); struct ModAssetsToReload { @@ -203,7 +203,7 @@ class ModManager public: ModManager(); - void LoadMods(bool bDeferredAssetReload); + void LoadMods(bool bReloadAssets, bool bDeferredAssetReload); std::string NormaliseModFilePath(const fs::path path); void CompileAssetsForFile(const char* filename); @@ -235,7 +235,14 @@ class ModManager void DeferredReloadADSPulls(); void DeferredReloadWeapons(const std::unordered_set<std::string> setsWeapons); - // asset reloading funcs + // hybrid asset reloading funcs (i.e. try reload on both client and server immediately, defer sides that aren't currently possible) + void TryImmediateReloadDamageFlags(); + void TryImmediateReloadWeaponSprings(); + void TryImmediateReloadAmmoSuckBehaviours(); + void TryImmediateReloadADSPulls(); + void TryImmediateReloadWeapons(const std::unordered_set<std::string> setsWeapons); + + // individual 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) diff --git a/NorthstarDLL/mods/reload/reloadmodweapons.cpp b/NorthstarDLL/mods/reload/reloadmodweapons.cpp index 4619fb31..077c2835 100644 --- a/NorthstarDLL/mods/reload/reloadmodweapons.cpp +++ b/NorthstarDLL/mods/reload/reloadmodweapons.cpp @@ -1,4 +1,6 @@ #include "mods/modmanager.h" +#include "dedicated/dedicated.h" +#include "engine/r2engine.h" AUTOHOOK_INIT() @@ -23,9 +25,13 @@ OFFSET_STRUCT(GlobalWeaponDefs) VAR_AT(client.dll + 0xB33A02, uint16_t*, g_pnClientWeaponsLoaded); VAR_AT(client.dll + 0xB339E8, GlobalWeaponDefs**, g_ppClientWeaponDefs); +VAR_AT(server.dll + 0xBB57C2, uint16_t*, g_pnServerWeaponsLoaded); +VAR_AT(server.dll + 0xBB57A8, GlobalWeaponDefs**, g_ppServerWeaponDefs); FUNCTION_AT(client.dll + 0x3D2FB0, void,, ClientReparseWeapon, (WeaponDefinition* pWeapon)); FUNCTION_AT(client.dll + 0x3CE270, void,, ClientReloadWeaponCallbacks, (int nWeaponIndex)); +FUNCTION_AT(client.dll + 0x6D1170, void,, ServerReparseWeapon, (WeaponDefinition * pWeapon)); +FUNCTION_AT(client.dll + 0x6CCE80, void, , ServerReloadWeaponCallbacks, (int nWeaponIndex)); std::unordered_set<std::string> setsClientWeaponsToReload; std::unordered_set<std::string> setsServerWeaponsToReload; @@ -43,6 +49,7 @@ struct SidedWeaponReloadPointers void (*m_fnReparseWeapon)(WeaponDefinition* pWeapon); void (*m_fnReloadWeaponCallbacks)(int nWeaponIndex); + SidedWeaponReloadPointers() {} // don't use SidedWeaponReloadPointers( uint16_t* pnWeaponsLoaded, GlobalWeaponDefs** ppWeaponDefs, @@ -56,8 +63,7 @@ struct SidedWeaponReloadPointers m_fnReparseWeapon = fnReparseWeapon; m_fnReloadWeaponCallbacks = fnReloadWeaponCallbacks; } -}; - +} clientReloadPointers, serverReloadPointers; int WeaponIndexByName(const char* pWeaponName, const SidedWeaponReloadPointers* pReloadPointers) { @@ -81,6 +87,24 @@ void ModManager::DeferredReloadWeapons(const std::unordered_set<std::string> set } } +void ModManager::TryImmediateReloadWeapons(const std::unordered_set<std::string> setsWeapons) +{ + // try to reload all weapons on client and server, if we can't reload for any reason + // (either due to either side being inactive, or just failure to reload) + for (const std::string& sWeapon : setsWeapons) + { + if (!IsDedicatedServer()) + { + setsClientWeaponsToReload.insert(sWeapon); + // if this fails, the weapon will still be there for deferred reload + TryReloadWeapon(sWeapon.c_str(), &clientReloadPointers); + } + + setsServerWeaponsToReload.insert(sWeapon); + TryReloadWeapon(sWeapon.c_str(), &serverReloadPointers); + } +} + bool ModManager::TryReloadWeapon(const char* pWeaponName, const SidedWeaponReloadPointers* pReloadPointers) { if (!pReloadPointers->m_psetsWeaponsToReload->contains(pWeaponName)) @@ -108,9 +132,6 @@ AUTOHOOK(ClientPrecacheWeaponFromStringtable, client.dll + 0x195A60, bool, __fastcall, (void* a1, void* a2, void* a3, const char* pWeaponName)) // clang-format on { - static SidedWeaponReloadPointers clientReloadPointers( - g_pnClientWeaponsLoaded, g_ppClientWeaponDefs, &setsClientWeaponsToReload, ClientReparseWeapon, ClientReloadWeaponCallbacks); - if (g_pModManager->TryReloadWeapon(pWeaponName, &clientReloadPointers)) return true; @@ -120,5 +141,16 @@ bool, __fastcall, (void* a1, void* a2, void* a3, const char* pWeaponName)) ON_DLL_LOAD_CLIENT("client.dll", ModReloadWeaponsClient, (CModule module)) { + AUTOHOOK_DISPATCH_MODULE(client.dll) + + clientReloadPointers = SidedWeaponReloadPointers( + g_pnClientWeaponsLoaded, g_ppClientWeaponDefs, &setsClientWeaponsToReload, ClientReparseWeapon, ClientReloadWeaponCallbacks); +} + +ON_DLL_LOAD_CLIENT("server.dll", ModReloadWeaponsServer, (CModule module)) +{ AUTOHOOK_DISPATCH_MODULE(server.dll) + + serverReloadPointers = SidedWeaponReloadPointers( + g_pnServerWeaponsLoaded, g_ppServerWeaponDefs, &setsServerWeaponsToReload, ServerReparseWeapon, ServerReloadWeaponCallbacks); } diff --git a/NorthstarDLL/mods/reload/reloadmodweapons_misc.cpp b/NorthstarDLL/mods/reload/reloadmodweapons_misc.cpp index 5f43b11f..75503382 100644 --- a/NorthstarDLL/mods/reload/reloadmodweapons_misc.cpp +++ b/NorthstarDLL/mods/reload/reloadmodweapons_misc.cpp @@ -1,4 +1,6 @@ #include "mods/modmanager.h" +#include "dedicated/dedicated.h" +#include "engine/r2engine.h" AUTOHOOK_INIT() @@ -9,11 +11,21 @@ VAR_AT(client.dll + 0x23EF0C6, bool*, g_pbClientHasLoadedWeaponSprings); VAR_AT(client.dll + 0x23EF0C7, bool*, g_pbClientHasLoadedWeaponAmmoSuckBehaviours); VAR_AT(client.dll + 0x23EF0C4, bool*, g_pbClientHasLoadedWeaponADSPulls); +FUNCTION_AT(client.dll + 0x3CDDF0, void,, ClientReparseDamageFlags, ()); // requires g_pbClientHasLoadedDamageFlags to be false +FUNCTION_AT(client.dll + 0x3CE5B0, void,, ClientReparseWeaponSprings, ()); +FUNCTION_AT(client.dll + 0x3CE060, void,, ClientReparseWeaponAmmoSuckBehaviours, ()); +FUNCTION_AT(client.dll + 0x3CD700, void,, ClientReparseWeaponADSPulls, ()); + VAR_AT(server.dll + 0x160B474, bool*, g_pbServerHasLoadedDamageFlags); VAR_AT(server.dll + 0x160B475, bool*, g_pbServerHasLoadedWeaponSprings); VAR_AT(server.dll + 0x160B476, bool*, g_pbServerHasLoadedWeaponAmmoSuckBehaviours); VAR_AT(server.dll + 0x160B477, bool*, g_pbServerHasLoadedWeaponADSPulls); +FUNCTION_AT(client.dll + 0x6CC9F0, void,, ServerReparseDamageFlags, ()); // requires g_pbClientHasLoadedDamageFlags to be false +FUNCTION_AT(client.dll + 0x6CD1C0, void,, ServerReparseWeaponSprings, ()); +FUNCTION_AT(client.dll + 0x6CCC70, void,, ServerReparseWeaponAmmoSuckBehaviours, ()); +FUNCTION_AT(client.dll + 0x6CC300, void,, ServerReparseWeaponADSPulls, ()); + void ModManager::DeferredReloadDamageFlags() { *g_pbClientHasLoadedDamageFlags = false; @@ -38,8 +50,68 @@ void ModManager::DeferredReloadADSPulls() *g_pbServerHasLoadedWeaponADSPulls = false; } +void ModManager::TryImmediateReloadDamageFlags() +{ + if (!IsDedicatedServer()) + { + *g_pbClientHasLoadedDamageFlags = false; + if (g_pSquirrel<ScriptContext::CLIENT>->m_pSQVM) + ClientReparseDamageFlags(); + } + + *g_pbServerHasLoadedDamageFlags = false; + if (*R2::g_pServerState == R2::ss_active) + ServerReparseDamageFlags(); +} + +void ModManager::TryImmediateReloadWeaponSprings() +{ + if (!IsDedicatedServer()) + { + *g_pbClientHasLoadedWeaponSprings = false; + if (g_pSquirrel<ScriptContext::CLIENT>->m_pSQVM) + ClientReparseWeaponSprings(); + } + + *g_pbServerHasLoadedWeaponSprings = false; + if (*R2::g_pServerState == R2::ss_active) + ServerReparseWeaponSprings(); +} + +void ModManager::TryImmediateReloadAmmoSuckBehaviours() +{ + if (!IsDedicatedServer()) + { + *g_pbClientHasLoadedWeaponAmmoSuckBehaviours = false; + if (g_pSquirrel<ScriptContext::CLIENT>->m_pSQVM) + ClientReparseWeaponAmmoSuckBehaviours(); + } + + *g_pbServerHasLoadedWeaponAmmoSuckBehaviours = false; + if (*R2::g_pServerState == R2::ss_active) + ServerReparseWeaponAmmoSuckBehaviours(); +} + +void ModManager::TryImmediateReloadADSPulls() +{ + if (!IsDedicatedServer()) + { + *g_pbClientHasLoadedWeaponADSPulls = false; + if (g_pSquirrel<ScriptContext::CLIENT>->m_pSQVM) + ClientReparseWeaponADSPulls(); + } + + *g_pbServerHasLoadedWeaponADSPulls = false; + if (*R2::g_pServerState == R2::ss_active) + ServerReparseWeaponADSPulls(); +} ON_DLL_LOAD_CLIENT("client.dll", ClientModReloadWeaponsMisc, (CModule module)) { AUTOHOOK_DISPATCH_MODULE(client.dll) } + +ON_DLL_LOAD_CLIENT("server.dll", ServerModReloadWeaponsMisc, (CModule module)) +{ + AUTOHOOK_DISPATCH_MODULE(server.dll) +} diff --git a/NorthstarDLL/scripts/client/scriptmodmenu.cpp b/NorthstarDLL/scripts/client/scriptmodmenu.cpp index e16216fd..b969fca6 100644 --- a/NorthstarDLL/scripts/client/scriptmodmenu.cpp +++ b/NorthstarDLL/scripts/client/scriptmodmenu.cpp @@ -158,10 +158,11 @@ ADD_SQFUNC( return SQRESULT_NOTNULL; // return empty array } -ADD_SQFUNC("void", NSReloadMods, "bool deferredReload = false", "", ScriptContext::UI) +ADD_SQFUNC("void", NSReloadMods, "bool reloadAssets = true, bool deferredReload = false", "", ScriptContext::UI) { - const SQBool bDeferredReload = g_pSquirrel<context>->getbool(sqvm, 1); - g_pModManager->LoadMods(bDeferredReload); + const SQBool bReloadAssets = g_pSquirrel<context>->getbool(sqvm, 1); + const SQBool bDeferredReload = g_pSquirrel<context>->getbool(sqvm, 2); + g_pModManager->LoadMods(bReloadAssets, bDeferredReload); return SQRESULT_NULL; } |