L L4D2node

CL4DGameStats::AddSurvivorStats

0x008e1560 · 854 bytes · __thiscall

_ZN13CL4DGameStats16AddSurvivorStatsEb

Decompiled

undefined (2 params)

/* CL4DGameStats::AddSurvivorStats(bool) */

void __thiscall CL4DGameStats::AddSurvivorStats(CL4DGameStats *this,bool param_1)

{
  CTerrorPlayer *this_00;
  char cVar1;
  L4D_Stat_SurvivorStat *this_01;
  KeyValues *this_02;
  int iVar2;
  int iVar3;
  undefined4 uVar4;
  int iVar5;
  longdouble lVar6;
  float fVar7;
  CTerrorPlayer *pCVar8;
  int local_40 [4];
  int local_30 [8];
  
  local_30[0] = 0;
  local_30[1] = 0;
  local_30[2] = 0;
  local_30[3] = 0;
  local_30[4] = 0;
  local_40[1] = 7;
  local_40[2] = 1;
  local_40[0] = (-(uint)!param_1 & 3) - 1;
  local_40[3] = 9;
                    /* try { // try from 008e15b6 to 008e15fa has its CatchHandler @ 008e18b6 */
  ForEachTerrorPlayer<PlayerCollector>((PlayerCollector *)local_40);
  if (0 < local_30[3]) {
    iVar5 = 0;
    do {
      this_00 = *(CTerrorPlayer **)(local_30[0] + iVar5 * 4);
      if ((this_00 != (CTerrorPlayer *)0x0) &&
         (pCVar8 = this_00, this_01 = (L4D_Stat_SurvivorStat *)FindOrCreateStatReport(this,this_00),
         this_01 != (L4D_Stat_SurvivorStat *)0x0)) {
        this_02 = KeyValues::operator_new((KeyValues *)0x2c,(uint)pCVar8);
                    /* try { // try from 008e1619 to 008e161d has its CatchHandler @ 008e18cb */
        KeyValues::KeyValues(this_02,"L4D2SurvivorData",(IKeyValuesSystem *)0x0,false);
                    /* try { // try from 008e1623 to 008e1864 has its CatchHandler @ 008e18b6 */
        cVar1 = (**(code **)(*(int *)this_00 + 0x778))(this_00);
        if (cVar1 == '\0') {
          KeyValues::SetInt(this_02,"IsBot",0);
          cVar1 = CTerrorGameRules::HasPlayerControlledZombies();
          iVar2 = *(int *)(this_00 + 0x2ba0);
          if (cVar1 != '\0') {
            iVar3 = CBaseEntity::GetTeamNumber((CBaseEntity *)this_00);
            iVar2 = iVar2 + -8 + iVar3 * 4;
          }
          KeyValues::SetInt(this_02,"CharacterID",iVar2);
          iVar2 = GetDifficulty();
          KeyValues::SetInt(this_02,"Difficulty",iVar2);
          cVar1 = CTerrorGameRules::IsVersusMode();
          if (cVar1 == '\0') {
            if (TheNavMesh == 0) goto LAB_008e18a3;
            lVar6 = (longdouble)CTerrorPlayer::GetFlowDistance(this_00,0);
            if ((float)lVar6 < 0.0) {
              fVar7 = 0.0;
            }
            else {
              lVar6 = (longdouble)CTerrorPlayer::GetFlowDistance(this_00,0);
              fVar7 = (float)lVar6;
            }
            fVar7 = fVar7 / *(float *)(TheNavMesh + 0x5f8);
            iVar2 = 100;
            if (fVar7 <= 1.0) {
              if (0.0 <= fVar7) goto LAB_008e1810;
              goto LAB_008e172e;
            }
          }
          else if (g_pGameRules == (CTerrorGameRules *)0x0) {
LAB_008e18a3:
            iVar2 = 0;
            if (-1 < *(int *)(this_01 + 0x74)) {
              iVar2 = *(int *)(this_01 + 0x74);
            }
          }
          else {
            iVar2 = CTerrorGameRules::GetVersusMaxCompletionScore(g_pGameRules);
            if ((float)(iVar2 >> 2) == 0.0) {
LAB_008e172e:
              iVar2 = 0;
            }
            else {
              uVar4 = CBaseEntity::GetTeamNumber((CBaseEntity *)this_00);
              iVar3 = CTerrorGameRules::GetVersusCompletionPerCharacter
                                (g_pGameRules,*(undefined4 *)(this_00 + 0x2ba0),uVar4);
              fVar7 = (float)iVar3 / (float)(iVar2 >> 2);
LAB_008e1810:
              iVar2 = (int)(fVar7 * 100.0);
              if (iVar2 < 0) {
                iVar2 = 0;
              }
            }
          }
          *(int *)(this_01 + 0x74) = iVar2;
          L4D_Stat_SurvivorStat::ExtractStats(this_01,this_00);
          *(undefined4 *)(this_01 + 0x38) = 0;
          if (*(int *)(this_01 + 0x30) != 0) {
            *(int *)(this_01 + 0x38) = *(int *)(this_01 + 4) / *(int *)(this_01 + 0x30);
          }
          *(undefined4 *)(this_01 + 0x54) = *(undefined4 *)(this + 0x3a4);
          L4D_Stat_SurvivorStat::SaveStatsToKeyValue(this_01,this_02);
          iVar2 = CSteamWorksGameStatsUploader::GetTimeSinceEpoch();
          KeyValues::SetInt(this_02,"TimeSubmitted",iVar2);
          if (engine != (int *)0x0) {
            uVar4 = (**(code **)(*engine + 0x220))(engine,*(undefined4 *)(this_00 + 0x30));
            KeyValues::SetUint64((char *)this_02,CONCAT44(uVar4,"AccountIDPlayer"));
          }
          CSteamWorksGameStatsUploader::AddStatsForUpload(steamGameStats,this_02);
        }
        *(undefined4 *)(this_01 + 4) = 0;
        iVar2 = 0;
        do {
          *(undefined4 *)(this_01 + iVar2 * 4 + 8) = 0;
          iVar2 = iVar2 + 1;
        } while (iVar2 != 0x28);
      }
      iVar5 = iVar5 + 1;
    } while (iVar5 < local_30[3]);
  }
  local_30[3] = 0;
  CUtlMemory<CTerrorPlayer*,int>::Purge((CUtlMemory<CTerrorPlayer*,int> *)local_30);
  local_30[4] = local_30[0];
  CUtlMemory<CTerrorPlayer*,int>::Purge((CUtlMemory<CTerrorPlayer*,int> *)local_30);
  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)