Merge branch 'develop' into develop

This commit is contained in:
Vlad 2022-11-07 13:52:23 +03:00 committed by GitHub
commit 7765668efa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 238 additions and 255 deletions

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -0,0 +1 @@
require("unlockall")

View 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

View File

@ -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": "ﺢﺘﻔﻟﺍ ءﺎﻐﻟﺇ"
}

View File

@ -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",

View File

@ -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.",

View File

@ -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"
}

View File

@ -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",

View File

@ -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": "アンロックをキャンセル"
}

View File

@ -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": "アンロックをキャンセル"
}

View File

@ -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": "잠금 해제 취소"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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.",

View File

@ -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.",

View File

@ -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": "取消解锁"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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

@ -1 +1 @@
Subproject commit c52bad36aa9d5ececcdf6be2d5cd2dce9daa4194
Subproject commit d69e578519840b9b74eff26ac01465ac07698063

2
deps/libtommath vendored

@ -1 +1 @@
Subproject commit 96f9edf9aaf145c6ecf5225eea3f5e86a0f26935
Subproject commit 03de03dee753442d4b23166982514639c4ccbc39

2
deps/lua vendored

@ -1 +1 @@
Subproject commit 26be27459b11feabed52cf40aaa76f86c7edc977
Subproject commit c954db39241a8b21d7b32b42b87a066b4708f969

View File

@ -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'}

View File

@ -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)

View File

@ -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()

View File

@ -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);

View File

@ -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)

View File

@ -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 + "\"";

View File

@ -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);

View File

@ -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();

View File

@ -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;

View File

@ -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;

View File

@ -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,

View File

@ -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>())

View File

@ -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);
}

View File

@ -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.

Binary file not shown.