kal
This commit is contained in:
@@ -0,0 +1,285 @@
|
||||
#pragma once
|
||||
|
||||
// @source: master/game/shared/cstrike15/gametypes.h
|
||||
#pragma region valve_gametypes
|
||||
|
||||
enum EGameType : int
|
||||
{
|
||||
GAMETYPE_UNKNOWN = -1,
|
||||
GAMETYPE_CLASSIC,
|
||||
GAMETYPE_GUNGAME,
|
||||
GAMETYPE_TRAINING,
|
||||
GAMETYPE_CUSTOM,
|
||||
GAMETYPE_COOPERATIVE,
|
||||
GAMETYPE_SKIRMISH,
|
||||
GAMETYPE_FREEFORALL
|
||||
};
|
||||
|
||||
enum EGameMode : int
|
||||
{
|
||||
GAMEMODE_UNKNOWN = -1,
|
||||
|
||||
// GAMETYPE_CLASSIC
|
||||
GAMEMODE_CLASSIC_CASUAL = 0,
|
||||
GAMEMODE_CLASSIC_COMPETITIVE,
|
||||
GAMEMODE_CLASSIC_SCRIM_COMPETITIVE2V2,
|
||||
GAMEMODE_CLASSIC_SCRIM_COMPETITIVE5V5,
|
||||
|
||||
// GAMETYPE_GUNGAME
|
||||
GAMEMODE_GUNGAME_PROGRESSIVE = 0,
|
||||
GAMEMODE_GUNGAME_BOMB,
|
||||
GAMEMODE_GUNGAME_DEATHMATCH,
|
||||
|
||||
// GAMETYPE_TRAINING
|
||||
GAMEMODE_TRAINING_DEFAULT = 0,
|
||||
|
||||
// GAMETYPE_CUSTOM
|
||||
GAMEMODE_CUSTOM_DEFAULT = 0,
|
||||
|
||||
// GAMETYPE_COOPERATIVE
|
||||
GAMEMODE_COOPERATIVE_DEFAULT = 0,
|
||||
GAMEMODE_COOPERATIVE_MISSION,
|
||||
|
||||
// GAMETYPE_SKIRMISH
|
||||
GAMEMODE_SKIRMISH_DEFAULT = 0,
|
||||
|
||||
// GAMETYPE_FREEFORALL
|
||||
GAMEMODE_FREEFORALL_SURVIVAL = 0
|
||||
};
|
||||
|
||||
#pragma endregion
|
||||
|
||||
enum ELifeState : int
|
||||
{
|
||||
LIFE_ALIVE = 0,
|
||||
LIFE_DYING,
|
||||
LIFE_DEAD,
|
||||
LIFE_RESPAWNABLE,
|
||||
LIFE_DISCARDBODY
|
||||
};
|
||||
|
||||
enum EFlags : int
|
||||
{
|
||||
FL_ONGROUND = (1 << 0), // entity is at rest / on the ground
|
||||
FL_DUCKING = (1 << 1), // player is fully crouched/uncrouched
|
||||
FL_ANIMDUCKING = (1 << 2), // player is in the process of crouching or uncrouching but could be in transition
|
||||
FL_WATERJUMP = (1 << 3), // player is jumping out of water
|
||||
FL_ONTRAIN = (1 << 4), // player is controlling a train, so movement commands should be ignored on client during prediction
|
||||
FL_INRAIN = (1 << 5), // entity is standing in rain
|
||||
FL_FROZEN = (1 << 6), // player is frozen for 3rd-person camera
|
||||
FL_ATCONTROLS = (1 << 7), // player can't move, but keeps key inputs for controlling another entity
|
||||
FL_CLIENT = (1 << 8), // entity is a client (player)
|
||||
FL_FAKECLIENT = (1 << 9), // entity is a fake client, simulated server side; don't send network messages to them
|
||||
FL_INWATER = (1 << 10), // entity is in water
|
||||
FL_FLY = (1 << 11),
|
||||
FL_SWIM = (1 << 12),
|
||||
FL_CONVEYOR = (1 << 13),
|
||||
FL_NPC = (1 << 14),
|
||||
FL_GODMODE = (1 << 15),
|
||||
FL_NOTARGET = (1 << 16),
|
||||
FL_AIMTARGET = (1 << 17),
|
||||
FL_PARTIALGROUND = (1 << 18), // entity is standing on a place where not all corners are valid
|
||||
FL_STATICPROP = (1 << 19), // entity is a static property
|
||||
FL_GRAPHED = (1 << 20),
|
||||
FL_GRENADE = (1 << 21),
|
||||
FL_STEPMOVEMENT = (1 << 22),
|
||||
FL_DONTTOUCH = (1 << 23),
|
||||
FL_BASEVELOCITY = (1 << 24), // entity have applied base velocity this frame
|
||||
FL_WORLDBRUSH = (1 << 25), // entity is not moveable/removeable brush (part of the world, but represented as an entity for transparency or something)
|
||||
FL_OBJECT = (1 << 26),
|
||||
FL_KILLME = (1 << 27), // entity is marked for death and will be freed by the game
|
||||
FL_ONFIRE = (1 << 28),
|
||||
FL_DISSOLVING = (1 << 29),
|
||||
FL_TRANSRAGDOLL = (1 << 30), // entity is turning into client-side ragdoll
|
||||
FL_UNBLOCKABLE_BY_PLAYER = (1 << 31)
|
||||
};
|
||||
|
||||
enum EEFlags : int
|
||||
{
|
||||
EFL_KILLME = (1 << 0),
|
||||
EFL_DORMANT = (1 << 1),
|
||||
EFL_NOCLIP_ACTIVE = (1 << 2),
|
||||
EFL_SETTING_UP_BONES = (1 << 3),
|
||||
EFL_KEEP_ON_RECREATE_ENTITIES = (1 << 4),
|
||||
EFL_DIRTY_SHADOWUPDATE = (1 << 5),
|
||||
EFL_NOTIFY = (1 << 6),
|
||||
EFL_FORCE_CHECK_TRANSMIT = (1 << 7),
|
||||
EFL_BOT_FROZEN = (1 << 8),
|
||||
EFL_SERVER_ONLY = (1 << 9),
|
||||
EFL_NO_AUTO_EDICT_ATTACH = (1 << 10),
|
||||
EFL_DIRTY_ABSTRANSFORM = (1 << 11),
|
||||
EFL_DIRTY_ABSVELOCITY = (1 << 12),
|
||||
EFL_DIRTY_ABSANGVELOCITY = (1 << 13),
|
||||
EFL_DIRTY_SURROUNDING_COLLISION_BOUNDS = (1 << 14),
|
||||
EFL_DIRTY_SPATIAL_PARTITION = (1 << 15),
|
||||
EFL_HAS_PLAYER_CHILD = (1 << 16),
|
||||
EFL_IN_SKYBOX = (1 << 17),
|
||||
EFL_USE_PARTITION_WHEN_NOT_SOLID = (1 << 18),
|
||||
EFL_TOUCHING_FLUID = (1 << 19),
|
||||
EFL_IS_BEING_LIFTED_BY_BARNACLE = (1 << 20),
|
||||
EFL_NO_ROTORWASH_PUSH = (1 << 21),
|
||||
EFL_NO_THINK_FUNCTION = (1 << 22),
|
||||
EFL_NO_GAME_PHYSICS_SIMULATION = (1 << 23),
|
||||
EFL_CHECK_UNTOUCH = (1 << 24),
|
||||
EFL_DONTBLOCKLOS = (1 << 25),
|
||||
EFL_DONTWALKON = (1 << 26),
|
||||
EFL_NO_DISSOLVE = (1 << 27),
|
||||
EFL_NO_MEGAPHYSCANNON_RAGDOLL = (1 << 28),
|
||||
EFL_NO_WATER_VELOCITY_CHANGE = (1 << 29),
|
||||
EFL_NO_PHYSCANNON_INTERACTION = (1 << 30),
|
||||
EFL_NO_DAMAGE_FORCES = (1 << 31)
|
||||
};
|
||||
|
||||
enum EMoveType : std::uint8_t
|
||||
{
|
||||
MOVETYPE_NONE = 0,
|
||||
MOVETYPE_OBSOLETE,
|
||||
MOVETYPE_WALK,
|
||||
MOVETYPE_FLY,
|
||||
MOVETYPE_FLYGRAVITY,
|
||||
MOVETYPE_VPHYSICS,
|
||||
MOVETYPE_PUSH,
|
||||
MOVETYPE_NOCLIP,
|
||||
MOVETYPE_OBSERVER,
|
||||
MOVETYPE_LADDER,
|
||||
MOVETYPE_CUSTOM,
|
||||
MOVETYPE_LAST,
|
||||
MOVETYPE_INVALID,
|
||||
MOVETYPE_MAX_BITS = 5
|
||||
};
|
||||
|
||||
// identifies how submerged in water a player is
|
||||
enum : int
|
||||
{
|
||||
WL_NOTINWATER = 0,
|
||||
WL_FEET,
|
||||
WL_WAIST,
|
||||
WL_EYES
|
||||
};
|
||||
|
||||
enum ETeamID : int
|
||||
{
|
||||
TEAM_UNK,
|
||||
TEAM_SPECTATOR,
|
||||
TEAM_TT,
|
||||
TEAM_CT
|
||||
};
|
||||
|
||||
using ItemDefinitionIndex_t = std::uint16_t;
|
||||
enum EItemDefinitionIndexes : ItemDefinitionIndex_t
|
||||
{
|
||||
WEAPON_NONE,
|
||||
WEAPON_DESERT_EAGLE,
|
||||
WEAPON_DUAL_BERETTAS,
|
||||
WEAPON_FIVE_SEVEN,
|
||||
WEAPON_GLOCK_18,
|
||||
WEAPON_AK_47 = 7,
|
||||
WEAPON_AUG,
|
||||
WEAPON_AWP,
|
||||
WEAPON_FAMAS,
|
||||
WEAPON_G3SG1,
|
||||
WEAPON_GALIL_AR = 13,
|
||||
WEAPON_M249,
|
||||
WEAPON_M4A4 = 16,
|
||||
WEAPON_MAC_10,
|
||||
WEAPON_P90 = 19,
|
||||
WEAPON_REPULSOR_DEVICE,
|
||||
WEAPON_MP5_SD = 23,
|
||||
WEAPON_UMP_45,
|
||||
WEAPON_XM1014,
|
||||
WEAPON_PP_BIZON,
|
||||
WEAPON_MAG_7,
|
||||
WEAPON_NEGEV,
|
||||
WEAPON_SAWED_OFF,
|
||||
WEAPON_TEC_9,
|
||||
WEAPON_ZEUS_X27,
|
||||
WEAPON_P2000,
|
||||
WEAPON_MP7,
|
||||
WEAPON_MP9,
|
||||
WEAPON_NOVA,
|
||||
WEAPON_P250,
|
||||
WEAPON_RIOT_SHIELD,
|
||||
WEAPON_SCAR_20,
|
||||
WEAPON_SG_553,
|
||||
WEAPON_SSG_08,
|
||||
WEAPON_KNIFE0,
|
||||
WEAPON_KNIFE1,
|
||||
WEAPON_FLASHBANG,
|
||||
WEAPON_HIGH_EXPLOSIVE_GRENADE,
|
||||
WEAPON_SMOKE_GRENADE,
|
||||
WEAPON_MOLOTOV,
|
||||
WEAPON_DECOY_GRENADE,
|
||||
WEAPON_INCENDIARY_GRENADE,
|
||||
WEAPON_C4_EXPLOSIVE,
|
||||
WEAPON_KEVLAR_VEST,
|
||||
WEAPON_KEVLAR_and_HELMET,
|
||||
WEAPON_HEAVY_ASSAULT_SUIT,
|
||||
WEAPON_NO_LOCALIZED_NAME0 = 54,
|
||||
WEAPON_DEFUSE_KIT,
|
||||
WEAPON_RESCUE_KIT,
|
||||
WEAPON_MEDI_SHOT,
|
||||
WEAPON_MUSIC_KIT,
|
||||
WEAPON_KNIFE2,
|
||||
WEAPON_M4A1_S,
|
||||
WEAPON_USP_S,
|
||||
WEAPON_TRADE_UP_CONTRACT,
|
||||
WEAPON_CZ75_AUTO,
|
||||
WEAPON_R8_REVOLVER,
|
||||
WEAPON_TACTICAL_AWARENESS_GRENADE = 68,
|
||||
WEAPON_BARE_HANDS,
|
||||
WEAPON_BREACH_CHARGE,
|
||||
WEAPON_TABLET = 72,
|
||||
WEAPON_KNIFE3 = 74,
|
||||
WEAPON_AXE,
|
||||
WEAPON_HAMMER,
|
||||
WEAPON_WRENCH = 78,
|
||||
WEAPON_SPECTRAL_SHIV = 80,
|
||||
WEAPON_FIRE_BOMB,
|
||||
WEAPON_DIVERSION_DEVICE,
|
||||
WEAPON_FRAG_GRENADE,
|
||||
WEAPON_SNOWBALL,
|
||||
WEAPON_BUMP_MINE,
|
||||
WEAPON_BAYONET = 500,
|
||||
WEAPON_CLASSIC_KNIFE = 503,
|
||||
WEAPON_FLIP_KNIFE = 505,
|
||||
WEAPON_GUT_KNIFE,
|
||||
WEAPON_KARAMBIT,
|
||||
WEAPON_M9_BAYONET,
|
||||
WEAPON_HUNTSMAN_KNIFE,
|
||||
WEAPON_FALCHION_KNIFE = 512,
|
||||
WEAPON_BOWIE_KNIFE = 514,
|
||||
WEAPON_BUTTERFLY_KNIFE,
|
||||
WEAPON_SHADOW_DAGGERS,
|
||||
WEAPON_PARACORD_KNIFE,
|
||||
WEAPON_SURVIVAL_KNIFE,
|
||||
WEAPON_URSUS_KNIFE,
|
||||
WEAPON_NAVAJA_KNIFE,
|
||||
WEAPON_NOMAD_KNIFE,
|
||||
WEAPON_STILETTO_KNIFE,
|
||||
WEAPON_TALON_KNIFE,
|
||||
WEAPON_SKELETON_KNIFE = 525,
|
||||
};
|
||||
|
||||
enum EWeaponType : std::uint32_t
|
||||
{
|
||||
WEAPONTYPE_KNIFE = 0,
|
||||
WEAPONTYPE_PISTOL = 1,
|
||||
WEAPONTYPE_SUBMACHINEGUN = 2,
|
||||
WEAPONTYPE_RIFLE = 3,
|
||||
WEAPONTYPE_SHOTGUN = 4,
|
||||
WEAPONTYPE_SNIPER_RIFLE = 5,
|
||||
WEAPONTYPE_MACHINEGUN = 6,
|
||||
WEAPONTYPE_C4 = 7,
|
||||
WEAPONTYPE_TASER = 8,
|
||||
WEAPONTYPE_GRENADE = 9,
|
||||
WEAPONTYPE_EQUIPMENT = 10,
|
||||
WEAPONTYPE_STACKABLEITEM = 11,
|
||||
WEAPONTYPE_FISTS = 12,
|
||||
WEAPONTYPE_BREACHCHARGE = 13,
|
||||
WEAPONTYPE_BUMPMINE = 14,
|
||||
WEAPONTYPE_TABLET = 15,
|
||||
WEAPONTYPE_MELEE = 16,
|
||||
WEAPONTYPE_SHIELD = 17,
|
||||
WEAPONTYPE_ZONE_REPULSOR = 18,
|
||||
WEAPONTYPE_UNKNOWN = 19
|
||||
};
|
||||
@@ -0,0 +1,232 @@
|
||||
#pragma once
|
||||
// used: [crt] fmodf
|
||||
#include <cmath>
|
||||
// used: bit_cast
|
||||
#include <bit>
|
||||
|
||||
#include "../../common.h"
|
||||
// used: swap
|
||||
#include "../../utilities/crt.h"
|
||||
// used: [ext] imu32
|
||||
#include "../../../dependencies/imgui/imgui.h"
|
||||
|
||||
enum
|
||||
{
|
||||
COLOR_R = 0,
|
||||
COLOR_G = 1,
|
||||
COLOR_B = 2,
|
||||
COLOR_A = 3
|
||||
};
|
||||
|
||||
struct ColorRGBExp32
|
||||
{
|
||||
std::uint8_t r, g, b;
|
||||
std::int8_t iExponent;
|
||||
};
|
||||
|
||||
static_assert(sizeof(ColorRGBExp32) == 0x4);
|
||||
|
||||
struct Color_t
|
||||
{
|
||||
Color_t() = default;
|
||||
|
||||
// 8-bit color constructor (in: [0 .. 255])
|
||||
constexpr Color_t(const std::uint8_t r, const std::uint8_t g, const std::uint8_t b, const std::uint8_t a = 255) :
|
||||
r(r), g(g), b(b), a(a) { }
|
||||
|
||||
// 8-bit color constructor (in: [0 .. 255])
|
||||
constexpr Color_t(const int r, const int g, const int b, const int a = 255) :
|
||||
r(static_cast<std::uint8_t>(r)), g(static_cast<std::uint8_t>(g)), b(static_cast<std::uint8_t>(b)), a(static_cast<std::uint8_t>(a)) { }
|
||||
|
||||
// 8-bit array color constructor (in: [0.0 .. 1.0])
|
||||
explicit constexpr Color_t(const std::uint8_t arrColor[4]) :
|
||||
r(arrColor[COLOR_R]), g(arrColor[COLOR_G]), b(arrColor[COLOR_B]), a(arrColor[COLOR_A]) { }
|
||||
|
||||
// 32-bit packed color constructor (in: 0x00000000 - 0xFFFFFFFF)
|
||||
explicit constexpr Color_t(const ImU32 uPackedColor) :
|
||||
r(static_cast<std::uint8_t>((uPackedColor >> IM_COL32_R_SHIFT) & 0xFF)), g(static_cast<std::uint8_t>((uPackedColor >> IM_COL32_G_SHIFT) & 0xFF)), b(static_cast<std::uint8_t>((uPackedColor >> IM_COL32_B_SHIFT) & 0xFF)), a(static_cast<std::uint8_t>((uPackedColor >> IM_COL32_A_SHIFT) & 0xFF)) { }
|
||||
|
||||
// 32-bit color constructor (in: [0.0 .. 1.0])
|
||||
constexpr Color_t(const float r, const float g, const float b, const float a = 1.0f) :
|
||||
r(static_cast<std::uint8_t>(r * 255.f)), g(static_cast<std::uint8_t>(g * 255.f)), b(static_cast<std::uint8_t>(b * 255.f)), a(static_cast<std::uint8_t>(a * 255.f)) { }
|
||||
|
||||
/// @returns: 32-bit packed integer representation of color
|
||||
[[nodiscard]] constexpr ImU32 GetU32(const float flAlphaMultiplier = 1.0f) const
|
||||
{
|
||||
return IM_COL32(r, g, b, a * flAlphaMultiplier);
|
||||
}
|
||||
|
||||
/// @return: converted color to imgui vector
|
||||
[[nodiscard]] ImVec4 GetVec4(const float flAlphaMultiplier = 1.0f) const
|
||||
{
|
||||
return ImVec4(this->Base<COLOR_R>(), this->Base<COLOR_G>(), this->Base<COLOR_B>(), this->Base<COLOR_A>() * flAlphaMultiplier);
|
||||
}
|
||||
|
||||
std::uint8_t& operator[](const std::uint8_t nIndex)
|
||||
{
|
||||
CS_ASSERT(nIndex <= COLOR_A); // given index is out of range
|
||||
return reinterpret_cast<std::uint8_t*>(this)[nIndex];
|
||||
}
|
||||
|
||||
const std::uint8_t& operator[](const std::uint8_t nIndex) const
|
||||
{
|
||||
CS_ASSERT(nIndex <= COLOR_A); // given index is out of range
|
||||
return reinterpret_cast<const std::uint8_t*>(this)[nIndex];
|
||||
}
|
||||
|
||||
bool operator==(const Color_t& colSecond) const
|
||||
{
|
||||
return (std::bit_cast<std::uint32_t>(*this) == std::bit_cast<std::uint32_t>(colSecond));
|
||||
}
|
||||
|
||||
bool operator!=(const Color_t& colSecond) const
|
||||
{
|
||||
return (std::bit_cast<std::uint32_t>(*this) != std::bit_cast<std::uint32_t>(colSecond));
|
||||
}
|
||||
|
||||
/// @returns: copy of color with certain R/G/B/A component changed to given value
|
||||
template <std::size_t N>
|
||||
[[nodiscard]] Color_t Set(const std::uint8_t nValue) const
|
||||
{
|
||||
static_assert(N >= COLOR_R && N <= COLOR_A, "color component index is out of range");
|
||||
|
||||
Color_t colCopy = *this;
|
||||
colCopy[N] = nValue;
|
||||
return colCopy;
|
||||
}
|
||||
|
||||
/// @returns: copy of color with certain R/G/B/A component multiplied by given value
|
||||
template <std::size_t N>
|
||||
[[nodiscard]] Color_t Multiplier(const float flValue) const
|
||||
{
|
||||
static_assert(N >= COLOR_R && N <= COLOR_A, "color component index is out of range");
|
||||
|
||||
Color_t colCopy = *this;
|
||||
colCopy[N] = static_cast<std::uint8_t>(static_cast<float>(colCopy[N]) * flValue);
|
||||
return colCopy;
|
||||
}
|
||||
|
||||
/// @returns: copy of color with certain R/G/B/A component divided by given value
|
||||
template <std::size_t N>
|
||||
[[nodiscard]] Color_t Divider(const int iValue) const
|
||||
{
|
||||
static_assert(N >= COLOR_R && N <= COLOR_A, "color component index is out of range");
|
||||
|
||||
Color_t colCopy = *this;
|
||||
colCopy[N] /= iValue;
|
||||
return colCopy;
|
||||
}
|
||||
|
||||
/// @returns: certain R/G/B/A float value (in: [0 .. 255], out: [0.0 .. 1.0])
|
||||
template <std::size_t N>
|
||||
[[nodiscard]] float Base() const
|
||||
{
|
||||
static_assert(N >= COLOR_R && N <= COLOR_A, "color component index is out of range");
|
||||
return reinterpret_cast<const std::uint8_t*>(this)[N] / 255.f;
|
||||
}
|
||||
|
||||
/// @param[out] arrBase output array of R/G/B color components converted to float (in: [0 .. 255], out: [0.0 .. 1.0])
|
||||
constexpr void Base(float (&arrBase)[3]) const
|
||||
{
|
||||
arrBase[COLOR_R] = static_cast<float>(r) / 255.f;
|
||||
arrBase[COLOR_G] = static_cast<float>(g) / 255.f;
|
||||
arrBase[COLOR_B] = static_cast<float>(b) / 255.f;
|
||||
}
|
||||
|
||||
/// @returns: color created from float[3] array (in: [0.0 .. 1.0], out: [0 .. 255])
|
||||
static Color_t FromBase3(const float arrBase[3])
|
||||
{
|
||||
return { arrBase[0], arrBase[1], arrBase[2] };
|
||||
}
|
||||
|
||||
/// @param[out] arrBase output array of R/G/B/A color components converted to float (in: [0 .. 255], out: [0.0 .. 1.0])
|
||||
constexpr void BaseAlpha(float (&arrBase)[4]) const
|
||||
{
|
||||
arrBase[COLOR_R] = static_cast<float>(r) / 255.f;
|
||||
arrBase[COLOR_G] = static_cast<float>(g) / 255.f;
|
||||
arrBase[COLOR_B] = static_cast<float>(b) / 255.f;
|
||||
arrBase[COLOR_A] = static_cast<float>(a) / 255.f;
|
||||
}
|
||||
|
||||
/// @returns : color created from float[3] array (in: [0.0 .. 1.0], out: [0 .. 255])
|
||||
static Color_t FromBase4(const float arrBase[4])
|
||||
{
|
||||
return { arrBase[COLOR_R], arrBase[COLOR_G], arrBase[COLOR_B], arrBase[COLOR_A] };
|
||||
}
|
||||
|
||||
/// @param[out] arrHSB output array of HSB/HSV color converted from RGB color
|
||||
void ToHSB(float (&arrHSB)[3]) const
|
||||
{
|
||||
float arrBase[3] = {};
|
||||
Base(arrBase);
|
||||
|
||||
float flKernel = 0.0f;
|
||||
if (arrBase[COLOR_G] < arrBase[COLOR_B])
|
||||
{
|
||||
CRT::Swap(arrBase[COLOR_G], arrBase[COLOR_B]);
|
||||
flKernel = -1.0f;
|
||||
}
|
||||
if (arrBase[COLOR_R] < arrBase[COLOR_G])
|
||||
{
|
||||
CRT::Swap(arrBase[COLOR_R], arrBase[COLOR_G]);
|
||||
flKernel = -2.0f / 6.0f - flKernel;
|
||||
}
|
||||
|
||||
const float flChroma = arrBase[COLOR_R] - MATH::Min(arrBase[COLOR_G], arrBase[COLOR_B]);
|
||||
arrHSB[COLOR_R] = std::fabsf(flKernel + (arrBase[COLOR_G] - arrBase[COLOR_B]) / (6.0f * flChroma + std::numeric_limits<float>::epsilon()));
|
||||
arrHSB[COLOR_G] = flChroma / (arrBase[COLOR_R] + std::numeric_limits<float>::epsilon());
|
||||
arrHSB[COLOR_G] = arrBase[COLOR_R];
|
||||
}
|
||||
|
||||
/// @returns: RGB color converted from HSB/HSV color
|
||||
static Color_t FromHSB(const float flHue, const float flSaturation, const float flBrightness, const float flAlpha = 1.0f)
|
||||
{
|
||||
constexpr float flHueRange = (60.0f / 360.0f);
|
||||
const float flHuePrime = std::fmodf(flHue, 1.0f) / flHueRange;
|
||||
const int iRoundHuePrime = static_cast<int>(flHuePrime);
|
||||
const float flDelta = flHuePrime - static_cast<float>(iRoundHuePrime);
|
||||
|
||||
const float p = flBrightness * (1.0f - flSaturation);
|
||||
const float q = flBrightness * (1.0f - flSaturation * flDelta);
|
||||
const float t = flBrightness * (1.0f - flSaturation * (1.0f - flDelta));
|
||||
|
||||
float flRed, flGreen, flBlue;
|
||||
switch (iRoundHuePrime)
|
||||
{
|
||||
case 0:
|
||||
flRed = flBrightness;
|
||||
flGreen = t;
|
||||
flBlue = p;
|
||||
break;
|
||||
case 1:
|
||||
flRed = q;
|
||||
flGreen = flBrightness;
|
||||
flBlue = p;
|
||||
break;
|
||||
case 2:
|
||||
flRed = p;
|
||||
flGreen = flBrightness;
|
||||
flBlue = t;
|
||||
break;
|
||||
case 3:
|
||||
flRed = p;
|
||||
flGreen = q;
|
||||
flBlue = flBrightness;
|
||||
break;
|
||||
case 4:
|
||||
flRed = t;
|
||||
flGreen = p;
|
||||
flBlue = flBrightness;
|
||||
break;
|
||||
default:
|
||||
flRed = flBrightness;
|
||||
flGreen = p;
|
||||
flBlue = q;
|
||||
break;
|
||||
}
|
||||
|
||||
return { flRed, flGreen, flBlue, flAlpha };
|
||||
}
|
||||
|
||||
std::uint8_t r = 0U, g = 0U, b = 0U, a = 0U;
|
||||
};
|
||||
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
// used: MEM_PAD, FindPattern
|
||||
#include "../../utilities/memory.h"
|
||||
|
||||
struct KV3ID_t
|
||||
{
|
||||
const char* szName;
|
||||
std::uint64_t unk0;
|
||||
std::uint64_t unk1;
|
||||
};
|
||||
|
||||
class CKeyValues3
|
||||
{
|
||||
public:
|
||||
MEM_PAD(0x100);
|
||||
std::uint64_t uKey;
|
||||
void* pValue;
|
||||
MEM_PAD(0x8);
|
||||
|
||||
void LoadFromBuffer(const char* szString);
|
||||
bool LoadKV3(CUtlBuffer* buffer);
|
||||
|
||||
static CKeyValues3* CreateMaterialResource()
|
||||
{
|
||||
using fnSetTypeKV3 = CKeyValues3*(CS_FASTCALL*)(CKeyValues3*, unsigned int, unsigned int);
|
||||
static const fnSetTypeKV3 oSetTypeKV3 = reinterpret_cast<fnSetTypeKV3>(MEM::FindPattern(CLIENT_DLL, CS_XOR("40 53 48 83 EC 20 48 8B 01 48 8B D9 44")));
|
||||
|
||||
#ifdef CS_PARANOID
|
||||
CS_ASSERT(oSetTypeKV3 != nullptr);
|
||||
#endif
|
||||
|
||||
CKeyValues3* pKeyValue = new CKeyValues3[0x10];
|
||||
return oSetTypeKV3(pKeyValue, 1U, 6U);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
#include "keyvalue3.h"
|
||||
// used: CRT
|
||||
#include "../../utilities/crt.h"
|
||||
// used: utlbuffer
|
||||
#include "utlbuffer.h"
|
||||
|
||||
void CKeyValues3::LoadFromBuffer(const char* szString)
|
||||
{
|
||||
CUtlBuffer buffer(0, (CRT::StringLength(szString) + 10), 1);
|
||||
buffer.PutString(szString);
|
||||
LoadKV3(&buffer);
|
||||
}
|
||||
|
||||
bool CKeyValues3::LoadKV3(CUtlBuffer* buffer)
|
||||
{
|
||||
using fnLoadKeyValues = bool(CS_FASTCALL*)(CKeyValues3*, void*, CUtlBuffer*, KV3ID_t*, void*, void*, void*, void*, const char*);
|
||||
static const fnLoadKeyValues oLoadKeyValues = reinterpret_cast<fnLoadKeyValues>(MEM::GetAbsoluteAddress(MEM::FindPattern(TIER0_DLL, CS_XOR("E8 ? ? ? ? EB 36 8B 43 10")), 0x1, 0x0));
|
||||
|
||||
#ifdef CS_PARANOID
|
||||
CS_ASSERT(oLoadKeyValues != nullptr);
|
||||
#endif
|
||||
|
||||
const char* szName = CS_XOR("");
|
||||
KV3ID_t kv3ID = KV3ID_t(CS_XOR("generic"), 0x41B818518343427E, 0xB5F447C23C0CDF8C);
|
||||
return oLoadKeyValues(this, nullptr, buffer, &kv3ID, nullptr, nullptr, nullptr, nullptr, CS_XOR(""));
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#include "matrix.h"
|
||||
|
||||
#include "qangle.h"
|
||||
|
||||
// used: m_rad2deg
|
||||
#include "../../utilities/math.h"
|
||||
|
||||
[[nodiscard]] QAngle_t Matrix3x4_t::ToAngles() const
|
||||
{
|
||||
// extract the basis vectors from the matrix. since we only need the z component of the up vector, we don't get x and y
|
||||
const Vector_t vecForward = this->GetForward();
|
||||
const Vector_t vecLeft = this->GetLeft();
|
||||
const float flUpZ = this->arrData[2][2];
|
||||
|
||||
const float flLength2D = vecForward.Length2D();
|
||||
const float flPitch = M_RAD2DEG(std::atan2f(-vecForward.z, flLength2D));
|
||||
|
||||
// check is enough here to get angles
|
||||
if (flLength2D > 0.001f)
|
||||
return { flPitch, M_RAD2DEG(std::atan2f(vecForward.y, vecForward.x)), M_RAD2DEG(std::atan2f(vecLeft.z, flUpZ)) };
|
||||
|
||||
// forward is mostly Z, gimbal lock
|
||||
// assume no roll in this case as one degree of freedom has been lost (i.e. yaw equals roll)
|
||||
return { flPitch, M_RAD2DEG(std::atan2f(-vecLeft.x, vecLeft.y)), 0.0f };
|
||||
}
|
||||
@@ -0,0 +1,439 @@
|
||||
#pragma once
|
||||
// used: sse2 intrinsics
|
||||
#include <xmmintrin.h>
|
||||
// used: bit_cast
|
||||
#include <bit>
|
||||
|
||||
#include "../../common.h"
|
||||
|
||||
#include "vector.h"
|
||||
|
||||
// forward declarations
|
||||
struct QAngle_t;
|
||||
|
||||
#pragma pack(push, 4)
|
||||
using Matrix3x3_t = float[3][3];
|
||||
|
||||
struct Matrix3x4_t
|
||||
{
|
||||
Matrix3x4_t() = default;
|
||||
|
||||
constexpr Matrix3x4_t(
|
||||
const float m00, const float m01, const float m02, const float m03,
|
||||
const float m10, const float m11, const float m12, const float m13,
|
||||
const float m20, const float m21, const float m22, const float m23)
|
||||
{
|
||||
arrData[0][0] = m00;
|
||||
arrData[0][1] = m01;
|
||||
arrData[0][2] = m02;
|
||||
arrData[0][3] = m03;
|
||||
arrData[1][0] = m10;
|
||||
arrData[1][1] = m11;
|
||||
arrData[1][2] = m12;
|
||||
arrData[1][3] = m13;
|
||||
arrData[2][0] = m20;
|
||||
arrData[2][1] = m21;
|
||||
arrData[2][2] = m22;
|
||||
arrData[2][3] = m23;
|
||||
}
|
||||
|
||||
constexpr Matrix3x4_t(const Vector_t& vecForward, const Vector_t& vecLeft, const Vector_t& vecUp, const Vector_t& vecOrigin)
|
||||
{
|
||||
SetForward(vecForward);
|
||||
SetLeft(vecLeft);
|
||||
SetUp(vecUp);
|
||||
SetOrigin(vecOrigin);
|
||||
}
|
||||
|
||||
[[nodiscard]] float* operator[](const int nIndex)
|
||||
{
|
||||
return arrData[nIndex];
|
||||
}
|
||||
|
||||
[[nodiscard]] const float* operator[](const int nIndex) const
|
||||
{
|
||||
return arrData[nIndex];
|
||||
}
|
||||
|
||||
constexpr void SetForward(const Vector_t& vecForward)
|
||||
{
|
||||
arrData[0][0] = vecForward.x;
|
||||
arrData[1][0] = vecForward.y;
|
||||
arrData[2][0] = vecForward.z;
|
||||
}
|
||||
|
||||
constexpr void SetLeft(const Vector_t& vecLeft)
|
||||
{
|
||||
arrData[0][1] = vecLeft.x;
|
||||
arrData[1][1] = vecLeft.y;
|
||||
arrData[2][1] = vecLeft.z;
|
||||
}
|
||||
|
||||
constexpr void SetUp(const Vector_t& vecUp)
|
||||
{
|
||||
arrData[0][2] = vecUp.x;
|
||||
arrData[1][2] = vecUp.y;
|
||||
arrData[2][2] = vecUp.z;
|
||||
}
|
||||
|
||||
constexpr void SetOrigin(const Vector_t& vecOrigin)
|
||||
{
|
||||
arrData[0][3] = vecOrigin.x;
|
||||
arrData[1][3] = vecOrigin.y;
|
||||
arrData[2][3] = vecOrigin.z;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr Vector_t GetForward() const
|
||||
{
|
||||
return { arrData[0][0], arrData[1][0], arrData[2][0] };
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr Vector_t GetLeft() const
|
||||
{
|
||||
return { arrData[0][1], arrData[1][1], arrData[2][1] };
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr Vector_t GetUp() const
|
||||
{
|
||||
return { arrData[0][2], arrData[1][2], arrData[2][2] };
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr Vector_t GetOrigin() const
|
||||
{
|
||||
return { arrData[0][3], arrData[1][3], arrData[2][3] };
|
||||
}
|
||||
|
||||
constexpr void Invalidate()
|
||||
{
|
||||
for (auto& arrSubData : arrData)
|
||||
{
|
||||
for (auto& flData : arrSubData)
|
||||
flData = std::numeric_limits<float>::infinity();
|
||||
}
|
||||
}
|
||||
|
||||
/// concatenate transformations of two matrices into one
|
||||
/// @returns: matrix with concatenated transformations
|
||||
[[nodiscard]] constexpr Matrix3x4_t ConcatTransforms(const Matrix3x4_t& matOther) const
|
||||
{
|
||||
return {
|
||||
arrData[0][0] * matOther.arrData[0][0] + arrData[0][1] * matOther.arrData[1][0] + arrData[0][2] * matOther.arrData[2][0],
|
||||
arrData[0][0] * matOther.arrData[0][1] + arrData[0][1] * matOther.arrData[1][1] + arrData[0][2] * matOther.arrData[2][1],
|
||||
arrData[0][0] * matOther.arrData[0][2] + arrData[0][1] * matOther.arrData[1][2] + arrData[0][2] * matOther.arrData[2][2],
|
||||
arrData[0][0] * matOther.arrData[0][3] + arrData[0][1] * matOther.arrData[1][3] + arrData[0][2] * matOther.arrData[2][3] + arrData[0][3],
|
||||
|
||||
arrData[1][0] * matOther.arrData[0][0] + arrData[1][1] * matOther.arrData[1][0] + arrData[1][2] * matOther.arrData[2][0],
|
||||
arrData[1][0] * matOther.arrData[0][1] + arrData[1][1] * matOther.arrData[1][1] + arrData[1][2] * matOther.arrData[2][1],
|
||||
arrData[1][0] * matOther.arrData[0][2] + arrData[1][1] * matOther.arrData[1][2] + arrData[1][2] * matOther.arrData[2][2],
|
||||
arrData[1][0] * matOther.arrData[0][3] + arrData[1][1] * matOther.arrData[1][3] + arrData[1][2] * matOther.arrData[2][3] + arrData[1][3],
|
||||
|
||||
arrData[2][0] * matOther.arrData[0][0] + arrData[2][1] * matOther.arrData[1][0] + arrData[2][2] * matOther.arrData[2][0],
|
||||
arrData[2][0] * matOther.arrData[0][1] + arrData[2][1] * matOther.arrData[1][1] + arrData[2][2] * matOther.arrData[2][1],
|
||||
arrData[2][0] * matOther.arrData[0][2] + arrData[2][1] * matOther.arrData[1][2] + arrData[2][2] * matOther.arrData[2][2],
|
||||
arrData[2][0] * matOther.arrData[0][3] + arrData[2][1] * matOther.arrData[1][3] + arrData[2][2] * matOther.arrData[2][3] + arrData[2][3]
|
||||
};
|
||||
}
|
||||
|
||||
/// @returns: angles converted from this matrix
|
||||
[[nodiscard]] QAngle_t ToAngles() const;
|
||||
|
||||
float arrData[3][4] = {};
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
class alignas(16) Matrix3x4a_t : public Matrix3x4_t
|
||||
{
|
||||
public:
|
||||
Matrix3x4a_t() = default;
|
||||
|
||||
constexpr Matrix3x4a_t(
|
||||
const float m00, const float m01, const float m02, const float m03,
|
||||
const float m10, const float m11, const float m12, const float m13,
|
||||
const float m20, const float m21, const float m22, const float m23)
|
||||
{
|
||||
arrData[0][0] = m00;
|
||||
arrData[0][1] = m01;
|
||||
arrData[0][2] = m02;
|
||||
arrData[0][3] = m03;
|
||||
arrData[1][0] = m10;
|
||||
arrData[1][1] = m11;
|
||||
arrData[1][2] = m12;
|
||||
arrData[1][3] = m13;
|
||||
arrData[2][0] = m20;
|
||||
arrData[2][1] = m21;
|
||||
arrData[2][2] = m22;
|
||||
arrData[2][3] = m23;
|
||||
}
|
||||
|
||||
constexpr Matrix3x4a_t(const Matrix3x4_t& matSource)
|
||||
{
|
||||
*this = matSource;
|
||||
}
|
||||
|
||||
constexpr Matrix3x4a_t& operator=(const Matrix3x4_t& matSource)
|
||||
{
|
||||
arrData[0][0] = matSource.arrData[0][0];
|
||||
arrData[0][1] = matSource.arrData[0][1];
|
||||
arrData[0][2] = matSource.arrData[0][2];
|
||||
arrData[0][3] = matSource.arrData[0][3];
|
||||
arrData[1][0] = matSource.arrData[1][0];
|
||||
arrData[1][1] = matSource.arrData[1][1];
|
||||
arrData[1][2] = matSource.arrData[1][2];
|
||||
arrData[1][3] = matSource.arrData[1][3];
|
||||
arrData[2][0] = matSource.arrData[2][0];
|
||||
arrData[2][1] = matSource.arrData[2][1];
|
||||
arrData[2][2] = matSource.arrData[2][2];
|
||||
arrData[2][3] = matSource.arrData[2][3];
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// concatenate transformations of two aligned matrices into one
|
||||
/// @returns: aligned matrix with concatenated transformations
|
||||
[[nodiscard]] Matrix3x4a_t ConcatTransforms(const Matrix3x4a_t& matOther) const
|
||||
{
|
||||
Matrix3x4a_t matOutput;
|
||||
CS_ASSERT((reinterpret_cast<std::uintptr_t>(this) & 15U) == 0 && (reinterpret_cast<std::uintptr_t>(&matOther) & 15U) == 0 && (reinterpret_cast<std::uintptr_t>(&matOutput) & 15U) == 0); // matrices aren't aligned
|
||||
|
||||
__m128 thisRow0 = _mm_load_ps(this->arrData[0]);
|
||||
__m128 thisRow1 = _mm_load_ps(this->arrData[1]);
|
||||
__m128 thisRow2 = _mm_load_ps(this->arrData[2]);
|
||||
|
||||
__m128 otherRow0 = _mm_load_ps(matOther.arrData[0]);
|
||||
__m128 otherRow1 = _mm_load_ps(matOther.arrData[1]);
|
||||
__m128 otherRow2 = _mm_load_ps(matOther.arrData[2]);
|
||||
|
||||
__m128 outRow0 = _mm_add_ps(_mm_mul_ps(_mm_shuffle_ps(thisRow0, thisRow0, _MM_SHUFFLE(0, 0, 0, 0)), otherRow0), _mm_add_ps(_mm_mul_ps(_mm_shuffle_ps(thisRow0, thisRow0, _MM_SHUFFLE(1, 1, 1, 1)), otherRow1), _mm_mul_ps(_mm_shuffle_ps(thisRow0, thisRow0, _MM_SHUFFLE(2, 2, 2, 2)), otherRow2)));
|
||||
__m128 outRow1 = _mm_add_ps(_mm_mul_ps(_mm_shuffle_ps(thisRow1, thisRow1, _MM_SHUFFLE(0, 0, 0, 0)), otherRow0), _mm_add_ps(_mm_mul_ps(_mm_shuffle_ps(thisRow1, thisRow1, _MM_SHUFFLE(1, 1, 1, 1)), otherRow1), _mm_mul_ps(_mm_shuffle_ps(thisRow1, thisRow1, _MM_SHUFFLE(2, 2, 2, 2)), otherRow2)));
|
||||
__m128 outRow2 = _mm_add_ps(_mm_mul_ps(_mm_shuffle_ps(thisRow2, thisRow2, _MM_SHUFFLE(0, 0, 0, 0)), otherRow0), _mm_add_ps(_mm_mul_ps(_mm_shuffle_ps(thisRow2, thisRow2, _MM_SHUFFLE(1, 1, 1, 1)), otherRow1), _mm_mul_ps(_mm_shuffle_ps(thisRow2, thisRow2, _MM_SHUFFLE(2, 2, 2, 2)), otherRow2)));
|
||||
|
||||
// add in translation vector
|
||||
constexpr std::uint32_t arrComponentMask[4] = { 0x0, 0x0, 0x0, 0xFFFFFFFF };
|
||||
outRow0 = _mm_add_ps(outRow0, _mm_and_ps(thisRow0, std::bit_cast<__m128>(arrComponentMask)));
|
||||
outRow1 = _mm_add_ps(outRow1, _mm_and_ps(thisRow1, std::bit_cast<__m128>(arrComponentMask)));
|
||||
outRow2 = _mm_add_ps(outRow2, _mm_and_ps(thisRow2, std::bit_cast<__m128>(arrComponentMask)));
|
||||
|
||||
_mm_store_ps(matOutput.arrData[0], outRow0);
|
||||
_mm_store_ps(matOutput.arrData[1], outRow1);
|
||||
_mm_store_ps(matOutput.arrData[2], outRow2);
|
||||
return matOutput;
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(alignof(Matrix3x4a_t) == 16);
|
||||
|
||||
#pragma pack(push, 4)
|
||||
|
||||
struct ViewMatrix_t
|
||||
{
|
||||
ViewMatrix_t() = default;
|
||||
|
||||
constexpr ViewMatrix_t(
|
||||
const float m00, const float m01, const float m02, const float m03,
|
||||
const float m10, const float m11, const float m12, const float m13,
|
||||
const float m20, const float m21, const float m22, const float m23,
|
||||
const float m30, const float m31, const float m32, const float m33)
|
||||
{
|
||||
arrData[0][0] = m00;
|
||||
arrData[0][1] = m01;
|
||||
arrData[0][2] = m02;
|
||||
arrData[0][3] = m03;
|
||||
arrData[1][0] = m10;
|
||||
arrData[1][1] = m11;
|
||||
arrData[1][2] = m12;
|
||||
arrData[1][3] = m13;
|
||||
arrData[2][0] = m20;
|
||||
arrData[2][1] = m21;
|
||||
arrData[2][2] = m22;
|
||||
arrData[2][3] = m23;
|
||||
arrData[3][0] = m30;
|
||||
arrData[3][1] = m31;
|
||||
arrData[3][2] = m32;
|
||||
arrData[3][3] = m33;
|
||||
}
|
||||
|
||||
constexpr ViewMatrix_t(const Matrix3x4_t& matFrom, const Vector4D_t& vecAdditionalRow = {})
|
||||
{
|
||||
arrData[0][0] = matFrom.arrData[0][0];
|
||||
arrData[0][1] = matFrom.arrData[0][1];
|
||||
arrData[0][2] = matFrom.arrData[0][2];
|
||||
arrData[0][3] = matFrom.arrData[0][3];
|
||||
arrData[1][0] = matFrom.arrData[1][0];
|
||||
arrData[1][1] = matFrom.arrData[1][1];
|
||||
arrData[1][2] = matFrom.arrData[1][2];
|
||||
arrData[1][3] = matFrom.arrData[1][3];
|
||||
arrData[2][0] = matFrom.arrData[2][0];
|
||||
arrData[2][1] = matFrom.arrData[2][1];
|
||||
arrData[2][2] = matFrom.arrData[2][2];
|
||||
arrData[2][3] = matFrom.arrData[2][3];
|
||||
arrData[3][0] = vecAdditionalRow.x;
|
||||
arrData[3][1] = vecAdditionalRow.y;
|
||||
arrData[3][2] = vecAdditionalRow.z;
|
||||
arrData[3][3] = vecAdditionalRow.w;
|
||||
}
|
||||
|
||||
[[nodiscard]] float* operator[](const int nIndex)
|
||||
{
|
||||
return arrData[nIndex];
|
||||
}
|
||||
|
||||
[[nodiscard]] const float* operator[](const int nIndex) const
|
||||
{
|
||||
return arrData[nIndex];
|
||||
}
|
||||
|
||||
[[nodiscard]] const bool operator==(const ViewMatrix_t& viewOther) const
|
||||
{
|
||||
return (
|
||||
arrData[0][0] == viewOther.arrData[0][0] && arrData[0][1] == viewOther.arrData[0][1] && arrData[0][2] == viewOther.arrData[0][2] && arrData[0][3] == viewOther.arrData[0][3] &&
|
||||
arrData[1][0] == viewOther.arrData[1][0] && arrData[1][1] == viewOther.arrData[1][1] && arrData[1][2] == viewOther.arrData[1][2] && arrData[1][3] == viewOther.arrData[1][3] &&
|
||||
arrData[2][0] == viewOther.arrData[2][0] && arrData[2][1] == viewOther.arrData[2][1] && arrData[2][2] == viewOther.arrData[2][2] && arrData[2][3] == viewOther.arrData[2][3] &&
|
||||
arrData[3][0] == viewOther.arrData[3][0] && arrData[3][1] == viewOther.arrData[3][1] && arrData[3][2] == viewOther.arrData[3][2] && arrData[3][3] == viewOther.arrData[3][3]);
|
||||
}
|
||||
|
||||
[[nodiscard]] const Matrix3x4_t& As3x4() const
|
||||
{
|
||||
return *reinterpret_cast<const Matrix3x4_t*>(this);
|
||||
}
|
||||
|
||||
[[nodiscard]] Matrix3x4_t& As3x4()
|
||||
{
|
||||
return *reinterpret_cast<Matrix3x4_t*>(this);
|
||||
}
|
||||
|
||||
constexpr ViewMatrix_t& operator+=(const ViewMatrix_t& matAdd)
|
||||
{
|
||||
for (std::uint8_t c = 0U; c < 4U; c++)
|
||||
{
|
||||
for (std::uint8_t r = 0U; r < 4U; r++)
|
||||
arrData[c][r] += matAdd[c][r];
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr ViewMatrix_t& operator-=(const ViewMatrix_t& matSubtract)
|
||||
{
|
||||
for (std::uint8_t c = 0U; c < 4U; c++)
|
||||
{
|
||||
for (std::uint8_t r = 0U; r < 4U; r++)
|
||||
arrData[c][r] -= matSubtract[c][r];
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr Vector4D_t GetRow(const int nIndex) const
|
||||
{
|
||||
return { arrData[nIndex][0], arrData[nIndex][1], arrData[nIndex][2], arrData[nIndex][3] };
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr Vector4D_t GetColumn(const int nIndex) const
|
||||
{
|
||||
return { arrData[0][nIndex], arrData[1][nIndex], arrData[2][nIndex], arrData[3][nIndex] };
|
||||
}
|
||||
|
||||
constexpr void Identity()
|
||||
{
|
||||
for (std::uint8_t c = 0U; c < 4U; c++)
|
||||
{
|
||||
for (std::uint8_t r = 0U; r < 4U; r++)
|
||||
arrData[c][r] = (c == r) ? 1.0f : 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/// concatenate transformations of two matrices into one
|
||||
/// @returns: matrix with concatenated transformations
|
||||
[[nodiscard]] constexpr ViewMatrix_t ConcatTransforms(const ViewMatrix_t& matOther) const
|
||||
{
|
||||
return {
|
||||
arrData[0][0] * matOther.arrData[0][0] + arrData[0][1] * matOther.arrData[1][0] + arrData[0][2] * matOther.arrData[2][0] + arrData[0][3] * matOther.arrData[3][0],
|
||||
arrData[0][0] * matOther.arrData[0][1] + arrData[0][1] * matOther.arrData[1][1] + arrData[0][2] * matOther.arrData[2][1] + arrData[0][3] * matOther.arrData[3][1],
|
||||
arrData[0][0] * matOther.arrData[0][2] + arrData[0][1] * matOther.arrData[1][2] + arrData[0][2] * matOther.arrData[2][2] + arrData[0][3] * matOther.arrData[3][2],
|
||||
arrData[0][0] * matOther.arrData[0][3] + arrData[0][1] * matOther.arrData[1][3] + arrData[0][2] * matOther.arrData[2][3] + arrData[0][3] * matOther.arrData[3][3],
|
||||
|
||||
arrData[1][0] * matOther.arrData[0][0] + arrData[1][1] * matOther.arrData[1][0] + arrData[1][2] * matOther.arrData[2][0] + arrData[1][3] * matOther.arrData[3][0],
|
||||
arrData[1][0] * matOther.arrData[0][1] + arrData[1][1] * matOther.arrData[1][1] + arrData[1][2] * matOther.arrData[2][1] + arrData[1][3] * matOther.arrData[3][1],
|
||||
arrData[1][0] * matOther.arrData[0][2] + arrData[1][1] * matOther.arrData[1][2] + arrData[1][2] * matOther.arrData[2][2] + arrData[1][3] * matOther.arrData[3][2],
|
||||
arrData[1][0] * matOther.arrData[0][3] + arrData[1][1] * matOther.arrData[1][3] + arrData[1][2] * matOther.arrData[2][3] + arrData[1][3] * matOther.arrData[3][3],
|
||||
|
||||
arrData[2][0] * matOther.arrData[0][0] + arrData[2][1] * matOther.arrData[1][0] + arrData[2][2] * matOther.arrData[2][0] + arrData[2][3] * matOther.arrData[3][0],
|
||||
arrData[2][0] * matOther.arrData[0][1] + arrData[2][1] * matOther.arrData[1][1] + arrData[2][2] * matOther.arrData[2][1] + arrData[2][3] * matOther.arrData[3][1],
|
||||
arrData[2][0] * matOther.arrData[0][2] + arrData[2][1] * matOther.arrData[1][2] + arrData[2][2] * matOther.arrData[2][2] + arrData[2][3] * matOther.arrData[3][2],
|
||||
arrData[2][0] * matOther.arrData[0][3] + arrData[2][1] * matOther.arrData[1][3] + arrData[2][2] * matOther.arrData[2][3] + arrData[2][3] * matOther.arrData[3][3],
|
||||
|
||||
arrData[3][0] * matOther.arrData[0][0] + arrData[3][1] * matOther.arrData[1][0] + arrData[3][2] * matOther.arrData[2][0] + arrData[3][3] * matOther.arrData[3][0],
|
||||
arrData[3][0] * matOther.arrData[0][1] + arrData[3][1] * matOther.arrData[1][1] + arrData[3][2] * matOther.arrData[2][1] + arrData[3][3] * matOther.arrData[3][1],
|
||||
arrData[3][0] * matOther.arrData[0][2] + arrData[3][1] * matOther.arrData[1][2] + arrData[3][2] * matOther.arrData[2][2] + arrData[3][3] * matOther.arrData[3][2],
|
||||
arrData[3][0] * matOther.arrData[0][3] + arrData[3][1] * matOther.arrData[1][3] + arrData[3][2] * matOther.arrData[2][3] + arrData[3][3] * matOther.arrData[3][3]
|
||||
};
|
||||
}
|
||||
|
||||
float arrData[4][4] = {};
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
struct Matrix2x4_t
|
||||
{
|
||||
public:
|
||||
Matrix3x4_t TranslateToMatrix3x4()
|
||||
{
|
||||
Matrix3x4_t matrix = Matrix3x4_t();
|
||||
Vector4D_t vecRotation = Vector4D_t();
|
||||
Vector_t vecPosition = Vector_t();
|
||||
|
||||
vecRotation.x = this->_21; //rot.x
|
||||
vecRotation.y = this->_22; //rot.y
|
||||
vecRotation.z = this->_23; //rot.z
|
||||
vecRotation.w = this->_24; //rot.w
|
||||
|
||||
vecPosition.x = this->_11; //bonepos.x
|
||||
vecPosition.y = this->_12; //bonepos.y
|
||||
vecPosition.z = this->_13; //bonepos.z
|
||||
|
||||
matrix[0][0] = 1.0f - 2.0f * vecRotation.y * vecRotation.y - 2.0f * vecRotation.z * vecRotation.z;
|
||||
matrix[1][0] = 2.0f * vecRotation.x * vecRotation.y + 2.0f * vecRotation.w * vecRotation.z;
|
||||
matrix[2][0] = 2.0f * vecRotation.x * vecRotation.z - 2.0f * vecRotation.w * vecRotation.y;
|
||||
|
||||
matrix[0][1] = 2.0f * vecRotation.x * vecRotation.y - 2.0f * vecRotation.w * vecRotation.z;
|
||||
matrix[1][1] = 1.0f - 2.0f * vecRotation.x * vecRotation.x - 2.0f * vecRotation.z * vecRotation.z;
|
||||
matrix[2][1] = 2.0f * vecRotation.y * vecRotation.z + 2.0f * vecRotation.w * vecRotation.x;
|
||||
|
||||
matrix[0][2] = 2.0f * vecRotation.x * vecRotation.z + 2.0f * vecRotation.w * vecRotation.y;
|
||||
matrix[1][2] = 2.0f * vecRotation.y * vecRotation.z - 2.0f * vecRotation.w * vecRotation.x;
|
||||
matrix[2][2] = 1.0f - 2.0f * vecRotation.x * vecRotation.x - 2.0f * vecRotation.y * vecRotation.y;
|
||||
|
||||
matrix[0][3] = vecPosition.x;
|
||||
matrix[1][3] = vecPosition.y;
|
||||
matrix[2][3] = vecPosition.z;
|
||||
|
||||
return matrix;
|
||||
}
|
||||
|
||||
[[nodiscard]] const Vector_t GetOrigin(int nIndex)
|
||||
{
|
||||
return Vector_t(this[nIndex]._11, this[nIndex]._12, this[nIndex]._13);
|
||||
}
|
||||
|
||||
const void SetOrigin(int nIndex, Vector_t vecValue)
|
||||
{
|
||||
this[nIndex]._11 = vecValue.x;
|
||||
this[nIndex]._12 = vecValue.y;
|
||||
this[nIndex]._13 = vecValue.z;
|
||||
}
|
||||
|
||||
[[nodiscard]] const Vector4D_t GetRotation(int nIndex)
|
||||
{
|
||||
return Vector4D_t(this[nIndex]._21, this[nIndex]._22, this[nIndex]._23, this[nIndex]._24);
|
||||
}
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
float _11, _12, _13, _14;
|
||||
float _21, _22, _23, _24;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,52 @@
|
||||
#include "qangle.h"
|
||||
|
||||
// used: [d3d] xmscalarsincos
|
||||
#include <directxmath.h>
|
||||
|
||||
#include "matrix.h"
|
||||
|
||||
// used: m_deg2rad
|
||||
#include "../../utilities/math.h"
|
||||
|
||||
void QAngle_t::ToDirections(Vector_t* pvecForward, Vector_t* pvecRight, Vector_t* pvecUp) const
|
||||
{
|
||||
float flPitchSin, flPitchCos, flYawSin, flYawCos, flRollSin, flRollCos;
|
||||
DirectX::XMScalarSinCos(&flPitchSin, &flPitchCos, M_DEG2RAD(this->x));
|
||||
DirectX::XMScalarSinCos(&flYawSin, &flYawCos, M_DEG2RAD(this->y));
|
||||
DirectX::XMScalarSinCos(&flRollSin, &flRollCos, M_DEG2RAD(this->z));
|
||||
|
||||
if (pvecForward != nullptr)
|
||||
{
|
||||
pvecForward->x = flPitchCos * flYawCos;
|
||||
pvecForward->y = flPitchCos * flYawSin;
|
||||
pvecForward->z = -flPitchSin;
|
||||
}
|
||||
|
||||
if (pvecRight != nullptr)
|
||||
{
|
||||
pvecRight->x = (-flRollSin * flPitchSin * flYawCos) + (-flRollCos * -flYawSin);
|
||||
pvecRight->y = (-flRollSin * flPitchSin * flYawSin) + (-flRollCos * flYawCos);
|
||||
pvecRight->z = (-flRollSin * flPitchCos);
|
||||
}
|
||||
|
||||
if (pvecUp != nullptr)
|
||||
{
|
||||
pvecUp->x = (flRollCos * flPitchSin * flYawCos) + (-flRollSin * -flYawSin);
|
||||
pvecUp->y = (flRollCos * flPitchSin * flYawSin) + (-flRollSin * flYawCos);
|
||||
pvecUp->z = (flRollCos * flPitchCos);
|
||||
}
|
||||
}
|
||||
|
||||
Matrix3x4_t QAngle_t::ToMatrix(const Vector_t& vecOrigin) const
|
||||
{
|
||||
float flPitchSin, flPitchCos, flYawSin, flYawCos, flRollSin, flRollCos;
|
||||
DirectX::XMScalarSinCos(&flPitchSin, &flPitchCos, M_DEG2RAD(this->x));
|
||||
DirectX::XMScalarSinCos(&flYawSin, &flYawCos, M_DEG2RAD(this->y));
|
||||
DirectX::XMScalarSinCos(&flRollSin, &flRollCos, M_DEG2RAD(this->z));
|
||||
|
||||
return {
|
||||
(flPitchCos * flYawCos), (flRollSin * flPitchSin * flYawCos + flRollCos * -flYawSin), (flRollCos * flPitchSin * flYawCos + -flRollSin * -flYawSin), vecOrigin.x,
|
||||
(flPitchCos * flYawSin), (flRollSin * flPitchSin * flYawSin + flRollCos * flYawCos), (flRollCos * flPitchSin * flYawSin + -flRollSin * flYawCos), vecOrigin.y,
|
||||
(-flPitchSin), (flRollSin * flPitchCos), (flRollCos * flPitchCos), vecOrigin.z
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
#pragma once
|
||||
// used: [crt] isfinite, fmodf, remainderf
|
||||
#include <cmath>
|
||||
|
||||
#include "vector.h"
|
||||
|
||||
// used: clamp
|
||||
#include "../../utilities/crt.h"
|
||||
|
||||
// forward declarations
|
||||
struct Matrix3x4_t;
|
||||
|
||||
struct QAngle_t
|
||||
{
|
||||
constexpr QAngle_t(float x = 0.f, float y = 0.f, float z = 0.f) :
|
||||
x(x), y(y), z(z) { }
|
||||
|
||||
constexpr QAngle_t(const float* arrAngles) :
|
||||
x(arrAngles[0]), y(arrAngles[1]), z(arrAngles[2]) { }
|
||||
|
||||
#pragma region qangle_array_operators
|
||||
|
||||
[[nodiscard]] float& operator[](const int nIndex)
|
||||
{
|
||||
return reinterpret_cast<float*>(this)[nIndex];
|
||||
}
|
||||
|
||||
[[nodiscard]] const float& operator[](const int nIndex) const
|
||||
{
|
||||
return reinterpret_cast<const float*>(this)[nIndex];
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region qangle_relational_operators
|
||||
|
||||
bool operator==(const QAngle_t& angBase) const
|
||||
{
|
||||
return this->IsEqual(angBase);
|
||||
}
|
||||
|
||||
bool operator!=(const QAngle_t& angBase) const
|
||||
{
|
||||
return !this->IsEqual(angBase);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region qangle_assignment_operators
|
||||
|
||||
constexpr QAngle_t& operator=(const QAngle_t& angBase)
|
||||
{
|
||||
this->x = angBase.x;
|
||||
this->y = angBase.y;
|
||||
this->z = angBase.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region qangle_arithmetic_assignment_operators
|
||||
|
||||
constexpr QAngle_t& operator+=(const QAngle_t& angBase)
|
||||
{
|
||||
this->x += angBase.x;
|
||||
this->y += angBase.y;
|
||||
this->z += angBase.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr QAngle_t& operator-=(const QAngle_t& angBase)
|
||||
{
|
||||
this->x -= angBase.x;
|
||||
this->y -= angBase.y;
|
||||
this->z -= angBase.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr QAngle_t& operator*=(const QAngle_t& angBase)
|
||||
{
|
||||
this->x *= angBase.x;
|
||||
this->y *= angBase.y;
|
||||
this->z *= angBase.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr QAngle_t& operator/=(const QAngle_t& angBase)
|
||||
{
|
||||
this->x /= angBase.x;
|
||||
this->y /= angBase.y;
|
||||
this->z /= angBase.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr QAngle_t& operator+=(const float flAdd)
|
||||
{
|
||||
this->x += flAdd;
|
||||
this->y += flAdd;
|
||||
this->z += flAdd;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr QAngle_t& operator-=(const float flSubtract)
|
||||
{
|
||||
this->x -= flSubtract;
|
||||
this->y -= flSubtract;
|
||||
this->z -= flSubtract;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr QAngle_t& operator*=(const float flMultiply)
|
||||
{
|
||||
this->x *= flMultiply;
|
||||
this->y *= flMultiply;
|
||||
this->z *= flMultiply;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr QAngle_t& operator/=(const float flDivide)
|
||||
{
|
||||
this->x /= flDivide;
|
||||
this->y /= flDivide;
|
||||
this->z /= flDivide;
|
||||
return *this;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region qangle_arithmetic_unary_operators
|
||||
|
||||
constexpr QAngle_t& operator-()
|
||||
{
|
||||
this->x = -this->x;
|
||||
this->y = -this->y;
|
||||
this->z = -this->z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr QAngle_t operator-() const
|
||||
{
|
||||
return { -this->x, -this->y, -this->z };
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region qangle_arithmetic_ternary_operators
|
||||
|
||||
constexpr QAngle_t operator+(const QAngle_t& angAdd) const
|
||||
{
|
||||
return { this->x + angAdd.x, this->y + angAdd.y, this->z + angAdd.z };
|
||||
}
|
||||
|
||||
constexpr QAngle_t operator-(const QAngle_t& angSubtract) const
|
||||
{
|
||||
return { this->x - angSubtract.x, this->y - angSubtract.y, this->z - angSubtract.z };
|
||||
}
|
||||
|
||||
constexpr QAngle_t operator*(const QAngle_t& angMultiply) const
|
||||
{
|
||||
return { this->x * angMultiply.x, this->y * angMultiply.y, this->z * angMultiply.z };
|
||||
}
|
||||
|
||||
constexpr QAngle_t operator/(const QAngle_t& angDivide) const
|
||||
{
|
||||
return { this->x / angDivide.x, this->y / angDivide.y, this->z / angDivide.z };
|
||||
}
|
||||
|
||||
constexpr QAngle_t operator+(const float flAdd) const
|
||||
{
|
||||
return { this->x + flAdd, this->y + flAdd, this->z + flAdd };
|
||||
}
|
||||
|
||||
constexpr QAngle_t operator-(const float flSubtract) const
|
||||
{
|
||||
return { this->x - flSubtract, this->y - flSubtract, this->z - flSubtract };
|
||||
}
|
||||
|
||||
constexpr QAngle_t operator*(const float flMultiply) const
|
||||
{
|
||||
return { this->x * flMultiply, this->y * flMultiply, this->z * flMultiply };
|
||||
}
|
||||
|
||||
constexpr QAngle_t operator/(const float flDivide) const
|
||||
{
|
||||
return { this->x / flDivide, this->y / flDivide, this->z / flDivide };
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
// @returns : true if each component of angle is finite, false otherwise
|
||||
[[nodiscard]] bool IsValid() const
|
||||
{
|
||||
return (std::isfinite(this->x) && std::isfinite(this->y) && std::isfinite(this->z));
|
||||
}
|
||||
|
||||
/// @returns: true if each component of angle equals to another, false otherwise
|
||||
[[nodiscard]] bool IsEqual(const QAngle_t& angEqual, const float flErrorMargin = std::numeric_limits<float>::epsilon()) const
|
||||
{
|
||||
return (std::fabsf(this->x - angEqual.x) < flErrorMargin && std::fabsf(this->y - angEqual.y) < flErrorMargin && std::fabsf(this->z - angEqual.z) < flErrorMargin);
|
||||
}
|
||||
|
||||
/// @returns: true if each component of angle equals zero, false otherwise
|
||||
[[nodiscard]] bool IsZero() const
|
||||
{
|
||||
// @test: to make this implementation right, we should use fpclassify here, but game aren't doing same, probably it's better to keep this same, just ensure that it will be compiled same
|
||||
return (this->x == 0.0f && this->y == 0.0f && this->z == 0.0f);
|
||||
}
|
||||
|
||||
/// @returns: length of hypotenuse
|
||||
[[nodiscard]] float Length2D() const
|
||||
{
|
||||
return std::sqrtf(x * x + y * y);
|
||||
}
|
||||
|
||||
/// clamp each angle component by minimal/maximal allowed value for source sdk games
|
||||
/// @returns: clamped angle
|
||||
constexpr QAngle_t& Clamp()
|
||||
{
|
||||
this->x = MATH::Clamp(this->x, -89.f, 89.f);
|
||||
this->y = MATH::Clamp(this->y, -180.f, 180.f);
|
||||
this->z = MATH::Clamp(this->z, -45.f, 45.f);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// map polar angles to the range of [-180, 180] degrees
|
||||
/// @returns: normalized angle
|
||||
QAngle_t& Normalize()
|
||||
{
|
||||
this->x = std::remainderf(this->x, 360.f);
|
||||
this->y = std::remainderf(this->y, 360.f);
|
||||
this->z = std::remainderf(this->z, 360.f);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// convert angle to direction vectors
|
||||
/// @param[out] pvecForward [optional] output for converted forward vector
|
||||
/// @param[out] pvecRight [optional] output for converted right vector
|
||||
/// @param[out] pvecUp [optional] output for converted up vector
|
||||
void ToDirections(Vector_t* pvecForward, Vector_t* pvecRight = nullptr, Vector_t* pvecUp = nullptr) const;
|
||||
|
||||
/// @param[in] vecOrigin [optional] origin for converted matrix
|
||||
/// @returns: matrix converted from angle
|
||||
[[nodiscard]] Matrix3x4_t ToMatrix(const Vector_t& vecOrigin = {}) const;
|
||||
|
||||
public:
|
||||
float x = 0.0f, y = 0.0f, z = 0.0f;
|
||||
};
|
||||
@@ -0,0 +1,74 @@
|
||||
#pragma once
|
||||
|
||||
struct Quaternion_t
|
||||
{
|
||||
constexpr Quaternion_t(const float x = 0.0f, const float y = 0.0f, const float z = 0.0f, const float w = 0.0f) :
|
||||
x(x), y(y), z(z), w(w) { }
|
||||
|
||||
[[nodiscard]] bool IsValid() const
|
||||
{
|
||||
return (std::isfinite(x) && std::isfinite(y) && std::isfinite(z) && std::isfinite(w));
|
||||
}
|
||||
|
||||
/// @param[in] vecOrigin [optional] translation for converted matrix
|
||||
/// @returns: matrix converted from quaternion
|
||||
[[nodiscard]] Matrix3x4_t ToMatrix(const Vector_t& vecOrigin = {}) const
|
||||
{
|
||||
CS_ASSERT(this->IsValid());
|
||||
|
||||
Matrix3x4_t matOut;
|
||||
|
||||
#ifdef _DEBUG // precalculate common multiplications
|
||||
const float x2 = this->x + this->x, y2 = this->y + this->y, z2 = this->z + this->z;
|
||||
const float xx = this->x * x2, xy = this->x * y2, xz = this->x * z2;
|
||||
const float yy = this->y * y2, yz = this->y * z2;
|
||||
const float zz = this->z * z2;
|
||||
const float wx = this->w * x2, wy = this->w * y2, wz = this->w * z2;
|
||||
|
||||
matOut[0][0] = 1.0f - (yy + zz);
|
||||
matOut[1][0] = xy + wz;
|
||||
matOut[2][0] = xz - wy;
|
||||
|
||||
matOut[0][1] = xy - wz;
|
||||
matOut[1][1] = 1.0f - (xx + zz);
|
||||
matOut[2][1] = yz + wx;
|
||||
|
||||
matOut[0][2] = xz + wy;
|
||||
matOut[1][2] = yz - wx;
|
||||
matOut[2][2] = 1.0f - (xx + yy);
|
||||
#else // let the compiler optimize calculations itself
|
||||
matOut[0][0] = 1.0f - 2.0f * this->y * this->y - 2.0f * this->z * this->z;
|
||||
matOut[1][0] = 2.0f * this->x * this->y + 2.0f * this->w * this->z;
|
||||
matOut[2][0] = 2.0f * this->x * this->z - 2.0f * this->w * this->y;
|
||||
|
||||
matOut[0][1] = 2.0f * this->x * this->y - 2.0f * this->w * this->z;
|
||||
matOut[1][1] = 1.0f - 2.0f * this->x * this->x - 2.0f * this->z * this->z;
|
||||
matOut[2][1] = 2.0f * this->y * this->z + 2.0f * this->w * this->x;
|
||||
|
||||
matOut[0][2] = 2.0f * this->x * this->z + 2.0f * this->w * this->y;
|
||||
matOut[1][2] = 2.0f * this->y * this->z - 2.0f * this->w * this->x;
|
||||
matOut[2][2] = 1.0f - 2.0f * this->x * this->x - 2.0f * this->y * this->y;
|
||||
#endif
|
||||
|
||||
matOut[0][3] = vecOrigin.x;
|
||||
matOut[1][3] = vecOrigin.y;
|
||||
matOut[2][3] = vecOrigin.z;
|
||||
return matOut;
|
||||
}
|
||||
|
||||
float x, y, z, w;
|
||||
};
|
||||
|
||||
struct alignas(16) QuaternionAligned_t : Quaternion_t
|
||||
{
|
||||
QuaternionAligned_t& operator=(const Quaternion_t& quatOther)
|
||||
{
|
||||
this->x = quatOther.x;
|
||||
this->y = quatOther.y;
|
||||
this->z = quatOther.z;
|
||||
this->w = quatOther.w;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(alignof(QuaternionAligned_t) == 16);
|
||||
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
struct ResourceBinding_t
|
||||
{
|
||||
void* pData;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class CStrongHandle
|
||||
{
|
||||
public:
|
||||
operator T* () const
|
||||
{
|
||||
if (pBinding == nullptr)
|
||||
return nullptr;
|
||||
|
||||
return static_cast<T*>(pBinding->pData);
|
||||
}
|
||||
|
||||
T* operator->() const
|
||||
{
|
||||
if (pBinding == nullptr)
|
||||
return nullptr;
|
||||
|
||||
return static_cast<T*>(pBinding->pData);
|
||||
}
|
||||
|
||||
const ResourceBinding_t* pBinding;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
// used: matResult
|
||||
#include "matrix.h"
|
||||
// used: quaternion
|
||||
#include "quaternion.h"
|
||||
|
||||
class CTransform
|
||||
{
|
||||
public:
|
||||
VectorAligned_t vecPosition;
|
||||
QuaternionAligned_t quatOrientation;
|
||||
};
|
||||
|
||||
static_assert(alignof(CTransform) == 16);
|
||||
@@ -0,0 +1,288 @@
|
||||
#pragma once
|
||||
|
||||
// used: QAngle_t
|
||||
#include "qangle.h"
|
||||
// used: MEM_PAD
|
||||
#include "../../utilities/memory.h"
|
||||
// used: memalloc
|
||||
#include "../../core/interfaces.h"
|
||||
#include "../interfaces/imemalloc.h"
|
||||
|
||||
// @source: server.dll
|
||||
enum ECommandButtons : std::uint64_t
|
||||
{
|
||||
IN_ATTACK = 1 << 0,
|
||||
IN_JUMP = 1 << 1,
|
||||
IN_DUCK = 1 << 2,
|
||||
IN_FORWARD = 1 << 3,
|
||||
IN_BACK = 1 << 4,
|
||||
IN_USE = 1 << 5,
|
||||
IN_LEFT = 1 << 7,
|
||||
IN_RIGHT = 1 << 8,
|
||||
IN_MOVELEFT = 1 << 9,
|
||||
IN_MOVERIGHT = 1 << 10,
|
||||
IN_SECOND_ATTACK = 1 << 11,
|
||||
IN_RELOAD = 1 << 13,
|
||||
IN_SPRINT = 1 << 16,
|
||||
IN_JOYAUTOSPRINT = 1 << 17,
|
||||
IN_SHOWSCORES = 1ULL << 33,
|
||||
IN_ZOOM = 1ULL << 34,
|
||||
IN_LOOKATWEAPON = 1ULL << 35
|
||||
};
|
||||
|
||||
// compiled protobuf messages and looked at what bits are used in them
|
||||
enum ESubtickMoveStepBits : std::uint32_t
|
||||
{
|
||||
MOVESTEP_BITS_BUTTON = 0x1U,
|
||||
MOVESTEP_BITS_PRESSED = 0x2U,
|
||||
MOVESTEP_BITS_WHEN = 0x4U,
|
||||
MOVESTEP_BITS_ANALOG_FORWARD_DELTA = 0x8U,
|
||||
MOVESTEP_BITS_ANALOG_LEFT_DELTA = 0x10U
|
||||
};
|
||||
|
||||
enum EInputHistoryBits : std::uint32_t
|
||||
{
|
||||
INPUT_HISTORY_BITS_VIEWANGLES = 0x1U,
|
||||
INPUT_HISTORY_BITS_SHOOTPOSITION = 0x2U,
|
||||
INPUT_HISTORY_BITS_TARGETHEADPOSITIONCHECK = 0x4U,
|
||||
INPUT_HISTORY_BITS_TARGETABSPOSITIONCHECK = 0x8U,
|
||||
INPUT_HISTORY_BITS_TARGETANGCHECK = 0x10U,
|
||||
INPUT_HISTORY_BITS_CL_INTERP = 0x20U,
|
||||
INPUT_HISTORY_BITS_SV_INTERP0 = 0x40U,
|
||||
INPUT_HISTORY_BITS_SV_INTERP1 = 0x80U,
|
||||
INPUT_HISTORY_BITS_PLAYER_INTERP = 0x100U,
|
||||
INPUT_HISTORY_BITS_RENDERTICKCOUNT = 0x200U,
|
||||
INPUT_HISTORY_BITS_RENDERTICKFRACTION = 0x400U,
|
||||
INPUT_HISTORY_BITS_PLAYERTICKCOUNT = 0x800U,
|
||||
INPUT_HISTORY_BITS_PLAYERTICKFRACTION = 0x1000U,
|
||||
INPUT_HISTORY_BITS_FRAMENUMBER = 0x2000U,
|
||||
INPUT_HISTORY_BITS_TARGETENTINDEX = 0x4000U
|
||||
};
|
||||
|
||||
enum EButtonStatePBBits : uint32_t
|
||||
{
|
||||
BUTTON_STATE_PB_BITS_BUTTONSTATE1 = 0x1U,
|
||||
BUTTON_STATE_PB_BITS_BUTTONSTATE2 = 0x2U,
|
||||
BUTTON_STATE_PB_BITS_BUTTONSTATE3 = 0x4U
|
||||
};
|
||||
|
||||
enum EBaseCmdBits : std::uint32_t
|
||||
{
|
||||
BASE_BITS_MOVE_CRC = 0x1U,
|
||||
BASE_BITS_BUTTONPB = 0x2U,
|
||||
BASE_BITS_VIEWANGLES = 0x4U,
|
||||
BASE_BITS_COMMAND_NUMBER = 0x8U,
|
||||
BASE_BITS_CLIENT_TICK = 0x10U,
|
||||
BASE_BITS_FORWARDMOVE = 0x20U,
|
||||
BASE_BITS_LEFTMOVE = 0x40U,
|
||||
BASE_BITS_UPMOVE = 0x80U,
|
||||
BASE_BITS_IMPULSE = 0x100U,
|
||||
BASE_BITS_WEAPON_SELECT = 0x200U,
|
||||
BASE_BITS_RANDOM_SEED = 0x400U,
|
||||
BASE_BITS_MOUSEDX = 0x800U,
|
||||
BASE_BITS_MOUSEDY = 0x1000U,
|
||||
BASE_BITS_CONSUMED_SERVER_ANGLE = 0x2000U,
|
||||
BASE_BITS_CMD_FLAGS = 0x4000U,
|
||||
BASE_BITS_ENTITY_HANDLE = 0x8000U
|
||||
};
|
||||
|
||||
enum ECSGOUserCmdBits : std::uint32_t
|
||||
{
|
||||
CSGOUSERCMD_BITS_BASECMD = 0x1U,
|
||||
CSGOUSERCMD_BITS_LEFTHAND = 0x2U,
|
||||
CSGOUSERCMD_BITS_ATTACK3START = 0x4U,
|
||||
CSGOUSERCMD_BITS_ATTACK1START = 0x8U,
|
||||
CSGOUSERCMD_BITS_ATTACK2START = 0x10U
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct RepeatedPtrField_t
|
||||
{
|
||||
struct Rep_t
|
||||
{
|
||||
int nAllocatedSize;
|
||||
T* tElements[(std::numeric_limits<int>::max() - 2 * sizeof(int)) / sizeof(void*)];
|
||||
};
|
||||
|
||||
void* pArena;
|
||||
int nCurrentSize;
|
||||
int nTotalSize;
|
||||
Rep_t* pRep;
|
||||
};
|
||||
|
||||
class CBasePB
|
||||
{
|
||||
public:
|
||||
MEM_PAD(0x8) // 0x0 VTABLE
|
||||
std::uint32_t nHasBits; // 0x8
|
||||
std::uint64_t nCachedBits; // 0xC
|
||||
|
||||
void SetBits(std::uint64_t nBits)
|
||||
{
|
||||
// @note: you don't need to check if the bits are already set as bitwise OR will not change the value if the bit is already set
|
||||
nCachedBits |= nBits;
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(CBasePB) == 0x18);
|
||||
|
||||
class CMsgQAngle : public CBasePB
|
||||
{
|
||||
public:
|
||||
QAngle_t angValue; // 0x18
|
||||
};
|
||||
|
||||
static_assert(sizeof(CMsgQAngle) == 0x28);
|
||||
|
||||
class CMsgVector : public CBasePB
|
||||
{
|
||||
public:
|
||||
Vector4D_t vecValue; // 0x18
|
||||
};
|
||||
|
||||
static_assert(sizeof(CMsgVector) == 0x28);
|
||||
|
||||
class CCSGOInterpolationInfoPB : public CBasePB
|
||||
{
|
||||
public:
|
||||
float flFraction; // 0x18
|
||||
int nSrcTick; // 0x1C
|
||||
int nDstTick; // 0x20
|
||||
};
|
||||
|
||||
static_assert(sizeof(CCSGOInterpolationInfoPB) == 0x28);
|
||||
|
||||
class CCSGOInputHistoryEntryPB : public CBasePB
|
||||
{
|
||||
public:
|
||||
CMsgQAngle* pViewAngles; // 0x18
|
||||
CMsgVector* pShootPosition; // 0x20
|
||||
CMsgVector* pTargetHeadPositionCheck; // 0x28
|
||||
CMsgVector* pTargetAbsPositionCheck; // 0x30
|
||||
CMsgQAngle* pTargetAngPositionCheck; // 0x38
|
||||
CCSGOInterpolationInfoPB* cl_interp; // 0x40
|
||||
CCSGOInterpolationInfoPB* sv_interp0; // 0x48
|
||||
CCSGOInterpolationInfoPB* sv_interp1; // 0x50
|
||||
CCSGOInterpolationInfoPB* player_interp; // 0x58
|
||||
int nRenderTickCount; // 0x60
|
||||
float flRenderTickFraction; // 0x64
|
||||
int nPlayerTickCount; // 0x68
|
||||
float flPlayerTickFraction; // 0x6C
|
||||
int nFrameNumber; // 0x70
|
||||
int nTargetEntIndex; // 0x74
|
||||
};
|
||||
|
||||
static_assert(sizeof(CCSGOInputHistoryEntryPB) == 0x78);
|
||||
|
||||
struct CInButtonStatePB : CBasePB
|
||||
{
|
||||
std::uint64_t nValue;
|
||||
std::uint64_t nValueChanged;
|
||||
std::uint64_t nValueScroll;
|
||||
};
|
||||
|
||||
static_assert(sizeof(CInButtonStatePB) == 0x30);
|
||||
|
||||
struct CSubtickMoveStep : CBasePB
|
||||
{
|
||||
public:
|
||||
std::uint64_t nButton;
|
||||
bool bPressed;
|
||||
float flWhen;
|
||||
float flAnalogForwardDelta;
|
||||
float flAnalogLeftDelta;
|
||||
};
|
||||
|
||||
static_assert(sizeof(CSubtickMoveStep) == 0x30);
|
||||
|
||||
class CBaseUserCmdPB : public CBasePB
|
||||
{
|
||||
public:
|
||||
RepeatedPtrField_t<CSubtickMoveStep> subtickMovesField;
|
||||
std::string* strMoveCrc;
|
||||
CInButtonStatePB* pInButtonState;
|
||||
CMsgQAngle* pViewAngles;
|
||||
std::int32_t nLegacyCommandNumber;
|
||||
std::int32_t nClientTick;
|
||||
float flForwardMove;
|
||||
float flSideMove;
|
||||
float flUpMove;
|
||||
std::int32_t nImpulse;
|
||||
std::int32_t nWeaponSelect;
|
||||
std::int32_t nRandomSeed;
|
||||
std::int32_t nMousedX;
|
||||
std::int32_t nMousedY;
|
||||
std::uint32_t nConsumedServerAngleChanges;
|
||||
std::int32_t nCmdFlags;
|
||||
std::uint32_t nPawnEntityHandle;
|
||||
|
||||
int CalculateCmdCRCSize()
|
||||
{
|
||||
return MEM::CallVFunc<int, 7U>(this);
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(CBaseUserCmdPB) == 0x80);
|
||||
|
||||
class CCSGOUserCmdPB
|
||||
{
|
||||
public:
|
||||
std::uint32_t nHasBits;
|
||||
std::uint64_t nCachedSize;
|
||||
RepeatedPtrField_t<CCSGOInputHistoryEntryPB> inputHistoryField;
|
||||
CBaseUserCmdPB* pBaseCmd;
|
||||
bool bLeftHandDesired;
|
||||
std::int32_t nAttack3StartHistoryIndex;
|
||||
std::int32_t nAttack1StartHistoryIndex;
|
||||
std::int32_t nAttack2StartHistoryIndex;
|
||||
|
||||
// @note: this function is used to check if the bits are set and set them if they are not
|
||||
void CheckAndSetBits(std::uint32_t nBits)
|
||||
{
|
||||
if (!(nHasBits & nBits))
|
||||
nHasBits |= nBits;
|
||||
}
|
||||
};
|
||||
static_assert(sizeof(CCSGOUserCmdPB) == 0x40);
|
||||
|
||||
struct CInButtonState
|
||||
{
|
||||
public:
|
||||
MEM_PAD(0x8) // 0x0 VTABLE
|
||||
std::uint64_t nValue; // 0x8
|
||||
std::uint64_t nValueChanged; // 0x10
|
||||
std::uint64_t nValueScroll; // 0x18
|
||||
};
|
||||
static_assert(sizeof(CInButtonState) == 0x20);
|
||||
|
||||
class CUserCmd
|
||||
{
|
||||
public:
|
||||
MEM_PAD(0x8); // 0x0 VTABLE
|
||||
MEM_PAD(0x10); // TODO: find out what this is, added 14.08.2024
|
||||
CCSGOUserCmdPB csgoUserCmd; // 0x18
|
||||
CInButtonState nButtons; // 0x58
|
||||
MEM_PAD(0x20); // 0x78
|
||||
|
||||
CCSGOInputHistoryEntryPB* GetInputHistoryEntry(int nIndex)
|
||||
{
|
||||
if (nIndex >= csgoUserCmd.inputHistoryField.pRep->nAllocatedSize || nIndex >= csgoUserCmd.inputHistoryField.nCurrentSize)
|
||||
return nullptr;
|
||||
|
||||
return csgoUserCmd.inputHistoryField.pRep->tElements[nIndex];
|
||||
}
|
||||
|
||||
void SetSubTickAngle(const QAngle_t& angView)
|
||||
{
|
||||
for (int i = 0; i < this->csgoUserCmd.inputHistoryField.pRep->nAllocatedSize; i++)
|
||||
{
|
||||
CCSGOInputHistoryEntryPB* pInputEntry = this->GetInputHistoryEntry(i);
|
||||
if (!pInputEntry || !pInputEntry->pViewAngles)
|
||||
continue;
|
||||
|
||||
pInputEntry->pViewAngles->angValue = angView;
|
||||
pInputEntry->SetBits(EInputHistoryBits::INPUT_HISTORY_BITS_VIEWANGLES);
|
||||
}
|
||||
}
|
||||
};
|
||||
static_assert(sizeof(CUserCmd) == 0x98);
|
||||
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
// used: MEM_PAD
|
||||
#include "../../utilities/memory.h"
|
||||
|
||||
class CUtlBuffer
|
||||
{
|
||||
public:
|
||||
MEM_PAD(0x80);
|
||||
|
||||
CUtlBuffer(int a1, int nSize, int a3)
|
||||
{
|
||||
#ifdef CS_PARANOID
|
||||
CS_ASSERT(MEM::fnUtlBufferInit != nullptr);
|
||||
#endif
|
||||
|
||||
MEM::fnUtlBufferInit(this, a1, nSize, a3);
|
||||
}
|
||||
|
||||
void PutString(const char* szString)
|
||||
{
|
||||
#ifdef CS_PARANOID
|
||||
CS_ASSERT(MEM::fnUtlBufferPutString != nullptr);
|
||||
#endif
|
||||
|
||||
MEM::fnUtlBufferPutString(this, szString);
|
||||
}
|
||||
|
||||
void EnsureCapacity(int nSize)
|
||||
{
|
||||
#ifdef CS_PARANOID
|
||||
CS_ASSERT(MEM::fnUtlBufferEnsureCapacity != nullptr);
|
||||
#endif
|
||||
|
||||
MEM::fnUtlBufferEnsureCapacity(this, nSize);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,234 @@
|
||||
#pragma once
|
||||
#include "../../common.h"
|
||||
|
||||
// @test: using interfaces in the header | not critical but could blow up someday with thousands of errors or affect to compilation time etc
|
||||
// used: interface handles
|
||||
#include "../../core/interfaces.h"
|
||||
// used: interface declarations
|
||||
#include "../interfaces/imemalloc.h"
|
||||
|
||||
// @source: master/public/tier1/utlfixedmemory.h
|
||||
|
||||
template <class T>
|
||||
class CUtlFixedMemory
|
||||
{
|
||||
protected:
|
||||
struct BlockHeader_t
|
||||
{
|
||||
BlockHeader_t* pNext;
|
||||
std::intptr_t nBlockSize;
|
||||
};
|
||||
|
||||
public:
|
||||
class Iterator_t
|
||||
{
|
||||
public:
|
||||
Iterator_t(BlockHeader_t* pBlockHeader, const std::intptr_t nIndex) :
|
||||
pBlockHeader(pBlockHeader), nIndex(nIndex) { }
|
||||
|
||||
bool operator==(const Iterator_t it) const
|
||||
{
|
||||
return pBlockHeader == it.pBlockHeader && nIndex == it.nIndex;
|
||||
}
|
||||
|
||||
bool operator!=(const Iterator_t it) const
|
||||
{
|
||||
return pBlockHeader != it.pBlockHeader || nIndex != it.nIndex;
|
||||
}
|
||||
|
||||
BlockHeader_t* pBlockHeader;
|
||||
std::intptr_t nIndex;
|
||||
};
|
||||
|
||||
CUtlFixedMemory(const int nGrowSize = 0, const int nInitAllocationCount = 0) :
|
||||
pBlocks(nullptr), nAllocationCount(0), nGrowSize(nGrowSize)
|
||||
{
|
||||
Purge();
|
||||
Grow(nInitAllocationCount);
|
||||
}
|
||||
|
||||
~CUtlFixedMemory()
|
||||
{
|
||||
Purge();
|
||||
}
|
||||
|
||||
CS_CLASS_NO_ASSIGNMENT(CUtlFixedMemory)
|
||||
|
||||
[[nodiscard]] T* Base()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] const T* Base() const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
T& operator[](std::intptr_t nIndex)
|
||||
{
|
||||
CS_ASSERT(IsValidIndex(nIndex));
|
||||
return *reinterpret_cast<T*>(nIndex);
|
||||
}
|
||||
|
||||
const T& operator[](std::intptr_t nIndex) const
|
||||
{
|
||||
CS_ASSERT(IsValidIndex(nIndex));
|
||||
return *reinterpret_cast<T*>(nIndex);
|
||||
}
|
||||
|
||||
[[nodiscard]] T& Element(const std::intptr_t nIndex)
|
||||
{
|
||||
CS_ASSERT(IsValidIndex(nIndex));
|
||||
return *reinterpret_cast<T*>(nIndex);
|
||||
}
|
||||
|
||||
[[nodiscard]] const T& Element(const std::intptr_t nIndex) const
|
||||
{
|
||||
CS_ASSERT(IsValidIndex(nIndex));
|
||||
return *reinterpret_cast<T*>(nIndex);
|
||||
}
|
||||
|
||||
[[nodiscard]] Iterator_t First() const
|
||||
{
|
||||
return (pBlocks != nullptr ? Iterator_t(pBlocks, InvalidIndex()) : InvalidIterator());
|
||||
}
|
||||
|
||||
[[nodiscard]] Iterator_t Next(const Iterator_t& it) const
|
||||
{
|
||||
if (!IsValidIterator(it))
|
||||
return InvalidIterator();
|
||||
|
||||
BlockHeader_t* pHeader = it.pBlockHeader;
|
||||
|
||||
if (it.nIndex + 1 < pHeader->nBlockSize)
|
||||
return Iterator_t(pHeader, it.nIndex + 1);
|
||||
|
||||
return (pHeader->pNext != nullptr ? Iterator_t(pHeader->pNext, InvalidIndex()) : InvalidIterator());
|
||||
}
|
||||
|
||||
[[nodiscard]] std::intptr_t GetIndex(const Iterator_t& it) const
|
||||
{
|
||||
if (!IsValidIterator(it))
|
||||
return InvalidIndex();
|
||||
|
||||
return reinterpret_cast<std::intptr_t>(HeaderToBlock(it.pBlockHeader) + it.nIndex);
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsIndexAfter(std::intptr_t nIndex, const Iterator_t& it) const
|
||||
{
|
||||
if (!IsValidIterator(it))
|
||||
return false;
|
||||
|
||||
if (IsInBlock(nIndex, it.pBlockHeader))
|
||||
return nIndex > GetIndex(it);
|
||||
|
||||
for (BlockHeader_t* pBlockHeader = it.pBlockHeader->pNext; pBlockHeader != nullptr; pBlockHeader = pBlockHeader->pNext)
|
||||
{
|
||||
if (IsInBlock(nIndex, pBlockHeader))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsValidIterator(const Iterator_t& it) const
|
||||
{
|
||||
return it.pBlockHeader != nullptr && it.nIndex >= 0 && it.nIndex < it.pBlockHeader->nBlockSize;
|
||||
}
|
||||
|
||||
[[nodiscard]] Iterator_t InvalidIterator() const
|
||||
{
|
||||
return Iterator_t(nullptr, InvalidIndex());
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsValidIndex(const std::intptr_t nIndex) const
|
||||
{
|
||||
return nIndex != InvalidIndex();
|
||||
}
|
||||
|
||||
[[nodiscard]] static std::intptr_t InvalidIndex()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] int Count() const
|
||||
{
|
||||
return nAllocationCount;
|
||||
}
|
||||
|
||||
void EnsureCapacity(const int nCapacity)
|
||||
{
|
||||
Grow(nCapacity - Count());
|
||||
}
|
||||
|
||||
void Grow(const int nCount = 1)
|
||||
{
|
||||
if (nCount <= 0)
|
||||
return;
|
||||
|
||||
int nBlockSize = (nGrowSize == 0 ? (nAllocationCount > 0 ? nAllocationCount : (31 + sizeof(T)) / sizeof(T)) : nGrowSize);
|
||||
|
||||
if (nBlockSize < nCount)
|
||||
nBlockSize *= (nCount + nBlockSize - 1) / nBlockSize;
|
||||
|
||||
nAllocationCount += nBlockSize;
|
||||
|
||||
BlockHeader_t* pNewBlockHeader = static_cast<BlockHeader_t*>(I::MemAlloc->Alloc(sizeof(BlockHeader_t) + nBlockSize * sizeof(T)));
|
||||
CS_ASSERT(pNewBlockHeader != nullptr); // container overflow
|
||||
|
||||
pNewBlockHeader->pNext = nullptr;
|
||||
pNewBlockHeader->nBlockSize = nBlockSize;
|
||||
|
||||
if (pBlocks == nullptr)
|
||||
pBlocks = pNewBlockHeader;
|
||||
else
|
||||
{
|
||||
BlockHeader_t* pBlockHeader = pBlocks;
|
||||
|
||||
while (pBlockHeader->pNext != nullptr)
|
||||
pBlockHeader = pBlockHeader->pNext;
|
||||
|
||||
pBlockHeader->pNext = pNewBlockHeader;
|
||||
}
|
||||
}
|
||||
|
||||
void Purge()
|
||||
{
|
||||
if (pBlocks == nullptr)
|
||||
return;
|
||||
|
||||
for (BlockHeader_t* pBlockHeader = pBlocks; pBlockHeader != nullptr;)
|
||||
{
|
||||
BlockHeader_t* pFree = pBlockHeader;
|
||||
pBlockHeader = pBlockHeader->pNext;
|
||||
I::MemAlloc->Free(pFree);
|
||||
}
|
||||
|
||||
pBlocks = nullptr;
|
||||
nAllocationCount = 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
[[nodiscard]] bool IsInBlock(std::intptr_t nIndex, BlockHeader_t* pBlockHeader) const
|
||||
{
|
||||
T* pCurrent = reinterpret_cast<T*>(nIndex);
|
||||
const T* pStart = HeaderToBlock(pBlockHeader);
|
||||
const T* pEnd = pStart + pBlockHeader->nBlockSize;
|
||||
|
||||
return (pCurrent >= pStart && pCurrent < pEnd);
|
||||
}
|
||||
|
||||
[[nodiscard]] const T* HeaderToBlock(const BlockHeader_t* pHeader) const
|
||||
{
|
||||
return reinterpret_cast<const T*>(pHeader + 1);
|
||||
}
|
||||
|
||||
[[nodiscard]] const BlockHeader_t* BlockToHeader(const T* pBlock) const
|
||||
{
|
||||
return reinterpret_cast<const BlockHeader_t*>(pBlock) - 1;
|
||||
}
|
||||
|
||||
BlockHeader_t* pBlocks;
|
||||
int nAllocationCount;
|
||||
int nGrowSize;
|
||||
};
|
||||
@@ -0,0 +1,347 @@
|
||||
#pragma once
|
||||
#include "utlmemory.h"
|
||||
#include "utlfixedmemory.h"
|
||||
|
||||
// @source: master/public/tier1/utllinkedlist.h
|
||||
|
||||
template <class T, class I>
|
||||
struct UtlLinkedListElement_t
|
||||
{
|
||||
UtlLinkedListElement_t(const UtlLinkedListElement_t&) = delete;
|
||||
|
||||
T element;
|
||||
I iPrevious;
|
||||
I iNext;
|
||||
};
|
||||
|
||||
template <class T, class S = unsigned short, bool ML = false, class I = S, class M = CUtlMemory<UtlLinkedListElement_t<T, S>, I>>
|
||||
class CUtlLinkedList
|
||||
{
|
||||
public:
|
||||
using ElemType_t = T;
|
||||
using IndexType_t = S;
|
||||
using IndexLocalType_t = I;
|
||||
using MemoryAllocator_t = M;
|
||||
|
||||
template <typename List_t>
|
||||
class ConstIterator_t
|
||||
{
|
||||
public:
|
||||
typedef typename List_t::ElemType_t ElemType_t;
|
||||
typedef typename List_t::IndexType_t IndexType_t;
|
||||
|
||||
ConstIterator_t() :
|
||||
pList(nullptr), nIndex(List_t::InvalidIndex()) { }
|
||||
|
||||
ConstIterator_t(const List_t& list, IndexType_t nIndex) :
|
||||
pList(&list), nIndex(nIndex) { }
|
||||
|
||||
ConstIterator_t& operator++()
|
||||
{
|
||||
nIndex = pList->Next(nIndex);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ConstIterator_t operator++(int)
|
||||
{
|
||||
ConstIterator_t pCopy = *this;
|
||||
++(*this);
|
||||
return pCopy;
|
||||
}
|
||||
|
||||
ConstIterator_t& operator--()
|
||||
{
|
||||
CS_ASSERT(nIndex != pList->Head());
|
||||
nIndex = (nIndex == pList->InvalidIndex() ? pList->Tail() : pList->Previous(nIndex));
|
||||
return *this;
|
||||
}
|
||||
|
||||
ConstIterator_t operator--(int)
|
||||
{
|
||||
ConstIterator_t pCopy = *this;
|
||||
--(*this);
|
||||
return pCopy;
|
||||
}
|
||||
|
||||
bool operator==(const ConstIterator_t& other) const
|
||||
{
|
||||
CS_ASSERT(pList == other.pList);
|
||||
return nIndex == other.nIndex;
|
||||
}
|
||||
|
||||
bool operator!=(const ConstIterator_t& other) const
|
||||
{
|
||||
CS_ASSERT(pList == other.pList);
|
||||
return nIndex != other.nIndex;
|
||||
}
|
||||
|
||||
const ElemType_t& operator*() const
|
||||
{
|
||||
return pList->Element(nIndex);
|
||||
}
|
||||
|
||||
const ElemType_t* operator->() const
|
||||
{
|
||||
return (&**this);
|
||||
}
|
||||
|
||||
protected:
|
||||
const List_t* pList;
|
||||
IndexType_t nIndex;
|
||||
};
|
||||
|
||||
template <typename List_t>
|
||||
class Iterator_t : public ConstIterator_t<List_t>
|
||||
{
|
||||
public:
|
||||
using ElemType_t = typename List_t::ElemType_t;
|
||||
using IndexType_t = typename List_t::IndexType_t;
|
||||
using Base_t = ConstIterator_t<List_t>;
|
||||
|
||||
Iterator_t() { }
|
||||
|
||||
Iterator_t(const List_t& list, IndexType_t nIndex) :
|
||||
ConstIterator_t<List_t>(list, nIndex) { }
|
||||
|
||||
Iterator_t& operator++()
|
||||
{
|
||||
Base_t::nIndex = Base_t::pList->Next(Base_t::nIndex);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Iterator_t operator++(int)
|
||||
{
|
||||
Iterator_t pCopy = *this;
|
||||
++(*this);
|
||||
return pCopy;
|
||||
}
|
||||
|
||||
Iterator_t& operator--()
|
||||
{
|
||||
Base_t::nIndex = (Base_t::nIndex == Base_t::pList->InvalidIndex() ? Base_t::pList->Tail() : Base_t::pList->Previous(Base_t::nIndex));
|
||||
return *this;
|
||||
}
|
||||
|
||||
Iterator_t operator--(int)
|
||||
{
|
||||
Iterator_t pCopy = *this;
|
||||
--(*this);
|
||||
return pCopy;
|
||||
}
|
||||
|
||||
ElemType_t& operator*() const
|
||||
{
|
||||
List_t* pMutableList = const_cast<List_t*>(Base_t::pList);
|
||||
return pMutableList->Element(Base_t::nIndex);
|
||||
}
|
||||
|
||||
ElemType_t* operator->() const
|
||||
{
|
||||
return (&**this);
|
||||
}
|
||||
};
|
||||
|
||||
CUtlLinkedList(int nGrowSize = 0, int nSize = 0) :
|
||||
memory(nGrowSize, nSize), iHead(InvalidIndex()), iTail(InvalidIndex()), iFirstFree(InvalidIndex()), nElementCount(0), nAllocated(0), itLastAlloc(memory.InvalidIterator()), pElements(memory.Base()) { }
|
||||
|
||||
~CUtlLinkedList()
|
||||
{
|
||||
RemoveAll();
|
||||
}
|
||||
|
||||
CUtlLinkedList(const CUtlLinkedList&) = delete;
|
||||
CUtlLinkedList& operator=(const CUtlLinkedList&) = delete;
|
||||
|
||||
T& operator[](const I nIndex)
|
||||
{
|
||||
CS_ASSERT(IsValidIndex(nIndex));
|
||||
return memory[nIndex].element;
|
||||
}
|
||||
|
||||
const T& operator[](const I nIndex) const
|
||||
{
|
||||
CS_ASSERT(IsValidIndex(nIndex));
|
||||
return memory[nIndex].element;
|
||||
}
|
||||
|
||||
[[nodiscard]] T& Element(const I nIndex)
|
||||
{
|
||||
CS_ASSERT(IsValidIndex(nIndex));
|
||||
return memory[nIndex].element;
|
||||
}
|
||||
|
||||
[[nodiscard]] const T& Element(const I nIndex) const
|
||||
{
|
||||
CS_ASSERT(IsValidIndex(nIndex));
|
||||
return memory[nIndex].element;
|
||||
}
|
||||
|
||||
[[nodiscard]] I Head() const
|
||||
{
|
||||
return iHead;
|
||||
}
|
||||
|
||||
[[nodiscard]] I Tail() const
|
||||
{
|
||||
return iTail;
|
||||
}
|
||||
|
||||
[[nodiscard]] I Previous(const I nIndex) const
|
||||
{
|
||||
CS_ASSERT(IsValidIndex(nIndex));
|
||||
return InternalElement(nIndex).iPrevious;
|
||||
}
|
||||
|
||||
[[nodiscard]] I Next(const I nIndex) const
|
||||
{
|
||||
CS_ASSERT(IsValidIndex(nIndex));
|
||||
return InternalElement(nIndex).iNext;
|
||||
}
|
||||
|
||||
[[nodiscard]] static S InvalidIndex()
|
||||
{
|
||||
return static_cast<S>(M::InvalidIndex());
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsValidIndex(const I nIndex) const
|
||||
{
|
||||
if (!memory.IsValidIndex(nIndex))
|
||||
return false;
|
||||
|
||||
if (memory.IsIndexAfter(nIndex, itLastAlloc))
|
||||
return false; // don't read values that have been allocated, but not constructed
|
||||
|
||||
return (memory[nIndex].iPrevious != nIndex) || (memory[nIndex].iNext == nIndex);
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool IsIndexInRange(I nIndex)
|
||||
{
|
||||
static_assert(sizeof(I) >= sizeof(S));
|
||||
static_assert(sizeof(S) > 2 || static_cast<S>(-1) > 0);
|
||||
static_assert(M::InvalidIndex() == -1 || M::InvalidIndex() == static_cast<S>(M::InvalidIndex()));
|
||||
|
||||
return (static_cast<S>(nIndex) == nIndex && static_cast<S>(nIndex) != InvalidIndex());
|
||||
}
|
||||
|
||||
[[nodiscard]] I Find(const T& source) const
|
||||
{
|
||||
for (I i = iHead; i != InvalidIndex(); i = Next(i))
|
||||
{
|
||||
if (Element(i) == source)
|
||||
return i;
|
||||
}
|
||||
|
||||
return InvalidIndex();
|
||||
}
|
||||
|
||||
void RemoveAll()
|
||||
{
|
||||
if (itLastAlloc == memory.InvalidIterator())
|
||||
{
|
||||
CS_ASSERT(iHead == InvalidIndex() && iTail == InvalidIndex() && iFirstFree == InvalidIndex() && nElementCount == 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if constexpr (ML)
|
||||
{
|
||||
for (typename M::Iterator_t it = memory.First(); it != memory.InvalidIterator(); it = memory.Next(it))
|
||||
{
|
||||
I i = memory.GetIndex(it);
|
||||
|
||||
// skip elements already in the free list
|
||||
if (IsValidIndex(i))
|
||||
{
|
||||
ListElement_t& internalElement = InternalElement(i);
|
||||
(&internalElement.element)->~T();
|
||||
internalElement.iPrevious = i;
|
||||
internalElement.iNext = iFirstFree;
|
||||
iFirstFree = i;
|
||||
}
|
||||
|
||||
// don't destruct elements that haven't ever been constructed
|
||||
if (it == itLastAlloc)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
I i = iHead, iNext;
|
||||
while (i != InvalidIndex())
|
||||
{
|
||||
ListElement_t& internalElement = InternalElement(i);
|
||||
(&internalElement.element)->~T();
|
||||
|
||||
internalElement.iPrevious = i;
|
||||
iNext = Next(i);
|
||||
internalElement.iNext = iNext == InvalidIndex() ? iFirstFree : iNext;
|
||||
i = iNext;
|
||||
}
|
||||
|
||||
if (iHead != InvalidIndex())
|
||||
iFirstFree = iHead;
|
||||
}
|
||||
|
||||
// clear everything else out
|
||||
iHead = InvalidIndex();
|
||||
iTail = InvalidIndex();
|
||||
nElementCount = 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto begin() const
|
||||
{
|
||||
return ConstIterator_t<CUtlLinkedList<T, S, ML, I, M>>(*this, Head());
|
||||
}
|
||||
|
||||
[[nodiscard]] auto begin()
|
||||
{
|
||||
return Iterator_t<CUtlLinkedList<T, S, ML, I, M>>(*this, Head());
|
||||
}
|
||||
|
||||
[[nodiscard]] auto end() const
|
||||
{
|
||||
return ConstIterator_t<CUtlLinkedList<T, S, ML, I, M>>(*this, InvalidIndex());
|
||||
}
|
||||
|
||||
[[nodiscard]] auto end()
|
||||
{
|
||||
return Iterator_t<CUtlLinkedList<T, S, ML, I, M>>(*this, InvalidIndex());
|
||||
}
|
||||
|
||||
protected:
|
||||
using ListElement_t = UtlLinkedListElement_t<T, S>;
|
||||
|
||||
[[nodiscard]] ListElement_t& InternalElement(const I nIndex)
|
||||
{
|
||||
return memory[nIndex];
|
||||
}
|
||||
|
||||
[[nodiscard]] const ListElement_t& InternalElement(const I nIndex) const
|
||||
{
|
||||
return memory[nIndex];
|
||||
}
|
||||
|
||||
M memory;
|
||||
I iHead;
|
||||
I iTail;
|
||||
I iFirstFree;
|
||||
I nElementCount;
|
||||
I nAllocated;
|
||||
typename M::Iterator_t itLastAlloc;
|
||||
ListElement_t* pElements;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class CUtlFixedLinkedList : public CUtlLinkedList<T, std::intptr_t, true, std::intptr_t, CUtlFixedMemory<UtlLinkedListElement_t<T, std::intptr_t>>>
|
||||
{
|
||||
public:
|
||||
CUtlFixedLinkedList(int nGrowSize = 0, int nInitAllocationCount = 0) :
|
||||
CUtlLinkedList<T, std::intptr_t, true, std::intptr_t, CUtlFixedMemory<UtlLinkedListElement_t<T, std::intptr_t>>>(nGrowSize, nInitAllocationCount) { }
|
||||
|
||||
[[nodiscard]] bool IsValidIndex(std::intptr_t nIndex) const
|
||||
{
|
||||
if (!this->memory.IsIndexValid(nIndex))
|
||||
return false;
|
||||
|
||||
return (this->memory[nIndex].iPrevious != nIndex) || (this->memory[nIndex].iNext == nIndex);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,135 @@
|
||||
#pragma once
|
||||
#include "utlrbtree.h"
|
||||
|
||||
// @source: master/public/tier1/utlmap.h
|
||||
|
||||
template <typename K, typename T, typename I = unsigned short, typename LessCallbackFn_t = bool(CS_CDECL*)(const K&, const K&)>
|
||||
class CUtlMap
|
||||
{
|
||||
public:
|
||||
using KeyType_t = K;
|
||||
using ElementType_t = T;
|
||||
using IndexType_t = I;
|
||||
|
||||
CUtlMap(int nGrowSize = 0, int nInitialSize = 0, const LessCallbackFn_t& fnLessCallback = nullptr) :
|
||||
tree(nGrowSize, nInitialSize, CKeyLess(fnLessCallback)) { }
|
||||
|
||||
CUtlMap(LessCallbackFn_t fnLessCallback) :
|
||||
tree(CKeyLess(fnLessCallback)) { }
|
||||
|
||||
[[nodiscard]] ElementType_t& operator[](IndexType_t nIndex)
|
||||
{
|
||||
return tree.Element(nIndex).nElement;
|
||||
}
|
||||
|
||||
[[nodiscard]] const ElementType_t& operator[](IndexType_t nIndex) const
|
||||
{
|
||||
return tree.Element(nIndex).nElement;
|
||||
}
|
||||
|
||||
[[nodiscard]] ElementType_t& Element(IndexType_t nIndex)
|
||||
{
|
||||
return tree.Element(nIndex).nElement;
|
||||
}
|
||||
|
||||
[[nodiscard]] const ElementType_t& Element(IndexType_t nIndex) const
|
||||
{
|
||||
return tree.Element(nIndex).nElement;
|
||||
}
|
||||
|
||||
[[nodiscard]] KeyType_t& Key(IndexType_t nIndex)
|
||||
{
|
||||
return tree.Element(nIndex).key;
|
||||
}
|
||||
|
||||
[[nodiscard]] const KeyType_t& Key(IndexType_t nIndex) const
|
||||
{
|
||||
return tree.Element(nIndex).key;
|
||||
}
|
||||
|
||||
[[nodiscard]] unsigned int Count() const
|
||||
{
|
||||
return tree.Count();
|
||||
}
|
||||
|
||||
[[nodiscard]] IndexType_t MaxElement() const
|
||||
{
|
||||
return tree.MaxElement();
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsValidIndex(IndexType_t nIndex) const
|
||||
{
|
||||
return tree.IsValidIndex(nIndex);
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsValid() const
|
||||
{
|
||||
return tree.IsValid();
|
||||
}
|
||||
|
||||
[[nodiscard]] static IndexType_t InvalidIndex()
|
||||
{
|
||||
return CUtlRBTree<Node_t, I, CKeyLess>::InvalidIndex();
|
||||
}
|
||||
|
||||
void EnsureCapacity(const int nCapacity)
|
||||
{
|
||||
tree.EnsureCapacity(nCapacity);
|
||||
}
|
||||
|
||||
[[nodiscard]] IndexType_t Find(const KeyType_t& key) const
|
||||
{
|
||||
Node_t dummyNode;
|
||||
dummyNode.key = key;
|
||||
return tree.Find(dummyNode);
|
||||
}
|
||||
|
||||
void RemoveAt(IndexType_t nIndex)
|
||||
{
|
||||
tree.RemoveAt(nIndex);
|
||||
}
|
||||
|
||||
bool Remove(const KeyType_t& key)
|
||||
{
|
||||
Node_t dummyNode = { key };
|
||||
return tree.Remove(dummyNode);
|
||||
}
|
||||
|
||||
void RemoveAll()
|
||||
{
|
||||
tree.RemoveAll();
|
||||
}
|
||||
|
||||
void Purge()
|
||||
{
|
||||
tree.Purge();
|
||||
}
|
||||
|
||||
struct Node_t
|
||||
{
|
||||
KeyType_t key;
|
||||
ElementType_t nElement;
|
||||
};
|
||||
|
||||
class CKeyLess
|
||||
{
|
||||
public:
|
||||
CKeyLess(const LessCallbackFn_t& fnLessCallback) :
|
||||
fnLessCallback(fnLessCallback) { }
|
||||
|
||||
bool operator!() const
|
||||
{
|
||||
return !fnLessCallback;
|
||||
}
|
||||
|
||||
bool operator()(const Node_t& left, const Node_t& right) const
|
||||
{
|
||||
return fnLessCallback(left.key, right.key);
|
||||
}
|
||||
|
||||
LessCallbackFn_t fnLessCallback;
|
||||
};
|
||||
|
||||
protected:
|
||||
CUtlRBTree<Node_t, I, CKeyLess> tree; // 0x00
|
||||
};
|
||||
@@ -0,0 +1,516 @@
|
||||
#pragma once
|
||||
// used: memorycopy
|
||||
#include "../../utilities/crt.h"
|
||||
|
||||
// @test: using interfaces in the header | not critical but could blow up someday with thousands of errors or affect to compilation time etc
|
||||
// used: interface handles
|
||||
#include "../../core/interfaces.h"
|
||||
// used: interface declarations
|
||||
#include "../interfaces/imemalloc.h"
|
||||
|
||||
// @source: master/public/tier1/utlmemory.h
|
||||
|
||||
template <class T, class N = int>
|
||||
class CUtlMemory
|
||||
{
|
||||
enum
|
||||
{
|
||||
EXTERNAL_BUFFER_MARKER = -1,
|
||||
EXTERNAL_CONST_BUFFER_MARKER = -2,
|
||||
};
|
||||
|
||||
public:
|
||||
class Iterator_t
|
||||
{
|
||||
public:
|
||||
Iterator_t(const N nIndex) :
|
||||
nIndex(nIndex) { }
|
||||
|
||||
bool operator==(const Iterator_t it) const
|
||||
{
|
||||
return nIndex == it.nIndex;
|
||||
}
|
||||
|
||||
bool operator!=(const Iterator_t it) const
|
||||
{
|
||||
return nIndex != it.nIndex;
|
||||
}
|
||||
|
||||
N nIndex;
|
||||
};
|
||||
|
||||
CUtlMemory(const int nInitialGrowSize, const int nAllocationCount) :
|
||||
pMemory(nullptr), nAllocationCount(nAllocationCount), nGrowSize(nInitialGrowSize)
|
||||
{
|
||||
CS_ASSERT(nInitialGrowSize >= 0);
|
||||
|
||||
if (nAllocationCount > 0)
|
||||
pMemory = static_cast<T*>(I::MemAlloc->Alloc(nAllocationCount * sizeof(T)));
|
||||
}
|
||||
|
||||
CUtlMemory(T* pMemory, const int nElements) :
|
||||
pMemory(pMemory), nAllocationCount(nElements), nGrowSize(EXTERNAL_BUFFER_MARKER) { }
|
||||
|
||||
CUtlMemory(const T* pMemory, const int nElements) :
|
||||
pMemory(pMemory), nAllocationCount(nElements), nGrowSize(EXTERNAL_CONST_BUFFER_MARKER) { }
|
||||
|
||||
~CUtlMemory()
|
||||
{
|
||||
Purge();
|
||||
}
|
||||
|
||||
CUtlMemory(const CUtlMemory&) = delete;
|
||||
|
||||
CUtlMemory(CUtlMemory&& moveFrom) noexcept :
|
||||
pMemory(moveFrom.pMemory), nAllocationCount(moveFrom.nAllocationCount), nGrowSize(moveFrom.nGrowSize)
|
||||
{
|
||||
moveFrom.pMemory = nullptr;
|
||||
moveFrom.nAllocationCount = 0;
|
||||
moveFrom.nGrowSize = 0;
|
||||
}
|
||||
|
||||
void* operator new(const std::size_t nSize)
|
||||
{
|
||||
return I::MemAlloc->Alloc(nSize);
|
||||
}
|
||||
|
||||
void operator delete(void* pMemory)
|
||||
{
|
||||
I::MemAlloc->Free(pMemory);
|
||||
}
|
||||
|
||||
CUtlMemory& operator=(const CUtlMemory&) = delete;
|
||||
|
||||
CUtlMemory& operator=(CUtlMemory&& moveFrom) noexcept
|
||||
{
|
||||
// copy member variables to locals before purge to handle self-assignment
|
||||
T* pMemoryTemp = moveFrom.pMemory;
|
||||
const int nAllocationCountTemp = moveFrom.nAllocationCount;
|
||||
const int nGrowSizeTemp = moveFrom.nGrowSize;
|
||||
|
||||
moveFrom.pMemory = nullptr;
|
||||
moveFrom.nAllocationCount = 0;
|
||||
moveFrom.nGrowSize = 0;
|
||||
|
||||
// if this is a self-assignment, Purge() is a no-op here
|
||||
Purge();
|
||||
|
||||
pMemory = pMemoryTemp;
|
||||
nAllocationCount = nAllocationCountTemp;
|
||||
nGrowSize = nGrowSizeTemp;
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]] T& operator[](const N nIndex)
|
||||
{
|
||||
CS_ASSERT(IsValidIndex(nIndex));
|
||||
return pMemory[nIndex];
|
||||
}
|
||||
|
||||
[[nodiscard]] const T& operator[](const N nIndex) const
|
||||
{
|
||||
CS_ASSERT(IsValidIndex(nIndex));
|
||||
return pMemory[nIndex];
|
||||
}
|
||||
|
||||
[[nodiscard]] T& Element(const N nIndex)
|
||||
{
|
||||
CS_ASSERT(IsValidIndex(nIndex));
|
||||
return pMemory[nIndex];
|
||||
}
|
||||
|
||||
[[nodiscard]] const T& Element(const N nIndex) const
|
||||
{
|
||||
CS_ASSERT(IsValidIndex(nIndex));
|
||||
return pMemory[nIndex];
|
||||
}
|
||||
|
||||
[[nodiscard]] T* Base()
|
||||
{
|
||||
return pMemory;
|
||||
}
|
||||
|
||||
[[nodiscard]] const T* Base() const
|
||||
{
|
||||
return pMemory;
|
||||
}
|
||||
|
||||
[[nodiscard]] int AllocationCount() const
|
||||
{
|
||||
return nAllocationCount;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsExternallyAllocated() const
|
||||
{
|
||||
return nGrowSize <= EXTERNAL_BUFFER_MARKER;
|
||||
}
|
||||
|
||||
[[nodiscard]] static N InvalidIndex()
|
||||
{
|
||||
return static_cast<N>(-1);
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsValidIndex(N nIndex) const
|
||||
{
|
||||
return (nIndex >= 0) && (nIndex < nAllocationCount);
|
||||
}
|
||||
|
||||
[[nodiscard]] Iterator_t First() const
|
||||
{
|
||||
return Iterator_t(IsValidIndex(0) ? 0 : InvalidIndex());
|
||||
}
|
||||
|
||||
[[nodiscard]] Iterator_t Next(const Iterator_t& it) const
|
||||
{
|
||||
return Iterator_t(IsValidIndex(it.nIndex + 1) ? it.nIndex + 1 : InvalidIndex());
|
||||
}
|
||||
|
||||
[[nodiscard]] N GetIndex(const Iterator_t& it) const
|
||||
{
|
||||
return it.nIndex;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsIndexAfter(N nIndex, const Iterator_t& it) const
|
||||
{
|
||||
return nIndex > it.nIndex;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsValidIterator(const Iterator_t& it) const
|
||||
{
|
||||
return IsValidIndex(it.index);
|
||||
}
|
||||
|
||||
[[nodiscard]] Iterator_t InvalidIterator() const
|
||||
{
|
||||
return Iterator_t(InvalidIndex());
|
||||
}
|
||||
|
||||
void Grow(const int nCount = 1)
|
||||
{
|
||||
if (IsExternallyAllocated())
|
||||
return;
|
||||
|
||||
int nAllocationRequested = nAllocationCount + nCount;
|
||||
int nNewAllocationCount = 0;
|
||||
|
||||
if (nGrowSize)
|
||||
nAllocationCount = ((1 + ((nAllocationRequested - 1) / nGrowSize)) * nGrowSize);
|
||||
else
|
||||
{
|
||||
if (nAllocationCount == 0)
|
||||
nAllocationCount = (31 + sizeof(T)) / sizeof(T);
|
||||
|
||||
while (nAllocationCount < nAllocationRequested)
|
||||
nAllocationCount <<= 1;
|
||||
}
|
||||
|
||||
if (static_cast<int>(static_cast<N>(nNewAllocationCount)) < nAllocationRequested)
|
||||
{
|
||||
if (static_cast<int>(static_cast<N>(nNewAllocationCount)) == 0 && static_cast<int>(static_cast<N>(nNewAllocationCount - 1)) >= nAllocationRequested)
|
||||
--nNewAllocationCount;
|
||||
else
|
||||
{
|
||||
if (static_cast<int>(static_cast<N>(nAllocationRequested)) != nAllocationRequested)
|
||||
return;
|
||||
|
||||
while (static_cast<int>(static_cast<N>(nNewAllocationCount)) < nAllocationRequested)
|
||||
nNewAllocationCount = (nNewAllocationCount + nAllocationRequested) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
nAllocationCount = nNewAllocationCount;
|
||||
|
||||
// @test: we can always call realloc, since it must allocate instead when passed null ptr
|
||||
if (pMemory != nullptr)
|
||||
pMemory = static_cast<T*>(I::MemAlloc->ReAlloc(pMemory, nAllocationCount * sizeof(T)));
|
||||
else
|
||||
pMemory = static_cast<T*>(I::MemAlloc->Alloc(nAllocationCount * sizeof(T)));
|
||||
}
|
||||
|
||||
void EnsureCapacity(const int nCapacity)
|
||||
{
|
||||
if (nAllocationCount >= nCapacity)
|
||||
return;
|
||||
|
||||
if (IsExternallyAllocated())
|
||||
{
|
||||
// can't grow a buffer whose memory was externally allocated
|
||||
CS_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
|
||||
nAllocationCount = nCapacity;
|
||||
|
||||
// @test: we can always call realloc, since it must allocate instead when passed null ptr
|
||||
if (pMemory != nullptr)
|
||||
pMemory = static_cast<T*>(I::MemAlloc->ReAlloc(pMemory, nAllocationCount * sizeof(T)));
|
||||
else
|
||||
pMemory = static_cast<T*>(I::MemAlloc->Alloc(nAllocationCount * sizeof(T)));
|
||||
}
|
||||
|
||||
void ConvertToGrowableMemory(int nInitialGrowSize)
|
||||
{
|
||||
if (!IsExternallyAllocated())
|
||||
return;
|
||||
|
||||
nGrowSize = nInitialGrowSize;
|
||||
|
||||
if (nAllocationCount > 0)
|
||||
{
|
||||
const int nByteCount = nAllocationCount * sizeof(T);
|
||||
T* pGrowableMemory = static_cast<T*>(I::MemAlloc->Alloc(nByteCount));
|
||||
CRT::MemoryCopy(pGrowableMemory, pMemory, nByteCount);
|
||||
pMemory = pGrowableMemory;
|
||||
}
|
||||
else
|
||||
pMemory = nullptr;
|
||||
}
|
||||
|
||||
void Purge()
|
||||
{
|
||||
if (IsExternallyAllocated())
|
||||
return;
|
||||
|
||||
if (pMemory != nullptr)
|
||||
{
|
||||
I::MemAlloc->Free(static_cast<void*>(pMemory));
|
||||
pMemory = nullptr;
|
||||
}
|
||||
|
||||
nAllocationCount = 0;
|
||||
}
|
||||
|
||||
void Purge(const int nElements)
|
||||
{
|
||||
CS_ASSERT(nElements >= 0);
|
||||
|
||||
if (nElements > nAllocationCount)
|
||||
{
|
||||
// ensure this isn't a grow request in disguise
|
||||
CS_ASSERT(nElements <= nAllocationCount);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nElements == 0)
|
||||
{
|
||||
Purge();
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsExternallyAllocated() || nElements == nAllocationCount)
|
||||
return;
|
||||
|
||||
if (pMemory == nullptr)
|
||||
{
|
||||
// allocation count is non zero, but memory is null
|
||||
CS_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
|
||||
nAllocationCount = nElements;
|
||||
pMemory = static_cast<T*>(I::MemAlloc->ReAlloc(pMemory, nAllocationCount * sizeof(T)));
|
||||
}
|
||||
|
||||
protected:
|
||||
T* pMemory; // 0x00
|
||||
int nAllocationCount; // 0x04
|
||||
int nGrowSize; // 0x08
|
||||
};
|
||||
|
||||
template <class T, int nAlignment>
|
||||
class CUtlMemoryAligned : public CUtlMemory<T>
|
||||
{
|
||||
public:
|
||||
// @note: not implemented
|
||||
CS_CLASS_NO_INITIALIZER(CUtlMemoryAligned);
|
||||
};
|
||||
|
||||
template <class T, std::size_t SIZE, class I = int>
|
||||
class CUtlMemoryFixedGrowable : public CUtlMemory<T, I>
|
||||
{
|
||||
typedef CUtlMemory<T, I> BaseClass;
|
||||
|
||||
public:
|
||||
CUtlMemoryFixedGrowable(int nInitialGrowSize = 0, int nInitialSize = SIZE) :
|
||||
BaseClass(arrFixedMemory, SIZE)
|
||||
{
|
||||
CS_ASSERT(nInitialSize == 0 || nInitialSize == SIZE);
|
||||
nMallocGrowSize = nInitialGrowSize;
|
||||
}
|
||||
|
||||
void Grow(int nCount = 1)
|
||||
{
|
||||
if (this->IsExternallyAllocated())
|
||||
this->ConvertToGrowableMemory(nMallocGrowSize);
|
||||
|
||||
BaseClass::Grow(nCount);
|
||||
}
|
||||
|
||||
void EnsureCapacity(int nCapacity)
|
||||
{
|
||||
if (CUtlMemory<T>::nAllocationCount >= nCapacity)
|
||||
return;
|
||||
|
||||
if (this->IsExternallyAllocated())
|
||||
// can't grow a buffer whose memory was externally allocated
|
||||
this->ConvertToGrowableMemory(nMallocGrowSize);
|
||||
|
||||
BaseClass::EnsureCapacity(nCapacity);
|
||||
}
|
||||
|
||||
private:
|
||||
int nMallocGrowSize;
|
||||
T arrFixedMemory[SIZE];
|
||||
};
|
||||
|
||||
template <typename T, std::size_t SIZE, int nAlignment = 0>
|
||||
class CUtlMemoryFixed
|
||||
{
|
||||
public:
|
||||
CUtlMemoryFixed(const int nGrowSize = 0, const int nInitialCapacity = 0)
|
||||
{
|
||||
CS_ASSERT(nInitialCapacity == 0 || nInitialCapacity == SIZE);
|
||||
}
|
||||
|
||||
CUtlMemoryFixed(const T* pMemory, const int nElements)
|
||||
{
|
||||
CS_ASSERT(false);
|
||||
}
|
||||
|
||||
[[nodiscard]] static constexpr bool IsValidIndex(const int nIndex)
|
||||
{
|
||||
return (nIndex >= 0) && (nIndex < SIZE);
|
||||
}
|
||||
|
||||
// specify the invalid ('null') index that we'll only return on failure
|
||||
static constexpr int INVALID_INDEX = -1;
|
||||
|
||||
[[nodiscard]] static constexpr int InvalidIndex()
|
||||
{
|
||||
return INVALID_INDEX;
|
||||
}
|
||||
|
||||
[[nodiscard]] T* Base()
|
||||
{
|
||||
if (nAlignment == 0)
|
||||
return reinterpret_cast<T*>(&pMemory[0]);
|
||||
|
||||
return reinterpret_cast<T*>((reinterpret_cast<std::uintptr_t>(&pMemory[0]) + nAlignment - 1) & ~(nAlignment - 1));
|
||||
}
|
||||
|
||||
[[nodiscard]] const T* Base() const
|
||||
{
|
||||
if (nAlignment == 0)
|
||||
return reinterpret_cast<T*>(&pMemory[0]);
|
||||
|
||||
return reinterpret_cast<T*>((reinterpret_cast<std::uintptr_t>(&pMemory[0]) + nAlignment - 1) & ~(nAlignment - 1));
|
||||
}
|
||||
|
||||
[[nodiscard]] T& operator[](int nIndex)
|
||||
{
|
||||
CS_ASSERT(IsValidIndex(nIndex));
|
||||
return Base()[nIndex];
|
||||
}
|
||||
|
||||
[[nodiscard]] const T& operator[](int nIndex) const
|
||||
{
|
||||
CS_ASSERT(IsValidIndex(nIndex));
|
||||
return Base()[nIndex];
|
||||
}
|
||||
|
||||
[[nodiscard]] T& Element(int nIndex)
|
||||
{
|
||||
CS_ASSERT(IsValidIndex(nIndex));
|
||||
return Base()[nIndex];
|
||||
}
|
||||
|
||||
[[nodiscard]] const T& Element(int nIndex) const
|
||||
{
|
||||
CS_ASSERT(IsValidIndex(nIndex));
|
||||
return Base()[nIndex];
|
||||
}
|
||||
|
||||
[[nodiscard]] int AllocationCount() const
|
||||
{
|
||||
return SIZE;
|
||||
}
|
||||
|
||||
[[nodiscard]] int Count() const
|
||||
{
|
||||
return SIZE;
|
||||
}
|
||||
|
||||
void Grow(int nCount = 1)
|
||||
{
|
||||
CS_ASSERT(false);
|
||||
}
|
||||
|
||||
void EnsureCapacity(const int nCapacity)
|
||||
{
|
||||
CS_ASSERT(nCapacity <= SIZE);
|
||||
}
|
||||
|
||||
void Purge() { }
|
||||
|
||||
void Purge(const int nElements)
|
||||
{
|
||||
CS_ASSERT(false);
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsExternallyAllocated() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
class Iterator_t
|
||||
{
|
||||
public:
|
||||
Iterator_t(const int nIndex) :
|
||||
nIndex(nIndex) { }
|
||||
|
||||
bool operator==(const Iterator_t it) const
|
||||
{
|
||||
return nIndex == it.nIndex;
|
||||
}
|
||||
|
||||
bool operator!=(const Iterator_t it) const
|
||||
{
|
||||
return nIndex != it.nIndex;
|
||||
}
|
||||
|
||||
int nIndex;
|
||||
};
|
||||
|
||||
[[nodiscard]] Iterator_t First() const
|
||||
{
|
||||
return Iterator_t(IsValidIndex(0) ? 0 : InvalidIndex());
|
||||
}
|
||||
|
||||
[[nodiscard]] Iterator_t Next(const Iterator_t& it) const
|
||||
{
|
||||
return Iterator_t(IsValidIndex(it.nIndex + 1) ? it.nIndex + 1 : InvalidIndex());
|
||||
}
|
||||
|
||||
[[nodiscard]] int GetIndex(const Iterator_t& it) const
|
||||
{
|
||||
return it.nIndex;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsIndexAfter(int i, const Iterator_t& it) const
|
||||
{
|
||||
return i > it.nIndex;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsValidIterator(const Iterator_t& it) const
|
||||
{
|
||||
return IsValidIndex(it.nIndex);
|
||||
}
|
||||
|
||||
[[nodiscard]] Iterator_t InvalidIterator() const
|
||||
{
|
||||
return Iterator_t(InvalidIndex());
|
||||
}
|
||||
|
||||
private:
|
||||
char pMemory[SIZE * sizeof(T) + nAlignment];
|
||||
};
|
||||
@@ -0,0 +1,244 @@
|
||||
#pragma once
|
||||
#include "utlmemory.h"
|
||||
|
||||
// @source: master/public/tier1/utlrbtree.h
|
||||
|
||||
template <typename T>
|
||||
class CDefLess
|
||||
{
|
||||
public:
|
||||
CDefLess() { }
|
||||
|
||||
CDefLess(int) { }
|
||||
|
||||
CS_INLINE bool operator()(const T& left, const T& right) const
|
||||
{
|
||||
return (left < right);
|
||||
}
|
||||
|
||||
CS_INLINE bool operator!() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <class I>
|
||||
struct UtlRBTreeLinks_t
|
||||
{
|
||||
I iLeft;
|
||||
I iRight;
|
||||
I iParent;
|
||||
I iTag;
|
||||
};
|
||||
|
||||
template <class T, class I>
|
||||
struct UtlRBTreeNode_t : public UtlRBTreeLinks_t<I>
|
||||
{
|
||||
T data;
|
||||
};
|
||||
|
||||
template <class T, class I = unsigned short, typename L = bool(CS_CDECL*)(const T&, const T&), class M = CUtlMemory<UtlRBTreeNode_t<T, I>, I>>
|
||||
class CUtlRBTree
|
||||
{
|
||||
public:
|
||||
using KeyType_t = T;
|
||||
using ElementType_t = T;
|
||||
using IndexType_t = I;
|
||||
using LessCallbackFn_t = L;
|
||||
|
||||
enum NodeColor_t
|
||||
{
|
||||
RED = 0,
|
||||
BLACK
|
||||
};
|
||||
|
||||
explicit CUtlRBTree(int nGrowSize = 0, int nInitialSize = 0, const LessCallbackFn_t& fnLessCallback = nullptr) :
|
||||
fnLessCallback(fnLessCallback), memory(nGrowSize, nInitialSize), iRoot(InvalidIndex()), nElements(0), iFirstFree(InvalidIndex()), itLastAlloc(memory.InvalidIterator()), pElements(memory.Base()) { }
|
||||
|
||||
explicit CUtlRBTree(const LessCallbackFn_t& fnLessCallback) :
|
||||
fnLessCallback(fnLessCallback), memory(0, 0), iRoot(InvalidIndex()), nElements(0), iFirstFree(InvalidIndex()), itLastAlloc(memory.InvalidIterator()), pElements(memory.Base()) { }
|
||||
|
||||
~CUtlRBTree()
|
||||
{
|
||||
Purge();
|
||||
}
|
||||
|
||||
[[nodiscard]] T& operator[](I nIndex)
|
||||
{
|
||||
CS_ASSERT(IsValidIndex(nIndex));
|
||||
return memory[nIndex].data;
|
||||
}
|
||||
|
||||
[[nodiscard]] const T& operator[](I nIndex) const
|
||||
{
|
||||
CS_ASSERT(IsValidIndex(nIndex));
|
||||
return memory[nIndex].data;
|
||||
}
|
||||
|
||||
[[nodiscard]] T& Element(I nIndex)
|
||||
{
|
||||
CS_ASSERT(IsValidIndex(nIndex));
|
||||
return memory[nIndex].data;
|
||||
}
|
||||
|
||||
[[nodiscard]] const T& Element(I nIndex) const
|
||||
{
|
||||
CS_ASSERT(IsValidIndex(nIndex));
|
||||
return memory[nIndex].data;
|
||||
}
|
||||
|
||||
[[nodiscard]] const UtlRBTreeLinks_t<I>& Links(I nIndex) const
|
||||
{
|
||||
constexpr UtlRBTreeLinks_t<I> linksSentinel = {
|
||||
M::INVALID_INDEX, M::INVALID_INDEX, M::INVALID_INDEX, BLACK
|
||||
};
|
||||
|
||||
return (nIndex != InvalidIndex()) ? memory[nIndex] : linksSentinel;
|
||||
}
|
||||
|
||||
[[nodiscard]] UtlRBTreeLinks_t<I>& Links(I nIndex)
|
||||
{
|
||||
CS_ASSERT(nIndex != InvalidIndex());
|
||||
return memory[nIndex];
|
||||
}
|
||||
|
||||
[[nodiscard]] I Parent(I nIndex) const
|
||||
{
|
||||
return (nIndex != InvalidIndex() ? memory[nIndex].iParent : InvalidIndex());
|
||||
}
|
||||
|
||||
[[nodiscard]] I LeftChild(I nIndex) const
|
||||
{
|
||||
return (nIndex != InvalidIndex() ? memory[nIndex].iLeft : InvalidIndex());
|
||||
}
|
||||
|
||||
[[nodiscard]] I RightChild(I nIndex) const
|
||||
{
|
||||
return (nIndex != InvalidIndex() ? memory[nIndex].iRight : InvalidIndex());
|
||||
}
|
||||
|
||||
void SetParent(I nIndex, I iParent)
|
||||
{
|
||||
Links(nIndex).iParent = iParent;
|
||||
}
|
||||
|
||||
void SetLeftChild(I nIndex, I iChild)
|
||||
{
|
||||
Links(nIndex).iLeft = iChild;
|
||||
}
|
||||
|
||||
void SetRightChild(I nIndex, I iChild)
|
||||
{
|
||||
Links(nIndex).iRight = iChild;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsRoot(I nIndex) const
|
||||
{
|
||||
return nIndex == iRoot;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsLeaf(I nIndex) const
|
||||
{
|
||||
return (LeftChild(nIndex) == InvalidIndex()) && (RightChild(nIndex) == InvalidIndex());
|
||||
}
|
||||
|
||||
[[nodiscard]] unsigned int Count() const
|
||||
{
|
||||
return nElements;
|
||||
}
|
||||
|
||||
[[nodiscard]] I MaxElement() const
|
||||
{
|
||||
return static_cast<I>(memory.NumAllocated());
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsValidIndex(I nIndex) const
|
||||
{
|
||||
if (!memory.IsValidIndex(nIndex))
|
||||
return false;
|
||||
|
||||
// don't read values that have been allocated, but not constructed
|
||||
if (memory.IsIndexAfter(nIndex, itLastAlloc))
|
||||
return false;
|
||||
|
||||
return LeftChild(nIndex) != nIndex;
|
||||
}
|
||||
|
||||
[[nodiscard]] static I InvalidIndex()
|
||||
{
|
||||
return static_cast<I>(M::InvalidIndex());
|
||||
}
|
||||
|
||||
void EnsureCapacity(const int nCapacity)
|
||||
{
|
||||
memory.EnsureCapacity(nCapacity);
|
||||
}
|
||||
|
||||
[[nodiscard]] I Find(const T& search) const
|
||||
{
|
||||
CS_ASSERT(!!fnLessCallback);
|
||||
|
||||
I iCurrent = iRoot;
|
||||
while (iCurrent != InvalidIndex())
|
||||
{
|
||||
if (fnLessCallback(search, Element(iCurrent)))
|
||||
iCurrent = LeftChild(iCurrent);
|
||||
else if (fnLessCallback(Element(iCurrent), search))
|
||||
iCurrent = RightChild(iCurrent);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return iCurrent;
|
||||
}
|
||||
|
||||
void RemoveAll()
|
||||
{
|
||||
if (itLastAlloc == memory.InvalidIterator())
|
||||
{
|
||||
CS_ASSERT(iRoot == InvalidIndex());
|
||||
CS_ASSERT(iFirstFree == InvalidIndex());
|
||||
CS_ASSERT(nElements == 0);
|
||||
return;
|
||||
}
|
||||
|
||||
for (typename M::Iterator_t it = memory.First(); it != memory.InvalidIterator(); it = memory.Next(it))
|
||||
{
|
||||
// skip elements in the free list
|
||||
if (I nIndex = memory.GetIndex(it); IsValidIndex(nIndex))
|
||||
{
|
||||
(&Element(nIndex))->~T();
|
||||
SetRightChild(nIndex, iFirstFree);
|
||||
SetLeftChild(nIndex, nIndex);
|
||||
iFirstFree = nIndex;
|
||||
}
|
||||
|
||||
// don't destruct elements that haven't ever been constucted
|
||||
if (it == itLastAlloc)
|
||||
break;
|
||||
}
|
||||
|
||||
// clear everything else out
|
||||
iRoot = InvalidIndex();
|
||||
nElements = 0;
|
||||
//CS_ASSERT(IsValid());
|
||||
}
|
||||
|
||||
void Purge()
|
||||
{
|
||||
RemoveAll();
|
||||
iFirstFree = InvalidIndex();
|
||||
|
||||
memory.Purge();
|
||||
itLastAlloc = memory.InvalidIterator();
|
||||
}
|
||||
|
||||
public:
|
||||
LessCallbackFn_t fnLessCallback; // 0x00
|
||||
M memory; // 0x04
|
||||
I iRoot; // 0x10
|
||||
I nElements;
|
||||
I iFirstFree;
|
||||
typename M::Iterator_t itLastAlloc;
|
||||
UtlRBTreeNode_t<T, I>* pElements;
|
||||
};
|
||||
@@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
#include "utlmemory.h"
|
||||
|
||||
class CUtlBinaryBlock
|
||||
{
|
||||
public:
|
||||
CUtlBinaryBlock(const int nInitialGrowSize = 0, const int nInitialSize = 0) :
|
||||
memory(nInitialGrowSize, nInitialSize), nLength(0) { }
|
||||
|
||||
CUtlMemory<unsigned char> memory;
|
||||
int nLength;
|
||||
};
|
||||
|
||||
class CUtlString
|
||||
{
|
||||
public:
|
||||
CUtlString() { }
|
||||
|
||||
[[nodiscard]] const char* Get() const
|
||||
{
|
||||
if (storage.nLength == 0)
|
||||
return "";
|
||||
|
||||
return reinterpret_cast<const char*>(storage.memory.Base());
|
||||
}
|
||||
|
||||
[[nodiscard]] int Length() const
|
||||
{
|
||||
return storage.nLength;
|
||||
}
|
||||
|
||||
private:
|
||||
CUtlBinaryBlock storage;
|
||||
};
|
||||
|
||||
template <typename T = char>
|
||||
class CUtlConstStringBase
|
||||
{
|
||||
public:
|
||||
CUtlConstStringBase() :
|
||||
pString(nullptr) { }
|
||||
|
||||
[[nodiscard]] const T* Get() const
|
||||
{
|
||||
return (pString != nullptr ? pString : static_cast<T*>(""));
|
||||
}
|
||||
|
||||
[[nodiscard]] operator const T*() const
|
||||
{
|
||||
return (pString != nullptr ? pString : static_cast<T*>(""));
|
||||
}
|
||||
|
||||
[[nodiscard]] bool Empty() const
|
||||
{
|
||||
return (pString == nullptr);
|
||||
}
|
||||
|
||||
protected:
|
||||
const T* pString;
|
||||
};
|
||||
|
||||
using CUtlConstString = CUtlConstStringBase<char>;
|
||||
using CUtlConstWideString = CUtlConstStringBase<wchar_t>;
|
||||
@@ -0,0 +1,196 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <cstdint>
|
||||
|
||||
class CUtlMemoryPool
|
||||
{
|
||||
public:
|
||||
int Count() const
|
||||
{
|
||||
return nBlocksAllocated;
|
||||
}
|
||||
|
||||
int PeakCount() const
|
||||
{
|
||||
return nPeakAlloc;
|
||||
}
|
||||
|
||||
int BlockSize() const
|
||||
{
|
||||
return nBlockSize;
|
||||
}
|
||||
|
||||
protected:
|
||||
class CBlob
|
||||
{
|
||||
public:
|
||||
CBlob* pPrev;
|
||||
CBlob* pNext;
|
||||
int nNumBytes;
|
||||
char Data[1];
|
||||
char Padding[3];
|
||||
};
|
||||
|
||||
int nBlockSize;
|
||||
int nBlocksPerBlob;
|
||||
int nGrowMode;
|
||||
int nBlocksAllocated;
|
||||
int nPeakAlloc;
|
||||
|
||||
unsigned short nAlignment;
|
||||
unsigned short nNumBlobs;
|
||||
|
||||
void* pHeadOfFreeList;
|
||||
void* pAllocOwner;
|
||||
CBlob BlobHead;
|
||||
};
|
||||
|
||||
using UtlTSHashHandle_t = std::uintptr_t;
|
||||
|
||||
inline unsigned HashIntConventional(const int n)
|
||||
{
|
||||
unsigned hash = 0xAAAAAAAA + (n & 0xFF);
|
||||
hash = (hash << 5) + hash + ((n >> 8) & 0xFF);
|
||||
hash = (hash << 5) + hash + ((n >> 16) & 0xFF);
|
||||
hash = (hash << 5) + hash + ((n >> 24) & 0xFF);
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
template <int nBucketCount, class tKey = std::uintptr_t>
|
||||
class CUtlTSHashGenericHash
|
||||
{
|
||||
public:
|
||||
static int Hash(const tKey& Key, int nBucketMask)
|
||||
{
|
||||
int nHash = HashIntConventional(std::uintptr_t(Key));
|
||||
if (nBucketCount <= UINT16_MAX)
|
||||
{
|
||||
nHash ^= (nHash >> 16);
|
||||
}
|
||||
|
||||
if (nBucketCount <= UINT8_MAX)
|
||||
{
|
||||
nHash ^= (nHash >> 8);
|
||||
}
|
||||
|
||||
return (nHash & nBucketMask);
|
||||
}
|
||||
|
||||
static bool Compare(const tKey& lhs, const tKey& rhs)
|
||||
{
|
||||
return lhs == rhs;
|
||||
}
|
||||
};
|
||||
|
||||
template <class tElement, int nBucketCount, class tKey = std::uintptr_t, class tHashFuncs = CUtlTSHashGenericHash<nBucketCount, tKey>, int nAlignment = 0>
|
||||
class CUtlTSHash
|
||||
{
|
||||
static constexpr int nBucketMask = nBucketCount - 1;
|
||||
|
||||
public:
|
||||
static constexpr UtlTSHashHandle_t InvalidHandle()
|
||||
{
|
||||
return static_cast<UtlTSHashHandle_t>(0);
|
||||
}
|
||||
|
||||
UtlTSHashHandle_t Find(tKey uiKey)
|
||||
{
|
||||
int iBucket = tHashFuncs::Hash(uiKey, nBucketCount);
|
||||
const HashBucket_t& hashBucket = aBuckets[iBucket];
|
||||
const UtlTSHashHandle_t hHash = Find(uiKey, hashBucket.pFirst, nullptr);
|
||||
return hHash ? hHash : Find(uiKey, hashBucket.pFirstUncommited, hashBucket.pFirst);
|
||||
}
|
||||
|
||||
int Count() const
|
||||
{
|
||||
return EntryMemory.Count();
|
||||
}
|
||||
|
||||
int GetElements(int nFirstElement, int nCount, UtlTSHashHandle_t* pHandles) const
|
||||
{
|
||||
int nIndex = 0;
|
||||
for (int nBucketIndex = 0; nBucketIndex < nBucketCount; nBucketIndex++)
|
||||
{
|
||||
const HashBucket_t& hashBucket = aBuckets[nBucketIndex];
|
||||
|
||||
HashFixedData_t* pElement = hashBucket.pFirstUncommited;
|
||||
for (; pElement; pElement = pElement->pNext)
|
||||
{
|
||||
if (--nFirstElement >= 0)
|
||||
continue;
|
||||
|
||||
pHandles[nIndex++] = reinterpret_cast<UtlTSHashHandle_t>(pElement);
|
||||
|
||||
if (nIndex >= nCount)
|
||||
return nIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return nIndex;
|
||||
}
|
||||
|
||||
tElement Element(UtlTSHashHandle_t hHash)
|
||||
{
|
||||
return ((HashFixedData_t*)(hHash))->Data;
|
||||
}
|
||||
|
||||
const tElement& Element(UtlTSHashHandle_t hHash) const
|
||||
{
|
||||
return reinterpret_cast<HashFixedData_t*>(hHash)->Data;
|
||||
}
|
||||
|
||||
tElement& operator[](UtlTSHashHandle_t hHash)
|
||||
{
|
||||
return reinterpret_cast<HashFixedData_t*>(hHash)->Data;
|
||||
}
|
||||
|
||||
const tElement& operator[](UtlTSHashHandle_t hHash) const
|
||||
{
|
||||
return reinterpret_cast<HashFixedData_t*>(hHash)->Data;
|
||||
}
|
||||
|
||||
tKey GetID(UtlTSHashHandle_t hHash) const
|
||||
{
|
||||
return reinterpret_cast<HashFixedData_t*>(hHash)->uiKey;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename tData>
|
||||
struct HashFixedDataInternal_t
|
||||
{
|
||||
tKey uiKey;
|
||||
HashFixedDataInternal_t<tData>* pNext;
|
||||
tData Data;
|
||||
};
|
||||
|
||||
using HashFixedData_t = HashFixedDataInternal_t<tElement>;
|
||||
|
||||
struct HashBucket_t
|
||||
{
|
||||
private:
|
||||
[[maybe_unused]] std::byte pad0[0x18];
|
||||
|
||||
public:
|
||||
HashFixedData_t* pFirst;
|
||||
HashFixedData_t* pFirstUncommited;
|
||||
};
|
||||
|
||||
UtlTSHashHandle_t Find(tKey uiKey, HashFixedData_t* pFirstElement, HashFixedData_t* pLastElement)
|
||||
{
|
||||
for (HashFixedData_t* pElement = pFirstElement; pElement != pLastElement; pElement = pElement->pNext)
|
||||
{
|
||||
if (tHashFuncs::Compare(pElement->uiKey, uiKey))
|
||||
return reinterpret_cast<UtlTSHashHandle_t>(pElement);
|
||||
}
|
||||
|
||||
return InvalidHandle();
|
||||
}
|
||||
|
||||
CUtlMemoryPool EntryMemory;
|
||||
MEM_PAD(0x40);
|
||||
HashBucket_t aBuckets[nBucketCount];
|
||||
bool bNeedsCommit;
|
||||
};
|
||||
@@ -0,0 +1,346 @@
|
||||
#pragma once
|
||||
#include "utlmemory.h"
|
||||
|
||||
// used: memorymove
|
||||
#include "../../utilities/crt.h"
|
||||
|
||||
// @source: master/public/tier1/utlvector.h
|
||||
|
||||
/*
|
||||
* a growable array class which doubles in size by default.
|
||||
* it will always keep all elements consecutive in memory, and may move the
|
||||
* elements around in memory (via a realloc) when elements are inserted or removed.
|
||||
* clients should therefore refer to the elements of the vector by index and not pointers
|
||||
*
|
||||
* @note: if variable that uses it intend to call any method that needs to allocate/deallocate should have overloaded constructor/destructor and/or new/delete operators respectively
|
||||
*/
|
||||
template <class T, class A = CUtlMemory<T>>
|
||||
class CUtlVector
|
||||
{
|
||||
using CAllocator = A;
|
||||
|
||||
public:
|
||||
explicit CUtlVector(const int nGrowSize = 0, const int nInitialCapacity = 0) :
|
||||
memory(nGrowSize, nInitialCapacity), nSize(0), pElements(memory.Base()) { }
|
||||
|
||||
CUtlVector(T* pMemory, const int nInitialCapacity, const int nInitialCount = 0) :
|
||||
memory(pMemory, nInitialCapacity), nSize(nInitialCount), pElements(memory.Base()) { }
|
||||
|
||||
CUtlVector(const CUtlVector&) = delete;
|
||||
|
||||
~CUtlVector()
|
||||
{
|
||||
Purge();
|
||||
}
|
||||
|
||||
CUtlVector& operator=(const CUtlVector& vecOther)
|
||||
{
|
||||
CS_ASSERT(&vecOther != this); // self-assignment isn't allowed
|
||||
|
||||
const int nSourceCount = vecOther.Count();
|
||||
SetCount(nSourceCount);
|
||||
|
||||
for (int i = 0; i < nSourceCount; i++)
|
||||
(*this)[i] = vecOther[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]] T& operator[](const int nIndex)
|
||||
{
|
||||
CS_ASSERT(IsValidIndex(nIndex)); // given index is out of range
|
||||
return memory[nIndex];
|
||||
}
|
||||
|
||||
[[nodiscard]] const T& operator[](const int nIndex) const
|
||||
{
|
||||
CS_ASSERT(IsValidIndex(nIndex)); // given index is out of range
|
||||
return memory[nIndex];
|
||||
}
|
||||
|
||||
[[nodiscard]] T& Element(const int nIndex)
|
||||
{
|
||||
CS_ASSERT(IsValidIndex(nIndex)); // given index is out of range
|
||||
return memory[nIndex];
|
||||
}
|
||||
|
||||
[[nodiscard]] const T& Element(const int nIndex) const
|
||||
{
|
||||
CS_ASSERT(IsValidIndex(nIndex)); // given index is out of range
|
||||
return memory[nIndex];
|
||||
}
|
||||
|
||||
[[nodiscard]] T* Base()
|
||||
{
|
||||
return memory.Base();
|
||||
}
|
||||
|
||||
[[nodiscard]] const T* Base() const
|
||||
{
|
||||
return memory.Base();
|
||||
}
|
||||
|
||||
[[nodiscard]] int Count() const
|
||||
{
|
||||
return nSize;
|
||||
}
|
||||
|
||||
[[nodiscard]] int& Size()
|
||||
{
|
||||
return nSize;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsValidIndex(const int nIndex) const
|
||||
{
|
||||
return (nIndex >= 0) && (nIndex < nSize);
|
||||
}
|
||||
|
||||
void CopyFromArray(const T* pArraySource, int nArraySize)
|
||||
{
|
||||
// can't insert something that's in the list. reallocation may hose us
|
||||
CS_ASSERT(memory.Base() == nullptr || pArraySource == nullptr || begin() >= (pArraySource + nArraySize) || pArraySource >= end());
|
||||
|
||||
// resize to accommodate array
|
||||
SetCount(nArraySize);
|
||||
|
||||
for (int i = 0; i < nArraySize; i++)
|
||||
(*this)[i] = pArraySource[i];
|
||||
}
|
||||
|
||||
void GrowVector(const int nCount = 1)
|
||||
{
|
||||
if (nSize + nCount > memory.AllocationCount())
|
||||
memory.Grow(nSize + nCount - memory.AllocationCount());
|
||||
|
||||
nSize += nCount;
|
||||
pElements = memory.Base();
|
||||
}
|
||||
|
||||
void EnsureCapacity(int nCapacity)
|
||||
{
|
||||
memory.EnsureCapacity(nCapacity);
|
||||
pElements = memory.Base();
|
||||
}
|
||||
|
||||
void Purge()
|
||||
{
|
||||
RemoveAll();
|
||||
memory.Purge();
|
||||
pElements = memory.Base();
|
||||
}
|
||||
|
||||
void ShiftElementsRight(const int nElement, const int nShift = 1)
|
||||
{
|
||||
CS_ASSERT(IsValidIndex(nElement) || nSize == 0 || nShift == 0);
|
||||
|
||||
if (const int nToMove = nSize - nElement - nShift; nToMove > 0 && nShift > 0)
|
||||
CRT::MemoryMove(&Element(nElement + nShift), &Element(nElement), nToMove * sizeof(T));
|
||||
}
|
||||
|
||||
void ShiftElementsLeft(const int nElement, const int nShift = 1)
|
||||
{
|
||||
CS_ASSERT(IsValidIndex(nElement) || nSize == 0 || nShift == 0);
|
||||
|
||||
if (const int nToMove = nSize - nElement - nShift; nToMove > 0 && nShift > 0)
|
||||
CRT::MemoryMove(&Element(nElement), &Element(nElement + nShift), nToMove * sizeof(T));
|
||||
}
|
||||
|
||||
int AddToHead()
|
||||
{
|
||||
return InsertBefore(0);
|
||||
}
|
||||
|
||||
int AddToHead(const T& source)
|
||||
{
|
||||
// can't insert something that's in the list. reallocation may hose us
|
||||
CS_ASSERT(memory.Base() == nullptr || &source < begin() || &source >= end());
|
||||
return InsertBefore(0, source);
|
||||
}
|
||||
|
||||
int AddMultipleToHead(const int nCount)
|
||||
{
|
||||
return InsertMultipleBefore(0, nCount);
|
||||
}
|
||||
|
||||
int AddToTail()
|
||||
{
|
||||
return InsertBefore(nSize);
|
||||
}
|
||||
|
||||
int AddToTail(const T& source)
|
||||
{
|
||||
// can't insert something that's in the list. reallocation may hose us
|
||||
CS_ASSERT(memory.Base() == nullptr || &source < begin() || &source >= end());
|
||||
return InsertBefore(nSize, source);
|
||||
}
|
||||
|
||||
int AddMultipleToTail(const int nCount)
|
||||
{
|
||||
return InsertMultipleBefore(nSize, nCount);
|
||||
}
|
||||
|
||||
void SetCount(const int nCount)
|
||||
{
|
||||
RemoveAll();
|
||||
AddMultipleToTail(nCount);
|
||||
}
|
||||
|
||||
int InsertBefore(const int nElement)
|
||||
{
|
||||
// can insert at the end
|
||||
CS_ASSERT(nElement == nSize || IsValidIndex(nElement));
|
||||
|
||||
GrowVector();
|
||||
ShiftElementsRight(nElement);
|
||||
new (&Element(nElement)) T; // @todo: all functions of game classes that using this should be wrapped with constraints 'requires (std::is_pointer_v<T> || have_constructor_overload<T> || have_new_overload<T>)'
|
||||
return nElement;
|
||||
}
|
||||
|
||||
int InsertMultipleBefore(const int nElement, const int nCount)
|
||||
{
|
||||
if (nCount == 0)
|
||||
return nElement;
|
||||
|
||||
// can insert at the end
|
||||
CS_ASSERT(nElement == nSize || IsValidIndex(nElement));
|
||||
|
||||
GrowVector(nCount);
|
||||
ShiftElementsRight(nElement, nCount);
|
||||
|
||||
// invoke default constructors
|
||||
for (int i = 0; i < nElement; ++i)
|
||||
new (&Element(nElement + i)) T;
|
||||
|
||||
return nElement;
|
||||
}
|
||||
|
||||
int InsertBefore(const int nElement, const T& source)
|
||||
{
|
||||
// can't insert something that's in the list. reallocation may hose us
|
||||
CS_ASSERT(memory.Base() == nullptr || &source < begin() || &source >= end());
|
||||
|
||||
// can insert at the end
|
||||
CS_ASSERT(nElement == nSize || IsValidIndex(nElement));
|
||||
|
||||
// reallocate if can't insert something that's in the list
|
||||
GrowVector();
|
||||
ShiftElementsRight(nElement);
|
||||
new (&Element(nElement)) T(source);
|
||||
return nElement;
|
||||
}
|
||||
|
||||
int InsertMultipleBefore(const int nElement, const int nCount, const T* pSource)
|
||||
{
|
||||
if (nCount == 0)
|
||||
return nElement;
|
||||
|
||||
// can insert at the end
|
||||
CS_ASSERT(nElement == nSize || IsValidIndex(nElement));
|
||||
|
||||
GrowVector(nCount);
|
||||
ShiftElementsRight(nElement, nCount);
|
||||
|
||||
// invoke default constructors
|
||||
if (pSource == nullptr)
|
||||
{
|
||||
for (int i = 0; i < nCount; ++i)
|
||||
new (&Element(nElement + i)) T;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < nCount; i++)
|
||||
new (&Element(nElement)) T(pSource[i]);
|
||||
}
|
||||
|
||||
return nElement;
|
||||
}
|
||||
|
||||
[[nodiscard]] int Find(const T& source) const
|
||||
{
|
||||
for (int i = 0; i < nSize; ++i)
|
||||
{
|
||||
if (Element(i) == source)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool FindAndRemove(const T& source)
|
||||
{
|
||||
if (const int nElement = Find(source); nElement != -1)
|
||||
{
|
||||
Remove(nElement);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Remove(const int nElement)
|
||||
{
|
||||
(&Element(nElement))->~T();
|
||||
ShiftElementsLeft(nElement);
|
||||
--nSize;
|
||||
}
|
||||
|
||||
void RemoveAll()
|
||||
{
|
||||
for (int i = nSize; --i >= 0;)
|
||||
(&Element(i))->~T();
|
||||
|
||||
nSize = 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto begin() noexcept
|
||||
{
|
||||
return memory.Base();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto end() noexcept
|
||||
{
|
||||
return memory.Base() + nSize;
|
||||
}
|
||||
|
||||
[[nodiscard]] auto begin() const noexcept
|
||||
{
|
||||
return memory.Base();
|
||||
}
|
||||
|
||||
[[nodiscard]] auto end() const noexcept
|
||||
{
|
||||
return memory.Base() + nSize;
|
||||
}
|
||||
|
||||
protected:
|
||||
int nSize;
|
||||
CAllocator memory;
|
||||
T* pElements;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class CUtlVectorAligned : public CUtlVector<T, CUtlMemoryAligned<T, alignof(T)>>
|
||||
{
|
||||
};
|
||||
|
||||
//a array class with a fixed allocation scheme
|
||||
template <class T, std::size_t MAX_SIZE>
|
||||
class CUtlVectorFixed : public CUtlVector<T, CUtlMemoryFixed<T, MAX_SIZE>>
|
||||
{
|
||||
using CBaseClass = CUtlVector<T, CUtlMemoryFixed<T, MAX_SIZE>>;
|
||||
|
||||
public:
|
||||
explicit CUtlVectorFixed(int nGrowSize = 0, int nInitialCapacity = 0) :
|
||||
CBaseClass(nGrowSize, nInitialCapacity) { }
|
||||
|
||||
CUtlVectorFixed(T* pMemory, int nElements) :
|
||||
CBaseClass(pMemory, nElements) { }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class C_NetworkUtlVectorBase
|
||||
{
|
||||
public:
|
||||
std::uint32_t nSize;
|
||||
T* pElements;
|
||||
};
|
||||
@@ -0,0 +1,52 @@
|
||||
#include "vector.h"
|
||||
|
||||
#include "matrix.h"
|
||||
#include "qangle.h"
|
||||
|
||||
// used: m_rad2deg
|
||||
#include "../../utilities/math.h"
|
||||
|
||||
[[nodiscard]] Vector_t Vector_t::Transform(const Matrix3x4_t& matTransform) const
|
||||
{
|
||||
return {
|
||||
this->DotProduct(matTransform[0]) + matTransform[0][3],
|
||||
this->DotProduct(matTransform[1]) + matTransform[1][3],
|
||||
this->DotProduct(matTransform[2]) + matTransform[2][3]
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]] QAngle_t Vector_t::ToAngles() const
|
||||
{
|
||||
float flPitch, flYaw;
|
||||
if (this->x == 0.0f && this->y == 0.0f)
|
||||
{
|
||||
flPitch = (this->z > 0.0f) ? 270.f : 90.f;
|
||||
flYaw = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
flPitch = M_RAD2DEG(std::atan2f(-this->z, this->Length2D()));
|
||||
|
||||
if (flPitch < 0.f)
|
||||
flPitch += 360.f;
|
||||
|
||||
flYaw = M_RAD2DEG(std::atan2f(this->y, this->x));
|
||||
|
||||
if (flYaw < 0.f)
|
||||
flYaw += 360.f;
|
||||
}
|
||||
|
||||
return { flPitch, flYaw, 0.0f };
|
||||
}
|
||||
|
||||
[[nodiscard]] Matrix3x4_t Vector_t::ToMatrix() const
|
||||
{
|
||||
Vector_t vecRight = {}, vecUp = {};
|
||||
this->ToDirections(&vecRight, &vecUp);
|
||||
|
||||
Matrix3x4a_t matOutput = {};
|
||||
matOutput.SetForward(*this);
|
||||
matOutput.SetLeft(-vecRight);
|
||||
matOutput.SetUp(vecUp);
|
||||
return matOutput;
|
||||
}
|
||||
@@ -0,0 +1,393 @@
|
||||
#pragma once
|
||||
// used: [stl] numeric_limits
|
||||
#include <limits>
|
||||
// used: [crt] isfinite, fmodf, sqrtf
|
||||
#include <cmath>
|
||||
|
||||
// forward declarations
|
||||
struct QAngle_t;
|
||||
struct Matrix3x4_t;
|
||||
|
||||
// @source: master/public/mathlib/vector.h
|
||||
|
||||
struct Vector2D_t
|
||||
{
|
||||
constexpr Vector2D_t(const float x = 0.0f, const float y = 0.0f) :
|
||||
x(x), y(y) { }
|
||||
|
||||
[[nodiscard]] bool IsZero() const
|
||||
{
|
||||
// @note: to make this implementation right, we should use fpclassify here, but game aren't doing same, probably it's better to keep this same, just ensure that it will be compiled same
|
||||
return (this->x == 0.0f && this->y == 0.0f);
|
||||
}
|
||||
|
||||
float x = 0.0f, y = 0.0f;
|
||||
};
|
||||
|
||||
struct Vector_t
|
||||
{
|
||||
constexpr Vector_t(const float x = 0.0f, const float y = 0.0f, const float z = 0.0f) :
|
||||
x(x), y(y), z(z) { }
|
||||
|
||||
constexpr Vector_t(const float* arrVector) :
|
||||
x(arrVector[0]), y(arrVector[1]), z(arrVector[2]) { }
|
||||
|
||||
constexpr Vector_t(const Vector2D_t& vecBase2D) :
|
||||
x(vecBase2D.x), y(vecBase2D.y) { }
|
||||
|
||||
#pragma region vector_array_operators
|
||||
|
||||
[[nodiscard]] float& operator[](const int nIndex)
|
||||
{
|
||||
return reinterpret_cast<float*>(this)[nIndex];
|
||||
}
|
||||
|
||||
[[nodiscard]] const float& operator[](const int nIndex) const
|
||||
{
|
||||
return reinterpret_cast<const float*>(this)[nIndex];
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region vector_relational_operators
|
||||
|
||||
bool operator==(const Vector_t& vecBase) const
|
||||
{
|
||||
return this->IsEqual(vecBase);
|
||||
}
|
||||
|
||||
bool operator!=(const Vector_t& vecBase) const
|
||||
{
|
||||
return !this->IsEqual(vecBase);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region vector_assignment_operators
|
||||
|
||||
constexpr Vector_t& operator=(const Vector_t& vecBase)
|
||||
{
|
||||
this->x = vecBase.x;
|
||||
this->y = vecBase.y;
|
||||
this->z = vecBase.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr Vector_t& operator=(const Vector2D_t& vecBase2D)
|
||||
{
|
||||
this->x = vecBase2D.x;
|
||||
this->y = vecBase2D.y;
|
||||
this->z = 0.0f;
|
||||
return *this;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region vector_arithmetic_assignment_operators
|
||||
|
||||
constexpr Vector_t& operator+=(const Vector_t& vecBase)
|
||||
{
|
||||
this->x += vecBase.x;
|
||||
this->y += vecBase.y;
|
||||
this->z += vecBase.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr Vector_t& operator-=(const Vector_t& vecBase)
|
||||
{
|
||||
this->x -= vecBase.x;
|
||||
this->y -= vecBase.y;
|
||||
this->z -= vecBase.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr Vector_t& operator*=(const Vector_t& vecBase)
|
||||
{
|
||||
this->x *= vecBase.x;
|
||||
this->y *= vecBase.y;
|
||||
this->z *= vecBase.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr Vector_t& operator/=(const Vector_t& vecBase)
|
||||
{
|
||||
this->x /= vecBase.x;
|
||||
this->y /= vecBase.y;
|
||||
this->z /= vecBase.z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr Vector_t& operator+=(const float flAdd)
|
||||
{
|
||||
this->x += flAdd;
|
||||
this->y += flAdd;
|
||||
this->z += flAdd;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr Vector_t& operator-=(const float flSubtract)
|
||||
{
|
||||
this->x -= flSubtract;
|
||||
this->y -= flSubtract;
|
||||
this->z -= flSubtract;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr Vector_t& operator*=(const float flMultiply)
|
||||
{
|
||||
this->x *= flMultiply;
|
||||
this->y *= flMultiply;
|
||||
this->z *= flMultiply;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr Vector_t& operator/=(const float flDivide)
|
||||
{
|
||||
this->x /= flDivide;
|
||||
this->y /= flDivide;
|
||||
this->z /= flDivide;
|
||||
return *this;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region vector_arithmetic_unary_operators
|
||||
|
||||
constexpr Vector_t& operator-()
|
||||
{
|
||||
this->x = -this->x;
|
||||
this->y = -this->y;
|
||||
this->z = -this->z;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr Vector_t operator-() const
|
||||
{
|
||||
return { -this->x, -this->y, -this->z };
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region vector_arithmetic_ternary_operators
|
||||
|
||||
Vector_t operator+(const Vector_t& vecAdd) const
|
||||
{
|
||||
return { this->x + vecAdd.x, this->y + vecAdd.y, this->z + vecAdd.z };
|
||||
}
|
||||
|
||||
Vector_t operator-(const Vector_t& vecSubtract) const
|
||||
{
|
||||
return { this->x - vecSubtract.x, this->y - vecSubtract.y, this->z - vecSubtract.z };
|
||||
}
|
||||
|
||||
Vector_t operator*(const Vector_t& vecMultiply) const
|
||||
{
|
||||
return { this->x * vecMultiply.x, this->y * vecMultiply.y, this->z * vecMultiply.z };
|
||||
}
|
||||
|
||||
Vector_t operator/(const Vector_t& vecDivide) const
|
||||
{
|
||||
return { this->x / vecDivide.x, this->y / vecDivide.y, this->z / vecDivide.z };
|
||||
}
|
||||
|
||||
Vector_t operator+(const float flAdd) const
|
||||
{
|
||||
return { this->x + flAdd, this->y + flAdd, this->z + flAdd };
|
||||
}
|
||||
|
||||
Vector_t operator-(const float flSubtract) const
|
||||
{
|
||||
return { this->x - flSubtract, this->y - flSubtract, this->z - flSubtract };
|
||||
}
|
||||
|
||||
Vector_t operator*(const float flMultiply) const
|
||||
{
|
||||
return { this->x * flMultiply, this->y * flMultiply, this->z * flMultiply };
|
||||
}
|
||||
|
||||
Vector_t operator/(const float flDivide) const
|
||||
{
|
||||
return { this->x / flDivide, this->y / flDivide, this->z / flDivide };
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
/// @returns: true if each component of the vector is finite, false otherwise
|
||||
[[nodiscard]] bool IsValid() const
|
||||
{
|
||||
return std::isfinite(this->x) && std::isfinite(this->y) && std::isfinite(this->z);
|
||||
}
|
||||
|
||||
constexpr void Invalidate()
|
||||
{
|
||||
this->x = this->y = this->z = std::numeric_limits<float>::infinity();
|
||||
}
|
||||
|
||||
/// @returns: true if each component of the vector equals to another, false otherwise
|
||||
[[nodiscard]] bool IsEqual(const Vector_t& vecEqual, const float flErrorMargin = std::numeric_limits<float>::epsilon()) const
|
||||
{
|
||||
return (std::fabsf(this->x - vecEqual.x) < flErrorMargin && std::fabsf(this->y - vecEqual.y) < flErrorMargin && std::fabsf(this->z - vecEqual.z) < flErrorMargin);
|
||||
}
|
||||
|
||||
/// @returns: true if each component of the vector equals to zero, false otherwise
|
||||
[[nodiscard]] bool IsZero() const
|
||||
{
|
||||
// @note: to make this implementation right, we should use fpclassify here, but game aren't doing same, probably it's better to keep this same, just ensure that it will be compiled same
|
||||
return (this->x == 0.0f && this->y == 0.0f && this->z == 0.0f);
|
||||
}
|
||||
|
||||
[[nodiscard]] float Length() const
|
||||
{
|
||||
return std::sqrtf(this->LengthSqr());
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr float LengthSqr() const
|
||||
{
|
||||
return DotProduct(*this);
|
||||
}
|
||||
|
||||
[[nodiscard]] float Length2D() const
|
||||
{
|
||||
return std::sqrtf(this->Length2DSqr());
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr float Length2DSqr() const
|
||||
{
|
||||
return (this->x * this->x + this->y * this->y);
|
||||
}
|
||||
|
||||
[[nodiscard]] float DistTo(const Vector_t& vecEnd) const
|
||||
{
|
||||
return (*this - vecEnd).Length();
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr float DistToSqr(const Vector_t& vecEnd) const
|
||||
{
|
||||
return (*this - vecEnd).LengthSqr();
|
||||
}
|
||||
|
||||
/// normalize magnitude of each component of the vector
|
||||
/// @returns: length of the vector
|
||||
float NormalizeInPlace()
|
||||
{
|
||||
const float flLength = this->Length();
|
||||
const float flRadius = 1.0f / (flLength + std::numeric_limits<float>::epsilon());
|
||||
|
||||
this->x *= flRadius;
|
||||
this->y *= flRadius;
|
||||
this->z *= flRadius;
|
||||
|
||||
return flLength;
|
||||
}
|
||||
|
||||
/// normalize magnitude of each component of the vector
|
||||
/// @returns: copy of the vector with normalized components
|
||||
[[nodiscard]] Vector_t Normalized() const
|
||||
{
|
||||
Vector_t vecOut = *this;
|
||||
vecOut.NormalizeInPlace();
|
||||
return vecOut;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr float DotProduct(const Vector_t& vecDot) const
|
||||
{
|
||||
return (this->x * vecDot.x + this->y * vecDot.y + this->z * vecDot.z);
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr Vector_t CrossProduct(const Vector_t& vecCross) const
|
||||
{
|
||||
return { this->y * vecCross.z - this->z * vecCross.y, this->z * vecCross.x - this->x * vecCross.z, this->x * vecCross.y - this->y * vecCross.x };
|
||||
}
|
||||
|
||||
/// @returns: transformed vector by given transformation matrix
|
||||
[[nodiscard]] Vector_t Transform(const Matrix3x4_t& matTransform) const;
|
||||
|
||||
[[nodiscard]] Vector2D_t ToVector2D() const
|
||||
{
|
||||
return { this->x, this->y };
|
||||
}
|
||||
|
||||
/// convert forward direction vector to other direction vectors
|
||||
/// @param[out] pvecRight [optional] output for converted right vector
|
||||
/// @param[out] pvecUp [optional] output for converted up vector
|
||||
void ToDirections(Vector_t* pvecRight, Vector_t* pvecUp) const
|
||||
{
|
||||
if (std::fabsf(this->x) < 1e-6f && std::fabsf(this->y) < 1e-6f)
|
||||
{
|
||||
// pitch 90 degrees up/down from identity
|
||||
if (pvecRight != nullptr)
|
||||
{
|
||||
pvecRight->x = 0.0f;
|
||||
pvecRight->y = -1.0f;
|
||||
pvecRight->z = 0.0f;
|
||||
}
|
||||
|
||||
if (pvecUp != nullptr)
|
||||
{
|
||||
pvecUp->x = -this->z;
|
||||
pvecUp->y = 0.0f;
|
||||
pvecUp->z = 0.0f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pvecRight != nullptr)
|
||||
{
|
||||
pvecRight->x = this->y;
|
||||
pvecRight->y = -this->x;
|
||||
pvecRight->z = 0.0f;
|
||||
pvecRight->NormalizeInPlace();
|
||||
}
|
||||
|
||||
if (pvecUp != nullptr)
|
||||
{
|
||||
pvecUp->x = (-this->x) * this->z;
|
||||
pvecUp->y = -(this->y * this->z);
|
||||
pvecUp->z = this->y * this->y - (-this->x) * this->x;
|
||||
pvecUp->NormalizeInPlace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// @returns: 2D angles converted from direction vector
|
||||
[[nodiscard]] QAngle_t ToAngles() const;
|
||||
|
||||
/// @returns: matrix converted from forward direction vector
|
||||
[[nodiscard]] Matrix3x4_t ToMatrix() const;
|
||||
|
||||
float x = 0.0f, y = 0.0f, z = 0.0f;
|
||||
};
|
||||
|
||||
struct Vector4D_t
|
||||
{
|
||||
constexpr Vector4D_t(const float x = 0.0f, const float y = 0.0f, const float z = 0.0f, const float w = 0.0f) :
|
||||
x(x), y(y), z(z), w(w) { }
|
||||
|
||||
float x = 0.0f, y = 0.0f, z = 0.0f, w = 0.0f;
|
||||
};
|
||||
|
||||
struct alignas(16) VectorAligned_t : Vector_t
|
||||
{
|
||||
VectorAligned_t() = default;
|
||||
|
||||
explicit VectorAligned_t(const Vector_t& vecBase)
|
||||
{
|
||||
this->x = vecBase.x;
|
||||
this->y = vecBase.y;
|
||||
this->z = vecBase.z;
|
||||
this->w = 0.0f;
|
||||
}
|
||||
|
||||
constexpr VectorAligned_t& operator=(const Vector_t& vecBase)
|
||||
{
|
||||
this->x = vecBase.x;
|
||||
this->y = vecBase.y;
|
||||
this->z = vecBase.z;
|
||||
this->w = 0.0f;
|
||||
return *this;
|
||||
}
|
||||
|
||||
float w = 0.0f;
|
||||
};
|
||||
|
||||
static_assert(alignof(VectorAligned_t) == 16);
|
||||
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
// used: mem_pad
|
||||
#include "../../utilities/memory.h"
|
||||
|
||||
// used: vector_t
|
||||
#include "vector.h"
|
||||
// used: qangle_t
|
||||
#include "qangle.h"
|
||||
|
||||
class CViewSetup
|
||||
{
|
||||
public:
|
||||
MEM_PAD(0x490);
|
||||
float flOrthoLeft; // 0x0494
|
||||
float flOrthoTop; // 0x0498
|
||||
float flOrthoRight; // 0x049C
|
||||
float flOrthoBottom; // 0x04A0
|
||||
MEM_PAD(0x38);
|
||||
float flFov; // 0x04D8
|
||||
float flFovViewmodel; // 0x04DC
|
||||
Vector_t vecOrigin; // 0x04E0
|
||||
MEM_PAD(0xC); // 0x04EC
|
||||
QAngle_t angView; // 0x04F8
|
||||
MEM_PAD(0x14); // 0x0504
|
||||
float flAspectRatio; // 0x0518
|
||||
};
|
||||
@@ -0,0 +1,154 @@
|
||||
#include "entity.h"
|
||||
|
||||
// used: convars
|
||||
#include "../core/convars.h"
|
||||
#include "interfaces/cgameentitysystem.h"
|
||||
#include "interfaces/ienginecvar.h"
|
||||
#include "interfaces/iengineclient.h"
|
||||
|
||||
// used: game's definitions, enums
|
||||
#include "const.h"
|
||||
|
||||
// global empty vector for when we can't get the origin
|
||||
static Vector_t vecEmpty = Vector_t(0, 0, 0);
|
||||
|
||||
CCSPlayerController* CCSPlayerController::GetLocalPlayerController()
|
||||
{
|
||||
const int nIndex = I::Engine->GetLocalPlayer();
|
||||
return I::GameResourceService->pGameEntitySystem->Get<CCSPlayerController>(nIndex);
|
||||
}
|
||||
|
||||
const Vector_t& CCSPlayerController::GetPawnOrigin()
|
||||
{
|
||||
CBaseHandle hPawnHandle = this->GetPawnHandle();
|
||||
if (!hPawnHandle.IsValid())
|
||||
return vecEmpty;
|
||||
|
||||
C_CSPlayerPawn* pPlayerPawn = I::GameResourceService->pGameEntitySystem->Get<C_CSPlayerPawn>(hPawnHandle);
|
||||
if (pPlayerPawn == nullptr)
|
||||
return vecEmpty;
|
||||
|
||||
return pPlayerPawn->GetSceneOrigin();
|
||||
}
|
||||
|
||||
C_BaseEntity* C_BaseEntity::GetLocalPlayer()
|
||||
{
|
||||
const int nIndex = I::Engine->GetLocalPlayer();
|
||||
return I::GameResourceService->pGameEntitySystem->Get(nIndex);
|
||||
}
|
||||
|
||||
const Vector_t& C_BaseEntity::GetSceneOrigin()
|
||||
{
|
||||
if (this->GetGameSceneNode())
|
||||
return GetGameSceneNode()->GetAbsOrigin();
|
||||
|
||||
return vecEmpty;
|
||||
}
|
||||
|
||||
bool C_CSPlayerPawn::IsOtherEnemy(C_CSPlayerPawn* pOther)
|
||||
{
|
||||
// check are other player is invalid or we're comparing against ourselves
|
||||
if (pOther == nullptr || this == pOther)
|
||||
return false;
|
||||
|
||||
if (CONVAR::game_type->value.i32 == GAMETYPE_FREEFORALL && CONVAR::game_mode->value.i32 == GAMEMODE_FREEFORALL_SURVIVAL)
|
||||
// check is not teammate
|
||||
return (this->GetSurvivalTeam() != pOther->GetSurvivalTeam());
|
||||
|
||||
// @todo: check is deathmatch
|
||||
if (CONVAR::mp_teammates_are_enemies->value.i1)
|
||||
return true;
|
||||
|
||||
return this->GetAssociatedTeam() != pOther->GetAssociatedTeam();
|
||||
}
|
||||
|
||||
int C_CSPlayerPawn::GetAssociatedTeam()
|
||||
{
|
||||
const int nTeam = this->GetTeam();
|
||||
|
||||
// @todo: check is coaching, currently cs2 doesnt have sv_coaching_enabled, so just let it be for now...
|
||||
//if (CONVAR::sv_coaching_enabled->GetBool() && nTeam == TEAM_SPECTATOR)
|
||||
// return this->GetCoachingTeam();
|
||||
|
||||
return nTeam;
|
||||
}
|
||||
|
||||
bool C_CSPlayerPawn::CanAttack(const float flServerTime)
|
||||
{
|
||||
// check is player ready to attack
|
||||
if (CCSPlayer_WeaponServices* pWeaponServices = this->GetWeaponServices(); pWeaponServices != nullptr)
|
||||
if (this->IsWaitForNoAttack() || pWeaponServices->GetNextAttack() > flServerTime)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
std::uint32_t C_CSPlayerPawn::GetOwnerHandleIndex()
|
||||
{
|
||||
std::uint32_t Result = -1;
|
||||
if (this && GetCollision() && !(GetCollision()->GetSolidFlags() & 4))
|
||||
Result = this->GetOwnerHandle().GetEntryIndex();
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
std::uint16_t C_CSPlayerPawn::GetCollisionMask()
|
||||
{
|
||||
if (this && GetCollision())
|
||||
return GetCollision()->CollisionMask(); // Collision + 0x38
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool C_CSWeaponBaseGun::CanPrimaryAttack(const int nWeaponType, const float flServerTime)
|
||||
{
|
||||
// check are weapon support burst mode and it's ready to attack
|
||||
if (this->IsBurstMode())
|
||||
{
|
||||
// check is it ready to attack
|
||||
if (this->GetBurstShotsRemaining() > 0 /*&& this->GetNextBurstShotTime() <= flServerTime*/)
|
||||
return true;
|
||||
}
|
||||
|
||||
// check is weapon ready to attack
|
||||
if (this->GetNextPrimaryAttackTick() > TIME_TO_TICKS(flServerTime))
|
||||
return false;
|
||||
|
||||
// we doesn't need additional checks for knives
|
||||
if (nWeaponType == WEAPONTYPE_KNIFE)
|
||||
return true;
|
||||
|
||||
// check do weapon have ammo
|
||||
if (this->GetClip1() <= 0)
|
||||
return false;
|
||||
|
||||
const ItemDefinitionIndex_t nDefinitionIndex = this->GetAttributeManager()->GetItem()->GetItemDefinitionIndex();
|
||||
|
||||
// check for revolver cocking ready
|
||||
if (nDefinitionIndex == WEAPON_R8_REVOLVER && this->GetPostponeFireReadyFrac() > flServerTime)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool C_CSWeaponBaseGun::CanSecondaryAttack(const int nWeaponType, const float flServerTime)
|
||||
{
|
||||
// check is weapon ready to attack
|
||||
if (this->GetNextSecondaryAttackTick() > TIME_TO_TICKS(flServerTime))
|
||||
return false;
|
||||
|
||||
// we doesn't need additional checks for knives
|
||||
if (nWeaponType == WEAPONTYPE_KNIFE)
|
||||
return true;
|
||||
|
||||
// check do weapon have ammo
|
||||
if (this->GetClip1() <= 0)
|
||||
return false;
|
||||
|
||||
// only revolver is allowed weapon for secondary attack
|
||||
if (this->GetAttributeManager()->GetItem()->GetItemDefinitionIndex() != WEAPON_R8_REVOLVER)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,432 @@
|
||||
#pragma once
|
||||
|
||||
// @test: using interfaces in the header | not critical but could blow up someday with thousands of errors or affect to compilation time etc
|
||||
// used: cgameentitysystem, ischemasystem
|
||||
#include "../core/interfaces.h"
|
||||
#include "interfaces/igameresourceservice.h"
|
||||
#include "interfaces/ischemasystem.h"
|
||||
|
||||
// used: schema field
|
||||
#include "../core/schema.h"
|
||||
|
||||
// used: l_print
|
||||
#include "../utilities/log.h"
|
||||
// used: vector_t
|
||||
#include "datatypes/vector.h"
|
||||
// used: qangle_t
|
||||
#include "datatypes/qangle.h"
|
||||
// used: ctransform
|
||||
#include "datatypes/transform.h"
|
||||
|
||||
// used: cbasehandle
|
||||
#include "entity_handle.h"
|
||||
// used: game's definitions
|
||||
#include "const.h"
|
||||
// used: entity vdata
|
||||
#include "vdata.h"
|
||||
|
||||
using GameTime_t = std::float_t;
|
||||
using GameTick_t = std::int32_t;
|
||||
|
||||
class CEntityInstance;
|
||||
|
||||
class CEntityIdentity
|
||||
{
|
||||
public:
|
||||
CS_CLASS_NO_INITIALIZER(CEntityIdentity);
|
||||
|
||||
// @note: handle index is not entity index
|
||||
SCHEMA_ADD_OFFSET(std::uint32_t, GetIndex, 0x10);
|
||||
SCHEMA_ADD_FIELD(const char*, GetDesignerName, "CEntityIdentity->m_designerName");
|
||||
SCHEMA_ADD_FIELD(std::uint32_t, GetFlags, "CEntityIdentity->m_flags");
|
||||
|
||||
[[nodiscard]] bool IsValid()
|
||||
{
|
||||
return GetIndex() != INVALID_EHANDLE_INDEX;
|
||||
}
|
||||
|
||||
[[nodiscard]] int GetEntryIndex()
|
||||
{
|
||||
if (!IsValid())
|
||||
return ENT_ENTRY_MASK;
|
||||
|
||||
return GetIndex() & ENT_ENTRY_MASK;
|
||||
}
|
||||
|
||||
[[nodiscard]] int GetSerialNumber()
|
||||
{
|
||||
return GetIndex() >> NUM_SERIAL_NUM_SHIFT_BITS;
|
||||
}
|
||||
|
||||
CEntityInstance* pInstance; // 0x00
|
||||
};
|
||||
|
||||
class CEntityInstance
|
||||
{
|
||||
public:
|
||||
CS_CLASS_NO_INITIALIZER(CEntityInstance);
|
||||
|
||||
void GetSchemaClassInfo(SchemaClassInfoData_t** pReturn)
|
||||
{
|
||||
return MEM::CallVFunc<void, 38U>(this, pReturn);
|
||||
}
|
||||
|
||||
[[nodiscard]] CBaseHandle GetRefEHandle()
|
||||
{
|
||||
CEntityIdentity* pIdentity = GetIdentity();
|
||||
if (pIdentity == nullptr)
|
||||
return CBaseHandle();
|
||||
|
||||
return CBaseHandle(pIdentity->GetEntryIndex(), pIdentity->GetSerialNumber() - (pIdentity->GetFlags() & 1));
|
||||
}
|
||||
|
||||
SCHEMA_ADD_FIELD(CEntityIdentity*, GetIdentity, "CEntityInstance->m_pEntity");
|
||||
};
|
||||
|
||||
class CCollisionProperty
|
||||
{
|
||||
public:
|
||||
std::uint16_t CollisionMask()
|
||||
{
|
||||
return *reinterpret_cast<std::uint16_t*>(reinterpret_cast<std::uintptr_t>(this) + 0x38);
|
||||
}
|
||||
|
||||
CS_CLASS_NO_INITIALIZER(CCollisionProperty);
|
||||
|
||||
SCHEMA_ADD_FIELD(Vector_t, GetMins, "CCollisionProperty->m_vecMins");
|
||||
SCHEMA_ADD_FIELD(Vector_t, GetMaxs, "CCollisionProperty->m_vecMaxs");
|
||||
|
||||
SCHEMA_ADD_FIELD(std::uint8_t, GetSolidFlags, "CCollisionProperty->m_usSolidFlags");
|
||||
SCHEMA_ADD_FIELD(std::uint8_t, GetCollisionGroup, "CCollisionProperty->m_CollisionGroup");
|
||||
};
|
||||
|
||||
class CSkeletonInstance;
|
||||
class CGameSceneNode
|
||||
{
|
||||
public:
|
||||
CS_CLASS_NO_INITIALIZER(CGameSceneNode);
|
||||
|
||||
SCHEMA_ADD_FIELD(CTransform, GetNodeToWorld, "CGameSceneNode->m_nodeToWorld");
|
||||
SCHEMA_ADD_FIELD(CEntityInstance*, GetOwner, "CGameSceneNode->m_pOwner");
|
||||
|
||||
SCHEMA_ADD_FIELD(Vector_t, GetAbsOrigin, "CGameSceneNode->m_vecAbsOrigin");
|
||||
SCHEMA_ADD_FIELD(Vector_t, GetRenderOrigin, "CGameSceneNode->m_vRenderOrigin");
|
||||
|
||||
SCHEMA_ADD_FIELD(QAngle_t, GetAngleRotation, "CGameSceneNode->m_angRotation");
|
||||
SCHEMA_ADD_FIELD(QAngle_t, GetAbsAngleRotation, "CGameSceneNode->m_angAbsRotation");
|
||||
|
||||
SCHEMA_ADD_FIELD(bool, IsDormant, "CGameSceneNode->m_bDormant");
|
||||
|
||||
CSkeletonInstance* GetSkeletonInstance()
|
||||
{
|
||||
return MEM::CallVFunc<CSkeletonInstance*, 8U>(this);
|
||||
}
|
||||
};
|
||||
|
||||
class C_BaseEntity : public CEntityInstance
|
||||
{
|
||||
public:
|
||||
CS_CLASS_NO_INITIALIZER(C_BaseEntity);
|
||||
|
||||
[[nodiscard]] bool IsBasePlayerController()
|
||||
{
|
||||
SchemaClassInfoData_t* pClassInfo;
|
||||
GetSchemaClassInfo(&pClassInfo);
|
||||
if (pClassInfo == nullptr)
|
||||
return false;
|
||||
|
||||
return FNV1A::Hash(pClassInfo->szName) == FNV1A::HashConst("C_CSPlayerController");
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsWeapon()
|
||||
{
|
||||
static SchemaClassInfoData_t* pWeaponBaseClass = nullptr;
|
||||
if (pWeaponBaseClass == nullptr)
|
||||
I::SchemaSystem->FindTypeScopeForModule(CS_XOR("client.dll"))->FindDeclaredClass(&pWeaponBaseClass, CS_XOR("C_CSWeaponBase"));
|
||||
|
||||
|
||||
SchemaClassInfoData_t* pClassInfo;
|
||||
GetSchemaClassInfo(&pClassInfo);
|
||||
if (pClassInfo == nullptr)
|
||||
return false;
|
||||
|
||||
return (pClassInfo->InheritsFrom(pWeaponBaseClass));
|
||||
}
|
||||
|
||||
static C_BaseEntity* GetLocalPlayer();
|
||||
|
||||
// get entity origin on scene
|
||||
[[nodiscard]] const Vector_t& GetSceneOrigin();
|
||||
|
||||
SCHEMA_ADD_FIELD(CGameSceneNode*, GetGameSceneNode, "C_BaseEntity->m_pGameSceneNode");
|
||||
SCHEMA_ADD_FIELD(CCollisionProperty*, GetCollision, "C_BaseEntity->m_pCollision");
|
||||
SCHEMA_ADD_FIELD(std::uint8_t, GetTeam, "C_BaseEntity->m_iTeamNum");
|
||||
SCHEMA_ADD_FIELD(CBaseHandle, GetOwnerHandle, "C_BaseEntity->m_hOwnerEntity");
|
||||
SCHEMA_ADD_FIELD(Vector_t, GetBaseVelocity, "C_BaseEntity->m_vecBaseVelocity");
|
||||
SCHEMA_ADD_FIELD(Vector_t, GetAbsVelocity, "C_BaseEntity->m_vecAbsVelocity");
|
||||
SCHEMA_ADD_FIELD(bool, IsTakingDamage, "C_BaseEntity->m_bTakesDamage");
|
||||
SCHEMA_ADD_FIELD(std::uint32_t, GetFlags, "C_BaseEntity->m_fFlags");
|
||||
SCHEMA_ADD_FIELD(std::int32_t, GetEflags, "C_BaseEntity->m_iEFlags");
|
||||
SCHEMA_ADD_FIELD(std::uint8_t, GetMoveType, "C_BaseEntity->m_nActualMoveType"); // m_nActualMoveType returns CSGO style movetype, m_nMoveType returns bitwise shifted move type
|
||||
SCHEMA_ADD_FIELD(std::uint8_t, GetLifeState, "C_BaseEntity->m_lifeState");
|
||||
SCHEMA_ADD_FIELD(std::int32_t, GetHealth, "C_BaseEntity->m_iHealth");
|
||||
SCHEMA_ADD_FIELD(std::int32_t, GetMaxHealth, "C_BaseEntity->m_iMaxHealth");
|
||||
SCHEMA_ADD_FIELD(float, GetWaterLevel, "C_BaseEntity->m_flWaterLevel");
|
||||
SCHEMA_ADD_FIELD_OFFSET(void*, GetVData, "C_BaseEntity->m_nSubclassID", 0x8);
|
||||
};
|
||||
|
||||
class CGlowProperty;
|
||||
|
||||
class C_BaseModelEntity : public C_BaseEntity
|
||||
{
|
||||
public:
|
||||
CS_CLASS_NO_INITIALIZER(C_BaseModelEntity);
|
||||
|
||||
SCHEMA_ADD_FIELD(CCollisionProperty, GetCollisionInstance, "C_BaseModelEntity->m_Collision");
|
||||
SCHEMA_ADD_FIELD(CGlowProperty, GetGlowProperty, "C_BaseModelEntity->m_Glow");
|
||||
SCHEMA_ADD_FIELD(Vector_t, GetViewOffset, "C_BaseModelEntity->m_vecViewOffset");
|
||||
SCHEMA_ADD_FIELD(GameTime_t, GetCreationTime, "C_BaseModelEntity->m_flCreateTime");
|
||||
SCHEMA_ADD_FIELD(GameTick_t, GetCreationTick, "C_BaseModelEntity->m_nCreationTick");
|
||||
SCHEMA_ADD_FIELD(CBaseHandle, GetMoveParent, "C_BaseModelEntity->m_hOldMoveParent");
|
||||
SCHEMA_ADD_FIELD(std::float_t, GetAnimTime, "C_BaseModelEntity->m_flAnimTime");
|
||||
SCHEMA_ADD_FIELD(std::float_t, GetSimulationTime, "C_BaseModelEntity->m_flSimulationTime");
|
||||
};
|
||||
|
||||
class CPlayer_ItemServices;
|
||||
class CPlayer_CameraServices;
|
||||
|
||||
class CPlayer_WeaponServices
|
||||
{
|
||||
public:
|
||||
SCHEMA_ADD_FIELD(CBaseHandle, GetActiveWeapon, "CPlayer_WeaponServices->m_hActiveWeapon");
|
||||
};
|
||||
|
||||
class CCSPlayer_WeaponServices : public CPlayer_WeaponServices
|
||||
{
|
||||
public:
|
||||
SCHEMA_ADD_FIELD(GameTime_t, GetNextAttack, "CCSPlayer_WeaponServices->m_flNextAttack");
|
||||
};
|
||||
|
||||
class C_BasePlayerPawn : public C_BaseModelEntity
|
||||
{
|
||||
public:
|
||||
CS_CLASS_NO_INITIALIZER(C_BasePlayerPawn);
|
||||
|
||||
SCHEMA_ADD_FIELD(CBaseHandle, GetControllerHandle, "C_BasePlayerPawn->m_hController");
|
||||
SCHEMA_ADD_FIELD(CCSPlayer_WeaponServices*, GetWeaponServices, "C_BasePlayerPawn->m_pWeaponServices");
|
||||
SCHEMA_ADD_FIELD(CPlayer_ItemServices*, GetItemServices, "C_BasePlayerPawn->m_pItemServices");
|
||||
SCHEMA_ADD_FIELD(CPlayer_CameraServices*, GetCameraServices, "C_BasePlayerPawn->m_pCameraServices");
|
||||
|
||||
[[nodiscard]] Vector_t GetEyePosition()
|
||||
{
|
||||
Vector_t vecEyePosition = Vector_t(0.0f, 0.0f, 0.0f);
|
||||
// Credit: https://www.unknowncheats.me/forum/4258133-post6228.html
|
||||
MEM::CallVFunc<void, 169U>(this, &vecEyePosition);
|
||||
return vecEyePosition;
|
||||
}
|
||||
};
|
||||
|
||||
class CCSPlayer_ViewModelServices;
|
||||
|
||||
class C_CSPlayerPawnBase : public C_BasePlayerPawn
|
||||
{
|
||||
public:
|
||||
CS_CLASS_NO_INITIALIZER(C_CSPlayerPawnBase);
|
||||
|
||||
SCHEMA_ADD_FIELD(CCSPlayer_ViewModelServices*, GetViewModelServices, "C_CSPlayerPawnBase->m_pViewModelServices");
|
||||
SCHEMA_ADD_FIELD(float, GetLowerBodyYawTarget, "C_CSPlayerPawnBase->m_flLowerBodyYawTarget");
|
||||
SCHEMA_ADD_FIELD(float, GetFlashMaxAlpha, "C_CSPlayerPawnBase->m_flFlashMaxAlpha");
|
||||
SCHEMA_ADD_FIELD(float, GetFlashDuration, "C_CSPlayerPawnBase->m_flFlashDuration");
|
||||
SCHEMA_ADD_FIELD(Vector_t, GetLastSmokeOverlayColor, "C_CSPlayerPawnBase->m_vLastSmokeOverlayColor");
|
||||
SCHEMA_ADD_FIELD(int, GetSurvivalTeam, "C_CSPlayerPawnBase->m_nSurvivalTeam"); // danger zone
|
||||
};
|
||||
|
||||
class C_CSPlayerPawn : public C_CSPlayerPawnBase
|
||||
{
|
||||
public:
|
||||
CS_CLASS_NO_INITIALIZER(C_CSPlayerPawn);
|
||||
|
||||
[[nodiscard]] bool IsOtherEnemy(C_CSPlayerPawn* pOther);
|
||||
[[nodiscard]] int GetAssociatedTeam();
|
||||
[[nodiscard]] bool CanAttack(const float flServerTime);
|
||||
[[nodiscard]] std::uint32_t GetOwnerHandleIndex();
|
||||
[[nodiscard]] std::uint16_t GetCollisionMask();
|
||||
|
||||
SCHEMA_ADD_FIELD(bool, IsScoped, "C_CSPlayerPawn->m_bIsScoped");
|
||||
SCHEMA_ADD_FIELD(bool, IsDefusing, "C_CSPlayerPawn->m_bIsDefusing");
|
||||
SCHEMA_ADD_FIELD(bool, IsGrabbingHostage, "C_CSPlayerPawn->m_bIsGrabbingHostage");
|
||||
SCHEMA_ADD_FIELD(bool, IsWaitForNoAttack, "C_CSPlayerPawn->m_bWaitForNoAttack");
|
||||
SCHEMA_ADD_FIELD(int, GetShotsFired, "C_CSPlayerPawn->m_iShotsFired");
|
||||
SCHEMA_ADD_FIELD(std::int32_t, GetArmorValue, "C_CSPlayerPawn->m_ArmorValue");
|
||||
SCHEMA_ADD_FIELD(QAngle_t, GetAimPuchAngle, "C_CSPlayerPawn->m_aimPunchAngle");
|
||||
};
|
||||
|
||||
class CBasePlayerController : public C_BaseModelEntity
|
||||
{
|
||||
public:
|
||||
CS_CLASS_NO_INITIALIZER(CBasePlayerController);
|
||||
|
||||
SCHEMA_ADD_FIELD(std::uint64_t, GetSteamId, "CBasePlayerController->m_steamID");
|
||||
SCHEMA_ADD_FIELD(std::uint32_t, GetTickBase, "CBasePlayerController->m_nTickBase");
|
||||
SCHEMA_ADD_FIELD(CBaseHandle, GetPawnHandle, "CBasePlayerController->m_hPawn");
|
||||
SCHEMA_ADD_FIELD(bool, IsLocalPlayerController, "CBasePlayerController->m_bIsLocalPlayerController");
|
||||
};
|
||||
|
||||
// forward decleration
|
||||
class C_CSWeaponBaseGun;
|
||||
class C_BasePlayerWeapon;
|
||||
class CCSPlayerController : public CBasePlayerController
|
||||
{
|
||||
public:
|
||||
CS_CLASS_NO_INITIALIZER(CCSPlayerController);
|
||||
|
||||
[[nodiscard]] static CCSPlayerController* GetLocalPlayerController();
|
||||
|
||||
// @note: always get origin from pawn not controller
|
||||
[[nodiscard]] const Vector_t& GetPawnOrigin();
|
||||
|
||||
SCHEMA_ADD_FIELD(std::uint32_t, GetPing, "CCSPlayerController->m_iPing");
|
||||
SCHEMA_ADD_FIELD(const char*, GetPlayerName, "CCSPlayerController->m_sSanitizedPlayerName");
|
||||
SCHEMA_ADD_FIELD(std::int32_t, GetPawnHealth, "CCSPlayerController->m_iPawnHealth");
|
||||
SCHEMA_ADD_FIELD(std::int32_t, GetPawnArmor, "CCSPlayerController->m_iPawnArmor");
|
||||
SCHEMA_ADD_FIELD(bool, IsPawnHasDefuser, "CCSPlayerController->m_bPawnHasDefuser");
|
||||
SCHEMA_ADD_FIELD(bool, IsPawnHasHelmet, "CCSPlayerController->m_bPawnHasHelmet");
|
||||
SCHEMA_ADD_FIELD(bool, IsPawnAlive, "CCSPlayerController->m_bPawnIsAlive");
|
||||
SCHEMA_ADD_FIELD(CBaseHandle, GetPlayerPawnHandle, "CCSPlayerController->m_hPlayerPawn");
|
||||
};
|
||||
|
||||
class CBaseAnimGraph : public C_BaseModelEntity
|
||||
{
|
||||
public:
|
||||
CS_CLASS_NO_INITIALIZER(CBaseAnimGraph);
|
||||
|
||||
SCHEMA_ADD_FIELD(bool, IsClientRagdoll, "CBaseAnimGraph->m_bClientRagdoll");
|
||||
};
|
||||
|
||||
class C_BaseFlex : public CBaseAnimGraph
|
||||
{
|
||||
public:
|
||||
CS_CLASS_NO_INITIALIZER(C_BaseFlex);
|
||||
/* not implemented */
|
||||
};
|
||||
|
||||
class C_EconItemView
|
||||
{
|
||||
public:
|
||||
CS_CLASS_NO_INITIALIZER(C_EconItemView);
|
||||
|
||||
SCHEMA_ADD_FIELD(std::uint16_t, GetItemDefinitionIndex, "C_EconItemView->m_iItemDefinitionIndex");
|
||||
SCHEMA_ADD_FIELD(std::uint64_t, GetItemID, "C_EconItemView->m_iItemID");
|
||||
SCHEMA_ADD_FIELD(std::uint32_t, GetItemIDHigh, "C_EconItemView->m_iItemIDHigh");
|
||||
SCHEMA_ADD_FIELD(std::uint32_t, GetItemIDLow, "C_EconItemView->m_iItemIDLow");
|
||||
SCHEMA_ADD_FIELD(std::uint32_t, GetAccountID, "C_EconItemView->m_iAccountID");
|
||||
SCHEMA_ADD_FIELD(char[161], GetCustomName, "C_EconItemView->m_szCustomName");
|
||||
SCHEMA_ADD_FIELD(char[161], GetCustomNameOverride, "C_EconItemView->m_szCustomNameOverride");
|
||||
};
|
||||
|
||||
class CAttributeManager
|
||||
{
|
||||
public:
|
||||
CS_CLASS_NO_INITIALIZER(CAttributeManager);
|
||||
virtual ~CAttributeManager() = 0;
|
||||
};
|
||||
static_assert(sizeof(CAttributeManager) == 0x8);
|
||||
|
||||
class C_AttributeContainer : public CAttributeManager
|
||||
{
|
||||
public:
|
||||
CS_CLASS_NO_INITIALIZER(C_AttributeContainer);
|
||||
|
||||
SCHEMA_ADD_PFIELD(C_EconItemView, GetItem, "C_AttributeContainer->m_Item");
|
||||
};
|
||||
|
||||
class C_EconEntity : public C_BaseFlex
|
||||
{
|
||||
public:
|
||||
CS_CLASS_NO_INITIALIZER(C_EconEntity);
|
||||
|
||||
SCHEMA_ADD_PFIELD(C_AttributeContainer, GetAttributeManager, "C_EconEntity->m_AttributeManager");
|
||||
SCHEMA_ADD_FIELD(std::uint32_t, GetOriginalOwnerXuidLow, "C_EconEntity->m_OriginalOwnerXuidLow");
|
||||
SCHEMA_ADD_FIELD(std::uint32_t, GetOriginalOwnerXuidHigh, "C_EconEntity->m_OriginalOwnerXuidHigh");
|
||||
SCHEMA_ADD_FIELD(std::int32_t, GetFallbackPaintKit, "C_EconEntity->m_nFallbackPaintKit");
|
||||
SCHEMA_ADD_FIELD(std::int32_t, GetFallbackSeed, "C_EconEntity->m_nFallbackSeed");
|
||||
SCHEMA_ADD_FIELD(std::int32_t, GetFallbackWear, "C_EconEntity->m_flFallbackWear");
|
||||
SCHEMA_ADD_FIELD(std::int32_t, GetFallbackStatTrak, "C_EconEntity->m_nFallbackStatTrak");
|
||||
SCHEMA_ADD_FIELD(CBaseHandle, GetViewModelAttachmentHandle, "C_EconEntity->m_hViewmodelAttachment");
|
||||
};
|
||||
|
||||
class C_EconWearable : public C_EconEntity
|
||||
{
|
||||
public:
|
||||
CS_CLASS_NO_INITIALIZER(C_EconWearable);
|
||||
|
||||
SCHEMA_ADD_FIELD(std::int32_t, GetForceSkin, "C_EconWearable->m_nForceSkin");
|
||||
SCHEMA_ADD_FIELD(bool, IsAlwaysAllow, "C_EconWearable->m_bAlwaysAllow");
|
||||
};
|
||||
|
||||
class C_BasePlayerWeapon : public C_EconEntity
|
||||
{
|
||||
public:
|
||||
CS_CLASS_NO_INITIALIZER(C_BasePlayerWeapon);
|
||||
|
||||
SCHEMA_ADD_FIELD(GameTick_t, GetNextPrimaryAttackTick, "C_BasePlayerWeapon->m_nNextPrimaryAttackTick");
|
||||
SCHEMA_ADD_FIELD(float, GetNextPrimaryAttackTickRatio, "C_BasePlayerWeapon->m_flNextPrimaryAttackTickRatio");
|
||||
SCHEMA_ADD_FIELD(GameTick_t, GetNextSecondaryAttackTick, "C_BasePlayerWeapon->m_nNextSecondaryAttackTick");
|
||||
SCHEMA_ADD_FIELD(float, GetNextSecondaryAttackTickRatio, "C_BasePlayerWeapon->m_flNextSecondaryAttackTickRatio");
|
||||
SCHEMA_ADD_FIELD(std::int32_t, GetClip1, "C_BasePlayerWeapon->m_iClip1");
|
||||
SCHEMA_ADD_FIELD(std::int32_t, GetClip2, "C_BasePlayerWeapon->m_iClip2");
|
||||
SCHEMA_ADD_FIELD(std::int32_t[2], GetReserveAmmo, "C_BasePlayerWeapon->m_pReserveAmmo");
|
||||
};
|
||||
|
||||
class C_CSWeaponBase : public C_BasePlayerWeapon
|
||||
{
|
||||
public:
|
||||
CS_CLASS_NO_INITIALIZER(C_CSWeaponBase);
|
||||
|
||||
SCHEMA_ADD_FIELD(bool, IsInReload, "C_CSWeaponBase->m_bInReload");
|
||||
|
||||
CCSWeaponBaseVData* GetWeaponVData()
|
||||
{
|
||||
return static_cast<CCSWeaponBaseVData*>(GetVData());
|
||||
}
|
||||
};
|
||||
|
||||
class C_CSWeaponBaseGun : public C_CSWeaponBase
|
||||
{
|
||||
public:
|
||||
CS_CLASS_NO_INITIALIZER(C_CSWeaponBaseGun);
|
||||
|
||||
SCHEMA_ADD_FIELD(std::int32_t, GetZoomLevel, "C_CSWeaponBaseGun->m_zoomLevel");
|
||||
SCHEMA_ADD_FIELD(std::int32_t, GetBurstShotsRemaining, "C_CSWeaponBaseGun->m_iBurstShotsRemaining");
|
||||
SCHEMA_ADD_FIELD(bool, IsBurstMode, "C_CSWeaponBase->m_bBurstMode");
|
||||
SCHEMA_ADD_FIELD(float, GetPostponeFireReadyFrac, "C_CSWeaponBase->m_flPostponeFireReadyFrac");
|
||||
|
||||
[[nodiscard]] bool CanPrimaryAttack(const int nWeaponType, const float flServerTime);
|
||||
[[nodiscard]] bool CanSecondaryAttack(const int nWeaponType, const float flServerTime);
|
||||
};
|
||||
|
||||
class C_BaseCSGrenade : public C_CSWeaponBase
|
||||
{
|
||||
public:
|
||||
SCHEMA_ADD_FIELD(bool, IsHeldByPlayer, "C_BaseCSGrenade->m_bIsHeldByPlayer");
|
||||
SCHEMA_ADD_FIELD(bool, IsPinPulled, "C_BaseCSGrenade->m_bPinPulled");
|
||||
SCHEMA_ADD_FIELD(GameTime_t, GetThrowTime, "C_BaseCSGrenade->m_fThrowTime");
|
||||
SCHEMA_ADD_FIELD(float, GetThrowStrength, "C_BaseCSGrenade->m_flThrowStrength");
|
||||
};
|
||||
|
||||
class C_BaseGrenade : public C_BaseFlex
|
||||
{
|
||||
public:
|
||||
CS_CLASS_NO_INITIALIZER(C_BaseGrenade);
|
||||
};
|
||||
|
||||
class CSkeletonInstance : public CGameSceneNode
|
||||
{
|
||||
public:
|
||||
MEM_PAD(0x1CC); //0x0000
|
||||
int nBoneCount; //0x01CC
|
||||
MEM_PAD(0x18); //0x01D0
|
||||
int nMask; //0x01E8
|
||||
MEM_PAD(0x4); //0x01EC
|
||||
Matrix2x4_t* pBoneCache; //0x01F0
|
||||
};
|
||||
@@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
#include "../common.h"
|
||||
|
||||
#define INVALID_EHANDLE_INDEX 0xFFFFFFFF
|
||||
#define ENT_ENTRY_MASK 0x7FFF
|
||||
#define NUM_SERIAL_NUM_SHIFT_BITS 15
|
||||
// @source: https://developer.valvesoftware.com/wiki/Entity_limit#Source_2_limits
|
||||
#define ENT_MAX_NETWORKED_ENTRY 16384
|
||||
|
||||
class CBaseHandle
|
||||
{
|
||||
public:
|
||||
CBaseHandle() noexcept :
|
||||
nIndex(INVALID_EHANDLE_INDEX) { }
|
||||
|
||||
CBaseHandle(const int nEntry, const int nSerial) noexcept
|
||||
{
|
||||
CS_ASSERT(nEntry >= 0 && (nEntry & ENT_ENTRY_MASK) == nEntry);
|
||||
CS_ASSERT(nSerial >= 0 && nSerial < (1 << NUM_SERIAL_NUM_SHIFT_BITS));
|
||||
|
||||
nIndex = nEntry | (nSerial << NUM_SERIAL_NUM_SHIFT_BITS);
|
||||
}
|
||||
|
||||
bool operator!=(const CBaseHandle& other) const noexcept
|
||||
{
|
||||
return nIndex != other.nIndex;
|
||||
}
|
||||
|
||||
bool operator==(const CBaseHandle& other) const noexcept
|
||||
{
|
||||
return nIndex == other.nIndex;
|
||||
}
|
||||
|
||||
bool operator<(const CBaseHandle& other) const noexcept
|
||||
{
|
||||
return nIndex < other.nIndex;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsValid() const noexcept
|
||||
{
|
||||
return nIndex != INVALID_EHANDLE_INDEX;
|
||||
}
|
||||
|
||||
[[nodiscard]] int GetEntryIndex() const noexcept
|
||||
{
|
||||
return static_cast<int>(nIndex & ENT_ENTRY_MASK);
|
||||
}
|
||||
|
||||
[[nodiscard]] int GetSerialNumber() const noexcept
|
||||
{
|
||||
return static_cast<int>(nIndex >> NUM_SERIAL_NUM_SHIFT_BITS);
|
||||
}
|
||||
|
||||
private:
|
||||
std::uint32_t nIndex;
|
||||
};
|
||||
@@ -0,0 +1,95 @@
|
||||
#pragma once
|
||||
|
||||
// used: mem_pad
|
||||
#include "../../utilities/memory.h"
|
||||
|
||||
// used: cusercmd
|
||||
#include "../datatypes/usercmd.h"
|
||||
|
||||
#define MULTIPLAYER_BACKUP 150
|
||||
|
||||
class CTinyMoveStepData
|
||||
{
|
||||
public:
|
||||
float flWhen; //0x0000
|
||||
MEM_PAD(0x4); //0x0004
|
||||
std::uint64_t nButton; //0x0008
|
||||
bool bPressed; //0x0010
|
||||
MEM_PAD(0x7); //0x0011
|
||||
}; //Size: 0x0018
|
||||
|
||||
class CMoveStepButtons
|
||||
{
|
||||
public:
|
||||
std::uint64_t nKeyboardPressed; //0x0000
|
||||
std::uint64_t nMouseWheelheelPressed; //0x0008
|
||||
std::uint64_t nUnPressed; //0x0010
|
||||
std::uint64_t nKeyboardCopy; //0x0018
|
||||
}; //Size: 0x0020
|
||||
|
||||
// @credits: www.unknowncheats.me/forum/members/2943409.html
|
||||
class CExtendedMoveData : public CMoveStepButtons
|
||||
{
|
||||
public:
|
||||
float flForwardMove; //0x0020
|
||||
float flSideMove; //0x0024
|
||||
float flUpMove; //0x0028
|
||||
std::int32_t nMouseDeltaX; //0x002C
|
||||
std::int32_t nMouseDeltaY; //0x0030
|
||||
std::int32_t nAdditionalStepMovesCount; //0x0034
|
||||
CTinyMoveStepData tinyMoveStepData[12]; //0x0038
|
||||
Vector_t vecViewAngle; //0x0158
|
||||
std::int32_t nTargetHandle; //0x0164
|
||||
}; //Size:0x0168
|
||||
|
||||
class CCSGOInput
|
||||
{
|
||||
public:
|
||||
MEM_PAD(0x250);
|
||||
CUserCmd arrCommands[MULTIPLAYER_BACKUP];
|
||||
MEM_PAD(0x99)
|
||||
bool bInThirdPerson;
|
||||
MEM_PAD(0x6);
|
||||
QAngle_t angThirdPersonAngles;
|
||||
MEM_PAD(0xE);
|
||||
std::int32_t nSequenceNumber;
|
||||
double dbSomeTimer;
|
||||
CExtendedMoveData currentMoveData;
|
||||
std::int32_t nWeaponSwitchTick;
|
||||
MEM_PAD(0x1C4);
|
||||
CExtendedMoveData* pExtendedMoveData;
|
||||
MEM_PAD(0x48);
|
||||
int32_t nAttackStartHistoryIndex1;
|
||||
int32_t nAttackStartHistoryIndex2;
|
||||
int32_t nAttackStartHistoryIndex3;
|
||||
|
||||
CUserCmd* GetUserCmd()
|
||||
{
|
||||
return &arrCommands[nSequenceNumber % MULTIPLAYER_BACKUP];
|
||||
}
|
||||
|
||||
void SetViewAngle(QAngle_t& angView)
|
||||
{
|
||||
// @ida: this got called before GetMatricesForView
|
||||
using fnSetViewAngle = std::int64_t(CS_FASTCALL*)(void*, std::int32_t, QAngle_t&);
|
||||
static auto oSetViewAngle = reinterpret_cast<fnSetViewAngle>(MEM::FindPattern(CLIENT_DLL, CS_XOR("85 D2 75 3F 48")));
|
||||
|
||||
#ifdef CS_PARANOID
|
||||
CS_ASSERT(oSetViewAngle != nullptr);
|
||||
#endif
|
||||
|
||||
oSetViewAngle(this, 0, std::ref(angView));
|
||||
}
|
||||
|
||||
QAngle_t GetViewAngles()
|
||||
{
|
||||
using fnGetViewAngles = std::int64_t(CS_FASTCALL*)(CCSGOInput*, std::int32_t);
|
||||
static auto oGetViewAngles = reinterpret_cast<fnGetViewAngles>(MEM::FindPattern(CLIENT_DLL, CS_XOR("4C 8B C1 85 D2 74 08 48 8D 05 ? ? ? ? C3")));
|
||||
|
||||
#ifdef CS_PARANOID
|
||||
CS_ASSERT(oGetViewAngles != nullptr);
|
||||
#endif
|
||||
|
||||
return *reinterpret_cast<QAngle_t*>(oGetViewAngles(this, 0));
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
// used: schema field
|
||||
#include "../../utilities/memory.h"
|
||||
|
||||
#include "../entity_handle.h"
|
||||
|
||||
#define MAX_ENTITIES_IN_LIST 512
|
||||
#define MAX_ENTITY_LISTS 64 // 0x3F
|
||||
#define MAX_TOTAL_ENTITIES MAX_ENTITIES_IN_LIST* MAX_ENTITY_LISTS
|
||||
|
||||
class C_BaseEntity;
|
||||
|
||||
class CGameEntitySystem
|
||||
{
|
||||
public:
|
||||
/// GetClientEntity
|
||||
template <typename T = C_BaseEntity>
|
||||
T* Get(int nIndex)
|
||||
{
|
||||
return reinterpret_cast<T*>(this->GetEntityByIndex(nIndex));
|
||||
}
|
||||
|
||||
/// GetClientEntityFromHandle
|
||||
template <typename T = C_BaseEntity>
|
||||
T* Get(const CBaseHandle hHandle)
|
||||
{
|
||||
if (!hHandle.IsValid())
|
||||
return nullptr;
|
||||
|
||||
return reinterpret_cast<T*>(this->GetEntityByIndex(hHandle.GetEntryIndex()));
|
||||
}
|
||||
|
||||
int GetHighestEntityIndex()
|
||||
{
|
||||
return *reinterpret_cast<int*>(reinterpret_cast<std::uintptr_t>(this) + 0x1510);
|
||||
}
|
||||
|
||||
private:
|
||||
void* GetEntityByIndex(int nIndex)
|
||||
{
|
||||
//@ida: #STR: "(missing),", "(missing)", "Ent %3d: %s class %s name %s\n" | or find "cl_showents" cvar -> look for callback
|
||||
// do { pEntity = GetBaseEntityByIndex(g_pGameEntitySystem, nCurrentIndex); ... }
|
||||
using fnGetBaseEntity = void*(CS_THISCALL*)(void*, int);
|
||||
static auto GetBaseEntity = reinterpret_cast<fnGetBaseEntity>(MEM::FindPattern(CLIENT_DLL, CS_XOR("81 FA ? ? ? ? 77 ? 8B C2 C1 F8 ? 83 F8 ? 77 ? 48 98 48 8B 4C C1 ? 48 85 C9 74 ? 8B C2 25 ? ? ? ? 48 6B C0 ? 48 03 C8 74 ? 8B 41 ? 25 ? ? ? ? 3B C2 75 ? 48 8B 01")));
|
||||
return GetBaseEntity(this, nIndex);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,59 @@
|
||||
// used: game trace manager
|
||||
#include "cgametracemanager.h"
|
||||
// used: c_csplayerpawn
|
||||
#include "../../sdk/entity.h"
|
||||
|
||||
SurfaceData_t* GameTrace_t::GetSurfaceData()
|
||||
{
|
||||
using fnGetSurfaceData = std::uint64_t(__fastcall*)(void*);
|
||||
static fnGetSurfaceData oGetSurfaceData = reinterpret_cast<fnGetSurfaceData>(MEM::GetAbsoluteAddress(MEM::FindPattern(CLIENT_DLL, CS_XOR("E8 ? ? ? ? 48 85 C0 74 ? 44 38 60")), 0x1, 0x0));
|
||||
|
||||
#ifdef CS_PARANOID
|
||||
CS_ASSERT(oGetSurfaceData != nullptr);
|
||||
#endif
|
||||
|
||||
return reinterpret_cast<SurfaceData_t*>(oGetSurfaceData(m_pSurface));
|
||||
}
|
||||
|
||||
int GameTrace_t::GetHitboxId()
|
||||
{
|
||||
if (m_pHitboxData)
|
||||
return m_pHitboxData->m_nHitboxId;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GameTrace_t::GetHitgroup()
|
||||
{
|
||||
if (m_pHitboxData)
|
||||
return m_pHitboxData->m_nHitGroup;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool GameTrace_t::IsVisible() const
|
||||
{
|
||||
return (m_flFraction > 0.97f);
|
||||
}
|
||||
|
||||
TraceFilter_t::TraceFilter_t(std::uint64_t uMask, C_CSPlayerPawn* pSkip1, C_CSPlayerPawn* pSkip2, int nLayer)
|
||||
{
|
||||
m_uTraceMask = uMask;
|
||||
m_v1[0] = m_v1[1] = 0;
|
||||
m_v2 = 7;
|
||||
m_v3 = nLayer;
|
||||
m_v4 = 0x49;
|
||||
m_v5 = 0;
|
||||
|
||||
if (pSkip1 != nullptr)
|
||||
{
|
||||
m_arrSkipHandles[0] = pSkip1->GetRefEHandle().GetEntryIndex();
|
||||
m_arrSkipHandles[2] = pSkip1->GetOwnerHandleIndex();
|
||||
m_arrCollisions[0] = pSkip1->GetCollisionMask();
|
||||
}
|
||||
|
||||
if (pSkip2 != nullptr)
|
||||
{
|
||||
m_arrSkipHandles[0] = pSkip2->GetRefEHandle().GetEntryIndex();
|
||||
m_arrSkipHandles[2] = pSkip2->GetOwnerHandleIndex();
|
||||
m_arrCollisions[0] = pSkip2->GetCollisionMask();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
#pragma once
|
||||
// used: pad and findpattern
|
||||
#include "../../utilities/memory.h"
|
||||
// used: vector
|
||||
#include "../../sdk/datatypes/vector.h"
|
||||
// used: array
|
||||
#include <array>
|
||||
|
||||
struct Ray_t
|
||||
{
|
||||
public:
|
||||
Vector_t m_vecStart;
|
||||
Vector_t m_vecEnd;
|
||||
Vector_t m_vecMins;
|
||||
Vector_t m_vecMaxs;
|
||||
MEM_PAD(0x4);
|
||||
std::uint8_t UnkType;
|
||||
};
|
||||
static_assert(sizeof(Ray_t) == 0x38);
|
||||
|
||||
struct SurfaceData_t
|
||||
{
|
||||
public:
|
||||
MEM_PAD(0x8)
|
||||
float m_flPenetrationModifier;
|
||||
float m_flDamageModifier;
|
||||
MEM_PAD(0x4)
|
||||
int m_iMaterial;
|
||||
};
|
||||
|
||||
static_assert(sizeof(SurfaceData_t) == 0x18);
|
||||
|
||||
struct TraceHitboxData_t
|
||||
{
|
||||
public:
|
||||
MEM_PAD(0x38);
|
||||
int m_nHitGroup;
|
||||
MEM_PAD(0x4);
|
||||
int m_nHitboxId;
|
||||
};
|
||||
static_assert(sizeof(TraceHitboxData_t) == 0x44);
|
||||
|
||||
class C_CSPlayerPawn;
|
||||
struct GameTrace_t
|
||||
{
|
||||
public:
|
||||
GameTrace_t() = default;
|
||||
|
||||
SurfaceData_t* GetSurfaceData();
|
||||
int GetHitboxId();
|
||||
int GetHitgroup();
|
||||
bool IsVisible() const;
|
||||
|
||||
void* m_pSurface;
|
||||
C_CSPlayerPawn* m_pHitEntity;
|
||||
TraceHitboxData_t* m_pHitboxData;
|
||||
MEM_PAD(0x38);
|
||||
std::uint32_t m_uContents;
|
||||
MEM_PAD(0x24);
|
||||
Vector_t m_vecStartPos;
|
||||
Vector_t m_vecEndPos;
|
||||
Vector_t m_vecNormal;
|
||||
Vector_t m_vecPosition;
|
||||
MEM_PAD(0x4);
|
||||
float m_flFraction;
|
||||
MEM_PAD(0x6);
|
||||
bool m_bAllSolid;
|
||||
MEM_PAD(0x4D)
|
||||
}; // Size: 0x108
|
||||
|
||||
static_assert(sizeof(GameTrace_t) == 0x108);
|
||||
|
||||
struct TraceFilter_t
|
||||
{
|
||||
public:
|
||||
MEM_PAD(0x8);
|
||||
std::int64_t m_uTraceMask;
|
||||
std::array<std::int64_t, 2> m_v1;
|
||||
std::array<std::int32_t, 4> m_arrSkipHandles;
|
||||
std::array<std::int16_t, 2> m_arrCollisions;
|
||||
std::int16_t m_v2;
|
||||
std::uint8_t m_v3;
|
||||
std::uint8_t m_v4;
|
||||
std::uint8_t m_v5;
|
||||
|
||||
TraceFilter_t() = default;
|
||||
TraceFilter_t(std::uint64_t uMask, C_CSPlayerPawn* pSkip1, C_CSPlayerPawn* pSkip2, int nLayer);
|
||||
};
|
||||
static_assert(sizeof(TraceFilter_t) == 0x40);
|
||||
|
||||
class CGameTraceManager
|
||||
{
|
||||
public:
|
||||
bool TraceShape(Ray_t* pRay, Vector_t vecStart, Vector_t vecEnd, TraceFilter_t* pFilter, GameTrace_t* pGameTrace)
|
||||
{
|
||||
using fnTraceShape = bool(__fastcall*)(CGameTraceManager*, Ray_t*, Vector_t*, Vector_t*, TraceFilter_t*, GameTrace_t*);
|
||||
// Credit: https://www.unknowncheats.me/forum/4265752-post6333.html
|
||||
static fnTraceShape oTraceShape = reinterpret_cast<fnTraceShape>(MEM::FindPattern(CLIENT_DLL, CS_XOR("48 89 5C 24 20 48 89 4C 24 08 55 56 41")));
|
||||
|
||||
#ifdef CS_PARANOID
|
||||
CS_ASSERT(oTraceShape != nullptr);
|
||||
#endif
|
||||
|
||||
return oTraceShape(this, pRay, &vecStart, &vecEnd, pFilter, pGameTrace);
|
||||
}
|
||||
|
||||
bool ClipRayToEntity(Ray_t* pRay, Vector_t vecStart, Vector_t vecEnd, C_CSPlayerPawn* pPawn, TraceFilter_t* pFilter, GameTrace_t* pGameTrace)
|
||||
{
|
||||
using fnClipRayToEntity = bool(__fastcall*)(CGameTraceManager*, Ray_t*, Vector_t*, Vector_t*, C_CSPlayerPawn*, TraceFilter_t*, GameTrace_t*);
|
||||
static fnClipRayToEntity oClipRayToEntity = reinterpret_cast<fnClipRayToEntity>(MEM::FindPattern(CLIENT_DLL, CS_XOR("48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 48 89 7C 24 20 41 54 41 56 41 57 48 81 EC C0 00 00 00 48 8B 9C")));
|
||||
|
||||
#ifdef CS_PARANOID
|
||||
CS_ASSERT(oClipRayToEntity != nullptr);
|
||||
#endif
|
||||
|
||||
return oClipRayToEntity(this, pRay, &vecStart, &vecEnd, pPawn, pFilter, pGameTrace);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
// used: find pattern, call virtual function
|
||||
#include "../../utilities/memory.h"
|
||||
|
||||
// used: vertor_t
|
||||
#include "../datatypes/vector.h"
|
||||
// used: color_t
|
||||
#include "../datatypes/color.h"
|
||||
|
||||
class IDebugOverlayGameSystem
|
||||
{
|
||||
public:
|
||||
// @todo: reverse this
|
||||
};
|
||||
@@ -0,0 +1,67 @@
|
||||
#pragma once
|
||||
|
||||
// used: callvfunc
|
||||
#include "../../utilities/memory.h"
|
||||
|
||||
enum EClientFrameStage : int
|
||||
{
|
||||
FRAME_UNDEFINED = -1,
|
||||
FRAME_START,
|
||||
// a network packet is being received
|
||||
FRAME_NET_UPDATE_START,
|
||||
// data has been received and we are going to start calling postdataupdate
|
||||
FRAME_NET_UPDATE_POSTDATAUPDATE_START,
|
||||
// data has been received and called postdataupdate on all data recipients
|
||||
FRAME_NET_UPDATE_POSTDATAUPDATE_END,
|
||||
// received all packets, we can now do interpolation, prediction, etc
|
||||
FRAME_NET_UPDATE_END,
|
||||
// start rendering the scene
|
||||
FRAME_RENDER_START,
|
||||
// finished rendering the scene
|
||||
FRAME_RENDER_END,
|
||||
FRAME_NET_FULL_FRAME_UPDATE_ON_REMOVE
|
||||
};
|
||||
|
||||
class IEngineClient
|
||||
{
|
||||
public:
|
||||
int GetMaxClients()
|
||||
{
|
||||
return MEM::CallVFunc<int, 34U>(this);
|
||||
}
|
||||
|
||||
bool IsInGame()
|
||||
{
|
||||
return MEM::CallVFunc<bool, 35U>(this);
|
||||
}
|
||||
|
||||
bool IsConnected()
|
||||
{
|
||||
return MEM::CallVFunc<bool, 36U>(this);
|
||||
}
|
||||
|
||||
// return CBaseHandle index
|
||||
int GetLocalPlayer()
|
||||
{
|
||||
int nIndex = -1;
|
||||
|
||||
MEM::CallVFunc<void, 47U>(this, std::ref(nIndex), 0);
|
||||
|
||||
return nIndex + 1;
|
||||
}
|
||||
|
||||
[[nodiscard]] const char* GetLevelName()
|
||||
{
|
||||
return MEM::CallVFunc<const char*, 56U>(this);
|
||||
}
|
||||
|
||||
[[nodiscard]] const char* GetLevelNameShort()
|
||||
{
|
||||
return MEM::CallVFunc<const char*, 57U>(this);
|
||||
}
|
||||
|
||||
[[nodiscard]] const char* GetProductVersionString()
|
||||
{
|
||||
return MEM::CallVFunc<const char*, 82U>(this);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,150 @@
|
||||
#pragma once
|
||||
|
||||
// used: cutllinkedlist
|
||||
#include "../datatypes/utllinkedlist.h"
|
||||
// used: fnv1a hashing
|
||||
#include "../../utilities/fnv1a.h"
|
||||
|
||||
// used: sdk datatypes
|
||||
#include "../datatypes/color.h"
|
||||
#include "../datatypes/vector.h"
|
||||
#include "../datatypes/qangle.h"
|
||||
|
||||
#pragma region convar_enumerations
|
||||
// command to convars and concommands
|
||||
enum EConVarFlag : int
|
||||
{
|
||||
// convar systems
|
||||
FCVAR_NONE = 0,
|
||||
FCVAR_UNREGISTERED = (1 << 0), // if this is set, don't add to linked list, etc
|
||||
FCVAR_DEVELOPMENTONLY = (1 << 1), // hidden in released products. flag is removed automatically if allow_development_cvars is defined
|
||||
FCVAR_GAMEDLL = (1 << 2), // defined by the game dll
|
||||
FCVAR_CLIENTDLL = (1 << 3), // defined by the client dll
|
||||
FCVAR_HIDDEN = (1 << 4), // hidden. doesn't appear in find or autocomplete. like developmentonly, but can't be compiled out
|
||||
|
||||
// convar only
|
||||
FCVAR_PROTECTED = (1 << 5), // it's a server cvar, but we don't send the data since it's a password, etc. sends 1 if it's not bland/zero, 0 otherwise as value
|
||||
FCVAR_SPONLY = (1 << 6), // this cvar cannot be changed by clients connected to a multiplayer server
|
||||
FCVAR_ARCHIVE = (1 << 7), // set to cause it to be saved to vars.rc
|
||||
FCVAR_NOTIFY = (1 << 8), // notifies players when changed
|
||||
FCVAR_USERINFO = (1 << 9), // changes the client's info string
|
||||
FCVAR_CHEAT = (1 << 14), // only useable in singleplayer/debug/multiplayer & sv_cheats
|
||||
FCVAR_PRINTABLEONLY = (1 << 10), // this cvar's string cannot contain unprintable characters (e.g., used for player name etc)
|
||||
FCVAR_UNLOGGED = (1 << 11), // if this is a fcvar_server, don't log changes to the log file / console if we are creating a log
|
||||
FCVAR_NEVER_AS_STRING = (1 << 12), // never try to print that cvar
|
||||
|
||||
// it's a convar that's shared between the client and the server.
|
||||
// at signon, the values of all such convars are sent from the server to the client (skipped for local client, ofc)
|
||||
// if a change is requested it must come from the console (i.e., no remote client changes)
|
||||
// if a value is changed while a server is active, it's replicated to all connected clients
|
||||
FCVAR_REPLICATED = (1 << 13), // server setting enforced on clients, replicated
|
||||
// @todo: (1 << 14) used by the game, probably used as modification detection
|
||||
FCVAR_DEMO = (1 << 16), // record this cvar when starting a demo file
|
||||
FCVAR_DONTRECORD = (1 << 17), // don't record these command in demofiles
|
||||
FCVAR_RELOAD_MATERIALS = (1 << 20), // if this cvar changes, it forces a material reload
|
||||
FCVAR_RELOAD_TEXTURES = (1 << 21), // if this cvar changes, if forces a texture reload
|
||||
FCVAR_NOT_CONNECTED = (1 << 22), // cvar cannot be changed by a client that is connected to a server
|
||||
FCVAR_MATERIAL_SYSTEM_THREAD = (1 << 23), // indicates this cvar is read from the material system thread
|
||||
FCVAR_ARCHIVE_XBOX = (1 << 24), // cvar written to config.cfg on the xbox
|
||||
FCVAR_ACCESSIBLE_FROM_THREADS = (1 << 25), // used as a debugging tool necessary to check material system thread convars
|
||||
FCVAR_SERVER_CAN_EXECUTE = (1 << 28), // the server is allowed to execute this command on clients via clientcommand/net_stringcmd/cbaseclientstate::processstringcmd
|
||||
FCVAR_SERVER_CANNOT_QUERY = (1 << 29), // if this is set, then the server is not allowed to query this cvar's value (via iserverpluginhelpers::startquerycvarvalue)
|
||||
FCVAR_CLIENTCMD_CAN_EXECUTE = (1 << 30), // ivengineclient::clientcmd is allowed to execute this command
|
||||
FCVAR_MATERIAL_THREAD_MASK = (FCVAR_RELOAD_MATERIALS | FCVAR_RELOAD_TEXTURES | FCVAR_MATERIAL_SYSTEM_THREAD)
|
||||
};
|
||||
|
||||
enum EConVarType : short
|
||||
{
|
||||
EConVarType_Invalid = -1,
|
||||
EConVarType_Bool,
|
||||
EConVarType_Int16,
|
||||
EConVarType_UInt16,
|
||||
EConVarType_Int32,
|
||||
EConVarType_UInt32,
|
||||
EConVarType_Int64,
|
||||
EConVarType_UInt64,
|
||||
EConVarType_Float32,
|
||||
EConVarType_Float64,
|
||||
EConVarType_String,
|
||||
EConVarType_Color,
|
||||
EConVarType_Vector2,
|
||||
EConVarType_Vector3,
|
||||
EConVarType_Vector4,
|
||||
EConVarType_Qangle,
|
||||
EConVarType_MAX
|
||||
};
|
||||
|
||||
#pragma endregion
|
||||
|
||||
union CVValue_t
|
||||
{
|
||||
bool i1;
|
||||
short i16;
|
||||
uint16_t u16;
|
||||
int i32;
|
||||
uint32_t u32;
|
||||
int64_t i64;
|
||||
uint64_t u64;
|
||||
float fl;
|
||||
double db;
|
||||
const char* sz;
|
||||
Color_t clr;
|
||||
Vector2D_t vec2;
|
||||
Vector_t vec3;
|
||||
Vector4D_t vec4;
|
||||
QAngle_t ang;
|
||||
};
|
||||
|
||||
class CConVar
|
||||
{
|
||||
public:
|
||||
const char* szName; // 0x0000
|
||||
CConVar* m_pNext; // 0x0008
|
||||
MEM_PAD(0x10); // 0x0010
|
||||
const char* szDescription; // 0x0020
|
||||
uint32_t nType; // 0x28
|
||||
uint32_t nRegistered; // 0x2C
|
||||
uint32_t nFlags; // 0x30
|
||||
MEM_PAD(0x8); // 0x34
|
||||
// @note: read-only, mofify with caution
|
||||
CVValue_t value; // 0x40
|
||||
};
|
||||
|
||||
class IEngineCVar
|
||||
{
|
||||
public:
|
||||
MEM_PAD(0x40);
|
||||
CUtlLinkedList<CConVar*> listConvars;
|
||||
|
||||
CConVar* Find(FNV1A_t uHashedName)
|
||||
{
|
||||
for (int i = I::Cvar->listConvars.Head(); i != I::Cvar->listConvars.InvalidIndex(); i = I::Cvar->listConvars.Next(i))
|
||||
{
|
||||
CConVar* pConVar = I::Cvar->listConvars.Element(i);
|
||||
if (pConVar == nullptr)
|
||||
continue;
|
||||
|
||||
if (FNV1A::Hash(pConVar->szName) == uHashedName)
|
||||
return pConVar;
|
||||
}
|
||||
|
||||
CS_ASSERT(false); // invalid convar name
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void UnlockHiddenCVars()
|
||||
{
|
||||
for (int i = I::Cvar->listConvars.Head(); i != I::Cvar->listConvars.InvalidIndex(); i = I::Cvar->listConvars.Next(i))
|
||||
{
|
||||
CConVar* pConVar = I::Cvar->listConvars.Element(i);
|
||||
if (pConVar == nullptr)
|
||||
continue;
|
||||
|
||||
if (pConVar->nFlags & FCVAR_HIDDEN)
|
||||
pConVar->nFlags &= ~FCVAR_HIDDEN;
|
||||
|
||||
if (pConVar->nFlags & FCVAR_DEVELOPMENTONLY)
|
||||
pConVar->nFlags &= ~FCVAR_DEVELOPMENTONLY;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
// used: mem_pad
|
||||
#include "../../utilities/memory.h"
|
||||
|
||||
class CGameEntitySystem;
|
||||
|
||||
class IGameResourceService
|
||||
{
|
||||
public:
|
||||
MEM_PAD(0x58);
|
||||
CGameEntitySystem* pGameEntitySystem;
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
// used: mem_pad
|
||||
#include "../../utilities/memory.h"
|
||||
|
||||
class IGlobalVars
|
||||
{
|
||||
public:
|
||||
float flRealTime; //0x0000
|
||||
int32_t nFrameCount; //0x0004
|
||||
float flFrameTime; //0x0008
|
||||
float flFrameTime2; //0x000C
|
||||
int32_t nMaxClients; //0x0010
|
||||
MEM_PAD(0x1C);
|
||||
float flFrameTime3; //0x0030
|
||||
float flCurrentTime; //0x0034
|
||||
float flCurrentTime2; //0x0038
|
||||
MEM_PAD(0xC);
|
||||
int32_t nTickCount; //0x0048
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
// used: getexportaddress
|
||||
#include "../../utilities/memory.h"
|
||||
|
||||
class IInputSystem
|
||||
{
|
||||
public:
|
||||
bool IsRelativeMouseMode()
|
||||
{
|
||||
// @ida: 'IInputSystem::SetRelativeMouseMode'.
|
||||
return *reinterpret_cast<bool*>(reinterpret_cast<std::uintptr_t>(this) + 0x4D);
|
||||
}
|
||||
|
||||
void* GetSDLWindow()
|
||||
{
|
||||
// @ida: IInputSystem::DebugSpew -> #STR: "Current coordinate bias %s: %g,%g scale %g,%g\n"
|
||||
return *reinterpret_cast<void**>(reinterpret_cast<std::uintptr_t>(this) + 0x26A8);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,126 @@
|
||||
#pragma once
|
||||
|
||||
// used: call virtual function
|
||||
#include "../../utilities/memory.h"
|
||||
|
||||
// used: color_t
|
||||
#include "../datatypes/color.h"
|
||||
// used: stronghandle
|
||||
#include "../datatypes/stronghandle.h"
|
||||
// used: keyvalue3
|
||||
#include "../datatypes/keyvalue3.h"
|
||||
// used vector4d_t
|
||||
#include "../datatypes/vector.h"
|
||||
|
||||
// used: cbasehandle
|
||||
#include "../entity_handle.h"
|
||||
|
||||
class CMaterial2
|
||||
{
|
||||
public:
|
||||
virtual const char* GetName() = 0;
|
||||
virtual const char* GetShareName() = 0;
|
||||
};
|
||||
|
||||
// idk
|
||||
struct MaterialKeyVar_t
|
||||
{
|
||||
std::uint64_t uKey;
|
||||
const char* szName;
|
||||
|
||||
MaterialKeyVar_t(std::uint64_t uKey, const char* szName) :
|
||||
uKey(uKey), szName(szName) { }
|
||||
|
||||
MaterialKeyVar_t(const char* szName, bool bShouldFindKey = false) :
|
||||
szName(szName)
|
||||
{
|
||||
uKey = bShouldFindKey ? FindKey(szName) : 0x0;
|
||||
}
|
||||
|
||||
std::uint64_t FindKey(const char* szName)
|
||||
{
|
||||
using fnFindKeyVar = std::uint64_t(CS_FASTCALL*)(const char*, unsigned int, int);
|
||||
static auto oFindKeyVar = reinterpret_cast<fnFindKeyVar>(MEM::FindPattern(PARTICLES_DLL, CS_XOR("48 89 5C 24 ? 57 48 81 EC ? ? ? ? 33 C0 8B DA")));
|
||||
|
||||
#ifdef CS_PARANOID
|
||||
CS_ASSERT(oFindKeyVar != nullptr);
|
||||
#endif
|
||||
|
||||
// idk those enum flags, just saw it called like that soooo yea
|
||||
return oFindKeyVar(szName, 0x12, 0x31415926);
|
||||
}
|
||||
};
|
||||
|
||||
class CObjectInfo
|
||||
{
|
||||
MEM_PAD(0xB0);
|
||||
int nId;
|
||||
};
|
||||
|
||||
class CSceneAnimatableObject
|
||||
{
|
||||
MEM_PAD(0xB8);
|
||||
CBaseHandle hOwner;
|
||||
};
|
||||
|
||||
// the naming is incorrect but i dont care atm
|
||||
class CMeshData
|
||||
{
|
||||
public:
|
||||
void SetShaderType(const char* szShaderName)
|
||||
{
|
||||
// @ida: #STR: shader, spritecard.vfx
|
||||
using fnSetMaterialShaderType = void(CS_FASTCALL*)(void*, MaterialKeyVar_t, const char*, int);
|
||||
static auto oSetMaterialShaderType = reinterpret_cast<fnSetMaterialShaderType>(MEM::FindPattern(PARTICLES_DLL, CS_XOR("48 89 5C 24 ? 48 89 6C 24 ? 56 57 41 54 41 56 41 57 48 83 EC ? 0F B6 01 45 0F B6 F9 8B 2A 4D 8B E0 4C 8B 72 ? 48 8B F9 C0 E8 ? 24 ? 3C ? 74 ? 41 B0 ? B2 ? E8 ? ? ? ? 0F B6 07 33 DB C0 E8 ? 24 ? 3C ? 75 ? 48 8B 77 ? EB ? 48 8B F3 4C 8D 44 24 ? C7 44 24 ? ? ? ? ? 48 8D 54 24 ? 89 6C 24 ? 48 8B CE 4C 89 74 24 ? E8 ? ? ? ? 8B D0 83 F8 ? 75 ? 45 33 C9 89 6C 24 ? 4C 8D 44 24 ? 4C 89 74 24 ? 48 8B D7 48 8B CE E8 ? ? ? ? 8B D0 0F B6 0F C0 E9 ? 80 E1 ? 80 F9 ? 75 ? 48 8B 4F ? EB ? 48 8B CB 8B 41 ? 85 C0 74 ? 48 8D 59 ? 83 F8 ? 76 ? 48 8B 1B 48 63 C2 4D 85 E4")));
|
||||
|
||||
#ifdef CS_PARANOID
|
||||
CS_ASSERT(oSetMaterialShaderType != nullptr);
|
||||
#endif
|
||||
|
||||
MaterialKeyVar_t shaderVar(0x162C1777, CS_XOR("shader"));
|
||||
oSetMaterialShaderType(this, shaderVar, szShaderName, 0x18);
|
||||
}
|
||||
|
||||
void SetMaterialFunction(const char* szFunctionName, int nValue)
|
||||
{
|
||||
using fnSetMaterialFunction = void(__fastcall*)(void*, MaterialKeyVar_t, int, int);
|
||||
static auto oSetMaterialFunction = reinterpret_cast<fnSetMaterialFunction>(MEM::FindPattern(PARTICLES_DLL, CS_XOR("48 89 5C 24 ? 48 89 6C 24 ? 56 57 41 54 41 56 41 57 48 83 EC ? 0F B6 01 45 0F B6 F9 8B 2A 48 8B F9")));
|
||||
|
||||
#ifdef CS_PARANOID
|
||||
CS_ASSERT(oSetMaterialFunction != nullptr);
|
||||
#endif
|
||||
|
||||
MaterialKeyVar_t functionVar(szFunctionName, true);
|
||||
oSetMaterialFunction(this, functionVar, nValue, 0x18);
|
||||
}
|
||||
|
||||
// Credit: https://www.unknowncheats.me/forum/4270816-post6392.html
|
||||
|
||||
MEM_PAD(0x18); // 0x0
|
||||
CSceneAnimatableObject* pSceneAnimatableObject; // 0x18
|
||||
CMaterial2* pMaterial; // 0x20
|
||||
CMaterial2* pMaterialCpy; // 0x28
|
||||
MEM_PAD(0x10);
|
||||
CObjectInfo* pObjectInfo;
|
||||
MEM_PAD(0x8);
|
||||
Color_t colValue;
|
||||
};
|
||||
|
||||
class IMaterialSystem2
|
||||
{
|
||||
public:
|
||||
CMaterial2*** FindOrCreateFromResource(CMaterial2*** pOutMaterial, const char* szMaterialName)
|
||||
{
|
||||
return MEM::CallVFunc<CMaterial2***, 14U>(this, pOutMaterial, szMaterialName);
|
||||
}
|
||||
|
||||
CMaterial2** CreateMaterial(CMaterial2*** pOutMaterial, const char* szMaterialName, CMeshData* pData)
|
||||
{
|
||||
return MEM::CallVFunc<CMaterial2**, 29U>(this, pOutMaterial, szMaterialName, pData, 0, 0, 0, 0, 0, 1);
|
||||
}
|
||||
|
||||
void SetCreateDataByMaterial(const void* pData, CMaterial2*** const pInMaterial)
|
||||
{
|
||||
return MEM::CallVFunc<void, 37U>(this, pInMaterial, pData);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
// used: mem::CallVFunc
|
||||
#include "../../utilities/memory.h"
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4191)
|
||||
|
||||
class IMemAlloc
|
||||
{
|
||||
public:
|
||||
void* Alloc(std::size_t nSize)
|
||||
{
|
||||
return MEM::CallVFunc<void*, 1>(this, nSize);
|
||||
}
|
||||
|
||||
void* ReAlloc(const void* pMemory, std::size_t nSize)
|
||||
{
|
||||
return MEM::CallVFunc<void*, 2>(this, pMemory, nSize);
|
||||
}
|
||||
|
||||
void Free(const void* pMemory)
|
||||
{
|
||||
return MEM::CallVFunc<void, 3>(this, pMemory);
|
||||
}
|
||||
|
||||
std::size_t GetSize(const void* pMemory)
|
||||
{
|
||||
return MEM::CallVFunc<std::size_t, 21>(this, pMemory);
|
||||
}
|
||||
};
|
||||
|
||||
#pragma warning(pop)
|
||||
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
#include "../../utilities/memory.h"
|
||||
|
||||
class CNetworkGameClient
|
||||
{
|
||||
public:
|
||||
bool IsConnected()
|
||||
{
|
||||
return MEM::CallVFunc<bool, 12U>(this);
|
||||
}
|
||||
|
||||
// force game to clear cache and reset delta tick
|
||||
void FullUpdate()
|
||||
{
|
||||
// @ida: #STR: "Requesting full game update (%s)...\n"
|
||||
MEM::CallVFunc<void, 28U>(this, CS_XOR("unk"));
|
||||
}
|
||||
|
||||
int GetDeltaTick()
|
||||
{
|
||||
// @ida: offset in FullUpdate();
|
||||
// (nDeltaTick = -1) == FullUpdate() called
|
||||
return *reinterpret_cast<int*>(reinterpret_cast<std::uintptr_t>(this) + 0x25C);
|
||||
}
|
||||
};
|
||||
|
||||
class INetworkClientService
|
||||
{
|
||||
public:
|
||||
[[nodiscard]] CNetworkGameClient* GetNetworkGameClient()
|
||||
{
|
||||
return MEM::CallVFunc<CNetworkGameClient*, 23U>(this);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
// used: MEM::CallVFunc
|
||||
#include "../../utilities/memory.h"
|
||||
|
||||
class CPVS
|
||||
{
|
||||
public:
|
||||
void Set(bool bState)
|
||||
{
|
||||
MEM::CallVFunc<void*, 7U>(this, bState);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
// used: callvfunc
|
||||
#include "../../utilities/memory.h"
|
||||
|
||||
struct ResourceBinding_t;
|
||||
|
||||
class IResourceSystem
|
||||
{
|
||||
public:
|
||||
void* QueryInterface(const char* szInterfaceName)
|
||||
{
|
||||
return MEM::CallVFunc<void*, 2U>(this, szInterfaceName);
|
||||
}
|
||||
};
|
||||
|
||||
class CResourceHandleUtils
|
||||
{
|
||||
public:
|
||||
void DeleteResource(const ResourceBinding_t* pBinding)
|
||||
{
|
||||
MEM::CallVFunc<void, 2U>(this, pBinding);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,208 @@
|
||||
#pragma once
|
||||
|
||||
// used: utlthash
|
||||
#include "../datatypes/utlthash.h"
|
||||
// used: utlvector
|
||||
#include "../datatypes/utlvector.h"
|
||||
// used: callvfunc
|
||||
#include "../../utilities/memory.h"
|
||||
|
||||
#define SCHEMASYSTEM_TYPE_SCOPES_OFFSET 0x188
|
||||
#define SCHEMASYSTEMTYPESCOPE_OFF1 0x3F8
|
||||
#define SCHEMASYSTEMTYPESCOPE_OFF2 0x8
|
||||
|
||||
using SchemaString_t = const char*;
|
||||
struct SchemaMetadataEntryData_t;
|
||||
|
||||
class CSchemaSystemTypeScope;
|
||||
class CSchemaType;
|
||||
|
||||
struct CSchemaClassBinding
|
||||
{
|
||||
CSchemaClassBinding* pParent;
|
||||
const char* szBinaryName; // ex: C_World
|
||||
const char* szModuleName; // ex: libclient.so
|
||||
const char* szClassName; // ex: client
|
||||
void* pClassInfoOldSynthesized;
|
||||
void* pClassInfo;
|
||||
void* pThisModuleBindingPointer;
|
||||
CSchemaType* pSchemaType;
|
||||
};
|
||||
|
||||
class CSchemaType
|
||||
{
|
||||
public:
|
||||
bool GetSizes(int* pOutSize, uint8_t* unkPtr)
|
||||
{
|
||||
return MEM::CallVFunc<bool, 3U>(this, pOutSize, unkPtr);
|
||||
}
|
||||
|
||||
public:
|
||||
bool GetSize(int* out_size)
|
||||
{
|
||||
uint8_t smh = 0;
|
||||
return GetSizes(out_size, &smh);
|
||||
}
|
||||
|
||||
public:
|
||||
void* pVtable; // 0x0000
|
||||
const char* szName; // 0x0008
|
||||
|
||||
CSchemaSystemTypeScope* pSystemTypeScope; // 0x0010
|
||||
uint8_t nTypeCategory; // ETypeCategory 0x0018
|
||||
uint8_t nAatomicCategory; // EAtomicCategory 0x0019
|
||||
};
|
||||
|
||||
struct SchemaClassFieldData_t
|
||||
{
|
||||
SchemaString_t szName; // 0x0000
|
||||
CSchemaType* pSchemaType; // 0x0008
|
||||
std::uint32_t nSingleInheritanceOffset; // 0x0010
|
||||
std::int32_t nMetadataSize; // 0x0014
|
||||
SchemaMetadataEntryData_t* pMetaData; // 0x0018
|
||||
};
|
||||
|
||||
struct SchemaClassInfoData_t;
|
||||
|
||||
struct SchemaBaseClassInfoData_t
|
||||
{
|
||||
int32_t nOffset;
|
||||
SchemaClassInfoData_t* pClass;
|
||||
};
|
||||
|
||||
struct SchemaClassInfoData_t
|
||||
{
|
||||
private:
|
||||
void* pVtable; // 0x0000
|
||||
public:
|
||||
const char* szName; // 0x0008
|
||||
char* szDescription; // 0x0010
|
||||
|
||||
int m_nSize; // 0x0018
|
||||
std::int16_t nFieldSize; // 0x001C
|
||||
std::int16_t nStaticSize; // 0x001E
|
||||
std::int16_t nMetadataSize; // 0x0020
|
||||
|
||||
std::uint8_t nAlignOf; // 0x0022
|
||||
std::uint8_t nBaseClassesCount; // 0x0023
|
||||
char pad2[0x4]; // 0x0024
|
||||
SchemaClassFieldData_t* pFields; // 0x0028
|
||||
char pad3[0x8]; // 0x0030
|
||||
SchemaBaseClassInfoData_t* pBaseClasses; // 0x0038
|
||||
char pad4[0x28]; // 0x0040
|
||||
|
||||
//public:
|
||||
//SchemaClassFieldData_t* pFields; // 0x0028
|
||||
|
||||
bool InheritsFrom(SchemaClassInfoData_t* pClassInfo)
|
||||
{
|
||||
if (pClassInfo == this && pClassInfo != nullptr)
|
||||
return true;
|
||||
else if (pBaseClasses == nullptr || pClassInfo == nullptr)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < nBaseClassesCount; i++)
|
||||
{
|
||||
auto& baseClass = pBaseClasses[i];
|
||||
if (baseClass.pClass->InheritsFrom(pClassInfo))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
struct SchemaEnumeratorInfoData_t
|
||||
{
|
||||
SchemaString_t szName;
|
||||
|
||||
union
|
||||
{
|
||||
unsigned char value_char;
|
||||
unsigned short value_short;
|
||||
unsigned int value_int;
|
||||
unsigned long long value;
|
||||
};
|
||||
|
||||
MEM_PAD(0x10); // 0x0010
|
||||
};
|
||||
|
||||
class CSchemaEnumInfo
|
||||
{
|
||||
public:
|
||||
SchemaEnumeratorInfoData_t enumInfoData;
|
||||
};
|
||||
|
||||
class CSchemaEnumBinding
|
||||
{
|
||||
public:
|
||||
virtual const char* GetBindingName() = 0;
|
||||
virtual CSchemaClassBinding* AsClassBinding() = 0;
|
||||
virtual CSchemaEnumBinding* AsEnumBinding() = 0;
|
||||
virtual const char* GetBinaryName() = 0;
|
||||
virtual const char* GetProjectName() = 0;
|
||||
|
||||
public:
|
||||
char* szBindingName_; // 0x0008
|
||||
char* szDllName_; // 0x0010
|
||||
std::int8_t nAlign_; // 0x0018
|
||||
MEM_PAD(0x3); // 0x0019
|
||||
std::int16_t nSize_; // 0x001C
|
||||
std::int16_t nFlags_; // 0x001E
|
||||
SchemaEnumeratorInfoData_t* pEnumInfo_;
|
||||
MEM_PAD(0x8); // 0x0028
|
||||
CSchemaSystemTypeScope* pTypeScope_; // 0x0030
|
||||
MEM_PAD(0x8); // 0x0038
|
||||
std::int32_t unk1_; // 0x0040
|
||||
};
|
||||
|
||||
class CSchemaSystemTypeScope
|
||||
{
|
||||
public:
|
||||
void FindDeclaredClass(SchemaClassInfoData_t** pReturnClass, const char* szClassName)
|
||||
{
|
||||
return MEM::CallVFunc<void, 2U>(this, pReturnClass, szClassName);
|
||||
}
|
||||
|
||||
CSchemaType* FindSchemaTypeByName(const char* szName, std::uintptr_t* pSchema)
|
||||
{
|
||||
return MEM::CallVFunc<CSchemaType*, 4U>(this, szName, pSchema);
|
||||
}
|
||||
|
||||
CSchemaType* FindTypeDeclaredClass(const char* szName)
|
||||
{
|
||||
return MEM::CallVFunc<CSchemaType*, 5U>(this, szName);
|
||||
}
|
||||
|
||||
CSchemaType* FindTypeDeclaredEnum(const char* szName)
|
||||
{
|
||||
return MEM::CallVFunc<CSchemaType*, 6U>(this, szName);
|
||||
}
|
||||
|
||||
CSchemaClassBinding* FindRawClassBinding(const char* szName)
|
||||
{
|
||||
return MEM::CallVFunc<CSchemaClassBinding*, 7U>(this, szName);
|
||||
}
|
||||
|
||||
void* pVtable; // 0x0000
|
||||
char szName[256U]; // 0x0008
|
||||
MEM_PAD(SCHEMASYSTEMTYPESCOPE_OFF1); // 0x0108
|
||||
CUtlTSHash<CSchemaClassBinding*, 256, unsigned int> hashClasses; // 0x0588
|
||||
MEM_PAD(SCHEMASYSTEMTYPESCOPE_OFF2); // 0x05C8
|
||||
CUtlTSHash<CSchemaEnumBinding*, 256, unsigned int> hashEnumes; // 0x2DD0
|
||||
};
|
||||
|
||||
class ISchemaSystem
|
||||
{
|
||||
public:
|
||||
CSchemaSystemTypeScope* FindTypeScopeForModule(const char* m_module_name)
|
||||
{
|
||||
return MEM::CallVFunc<CSchemaSystemTypeScope*, 13U>(this, m_module_name, nullptr);
|
||||
}
|
||||
|
||||
private:
|
||||
MEM_PAD(SCHEMASYSTEM_TYPE_SCOPES_OFFSET); // 0x0000
|
||||
public:
|
||||
// table of type scopes
|
||||
CUtlVector<CSchemaSystemTypeScope*> vecTypeScopes; // SCHEMASYSTEM_TYPE_SCOPES_OFFSET
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
// used: call virtual function
|
||||
#include "../../utilities/memory.h"
|
||||
|
||||
// forward declarations
|
||||
struct IDXGISwapChain;
|
||||
|
||||
class ISwapChainDx11
|
||||
{
|
||||
MEM_PAD(0x170);
|
||||
IDXGISwapChain* pDXGISwapChain;
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "../datatypes/qangle.h"
|
||||
#include "../datatypes/matrix.h"
|
||||
|
||||
class IViewRender
|
||||
{
|
||||
public:
|
||||
Vector_t vecOrigin; // 0x0000
|
||||
QAngle_t vecAngles; // 0x000C
|
||||
float flFov; // 0x0018
|
||||
char pad_0x001C[0x14]; // 0x001C
|
||||
ViewMatrix_t matUNK1; // 0x0030
|
||||
char pad_0x0070[0x30]; // 0x0070
|
||||
ViewMatrix_t matUNK2; // 0x00A0
|
||||
char pad_0x00E0[0xC8]; // 0x00E0
|
||||
ViewMatrix_t matUNK3; // 0x01A8
|
||||
char pad_0x01E8[0x28]; // 0x01E8
|
||||
};
|
||||
@@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
// used: schema field
|
||||
#include "../core/schema.h"
|
||||
// used: rop
|
||||
#include "../utilities/memory.h"
|
||||
|
||||
using CFiringModeFloat = std::float_t[2];
|
||||
using CSkillFloat = std::float_t[4];
|
||||
|
||||
class CBasePlayerVData
|
||||
{
|
||||
public:
|
||||
CS_CLASS_NO_INITIALIZER(CBasePlayerVData);
|
||||
|
||||
//CResourceNameTyped< CWeakHandle< InfoForResourceTypeCModel > > m_sModelName = 0x28
|
||||
//CSkillFloat m_flHeadDamageMultiplier = 0x108
|
||||
//CSkillFloat m_flChestDamageMultiplier = 0x118
|
||||
//CSkillFloat m_flStomachDamageMultiplier = 0x128
|
||||
//CSkillFloat m_flArmDamageMultiplier = 0x138
|
||||
//CSkillFloat m_flLegDamageMultiplier = 0x148
|
||||
//float32 m_flHoldBreathTime = 0x158
|
||||
//float32 m_flDrowningDamageInterval = 0x15C
|
||||
//int32 m_nDrowningDamageInitial = 0x160
|
||||
//int32 m_nDrowningDamageMax = 0x164
|
||||
//int32 m_nWaterSpeed = 0x168
|
||||
//float32 m_flUseRange = 0x16C
|
||||
//float32 m_flUseAngleTolerance = 0x170
|
||||
//float32 m_flCrouchTime = 0x174
|
||||
};
|
||||
|
||||
class CBasePlayerWeaponVData
|
||||
{
|
||||
public:
|
||||
CS_CLASS_NO_INITIALIZER(CBasePlayerWeaponVData);
|
||||
|
||||
SCHEMA_ADD_FIELD(bool, IsFullAuto, "CBasePlayerWeaponVData->m_bIsFullAuto");
|
||||
SCHEMA_ADD_FIELD(std::int32_t, GetMaxClip1, "CBasePlayerWeaponVData->m_iMaxClip1");
|
||||
};
|
||||
|
||||
class CCSWeaponBaseVData : public CBasePlayerWeaponVData
|
||||
{
|
||||
public:
|
||||
CS_CLASS_NO_INITIALIZER(CCSWeaponBaseVData);
|
||||
|
||||
SCHEMA_ADD_FIELD(std::int32_t, GetWeaponType, "CCSWeaponBaseVData->m_WeaponType");
|
||||
SCHEMA_ADD_FIELD(float, GetRange, "CCSWeaponBaseVData->m_flRange");
|
||||
};
|
||||
Reference in New Issue
Block a user