diff --git a/csgo2/csgo2.vcxproj.filters b/csgo2/csgo2.vcxproj.filters
index d4b9b37..8b61b51 100644
--- a/csgo2/csgo2.vcxproj.filters
+++ b/csgo2/csgo2.vcxproj.filters
@@ -386,9 +386,6 @@
源文件\script_engine
-
- 头文件
-
源文件\native_sdk
@@ -503,6 +500,9 @@
源文件\game_time_system
+
+ 源文件
+
diff --git a/csgo2/dllmain.cpp b/csgo2/dllmain.cpp
index b5b10b3..167b86b 100644
--- a/csgo2/dllmain.cpp
+++ b/csgo2/dllmain.cpp
@@ -16,19 +16,25 @@ auto WatchExitThread(void *ctx) -> void {
unload();
}
auto init(void* ctx) -> bool {
+
AllocConsole();
SetConsoleTitleA("huoji debug console");
freopen_s(reinterpret_cast stdout, "CONOUT$", "w", stdout);
CreateThread(NULL, 0,
reinterpret_cast(WatchExitThread),
NULL, 0, NULL);
+ uint64_t serverHandle{};
+ uint64_t localizeHandle{};
- while (Offset::Module_tier0 == 0)
+ while (Offset::Module_tier0 == 0 || serverHandle == 0 || localizeHandle == 0)
{
if (global::Exit) {
return false;
}
Offset::Module_tier0 = reinterpret_cast(GetModuleHandleA("tier0"));
+ serverHandle = reinterpret_cast(GetModuleHandleA("server.dll"));
+ localizeHandle = reinterpret_cast(GetModuleHandleA("localize.dll"));
+
Sleep(200);
}
if (Offset::Init() == false) {
@@ -40,6 +46,10 @@ auto init(void* ctx) -> bool {
isSuccess = hooks::init();
if (isSuccess) {
LOG("plugin install success !\n");
+ while (Offset::InitOffsetSuccess == false)
+ {
+ Sleep(200);
+ }
ScriptEngine::Init();
}
return isSuccess;
diff --git a/csgo2/hooks.cpp b/csgo2/hooks.cpp
index 6a1d0b5..ab96989 100644
--- a/csgo2/hooks.cpp
+++ b/csgo2/hooks.cpp
@@ -36,6 +36,7 @@ void __fastcall hook_GameFrame(void* rcx, bool simulating, bool bFirstTick,
}
GameTimer::ExcuteTimers();
+ GameTickRunTime::ExcuteTickFunctions();
return origin_GameFrame(rcx, simulating, bFirstTick, bLastTick);
}
void __fastcall hook_StartServer(void* rcx,
diff --git a/csgo2/native_sdk.h b/csgo2/native_sdk.h
index 3f495bd..969534f 100644
--- a/csgo2/native_sdk.h
+++ b/csgo2/native_sdk.h
@@ -459,6 +459,9 @@ class CCSPlayerPawn : public CCSPlayerPawnBase {
DECLARE_CLASS(CCSPlayerPawn);
SCHEMA_FIELD(const char*, m_szLastPlaceName)
auto GetPlayerController() -> CCSPlayerController*;
+ auto ForceRespawnPlayer() {
+ return CALL_VIRTUAL(void, 324, this);
+ }
};
class CGameEntitySystem;
@@ -491,4 +494,7 @@ class CCSGameRules {
public:
DECLARE_CLASS(CCSGameRules)
SCHEMA_FIELD(bool, m_bForceTeamChangeSilent)
+ auto PlayerRespawn(CCSPlayerPawn* PlayerPawn) {
+ return CALL_VIRTUAL(void, 110, this, PlayerPawn);
+ }
};
diff --git a/csgo2/offset.cpp b/csgo2/offset.cpp
index b6d2b00..401bb0b 100644
--- a/csgo2/offset.cpp
+++ b/csgo2/offset.cpp
@@ -11,8 +11,10 @@ uint64_t MaxPlayerNumsPtr;
HashFunction_t FnServerHashFunction;
StateChanged_t FnStateChanged;
NetworkStateChanged_t FnNetworkStateChanged;
-//CreateGameRuleInterFace_t FnCreateCCSGameRulesInterFace;
+RespawnPlayer_t FnRespawnPlayer;
+//CreateGameRuleInterFace_t FnCreateCCSGameRulesInterFace;
+bool InitOffsetSuccess = false;
namespace InterFaces {
CSchemaSystem* SchemaSystem;
IGameEventManager2* GameEventManager;
@@ -25,7 +27,24 @@ CLocalize* ILocalize;
INetworkServerService* INetworkServerServiceInteFace;
CCSGameRules* CCSGameRulesInterFace;
}; // namespace InterFaces
+auto SafeDelayInit(void* ctx) -> void {
+ // ҪϷúʼ
+ InterFaces::CCSGameRulesInterFace =
+ reinterpret_cast(Memory::read(CCSGameRulesInterFacePtr));
+ while (InterFaces::CCSGameRulesInterFace == 0)
+ {
+ InterFaces::CCSGameRulesInterFace =
+ reinterpret_cast(Memory::read(CCSGameRulesInterFacePtr));
+ Sleep(100);
+ }
+ InitOffsetSuccess = true;
+ LOG("[huoji]InterFaces::CCSGameRulesInterFace : %llx \n", InterFaces::CCSGameRulesInterFace);
+ LOG("[huoji]InterFaces::CCSGameRulesInterFace->respawnPlayer : %llx \n", ((void**)InterFaces::CCSGameRulesInterFace)[110]);
+
+ LOG("m_bForceTeamChangeSilent: %d \n", InterFaces::CCSGameRulesInterFace->m_bForceTeamChangeSilent());
+
+}
auto Init() -> bool {
CModule server("server.dll");
CModule schemasystem("schemasystem.dll");
@@ -46,8 +65,10 @@ auto Init() -> bool {
.ToAbsolute(3, 0)
.Get(CGameEventManagerPtr);
server.FindPattern(pattern_CreateCCSGameRulesInterFacePtr)
- .ToAbsolute(10, 0)
+ .ToAbsolute(3, 0)
.Get(CCSGameRulesInterFacePtr);
+ server.FindPattern(pattern_FnRespawnPlayer)
+ .Get(FnRespawnPlayer);
server.FindPattern(pattern_fnHost_SayPtr).Get(Host_SayPtr);
server.FindPattern(pattern_ServerHashFunctionPtr).Get(FnServerHashFunction);
@@ -78,8 +99,7 @@ auto Init() -> bool {
}
InterFaces::CGameEventManger =
reinterpret_cast(CGameEventManagerPtr);
- InterFaces::CCSGameRulesInterFace =
- reinterpret_cast(CCSGameRulesInterFacePtr + (8 * 2));
+
// global::MaxPlayers = *(int*)((char*)MaxPlayerNumsPtr + 2);
// client.FindPattern(pattern_FireEventServerSide).Get(FireEventServerSidePtr);
global::MaxPlayers = 64;
@@ -104,12 +124,11 @@ 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());
LOG("init offset success !\n");
-
+ CreateThread(NULL, 0,
+ reinterpret_cast(SafeDelayInit),
+ NULL, 0, NULL);
// LOG("FnServerHashFunction: %llx \n", FnServerHashFunction("here",
// sizeof("here") - 1, 0x31415926));
return FnServerHashFunction && Host_SayPtr && InterFaces::IVEngineServer &&
diff --git a/csgo2/offset.h b/csgo2/offset.h
index f50f325..b1a87e2 100644
--- a/csgo2/offset.h
+++ b/csgo2/offset.h
@@ -2,6 +2,7 @@
#include "head.h"
#define SERVER_HASH_FUCNTION_KEY 0x31415926
class CEntityInstance;
+class CCSPlayerPawn;
typedef uint64_t(__fastcall* HashFunction_t)(const char*, unsigned int,
unsigned int);
typedef void(__fastcall* StateChanged_t)(void* networkTransmitComponent,
@@ -10,6 +11,8 @@ typedef void(__fastcall* StateChanged_t)(void* networkTransmitComponent,
typedef void(__fastcall* NetworkStateChanged_t)(uintptr_t chainEntity,
uintptr_t offset, uintptr_t a3);
typedef void*(__fastcall* CreateGameRuleInterFace_t)();
+typedef bool(__fastcall* RespawnPlayer_t)(CCSPlayerPawn* player);
+
class CSchemaSystem;
class CGameResourceService;
class CLocalize;
@@ -55,9 +58,8 @@ static const auto pattern_ServerHashFunctionPtr = THE_GAME_SIG(
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");
-
+ "48 ?? ?? ?? ?? ?? ?? 48 8B 01 FF ?? ?? ?? ?? ?? 48 8D ?? ?? ?? E8 ?? ?? ?? ?? 4C 8D ?? ?? ?? 49 8B ?? ?? 49 8B ?? ?? 49 8B ?? ?? 49 8B E3 41 5F 41 5E 5F C3");
+static const auto pattern_FnRespawnPlayer = THE_GAME_SIG("48 89 ?? ?? ?? 57 48 ?? ?? ?? 48 8D ?? ?? ?? 48 8B F9 E8 ?? ?? ?? ?? 83 ?? ?? 74 ?? 48 ?? ?? ?? ?? ?? ?? 48 8B CF 48 8B 10 48 8B ?? ?? ?? ?? ?? 48 8D ?? ?? ?? E8 ?? ?? ?? ?? 48 ?? ?? ?? ?? ?? ??");
extern uint64_t GameResourceServicePtr;
extern uint64_t FireEventServerSidePtr;
extern uint64_t Module_tier0;
@@ -66,6 +68,7 @@ extern uint64_t MaxPlayerNumsPtr;
extern HashFunction_t FnServerHashFunction;
extern StateChanged_t FnStateChanged;
extern NetworkStateChanged_t FnNetworkStateChanged;
-
+extern RespawnPlayer_t FnRespawnPlayer;
+extern bool InitOffsetSuccess;
auto Init() -> bool;
}; // namespace Offset
diff --git a/csgo2/script_apis.cpp b/csgo2/script_apis.cpp
index f1bac3f..e91a4d5 100644
--- a/csgo2/script_apis.cpp
+++ b/csgo2/script_apis.cpp
@@ -12,8 +12,18 @@ struct _luaApi_WeaponInfo {
int weaponType;
};
namespace ScriptApis {
+auto RunTickCallBack(_GameTickRunTime* timer) -> void {
+ LOG("excute tick function: %d %d \n", timer->m_iLuaCallBackFn,
+ timer->m_iParamIndex);
+ 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);
+ luaL_unref(timer->m_luaVm, LUA_REGISTRYINDEX, timer->m_iLuaCallBackFn);
+ luaL_unref(timer->m_luaVm, LUA_REGISTRYINDEX, timer->m_iParamIndex);
+}
auto TimerCallBack(_GameTimer* timer) -> void {
- LOG("excute timer: %d %d m_bRepeat: %d\n", timer->m_iLuaCallBackFn, timer->m_iParamIndex, timer->m_bRepeat);
+ 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);
@@ -109,8 +119,9 @@ auto luaApi_RespawnPlayer(lua_State* luaVm) -> int {
}
auto playerController = reinterpret_cast(player);
auto playerPawn = playerController->m_hPawn().Get();
-
- playerPawn->m_bRespawning(false);
+ LOG("respawn player: %llx \n", playerPawn);
+ Offset::FnRespawnPlayer(playerPawn);
+ //playerPawn->ForceRespawnPlayer();
} while (false);
lua_pop(luaVm, 1);
return 0;
@@ -269,26 +280,57 @@ auto luaApi_GetPlayerCurrentWeaponInfo(lua_State* luaVm) -> _luaApi_WeaponInfo {
} while (false);
return info;
}
+auto luaApi_CreateTickRunFunction(lua_State* luaVm) -> int {
+ // params:lua_table, callback:function
+ if (!lua_istable(luaVm, 1)) {
+ luaL_error(luaVm, "Parameter 'params' must be a table");
+ return 0;
+ }
+ lua_pushvalue(luaVm, 1); // Duplicate the table for luaL_ref
+ const auto params = luaL_ref(luaVm, LUA_REGISTRYINDEX);
+
+ if (!lua_isfunction(luaVm, 2)) {
+ luaL_error(luaVm, "Parameter 'callback' must be a function");
+ return 0;
+ }
+ lua_pushvalue(luaVm, 2); // Duplicate the function for luaL_ref
+ const auto callback = luaL_ref(luaVm, LUA_REGISTRYINDEX);
+ GameTickRunTime::AddTickFunction(new _GameTickRunTime{
+ .m_luaVm = luaVm,
+ .m_iParamIndex = params,
+ .m_iLuaCallBackFn = callback,
+ });
+ return 0;
+}
auto luaApi_CreateTimer(lua_State* luaVm) -> int {
- // param: time:float, callback:function, params:lua_table
- const auto time = lua_tonumber(luaVm, 1);
+ // param: time:float,repeat:bool,preservermapchange:bool,params:lua_table,
+ // callback:function
+ const auto time = luaL_checknumber(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);
+
+ if (!lua_istable(luaVm, 4)) {
+ luaL_error(luaVm, "Parameter 'params' must be a table");
+ return 0;
+ }
+ lua_pushvalue(luaVm, 4); // Duplicate the table for luaL_ref
+ const auto params = luaL_ref(luaVm, LUA_REGISTRYINDEX);
+
+ if (!lua_isfunction(luaVm, 5)) {
+ luaL_error(luaVm, "Parameter 'callback' must be a function");
+ return 0;
+ }
+ lua_pushvalue(luaVm, 5); // Duplicate the function for luaL_ref
+ const auto callback = luaL_ref(luaVm, LUA_REGISTRYINDEX);
+
+ auto 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});
+
lua_pushinteger(luaVm, timerHandle);
return 1;
}
@@ -359,7 +401,7 @@ auto luaApi_SetPlayerTeam(lua_State* luaVm) -> int {
break;
}
auto playerController = reinterpret_cast(player);
- playerController->m_iTeamNum() = team;
+ playerController->m_iTeamNum(team);
isSuccess = true;
} while (false);
lua_pop(luaVm, 2);
@@ -401,6 +443,8 @@ auto initFunciton(lua_State* luaVm) -> void {
luaApi_SetPlayerArmorValue);
lua_register(luaVm, "luaApi_RespawnPlayer", luaApi_RespawnPlayer);
lua_register(luaVm, "luaApi_CreateTimer", luaApi_CreateTimer);
+ lua_register(luaVm, "luaApi_CreateTickRunFunction",
+ luaApi_CreateTickRunFunction);
lua_register(luaVm, "luaApi_CheckPlayerIsAlive", luaApi_CheckPlayerIsAlive);
lua_register(luaVm, "luaApi_GetPlayerTeam", luaApi_GetPlayerTeam);
lua_register(luaVm, "luaApi_SetPlayerTeam", luaApi_SetPlayerTeam);
diff --git a/csgo2/timer.cpp b/csgo2/timer.cpp
index 7bc0d9f..c709ff2 100644
--- a/csgo2/timer.cpp
+++ b/csgo2/timer.cpp
@@ -1,7 +1,8 @@
#include "timer.h"
namespace ScriptApis {
- extern auto TimerCallBack(_GameTimer* timer) -> void;
-};
+extern auto TimerCallBack(_GameTimer* timer) -> void;
+extern auto RunTickCallBack(_GameTickRunTime* timer) -> void;
+}; // namespace ScriptApis
namespace GameTimer {
std::shared_mutex mutex_timerList;
std::vector<_GameTimer*> timerList;
@@ -27,7 +28,8 @@ auto ExcuteTimers() -> void {
if ((*it)->m_flLastExecute == -1) {
(*it)->m_flLastExecute = global::m_flUniversalTime;
}
- if ((*it)->m_flLastExecute + (*it)->m_flTime <= 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;
@@ -41,3 +43,26 @@ auto ExcuteTimers() -> void {
}
}
}; // namespace GameTimer
+namespace GameTickRunTime {
+std::shared_mutex mutex_tickRunList;
+std::vector<_GameTickRunTime*> tickRunList;
+auto AddTickFunction(_GameTickRunTime* timer) -> void {
+ std::unique_lock lock(mutex_tickRunList);
+ tickRunList.push_back(timer);
+};
+auto CleanUpTickFunctions() -> void {
+ std::unique_lock lock(mutex_tickRunList);
+ for (auto it = tickRunList.begin(); it != tickRunList.end();) {
+ delete (*it);
+ it = tickRunList.erase(it);
+ }
+};
+auto ExcuteTickFunctions() -> void {
+ std::shared_lock lock(mutex_tickRunList);
+ for (auto it = tickRunList.begin(); it != tickRunList.end();) {
+ ScriptApis::RunTickCallBack(*it);
+ delete (*it);
+ it = tickRunList.erase(it);
+ }
+}
+}; // namespace GameTickRunTime
diff --git a/csgo2/timer.h b/csgo2/timer.h
index a5b79e6..2cf4889 100644
--- a/csgo2/timer.h
+++ b/csgo2/timer.h
@@ -1,18 +1,29 @@
#pragma once
#include "head.h"
class _GameTimer {
-public:
+ public:
float m_flTime;
float m_flLastExecute = -1;
bool m_bRepeat;
bool m_bPreserveMapChange;
- lua_State* m_luaVm;
+ lua_State* m_luaVm;
+ int m_iParamIndex;
+ int m_iLuaCallBackFn;
+};
+class _GameTickRunTime {
+ public:
+ 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
+
+namespace GameTickRunTime {
+auto AddTickFunction(_GameTickRunTime* timer) -> void;
+auto CleanUpTickFunctions() -> void;
+auto ExcuteTickFunctions() -> void;
+}; // namespace GameTickRunTime