add weapon inspect and actionslot 8

This commit is contained in:
quaK 2024-07-03 13:09:25 +03:00
parent 99db27c36d
commit c532fabff7
5 changed files with 636 additions and 151 deletions

View File

@ -1,150 +0,0 @@
#include <std_include.hpp>
#include "loader/component_loader.hpp"
#include "game/game.hpp"
#include <utils/hook.hpp>
#include <utils/string.hpp>
namespace binding
{
namespace
{
std::vector<std::string> custom_binds = {};
utils::hook::detour cl_execute_key_hook;
int get_num_keys()
{
return 118;
}
int key_write_bindings_to_buffer_stub(int, char* buffer, const int buffer_size)
{
auto bytes_used = 0;
const auto buffer_size_align = static_cast<std::int32_t>(buffer_size) - 4;
for (auto key_index = 0; key_index < 256; ++key_index)
{
const auto* const key_button = game::Key_KeynumToString(key_index, 0, 1);
auto value = game::playerKeys->keys[key_index].binding;
if (value && value < get_num_keys())
{
const auto len = sprintf_s(&buffer[bytes_used], (buffer_size_align - bytes_used),
"bind %s \"%s\"\n", key_button, game::command_whitelist[value]);
if (len < 0)
{
return bytes_used;
}
bytes_used += len;
}
else if (value >= get_num_keys())
{
value -= get_num_keys();
if (static_cast<size_t>(value) < custom_binds.size() && !custom_binds[value].empty())
{
const auto len = sprintf_s(&buffer[bytes_used], (buffer_size_align - bytes_used),
"bind %s \"%s\"\n", key_button, custom_binds[value].data());
if (len < 0)
{
return bytes_used;
}
bytes_used += len;
}
}
}
buffer[bytes_used] = 0;
return bytes_used;
}
int get_binding_for_custom_command(const char* command)
{
auto index = 0;
for (auto& bind : custom_binds)
{
if (bind == command)
{
return index;
}
index++;
}
custom_binds.emplace_back(command);
index = static_cast<unsigned int>(custom_binds.size()) - 1;
return index;
}
int key_get_binding_for_cmd_stub(const char* command)
{
// original binds
for (auto i = 0; i < get_num_keys(); i++)
{
if (game::command_whitelist[i] && !strcmp(command, game::command_whitelist[i]))
{
return i;
}
}
// custom binds
return get_num_keys() + get_binding_for_custom_command(command);
}
std::optional<std::string> get_custom_binding_for_key(int key)
{
key -= get_num_keys();
if (static_cast<size_t>(key) < custom_binds.size() && !custom_binds[key].empty())
{
return { custom_binds[key] };
}
return {};
}
void cl_execute_key_stub(const int local_client_num, int key, const int down, const unsigned int time)
{
if (key >= get_num_keys())
{
const auto bind = get_custom_binding_for_key(key);
if (!bind.has_value())
{
return;
}
return game::Cbuf_AddText(local_client_num, utils::string::va("%s\n", bind.value().data()));
}
cl_execute_key_hook.invoke<void>(local_client_num, key, down, time);
}
}
class component final : public component_interface
{
public:
void post_unpack() override
{
if (game::environment::is_dedi())
{
return;
}
// write all bindings to config file
utils::hook::jump(0x9A9F70_b, key_write_bindings_to_buffer_stub);
// links a custom command to an index
utils::hook::jump(0x9A8EA0_b, key_get_binding_for_cmd_stub);
// execute custom binds
cl_execute_key_hook.create(0x32A3B0_b, &cl_execute_key_stub);
}
};
}
REGISTER_COMPONENT(binding::component)

View File

