Skip to content

Commit ba86a17

Browse files
committed
Add tracking for players active ZR class & model
We also suspected ZR classes may have been leaking memory, this smart pointer approach should make that impossible
1 parent aedc26b commit ba86a17

File tree

3 files changed

+64
-45
lines changed

3 files changed

+64
-45
lines changed

src/playermanager.h

+10
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ enum class ETargetError
100100
};
101101

102102
class ZEPlayer;
103+
struct ZRClass;
104+
struct ZRModelEntry;
103105

104106
class ZEPlayerHandle
105107
{
@@ -172,6 +174,8 @@ class ZEPlayer
172174
m_flMaxSpeed = 1.f;
173175
m_iLastInputs = IN_NONE;
174176
m_iLastInputTime = std::time(0);
177+
m_pActiveZRClass = nullptr;
178+
m_pActiveZRModel = nullptr;
175179
}
176180

177181
~ZEPlayer()
@@ -227,6 +231,8 @@ class ZEPlayer
227231
void UpdateLastInputTime() { m_iLastInputTime = std::time(0); }
228232
void SetMaxSpeed(float flMaxSpeed) { m_flMaxSpeed = flMaxSpeed; }
229233
void ReplicateConVar(const char* pszName, const char* pszValue);
234+
void SetActiveZRClass(std::shared_ptr<ZRClass> pZRModel) { m_pActiveZRClass = pZRModel; }
235+
void SetActiveZRModel(std::shared_ptr<ZRModelEntry> pZRClass) { m_pActiveZRModel = pZRClass; }
230236

231237
uint64 GetAdminFlags() { return m_iAdminFlags; }
232238
int GetAdminImmunity() { return m_iAdminImmunity; }
@@ -262,6 +268,8 @@ class ZEPlayer
262268
float GetMaxSpeed() { return m_flMaxSpeed; }
263269
uint64 GetLastInputs() { return m_iLastInputs; }
264270
std::time_t GetLastInputTime() { return m_iLastInputTime; }
271+
std::shared_ptr<ZRClass> GetActiveZRClass() { return m_pActiveZRClass; }
272+
std::shared_ptr<ZRModelEntry> GetActiveZRModel() { return m_pActiveZRModel; }
265273

266274
void OnSpawn();
267275
void OnAuthenticated();
@@ -316,6 +324,8 @@ class ZEPlayer
316324
float m_flMaxSpeed;
317325
uint64 m_iLastInputs;
318326
std::time_t m_iLastInputTime;
327+
std::shared_ptr<ZRClass> m_pActiveZRClass;
328+
std::shared_ptr<ZRModelEntry> m_pActiveZRModel;
319329
};
320330

321331
class CPlayerManager

src/zombiereborn.cpp

+36-27
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ void ZR_CreateOverlay(const char* pszOverlayParticlePath, float flAlpha, float f
174174
UTIL_AddEntityIOEvent(particle, "Kill", nullptr, nullptr, "", flLifeTime + 1.0);
175175
}
176176

177-
ZRModelEntry::ZRModelEntry(ZRModelEntry *modelEntry) :
177+
ZRModelEntry::ZRModelEntry(std::shared_ptr<ZRModelEntry> modelEntry) :
178178
szModelPath(modelEntry->szModelPath),
179179
szColor(modelEntry->szColor)
180180
{
@@ -237,7 +237,7 @@ ZRClass::ZRClass(ordered_json jsonKeys, std::string szClassname) :
237237

238238
for (auto& [key, jsonModelEntry] : jsonKeys["models"].items())
239239
{
240-
ZRModelEntry *modelEntry = new ZRModelEntry(jsonModelEntry);
240+
std::shared_ptr<ZRModelEntry> modelEntry = std::make_shared<ZRModelEntry>(jsonModelEntry);
241241
vecModels.AddToTail(modelEntry);
242242
}
243243
};
@@ -303,7 +303,7 @@ void ZRClass::Override(ordered_json jsonKeys, std::string szClassname)
303303

304304
for (auto& [key, jsonModelEntry] : jsonKeys["models"].items())
305305
{
306-
ZRModelEntry *modelEntry = new ZRModelEntry(jsonModelEntry);
306+
std::shared_ptr<ZRModelEntry> modelEntry = std::make_shared<ZRModelEntry>(jsonModelEntry);
307307
vecModels.AddToTail(modelEntry);
308308
}
309309
}
@@ -460,13 +460,13 @@ void CZRPlayerClassManager::LoadPlayerClass()
460460

