diff --git a/.vscode/settings.json b/.vscode/settings.json index 601b48d..ad52f84 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -87,6 +87,7 @@ "*.rh": "cpp", "random": "cpp", "hash_map": "cpp", - "hash_set": "cpp" + "hash_set": "cpp", + "filesystem": "cpp" } } diff --git a/csgo2/csgo2.vcxproj b/csgo2/csgo2.vcxproj index 14f57d5..4de1031 100644 --- a/csgo2/csgo2.vcxproj +++ b/csgo2/csgo2.vcxproj @@ -230,6 +230,7 @@ + @@ -297,6 +298,7 @@ + diff --git a/csgo2/csgo2.vcxproj.filters b/csgo2/csgo2.vcxproj.filters index 907a65b..d4b9b37 100644 --- a/csgo2/csgo2.vcxproj.filters +++ b/csgo2/csgo2.vcxproj.filters @@ -76,6 +76,12 @@ {d58fcaf6-b1d7-484d-9ec4-d6b67ff46cf5} + + {ccc753a5-6730-455d-b12b-9fa7e9a4cf03} + + + {f26913ae-881a-43da-a215-8c0c7a9173cd} + @@ -318,6 +324,9 @@ 头文件\native_sdk + + 头文件\game_time_system + @@ -491,6 +500,9 @@ 源文件\script_engine + + 源文件\game_time_system + diff --git a/csgo2/events.cpp b/csgo2/events.cpp index 8990846..307a817 100644 --- a/csgo2/events.cpp +++ b/csgo2/events.cpp @@ -28,7 +28,8 @@ auto OnPlayerDeathEvent(IGameEvent* event) -> void { } const auto victimIndex = victim->GetRefEHandle().GetEntryIndex(); const auto attackerIndex = attacker->GetRefEHandle().GetEntryIndex(); - ScriptCallBacks::luaCall_onPlayerDeath(victimIndex, attackerIndex, isHeadShot); + ScriptCallBacks::luaCall_onPlayerDeath(victimIndex, attackerIndex, + isHeadShot); // printf("player[%p] %s kill[%p] %llu\n", attacker, // &attacker->m_iszPlayerName(), victim, &victim->m_steamID()); } @@ -38,10 +39,8 @@ auto OnPlayerChat(CCSPlayerController* player, std::string message) -> bool { if (procesChatSuccess == false) { return false; } - if (chatCtx.at(0) == '/' || chatCtx.at(0) == '!') { - return true; - } - return false; + return ScriptCallBacks::luaCall_onPlayerSpeak( + player->GetRefEHandle().GetEntryIndex(), chatType, chatCtx); } auto OnPlayerConnect(int slot, const char* pszName, uint64_t xuid, const char* pszNetworkID, const char* pszAddress, diff --git a/csgo2/global.cpp b/csgo2/global.cpp index 0312374..1c49f54 100644 --- a/csgo2/global.cpp +++ b/csgo2/global.cpp @@ -2,4 +2,9 @@ namespace global { bool Exit; int MaxPlayers; + CGameEntitySystem* EntitySystem; + bool HasTicked; + CGlobalVars* GlobalVars; + float m_flUniversalTime; + float m_flLastTickedTime; } \ No newline at end of file diff --git a/csgo2/global.h b/csgo2/global.h index b6797cd..41ccf18 100644 --- a/csgo2/global.h +++ b/csgo2/global.h @@ -1,6 +1,13 @@ #pragma once #include "head.h" +class CGlobalVars; +class CGameEntitySystem; namespace global { extern bool Exit; extern int MaxPlayers; + extern CGameEntitySystem* EntitySystem; + extern bool HasTicked; + extern CGlobalVars* GlobalVars; + extern float m_flUniversalTime; + extern float m_flLastTickedTime; } \ No newline at end of file diff --git a/csgo2/head.h b/csgo2/head.h index 474ad4f..9d4a975 100644 --- a/csgo2/head.h +++ b/csgo2/head.h @@ -79,3 +79,4 @@ static void DebugPrintA(const char* format, ...) { #include "script_engine.h" #include "script_apis.h" #include "script_callbacks.h" +#include "timer.h" diff --git a/csgo2/hooks.cpp b/csgo2/hooks.cpp index 8cddb34..6a1d0b5 100644 --- a/csgo2/hooks.cpp +++ b/csgo2/hooks.cpp @@ -1,13 +1,58 @@ #include "hooks.h" - +extern auto GetGameGlobals() -> CGlobalVars*; FireEventServerSide_t original_FireEventServerSide = NULL; OnClientConnect_t original_OnClientConnected = NULL; OnClientDisconnect_t original_OnClientDisconnect = NULL; Host_Say_t original_Host_Say = NULL; - +StartupServer_t origin_StartServer = NULL; +GameFrame_t origin_GameFrame = NULL; namespace hooks { // "player_connect" VMTHook* VMT_IServerGameClient; +VMTHook* VMT_INetworkServerServiceInteFace; +VMTHook* VMT_ISource2ServerInterFace; + +void __fastcall hook_GameFrame(void* rcx, bool simulating, bool bFirstTick, + bool bLastTick) { + /** + * simulating: + * *********** + * true | game is ticking + * false | game is not ticking + */ + if (simulating && global::HasTicked) { + global::m_flUniversalTime += + global::GlobalVars->curtime - global::m_flLastTickedTime; + } else { + global::m_flUniversalTime += global::GlobalVars->interval_per_tick; + } + + global::m_flLastTickedTime = global::GlobalVars->curtime; + global::HasTicked = true; + + if (global::EntitySystem == nullptr) { + global::EntitySystem = Offset::InterFaces::GameResourceServiceServer + ->GetGameEntitySystem(); + } + + GameTimer::ExcuteTimers(); + return origin_GameFrame(rcx, simulating, bFirstTick, bLastTick); +} +void __fastcall hook_StartServer(void* rcx, + const GameSessionConfiguration_t& config, + ISource2WorldSession* pWorldSession, + const char* a1) { + if (global::HasTicked) { + GameTimer::CleanUpTimers(); + } + + global::HasTicked = false; + global::GlobalVars = GetGameGlobals(); + global::EntitySystem = + Offset::InterFaces::GameResourceServiceServer->GetGameEntitySystem(); + + return origin_StartServer(rcx, config, pWorldSession, a1); +} void __fastcall hook_ClientDisconnect(void* rcx, CPlayerSlot slot, int reason, const char* pszName, uint64_t xuid, const char* pszNetworkID) { @@ -134,11 +179,24 @@ auto initMinHook() -> bool { auto initVmtHook() -> bool { VMT_IServerGameClient = new VMTHook(Memory::read( reinterpret_cast(Offset::InterFaces::IServerGameClient))); + VMT_INetworkServerServiceInteFace = + new VMTHook(Memory::read(reinterpret_cast( + Offset::InterFaces::INetworkServerServiceInteFace))); + VMT_ISource2ServerInterFace = + new VMTHook(Memory::read(reinterpret_cast( + Offset::InterFaces::ISource2ServerInterFace))); + original_OnClientConnected = reinterpret_cast( VMT_IServerGameClient->Hook(11, hook_OnClientConnected)); original_OnClientDisconnect = reinterpret_cast( VMT_IServerGameClient->Hook(16, hook_ClientDisconnect)); - return original_OnClientConnected && original_OnClientDisconnect; + + origin_StartServer = reinterpret_cast( + VMT_INetworkServerServiceInteFace->Hook(27, hook_StartServer)); + origin_GameFrame = reinterpret_cast( + VMT_ISource2ServerInterFace->Hook(19, hook_GameFrame)); + return original_OnClientConnected && original_OnClientDisconnect && + origin_StartServer && origin_GameFrame; } auto init() -> bool { bool isSuccess = initMinHook() && initVmtHook(); diff --git a/csgo2/hooks.h b/csgo2/hooks.h index f41ad1a..d1c0447 100644 --- a/csgo2/hooks.h +++ b/csgo2/hooks.h @@ -5,6 +5,8 @@ typedef bool(__fastcall* FireEventServerSide_t)(CGameEventManager*, IGameEvent*, typedef void(__fastcall* Host_Say_t)(void*, void*, bool, int, const char*); typedef void(__fastcall* OnClientConnect_t)(void*, CPlayerSlot, const char*, uint64_t, const char*, const char*, bool); typedef void(__fastcall* OnClientDisconnect_t)(void*, CPlayerSlot, int, const char*, uint64_t, const char*); +typedef void(__fastcall* StartupServer_t)(void*, const GameSessionConfiguration_t&, ISource2WorldSession*, const char*); +typedef void(__fastcall* GameFrame_t)(void*, bool, bool, bool); extern FireEventServerSide_t original_FireEventServerSide; extern Host_Say_t original_Host_Say; diff --git a/csgo2/native_sdk.cpp b/csgo2/native_sdk.cpp index 180f51b..d4f7414 100644 --- a/csgo2/native_sdk.cpp +++ b/csgo2/native_sdk.cpp @@ -1,10 +1,8 @@ #include "native_sdk.h" -CBaseEntity* CHandle::GetBaseEntity() const -{ +CBaseEntity* CHandle::GetBaseEntity() const { CGameEntitySystem* pEntitySystem = CGameEntitySystem::GetInstance(); - if (!pEntitySystem) - return nullptr; + if (!pEntitySystem) return nullptr; return pEntitySystem->GetBaseEntity(GetEntryIndex()); } @@ -12,29 +10,27 @@ CGameEntitySystem* CGameEntitySystem::GetInstance() { return Offset::InterFaces::GameResourceServiceServer->GetGameEntitySystem(); } -auto CSchemaSystemTypeScope::FindDeclaredClass(const char* pClass) -> SchemaClassInfoData_t* -{ +auto CSchemaSystemTypeScope::FindDeclaredClass(const char* pClass) + -> SchemaClassInfoData_t* { SchemaClassInfoData_t* rv = nullptr; CALL_VIRTUAL(void, 2, this, &rv, pClass); return rv; } -auto CSchemaSystem::FindTypeScopeForModule(const char* module) -> CSchemaSystemTypeScope* -{ +auto CSchemaSystem::FindTypeScopeForModule(const char* module) + -> CSchemaSystemTypeScope* { return CALL_VIRTUAL(CSchemaSystemTypeScope*, 13, this, module, nullptr); } -bool CBaseEntity::IsBasePlayerController() { +auto CBaseEntity::IsBasePlayerController() -> bool { return CALL_VIRTUAL(bool, 144, this); } - -auto CBasePlayer::ForceRespawn() -> void -{ +auto CBaseEntity::SpawnClientEntity() -> void { CALL_VIRTUAL(void, 19, this); } +auto CBasePlayer::ForceRespawn() -> void { return CALL_VIRTUAL(void, 26, this); } -auto CCSPlayerPawn::GetPlayerController() -> CCSPlayerController* -{ +auto CCSPlayerPawn::GetPlayerController() -> CCSPlayerController* { CGameEntitySystem* pEntitySystem = CGameEntitySystem::GetInstance(); if (!pEntitySystem) { return nullptr; @@ -45,7 +41,9 @@ auto CCSPlayerPawn::GetPlayerController() -> CCSPlayerController* if (pEntity->IsBasePlayerController()) { const auto player = reinterpret_cast(pEntity); if (player->m_hPawn().Get() == this) { - //printf("Found Pawn Player: %d %s \n", player->GetRefEHandle().GetEntryIndex(), &player->m_iszPlayerName()); + // printf("Found Pawn Player: %d %s \n", + // player->GetRefEHandle().GetEntryIndex(), + // &player->m_iszPlayerName()); return player; } } @@ -56,11 +54,8 @@ auto CCSPlayerPawn::GetPlayerController() -> CCSPlayerController* using SchemaKeyValueMap_t = CUtlMap; using SchemaTableMap_t = CUtlMap; - -static bool IsFieldNetworked(SchemaClassFieldData_t& field) -{ - for (int i = 0; i < field.m_metadata_size; i++) - { +static bool IsFieldNetworked(SchemaClassFieldData_t& field) { + for (int i = 0; i < field.m_metadata_size; i++) { static auto networkEnabled = hash_32_fnv1a_const("MNetworkEnable"); if (networkEnabled == hash_32_fnv1a_const(field.m_metadata[i].m_name)) return true; @@ -69,18 +64,18 @@ static bool IsFieldNetworked(SchemaClassFieldData_t& field) return false; } -static bool InitSchemaFieldsForClass(SchemaTableMap_t* tableMap, const char* className, uint32_t classKey) -{ - CSchemaSystemTypeScope* pType = Offset::InterFaces::SchemaSystem->FindTypeScopeForModule("server.dll"); +static bool InitSchemaFieldsForClass(SchemaTableMap_t* tableMap, + const char* className, uint32_t classKey) { + CSchemaSystemTypeScope* pType = + Offset::InterFaces::SchemaSystem->FindTypeScopeForModule("server.dll"); - if (!pType) - return false; + if (!pType) return false; SchemaClassInfoData_t* pClassInfo = pType->FindDeclaredClass(className); - if (!pClassInfo) - { - SchemaKeyValueMap_t* map = new SchemaKeyValueMap_t(0, 0, DefLessFunc(uint32_t)); + if (!pClassInfo) { + SchemaKeyValueMap_t* map = + new SchemaKeyValueMap_t(0, 0, DefLessFunc(uint32_t)); tableMap->Insert(classKey, map); LOG("InitSchemaFieldsForClass(): '%s' was not found!\n", className); @@ -90,40 +85,38 @@ static bool InitSchemaFieldsForClass(SchemaTableMap_t* tableMap, const char* cla short fieldsSize = pClassInfo->GetFieldsSize(); SchemaClassFieldData_t* pFields = pClassInfo->GetFields(); - SchemaKeyValueMap_t* keyValueMap = new SchemaKeyValueMap_t(0, 0, DefLessFunc(uint32_t)); + SchemaKeyValueMap_t* keyValueMap = + new SchemaKeyValueMap_t(0, 0, DefLessFunc(uint32_t)); keyValueMap->EnsureCapacity(fieldsSize); tableMap->Insert(classKey, keyValueMap); - for (int i = 0; i < fieldsSize; ++i) - { + for (int i = 0; i < fieldsSize; ++i) { SchemaClassFieldData_t& field = pFields[i]; + // LOG("%s::%s found at -> 0x%X - %llx\n", className, field.m_name, + // field.m_offset, &field); - keyValueMap->Insert(hash_32_fnv1a_const(field.m_name), { field.m_offset, IsFieldNetworked(field) }); + keyValueMap->Insert(hash_32_fnv1a_const(field.m_name), + {field.m_offset, IsFieldNetworked(field)}); } return true; } -int16_t schema::FindChainOffset(const char* className) -{ - - CSchemaSystemTypeScope* pType = Offset::InterFaces::SchemaSystem->FindTypeScopeForModule("server.dll"); +int16_t schema::FindChainOffset(const char* className) { + CSchemaSystemTypeScope* pType = + Offset::InterFaces::SchemaSystem->FindTypeScopeForModule("server.dll"); - if (!pType) - return false; + if (!pType) return false; SchemaClassInfoData_t* pClassInfo = pType->FindDeclaredClass(className); - do - { + do { SchemaClassFieldData_t* pFields = pClassInfo->GetFields(); short fieldsSize = pClassInfo->GetFieldsSize(); - for (int i = 0; i < fieldsSize; ++i) - { + for (int i = 0; i < fieldsSize; ++i) { SchemaClassFieldData_t& field = pFields[i]; - if (strcmp(field.m_name, "__m_pChainEntity") == 0) - { + if (strcmp(field.m_name, "__m_pChainEntity") == 0) { return field.m_offset; } } @@ -132,24 +125,23 @@ int16_t schema::FindChainOffset(const char* className) return 0; } -SchemaKey schema::GetOffset(const char* className, uint32_t classKey, const char* memberName, uint32_t memberKey) -{ +SchemaKey schema::GetOffset(const char* className, uint32_t classKey, + const char* memberName, uint32_t memberKey) { static SchemaTableMap_t schemaTableMap(0, 0, DefLessFunc(uint32_t)); int16_t tableMapIndex = schemaTableMap.Find(classKey); - if (!schemaTableMap.IsValidIndex(tableMapIndex)) - { + if (!schemaTableMap.IsValidIndex(tableMapIndex)) { if (InitSchemaFieldsForClass(&schemaTableMap, className, classKey)) return GetOffset(className, classKey, memberName, memberKey); - return { 0, 0 }; + return {0, 0}; } SchemaKeyValueMap_t* tableMap = schemaTableMap[tableMapIndex]; int16_t memberIndex = tableMap->Find(memberKey); - if (!tableMap->IsValidIndex(memberIndex)) - { - LOG("schema::GetOffset(): '%s' was not found in '%s'!\n", memberName, className); - return { 0, 0 }; + if (!tableMap->IsValidIndex(memberIndex)) { + LOG("schema::GetOffset(): '%s' was not found in '%s'!\n", memberName, + className); + return {0, 0}; } return tableMap->Element(memberIndex); @@ -177,27 +169,26 @@ bool CEconItemDefinition::IsGlove(bool excludeDefault) { return excludeDefault ? !defaultGlove : true; } -auto CLocalize::FindSafe(const char* tokenName) -> const char* -{ +auto CLocalize::FindSafe(const char* tokenName) -> const char* { return CALL_VIRTUAL(const char*, 17, this, tokenName); } -auto GetGameGlobals() -> CGlobalVars* -{ - INetworkGameServer* server = Offset::InterFaces::INetworkServerServiceInteFace->GetIGameServer(); +auto GetGameGlobals() -> CGlobalVars* { + INetworkGameServer* server = + Offset::InterFaces::INetworkServerServiceInteFace->GetIGameServer(); - if (!server) - return nullptr; + if (!server) return nullptr; - return Offset::InterFaces::INetworkServerServiceInteFace->GetIGameServer()->GetGlobals(); + return Offset::InterFaces::INetworkServerServiceInteFace->GetIGameServer() + ->GetGlobals(); } -auto SetStateChanged(Z_CBaseEntity* pEntity, int offset) -> void -{ - Offset::FnStateChanged(pEntity->m_NetworkTransmitComponent(), pEntity, offset, -1, -1); - auto vars = GetGameGlobals(); +auto SetStateChanged(Z_CBaseEntity* pEntity, int offset) -> void { + Offset::FnStateChanged(pEntity->m_NetworkTransmitComponent(), pEntity, + offset, -1, -1); + // auto vars = GetGameGlobals(); + auto vars = global::GlobalVars; - if (vars) - pEntity->m_lastNetworkChange(vars->curtime); + if (vars) pEntity->m_lastNetworkChange(vars->curtime); pEntity->m_isSteadyState(0); }; diff --git a/csgo2/native_sdk.h b/csgo2/native_sdk.h index a7ed4e0..3f495bd 100644 --- a/csgo2/native_sdk.h +++ b/csgo2/native_sdk.h @@ -1,313 +1,287 @@ #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); +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; -} +extern StateChanged_t FnStateChanged; +extern NetworkStateChanged_t FnNetworkStateChanged; +} // namespace Offset struct SchemaKey { - int16_t offset; - bool networked; + 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 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 ENT_ENTRY_MASK 0x7FFF -#define DECLARE_SCHEMA_CLASS_BASE(className, isStruct) \ - static constexpr const char *ThisClass = #className; \ - static constexpr bool OffsetIsStruct = isStruct; +#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) +// 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) + 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(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(type, varName) \ - SCHEMA_FIELD_OFFSET(type, varName, 0) +#define SCHEMA_FIELD(type, varName) SCHEMA_FIELD_OFFSET(type, 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_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) -#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 { +int16_t FindChainOffset(const char* className); +SchemaKey GetOffset(const char* className, uint32_t classKey, + const char* memberName, uint32_t memberKey); +} // namespace schema struct CSchemaNetworkValue { - union { - const char* m_sz_value; - int m_n_value; - float m_f_value; - std::uintptr_t m_p_value; - }; + 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; + 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; +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; +struct SchemaBaseClassInfoData_t { + unsigned int m_offset; + SchemaClassInfoData_t* m_class; }; -class SchemaClassInfoData_t -{ -public: - auto GetName() - { - return m_name; - } +class SchemaClassInfoData_t { + public: + auto GetName() { return m_name; } - auto GetFieldsSize() - { - return m_align; - } + auto GetFieldsSize() { return m_align; } - auto GetFields() - { - return m_fields; - } + auto GetFields() { return m_fields; } - auto GetParent() -> SchemaClassInfoData_t* - { - if (!m_schema_parent) - return nullptr; + auto GetParent() -> SchemaClassInfoData_t* { + if (!m_schema_parent) return nullptr; - return m_schema_parent->m_class; - } + return m_schema_parent->m_class; + } -private: - char pad_0x0000[0x8]; // 0x0000 + private: + char pad_0x0000[0x8]; // 0x0000 - const char* m_name; // 0x0008 - char* m_module; // 0x0010 + const char* m_name; // 0x0008 + char* m_module; // 0x0010 - int m_size; // 0x0018 - std::int16_t m_align; // 0x001C + 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 + 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 + SchemaClassFieldData_t* m_fields; // 0x0028 - char pad_0x0030[0x8]; // 0x0030 - SchemaBaseClassInfoData_t* m_schema_parent; // 0x0038 + char pad_0x0030[0x8]; // 0x0030 + SchemaBaseClassInfoData_t* m_schema_parent; // 0x0038 - char pad_0x0038[0x10]; // 0x0038 + char pad_0x0038[0x10]; // 0x0038 }; -class CSchemaSystemTypeScope -{ -public: - auto FindDeclaredClass(const char* pClass) -> SchemaClassInfoData_t*; +class CSchemaSystemTypeScope { + public: + auto FindDeclaredClass(const char* pClass) -> SchemaClassInfoData_t*; }; -class CSchemaSystem -{ -public: - auto FindTypeScopeForModule(const char* module) -> CSchemaSystemTypeScope*; +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; } + 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; } + 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 + 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* internalName; - const char* entityName; - void* unk2; - void* unk3; - void* unk4; - void* unk5; - CEntityIdentity* prevValid; - CEntityIdentity* nextValid; - void* unkptr; - void* unkptr2; - void* unkptr3; +class CEntityIdentity { + public: + CBaseEntity* entity; // 0 + void* dunno; // 8 + int64_t unk0; // 12 + int64_t unk1; // 16 + const char* internalName; + const char* entityName; + 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 CEntityIdentities { + public: + CEntityIdentity m_pIdentities[MAX_ENTITIES_IN_LIST]; }; -class EntityIdentityList -{ -public: - CEntityIdentities* m_pIdentityList; +class EntityIdentityList { + public: + CEntityIdentities* m_pIdentityList; }; -class CGameEntitySystem -{ -public: - virtual void n_0(); - void* unk; - CEntityIdentities* m_pEntityList[MAX_ENTITY_LISTS]; +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; + 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; + 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; - } + 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(); + static CGameEntitySystem* GetInstance(); }; -struct VPhysicsCollisionAttribute_t -{ - DECLARE_CLASS(VPhysicsCollisionAttribute_t) +struct VPhysicsCollisionAttribute_t { + DECLARE_CLASS(VPhysicsCollisionAttribute_t) - SCHEMA_FIELD(uint8_t, m_nCollisionGroup) + SCHEMA_FIELD(uint8_t, m_nCollisionGroup) }; -class CCollisionProperty -{ -public: - DECLARE_CLASS(CCollisionProperty) +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) + 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 CHandle -{ - CBaseEntity* GetBaseEntity() const; +class CHandle { + CBaseEntity* GetBaseEntity() const; -public: - bool operator==(CHandle rhs) const { return m_Index == rhs.m_Index; } + public: + bool operator==(CHandle rhs) const { return m_Index == rhs.m_Index; } - bool IsValid() const { return m_Index != INVALID_EHANDLE_INDEX; } + bool IsValid() const { return m_Index != INVALID_EHANDLE_INDEX; } - int GetEntryIndex() const { return m_Index & ENT_ENTRY_MASK; } + int GetEntryIndex() const { return m_Index & ENT_ENTRY_MASK; } - template - T* Get() const - { - return reinterpret_cast(GetBaseEntity()); - } - uint32_t m_Index; + template + T* Get() const { + return reinterpret_cast(GetBaseEntity()); + } + uint32_t m_Index; }; class CEntityInstance { -public: + public: DECLARE_CLASS(CEntityInstance); auto Schema_DynamicBinding() { @@ -333,18 +307,19 @@ public: }; class CBaseEntity : public CEntityInstance { -public: + public: DECLARE_CLASS(CBaseEntity); SCHEMA_FIELD(int, m_iHealth) + SCHEMA_FIELD(int, m_iTeamNum) // SCHEMA_FIELD(Vector, m_vecBaseVelocity) SCHEMA_FIELD(CCollisionProperty*, m_pCollision) - bool IsBasePlayerController(); + auto IsBasePlayerController() -> bool; + auto SpawnClientEntity() -> void; }; - class CBasePlayerController : public CBaseEntity { -public: + public: DECLARE_CLASS(CBasePlayerController); SCHEMA_FIELD(uint64_t, m_steamID) @@ -354,7 +329,7 @@ public: }; class CCSPlayerController : public CBasePlayerController { -public: + public: DECLARE_CLASS(CCSPlayerController) SCHEMA_FIELD(uint32_t, m_iPawnHealth) @@ -363,159 +338,157 @@ public: }; class CEconItemDefinition { -public: - bool IsWeapon(); - bool IsKnife(bool excludeDefault); - bool IsGlove(bool excludeDefault); + public: + bool IsWeapon(); + bool IsKnife(bool excludeDefault); + bool IsGlove(bool excludeDefault); - auto GetModelName() { - return *reinterpret_cast((uintptr_t)(this) + 0xD8); - } + auto GetModelName() { + return *reinterpret_cast((uintptr_t)(this) + 0xD8); + } - auto GetStickersSupportedCount() { - return *reinterpret_cast((uintptr_t)(this) + 0x100); - } + auto GetStickersSupportedCount() { + return *reinterpret_cast((uintptr_t)(this) + 0x100); + } - auto GetSimpleWeaponName() { - return *reinterpret_cast((uintptr_t)(this) + 0x210); - } + auto GetSimpleWeaponName() { + return *reinterpret_cast((uintptr_t)(this) + 0x210); + } - auto GetLoadoutSlot() { - return *reinterpret_cast((uintptr_t)(this) + 0x2E8); - } + 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; + 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); - } + public: + DECLARE_CLASS(CEconItemView); + auto GetCustomPaintKitIndex() { return CALL_VIRTUAL(int, 2, this); } + auto GetStaticData() { + return CALL_VIRTUAL(CEconItemDefinition*, 13, this); + } }; -class CAttributeContainer -{ -public: - DECLARE_CLASS(CAttributeContainer); +class CAttributeContainer { + public: + DECLARE_CLASS(CAttributeContainer); - PSCHEMA_FIELD(CEconItemView, m_Item); + PSCHEMA_FIELD(CEconItemView, m_Item); }; class CEconEntity { -public: - DECLARE_CLASS(CEconEntity); + public: + DECLARE_CLASS(CEconEntity); - PSCHEMA_FIELD(CAttributeContainer, m_AttributeManager); + PSCHEMA_FIELD(CAttributeContainer, m_AttributeManager); }; -class CBasePlayerWeapon : public CEconEntity -{ -public: - DECLARE_CLASS(CBasePlayerWeapon); +class CBasePlayerWeapon : public CEconEntity { + public: + DECLARE_CLASS(CBasePlayerWeapon); - SCHEMA_FIELD(int, m_iClip1); - SCHEMA_FIELD(int, m_iClip2); - SCHEMA_FIELD(int, m_pReserveAmmo); + 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(uint16_t, m_iAmmo); + public: + DECLARE_CLASS(CPlayer_WeaponServices) + SCHEMA_FIELD(CHandle, m_hActiveWeapon); + SCHEMA_FIELD(uint16_t, m_iAmmo); }; - class CBasePlayer { -public: - auto ForceRespawn() -> void; + public: + auto ForceRespawn() -> void; }; class CPlayer_MovementServices { -public: - DECLARE_CLASS(CPlayer_MovementServices); + public: + DECLARE_CLASS(CPlayer_MovementServices); }; class CCSPlayerController_InGameMoneyServices { -public: - DECLARE_CLASS(CCSPlayerController_InGameMoneyServices); + public: + DECLARE_CLASS(CCSPlayerController_InGameMoneyServices); - SCHEMA_FIELD(int, m_iAccount) + SCHEMA_FIELD(int, m_iAccount) }; class CBasePlayerPawn : public CBaseEntity { -public: - DECLARE_CLASS(CBasePlayerPawn); + public: + DECLARE_CLASS(CBasePlayerPawn); - SCHEMA_FIELD(CPlayer_MovementServices*, m_pMovementServices) - SCHEMA_FIELD(CPlayer_WeaponServices*, m_pWeaponServices) - SCHEMA_FIELD(uint8_t**, m_pItemServices) + 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 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*; + public: + DECLARE_CLASS(CCSPlayerPawn); + SCHEMA_FIELD(const char*, m_szLastPlaceName) + auto GetPlayerController() -> CCSPlayerController*; }; class CGameEntitySystem; -class CGameResourceService -{ -public: - CGameEntitySystem* GetGameEntitySystem() - { - return *reinterpret_cast((uintptr_t)(this) + 0x58); - } +class CGameResourceService { + public: + CGameEntitySystem* GetGameEntitySystem() { + return *reinterpret_cast((uintptr_t)(this) + 0x58); + } }; class CLocalize { -public: - auto FindSafe(const char* tokenName) -> const char*; + public: + auto FindSafe(const char* tokenName) -> const char*; }; -class Z_CBaseEntity : public CBaseEntity -{ -public: - DECLARE_CLASS(CBaseEntity) +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) + 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) }; diff --git a/csgo2/offset.cpp b/csgo2/offset.cpp index 4a8937d..b6d2b00 100644 --- a/csgo2/offset.cpp +++ b/csgo2/offset.cpp @@ -4,12 +4,15 @@ namespace Offset { uint64_t GameResourceServicePtr; uint64_t FireEventServerSidePtr; uint64_t CGameEventManagerPtr; +uint64_t CCSGameRulesInterFacePtr; uint64_t Host_SayPtr; uint64_t Module_tier0; uint64_t MaxPlayerNumsPtr; HashFunction_t FnServerHashFunction; StateChanged_t FnStateChanged; NetworkStateChanged_t FnNetworkStateChanged; +//CreateGameRuleInterFace_t FnCreateCCSGameRulesInterFace; + namespace InterFaces { CSchemaSystem* SchemaSystem; IGameEventManager2* GameEventManager; @@ -20,7 +23,9 @@ IVEngineServer2* IVEngineServer; ISource2Server* ISource2ServerInterFace; CLocalize* ILocalize; INetworkServerService* INetworkServerServiceInteFace; +CCSGameRules* CCSGameRulesInterFace; }; // namespace InterFaces + auto Init() -> bool { CModule server("server.dll"); CModule schemasystem("schemasystem.dll"); @@ -28,43 +33,55 @@ auto Init() -> bool { CModule localize("localize.dll"); // engine.dll - engine.FindPattern(pattern_MaxPlayerNumsPtr).ToAbsolute(3, 0).Get(MaxPlayerNumsPtr); + engine.FindPattern(pattern_MaxPlayerNumsPtr) + .ToAbsolute(3, 0) + .Get(MaxPlayerNumsPtr); // server.dll server.FindPattern(pattern_FireEventServerSide).Get(FireEventServerSidePtr); server.FindPattern(pattern_NetworkStateChanged).Get(FnNetworkStateChanged); server.FindPattern(pattern_FnStateChangedPtr).Get(FnStateChanged); - // 48 8D 05 4A 30 82 00 lea rax, ??_7CGameEventManager@@6B@ server.FindPattern(pattern_CGameEventManager) .ToAbsolute(3, 0) .Get(CGameEventManagerPtr); + server.FindPattern(pattern_CreateCCSGameRulesInterFacePtr) + .ToAbsolute(10, 0) + .Get(CCSGameRulesInterFacePtr); + server.FindPattern(pattern_fnHost_SayPtr).Get(Host_SayPtr); server.FindPattern(pattern_ServerHashFunctionPtr).Get(FnServerHashFunction); InterFaces::SchemaSystem = reinterpret_cast( schemasystem.FindInterface("SchemaSystem_001").Get()); - //InterFaces::GameEventManager = reinterpret_cast( - // engine.FindInterface("GameEventSystemServerV001").Get()); - InterFaces::ILocalize = reinterpret_cast(localize.FindInterface("Localize_001").Get()); + // InterFaces::GameEventManager = reinterpret_cast( + // engine.FindInterface("GameEventSystemServerV001").Get()); + InterFaces::ILocalize = reinterpret_cast( + localize.FindInterface("Localize_001").Get()); InterFaces::GameResourceServiceServer = reinterpret_cast( engine.FindInterface("GameResourceServiceServerV001").Get()); InterFaces::IVEngineServer = reinterpret_cast( engine.FindInterface("Source2EngineToServer001").Get()); - InterFaces::INetworkServerServiceInteFace = reinterpret_cast( - engine.FindInterface("NetworkServerService_001").Get()); + InterFaces::INetworkServerServiceInteFace = + reinterpret_cast( + engine.FindInterface("NetworkServerService_001").Get()); InterFaces::IServerGameClient = reinterpret_cast( server.FindInterface("Source2GameClients001").Get()); InterFaces::ISource2ServerInterFace = reinterpret_cast( server.FindInterface("Source2Server001").Get()); if (InterFaces::ISource2ServerInterFace) { - InterFaces::GameEventManager = (IGameEventManager2*)(CALL_VIRTUAL(uintptr_t, 91, InterFaces::ISource2ServerInterFace) - 8); + InterFaces::GameEventManager = + (IGameEventManager2*)(CALL_VIRTUAL( + uintptr_t, 91, + InterFaces::ISource2ServerInterFace) - + 8); } InterFaces::CGameEventManger = reinterpret_cast(CGameEventManagerPtr); - - //global::MaxPlayers = *(int*)((char*)MaxPlayerNumsPtr + 2); - // client.FindPattern(pattern_FireEventServerSide).Get(FireEventServerSidePtr); + InterFaces::CCSGameRulesInterFace = + reinterpret_cast(CCSGameRulesInterFacePtr + (8 * 2)); + // global::MaxPlayers = *(int*)((char*)MaxPlayerNumsPtr + 2); + // client.FindPattern(pattern_FireEventServerSide).Get(FireEventServerSidePtr); global::MaxPlayers = 64; LOG("[huoji]FireEventServerSidePtr : %llx \n", FireEventServerSidePtr); @@ -87,14 +104,17 @@ auto Init() -> bool { InterFaces::IVEngineServer); LOG("[huoji]InterFaces::ISource2ServerInterFace : %llx \n", InterFaces::ISource2ServerInterFace); + LOG("[huoji]InterFaces::CCSGameRulesInterFace : %llx \n", InterFaces::CCSGameRulesInterFace); + + //LOG("m_bForceTeamChangeSilent: %d \n", InterFaces::CCSGameRulesInterFace->m_bForceTeamChangeSilent()); - // GetOffsets(); LOG("init offset success !\n"); - //LOG("FnServerHashFunction: %llx \n", FnServerHashFunction("here", sizeof("here") - 1, 0x31415926)); + + // LOG("FnServerHashFunction: %llx \n", FnServerHashFunction("here", + // sizeof("here") - 1, 0x31415926)); return FnServerHashFunction && Host_SayPtr && InterFaces::IVEngineServer && InterFaces::GameResourceServiceServer && InterFaces::IServerGameClient && InterFaces::GameEventManager && - InterFaces::SchemaSystem && FireEventServerSidePtr && - FnNetworkStateChanged; + InterFaces::SchemaSystem && FireEventServerSidePtr && FnNetworkStateChanged; } } // namespace Offset diff --git a/csgo2/offset.h b/csgo2/offset.h index 17e9dc5..f50f325 100644 --- a/csgo2/offset.h +++ b/csgo2/offset.h @@ -2,27 +2,38 @@ #include "head.h" #define SERVER_HASH_FUCNTION_KEY 0x31415926 class CEntityInstance; -typedef uint64_t(__fastcall* HashFunction_t)(const char*, unsigned int, unsigned int); -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); - +typedef uint64_t(__fastcall* HashFunction_t)(const char*, unsigned int, + unsigned int); +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); +typedef void*(__fastcall* CreateGameRuleInterFace_t)(); class CSchemaSystem; class CGameResourceService; class CLocalize; +class CCSGameRules; namespace Offset { namespace InterFaces { - extern CSchemaSystem* SchemaSystem; - extern IGameEventManager2* GameEventManager; - extern CGameEventManager* CGameEventManger; - extern CGameResourceService* GameResourceServiceServer; - extern IServerGameClients* IServerGameClient; - extern IVEngineServer2* IVEngineServer; - extern CLocalize* ILocalize; - extern INetworkServerService* INetworkServerServiceInteFace; -}; -static const auto pattern_CGameEventManager = THE_GAME_SIG("48 ?? ?? ?? ?? ?? ?? 48 89 ?? ?? ?? 48 89 01 48 8B D9 48 ?? ?? ?? ?? ?? ?? 48 89 ?? ?? E8 ?? ?? ?? ?? 48 ?? ?? ?? ?? ?? ??"); -static const auto pattern_NetworkStateChanged = THE_GAME_SIG("4C 8B C9 48 8B 09 48 85 C9 74 ? 48 8B 41 10"); -static const auto pattern_FnStateChangedPtr = THE_GAME_SIG("48 89 54 24 10 55 53 57 41 55"); +extern CSchemaSystem* SchemaSystem; +extern IGameEventManager2* GameEventManager; +extern CGameEventManager* CGameEventManger; +extern CGameResourceService* GameResourceServiceServer; +extern IServerGameClients* IServerGameClient; +extern IVEngineServer2* IVEngineServer; +extern CLocalize* ILocalize; +extern INetworkServerService* INetworkServerServiceInteFace; +extern ISource2Server* ISource2ServerInterFace; +extern CCSGameRules* CCSGameRulesInterFace; +}; // namespace InterFaces +static const auto pattern_CGameEventManager = THE_GAME_SIG( + "48 ?? ?? ?? ?? ?? ?? 48 89 ?? ?? ?? 48 89 01 48 8B D9 48 ?? ?? ?? ?? ?? " + "?? 48 89 ?? ?? E8 ?? ?? ?? ?? 48 ?? ?? ?? ?? ?? ??"); +static const auto pattern_NetworkStateChanged = + THE_GAME_SIG("4C 8B C9 48 8B 09 48 85 C9 74 ? 48 8B 41 10"); +static const auto pattern_FnStateChangedPtr = + THE_GAME_SIG("48 89 54 24 10 55 53 57 41 55"); static const auto pattern_FireEventServerSide = THE_GAME_SIG( "40 53 57 41 54 41 55 41 56 48 ?? ?? ?? 4C 8B F2 4C 8B E1 BA ?? ?? ?? " "?? 48 ?? ?? ?? ?? ?? ?? 45 0F B6 E8 E8 ?? ?? ?? ?? 48 85 C0 75 ?? 48 " @@ -37,10 +48,16 @@ static const auto pattern_fnGetLocalPlayerController = //"\"Console<0>\" say \"%s\"\n" static const auto pattern_fnHost_SayPtr = THE_GAME_SIG("44 89 4C 24 ?? 44 88 44 24 ?? 55 53 56 57 41 54 41 55"); -static const auto pattern_ServerHashFunctionPtr = - THE_GAME_SIG("48 89 ?? ?? ?? 57 48 ?? ?? ?? ?? ?? ?? 33 C0 8B DA 41 8B F8 48 89 ?? ?? ?? 4C 8B C1 C7 44 ?? ?? ?? ?? ?? ?? 44 8B CA 89 44 ?? ?? 48 8D ?? ?? ?? 88 44 ?? ?? 33 D2"); -static const auto pattern_MaxPlayerNumsPtr = +static const auto pattern_ServerHashFunctionPtr = THE_GAME_SIG( + "48 89 ?? ?? ?? 57 48 ?? ?? ?? ?? ?? ?? 33 C0 8B DA 41 8B F8 48 89 ?? ?? " + "?? 4C 8B C1 C7 44 ?? ?? ?? ?? ?? ?? 44 8B CA 89 44 ?? ?? 48 8D ?? ?? ?? " + "88 44 ?? ?? 33 D2"); +static const auto pattern_MaxPlayerNumsPtr = THE_GAME_SIG("41 3B 87 ?? ?? ?? ?? 0F 8E ?? ?? ?? ?? 8B 0D ?? ?? ?? ??"); +static const auto pattern_CreateCCSGameRulesInterFacePtr = THE_GAME_SIG( + "40 53 48 ?? ?? ?? B9 ?? ?? ?? ?? E8 ?? ?? ?? ?? 33 D2 41 ?? ?? ?? ?? ?? " + "48 8B C8 48 8B D8 E8 ?? ?? ?? ?? 48 85 DB"); + extern uint64_t GameResourceServicePtr; extern uint64_t FireEventServerSidePtr; extern uint64_t Module_tier0; @@ -50,6 +67,5 @@ extern HashFunction_t FnServerHashFunction; extern StateChanged_t FnStateChanged; extern NetworkStateChanged_t FnNetworkStateChanged; - auto Init() -> bool; }; // namespace Offset diff --git a/csgo2/script_apis.cpp b/csgo2/script_apis.cpp index 1ed7841..f1bac3f 100644 --- a/csgo2/script_apis.cpp +++ b/csgo2/script_apis.cpp @@ -12,6 +12,16 @@ struct _luaApi_WeaponInfo { int weaponType; }; namespace ScriptApis { +auto TimerCallBack(_GameTimer* timer) -> void { + LOG("excute timer: %d %d m_bRepeat: %d\n", timer->m_iLuaCallBackFn, timer->m_iParamIndex, timer->m_bRepeat); + lua_rawgeti(timer->m_luaVm, LUA_REGISTRYINDEX, timer->m_iLuaCallBackFn); + lua_rawgeti(timer->m_luaVm, LUA_REGISTRYINDEX, timer->m_iParamIndex); + lua_pcall(timer->m_luaVm, 1, 0, 0); + if (timer->m_bRepeat == false) { + luaL_unref(timer->m_luaVm, LUA_REGISTRYINDEX, timer->m_iLuaCallBackFn); + luaL_unref(timer->m_luaVm, LUA_REGISTRYINDEX, timer->m_iParamIndex); + } +} // Ƿֵ,ֵҪԼpushstack auto luaApi_ListenToGameEvent(lua_State* luaVm) -> int { const auto eventName = lua_tostring(luaVm, 1); @@ -99,6 +109,7 @@ auto luaApi_RespawnPlayer(lua_State* luaVm) -> int { } auto playerController = reinterpret_cast(player); auto playerPawn = playerController->m_hPawn().Get(); + playerPawn->m_bRespawning(false); } while (false); lua_pop(luaVm, 1); @@ -256,9 +267,128 @@ auto luaApi_GetPlayerCurrentWeaponInfo(lua_State* luaVm) -> _luaApi_WeaponInfo { : (itemStaticData->IsWeapon() ? _luaApi_WeaponType::kGun : _luaApi_WeaponType::kOther)); } while (false); - return info; } +auto luaApi_CreateTimer(lua_State* luaVm) -> int { + // param: time:float, callback:function, params:lua_table + const auto time = lua_tonumber(luaVm, 1); + const auto repeat = lua_toboolean(luaVm, 2); + const auto preserveMapChange = lua_toboolean(luaVm, 3); + auto timerHandle = 0; + do { + const auto params = lua_gettable(luaVm, 4); + const auto callback = luaL_ref(luaVm, LUA_REGISTRYINDEX); + LOG("luaApi_CreateTimer: params: %d callback: %d \n", params, callback); + timerHandle = GameTimer::AddTimer(new _GameTimer{ + .m_flTime = (float)time, + .m_bRepeat = (bool)repeat, + .m_bPreserveMapChange = (bool)preserveMapChange, + .m_luaVm = luaVm, + .m_iParamIndex = params, + .m_iLuaCallBackFn = callback + }); + } while (false); + lua_pop(luaVm, 5); + lua_pushinteger(luaVm, timerHandle); + return 1; +} +auto luaApi_CheckPlayerIsAlive(lua_State* luaVm) -> int { + // param: playerIndex:int + const auto playerIndex = lua_tointeger(luaVm, 1); + auto isAlive = false; + + CGameEntitySystem* EntitySystem = CGameEntitySystem::GetInstance(); + do { + if (EntitySystem == nullptr || playerIndex == 0) { + break; + } + auto player = EntitySystem->GetBaseEntity(playerIndex); + if (player == nullptr) { + break; + } + if (player->IsBasePlayerController() == false) { + break; + } + auto playerController = reinterpret_cast(player); + isAlive = playerController->m_bPawnIsAlive(); + } while (false); + lua_pop(luaVm, 1); + lua_pushboolean(luaVm, isAlive); + return 1; +} +auto luaApi_GetPlayerTeam(lua_State* luaVm) -> int { + // param: playerIndex:int + const auto playerIndex = lua_tointeger(luaVm, 1); + auto team = 0; + + CGameEntitySystem* EntitySystem = CGameEntitySystem::GetInstance(); + do { + if (EntitySystem == nullptr || playerIndex == 0) { + break; + } + auto player = EntitySystem->GetBaseEntity(playerIndex); + if (player == nullptr) { + break; + } + if (player->IsBasePlayerController() == false) { + break; + } + auto playerController = reinterpret_cast(player); + team = playerController->m_iTeamNum(); + } while (false); + lua_pop(luaVm, 1); + lua_pushinteger(luaVm, team); + return 1; +} +auto luaApi_SetPlayerTeam(lua_State* luaVm) -> int { + // param: playerIndex:int, team:int + const auto playerIndex = lua_tointeger(luaVm, 1); + const auto team = lua_tointeger(luaVm, 2); + auto isSuccess = false; + + CGameEntitySystem* EntitySystem = CGameEntitySystem::GetInstance(); + do { + if (EntitySystem == nullptr || playerIndex == 0) { + break; + } + auto player = EntitySystem->GetBaseEntity(playerIndex); + if (player == nullptr) { + break; + } + if (player->IsBasePlayerController() == false) { + break; + } + auto playerController = reinterpret_cast(player); + playerController->m_iTeamNum() = team; + isSuccess = true; + } while (false); + lua_pop(luaVm, 2); + lua_pushboolean(luaVm, isSuccess); + return 1; +} +auto luaApi_CheckPlayerIsInServer(lua_State* luaVm) -> int { + // param: playerIndex:int + const auto playerIndex = lua_tointeger(luaVm, 1); + auto isInServer = false; + + CGameEntitySystem* EntitySystem = CGameEntitySystem::GetInstance(); + do { + if (EntitySystem == nullptr || playerIndex == 0) { + break; + } + auto player = EntitySystem->GetBaseEntity(playerIndex); + if (player == nullptr) { + break; + } + if (player->IsBasePlayerController() == false) { + break; + } + isInServer = true; + } while (false); + lua_pop(luaVm, 1); + lua_pushboolean(luaVm, isInServer); + return 1; +} auto initFunciton(lua_State* luaVm) -> void { lua_register(luaVm, "ListenToGameEvent", luaApi_ListenToGameEvent); lua_register(luaVm, "luaApi_SetPlayerCurrentWeaponAmmo", @@ -270,7 +400,12 @@ auto initFunciton(lua_State* luaVm) -> void { lua_register(luaVm, "luaApi_SetPlayerArmorValue", luaApi_SetPlayerArmorValue); lua_register(luaVm, "luaApi_RespawnPlayer", luaApi_RespawnPlayer); - + lua_register(luaVm, "luaApi_CreateTimer", luaApi_CreateTimer); + lua_register(luaVm, "luaApi_CheckPlayerIsAlive", luaApi_CheckPlayerIsAlive); + lua_register(luaVm, "luaApi_GetPlayerTeam", luaApi_GetPlayerTeam); + lua_register(luaVm, "luaApi_SetPlayerTeam", luaApi_SetPlayerTeam); + lua_register(luaVm, "luaApi_CheckPlayerIsInServer", + luaApi_CheckPlayerIsInServer); // Ҳϲ luabridge::getGlobalNamespace(luaVm) .beginClass<_luaApi_WeaponInfo>("WeaponInfo") diff --git a/csgo2/script_callbacks.cpp b/csgo2/script_callbacks.cpp index 72864c6..f923877 100644 --- a/csgo2/script_callbacks.cpp +++ b/csgo2/script_callbacks.cpp @@ -8,7 +8,9 @@ std::unordered_map callbackNameWithEnumMap{ {hash_32_fnv1a_const("player_connect"), _CallbackNames::kOnPlayerConnect}, {hash_32_fnv1a_const("player_disconnect"), _CallbackNames::kOnPlayerDisconnect}, - {hash_32_fnv1a_const("player_death"), _CallbackNames::kOnPlayerDeath}}; + {hash_32_fnv1a_const("player_death"), _CallbackNames::kOnPlayerDeath}, + {hash_32_fnv1a_const("player_chat"), _CallbackNames::kOnPlayerSpeak}, +}; auto CallBackNameToEnum(const char* name) -> _CallbackNames { if (name == nullptr) { return _CallbackNames::kError; @@ -104,4 +106,27 @@ auto luaCall_onPlayerDeath(int victim, int killer, bool isHeadShot) -> void { } }); } +auto luaCall_onPlayerSpeak(int speaker, int chatType, std::string message) + -> bool { + bool result = false; + ExcuteCallbackInAllLuaVm(_CallbackNames::kOnPlayerSpeak, + [&](lua_State* luaVm, int refIndex) -> void { + lua_rawgeti(luaVm, LUA_REGISTRYINDEX, + refIndex); + if (lua_isfunction(luaVm, -1)) { + lua_pushinteger(luaVm, speaker); + lua_pushinteger(luaVm, chatType); + lua_pushstring(luaVm, message.c_str()); + if (lua_pcall(luaVm, 3, 1, 0) != LUA_OK) { + LOG("Error calling Lua callback: %s\n", + lua_tostring(luaVm, -1)); + lua_pop(luaVm, 1); + } + if (lua_isboolean(luaVm, -1)) { + result = lua_toboolean(luaVm, -1); + } + } + }); + return result; +} } // namespace ScriptCallBacks diff --git a/csgo2/script_callbacks.h b/csgo2/script_callbacks.h index d5f4d22..180e374 100644 --- a/csgo2/script_callbacks.h +++ b/csgo2/script_callbacks.h @@ -6,7 +6,8 @@ enum class _CallbackNames { kError, kOnPlayerConnect, kOnPlayerDisconnect, - kOnPlayerDeath + kOnPlayerDeath, + kOnPlayerSpeak }; extern std::unordered_map> callbackList; @@ -19,4 +20,6 @@ auto luaCall_onPlayerDisconnect(int player, int slot, const char* pszName, const char* pszAddress, bool bFakePlayer) -> void; auto luaCall_onPlayerDeath(int victim, int killer, bool isHeadShot) -> void; +auto luaCall_onPlayerSpeak(int speaker, int chatType, std::string message) + -> bool; } // namespace ScriptCallBacks diff --git a/csgo2/sdk/public/eiface.h b/csgo2/sdk/public/eiface.h index a5dd3d3..0296e55 100644 --- a/csgo2/sdk/public/eiface.h +++ b/csgo2/sdk/public/eiface.h @@ -193,6 +193,7 @@ public: class ISource2Server : public IAppSystem { public: + //vmt index 11 virtual bool Unknown0() const = 0; virtual void SetGlobals(CGlobalVars* pGlobals) = 0; @@ -213,6 +214,7 @@ public: // The server should run physics/think on all edicts // One of these bools is 'simulating'... probably + // index 19 virtual void GameFrame(bool simulating, bool bFirstTick, bool bLastTick) = 0; // Returns true if the game DLL wants the server not to be made public. diff --git a/csgo2/sdk/public/iserver.h b/csgo2/sdk/public/iserver.h index f64bdeb..ba6e4d1 100644 --- a/csgo2/sdk/public/iserver.h +++ b/csgo2/sdk/public/iserver.h @@ -91,6 +91,7 @@ public: class IEngineService : public IAppSystem { public: + //vmt index 11 virtual void* GetServiceDependencies(void) = 0; virtual const char* GetName(void) const = 0; virtual bool ShouldActivate(const char*) = 0; @@ -107,10 +108,12 @@ public: class INetworkServerService : public IEngineService { public: + //vmt index 22 virtual ~INetworkServerService() {} virtual INetworkGameServer * GetIGameServer(void) = 0; virtual bool IsActiveInGame(void) const = 0; virtual bool IsMultiplayer(void) const = 0; + //vmt index 26 virtual void StartupServer(const GameSessionConfiguration_t& config, ISource2WorldSession* pWorldSession, const char*) = 0; virtual void SetGameSpawnGroupMgr(IGameSpawnGroupMgr* pMgr) = 0; virtual void AddServerPrerequisites(const GameSessionConfiguration_t&, const char*, void*, bool) = 0; diff --git a/csgo2/timer.cpp b/csgo2/timer.cpp new file mode 100644 index 0000000..7bc0d9f --- /dev/null +++ b/csgo2/timer.cpp @@ -0,0 +1,43 @@ +#include "timer.h" +namespace ScriptApis { + extern auto TimerCallBack(_GameTimer* timer) -> void; +}; +namespace GameTimer { +std::shared_mutex mutex_timerList; +std::vector<_GameTimer*> timerList; +auto AddTimer(_GameTimer* timer) -> int { + std::unique_lock lock(mutex_timerList); + timerList.push_back(timer); + return timerList.size() - 1; +}; +auto CleanUpTimers() -> void { + std::unique_lock lock(mutex_timerList); + for (auto it = timerList.begin(); it != timerList.end();) { + if ((*it)->m_bPreserveMapChange) { + ++it; + } else { + delete (*it); + it = timerList.erase(it); + } + } +}; +auto ExcuteTimers() -> void { + std::shared_lock lock(mutex_timerList); + for (auto it = timerList.begin(); it != timerList.end();) { + if ((*it)->m_flLastExecute == -1) { + (*it)->m_flLastExecute = global::m_flUniversalTime; + } + if ((*it)->m_flLastExecute + (*it)->m_flTime <= global::m_flUniversalTime) { + ScriptApis::TimerCallBack(*it); + if ((*it)->m_bRepeat) { + (*it)->m_flLastExecute = global::m_flUniversalTime; + } else { + delete (*it); + it = timerList.erase(it); + continue; + } + } + ++it; + } +} +}; // namespace GameTimer diff --git a/csgo2/timer.h b/csgo2/timer.h new file mode 100644 index 0000000..a5b79e6 --- /dev/null +++ b/csgo2/timer.h @@ -0,0 +1,18 @@ +#pragma once +#include "head.h" +class _GameTimer { +public: + float m_flTime; + float m_flLastExecute = -1; + bool m_bRepeat; + bool m_bPreserveMapChange; + lua_State* m_luaVm; + int m_iParamIndex; + int m_iLuaCallBackFn; + +}; +namespace GameTimer { +auto AddTimer(_GameTimer* timer) -> int; +auto CleanUpTimers() -> void; +auto ExcuteTimers() -> void; +}; // namespace GameTimer diff --git a/csgo2/vmthook.cpp b/csgo2/vmthook.cpp index f233ccb..4fe104e 100644 --- a/csgo2/vmthook.cpp +++ b/csgo2/vmthook.cpp @@ -9,13 +9,13 @@ void* VMTHook::Hook(int index, void* hk) { // Store the index and original function address hooked_funcs.insert(std::make_pair(index, vmt[index])); + printf("vmt hook at: %p \n", vmt[index]); // Change the memory's access rights, patch the address to our hook, restore original rights DWORD old; VirtualProtect(&vmt[index], sizeof(void*), PAGE_EXECUTE_READWRITE, &old); vmt[index] = hk; VirtualProtect(&vmt[index], sizeof(void*), old, NULL); - return hooked_funcs[index]; }