L L4D2node

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 into addons/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.



        

        

          

Type inference is best-effort from the C signature - sanity-check the DHooks types before shipping.

Return-type handling cheatsheet (DHookReturn)