diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0428d594..840ec331 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,7 +27,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Check out files - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: submodules: true fetch-depth: 0 @@ -35,10 +35,9 @@ jobs: lfs: false - name: Add msbuild to PATH - uses: microsoft/setup-msbuild@v1.0.2 + uses: microsoft/setup-msbuild@v1.1.3 - name: Generate project files - #run: tools/premake5 vs2022 --ci-build run: tools/premake5 vs2022 - name: Set up problem matching @@ -48,7 +47,7 @@ jobs: run: msbuild /m /v:minimal /p:Configuration=${{matrix.configuration}} /p:Platform=x64 build/h2-mod.sln - name: Upload ${{matrix.configuration}} binaries - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3.1.0 with: name: ${{matrix.configuration}} binaries path: | @@ -56,7 +55,7 @@ jobs: build/bin/x64/${{matrix.configuration}}/h2-mod.pdb - name: Upload ${{matrix.configuration}} data artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3.1.0 with: name: ${{matrix.configuration}} data artifacts path: | @@ -76,12 +75,12 @@ jobs: run: echo "FED_MASTER_PATH=${{ secrets.FED_MASTER_SSH_PATH_DEV }}" >> $GITHUB_ENV - name: Download Release binaries - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: Release binaries - name: Download Release data artifacts - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 with: name: Release data artifacts path: data diff --git a/README.md b/README.md index 9a96b4e5..4c74257f 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ ![license](https://img.shields.io/github/license/fedddddd/h2-mod.svg) [![open bugs](https://img.shields.io/github/issues/fedddddd/h2-mod/bug?label=bugs)](https://github.com/fedddddd/h2-mod/issues?q=is%3Aissue+is%3Aopen+label%3Abug) [![Build](https://github.com/fedddddd/h2-mod/workflows/Build/badge.svg)](https://github.com/fedddddd/h2-mod/actions) -[![Build status](https://ci.appveyor.com/api/projects/status/0sh80kdnsvm53rno?svg=true)](https://ci.appveyor.com/project/fedddddd/h2-mod) [![Discord](https://img.shields.io/discord/955362057581129738?color=%237289DA&label=members&logo=discord&logoColor=%23FFFFFF)](https://discord.gg/dpnRn2tKT9) # H2: Mod @@ -15,7 +14,7 @@ **NOTE**: Cracked/Pirated versions of the game are **NOT** compatible with this mod, if you run such a version and have issues/crashes when running the client read **Step 2**. -1. Download the latest **[release](https://github.com/fedddddd/h2-mod/releases/latest/download/h2-mod.exe)** or **[develop](https://ci.appveyor.com/api/projects/fedddddd/h2-mod/artifacts/build%2Fbin%2Fx64%2FRelease%2Fh2-mod.exe?branch=develop&job=Environment%3A%20APPVEYOR_BUILD_WORKER_IMAGE%3DVisual%20Studio%202022%2C%20PREMAKE_ACTION%3Dvs2022%2C%20CI%3D1%3B%20Configuration%3A%20Release)** build +1. Download the latest **[release](https://github.com/fedddddd/h2-mod/releases/latest/download/h2-mod.exe)** or **[develop](https://master.fed0001.xyz/data-dev/h2-mod.exe)** build 2. Drop the file in your **Call of Duty: Modern Warfare 2 Campaign Remastered** installation folder. If you don't have the game installed (or own a cracked/pirated copy of it) you can download it for free from the official **Battle.Net** servers using [Battle.Net Installer](https://github.com/barncastle/Battle.Net-Installer) and executing this command: diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 400aa2b2..00000000 --- a/appveyor.yml +++ /dev/null @@ -1,41 +0,0 @@ -# AppVeyor CI configuration - -version: "#{build} ({branch})" - -environment: - matrix: - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022 - PREMAKE_ACTION: vs2022 - CI: 1 - -branches: - only: - - develop - - main - -skip_branch_with_pr: true - -configuration: - - Debug - - Release - -platform: x64 - -install: - - ps: | - Write-Host "Updating version information..." -ForegroundColor Cyan - Update-AppveyorBuild -Version $(& tools/premake5.exe version | select -Last 1) - - git submodule update --init --recursive - - ps: | - Write-Host "Generating project files with premake..." -ForegroundColor Cyan - & "./tools/premake5.exe" $env:PREMAKE_ACTION - Write-Host "Generated" -ForegroundColor Green - -build: - project: build/h2-mod.sln - parallel: true - verbosity: minimal - -artifacts: - - path: build/version.txt - - path: build/bin/**/h2-mod.exe \ No newline at end of file diff --git a/data/cdata/ui_scripts/patches/__init__.lua b/data/cdata/ui_scripts/patches/__init__.lua index e69de29b..da3e488b 100644 --- a/data/cdata/ui_scripts/patches/__init__.lua +++ b/data/cdata/ui_scripts/patches/__init__.lua @@ -0,0 +1 @@ +require("unlockall") diff --git a/data/cdata/ui_scripts/patches/unlockall.lua b/data/cdata/ui_scripts/patches/unlockall.lua new file mode 100644 index 00000000..fd33a69e --- /dev/null +++ b/data/cdata/ui_scripts/patches/unlockall.lua @@ -0,0 +1,33 @@ +if (Engine.InFrontend()) then + local levelselectmenu = LUI.sp_menus.LevelSelectMenu + levelselectmenu.DisplayUnlockAllFooterPrompt = function(f79_arg0, f79_arg1) + if Engine.GetDvarBool("profileMenuOption_hasUnlockedAll_SP") then + f79_arg0:AddHelp({ + name = "add_button_helper_text", + button_ref = "button_alt2", + helper_text = Engine.Localize("@LUA_MENU_CANCEL_UNLOCK_CAPS"), + side = "right", + clickable = true + }, levelselectmenu.SetUnlockAll) + else + f79_arg0:AddHelp({ + name = "add_button_helper_text", + button_ref = "button_alt2", + helper_text = Engine.Localize("@LUA_MENU_CAMPAIGN_UNLOCKED_ALL_TITLE"), + side = "right", + clickable = true + }, levelselectmenu.UnlockAllPopup) + end + end + + levelselectmenu.UnlockAllPopup = function(f70_arg0, f70_arg1) + LUI.FlowManager.RequestAddMenu(nil, "request_yesno_popup_generic", true, f70_arg1.controller, nil, { + popup_title = Engine.Localize("@LUA_MENU_CAMPAIGN_UNLOCKED_ALL_TITLE"), + yes_action = levelselectmenu.SetUnlockAll, + message_text = Engine.Localize("@MENU_COMPLETED_CHEAT") .. ". " .. + Engine.Localize("@LUA_MENU_CAMPAIGN_UNLOCKED_ALL_DESC") + }) + end +end + +CoD.AllowUnlockAllInShip = true diff --git a/data/zonetool/localizedstrings/arabic.json b/data/zonetool/localizedstrings/arabic.json index 63c934ff..bee5affd 100644 --- a/data/zonetool/localizedstrings/arabic.json +++ b/data/zonetool/localizedstrings/arabic.json @@ -16,5 +16,8 @@ "LOCALE_14": "الإسبانية (أمريكا اللاتينية)", "LOCALE_15": "الكورية", "LOCALE_16": "اللغة الإنجليزية (آمنة)", - "LOCALE_17": "(جزئي) الروسية" + "LOCALE_17": "(جزئي) الروسية", + + "LUA_MENU_CAMPAIGN_UNLOCKED_ALL_TITLE": ".ﻡﺎﻬﻤﻟﺍ ﻊﻴﻤﺟ ﺢﺘﻓ", + "LUA_MENU_CANCEL_UNLOCK_CAPS": "ﺢﺘﻔﻟﺍ ءﺎﻐﻟﺇ" } \ No newline at end of file diff --git a/data/zonetool/localizedstrings/english.json b/data/zonetool/localizedstrings/english.json index 5a3b8b81..c0d4592e 100644 --- a/data/zonetool/localizedstrings/english.json +++ b/data/zonetool/localizedstrings/english.json @@ -24,6 +24,9 @@ "UPDATER_POPUP_RESTART_POPUP_TEXT": "Update requires restart", "UPDATER_POPUP_CHECKING_FOR_UPDATES": "Checking for updates...", + "LUA_MENU_CAMPAIGN_UNLOCKED_ALL_TITLE": "Unlock All Missions and Intel", + "LUA_MENU_CANCEL_UNLOCK_CAPS": "Cancel Unlock All Missions", + "MENU_MODS_DESC": "Load installed mods.", "LUA_MENU_MOD_DESC_DEFAULT": "Load &&1.", "LUA_MENU_MOD_DESC": "&&1\nAuthor: &&2\nVersion: &&3", diff --git a/data/zonetool/localizedstrings/french.json b/data/zonetool/localizedstrings/french.json index a5e30500..36e937b0 100644 --- a/data/zonetool/localizedstrings/french.json +++ b/data/zonetool/localizedstrings/french.json @@ -17,13 +17,16 @@ "LOCALE_15": "Coréen", "LOCALE_16": "Anglais (sécuritaire)", "LOCALE_17": "Russe (partiel)", - + "UPDATER_POPUP_NO_UPDATES_AVAILABLE": "Aucune mise à jour disponible", "UPDATER_POPUP_AVAILABLE_UPDATE_TEXT": "Une mise à jour est disponible,\npoursuivre l'installation ?", "UPDATER_POPUP_SUCCESSFUL": "Mise à jour réussie", "UPDATER_POPUP_RESTART_POPUP_TEXT": "La mise à jour nécessite un redémarrage", "UPDATER_POPUP_CHECKING_FOR_UPDATES": "Vérification des mises à jour...", + "LUA_MENU_CAMPAIGN_UNLOCKED_ALL_TITLE": "Débloquer toutes les missions", + "LUA_MENU_CANCEL_UNLOCK_CAPS": "Annuler déblocage", + "MENU_MODS": "MODS", "MENU_MODS_DESC": "Charger les mods installés.", "LUA_MENU_MOD_DESC_DEFAULT": "Charger &&1.", diff --git a/data/zonetool/localizedstrings/german.json b/data/zonetool/localizedstrings/german.json index b1b858c2..c0235f4a 100644 --- a/data/zonetool/localizedstrings/german.json +++ b/data/zonetool/localizedstrings/german.json @@ -16,5 +16,8 @@ "LOCALE_14": "Spanisch (Lateinamerika)", "LOCALE_15": "Koreanisch", "LOCALE_16": "Englisch (Sicher)", - "LOCALE_17": "Russisch (Untertitelt)" + "LOCALE_17": "Russisch (Untertitelt)", + + "LUA_MENU_CAMPAIGN_UNLOCKED_ALL_TITLE": "Alle Missionen freischalten", + "LUA_MENU_CANCEL_UNLOCK_CAPS": "Freischalten abbrechen" } \ No newline at end of file diff --git a/data/zonetool/localizedstrings/italian.json b/data/zonetool/localizedstrings/italian.json index 5fbb5f09..13524d5f 100644 --- a/data/zonetool/localizedstrings/italian.json +++ b/data/zonetool/localizedstrings/italian.json @@ -18,6 +18,9 @@ "LOCALE_16": "Inglese (sicuro)", "LOCALE_17": "Russo (parziale)", + "LUA_MENU_CAMPAIGN_UNLOCKED_ALL_TITLE": "Sblocca tutte le missioni", + "LUA_MENU_CANCEL_UNLOCK_CAPS": "Annulla sblocco", + "MENU_MODS_DESC": "Abilita mod installate.", "LUA_MENU_MOD_DESC_DEFAULT": "Abilita &&1.", "LUA_MENU_MOD_DESC": "&&1\nAutore: &&2\nVersione: &&3", diff --git a/data/zonetool/localizedstrings/japanese_full.json b/data/zonetool/localizedstrings/japanese_full.json index dd16e435..6ffa51e4 100644 --- a/data/zonetool/localizedstrings/japanese_full.json +++ b/data/zonetool/localizedstrings/japanese_full.json @@ -16,5 +16,8 @@ "LOCALE_14": "スペイン語(南米)", "LOCALE_15": "韓国語", "LOCALE_16": "英語(検閲)", - "LOCALE_17": "ロシア語(一部)" + "LOCALE_17": "ロシア語(一部)", + + "LUA_MENU_CAMPAIGN_UNLOCKED_ALL_TITLE": "全ミッションをアンロック", + "LUA_MENU_CANCEL_UNLOCK_CAPS": "アンロックをキャンセル" } \ No newline at end of file diff --git a/data/zonetool/localizedstrings/japenese_partial.json b/data/zonetool/localizedstrings/japenese_partial.json index dd16e435..6ffa51e4 100644 --- a/data/zonetool/localizedstrings/japenese_partial.json +++ b/data/zonetool/localizedstrings/japenese_partial.json @@ -16,5 +16,8 @@ "LOCALE_14": "スペイン語(南米)", "LOCALE_15": "韓国語", "LOCALE_16": "英語(検閲)", - "LOCALE_17": "ロシア語(一部)" + "LOCALE_17": "ロシア語(一部)", + + "LUA_MENU_CAMPAIGN_UNLOCKED_ALL_TITLE": "全ミッションをアンロック", + "LUA_MENU_CANCEL_UNLOCK_CAPS": "アンロックをキャンセル" } \ No newline at end of file diff --git a/data/zonetool/localizedstrings/korean.json b/data/zonetool/localizedstrings/korean.json index f8bd4a27..9b7fd9d2 100644 --- a/data/zonetool/localizedstrings/korean.json +++ b/data/zonetool/localizedstrings/korean.json @@ -16,5 +16,8 @@ "LOCALE_14": "스페인어(라틴아메리카)", "LOCALE_15": "한국어", "LOCALE_16": "영어(검열)", - "LOCALE_17": "러시아어(일부)" + "LOCALE_17": "러시아어(일부)", + + "LUA_MENU_CAMPAIGN_UNLOCKED_ALL_TITLE": "모든 임무 잠금 해제", + "LUA_MENU_CANCEL_UNLOCK_CAPS": "잠금 해제 취소" } \ No newline at end of file diff --git a/data/zonetool/localizedstrings/polish.json b/data/zonetool/localizedstrings/polish.json index 2d91cbda..abf226f7 100644 --- a/data/zonetool/localizedstrings/polish.json +++ b/data/zonetool/localizedstrings/polish.json @@ -16,5 +16,8 @@ "LOCALE_14": "Hiszpański (Iberoameryka)", "LOCALE_15": "Koreański", "LOCALE_16": "Angielski (cenzuralny)", - "LOCALE_17": "Rosyjski (częściowy)" + "LOCALE_17": "Rosyjski (częściowy)", + + "LUA_MENU_CAMPAIGN_UNLOCKED_ALL_TITLE": "Odblokuj wszystkie misje", + "LUA_MENU_CANCEL_UNLOCK_CAPS": "Anuluj odblokowanie" } \ No newline at end of file diff --git a/data/zonetool/localizedstrings/portuguese.json b/data/zonetool/localizedstrings/portuguese.json index d4c0c9ef..408bd359 100644 --- a/data/zonetool/localizedstrings/portuguese.json +++ b/data/zonetool/localizedstrings/portuguese.json @@ -16,5 +16,8 @@ "LOCALE_14": "Español (América Latina)", "LOCALE_15": "Coreano", "LOCALE_16": "Inglês (Censurado)", - "LOCALE_17": "Russo (Parcial)" + "LOCALE_17": "Russo (Parcial)", + + "LUA_MENU_CAMPAIGN_UNLOCKED_ALL_TITLE": "Desbloquear todas as missões", + "LUA_MENU_CANCEL_UNLOCK_CAPS": "Cancelar desbloqueio" } \ No newline at end of file diff --git a/data/zonetool/localizedstrings/russian.json b/data/zonetool/localizedstrings/russian.json index caa3197e..05466a68 100644 --- a/data/zonetool/localizedstrings/russian.json +++ b/data/zonetool/localizedstrings/russian.json @@ -24,6 +24,9 @@ "UPDATER_POPUP_RESTART_POPUP_TEXT": "Для применения изменений необходим перезапуск игры", "UPDATER_POPUP_CHECKING_FOR_UPDATES": "Проверка наличия обновлений...", + "LUA_MENU_CAMPAIGN_UNLOCKED_ALL_TITLE": "Открыть все задания и чит-коды", + "LUA_MENU_CANCEL_UNLOCK_CAPS": "Вернуться к своему прогрессу прохождения", + "MENU_MODS": "Моды", "MENU_MODS_DESC": "Запуск установленных модов.", "LUA_MENU_MOD_DESC_DEFAULT": "Запустить &&1.", diff --git a/data/zonetool/localizedstrings/russian_partial.json b/data/zonetool/localizedstrings/russian_partial.json index 02e9ac9b..d4d05f10 100644 --- a/data/zonetool/localizedstrings/russian_partial.json +++ b/data/zonetool/localizedstrings/russian_partial.json @@ -24,6 +24,9 @@ "UPDATER_POPUP_RESTART_POPUP_TEXT": "Для применения изменений необходим перезапуск игры", "UPDATER_POPUP_CHECKING_FOR_UPDATES": "Проверка наличия обновлений...", + "LUA_MENU_CAMPAIGN_UNLOCKED_ALL_TITLE": "Открыть все задания и чит-коды", + "LUA_MENU_CANCEL_UNLOCK_CAPS": "Вернуться к своему прогрессу прохождения", + "MENU_MODS": "Моды", "MENU_MODS_DESC": "Запуск установленных модов.", "LUA_MENU_MOD_DESC_DEFAULT": "Запустить &&1.", diff --git a/data/zonetool/localizedstrings/simplified_chinese.json b/data/zonetool/localizedstrings/simplified_chinese.json index b45621ca..be1c7430 100644 --- a/data/zonetool/localizedstrings/simplified_chinese.json +++ b/data/zonetool/localizedstrings/simplified_chinese.json @@ -16,5 +16,8 @@ "LOCALE_14": "西班牙语(拉丁美洲)", "LOCALE_15": "韩语", "LOCALE_16": "英语 (审查制度)", - "LOCALE_17": "俄语(拉丁美洲)" + "LOCALE_17": "俄语(拉丁美洲)", + + "LUA_MENU_CAMPAIGN_UNLOCKED_ALL_TITLE": "解锁全部任务", + "LUA_MENU_CANCEL_UNLOCK_CAPS": "取消解锁" } \ No newline at end of file diff --git a/data/zonetool/localizedstrings/spanish.json b/data/zonetool/localizedstrings/spanish.json index 790c2774..033d1070 100644 --- a/data/zonetool/localizedstrings/spanish.json +++ b/data/zonetool/localizedstrings/spanish.json @@ -16,5 +16,8 @@ "LOCALE_14": "Español (América Latina)", "LOCALE_15": "Coreano", "LOCALE_16": "Inglés (censura)", - "LOCALE_17": "Ruso (parcial)" + "LOCALE_17": "Ruso (parcial)", + + "LUA_MENU_CAMPAIGN_UNLOCKED_ALL_TITLE": "Desbloquear todas las misiones", + "LUA_MENU_CANCEL_UNLOCK_CAPS": "Cancelar desbloqueo" } \ No newline at end of file diff --git a/data/zonetool/localizedstrings/spanishna.json b/data/zonetool/localizedstrings/spanishna.json index 790c2774..033d1070 100644 --- a/data/zonetool/localizedstrings/spanishna.json +++ b/data/zonetool/localizedstrings/spanishna.json @@ -16,5 +16,8 @@ "LOCALE_14": "Español (América Latina)", "LOCALE_15": "Coreano", "LOCALE_16": "Inglés (censura)", - "LOCALE_17": "Ruso (parcial)" + "LOCALE_17": "Ruso (parcial)", + + "LUA_MENU_CAMPAIGN_UNLOCKED_ALL_TITLE": "Desbloquear todas las misiones", + "LUA_MENU_CANCEL_UNLOCK_CAPS": "Cancelar desbloqueo" } \ No newline at end of file diff --git a/data/zonetool/localizedstrings/traditional_chinese.json b/data/zonetool/localizedstrings/traditional_chinese.json index 9b31e4bc..b6406dd5 100644 --- a/data/zonetool/localizedstrings/traditional_chinese.json +++ b/data/zonetool/localizedstrings/traditional_chinese.json @@ -16,5 +16,8 @@ "LOCALE_14": "西班牙文(洛杉磯)", "LOCALE_15": "韓文", "LOCALE_16": "英文 (審查制度)", - "LOCALE_17": "俄文(部份)" + "LOCALE_17": "俄文(部份)", + + "LUA_MENU_CAMPAIGN_UNLOCKED_ALL_TITLE": "解鎖所有任務", + "LUA_MENU_CANCEL_UNLOCK_CAPS": "取消解鎖" } \ No newline at end of file diff --git a/deps/GSL b/deps/GSL index c52bad36..d69e5785 160000 --- a/deps/GSL +++ b/deps/GSL @@ -1 +1 @@ -Subproject commit c52bad36aa9d5ececcdf6be2d5cd2dce9daa4194 +Subproject commit d69e578519840b9b74eff26ac01465ac07698063 diff --git a/deps/libtommath b/deps/libtommath index 96f9edf9..03de03de 160000 --- a/deps/libtommath +++ b/deps/libtommath @@ -1 +1 @@ -Subproject commit 96f9edf9aaf145c6ecf5225eea3f5e86a0f26935 +Subproject commit 03de03dee753442d4b23166982514639c4ccbc39 diff --git a/deps/lua b/deps/lua index 26be2745..c954db39 160000 --- a/deps/lua +++ b/deps/lua @@ -1 +1 @@ -Subproject commit 26be27459b11feabed52cf40aaa76f86c7edc977 +Subproject commit c954db39241a8b21d7b32b42b87a066b4708f969 diff --git a/premake5.lua b/premake5.lua index 1818c93c..3b69b2c5 100644 --- a/premake5.lua +++ b/premake5.lua @@ -227,10 +227,12 @@ targetdir "%{wks.location}/bin/%{cfg.platform}/%{cfg.buildcfg}" configurations {"Debug", "Release"} -architecture "x64" +language "C++" +cppdialect "C++20" + +architecture "x86_64" platforms "x64" -buildoptions "/std:c++latest" systemversion "latest" symbols "On" staticruntime "On" @@ -255,7 +257,7 @@ filter {} filter "configurations:Release" optimize "Size" buildoptions {"/GL"} - linkoptions { "/IGNORE:4702", "/LTCG" } + linkoptions {"/IGNORE:4702", "/LTCG"} defines {"NDEBUG"} flags {"FatalCompileWarnings"} filter {} @@ -321,13 +323,3 @@ resincludedirs {"$(ProjectDir)src"} group "Dependencies" dependencies.projects() - -rule "ProtobufCompiler" -display "Protobuf compiler" -location "./build" -fileExtension ".proto" -buildmessage "Compiling %(Identity) with protoc..." -buildcommands {'@echo off', 'path "$(SolutionDir)\\..\\tools"', - 'if not exist "$(ProjectDir)\\src\\proto" mkdir "$(ProjectDir)\\src\\proto"', - 'protoc --error_format=msvs -I=%(RelativeDir) --cpp_out=src\\proto %(Identity)'} -buildoutputs {'$(ProjectDir)\\src\\proto\\%(Filename).pb.cc', '$(ProjectDir)\\src\\proto\\%(Filename).pb.h'} diff --git a/src/client/component/fastfiles.cpp b/src/client/component/fastfiles.cpp index e2db9a4c..9079d33e 100644 --- a/src/client/component/fastfiles.cpp +++ b/src/client/component/fastfiles.cpp @@ -1,5 +1,6 @@ #include #include "loader/component_loader.hpp" +#include "game/dvars.hpp" #include "fastfiles.hpp" #include "command.hpp" @@ -16,6 +17,8 @@ namespace fastfiles namespace { + game::dvar_t* db_print_default_assets = nullptr; + template struct bit_array { @@ -41,18 +44,25 @@ namespace fastfiles const auto result = db_find_xasset_header.invoke(type, name, allow_create_default); const auto diff = game::Sys_Milliseconds() - start; + if (db_print_default_assets->current.enabled && game::DB_IsXAssetDefault(type, name)) + { + console::warn("Waited %i msec for default asset \"%s\" of type \"%s\"\n", + diff, name, game::g_assetNames[type]); + } + if (diff > 100) { + const auto missing = result.data == nullptr; console::print( - result.data == nullptr + missing ? console::con_type_error : console::con_type_warning, - "Waited %i msec for %sasset \"%s\", of type \"%s\"\n", - diff, - result.data == nullptr - ? "missing " - : "", - name, + "Waited %i msec for %sasset \"%s\" of type \"%s\"\n", + diff, + missing + ? "missing " + : "", + name, game::g_assetNames[type] ); } @@ -143,7 +153,7 @@ namespace fastfiles { 96, 88, 128, 56, 40, 216, 56, 696, 624, 32, 32, 32, 32, 32, 2112, 2032, - 104, 32, 24, 1520, 152, 152, 16, 64, + 104, 32, 24, 152, 152, 152, 16, 64, 640, 40, 16, 136, 24, 296, 176, 2896, 48, 0, 24, 200, 88, 16, 144, 3848, 56, 72, 16, 16, 0, 0, 0, 0, 24, @@ -420,6 +430,12 @@ namespace fastfiles } } + const std::string mapname = name; + if (mapname.starts_with("mp_")) + { + add_custom_level_load_zone(load, "common_mp", 0x40000); + } + if (is_builtin_map) { const auto name_ = "h2_mod_patch_"s + name; @@ -440,6 +456,18 @@ namespace fastfiles { game::DB_LoadXAssets(info, zone_count, game::DB_LOAD_ASYNC); } + + void db_find_aipaths_stub(game::XAssetType type, const char* name, int allow_create_default) + { + if (game::DB_XAssetExists(type, name)) + { + game::DB_FindXAssetHeader(type, name, allow_create_default); + } + else + { + console::warn("No aipaths found for this map\n"); + } + } } bool exists(const std::string& zone) @@ -484,6 +512,9 @@ namespace fastfiles public: void post_unpack() override { + db_print_default_assets = dvars::register_bool("db_printDefaultAssets", + false, game::DVAR_FLAG_SAVED, "Print default asset usage"); + db_try_load_x_file_internal_hook.create(0x1404173B0, db_try_load_x_file_internal); db_find_xasset_header.create(game::DB_FindXAssetHeader, db_find_xasset_header_stub); @@ -504,7 +535,7 @@ namespace fastfiles reallocate_asset_pools(); - // only load extra zones with addon maps & common_specialops & common_survival & custom maps if the exist + // only load extra zones with addon maps & common_specialops & common_survival & custom maps if they exist utils::hook::call(0x1404128B0, db_load_level_add_map_zone_stub); utils::hook::call(0x140412854, db_load_level_add_custom_zone_stub); utils::hook::call(0x14041282D, db_load_level_add_custom_zone_stub); @@ -513,6 +544,11 @@ namespace fastfiles // Load assets from 2nd phase (common_specialops, addon map) with DB_LOAD_SYNC utils::hook::call(0x140414EA1, db_load_xassets_stub); + // Allow loading mp maps + utils::hook::set(0x140609630, 0xC300B0); + // Don't sys_error if aipaths are missing + utils::hook::call(0x140522299, db_find_aipaths_stub); + command::add("loadzone", [](const command::params& params) { if (params.size() < 2) diff --git a/src/client/component/filesystem.cpp b/src/client/component/filesystem.cpp index 1c5d8f00..46dcea4b 100644 --- a/src/client/component/filesystem.cpp +++ b/src/client/component/filesystem.cpp @@ -86,15 +86,11 @@ namespace filesystem bool can_insert_path(const std::filesystem::path& path) { - for (const auto& path_ : get_search_paths_internal()) + const auto& paths = get_search_paths_internal(); + return std::ranges::none_of(paths.cbegin(), paths.cend(), [path](const auto& elem) { - if (path_ == path) - { - return false; - } - } - - return true; + return elem == path; + }); } const char* sys_default_install_path_stub() diff --git a/src/client/component/gameplay.cpp b/src/client/component/gameplay.cpp index f1926661..18728c4f 100644 --- a/src/client/component/gameplay.cpp +++ b/src/client/component/gameplay.cpp @@ -87,6 +87,30 @@ namespace gameplay a.jmp(0x14067AE1A); } + + void pm_bouncing_stub_mp(utils::hook::assembler& a) + { + const auto no_bounce = a.newLabel(); + const auto loc_140691518 = a.newLabel(); + + a.push(rax); + + a.mov(rax, qword_ptr(reinterpret_cast(&dvars::pm_bouncing))); + a.mov(al, byte_ptr(rax, 0x10)); + a.cmp(byte_ptr(rbp, -0x5D), al); + + a.pop(rax); + a.jz(no_bounce); + a.jmp(0x140691481); + + a.bind(no_bounce); + a.cmp(dword_ptr(rsp, 0x44), 0); + a.jnz(loc_140691518); + a.jmp(0x14069146F); + + a.bind(loc_140691518); + a.jmp(0x140691518); + } } class component final : public component_interface @@ -103,6 +127,10 @@ namespace gameplay dvars::jump_spreadAdd = dvars::register_float("jump_spreadAdd", 64.0f, 0.0f, 512.0f, game::DVAR_FLAG_REPLICATED, "The amount of spread scale to add as a side effect of jumping"); + dvars::pm_bouncing = dvars::register_bool("pm_bouncing", false, + game::DVAR_FLAG_REPLICATED, "Enable bouncing"); + utils::hook::jump(0x14069145E, utils::hook::assemble(pm_bouncing_stub_mp), true); + // Influence PM_JitterPoint code flow so the trace->startsolid checks are 'ignored' pm_player_trace_hook.create(0x14068F0A0, &pm_player_trace_stub); diff --git a/src/client/component/gsc.cpp b/src/client/component/gsc.cpp index cc207a3c..435314e7 100644 --- a/src/client/component/gsc.cpp +++ b/src/client/component/gsc.cpp @@ -10,6 +10,7 @@ #include "gsc.hpp" #include "scheduler.hpp" #include "fastfiles.hpp" +#include "command.hpp" #include "game/scripting/execution.hpp" #include "game/scripting/functions.hpp" @@ -49,9 +50,9 @@ namespace gsc std::unordered_map functions; std::optional gsc_error; - char* allocate_buffer(size_t size) + char* allocate_buffer(std::uint32_t size) { - return utils::hook::invoke(0x14061E680, size, 4, 1, 5); + return static_cast(game::PMem_AllocFromSource_NoDebug(size, 4, 1, 5)); } bool read_scriptfile(const std::string& name, std::string* data) @@ -109,7 +110,18 @@ namespace gsc } auto assembly = compiler->output(); - assembler->assemble(real_name, assembly); + + try + { + assembler->assemble(real_name, assembly); + } + catch (const std::exception& e) + { + console::error("*********** script compile error *************\n"); + console::error("failed to assemble '%s':\n%s", real_name.data(), e.what()); + console::error("**********************************************\n"); + return nullptr; + } const auto script_file_ptr = reinterpret_cast(allocate_buffer(sizeof(game::ScriptFile))); script_file_ptr->name = file_name; @@ -123,7 +135,7 @@ namespace gsc const auto script_size = script.size(); const auto buffer_size = script_size + stack.size() + 2; - const auto buffer = allocate_buffer(buffer_size); + const auto buffer = allocate_buffer(static_cast(buffer_size)); std::memcpy(buffer, script.data(), script_size); std::memcpy(&buffer[script_size], stack.data(), stack.size()); @@ -703,6 +715,12 @@ namespace gsc return game::Scr_AddInt(sound->head->soundFile->u.streamSnd.totalMsec); }); + add_function("executecommand", [](const game::scr_entref_t ref) + { + const auto cmd = get_argument(0).as(); + command::execute(cmd); + }); + scripting::on_shutdown([](int free_scripts) { if (free_scripts) diff --git a/src/client/component/mapents.cpp b/src/client/component/mapents.cpp index b0fbf48c..bf9988ef 100644 --- a/src/client/component/mapents.cpp +++ b/src/client/component/mapents.cpp @@ -44,6 +44,12 @@ namespace mapents } const auto id = static_cast(std::atoi(line.substr(0, first_space).data())); + if (id == 0) // 0 "key" "value" + { + buffer.append(line); + continue; + } + const auto token = xsk::gsc::h2::resolver::token_name(static_cast(id)); const auto key = "\"" + token + "\""; diff --git a/src/client/component/patches.cpp b/src/client/component/patches.cpp index 510d5710..4c474511 100644 --- a/src/client/component/patches.cpp +++ b/src/client/component/patches.cpp @@ -89,9 +89,9 @@ namespace patches // Fix startup crashes utils::hook::set(0x140633080, 0xC301B0); utils::hook::set(0x140272F70, 0xC301B0); - utils::hook::jump(0x140046148, sub_46148, true); + utils::hook::jump(0x140046148, sub_46148); - utils::hook::jump(0x14064EF10, quit_stub, true); + utils::hook::jump(0x1408B1CD0, quit_stub); // Unlock fps in main menu utils::hook::set(0x1403D8E1B, 0xEB); diff --git a/src/client/component/scripting.cpp b/src/client/component/scripting.cpp index 9177f60a..e47cfb37 100644 --- a/src/client/component/scripting.cpp +++ b/src/client/component/scripting.cpp @@ -7,6 +7,7 @@ #include "scheduler.hpp" #include "scripting.hpp" #include "gsc.hpp" +#include "console.hpp" #include "game/scripting/event.hpp" #include "game/scripting/functions.hpp" @@ -274,6 +275,17 @@ namespace scripting scr_get_dvar_int_hook.invoke(); } + + void* get_spawn_point_stub() + { + const auto spawn_point = utils::hook::invoke(0x1404B1670); + if (spawn_point == nullptr) + { + console::warn("No spawnpoint found for this map, using (0, 0, 0)\n"); + return &game::g_entities[0]; + } + return spawn_point; + } } std::string get_token_single(unsigned int id) @@ -324,6 +336,8 @@ namespace scripting scr_get_dvar_int_hook.create(0x1404F0730, scr_get_dvar_int_stub); + utils::hook::call(0x1404B07D2, get_spawn_point_stub); + scheduler::loop([]() { lua::engine::run_frame(); diff --git a/src/client/game/dvars.cpp b/src/client/game/dvars.cpp index 5fc1e56b..17fe26f2 100644 --- a/src/client/game/dvars.cpp +++ b/src/client/game/dvars.cpp @@ -20,6 +20,8 @@ namespace dvars game::dvar_t* jump_ladderPushVel = nullptr; game::dvar_t* jump_spreadAdd = nullptr; + game::dvar_t* pm_bouncing = nullptr; + game::dvar_t* r_fullbright = nullptr; game::dvar_t* cg_legacyCrashHandling = nullptr; diff --git a/src/client/game/dvars.hpp b/src/client/game/dvars.hpp index ae7ceb08..82822fc6 100644 --- a/src/client/game/dvars.hpp +++ b/src/client/game/dvars.hpp @@ -28,6 +28,8 @@ namespace dvars extern game::dvar_t* jump_ladderPushVel; extern game::dvar_t* jump_spreadAdd; + extern game::dvar_t* pm_bouncing; + extern game::dvar_t* r_fullbright; extern game::dvar_t* cg_legacyCrashHandling; diff --git a/src/client/game/scripting/lua/context.cpp b/src/client/game/scripting/lua/context.cpp index c2a5619d..016eaf0c 100644 --- a/src/client/game/scripting/lua/context.cpp +++ b/src/client/game/scripting/lua/context.cpp @@ -428,14 +428,12 @@ namespace scripting::lua entity_type["struct"] = sol::property([](const entity& entity, const sol::this_state s) { - const auto id = entity.get_entity_id(); - return scripting::lua::entity_to_struct(s, id); + return entity; }); entity_type["getstruct"] = [](const entity& entity, const sol::this_state s) { - const auto id = entity.get_entity_id(); - return scripting::lua::entity_to_struct(s, id); + return entity; }; entity_type["scriptcall"] = [](const entity& entity, const sol::this_state s, const std::string& filename, diff --git a/src/client/game/scripting/lua/value_conversion.cpp b/src/client/game/scripting/lua/value_conversion.cpp index d9980827..d0cd2312 100644 --- a/src/client/game/scripting/lua/value_conversion.cpp +++ b/src/client/game/scripting/lua/value_conversion.cpp @@ -8,110 +8,6 @@ namespace scripting::lua { namespace { - struct array_value - { - int index; - script_value value; - }; - - sol::lua_value entity_to_array(lua_State* state, unsigned int id) - { - auto table = sol::table::create(state); - auto metatable = sol::table::create(state); - - std::unordered_map values; - - const auto offset = 0xA000 * (id & 3); - - auto current = game::scr_VarGlob->objectVariableChildren[id].firstChild; - auto idx = 1; - - for (auto i = offset + current; current; i = offset + current) - { - const auto var = game::scr_VarGlob->childVariableValue[i]; - - if (var.type == game::SCRIPT_NONE) - { - current = var.nextSibling; - continue; - } - - const auto string_value = (game::scr_string_t)((unsigned __int8)var.name_lo + (var.k.keys.name_hi << 8)); - const auto* str = game::SL_ConvertToString(string_value); - - std::string key = string_value < 0x40000 && str - ? str - : std::to_string(idx++); - - game::VariableValue variable{}; - variable.type = var.type; - variable.u = var.u.u; - - array_value value; - value.index = i; - value.value = variable; - - values[key] = value; - - current = var.nextSibling; - } - - table["getkeys"] = [values]() - { - std::vector _keys; - - for (const auto& entry : values) - { - _keys.push_back(entry.first); - } - - return _keys; - }; - - metatable[sol::meta_function::new_index] = [values](const sol::table t, const sol::this_state s, - const sol::lua_value& key_value, const sol::lua_value& value) - { - const auto key = key_value.is() - ? std::to_string(key_value.as()) - : key_value.as(); - - if (values.find(key) == values.end()) - { - return; - } - - const auto variable = convert({s, value}).get_raw(); - const auto i = values.at(key).index; - - game::scr_VarGlob->childVariableValue[i].type = (char)variable.type; - game::scr_VarGlob->childVariableValue[i].u.u = variable.u; - }; - - metatable[sol::meta_function::index] = [values](const sol::table t, const sol::this_state s, - const sol::lua_value& key_value) - { - const auto key = key_value.is() - ? std::to_string(key_value.as()) - : key_value.as(); - - if (values.find(key) == values.end()) - { - return sol::lua_value{s, sol::lua_nil}; - } - - return convert(s, values.at(key).value); - }; - - metatable[sol::meta_function::length] = [values]() - { - return values.size(); - }; - - table[sol::metatable_key] = metatable; - - return {state, table}; - } - bool is_istring(const sol::lua_value& value) { if (!value.is()) @@ -170,50 +66,6 @@ namespace scripting::lua } } - sol::lua_value entity_to_struct(lua_State* state, unsigned int parent_id) - { - auto table = sol::table::create(state); - auto metatable = sol::table::create(state); - - table["getentity"] = [parent_id]() - { - return entity(parent_id); - }; - - metatable[sol::meta_function::new_index] = [parent_id](const sol::table t, const sol::this_state s, - const sol::lua_value& field, const sol::lua_value& value) - { - const auto new_variable = convert({s, value}); - if (field.is()) - { - scripting::set_object_variable(parent_id, field.as(), new_variable); - } - else if (field.is()) - { - scripting::set_object_variable(parent_id, field.as(), new_variable); - } - }; - - metatable[sol::meta_function::index] = [parent_id](const sol::table t, const sol::this_state s, - const sol::lua_value& field) - { - if (field.is()) - { - return convert(s, scripting::get_object_variable(parent_id, field.as())); - } - else if (field.is()) - { - return convert(s, scripting::get_object_variable(parent_id, field.as())); - } - - return sol::lua_value{s, sol::lua_nil}; - }; - - table[sol::metatable_key] = metatable; - - return {state, table}; - } - script_value convert(const sol::lua_value& value) { if (value.is()) diff --git a/src/client/game/scripting/lua/value_conversion.hpp b/src/client/game/scripting/lua/value_conversion.hpp index 93256f80..27acaad3 100644 --- a/src/client/game/scripting/lua/value_conversion.hpp +++ b/src/client/game/scripting/lua/value_conversion.hpp @@ -4,8 +4,6 @@ namespace scripting::lua { - sol::lua_value entity_to_struct(lua_State* state, unsigned int parent_id); - script_value convert(const sol::lua_value& value); sol::lua_value convert(lua_State* state, const script_value& value); } diff --git a/src/client/game/symbols.hpp b/src/client/game/symbols.hpp index 84325c22..0a25474c 100644 --- a/src/client/game/symbols.hpp +++ b/src/client/game/symbols.hpp @@ -133,6 +133,8 @@ namespace game WEAK symbol Scr_ExecThread{0x1405C6F40}; WEAK symbol Scr_RegisterFunction{0x1405BC7B0}; + WEAK symbol PMem_AllocFromSource_NoDebug{0x14061E680}; + WEAK symbol VM_Execute{0x1405C8DB0}; WEAK symbol