aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2024-03-13 18:51:29 +0100
committerfunjoker <funjoker109@gmail.com>2024-03-25 20:21:24 +0100
commit64724464407e5b7646a48e6a5191d6fd8997ac77 (patch)
treec2ddc8dcdfc7032e9d60fb59735895b388c0b096
parent382d67622fc9b4ec7eeb9e3f8bd56876133901fd (diff)
Core/Misc: Use our new unique_trackable_ptr for various classes exposed to scripts (not actually used anywhere currently)
(cherry picked from commit 4779fa5048642b57a0f69de7ab56b9d563c1cbc4)
-rw-r--r--src/server/game/Achievements/CriteriaHandler.cpp4
-rw-r--r--src/server/game/Battlegrounds/Battleground.cpp1
-rw-r--r--src/server/game/Battlegrounds/Battleground.h6
-rw-r--r--src/server/game/Battlegrounds/BattlegroundMgr.cpp37
-rw-r--r--src/server/game/Battlegrounds/BattlegroundMgr.h4
-rw-r--r--src/server/game/Entities/Object/Object.cpp9
-rw-r--r--src/server/game/Entities/Object/Object.h6
-rw-r--r--src/server/game/Entities/Player/Player.cpp2
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp6
-rw-r--r--src/server/game/Entities/Unit/Unit.h3
-rw-r--r--src/server/game/Entities/Vehicle/Vehicle.cpp5
-rw-r--r--src/server/game/Entities/Vehicle/Vehicle.h5
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp24
-rw-r--r--src/server/game/Globals/ObjectMgr.h3
-rw-r--r--src/server/game/Groups/Group.cpp2
-rw-r--r--src/server/game/Groups/Group.h6
-rw-r--r--src/server/game/Guilds/Guild.cpp39
-rw-r--r--src/server/game/Guilds/Guild.h8
-rw-r--r--src/server/game/Guilds/GuildMgr.cpp28
-rw-r--r--src/server/game/Guilds/GuildMgr.h3
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp8
-rw-r--r--src/server/game/Maps/Map.h5
-rw-r--r--src/server/game/Maps/MapManager.cpp18
-rw-r--r--src/server/game/Maps/MapManager.h7
-rw-r--r--src/server/game/Quests/QuestDef.h5
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.cpp4
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.h6
-rw-r--r--src/server/game/Spells/Spell.cpp22
-rw-r--r--src/server/game/Spells/Spell.h4
-rw-r--r--src/server/scripts/Commands/cs_guild.cpp4
-rw-r--r--src/server/scripts/Commands/cs_learn.cpp4
-rw-r--r--src/server/scripts/Commands/cs_lookup.cpp18
32 files changed, 177 insertions, 129 deletions
diff --git a/src/server/game/Achievements/CriteriaHandler.cpp b/src/server/game/Achievements/CriteriaHandler.cpp
index 66627e24b0a..02576edbd5c 100644
--- a/src/server/game/Achievements/CriteriaHandler.cpp
+++ b/src/server/game/Achievements/CriteriaHandler.cpp
@@ -4090,9 +4090,9 @@ void CriteriaMgr::LoadCriteriaList()
scenarioCriteriaTreeIds[scenarioStep->Criteriatreeid] = scenarioStep;
std::unordered_map<uint32 /*criteriaTreeID*/, QuestObjective const*> questObjectiveCriteriaTreeIds;
- for (auto const& questTemplatePair : sObjectMgr->GetQuestTemplates())
+ for (auto const& [questId, quest] : sObjectMgr->GetQuestTemplates())
{
- for (QuestObjective const& objective : questTemplatePair.second.Objectives)
+ for (QuestObjective const& objective : quest->Objectives)
{
if (objective.Type != QUEST_OBJECTIVE_CRITERIA_TREE)
continue;
diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp
index 9d123881401..fff4ceebca7 100644
--- a/src/server/game/Battlegrounds/Battleground.cpp
+++ b/src/server/game/Battlegrounds/Battleground.cpp
@@ -124,7 +124,6 @@ Battleground::~Battleground()
for (uint32 i = 0; i < size; ++i)
DelObject(i);
- sBattlegroundMgr->RemoveBattleground(GetTypeID(), GetInstanceID());
// unload map
if (m_Map)
{
diff --git a/src/server/game/Battlegrounds/Battleground.h b/src/server/game/Battlegrounds/Battleground.h
index a3e0ca3ee32..b01152636e5 100644
--- a/src/server/game/Battlegrounds/Battleground.h
+++ b/src/server/game/Battlegrounds/Battleground.h
@@ -22,6 +22,7 @@
#include "ObjectGuid.h"
#include "Position.h"
#include "SharedDefines.h"
+#include "UniqueTrackablePtr.h"
#include "ZoneScript.h"
#include <deque>
#include <map>
@@ -497,6 +498,9 @@ class TC_GAME_API Battleground : public ZoneScript
// Called when valid BattlegroundMap is assigned to the battleground
virtual void OnMapSet([[maybe_unused]] BattlegroundMap* map) { }
+ Trinity::unique_weak_ptr<Battleground> GetWeakPtr() const { return m_weakRef; }
+ void SetWeakPtr(Trinity::unique_weak_ptr<Battleground> weakRef) { m_weakRef = std::move(weakRef); }
+
protected:
// this method is called, when BG cannot spawn its own spirit guide, or something is wrong, It correctly ends Battleground
void EndNow();
@@ -612,5 +616,7 @@ class TC_GAME_API Battleground : public ZoneScript
// Time when the first message "the battle will begin in 2minutes" is send (or 1m for arenas)
time_t _preparationStartTime;
+
+ Trinity::unique_weak_ptr<Battleground> m_weakRef;
};
#endif
diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
index b07012c59db..37311c718f2 100644
--- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp
+++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
@@ -84,22 +84,7 @@ BattlegroundMgr::~BattlegroundMgr()
void BattlegroundMgr::DeleteAllBattlegrounds()
{
- for (BattlegroundDataContainer::iterator itr1 = bgDataStore.begin(); itr1 != bgDataStore.end(); ++itr1)
- {
- BattlegroundData& data = itr1->second;
-
- while (!data.m_Battlegrounds.empty())
- delete data.m_Battlegrounds.begin()->second;
-
- data.m_Battlegrounds.clear();
- }
-
bgDataStore.clear();
-
- for (auto itr = m_BGFreeSlotQueue.begin(); itr != m_BGFreeSlotQueue.end(); ++itr)
- while (!itr->second.empty())
- delete itr->second.front();
-
m_BGFreeSlotQueue.clear();
}
@@ -122,18 +107,19 @@ void BattlegroundMgr::Update(uint32 diff)
for (BattlegroundContainer::iterator itr = itrDelete; itr != bgs.end();)
{
itrDelete = itr++;
- Battleground* bg = itrDelete->second;
+ Battleground* bg = itrDelete->second.get();
bg->Update(m_UpdateTimer);
if (bg->ToBeDeleted())
{
- itrDelete->second = nullptr;
- bgs.erase(itrDelete);
BattlegroundClientIdsContainer& clients = itr1->second.m_ClientBattlegroundIds[bg->GetBracketId()];
if (!clients.empty())
clients.erase(bg->GetClientInstanceID());
- delete bg;
+ // move out unique_ptr to delete after erasing
+ Trinity::unique_trackable_ptr<Battleground> bgPtr = std::move(itrDelete->second);
+
+ bgs.erase(itrDelete);
}
}
}
@@ -270,7 +256,7 @@ Battleground* BattlegroundMgr::GetBattleground(uint32 instanceId, BattlegroundTy
BattlegroundContainer const& bgs = it->second.m_Battlegrounds;
BattlegroundContainer::const_iterator itr = bgs.find(instanceId);
if (itr != bgs.end())
- return itr->second;
+ return itr->second.get();
}
return nullptr;
@@ -745,10 +731,9 @@ void BattlegroundMgr::RemoveFromBGFreeSlotQueue(uint32 mapId, uint32 instanceId)
void BattlegroundMgr::AddBattleground(Battleground* bg)
{
if (bg)
- bgDataStore[bg->GetTypeID()].m_Battlegrounds[bg->GetInstanceID()] = bg;
-}
-
-void BattlegroundMgr::RemoveBattleground(BattlegroundTypeId bgTypeId, uint32 instanceId)
-{
- bgDataStore[bgTypeId].m_Battlegrounds.erase(instanceId);
+ {
+ Trinity::unique_trackable_ptr<Battleground>& ptr = bgDataStore[bg->GetTypeID()].m_Battlegrounds[bg->GetInstanceID()];
+ ptr.reset(bg);
+ bg->SetWeakPtr(ptr);
+ }
}
diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.h b/src/server/game/Battlegrounds/BattlegroundMgr.h
index ff62461b6c2..854f6da9cfa 100644
--- a/src/server/game/Battlegrounds/BattlegroundMgr.h
+++ b/src/server/game/Battlegrounds/BattlegroundMgr.h
@@ -22,12 +22,13 @@
#include "DBCEnums.h"
#include "Battleground.h"
#include "BattlegroundQueue.h"
+#include "UniqueTrackablePtr.h"
#include <unordered_map>
class Battleground;
struct BattlemasterListEntry;
-typedef std::map<uint32, Battleground*> BattlegroundContainer;
+typedef std::map<uint32, Trinity::unique_trackable_ptr<Battleground>> BattlegroundContainer;
typedef std::set<uint32> BattlegroundClientIdsContainer;
typedef std::unordered_map<uint32, BattlegroundTypeId> BattleMastersMap;
@@ -102,7 +103,6 @@ class TC_GAME_API BattlegroundMgr
Battleground* CreateNewBattleground(BattlegroundQueueTypeId queueId, BattlegroundBracketId bracketId);
void AddBattleground(Battleground* bg);
- void RemoveBattleground(BattlegroundTypeId bgTypeId, uint32 instanceId);
void AddToBGFreeSlotQueue(Battleground* bg);
void RemoveFromBGFreeSlotQueue(uint32 mapId, uint32 instanceId);
BGFreeSlotQueueContainer& GetBGFreeSlotQueueStore(uint32 mapId);
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index 8e31a00d45f..b6434b2b0b0 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -69,7 +69,7 @@ constexpr float VisibilityDistances[AsUnderlyingType(VisibilityDistanceType::Max
MAX_VISIBILITY_DISTANCE
};
-Object::Object() : m_values(this)
+Object::Object() : m_values(this), m_scriptRef(this, NoopObjectDeleter())
{
m_objectTypeId = TYPEID_OBJECT;
m_objectType = TYPEMASK_OBJECT;
@@ -114,6 +114,11 @@ void Object::AddToWorld()
// synchronize values mirror with values array (changes will send in updatecreate opcode any way
ASSERT(!m_objectUpdated);
ClearUpdateMask(false);
+
+ // Set new ref when adding to world (except if we already have one - also set in constructor to allow scripts to work in initialization phase)
+ // Changing the ref when adding/removing from world prevents accessing players on different maps (possibly from another thread)
+ if (!m_scriptRef)
+ m_scriptRef.reset(this, NoopObjectDeleter());
}
void Object::RemoveFromWorld()
@@ -125,6 +130,8 @@ void Object::RemoveFromWorld()
// if we remove from world then sending changes not required
ClearUpdateMask(true);
+
+ m_scriptRef = nullptr;
}
void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) const
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index 07cf03d3e28..2df91649ae5 100644
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -32,6 +32,7 @@
#include "Position.h"
#include "SharedDefines.h"
#include "SpellDefines.h"
+#include "UniqueTrackablePtr.h"
#include "UpdateFields.h"
#include <list>
#include <unordered_map>
@@ -260,6 +261,8 @@ class TC_GAME_API Object
virtual std::string GetDebugInfo() const;
+ Trinity::unique_weak_ptr<Object> GetWeakPtr() const { return m_scriptRef; }
+
virtual Loot* GetLootForPlayer([[maybe_unused]] Player const* player) const { return nullptr; }
protected:
@@ -399,6 +402,9 @@ class TC_GAME_API Object
bool m_isNewObject;
bool m_isDestroyedObject;
+ struct NoopObjectDeleter { void operator()(Object*) const { /*noop - not managed*/ } };
+ Trinity::unique_trackable_ptr<Object> m_scriptRef;
+
Object(Object const& right) = delete;
Object(Object&& right) = delete;
Object& operator=(Object const& right) = delete;
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 37e84f8b105..7003838c8bb 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -3847,7 +3847,7 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
if (ObjectGuid::LowType guildId = sCharacterCache->GetCharacterGuildIdByGuid(playerguid))
if (Guild* guild = sGuildMgr->GetGuildById(guildId))
- guild->DeleteMember(trans, playerguid, false, false, true);
+ guild->DeleteMember(trans, playerguid, false, false);
// remove from arena teams
LeaveAllArenaTeams(playerguid);
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 688628d2cd6..fd85298a660 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -4250,8 +4250,8 @@ void Unit::RemoveAllAuras()
{
sstr << "m_ownedAuras:" << "\n";
- for (std::pair<uint32 const, Aura*>& auraPair : m_ownedAuras)
- sstr << auraPair.second->GetDebugInfo() << "\n";
+ for (auto const& [spellId, aura] : m_ownedAuras)
+ sstr << aura->GetDebugInfo() << "\n";
}
TC_LOG_ERROR("entities.unit", "{}", sstr.str());
@@ -11386,7 +11386,7 @@ bool Unit::CreateVehicleKit(uint32 id, uint32 creatureEntry, bool loading /*= fa
if (!vehInfo)
return false;
- m_vehicleKit = std::make_unique<Vehicle>(this, vehInfo, creatureEntry);
+ m_vehicleKit = Trinity::make_unique_trackable<Vehicle>(this, vehInfo, creatureEntry);
m_updateFlag.Vehicle = true;
m_unitTypeMask |= UNIT_MASK_VEHICLE;
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 86040e3dcbd..7957161d9e7 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -1690,6 +1690,7 @@ class TC_GAME_API Unit : public WorldObject
bool CreateVehicleKit(uint32 id, uint32 creatureEntry, bool loading = false);
void RemoveVehicleKit(bool onRemoveFromWorld = false);
Vehicle* GetVehicleKit() const { return m_vehicleKit.get(); }
+ Trinity::unique_weak_ptr<Vehicle> GetVehicleKitWeakPtr() const { return m_vehicleKit; }
Vehicle* GetVehicle() const { return m_vehicle; }
void SetVehicle(Vehicle* vehicle) { m_vehicle = vehicle; }
bool IsOnVehicle(Unit const* vehicle) const;
@@ -1888,7 +1889,7 @@ class TC_GAME_API Unit : public WorldObject
uint32 m_regenTimer;
Vehicle* m_vehicle;
- std::unique_ptr<Vehicle> m_vehicleKit;
+ Trinity::unique_trackable_ptr<Vehicle> m_vehicleKit;
uint32 m_unitTypeMask;
LiquidTypeEntry const* _lastLiquid;
diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp
index d00f313e56d..1d5a4abede9 100644
--- a/src/server/game/Entities/Vehicle/Vehicle.cpp
+++ b/src/server/game/Entities/Vehicle/Vehicle.cpp
@@ -993,3 +993,8 @@ std::string Vehicle::GetDebugInfo() const
return sstr.str();
}
+
+Trinity::unique_weak_ptr<Vehicle> Vehicle::GetWeakPtr() const
+{
+ return _me->GetVehicleKitWeakPtr();
+}
diff --git a/src/server/game/Entities/Vehicle/Vehicle.h b/src/server/game/Entities/Vehicle/Vehicle.h
index a888a8a9007..e0ca5e9d632 100644
--- a/src/server/game/Entities/Vehicle/Vehicle.h
+++ b/src/server/game/Entities/Vehicle/Vehicle.h
@@ -19,8 +19,9 @@
#define __TRINITY_VEHICLE_H
#include "Object.h"
-#include "VehicleDefines.h"
+#include "UniqueTrackablePtr.h"
#include "Unit.h"
+#include "VehicleDefines.h"
#include <list>
struct VehicleEntry;
@@ -73,6 +74,8 @@ class TC_GAME_API Vehicle final : public TransportBase
std::string GetDebugInfo() const;
+ Trinity::unique_weak_ptr<Vehicle> GetWeakPtr() const;
+
protected:
friend class VehicleJoinEvent;
uint32 UsableSeatNum; ///< Number of seats that match VehicleSeatEntry::UsableByPlayer, used for proper display flags
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 76d05614af6..a40f31552f0 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -4565,9 +4565,10 @@ void ObjectMgr::LoadQuests()
Field* fields = result->Fetch();
uint32 questId = fields[0].GetUInt32();
- auto itr = _questTemplates.emplace(std::piecewise_construct, std::forward_as_tuple(questId), std::forward_as_tuple(fields)).first;
- if (itr->second.IsAutoPush())
- _questTemplatesAutoPush.push_back(&itr->second);
+ auto itr = _questTemplates.emplace(std::piecewise_construct, std::forward_as_tuple(questId), std::forward_as_tuple(new Quest(fields))).first;
+ itr->second->_weakRef = itr->second;
+ if (itr->second->IsAutoPush())
+ _questTemplatesAutoPush.push_back(itr->second.get());
} while (result->NextRow());
struct QuestLoaderHelper
@@ -4642,7 +4643,7 @@ void ObjectMgr::LoadQuests()
auto itr = _questTemplates.find(questId);
if (itr != _questTemplates.end())
- (itr->second.*loader.LoaderFunction)(fields);
+ (itr->second.get()->*loader.LoaderFunction)(fields);
else
TC_LOG_ERROR("server.loading", "Table `{}` has data for quest {} but such quest does not exist", loader.TableName, questId);
} while (result->NextRow());
@@ -4683,7 +4684,7 @@ void ObjectMgr::LoadQuests()
// Do not throw error here because error for non existing quest is thrown while loading quest objectives. we do not need duplication
auto itr = _questTemplates.find(questId);
if (itr != _questTemplates.end())
- itr->second.LoadQuestObjectiveVisualEffect(fields);
+ itr->second->LoadQuestObjectiveVisualEffect(fields);
} while (result->NextRow());
}
@@ -4696,7 +4697,7 @@ void ObjectMgr::LoadQuests()
if (DisableMgr::IsDisabledFor(DISABLE_TYPE_QUEST, questPair.first, nullptr))
continue;
- Quest* qinfo = &questPair.second;
+ Quest* qinfo = questPair.second.get();
// additional quest integrity checks (GO, creature_template and items must be loaded already)
@@ -5276,7 +5277,7 @@ void ObjectMgr::LoadQuests()
auto prevQuestItr = _questTemplates.find(prevQuestId);
if (prevQuestItr == _questTemplates.end())
TC_LOG_ERROR("sql.sql", "Quest {} has PrevQuestId {}, but no such quest", qinfo->GetQuestId(), qinfo->GetPrevQuestId());
- else if (prevQuestItr->second._breadcrumbForQuestId)
+ else if (prevQuestItr->second->_breadcrumbForQuestId)
TC_LOG_ERROR("sql.sql", "Quest {} should not be unlocked by breadcrumb quest {}", qinfo->_id, prevQuestId);
else if (qinfo->_prevQuestID > 0)
qinfo->DependentPreviousQuests.push_back(prevQuestId);
@@ -5288,7 +5289,7 @@ void ObjectMgr::LoadQuests()
if (nextQuestItr == _questTemplates.end())
TC_LOG_ERROR("sql.sql", "Quest {} has NextQuestId {}, but no such quest", qinfo->GetQuestId(), qinfo->_nextQuestID);
else
- nextQuestItr->second.DependentPreviousQuests.push_back(qinfo->GetQuestId());
+ nextQuestItr->second->DependentPreviousQuests.push_back(qinfo->GetQuestId());
}
if (uint32 breadcrumbForQuestId = std::abs(qinfo->_breadcrumbForQuestId))
@@ -5313,7 +5314,7 @@ void ObjectMgr::LoadQuests()
if (DisableMgr::IsDisabledFor(DISABLE_TYPE_QUEST, questPair.first, nullptr))
continue;
- Quest* qinfo = &questPair.second;
+ Quest* qinfo = questPair.second.get();
uint32 qid = qinfo->GetQuestId();
uint32 breadcrumbForQuestId = std::abs(qinfo->_breadcrumbForQuestId);
std::set<uint32> questSet;
@@ -6762,7 +6763,8 @@ uint32 ObjectMgr::GetTaxiMountDisplayId(uint32 id, uint32 team, bool allowed_alt
Quest const* ObjectMgr::GetQuestTemplate(uint32 quest_id) const
{
- return Trinity::Containers::MapGetValuePtr(_questTemplates, quest_id);
+ auto itr = _questTemplates.find(quest_id);
+ return itr != _questTemplates.end() ? itr->second.get() : nullptr;
}
void ObjectMgr::LoadGraveyardZones()
@@ -10851,7 +10853,7 @@ void ObjectMgr::InitializeQueriesData(QueryDataGroup mask)
// Initialize Query Data for quests
if (mask & QUERY_DATA_QUESTS)
for (auto& questTemplatePair : _questTemplates)
- pool.PostWork([quest = &questTemplatePair.second]() { quest->InitializeQueryData(); });
+ pool.PostWork([quest = questTemplatePair.second.get()]() { quest->InitializeQueryData(); });
// Initialize Quest POI data
if (mask & QUERY_DATA_POIS)
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index 392fb9abaef..2ffc9f94989 100644
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -36,6 +36,7 @@
#include "SharedDefines.h"
#include "Trainer.h"
#include "VehicleDefines.h"
+#include "UniqueTrackablePtr.h"
#include <iterator>
#include <map>
#include <unordered_map>
@@ -1067,7 +1068,7 @@ class TC_GAME_API ObjectMgr
static ObjectMgr* instance();
- typedef std::unordered_map<uint32, Quest> QuestContainer;
+ typedef std::unordered_map<uint32, Trinity::unique_trackable_ptr<Quest>> QuestContainer;
typedef std::unordered_map<uint32 /*questObjectiveId*/, QuestObjective const*> QuestObjectivesByIdContainer;
typedef std::unordered_map<uint32, AreaTriggerStruct> AreaTriggerContainer;
diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp
index ea6c783571e..9f585f1fa04 100644
--- a/src/server/game/Groups/Group.cpp
+++ b/src/server/game/Groups/Group.cpp
@@ -59,7 +59,7 @@ Group::Group() : m_leaderGuid(), m_leaderFactionGroup(0), m_leaderName(""), m_gr
m_dungeonDifficulty(DIFFICULTY_NORMAL), m_raidDifficulty(DIFFICULTY_NORMAL_RAID), m_legacyRaidDifficulty(DIFFICULTY_10_N),
m_bgGroup(nullptr), m_bfGroup(nullptr), m_lootMethod(PERSONAL_LOOT), m_lootThreshold(ITEM_QUALITY_UNCOMMON), m_looterGuid(),
m_masterLooterGuid(), m_subGroupsCounts(nullptr), m_guid(), m_dbStoreId(0), m_isLeaderOffline(false),
-m_readyCheckStarted(false), m_readyCheckTimer(Milliseconds::zero()), m_activeMarkers(0)
+m_readyCheckStarted(false), m_readyCheckTimer(Milliseconds::zero()), m_activeMarkers(0), m_scriptRef(this, NoopGroupDeleter())
{
for (uint8 i = 0; i < TARGET_ICONS_COUNT; ++i)
m_targetIcons[i].Clear();
diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h
index ee28dcb7f9a..917da8dc599 100644
--- a/src/server/game/Groups/Group.h
+++ b/src/server/game/Groups/Group.h
@@ -26,6 +26,7 @@
#include "RaceMask.h"
#include "SharedDefines.h"
#include "Timer.h"
+#include "UniqueTrackablePtr.h"
#include <map>
class Battlefield;
@@ -409,6 +410,8 @@ class TC_GAME_API Group
void StartCountdown(CountdownTimerType timerType, Seconds duration, Optional<time_t> startTime = { });
CountdownInfo const* GetCountdownInfo(CountdownTimerType timerType) const;
+ Trinity::unique_weak_ptr<Group> GetWeakPtr() const { return m_scriptRef; }
+
protected:
bool _setMembersGroup(ObjectGuid guid, uint8 group);
void _homebindIfInstance(Player* player);
@@ -455,5 +458,8 @@ class TC_GAME_API Group
uint32 m_activeMarkers;
std::array<std::unique_ptr<CountdownInfo>, 3> _countdowns;
+
+ struct NoopGroupDeleter { void operator()(Group*) const { /*noop - not managed*/ } };
+ Trinity::unique_trackable_ptr<Group> m_scriptRef;
};
#endif
diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp
index dd37eb767fb..714d9fd4729 100644
--- a/src/server/game/Guilds/Guild.cpp
+++ b/src/server/game/Guilds/Guild.cpp
@@ -1761,7 +1761,8 @@ void Guild::HandleAcceptMember(WorldSession* session)
void Guild::HandleLeaveMember(WorldSession* session)
{
Player* player = session->GetPlayer();
- bool disband = false;
+
+ sCalendarMgr->RemovePlayerGuildEventsAndSignups(player->GetGUID(), GetId());
// If leader is leaving
if (_IsLeader(player))
@@ -1773,7 +1774,6 @@ void Guild::HandleLeaveMember(WorldSession* session)
{
// Guild is disbanded if leader leaves.
Disband();
- disband = true;
}
}
else
@@ -1781,16 +1781,11 @@ void Guild::HandleLeaveMember(WorldSession* session)
_LogEvent(GUILD_EVENT_LOG_LEAVE_GUILD, player->GetGUID().GetCounter());
SendEventPlayerLeft(GetMember(player->GetGUID()));
+ SendCommandResult(session, GUILD_COMMAND_LEAVE_GUILD, ERR_GUILD_COMMAND_SUCCESS, m_name);
+
CharacterDatabaseTransaction trans(nullptr);
DeleteMember(trans, player->GetGUID(), false, false);
-
- SendCommandResult(session, GUILD_COMMAND_LEAVE_GUILD, ERR_GUILD_COMMAND_SUCCESS, m_name);
}
-
- sCalendarMgr->RemovePlayerGuildEventsAndSignups(player->GetGUID(), GetId());
-
- if (disband)
- delete this;
}
void Guild::HandleRemoveMember(WorldSession* session, ObjectGuid guid)
@@ -1821,11 +1816,11 @@ void Guild::HandleRemoveMember(WorldSession* session, ObjectGuid guid)
_LogEvent(GUILD_EVENT_LOG_UNINVITE_PLAYER, player->GetGUID().GetCounter(), guid.GetCounter());
SendEventPlayerLeft(member, memberMe, true);
+ SendCommandResult(session, GUILD_COMMAND_REMOVE_PLAYER, ERR_GUILD_COMMAND_SUCCESS, name);
+
// After call to DeleteMember pointer to member becomes invalid
CharacterDatabaseTransaction trans(nullptr);
DeleteMember(trans, guid, false, true);
-
- SendCommandResult(session, GUILD_COMMAND_REMOVE_PLAYER, ERR_GUILD_COMMAND_SUCCESS, name);
}
}
}
@@ -2145,7 +2140,6 @@ void Guild::HandleDelete(WorldSession* session)
{
Disband();
TC_LOG_DEBUG("guild", "{} successfully deleted", GetGUID().ToString());
- delete this;
}
}
@@ -2708,13 +2702,8 @@ bool Guild::Validate()
if (!leader)
{
CharacterDatabaseTransaction dummy(nullptr);
- DeleteMember(dummy, m_leaderGuid);
- // If no more members left, disband guild
- if (m_members.empty())
- {
- Disband();
+ if (DeleteMember(dummy, m_leaderGuid))
return false;
- }
}
else if (!leader->IsRank(GuildRankId::GuildMaster))
_SetLeader(trans, *leader);
@@ -2963,7 +2952,7 @@ bool Guild::AddMember(CharacterDatabaseTransaction trans, ObjectGuid guid, Optio
return true;
}
-void Guild::DeleteMember(CharacterDatabaseTransaction trans, ObjectGuid guid, bool isDisbanding, bool isKicked, bool canDeleteGuild)
+bool Guild::DeleteMember(CharacterDatabaseTransaction trans, ObjectGuid guid, bool isDisbanding, bool isKicked)
{
// Guild master can be deleted when loading guild and guid doesn't exist in characters table
// or when he is removed from guild by gm command
@@ -2982,9 +2971,7 @@ void Guild::DeleteMember(CharacterDatabaseTransaction trans, ObjectGuid guid, bo
if (!newLeader)
{
Disband();
- if (canDeleteGuild)
- delete this;
- return;
+ return true;
}
_SetLeader(trans, *newLeader);
@@ -3018,6 +3005,14 @@ void Guild::DeleteMember(CharacterDatabaseTransaction trans, ObjectGuid guid, bo
Guild::_DeleteMemberFromDB(trans, guid.GetCounter());
if (!isDisbanding)
_UpdateAccountsNumber();
+
+ if (m_members.empty())
+ {
+ Disband();
+ return true;
+ }
+
+ return false;
}
bool Guild::ChangeMemberRank(CharacterDatabaseTransaction trans, ObjectGuid guid, GuildRankId newRank)
diff --git a/src/server/game/Guilds/Guild.h b/src/server/game/Guilds/Guild.h
index 10384f091d1..ea39a1682b7 100644
--- a/src/server/game/Guilds/Guild.h
+++ b/src/server/game/Guilds/Guild.h
@@ -25,6 +25,7 @@
#include "Optional.h"
#include "RaceMask.h"
#include "SharedDefines.h"
+#include "UniqueTrackablePtr.h"
#include <set>
#include <unordered_map>
@@ -843,7 +844,7 @@ class TC_GAME_API Guild
// Members
// Adds member to guild. If rankId == GUILD_RANK_NONE, lowest rank is assigned.
bool AddMember(CharacterDatabaseTransaction trans, ObjectGuid guid, Optional<GuildRankId> rankId = {});
- void DeleteMember(CharacterDatabaseTransaction trans, ObjectGuid guid, bool isDisbanding = false, bool isKicked = false, bool canDeleteGuild = false);
+ bool DeleteMember(CharacterDatabaseTransaction trans, ObjectGuid guid, bool isDisbanding = false, bool isKicked = false);
bool ChangeMemberRank(CharacterDatabaseTransaction trans, ObjectGuid guid, GuildRankId newRank);
bool IsMember(ObjectGuid guid) const;
uint32 GetMembersCount() const { return uint32(m_members.size()); }
@@ -872,6 +873,9 @@ class TC_GAME_API Guild
bool HasAchieved(uint32 achievementId) const;
void UpdateCriteria(CriteriaType type, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, WorldObject const* ref, Player* player);
+ Trinity::unique_weak_ptr<Guild> GetWeakPtr() const { return m_weakRef; }
+ void SetWeakPtr(Trinity::unique_weak_ptr<Guild> weakRef) { m_weakRef = std::move(weakRef); }
+
protected:
ObjectGuid::LowType m_id;
std::string m_name;
@@ -894,6 +898,8 @@ class TC_GAME_API Guild
LogHolder<NewsLogEntry> m_newsLog;
std::unique_ptr<GuildAchievementMgr> m_achievementMgr;
+ Trinity::unique_weak_ptr<Guild> m_weakRef;
+
private:
inline uint8 _GetRanksSize() const { return uint8(m_ranks.size()); }
RankInfo const* GetRankInfo(GuildRankId rankId) const;
diff --git a/src/server/game/Guilds/GuildMgr.cpp b/src/server/game/Guilds/GuildMgr.cpp
index f7d8dd86f6e..b7d32576147 100644
--- a/src/server/game/Guilds/GuildMgr.cpp
+++ b/src/server/game/Guilds/GuildMgr.cpp
@@ -17,8 +17,8 @@
#include "GuildMgr.h"
#include "AchievementMgr.h"
-#include "DatabaseEnv.h"
#include "DB2Stores.h"
+#include "DatabaseEnv.h"
#include "Guild.h"
#include "Log.h"
#include "ObjectMgr.h"
@@ -29,15 +29,13 @@ GuildMgr::GuildMgr() : NextGuildId(UI64LIT(1))
{
}
-GuildMgr::~GuildMgr()
-{
- for (GuildContainer::iterator itr = GuildStore.begin(); itr != GuildStore.end(); ++itr)
- delete itr->second;
-}
+GuildMgr::~GuildMgr() = default;
void GuildMgr::AddGuild(Guild* guild)
{
- GuildStore[guild->GetId()] = guild;
+ Trinity::unique_trackable_ptr<Guild>& ptr = GuildStore[guild->GetId()];
+ ptr.reset(guild);
+ guild->SetWeakPtr(ptr);
}
void GuildMgr::RemoveGuild(ObjectGuid::LowType guildId)
@@ -66,7 +64,7 @@ Guild* GuildMgr::GetGuildById(ObjectGuid::LowType guildId) const
{
GuildContainer::const_iterator itr = GuildStore.find(guildId);
if (itr != GuildStore.end())
- return itr->second;
+ return itr->second.get();
return nullptr;
}
@@ -84,9 +82,9 @@ Guild* GuildMgr::GetGuildByGuid(ObjectGuid guid) const
Guild* GuildMgr::GetGuildByName(std::string_view guildName) const
{
- for (auto [id, guild] : GuildStore)
+ for (auto const& [id, guild] : GuildStore)
if (StringEqualI(guild->GetName(), guildName))
- return guild;
+ return guild.get();
return nullptr;
}
@@ -109,7 +107,7 @@ Guild* GuildMgr::GetGuildByLeader(ObjectGuid guid) const
{
for (GuildContainer::const_iterator itr = GuildStore.begin(); itr != GuildStore.end(); ++itr)
if (itr->second->GetLeaderGUID() == guid)
- return itr->second;
+ return itr->second.get();
return nullptr;
}
@@ -483,10 +481,10 @@ void GuildMgr::LoadGuilds()
for (GuildContainer::iterator itr = GuildStore.begin(); itr != GuildStore.end();)
{
- Guild* guild = itr->second;
+ Guild* guild = itr->second.get();
++itr;
- if (guild && !guild->Validate())
- delete guild;
+ if (guild)
+ guild->Validate();
}
TC_LOG_INFO("server.loading", ">> Validated data of loaded guilds in {} ms", GetMSTimeDiffToNow(oldMSTime));
@@ -562,6 +560,6 @@ void GuildMgr::ResetTimes(bool week)
CharacterDatabase.Execute(CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_MEMBER_WITHDRAW));
for (GuildContainer::const_iterator itr = GuildStore.begin(); itr != GuildStore.end(); ++itr)
- if (Guild* guild = itr->second)
+ if (Guild* guild = itr->second.get())
guild->ResetTimes(week);
}
diff --git a/src/server/game/Guilds/GuildMgr.h b/src/server/game/Guilds/GuildMgr.h
index f700f8122c1..5c021648a28 100644
--- a/src/server/game/Guilds/GuildMgr.h
+++ b/src/server/game/Guilds/GuildMgr.h
@@ -20,6 +20,7 @@
#include "Define.h"
#include "ObjectGuid.h"
+#include "UniqueTrackablePtr.h"
#include <unordered_map>
#include <vector>
@@ -60,7 +61,7 @@ public:
void ResetTimes(bool week);
protected:
- typedef std::unordered_map<ObjectGuid::LowType, Guild*> GuildContainer;
+ typedef std::unordered_map<ObjectGuid::LowType, Trinity::unique_trackable_ptr<Guild>> GuildContainer;
ObjectGuid::LowType NextGuildId;
GuildContainer GuildStore;
std::vector<GuildReward> GuildRewards;
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index 01d75d58b51..ebb57753f3a 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -2314,7 +2314,7 @@ void WorldSession::HandleCharRaceOrFactionChangeCallback(std::shared_ptr<WorldPa
{
// Reset guild
if (Guild* guild = sGuildMgr->GetGuildById(characterInfo->GuildId))
- guild->DeleteMember(trans, factionChangeInfo->Guid, false, false, true);
+ guild->DeleteMember(trans, factionChangeInfo->Guid, false, false);
Player::LeaveAllArenaTeams(factionChangeInfo->Guid);
}
@@ -2432,14 +2432,14 @@ void WorldSession::HandleCharRaceOrFactionChangeCallback(std::shared_ptr<WorldPa
// Disable all old-faction specific quests
{
ObjectMgr::QuestContainer const& questTemplates = sObjectMgr->GetQuestTemplates();
- for (auto const& questTemplatePair : questTemplates)
+ for (auto const& [questId, quest] : questTemplates)
{
Trinity::RaceMask<uint64> newRaceMask = (newTeamId == TEAM_ALLIANCE) ? RACEMASK_ALLIANCE : RACEMASK_HORDE;
- if (questTemplatePair.second.GetAllowableRaces().RawValue != uint64(-1) && (questTemplatePair.second.GetAllowableRaces() & newRaceMask).IsEmpty())
+ if (quest->GetAllowableRaces().RawValue != uint64(-1) && (quest->GetAllowableRaces() & newRaceMask).IsEmpty())
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_QUESTSTATUS_REWARDED_ACTIVE_BY_QUEST);
stmt->setUInt64(0, lowGuid);
- stmt->setUInt32(1, questTemplatePair.first);
+ stmt->setUInt32(1, questId);
trans->Append(stmt);
}
}
diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h
index 78a8cb3e647..0339d92a6ee 100644
--- a/src/server/game/Maps/Map.h
+++ b/src/server/game/Maps/Map.h
@@ -35,6 +35,7 @@
#include "SharedDefines.h"
#include "SpawnData.h"
#include "Timer.h"
+#include "UniqueTrackablePtr.h"
#include "WorldStateDefines.h"
#include <bitset>
#include <list>
@@ -312,6 +313,9 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
uint32 GetInstanceId() const { return i_InstanceId; }
+ Trinity::unique_weak_ptr<Map> GetWeakPtr() const { return m_weakRef; }
+ void SetWeakPtr(Trinity::unique_weak_ptr<Map> weakRef) { m_weakRef = std::move(weakRef); }
+
static TransferAbortParams PlayerCannotEnter(uint32 mapid, Player* player);
virtual TransferAbortParams CannotEnter(Player* /*player*/) { return { TRANSFER_ABORT_NONE }; }
char const* GetMapName() const;
@@ -605,6 +609,7 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
MapEntry const* i_mapEntry;
Difficulty i_spawnMode;
uint32 i_InstanceId;
+ Trinity::unique_weak_ptr<Map> m_weakRef;
uint32 m_unloadTimer;
float m_VisibleDistance;
DynamicMapTree _dynamicTree;
diff --git a/src/server/game/Maps/MapManager.cpp b/src/server/game/Maps/MapManager.cpp
index a5adf85a197..3288b8551d1 100644
--- a/src/server/game/Maps/MapManager.cpp
+++ b/src/server/game/Maps/MapManager.cpp
@@ -65,7 +65,8 @@ MapManager* MapManager::instance()
Map* MapManager::FindMap_i(uint32 mapId, uint32 instanceId) const
{
- return Trinity::Containers::MapGetValuePtr(i_maps, { mapId, instanceId });
+ auto itr = i_maps.find({ mapId, instanceId });
+ return itr != i_maps.end() ? itr->second.get() : nullptr;
}
Map* MapManager::CreateWorldMap(uint32 mapId, uint32 instanceId)
@@ -230,7 +231,14 @@ Map* MapManager::CreateMap(uint32 mapId, Player* player)
}
if (map)
- i_maps[{ map->GetId(), map->GetInstanceId() }] = map;
+ {
+ Trinity::unique_trackable_ptr<Map>& ptr = i_maps[{ map->GetId(), map->GetInstanceId() }];
+ if (ptr.get() != map)
+ {
+ ptr.reset(map);
+ map->SetWeakPtr(ptr);
+ }
+ }
return map;
}
@@ -295,7 +303,7 @@ void MapManager::Update(uint32 diff)
{
if (iter->second->CanUnload(diff))
{
- if (DestroyMap(iter->second))
+ if (DestroyMap(iter->second.get()))
iter = i_maps.erase(iter);
else
++iter;
@@ -332,7 +340,6 @@ bool MapManager::DestroyMap(Map* map)
sMapMgr->FreeInstanceId(map->GetInstanceId());
// erase map
- delete map;
return true;
}
@@ -348,9 +355,6 @@ void MapManager::UnloadAll()
iter->second->UnloadAll();
// then delete them
- for (auto iter = i_maps.begin(); iter != i_maps.end(); ++iter)
- delete iter->second;
-
i_maps.clear();
if (m_updater.activated())
diff --git a/src/server/game/Maps/MapManager.h b/src/server/game/Maps/MapManager.h
index 53a7c731c43..aec828daff5 100644
--- a/src/server/game/Maps/MapManager.h
+++ b/src/server/game/Maps/MapManager.h
@@ -23,6 +23,7 @@
#include "MapUpdater.h"
#include "Position.h"
#include "SharedDefines.h"
+#include "UniqueTrackablePtr.h"
#include <boost/dynamic_bitset_fwd.hpp>
#include <map>
#include <shared_mutex>
@@ -131,7 +132,7 @@ class TC_GAME_API MapManager
private:
using MapKey = std::pair<uint32, uint32>;
- typedef std::map<MapKey, Map*> MapMapType;
+ typedef std::map<MapKey, Trinity::unique_trackable_ptr<Map>> MapMapType;
typedef boost::dynamic_bitset<size_t> InstanceIds;
Map* FindMap_i(uint32 mapId, uint32 instanceId) const;
@@ -161,7 +162,7 @@ void MapManager::DoForAllMaps(Worker&& worker)
std::shared_lock<std::shared_mutex> lock(_mapsLock);
for (auto const& [key, map] : i_maps)
- worker(map);
+ worker(map.get());
}
template<typename Worker>
@@ -175,7 +176,7 @@ void MapManager::DoForAllMapsWithMapId(uint32 mapId, Worker&& worker)
);
for (auto const& [key, map] : range)
- worker(map);
+ worker(map.get());
}
#define sMapMgr MapManager::instance()
diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h
index f795eedb51c..a518302143a 100644
--- a/src/server/game/Quests/QuestDef.h
+++ b/src/server/game/Quests/QuestDef.h
@@ -25,6 +25,7 @@
#include "Optional.h"
#include "RaceMask.h"
#include "SharedDefines.h"
+#include "UniqueTrackablePtr.h"
#include "WorldPacket.h"
#include <bitset>
#include <vector>
@@ -719,6 +720,8 @@ class TC_GAME_API Quest
// Helpers
static uint32 RoundXPValue(uint32 xp);
+ Trinity::unique_weak_ptr<Quest> GetWeakPtr() const { return _weakRef; }
+
std::vector<uint32> DependentPreviousQuests;
std::vector<uint32> DependentBreadcrumbQuests;
std::array<WorldPacket, TOTAL_LOCALES> QueryData;
@@ -828,6 +831,8 @@ class TC_GAME_API Quest
uint32 _specialFlags = 0; // custom flags, not sniffed/WDB
std::bitset<MAX_QUEST_OBJECTIVE_TYPE> _usedQuestObjectiveTypes;
uint32 _scriptId = 0;
+
+ Trinity::unique_weak_ptr<Quest> _weakRef;
};
struct QuestStatusData
diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp
index 02790ed5d77..329ba558659 100644
--- a/src/server/game/Spells/Auras/SpellAuras.cpp
+++ b/src/server/game/Spells/Auras/SpellAuras.cpp
@@ -467,7 +467,7 @@ m_applyTime(GameTime::GetGameTime()), m_owner(createInfo._owner), m_timeCla(0),
m_casterLevel(createInfo.Caster ? createInfo.Caster->GetLevel() : m_spellInfo->SpellLevel), m_procCharges(0), m_stackAmount(1),
m_isRemoved(false), m_isSingleTarget(false), m_isUsingCharges(false), m_dropEvent(nullptr),
m_procCooldown(TimePoint::min()),
-m_lastProcAttemptTime(GameTime::Now() - Seconds(10)), m_lastProcSuccessTime(GameTime::Now() - Seconds(120))
+m_lastProcAttemptTime(GameTime::Now() - Seconds(10)), m_lastProcSuccessTime(GameTime::Now() - Seconds(120)), m_scriptRef(this, NoopAuraDeleter())
{
for (SpellPowerEntry const* power : m_spellInfo->PowerCosts)
if (power && (power->ManaPerSecond != 0 || power->PowerPctPerSecond > 0.0f))
@@ -614,6 +614,8 @@ void Aura::_Remove(AuraRemoveMode removeMode)
m_dropEvent->ScheduleAbort();
m_dropEvent = nullptr;
}
+
+ m_scriptRef = nullptr;
}
void Aura::UpdateTargetMap(Unit* caster, bool apply)
diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h
index 195f5a2fda6..c38f8ee78ec 100644
--- a/src/server/game/Spells/Auras/SpellAuras.h
+++ b/src/server/game/Spells/Auras/SpellAuras.h
@@ -20,6 +20,7 @@
#include "SpellAuraDefines.h"
#include "SpellInfo.h"
+#include "UniqueTrackablePtr.h"
#include <typeinfo>
class SpellInfo;
@@ -308,6 +309,8 @@ class TC_GAME_API Aura
virtual std::string GetDebugInfo() const;
+ Trinity::unique_weak_ptr<Aura> GetWeakPtr() const { return m_scriptRef; }
+
Aura(Aura const&) = delete;
Aura(Aura&&) = delete;
@@ -356,6 +359,9 @@ class TC_GAME_API Aura
std::vector<AuraApplication*> _removedApplications;
AuraEffectVector _effects;
+
+ struct NoopAuraDeleter { void operator()(Aura*) const { /*noop - not managed*/ } };
+ Trinity::unique_trackable_ptr<Aura> m_scriptRef;
};
class TC_GAME_API UnitAura : public Aura
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 53f3f79bc92..bb43a8be767 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -59,6 +59,7 @@
#include "TemporarySummon.h"
#include "TradeData.h"
#include "TraitPackets.h"
+#include "UniqueTrackablePtr.h"
#include "Util.h"
#include "VMapFactory.h"
#include "Vehicle.h"
@@ -483,18 +484,19 @@ SpellValue::SpellValue(SpellInfo const* proto, WorldObject const* caster)
class TC_GAME_API SpellEvent : public BasicEvent
{
public:
- SpellEvent(Spell* spell);
+ explicit SpellEvent(Spell* spell);
~SpellEvent();
bool Execute(uint64 e_time, uint32 p_time) override;
void Abort(uint64 e_time) override;
bool IsDeletable() const override;
- Spell const* GetSpell() const { return m_Spell; }
+ Spell const* GetSpell() const { return m_Spell.get(); }
+ Trinity::unique_weak_ptr<Spell> GetSpellWeakPtr() const { return m_Spell; }
std::string GetDebugInfo() const { return m_Spell->GetDebugInfo(); }
protected:
- Spell* m_Spell;
+ Trinity::unique_trackable_ptr<Spell> m_Spell;
};
Spell::Spell(WorldObject* caster, SpellInfo const* info, TriggerCastFlags triggerFlags, ObjectGuid originalCasterGUID /*= ObjectGuid::Empty*/,
@@ -8116,9 +8118,8 @@ Unit* Spell::GetUnitCasterForEffectHandlers() const
return m_originalCaster ? m_originalCaster : m_caster->ToUnit();
}
-SpellEvent::SpellEvent(Spell* spell) : BasicEvent()
+SpellEvent::SpellEvent(Spell* spell) : BasicEvent(), m_Spell(spell)
{
- m_Spell = spell;
}
SpellEvent::~SpellEvent()
@@ -8126,11 +8127,7 @@ SpellEvent::~SpellEvent()
if (m_Spell->getState() != SPELL_STATE_FINISHED)
m_Spell->cancel();
- if (m_Spell->IsDeletable())
- {
- delete m_Spell;
- }
- else
+ if (!m_Spell->IsDeletable())
{
TC_LOG_ERROR("spells", "~SpellEvent: {} {} tried to delete non-deletable spell {}. Was not deleted, causes memory leak.",
(m_Spell->GetCaster()->GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature"), m_Spell->GetCaster()->GetGUID().ToString(), m_Spell->m_spellInfo->Id);
@@ -8958,6 +8955,11 @@ std::string Spell::GetDebugInfo() const
return sstr.str();
}
+Trinity::unique_weak_ptr<Spell> Spell::GetWeakPtr() const
+{
+ return _spellEvent->GetSpellWeakPtr();
+}
+
bool Spell::IsWithinLOS(WorldObject const* source, WorldObject const* target, bool targetAsSourceLocation, VMAP::ModelIgnoreFlags ignoreFlags) const
{
if (m_spellInfo->HasAttribute(SPELL_ATTR2_IGNORE_LINE_OF_SIGHT))
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index 9deaa008721..0c484b5ba56 100644
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -26,6 +26,7 @@
#include "Position.h"
#include "SharedDefines.h"
#include "SpellDefines.h"
+#include "UniqueTrackablePtr.h"
#include <memory>
namespace WorldPackets::Spells
@@ -664,6 +665,9 @@ class TC_GAME_API Spell
int64 GetCorpseTargetCountForEffect(SpellEffIndex effect) const;
std::string GetDebugInfo() const;
+
+ Trinity::unique_weak_ptr<Spell> GetWeakPtr() const;
+
void CallScriptOnResistAbsorbCalculateHandlers(DamageInfo const& damageInfo, uint32& resistAmount, int32& absorbAmount);
bool IsWithinLOS(WorldObject const* source, WorldObject const* target, bool targetAsSourceLocation, VMAP::ModelIgnoreFlags ignoreFlags) const;
diff --git a/src/server/scripts/Commands/cs_guild.cpp b/src/server/scripts/Commands/cs_guild.cpp
index c824e370632..1518d0b5422 100644
--- a/src/server/scripts/Commands/cs_guild.cpp
+++ b/src/server/scripts/Commands/cs_guild.cpp
@@ -143,8 +143,6 @@ public:
return false;
targetGuild->Disband();
- delete targetGuild;
-
return true;
}
@@ -192,7 +190,7 @@ public:
return false;
CharacterDatabaseTransaction trans(nullptr);
- targetGuild->DeleteMember(trans, targetGuid, false, true, true);
+ targetGuild->DeleteMember(trans, targetGuid, false, true);
return true;
}
diff --git a/src/server/scripts/Commands/cs_learn.cpp b/src/server/scripts/Commands/cs_learn.cpp
index 2986bb3ce13..2bbcf492c4a 100644
--- a/src/server/scripts/Commands/cs_learn.cpp
+++ b/src/server/scripts/Commands/cs_learn.cpp
@@ -135,8 +135,8 @@ public:
Player* player = handler->GetPlayer();
for (auto const& [id, quest] : sObjectMgr->GetQuestTemplates())
{
- if (quest.GetAllowableClasses() && player->SatisfyQuestClass(&quest, false))
- player->LearnQuestRewardedSpells(&quest);
+ if (quest->GetAllowableClasses() && player->SatisfyQuestClass(quest.get(), false))
+ player->LearnQuestRewardedSpells(quest.get());
}
return true;
}
diff --git a/src/server/scripts/Commands/cs_lookup.cpp b/src/server/scripts/Commands/cs_lookup.cpp
index 354820cb2ec..e2e62eb3373 100644
--- a/src/server/scripts/Commands/cs_lookup.cpp
+++ b/src/server/scripts/Commands/cs_lookup.cpp
@@ -684,16 +684,16 @@ public:
if (handler->GetSession())
{
int32 maxLevel = 0;
- if (Optional<ContentTuningLevels> questLevels = sDB2Manager.GetContentTuningData(questTemplatePair.second.GetContentTuningId(), 0))
+ if (Optional<ContentTuningLevels> questLevels = sDB2Manager.GetContentTuningData(questTemplatePair.second->GetContentTuningId(), 0))
maxLevel = questLevels->MaxLevel;
int32 scalingFactionGroup = 0;
- if (ContentTuningEntry const* contentTuning = sContentTuningStore.LookupEntry(questTemplatePair.second.GetContentTuningId()))
+ if (ContentTuningEntry const* contentTuning = sContentTuningStore.LookupEntry(questTemplatePair.second->GetContentTuningId()))
scalingFactionGroup = contentTuning->GetScalingFactionGroup();
handler->PSendSysMessage(LANG_QUEST_LIST_CHAT, questTemplatePair.first, questTemplatePair.first,
- handler->GetSession()->GetPlayer()->GetQuestLevel(&questTemplatePair.second),
- handler->GetSession()->GetPlayer()->GetQuestMinLevel(&questTemplatePair.second),
+ handler->GetSession()->GetPlayer()->GetQuestLevel(questTemplatePair.second.get()),
+ handler->GetSession()->GetPlayer()->GetQuestMinLevel(questTemplatePair.second.get()),
maxLevel, scalingFactionGroup,
title.c_str(), statusStr);
}
@@ -708,7 +708,7 @@ public:
}
}
- std::string title = questTemplatePair.second.GetLogTitle();
+ std::string title = questTemplatePair.second->GetLogTitle();
if (title.empty())
continue;
@@ -743,16 +743,16 @@ public:
if (handler->GetSession())
{
int32 maxLevel = 0;
- if (Optional<ContentTuningLevels> questLevels = sDB2Manager.GetContentTuningData(questTemplatePair.second.GetContentTuningId(), 0))
+ if (Optional<ContentTuningLevels> questLevels = sDB2Manager.GetContentTuningData(questTemplatePair.second->GetContentTuningId(), 0))
maxLevel = questLevels->MaxLevel;
int32 scalingFactionGroup = 0;
- if (ContentTuningEntry const* contentTuning = sContentTuningStore.LookupEntry(questTemplatePair.second.GetContentTuningId()))
+ if (ContentTuningEntry const* contentTuning = sContentTuningStore.LookupEntry(questTemplatePair.second->GetContentTuningId()))
scalingFactionGroup = contentTuning->GetScalingFactionGroup();
handler->PSendSysMessage(LANG_QUEST_LIST_CHAT, questTemplatePair.first, questTemplatePair.first,
- handler->GetSession()->GetPlayer()->GetQuestLevel(&questTemplatePair.second),
- handler->GetSession()->GetPlayer()->GetQuestMinLevel(&questTemplatePair.second),
+ handler->GetSession()->GetPlayer()->GetQuestLevel(questTemplatePair.second.get()),
+ handler->GetSession()->GetPlayer()->GetQuestMinLevel(questTemplatePair.second.get()),
maxLevel, scalingFactionGroup,
title.c_str(), statusStr);
}