CDirector::OnThreatEncountered
0x0088abd0 · 1229 bytes · __thiscall
_ZN9CDirector19OnThreatEncounteredEP13TerrorNavArea
Decompiled
undefined (2 params)
/* CDirector::OnThreatEncountered(TerrorNavArea*) */
undefined4 __thiscall CDirector::OnThreatEncountered(CDirector *this,TerrorNavArea *param_1)
{
bool bVar1;
char cVar2;
undefined4 uVar3;
TerrorNavArea *this_00;
CBaseEntity *pCVar4;
int iVar5;
longdouble lVar6;
float local_48;
float local_44;
int local_40;
Vector local_34 [12];
undefined4 local_28;
float local_24;
undefined4 local_20;
cVar2 = AreBossesProhibited(this);
if (((cVar2 != '\0') || (uVar3 = IsInCommentaryMode(), (char)uVar3 != '\0')) ||
(*(int *)(DirectorNoSpecials._28_4_ + 0x30) != 0)) {
return 0;
}
cVar2 = CDirectorVersusMode::IsOverridingThreats();
if (cVar2 != '\0') {
return uVar3;
}
if (**(int **)(this + 0x638) != 5) {
return 0;
}
cVar2 = CTerrorGameRules::IsSurvivalMode();
if (cVar2 != '\0') {
return 0;
}
cVar2 = CDirectorChallengeMode::IgnoreNavThreatAreas(*(CDirectorChallengeMode **)(this + 0x648));
if (cVar2 != '\0') {
return uVar3;
}
if (param_1 == (TerrorNavArea *)0x0) {
return uVar3;
}
if (((byte)param_1[300] & 0x40) != 0) {
return uVar3;
}
local_40 = GetThreatType(this);
if (*(int *)(DirectorForceWitch._28_4_ + 0x30) == 0) {
if (*(int *)(DirectorForceTank._28_4_ + 0x30) == 0) {
if (1 < local_40 - 7U) goto LAB_0088ae5e;
if (local_40 == 7) goto LAB_0088ac7c;
}
else {
local_40 = 8;
}
local_48 = 32.0;
local_44 = 72.0;
}
else {
local_40 = 7;
LAB_0088ac7c:
local_48 = 26.0;
local_44 = 68.0;
}
bVar1 = true;
iVar5 = 0x65;
this_00 = param_1;
while (iVar5 = iVar5 + -1, iVar5 != 0) {
if (bVar1) {
local_28 = *(undefined4 *)(this_00 + 0x2c);
local_24 = *(float *)(this_00 + 0x30);
local_20 = *(undefined4 *)(this_00 + 0x34);
cVar2 = CDirectorTacticalServices::IsSpawnLocationVisibleToTeam
(*(CDirectorTacticalServices **)(TheDirector + 0x628),(Vector *)&local_28,2,
3,this_00,local_48,local_44);
if (cVar2 == '\0') goto LAB_0088ad97;
}
this_00 = (TerrorNavArea *)TerrorNavArea::GetNextEscapeStep(this_00,(NavTraverseType *)0x0);
if (((this_00 == (TerrorNavArea *)0x0) || (this_00 == *(TerrorNavArea **)(TheNavMesh + 0x608)))
|| (cVar2 = CZombieBorder::IsBehindZombieBorder((Vector *)(this_00 + 0x2c)), cVar2 != '\0'))
goto LAB_0088ad49;
bVar1 = false;
if ((((byte)this_00[0x12e] & 8) == 0) &&
(24.0 <= *(float *)(this_00 + 0x10) - *(float *)(this_00 + 4))) {
bVar1 = 24.0 <= *(float *)(this_00 + 0x14) - *(float *)(this_00 + 8);
}
}
this_00 = param_1;
if (!bVar1) {
LAB_0088ad49:
if (*(int *)(ZombieDebug._28_4_ + 0x30) != 0) {
Msg(
"Tank/Witch threat spawn: No non-visible valid areas between threat area and goal area! Choosing random area.\n"
);
}
iVar5 = 5;
do {
cVar2 = ZombieManager::GetRandomPZSpawnPosition(TheZombieManager,8,5,0,(Vector *)&local_28);
if ((((cVar2 != '\0') &&
(this_00 = (TerrorNavArea *)CNavMesh::GetNavArea(TheNavMesh,(Vector *)&local_28,120.0),
this_00 != (TerrorNavArea *)0x0)) && ((*(uint *)(this_00 + 300) & 0x90882) == 0)) &&
(cVar2 = CZombieBorder::IsBehindZombieBorder((Vector *)(this_00 + 0x2c)), cVar2 == '\0'))
break;
iVar5 = iVar5 + -1;
this_00 = param_1;
} while (iVar5 != 0);
}
LAB_0088ad97:
param_1 = this_00;
if (local_40 == 7) {
lVar6 = (longdouble)RandomFloat(0,0x43b40000);
local_24 = (float)lVar6;
local_28 = 0;
local_20 = 0;
iVar5 = ZombieManager::SpawnWitch(TheZombieManager,param_1,(QAngle *)&local_28,true);
if (iVar5 == 0) {
return 1;
}
SearchSurroundingAreas<RemoveWanderersScan>
((CNavArea *)param_1,(Vector *)(param_1 + 0x2c),(RemoveWanderersScan *)&local_28,
*(float *)(DirectorThreatClearRadius._28_4_ + 0x2c),0,-1);
}
else if ((*(int *)(this + 0x1c0) == 0) ||
(cVar2 = CTerrorGameRules::HasPlayerControlledZombies(), cVar2 == '\0')) {
lVar6 = (longdouble)RandomFloat(0,0x43b40000);
local_24 = (float)lVar6;
local_28 = 0;
local_20 = 0;
pCVar4 = (CBaseEntity *)
ZombieManager::SpawnTank(TheZombieManager,param_1,(QAngle *)&local_28,true);
if (pCVar4 == (CBaseEntity *)0x0) {
cVar2 = ZombieManager::GetRandomPZSpawnPosition(TheZombieManager,8,10,0,local_34);
if (cVar2 == '\0') {
return 1;
}
lVar6 = (longdouble)RandomFloat(0,0x43b40000);
local_24 = (float)lVar6;
local_28 = 0;
local_20 = 0;
pCVar4 = (CBaseEntity *)
ZombieManager::SpawnTank(TheZombieManager,local_34,(QAngle *)&local_28);
if (pCVar4 == (CBaseEntity *)0x0) {
return 1;
}
}
this[0x4f5] = (CDirector)0x0;
TryOfferingTankBot(this,pCVar4,true);
local_40 = 8;
}
else {
local_40 = 8;
}
LAB_0088ae5e:
iVar5 = *(int *)(this + 0x450);
*(int *)(this + 0x450) = iVar5 + 1;
if (iVar5 + 1 < 3) {
return 1;
}
(**(code **)(*(int *)this + 0x60))(this,local_40);
return 1;
}
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.