aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp27
-rw-r--r--src/server/game/Entities/GameObject/GameObject.h1
2 files changed, 16 insertions, 12 deletions
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index 8b3946d22c5..0ed19a3642e 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -991,10 +991,7 @@ void GameObject::Update(uint32 diff)
// If there is no restock timer, or if the restock timer passed, the chest becomes ready to loot
m_restockTime = 0;
m_lootState = GO_READY;
- m_loot = nullptr;
- m_personalLoot.clear();
- m_unique_users.clear();
- m_usetimes = 0;
+ ClearLoot();
UpdateDynamicFlagsForNearbyPlayers();
break;
default:
@@ -1223,10 +1220,7 @@ void GameObject::Update(uint32 diff)
{
m_restockTime = 0;
m_lootState = GO_READY;
- m_loot = nullptr;
- m_personalLoot.clear();
- m_unique_users.clear();
- m_usetimes = 0;
+ ClearLoot();
UpdateDynamicFlagsForNearbyPlayers();
}
break;
@@ -1300,10 +1294,7 @@ void GameObject::Update(uint32 diff)
return;
}
- m_loot = nullptr;
- m_personalLoot.clear();
- m_unique_users.clear();
- m_usetimes = 0;
+ ClearLoot();
// Do not delete chests or goobers that are not consumed on loot, while still allowing them to despawn when they expire if summoned
bool isSummonedAndExpired = (GetOwner() || GetSpellId()) && m_respawnTime == 0;
@@ -3323,6 +3314,18 @@ void GameObject::SetLootState(LootState state, Unit* unit)
}
}
+void GameObject::ClearLoot()
+{
+ // Unlink loot objects from this GameObject before destroying to avoid accessing freed memory from Loot destructor
+ std::unique_ptr<Loot> loot(std::move(m_loot));
+ std::unordered_map<ObjectGuid, std::unique_ptr<Loot>> personalLoot(std::move(m_personalLoot));
+
+ loot.reset();
+ personalLoot.clear();
+ m_unique_users.clear();
+ m_usetimes = 0;
+}
+
bool GameObject::IsFullyLooted() const
{
if (m_loot && !m_loot->isLooted())
diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h
index 6800d3c9aed..170e5c18c2b 100644
--- a/src/server/game/Entities/GameObject/GameObject.h
+++ b/src/server/game/Entities/GameObject/GameObject.h
@@ -263,6 +263,7 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject<GameObject>
void AddLootMode(uint16 lootMode) { m_LootMode |= lootMode; }
void RemoveLootMode(uint16 lootMode) { m_LootMode &= ~lootMode; }
void ResetLootMode() { m_LootMode = LOOT_MODE_DEFAULT; }
+ void ClearLoot();
bool IsFullyLooted() const;
void OnLootRelease(Player* looter);