diff --git a/src/client/component/script.cpp b/src/client/component/script.cpp index 4a9e3eb6..6cc659db 100644 --- a/src/client/component/script.cpp +++ b/src/client/component/script.cpp @@ -12,6 +12,8 @@ namespace script { namespace { + constexpr size_t GSC_MAGIC = 0x1C000A0D43534780; + utils::hook::detour db_findxassetheader_hook; utils::hook::detour gscr_get_bgb_remaining_hook; @@ -23,11 +25,6 @@ namespace script return (itr == loaded_scripts.end()) ? nullptr : itr->second; } - void print_loading_script(const std::string& name) - { - printf("Loading GSC script '%s'\n", name.data()); - } - void load_script(std::string& name, const std::string& data) { auto& allocator = *utils::memory::get_allocator(); @@ -49,11 +46,14 @@ namespace script } auto* rawfile = allocator.allocate(); - rawfile->name = name.c_str(); + rawfile->name = name.data(); rawfile->buffer = file_string; rawfile->len = static_cast(data.length()); loaded_scripts[name] = rawfile; + + const auto base_name = name.substr(0, name.size() - 4); // .gsc suffix will be readded by Scr_LoadScript + game::Scr_LoadScript(game::SCRIPTINSTANCE_SERVER, base_name.data()); } void load_scripts_folder(const std::string& script_dir) @@ -64,15 +64,18 @@ namespace script } const auto scripts = utils::io::list_files(script_dir); - for (const auto& script : scripts) { std::string data; auto script_file = script.generic_string(); if (!std::filesystem::is_directory(script) && utils::io::read_file(script_file, &data)) { - print_loading_script(script_file); - load_script(script_file, data); + if (data.size() >= sizeof(GSC_MAGIC) && !std::memcmp(data.data(), &GSC_MAGIC, sizeof(GSC_MAGIC))) + { + auto base_name = script_file.substr(0, script_file.size() - 4); + printf("Loading GSC script '%s'\n", base_name.data()); + load_script(script_file, data); + } } else if (std::filesystem::is_directory(script)) { @@ -86,7 +89,8 @@ namespace script loaded_scripts = {}; const utils::nt::library host{}; load_scripts_folder((game::get_appdata_path() / "data/scripts").string()); - load_scripts_folder((host.get_folder() / "boiii/scripts").string()); + auto path = (host.get_folder() / "boiii/scripts").string(); + load_scripts_folder(path); } game::RawFile* db_findxassetheader_stub(const game::XAssetType type, const char* name, @@ -104,9 +108,10 @@ namespace script auto* script = get_loaded_script(name); if (script) { - // Copy over the checksum of the original script + /* + // TODO: don't check checksums for custom GSC, but only for stock scripts we override utils::hook::copy(const_cast(script->buffer + 0x8), asset_header->buffer + 0x8, 4); - + */ return script; } @@ -117,23 +122,30 @@ namespace script { game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, 255); } + + utils::hook::detour load_gametype_script_hook; + + void load_gametype_script_stub() + { + if (!game::Com_IsInGame() || game::Com_IsRunningUILevel()) + { + load_gametype_script_hook.invoke(); + return; + } + + load_gametype_script_hook.invoke(); + load_scripts(); + } } struct component final : generic_component { void post_unpack() override { - if (game::is_server()) - { - load_scripts(); - } - else - { - scheduler::once(load_scripts, scheduler::pipeline::renderer); - } - db_findxassetheader_hook.create(game::select(0x141420ED0, 0x1401D5FB0), db_findxassetheader_stub); gscr_get_bgb_remaining_hook.create(game::select(0x141A8CAB0, 0x1402D2310), gscr_get_bgb_remaining_stub); + + load_gametype_script_hook.create(0x141AAD850_g, load_gametype_script_stub); } }; }; diff --git a/src/client/game/structs.hpp b/src/client/game/structs.hpp index 883c243b..1c6a22e0 100644 --- a/src/client/game/structs.hpp +++ b/src/client/game/structs.hpp @@ -1814,7 +1814,9 @@ namespace game PlayerSoundsTable* playerSounds; PlayerFXTable* playerFX; SharedWeaponSounds* sharedWeaponSounds; + */ RawFile* rawfile; + /* StringTable* stringTable; StructuredTable* structuredTable; LeaderboardDef* leaderboardDef; diff --git a/src/client/game/symbols.hpp b/src/client/game/symbols.hpp index a0513a45..f78016bd 100644 --- a/src/client/game/symbols.hpp +++ b/src/client/game/symbols.hpp @@ -35,6 +35,7 @@ namespace game 0x1420F4E00, 0x1404FE5C0 }; WEAK symbol Com_IsRunningUILevel{0x142148350}; + WEAK symbol Com_IsInGame{0x1421482C0}; WEAK symbol Com_SwitchMode{ 0x14214A4D0 }; @@ -80,6 +81,9 @@ namespace game WEAK symbol StuckInClient{0x1415A8360, 0x14023BFE0}; + // GScr + WEAK symbol GScr_LoadGametypeScript{0x14092F680, 0x0}; + // Live WEAK symbol Live_GetConnectivityInformation{0x141E0C380}; @@ -175,6 +179,7 @@ namespace game 0x0, 0x1402F5FF0 }; WEAK symbol Scr_GetNumParam{0x0, 0x140171320}; + WEAK symbol Scr_LoadScript{0x1412C83F0}; WEAK symbol Cinematic_StartPlayback{0x1412BE3A0};