diff --git a/src/client/component/fastfiles.cpp b/src/client/component/fastfiles.cpp index e7f41bd8..e0f5c10b 100644 --- a/src/client/component/fastfiles.cpp +++ b/src/client/component/fastfiles.cpp @@ -6,6 +6,7 @@ #include "fastfiles.hpp" #include "filesystem.hpp" #include "imagefiles.hpp" +#include "weapon.hpp" #include "game/dvars.hpp" @@ -27,10 +28,12 @@ namespace fastfiles game::dvar_t* g_dump_scripts; std::vector fastfile_handles; + bool is_mod_pre_gfx = false; void db_try_load_x_file_internal(const char* zone_name, const int flags) { console::info("Loading fastfile %s\n", zone_name); + is_mod_pre_gfx = zone_name == "mod_pre_gfx"s; current_fastfile.access([&](std::string& fastfile) { fastfile = zone_name; @@ -346,7 +349,9 @@ namespace fastfiles // code_pre_gfx - try_load_zone("h1_mod_code_pre_gfx", true); + weapon::clear_modifed_enums(); + try_load_zone("mod_pre_gfx", true); + try_load_zone("h1_mod_pre_gfx", true); game::DB_LoadXAssets(data.data(), static_cast(data.size()), syncMode); } @@ -960,6 +965,24 @@ namespace fastfiles mp::reallocate_asset_pools(); } } + + utils::hook::detour db_link_x_asset_entry_hook; + game::XAssetEntry* db_link_x_asset_entry_stub(game::XAssetType type, game::XAssetHeader* header) + { + if (!is_mod_pre_gfx) + { + return db_link_x_asset_entry_hook.invoke(type, header); + } + + static game::XAssetEntry entry{}; + + if (type != game::ASSET_TYPE_STRINGTABLE) + { + return &entry; + } + + return db_link_x_asset_entry_hook.invoke(type, header); + } } bool exists(const std::string& zone, bool ignore_usermap) @@ -1055,6 +1078,11 @@ namespace fastfiles db_unload_x_zones_hook.create(SELECT_VALUE(0x1F6040_b, 0x39B3C0_b), db_unload_x_zones_stub); + if (!game::environment::is_sp()) + { + db_link_x_asset_entry_hook.create(0x396E80_b, db_link_x_asset_entry_stub); + } + g_dump_scripts = dvars::register_bool("g_dumpScripts", false, game::DVAR_FLAG_NONE, "Dump GSC scripts"); reallocate_asset_pools(); diff --git a/src/client/component/mods.cpp b/src/client/component/mods.cpp index c48a16f1..a231f361 100644 --- a/src/client/component/mods.cpp +++ b/src/client/component/mods.cpp @@ -12,6 +12,7 @@ #include "materials.hpp" #include "mods.hpp" #include "scheduler.hpp" +#include "game/demonware/services.hpp" #include #include @@ -55,6 +56,11 @@ namespace mods if (game::environment::is_mp()) { command::execute("vid_restart"); + scheduler::once([] + { + demonware::set_storage_path(mod_path.value_or("")); + utils::hook::invoke(0x4E6B60_b, 0); // read stats + }, scheduler::main); return; } diff --git a/src/client/component/party.cpp b/src/client/component/party.cpp index 422674f5..02413bab 100644 --- a/src/client/component/party.cpp +++ b/src/client/component/party.cpp @@ -57,6 +57,7 @@ namespace party std::vector mod_files = { {".ff", "modHash", false}, + {"_pre_gfx.ff", "modpregfxhash", false}, {".pak", "modpakhash", true}, }; diff --git a/src/client/component/weapon.cpp b/src/client/component/weapon.cpp index cd7fbf2f..7e1b278d 100644 --- a/src/client/component/weapon.cpp +++ b/src/client/component/weapon.cpp @@ -138,6 +138,7 @@ namespace weapon } utils::memory::allocator ddl_allocator; + std::unordered_set modified_enums; std::vector get_stringtable_entries(const std::string& name) { @@ -194,8 +195,6 @@ namespace weapon void load_ddl_asset_stub(game::DDLRoot** asset) { - static std::unordered_set modified_enums; - const auto root = *asset; if (!root->ddlDef) { @@ -215,14 +214,14 @@ namespace weapon if ((enum_->name == "WeaponStats"s || enum_->name == "Weapon"s)) { - static const auto weapons = get_stringtable_entries("mp/customWeapons.csv"); + const auto weapons = get_stringtable_entries("mp/customweapons.csv"); add_entries_to_enum(enum_, weapons); modified_enums.insert(enum_); } if (enum_->name == "AttachmentBase"s) { - static const auto attachments = get_stringtable_entries("mp/customAttachments.csv"); + const auto attachments = get_stringtable_entries("mp/customattachments.csv"); add_entries_to_enum(enum_, attachments); modified_enums.insert(enum_); } @@ -235,6 +234,11 @@ namespace weapon } } + void clear_modifed_enums() + { + modified_enums.clear(); + } + class component final : public component_interface { public: diff --git a/src/client/component/weapon.hpp b/src/client/component/weapon.hpp new file mode 100644 index 00000000..f0033b2e --- /dev/null +++ b/src/client/component/weapon.hpp @@ -0,0 +1,6 @@ +#pragma once + +namespace weapon +{ + void clear_modifed_enums(); +} \ No newline at end of file diff --git a/src/client/game/demonware/services/bdStorage.cpp b/src/client/game/demonware/services/bdStorage.cpp index b5a80925..047f8a64 100644 --- a/src/client/game/demonware/services/bdStorage.cpp +++ b/src/client/game/demonware/services/bdStorage.cpp @@ -7,8 +7,16 @@ #include "game/game.hpp" +#include "../../../component/mods.hpp" + namespace demonware { + std::string storage_path; + void set_storage_path(const std::string& path) + { + storage_path = path; + } + bdStorage::bdStorage() : service(10, "bdStorage") { this->register_task(20, &bdStorage::list_publisher_files); @@ -162,7 +170,31 @@ namespace demonware std::string bdStorage::get_user_file_path(const std::string& name) { - return "players2/user/" + name; + const auto regular_path = "players2/user/"; + if (storage_path.empty()) + { + return regular_path + name; + } + + const auto custom_path = regular_path + storage_path + "/"; + if (!utils::io::directory_exists(custom_path)) + { + utils::io::create_directory(custom_path); + const auto copy_file = [&](const std::string& name) + { + const auto file_path = regular_path + name; + if (utils::io::file_exists(file_path)) + { + const auto data = utils::io::read_file(file_path); + utils::io::write_file(custom_path + name, data, false); + } + }; + + copy_file("commondata"); + copy_file("mpdata"); + } + + return custom_path + name; } void bdStorage::upload_and_validate_files(service_server* server, byte_buffer* buffer) const diff --git a/src/client/game/demonware/services/bdStorage.hpp b/src/client/game/demonware/services/bdStorage.hpp index e34036fb..58dcbd80 100644 --- a/src/client/game/demonware/services/bdStorage.hpp +++ b/src/client/game/demonware/services/bdStorage.hpp @@ -2,6 +2,8 @@ namespace demonware { + void set_storage_path(const std::string& path); + class bdStorage final : public service { public: