Merge branch 'main' into scripts
This commit is contained in:
commit
0916d71204
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -16,6 +16,20 @@ DataSources.MPStatsSettings = DataSourceHelpers.ListSetup("MPStatsSettings", fun
|
||||
if dvarName == "cg_unlockall_loot" then
|
||||
Engine.SetDvar("ui_enableAllHeroes", f1_arg1.value)
|
||||
end
|
||||
if dvarName == "all_ee_completed" then
|
||||
Engine.ExecNow(f1_arg0, "statsetbyname darkops_zod_ee " .. f1_arg1.value)
|
||||
Engine.ExecNow(f1_arg0, "statsetbyname darkops_zod_super_ee " .. f1_arg1.value)
|
||||
Engine.ExecNow(f1_arg0, "statsetbyname darkops_factory_ee " .. f1_arg1.value)
|
||||
Engine.ExecNow(f1_arg0, "statsetbyname darkops_factory_super_ee " .. f1_arg1.value)
|
||||
Engine.ExecNow(f1_arg0, "statsetbyname darkops_castle_ee " .. f1_arg1.value)
|
||||
Engine.ExecNow(f1_arg0, "statsetbyname darkops_castle_super_ee " .. f1_arg1.value)
|
||||
Engine.ExecNow(f1_arg0, "statsetbyname darkops_island_ee " .. f1_arg1.value)
|
||||
Engine.ExecNow(f1_arg0, "statsetbyname darkops_island_super_ee " .. f1_arg1.value)
|
||||
Engine.ExecNow(f1_arg0, "statsetbyname darkops_stalingrad_ee " .. f1_arg1.value)
|
||||
Engine.ExecNow(f1_arg0, "statsetbyname darkops_stalingrad_super_ee " .. f1_arg1.value)
|
||||
Engine.ExecNow(f1_arg0, "statsetbyname darkops_genesis_ee " .. f1_arg1.value)
|
||||
Engine.ExecNow(f1_arg0, "statsetbyname DARKOPS_GENESIS_SUPER_EE " .. f1_arg1.value)
|
||||
end
|
||||
end
|
||||
|
||||
table.insert(optionsTable,
|
||||
@ -103,59 +117,91 @@ DataSources.MPStatsSettings = DataSourceHelpers.ListSetup("MPStatsSettings", fun
|
||||
value = 1
|
||||
},
|
||||
}, nil, updateDvar))
|
||||
table.insert(optionsTable,
|
||||
CoD.OptionsUtility.CreateDvarSettings(controller, "Unlock all Specialists Outfits",
|
||||
"All specialists outfits are unlocked.", "MPStatsSettings_unlockall_specialists_outfits",
|
||||
"cg_unlockall_specialists_outfits", {
|
||||
{
|
||||
option = "MENU_DISABLED",
|
||||
value = 0,
|
||||
default = true
|
||||
},
|
||||
{
|
||||
option = "MENU_ENABLED",
|
||||
value = 1
|
||||
},
|
||||
}, nil, updateDvar))
|
||||
if Engine.CurrentSessionMode() == Enum.eModes.MODE_MULTIPLAYER then
|
||||
table.insert(optionsTable,
|
||||
CoD.OptionsUtility.CreateDvarSettings(controller, "Unlock all Specialists Outfits",
|
||||
"All specialists outfits are unlocked.", "MPStatsSettings_unlockall_specialists_outfits",
|
||||
"cg_unlockall_specialists_outfits", {
|
||||
{
|
||||
option = "MENU_DISABLED",
|
||||
value = 0,
|
||||
default = true
|
||||
},
|
||||
{
|
||||
option = "MENU_ENABLED",
|
||||
value = 1
|
||||
},
|
||||
}, nil, updateDvar))
|
||||
end
|
||||
if Engine.CurrentSessionMode() == Enum.eModes.MODE_ZOMBIES then
|
||||
table.insert(optionsTable,
|
||||
CoD.OptionsUtility.CreateDvarSettings(controller, "Unlock Easter Eggs",
|
||||
"Complete all Easter Egg Achievements.", "MPStatsSettings_complete_ee",
|
||||
"all_ee_completed", {
|
||||
{
|
||||
option = "MENU_DISABLED",
|
||||
value = 0,
|
||||
default = true
|
||||
},
|
||||
{
|
||||
option = "MENU_ENABLED",
|
||||
value = 1
|
||||
},
|
||||
}, nil, updateDvar))
|
||||
end
|
||||
|
||||
local rankLevels = {}
|
||||
if Engine.CurrentSessionMode() == Enum.eModes.MODE_MULTIPLAYER then
|
||||
rankLevels = { 1, 10, 20, 30, 40, 50, 55 }
|
||||
elseif Engine.CurrentSessionMode() == Enum.eModes.MODE_ZOMBIES then
|
||||
rankLevels = { 1, 10, 20, 30, 35 }
|
||||
end
|
||||
local rankObjs = {}
|
||||
local hasDefault = false
|
||||
local hasDefault = true
|
||||
local currentPrestige = CoD.PrestigeUtility.GetCurrentPLevel(controller, Engine.CurrentSessionMode())
|
||||
local currentRank = CoD.BlackMarketUtility.GetCurrentRank(controller) + 1
|
||||
for index, value in ipairs(rankLevels) do
|
||||
table.insert(rankObjs, {
|
||||
name = value,
|
||||
value = value - 1,
|
||||
default = value == currentRank,
|
||||
title = "Rank Level",
|
||||
desc = ""
|
||||
})
|
||||
if not hasDefault then
|
||||
hasDefault = value == currentRank
|
||||
|
||||
local isMasterPrestige = currentPrestige == 11
|
||||
|
||||
if Engine.CurrentSessionMode() == Enum.eModes.MODE_MULTIPLAYER then
|
||||
if not isMasterPrestige then
|
||||
rankLevels = { 1, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55 }
|
||||
else
|
||||
rankLevels = { 56, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000 }
|
||||
end
|
||||
elseif Engine.CurrentSessionMode() == Enum.eModes.MODE_ZOMBIES then
|
||||
if not isMasterPrestige then
|
||||
rankLevels = { 1, 5, 10, 15, 20, 25, 30, 35 }
|
||||
else
|
||||
rankLevels = { 36, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000 }
|
||||
end
|
||||
end
|
||||
|
||||
if not hasDefault then
|
||||
local maxlevel = math.max(table.unpack(rankLevels))
|
||||
local minlevel = math.min(table.unpack(rankLevels))
|
||||
|
||||
for index, value in ipairs(rankLevels) do
|
||||
table.insert(rankObjs, {
|
||||
name = currentRank,
|
||||
name = value <= minlevel and "Min" or value >= maxlevel and "Max" or value,
|
||||
value = value - 1,
|
||||
default = value == currentRank,
|
||||
title = "Rank Level",
|
||||
desc = value ~= currentRank and "" or "Current Rank"
|
||||
})
|
||||
end
|
||||
|
||||
if hasDefault and currentRank ~= minlevel and currentRank < maxlevel and not isMasterPrestige then
|
||||
table.insert(rankObjs, {
|
||||
name = "Current: " ..
|
||||
tostring(currentRank <= minlevel and "Min" or currentRank >= maxlevel and "Max" or currentRank),
|
||||
value = currentRank - 1,
|
||||
default = true,
|
||||
title = "Rank Level",
|
||||
desc = ""
|
||||
desc = "Do not adjust rank"
|
||||
})
|
||||
end
|
||||
|
||||
local prestigeTable = {}
|
||||
for i = 0, 10 do
|
||||
for i = 0, 11 do
|
||||
table.insert(prestigeTable, {
|
||||
name = i == 0 and "None" or i,
|
||||
name = i == 0 and "None" or i == 11 and "Master" or i,
|
||||
value = i,
|
||||
default = i == CoD.PrestigeUtility.GetCurrentPLevel(controller),
|
||||
default = i == currentPrestige,
|
||||
title = "Prestige",
|
||||
desc = ""
|
||||
})
|
||||
@ -196,25 +242,19 @@ DataSources.MPStatsSettings = DataSourceHelpers.ListSetup("MPStatsSettings", fun
|
||||
|
||||
table.insert(optionsTable, {
|
||||
models = {
|
||||
name = "Rank Level",
|
||||
name = "Prestige",
|
||||
desc = "",
|
||||
image = nil,
|
||||
optionsDatasource = createSettingsDatasource(controller, "MPStatsSettings_rank_level", rankObjs,
|
||||
CoD.BlackMarketUtility.GetCurrentRank(controller), false, function(f1_arg0, f1_arg1, f1_arg2, dvarName, f1_arg4)
|
||||
optionsDatasource = createSettingsDatasource(controller, "MPStatsSettings_rank_prestige", prestigeTable,
|
||||
CoD.PrestigeUtility.GetCurrentPLevel(controller, Engine.CurrentSessionMode()), false,
|
||||
function(f1_arg0, f1_arg1, f1_arg2, dvarName, f1_arg4)
|
||||
UpdateInfoModels(f1_arg1)
|
||||
local rankTable = nil
|
||||
if Engine.CurrentSessionMode() == Enum.eModes.MODE_MULTIPLAYER then
|
||||
rankTable = "gamedata/tables/mp/mp_ranktable.csv"
|
||||
elseif Engine.CurrentSessionMode() == Enum.eModes.MODE_ZOMBIES then
|
||||
rankTable = "gamedata/tables/zm/zm_ranktable.csv"
|
||||
local newPrestige = f1_arg1.value
|
||||
if newPrestige == 11 then
|
||||
Engine.Exec(f1_arg0, "PrestigeStatsMaster " .. tostring(Engine.CurrentSessionMode()))
|
||||
end
|
||||
local skipLines = Engine.CurrentSessionMode() == Enum.eModes.MODE_MULTIPLAYER and 3 or 2
|
||||
local maxXp = tonumber(Engine.TableLookupGetColumnValueForRow(rankTable, f1_arg1.value + skipLines, 7))
|
||||
if maxXp == nil then
|
||||
maxXp = 9999999999
|
||||
end
|
||||
Engine.ExecNow(f1_arg0, "statsetbyname rankxp " .. maxXp - 1)
|
||||
Engine.ExecNow(f1_arg0, "statsetbyname rank " .. f1_arg1.value)
|
||||
Engine.ExecNow(f1_arg0, "statsetbyname plevel " .. newPrestige)
|
||||
Engine.ExecNow(f1_arg0, "statsetbyname hasprestiged " .. (newPrestige > 0 and 1 or 0))
|
||||
Engine.Exec(f1_arg0, "uploadstats " .. tostring(Engine.CurrentSessionMode()))
|
||||
end)
|
||||
},
|
||||
@ -226,16 +266,70 @@ DataSources.MPStatsSettings = DataSourceHelpers.ListSetup("MPStatsSettings", fun
|
||||
|
||||
table.insert(optionsTable, {
|
||||
models = {
|
||||
name = "Prestige",
|
||||
name = "Rank Level",
|
||||
desc = "",
|
||||
image = nil,
|
||||
optionsDatasource = createSettingsDatasource(controller, "MPStatsSettings_rank_prestige", prestigeTable,
|
||||
CoD.PrestigeUtility.GetCurrentPLevel(controller), false, function(f1_arg0, f1_arg1, f1_arg2, dvarName, f1_arg4)
|
||||
optionsDatasource = createSettingsDatasource(controller, "MPStatsSettings_rank_level", rankObjs,
|
||||
CoD.BlackMarketUtility.GetCurrentRank(controller), false,
|
||||
function(f1_arg0, f1_arg1, f1_arg2, dvarName, f1_arg4)
|
||||
UpdateInfoModels(f1_arg1)
|
||||
local newPrestige = f1_arg1.value
|
||||
Engine.ExecNow(f1_arg0, "statsetbyname plevel " .. newPrestige)
|
||||
Engine.ExecNow(f1_arg0, "statsetbyname hasprestiged " .. (newPrestige > 0 and 1 or 0))
|
||||
local rankTable = nil
|
||||
local rank = f1_arg1.value + 1
|
||||
if currentPrestige <= 10 then
|
||||
if Engine.CurrentSessionMode() == Enum.eModes.MODE_MULTIPLAYER then
|
||||
rankTable = "gamedata/tables/mp/mp_ranktable.csv"
|
||||
elseif Engine.CurrentSessionMode() == Enum.eModes.MODE_ZOMBIES then
|
||||
rankTable = "gamedata/tables/zm/zm_ranktable.csv"
|
||||
end
|
||||
local skipLines = Engine.CurrentSessionMode() == Enum.eModes.MODE_MULTIPLAYER and 3 or 2
|
||||
local maxXp = tonumber(Engine.TableLookupGetColumnValueForRow(rankTable, rank - 2 + skipLines, 7))
|
||||
if Engine.CurrentSessionMode() == Enum.eModes.MODE_MULTIPLAYER then
|
||||
if maxXp ~= nil and rank == maxlevel then
|
||||
maxXp = maxXp + 55600
|
||||
end
|
||||
end
|
||||
if Engine.CurrentSessionMode() == Enum.eModes.MODE_ZOMBIES then
|
||||
if maxXp ~= nil and rank == maxlevel then
|
||||
maxXp = maxXp + 54244
|
||||
end
|
||||
end
|
||||
if maxXp == nil then
|
||||
maxXp = 0
|
||||
end
|
||||
Engine.ExecNow(f1_arg0, "statsetbyname rank " .. rank - 1)
|
||||
Engine.ExecNow(f1_arg0, "statsetbyname rankxp " .. maxXp)
|
||||
Engine.ExecNow(f1_arg0, "statsetbyname paragon_rankxp " .. 0)
|
||||
else
|
||||
if Engine.CurrentSessionMode() == Enum.eModes.MODE_MULTIPLAYER then
|
||||
rankTable = "gamedata/tables/mp/mp_paragonranktable.csv"
|
||||
elseif Engine.CurrentSessionMode() == Enum.eModes.MODE_ZOMBIES then
|
||||
rankTable = "gamedata/tables/zm/zm_paragonranktable.csv"
|
||||
end
|
||||
local skipLines = 2
|
||||
local maxXp = 0
|
||||
if Engine.CurrentSessionMode() == Enum.eModes.MODE_MULTIPLAYER then
|
||||
maxXp = tonumber(Engine.TableLookupGetColumnValueForRow(rankTable, rank - 57 + skipLines, 7))
|
||||
if maxXp ~= nil and rank == maxlevel then
|
||||
maxXp = maxXp + 55600
|
||||
end
|
||||
rank = rank - 55
|
||||
end
|
||||
if Engine.CurrentSessionMode() == Enum.eModes.MODE_ZOMBIES then
|
||||
maxXp = tonumber(Engine.TableLookupGetColumnValueForRow(rankTable, rank - 37 + skipLines, 7))
|
||||
if maxXp ~= nil and rank == maxlevel then
|
||||
maxXp = maxXp + 54244
|
||||
end
|
||||
rank = rank - 35
|
||||
end
|
||||
if maxXp == nil then
|
||||
maxXp = 0
|
||||
end
|
||||
Engine.ExecNow(f1_arg0, "statsetbyname paragon_rank " .. rank - 1)
|
||||
Engine.ExecNow(f1_arg0, "statsetbyname paragon_rankxp " .. maxXp)
|
||||
end
|
||||
Engine.Exec(f1_arg0, "uploadstats " .. tostring(Engine.CurrentSessionMode()))
|
||||
|
||||
currentRank = rank
|
||||
end)
|
||||
},
|
||||
properties = {
|
||||
@ -268,8 +362,8 @@ LUI.createMenu.BoiiiStatsMenu = function(controller)
|
||||
GameSettingsBackground:setLeftRight(true, true, 0, 0)
|
||||
GameSettingsBackground:setTopBottom(true, true, 0, 0)
|
||||
GameSettingsBackground.MenuFrame.titleLabel:setText(Engine.Localize("STATS SETTINGS"))
|
||||
GameSettingsBackground.MenuFrame.cac3dTitleIntermediary0.FE3dTitleContainer0.MenuTitle.TextBox1.Label0:setText(Engine
|
||||
.Localize("STATS SETTINGS"))
|
||||
GameSettingsBackground.MenuFrame.cac3dTitleIntermediary0.FE3dTitleContainer0.MenuTitle.TextBox1.Label0:setText(
|
||||
Engine.Localize("STATS SETTINGS"))
|
||||
GameSettingsBackground.GameSettingsSelectedItemInfo.GameModeInfo:setAlpha(0)
|
||||
GameSettingsBackground.GameSettingsSelectedItemInfo.GameModeName:setAlpha(0)
|
||||
self:addElement(GameSettingsBackground)
|
||||
|
2
deps/curl
vendored
2
deps/curl
vendored
@ -1 +1 @@
|
||||
Subproject commit 8e21b1a05f3c0ee098dbcb6c3d84cb61f102a122
|
||||
Subproject commit ac5ad5214261a2237bdbe344708f9d32c9393fd6
|
2
deps/rapidjson
vendored
2
deps/rapidjson
vendored
@ -1 +1 @@
|
||||
Subproject commit 949c771b03de448bdedea80c44a4a5f65284bfeb
|
||||
Subproject commit 2a1f586ba692ecbbf6d63c8ffbd4d837b1d4a9a4
|
@ -98,7 +98,7 @@ namespace auth
|
||||
{
|
||||
static const auto is_first = []
|
||||
{
|
||||
static utils::nt::handle<> mutex = CreateMutexA(nullptr, FALSE, "boiii_mutex");
|
||||
static utils::nt::handle mutex = CreateMutexA(nullptr, FALSE, "boiii_mutex");
|
||||
return mutex && GetLastError() != ERROR_ALREADY_EXISTS;
|
||||
}();
|
||||
|
||||
@ -134,9 +134,9 @@ namespace auth
|
||||
|
||||
const auto& fragment_packet = packet_buffer.get_buffer();
|
||||
|
||||
game::NET_OutOfBandData(
|
||||
sock, adr, fragment_packet.data(),
|
||||
static_cast<int>(fragment_packet.size()));
|
||||
game::NET_OutOfBandData(sock, adr,
|
||||
fragment_packet.data(),
|
||||
static_cast<int>(fragment_packet.size()));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "loader/component_loader.hpp"
|
||||
|
||||
#include "command.hpp"
|
||||
#include "scheduler.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
#include <utils/io.hpp>
|
||||
@ -94,9 +95,9 @@ namespace bots
|
||||
}
|
||||
|
||||
int format_bot_string(char* buffer, [[maybe_unused]] const char* format, const char* name, const char* xuid,
|
||||
const char* xnaddr, int protocol, int net_field_chk, const char* session_mode, int qport)
|
||||
const char* xnaddr, int protocol, int net_field_chk, const char* session_mode, int qport)
|
||||
{
|
||||
const auto find_name = [](const std::string& needle) -> const char*
|
||||
const auto find_clan_name = [](const std::string& needle) -> const char*
|
||||
{
|
||||
for (const auto& entry : get_bot_names())
|
||||
{
|
||||
@ -109,7 +110,8 @@ namespace bots
|
||||
return "3arc";
|
||||
};
|
||||
|
||||
return sprintf_s(buffer, 1024, bot_format_string, name, find_name(name), xuid, xnaddr, protocol, net_field_chk, session_mode, qport);
|
||||
return sprintf_s(buffer, 1024, bot_format_string, name, find_clan_name(name),
|
||||
xuid, xnaddr, protocol, net_field_chk, session_mode, qport);
|
||||
}
|
||||
}
|
||||
|
||||
@ -147,13 +149,16 @@ namespace bots
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
scheduler::once([count]
|
||||
{
|
||||
if (!game::SV_AddTestClient())
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
{
|
||||
break;
|
||||
if (!game::SV_AddTestClient())
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}, scheduler::server);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -5,8 +5,6 @@
|
||||
|
||||
#include "auth.hpp"
|
||||
|
||||
#include "steam/steam.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
#include <utils/string.hpp>
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
#include "loader/component_loader.hpp"
|
||||
|
||||
#include "game/game.hpp"
|
||||
#include "scheduler.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
|
||||
@ -12,7 +11,7 @@ namespace dedicated_patches
|
||||
{
|
||||
utils::hook::detour spawn_server_hook;
|
||||
|
||||
void scr_are_textures_loaded_stub([[maybe_unused]] game::scriptInstance_t inst)
|
||||
void scr_are_textures_loaded_stub()
|
||||
{
|
||||
game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, 1);
|
||||
}
|
||||
|
45
src/client/component/fov.cpp
Normal file
45
src/client/component/fov.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
|
||||
#include "game/game.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
|
||||
namespace fov
|
||||
{
|
||||
namespace
|
||||
{
|
||||
void cg_calc_fov_stub(const int local_client_num, float* fov_x, float* dx_dz_at_default_aspect_ratio,
|
||||
float* dx_dz, float* dy_dz)
|
||||
{
|
||||
game::CG_CalcFOVfromLens.call_safe(local_client_num, fov_x, dx_dz_at_default_aspect_ratio, dx_dz, dy_dz);
|
||||
|
||||
const game::dvar_t* cg_fovScale = *reinterpret_cast<game::dvar_t**>(0x144A31A88_g);
|
||||
if (cg_fovScale && !game::Com_IsRunningUILevel())
|
||||
{
|
||||
const auto scale = cg_fovScale->current.value.value;
|
||||
|
||||
*fov_x *= scale;
|
||||
*dx_dz *= scale;
|
||||
*dy_dz *= scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct component final : client_component
|
||||
{
|
||||
void post_unpack() override
|
||||
{
|
||||
// Hook CG_CalcFOVfromLens within CG_CalcFov
|
||||
utils::hook::call(0x1404DADA7_g, cg_calc_fov_stub);
|
||||
|
||||
// Patch cg_fovScale flags
|
||||
utils::hook::set<uint32_t>(0x14090E735_g, game::DVAR_ARCHIVE);
|
||||
|
||||
// Don't reset cg_fovScale
|
||||
utils::hook::set<uint8_t>(0x140926D2A_g, 0xC3);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
REGISTER_COMPONENT(fov::component)
|
@ -68,14 +68,6 @@ namespace getinfo
|
||||
return count;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
int Com_SessionMode_GetGameMode()
|
||||
{
|
||||
return *reinterpret_cast<int*>(game::select(0x1568ED7F4, 0x14948DB04)) << 14 >> 28;
|
||||
}
|
||||
}
|
||||
|
||||
int get_assigned_team()
|
||||
{
|
||||
return (rand() % 2) + 1;
|
||||
@ -112,7 +104,7 @@ namespace getinfo
|
||||
info.set("protocol", std::to_string(PROTOCOL));
|
||||
info.set("sub_protocol", std::to_string(SUB_PROTOCOL));
|
||||
info.set("playmode", std::to_string(game::Com_SessionMode_GetMode()));
|
||||
info.set("gamemode", std::to_string(Com_SessionMode_GetGameMode()));
|
||||
info.set("gamemode", std::to_string(game::Com_SessionMode_GetGameMode()));
|
||||
info.set("sv_running", std::to_string(game::is_server_running()));
|
||||
info.set("dedicated", game::is_server() ? "1" : "0");
|
||||
info.set("hc", std::to_string(game::Com_GametypeSettings_GetUInt("hardcoremode", false)));
|
||||
|
@ -54,7 +54,7 @@ namespace party
|
||||
{
|
||||
const auto local_client = *reinterpret_cast<DWORD*>(0x14342155C_g);
|
||||
const auto current_mode = game::Com_SessionMode_GetMode();
|
||||
game::Com_SwitchMode(local_client, current_mode, mode, 6);
|
||||
game::Com_SwitchMode(local_client, static_cast<game::eModes>(current_mode), mode, 6);
|
||||
}, scheduler::main);
|
||||
}
|
||||
|
||||
|
@ -2,8 +2,7 @@
|
||||
#include "loader/component_loader.hpp"
|
||||
|
||||
#include <game/game.hpp>
|
||||
|
||||
#include "network.hpp"
|
||||
#include <game/utils.hpp>
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
|
||||
@ -11,21 +10,10 @@ namespace patches
|
||||
{
|
||||
namespace
|
||||
{
|
||||
utils::hook::detour sv_execute_client_messages_hook;
|
||||
const game::dvar_t* lobby_min_players;
|
||||
|
||||
void sv_execute_client_messages_stub(game::client_s* client, game::msg_t* msg)
|
||||
{
|
||||
if ((client->reliableSequence - client->reliableAcknowledge) < 0)
|
||||
{
|
||||
client->reliableAcknowledge = client->reliableSequence;
|
||||
network::send(client->address, "error", "EXE_LOSTRELIABLECOMMANDS");
|
||||
return;
|
||||
}
|
||||
|
||||
sv_execute_client_messages_hook.invoke<void>(client, msg);
|
||||
}
|
||||
|
||||
void script_errors_stub(const char* file, int line, unsigned int code, const char* fmt, ...)
|
||||
void script_errors_stub([[maybe_unused]] const char* file, [[maybe_unused]] int line,
|
||||
[[maybe_unused]] unsigned int code, const char* fmt, ...)
|
||||
{
|
||||
char buffer[0x1000];
|
||||
|
||||
@ -38,28 +26,58 @@ namespace patches
|
||||
|
||||
game::Com_Error(game::ERROR_SCRIPT_DROP, "%s", buffer);
|
||||
}
|
||||
|
||||
void scr_get_num_expected_players()
|
||||
{
|
||||
auto expected_players = game::LobbyHost_GetClientCount(game::LOBBY_TYPE_GAME,
|
||||
game::LOBBY_CLIENT_TYPE_ALL);
|
||||
|
||||
const auto mode = game::Com_SessionMode_GetMode();
|
||||
if ((mode == game::MODE_ZOMBIES || mode == game::MODE_CAMPAIGN))
|
||||
{
|
||||
if (const auto min_players = lobby_min_players->current.value.integer)
|
||||
{
|
||||
expected_players = min_players;
|
||||
}
|
||||
}
|
||||
|
||||
const auto num_expected_players = std::max(1, expected_players);
|
||||
game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, num_expected_players);
|
||||
}
|
||||
|
||||
void sv_execute_client_messages_stub(game::client_s* client, game::msg_t* msg)
|
||||
{
|
||||
if ((client->reliableSequence - client->reliableAcknowledge) < 0)
|
||||
{
|
||||
client->reliableAcknowledge = client->reliableSequence;
|
||||
game::SV_DropClient(client, "EXE_LOSTRELIABLECOMMANDS", true, true);
|
||||
return;
|
||||
}
|
||||
|
||||
game::SV_ExecuteClientMessage(client, msg);
|
||||
}
|
||||
}
|
||||
|
||||
struct component final : generic_component
|
||||
{
|
||||
void post_unpack() override
|
||||
{
|
||||
// print hexadecimal xuids in status command
|
||||
utils::hook::copy_string(game::select(0x143050560, 0x140E85B00), "%12llx ");
|
||||
|
||||
// print hexadecimal xuids in chat game log command
|
||||
utils::hook::set<char>(game::select(0x142FD9362, 0x140E16FA2), 'x');
|
||||
|
||||
// don't make script errors fatal error
|
||||
utils::hook::call(game::select(0x1412CAC4D, 0x140158EB2), script_errors_stub);
|
||||
|
||||
// Change 4 character name limit to 3 characters
|
||||
// change 4 character name limit to 3 characters
|
||||
utils::hook::set<uint8_t>(game::select(0x14224DA53, 0x140531143), 3);
|
||||
utils::hook::set<uint8_t>(game::select(0x14224DBB4, 0x1405312A8), 3);
|
||||
utils::hook::set<uint8_t>(game::select(0x14224DF8C, 0x1405316DC), 3);
|
||||
|
||||
// make sure client's reliableAck are not negative
|
||||
sv_execute_client_messages_hook.create(game::select(0x14224A460, 0x14052F840), sv_execute_client_messages_stub);
|
||||
// make sure reliableAck is not negative or too big
|
||||
utils::hook::call(game::select(0x14225489C, 0x140537C4C), sv_execute_client_messages_stub);
|
||||
|
||||
lobby_min_players = game::register_dvar_int("lobby_min_players", 0, 0, 8, game::DVAR_NONE, "");
|
||||
utils::hook::jump(game::select(0x141A7BCF0, 0x1402CB900), scr_get_num_expected_players, true);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ namespace scheduler
|
||||
};
|
||||
|
||||
volatile bool kill = false;
|
||||
std::thread thread;
|
||||
std::thread async_thread;
|
||||
task_pipeline pipelines[pipeline::count];
|
||||
|
||||
utils::hook::detour r_end_frame_hook;
|
||||
@ -153,7 +153,7 @@ namespace scheduler
|
||||
{
|
||||
void post_load() override
|
||||
{
|
||||
thread = utils::thread::create_named_thread("Async Scheduler", []()
|
||||
async_thread = utils::thread::create_named_thread("Async Scheduler", []()
|
||||
{
|
||||
while (!kill)
|
||||
{
|
||||
@ -180,9 +180,9 @@ namespace scheduler
|
||||
void pre_destroy() override
|
||||
{
|
||||
kill = true;
|
||||
if (thread.joinable())
|
||||
if (async_thread.joinable())
|
||||
{
|
||||
thread.join();
|
||||
async_thread.join();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -30,12 +30,12 @@ namespace scheduler
|
||||
|
||||
void execute(const pipeline type);
|
||||
|
||||
void schedule(const std::function<bool()>& callback, pipeline type = pipeline::async,
|
||||
void schedule(const std::function<bool()>& callback, pipeline type,
|
||||
std::chrono::milliseconds delay = 0ms);
|
||||
void loop(const std::function<void()>& callback, pipeline type = pipeline::async,
|
||||
void loop(const std::function<void()>& callback, pipeline type,
|
||||
std::chrono::milliseconds delay = 0ms);
|
||||
void once(const std::function<void()>& callback, pipeline type = pipeline::async,
|
||||
void once(const std::function<void()>& callback, pipeline type,
|
||||
std::chrono::milliseconds delay = 0ms);
|
||||
void on_game_initialized(const std::function<void()>& callback, pipeline type = pipeline::async,
|
||||
void on_game_initialized(const std::function<void()>& callback, pipeline type,
|
||||
std::chrono::milliseconds delay = 0ms);
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ namespace script
|
||||
{
|
||||
constexpr size_t GSC_MAGIC = 0x1C000A0D43534780;
|
||||
|
||||
utils::hook::detour db_findxassetheader_hook;
|
||||
utils::hook::detour db_find_x_asset_header_hook;
|
||||
utils::hook::detour gscr_get_bgb_remaining_hook;
|
||||
|
||||
std::unordered_map<std::string, game::RawFile*> loaded_scripts;
|
||||
@ -33,7 +33,6 @@ namespace script
|
||||
void load_script(std::string& name, const std::string& data)
|
||||
{
|
||||
auto& allocator = *utils::memory::get_allocator();
|
||||
const auto* file_string = allocator.duplicate_string(data);
|
||||
|
||||
const auto appdata_path = (game::get_appdata_path() / "data/").generic_string();
|
||||
const auto host_path = (utils::nt::library{}.get_folder() / "boiii/").generic_string();
|
||||
@ -62,12 +61,12 @@ namespace script
|
||||
return;
|
||||
}
|
||||
|
||||
auto* rawfile = allocator.allocate<game::RawFile>();
|
||||
rawfile->name = name.data(); // use script name with .gsc suffix for FindXAssetHeader hook
|
||||
rawfile->buffer = file_string;
|
||||
rawfile->len = static_cast<int>(data.length());
|
||||
auto* raw_file = allocator.allocate<game::RawFile>();
|
||||
raw_file->name = allocator.duplicate_string(name); // use script name with .gsc suffix for FindXAssetHeader hook
|
||||
raw_file->buffer = allocator.duplicate_string(data);
|
||||
raw_file->len = static_cast<int>(data.length());
|
||||
|
||||
loaded_scripts[name] = rawfile;
|
||||
loaded_scripts[name] = raw_file;
|
||||
|
||||
game::Scr_LoadScript(game::SCRIPTINSTANCE_SERVER, base_name.data());
|
||||
}
|
||||
@ -108,11 +107,11 @@ namespace script
|
||||
load_scripts_folder((host.get_folder() / "boiii/scripts").string());
|
||||
}
|
||||
|
||||
game::RawFile* db_findxassetheader_stub(const game::XAssetType type, const char* name,
|
||||
game::RawFile* db_find_x_asset_header_stub(const game::XAssetType type, const char* name,
|
||||
const bool error_if_missing,
|
||||
const int wait_time)
|
||||
{
|
||||
auto* asset_header = db_findxassetheader_hook.invoke<game::RawFile*>(
|
||||
auto* asset_header = db_find_x_asset_header_hook.invoke<game::RawFile*>(
|
||||
type, name, error_if_missing, wait_time);
|
||||
|
||||
if (type != game::ASSET_TYPE_SCRIPTPARSETREE)
|
||||
|
47
src/client/component/status.cpp
Normal file
47
src/client/component/status.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
#include <game/game.hpp>
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
|
||||
namespace status
|
||||
{
|
||||
namespace
|
||||
{
|
||||
thread_local int g_client_num{0};
|
||||
|
||||
void print_client_num(const int channel, const int label, const char* fmt, const int client_num)
|
||||
{
|
||||
g_client_num = client_num;
|
||||
game::Com_Printf(channel, label, fmt, client_num);
|
||||
}
|
||||
|
||||
void print_client_xuid(const int channel, const int label, [[maybe_unused]] const char* fmt, const uint64_t xuid)
|
||||
{
|
||||
if (game::SV_IsTestClient(g_client_num))
|
||||
{
|
||||
game::Com_Printf(channel, label, "%16s ", "bot0");
|
||||
return;
|
||||
}
|
||||
|
||||
game::Com_Printf(channel, label, "%12llx ", xuid);
|
||||
}
|
||||
}
|
||||
|
||||
struct component final : generic_component
|
||||
{
|
||||
void post_unpack() override
|
||||
{
|
||||
// Patch the status command for test clients
|
||||
utils::hook::call(game::select(0x142246E37, 0x14052C527), print_client_num);
|
||||
utils::hook::call(game::select(0x142246EDE, 0x14052C5CE), print_client_xuid);
|
||||
|
||||
utils::hook::copy_string(game::select(0x143050480, 0x140E85A20),
|
||||
"num score ping xuid name address qport \n");
|
||||
utils::hook::copy_string(game::select(0x1430504E0, 0x140E85A80),
|
||||
"--- ----- ---- ---------------- ---------------- ------------------------ ------ \n");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
REGISTER_COMPONENT(status::component)
|
@ -890,7 +890,7 @@ namespace game
|
||||
|
||||
enum LobbyType
|
||||
{
|
||||
LOBBY_TYPE_INVALID = 0xFFFFFFFF,
|
||||
LOBBY_TYPE_INVALID = -1,
|
||||
LOBBY_TYPE_PRIVATE = 0x0,
|
||||
LOBBY_TYPE_GAME = 0x1,
|
||||
LOBBY_TYPE_TRANSITION = 0x2,
|
||||
@ -900,6 +900,14 @@ namespace game
|
||||
LOBBY_TYPE_AUTO = 0x3,
|
||||
};
|
||||
|
||||
enum LobbyClientType
|
||||
{
|
||||
LOBBY_CLIENT_TYPE_INVALID = -1,
|
||||
LOBBY_CLIENT_TYPE_ALL = 0x0,
|
||||
LOBBY_CLIENT_TYPE_LOCAL = 0x1,
|
||||
LOBBY_CLIENT_TYPE_REMOTE = 0x2,
|
||||
};
|
||||
|
||||
enum LobbyNetworkMode
|
||||
{
|
||||
LOBBY_NETWORKMODE_INVALID = 0xFFFFFFFF,
|
||||
@ -1579,9 +1587,19 @@ namespace game
|
||||
SV_CMD_RELIABLE_0 = 0x1,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CS_FREE = 0x0,
|
||||
CS_ZOMBIE = 0x1,
|
||||
CS_RECONNECTING = 0x2,
|
||||
CS_CONNECTED = 0x3,
|
||||
CS_CLIENTLOADING = 0x4,
|
||||
CS_ACTIVE = 0x5,
|
||||
};
|
||||
|
||||
struct client_s
|
||||
{
|
||||
int client_state;
|
||||
int state;
|
||||
char __pad0[0x28];
|
||||
netadr_t address;
|
||||
char __pad1[20468];
|
||||
@ -1600,7 +1618,6 @@ namespace game
|
||||
char __pad6[171432];
|
||||
};
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
static_assert(sizeof(client_s) == 0xE5110);
|
||||
|
||||
@ -1637,14 +1654,23 @@ namespace game
|
||||
struct EntityState
|
||||
{
|
||||
int number;
|
||||
};
|
||||
}; // Incomplete
|
||||
|
||||
struct gentity_s
|
||||
{
|
||||
EntityState s;
|
||||
unsigned char __pad0[0x24C];
|
||||
gclient_s* client;
|
||||
unsigned char __pad1[0x2A0];
|
||||
unsigned char __pad1[0x17C];
|
||||
struct
|
||||
{
|
||||
unsigned int notifyString;
|
||||
unsigned int index;
|
||||
unsigned char stoppable;
|
||||
int basetime;
|
||||
int duration;
|
||||
} snd_wait;
|
||||
unsigned char __pad2[0x110];
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -4,11 +4,6 @@
|
||||
|
||||
namespace game
|
||||
{
|
||||
eModes Com_SessionMode_GetMode()
|
||||
{
|
||||
return eModes(*reinterpret_cast<uint32_t*>(game::select(0x1568ED7F4, 0x14948DB04)) << 28 >> 28);
|
||||
}
|
||||
|
||||
bool I_islower(int c)
|
||||
{
|
||||
return c >= 'a' && c <= 'z';
|
||||
|
@ -8,6 +8,10 @@ namespace game
|
||||
{
|
||||
#define Com_Error(code, fmt, ...) Com_Error_(__FILE__, __LINE__, code, fmt, ##__VA_ARGS__)
|
||||
|
||||
// CG
|
||||
WEAK symbol<void(int localClientNum, float* fov_x, float* dxDzAtDefaultAspectRatio, float* dxDz, float* dyDz)>
|
||||
CG_CalcFOVfromLens{0x1404D6230};
|
||||
|
||||
// CL
|
||||
WEAK symbol<void(int controllerIndex, XSESSION_INFO* hostInfo, const netadr_t* addr, int numPublicSlots,
|
||||
int numPrivateSlots, const char* mapname, const char* gametype,
|
||||
@ -25,6 +29,8 @@ namespace game
|
||||
WEAK symbol<void(int channel, unsigned int label, const char* fmt, ...)> Com_Printf{0x142148F60, 0x140505630};
|
||||
WEAK symbol<void(const char* file, int line, int code, const char* fmt, ...)> Com_Error_{0x1420F8170, 0x140501470};
|
||||
WEAK symbol<bool(eModes mode)> Com_SessionMode_IsMode{0x1420F7370};
|
||||
WEAK symbol<int()> Com_SessionMode_GetMode{0x1420F6D30 , 0x1405002D0};
|
||||
WEAK symbol<int()> Com_SessionMode_GetGameMode{0x1420F68B0, 0x1404FFE50};
|
||||
WEAK symbol<void(eNetworkModes networkMode)> Com_SessionMode_SetNetworkMode{0x1420F75B0, 0x140500B80};
|
||||
WEAK symbol<eGameModes(eGameModes gameMode)> Com_SessionMode_SetGameMode{0x1420F7570, 0x140500B40};
|
||||
WEAK symbol<eModes(eModes mode)> Com_SessionMode_SetMode{0x1420F7570};
|
||||
@ -132,7 +138,7 @@ namespace game
|
||||
};
|
||||
WEAK symbol<dvar_t*(dvarStrHash_t hash, const char* dvarName, int value, int min, int max, unsigned int flags,
|
||||
const char* description)> Dvar_RegisterInt{
|
||||
0x0, 0x14057B7B0
|
||||
0x1422D0AE0, 0x14057B7B0
|
||||
};
|
||||
WEAK symbol<dvar_t*(dvarStrHash_t hash, const char* dvarName, float value, float min, float max, unsigned int flags,
|
||||
const char* description)> Dvar_RegisterFloat{
|
||||
@ -158,7 +164,9 @@ namespace game
|
||||
};
|
||||
|
||||
// UI
|
||||
WEAK symbol<void(int localClientNumber, int errorcode, const char* errorMessage)> UI_OpenErrorPopupWithMessage{0x14228DEE0};
|
||||
WEAK symbol<void(int localClientNumber, int errorcode, const char* errorMessage)> UI_OpenErrorPopupWithMessage{
|
||||
0x14228DEE0
|
||||
};
|
||||
WEAK symbol<void(bool frontend)> UI_CoD_Init{0x141F29010, 0x1404A0A50};
|
||||
WEAK symbol<void()> UI_CoD_LobbyUI_Init{0x141F2BD80, 0x1404A1F50};
|
||||
WEAK symbol<void()> UI_CoD_Shutdown{0x141F32E10, 0x0};
|
||||
@ -206,10 +214,20 @@ namespace game
|
||||
};
|
||||
WEAK symbol<void(const char* text_in)> SV_Cmd_TokenizeString{0x1420EF130, 0x1404FA6C0};
|
||||
WEAK symbol<void()> SV_Cmd_EndTokenizedString{0x1420EF0E0, 0x1404FA670};
|
||||
WEAK symbol<void(void* client, msg_t* msg)> SV_ExecuteClientMessage{0x14224A460, 0x14052F840};
|
||||
|
||||
WEAK symbol<void(void* drop, const char* reason, bool tellThem, bool removeFromLobby)> SV_DropClient{
|
||||
0x14224A050, 0x14052F430
|
||||
};
|
||||
|
||||
// FS
|
||||
WEAK symbol<char*(int bytes)> FS_AllocMem{0x1422AC9F0, 0x14056C340};
|
||||
|
||||
// Lobby
|
||||
WEAK symbol<int(LobbyType lobbyType, LobbyClientType clientType)> LobbyHost_GetClientCount{
|
||||
0x141ED8AC0, 0x14048A360
|
||||
};
|
||||
|
||||
// Utils
|
||||
WEAK symbol<const char*(char* str)> I_CleanStr{0x1422E9050, 0x140580E80};
|
||||
WEAK symbol<void(char* dest, size_t destsize, const char* src)> I_strcpy{
|
||||
@ -265,8 +283,6 @@ namespace game
|
||||
constexpr auto CMD_MAX_NESTING = 8;
|
||||
|
||||
// Re-implementations
|
||||
eModes Com_SessionMode_GetMode();
|
||||
|
||||
bool I_islower(int c);
|
||||
bool I_isupper(int c);
|
||||
|
||||
|
@ -136,11 +136,10 @@ namespace game
|
||||
}
|
||||
|
||||
auto* dvar_to_change = dvar;
|
||||
|
||||
if (dvar_to_change->type == DVAR_TYPE_SESSIONMODE_BASE_DVAR)
|
||||
{
|
||||
const auto mode = Com_SessionMode_GetMode();
|
||||
dvar_to_change = Dvar_GetSessionModeSpecificDvar(dvar_to_change, mode);
|
||||
dvar_to_change = Dvar_GetSessionModeSpecificDvar(dvar_to_change, static_cast<eModes>(mode));
|
||||
}
|
||||
|
||||
dvar_to_change->flags |= flags;
|
||||
@ -156,11 +155,10 @@ namespace game
|
||||
}
|
||||
|
||||
auto* dvar_to_change = dvar;
|
||||
|
||||
if (dvar_to_change->type == DVAR_TYPE_SESSIONMODE_BASE_DVAR)
|
||||
{
|
||||
const auto mode = Com_SessionMode_GetMode();
|
||||
dvar_to_change = Dvar_GetSessionModeSpecificDvar(dvar_to_change, mode);
|
||||
dvar_to_change = Dvar_GetSessionModeSpecificDvar(dvar_to_change, static_cast<eModes>(mode));
|
||||
}
|
||||
|
||||
dvar_to_change->flags = flags;
|
||||
@ -205,7 +203,7 @@ namespace game
|
||||
}
|
||||
|
||||
auto& client = client_states[index];
|
||||
if (client.client_state <= 0)
|
||||
if (client.state == CS_FREE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -238,7 +236,7 @@ namespace game
|
||||
{
|
||||
foreach_client([&](client_s& client, const size_t index)
|
||||
{
|
||||
if (client.client_state > 0)
|
||||
if (client.state != CS_FREE)
|
||||
{
|
||||
callback(client, index);
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ namespace utils::hook
|
||||
|
||||
uint8_t* allocate_somewhere_near(const void* base_address, const size_t granularity, const size_t size)
|
||||
{
|
||||
size_t target_address = reinterpret_cast<size_t>(base_address) - (1ull << 31);
|
||||
size_t target_address = reinterpret_cast<size_t>(base_address) - (1ull << 31);
|
||||
target_address &= ~(granularity - 1);
|
||||
|
||||
while (true)
|
||||
@ -415,7 +415,12 @@ namespace utils::hook
|
||||
|
||||
bool is_relatively_far(const void* pointer, const void* data, const int offset)
|
||||
{
|
||||
const int64_t diff = reinterpret_cast<size_t>(data) - (reinterpret_cast<size_t>(pointer) + offset);
|
||||
return is_relatively_far(reinterpret_cast<size_t>(pointer), reinterpret_cast<size_t>(data), offset);
|
||||
}
|
||||
|
||||
bool is_relatively_far(const size_t pointer, const size_t data, const int offset)
|
||||
{
|
||||
const auto diff = static_cast<int64_t>(data - (pointer + offset));
|
||||
const auto small_diff = static_cast<int32_t>(diff);
|
||||
return diff != static_cast<int64_t>(small_diff);
|
||||
}
|
||||
@ -534,19 +539,25 @@ namespace utils::hook
|
||||
return result;
|
||||
}
|
||||
|
||||
void inject(void* pointer, const void* data)
|
||||
void inject(size_t pointer, size_t data)
|
||||
{
|
||||
if (is_relatively_far(pointer, data, 4))
|
||||
{
|
||||
throw std::runtime_error("Too far away to create 32bit relative branch");
|
||||
}
|
||||
|
||||
set<int32_t>(pointer, int32_t(size_t(data) - (size_t(pointer) + 4)));
|
||||
set<int32_t>(
|
||||
pointer, static_cast<int32_t>(data - (pointer + 4)));
|
||||
}
|
||||
|
||||
void inject(void* pointer, const void* data)
|
||||
{
|
||||
return inject(reinterpret_cast<size_t>(pointer), reinterpret_cast<size_t>(data));
|
||||
}
|
||||
|
||||
void inject(const size_t pointer, const void* data)
|
||||
{
|
||||
return inject(reinterpret_cast<void*>(pointer), data);
|
||||
return inject(pointer, reinterpret_cast<size_t>(data));
|
||||
}
|
||||
|
||||
std::vector<uint8_t> move_hook(void* pointer)
|
||||
|
@ -162,6 +162,7 @@ namespace utils::hook
|
||||
void copy_string(size_t place, const char* str);
|
||||
|
||||
bool is_relatively_far(const void* pointer, const void* data, int offset = 5);
|
||||
bool is_relatively_far(size_t pointer, size_t data, int offset = 5);
|
||||
|
||||
void call(void* pointer, void* data);
|
||||
void call(size_t pointer, void* data);
|
||||
@ -175,6 +176,7 @@ namespace utils::hook
|
||||
|
||||
void inject(void* pointer, const void* data);
|
||||
void inject(size_t pointer, const void* data);
|
||||
void inject(size_t pointer, size_t data);
|
||||
|
||||
std::vector<uint8_t> move_hook(void* pointer);
|
||||
std::vector<uint8_t> move_hook(size_t pointer);
|
||||
|
Loading…
Reference in New Issue
Block a user