Merge branch 'develop' into refactor-movement

This commit is contained in:
Edo 2022-02-05 17:27:22 +01:00 committed by GitHub
commit 50c5793432
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 253 additions and 763 deletions

View File

@ -12,7 +12,7 @@ on:
jobs:
build:
name: Build binaries
runs-on: windows-latest
runs-on: windows-2022
strategy:
matrix:
configuration:
@ -36,11 +36,11 @@ jobs:
lfs: false
- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1.0.2
uses: microsoft/setup-msbuild@v1.1
- name: Generate project files
#run: tools/premake5 vs2019 --ci-build
run: tools/premake5 vs2019 --ac-disable
#run: tools/premake5 vs2022 --ci-build --ac-disable
run: tools/premake5 vs2022 --ac-disable
- name: Set up problem matching
uses: ammaraskar/msvc-problem-matcher@master

2
.gitmodules vendored
View File

@ -25,7 +25,7 @@
[submodule "deps/protobuf"]
path = deps/protobuf
url = https://github.com/google/protobuf.git
branch = 3.11.x
branch = 3.17.x
[submodule "deps/udis86"]
path = deps/udis86
url = https://github.com/vmt/udis86.git

317
Jenkinsfile vendored
View File

@ -1,317 +0,0 @@
#!groovy
/*
This is our new pipeline script to do all of the building in, of and around IW4x.
Here's what it is supposed to do:
- Make sure Modern Warfare 2 is installed (CI should provide the folder like a custom tool)
- Check out code from iw4x-data
- Build the IW4x client library (this code repository)
- Use iw4x.exe from the iw4x-data repository in order to build the zone files in iw4x-data
- Package the IW4x client with the newly built data files
At this point it is done building everything, however afterwards we want the build server to
also push the newly built files to an update repository, depending on the branch we're on.
- For "develop", release to the "iw4x-dev" branch on the repository server.
- For "master", release to the "iw4x" branch on the repository server.
I'm looking into how the logic of pipelining works in detail before deciding on whether to
throw in the IW4x Updater and the IW4x Node binaries in as well or not.
*/
/*
Note that this is just a rewrite of the jobs as they are currently set up on the production
Jenkins server. This will allow every developer to tinker around with how the build process
is set up. For those who want to play around with this, here's a bit of information:
- This is a Groovy script. Essentially Java but with less bullshit (like brackets and verbose writing).
- This gets directly translated into a Jenkins pipeline.
- If you have no idea how to handle scripts, get your hands off this file.
- If you do not use Jenkins, get your hands off this file.
- If you fuck this script up, I will kill you.
*/
import groovy.transform.Field
@Field def configurations = [
"Debug": [
WorkspaceID: "build@debug",
StashName: "iw4x-debug",
MSBuildConfiguration: "Debug",
PremakeArgs: "",
Archive: true,
],
"Release": [
WorkspaceID: "build@release",
StashName: "iw4x-release",
MSBuildConfiguration: "Release",
PremakeArgs: "",
Archive: true,
],
"Release with unit tests": [
WorkspaceID: "build@release+unittests",
StashName: "iw4x-release-unittests",
MSBuildConfiguration: "Release",
PremakeArgs: "--force-unit-tests",
Archive: false,
],
].collect {k, v -> [k, v]}
@Field def testing = [
"Debug": [
WorkspaceID: "testing@debug",
StashName: "iw4x-debug",
],
"Release": [
WorkspaceID: "testing@release",
StashName: "iw4x-release-unittests",
],
].collect {k, v -> [k, v]}
def jobWorkspace(id, f) {
ws("workspace/${env.JOB_NAME.replaceAll(/[%$]/, "_")}@$id", f)
}
def useShippedPremake(f) {
def premakeHome = "${pwd()}\\tools"
withEnv(["PATH+=${premakeHome}"], f)
}
def getIW4xExecutable() {
step([
$class: 'CopyArtifact',
filter: '*',
fingerprintArtifacts: true,
projectName: 'iw4x/iw4x-executable/' + iw4xExecutableBranch(),
selector: [
$class: 'TriggeredBuildSelector',
allowUpstreamDependencies: false,
fallbackToLastSuccessful: true,
upstreamFilterStrategy: 'UseGlobalSetting'
]
])
}
// This will build the IW4x client.
// We need a Windows Server with Visual Studio 2015, Premake5 and Git on it.
def doBuild(cfg) {
retry(5) {
checkout scm
}
useShippedPremake {
def outputDir = pwd()
def msbuild = tool "Microsoft.NET MSBuild 15.0"
bat "premake5 vs2017 ${cfg.PremakeArgs}"
bat "\"${msbuild}\" build\\iw4x.sln \"/p:OutDir=$outputDir\\\\\" \"/p:Configuration=${cfg.MSBuildConfiguration}\""
}
stash name: "${cfg.StashName}", includes: "*.dll,*.pdb"
}
// This will run the unit tests for IW4x.
// We need a Windows Server with MW2 on it.
def doUnitTests(name) {
mw2dir = tool "Modern Warfare 2"
unstash "$name"
// Get installed localization for correct zonefiles directory junction
def localization = readFile("${tool "Modern Warfare 2"}/localization.txt").split("\r?\n")[0]
try {
timeout(time: 10, unit: "MINUTES") {
// Set up environment
if (isUnix()) {
def mw2dir = tool "Modern Warfare 2"
sh """
mkdir -p zone
for f in main zone/dlc \"zone/$localization\"; do
ln -sfv \"$mw2dir/\$f\" \"\$f\"
done
for f in \"$mw2dir\"/*.dll \"$mw2dir\"/*.txt \"$mw2dir\"/*.bmp; do
ln -sfv \"\$f\" \"\$(basename \"\$f\")\"
done
"""
} else {
def mw2dir = tool "Modern Warfare 2"
bat """
mklink /J \"main\" \"$mw2dir\\main\"
mkdir \"zone\"
mklink /J \"zone\\dlc\" \"$mw2dir\\zone\\dlc\"
mklink /J \"zone\\$localization\" \"$mw2dir\\zone\\$localization\"
copy /y \"$mw2dir\\*.dll\"
copy /y \"$mw2dir\\*.txt\"
copy /y \"$mw2dir\\*.bmp\"
"""
}
// Run tests
getIW4xExecutable()
retry(2) {
if (isUnix()) {
sh "WINEDEBUG=warn+all wine iw4x.exe -tests; wineserver -w"
} else {
bat "iw4x.exe -tests"
}
}
}
} catch (org.jenkinsci.plugins.workflow.steps.FlowInterruptedException e) {
currentBuild.result = 'UNSTABLE'
println("${name} unit test interrupted (ran too long?)")
} catch (Exception e) {
println("${name} unit test failed.")
if (isUnix()) {
currentBuild.result = 'UNSTABLE'
} else {
throw e
}
} finally {
// In all cases make sure to at least remove the directory junctions!
if (!isUnix()) {
bat """
rmdir \"main\"
rmdir \"zone\\dlc\"
rmdir \"zone\\$localization\"
"""
}
deleteDir()
}
}
// Returns the IW4x executable branch to use
def iw4xExecutableBranch() {
try {
return IW4X_EXECUTABLE_BRANCH;
} catch(MissingPropertyException) {
return "master";
}
}
// Job properties
properties([
buildDiscarder(logRotator(artifactDaysToKeepStr: '', artifactNumToKeepStr: '', daysToKeepStr: '', numToKeepStr: '30')),
disableConcurrentBuilds(),
gitLabConnection('iw4x'),
[$class: 'LeastLoadDisabledProperty', leastLoadDisabled: false]
])
gitlabBuilds(builds: ["Checkout & Versioning", "Build", "Testing", "Archiving"]) {
// First though let's give this build a proper name
stage("Checkout & Versioning") {
gitlabCommitStatus(name: "Checkout & Versioning") {
node("windows") {
jobWorkspace("versioning") {
if (env.BRANCH_NAME == 'master')
{
echo 'Reset build environment'
deleteDir()
}
retry(5) {
checkout scm
}
useShippedPremake {
def version = bat(returnStdout: true, script: '@premake5 version').split("\r?\n")[2]
currentBuild.setDisplayName "$version (#${env.BUILD_NUMBER})"
}
stash name: "jenkins-files", includes: "jenkins/**"
}
}
}
}
// For each available configuration generate a normal build and a unit test build.
stage("Build") {
gitlabCommitStatus(name: "Build") {
def executions = [:]
for (int i = 0; i < configurations.size(); i++) {
def entry = configurations[i]
def configName = entry[0]
def config = entry[1]
executions[configName] = {
node("windows") {
jobWorkspace(config.WorkspaceID) {
doBuild(config)
}
}
}
}
parallel executions
}
}
// Run unit tests on each configuration.
stage("Testing") {
gitlabCommitStatus(name: "Testing") {
executions = [:]
for (int i = 0; i < testing.size(); i++) {
def entry = testing.get(i)
def testName = entry[0]
def test = entry[1]
executions["$testName on Windows"] = {
node("windows") {
jobWorkspace(test.WorkspaceID) {
doUnitTests(test.StashName)
}
}
}
executions["$testName on Linux"] = {
node("docker && linux && amd64") {
timeout(time: 10, unit: "MINUTES") {
wrap([$class: 'AnsiColorBuildWrapper', 'colorMapName': 'XTerm']) {
def image = null
dir("src") {
unstash "jenkins-files"
image = docker.build("github.com/IW4x/iw4x-client-testing-wine32", "--rm --force-rm -f jenkins/wine32.Dockerfile jenkins")
deleteDir()
}
image.inside {
doUnitTests(test.StashName)
}
}
}
}
}
parallel executions
}
}
}
// Collect all the binaries and give each configuration its own subfolder
stage("Archiving") {
gitlabCommitStatus(name: "Archiving") {
node("windows") { // any node will do
jobWorkspace("archiving") {
try {
for (int i = 0; i < configurations.size(); i++) {
def entry = configurations[i]
def configName = entry[0]
def config = entry[1]
if (config.Archive) {
dir(configName) {
unstash config.StashName
}
}
}
archiveArtifacts artifacts: "**/*.dll,**/*.pdb", fingerprint: true
} finally {
deleteDir()
}
}
}
}
}
}

View File

@ -11,8 +11,8 @@
## How to compile
- Run `premake5 vs2019` or use the delivered `generate.bat`.
- Build via solution file in `build\iw4x.sln`. (You can use the `build.bat` script to do it quick and easy.)
- Run `premake5 vs2022` or use the delivered `generate.bat`.
- Build via solution file in `build\iw4x.sln`.
## Premake arguments
@ -33,24 +33,22 @@
## Command line arguments
| Argument | Description |
|:----------------------------|:-----------------------------------------------|
| `-tests` | Perform unit tests. |
| `-entries` | Prints fast file info to the console. |
| `-stdout` | Redirect stdout to the external console. |
| `-console` | Enables external console. |
| `-dedicated` | Dedicated server. |
| `-scriptablehttp` | Adds HTTP console commands. |
| `-bigdumps` | Enables dumps. |
| `-reallybigdumps` | Unused. |
| `-bigminidumps` | Mini dumps. |
| `-reallybigminidumps` | Big mini dumps. |
| `-dump` | Prints asset info to a .ents file. |
| `-monitor` | Enables monitor. |
| `-nointro` | Skips game's intro. |
| `-version` | Prints IW4X version. |
| `-zonebuilder` | Enables zone builder. |
| `-nosteam` | Disables Steam features. |
| Argument | Description |
|:------------------------|:-----------------------------------------------|
| `-tests` | Perform unit tests. |
| `-entries` | Print to the console a list of every asset as they are loaded from zonefiles. |
| `-stdout` | Redirect all logging output to the terminal iw4x is started from, or if there is none, creates a new terminal window to write log information in. |
| `-console` | Allow the game to display its own separate interactive console window. |
| `-dedicated` | Starts the game as a headless dedicated server. |
| `-scriptablehttp` | Enable HTTP related gsc functions. |
| `-bigminidumps` | Include all code sections from loaded modules in the dump. |
| `-reallybigminidumps` | Include data sections from all loaded modules in the dump. |
| `-dump` | Write info of loaded assets to the raw folder as they are being loaded. |
| `-monitor` | This flag is for internal use and it is used to indicate if an external console is present. |
| `-nointro` | Skip game's cinematic intro. |
| `-version` | Print IW4x build info on startup. |
| `-zonebuilder` | Start the interactive zonebuilder tool console instead of starting the game. |
| `-nosteam` | Disable friends feature and do not update Steam about the game's current status just like an invisible mode. |
## Disclaimer

View File

@ -4,8 +4,8 @@ version: "#{build} ({branch})"
environment:
matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
PREMAKE_ACTION: vs2019
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2022
PREMAKE_ACTION: vs2022
configuration:
- Debug

View File

