Merge branch 'main' into scripts
This commit is contained in:
commit
0916d71204
Binary file not shown.
@ -1,4 +1,5 @@
|
||||
#using scripts\codescripts\struct;
|
||||
|
||||
#using scripts\shared\array_shared;
|
||||
#using scripts\shared\callbacks_shared;
|
||||
#using scripts\shared\killstreaks_shared;
|
||||
@ -7,12 +8,14 @@
|
||||
#using scripts\shared\system_shared;
|
||||
#using scripts\shared\util_shared;
|
||||
#using scripts\shared\weapons_shared;
|
||||
|
||||
#using scripts\shared\weapons\_weapons;
|
||||
|
||||
#using scripts\shared\bots\_bot;
|
||||
#using scripts\shared\bots\_bot_combat;
|
||||
#using scripts\shared\bots\bot_traversals;
|
||||
#using scripts\shared\bots\bot_buttons;
|
||||
#using scripts\shared\bots\bot_traversals;
|
||||
|
||||
#using scripts\mp\bots\_bot_ball;
|
||||
#using scripts\mp\bots\_bot_clean;
|
||||
#using scripts\mp\bots\_bot_combat;
|
||||
@ -25,8 +28,7 @@
|
||||
#using scripts\mp\bots\_bot_koth;
|
||||
#using scripts\mp\bots\_bot_loadout;
|
||||
#using scripts\mp\bots\_bot_sd;
|
||||
#using scripts\mp\killstreaks\_killstreakrules;
|
||||
#using scripts\mp\killstreaks\_killstreaks;
|
||||
|
||||
#using scripts\mp\killstreaks\_ai_tank;
|
||||
#using scripts\mp\killstreaks\_airsupport;
|
||||
#using scripts\mp\killstreaks\_combat_robot;
|
||||
@ -66,11 +68,14 @@
|
||||
#define MAX_ONLINE_PLAYERS 18
|
||||
#define MAX_ONLINE_PLAYERS_PER_TEAM 6
|
||||
|
||||
#define RESPAWN_DELAY 0
|
||||
#define RESPAWN_INTERVAL 0.2
|
||||
#define RESPAWN_DELAY 0.1
|
||||
#define RESPAWN_INTERVAL 0.1
|
||||
|
||||
#namespace bot;
|
||||
|
||||
#precache("eventstring", "mpl_killstreak_cruisemissile");
|
||||
#precache("eventstring", "mpl_killstreak_raps");
|
||||
|
||||
REGISTER_SYSTEM("bot_mp", &__init__, undefined)
|
||||
|
||||
function __init__()
|
||||
@ -93,7 +98,13 @@ function __init__()
|
||||
|
||||
level.botIgnoreThreat = &bot_combat::bot_ignore_threat;
|
||||
|
||||
level.enemyEmpActive = &emp::EnemyEmpActive;
|
||||
level.enemyEmpActive = &emp::enemyEmpActive;
|
||||
|
||||
/#
|
||||
level.botDevguiCmd = &bot_devgui_cmd;
|
||||
level thread system_devgui_gadget_think();
|
||||
#/
|
||||
setDvar("bot_enableWallrun", 1);
|
||||
}
|
||||
|
||||
function init()
|
||||
@ -101,8 +112,7 @@ function init()
|
||||
level endon("game_ended");
|
||||
|
||||
level.botSoak = is_bot_soak();
|
||||
|
||||
if( level.rankedmatch && level.botsoak || !init_bot_gametype() )
|
||||
if (!init_bot_gametype())
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -117,18 +127,13 @@ function init()
|
||||
|
||||
function is_bot_soak()
|
||||
{
|
||||
return IsDedicated() && GetDvarInt( "sv_botsoak", 0 );
|
||||
return getDvarInt("sv_botsoak", 0);
|
||||
}
|
||||
|
||||
function wait_for_host()
|
||||
{
|
||||
level endon("game_ended");
|
||||
|
||||
if ( level.botSoak )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
host = util::getHostPlayerForBots();
|
||||
|
||||
while (!isdefined(host))
|
||||
@ -155,7 +160,6 @@ function is_bot_comp_stomp()
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Bot Events
|
||||
//========================================
|
||||
|
||||
@ -194,6 +198,31 @@ function on_bot_connect()
|
||||
function on_bot_spawned()
|
||||
{
|
||||
self.bot.goalTag = undefined;
|
||||
/#
|
||||
weapon = undefined;
|
||||
|
||||
if (getDvarInt("scr_botsHasPlayerWeapon") != 0)
|
||||
{
|
||||
player = util::getHostPlayer();
|
||||
weapon = player getCurrentWeapon();
|
||||
}
|
||||
|
||||
if (getDvarString("devgui_bot_weapon", "") != "")
|
||||
{
|
||||
weapon = getWeapon(getDvarString("devgui_bot_weapon"));
|
||||
}
|
||||
|
||||
if (isdefined(weapon) && level.weaponNone != weapon)
|
||||
{
|
||||
self weapons::detach_all_weapons();
|
||||
self takeAllWeapons();
|
||||
self giveWeapon(weapon);
|
||||
self switchToWeapon(weapon);
|
||||
self setSpawnWeapon(weapon);
|
||||
|
||||
self teams::set_player_model(self.team, weapon);
|
||||
}
|
||||
#/
|
||||
}
|
||||
|
||||
function on_bot_killed()
|
||||
@ -246,7 +275,7 @@ function bot_idle()
|
||||
|
||||
function do_supplydrop(maxRange = 1400) // A little under minimap width
|
||||
{
|
||||
crates = GetEntArray( "care_package", "script_noteworthy" );
|
||||
crates = getEntArray("care_package", "script_noteworthy");
|
||||
|
||||
maxRangeSq = maxRange * maxRange;
|
||||
|
||||
@ -257,12 +286,12 @@ function do_supplydrop( maxRange = 1400 ) // A little under minimap width
|
||||
|
||||
foreach(crate in crates)
|
||||
{
|
||||
if ( !crate IsOnGround() )
|
||||
if (!crate isOnGround())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
crateDistSq = Distance2DSquared( self.origin, crate.origin );
|
||||
crateDistSq = distance2DSquared(self.origin, crate.origin);
|
||||
|
||||
if (crateDistSq > maxRangeSq)
|
||||
{
|
||||
@ -282,7 +311,7 @@ function do_supplydrop( maxRange = 1400 ) // A little under minimap width
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( !self has_minimap() && !self BotSightTracePassed( crate ) )
|
||||
if (!self has_minimap() && !self botSightTracePassed(crate))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -296,12 +325,12 @@ function do_supplydrop( maxRange = 1400 ) // A little under minimap width
|
||||
|
||||
if (isdefined(closestCrate))
|
||||
{
|
||||
randomAngle = ( 0, RandomInt( 360 ), 0 );
|
||||
randomAngle = (0, randomInt(360), 0);
|
||||
randomVec = AnglesToForward(randomAngle);
|
||||
|
||||
point = closestCrate.origin + randomVec * CRATE_GOAL_RADIUS;
|
||||
|
||||
if ( self BotSetGoal( point ) )
|
||||
if (self botSetGoal(point))
|
||||
{
|
||||
self thread watch_crate(closestCrate);
|
||||
return true;
|
||||
@ -322,7 +351,7 @@ function watch_crate( crate )
|
||||
wait level.botSettings.thinkInterval;
|
||||
}
|
||||
|
||||
self BotSetGoal( self.origin );
|
||||
self botSetGoal(self.origin);
|
||||
}
|
||||
|
||||
// Bot Team Population
|
||||
@ -334,14 +363,14 @@ function populate_bots()
|
||||
|
||||
if (level.teambased)
|
||||
{
|
||||
maxAllies = GetDvarInt( "bot_maxAllies", 0 );
|
||||
maxAxis = GetDvarInt( "bot_maxAxis", 0 );
|
||||
maxAllies = getDvarInt("bot_maxAllies", 0);
|
||||
maxAxis = getDvarInt("bot_maxAxis", 0);
|
||||
|
||||
level thread monitor_bot_team_population(maxAllies, maxAxis);
|
||||
}
|
||||
else
|
||||
{
|
||||
maxFree = GetDvarInt( "bot_maxFree", 0 );
|
||||
maxFree = getDvarInt("bot_maxFree", 0);
|
||||
|
||||
level thread monitor_bot_population(maxFree);
|
||||
}
|
||||
@ -363,8 +392,8 @@ function monitor_bot_team_population( maxAllies, maxAxis )
|
||||
wait 3;
|
||||
|
||||
// TODO: Get a player count that includes 'CON_CONNECTING' players
|
||||
allies = GetPlayers( "allies" );
|
||||
axis = GetPlayers( "axis" );
|
||||
allies = getPlayers("allies");
|
||||
axis = getPlayers("axis");
|
||||
|
||||
if (allies.size > maxAllies &&
|
||||
remove_best_bot(allies))
|
||||
@ -387,16 +416,16 @@ function monitor_bot_team_population( maxAllies, maxAxis )
|
||||
|
||||
function fill_balanced_teams(maxAllies, maxAxis)
|
||||
{
|
||||
allies = GetPlayers( "allies" );
|
||||
axis = GetPlayers( "axis" );
|
||||
allies = getPlayers("allies");
|
||||
axis = getPlayers("axis");
|
||||
|
||||
while ((allies.size < maxAllies || axis.size < maxAxis) &&
|
||||
add_balanced_bot(allies, maxAllies, axis, maxAxis))
|
||||
{
|
||||
WAIT_SERVER_FRAME;
|
||||
|
||||
allies = GetPlayers( "allies" );
|
||||
axis = GetPlayers( "axis" );
|
||||
allies = getPlayers("allies");
|
||||
axis = getPlayers("axis");
|
||||
}
|
||||
}
|
||||
|
||||
@ -427,12 +456,12 @@ function monitor_bot_population( maxFree )
|
||||
}
|
||||
|
||||
// Initial Fill
|
||||
players = GetPlayers( );
|
||||
players = getPlayers();
|
||||
while (players.size < maxFree)
|
||||
{
|
||||
add_bot();
|
||||
WAIT_SERVER_FRAME;
|
||||
players = GetPlayers( );
|
||||
players = getPlayers();
|
||||
}
|
||||
|
||||
while (1)
|
||||
@ -440,7 +469,7 @@ function monitor_bot_population( maxFree )
|
||||
wait 3;
|
||||
|
||||
// TODO: Get a player count that includes 'CON_CONNECTING' players
|
||||
players = GetPlayers( );
|
||||
players = getPlayers();
|
||||
|
||||
if (players.size < maxFree)
|
||||
{
|
||||
@ -481,11 +510,11 @@ function remove_best_bot( players )
|
||||
|
||||
if (bestBots.size)
|
||||
{
|
||||
remove_bot( bestBots[RandomInt( bestBots.size )] );
|
||||
remove_bot(bestBots[randomInt(bestBots.size)]);
|
||||
}
|
||||
else
|
||||
{
|
||||
remove_bot( bots[RandomInt( bots.size )] );
|
||||
remove_bot(bots[randomInt(bots.size)]);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -503,13 +532,13 @@ function choose_class()
|
||||
|
||||
currClass = self bot_loadout::get_current_class();
|
||||
|
||||
if ( !isdefined( currClass ) || RandomInt( 100 ) < VAL( level.botSettings.changeClassWeight, 0 ) )
|
||||
if (!isdefined(currClass) || randomInt(100) < VAL(level.botSettings.changeClassWeight, 0))
|
||||
{
|
||||
classIndex = RandomInt( self.loadoutClasses.size );
|
||||
classIndex = randomInt(self.loadoutClasses.size);
|
||||
className = self.loadoutClasses[classIndex].name;
|
||||
}
|
||||
|
||||
if ( !isdefined(className) || className === currClass )
|
||||
if (!isdefined(className) || className == currClass)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -525,13 +554,13 @@ function choose_class()
|
||||
function use_killstreak()
|
||||
{
|
||||
if (!level.loadoutKillstreaksEnabled ||
|
||||
self emp::EnemyEMPActive() )
|
||||
self emp::enemyEmpActive())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
weapons = self GetWeaponsList();
|
||||
inventoryWeapon = self GetInventoryWeapon();
|
||||
weapons = self getWeaponsList();
|
||||
inventoryWeapon = self getInventoryWeapon();
|
||||
|
||||
foreach(weapon in weapons)
|
||||
{
|
||||
@ -542,7 +571,7 @@ function use_killstreak()
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( weapon != inventoryWeapon && !self GetWeaponAmmoClip( weapon ) )
|
||||
if (weapon != inventoryWeapon && !self getWeaponAmmoClip(weapon))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -565,25 +594,27 @@ function use_killstreak()
|
||||
{
|
||||
case "killstreak_uav":
|
||||
case "killstreak_counteruav":
|
||||
case "killstreak_remote_missile":
|
||||
{
|
||||
self switchtoweapon( weapon );
|
||||
self waittill( "weapon_change_complete" );
|
||||
wait 1.5;
|
||||
self bot::press_attack_button();
|
||||
}
|
||||
return;
|
||||
case "killstreak_satellite":
|
||||
case "killstreak_helicopter_player_gunner":
|
||||
case "killstreak_ai_tank_drop":
|
||||
self use_supply_drop( weapon );
|
||||
break;
|
||||
case "killstreak_raps":
|
||||
case "killstreak_sentinel":
|
||||
{
|
||||
self switchtoweapon(useweapon);
|
||||
self switchToWeapon(useWeapon);
|
||||
break;
|
||||
}
|
||||
case "killstreak_ai_tank_drop":
|
||||
{
|
||||
self use_supply_drop(weapon);
|
||||
break;
|
||||
}
|
||||
case "killstreak_remote_missile":
|
||||
{
|
||||
self switchToWeapon(weapon);
|
||||
self waittill("weapon_change_complete");
|
||||
wait 1.5;
|
||||
self bot::press_attack_button();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -632,16 +663,16 @@ function use_supply_drop( weapon )
|
||||
|
||||
wait 0.5;
|
||||
|
||||
if ( self getcurrentweapon() != weapon )
|
||||
if (self getCurrentWeapon() != weapon)
|
||||
{
|
||||
self thread weapon_switch_failsafe();
|
||||
self switchtoweapon( weapon );
|
||||
self switchToWeapon(weapon);
|
||||
|
||||
self waittill("weapon_change_complete");
|
||||
}
|
||||
|
||||
use_item(weapon);
|
||||
self switchtoweapon( self.lastnonkillstreakweapon );
|
||||
self switchToWeapon(self.lastnonkillstreakweapon);
|
||||
self clearlookat();
|
||||
self cancelgoal("killstreak");
|
||||
}
|
||||
@ -653,7 +684,7 @@ function use_item( weapon )
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
if ( self getcurrentweapon() == weapon || self getcurrentweapon() == "none" )
|
||||
if (self getCurrentWeapon() == weapon || self getCurrentWeapon() == "none")
|
||||
self bot::press_attack_button();
|
||||
else
|
||||
return;
|
||||
@ -662,6 +693,52 @@ function use_item( weapon )
|
||||
}
|
||||
}
|
||||
|
||||
function killstreak_location(num, weapon)
|
||||
{
|
||||
enemies = get_enemies();
|
||||
|
||||
if (!enemies.size)
|
||||
return;
|
||||
|
||||
if (!self switchToWeapon(weapon))
|
||||
return;
|
||||
|
||||
self waittill("weapon_change");
|
||||
|
||||
self util::freeze_player_controls(true);
|
||||
wait_time = 1;
|
||||
|
||||
while (!isdefined(self.selectinglocation) || self.selectinglocation == 0)
|
||||
{
|
||||
wait 0.05;
|
||||
wait_time -= 0.05;
|
||||
|
||||
if (wait_time <= 0)
|
||||
{
|
||||
self util::freeze_player_controls(false);
|
||||
self switchToWeapon(self.lastnonkillstreakweapon);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
wait 2;
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
enemies = get_enemies();
|
||||
|
||||
if (enemies.size)
|
||||
{
|
||||
enemy = randomInt(enemies);
|
||||
self notify("confirm_location", enemy.origin, 0);
|
||||
}
|
||||
|
||||
wait 0.25;
|
||||
}
|
||||
|
||||
self util::freeze_player_controls(false);
|
||||
}
|
||||
|
||||
function weapon_switch_failsafe()
|
||||
{
|
||||
self endon("death");
|
||||
@ -671,7 +748,6 @@ function weapon_switch_failsafe()
|
||||
self notify("weapon_change_complete");
|
||||
}
|
||||
|
||||
|
||||
function has_radar()
|
||||
{
|
||||
if (level.teambased)
|
||||
@ -706,18 +782,29 @@ function get_enemies( on_radar )
|
||||
|
||||
enemies = self GetEnemies();
|
||||
|
||||
/#
|
||||
for (i = 0; i < enemies.size; i++)
|
||||
{
|
||||
if (isplayer(enemies[i]) && enemies[i] isInMoveMode("ufo", "noclip"))
|
||||
{
|
||||
arrayRemoveIndex(enemies, i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
#/
|
||||
|
||||
if (on_radar && !self has_radar())
|
||||
{
|
||||
for (i = 0; i < enemies.size; i++)
|
||||
{
|
||||
if (!isdefined(enemies[i].lastFireTime))
|
||||
{
|
||||
ArrayRemoveIndex( enemies, i );
|
||||
arrayRemoveIndex(enemies, i);
|
||||
i--;
|
||||
}
|
||||
else if (GetTime() - enemies[i].lastFireTime > 2000)
|
||||
{
|
||||
ArrayRemoveIndex( enemies, i );
|
||||
arrayRemoveIndex(enemies, i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
@ -728,7 +815,7 @@ function get_enemies( on_radar )
|
||||
|
||||
function set_rank()
|
||||
{
|
||||
players = GetPlayers();
|
||||
players = getPlayers();
|
||||
|
||||
ranks = [];
|
||||
bot_ranks = [];
|
||||
@ -760,12 +847,12 @@ function set_rank()
|
||||
while (bot_ranks.size + human_ranks.size < 5)
|
||||
{
|
||||
// add some random ranks for better random number distribution
|
||||
r = human_avg + RandomIntRange( -5, 5 );
|
||||
r = human_avg + randomIntRange(-5, 5);
|
||||
rank = math::clamp(r, 0, level.maxRank);
|
||||
human_ranks[human_ranks.size] = rank;
|
||||
}
|
||||
|
||||
ranks = ArrayCombine( human_ranks, bot_ranks, true, false );
|
||||
ranks = arrayCombine(human_ranks, bot_ranks, true, false);
|
||||
|
||||
avg = math::array_average(ranks);
|
||||
s = math::array_std_deviation(ranks, avg);
|
||||
@ -786,69 +873,49 @@ function set_rank()
|
||||
|
||||
function init_bot_gametype()
|
||||
{
|
||||
switch(level.gametype)
|
||||
switch (level.gameType)
|
||||
{
|
||||
case "ball":
|
||||
{
|
||||
bot_ball::init();
|
||||
return true;
|
||||
}
|
||||
case "conf":
|
||||
{
|
||||
bot_conf::init();
|
||||
return true;
|
||||
}
|
||||
case "ctf":
|
||||
{
|
||||
bot_ctf::init();
|
||||
return true;
|
||||
}
|
||||
case "dem":
|
||||
{
|
||||
bot_dem::init();
|
||||
return true;
|
||||
}
|
||||
case "dm":
|
||||
{
|
||||
return true;
|
||||
}
|
||||
case "dom":
|
||||
{
|
||||
bot_dom::init();
|
||||
return true;
|
||||
}
|
||||
case "escort":
|
||||
{
|
||||
bot_escort::init();
|
||||
return true;
|
||||
}
|
||||
/* case "infect":
|
||||
{
|
||||
// case "infect":
|
||||
// return true;
|
||||
case "gun":
|
||||
return true;
|
||||
}
|
||||
*/ case "gun":
|
||||
{
|
||||
return true;
|
||||
}
|
||||
case "koth":
|
||||
{
|
||||
bot_koth::init();
|
||||
return true;
|
||||
}
|
||||
case "sd":
|
||||
{
|
||||
bot_sd::init();
|
||||
return true;
|
||||
}
|
||||
case "clean":
|
||||
{
|
||||
bot_clean::init();
|
||||
return true;
|
||||
}
|
||||
case "tdm":
|
||||
{
|
||||
return true;
|
||||
}
|
||||
case "sas":
|
||||
return true;
|
||||
case "prop":
|
||||
return true;
|
||||
case "sniperonly":
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -856,7 +923,7 @@ function init_bot_gametype()
|
||||
|
||||
function get_bot_settings()
|
||||
{
|
||||
switch ( GetDvarInt( "bot_difficulty", 1 ) )
|
||||
switch (getDvarInt("bot_difficulty", 1))
|
||||
{
|
||||
case 0:
|
||||
bundleName = "bot_mp_easy";
|
||||
@ -907,3 +974,144 @@ function dive_to_prone( exit_stance )
|
||||
|
||||
}
|
||||
|
||||
/#
|
||||
|
||||
// Devgui
|
||||
//========================================
|
||||
|
||||
function bot_devgui_cmd(cmd)
|
||||
{
|
||||
cmdTokens = strtok(cmd, " ");
|
||||
|
||||
if (cmdTokens.size == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
host = util::getHostPlayerForBots();
|
||||
team = get_host_team();
|
||||
|
||||
switch (cmdTokens[0])
|
||||
{
|
||||
case "spawn_enemy":
|
||||
team = util::getotherteam(team);
|
||||
case "spawn_friendly":
|
||||
count = 1;
|
||||
if (cmdTokens.size > 1)
|
||||
{
|
||||
count = int(cmdTokens[1]);
|
||||
}
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
add_bot(team);
|
||||
}
|
||||
return true;
|
||||
case "remove_enemy":
|
||||
team = util::getotherteam(team);
|
||||
case "remove_friendly":
|
||||
remove_bots(undefined, team);
|
||||
return true;
|
||||
case "fixed_spawn_enemy":
|
||||
team = util::getotherteam(team);
|
||||
case "fixed_spawn_friendly":
|
||||
bot = add_bot_at_eye_trace(team);
|
||||
if (isdefined(bot))
|
||||
{
|
||||
bot thread fixed_spawn_override();
|
||||
}
|
||||
return true;
|
||||
|
||||
case "player_weapon":
|
||||
players = getPlayers();
|
||||
foreach(player in players)
|
||||
{
|
||||
if (!player util::is_bot())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
weapon = host getCurrentWeapon();
|
||||
|
||||
player weapons::detach_all_weapons();
|
||||
player takeAllWeapons();
|
||||
player giveWeapon(weapon);
|
||||
player switchToWeapon(weapon);
|
||||
player setSpawnWeapon(weapon);
|
||||
|
||||
player teams::set_player_model(player.team, weapon);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function system_devgui_gadget_think()
|
||||
{
|
||||
setDvar("devgui_bot_gadget", "");
|
||||
|
||||
for (;; )
|
||||
{
|
||||
wait(1);
|
||||
|
||||
gadget = getDvarString("devgui_bot_gadget");
|
||||
|
||||
if (gadget.size == 0)
|
||||
{
|
||||
bot_turn_on_gadget(getWeapon(gadget));
|
||||
setDvar("devgui_bot_gadget", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function bot_turn_on_gadget(gadget)
|
||||
{
|
||||
players = getPlayers();
|
||||
|
||||
foreach(player in players)
|
||||
{
|
||||
if (!player util::is_bot())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
host = util::getHostPlayer();
|
||||
weapon = host getCurrentWeapon();
|
||||
|
||||
if (!isdefined(weapon) || weapon == level.weaponNone || weapon == level.weaponNull)
|
||||
{
|
||||
weapon = getWeapon("smg_standard");
|
||||
}
|
||||
|
||||
player weapons::detach_all_weapons();
|
||||
player takeAllWeapons();
|
||||
player giveWeapon(weapon);
|
||||
player switchToWeapon(weapon);
|
||||
player setSpawnWeapon(weapon);
|
||||
|
||||
player teams::set_player_model(player.team, weapon);
|
||||
|
||||
player giveWeapon(gadget);
|
||||
slot = player gadgetGetSlot(gadget);
|
||||
player gadgetPowerSet(slot, 100.0);
|
||||
player botPressButtonForGadget(gadget);
|
||||
}
|
||||
}
|
||||
|
||||
function fixed_spawn_override()
|
||||
{
|
||||
self endon("disconnect");
|
||||
|
||||
spawnOrigin = self.origin;
|
||||
spawnAngles = self.angles;
|
||||
|
||||
while (1)
|
||||
{
|
||||
self waittill("spawned_player");
|
||||
|
||||
self setOrigin(spawnOrigin);
|
||||
self setPlayerAngles(spawnAngles);
|
||||
}
|
||||
}
|
||||
|
||||
#/
|
||||
|
@ -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,6 +117,7 @@ DataSources.MPStatsSettings = DataSourceHelpers.ListSetup("MPStatsSettings", fun
|
||||
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",
|
||||
@ -117,45 +132,76 @@ DataSources.MPStatsSettings = DataSourceHelpers.ListSetup("MPStatsSettings", fun
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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 = value,
|
||||
name = value <= minlevel and "Min" or value >= maxlevel and "Max" or value,
|
||||
value = value - 1,
|
||||
default = value == currentRank,
|
||||
title = "Rank Level",
|
||||
desc = ""
|
||||
desc = value ~= currentRank and "" or "Current Rank"
|
||||
})
|
||||
if not hasDefault then
|
||||
hasDefault = value == currentRank
|
||||
end
|
||||
end
|
||||
|
||||
if not hasDefault then
|
||||
if hasDefault and currentRank ~= minlevel and currentRank < maxlevel and not isMasterPrestige then
|
||||
table.insert(rankObjs, {
|
||||
name = currentRank,
|
||||
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,8 +134,8 @@ namespace auth
|
||||
|
||||
const auto& fragment_packet = packet_buffer.get_buffer();
|
||||
|
||||
game::NET_OutOfBandData(
|
||||
sock, adr, fragment_packet.data(),
|
||||
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>
|
||||
@ -96,7 +97,7 @@ 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 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,6 +149,8 @@ namespace bots
|
||||
}
|
||||
}
|
||||
|
||||
scheduler::once([count]
|
||||
{
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
{
|
||||
if (!game::SV_AddTestClient())
|
||||
@ -154,6 +158,7 @@ namespace bots
|
||||
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);
|
||||
}
|
||||
|
@ -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…
x
Reference in New Issue
Block a user