L L4D2node

ZombieManager::CanZombieSpawnHere

0x00a5a120 · 2114 bytes · __thiscall

_ZNK13ZombieManager18CanZombieSpawnHereERK6VectorP13TerrorNavArea15ZombieClassTypebP20CBaseCombatCharacter

Decompiled

undefined (6 params)

/* ZombieManager::CanZombieSpawnHere(Vector const&, TerrorNavArea*, ZombieClassType, bool,
   CBaseCombatCharacter*) const */

undefined4 __thiscall
ZombieManager::CanZombieSpawnHere
          (undefined4 this,Vector *param_1,CNavArea *param_2,int param_4,char param_5,
          IHandleEntity *param_6)

{
  CDirectorTacticalServices *this_00;
  CBaseEntity *this_01;
  char cVar1;
  char cVar2;
  undefined4 uVar3;
  int iVar4;
  int iVar5;
  uint uVar6;
  char *pcVar7;
  undefined4 uVar8;
  float fVar9;
  float fVar10;
  undefined4 local_e8;
  undefined4 local_e4;
  float local_e0;
  undefined4 local_dc;
  undefined4 local_d8;
  float local_d4;
  float local_cc;
  float local_c8;
  float local_c4;
  undefined4 local_c0;
  undefined4 local_bc;
  CBaseEntity *local_b8;
  undefined4 local_b4;
  undefined4 local_b0;
  float local_ac;
  float local_a8;
  float local_a4;
  float local_9c;
  float local_98;
  float local_94;
  undefined4 local_8c;
  undefined1 local_88;
  undefined1 local_87;
  Vector local_70 [12];
  Vector local_64 [32];
  float local_44;
  char local_39;
  
  uVar3 = CDirector::IsInTransition(TheDirector);
  if ((char)uVar3 != '\0') {
    return 0;
  }
  if ((param_4 != 0) && (((byte)param_2[0x54] & 1) != 0)) {
    return 0;
  }
  if ((param_6 == (IHandleEntity *)0x0) ||
     (cVar1 = (**(code **)(*(int *)param_6 + 0x16c))(param_6), cVar1 == '\0')) {
    uVar8 = 0x202420b;
  }
  else {
    cVar1 = (**(code **)(*(int *)param_6 + 0x16c))(param_6);
    uVar8 = 0x202420b;
    if (cVar1 != '\0') {
      uVar8 = (**(code **)(*(int *)param_6 + 0x7a0))(param_6,0);
    }
  }
  iVar4 = (**(code **)(*g_pGameRules + 0x7c))(g_pGameRules);
  iVar5 = (**(code **)(*g_pGameRules + 0x7c))(g_pGameRules);
  local_87 = 0;
  local_bc = 0;
  local_b8 = (CBaseEntity *)0x0;
  local_b4 = 0;
  local_8c = 0;
  local_9c = (*(float *)(iVar4 + 0x18) - *(float *)(iVar5 + 0xc)) * 0.5;
  local_98 = (*(float *)(iVar4 + 0x1c) - *(float *)(iVar5 + 0x10)) * 0.5;
  local_94 = (*(float *)(iVar4 + 0x20) - *(float *)(iVar5 + 0x14)) * 0.5;
  local_88 = local_98 * local_98 + local_9c * local_9c + local_94 * local_94 < 1e-06;
  local_ac = (*(float *)(iVar4 + 0x18) + *(float *)(iVar5 + 0xc)) * 0.5;
  local_cc = *(float *)param_1 + local_ac;
  local_a8 = (*(float *)(iVar4 + 0x1c) + *(float *)(iVar5 + 0x10)) * 0.5;
  local_c8 = *(float *)(param_1 + 4) + local_a8;
  local_a4 = (*(float *)(iVar4 + 0x20) + *(float *)(iVar5 + 0x14)) * 0.5;
  local_c4 = *(float *)(param_1 + 8) + local_a4;
  local_ac = -local_ac;
  local_a8 = -local_a8;
  local_a4 = -local_a4;
  CTraceFilterSimple::CTraceFilterSimple
            ((CTraceFilterSimple *)&local_dc,param_6,8,(_func_bool_IHandleEntity_ptr_int *)0x0);
  (**(code **)(*enginetrace + 0x14))(enginetrace,&local_cc,uVar8,(CTraceFilterSimple *)&local_dc);
  if (*(int *)(r_visualizetraces._28_4_ + 0x30) != 0) {
    DebugDrawLine(local_70,local_64,0xff,0xff,0,true,-1.0);
  }
  if ((local_39 != '\0') || (local_44 < 1.0)) {
    if (*(int *)(ZombieDebug._28_4_ + 0x30) == 0) {
      return uVar3;
    }
    iVar4 = CDirector::GetCommonInfectedLimit(TheDirector);
    if (0 < iVar4) {
      uVar8 = ZombieClassName(param_4);
      pcVar7 = "(mob) ";
      if (param_5 == '\0') {
        pcVar7 = "";
      }
      Msg("CanZombieSpawnHere: Spot blocked (%.0f, %.0f, %.0f) for a %s%s\n",
          (double)*(float *)param_1,(double)*(float *)(param_1 + 4),(double)*(float *)(param_1 + 8),
          pcVar7,uVar8);
      return uVar3;
    }
    return uVar3;
  }
  if (param_2 == (CNavArea *)0x0) {
    param_2 = (CNavArea *)CNavMesh::GetNavArea(TheNavMesh,param_1,120.0);
    cVar1 = CDirectorChallengeMode::TankRun(*(CDirectorChallengeMode **)(TheDirector + 0x648));
    if (s_ManualSpawn != '\0') goto LAB_00a5a3bf;
    if (param_2 != (CNavArea *)0x0) goto LAB_00a5a440;
  }
  else {
    cVar1 = CDirectorChallengeMode::TankRun(*(CDirectorChallengeMode **)(TheDirector + 0x648));
    if (s_ManualSpawn != '\0') goto LAB_00a5a3bf;
LAB_00a5a440:
    uVar6 = *(uint *)(param_2 + 300);
    if ((uVar6 & 0x800) != 0) {
      cVar2 = CDirector::HasAnySurvivorLeftSafeArea(TheDirector);
      if (cVar2 == '\0') {
        return 0;
      }
      uVar6 = *(uint *)(param_2 + 300);
    }
    if (((uVar6 & 0x80) != 0) && (cVar1 == '\0')) {
      return 0;
    }
    cVar2 = CNavArea::IsBlocked(param_2,3,false);
    if (cVar2 != '\0') {
      return 0;
    }
    uVar3 = CZombieBorder::IsBehindZombieBorder((Vector *)(param_2 + 0x2c));
    if ((char)uVar3 != '\0') {
      return 0;
    }
    if (((byte)param_2[0x12d] & 0x10) != 0) {
      iVar4 = UTIL_GetClosestPlayer(param_1,2,&local_cc);
      if ((iVar4 != 0) && (local_cc < *(float *)(NavObscureRange._28_4_ + 0x2c))) {
        return uVar3;
      }
      goto LAB_00a5a3bf;
    }
  }
  if (cVar1 == '\0') {
    this_00 = *(CDirectorTacticalServices **)(TheDirector + 0x628);
    local_e8 = *(undefined4 *)param_1;
    local_e4 = *(undefined4 *)(param_1 + 4);
    local_e0 = *(float *)(param_1 + 8) + 56.8;
                    /* try { // try from 00a5a6c2 to 00a5a6c6 has its CatchHandler @ 00a5a97b */
    cVar1 = CDirectorTacticalServices::IsVisibleToTeam
                      (this_00,(Vector *)&local_e8,2,3,0.0,(TerrorNavArea *)param_2,
                       (CBaseEntity *)0x0);
    if (cVar1 == '\0') {
      local_dc = *(undefined4 *)param_1;
      local_d8 = *(undefined4 *)(param_1 + 4);
      local_d4 = *(float *)(param_1 + 8) + 35.5;
                    /* try { // try from 00a5a8f7 to 00a5a8fb has its CatchHandler @ 00a5a987 */
      cVar1 = CDirectorTacticalServices::IsVisibleToTeam
                        (this_00,(Vector *)&local_dc,2,3,0.0,(TerrorNavArea *)param_2,
                         (CBaseEntity *)0x0);
      if (cVar1 == '\0') {
        local_cc = *(float *)param_1;
        local_c8 = *(float *)(param_1 + 4);
        local_c4 = *(float *)(param_1 + 8) + 1.0;
                    /* try { // try from 00a5a969 to 00a5a96d has its CatchHandler @ 00a5a985 */
        cVar1 = CDirectorTacticalServices::IsVisibleToTeam
                          (this_00,(Vector *)&local_cc,2,3,0.0,(TerrorNavArea *)param_2,
                           (CBaseEntity *)0x0);
        if (cVar1 == '\0') goto LAB_00a5a3bf;
      }
    }
    uVar3 = CDirector::IsLocationFoggedToSurvivors(TheDirector,param_1);
    if ((char)uVar3 == '\0') {
      if (param_2 == (CNavArea *)0x0) {
        return 0;
      }
      TerrorNavArea::MarkAreaCleared((TerrorNavArea *)param_2,(CTerrorPlayer *)0x0);
      return uVar3;
    }
  }
LAB_00a5a3bf:
  g_IsZombieSpawnMobRush = param_5;
  if (param_4 == 9) {
    return 0;
  }
  g_ZombieClass = param_4;
  if (param_4 != 0) {
    if (s_ManualSpawn == '\0') {
      fVar10 = *(float *)(ZombieSpawnSafetyRange._28_4_ + 0x2c);
      local_bc = CONCAT31(local_bc._1_3_,1);
      local_c0 = 2;
      local_b8 = (CBaseEntity *)0x0;
      local_b4 = 0x4e6e6b28;
      local_b0 = 0;
      local_cc = *(float *)param_1;
      local_c8 = *(float *)(param_1 + 4);
      local_c4 = *(float *)(param_1 + 8);
      ForEachPlayer<ClosestPlayerScan>((ClosestPlayerScan *)&local_cc);
      this_01 = local_b8;
      if (local_b8 == (CBaseEntity *)0x0) {
        return 0;
      }
      if (((byte)local_b8[0x14d] & 8) == 0) {
        fVar9 = *(float *)(local_b8 + 0x2e8) - *(float *)(param_1 + 8);
        fVar10 = fVar10 - ABS(fVar9);
      }
      else {
        CBaseEntity::CalcAbsolutePosition(local_b8);
        fVar9 = *(float *)(this_01 + 0x2e8) - *(float *)(param_1 + 8);
        fVar10 = fVar10 - ABS(fVar9);
        if (((byte)this_01[0x14d] & 8) != 0) {
          CBaseEntity::CalcAbsolutePosition(this_01);
          fVar9 = *(float *)(this_01 + 0x2e8) - *(float *)(param_1 + 8);
        }
      }
      if ((*(float *)(this_01 + 0x2e4) - *(float *)(param_1 + 4)) *
          (*(float *)(this_01 + 0x2e4) - *(float *)(param_1 + 4)) +
          (*(float *)(this_01 + 0x2e0) - *(float *)param_1) *
          (*(float *)(this_01 + 0x2e0) - *(float *)param_1) + fVar9 * fVar9 < fVar10 * fVar10) {
        return 0;
      }
    }
    if ((((g_ZombieClass == 7) && (s_ManualSpawn == '\0')) &&
        (*(float *)(param_2 + 0x154) <= 0.0 && *(float *)(param_2 + 0x154) != 0.0)) &&
       (cVar1 = CDirector::IsFinale(TheDirector), cVar1 == '\0')) {
      g_ZombieClass = 0;
      Warning("Witch converted to a normal Infected!\n");
    }
  }
  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)