@ -6,13 +6,20 @@
#include "game_console.hpp"
#include <utils/hook.hpp>
#include <utils/string.hpp>
namespace input
{
namespace
{
std::vector<std::string> custom_binds = {};
utils::hook::detour cl_char_event_hook;
utils::hook::detour cl_key_event_hook;
utils::hook::detour cl_execute_key_hook;
utils::hook::detour key_get_binding_for_key_hook;
int key_get_binding_for_cmd_stub(const char* command);
void cl_char_event_stub(const int local_client_num, const int key)
{
@ -32,6 +39,133 @@ namespace input
}
cl_key_event_hook.invoke<void>(local_client_num, key, down);
const auto key_catchers = *game::keyCatchers;
if (key_catchers != 0)
{
return;
}
auto binding = game::playerKeys->keys[key].binding;
static const auto binding1 = key_get_binding_for_cmd_stub("+actionslot 8");
if (binding == binding1)
{
if (!down)
{
binding = binding + 1;
}
utils::hook::invoke<void>(0x35DFB0_b, local_client_num, binding, key, 1); // CL_InputMP_ExecBinding
}
}
int get_num_keys()
{
return 118;
}
int key_write_bindings_to_buffer_stub(int, char* buffer, const int buffer_size)
{
auto bytes_used = 0;
const auto buffer_size_align = static_cast<std::int32_t>(buffer_size) - 4;
for (auto key_index = 0; key_index < 256; ++key_index)
{
const auto* const key_button = game::Key_KeynumToString(key_index, 0, 1);
auto value = game::playerKeys->keys[key_index].binding;
if (value && value < get_num_keys())
{
const auto len = sprintf_s(&buffer[bytes_used], (buffer_size_align - bytes_used),
"bind %s \"%s\"\n", key_button, game::command_whitelist[value]);
if (len < 0)
{
return bytes_used;
}
bytes_used += len;
}
else if (value >= get_num_keys())
{
value -= get_num_keys();
if (static_cast<size_t>(value) < custom_binds.size() && !custom_binds[value].empty())
{
const auto len = sprintf_s(&buffer[bytes_used], (buffer_size_align - bytes_used),
"bind %s \"%s\"\n", key_button, custom_binds[value].data());
if (len < 0)
{
return bytes_used;
}
bytes_used += len;
}
}
}
buffer[bytes_used] = 0;
return bytes_used;
}
int get_binding_for_custom_command(const char* command)
{
auto index = 0;
for (auto& bind : custom_binds)
{
if (bind == command)
{
return index;
}
index++;
}
custom_binds.emplace_back(command);
index = static_cast<unsigned int>(custom_binds.size()) - 1;
return index;
}
int key_get_binding_for_cmd_stub(const char* command)
{
// original binds
for (auto i = 0; i < get_num_keys(); i++)
{
if (game::command_whitelist[i] && !strcmp(command, game::command_whitelist[i]))
{
return i;
}
}
// custom binds
return get_num_keys() + get_binding_for_custom_command(command);
}
std::optional<std::string> get_custom_binding_for_key(int key)
{
key -= get_num_keys();
if (static_cast<size_t>(key) < custom_binds.size() && !custom_binds[key].empty())
{
return { custom_binds[key] };
}
return {};
}
void cl_execute_key_stub(const int local_client_num, int key, const int down, const unsigned int time)
{
if (key >= get_num_keys())
{
const auto bind = get_custom_binding_for_key(key);
if (!bind.has_value())
{
return;
}
return game::Cbuf_AddText(local_client_num, utils::string::va("%s\n", bind.value().data()));
}
cl_execute_key_hook.invoke<void>(local_client_num, key, down, time);
}
}
@ -47,6 +181,18 @@ namespace input
cl_char_event_hook.create(0x9A7350_b, cl_char_event_stub);
cl_key_event_hook.create(0x9A7980_b, cl_key_event_stub);
custom_binds.push_back("+actionslot 8");
custom_binds.push_back("-actionslot 8");
// write all bindings to config file
utils::hook::jump(0x9A9F70_b, key_write_bindings_to_buffer_stub);
// links a custom command to an index
utils::hook::jump(0x9A8EA0_b, key_get_binding_for_cmd_stub);
// execute custom binds
cl_execute_key_hook.create(0x32A3B0_b, &cl_execute_key_stub);
}
};
}

View File

