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