L L4D2node

CDirector::UpdateTankSpawns

0x0087ee70 · 2275 bytes · __thiscall

_ZN9CDirector16UpdateTankSpawnsEv

Decompiled

undefined (1 param)

/* CDirector::UpdateTankSpawns() */

void __thiscall CDirector::UpdateTankSpawns(CDirector *this)

{
  float fVar1;
  uint uVar2;
  bool bVar3;
  char cVar4;
  CBaseEntity *pCVar5;
  int iVar6;
  int *piVar7;
  undefined4 uVar8;
  undefined *puVar9;
  int iVar10;
  int iVar11;
  CBaseCombatCharacter *pCVar12;
  int iVar13;
  longdouble lVar14;
  int *piVar15;
  int local_4c;
  int local_48;
  CUtlMemory<int,int> *local_40;
  int local_34;
  int *local_30;
  undefined4 local_2c;
  undefined4 local_28;
  int local_24;
  int *local_20;
  
  if (0.0 < *(float *)(this + 0x270)) {
    return;
  }
  cVar4 = AreBossesProhibited(this);
  if ((cVar4 != '\0') || (cVar4 = IsInCommentaryMode(), cVar4 != '\0')) {
    ReleaseLotteryTank(this);
    return;
  }
  if (0.0 < *(float *)(this + 0x180)) {
    lVar14 = (longdouble)CountdownTimer::Now();
    if (*(float *)(this + 0x180) <= (float)lVar14) {
      if (*(float *)(this + 0x180) != -1.0) {
        (**(code **)(*(int *)(this + 0x178) + 4))(this + 0x178,this + 0x180);
        *(undefined4 *)(this + 0x180) = 0xbf800000;
      }
      fVar1 = *(float *)(DirectorTankLotterySelectionTime._28_4_ + 0x2c);
      lVar14 = (longdouble)CountdownTimer::Now();
      if ((float)lVar14 + fVar1 != *(float *)(this + 0x18c)) {
        (**(code **)(*(int *)(this + 0x184) + 4))(this + 0x184,this + 0x18c);
        *(float *)(this + 0x18c) = (float)lVar14 + fVar1;
      }
      if (fVar1 != *(float *)(this + 0x188)) {
        (**(code **)(*(int *)(this + 0x184) + 4))(this + 0x184,this + 0x188);
        *(float *)(this + 0x188) = fVar1;
      }
      local_30 = (int *)0x0;
      local_2c = 0;
      local_28 = 0;
      local_24 = 0;
      local_20 = (int *)0x0;
      if (*(int *)(DirectorTankOfferDebug._28_4_ + 0x30) != 0) {
        DevMsg("TANK OFFER: Looking for players\n");
      }
      if (0 < *(int *)(gpGlobals + 0x14)) {
        iVar13 = 0;
        iVar11 = 1;
        local_48 = 0;
        local_4c = 0;
        do {
                    /* try { // try from 0087f00b to 0087f162 has its CatchHandler @ 0087f789 */
          pCVar5 = (CBaseEntity *)UTIL_PlayerByIndex(iVar11);
          if ((pCVar5 == (CBaseEntity *)0x0) ||
             (cVar4 = (**(code **)(*(int *)pCVar5 + 0x16c))(pCVar5), cVar4 == '\0')) {
            pCVar5 = (CBaseEntity *)0x0;
          }
          piVar7 = &local_34;
          local_34 = 0;
          CUtlVector<int,CUtlMemory<int,int>>::InsertBefore
                    ((CUtlVector<int,CUtlMemory<int,int>> *)&local_30,local_24,piVar7);
                    /* try { // try from 0087f3b5 to 0087f423 has its CatchHandler @ 0087f789 */
          if ((((pCVar5 != (CBaseEntity *)0x0) && (*(int *)(pCVar5 + 0x30) != 0)) &&
              (*(int *)(pCVar5 + 0x30) - *(int *)(gpGlobals + 0x58) >> 4 != 0)) &&
             (((iVar6 = CBaseEntity::GetTeamNumber(pCVar5), iVar6 == 3 &&
               (cVar4 = (**(code **)(*(int *)pCVar5 + 0x778))(pCVar5), cVar4 == '\0')) &&
              ((cVar4 = (**(code **)(*(int *)pCVar5 + 300))(pCVar5), cVar4 == '\0' ||
               ((iVar6 = CBaseEntity::GetTeamNumber(pCVar5), iVar6 != 3 ||
                (iVar6 = (**(code **)(*(int *)pCVar5 + 0x544))(pCVar5), iVar6 != 8)))))))) {
            local_48 = local_48 + 1;
            *(undefined4 *)((int)local_30 + iVar13) = *(undefined4 *)(pCVar5 + 0x3088);
            piVar15 = *(int **)((int)local_30 + iVar13);
            local_4c = local_4c + (int)piVar15;
            if (*(int *)(DirectorTankOfferDebug._28_4_ + 0x30) != 0) {
              uVar8 = (**(code **)(*(int *)pCVar5 + 0xb8))(pCVar5);
              DevMsg("TANK OFFER: Player %s has %d tickets\n",uVar8,piVar15);
              piVar7 = piVar15;
            }
          }
          iVar11 = iVar11 + 1;
          iVar13 = iVar13 + 4;
        } while (iVar11 <= *(int *)(gpGlobals + 0x14));
        if (local_48 != 0) {
          *(undefined4 *)(this + 0x398) = 0;
          if (local_4c < 1) {
            iVar11 = RandomInt(1,local_48);
            if (*(int *)(DirectorTankOfferDebug._28_4_ + 0x30) != 0) {
              DevMsg("TANK OFFER: No tickets, choosing randomly\n",local_48,piVar7);
            }
            iVar13 = DirectorTankOfferDebug._28_4_;
            if (0 < *(int *)(gpGlobals + 0x14)) {
              iVar6 = 1;
              do {
                pCVar12 = (CBaseCombatCharacter *)UTIL_PlayerByIndex(iVar6);
                    /* try { // try from 0087f6f5 to 0087f6f9 has its CatchHandler @ 0087f789 */
                if ((((pCVar12 != (CBaseCombatCharacter *)0x0) &&
                     (cVar4 = (**(code **)(*(int *)pCVar12 + 0x16c))(pCVar12), cVar4 != '\0')) &&
                    (*(int *)(pCVar12 + 0x30) != 0)) &&
                   (((*(int *)(pCVar12 + 0x30) - *(int *)(gpGlobals + 0x58) >> 4 != 0 &&
                     (iVar13 = CBaseEntity::GetTeamNumber((CBaseEntity *)pCVar12), iVar13 == 3)) &&
                    (((cVar4 = (**(code **)(*(int *)pCVar12 + 0x778))(pCVar12), cVar4 == '\0' &&
                      ((cVar4 = (**(code **)(*(int *)pCVar12 + 300))(pCVar12), cVar4 == '\0' ||
                       (cVar4 = CBaseCombatCharacter::IsA(pCVar12,8), cVar4 == '\0')))) &&
                     (iVar11 = iVar11 + -1, iVar11 < 1)))))) {
                  *(int *)(this + 0x398) = iVar6;
                  iVar13 = DirectorTankOfferDebug._28_4_;
                  break;
                }
                iVar6 = iVar6 + 1;
                iVar13 = DirectorTankOfferDebug._28_4_;
              } while (iVar6 <= *(int *)(gpGlobals + 0x14));
            }
          }
          else {
            iVar11 = RandomInt(1,local_4c);
            if (*(int *)(DirectorTankOfferDebug._28_4_ + 0x30) != 0) {
                    /* try { // try from 0087f5eb to 0087f65e has its CatchHandler @ 0087f789 */
              DevMsg("TANK OFFER: Winning ticket = %d\n",iVar11,piVar7);
            }
            iVar13 = DirectorTankOfferDebug._28_4_;
            if (0 < *(int *)(gpGlobals + 0x14)) {
              iVar11 = iVar11 - *local_30;
              iVar6 = 1;
              if (iVar11 < 1) {
                iVar10 = 1;
              }
              else {
                do {
                  iVar10 = iVar6 + 1;
                  if (*(int *)(gpGlobals + 0x14) < iVar10) goto LAB_0087f113;
                  iVar11 = iVar11 - local_30[iVar6];
                  iVar6 = iVar10;
                } while (0 < iVar11);
              }
              *(int *)(this + 0x398) = iVar10;
            }
          }
LAB_0087f113:
          if (*(int *)(iVar13 + 0x30) != 0) {
            piVar7 = (int *)UTIL_PlayerByIndex(*(int *)(this + 0x398));
            if ((piVar7 == (int *)0x0) ||
               (cVar4 = (**(code **)(*piVar7 + 0x16c))(piVar7), cVar4 == '\0')) {
              piVar7 = (int *)0x0;
            }
            uVar8 = (**(code **)(*piVar7 + 0xb8))(piVar7);
            DevMsg("TANK OFFER: Winning Player = %s\n",uVar8);
          }
          local_24 = 0;
          CUtlMemory<int,int>::Purge((CUtlMemory<int,int> *)&local_30);
          local_20 = local_30;
          CUtlMemory<int,int>::Purge((CUtlMemory<int,int> *)&local_30);
          goto LAB_0087f183;
        }
      }
      local_40 = (CUtlMemory<int,int> *)&local_30;
                    /* try { // try from 0087f472 to 0087f577 has its CatchHandler @ 0087f789 */
      ReleaseLotteryTank(this);
      local_24 = 0;
      CUtlMemory<int,int>::Purge(local_40);
      local_20 = local_30;
      CUtlMemory<int,int>::Purge(local_40);
      return;
    }
  }
LAB_0087f183:
  if (0.0 < *(float *)(this + 0x18c)) {
    lVar14 = (longdouble)CountdownTimer::Now();
    if (*(float *)(this + 0x18c) <= (float)lVar14) {
      if (*(float *)(this + 0x18c) != -1.0) {
        (**(code **)(*(int *)(this + 0x184) + 4))(this + 0x184,this + 0x18c);
        *(undefined4 *)(this + 0x18c) = 0xbf800000;
      }
      pCVar12 = (CBaseCombatCharacter *)0x0;
      uVar2 = *(uint *)(this + 400);
      if ((((uVar2 != 0xffffffff) &&
           (puVar9 = g_pEntityList + (uVar2 & 0xfff) * 0x10, puVar9 != (undefined *)0xfffffffc)) &&
          (*(uint *)(puVar9 + 8) == uVar2 >> 0xc)) &&
         ((*(int *)(puVar9 + 4) != 0 &&
          (pCVar12 = (CBaseCombatCharacter *)
                     __dynamic_cast(*(int *)(puVar9 + 4),&CBaseEntity::typeinfo,
                                    &CTerrorPlayer::typeinfo,0),
          pCVar12 != (CBaseCombatCharacter *)0x0)))) {
        ReleaseLotteryTank(this);
      }
      if (((*(int *)(this + 0x398) != 0) &&
          (pCVar5 = (CBaseEntity *)UTIL_PlayerByIndex(*(int *)(this + 0x398)),
          pCVar5 != (CBaseEntity *)0x0)) &&
         ((cVar4 = (**(code **)(*(int *)pCVar5 + 0x16c))(pCVar5), cVar4 != '\0' &&
          (iVar11 = CBaseEntity::GetTeamNumber(pCVar5), iVar11 == 3)))) {
        if ((((pCVar12 == (CBaseCombatCharacter *)0x0) ||
             (iVar11 = CBaseEntity::GetTeamNumber((CBaseEntity *)pCVar12), iVar11 != 3)) ||
            (cVar4 = (**(code **)(*(int *)pCVar12 + 300))(pCVar12), cVar4 == '\0')) ||
           ((cVar4 = CBaseCombatCharacter::IsA(pCVar12,8), cVar4 == '\0' ||
            (cVar4 = (**(code **)(*(int *)pCVar12 + 0x778))(pCVar12), cVar4 == '\0')))) {
          if (0 < *(int *)(gpGlobals + 0x14)) {
            iVar11 = 1;
            bVar3 = false;
            do {
              pCVar12 = (CBaseCombatCharacter *)UTIL_PlayerByIndex(iVar11);
              if ((((pCVar12 != (CBaseCombatCharacter *)0x0) &&
                   (cVar4 = (**(code **)(*(int *)pCVar12 + 0x16c))(pCVar12), cVar4 != '\0')) &&
                  ((*(int *)(pCVar12 + 0x30) != 0 &&
                   (((*(int *)(pCVar12 + 0x30) - *(int *)(gpGlobals + 0x58) >> 4 != 0 &&
                     (cVar4 = (**(code **)(*(int *)pCVar12 + 0x7e8))(pCVar12), cVar4 == '\0')) &&
                    (iVar13 = CBaseEntity::GetTeamNumber((CBaseEntity *)pCVar12), iVar13 == 3))))))
                 && ((cVar4 = (**(code **)(*(int *)pCVar12 + 300))(pCVar12), cVar4 != '\0' &&
                     (cVar4 = CBaseCombatCharacter::IsA(pCVar12,8), cVar4 != '\0')))) {
                iVar13 = CBaseEntity::GetTeamNumber(pCVar5);
                if (((iVar13 != 3) ||
                    (iVar13 = (**(code **)(*(int *)pCVar5 + 0x544))(pCVar5), iVar13 != 8)) &&
                   ((cVar4 = (**(code **)(*(int *)pCVar5 + 300))(pCVar5), cVar4 != '\0' &&
                    (cVar4 = (**(code **)(*(int *)pCVar5 + 0x558))(pCVar5), cVar4 == '\0')))) {
                  CTerrorPlayer::ReplaceWithBot((CTerrorPlayer *)pCVar5,false);
                }
                *(int *)(this + 0x118) = *(int *)(this + 0x118) + 1;
                ZombieManager::ReplaceTank
                          (TheZombieManager,(CTerrorPlayer *)pCVar12,(CTerrorPlayer *)pCVar5);
                bVar3 = true;
                *(undefined4 *)(this + 0x398) = 0;
              }
              iVar11 = iVar11 + 1;
            } while (iVar11 <= *(int *)(gpGlobals + 0x14));
            if (bVar3) {
              return;
            }
          }
          *(undefined4 *)(this + 0x398) = 0;
        }
        else {
          iVar11 = CBaseEntity::GetTeamNumber(pCVar5);
          if ((((iVar11 != 3) ||
               (iVar11 = (**(code **)(*(int *)pCVar5 + 0x544))(pCVar5), iVar11 != 8)) &&
              (cVar4 = (**(code **)(*(int *)pCVar5 + 300))(pCVar5), cVar4 != '\0')) &&
             (cVar4 = (**(code **)(*(int *)pCVar5 + 0x558))(pCVar5), cVar4 == '\0')) {
            CTerrorPlayer::ReplaceWithBot((CTerrorPlayer *)pCVar5,false);
          }
          *(int *)(this + 0x118) = *(int *)(this + 0x118) + 1;
          CTerrorPlayer::TakeOverZombieBot((CTerrorPlayer *)pCVar5,(CTerrorPlayer *)pCVar12);
          *(undefined4 *)(this + 0x398) = 0;
        }
      }
    }
  }
  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)