#pragma once #include "head.h" class CEntityInstance; typedef void(__fastcall* StateChanged_t)(void* networkTransmitComponent, CEntityInstance* ent, uint64_t offset, int a4, int a5); typedef void(__fastcall* NetworkStateChanged_t)(uintptr_t chainEntity, uintptr_t offset, uintptr_t a3); namespace Offset { extern StateChanged_t FnStateChanged; extern NetworkStateChanged_t FnNetworkStateChanged; } // namespace Offset struct SchemaKey { int16_t offset; bool networked; }; class Z_CBaseEntity; extern auto SetStateChanged(Z_CBaseEntity* pEntity, int offset) -> void; #define MAX_ENTITIES_IN_LIST 512 #define MAX_ENTITY_LISTS 64 #define MAX_TOTAL_ENTITIES MAX_ENTITIES_IN_LIST* MAX_ENTITY_LISTS #define INVALID_EHANDLE_INDEX 0xFFFFFFFF #define ENT_ENTRY_MASK 0x7FFF #define DECLARE_SCHEMA_CLASS_BASE(className, isStruct) \ static constexpr const char* ThisClass = #className; \ static constexpr bool OffsetIsStruct = isStruct; #define DECLARE_CLASS(className) DECLARE_SCHEMA_CLASS_BASE(className, false) // Use this for classes that can be wholly included within other classes (like // CCollisionProperty within CBaseModelEntity) #define DECLARE_SCHEMA_CLASS_INLINE(className) \ DECLARE_SCHEMA_CLASS_BASE(className, true) #define SCHEMA_FIELD_OFFSET(type, varName, extra_offset) \ std::add_lvalue_reference_t varName() { \ static constexpr auto datatable_hash = hash_32_fnv1a_const(ThisClass); \ static constexpr auto prop_hash = hash_32_fnv1a_const(#varName); \ \ static const auto m_key = \ schema::GetOffset(ThisClass, datatable_hash, #varName, prop_hash); \ \ return *reinterpret_cast>( \ (uintptr_t)(this) + m_key.offset + extra_offset); \ } \ void varName(type val) { \ static constexpr auto datatable_hash = hash_32_fnv1a_const(ThisClass); \ static constexpr auto prop_hash = hash_32_fnv1a_const(#varName); \ \ static const auto m_key = \ schema::GetOffset(ThisClass, datatable_hash, #varName, prop_hash); \ \ static const auto m_chain = schema::FindChainOffset(ThisClass); \ \ if (m_chain != 0 && m_key.networked) { \ LOG("Found chain offset %d for %s::%s\n", m_chain, ThisClass, \ #varName); \ Offset::FnNetworkStateChanged((uintptr_t)(this) + m_chain, \ m_key.offset + extra_offset, \ 0xFFFFFFFF); \ } else if (m_key.networked) { \ /* WIP: Works fine for most props, but inlined classes in the \ middle of a class will need to have their this pointer \ corrected by the offset .*/ \ LOG("Attempting to call SetStateChanged on on %s::%s\n", \ ThisClass, #varName); \ if (!OffsetIsStruct) \ SetStateChanged((Z_CBaseEntity*)this, \ m_key.offset + extra_offset); \ else \ CALL_VIRTUAL(void, 1, this, m_key.offset + extra_offset, \ 0xFFFFFFFF, 0xFFFF); \ } \ *reinterpret_cast>( \ (uintptr_t)(this) + m_key.offset + extra_offset) = val; \ } #define SCHEMA_FIELD_OFFSET_EX(type, datatableName, varName, extra_offset) \ std::add_lvalue_reference_t varName() { \ static constexpr auto datatable_hash = \ hash_32_fnv1a_const(datatableName); \ static constexpr auto prop_hash = hash_32_fnv1a_const(#varName); \ \ static const auto m_key = \ schema::GetOffset(datatableName, datatable_hash, #varName, prop_hash); \ \ return *reinterpret_cast>( \ (uintptr_t)(this) + m_key.offset + extra_offset); \ } \ void varName(type val) { \ static constexpr auto datatable_hash = \ hash_32_fnv1a_const(datatableName); \ static constexpr auto prop_hash = hash_32_fnv1a_const(#varName); \ \ static const auto m_key = \ schema::GetOffset(datatableName, datatable_hash, #varName, prop_hash); \ \ static const auto m_chain = schema::FindChainOffset(ThisClass); \ \ if (m_chain != 0 && m_key.networked) { \ LOG("Found chain offset %d for %s::%s\n", m_chain, ThisClass, \ #varName); \ Offset::FnNetworkStateChanged((uintptr_t)(this) + m_chain, \ m_key.offset + extra_offset, \ 0xFFFFFFFF); \ } else if (m_key.networked) { \ /* WIP: Works fine for most props, but inlined classes in the \ middle of a class will need to have their this pointer \ corrected by the offset .*/ \ LOG("Attempting to call SetStateChanged on on %s::%s\n", \ datatableName, #varName); \ if (!OffsetIsStruct) \ SetStateChanged((Z_CBaseEntity*)this, \ m_key.offset + extra_offset); \ else \ CALL_VIRTUAL(void, 1, this, m_key.offset + extra_offset, \ 0xFFFFFFFF, 0xFFFF); \ } \ *reinterpret_cast>( \ (uintptr_t)(this) + m_key.offset + extra_offset) = val; \ } #define SCHEMA_FIELD(type, varName) SCHEMA_FIELD_OFFSET(type, varName, 0) #define SCHEMA_FIELD_EX(type, dataTableName, varName) \ SCHEMA_FIELD_OFFSET_EX(type, dataTableName, varName, 0) #define PSCHEMA_FIELD_OFFSET(type, varName, extra_offset) \ auto varName() { \ static constexpr auto datatable_hash = hash_32_fnv1a_const(ThisClass); \ static constexpr auto prop_hash = hash_32_fnv1a_const(#varName); \ \ static const auto m_key = \ schema::GetOffset(ThisClass, datatable_hash, #varName, prop_hash); \ \ return reinterpret_cast>( \ (uintptr_t)(this) + m_key.offset + extra_offset); \ } #define PSCHEMA_FIELD(type, varName) PSCHEMA_FIELD_OFFSET(type, varName, 0) namespace schema { int16_t FindChainOffset(const char* className); SchemaKey GetOffset(const char* className, uint32_t classKey, const char* memberName, uint32_t memberKey); } // namespace schema template class CNetworkUtlVectorBase { public: auto begin() const { return m_data; } auto end() const { return m_data + m_size; } int m_size; char pad0[0x4]; // no idea T* m_data; }; struct CSchemaNetworkValue { union { const char* m_sz_value; int m_n_value; float m_f_value; std::uintptr_t m_p_value; }; }; struct SchemaMetadataEntryData_t { const char* m_name; CSchemaNetworkValue* m_value; }; struct SchemaClassFieldData_t { const char* m_name; char pad0[0x8]; short m_offset; int32_t m_metadata_size; SchemaMetadataEntryData_t* m_metadata; }; class SchemaClassInfoData_t; struct SchemaBaseClassInfoData_t { unsigned int m_offset; SchemaClassInfoData_t* m_class; }; class SchemaClassInfoData_t { public: auto GetName() { return m_name; } auto GetFieldsSize() { return m_align; } auto GetFields() { return m_fields; } auto GetParent() -> SchemaClassInfoData_t* { if (!m_schema_parent) return nullptr; return m_schema_parent->m_class; } private: char pad_0x0000[0x8]; // 0x0000 const char* m_name; // 0x0008 char* m_module; // 0x0010 int m_size; // 0x0018 std::int16_t m_align; // 0x001C std::int16_t m_static_size; // 0x001E std::int16_t m_metadata_size; // 0x0020 std::int16_t m_i_unk1; // 0x0022 std::int16_t m_i_unk2; // 0x0024 std::int16_t m_i_unk3; // 0x0026 SchemaClassFieldData_t* m_fields; // 0x0028 char pad_0x0030[0x8]; // 0x0030 SchemaBaseClassInfoData_t* m_schema_parent; // 0x0038 char pad_0x0038[0x10]; // 0x0038 }; class CSchemaSystemTypeScope { public: auto FindDeclaredClass(const char* pClass) -> SchemaClassInfoData_t*; }; class CSchemaSystem { public: auto FindTypeScopeForModule(const char* module) -> CSchemaSystemTypeScope*; }; template class CUtlVector_NativeSdk { public: auto begin() const { return m_data; } auto end() const { return m_data + m_size; } bool Exists(T val) const { for (const auto& it : *this) if (it == val) return true; return false; } bool Empty() const { return m_size == 0; } int m_size; char pad0[0x4]; // no idea T* m_data; char pad1[0x8]; // no idea }; class CBaseEntity; class CEntityIdentity { public: CBaseEntity* entity; // 0 void* dunno; // 8 int64_t unk0; // 12 int64_t unk1; // 16 const char* m_name; const char* m_designerName; void* unk2; void* unk3; void* unk4; void* unk5; CEntityIdentity* prevValid; CEntityIdentity* nextValid; void* unkptr; void* unkptr2; void* unkptr3; }; class CEntityIdentities { public: CEntityIdentity m_pIdentities[MAX_ENTITIES_IN_LIST]; }; class EntityIdentityList { public: CEntityIdentities* m_pIdentityList; }; class CGameEntitySystem { public: virtual void n_0(); void* unk; CEntityIdentities* m_pEntityList[MAX_ENTITY_LISTS]; CBaseEntity* GetBaseEntity(int index) { if (index <= -1 || index >= MAX_TOTAL_ENTITIES) return nullptr; int listToUse = (index / MAX_ENTITIES_IN_LIST); if (!m_pEntityList[listToUse]) return nullptr; if (m_pEntityList[listToUse] ->m_pIdentities[index % MAX_ENTITIES_IN_LIST] .entity) return m_pEntityList[listToUse] ->m_pIdentities[index % MAX_ENTITIES_IN_LIST] .entity; else return nullptr; } static CGameEntitySystem* GetInstance(); }; struct VPhysicsCollisionAttribute_t { DECLARE_CLASS(VPhysicsCollisionAttribute_t) SCHEMA_FIELD(uint8_t, m_nCollisionGroup) }; class CCollisionProperty { public: DECLARE_CLASS(CCollisionProperty) SCHEMA_FIELD(VPhysicsCollisionAttribute_t, m_collisionAttribute) // SCHEMA_FIELD(SolidType_t, m_nSolidType) SCHEMA_FIELD(uint8_t, m_usSolidFlags) SCHEMA_FIELD(uint8_t, m_CollisionGroup) }; class CCSPlayerController_InGameMoneyServices { public: DECLARE_CLASS(CCSPlayerController_InGameMoneyServices); SCHEMA_FIELD(int, m_iAccount) }; class CHandle { CBaseEntity* GetBaseEntity() const; public: bool operator==(CHandle rhs) const { return m_Index == rhs.m_Index; } bool IsValid() const { return m_Index != INVALID_EHANDLE_INDEX; } int GetEntryIndex() const { return m_Index & ENT_ENTRY_MASK; } template T* Get() const { return reinterpret_cast(GetBaseEntity()); } uint32_t m_Index; }; class CEntityInstance { public: DECLARE_CLASS(CEntityInstance); auto Schema_DynamicBinding() { SchemaClassInfoData_t* rv = nullptr; CALL_VIRTUAL(void, 34, this, &rv); return rv; } auto GetRefEHandle() { char* pIdentity = (char*)m_pEntity(); auto v3 = *(uint32_t*)(pIdentity + 16); auto v4 = ENT_ENTRY_MASK; auto v5 = ((v3 >> 15) - (*(uint32_t*)(pIdentity + 48) & 1)) << 15; if (v3 != -1) { v4 = *(uint32_t*)(pIdentity + 16) & ENT_ENTRY_MASK; } return CHandle(v4 | v5); } SCHEMA_FIELD(CEntityIdentity*, m_pEntity); SCHEMA_FIELD(const char*, m_designerName); }; class CGlowProperty { public: DECLARE_SCHEMA_CLASS_INLINE(CGlowProperty) SCHEMA_FIELD(Vector, m_fGlowColor) SCHEMA_FIELD(int, m_iGlowType) SCHEMA_FIELD(int, m_nGlowRange) SCHEMA_FIELD(Color, m_glowColorOverride) SCHEMA_FIELD(bool, m_bFlashing) SCHEMA_FIELD(bool, m_bGlowing) }; class CBaseEntity : public CEntityInstance { public: DECLARE_CLASS(CBaseEntity); SCHEMA_FIELD(int, m_iHealth) SCHEMA_FIELD(int, m_iTeamNum) // SCHEMA_FIELD(Vector, m_vecBaseVelocity) SCHEMA_FIELD(CCollisionProperty*, m_pCollision) SCHEMA_FIELD(Vector, m_vecBaseVelocity) //SCHEMA_FIELD_EX(CGlowProperty, "CBaseModelEntity", m_Glow); auto IsBasePlayerController() -> bool; auto SpawnClientEntity() -> void; }; class CBaseModelEntity : public CBaseEntity { public: DECLARE_CLASS(CBaseModelEntity); SCHEMA_FIELD(CCollisionProperty, m_Collision) SCHEMA_FIELD(CGlowProperty, m_Glow) }; class CBasePlayerController : public CBaseEntity { public: DECLARE_CLASS(CBasePlayerController); SCHEMA_FIELD(uint64_t, m_steamID) SCHEMA_FIELD(CHandle, m_hPawn) SCHEMA_FIELD(char, m_iszPlayerName) SCHEMA_FIELD(CUtlString, m_szNetworkIDString) }; class CCSPlayerController : public CBasePlayerController { public: DECLARE_CLASS(CCSPlayerController) SCHEMA_FIELD(uint32_t, m_iPawnHealth) SCHEMA_FIELD(bool, m_bPawnIsAlive) SCHEMA_FIELD(const char*, m_szClanName) SCHEMA_FIELD(CCSPlayerController_InGameMoneyServices*, m_pInGameMoneyServices) }; class CEconItemDefinition { public: bool IsWeapon(); bool IsKnife(bool excludeDefault); bool IsGlove(bool excludeDefault); auto GetModelName() { return *reinterpret_cast((uintptr_t)(this) + 0xD8); } auto GetStickersSupportedCount() { return *reinterpret_cast((uintptr_t)(this) + 0x100); } auto GetSimpleWeaponName() { return *reinterpret_cast((uintptr_t)(this) + 0x210); } auto GetLoadoutSlot() { return *reinterpret_cast((uintptr_t)(this) + 0x2E8); } char pad0[0x8]; // vtable void* m_pKVItem; uint16_t m_nDefIndex; CUtlVector_NativeSdk m_nAssociatedItemsDefIndexes; bool m_bEnabled; const char* m_szPrefab; uint8_t m_unMinItemLevel; uint8_t m_unMaxItemLevel; uint8_t m_nItemRarity; uint8_t m_nItemQuality; uint8_t m_nForcedItemQuality; uint8_t m_nDefaultDropItemQuality; uint8_t m_nDefaultDropQuantity; CUtlVector_NativeSdk m_vecStaticAttributes; uint8_t m_nPopularitySeed; void* m_pPortraitsKV; const char* m_pszItemBaseName; bool m_bProperName; const char* m_pszItemTypeName; uint32_t m_unItemTypeID; const char* m_pszItemDesc; }; class CEconItemView { public: DECLARE_CLASS(CEconItemView); auto GetCustomPaintKitIndex() { return CALL_VIRTUAL(int, 2, this); } auto GetStaticData() { return CALL_VIRTUAL(CEconItemDefinition*, 13, this); } SCHEMA_FIELD(uint16_t, m_iItemDefinitionIndex) SCHEMA_FIELD(bool, m_bInitialized) }; class CAttributeContainer { public: DECLARE_CLASS(CAttributeContainer); PSCHEMA_FIELD(CEconItemView, m_Item); }; class CEconEntity { public: DECLARE_CLASS(CEconEntity); PSCHEMA_FIELD(CAttributeContainer, m_AttributeManager); }; class CCSWeaponBase : public CEconEntity { public: DECLARE_CLASS(CCSWeaponBase) }; class CBasePlayerWeapon : public CEconEntity { public: DECLARE_CLASS(CBasePlayerWeapon); SCHEMA_FIELD(int, m_iClip1); SCHEMA_FIELD(int, m_iClip2); SCHEMA_FIELD(int, m_pReserveAmmo); }; class CPlayer_WeaponServices { public: DECLARE_CLASS(CPlayer_WeaponServices) SCHEMA_FIELD(CHandle, m_hActiveWeapon); SCHEMA_FIELD(CNetworkUtlVectorBase, m_hMyWeapons); SCHEMA_FIELD(uint16_t, m_iAmmo); auto RemoveWeapon(CBasePlayerWeapon* weapon) { return CALL_VIRTUAL(void, 20, this, weapon, nullptr, nullptr); } }; class CBasePlayer { public: auto ForceRespawn() -> void; }; class CPlayer_MovementServices { public: DECLARE_CLASS(CPlayer_MovementServices); }; class CBasePlayerPawn : public CBaseEntity { public: DECLARE_CLASS(CBasePlayerPawn); SCHEMA_FIELD(CPlayer_MovementServices*, m_pMovementServices) SCHEMA_FIELD(CPlayer_WeaponServices*, m_pWeaponServices) SCHEMA_FIELD(uint8_t**, m_pItemServices) // m_hController SCHEMA_FIELD(CBasePlayerController*, m_hController) }; // Size: 0x1568 class CCSPlayerPawnBase : public CBasePlayerPawn { public: DECLARE_CLASS(CCSPlayerPawnBase); SCHEMA_FIELD(bool, m_bRespawning) SCHEMA_FIELD(int, m_ArmorValue) }; class CCSPlayerPawn : public CCSPlayerPawnBase { public: DECLARE_CLASS(CCSPlayerPawn); SCHEMA_FIELD(const char*, m_szLastPlaceName) auto GetPlayerController() -> CCSPlayerController*; auto ForceRespawnPlayer() { return CALL_VIRTUAL(void, 324, this); } }; class CGameEntitySystem; class CGameResourceService { public: CGameEntitySystem* GetGameEntitySystem() { return *reinterpret_cast((uintptr_t)(this) + 0x58); } }; class CLocalize { public: auto FindSafe(const char* tokenName) -> const char*; }; class Z_CBaseEntity : public CBaseEntity { public: DECLARE_CLASS(CBaseEntity) SCHEMA_FIELD(CBitVec<64>, m_isSteadyState) SCHEMA_FIELD(float, m_lastNetworkChange) PSCHEMA_FIELD(void*, m_NetworkTransmitComponent) SCHEMA_FIELD(int, m_iHealth) SCHEMA_FIELD(int, m_iTeamNum) SCHEMA_FIELD(Vector, m_vecBaseVelocity) SCHEMA_FIELD(CCollisionProperty*, m_pCollision) }; class CCSGameRules { public: DECLARE_CLASS(CCSGameRules) SCHEMA_FIELD(bool, m_bForceTeamChangeSilent) auto PlayerRespawn(CCSPlayerPawn* PlayerPawn) { return CALL_VIRTUAL(void, 110, this, PlayerPawn); } };