CTerrorPlayer::OnEndChangeLevel
0x008f8510 · 1072 bytes · __thiscall
_ZN13CTerrorPlayer16OnEndChangeLevelEv
Decompiled
undefined (1 param)
/* CTerrorPlayer::OnEndChangeLevel() */
undefined4 __thiscall CTerrorPlayer::OnEndChangeLevel(CTerrorPlayer *this)
{
CBaseEdict *this_00;
char cVar1;
undefined4 uVar2;
undefined4 uVar3;
undefined4 uVar4;
int iVar5;
int iVar6;
char *pcVar7;
char *pcVar8;
int iVar9;
Checkpoint *pCVar10;
undefined4 *puVar11;
int iVar12;
undefined1 *puVar13;
ResetCheckpointStats(this);
iVar9 = DAT_0100e518;
uVar2 = (**(code **)(*engine + 0x40))(engine,*(undefined4 *)(this + 0x30));
uVar3 = (**(code **)(*(int *)this + 0xb8))(this);
iVar12 = 0;
UTIL_LogPrintf("OnEndChangelevel %s(%d): %d saved players:\n",uVar3,uVar2,iVar9);
if (0 < DAT_0100e518) {
do {
while( true ) {
iVar9 = iVar12 * 4;
puVar11 = (undefined4 *)(g_SavedPlayers + iVar9);
uVar2 = KeyValues::GetInt((KeyValues *)*puVar11,"restoreState",0);
uVar3 = KeyValues::GetInt((KeyValues *)*puVar11,"userID",0);
uVar4 = KeyValues::GetString((KeyValues *)*puVar11,"idealName","");
UTIL_LogPrintf("\t%s(%d), state %d\n",uVar4,uVar3,uVar2);
iVar5 = KeyValues::GetInt((KeyValues *)*puVar11,"userID",0);
iVar6 = (**(code **)(*engine + 0x40))(engine,*(undefined4 *)(this + 0x30));
if (iVar5 != iVar6) break;
iVar5 = KeyValues::GetInt((KeyValues *)*puVar11,"restoreState",0);
if (iVar5 == 0) {
pcVar7 = (char *)KeyValues::GetString((KeyValues *)*puVar11,"targetMap","");
pcVar8 = *(char **)(gpGlobals + 0x3c);
if (pcVar8 == (char *)0x0) {
pcVar8 = "";
}
if ((pcVar7 == pcVar8) || (iVar5 = _V_stricmp(pcVar7,pcVar8), iVar5 == 0)) {
KeyValues::SetInt(*(KeyValues **)(g_SavedPlayers + iVar9),"restoreState",1);
iVar12 = (**(code **)(*engine + 0x40))(engine,*(undefined4 *)(this + 0x30));
KeyValues::SetInt(*(KeyValues **)(g_SavedPlayers + iVar9),"userID",iVar12);
this[0x3374] = (CTerrorPlayer)0x1;
(**(code **)(*(int *)this + 0x578))(this);
CDirector::OnPlayerTransitioned(TheDirector);
puVar11 = (undefined4 *)TransitionRestore(this);
iVar9 = CBaseEntity::GetTeamNumber((CBaseEntity *)this);
if (iVar9 == 2) {
cVar1 = CDirector::IsInTransition(TheDirector);
if (cVar1 == '\0') {
CDirector::IsInTransition(TheDirector);
}
else if ((puVar11 == (undefined4 *)0x0) ||
(iVar9 = KeyValues::GetInt((KeyValues *)*puVar11,"tookOverBot",0), iVar9 == 0)
) {
cVar1 = (**(code **)(*(int *)this + 300))(this);
if (cVar1 == '\0') {
pCVar10 = (Checkpoint *)TerrorNavMesh::GetInitialCheckpoint(TheNavMesh);
CheckpointRespawn(this,pCVar10);
if ((puVar11 != (undefined4 *)0x0) &&
(iVar9 = KeyValues::GetInt((KeyValues *)*puVar11,"skin",0),
iVar9 != *(int *)(this + 0x458))) {
if (this[0x6c] == (CTerrorPlayer)0x0) {
this_00 = *(CBaseEdict **)(this + 0x30);
if (this_00 != (CBaseEdict *)0x0) {
*(uint *)this_00 = *(uint *)this_00 | 0x101;
iVar12 = CBaseEdict::GetChangeAccessor(this_00);
*(undefined2 *)(iVar12 + 2) = 0;
}
}
else {
this[0x70] = (CTerrorPlayer)((byte)this[0x70] | 1);
}
*(int *)(this + 0x458) = iVar9;
}
}
}
else {
(**(code **)(*(int *)this + 300))(this);
}
CDirector::OnSurvivorAdded((CTerrorPlayer *)TheDirector);
}
return 1;
}
puVar13 = &DAT_00d539c2;
if (*(undefined1 **)(gpGlobals + 0x3c) != (undefined1 *)0x0) {
puVar13 = *(undefined1 **)(gpGlobals + 0x3c);
}
uVar2 = KeyValues::GetInt((KeyValues *)*puVar11,"userID",0);
uVar3 = KeyValues::GetString((KeyValues *)*puVar11,"idealName","");
UTIL_LogPrintf("Skipping saved player %s(%d) - we\'re on %s and it\'s only valid for %s\n"
,uVar3,uVar2,puVar13,pcVar7);
break;
}
iVar12 = iVar12 + 1;
uVar2 = KeyValues::GetInt((KeyValues *)*puVar11,"userID",0);
uVar3 = KeyValues::GetString((KeyValues *)*puVar11,"idealName","");
UTIL_LogPrintf("Skipping saved player %s(%d) - restore was already done\n",uVar3,uVar2);
if (DAT_0100e518 <= iVar12) {
return 0;
}
}
iVar12 = iVar12 + 1;
} while (iVar12 < DAT_0100e518);
}
return 0;
}
SourceMod gamedata
paste intoaddons/sourcemod/gamedata/<your_plugin>.txt
used as the SourceMod key — change to fit your plugin's convention
SourceMod library name (server / engine / matchmaking)
Just a Signatures{} block, ready to drop into a gamedata
file. Wire it up in your plugin however you like - SDKCall, DHooks,
raw memory ops, or anything else.
Signatures + Functions block. The plugin uses
DHookCreateFromConf - DHooks reads return type, this-type,
calling convention, and argument types straight from the gamedata. Less
boilerplate in the plugin, types travel with the gamedata.
Gamedata KeyValues
DHooks plugin example
Type inference is best-effort from the C signature - sanity-check the DHooks types before shipping.