461461
if (bHuman)
462462
{
463-
ZRHumanClass *pHumanClass;
463+
std::shared_ptr<ZRHumanClass> pHumanClass;
464464
if (!szBase.empty())
465465
{
466-
ZRHumanClass *pBaseHumanClass = GetHumanClass(szBase.c_str());
466+
std::shared_ptr<ZRHumanClass> pBaseHumanClass = GetHumanClass(szBase.c_str());
467467
if (pBaseHumanClass)
468468
{
469-
pHumanClass = new ZRHumanClass(pBaseHumanClass);
469+
pHumanClass = std::make_shared<ZRHumanClass>(pBaseHumanClass);
470470
pHumanClass->Override(jsonClass, szClassName);
471471
}
472472
else
@@ -476,7 +476,7 @@ void CZRPlayerClassManager::LoadPlayerClass()
476476
}
477477
}
478478
else
479-
pHumanClass = new ZRHumanClass(jsonClass, szClassName);
479+
pHumanClass = std::make_shared<ZRHumanClass>(jsonClass, szClassName);
480480

481481
m_HumanClassMap.Insert(hash_32_fnv1a_const(szClassName.c_str()), pHumanClass);
482482

@@ -487,13 +487,13 @@ void CZRPlayerClassManager::LoadPlayerClass()
487487
}
488488
else
489489
{
490-
ZRZombieClass *pZombieClass;
490+
std::shared_ptr<ZRZombieClass> pZombieClass;
491491
if (!szBase.empty())
492492
{
493-
ZRZombieClass *pBaseZombieClass = GetZombieClass(szBase.c_str());
493+
std::shared_ptr<ZRZombieClass> pBaseZombieClass = GetZombieClass(szBase.c_str());
494494
if (pBaseZombieClass)
495495
{
496-
pZombieClass = new ZRZombieClass(pBaseZombieClass);
496+
pZombieClass = std::make_shared<ZRZombieClass>(pBaseZombieClass);
497497
pZombieClass->Override(jsonClass, szClassName);
498498
}
499499
else
@@ -503,7 +503,7 @@ void CZRPlayerClassManager::LoadPlayerClass()
503503
}
504504
}
505505
else
506-
pZombieClass = new ZRZombieClass(jsonClass, szClassName);
506+
pZombieClass = std::make_shared<ZRZombieClass>(jsonClass, szClassName);
507507

508508
m_ZombieClassMap.Insert(hash_32_fnv1a_const(szClassName.c_str()), pZombieClass);
509509
if (bTeamDefault)
@@ -526,9 +526,9 @@ void split(const std::string& s, char delim, Out result)
526526
*result++ = item;
527527
}
528528