@ -1,24 +0,0 @@
@echo off & setlocal
cd %~dp0
if exist "%PROGRAMFILES(x86)%\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\VsMSBuildCmd.bat" call "%PROGRAMFILES(x86)%\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\VsMSBuildCmd.bat"
call msbuild /version >NUL 2>NUL
if errorlevel 0 goto:build
if exist "%PROGRAMFILES(x86)%\Microsoft Visual Studio\2019\Enterprise\MSBuild\15.0\Bin\msbuild.exe" path %PROGRAMFILES(x86)%\Microsoft Visual Studio\2019\Enterprise\MSBuild\15.0\Bin;%PATH%
call msbuild /version >NUL 2>NUL
if errorlevel 0 goto:build
echo Couldn't find any MSBuild to build this project.
echo Make sure you have Visual C++ Build Tools 2019 or Visual Studio 2019 installed.
endlocal
exit /B 1
:build
call generate.bat
set PLATFORM=Win32
set CONFIGURATION=Release
call msbuild /nologo /m /v:m %* build\iw4x.sln
endlocal
exit /B %ERRORLEVEL%

2
deps/pdcurses vendored

@ -1 +1 @@
Subproject commit f1cd4f4569451a5028ddf3d3c202f0ad6b1ae446
Subproject commit 2fa0f10dd844da47ee83c05a40a1ec541ceb95e1

2
deps/protobuf vendored

@ -1 +1 @@
Subproject commit df2bce345d4bc8cdc3eba2a866e11e79e1fff4df
Subproject commit 5500c72c5b616da9f0125bcfab513987a1226e2b

2
deps/zlib vendored

@ -1 +1 @@
Subproject commit c3f3043f7aa80750245f8166a338c4877020b589
Subproject commit 2014a993addbc8f1b9785d97f55fd189792c2f78

View File

@ -1,4 +1,4 @@
@echo off
echo Updating submodules...
call git submodule update --init --recursive
call tools\premake5 %* vs2019 --ac-disable
call tools\premake5 %* vs2022 --ac-disable

View File

