CTerrorPlayer::CanBecomeGhost
0x009c6780 · 2741 bytes · __thiscall
_ZN13CTerrorPlayer14CanBecomeGhostEb
Decompiled
undefined (2 params)
/* CTerrorPlayer::CanBecomeGhost(bool) */
bool __thiscall CTerrorPlayer::CanBecomeGhost(CTerrorPlayer *this,bool param_1)
{
CBaseEdict *pCVar1;
code *pcVar2;
CBaseEntity *pCVar3;
short sVar4;
bool bVar5;
char cVar6;
int iVar7;
int iVar8;
Vector *this_00;
int *piVar9;
undefined4 uVar10;
CTerrorPlayer *this_01;
int *piVar11;
byte bVar12;
longdouble lVar13;
longdouble lVar14;
longdouble lVar15;
float fVar16;
float fVar17;
float local_70;
float local_6c;
int local_68;
float local_60;
int local_5c;
undefined4 local_58;
undefined4 local_54;
float local_50;
float local_4c;
float local_48;
float local_44;
float local_40;
float local_3c;
int local_38;
undefined4 local_34;
undefined4 local_30;
CBaseEntity *local_2c;
undefined4 local_28;
undefined4 local_24;
undefined1 local_20;
bVar12 = 0;
iVar7 = CBaseEntity::GetTeamNumber((CBaseEntity *)this);
if (iVar7 == 3) {
cVar6 = (**(code **)(*(int *)this + 0x558))(this);
if (cVar6 != '\0') goto LAB_009c67a6;
cVar6 = (**(code **)(*(int *)this + 300))(this);
if ((cVar6 == '\0') && (1 < *(int *)(this + 0x23bc) - 4U)) {
if (*(int *)(DirectorNoSpecials._28_4_ + 0x30) == 0) {
cVar6 = CDirector::IsFinale(TheDirector);
sVar4 = (short)this;
if ((cVar6 == '\0') && (*(char *)(*(int *)(TheDirector + 0x638) + 0x111) == '\0')) {
if (((*(int *)(this + 0x2c14) != 0) && (!param_1)) &&
(cVar6 = CTerrorGameRules::HasPlayerControlledZombies(), cVar6 == '\0')) {
if ((this[0x2cce] == (CTerrorPlayer)0x0) &&
(cVar6 = CDirectorScriptedEventManager::AreAllSurvivorsInBattlefield
(*(CDirectorScriptedEventManager **)(TheDirector + 0x638)),
cVar6 != '\0')) {
if (*(int *)(this + 0x2ca8) != 4) {
CServerNetworkProperty::NetworkStateChanged(sVar4 + 0x24);
*(undefined4 *)(this + 0x2ca8) = 4;
}
goto LAB_009c67a6;
}
this[0x2cce] = (CTerrorPlayer)0x1;
}
}
else {
cVar6 = CDirector::AreGhostsAllowedInFinale();
if (cVar6 == '\0') {
if (*(int *)(this + 0x2ca8) != 0x40) {
CServerNetworkProperty::NetworkStateChanged(sVar4 + 0x24);
*(undefined4 *)(this + 0x2ca8) = 0x40;
}
goto LAB_009c67a6;
}
}
cVar6 = CDirector::IsFinaleWon(TheDirector);
if ((cVar6 == '\0') &&
(cVar6 = CDirector::IsFinaleEscapeInProgress(TheDirector), cVar6 == '\0')) {
cVar6 = CDirector::HasAnySurvivorLeftSafeArea(TheDirector);
if ((cVar6 != '\0') ||
(cVar6 = CDirectorChallengeMode::TankRun
(*(CDirectorChallengeMode **)(TheDirector + 0x648)), cVar6 == '\0'))
{
if ((param_1) ||
(cVar6 = CDirector::HasAnySurvivorLeftSafeArea(TheDirector), cVar6 == '\0')) {
if (*(int *)(this + 0x2ca8) == 0) {
return true;
}
CServerNetworkProperty::NetworkStateChanged(sVar4 + 0x24);
*(undefined4 *)(this + 0x2ca8) = 0;
return true;
}
lVar13 = (longdouble)
CDirector::GetScriptValue
(TheDirector,"ZombieGhostDelayMin",
*(float *)(DirectorPrivate_DirectorZombieGhostDelayMin._28_4_ + 0x2c
));
lVar14 = (longdouble)
CDirector::GetScriptValue
(TheDirector,"ZombieGhostDelayMax",
*(float *)(DirectorPrivate_DirectorZombieGhostDelayMax._28_4_ + 0x2c
));
local_60 = (float)lVar14;
cVar6 = CTerrorGameRules::IsSurvivalMode();
if (cVar6 == '\0') {
lVar14 = (longdouble)GetScrimmageSphereRadius(this);
fVar16 = (float)lVar14;
piVar9 = (int *)GetScrimmageSphereCenter(this);
iVar7 = *(int *)(this + 0x2ca8);
piVar11 = &local_5c;
for (iVar8 = 3; iVar8 != 0; iVar8 = iVar8 + -1) {
*piVar11 = *piVar9;
piVar9 = piVar9 + (uint)bVar12 * -2 + 1;
piVar11 = piVar11 + (uint)bVar12 * -2 + 1;
}
if (iVar7 != 0) {
CServerNetworkProperty::NetworkStateChanged(sVar4 + 0x24);
*(undefined4 *)(this + 0x2ca8) = 0;
}
local_2c = (CBaseEntity *)0x0;
local_38 = local_5c;
local_28 = 0xbf800000;
local_34 = local_58;
local_24 = 0;
local_30 = local_54;
local_20 = 1;
ForEachSurvivor<FarthestSurvivorScan>((FarthestSurvivorScan *)&local_38);
pCVar3 = local_2c;
if (local_2c != (CBaseEntity *)0x0) {
if (local_2c[0x1a90] == (CBaseEntity)0x0) {
iVar7 = (**(code **)(*g_pGameRules + 0x7c))(g_pGameRules);
if (((byte)pCVar3[0x14d] & 8) != 0) {
CBaseEntity::CalcAbsolutePosition(pCVar3);
}
local_4c = *(float *)(iVar7 + 0x10) + *(float *)(pCVar3 + 0x2e4);
local_48 = *(float *)(iVar7 + 0x14) + *(float *)(pCVar3 + 0x2e8);
local_50 = *(float *)(iVar7 + 0xc) + *(float *)(pCVar3 + 0x2e0);
iVar7 = (**(code **)(*g_pGameRules + 0x7c))(g_pGameRules);
if (((byte)pCVar3[0x14d] & 8) != 0) {
CBaseEntity::CalcAbsolutePosition(pCVar3);
}
local_40 = *(float *)(iVar7 + 0x1c) + *(float *)(pCVar3 + 0x2e4);
local_3c = *(float *)(iVar7 + 0x20) + *(float *)(pCVar3 + 0x2e8);
local_44 = *(float *)(iVar7 + 0x18) + *(float *)(pCVar3 + 0x2e0);
}
else {
iVar7 = (**(code **)(*g_pGameRules + 0x7c))();
if (((byte)pCVar3[0x14d] & 8) != 0) {
CBaseEntity::CalcAbsolutePosition(pCVar3);
}
local_4c = *(float *)(iVar7 + 0x28) + *(float *)(pCVar3 + 0x2e4);
local_48 = *(float *)(iVar7 + 0x2c) + *(float *)(pCVar3 + 0x2e8);
local_50 = *(float *)(iVar7 + 0x24) + *(float *)(pCVar3 + 0x2e0);
iVar7 = (**(code **)(*g_pGameRules + 0x7c))(g_pGameRules);
if (((byte)pCVar3[0x14d] & 8) != 0) {
CBaseEntity::CalcAbsolutePosition(pCVar3);
}
local_40 = *(float *)(iVar7 + 0x34) + *(float *)(pCVar3 + 0x2e4);
local_3c = *(float *)(iVar7 + 0x38) + *(float *)(pCVar3 + 0x2e8);
local_44 = *(float *)(iVar7 + 0x30) + *(float *)(pCVar3 + 0x2e0);
}
lVar14 = (longdouble)Vector::DistTo((Vector *)&local_50,(Vector *)&local_44);
this_00 = (Vector *)(**(code **)(*(int *)pCVar3 + 0x288))(pCVar3);
lVar15 = (longdouble)Vector::DistTo(this_00,(Vector *)&local_5c);
fVar17 = (float)lVar14 * 0.5 + (float)lVar15;
if (fVar16 - fVar17 != *(float *)(this + 0x2c1c)) {
CServerNetworkProperty::NetworkStateChanged(sVar4 + 0x24);
*(float *)(this + 0x2c1c) = fVar16 - fVar17;
}
if (fVar16 == 0.0) {
local_60 = (float)(~-(uint)(fVar17 < 0.0) & (uint)(float)lVar13 |
(uint)local_60 & -(uint)(fVar17 < 0.0));
}
else {
fVar17 = fVar17 / fVar16;
if (1.0 <= fVar17) {
fVar17 = 1.0;
}
if (fVar17 <= 0.0) {
fVar17 = 0.0;
}
local_60 = fVar17 * ((float)lVar13 - local_60) + local_60;
}
}
}
else {
lVar13 = (longdouble)CDirector::GetSpecialRespawnInterval(TheDirector);
local_60 = (float)lVar13;
}
iVar7 = CDirector::GetPlayerCount(TheDirector,3,0);
iVar8 = (**(code **)(*(int *)TheDirector + 0x30))(TheDirector);
local_6c = 0.0;
if (iVar7 < iVar8) {
fVar16 = ((float)iVar7 / (float)iVar8) * local_60;
if (fVar16 <= *(float *)(ZombieGhostMinSpawnTime._28_4_ + 0x2c)) {
fVar16 = *(float *)(ZombieGhostMinSpawnTime._28_4_ + 0x2c);
}
local_6c = local_60 - fVar16;
local_60 = fVar16;
if (local_6c <= 0.0) {
local_6c = 0.0;
}
}
if ((((((*(float *)(ZombieGhostRunnerSpawnMultiplier._28_4_ + 0x2c) != 0.0) &&
(*(int *)(TheDirector + 0x1c0) < 1)) && (*(int *)(TheDirector + 0x1bc) < 1)) &&
((cVar6 = CDirector::IsFinale(TheDirector), cVar6 == '\0' &&
(*(char *)(*(int *)(TheDirector + 0x638) + 0x111) == '\0')))) &&
((this_01 = (CTerrorPlayer *)
CDirectorTacticalServices::GetHighestFlowSurvivor
(*(CDirectorTacticalServices **)(TheDirector + 0x628),0),
this_01 != (CTerrorPlayer *)0x0 &&
((cVar6 = (**(code **)(*(int *)this_01 + 0x7e8))(this_01), cVar6 == '\0' &&
(cVar6 = IsDominatedBySpecialInfected(this_01), cVar6 == '\0')))))) &&
(this_01[0x39f1] == (CTerrorPlayer)0x0)) {
local_38 = 0;
local_34 = 0;
local_30 = 0;
local_2c = (CBaseEntity *)0x0;
local_28 = 0;
/* try { // try from 009c7037 to 009c717d has its CatchHandler @ 009c71bf */
ForEachSurvivor<AmbulatorySurvivorCollector>((AmbulatorySurvivorCollector *)&local_38)
;
if (1 < (int)local_2c) {
bVar5 = true;
for (local_68 = 0; local_68 < (int)local_2c; local_68 = local_68 + 1) {
pCVar3 = *(CBaseEntity **)(local_38 + local_68 * 4);
if (this_01 != (CTerrorPlayer *)pCVar3) {
iVar7 = *(int *)(pCVar3 + 0x100);
lVar13 = (longdouble)(**(code **)(*(int *)pCVar3 + 0x7e4))(pCVar3);
if (5.0 < (float)lVar13 + (float)iVar7) {
bVar5 = false;
}
iVar7 = (**(code **)(*(int *)this_01 + 0x52c))(this_01);
if (iVar7 == 0) {
local_70 = -9999.0;
}
else {
local_70 = *(float *)(iVar7 + 0x154);
}
iVar7 = (**(code **)(*(int *)pCVar3 + 0x52c))(pCVar3);
if (iVar7 == 0) {
fVar16 = -9999.0;
}
else {
fVar16 = *(float *)(iVar7 + 0x154);
}
if (local_70 - fVar16 <
*(float *)(ZombieGhostRunnerSpawnMultiplierDist._28_4_ + 0x2c))
goto LAB_009c71a9;
if (((byte)pCVar3[0x14d] & 8) != 0) {
CBaseEntity::CalcAbsolutePosition(pCVar3);
}
if (((byte)this_01[0x14d] & 8) != 0) {
CBaseEntity::CalcAbsolutePosition((CBaseEntity *)this_01);
}
if ((*(float *)(this_01 + 0x2e0) - *(float *)(pCVar3 + 0x2e0)) *
(*(float *)(this_01 + 0x2e0) - *(float *)(pCVar3 + 0x2e0)) +
(*(float *)(this_01 + 0x2e4) - *(float *)(pCVar3 + 0x2e4)) *
(*(float *)(this_01 + 0x2e4) - *(float *)(pCVar3 + 0x2e4)) +
(*(float *)(this_01 + 0x2e8) - *(float *)(pCVar3 + 0x2e8)) *
(*(float *)(this_01 + 0x2e8) - *(float *)(pCVar3 + 0x2e8)) < 1.44e+06)
goto LAB_009c71a9;
}
}
if (!bVar5) {
local_60 = local_60 * *(float *)(ZombieGhostRunnerSpawnMultiplier._28_4_ + 0x2c);
if (local_60 <= *(float *)(ZombieGhostMinSpawnTime._28_4_ + 0x2c)) {
local_60 = *(float *)(ZombieGhostMinSpawnTime._28_4_ + 0x2c);
}
}
}
LAB_009c71a9:
CUtlVector<CTerrorPlayer*,CUtlMemory<CTerrorPlayer*,int>>::~CUtlVector
((CUtlVector<CTerrorPlayer*,CUtlMemory<CTerrorPlayer*,int>> *)&local_38);
}
cVar6 = CDirectorChallengeMode::TankRun
(*(CDirectorChallengeMode **)(TheDirector + 0x648));
if (cVar6 != '\0') {
lVar13 = (longdouble)
CDirector::GetScriptValue
(TheDirector,"TankRunSpawnDelay",
*(float *)(DirectorPrivate_DirectorTankRunSpawnDelay._28_4_ + 0x2c
));
local_60 = (float)lVar13;
}
if (*(float *)(this + 0x2c00) == -1.0) {
SetBecomeGhostAt(this,local_60 + *(float *)(gpGlobals + 0xc));
CDirector::DelayNextSpecialBotSpawn(TheDirector,local_6c);
piVar9 = (int *)(**(code **)(*gameeventmanager + 0x1c))
(gameeventmanager,"ghost_spawn_time",0,0);
if (piVar9 != (int *)0x0) {
pcVar2 = *(code **)(*piVar9 + 0x30);
uVar10 = (**(code **)(*engine + 0x40))(engine,*(undefined4 *)(this + 0x30));
(*pcVar2)(piVar9,"userid",uVar10);
(**(code **)(*piVar9 + 0x30))(piVar9,"spawntime",(int)local_60);
(**(code **)(*gameeventmanager + 0x20))(gameeventmanager,piVar9,0);
}
if (*(int *)(this + 0x2c14) != 0) {
CServerNetworkProperty::NetworkStateChanged(sVar4 + 0x24);
*(undefined4 *)(this + 0x2c14) = 0;
}
iVar7 = gpGlobals;
if (*(int *)(this + 0x2ca8) != 0) {
CServerNetworkProperty::NetworkStateChanged(sVar4 + 0x24);
iVar7 = gpGlobals;
*(undefined4 *)(this + 0x2ca8) = 0;
}
}
else {
iVar7 = gpGlobals;
if (3.0 < (*(float *)(this + 0x2c00) - *(float *)(gpGlobals + 0xc)) - local_60) {
SetBecomeGhostAt(this,*(float *)(gpGlobals + 0xc) + local_60);
iVar7 = gpGlobals;
}
}
return *(float *)(this + 0x2c00) <= *(float *)(iVar7 + 0xc) &&
*(float *)(iVar7 + 0xc) != *(float *)(this + 0x2c00);
}
if (*(int *)(this + 0x2ca8) != 2) {
CServerNetworkProperty::NetworkStateChanged(sVar4 + 0x24);
*(undefined4 *)(this + 0x2ca8) = 2;
}
}
else if (*(int *)(this + 0x2ca8) != 0x10) {
if (this[0x6c] == (CTerrorPlayer)0x0) {
pCVar1 = *(CBaseEdict **)(this + 0x30);
if (pCVar1 != (CBaseEdict *)0x0) {
*(uint *)pCVar1 = *(uint *)pCVar1 | 0x101;
iVar7 = CBaseEdict::GetChangeAccessor(pCVar1);
*(undefined2 *)(iVar7 + 2) = 0;
}
}
else {
this[0x70] = (CTerrorPlayer)((byte)this[0x70] | 1);
}
*(undefined4 *)(this + 0x2ca8) = 0x10;
}
}
else if (*(int *)(this + 0x2ca8) != 1) {
if (this[0x6c] == (CTerrorPlayer)0x0) {
pCVar1 = *(CBaseEdict **)(this + 0x30);
if (pCVar1 != (CBaseEdict *)0x0) {
*(uint *)pCVar1 = *(uint *)pCVar1 | 0x101;
iVar7 = CBaseEdict::GetChangeAccessor(pCVar1);
*(undefined2 *)(iVar7 + 2) = 0;
}
}
else {
this[0x70] = (CTerrorPlayer)((byte)this[0x70] | 1);
}
*(undefined4 *)(this + 0x2ca8) = 1;
}
goto LAB_009c67a6;
}
}
if (*(int *)(this + 0x2ca8) != 0) {
if (this[0x6c] == (CTerrorPlayer)0x0) {
pCVar1 = *(CBaseEdict **)(this + 0x30);
if (pCVar1 != (CBaseEdict *)0x0) {
*(uint *)pCVar1 = *(uint *)pCVar1 | 0x101;
iVar7 = CBaseEdict::GetChangeAccessor(pCVar1);
*(undefined2 *)(iVar7 + 2) = 0;
}
*(undefined4 *)(this + 0x2ca8) = 0;
}
else {
this[0x70] = (CTerrorPlayer)((byte)this[0x70] | 1);
*(undefined4 *)(this + 0x2ca8) = 0;
}
}
LAB_009c67a6:
SetBecomeGhostAt(this,-1.0);
return false;
}
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.