529-
void CZRPlayerClassManager::ApplyBaseClass(ZRClass* pClass, CCSPlayerPawn *pPawn)
529+
void CZRPlayerClassManager::ApplyBaseClass(std::shared_ptr<ZRClass> pClass, CCSPlayerPawn* pPawn)
530530
{
531-
ZRModelEntry *pModelEntry = pClass->GetRandomModelEntry();
531+
std::shared_ptr<ZRModelEntry> pModelEntry = pClass->GetRandomModelEntry();
532532
Color clrRender;
533533
V_StringToColor(pModelEntry->szColor.c_str(), clrRender);
534534

@@ -547,36 +547,45 @@ void CZRPlayerClassManager::ApplyBaseClass(ZRClass* pClass, CCSPlayerPawn *pPawn
547547
if (const auto pPlayer = pController != nullptr ? pController->GetZEPlayer() : nullptr)
548548
{
549549
pPlayer->SetMaxSpeed(pClass->flSpeed);
550+
pPlayer->SetActiveZRClass(pClass);
551+
pPlayer->SetActiveZRModel(pModelEntry);
550552
}
551553

552554
// This has to be done a bit later
553555
UTIL_AddEntityIOEvent(pPawn, "SetScale", nullptr, nullptr, pClass->flScale);
554556
}
555557

556558
// only changes that should not (directly) affect gameplay
557-
void CZRPlayerClassManager::ApplyBaseClassVisuals(ZRClass *pClass, CCSPlayerPawn *pPawn)
559+
void CZRPlayerClassManager::ApplyBaseClassVisuals(std::shared_ptr<ZRClass> pClass, CCSPlayerPawn* pPawn)
558560
{
559-
ZRModelEntry *pModelEntry = pClass->GetRandomModelEntry();
561+
std::shared_ptr<ZRModelEntry> pModelEntry = pClass->GetRandomModelEntry();
560562
Color clrRender;
561563
V_StringToColor(pModelEntry->szColor.c_str(), clrRender);
562564

563565
pPawn->SetModel(pModelEntry->szModelPath.c_str());
564566
pPawn->m_clrRender = clrRender;
565567
pPawn->AcceptInput("Skin", pModelEntry->GetRandomSkin());
566568

569+
const auto pController = reinterpret_cast<CCSPlayerController*>(pPawn->GetController());
570+
if (const auto pPlayer = pController != nullptr ? pController->GetZEPlayer() : nullptr)
571+
{
572+
pPlayer->SetActiveZRClass(pClass);
573+
pPlayer->SetActiveZRModel(pModelEntry);
574+
}
575+
567576
// This has to be done a bit later
568577
UTIL_AddEntityIOEvent(pPawn, "SetScale", nullptr, nullptr, pClass->flScale);
569578
}
570579

571-
ZRHumanClass* CZRPlayerClassManager::GetHumanClass(const char *pszClassName)
580+
std::shared_ptr<ZRHumanClass> CZRPlayerClassManager::GetHumanClass(const char* pszClassName)
572581
{
573582
uint16 index = m_HumanClassMap.Find(hash_32_fnv1a_const(pszClassName));
574583
if (!m_HumanClassMap.IsValidIndex(index))
575584
return nullptr;
576585
return m_HumanClassMap[index];
577586
}
578587

579-
void CZRPlayerClassManager::ApplyHumanClass(ZRHumanClass *pClass, CCSPlayerPawn *pPawn)
588+
void CZRPlayerClassManager::ApplyHumanClass(std::shared_ptr<ZRHumanClass> pClass, CCSPlayerPawn* pPawn)
580589
{
581590
ApplyBaseClass(pClass, pPawn);
582591
CCSPlayerController *pController = CCSPlayerController::FromPawn(pPawn);
@@ -609,7 +618,7 @@ void CZRPlayerClassManager::ApplyPreferredOrDefaultHumanClass(CCSPlayerPawn *pPa
609618

610619
// Get the human class user preference, or default if no class is set
611620
int iSlot = pController->GetPlayerSlot();
612-
ZRHumanClass* humanClass = nullptr;
621+
std::shared_ptr<ZRHumanClass> humanClass = nullptr;
613622
const char* sPreferredHumanClass = g_pUserPreferencesSystem->GetPreference(iSlot, HUMAN_CLASS_KEY_NAME);
614623

615624
// If the preferred human class exists and can be applied, override the default
@@ -633,7 +642,7 @@ void CZRPlayerClassManager::ApplyPreferredOrDefaultHumanClassVisuals(CCSPlayerPa
633642

634643
// Get the human class user preference, or default if no class is set
635644
int iSlot = pController->GetPlayerSlot();
636-
ZRHumanClass* humanClass = nullptr;
645+
std::shared_ptr<ZRHumanClass> humanClass = nullptr;
637646
const char* sPreferredHumanClass = g_pUserPreferencesSystem->GetPreference(iSlot, HUMAN_CLASS_KEY_NAME);
638647

639648
// If the preferred human class exists and can be applied, override the default
@@ -647,18 +656,18 @@ void CZRPlayerClassManager::ApplyPreferredOrDefaultHumanClassVisuals(CCSPlayerPa
647656
return;
648657
}
649658

650-
ApplyBaseClassVisuals((ZRClass *)humanClass, pPawn);
659+
ApplyBaseClassVisuals(humanClass, pPawn);
651660
}
652661

653-
ZRZombieClass* CZRPlayerClassManager::GetZombieClass(const char *pszClassName)
662+
std::shared_ptr<ZRZombieClass> CZRPlayerClassManager::GetZombieClass(const char* pszClassName)
654663
{
655664
uint16 index = m_ZombieClassMap.Find(hash_32_fnv1a_const(pszClassName));
656665
if (!m_ZombieClassMap.IsValidIndex(index))
657666
return nullptr;
658667
return m_ZombieClassMap[index];
659668
}
660669

661-
void CZRPlayerClassManager::ApplyZombieClass(ZRZombieClass *pClass, CCSPlayerPawn *pPawn)
670+
void CZRPlayerClassManager::ApplyZombieClass(std::shared_ptr<ZRZombieClass> pClass, CCSPlayerPawn* pPawn)
662671
{
663672
ApplyBaseClass(pClass, pPawn);
664673
CCSPlayerController *pController = CCSPlayerController::FromPawn(pPawn);
@@ -673,7 +682,7 @@ void CZRPlayerClassManager::ApplyPreferredOrDefaultZombieClass(CCSPlayerPawn *pP
673682

674683
// Get the zombie class user preference, or default if no class is set
675684
int iSlot = pController->GetPlayerSlot();
676-
ZRZombieClass* zombieClass = nullptr;
685+
std::shared_ptr<ZRZombieClass> zombieClass = nullptr;
677686
const char* sPreferredZombieClass = g_pUserPreferencesSystem->GetPreference(iSlot, ZOMBIE_CLASS_KEY_NAME);
678687

679688
// If the preferred zombie class exists and can be applied, override the default
@@ -690,7 +699,7 @@ void CZRPlayerClassManager::ApplyPreferredOrDefaultZombieClass(CCSPlayerPawn *pP
690699
ApplyZombieClass(zombieClass, pPawn);
691700
}
692701

693-
void CZRPlayerClassManager::GetZRClassList(int iTeam, CUtlVector<ZRClass*> &vecClasses, CCSPlayerController* pController)
702+
void CZRPlayerClassManager::GetZRClassList(int iTeam, CUtlVector<std::shared_ptr<ZRClass>>& vecClasses, CCSPlayerController* pController)
694703
{
695704
if (iTeam == CS_TEAM_T || iTeam == CS_TEAM_NONE)
696705
{
@@ -1187,7 +1196,7 @@ void ZR_InfectMotherZombie(CCSPlayerController *pVictimController, std::vector<S
11871196
pVictimController->SwitchTeam(CS_TEAM_T);
11881197
pVictimPawn->EmitSound("zr.amb.scream");
11891198

1190-
ZRZombieClass *pClass = g_pZRPlayerClassManager->GetZombieClass("MotherZombie");
1199+
std::shared_ptr<ZRZombieClass> pClass = g_pZRPlayerClassManager->GetZombieClass("MotherZombie");
11911200
if (pClass)
11921201
g_pZRPlayerClassManager->ApplyZombieClass(pClass, pVictimPawn);
11931202
else
@@ -1730,7 +1739,7 @@ CON_COMMAND_CHAT(zclass, "<teamname/class name/number> - Find and select your Z:
17301739
return;
17311740
}
17321741

1733-
CUtlVector<ZRClass*> vecClasses;
1742+
CUtlVector<std::shared_ptr<ZRClass>> vecClasses;
17341743
int iSlot = player->GetPlayerSlot();
17351744
bool bListingZombie = true;
17361745
bool bListingHuman = true;
@@ -1773,7 +1782,7 @@ CON_COMMAND_CHAT(zclass, "<teamname/class name/number> - Find and select your Z:
17731782
{
17741783
const char* sClassName = vecClasses[i]->szClassName.c_str();
17751784
bool bClassMatches = !V_stricmp(sClassName, args[1]) || (V_StringToInt32(args[1], -1) - 1) == i;
1776-
ZRClass* pClass = vecClasses[i];
1785+
std::shared_ptr<ZRClass> pClass = vecClasses[i];
17771786

17781787
if (bClassMatches)
17791788
{

src/zombiereborn.h

+18-18
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ struct ZRModelEntry
5151
std::string szModelPath;
5252
CUtlVector<int> vecSkins;
5353
std::string szColor;
54-
ZRModelEntry(ZRModelEntry* modelEntry);
54+
ZRModelEntry(std::shared_ptr<ZRModelEntry> modelEntry);
5555
ZRModelEntry(ordered_json jsonModelEntry);
5656
int GetRandomSkin()
5757
{
@@ -66,12 +66,12 @@ struct ZRClass
6666
bool bEnabled;
6767
std::string szClassName;
6868
int iHealth;
69-
CUtlVector<ZRModelEntry*> vecModels;
69+
CUtlVector<std::shared_ptr<ZRModelEntry>> vecModels;
7070
float flScale;
7171
float flSpeed;
7272
float flGravity;
7373
uint64 iAdminFlag;
74-
ZRClass(ZRClass *pClass, int iTeam) :
74+
ZRClass(std::shared_ptr<ZRClass> pClass, int iTeam) :
7575
iTeam(iTeam),
7676
bEnabled(pClass->bEnabled),
7777
szClassName(pClass->szClassName),
@@ -84,7 +84,7 @@ struct ZRClass
8484
vecModels.Purge();
8585
FOR_EACH_VEC(pClass->vecModels, i)
8686
{
87-
ZRModelEntry *modelEntry = new ZRModelEntry(pClass->vecModels[i]);
87+
std::shared_ptr<ZRModelEntry> modelEntry = std::make_shared<ZRModelEntry>(pClass->vecModels[i]);
8888
vecModels.AddToTail(modelEntry);
8989
}
9090
};
@@ -127,7 +127,7 @@ struct ZRClass
127127
void Override(ordered_json jsonKeys, std::string szClassname);
128128
bool IsApplicableTo(CCSPlayerController *pController);
129129
uint64 ParseClassFlags(const char* pszFlags);
130-
ZRModelEntry *GetRandomModelEntry()
130+
std::shared_ptr<ZRModelEntry> GetRandomModelEntry()
131131
{
132132
return vecModels[rand() % vecModels.Count()];
133133
};
@@ -136,15 +136,15 @@ struct ZRClass
136136

137137
struct ZRHumanClass : ZRClass
138138
{
139-
ZRHumanClass(ZRHumanClass *pClass) : ZRClass(pClass, CS_TEAM_CT){};
139+
ZRHumanClass(std::shared_ptr<ZRHumanClass> pClass) : ZRClass(pClass, CS_TEAM_CT) {};
140140
ZRHumanClass(ordered_json jsonKeys, std::string szClassname);
141141
};
142142

143143
struct ZRZombieClass : ZRClass
144144
{
145145
int iHealthRegenCount;
146146
float flHealthRegenInterval;
147-
ZRZombieClass(ZRZombieClass *pClass) :
147+
ZRZombieClass(std::shared_ptr<ZRZombieClass> pClass) :
148148
ZRClass(pClass, CS_TEAM_T),
149149
iHealthRegenCount(pClass->iHealthRegenCount),
150150
flHealthRegenInterval(pClass->flHealthRegenInterval){};
@@ -199,22 +199,22 @@ class CZRPlayerClassManager
199199
m_HumanClassMap.SetLessFunc(DefLessFunc(uint32));
200200
};
201201
void LoadPlayerClass();
202-
void ApplyBaseClassVisuals(ZRClass *pClass, CCSPlayerPawn *pPawn);
203-
ZRHumanClass* GetHumanClass(const char *pszClassName);
204-
void ApplyHumanClass(ZRHumanClass *pClass, CCSPlayerPawn *pPawn);
202+
void ApplyBaseClassVisuals(std::shared_ptr<ZRClass> pClass, CCSPlayerPawn* pPawn);
203+
std::shared_ptr<ZRHumanClass> GetHumanClass(const char* pszClassName);
204+
void ApplyHumanClass(std::shared_ptr<ZRHumanClass> pClass, CCSPlayerPawn* pPawn);
205205
void ApplyPreferredOrDefaultHumanClass(CCSPlayerPawn *pPawn);
206206
void ApplyPreferredOrDefaultHumanClassVisuals(CCSPlayerPawn *pPawn);
207-
ZRZombieClass* GetZombieClass(const char*pszClassName);
208-
void ApplyZombieClass(ZRZombieClass *pClass, CCSPlayerPawn *pPawn);
207+
std::shared_ptr<ZRZombieClass> GetZombieClass(const char* pszClassName);
208+
void ApplyZombieClass(std::shared_ptr<ZRZombieClass> pClass, CCSPlayerPawn* pPawn);
209209
void ApplyPreferredOrDefaultZombieClass(CCSPlayerPawn *pPawn);
210210
void PrecacheModels(IEntityResourceManifest* pResourceManifest);
211-
void GetZRClassList(int iTeam, CUtlVector<ZRClass*> &vecClasses, CCSPlayerController* pController = nullptr);
211+
void GetZRClassList(int iTeam, CUtlVector<std::shared_ptr<ZRClass>>& vecClasses, CCSPlayerController* pController = nullptr);
212212
private:
213-
void ApplyBaseClass(ZRClass* pClass, CCSPlayerPawn *pPawn);
214-
CUtlVector<ZRZombieClass*> m_vecZombieDefaultClass;
215-
CUtlVector<ZRHumanClass*> m_vecHumanDefaultClass;
216-
CUtlMap<uint32, ZRZombieClass*> m_ZombieClassMap;
217-
CUtlMap<uint32, ZRHumanClass*> m_HumanClassMap;
213+
void ApplyBaseClass(std::shared_ptr<ZRClass> pClass, CCSPlayerPawn* pPawn);
214+
CUtlVector<std::shared_ptr<ZRZombieClass>> m_vecZombieDefaultClass;
215+
CUtlVector<std::shared_ptr<ZRHumanClass>> m_vecHumanDefaultClass;
216+
CUtlMap<uint32, std::shared_ptr<ZRZombieClass>> m_ZombieClassMap;
217+
CUtlMap<uint32, std::shared_ptr<ZRHumanClass>> m_HumanClassMap;
218218
};
219219

220220
class CZRRegenTimer : public CTimerBase

0 commit comments

Comments
 (0)