@ -0,0 +1,318 @@
#include <std_include.hpp>
#include "loader/component_loader.hpp"
#include "game/game.hpp"
#include "game/dvars.hpp"
#include "command.hpp"
#include "console/console.hpp"
#include "scheduler.hpp"
#include "gsc/script_extension.hpp"
#include "gsc/script_error.hpp"
#include <utils/hook.hpp>
#define WEAP_ANIM_INSPECT WEAP_ANIM_RELOAD_MULTIPLE_FAST_8
#define WEAP_STATE_INSPECT 34 // night vision wear?
#define WEAP_FLAG2_INSPECT 0x4
namespace weapon
{
namespace
{
#ifdef DEBUG
template <typename T>
void set_weapon_field(const std::string& weapon_name, unsigned int field, T value)
{
auto weapon = game::DB_FindXAssetHeader(game::ASSET_TYPE_WEAPON, weapon_name.data(), false).weapon;
if (weapon)
{
if (field && field < (sizeof(game::WeaponDef)))
{
*reinterpret_cast<T*>(reinterpret_cast<std::uintptr_t>(weapon->weapDef) + field) = value;
}
else
{
console::warn("weapon field: %d is higher than the size of weapon struct!\n", field);
}
}
else
{
console::warn("weapon %s not found!\n", weapon_name.data());
}
}
void set_weapon_field_float(const std::string& weapon_name, unsigned int field, float value)
{
set_weapon_field<float>(weapon_name, field, value);
}
void set_weapon_field_int(const std::string& weapon_name, unsigned int field, int value)
{
set_weapon_field<int>(weapon_name, field, value);
}
void set_weapon_field_bool(const std::string& weapon_name, unsigned int field, bool value)
{
set_weapon_field<bool>(weapon_name, field, value);
}
#endif
game::WeaponDef* GetWeaponDef(unsigned __int16* weapon)
{
game::symbol<game::WeaponDef*> bg_weaponDefs{ 0x5210120 };
auto* weapon_def = bg_weaponDefs[*weapon];
return weapon_def;
}
int XAnimPartsGetLengthMsec(game::XAnimParts* parts)
{
return (int)(((float)parts->numframes / parts->framerate) * 1000.0f);
}
bool HasAnimState(int num, int compare)
{
return (num == compare || (num | 0x80) == compare);
}
int BG_GetWeaponInspectTime(game::playerState_s* ps, unsigned __int16* weapon, char isAlternate, char isDualWielding)
{
int result = 0;
auto* weapon_def = GetWeaponDef(weapon);
if (!weapon_def->szXAnims)
{
return result;
}
result = weapon_def->szXAnims->pad;
if (!result)
{
if (weapon_def->szXAnims->anims[game::WEAP_ANIM_INSPECT])
{
result = XAnimPartsGetLengthMsec(weapon_def->szXAnims->anims[game::WEAP_ANIM_INSPECT]) + 33;
}
}
return result;
}
utils::hook::detour CG_Weapons_GetWeaponAnimRate_hook;
float CG_Weapons_GetWeaponAnimRate_stub(int localClientNum, game::playerState_s* ps, int hand, __int64* weapon, unsigned __int8 isAlternate,
unsigned __int8 isDualWielding, game::XAnim_s* anims, game::weapAnimFiles_t animIndex, game::weapAnimFiles_t animIndex2)
{
// inspect animation time
if (animIndex == game::WEAP_ANIM_INSPECT)
{
animIndex2 = animIndex;
auto time = BG_GetWeaponInspectTime(ps, (unsigned __int16*)weapon, isAlternate, isDualWielding);
if (!time)
return 0.0f;
auto anim_time = game::XAnimGetLengthMsec(anims, animIndex2);
return (float)anim_time / (float)time;
}
return CG_Weapons_GetWeaponAnimRate_hook.invoke<float>(localClientNum, ps, hand, weapon,
isAlternate, isDualWielding, anims, animIndex, animIndex2);
}
utils::hook::detour BG_MapWeaponAnimStateToAnimIndex_hook;
game::weapAnimFiles_t BG_MapWeaponAnimStateToAnimIndex_stub(__int64 a1, game::playerState_s* ps, int animState, __int64* weapon, unsigned __int8 isAlternate,
int handIndex, unsigned __int8 pmoveHandler)
{
if (HasAnimState(game::WEAP_INSPECT, animState) && ps->weapState[handIndex].weaponState == WEAP_STATE_INSPECT)
{
return game::WEAP_ANIM_INSPECT;
}
return BG_MapWeaponAnimStateToAnimIndex_hook.invoke<game::weapAnimFiles_t>(a1, ps, animState, weapon, isAlternate, handIndex, pmoveHandler);
}
bool BG_GetWeaponInspectEnabled()
{
return true;
}
void PM_Weap_Inspect(game::pmove_t* pm, game::playerState_s* ps, unsigned short* weapon, int hand)
{
if (pm->ps->weapState[hand].weaponState != game::WEAPON_READY)
{
return;
}
if (pm->ps->weapState[hand].weaponState == WEAP_STATE_INSPECT)
{
return;
}
if (!game::BG_ViewModelAnimExists(pm->ps, game::WEAP_ANIM_INSPECT, hand, pm->handler))
{
return;
}
ps->weapState[hand].weaponState = WEAP_STATE_INSPECT;
ps->weapState[hand].weaponTime = BG_GetWeaponInspectTime(ps, weapon, false, false);
ps->weapState[hand].weaponDelay = 0;
if (ps->pm_type < 7)
ps->weapState[hand].weapAnim = ~(unsigned __int8)ps->weapState[hand].weapAnim & 0x80 | game::WEAP_INSPECT;
//PM_BuildWeaponAnimArrays(*(__int64*)((char*)pm + 568), pm->ps, *(char*)((char*)pm + 576));
}
void PM_Weapon_CheckForInspect(game::pmove_t* pm, game::pml_t* pml)
{
if ((pm->ps->weapFlags[1] & WEAP_FLAG2_INSPECT) != 0)
{
pm->ps->weapFlags[1] = ~pm->ps->weapFlags[1] & WEAP_FLAG2_INSPECT;
}
else
{
return;
}
if (!BG_GetWeaponInspectEnabled())
{
return;
}
auto v3 = *(__int64*)((char*)pm + 568) + 16i64 * *(unsigned __int16*)((char*)pm->ps + 2176);
unsigned short* weapon = (unsigned short*)((char*)v3 + 10);
unsigned int hand = 0;
if (game::BG_PlayerLastWeaponHandForViewWeapon(weapon, pm->ps) >= 0)
{
do
{
PM_Weap_Inspect(pm, pm->ps, weapon, hand++);
} while (hand <= game::BG_PlayerLastWeaponHandForViewWeapon(weapon, pm->ps));
}
}
utils::hook::detour PM_Weapon_Check_hook;
void PM_Weapon_Check_stub(game::pmove_t* pm, game::pml_t* pml)
{
PM_Weapon_Check_hook.invoke<void>(pm, pml);
PM_Weapon_CheckForInspect(pm, pml);
}
utils::hook::detour PM_Weapon_IsInInterruptibleState_hook;
bool PM_Weapon_IsInInterruptibleState_stub(__int64 weaponMap, game::playerState_s* ps, unsigned int hand, unsigned __int8 pmoveHandler)
{
auto result = PM_Weapon_IsInInterruptibleState_hook.invoke<bool>(weaponMap, ps, hand, pmoveHandler);
if (HasAnimState(game::WEAP_INSPECT, ps->weapState[hand].weapAnim) && ps->weapState[hand].weaponState == WEAP_STATE_INSPECT)
{
return true;
}
return result;
}
utils::hook::detour PM_WeaponProcessState_hook;
unsigned int PM_WeaponProcessState_stub(game::pmove_t* pm, game::pml_t* pml, unsigned int delayedAction, int hand, unsigned __int8 interruptable)
{
if (HasAnimState(game::WEAP_INSPECT, pm->ps->weapState[hand].weapAnim) && pm->ps->weapState[hand].weaponState == WEAP_STATE_INSPECT)
{
if (pm->ps->weapState[hand].weaponTime > 0)
{
return 1;
}
pm->ps->weapState->weaponState = game::WEAPON_READY;
if (pm->ps->pm_type < 7)
pm->ps->weapState[hand].weapAnim = ~(unsigned __int8)pm->ps->weapState[hand].weapAnim & 0x80;
return 1;
}
return PM_WeaponProcessState_hook.invoke<unsigned int>(pm, pml, delayedAction, hand, interruptable);
}
}
class component final : public component_interface
{
public:
void post_unpack() override
{
if (game::environment::is_dedi())
{
return;
}
#ifdef DEBUG
command::add("setWeaponFieldFloat", [](const command::params& params)
{
if (params.size() <= 3)
{
console::info("usage: setWeaponFieldInt <weapon> <field> <value>\n");
return;
}
set_weapon_field_float(params.get(1), atoi(params.get(2)), static_cast<float>(atof(params.get(3))));
});
command::add("setWeaponFieldInt", [](const command::params& params)
{
if (params.size() <= 3)
{
console::info("usage: setWeaponFieldInt <weapon> <field> <value>\n");
return;
}
set_weapon_field_int(params.get(1), atoi(params.get(2)), static_cast<int>(atoi(params.get(3))));
});
command::add("setWeaponFieldBool", [](const command::params& params)
{
if (params.size() <= 3)
{
console::info("usage: setWeaponFieldBool <weapon> <field> <value>\n");
return;
}
set_weapon_field_bool(params.get(1), atoi(params.get(2)), static_cast<bool>(atoi(params.get(3))));
});
#endif
CG_Weapons_GetWeaponAnimRate_hook.create(0x932550_b, CG_Weapons_GetWeaponAnimRate_stub);
BG_MapWeaponAnimStateToAnimIndex_hook.create(0x74A300_b, BG_MapWeaponAnimStateToAnimIndex_stub);
PM_Weapon_Check_hook.create(0x723350_b, PM_Weapon_Check_stub);
PM_Weapon_IsInInterruptibleState_hook.create(0x728210_b, PM_Weapon_IsInInterruptibleState_stub);
PM_WeaponProcessState_hook.create(0x72C3B0_b, PM_WeaponProcessState_stub);
gsc::method::add("startweaponinspection", [](game::scr_entref_t ent_ref, const gsc::function_args& args)
{
auto* ent = game::GetEntity(ent_ref);
if (!ent->client)
{
gsc::scr_error(utils::string::va("entity %i is not player", ent_ref));
return scripting::script_value{};
}
ent->client->ps.weapFlags[1] |= WEAP_FLAG2_INSPECT; // lets hope the game doesn't use this flag already...
return scripting::script_value{};
});
gsc::method::add("isinspectingweapon", [](game::scr_entref_t ent_ref, const gsc::function_args& args)
{
auto* ent = game::GetEntity(ent_ref);
if (!ent->client)
{
gsc::scr_error(utils::string::va("entity %i is not player", ent_ref));
return scripting::script_value{ false };
}
if (ent->client->ps.weapState[0].weaponState == WEAP_STATE_INSPECT && HasAnimState(game::WEAP_INSPECT, ent->client->ps.weapState[0].weapAnim))
{
return scripting::script_value{ true };
}
return scripting::script_value{ false };
});
}
};
}
REGISTER_COMPONENT(weapon::component)

