L L4D2node

CInfoZombieSpawn::SpawnZombie

0x008d49c0 · 1379 bytes · __thiscall

_ZN16CInfoZombieSpawn11SpawnZombieER11inputdata_t

Decompiled

undefined (2 params)

/* CInfoZombieSpawn::SpawnZombie(inputdata_t&) */

void __thiscall CInfoZombieSpawn::SpawnZombie(CInfoZombieSpawn *this,inputdata_t *param_1)

{
  char cVar1;
  KeyValues *pKVar2;
  int iVar3;
  int iVar4;
  char *pcVar5;
  undefined1 *puVar6;
  int *piVar7;
  undefined4 *puVar8;
  CBaseEntity *this_00;
  Infected *this_01;
  char *pcVar9;
  int iVar10;
  uint uVar11;
  int in_GS_OFFSET;
  char *local_150 [3];
  undefined4 local_144;
  undefined4 local_140;
  undefined4 local_13c;
  undefined4 local_138;
  undefined4 local_134;
  undefined4 local_130;
  CFmtStrN<256> local_12c [268];
  int local_20;
  
  local_20 = *(int *)(in_GS_OFFSET + 0x14);
  pKVar2 = (KeyValues *)CDirector::GetPopulationData(TheDirector);
  if (pKVar2 == (KeyValues *)0x0) {
    puVar6 = &DAT_00d539c2;
    if (*(undefined1 **)(this + 0x7c) != (undefined1 *)0x0) {
      puVar6 = *(undefined1 **)(this + 0x7c);
    }
    DevMsg("%s failed to spawn: missing director population data\n",puVar6);
  }
  else {
    pcVar9 = *(char **)(this + 0x440);
    if (pcVar9 == (char *)0x0) {
      pcVar9 = "";
    }
    pKVar2 = (KeyValues *)KeyValues::FindKey(pKVar2,pcVar9,false);
    if (pKVar2 == (KeyValues *)0x0) {
      puVar6 = *(undefined1 **)(this + 0x7c);
      if (puVar6 == (undefined1 *)0x0) {
        puVar6 = &DAT_00d539c2;
      }
      DevMsg("%s failed to spawn: invalid population \'%s\'\n",puVar6,pcVar9);
    }
    else {
      iVar3 = RandomInt(1,100);
      pKVar2 = (KeyValues *)KeyValues::GetFirstSubKey(pKVar2);
      if (pKVar2 != (KeyValues *)0x0) {
        iVar10 = 0;
        do {
          iVar4 = KeyValues::GetInt(pKVar2,(char *)0x0,0);
          iVar10 = iVar10 + iVar4;
          if (iVar3 <= iVar10) {
            uVar11 = 3;
            pcVar5 = (char *)KeyValues::GetName(pKVar2);
            CFmtStrN<256>::CFmtStrN(local_12c,"models/infected/%s.mdl",pcVar5);
            AllocPooledString((char *)local_150);
            iVar3 = StringAfterPrefix(pcVar5,"hunter");
            if (iVar3 == 0) {
              uVar11 = 6;
              iVar3 = StringAfterPrefix(pcVar5,"charger");
              if (iVar3 == 0) {
                uVar11 = 1;
                iVar3 = StringAfterPrefix(pcVar5,"smoker");
                if (iVar3 == 0) {
                  uVar11 = 2;
                  iVar3 = StringAfterPrefix(pcVar5,"boomer");
                  if (iVar3 == 0) {
                    uVar11 = 7;
                    iVar3 = StringAfterPrefix(pcVar5,"witch");
                    if (iVar3 == 0) {
                      iVar3 = StringAfterPrefix(pcVar5,"tank");
                      uVar11 = ~-(uint)(iVar3 == 0) & 8;
                    }
                  }
                }
              }
            }
            if (local_150[0] != (char *)0x0) {
              if (((byte)this[0x14d] & 8) == 0) {
                local_144 = *(undefined4 *)(this + 0x2e0);
                local_140 = *(undefined4 *)(this + 0x2e4);
                local_13c = *(undefined4 *)(this + 0x2e8);
                local_138 = vec3_angle;
                local_130 = DAT_01053d44;
              }
              else {
                CBaseEntity::CalcAbsolutePosition((CBaseEntity *)this);
                local_144 = *(undefined4 *)(this + 0x2e0);
                local_140 = *(undefined4 *)(this + 0x2e4);
                local_13c = *(undefined4 *)(this + 0x2e8);
                local_138 = vec3_angle;
                local_134 = DAT_01053d40;
                local_130 = DAT_01053d44;
                if ((*(uint *)(this + 0x14c) & 0x800) != 0) {
                  CBaseEntity::CalcAbsolutePosition((CBaseEntity *)this);
                }
              }
              local_134 = *(undefined4 *)(this + 0x380);
              EnableManualSpawnOverride();
              if (uVar11 - 1 < 6) {
                this_00 = (CBaseEntity *)
                          ZombieManager::SpawnSpecial(TheZombieManager,uVar11,&local_144,&local_138)
                ;
LAB_008d4c70:
                if (this_00 == (CBaseEntity *)0x0) goto LAB_008d4bab;
LAB_008d4c78:
                piVar7 = (int *)(**(code **)(*(int *)this_00 + 0x144))(this_00);
                if ((piVar7 != (int *)0x0) &&
                   (uVar11 = (**(code **)(*piVar7 + 0x544))(piVar7), uVar11 < 9)) {
                  COutputEvent::FireOutput
                            ((COutputEvent *)(this + uVar11 * 0x18 + 0x44c),*(CBaseEntity **)param_1
                             ,(CBaseEntity *)this,0.0);
                }
                puVar8 = (undefined4 *)(**(code **)(*(int *)this_00 + 0xc))(this_00);
                *(undefined4 *)(this + 0x448) = *puVar8;
              }
              else {
                if (uVar11 == 7) {
                  iVar3 = V_stristr(local_150[0],"bride");
                  if (iVar3 == 0) {
                    this_00 = (CBaseEntity *)
                              ZombieManager::SpawnWitch
                                        (TheZombieManager,(Vector *)&local_144,(QAngle *)&local_138)
                    ;
                  }
                  else {
                    this_00 = (CBaseEntity *)
                              ZombieManager::SpawnWitchBride
                                        (TheZombieManager,(Vector *)&local_144,(QAngle *)&local_138)
                    ;
                  }
                  goto LAB_008d4c70;
                }
                if (uVar11 == 8) {
                  this_00 = (CBaseEntity *)
                            ZombieManager::SpawnTank
                                      (TheZombieManager,(Vector *)&local_144,(QAngle *)&local_138);
                  if ((this[0x444] != (CInfoZombieSpawn)0x0) &&
                     (cVar1 = CTerrorGameRules::HasPlayerControlledZombies(), cVar1 != '\0')) {
                    CDirector::TryOfferingTankBot(TheDirector,this_00,true);
                  }
                  goto LAB_008d4c70;
                }
                if ((uVar11 == 0) &&
                   (this_00 = (CBaseEntity *)CreateEntityByName("infected",-1,true),
                   this_00 != (CBaseEntity *)0x0)) {
                  CBaseEntity::SetAbsAngles(this_00,(QAngle *)&local_138);
                  CBaseEntity::SetAbsOrigin(this_00,(Vector *)&local_144);
                  (**(code **)(*(int *)this_00 + 0x70))(this_00,local_150[0]);
                  DispatchSpawn(this_00,true);
                  this_01 = (Infected *)(**(code **)(*(int *)this_00 + 0x14c))(this_00);
                  if (this_01 != (Infected *)0x0) {
                    Infected::AttackSurvivorTeam(this_01);
                  }
                  goto LAB_008d4c78;
                }
LAB_008d4bab:
                *(undefined4 *)(this + 0x448) = 0xffffffff;
              }
              DisableManualSpawnOverride();
              goto LAB_008d4bf0;
            }
            break;
          }
          pKVar2 = (KeyValues *)KeyValues::GetNextKey(pKVar2);
        } while (pKVar2 != (KeyValues *)0x0);
      }
      puVar6 = &DAT_00d539c2;
      if (*(undefined1 **)(this + 0x7c) != (undefined1 *)0x0) {
        puVar6 = *(undefined1 **)(this + 0x7c);
      }
      DevMsg("%s failed to spawn: incomplete population \'%s\'\n",puVar6,pcVar9);
    }
  }
LAB_008d4bf0:
  if (local_20 != *(int *)(in_GS_OFFSET + 0x14)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return;
}

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)