From 31fdbecd7d01e5418596b091fd4d9994679dd168 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Sep 2021 17:27:23 +0000 Subject: [PATCH 01/41] Bump deps/libtommath from `eda0bd6` to `8355b88` Bumps [deps/libtommath](https://github.com/libtom/libtommath) from `eda0bd6` to `8355b88`. - [Release notes](https://github.com/libtom/libtommath/releases) - [Commits](https://github.com/libtom/libtommath/compare/eda0bd6ae5705ab90b866dfb52c5f15c23687f81...8355b88db088e41d6f7e19a8d58d46c9ed0333d3) --- updated-dependencies: - dependency-name: deps/libtommath dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/libtommath | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/libtommath b/deps/libtommath index eda0bd6a..8355b88d 160000 --- a/deps/libtommath +++ b/deps/libtommath @@ -1 +1 @@ -Subproject commit eda0bd6ae5705ab90b866dfb52c5f15c23687f81 +Subproject commit 8355b88db088e41d6f7e19a8d58d46c9ed0333d3 From 737fab16421fb758ca6f651075257543af5dbbd9 Mon Sep 17 00:00:00 2001 From: Jan Date: Sat, 9 Oct 2021 01:57:52 +0200 Subject: [PATCH 02/41] Fix gamepad hold x to pickup only being applied to non dedi --- src/Components/Modules/Gamepad.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Components/Modules/Gamepad.cpp b/src/Components/Modules/Gamepad.cpp index 5ba7a66b..5068f5b6 100644 --- a/src/Components/Modules/Gamepad.cpp +++ b/src/Components/Modules/Gamepad.cpp @@ -1870,6 +1870,9 @@ namespace Components Utils::Hook(0x60B264, Com_WriteConfiguration_Modified_Stub, HOOK_JUMP).install()->quick(); Utils::Hook(0x60B223, Key_WriteBindings_Hk, HOOK_CALL).install()->quick(); + // Add hold time to gamepad usereload on hold prompts + Utils::Hook(0x5FE396, Player_UseEntity_Stub, HOOK_JUMP).install()->quick(); + CreateKeyNameMap(); Command::Add("bindaxis", Axis_Bind_f); @@ -1896,9 +1899,6 @@ namespace Components // Only return gamepad keys when gamepad enabled and only non gamepad keys when not Utils::Hook(0x5A7A23, Key_GetCommandAssignmentInternal_Hk, HOOK_CALL).install()->quick(); - // Add hold time to gamepad usereload on hold prompts - Utils::Hook(0x5FE396, Player_UseEntity_Stub, HOOK_JUMP).install()->quick(); - // Add gamepad inputs to remote control (eg predator) handling Utils::Hook(0x5A6D4E, CL_RemoteControlMove_Stub, HOOK_CALL).install()->quick(); From 4a40a89e70ee3125d3484876d0977f6a3e230657 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Sat, 16 Oct 2021 13:36:29 +0100 Subject: [PATCH 03/41] [Script] Add ufo and noclip function --- src/Components/Modules/Script.cpp | 22 ++++++++++++++++++++++ src/Game/Functions.hpp | 1 + 2 files changed, 23 insertions(+) diff --git a/src/Components/Modules/Script.cpp b/src/Components/Modules/Script.cpp index 72995ce6..c0213610 100644 --- a/src/Components/Modules/Script.cpp +++ b/src/Components/Modules/Script.cpp @@ -531,6 +531,28 @@ namespace Components { Script::ScriptStorage.clear(); }); + + Script::AddFunction("NoClip", [](Game::scr_entref_t entref) + { + if (entref >= Game::MAX_GENTITIES || Game::g_entities[entref].client == nullptr) + { + Game::Scr_Error(Utils::String::VA("^1NoClip: entity %u is not a client\n", entref)); + return; + } + + Game::g_entities[entref].client->flags ^= Game::PLAYER_FLAG_NOCLIP; + }); + + Script::AddFunction("Ufo", [](Game::scr_entref_t entref) + { + if (entref >= Game::MAX_GENTITIES || Game::g_entities[entref].client == nullptr) + { + Game::Scr_Error(Utils::String::VA("^1Ufo: entity %u is not a client\n", entref)); + return; + } + + Game::g_entities[entref].client->flags ^= Game::PLAYER_FLAG_UFO; + }); } Script::Script() diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index 2569dbcf..984bf7c5 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -931,6 +931,7 @@ namespace Game extern int* demoRecording; extern int* serverMessageSequence; + constexpr auto MAX_GENTITIES = 2048; extern gentity_t* g_entities; extern netadr_t* connectedHost; From eda10589a1bb2a5c805e3fc97d992bff82237e14 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Sat, 16 Oct 2021 13:51:57 +0100 Subject: [PATCH 04/41] [Script] Make MAX_GENTITIES unsigned --- src/Game/Functions.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index 984bf7c5..00318046 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -931,7 +931,7 @@ namespace Game extern int* demoRecording; extern int* serverMessageSequence; - constexpr auto MAX_GENTITIES = 2048; + constexpr auto MAX_GENTITIES = 2048u; extern gentity_t* g_entities; extern netadr_t* connectedHost; From 4d2356f824f057c8bb491e7967c0451deb251844 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Sat, 16 Oct 2021 17:44:22 +0100 Subject: [PATCH 05/41] [Script] Add optional toggle parameter to ufo/noclip --- src/Components/Modules/Script.cpp | 34 ++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/src/Components/Modules/Script.cpp b/src/Components/Modules/Script.cpp index c0213610..730be18e 100644 --- a/src/Components/Modules/Script.cpp +++ b/src/Components/Modules/Script.cpp @@ -532,7 +532,7 @@ namespace Components Script::ScriptStorage.clear(); }); - Script::AddFunction("NoClip", [](Game::scr_entref_t entref) + Script::AddFunction("Noclip", [](Game::scr_entref_t entref) { if (entref >= Game::MAX_GENTITIES || Game::g_entities[entref].client == nullptr) { @@ -540,7 +540,21 @@ namespace Components return; } - Game::g_entities[entref].client->flags ^= Game::PLAYER_FLAG_NOCLIP; + if (Game::Scr_GetNumParam() == 1 && Game::Scr_GetType(0) == Game::VAR_INTEGER) + { + if (Game::Scr_GetInt(0)) + { + Game::g_entities[entref].client->flags |= Game::PLAYER_FLAG_NOCLIP; + } + else + { + Game::g_entities[entref].client->flags &= ~Game::PLAYER_FLAG_NOCLIP; + } + } + else + { + Game::g_entities[entref].client->flags ^= Game::PLAYER_FLAG_NOCLIP; + } }); Script::AddFunction("Ufo", [](Game::scr_entref_t entref) @@ -551,7 +565,21 @@ namespace Components return; } - Game::g_entities[entref].client->flags ^= Game::PLAYER_FLAG_UFO; + if (Game::Scr_GetNumParam() == 1 && Game::Scr_GetType(0) == Game::VAR_INTEGER) + { + if (Game::Scr_GetInt(0)) + { + Game::g_entities[entref].client->flags |= Game::PLAYER_FLAG_UFO; + } + else + { + Game::g_entities[entref].client->flags &= ~Game::PLAYER_FLAG_UFO; + } + } + else + { + Game::g_entities[entref].client->flags ^= Game::PLAYER_FLAG_UFO; + } }); } From 9897f399a598e0fff1fbac339ec25602eea7e730 Mon Sep 17 00:00:00 2001 From: Chase Date: Sat, 16 Oct 2021 12:39:25 -0500 Subject: [PATCH 06/41] Update Gamepad.hpp --- src/Components/Modules/Gamepad.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Components/Modules/Gamepad.hpp b/src/Components/Modules/Gamepad.hpp index 9808909f..b2621b3b 100644 --- a/src/Components/Modules/Gamepad.hpp +++ b/src/Components/Modules/Gamepad.hpp @@ -65,6 +65,7 @@ namespace Components static Dvar::Var gpad_debug; static Dvar::Var gpad_present; static Dvar::Var gpad_in_use; + static Dvar::Var gpad_style; static Dvar::Var gpad_sticksConfig; static Dvar::Var gpad_buttonConfig; static Dvar::Var gpad_menu_scroll_delay_first; From 3b00c823d51c4d6d1c761c1c75a7b8c666596a8b Mon Sep 17 00:00:00 2001 From: Chase Date: Sat, 16 Oct 2021 12:40:07 -0500 Subject: [PATCH 07/41] Update Gamepad.cpp --- src/Components/Modules/Gamepad.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Components/Modules/Gamepad.cpp b/src/Components/Modules/Gamepad.cpp index 5068f5b6..2b62f102 100644 --- a/src/Components/Modules/Gamepad.cpp +++ b/src/Components/Modules/Gamepad.cpp @@ -155,6 +155,7 @@ namespace Components Dvar::Var Gamepad::gpad_debug; Dvar::Var Gamepad::gpad_present; Dvar::Var Gamepad::gpad_in_use; + Dvar::Var Gamepad::gpad_style; Dvar::Var Gamepad::gpad_sticksConfig; Dvar::Var Gamepad::gpad_buttonConfig; Dvar::Var Gamepad::gpad_menu_scroll_delay_first; @@ -1694,6 +1695,7 @@ namespace Components gpad_debug = Dvar::Register("gpad_debug", false, Game::DVAR_FLAG_NONE, "Game pad debugging"); gpad_present = Dvar::Register("gpad_present", false, Game::DVAR_FLAG_NONE, "Game pad present"); gpad_in_use = Dvar::Register("gpad_in_use", false, Game::DVAR_FLAG_NONE, "A game pad is in use"); + gpad_style = Dvar::Register("gpad_style", false, Game::DVAR_FLAG_SAVED, "Switch between Xbox and PS HUD"); gpad_sticksConfig = Dvar::Register("gpad_sticksConfig", "", Game::DVAR_FLAG_SAVED, "Game pad stick configuration"); gpad_buttonConfig = Dvar::Register("gpad_buttonConfig", "", Game::DVAR_FLAG_SAVED, "Game pad button configuration"); gpad_menu_scroll_delay_first = Dvar::Register("gpad_menu_scroll_delay_first", 420, 0, 1000, Game::DVAR_FLAG_SAVED, "Menu scroll key-repeat delay, for the first repeat, in milliseconds"); From c22abf2791236892e9d9225bf2c90c1284cb4432 Mon Sep 17 00:00:00 2001 From: Jan Date: Sat, 16 Oct 2021 22:20:12 +0200 Subject: [PATCH 08/41] Swap between playstation and xbox buttons depending on the style dvar --- src/Components/Modules/Gamepad.cpp | 68 +++++++++++++++++++++++++++--- src/Components/Modules/Gamepad.hpp | 9 +++- 2 files changed, 68 insertions(+), 9 deletions(-) diff --git a/src/Components/Modules/Gamepad.cpp b/src/Components/Modules/Gamepad.cpp index 2b62f102..c3555fc7 100644 --- a/src/Components/Modules/Gamepad.cpp +++ b/src/Components/Modules/Gamepad.cpp @@ -108,7 +108,7 @@ namespace Components {"DPAD_RIGHT", Game::K_DPAD_RIGHT}, }; - Game::keyname_t Gamepad::extendedLocalizedKeyNames[] + Game::keyname_t Gamepad::extendedLocalizedKeyNamesXenon[] { // Material text icons pattern: 0x01 width height material_name_len {"^\x01\x32\x32\x08""button_a", Game::K_BUTTON_A}, @@ -128,8 +128,30 @@ namespace Components {"^\x01\x32\x32\x09""dpad_left", Game::K_DPAD_LEFT}, {"^\x01\x32\x32\x0A""dpad_right", Game::K_DPAD_RIGHT}, }; + + Game::keyname_t Gamepad::extendedLocalizedKeyNamesPs3[] + { + // Material text icons pattern: 0x01 width height material_name_len + {"^\x01\x32\x32\x10""button_ps3_cross", Game::K_BUTTON_A}, + {"^\x01\x32\x32\x11""button_ps3_circle", Game::K_BUTTON_B}, + {"^\x01\x32\x32\x11""button_ps3_square", Game::K_BUTTON_X}, + {"^\x01\x32\x32\x13""button_ps3_triangle", Game::K_BUTTON_Y}, + {"^\x01\x32\x32\x0D""button_ps3_l1", Game::K_BUTTON_LSHLDR}, + {"^\x01\x32\x32\x0D""button_ps3_r1", Game::K_BUTTON_RSHLDR}, + {"^\x01\x32\x32\x10""button_ps3_start", Game::K_BUTTON_START}, + {"^\x01\x32\x32\x0F""button_ps3_back", Game::K_BUTTON_BACK}, + {"^\x01\x48\x32\x0D""button_ps3_l3", Game::K_BUTTON_LSTICK}, + {"^\x01\x48\x32\x0D""button_ps3_r3", Game::K_BUTTON_RSTICK}, + {"^\x01\x32\x32\x0D""button_ps3_l2", Game::K_BUTTON_LTRIG}, + {"^\x01\x32\x32\x0D""button_ps3_r2", Game::K_BUTTON_RTRIG}, + {"^\x01\x32\x32\x0B""dpad_ps3_up", Game::K_DPAD_UP}, + {"^\x01\x32\x32\x0D""dpad_ps3_down", Game::K_DPAD_DOWN}, + {"^\x01\x32\x32\x0D""dpad_ps3_left", Game::K_DPAD_LEFT}, + {"^\x01\x32\x32\x0E""dpad_ps3_right", Game::K_DPAD_RIGHT}, + }; Game::keyname_t Gamepad::combinedKeyNames[Game::KEY_NAME_COUNT + std::extent_v + 1]; - Game::keyname_t Gamepad::combinedLocalizedKeyNames[Game::KEY_NAME_COUNT + std::extent_v + 1]; + Game::keyname_t Gamepad::combinedLocalizedKeyNamesXenon[Game::KEY_NAME_COUNT + std::extent_v + 1]; + Game::keyname_t Gamepad::combinedLocalizedKeyNamesPs3[Game::KEY_NAME_COUNT + std::extent_v + 1]; Gamepad::ControllerMenuKeyMapping Gamepad::controllerMenuKeyMappings[] { @@ -1832,21 +1854,53 @@ namespace Components return cl_bypassMouseInput.get() || IsGamePadInUse(); } + Game::keyname_t* Gamepad::GetLocalizedKeyNameMap() + { + if(gpad_style.get()) + return combinedLocalizedKeyNamesPs3; + + return combinedLocalizedKeyNamesXenon; + } + + void __declspec(naked) Gamepad::GetLocalizedKeyName_Stub() + { + __asm + { + push eax + pushad + + call GetLocalizedKeyNameMap + mov [esp + 0x20], eax + + popad + pop eax + + // Re-execute last instruction from game to set flags again for upcoming jump + test edi, edi + ret + } + } + void Gamepad::CreateKeyNameMap() { memcpy(combinedKeyNames, Game::keyNames, sizeof(Game::keyname_t) * Game::KEY_NAME_COUNT); memcpy(&combinedKeyNames[Game::KEY_NAME_COUNT], extendedKeyNames, sizeof(Game::keyname_t) * std::extent_v); combinedKeyNames[std::extent_v - 1] = {nullptr, 0}; - memcpy(combinedLocalizedKeyNames, Game::localizedKeyNames, sizeof(Game::keyname_t) * Game::LOCALIZED_KEY_NAME_COUNT); - memcpy(&combinedLocalizedKeyNames[Game::LOCALIZED_KEY_NAME_COUNT], extendedLocalizedKeyNames, - sizeof(Game::keyname_t) * std::extent_v); - combinedLocalizedKeyNames[std::extent_v - 1] = {nullptr, 0}; + memcpy(combinedLocalizedKeyNamesXenon, Game::localizedKeyNames, sizeof(Game::keyname_t) * Game::LOCALIZED_KEY_NAME_COUNT); + memcpy(&combinedLocalizedKeyNamesXenon[Game::LOCALIZED_KEY_NAME_COUNT], extendedLocalizedKeyNamesXenon, + sizeof(Game::keyname_t) * std::extent_v); + combinedLocalizedKeyNamesXenon[std::extent_v - 1] = {nullptr, 0}; + + memcpy(combinedLocalizedKeyNamesPs3, Game::localizedKeyNames, sizeof(Game::keyname_t) * Game::LOCALIZED_KEY_NAME_COUNT); + memcpy(&combinedLocalizedKeyNamesPs3[Game::LOCALIZED_KEY_NAME_COUNT], extendedLocalizedKeyNamesPs3, + sizeof(Game::keyname_t) * std::extent_v); + combinedLocalizedKeyNamesPs3[std::extent_v - 1] = {nullptr, 0}; Utils::Hook::Set(0x4A780A, combinedKeyNames); Utils::Hook::Set(0x4A7810, combinedKeyNames); Utils::Hook::Set(0x435C9F, combinedKeyNames); - Utils::Hook::Set(0x435C98, combinedLocalizedKeyNames); + Utils::Hook(0x435C97, GetLocalizedKeyName_Stub, HOOK_CALL).install()->quick(); } Gamepad::Gamepad() diff --git a/src/Components/Modules/Gamepad.hpp b/src/Components/Modules/Gamepad.hpp index b2621b3b..5c55325c 100644 --- a/src/Components/Modules/Gamepad.hpp +++ b/src/Components/Modules/Gamepad.hpp @@ -51,9 +51,11 @@ namespace Components static const char* gamePadMappingTypeNames[]; static Game::keyNum_t menuScrollButtonList[]; static Game::keyname_t extendedKeyNames[]; - static Game::keyname_t extendedLocalizedKeyNames[]; + static Game::keyname_t extendedLocalizedKeyNamesXenon[]; + static Game::keyname_t extendedLocalizedKeyNamesPs3[]; static Game::keyname_t combinedKeyNames[]; - static Game::keyname_t combinedLocalizedKeyNames[]; + static Game::keyname_t combinedLocalizedKeyNamesXenon[]; + static Game::keyname_t combinedLocalizedKeyNamesPs3[]; static ControllerMenuKeyMapping controllerMenuKeyMappings[]; static GamePad gamePads[Game::MAX_GAMEPADS]; @@ -193,6 +195,9 @@ namespace Components static void CL_KeyEvent_Hk(int localClientNum, int key, int down, unsigned int time); static int CL_MouseEvent_Hk(int x, int y, int dx, int dy); static bool UI_RefreshViewport_Hk(); + + static Game::keyname_t* GetLocalizedKeyNameMap(); + static void GetLocalizedKeyName_Stub(); static void CreateKeyNameMap(); }; } From bc36a2999154a393bc0f641f47e19862a74d69db Mon Sep 17 00:00:00 2001 From: Jan Date: Sat, 16 Oct 2021 22:21:32 +0200 Subject: [PATCH 09/41] Add "Chase" to list of contributors --- src/Components/Modules/Localization.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Components/Modules/Localization.cpp b/src/Components/Modules/Localization.cpp index 3c5b82a7..1bdb421c 100644 --- a/src/Components/Modules/Localization.cpp +++ b/src/Components/Modules/Localization.cpp @@ -181,6 +181,7 @@ namespace Components "a231", "AmateurHailbut", "Aoki", + "Chase", "civil", "Dasfonia", "Deity", From b7ca47699c204381e8c41d4f3d2cfb9122dc5f61 Mon Sep 17 00:00:00 2001 From: Maurice Heumann Date: Sun, 7 Nov 2021 09:23:06 +0100 Subject: [PATCH 10/41] Add build scripts --- .github/workflows/build.yml | 119 ++++++++++++++++++++++++ .github/workflows/draft-new-release.yml | 48 ++++++++++ .github/workflows/release.yml | 83 +++++++++++++++++ 3 files changed, 250 insertions(+) create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/draft-new-release.yml create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..88f0aa8c --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,119 @@ +name: Build + +on: + push: + branches: + - "*" + pull_request: + branches: + - "*" + types: [opened, synchronize, reopened] + +jobs: + build: + name: Build binaries + runs-on: windows-latest + strategy: + matrix: + configuration: + - Debug + - Release + steps: + - name: Wait for previous workflows + if: github.event_name == 'push' && github.ref == 'refs/heads/master' + uses: softprops/turnstyle@v1 + with: + poll-interval-seconds: 10 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Check out files + uses: actions/checkout@v2 + with: + submodules: true + fetch-depth: 0 + # NOTE - If LFS ever starts getting used during builds, switch this to true! + lfs: false + + - name: Add msbuild to PATH + uses: microsoft/setup-msbuild@v1.0.2 + + - name: Generate project files + #run: tools/premake5 vs2019 --ci-build + run: tools/premake5 vs2019 --ac-disable + + - name: Set up problem matching + uses: ammaraskar/msvc-problem-matcher@master + + - name: Build ${{matrix.configuration}} binaries + run: msbuild /m /v:minimal /p:Configuration=${{matrix.configuration}} build/iw4x.sln + + - name: Upload ${{matrix.configuration}} binaries + uses: actions/upload-artifact@v2 + with: + name: ${{matrix.configuration}} binaries + path: | + build/bin/x64/${{matrix.configuration}}/iw4x.dll + build/bin/x64/${{matrix.configuration}}/iw4x.pdb + +# - name: Upload ${{matrix.configuration}} data artifacts +# uses: actions/upload-artifact@v2 +# with: +# name: ${{matrix.configuration}} data artifacts +# path: | +# data/* + + + deploy: + name: Deploy artifacts + needs: build + runs-on: ubuntu-latest + if: github.event_name == 'push' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/develop') + steps: + - name: Setup main environment + if: github.ref == 'refs/heads/master' + run: echo "XLABS_MASTER_PATH=${{ secrets.XLABS_MASTER_SSH_PATH }}" >> $GITHUB_ENV + + - name: Setup develop environment + if: github.ref == 'refs/heads/develop' + run: echo "XLABS_MASTER_PATH=${{ secrets.XLABS_MASTER_SSH_PATH_DEV }}" >> $GITHUB_ENV + + - name: Download Release binaries + uses: actions/download-artifact@v2 + with: + name: Release binaries + + - name: Download Release data artifacts + uses: actions/download-artifact@v2 + with: + name: Release data artifacts + path: data + + # Set up committer info and GPG key + - name: Install SSH key + uses: shimataro/ssh-key-action@v2 + with: + key: ${{ secrets.XLABS_MASTER_SSH_PRIVATE_KEY }} + known_hosts: 'just-a-placeholder-so-we-dont-get-errors' + + - name: Add known hosts + run: ssh-keyscan -H ${{ secrets.XLABS_MASTER_SSH_ADDRESS }} >> ~/.ssh/known_hosts + + - name: Wait for previous workflows + uses: softprops/turnstyle@v1 + with: + poll-interval-seconds: 10 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + +# - name: Remove old data files +# run: ssh ${{ secrets.XLABS_MASTER_SSH_USER }}@${{ secrets.XLABS_MASTER_SSH_ADDRESS }} rm -rf ${{ env.XLABS_MASTER_PATH }}/iw4x/data/* + + - name: Upload iw4x binary + run: rsync -avz iw4x.dll ${{ secrets.XLABS_MASTER_SSH_USER }}@${{ secrets.XLABS_MASTER_SSH_ADDRESS }}:${{ env.XLABS_MASTER_PATH }}/iw4x/ + +# - name: Upload data files +# run: rsync -avz ./data/ ${{ secrets.XLABS_MASTER_SSH_USER }}@${{ secrets.XLABS_MASTER_SSH_ADDRESS }}:${{ env.XLABS_MASTER_PATH }}/iw4x/data/ + + - name: Publish changes + run: ssh ${{ secrets.XLABS_MASTER_SSH_USER }}@${{ secrets.XLABS_MASTER_SSH_ADDRESS }} ${{ secrets.XLABS_MASTER_SSH_CHANGE_PUBLISH_COMMAND }} \ No newline at end of file diff --git a/.github/workflows/draft-new-release.yml b/.github/workflows/draft-new-release.yml new file mode 100644 index 00000000..35f0f8cc --- /dev/null +++ b/.github/workflows/draft-new-release.yml @@ -0,0 +1,48 @@ +name: "Draft new release" + +on: + workflow_dispatch: + inputs: + version: + description: "The version you want to release." + required: true + +jobs: + draft-new-release: + name: "Draft a new release" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Normalize version + id: normalize_version + run: | + version="${{ github.event.inputs.version }}" + version="v${version#v}" + echo "::set-output name=version::$version" + + # Set up committer info and GPG key + - name: Import GPG key + id: import_gpg + uses: XLabsProject/ghaction-import-gpg@25d9d6ab99eb355c169c33c2306a72df85d9f516 + with: + git-commit-gpgsign: true + git-committer-email: "${{ secrets.XLABS_CI_EMAIL }}" + git-committer-name: "${{ secrets.XLABS_CI_NAME }}" + # git-push-gpgsign: true + git-tag-gpgsign: true + git-user-signingkey: true + gpg-private-key: ${{ secrets.XLABS_CI_GPG_PRIVATE_KEY }} + passphrase: ${{ secrets.XLABS_CI_GPG_PASSWORD }} + + - name: Create Pull Request + uses: repo-sync/pull-request@v2 + with: + github_token: ${{ secrets.XLABS_CI_GITHUB_TOKEN }} + source_branch: "develop" + destination_branch: "master" + pr_allow_empty: true + pr_body: | + This Pull Request is for the release of IW4x ${{ steps.normalize_version.outputs.version }} and was [automatically created by a workflow](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) triggered by @${{ github.actor }}. + pr_title: Release ${{ steps.normalize_version.outputs.version }} + pr_label: release diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..70fbf24c --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,83 @@ +name: Release + +on: + pull_request: + branches: + - "master" + types: [closed] +jobs: + merge: + runs-on: ubuntu-latest + name: Merge Release + steps: + - name: Check out files + if: github.event.pull_request.merged + uses: actions/checkout@v2 + with: + submodules: false + lfs: false + + # Set up committer info and GPG key + - name: Import GPG key + if: github.event.pull_request.merged + id: import_gpg + uses: XLabsProject/ghaction-import-gpg@25d9d6ab99eb355c169c33c2306a72df85d9f516 + with: + git-commit-gpgsign: true + git-committer-email: "${{ secrets.XLABS_CI_EMAIL }}" + git-committer-name: "${{ secrets.XLABS_CI_NAME }}" + git-push-gpgsign: false + git-tag-gpgsign: true + git-user-signingkey: true + gpg-private-key: ${{ secrets.XLABS_CI_GPG_PRIVATE_KEY }} + passphrase: ${{ secrets.XLABS_CI_GPG_PASSWORD }} + + - name: Extract version from pull request + if: github.event.pull_request.merged + id: extract_version + run: | + title="${{ github.event.pull_request.title }}" + version="${title#Release }" + echo "::set-output name=version::$version" + + - name: Create annotated tag + if: github.event.pull_request.merged + run: | + git tag -a -m "${{ github.event.pull_request.title }}" \ + "${{ steps.extract_version.outputs.version }}" \ + "${{ github.event.pull_request.merge_commit_sha }}" + git push origin --tags + + - name: Create Pull Request + if: github.event.pull_request.merged + uses: repo-sync/pull-request@v2 + with: + github_token: ${{ secrets.XLABS_CI_GITHUB_TOKEN }} + source_branch: "master" + destination_branch: "develop" + pr_allow_empty: true + pr_body: | + This Pull Request merges the release of IW4x ${{ steps.extract_version.outputs.version }} and was [automatically created by a workflow](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) triggered by @${{ github.actor }}. + pr_title: Merge release ${{ steps.extract_version.outputs.version }} + pr_label: release + + + notify: + name: Notify Discord + runs-on: ubuntu-latest + if: | + github.repository_owner == 'XLabsProject' && ( + ( + github.event.pull_request.merged + ) || ( + github.event.push.ref == 'refs/heads/master' || + github.event.push.ref == 'refs/heads/develop' + ) + ) + steps: + - name: Post CI status notification to Discord + uses: sarisia/actions-status-discord@v1.7.1 + if: always() + with: + webhook: ${{ secrets.DISCORD_CI_BOT_WEBHOOK }} + title: "Build" From 93443050dd7bbce7e858cbe429a7ddfe147cbdd6 Mon Sep 17 00:00:00 2001 From: Maurice Heumann Date: Sun, 7 Nov 2021 09:27:01 +0100 Subject: [PATCH 11/41] Disable warning --- src/Components/Modules/Maps.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Components/Modules/Maps.cpp b/src/Components/Modules/Maps.cpp index 012b1d41..97ec8f61 100644 --- a/src/Components/Modules/Maps.cpp +++ b/src/Components/Modules/Maps.cpp @@ -752,6 +752,7 @@ namespace Components int16 Maps::CM_TriggerModelBounds(int modelPointer, Game::Bounds* bounds) { #ifdef DEBUG Game::MapEnts* ents = *reinterpret_cast(0x1AA651C); // Use me for debugging + (void)ents; #endif return Utils::Hook::Call(0x4416C0)(modelPointer, bounds); } From 3fe218b22a2b214e566fb6f93a5b042de983e462 Mon Sep 17 00:00:00 2001 From: Maurice Heumann Date: Sun, 7 Nov 2021 09:28:04 +0100 Subject: [PATCH 12/41] Add data files later --- .github/workflows/build.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 88f0aa8c..e08f2dc7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -83,11 +83,11 @@ jobs: with: name: Release binaries - - name: Download Release data artifacts - uses: actions/download-artifact@v2 - with: - name: Release data artifacts - path: data +# - name: Download Release data artifacts +# uses: actions/download-artifact@v2 +# with: +# name: Release data artifacts +# path: data # Set up committer info and GPG key - name: Install SSH key From e1ad2e1c29688e2638db557373a76e9e9248b1c3 Mon Sep 17 00:00:00 2001 From: Maurice Heumann Date: Sun, 7 Nov 2021 09:32:32 +0100 Subject: [PATCH 13/41] Fix artifact uploading --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e08f2dc7..e962961e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -53,8 +53,8 @@ jobs: with: name: ${{matrix.configuration}} binaries path: | - build/bin/x64/${{matrix.configuration}}/iw4x.dll - build/bin/x64/${{matrix.configuration}}/iw4x.pdb + build/bin/${{matrix.configuration}}/iw4x.dll + build/bin/${{matrix.configuration}}/iw4x.pdb # - name: Upload ${{matrix.configuration}} data artifacts # uses: actions/upload-artifact@v2 From 5ce4457aa6585a90ecf7f5f691a8f54999bb022e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 7 Nov 2021 08:41:01 +0000 Subject: [PATCH 14/41] Bump deps/pdcurses from `4bc97e2` to `2e15c90` Bumps [deps/pdcurses](https://github.com/wmcbrine/PDCurses) from `4bc97e2` to `2e15c90`. - [Release notes](https://github.com/wmcbrine/PDCurses/releases) - [Commits](https://github.com/wmcbrine/PDCurses/compare/4bc97e287be5d8927405614c193fd0a039df027a...2e15c90f122fef329b83a4c3c011f192d97ec516) --- updated-dependencies: - dependency-name: deps/pdcurses dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/pdcurses | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/pdcurses b/deps/pdcurses index 4bc97e28..2e15c90f 160000 --- a/deps/pdcurses +++ b/deps/pdcurses @@ -1 +1 @@ -Subproject commit 4bc97e287be5d8927405614c193fd0a039df027a +Subproject commit 2e15c90f122fef329b83a4c3c011f192d97ec516 From b0e702f33c888f866d5e0869397cd6918caca222 Mon Sep 17 00:00:00 2001 From: Maurice Heumann Date: Sun, 7 Nov 2021 09:50:36 +0100 Subject: [PATCH 15/41] Update README.md --- README.md | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/README.md b/README.md index fe82b30b..f04e11dc 100644 --- a/README.md +++ b/README.md @@ -2,24 +2,13 @@ ![forks](https://img.shields.io/github/forks/IW4x/iw4x-client.svg) ![stars](https://img.shields.io/github/stars/IW4x/iw4x-client.svg) ![issues](https://img.shields.io/github/issues/IW4x/iw4x-client.svg) +[![build](https://github.com/XLabsProject/iw4x-client/workflows/Build/badge.svg)](https://github.com/XLabsProject/iw4x-client/actions) [![build status](https://ci.appveyor.com/api/projects/status/rvljq0ooxen0oexm/branch/develop?svg=true)](https://ci.appveyor.com/project/iw4x/iw4x-client/branch/develop) [![discord](https://img.shields.io/endpoint?url=https://momo5502.com/iw4x/members-badge.php)](https://discord.gg/sKeVmR3) [![patreon](https://img.shields.io/badge/patreon-support-blue.svg?logo=patreon)](https://www.patreon.com/xlabsproject) # IW4x: Client -## Commit message style - -``` -[Module] Imperative summary - -- points or text - -[ci skip] -``` - -`[ci skip]` is optional. - ## How to compile - Run `premake5 vs2019` or use the delivered `generate.bat`. From 1112eba7fa2a25007a97cbda6757cf634fb24179 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Sun, 7 Nov 2021 11:09:00 +0000 Subject: [PATCH 16/41] Add customizable speed scale for stance --- src/Components/Loader.cpp | 1 + src/Components/Loader.hpp | 1 + src/Components/Modules/Dvar.cpp | 3 +++ src/Game/Structs.hpp | 31 +++++++++++++++++++++++++++++++ 4 files changed, 36 insertions(+) diff --git a/src/Components/Loader.cpp b/src/Components/Loader.cpp index 7b76cb02..fea7625e 100644 --- a/src/Components/Loader.cpp +++ b/src/Components/Loader.cpp @@ -104,6 +104,7 @@ namespace Components Loader::Register(new Gamepad()); Loader::Register(new Chat()); Loader::Register(new TextRenderer()); + Loader::Register(new Movement()); Loader::Register(new Client()); diff --git a/src/Components/Loader.hpp b/src/Components/Loader.hpp index 2265b729..dd948b09 100644 --- a/src/Components/Loader.hpp +++ b/src/Components/Loader.hpp @@ -132,6 +132,7 @@ namespace Components #include "Modules/SoundMutexFix.hpp" #include "Modules/Chat.hpp" #include "Modules/TextRenderer.hpp" +#include "Modules/Movement.hpp" #include "Modules/Gamepad.hpp" #include "Modules/Client.hpp" diff --git a/src/Components/Modules/Dvar.cpp b/src/Components/Modules/Dvar.cpp index d0892d2e..24149280 100644 --- a/src/Components/Modules/Dvar.cpp +++ b/src/Components/Modules/Dvar.cpp @@ -299,6 +299,9 @@ namespace Components // Uncheat ui_debugMode Utils::Hook::Xor(0x6312DE, Game::dvar_flag::DVAR_FLAG_CHEAT); + // Remove unknown flag (to prevent unknown behaviour) + Utils::Hook::Xor(0x448B42, Game::dvar_flag::DVAR_FLAG_UNKNOWN80); + // Hook dvar 'name' registration Utils::Hook(0x40531C, Dvar::RegisterName, HOOK_CALL).install()->quick(); diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index 7be1e8d7..1a9c019c 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -6876,6 +6876,37 @@ namespace Game const char* args[9]; }; + struct pmove_s + { + playerState_s* ps; + usercmd_s cmd; + usercmd_s oldcmd; + int tracemask; + int numtouch; + int touchents[32]; + char __pad0[24]; + float xyspeed; + int proneChange; + float maxSprintTimeMultiplier; + bool mantleStarted; + float mantleEndPos[3]; + int mantleDuration; + int viewChangeTime; + float viewChange; + float fTorsoPitch; + float fWaistPitch; + unsigned char handler; + }; + + enum EffectiveStance + { + PM_EFF_STANCE_DEFAULT = 0, + PM_EFF_STANCE_PRONE = 1, + PM_EFF_STANCE_DUCKED = 2, + PM_EFF_STANCE_LASTSTANDCRAWL = 3, + PM_EFF_STANCE_COUNT = 4 + }; + #pragma endregion #ifndef IDA From 1b1a53cef623dfcfc99870a46261bfe2b0bea5e3 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Sun, 7 Nov 2021 11:16:56 +0000 Subject: [PATCH 17/41] Add Module --- src/Components/Modules/Dvar.cpp | 2 +- src/Components/Modules/Movement.cpp | 151 ++++++++++++++++++++++++++++ src/Components/Modules/Movement.hpp | 20 ++++ 3 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 src/Components/Modules/Movement.cpp create mode 100644 src/Components/Modules/Movement.hpp diff --git a/src/Components/Modules/Dvar.cpp b/src/Components/Modules/Dvar.cpp index 24149280..5b7122d2 100644 --- a/src/Components/Modules/Dvar.cpp +++ b/src/Components/Modules/Dvar.cpp @@ -299,7 +299,7 @@ namespace Components // Uncheat ui_debugMode Utils::Hook::Xor(0x6312DE, Game::dvar_flag::DVAR_FLAG_CHEAT); - // Remove unknown flag (to prevent unknown behaviour) + // Remove unknown flag (prevent unknown behaviour) Utils::Hook::Xor(0x448B42, Game::dvar_flag::DVAR_FLAG_UNKNOWN80); // Hook dvar 'name' registration diff --git a/src/Components/Modules/Movement.cpp b/src/Components/Modules/Movement.cpp new file mode 100644 index 00000000..10a1377a --- /dev/null +++ b/src/Components/Modules/Movement.cpp @@ -0,0 +1,151 @@ +#include "STDInclude.hpp" + +namespace Components +{ + Dvar::Var Movement::PlayerDuckedSpeedScale; + Dvar::Var Movement::PlayerLastStandCrawlSpeedScale; + Dvar::Var Movement::PlayerProneSpeedScale; + + int Movement::PMGetEffectiveStance(Game::playerState_s* ps) + { + auto heightTarget = ps->viewHeightTarget; + + if (heightTarget == 0x16) + return Game::PM_EFF_STANCE_LASTSTANDCRAWL; + + if (heightTarget == 0x28) + return Game::PM_EFF_STANCE_DUCKED; + + if (heightTarget == 0xB) + return Game::PM_EFF_STANCE_PRONE; + + return Game::PM_EFF_STANCE_DEFAULT; + } + + float Movement::PMCmdScaleForStance(Game::pmove_s* move) + { + auto* playerState = move->ps; + float scale; + + if (playerState->viewHeightLerpTime != 0 && playerState->viewHeightLerpTarget == 0xB) + { + scale = move->cmd.serverTime - playerState->viewHeightLerpTime / 400.0f; + + if (0.0f <= scale) + { + auto flags = 0; + + if (scale < 1.0f) + { + flags |= 1 << 8; + } + + if (scale == 1.0f) + { + flags |= 1 << 14; + } + + if (flags == 0) + { + scale = 1.0f; + return scale * 0.15f + (1.0f - scale) * 0.65f; + } + + if (scale != 0.0f) + { + return scale * 0.15f + (1.0f - scale) * 0.65f; + } + } + } + + if ((playerState->viewHeightLerpTime != 0 && playerState->viewHeightLerpTarget == 0x28) && + playerState->viewHeightLerpDown == 0) + { + scale = 400.0f / move->cmd.serverTime - playerState->viewHeightLerpTime; + + if (0.0f <= scale) + { + auto flags = 0; + + if (scale < 1.0f) + { + flags |= 1 << 8; + } + + if (scale == 1.0f) + { + flags |= 1 << 14; + } + + if (flags == 0) + { + scale = 1.0f; + } + else if (scale != 0.0f) + { + return scale * 0.65f + (1.0f - scale) * 0.15f; + } + } + } + + scale = 1.0f; + auto stance = Movement::PMGetEffectiveStance(playerState); + + if (stance == Game::PM_EFF_STANCE_PRONE) + { + scale = Movement::PlayerProneSpeedScale.get(); + } + + else if (stance == Game::PM_EFF_STANCE_DUCKED) + { + scale = Movement::PlayerDuckedSpeedScale.get(); + } + + else if (stance == Game::PM_EFF_STANCE_LASTSTANDCRAWL) + { + scale = Movement::PlayerLastStandCrawlSpeedScale.get(); + } + + return scale; + } + + __declspec(naked) void Movement::PMCmdScaleForStanceStub() + { + __asm + { + pushad + + push edx + call Movement::PMCmdScaleForStance + add esp, 4 + + popad + ret + } + } + + Movement::Movement() + { + Dvar::OnInit([] + { + Movement::PlayerDuckedSpeedScale = Dvar::Register("player_duckedSpeedScale", + 0.65f, 0.0f, 5.0f, Game::DVAR_FLAG_CHEAT | Game::DVAR_FLAG_REPLICATED, + "The scale applied to the player speed when ducking"); + + Movement::PlayerLastStandCrawlSpeedScale = Dvar::Register("player_lastStandCrawlSpeedScale", + 0.2f, 0.0f, 5.0f, Game::DVAR_FLAG_CHEAT | Game::DVAR_FLAG_REPLICATED, + "The scale applied to the player speed when crawling in last stand"); + + Movement::PlayerProneSpeedScale = Dvar::Register("player_proneSpeedScale", + 0.15f, 0.0f, 5.0f, Game::DVAR_FLAG_CHEAT | Game::DVAR_FLAG_REPLICATED, + "The scale applied to the player speed when crawling"); + }); + + Utils::Hook(0x572F34, Movement::PMCmdScaleForStanceStub, HOOK_CALL).install()->quick(); + Utils::Hook(0x57395F, Movement::PMCmdScaleForStanceStub, HOOK_CALL).install()->quick(); + } + + Movement::~Movement() + { + } +} diff --git a/src/Components/Modules/Movement.hpp b/src/Components/Modules/Movement.hpp new file mode 100644 index 00000000..4c8104a2 --- /dev/null +++ b/src/Components/Modules/Movement.hpp @@ -0,0 +1,20 @@ +#pragma once + +namespace Components +{ + class Movement : public Component + { + public: + Movement(); + ~Movement(); + + private: + static Dvar::Var PlayerDuckedSpeedScale; + static Dvar::Var PlayerLastStandCrawlSpeedScale; + static Dvar::Var PlayerProneSpeedScale; + + static int PMGetEffectiveStance(Game::playerState_s* ps); + static float PMCmdScaleForStance(Game::pmove_s* move); + static void PMCmdScaleForStanceStub(); + }; +} From 7664a773e729d47f4b1876dfe64c1d832e04df0b Mon Sep 17 00:00:00 2001 From: FutureRave Date: Sun, 7 Nov 2021 17:58:33 +0000 Subject: [PATCH 18/41] Have comment explain what dvar flag is being modified --- src/Components/Modules/Dvar.cpp | 2 +- src/Game/Structs.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Components/Modules/Dvar.cpp b/src/Components/Modules/Dvar.cpp index 5b7122d2..0d7f8f9f 100644 --- a/src/Components/Modules/Dvar.cpp +++ b/src/Components/Modules/Dvar.cpp @@ -299,7 +299,7 @@ namespace Components // Uncheat ui_debugMode Utils::Hook::Xor(0x6312DE, Game::dvar_flag::DVAR_FLAG_CHEAT); - // Remove unknown flag (prevent unknown behaviour) + // Remove unknown flag from player_lastStandCrawlSpeedScale (prevent unknown behaviour) Utils::Hook::Xor(0x448B42, Game::dvar_flag::DVAR_FLAG_UNKNOWN80); // Hook dvar 'name' registration diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index 1a9c019c..2d8b443c 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -109,7 +109,7 @@ namespace Game IMG_CATEGORY_WATER = 0x5, IMG_CATEGORY_RENDERTARGET = 0x6, IMG_CATEGORY_TEMP = 0x7, - } ; + }; enum buttons_t { From b77e95a846b67bfa77678073f329a3ec8ac62bf4 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Wed, 10 Nov 2021 19:48:00 +0000 Subject: [PATCH 19/41] Refactor quick patch a bit --- src/Components/Modules/QuickPatch.cpp | 38 +++++++++++++-------------- src/Components/Modules/QuickPatch.hpp | 4 +-- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/Components/Modules/QuickPatch.cpp b/src/Components/Modules/QuickPatch.cpp index 1ab8479b..33c8f84f 100644 --- a/src/Components/Modules/QuickPatch.cpp +++ b/src/Components/Modules/QuickPatch.cpp @@ -3,6 +3,7 @@ namespace Components { int QuickPatch::FrameTime = 0; + Dvar::Var QuickPatch::r_customAspectRatio; void QuickPatch::UnlockStats() { @@ -139,16 +140,15 @@ namespace Components } } - bool QuickPatch::InvalidNameCheck(char *dest, char *source, int size) + bool QuickPatch::InvalidNameCheck(char* dest, const char* source, int size) { - strncpy(dest, source, size - 1); - dest[size - 1] = 0; + Utils::Hook::Call(0x4D6F80)(dest, source, size); // I_strncpyz for (int i = 0; i < size - 1; i++) { if (!dest[i]) break; - if (dest[i] > 125 || dest[i] < 32 || dest[i] == '%') + if (dest[i] > 125 || dest[i] < 32 || dest[i] == '%') { return false; } @@ -172,7 +172,7 @@ namespace Components push 1; push kick_reason; push edi; - mov eax, 0x004D1600; + mov eax, 0x004D1600; // SV_DropClientInternal call eax; add esp, 12; popad; @@ -184,7 +184,6 @@ namespace Components } Game::dvar_t* QuickPatch::g_antilag; - __declspec(naked) void QuickPatch::ClientEventsFireWeaponStub() { __asm @@ -268,30 +267,31 @@ namespace Components } } - Game::dvar_t* QuickPatch::r_customAspectRatio; Game::dvar_t* QuickPatch::Dvar_RegisterAspectRatioDvar(const char* name, char**, int defaultVal, int flags, const char* description) { - static std::vector < char * > values = + static char* r_aspectRatioEnum[] = { - const_cast("auto"), - const_cast("standard"), - const_cast("wide 16:10"), - const_cast("wide 16:9"), - const_cast("custom"), - nullptr, + "auto", + "standard", + "wide 16:10", + "wide 16:9", + "custom", + nullptr }; // register custom aspect ratio dvar - r_customAspectRatio = Game::Dvar_RegisterFloat("r_customAspectRatio", 16.0f / 9.0f, 4.0f / 3.0f, 63.0f / 9.0f, flags, "Screen aspect ratio. Divide the width by the height in order to get the aspect ratio value. For example: 16 / 9 = 1,77"); + QuickPatch::r_customAspectRatio = Dvar::Register("r_customAspectRatio", + 16.0f / 9.0f, 4.0f / 3.0f, 63.0f / 9.0f, flags, + "Screen aspect ratio. Divide the width by the height in order to get the aspect ratio value. For example: 16 / 9 = 1,77"); // register enumeration dvar - return Game::Dvar_RegisterEnum(name, values.data(), defaultVal, flags, description); + return Game::Dvar_RegisterEnum(name, r_aspectRatioEnum, defaultVal, flags, description); } void QuickPatch::SetAspectRatio() { // set the aspect ratio - Utils::Hook::Set(0x66E1C78, r_customAspectRatio->current.value); + Utils::Hook::Set(0x66E1C78, r_customAspectRatio.get()); } __declspec(naked) void QuickPatch::SetAspectRatioStub() @@ -483,8 +483,8 @@ namespace Components Utils::Hook(0x578F52, QuickPatch::JavelinResetHookStub, HOOK_JUMP).install()->quick(); // Add ultrawide support - Utils::Hook(0x0051B13B, QuickPatch::Dvar_RegisterAspectRatioDvar, HOOK_CALL).install()->quick(); - Utils::Hook(0x005063F3, QuickPatch::SetAspectRatioStub, HOOK_JUMP).install()->quick(); + Utils::Hook(0x51B13B, QuickPatch::Dvar_RegisterAspectRatioDvar, HOOK_CALL).install()->quick(); + Utils::Hook(0x5063F3, QuickPatch::SetAspectRatioStub, HOOK_JUMP).install()->quick(); // Make sure preDestroy is called when the game shuts down Scheduler::OnShutdown(Loader::PreDestroy); diff --git a/src/Components/Modules/QuickPatch.hpp b/src/Components/Modules/QuickPatch.hpp index 008f4a05..6b13a5a1 100644 --- a/src/Components/Modules/QuickPatch.hpp +++ b/src/Components/Modules/QuickPatch.hpp @@ -28,13 +28,13 @@ namespace Components static void JavelinResetHookStub(); - static bool InvalidNameCheck(char *dest, char *source, int size); + static bool InvalidNameCheck(char* dest, const char* source, int size); static void InvalidNameStub(); static Game::dvar_t* sv_enableBounces; static void BounceStub(); - static Game::dvar_t* r_customAspectRatio; + static Dvar::Var r_customAspectRatio; static Game::dvar_t* Dvar_RegisterAspectRatioDvar(const char* name, char** enumValues, int defaultVal, int flags, const char* description); static void SetAspectRatioStub(); static void SetAspectRatio(); From 37e79f7c3acce22bc4f8e5caca4ef4a9f1f36dd0 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Thu, 11 Nov 2021 13:38:51 +0000 Subject: [PATCH 20/41] Hook dvar register func --- src/Components/Modules/Dvar.cpp | 3 --- src/Components/Modules/Movement.cpp | 18 ++++++++++++++---- src/Components/Modules/Movement.hpp | 2 ++ 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/Components/Modules/Dvar.cpp b/src/Components/Modules/Dvar.cpp index 0d7f8f9f..d0892d2e 100644 --- a/src/Components/Modules/Dvar.cpp +++ b/src/Components/Modules/Dvar.cpp @@ -299,9 +299,6 @@ namespace Components // Uncheat ui_debugMode Utils::Hook::Xor(0x6312DE, Game::dvar_flag::DVAR_FLAG_CHEAT); - // Remove unknown flag from player_lastStandCrawlSpeedScale (prevent unknown behaviour) - Utils::Hook::Xor(0x448B42, Game::dvar_flag::DVAR_FLAG_UNKNOWN80); - // Hook dvar 'name' registration Utils::Hook(0x40531C, Dvar::RegisterName, HOOK_CALL).install()->quick(); diff --git a/src/Components/Modules/Movement.cpp b/src/Components/Modules/Movement.cpp index 10a1377a..3c04b232 100644 --- a/src/Components/Modules/Movement.cpp +++ b/src/Components/Modules/Movement.cpp @@ -124,6 +124,14 @@ namespace Components } } + Game::dvar_t* Movement::Dvar_RegisterLastStandSpeedScale(const char* name, float defaultVal, float min, float max, int, const char*) + { + Movement::PlayerLastStandCrawlSpeedScale = Dvar::Register(name, defaultVal, + min, max, Game::DVAR_FLAG_CHEAT | Game::DVAR_FLAG_REPLICATED, "TEST DESC"); + + return Movement::PlayerLastStandCrawlSpeedScale.get(); + } + Movement::Movement() { Dvar::OnInit([] @@ -132,17 +140,19 @@ namespace Components 0.65f, 0.0f, 5.0f, Game::DVAR_FLAG_CHEAT | Game::DVAR_FLAG_REPLICATED, "The scale applied to the player speed when ducking"); - Movement::PlayerLastStandCrawlSpeedScale = Dvar::Register("player_lastStandCrawlSpeedScale", - 0.2f, 0.0f, 5.0f, Game::DVAR_FLAG_CHEAT | Game::DVAR_FLAG_REPLICATED, - "The scale applied to the player speed when crawling in last stand"); - Movement::PlayerProneSpeedScale = Dvar::Register("player_proneSpeedScale", 0.15f, 0.0f, 5.0f, Game::DVAR_FLAG_CHEAT | Game::DVAR_FLAG_REPLICATED, "The scale applied to the player speed when crawling"); }); + // Hook PM_CmdScaleForStance in PM_CmdScale_Walk Utils::Hook(0x572F34, Movement::PMCmdScaleForStanceStub, HOOK_CALL).install()->quick(); + + //Hook PM_CmdScaleForStance in PM_GetMaxSpeed Utils::Hook(0x57395F, Movement::PMCmdScaleForStanceStub, HOOK_CALL).install()->quick(); + + // Hook Dvar_RegisterFloat. Only thing that's changed is that the 0x80 flag is not used. + Utils::Hook(0x448B66, Movement::Dvar_RegisterLastStandSpeedScale, HOOK_CALL).install()->quick(); } Movement::~Movement() diff --git a/src/Components/Modules/Movement.hpp b/src/Components/Modules/Movement.hpp index 4c8104a2..07ad6894 100644 --- a/src/Components/Modules/Movement.hpp +++ b/src/Components/Modules/Movement.hpp @@ -16,5 +16,7 @@ namespace Components static int PMGetEffectiveStance(Game::playerState_s* ps); static float PMCmdScaleForStance(Game::pmove_s* move); static void PMCmdScaleForStanceStub(); + + static Game::dvar_t* Dvar_RegisterLastStandSpeedScale(const char* name, float defaultVal, float min, float max, int flags, const char* desc); }; } From b02d7f41aee85ef2a063f077469737d4376f88b2 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Thu, 11 Nov 2021 13:40:52 +0000 Subject: [PATCH 21/41] Overlooked this detail --- src/Components/Modules/Movement.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Components/Modules/Movement.cpp b/src/Components/Modules/Movement.cpp index 3c04b232..f71c9699 100644 --- a/src/Components/Modules/Movement.cpp +++ b/src/Components/Modules/Movement.cpp @@ -124,10 +124,10 @@ namespace Components } } - Game::dvar_t* Movement::Dvar_RegisterLastStandSpeedScale(const char* name, float defaultVal, float min, float max, int, const char*) + Game::dvar_t* Movement::Dvar_RegisterLastStandSpeedScale(const char* name, float defaultVal, float min, float max, int, const char* desc) { Movement::PlayerLastStandCrawlSpeedScale = Dvar::Register(name, defaultVal, - min, max, Game::DVAR_FLAG_CHEAT | Game::DVAR_FLAG_REPLICATED, "TEST DESC"); + min, max, Game::DVAR_FLAG_CHEAT | Game::DVAR_FLAG_REPLICATED, desc); return Movement::PlayerLastStandCrawlSpeedScale.get(); } From f6c973bc76de9a33ef56b2d1559b75dc57b21eec Mon Sep 17 00:00:00 2001 From: FutureRave Date: Thu, 11 Nov 2021 16:47:42 +0000 Subject: [PATCH 22/41] Make DvarRegisterEnum accept const char** --- src/Components/Modules/QuickPatch.cpp | 2 +- src/Game/Functions.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Components/Modules/QuickPatch.cpp b/src/Components/Modules/QuickPatch.cpp index 33c8f84f..59691749 100644 --- a/src/Components/Modules/QuickPatch.cpp +++ b/src/Components/Modules/QuickPatch.cpp @@ -269,7 +269,7 @@ namespace Components Game::dvar_t* QuickPatch::Dvar_RegisterAspectRatioDvar(const char* name, char**, int defaultVal, int flags, const char* description) { - static char* r_aspectRatioEnum[] = + static const char* r_aspectRatioEnum[] = { "auto", "standard", diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index 2569dbcf..ae4198b9 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -247,7 +247,7 @@ namespace Game typedef dvar_t* (__cdecl * Dvar_RegisterInt_t)(const char* name, int defaultVal, int min, int max, int flags, const char* description); extern Dvar_RegisterInt_t Dvar_RegisterInt; - typedef dvar_t* (__cdecl * Dvar_RegisterEnum_t)(const char* name, char** enumValues, int defaultVal, int flags, const char* description); + typedef dvar_t* (__cdecl * Dvar_RegisterEnum_t)(const char* name, const char** enumValues, int defaultVal, int flags, const char* description); extern Dvar_RegisterEnum_t Dvar_RegisterEnum; typedef dvar_t* (__cdecl * Dvar_RegisterString_t)(const char* name, const char* defaultVal, int, const char*); From 8cd3f2cad44216a35b6ab169fe1ad62572e7085f Mon Sep 17 00:00:00 2001 From: FutureRave Date: Sat, 13 Nov 2021 13:15:27 +0000 Subject: [PATCH 23/41] [Script] Add replaceFun --- src/Components/Modules/Script.cpp | 95 +++++++++++++++++++++++++++++++ src/Components/Modules/Script.hpp | 7 +++ src/Game/Functions.hpp | 4 +- src/Game/Structs.hpp | 2 +- 4 files changed, 105 insertions(+), 3 deletions(-) diff --git a/src/Components/Modules/Script.cpp b/src/Components/Modules/Script.cpp index 72995ce6..4d7435f2 100644 --- a/src/Components/Modules/Script.cpp +++ b/src/Components/Modules/Script.cpp @@ -9,6 +9,8 @@ namespace Components unsigned short Script::FunctionName; std::unordered_map Script::ScriptStorage; std::unordered_map Script::ScriptBaseProgramNum; + std::unordered_map Script::ReplacedFunctions; + const char* Script::ReplacedPos = 0; int Script::LastFrameTime = -1; Utils::Signal Script::VMShutdownSignal; @@ -397,6 +399,75 @@ namespace Components return Game::Scr_GetNumParam(); } + const char* Script::GetCodePosForParam(int index) + { + return Game::scriptContainer->stack[index].u.codePosValue; + } + + void Script::GetReplacedPos(const char* pos) + { + if (Script::ReplacedFunctions.find(pos) != Script::ReplacedFunctions.end()) + { + Script::ReplacedPos = Script::ReplacedFunctions[pos];; + } + } + + void Script::SetReplacedPos(const char* what, const char* with) + { + // Warn if the function was already detoured + if (Script::ReplacedFunctions.find(what) != Script::ReplacedFunctions.end()) + { + Logger::Print("Warning: a function was already detoured by a script\n"); + } + + Script::ReplacedFunctions[what] = with; + } + + __declspec(naked) void Script::VMExecuteInternalStub() + { + __asm + { + pushad + + push edx + call Script::GetReplacedPos + + pop edx + popad + + cmp Script::ReplacedPos, 0 + jne SetPos + + movzx eax, byte ptr [edx] + inc edx + + Loc1: + cmp eax, 0x8B + + push ecx + + mov ecx, 0x2045094 + mov [ecx], eax + + mov ecx, 0x2040CD4 + mov [ecx], edx + + pop ecx + + push 0x061E944 + retn + + SetPos: + mov edx, Script::ReplacedPos + mov Script::ReplacedPos, 0 + + movzx eax, byte ptr [edx] + inc edx + + jmp Loc1 + } + } + Game::gentity_t* Script::getEntFromEntRef(Game::scr_entref_t entref) { Game::gentity_t* gentity = &Game::g_entities[entref]; @@ -414,6 +485,26 @@ namespace Components void Script::AddFunctions() { + Script::AddFunction("ReplaceFunc", [](Game::scr_entref_t) // gsc: ReplaceFunc(,) + { + if (Game::Scr_GetNumParam() != 2) + { + Game::Scr_Error("^1ReplaceFunc: Needs two parameters!\n"); + return; + } + + if (Game::Scr_GetType(0) != Game::VAR_FUNCTION || Game::Scr_GetType(1) != Game::VAR_FUNCTION) + { + Game::Scr_Error("^1ReplaceFunc: Needs function pointers as parameters!\n"); + return; + } + + const auto what = Script::GetCodePosForParam(0); + const auto with = Script::GetCodePosForParam(-1); + + Script::SetReplacedPos(what, with); + }); + // System time Script::AddFunction("GetSystemTime", [](Game::scr_entref_t) // gsc: GetSystemTime() { @@ -562,6 +653,9 @@ namespace Components Utils::Hook(0x5F41A3, Script::SetExpFogStub, HOOK_CALL).install()->quick(); + Utils::Hook(0x61E92E, Script::VMExecuteInternalStub, HOOK_JUMP).install()->quick(); + Utils::Hook::Nop(0x61E933, 1); + Utils::Hook(0x47548B, Script::ScrShutdownSystemStub, HOOK_CALL).install()->quick(); Utils::Hook(0x4D06BA, Script::ScrShutdownSystemStub, HOOK_CALL).install()->quick(); @@ -623,6 +717,7 @@ namespace Components Script::ScriptHandles.clear(); Script::ScriptNameStack.clear(); Script::ScriptFunctions.clear(); + Script::ReplacedFunctions.clear(); Script::VMShutdownSignal.clear(); Script::ScriptStorage.clear(); diff --git a/src/Components/Modules/Script.hpp b/src/Components/Modules/Script.hpp index dd429cde..8d6e2c8b 100644 --- a/src/Components/Modules/Script.hpp +++ b/src/Components/Modules/Script.hpp @@ -40,6 +40,8 @@ namespace Components static unsigned short FunctionName; static std::unordered_map ScriptStorage; static std::unordered_map ScriptBaseProgramNum; + static std::unordered_map ReplacedFunctions; + static const char* ReplacedPos; static int LastFrameTime; static Utils::Signal VMShutdownSignal; @@ -70,6 +72,11 @@ namespace Components static int SetExpFogStub(); + static const char* GetCodePosForParam(int index); + static void GetReplacedPos(const char* pos); + static void SetReplacedPos(const char* what, const char* with); + static void VMExecuteInternalStub(); + static void AddFunctions(); }; } diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index 2569dbcf..47487a29 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -660,7 +660,7 @@ namespace Game typedef unsigned int(__cdecl * Scr_GetObject_t)(int); extern Scr_GetObject_t Scr_GetObject; - typedef int(__cdecl * Scr_GetNumParam_t)(); + typedef unsigned int(__cdecl * Scr_GetNumParam_t)(); extern Scr_GetNumParam_t Scr_GetNumParam; typedef int(__cdecl * Scr_GetFunctionHandle_t)(const char*, const char*); @@ -687,7 +687,7 @@ namespace Game typedef bool(__cdecl * Scr_IsSystemActive_t)(); extern Scr_IsSystemActive_t Scr_IsSystemActive; - typedef int(__cdecl* Scr_GetType_t)(int); + typedef int(__cdecl* Scr_GetType_t)(unsigned int); extern Scr_GetType_t Scr_GetType; typedef void(__cdecl* Scr_Error_t)(const char*); diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index 7be1e8d7..6e112ee4 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -4886,7 +4886,7 @@ namespace Game struct VariableValue { VariableUnion u; - int type; + VariableType type; }; struct ScriptContainer From 446c55b0b0c0c7cacdedcbc89259f4cc7fef531c Mon Sep 17 00:00:00 2001 From: FutureRave Date: Sat, 13 Nov 2021 13:22:06 +0000 Subject: [PATCH 24/41] [Script] Fix unsigned/signed mismatch --- src/Components/Modules/Bots.cpp | 8 ++++---- src/Components/Modules/Download.cpp | 4 ++-- src/Components/Modules/Script.cpp | 20 ++++++++++---------- src/Components/Modules/Script.hpp | 2 +- src/Components/Modules/Slowmotion.cpp | 4 ++-- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/Components/Modules/Bots.cpp b/src/Components/Modules/Bots.cpp index 7e0f16ba..15e36cfb 100644 --- a/src/Components/Modules/Bots.cpp +++ b/src/Components/Modules/Bots.cpp @@ -160,7 +160,7 @@ namespace Components { Script::AddFunction("SetPing", [](Game::scr_entref_t id) // gsc: self SetPing() { - if (Game::Scr_GetNumParam() != 1 || Game::Scr_GetType(0) != Game::VAR_INTEGER) + if (Game::Scr_GetNumParam() != 1u || Game::Scr_GetType(0) != Game::VAR_INTEGER) { Game::Scr_Error("^1SetPing: Needs one integer parameter!\n"); return; @@ -250,7 +250,7 @@ namespace Components Script::AddFunction("botWeapon", [](Game::scr_entref_t id) // Usage: botWeapon(); { - if (Game::Scr_GetNumParam() != 1 || Game::Scr_GetType(0) != Game::VAR_STRING) + if (Game::Scr_GetNumParam() != 1u || Game::Scr_GetType(0) != Game::VAR_STRING) { Game::Scr_Error("^1botWeapon: Needs one string parameter!\n"); return; @@ -293,7 +293,7 @@ namespace Components Script::AddFunction("botAction", [](Game::scr_entref_t id) // Usage: botAction(); { - if (Game::Scr_GetNumParam() != 1 || Game::Scr_GetType(0) != Game::VAR_STRING) + if (Game::Scr_GetNumParam() != 1u || Game::Scr_GetType(0) != Game::VAR_STRING) { Game::Scr_Error("^1botAction: Needs one string parameter!\n"); return; @@ -346,7 +346,7 @@ namespace Components Script::AddFunction("botMovement", [](Game::scr_entref_t id) // Usage: botMovement(, ); { - if (Game::Scr_GetNumParam() != 2 || Game::Scr_GetType(0) != Game::VAR_INTEGER || Game::Scr_GetType(1) != Game::VAR_INTEGER) + if (Game::Scr_GetNumParam() != 2u || Game::Scr_GetType(0) != Game::VAR_INTEGER || Game::Scr_GetType(1) != Game::VAR_INTEGER) { Game::Scr_Error("^1botMovement: Needs two integer parameters!\n"); return; diff --git a/src/Components/Modules/Download.cpp b/src/Components/Modules/Download.cpp index d2bb9649..7d1d6f27 100644 --- a/src/Components/Modules/Download.cpp +++ b/src/Components/Modules/Download.cpp @@ -967,7 +967,7 @@ namespace Components Script::AddFunction("httpGet", [](Game::scr_entref_t) { if (!Dedicated::IsEnabled() && !Flags::HasFlag("scriptablehttp")) return; - if (Game::Scr_GetNumParam() < 1) return; + if (Game::Scr_GetNumParam() < 1u) return; std::string url = Game::Scr_GetString(0); unsigned int object = Game::AllocObject(); @@ -981,7 +981,7 @@ namespace Components Script::AddFunction("httpCancel", [](Game::scr_entref_t) { if (!Dedicated::IsEnabled() && !Flags::HasFlag("scriptablehttp")) return; - if (Game::Scr_GetNumParam() < 1) return; + if (Game::Scr_GetNumParam() < 1u) return; unsigned int object = Game::Scr_GetObject(0); for (auto& download : Download::ScriptDownloads) diff --git a/src/Components/Modules/Script.cpp b/src/Components/Modules/Script.cpp index 4d7435f2..4758784c 100644 --- a/src/Components/Modules/Script.cpp +++ b/src/Components/Modules/Script.cpp @@ -384,9 +384,9 @@ namespace Components Utils::Hook::Call(0x421EE0)(num); } - int Script::SetExpFogStub() + unsigned int Script::SetExpFogStub() { - if (Game::Scr_GetNumParam() == 6) + if (Game::Scr_GetNumParam() == 6u) { std::memmove(&Game::scriptContainer->stack[-4], &Game::scriptContainer->stack[-5], sizeof(Game::VariableValue) * 6); Game::scriptContainer->stack += 1; @@ -408,7 +408,7 @@ namespace Components { if (Script::ReplacedFunctions.find(pos) != Script::ReplacedFunctions.end()) { - Script::ReplacedPos = Script::ReplacedFunctions[pos];; + Script::ReplacedPos = Script::ReplacedFunctions[pos]; } } @@ -487,7 +487,7 @@ namespace Components { Script::AddFunction("ReplaceFunc", [](Game::scr_entref_t) // gsc: ReplaceFunc(,) { - if (Game::Scr_GetNumParam() != 2) + if (Game::Scr_GetNumParam() != 2u) { Game::Scr_Error("^1ReplaceFunc: Needs two parameters!\n"); return; @@ -525,7 +525,7 @@ namespace Components // Print to console, even without being in 'developer 1'. Script::AddFunction("PrintConsole", [](Game::scr_entref_t) // gsc: PrintConsole() { - if (Game::Scr_GetNumParam() != 1 || Game::Scr_GetType(0) != Game::VAR_STRING) + if (Game::Scr_GetNumParam() != 1u || Game::Scr_GetType(0) != Game::VAR_STRING) { Game::Scr_Error("^1PrintConsole: Needs one string parameter!\n"); return; @@ -539,7 +539,7 @@ namespace Components // Executes command to the console Script::AddFunction("Exec", [](Game::scr_entref_t) // gsc: Exec() { - if (Game::Scr_GetNumParam() != 1 || Game::Scr_GetType(0) != Game::VAR_STRING) + if (Game::Scr_GetNumParam() != 1u || Game::Scr_GetType(0) != Game::VAR_STRING) { Game::Scr_Error("^1Exec: Needs one string parameter!\n"); return; @@ -554,7 +554,7 @@ namespace Components // Script Storage Funcs Script::AddFunction("StorageSet", [](Game::scr_entref_t) // gsc: StorageSet(, ); { - if (Game::Scr_GetNumParam() != 2 || Game::Scr_GetType(0) != Game::VAR_STRING || Game::Scr_GetType(1) != Game::VAR_STRING) + if (Game::Scr_GetNumParam() != 2u || Game::Scr_GetType(0) != Game::VAR_STRING || Game::Scr_GetType(1) != Game::VAR_STRING) { Game::Scr_Error("^1StorageSet: Needs two string parameters!\n"); return; @@ -568,7 +568,7 @@ namespace Components Script::AddFunction("StorageRemove", [](Game::scr_entref_t) // gsc: StorageRemove(); { - if (Game::Scr_GetNumParam() != 1 || Game::Scr_GetType(0) != Game::VAR_STRING) + if (Game::Scr_GetNumParam() != 1u || Game::Scr_GetType(0) != Game::VAR_STRING) { Game::Scr_Error("^1StorageRemove: Needs one string parameter!\n"); return; @@ -587,7 +587,7 @@ namespace Components Script::AddFunction("StorageGet", [](Game::scr_entref_t) // gsc: StorageGet(); { - if (Game::Scr_GetNumParam() != 1 || Game::Scr_GetType(0) != Game::VAR_STRING) + if (Game::Scr_GetNumParam() != 1u || Game::Scr_GetType(0) != Game::VAR_STRING) { Game::Scr_Error("^1StorageGet: Needs one string parameter!\n"); return; @@ -607,7 +607,7 @@ namespace Components Script::AddFunction("StorageHas", [](Game::scr_entref_t) // gsc: StorageHas(); { - if (Game::Scr_GetNumParam() != 1 || Game::Scr_GetType(0) != Game::VAR_STRING) + if (Game::Scr_GetNumParam() != 1u || Game::Scr_GetType(0) != Game::VAR_STRING) { Game::Scr_Error("^1StorageHas: Needs one string parameter!\n"); return; diff --git a/src/Components/Modules/Script.hpp b/src/Components/Modules/Script.hpp index 8d6e2c8b..c9125831 100644 --- a/src/Components/Modules/Script.hpp +++ b/src/Components/Modules/Script.hpp @@ -70,7 +70,7 @@ namespace Components static void Scr_PrintPrevCodePosStub(); static void Scr_PrintPrevCodePos(int); - static int SetExpFogStub(); + static unsigned int SetExpFogStub(); static const char* GetCodePosForParam(int index); static void GetReplacedPos(const char* pos); diff --git a/src/Components/Modules/Slowmotion.cpp b/src/Components/Modules/Slowmotion.cpp index 0a15b94d..4879e142 100644 --- a/src/Components/Modules/Slowmotion.cpp +++ b/src/Components/Modules/Slowmotion.cpp @@ -38,12 +38,12 @@ namespace Components float start = Game::Scr_GetFloat(0); float end = 1.0f; - if (Game::Scr_GetNumParam() >= 2) + if (Game::Scr_GetNumParam() >= 2u) { end = Game::Scr_GetFloat(1); } - if (Game::Scr_GetNumParam() >= 3) + if (Game::Scr_GetNumParam() >= 3u) { duration = static_cast(Game::Scr_GetFloat(2) * 1000.0); } From c73794f6ea6d8aa79df7f665d1faa8945f7f50c7 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Sat, 13 Nov 2021 13:32:20 +0000 Subject: [PATCH 25/41] [Script] Better comments --- src/Components/Modules/Script.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Components/Modules/Script.cpp b/src/Components/Modules/Script.cpp index 4758784c..c88b219c 100644 --- a/src/Components/Modules/Script.cpp +++ b/src/Components/Modules/Script.cpp @@ -414,7 +414,6 @@ namespace Components void Script::SetReplacedPos(const char* what, const char* with) { - // Warn if the function was already detoured if (Script::ReplacedFunctions.find(what) != Script::ReplacedFunctions.end()) { Logger::Print("Warning: a function was already detoured by a script\n"); @@ -485,7 +484,7 @@ namespace Components void Script::AddFunctions() { - Script::AddFunction("ReplaceFunc", [](Game::scr_entref_t) // gsc: ReplaceFunc(,) + Script::AddFunction("ReplaceFunc", [](Game::scr_entref_t) // gsc: ReplaceFunc(, ) { if (Game::Scr_GetNumParam() != 2u) { From f101dbadec8bf0dbde36ec3845aa60cd9c87f16e Mon Sep 17 00:00:00 2001 From: FutureRave Date: Sat, 13 Nov 2021 18:51:37 +0000 Subject: [PATCH 26/41] [Script] Improve structs, add extra checks --- src/Components/Modules/Script.cpp | 69 +++++++++++++++---------------- src/Components/Modules/Script.hpp | 2 +- src/Game/Functions.cpp | 2 +- src/Game/Functions.hpp | 2 +- src/Game/Structs.hpp | 36 ++++++++++++---- 5 files changed, 65 insertions(+), 46 deletions(-) diff --git a/src/Components/Modules/Script.cpp b/src/Components/Modules/Script.cpp index c88b219c..5d10ca9c 100644 --- a/src/Components/Modules/Script.cpp +++ b/src/Components/Modules/Script.cpp @@ -388,20 +388,34 @@ namespace Components { if (Game::Scr_GetNumParam() == 6u) { - std::memmove(&Game::scriptContainer->stack[-4], &Game::scriptContainer->stack[-5], sizeof(Game::VariableValue) * 6); - Game::scriptContainer->stack += 1; - Game::scriptContainer->stack[-6].type = Game::VAR_FLOAT; - Game::scriptContainer->stack[-6].u.floatValue = 0; + std::memmove(&Game::scrVmPub->top[-4], &Game::scrVmPub->top[-5], sizeof(Game::VariableValue) * 6); + Game::scrVmPub->top += 1; + Game::scrVmPub->top[-6].type = Game::VAR_FLOAT; + Game::scrVmPub->top[-6].u.floatValue = 0; - ++Game::scriptContainer->numParam; + ++Game::scrVmPub->outparamcount; } return Game::Scr_GetNumParam(); } - const char* Script::GetCodePosForParam(int index) + const char* Script::GetCodePosForParam(unsigned int index) { - return Game::scriptContainer->stack[index].u.codePosValue; + if (index >= Game::scrVmPub->outparamcount) + { + Game::Scr_Error("^1GetCodePosForParam: Index is out of range!\n"); + return ""; + } + + const auto value = &Game::scrVmPub->top[0 - index]; + + if (value->type != Game::VAR_FUNCTION) + { + Game::Scr_Error("^1GetCodePosForParam: Expects a function as parameter!\n"); + return ""; + } + + return value->u.codePosValue; } void Script::GetReplacedPos(const char* pos) @@ -414,9 +428,15 @@ namespace Components void Script::SetReplacedPos(const char* what, const char* with) { + if (what[0] == '\0' || with[0] == '\0') + { + Logger::Print("Warning: Invalid paramters passed to ReplacedFunctions\n"); + return; + } + if (Script::ReplacedFunctions.find(what) != Script::ReplacedFunctions.end()) { - Logger::Print("Warning: a function was already detoured by a script\n"); + Logger::Print("Warning: ReplacedFunctions already contains codePosValue for a function\n"); } Script::ReplacedFunctions[what] = with; @@ -453,7 +473,7 @@ namespace Components pop ecx - push 0x061E944 + push 0x61E944 retn SetPos: @@ -499,7 +519,7 @@ namespace Components } const auto what = Script::GetCodePosForParam(0); - const auto with = Script::GetCodePosForParam(-1); + const auto with = Script::GetCodePosForParam(1); Script::SetReplacedPos(what, with); }); @@ -683,31 +703,10 @@ namespace Components Script::AddFunctions(); - // Script::AddFunction("playviewmodelfx", [](Game::scr_entref_t /*index*/) - // { - // /*auto Scr_Error = Utils::Hook::Call(0x42EF40); - // if (index >> 16) - // { - // Scr_Error("not an entity"); - // return; - // }*/ - - // // obtain FX name - // auto fxName = Game::Scr_GetString(0); - // auto fx = Game::DB_FindXAssetHeader(Game::XAssetType::ASSET_TYPE_FX, fxName).fx; - - // auto tagName = Game::Scr_GetString(1); - // auto tagIndex = Game::SL_GetString(tagName, 0); - - // /*char boneIndex = -2; - // if (!Game::CG_GetBoneIndex(2048, tagIndex, &boneIndex)) - // { - // Scr_Error(Utils::String::VA("Unknown bone %s.\n", tagName)); - // return; - // }*/ - - // Game::CG_PlayBoltedEffect(0, fx, 2048, tagIndex); - // }); + Script::OnVMShutdown([] + { + Script::ReplacedFunctions.clear(); + }); } Script::~Script() diff --git a/src/Components/Modules/Script.hpp b/src/Components/Modules/Script.hpp index c9125831..5fb13727 100644 --- a/src/Components/Modules/Script.hpp +++ b/src/Components/Modules/Script.hpp @@ -72,7 +72,7 @@ namespace Components static unsigned int SetExpFogStub(); - static const char* GetCodePosForParam(int index); + static const char* GetCodePosForParam(unsigned int index); static void GetReplacedPos(const char* pos); static void SetReplacedPos(const char* what, const char* with); static void VMExecuteInternalStub(); diff --git a/src/Game/Functions.cpp b/src/Game/Functions.cpp index 462c6d9c..d61e41fa 100644 --- a/src/Game/Functions.cpp +++ b/src/Game/Functions.cpp @@ -460,7 +460,7 @@ namespace Game XZone* g_zones = reinterpret_cast(0x14C0F80); unsigned short* db_hashTable = reinterpret_cast(0x12412B0); - ScriptContainer* scriptContainer = reinterpret_cast(0x2040D00); + scrVmPub_t* scrVmPub = reinterpret_cast(0x2040CF0); clientstate_t* clcState = reinterpret_cast(0xB2C540); diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index 47487a29..f5e89711 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -968,7 +968,7 @@ namespace Game extern XZone* g_zones; extern unsigned short* db_hashTable; - extern ScriptContainer* scriptContainer; + extern scrVmPub_t* scrVmPub; extern clientstate_t* clcState; diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index 6e112ee4..1f090ec0 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -4889,15 +4889,35 @@ namespace Game VariableType type; }; - struct ScriptContainer + struct function_stack_t { - VariableValue* stack; - char unk1; - char unk2; - char unk3; - char pad; - DWORD unk4; - int numParam; + const char* pos; + unsigned int localId; + unsigned int localVarCount; + VariableValue* top; + VariableValue* startTop; + }; + + struct function_frame_t + { + function_stack_t fs; + int topType; + }; + + struct scrVmPub_t + { + unsigned int* localVars; + VariableValue* maxStack; + int function_count; + function_frame_t* function_frame; + VariableValue* top; + bool debugCode; + bool abort_on_error; + bool terminal_error; + unsigned int inparamcount; + unsigned int outparamcount; + function_frame_t function_frame_start[32]; + VariableValue stack[2048]; }; enum UILocalVarType From 4cb8cdfca3570619babae558a510499086e0cbd9 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Sat, 13 Nov 2021 19:12:16 +0000 Subject: [PATCH 27/41] [Script] Removed double check' --- src/Components/Modules/Script.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Components/Modules/Script.cpp b/src/Components/Modules/Script.cpp index 5d10ca9c..b4a0bf86 100644 --- a/src/Components/Modules/Script.cpp +++ b/src/Components/Modules/Script.cpp @@ -512,12 +512,6 @@ namespace Components return; } - if (Game::Scr_GetType(0) != Game::VAR_FUNCTION || Game::Scr_GetType(1) != Game::VAR_FUNCTION) - { - Game::Scr_Error("^1ReplaceFunc: Needs function pointers as parameters!\n"); - return; - } - const auto what = Script::GetCodePosForParam(0); const auto with = Script::GetCodePosForParam(1); From 5c69267ba3b057d6dbf98a3b149dc65b06d675f1 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Sat, 13 Nov 2021 20:46:58 +0000 Subject: [PATCH 28/41] [Script] Make index signed to keep consistency --- src/Components/Modules/Script.cpp | 4 ++-- src/Components/Modules/Script.hpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Components/Modules/Script.cpp b/src/Components/Modules/Script.cpp index b4a0bf86..fa97048f 100644 --- a/src/Components/Modules/Script.cpp +++ b/src/Components/Modules/Script.cpp @@ -399,7 +399,7 @@ namespace Components return Game::Scr_GetNumParam(); } - const char* Script::GetCodePosForParam(unsigned int index) + const char* Script::GetCodePosForParam(int index) { if (index >= Game::scrVmPub->outparamcount) { @@ -407,7 +407,7 @@ namespace Components return ""; } - const auto value = &Game::scrVmPub->top[0 - index]; + const auto value = &Game::scrVmPub->top[-index]; if (value->type != Game::VAR_FUNCTION) { diff --git a/src/Components/Modules/Script.hpp b/src/Components/Modules/Script.hpp index 5fb13727..c9125831 100644 --- a/src/Components/Modules/Script.hpp +++ b/src/Components/Modules/Script.hpp @@ -72,7 +72,7 @@ namespace Components static unsigned int SetExpFogStub(); - static const char* GetCodePosForParam(unsigned int index); + static const char* GetCodePosForParam(int index); static void GetReplacedPos(const char* pos); static void SetReplacedPos(const char* what, const char* with); static void VMExecuteInternalStub(); From c3dd5015e141b93626302363140994c817f01526 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Sat, 13 Nov 2021 20:55:22 +0000 Subject: [PATCH 29/41] [Script] Fix compilation --- src/Components/Modules/Script.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Components/Modules/Script.cpp b/src/Components/Modules/Script.cpp index fa97048f..d8c7b955 100644 --- a/src/Components/Modules/Script.cpp +++ b/src/Components/Modules/Script.cpp @@ -401,7 +401,7 @@ namespace Components const char* Script::GetCodePosForParam(int index) { - if (index >= Game::scrVmPub->outparamcount) + if (static_cast(index) >= Game::scrVmPub->outparamcount) { Game::Scr_Error("^1GetCodePosForParam: Index is out of range!\n"); return ""; From 6eaf72e86f7517d059d3dd8e8001e1469011f88c Mon Sep 17 00:00:00 2001 From: FutureRave Date: Mon, 15 Nov 2021 17:44:23 +0000 Subject: [PATCH 30/41] [Script] Small adjustment to variable type --- src/Components/Modules/Script.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Components/Modules/Script.cpp b/src/Components/Modules/Script.cpp index d8c7b955..0f1384d4 100644 --- a/src/Components/Modules/Script.cpp +++ b/src/Components/Modules/Script.cpp @@ -391,7 +391,7 @@ namespace Components std::memmove(&Game::scrVmPub->top[-4], &Game::scrVmPub->top[-5], sizeof(Game::VariableValue) * 6); Game::scrVmPub->top += 1; Game::scrVmPub->top[-6].type = Game::VAR_FLOAT; - Game::scrVmPub->top[-6].u.floatValue = 0; + Game::scrVmPub->top[-6].u.floatValue = 0.0f; ++Game::scrVmPub->outparamcount; } From f0687f8203d71eaff715b3e1212c7027d2cee259 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Tue, 16 Nov 2021 16:56:13 +0000 Subject: [PATCH 31/41] Use correct enum over numbers for com_error --- src/Components/Modules/Dedicated.cpp | 2 +- src/Components/Modules/Dedicated.hpp | 2 +- src/Components/Modules/Logger.cpp | 8 ++++---- src/Components/Modules/Logger.hpp | 4 ++-- src/Components/Modules/Renderer.cpp | 2 +- src/Components/Modules/Script.cpp | 8 ++++---- src/Components/Modules/ZoneBuilder.cpp | 4 ++-- src/Game/Functions.hpp | 2 +- src/Game/Structs.hpp | 12 ++++++++++++ 9 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/Components/Modules/Dedicated.cpp b/src/Components/Modules/Dedicated.cpp index 7ff6330c..f99ce32f 100644 --- a/src/Components/Modules/Dedicated.cpp +++ b/src/Components/Modules/Dedicated.cpp @@ -96,7 +96,7 @@ namespace Components Game::SV_GameSendServerCommand(-1, 0, list.data()); } - void Dedicated::TimeWrapStub(int code, const char* message) + void Dedicated::TimeWrapStub(Game::errorParm_t code, const char* message) { static bool partyEnable; static std::string mapname; diff --git a/src/Components/Modules/Dedicated.hpp b/src/Components/Modules/Dedicated.hpp index 162e1a8f..f7210be2 100644 --- a/src/Components/Modules/Dedicated.hpp +++ b/src/Components/Modules/Dedicated.hpp @@ -25,6 +25,6 @@ namespace Components static void TransmitGuids(); - static void TimeWrapStub(int code, const char* message); + static void TimeWrapStub(Game::errorParm_t code, const char* message); }; } diff --git a/src/Components/Modules/Logger.cpp b/src/Components/Modules/Logger.cpp index 22ad6e09..10a38fc9 100644 --- a/src/Components/Modules/Logger.cpp +++ b/src/Components/Modules/Logger.cpp @@ -51,7 +51,7 @@ namespace Components } } - void Logger::ErrorPrint(int error, const std::string& message) + void Logger::ErrorPrint(Game::errorParm_t error, const std::string& message) { #ifdef DEBUG if (IsDebuggerPresent()) __debugbreak(); @@ -60,19 +60,19 @@ namespace Components return Game::Com_Error(error, "%s", message.data()); } - void Logger::Error(int error, const char* message, ...) + void Logger::Error(Game::errorParm_t error, const char* message, ...) { return Logger::ErrorPrint(error, Logger::Format(&message)); } void Logger::Error(const char* message, ...) { - return Logger::ErrorPrint(0, Logger::Format(&message)); + return Logger::ErrorPrint(Game::ERR_FATAL, Logger::Format(&message)); } void Logger::SoftError(const char* message, ...) { - return Logger::ErrorPrint(2, Logger::Format(&message)); + return Logger::ErrorPrint(Game::ERR_SERVERDISCONNECT, Logger::Format(&message)); } std::string Logger::Format(const char** message) diff --git a/src/Components/Modules/Logger.hpp b/src/Components/Modules/Logger.hpp index 26625324..a6799b96 100644 --- a/src/Components/Modules/Logger.hpp +++ b/src/Components/Modules/Logger.hpp @@ -11,9 +11,9 @@ namespace Components static void MessagePrint(int channel, const std::string& message); static void Print(int channel, const char* message, ...); static void Print(const char* message, ...); - static void ErrorPrint(int error, const std::string& message); + static void ErrorPrint(Game::errorParm_t error, const std::string& message); static void Error(const char* message, ...); - static void Error(int error, const char* message, ...); + static void Error(Game::errorParm_t error, const char* message, ...); static void SoftError(const char* message, ...); static bool IsConsoleReady(); diff --git a/src/Components/Modules/Renderer.cpp b/src/Components/Modules/Renderer.cpp index 2422fde2..984474b0 100644 --- a/src/Components/Modules/Renderer.cpp +++ b/src/Components/Modules/Renderer.cpp @@ -108,7 +108,7 @@ namespace Components void Renderer::R_TextureFromCodeError(const char* sampler, Game::GfxCmdBufState* state) { - Game::Com_Error(0, "Tried to use sampler '%s' when it isn't valid for material '%s' and technique '%s'", + Game::Com_Error(Game::ERR_FATAL, "Tried to use sampler '%s' when it isn't valid for material '%s' and technique '%s'", sampler, state->material->info.name, state->technique->name); } diff --git a/src/Components/Modules/Script.cpp b/src/Components/Modules/Script.cpp index 72995ce6..354b9465 100644 --- a/src/Components/Modules/Script.cpp +++ b/src/Components/Modules/Script.cpp @@ -24,7 +24,7 @@ namespace Components Logger::Print(23, "Error: unknown function %s in %s\n", funcName.data(), Script::ScriptName.data()); Logger::Print(23, "************************************\n"); - Logger::Error(5, "script compile error\nunknown function %s\n%s\n\n", funcName.data(), Script::ScriptName.data()); + Logger::Error(Game::ERR_SCRIPT_DROP, "script compile error\nunknown function %s\n%s\n\n", funcName.data(), Script::ScriptName.data()); } __declspec(naked) void Script::StoreFunctionNameStub() @@ -168,7 +168,7 @@ namespace Components Script::PrintSourcePos(Script::ScriptName.data(), offset); Logger::Print(23, "************************************\n\n"); - Logger::Error(5, "script compile error\n%s\n%s\n(see console for actual details)\n", msgbuf, Script::ScriptName.data()); + Logger::Error(Game::ERR_SCRIPT_DROP, "script compile error\n%s\n%s\n(see console for actual details)\n", msgbuf, Script::ScriptName.data()); } int Script::LoadScriptAndLabel(const std::string& script, const std::string& label) @@ -178,7 +178,7 @@ namespace Components if (!Game::Scr_LoadScript(script.data())) { Logger::Print("Script %s encountered an error while loading. (doesn't exist?)", script.data()); - Logger::Error(1, reinterpret_cast(0x70B810), script.data()); + Logger::Error(Game::ERR_DROP, reinterpret_cast(0x70B810), script.data()); } else { @@ -407,7 +407,7 @@ namespace Components { if (!gentity->client) { - Logger::Error(5, "Entity: %i is not a client", gentity); + Logger::Error(Game::ERR_SCRIPT_DROP, "Entity: %i is not a client", gentity); } return &Game::svs_clients[gentity->s.number]; } diff --git a/src/Components/Modules/ZoneBuilder.cpp b/src/Components/Modules/ZoneBuilder.cpp index efff6316..f8f45fc4 100644 --- a/src/Components/Modules/ZoneBuilder.cpp +++ b/src/Components/Modules/ZoneBuilder.cpp @@ -851,7 +851,7 @@ namespace Components Command::Add("error", [](Command::Params*) { - Game::Com_Error(0, "This is a test %s\n", "error"); + Game::Com_Error(Game::ERR_FATAL, "This is a test %s\n", "error"); }); // now load default assets and shaders @@ -1412,7 +1412,7 @@ namespace Components // build final techsets fastfile if (subCount > 24) { - Logger::ErrorPrint(1, "How did you have 576 fastfiles?\n"); + Logger::ErrorPrint(Game::ERR_DROP, "How did you have 576 fastfiles?\n"); } curTechsets_list.clear(); diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index 2569dbcf..e98103c4 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -121,7 +121,7 @@ namespace Game typedef void(__cdecl * Com_ClientPacketEvent_t)(); extern Com_ClientPacketEvent_t Com_ClientPacketEvent; - typedef void(__cdecl * Com_Error_t)(int type, const char* message, ...); + typedef void(__cdecl * Com_Error_t)(errorParm_t type, const char* message, ...); extern Com_Error_t Com_Error; typedef void(__cdecl * Com_Printf_t)(int channel, const char *fmt, ...); diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index 2d8b443c..63d4ce72 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -177,6 +177,18 @@ namespace Game CS_ACTIVE = 0x5, } clientstate_t; + typedef enum + { + ERR_FATAL = 0x0, + ERR_DROP = 0x1, + ERR_SERVERDISCONNECT = 0x2, + ERR_DISCONNECT = 0x3, + ERR_SCRIPT = 0x4, + ERR_SCRIPT_DROP = 0x5, + ERR_LOCALIZATION = 0x6, + ERR_MAPLOADERRORSUMMARY = 0x7 + } errorParm_t; + struct FxEffectDef; struct pathnode_t; struct pathnode_tree_t; From fb8ecf637fd6c7d7419b207de19c8d84ff5a058a Mon Sep 17 00:00:00 2001 From: FutureRave Date: Tue, 16 Nov 2021 18:21:06 +0000 Subject: [PATCH 32/41] Added random map rotation --- src/Components/Modules/Dedicated.cpp | 55 ++++++++++++++++++++++++++-- src/Components/Modules/Dedicated.hpp | 3 ++ src/STDInclude.hpp | 3 +- 3 files changed, 55 insertions(+), 6 deletions(-) diff --git a/src/Components/Modules/Dedicated.cpp b/src/Components/Modules/Dedicated.cpp index 7ff6330c..68223880 100644 --- a/src/Components/Modules/Dedicated.cpp +++ b/src/Components/Modules/Dedicated.cpp @@ -3,6 +3,7 @@ namespace Components { SteamID Dedicated::PlayerGuids[18][2]; + Dvar::Var Dedicated::SVRandomMapRotation; bool Dedicated::IsEnabled() { @@ -119,6 +120,41 @@ namespace Components Game::Com_Error(code, message); } + void Dedicated::RandomizeMapRotation() + { + auto rotation = Dvar::Var("sv_mapRotation").get(); + + const auto tokens = Utils::String::Explode(rotation, ' '); + std::vector> mapRotationPair; + + for (auto i = 0u; i < (tokens.size() - 1); i += 2) + { + if (i + 1 >= tokens.size()) break; + + const std::string key = tokens[i]; + const std::string value = tokens[i + 1]; + mapRotationPair.push_back(std::make_pair(key, value)); + } + + const auto seed = Utils::Cryptography::Rand::GenerateInt(); + std::shuffle(std::begin(mapRotationPair), std::end(mapRotationPair), std::default_random_engine(seed)); + + // Rebuild map rotation using the randomized key/values + rotation.clear(); + for (auto j = 0u; j < mapRotationPair.size(); j++) + { + std::pair pair = mapRotationPair[j]; + rotation.append(pair.first); + rotation.append(" "); + rotation.append(pair.second); + + if (j != mapRotationPair.size() - 1) + rotation.append(" "); + } + + Dvar::Var("sv_mapRotationCurrent").set(rotation); + } + void Dedicated::MapRotate() { if (!Dedicated::IsEnabled() && Dvar::Var("sv_dontrotate").get()) @@ -134,9 +170,10 @@ namespace Components } Logger::Print("Rotating map...\n"); + const auto mapRotation = Dvar::Var("sv_mapRotation").get(); // if nothing, just restart - if (Dvar::Var("sv_mapRotation").get().empty()) + if (mapRotation.empty()) { Logger::Print("No rotation defined, restarting map.\n"); @@ -152,14 +189,23 @@ namespace Components return; } - // first, check if the string contains nothing + // First, check if the string contains nothing if (Dvar::Var("sv_mapRotationCurrent").get().empty()) { Logger::Print("Current map rotation has finished, reloading...\n"); - Dvar::Var("sv_mapRotationCurrent").set(Dvar::Var("sv_mapRotation").get()); + + if (Dedicated::SVRandomMapRotation.get()) + { + Logger::Print("Randomizing map rotaion\n"); + Dedicated::RandomizeMapRotation(); + } + else + { + Dvar::Var("sv_mapRotationCurrent").set(mapRotation); + } } - std::string rotation = Dvar::Var("sv_mapRotationCurrent").get(); + auto rotation = Dvar::Var("sv_mapRotationCurrent").get(); auto tokens = Utils::String::Explode(rotation, ' '); @@ -346,6 +392,7 @@ namespace Components Dvar::OnInit([]() { + Dedicated::SVRandomMapRotation = Dvar::Register("sv_randomMapRotation", false, Game::dvar_flag::DVAR_FLAG_SAVED, "Randomize map rotation when true"); Dvar::Register("sv_sayName", "^7Console", Game::dvar_flag::DVAR_FLAG_NONE, "The name to pose as for 'say' commands"); Dvar::Register("sv_motd", "", Game::dvar_flag::DVAR_FLAG_NONE, "A custom message of the day for servers"); diff --git a/src/Components/Modules/Dedicated.hpp b/src/Components/Modules/Dedicated.hpp index 162e1a8f..aaf51f0d 100644 --- a/src/Components/Modules/Dedicated.hpp +++ b/src/Components/Modules/Dedicated.hpp @@ -15,6 +15,9 @@ namespace Components static void Heartbeat(); private: + static Dvar::Var SVRandomMapRotation; + + static void RandomizeMapRotation(); static void MapRotate(); static void InitDedicatedServer(); diff --git a/src/STDInclude.hpp b/src/STDInclude.hpp index 208e0cab..4ae48092 100644 --- a/src/STDInclude.hpp +++ b/src/STDInclude.hpp @@ -42,10 +42,9 @@ #include #include #include - -// Experimental C++17 features #include #include +#include #pragma warning(pop) From daced4427b364ab820f9ed80e1ea541454235e8c Mon Sep 17 00:00:00 2001 From: FutureRave Date: Tue, 16 Nov 2021 18:33:32 +0000 Subject: [PATCH 33/41] Use auto --- src/Components/Modules/Dedicated.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Components/Modules/Dedicated.cpp b/src/Components/Modules/Dedicated.cpp index 68223880..92728421 100644 --- a/src/Components/Modules/Dedicated.cpp +++ b/src/Components/Modules/Dedicated.cpp @@ -131,8 +131,8 @@ namespace Components { if (i + 1 >= tokens.size()) break; - const std::string key = tokens[i]; - const std::string value = tokens[i + 1]; + const auto& key = tokens[i]; + const auto& value = tokens[i + 1]; mapRotationPair.push_back(std::make_pair(key, value)); } @@ -143,7 +143,7 @@ namespace Components rotation.clear(); for (auto j = 0u; j < mapRotationPair.size(); j++) { - std::pair pair = mapRotationPair[j]; + const auto& pair = mapRotationPair[j]; rotation.append(pair.first); rotation.append(" "); rotation.append(pair.second); @@ -196,7 +196,7 @@ namespace Components if (Dedicated::SVRandomMapRotation.get()) { - Logger::Print("Randomizing map rotaion\n"); + Logger::Print("Randomizing map rotation\n"); Dedicated::RandomizeMapRotation(); } else From 447ab3ea615e324df937743a3ed67d93d1be9932 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Nov 2021 17:24:37 +0000 Subject: [PATCH 34/41] Bump deps/pdcurses from `2e15c90` to `6c31f22` Bumps [deps/pdcurses](https://github.com/wmcbrine/PDCurses) from `2e15c90` to `6c31f22`. - [Release notes](https://github.com/wmcbrine/PDCurses/releases) - [Commits](https://github.com/wmcbrine/PDCurses/compare/2e15c90f122fef329b83a4c3c011f192d97ec516...6c31f226922bd8653e7ed40cd4b11cee9845ea97) --- updated-dependencies: - dependency-name: deps/pdcurses dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/pdcurses | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/pdcurses b/deps/pdcurses index 2e15c90f..6c31f226 160000 --- a/deps/pdcurses +++ b/deps/pdcurses @@ -1 +1 @@ -Subproject commit 2e15c90f122fef329b83a4c3c011f192d97ec516 +Subproject commit 6c31f226922bd8653e7ed40cd4b11cee9845ea97 From ae627d5f8f230aeb5f12cd093199ceabcd423f02 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Mon, 29 Nov 2021 12:26:53 +0000 Subject: [PATCH 35/41] Elevators for trickshotting --- src/Components/Loader.cpp | 1 + src/Components/Loader.hpp | 1 + src/Components/Modules/Elevators.cpp | 81 ++++++++++++++++++++++++++++ src/Components/Modules/Elevators.hpp | 17 ++++++ 4 files changed, 100 insertions(+) create mode 100644 src/Components/Modules/Elevators.cpp create mode 100644 src/Components/Modules/Elevators.hpp diff --git a/src/Components/Loader.cpp b/src/Components/Loader.cpp index fea7625e..3217dcd4 100644 --- a/src/Components/Loader.cpp +++ b/src/Components/Loader.cpp @@ -105,6 +105,7 @@ namespace Components Loader::Register(new Chat()); Loader::Register(new TextRenderer()); Loader::Register(new Movement()); + Loader::Register(new Elevators()); Loader::Register(new Client()); diff --git a/src/Components/Loader.hpp b/src/Components/Loader.hpp index dd948b09..f9d1e6ed 100644 --- a/src/Components/Loader.hpp +++ b/src/Components/Loader.hpp @@ -133,6 +133,7 @@ namespace Components #include "Modules/Chat.hpp" #include "Modules/TextRenderer.hpp" #include "Modules/Movement.hpp" +#include "Modules/Elevators.hpp" #include "Modules/Gamepad.hpp" #include "Modules/Client.hpp" diff --git a/src/Components/Modules/Elevators.cpp b/src/Components/Modules/Elevators.cpp new file mode 100644 index 00000000..c8f5a14a --- /dev/null +++ b/src/Components/Modules/Elevators.cpp @@ -0,0 +1,81 @@ +#include "STDInclude.hpp" + +namespace Components +{ + Game::dvar_t* Elevators::SV_EnableEasyElevators; + + __declspec(naked) void Elevators::PM_CorrectAllSolidStub() + { + __asm + { + push ecx + mov ecx, Elevators::SV_EnableEasyElevators + cmp byte ptr [ecx + 16], 1 + pop ecx + + // Always elevate if SV_EnableEasyElevators is set to 1 + je elevate + + // Original code + cmp byte ptr [eax + 0x29], 0 + + // Original code flow + jz elevate + + push 0x5734FF + retn + + elevate: + push 0x57353D + retn + } + } + + __declspec(naked) void Elevators::PM_CheckDuckStub() + { + __asm + { + push eax + mov eax, Elevators::SV_EnableEasyElevators + cmp byte ptr [eax + 16], 1 + pop eax + + // Always stand if SV_EnableEasyElevators is set to 1 + je stand + + // Original code + cmp byte ptr [esp + 0x38], 0 + + // Original code flow + jnz noStand + + stand: + + push 0x570ED4 + retn + + noStand: + push 0x570EF4 + retn + } + } + + Elevators::Elevators() + { + Dvar::OnInit([] + { + Elevators::SV_EnableEasyElevators = Game::Dvar_RegisterBool("sv_enableEasyElevators", + false, Game::DVAR_FLAG_CHEAT | Game::DVAR_FLAG_REPLICATED, + "Enable easy elevators for trickshotting"); + }); + + Utils::Hook(0x5734F9, Elevators::PM_CorrectAllSolidStub, HOOK_JUMP).install()->quick(); + Utils::Hook::Nop(0x5734FE, 1); + + Utils::Hook(0x570ECD, Elevators::PM_CheckDuckStub, HOOK_JUMP).install()->quick(); + } + + Elevators::~Elevators() + { + } +} diff --git a/src/Components/Modules/Elevators.hpp b/src/Components/Modules/Elevators.hpp new file mode 100644 index 00000000..f5af25fd --- /dev/null +++ b/src/Components/Modules/Elevators.hpp @@ -0,0 +1,17 @@ +#pragma once + +namespace Components +{ + class Elevators : public Component + { + public: + Elevators(); + ~Elevators(); + + private: + static Game::dvar_t* SV_EnableEasyElevators; + + static void PM_CorrectAllSolidStub(); + static void PM_CheckDuckStub(); + }; +} From ed53211400d847ccdc88f04c142de3303ec848b5 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Mon, 29 Nov 2021 14:08:44 +0000 Subject: [PATCH 36/41] Comments as requested --- src/Components/Modules/Elevators.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Components/Modules/Elevators.cpp b/src/Components/Modules/Elevators.cpp index c8f5a14a..cd71382a 100644 --- a/src/Components/Modules/Elevators.cpp +++ b/src/Components/Modules/Elevators.cpp @@ -22,10 +22,12 @@ namespace Components // Original code flow jz elevate + // Go to conditional check for the loop push 0x5734FF retn elevate: + // Continue with loop execution push 0x57353D retn } @@ -50,11 +52,12 @@ namespace Components jnz noStand stand: - + // Player is allowed to stand push 0x570ED4 retn noStand: + // Player will remain ducked push 0x570EF4 retn } @@ -69,9 +72,11 @@ namespace Components "Enable easy elevators for trickshotting"); }); + // Place hook PM_CorrectAllSolid so we may skip PM_Trace check Utils::Hook(0x5734F9, Elevators::PM_CorrectAllSolidStub, HOOK_JUMP).install()->quick(); Utils::Hook::Nop(0x5734FE, 1); + // Place hook PM_CheckDuck so we may skip PM_Trace check Utils::Hook(0x570ECD, Elevators::PM_CheckDuckStub, HOOK_JUMP).install()->quick(); } From 79be9e12d5971308d8571b29428af6dd53ed94a0 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Mon, 29 Nov 2021 17:16:18 +0000 Subject: [PATCH 37/41] Add dvar to disable elevators entirely --- src/Components/Modules/Elevators.cpp | 44 ++++++++++++++++++++++++++-- src/Components/Modules/Elevators.hpp | 2 ++ 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/Components/Modules/Elevators.cpp b/src/Components/Modules/Elevators.cpp index cd71382a..a932782c 100644 --- a/src/Components/Modules/Elevators.cpp +++ b/src/Components/Modules/Elevators.cpp @@ -3,6 +3,7 @@ namespace Components { Game::dvar_t* Elevators::SV_EnableEasyElevators; + Game::dvar_t* Elevators::SV_DisableElevators; __declspec(naked) void Elevators::PM_CorrectAllSolidStub() { @@ -63,6 +64,39 @@ namespace Components } } + __declspec(naked) void Elevators::PM_GroundTraceStub() + { + __asm + { + push eax + mov eax, Elevators::SV_DisableElevators + cmp byte ptr [eax + 16], 1 + pop eax + + // Always skip PM_CorrectAllSolid if SV_DisableElevators is set to 1 + je noElevators + + // Original code + cmp byte ptr [esp + 0x50], 0 + rep movsd + mov esi, [esp + 0x58] + + // Original code flow + push 0x573694 + retn + + noElevators: + + // Original code + rep movsd + mov esi, [esp + 0x58] + + // Jump over call to PM_CorrectAllSolid + push 0x5736AE + retn + } + } + Elevators::Elevators() { Dvar::OnInit([] @@ -70,14 +104,20 @@ namespace Components Elevators::SV_EnableEasyElevators = Game::Dvar_RegisterBool("sv_enableEasyElevators", false, Game::DVAR_FLAG_CHEAT | Game::DVAR_FLAG_REPLICATED, "Enable easy elevators for trickshotting"); + Elevators::SV_DisableElevators = Game::Dvar_RegisterBool("sv_disableElevators", + false, Game::DVAR_FLAG_CHEAT | Game::DVAR_FLAG_REPLICATED, + "Disable elevators"); }); - // Place hook PM_CorrectAllSolid so we may skip PM_Trace check + // Hook PM_CorrectAllSolid so we may skip PM_Trace check Utils::Hook(0x5734F9, Elevators::PM_CorrectAllSolidStub, HOOK_JUMP).install()->quick(); Utils::Hook::Nop(0x5734FE, 1); - // Place hook PM_CheckDuck so we may skip PM_Trace check + // Hook PM_CheckDuck so we may skip PM_Trace check Utils::Hook(0x570ECD, Elevators::PM_CheckDuckStub, HOOK_JUMP).install()->quick(); + + // Hook PM_GroundTrace so me way skip PM_CorrectAllSolid (disable elevators) + Utils::Hook(0x573689, Elevators::PM_GroundTraceStub, HOOK_JUMP).install()->quick(); } Elevators::~Elevators() diff --git a/src/Components/Modules/Elevators.hpp b/src/Components/Modules/Elevators.hpp index f5af25fd..c01b2c98 100644 --- a/src/Components/Modules/Elevators.hpp +++ b/src/Components/Modules/Elevators.hpp @@ -10,8 +10,10 @@ namespace Components private: static Game::dvar_t* SV_EnableEasyElevators; + static Game::dvar_t* SV_DisableElevators; static void PM_CorrectAllSolidStub(); static void PM_CheckDuckStub(); + static void PM_GroundTraceStub(); }; } From bf9ea143333b9829925328e738f5b5778a18cf46 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Mon, 29 Nov 2021 18:22:21 +0000 Subject: [PATCH 38/41] One feature at the time --- src/Components/Modules/Elevators.cpp | 70 ---------------------------- src/Components/Modules/Elevators.hpp | 3 -- 2 files changed, 73 deletions(-) diff --git a/src/Components/Modules/Elevators.cpp b/src/Components/Modules/Elevators.cpp index a932782c..38c69282 100644 --- a/src/Components/Modules/Elevators.cpp +++ b/src/Components/Modules/Elevators.cpp @@ -2,68 +2,8 @@ namespace Components { - Game::dvar_t* Elevators::SV_EnableEasyElevators; Game::dvar_t* Elevators::SV_DisableElevators; - __declspec(naked) void Elevators::PM_CorrectAllSolidStub() - { - __asm - { - push ecx - mov ecx, Elevators::SV_EnableEasyElevators - cmp byte ptr [ecx + 16], 1 - pop ecx - - // Always elevate if SV_EnableEasyElevators is set to 1 - je elevate - - // Original code - cmp byte ptr [eax + 0x29], 0 - - // Original code flow - jz elevate - - // Go to conditional check for the loop - push 0x5734FF - retn - - elevate: - // Continue with loop execution - push 0x57353D - retn - } - } - - __declspec(naked) void Elevators::PM_CheckDuckStub() - { - __asm - { - push eax - mov eax, Elevators::SV_EnableEasyElevators - cmp byte ptr [eax + 16], 1 - pop eax - - // Always stand if SV_EnableEasyElevators is set to 1 - je stand - - // Original code - cmp byte ptr [esp + 0x38], 0 - - // Original code flow - jnz noStand - - stand: - // Player is allowed to stand - push 0x570ED4 - retn - - noStand: - // Player will remain ducked - push 0x570EF4 - retn - } - } - __declspec(naked) void Elevators::PM_GroundTraceStub() { __asm @@ -101,21 +41,11 @@ namespace Components { Dvar::OnInit([] { - Elevators::SV_EnableEasyElevators = Game::Dvar_RegisterBool("sv_enableEasyElevators", - false, Game::DVAR_FLAG_CHEAT | Game::DVAR_FLAG_REPLICATED, - "Enable easy elevators for trickshotting"); Elevators::SV_DisableElevators = Game::Dvar_RegisterBool("sv_disableElevators", false, Game::DVAR_FLAG_CHEAT | Game::DVAR_FLAG_REPLICATED, "Disable elevators"); }); - // Hook PM_CorrectAllSolid so we may skip PM_Trace check - Utils::Hook(0x5734F9, Elevators::PM_CorrectAllSolidStub, HOOK_JUMP).install()->quick(); - Utils::Hook::Nop(0x5734FE, 1); - - // Hook PM_CheckDuck so we may skip PM_Trace check - Utils::Hook(0x570ECD, Elevators::PM_CheckDuckStub, HOOK_JUMP).install()->quick(); - // Hook PM_GroundTrace so me way skip PM_CorrectAllSolid (disable elevators) Utils::Hook(0x573689, Elevators::PM_GroundTraceStub, HOOK_JUMP).install()->quick(); } diff --git a/src/Components/Modules/Elevators.hpp b/src/Components/Modules/Elevators.hpp index c01b2c98..73af502a 100644 --- a/src/Components/Modules/Elevators.hpp +++ b/src/Components/Modules/Elevators.hpp @@ -9,11 +9,8 @@ namespace Components ~Elevators(); private: - static Game::dvar_t* SV_EnableEasyElevators; static Game::dvar_t* SV_DisableElevators; - static void PM_CorrectAllSolidStub(); - static void PM_CheckDuckStub(); static void PM_GroundTraceStub(); }; } From a54d83945d3ee27eb6527fad4518e340b7c3488d Mon Sep 17 00:00:00 2001 From: FutureRave Date: Mon, 29 Nov 2021 18:36:23 +0000 Subject: [PATCH 39/41] Match sv_enableBounces dvar flags --- src/Components/Modules/Elevators.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Components/Modules/Elevators.cpp b/src/Components/Modules/Elevators.cpp index 38c69282..f297f48a 100644 --- a/src/Components/Modules/Elevators.cpp +++ b/src/Components/Modules/Elevators.cpp @@ -42,8 +42,7 @@ namespace Components Dvar::OnInit([] { Elevators::SV_DisableElevators = Game::Dvar_RegisterBool("sv_disableElevators", - false, Game::DVAR_FLAG_CHEAT | Game::DVAR_FLAG_REPLICATED, - "Disable elevators"); + false, Game::DVAR_FLAG_REPLICATED, "Disable elevators"); }); // Hook PM_GroundTrace so me way skip PM_CorrectAllSolid (disable elevators) From 759634833bf1ff3d44d02c4ba2f148953bb7c2e5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Dec 2021 17:19:13 +0000 Subject: [PATCH 40/41] Bump deps/libtommath from `8355b88` to `2cec6ad` Bumps [deps/libtommath](https://github.com/libtom/libtommath) from `8355b88` to `2cec6ad`. - [Release notes](https://github.com/libtom/libtommath/releases) - [Commits](https://github.com/libtom/libtommath/compare/8355b88db088e41d6f7e19a8d58d46c9ed0333d3...2cec6addaf4acbd8250611ec4cecadf1f4d655ee) --- updated-dependencies: - dependency-name: deps/libtommath dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- deps/libtommath | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/libtommath b/deps/libtommath index 8355b88d..2cec6add 160000 --- a/deps/libtommath +++ b/deps/libtommath @@ -1 +1 @@ -Subproject commit 8355b88db088e41d6f7e19a8d58d46c9ed0333d3 +Subproject commit 2cec6addaf4acbd8250611ec4cecadf1f4d655ee From e4b76a3d1fb283bc92d59e9a6450014e2f0e3456 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Thu, 2 Dec 2021 18:35:20 +0000 Subject: [PATCH 41/41] Remove random function call --- src/Components/Modules/Party.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Components/Modules/Party.cpp b/src/Components/Modules/Party.cpp index 527f5b8b..4d7bc515 100644 --- a/src/Components/Modules/Party.cpp +++ b/src/Components/Modules/Party.cpp @@ -151,7 +151,7 @@ namespace Components Party::Party() { static Game::dvar_t* partyEnable = Dvar::Register("party_enable", Dedicated::IsEnabled(), Game::dvar_flag::DVAR_FLAG_NONE, "Enable party system").get(); - Dvar::Register("xblive_privatematch", true, Game::dvar_flag::DVAR_FLAG_WRITEPROTECTED, "").get(); + Dvar::Register("xblive_privatematch", true, Game::dvar_flag::DVAR_FLAG_WRITEPROTECTED, ""); // various changes to SV_DirectConnect-y stuff to allow non-party joinees Utils::Hook::Set(0x460D96, 0x90E9);