@ -1,46 +0,0 @@
# Requires a decent modern Docker version (v1.10.x at least ideally)
# Use semi-official Arch Linux image with fixed versioning
FROM archlinux/base
# Environment variables
ENV WINEPREFIX /wine32
ENV WINEARCH win32
ENV WINEDEBUG -all
# Install Wine (32-bit)
RUN \
echo -e "#!/bin/sh\nwine \$@\nretval=\$?\nwineserver -w\nexit \$retval" > /usr/local/bin/wine-wrapper &&\
chmod +x /usr/local/bin/wine-wrapper &&\
\
(\
echo '' &&\
echo '[multilib]' &&\
echo 'Include = /etc/pacman.d/mirrorlist'\
) >> /etc/pacman.conf &&\
pacman -Sy --noconfirm \
awk \
lib32-gnutls \
wine \
wget \
xorg-server-xvfb \
pacman-contrib \
awk \
&&\
\
wine-wrapper wineboot.exe -i &&\
wget -Ovcredist_x86.exe https://download.microsoft.com/download/d/d/9/dd9a82d0-52ef-40db-8dab-795376989c03/vcredist_x86.exe &&\
WINEDEBUG=+all-trace xvfb-run sh -c 'wine-wrapper vcredist_x86.exe /q' &&\
rm vcredist_x86.exe &&\
\
pacman -Rs --noconfirm \
xorg-server-xvfb \
wget \
&&\
\
find /. -name "*~" -type f -delete &&\
rm -rf /tmp/* /var/tmp/* /usr/share/man/* /usr/share/info/* /usr/share/doc/* &&\
pacman -Scc --noconfirm &&\
rm -rf /var/lib/pacman/sync/*
USER 0

View File

@ -1,54 +0,0 @@
iw4mvm = {
settings = nil
}
function iw4mvm.setup(settings)
if not settings.source then error("Missing source.") end
iw4mvm.settings = settings
if not iw4mvm.settings.defines then iw4mvm.settings.defines = {} end
end
function iw4mvm.import()
if not iw4mvm.settings then error("You need to call iw4mvm.setup first") end
links { "iw4mvm" }
iw4mvm.includes()
end
function iw4mvm.includes()
if not iw4mvm.settings then error("You need to call iw4mvm.setup first") end
includedirs { iw4mvm.settings.source }
libdirs { path.join(iw4mvm.settings.source, "IW4MVM") }
defines(iw4mvm.settings.defines)
end
function iw4mvm.project()
if not iw4mvm.settings then error("You need to call iw4mvm.setup first") end
project "iw4mvm"
language "C++"
characterset ("MBCS")
defines("_CRT_SECURE_NO_WARNINGS")
iw4mvm.includes()
files
{
path.join(iw4mvm.settings.source, "IW4MVM/*.h"),
path.join(iw4mvm.settings.source, "IW4MVM/*.cpp"),
}
removefiles
{
--path.join(iw4mvm.settings.source, "IW4MVM/detours.cpp"),
path.join(iw4mvm.settings.source, "IW4MVM/DllMain.cpp"),
}
-- not our code, ignore POSIX usage warnings for now
warnings "Off"
kind "StaticLib"
end

View File

@ -193,7 +193,6 @@ require "premake/pdcurses"
require "premake/protobuf"
require "premake/zlib"
require "premake/udis86"
require "premake/iw4mvm"
require "premake/dxsdk"
json11.setup
@ -240,15 +239,6 @@ udis86.setup
{
source = path.join(depsBasePath, "udis86"),
}
iw4mvm.setup
{
defines = {
"IW4X",
"DETOURS_X86",
"DETOURS_32BIT",
},
source = path.join(depsBasePath, "iw4mvm"),
}
dxsdk.setup
{
source = path.join(depsBasePath, "dxsdk"),
@ -260,34 +250,44 @@ workspace "iw4x"
objdir "%{wks.location}/obj"
targetdir "%{wks.location}/bin/%{cfg.buildcfg}"
buildlog "%{wks.location}/obj/%{cfg.architecture}/%{cfg.buildcfg}/%{prj.name}/%{prj.name}.log"
configurations { "Debug", "Release" }
language "C++"
cppdialect "C++17"
architecture "x86"
platforms "x86"
--exceptionhandling ("SEH")
systemversion "latest"
symbols "On"
staticruntime "On"
editandcontinue "Off"
warnings "Extra"
characterset "ASCII"
configuration "windows"
defines { "_WINDOWS", "WIN32" }
flags { "NoIncrementalLink", "NoMinimalRebuild", "MultiProcessorCompile", "No64BitChecks" }
configuration "Release*"
defines { "NDEBUG" }
flags { "MultiProcessorCompile", "LinkTimeOptimization", "No64BitChecks" }
filter "platforms:x86"
defines {"_WINDOWS", "WIN32"}
filter {}
filter "configurations:Release"
optimize "On"
buildoptions { "/GL" }
linkoptions { "/IGNORE:4702", "/LTCG" }
defines { "NDEBUG" }
flags { "FatalCompileWarnings", "FatalLinkWarnings" }
if not _OPTIONS["force-unit-tests"] then
rtti ("Off")
end
filter {}
configuration "Debug*"
defines { "DEBUG", "_DEBUG" }
flags { "MultiProcessorCompile", "No64BitChecks" }
filter "configurations:Debug"
optimize "Debug"
if symbols ~= nil then
symbols "On"
else
flags { "Symbols" }
end
defines { "DEBUG", "_DEBUG" }
filter {}
project "iw4x"
kind "SharedLib"
@ -347,7 +347,6 @@ workspace "iw4x"
protobuf.import()
zlib.import()
udis86.import()
--iw4mvm.import()
dxsdk.import()
-- fix vpaths for protobuf sources
@ -401,23 +400,6 @@ workspace "iw4x"
}
end
-- Specific configurations
flags { "UndefinedIdentifiers" }
warnings "Extra"
if symbols ~= nil then
symbols "On"
else
flags { "Symbols" }
end
configuration "Release*"
flags {
"FatalCompileWarnings",
"FatalLinkWarnings",
}
configuration {}
--[[
-- Generate source code from protobuf definitions
rules { "ProtobufCompiler" }
@ -461,11 +443,6 @@ workspace "iw4x"
protobuf.project()
zlib.project()
udis86.project()
--iw4mvm.project()
workspace "*"
cppdialect "C++17"
defines { "_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS" }
rule "ProtobufCompiler"
display "Protobuf compiler"

View File

@ -48,9 +48,6 @@ namespace Components
Loader::Register(new Party());
Loader::Register(new Zones());
Loader::Register(new D3D9Ex());
#if (!defined(VLD_RPTHOOK_INSTALL) || defined(VLDEnable)) && defined(COMPILE_IW4MVM) // IW4MVM uses detours which produces memory leaks, but those are not really relevant
Loader::Register(new IW4MVM());
#endif
Loader::Register(new Logger());
Loader::Register(new Script());
Loader::Register(new Weapon());

View File

@ -88,7 +88,6 @@ namespace Components
#include "Modules/Node.hpp"
#include "Modules/RCon.hpp"
#include "Modules/Party.hpp" // Destroys the order, but requires network classes :D
#include "Modules/IW4MVM.hpp"
#include "Modules/Logger.hpp"
#include "Modules/Friends.hpp"
#include "Modules/IPCPipe.hpp"

View File

@ -634,7 +634,7 @@ namespace Components
LUID luid;
TOKEN_PRIVILEGES tp = { 0 };
DWORD cb = sizeof(TOKEN_PRIVILEGES);
if (!LookupPrivilegeValueW(nullptr, SE_DEBUG_NAME, &luid)) return;
if (!LookupPrivilegeValueA(nullptr, SE_DEBUG_NAME, &luid)) return;
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;

View File

@ -3,7 +3,7 @@
namespace Components
{
thread_local int AssetHandler::BypassState = 0;
bool AssetHandler::ShouldSearchTempAssets = false;
bool AssetHandler::ShouldSearchTempAssets = false;
std::map<Game::XAssetType, AssetHandler::IAsset*> AssetHandler::AssetInterfaces;
std::map<Game::XAssetType, Utils::Slot<AssetHandler::Callback>> AssetHandler::TypeCallbacks;
Utils::Signal<AssetHandler::RestrictCallback> AssetHandler::RestrictSignal;
@ -70,20 +70,20 @@ namespace Components
return header;
}
Game::XAssetHeader AssetHandler::FindTemporaryAsset(Game::XAssetType type, const char* filename)
{
Game::XAssetHeader header = { nullptr };
if (type >= Game::XAssetType::ASSET_TYPE_COUNT) return header;
Game::XAssetHeader AssetHandler::FindTemporaryAsset(Game::XAssetType type, const char* filename)
{
Game::XAssetHeader header = { nullptr };
if (type >= Game::XAssetType::ASSET_TYPE_COUNT) return header;
auto tempPool = &AssetHandler::TemporaryAssets[type];
auto entry = tempPool->find(filename);
if (entry != tempPool->end())
{
header = { entry->second };
}
auto tempPool = &AssetHandler::TemporaryAssets[type];
auto entry = tempPool->find(filename);
if (entry != tempPool->end())
{
header = { entry->second };
}
return header;
}
return header;
}
int AssetHandler::HasThreadBypass()
{
@ -119,7 +119,6 @@ namespace Components
push esi
push edi
push eax
pushad
@ -130,14 +129,12 @@ namespace Components
popad
pop eax
test al, al
jnz checkTempAssets
mov ecx, [esp + 18h] // Asset type
mov ebx, [esp + 1Ch] // Filename
push eax
pushad
@ -152,31 +149,30 @@ namespace Components
popad
pop eax
test eax, eax
jnz finishFound
checkTempAssets:
mov al, AssetHandler::ShouldSearchTempAssets // check to see if enabled
test eax, eax
jz finishOriginal
mov ecx, [esp + 18h] // Asset type
mov ebx, [esp + 1Ch] // Filename
push ebx
push ecx
call AssetHandler::FindTemporaryAsset
add esp, 8h
test eax, eax
jnz finishFound
checkTempAssets:
mov al, AssetHandler::ShouldSearchTempAssets // check to see if enabled
test eax, eax
jz finishOriginal
mov ecx, [esp + 18h] // Asset type
mov ebx, [esp + 1Ch] // Filename
push ebx
push ecx
call AssetHandler::FindTemporaryAsset
add esp, 8h
test eax, eax
jnz finishFound
finishOriginal:
finishOriginal:
// Asset not found using custom handlers or in temp assets or bypasses were enabled
// redirect to DB_FindXAssetHeader
// redirect to DB_FindXAssetHeader
mov ebx, ds:6D7190h // InterlockedDecrement
mov eax, 40793Bh
jmp eax
@ -546,10 +542,10 @@ namespace Components
for (int i = 0; i < vertexdecl->streamCount; i++)
{
routingData.push_back(json11::Json::object
{
{ "source", (int)vertexdecl->routing.data[i].source },
{ "dest", (int)vertexdecl->routing.data[i].dest },
});
{
{ "source", (int)vertexdecl->routing.data[i].source },
{ "dest", (int)vertexdecl->routing.data[i].dest },
});
}
std::vector<json11::Json> declData;
@ -770,7 +766,7 @@ namespace Components
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_LEADERBOARD, 500);
AssetHandler::RegisterInterface(new Assets::IFont_s());
AssetHandler::RegisterInterface(new Assets::IWeapon());
AssetHandler::RegisterInterface(new Assets::IWeapon());
AssetHandler::RegisterInterface(new Assets::IXModel());
AssetHandler::RegisterInterface(new Assets::IFxWorld());
AssetHandler::RegisterInterface(new Assets::IMapEnts());
@ -781,9 +777,9 @@ namespace Components
AssetHandler::RegisterInterface(new Assets::ISndCurve());
AssetHandler::RegisterInterface(new Assets::IMaterial());
AssetHandler::RegisterInterface(new Assets::IMenuList());
AssetHandler::RegisterInterface(new Assets::IclipMap_t());
AssetHandler::RegisterInterface(new Assets::IclipMap_t());
AssetHandler::RegisterInterface(new Assets::ImenuDef_t());
AssetHandler::RegisterInterface(new Assets::ITracerDef());
AssetHandler::RegisterInterface(new Assets::ITracerDef());
AssetHandler::RegisterInterface(new Assets::IPhysPreset());
AssetHandler::RegisterInterface(new Assets::IXAnimParts());
AssetHandler::RegisterInterface(new Assets::IFxEffectDef());

View File

@ -39,13 +39,13 @@ namespace Components
static void ResetBypassState();
static void ExposeTemporaryAssets(bool expose);
static void ExposeTemporaryAssets(bool expose);
static void OffsetToAlias(Utils::Stream::Offset* offset);
private:
static thread_local int BypassState;
static bool ShouldSearchTempAssets;
static bool ShouldSearchTempAssets;
static std::map<std::string, Game::XAssetHeader> TemporaryAssets[Game::XAssetType::ASSET_TYPE_COUNT];
@ -60,7 +60,7 @@ namespace Components
static void RegisterInterface(IAsset* iAsset);
static Game::XAssetHeader FindAsset(Game::XAssetType type, const char* filename);
static Game::XAssetHeader FindTemporaryAsset(Game::XAssetType type, const char* filename);
static Game::XAssetHeader FindTemporaryAsset(Game::XAssetType type, const char* filename);
static bool IsAssetEligible(Game::XAssetType type, Game::XAssetHeader* asset);
static void FindAssetStub();
static void AddAssetStub();

View File

@ -136,6 +136,41 @@ namespace Components
Game::SV_GameSendServerCommand(entNum, 0, Utils::String::VA("%c \"%s\"", 0x65,
(ent->flags & Game::FL_NOTARGET) ? "GAME_NOTARGETON" : "GAME_NOTARGETOFF"));
});
ClientCommand::Add("setviewpos", [](Game::gentity_s* ent)
{
assert(ent != nullptr);
if (!ClientCommand::CheatsOk(ent))
return;
Command::ServerParams params = {};
Game::vec3_t origin, angles{0.f, 0.f, 0.f};
if (params.length() < 4u || params.length() > 6u)
{
Game::SV_GameSendServerCommand(ent->s.number, 0,
Utils::String::VA("%c \"GAME_USAGE\x15: setviewpos x y z [yaw] [pitch]\n\"", 0x65));
return;
}
for (auto i = 0; i < 3; i++)
{
origin[i] = std::strtof(params.get(i + 1), nullptr);
}
if (params.length() >= 5u)
{
angles[1] = std::strtof(params.get(4), nullptr); // Yaw
}
if (params.length() == 6u)
{
angles[0] = std::strtof(params.get(5), nullptr); // Pitch
}
Game::TeleportPlayer(ent, origin, angles);
});
}
void ClientCommand::AddScriptFunctions()

View File

@ -18,14 +18,14 @@ namespace Components
return result;
}
char* Command::Params::operator[](size_t index)
const char* Command::Params::operator[](size_t index)
{
return this->get(index);
}
char* Command::ClientParams::get(size_t index)
const char* Command::ClientParams::get(size_t index)
{
if (index >= this->length()) return const_cast<char*>("");
if (index >= this->length()) return "";
return Game::cmd_argv[this->commandId][index];
}
@ -34,9 +34,9 @@ namespace Components
return Game::cmd_argc[this->commandId];
}
char* Command::ServerParams::get(size_t index)
const char* Command::ServerParams::get(size_t index)
{
if (index >= this->length()) return const_cast<char*>("");
if (index >= this->length()) return "";
return Game::cmd_argv_sv[this->commandId][index];
}
@ -160,52 +160,6 @@ namespace Components
{
AssertSize(Game::cmd_function_t, 24);
static int toastDurationShort = 1000;
static int toastDurationMedium = 2500;
static int toastDurationLong = 5000;
Command::Add("setviewpos", [](Command::Params* params)
{
int clientNum = Game::CG_GetClientNum();
if (!Game::CL_IsCgameInitialized() || clientNum >= 18 || clientNum < 0 || !Game::g_entities[clientNum].client)
{
Logger::Print("You are not hosting a match!\n");
Toast::Show("cardicon_stop", "Error", "You are not hosting a match!", toastDurationMedium);
return;
}
if (!Dvar::Var("sv_cheats").get<bool>())
{
Logger::Print("Cheats disabled!\n");
Toast::Show("cardicon_stop", "Error", "Cheats disabled!", toastDurationMedium);
return;
}
if (params->length() != 4 && params->length() != 6)
{
Logger::Print("Invalid coordinate specified!\n");
Toast::Show("cardicon_stop", "Error", "Invalid coordinate specified!", toastDurationMedium);
return;
}
float pos[3] = { 0.0f, 0.0f, 0.0f };
float orientation[3] = { 0.0f, 0.0f, 0.0f };
pos[0] = strtof(params->get(1), nullptr);
pos[1] = strtof(params->get(2), nullptr);
pos[2] = strtof(params->get(3), nullptr);
if (params->length() == 6)
{
orientation[0] = strtof(params->get(4), nullptr);
orientation[1] = strtof(params->get(5), nullptr);
}
Game::TeleportPlayer(&Game::g_entities[clientNum], pos, orientation);
// Logging will spam the console and screen if people use cinematics
});
Command::Add("openLink", [](Command::Params* params)
{
if (params->length() > 1)

View File

@ -10,11 +10,11 @@ namespace Components
public:
Params() {};
virtual ~Params() {};
virtual char* get(size_t index) = 0;
virtual const char* get(size_t index) = 0;
virtual size_t length() = 0;
virtual std::string join(size_t startIndex);
virtual char* operator[](size_t index);
virtual const char* operator[](size_t index);
};
class ClientParams : public Params
@ -24,7 +24,7 @@ namespace Components
ClientParams(const ClientParams &obj) : commandId(obj.commandId) {};
ClientParams() : ClientParams(*Game::cmd_id) {};
char* get(size_t index) override;
const char* get(size_t index) override;
size_t length() override;
private:
@ -38,7 +38,7 @@ namespace Components
ServerParams(const ServerParams &obj) : commandId(obj.commandId) {};
ServerParams() : ServerParams(*Game::cmd_id_sv) {};
char* get(size_t index) override;
const char* get(size_t index) override;
size_t length() override;
private:

View File

@ -273,6 +273,11 @@ namespace Components
}
}
Game::dvar_t* Dedicated::Dvar_RegisterSVNetworkFps(const char* dvarName, int, int min, int, int, const char* description)
{
return Game::Dvar_RegisterInt(dvarName, 1000, min, 1000, Game::dvar_flag::DVAR_FLAG_NONE, description);
}
Dedicated::Dedicated()
{
// Map rotation
@ -311,7 +316,7 @@ namespace Components
Utils::Hook::Nop(0x4DCEC9, 2); // some check preventing proper game functioning
Utils::Hook::Nop(0x507C79, 6); // another similar bsp check
Utils::Hook::Nop(0x414E4D, 6); // unknown check in SV_ExecuteClientMessage (0x20F0890 == 0, related to client->f_40)
Utils::Hook::Nop(0x414E4D, 6); // cl->messageAcknowledge > cl->gamestateMessageNum check in SV_ExecuteClientMessage
Utils::Hook::Nop(0x4DCEE9, 5); // some deinit renderer function
Utils::Hook::Nop(0x59A896, 5); // warning message on a removed subsystem
Utils::Hook::Nop(0x4B4EEF, 5); // same as above
@ -326,14 +331,8 @@ namespace Components
// isHost script call return 0
Utils::Hook::Set<DWORD>(0x5DEC04, 0);
// sv_network_fps max 1000, and uncheat
Utils::Hook::Set<BYTE>(0x4D3C67, 0); // ?
Utils::Hook::Set<DWORD>(0x4D3C69, 1000);
// Manually register sv_network_fps
Utils::Hook::Nop(0x4D3C7B, 5);
Utils::Hook::Nop(0x4D3C8E, 5);
*reinterpret_cast<Game::dvar_t**>(0x62C7C00) = Dvar::Register<int>("sv_network_fps", 1000, 20, 1000, Game::dvar_flag::DVAR_FLAG_NONE, "Number of times per second the server checks for net messages").get<Game::dvar_t*>();
Utils::Hook(0x4D3C7B, Dedicated::Dvar_RegisterSVNetworkFps, HOOK_CALL).install()->quick();
// r_loadForRenderer default to 0
Utils::Hook::Set<BYTE>(0x519DDF, 0);

View File

@ -29,5 +29,7 @@ namespace Components
static void TransmitGuids();
static void TimeWrapStub(Game::errorParm_t code, const char* message);
static Game::dvar_t* Dvar_RegisterSVNetworkFps(const char* dvarName, int value, int min, int max, int flags, const char* description);
};
}

View File

@ -22,19 +22,19 @@ namespace Components
return this->dvar;
}
template <> char* Dvar::Var::get()
{
if (this->dvar && this->dvar->type == Game::dvar_type::DVAR_TYPE_STRING && this->dvar->current.string)
{
return const_cast<char*>(this->dvar->current.string);
}
return const_cast<char*>("");
}
template <> const char* Dvar::Var::get()
{
return this->get<char*>();
if (this->dvar == nullptr)
return "";
if (this->dvar->type == Game::dvar_type::DVAR_TYPE_STRING
|| this->dvar->type == Game::dvar_type::DVAR_TYPE_ENUM)
{
if (this->dvar->current.string != nullptr)
return this->dvar->current.string;
}
return "";
}
template <> int Dvar::Var::get()
@ -193,7 +193,7 @@ namespace Components
void Dvar::ResetDvarsValue()
{
if (!Utils::IO::FileExists(Dvar::ArchiveDvarPath))
return
return;
Command::Execute("exec archivedvars.cfg", true);
// Clean up
@ -209,7 +209,7 @@ namespace Components
Scheduler::OnFrame([]()
{
static std::string lastValidName = "Unknown Soldier";
std::string name = Dvar::Var("name").get<char*>();
std::string name = Dvar::Var("name").get<const char*>();
// Don't perform any checks if name didn't change
if (name == lastValidName) return;

View File

@ -114,8 +114,11 @@ namespace Components
//Replace PM_CorrectAllSolid
Utils::Hook(0x57369E, Elevators::PM_CorrectAllSolidStub, HOOK_CALL).install()->quick();
// Place hook in PM_CheckDuck
// Place hooks in PM_CheckDuck. If the elevators dvar is set to easy the
// flags for duck/prone will always be removed from the player state
Utils::Hook(0x570EC5, Elevators::PM_Trace_Hk, HOOK_CALL).install()->quick();
Utils::Hook(0x570E0B, Elevators::PM_Trace_Hk, HOOK_CALL).install()->quick();
Utils::Hook(0x570D70, Elevators::PM_Trace_Hk, HOOK_CALL).install()->quick();
}
Elevators::~Elevators()

View File

@ -78,21 +78,9 @@ namespace Components
//Exception::SuspendProcess();
bool doFullDump = Flags::HasFlag("bigdumps") || Flags::HasFlag("reallybigdumps");
/*if (!doFullDump)
{
if (MessageBoxA(nullptr,
Utils::String::VA("%s\n\n" // errorStr
"Would you like to create a full crash dump for the developers (this can be 100mb or more)?\nNo will create small dumps that are automatically uploaded.", errorStr),
"IW4x Error!", MB_YESNO | MB_ICONERROR) == IDYES)
{
doFullDump = true;
}
}*/
MessageBoxA(nullptr, errorStr.data(), "ERROR", MB_ICONERROR);
if (doFullDump)
if ( Flags::HasFlag("bigminidumps"))
{
Exception::SetMiniDumpType(true, false);
}