View File

@ -517,6 +517,42 @@ namespace game
int time;
};
struct XAnimParent
{
unsigned __int16 flags;
unsigned __int16 children;
};
union $1A6660B292B883AB62F4E15A2C35B0BF
{
game::XAnimParts* parts;
XAnimParent animParent;
};
struct XAnimEntry
{
char nodeType[1];
char lod;
unsigned __int16 numAnims;
unsigned __int16 parent;
unsigned __int16 bindingIndex;
$1A6660B292B883AB62F4E15A2C35B0BF ___u2;
};
struct XAnim_s
{
unsigned int size;
bool initialized;
bool dirtyBindings;
unsigned __int16 numGameParameters;
unsigned __int16 maxGameParameters;
unsigned __int16 numBindings;
unsigned __int16 maxBindings;
const void** gameParameterNames;
void* bindings;
XAnimEntry entries[1];
};
namespace entity
{
enum connstate_t : std::uint32_t
@ -560,9 +596,134 @@ namespace game
assert_offsetof(entityState_t, clientNum, 156);
enum weaponstate_t : std::int32_t
{
WEAPON_READY = 0,
WEAPON_RAISING = 1,
WEAPON_RAISING_ALTSWITCH = 2,
WEAPON_RAISING_ALTSWITCH_ADS = 3,
};
enum WeaponAnimNumber : std::int32_t
{
WEAP_IDLE = 0,
WEAP_FORCE_IDLE = 1,
WEAP_ATTACK = 2,
WEAP_ATTACK_LASTSHOT = 3,
WEAP_RECHAMBER = 4,
WEAP_ADS_ATTACK = 5,
WEAP_ADS_ATTACK_LASTSHOT = 6,
WEAP_ADS_RECHAMBER = 7,
WEAP_GRENADE_PRIME = 8,
WEAP_GRENADE_PRIME_READY_TO_THROW = 9,
WEAP_MELEE_SWIPE = 10,
WEAP_MELEE_HIT = 11,
WEAP_MELEE_FATAL = 12,
WEAP_MELEE_MISS = 13,
WEAP_MELEE_VICTIM_CROUCHING_HIT = 14,
WEAP_MELEE_VICTIM_CROUCHING_FATAL = 15,
WEAP_MELEE_VICTIM_CROUCHING_MISS = 16,
WEAP_DROP = 17,
WEAP_RAISE = 18,
WEAP_FIRST_RAISE = 19,
WEAP_RELOAD = 20,
WEAP_RELOAD_EMPTY = 21,
WEAP_RELOAD_START = 22,
WEAP_RELOAD_END = 23,
WEAP_ALTSWITCHFROM = 24,
WEAP_ALTSWITCHFROM_ADS = 25,
WEAP_ALTSWITCHFROM_AKIMBO = 26,
WEAP_ALTSWITCHTO = 27,
WEAP_ALTSWITCHTO_ADS = 28,
WEAP_ALTSWITCHTO_AKIMBO = 29,
WEAP_QUICK_DROP = 30,
WEAP_QUICK_RAISE = 31,
WEAP_EMPTY_DROP = 32,
WEAP_EMPTY_RAISE = 33,
WEAP_SPRINT_IN = 34,
WEAP_SPRINT_IN_CANCEL = 35,
WEAP_SPRINT_LOOP = 36,
WEAP_SPRINT_OUT = 37,
WEAP_STUNNED_START = 38,
WEAP_STUNNED_LOOP = 39,
WEAP_STUNNED_END = 40,
WEAP_HOLD_FIRE = 41,
WEAP_DETONATE = 42,
WEAP_NIGHTVISION_WEAR = 43,
WEAP_NIGHTVISION_REMOVE = 44,
WEAP_BLAST_IMPACT_FRONT = 45,
WEAP_BLAST_IMPACT_LEFT = 46,
WEAP_BLAST_IMPACT_BACK = 47,
WEAP_BLAST_IMPACT_RIGHT = 48,
WEAP_SLIDE = 49,
WEAP_SWIM_LOOP = 50,
WEAP_DODGE = 51,
WEAP_LEAP_IN = 52,
WEAP_LEAP_LOOP = 53,
WEAP_LEAP_OUT = 54,
WEAP_LEAP_CANCEL = 55,
WEAP_CHARGE_INT = 56,
WEAP_CHARGE_LOOP = 57,
WEAP_CHARGE_OUT = 58,
WEAP_ADS_CHARGE_INT = 59,
WEAP_ADS_CHARGE_LOOP = 60,
WEAP_ADS_CHARGE_OUT = 61,
WEAP_WALLRUN = 62,
WEAP_INSPECT = 100, // custom added
};
struct PlayerActiveWeaponState
{
int weapAnim;
int weaponTime;
int weaponDelay;
int weaponRestrictKickTime;
int weaponState;
char __pad0[32];
};
assert_sizeof(PlayerActiveWeaponState, 52);
assert_offsetof(PlayerActiveWeaponState, weapAnim, 0);
assert_offsetof(PlayerActiveWeaponState, weaponTime, 4);
assert_offsetof(PlayerActiveWeaponState, weaponDelay, 8);
assert_offsetof(PlayerActiveWeaponState, weaponState, 16);
typedef int GameModeFlagValues[2];
struct playerState_s
{
int commandTime;
int pm_type;
char __pad0[1612];
PlayerActiveWeaponState weapState[2];
char __pad1[464];
GameModeFlagValues weapFlags;
};
assert_offsetof(playerState_s, weapState, 1620);
assert_offsetof(playerState_s, weapFlags, 2188);
struct pmove_t
{
void* unk;
playerState_s* ps;
char __pad0[560];
unsigned char handler;
};
assert_offsetof(pmove_t, handler, 576);
struct pml_t
{
float forward[3];
float right[3];
float up[3];
float frametime;
int msec;
};
assert_offsetof(pml_t, msec, 40);
struct gclient_s
{
char __pad0[19376];
playerState_s ps;
char __pad0[17180];
char name[32]; // 19376
char __pad1[1516];
int flags; // 20924

View File

@ -19,6 +19,8 @@ namespace game
WEAK symbol<unsigned int(int handle, int num_param)> Scr_ExecThread{ 0xC0ACD0 };
WEAK symbol<float()> BG_GetGravity{ 0x68DD0 };
WEAK game::symbol<unsigned int(unsigned short* weapon, game::playerState_s* ps)> BG_PlayerLastWeaponHandForViewWeapon{ 0x74B410 };
WEAK game::symbol<bool(game::playerState_s* ps, game::weapAnimFiles_t anim, int hand, unsigned char pmoveHandler)> BG_ViewModelAnimExists{ 0x751200 };
WEAK symbol<void(errorParm code, const char* message, ...)> Com_Error{ 0xB8D830 };
@ -126,6 +128,7 @@ namespace game
WEAK symbol<void(char* buffer)> FS_FreeFile{ 0xCDE1F0 };
WEAK symbol<void(int h, const char* fmt, ...)> FS_Printf{ 0xCDD1C0 };
WEAK symbol<gentity_s* (scr_entref_t ent)> GetEntity{ 0xB50EA0 };
WEAK symbol<unsigned int(unsigned int)> GetObjectType{ 0xC059E0 };
WEAK symbol<unsigned int(unsigned int, unsigned int)> GetVariable{ 0xC05A90 };
WEAK symbol<unsigned int(unsigned int parentId, unsigned int unsignedValue)> GetNewVariable{ 0xC05660 };
@ -215,6 +218,10 @@ namespace game
WEAK symbol<char* (const size_t size, unsigned int alignment, int type, int source)> PMem_AllocFromSource_NoDebug{ 0xCF0A90 };
WEAK symbol<void(const char* name, int allocDir)> PMem_Free{ 0xCF10D0 };
WEAK game::symbol<bool(__int64 weaponMap, game::playerState_s* ps, unsigned int hand, unsigned char pmoveHandler)> PM_Weapon_IsInInterruptibleState{ 0x728210 };
WEAK game::symbol<void(__int64 weaponMap, game::playerState_s* ps, unsigned char pmoveHandler)> PM_BuildWeaponAnimArrays{ 0x71AC50 };
WEAK game::symbol<void(game::pmove_t* pm, int hand)> PM_Weapon_Idle{ 0x727910 };
WEAK symbol<unsigned int(unsigned int localId, const char* pos,
unsigned int paramcount)> VM_Execute{ 0xC0CDB0 };
@ -229,6 +236,7 @@ namespace game
WEAK symbol<int(unsigned int classnum, int entnum, int offset)> Scr_SetObjectField{ 0x40B6E0 };
WEAK symbol<int()> Scr_GetInt{ 0xC0B950 };
WEAK symbol<void()> Scr_ErrorInternal{ 0xC0AC30 };
WEAK symbol<void(const char* str)> Scr_AllocGlobalString{ 0xC03C70 };
WEAK symbol<ScreenPlacement* ()> ScrPlace_GetViewPlacement{ 0x9E4090 };
@ -271,6 +279,8 @@ namespace game
WEAK symbol<void(unsigned int localClientNum, const char** args)> UI_RunMenuScript{ 0xCC9710 };
WEAK symbol<const char* (const char* string)> UI_SafeTranslateString{ 0xCC9790 };
WEAK game::symbol<float(game::XAnim_s* anims, unsigned int anim)> XAnimGetLengthMsec{ 0xD761C0 };
WEAK symbol<void* (jmp_buf* Buf, int Value)> longjmp{ 0x12C0758 };
WEAK symbol<int(jmp_buf* Buf)> _setjmp{ 0x1423110 };