View File

@ -111,8 +111,8 @@ namespace Components
Friends::SortList();
int notify = Dvar::Var("cl_notifyFriendState").get<int>();
if (gotOnline && (notify == -1 || (notify == 1 && !Game::CL_IsCgameInitialized())) && !Dvar::Var("ui_streamFriendly").get<bool>())
const auto notify = Dvar::Var("cl_notifyFriendState").get<bool>();
if (gotOnline && (!notify || (notify && !Game::CL_IsCgameInitialized())) && !Dvar::Var("ui_streamFriendly").get<bool>())
{
Game::Material* material = Friends::CreateAvatar(user);
Toast::Show(material, entry->name, "is playing IW4x", 3000, [material]()
@ -186,7 +186,7 @@ namespace Components
{
std::lock_guard<std::recursive_mutex> _(Friends::Mutex);
const unsigned int modId = *reinterpret_cast<unsigned int*>(const_cast<char*>("IW4x")) | 0x80000000;
const unsigned int modId = *reinterpret_cast<unsigned int*>("IW4x") | 0x80000000;
// Split up the list
for (auto entry : Friends::FriendsList)
@ -578,14 +578,19 @@ namespace Components
if (Dedicated::IsEnabled() || ZoneBuilder::IsEnabled() || Monitor::IsEnabled()) return;
Dvar::Register<bool>("cl_anonymous", false, Game::DVAR_FLAG_SAVED, "");
Dvar::Register<int>("cl_notifyFriendState", 1, -1, 1, Game::DVAR_FLAG_SAVED, "");
Dvar::Register<bool>("cl_anonymous", false, Game::DVAR_FLAG_SAVED, "Enable invisible mode for Steam");
Dvar::Register<bool>("cl_notifyFriendState", true, Game::DVAR_FLAG_SAVED, "Update friends about current game status");
Command::Add("addFriend", [](Command::Params* params)
{
if (params->length() <= 1) return;
if (params->length() < 2u)
{
Logger::Print("Usage: %s <Steam ID in hexadecimal format>\n", params->get(0));
return;
}
SteamID id;
id.bits = atoll(params->get(1));
id.bits = std::strtoull(params->get(1), nullptr, 16);
Friends::AddFriend(id);
});

View File

@ -536,14 +536,13 @@ namespace Components
if (weaponDef->requireLockonToFire)
return false;
if (ps->linkFlags & 4)
if (ps->linkFlags & Game::PLF_WEAPONVIEW_ONLY)
return false;
if (ps->weaponState >= Game::WEAPON_STUNNED_START && ps->weaponState <= Game::WEAPON_STUNNED_END)
return false;
// The game checks for these flags. Their meaning is to be researched if necessary.
if (ps->eFlags & 0x100C00)
if (ps->eFlags & (Game::EF_VEHICLE_ACTIVE | Game::EF_TURRET_ACTIVE_DUCK | Game::EF_TURRET_ACTIVE_PRONE))
return false;
if (!ps->hasAmmo)

View File

@ -1,36 +0,0 @@
#include "STDInclude.hpp"
#ifdef COMPILE_IW4MVM
#include <IW4MVM/client_main.h>
#endif
namespace Components
{
IW4MVM::IW4MVM()
{
if (Dedicated::IsEnabled() || ZoneBuilder::IsEnabled() || Monitor::IsEnabled() || Loader::IsPerformingUnitTests()) return;
DWORD oldProtect;
std::uint8_t* _module = reinterpret_cast<std::uint8_t*>(GetModuleHandle(nullptr));
VirtualProtect(_module + 0x1000, 0x2D6000, PAGE_EXECUTE_READWRITE, &oldProtect);
#ifdef COMPILE_IW4MVM
client_main::Init();
Scheduler::Once(client_main::PostInit);
#endif
Scheduler::OnFrame([]()
{
if (!Game::CL_IsCgameInitialized())
{
Dvar::Var("com_timescale").set(1.0f);
}
});
VirtualProtect(_module + 0x1000, 0x2D6000, PAGE_EXECUTE_READ, &oldProtect);
}
IW4MVM::~IW4MVM()
{
}
}

View File

@ -1,14 +0,0 @@
#pragma once
// Disabled for public release
//#define COMPILE_IW4MVM
namespace Components
{
class IW4MVM : public Component
{
public:
IW4MVM();
~IW4MVM();
};
}

View File

@ -241,14 +241,13 @@ namespace Components
{
if (Flags::HasFlag("dump"))
{
Utils::IO::WriteFile(Utils::String::VA("raw/%s.ents", name.data()), asset.mapEnts->entityString);
Utils::IO::WriteFile(Utils::String::VA("raw/%s.ents", name.data()), asset.mapEnts->entityString, true);
}
static std::string mapEntities;
FileSystem::File ents(name + ".ents");
if (ents.exists())
{
mapEntities = ents.getBuffer();
const auto& mapEntities = ents.getBuffer();
asset.mapEnts->entityString = const_cast<char*>(mapEntities.data());
asset.mapEnts->numEntityChars = mapEntities.size() + 1;
}
@ -784,7 +783,7 @@ namespace Components
{
if (pack.index == dlc)
{
ShellExecute(0, 0, L"https://xlabs.dev/support_iw4x_client.html", 0, 0, SW_SHOW);
ShellExecuteW(0, 0, L"https://xlabs.dev/support_iw4x_client.html", 0, 0, SW_SHOW);
return;
}
}

View File

@ -21,7 +21,7 @@ namespace Components
Dvar::Var("xblive_privateserver").set(false);
std::string playlistFilename = Dvar::Var("playlistFilename").get<char*>();
std::string playlistFilename = Dvar::Var("playlistFilename").get<const char*>();
FileSystem::File playlist(playlistFilename);
if (playlist.exists())

View File

@ -2,7 +2,6 @@
namespace Components
{
int QuickPatch::FrameTime = 0;
Dvar::Var QuickPatch::r_customAspectRatio;
void QuickPatch::UnlockStats()
@ -405,15 +404,9 @@ namespace Components
jmp ebx
}
}
QuickPatch::QuickPatch()
{
QuickPatch::FrameTime = 0;
Scheduler::OnFrame([]()
{
QuickPatch::FrameTime = Game::Sys_Milliseconds();
});
// quit_hard
Command::Add("quit_hard", [](Command::Params*)
{
@ -722,7 +715,7 @@ namespace Components
Utils::Hook(0x4A9F56, QuickPatch::MsgReadBitsCompressCheckCL, HOOK_CALL).install()->quick(); // CL_ParseServerMessage
Utils::Hook(0x407376, QuickPatch::SVCanReplaceServerCommand , HOOK_CALL).install()->quick(); // SV_CanReplaceServerCommand
Utils::Hook(0x5B67ED, QuickPatch::AtolAdjustPlayerLimit , HOOK_CALL).install()->quick(); // PartyHost_HandleJoinPartyRequest
Utils::Hook::Nop(0x41698E, 5); // Disable Svcmd_EntityList_f
// Patch selectStringTableEntryInDvar
Utils::Hook::Set(0x405959, QuickPatch::SelectStringTableEntryInDvarStub);

View File

@ -11,11 +11,8 @@ namespace Components
bool unitTest() override;
static void UnlockStats();
static int GetFrameTime() { return FrameTime; }
private:
static int FrameTime;
static void SelectStringTableEntryInDvarStub();
static int SVCanReplaceServerCommand(Game::client_t *client, const char *cmd);

View File

@ -23,16 +23,22 @@ namespace Components
StartupMessages::TotalMessages = StartupMessages::MessageList.size();
}
std::string message = StartupMessages::MessageList.front();
StartupMessages::MessageList.pop_front();
const auto& message = StartupMessages::MessageList.front();
Game::Dvar_SetStringByName("ui_startupMessage", message.data());
Game::Dvar_SetStringByName("ui_startupMessageTitle", Utils::String::VA("Messages (%d/%d)", StartupMessages::TotalMessages - StartupMessages::MessageList.size(), StartupMessages::TotalMessages));
Game::Dvar_SetStringByName("ui_startupNextButtonText", StartupMessages::MessageList.size() ? "Next" : "Close");
Game::Cbuf_AddText(0, "openmenu startup_messages");
StartupMessages::MessageList.pop_front();
});
}
StartupMessages::~StartupMessages()
{
StartupMessages::MessageList.clear();
}
void StartupMessages::AddMessage(const std::string& message)
{
StartupMessages::MessageList.push_back(message);

View File

@ -6,6 +6,7 @@ namespace Components
{
public:
StartupMessages();
~StartupMessages();
static void AddMessage(const std::string& message);

View File

@ -15,19 +15,14 @@ namespace Components
return 0;
}
template<> char* UIScript::Token::get()
template<> const char* UIScript::Token::get()
{
if (this->isValid())
{
return this->token;
}
return const_cast<char*>("");
}
template<> const char* UIScript::Token::get()
{
return this->get<char*>();
return "";
}
template<> std::string UIScript::Token::get()

View File

@ -1300,7 +1300,7 @@ namespace Components
}, nullptr, false);
// HACK: set language to 'techsets' to load from that dir
char* language = Utils::Hook::Get<char*>(0x649E740);
const char* language = Utils::Hook::Get<const char*>(0x649E740);
Utils::Hook::Set<const char*>(0x649E740, "techsets");
// load generated techset fastfiles
@ -1447,7 +1447,7 @@ namespace Components
Utils::IO::WriteFile("zone_source/techsets/techsets.csv", csvStr.data());
// set language back
Utils::Hook::Set<char*>(0x649E740, language);
Utils::Hook::Set<const char*>(0x649E740, language);
Logger::Print("Building zone 'techsets/techsets'...\n");
Zone("techsets/techsets").build();

View File

@ -785,9 +785,9 @@ namespace Game
float Vec2Normalize(vec2_t& vec)
{
const float length = std::sqrt((vec[0] * vec[0]) + (vec[1] * vec[1]));
const auto length = std::sqrt(vec[0] * vec[0] + vec[1] * vec[1]);
if(length > 0.0f)
if (length > 0.0f)
{
vec[0] /= length;
vec[1] /= length;
@ -798,9 +798,9 @@ namespace Game
float Vec3Normalize(vec3_t& vec)
{
const float length = std::sqrt(std::pow(vec[0], 2.0f) + std::pow(vec[1], 2.0f) + std::pow(vec[2], 2.0f));
const auto length = std::sqrt(vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2]);
if(length > 0.0f)
if (length > 0.0f)
{
vec[0] /= length;
vec[1] /= length;

View File

@ -1169,6 +1169,40 @@ namespace Game
PM_DEAD_LINKED = 0x9,
};
enum playerEFlag
{
EF_NONSOLID_BMODEL = 0x1,
EF_TELEPORT_BIT = 0x2,
EF_CROUCHING = 0x4,
EF_PRONE = 0x8,
EF_NODRAW = 0x20,
EF_TIMED_OBJECT = 0x40,
EF_VOTED = 0x80,
EF_TALK = 0x100,
EF_FIRING = 0x200,
EF_TURRET_ACTIVE_PRONE = 0x400,
EF_TURRET_ACTIVE_DUCK = 0x800,
EF_LOCK_LIGHT_VIS = 0x1000,
EF_AIM_ASSIST = 0x2000,
EF_LOOP_RUMBLE = 0x4000,
EF_LASER_SIGHT = 0x8000,
EF_MANTLE = 0x10000,
EF_DEAD = 0x20000,
EF_ADS = 0x40000,
EF_NEW = 0x80000,
EF_VEHICLE_ACTIVE = 0x100000,
EF_JAMMING = 0x200000,
EF_COMPASS_PING = 0x400000,
EF_SOFT = 0x800000
};
enum playerLinkFlag
{
PLF_ANGLES_LOCKED = 0x1,
PLF_USES_OFFSET = 0x2,
PLF_WEAPONVIEW_ONLY = 0x4
};
struct playerState_s
{
int commandTime;
@ -5539,14 +5573,14 @@ namespace Game
void /*Vehicle*/* vehicle;
int physObjId;
unsigned __int16 model;
char physicsObject;
char takedamage;
char active;
char handler;
char team;
unsigned char physicsObject;
unsigned char takedamage;
unsigned char active;
unsigned char handler;
unsigned char team;
bool freeAfterEvent;
__int16 padding_short;
short classname;
unsigned __int16 classname;
unsigned __int16 script_classname;
unsigned __int16 script_linkName;
unsigned __int16 target;
@ -5574,6 +5608,8 @@ namespace Game
char pad[100];
} gentity_t;
static_assert(sizeof(gentity_s) == 0x274);
struct lockonFireParms
{
bool lockon;
@ -5583,6 +5619,7 @@ namespace Game
};
#pragma pack(push, 1)
typedef struct client_s
{
clientstate_t state; // 0
@ -5621,6 +5658,7 @@ namespace Game
unsigned __int64 steamID; // 278272
char __pad9[403592]; // 278280
} client_t;
#pragma pack(pop)
static_assert(sizeof(client_t) == 0xA6790);

View File

@ -156,13 +156,13 @@ namespace Steam
gameID.type = 1; // k_EGameIDTypeGameMod
gameID.appID = Proxy::AppId & 0xFFFFFF;
char* modId = const_cast<char*>("IW4x");
gameID.modID = *reinterpret_cast<unsigned int*>(modId) | 0x80000000;
const char* modId = "IW4x";
gameID.modID = *reinterpret_cast<const unsigned int*>(modId) | 0x80000000;
Interface clientUtils(Proxy::ClientEngine->GetIClientUtils(Proxy::SteamPipe));
clientUtils.invoke<void>("SetAppIDForCurrentPipe", Proxy::AppId, false);
char ourPath[MAX_PATH] = { 0 };
char ourPath[MAX_PATH] = {0};
GetModuleFileNameA(GetModuleHandle(nullptr), ourPath, sizeof(ourPath));
char ourDirectory[MAX_PATH] = { 0 };

View File

@ -107,12 +107,12 @@ namespace Utils
void SetEnvironment()
{
wchar_t exeName[512];
GetModuleFileName(GetModuleHandle(nullptr), exeName, sizeof(exeName) / 2);
GetModuleFileNameW(GetModuleHandle(nullptr), exeName, sizeof(exeName) / 2);
wchar_t* exeBaseName = wcsrchr(exeName, L'\\');
exeBaseName[0] = L'\0';
SetCurrentDirectory(exeName);
SetCurrentDirectoryW(exeName);
}
HMODULE GetNTDLL()

Binary file not shown.

Binary file not shown.