Core/GameObjects: Unlink loot from gameobject before deleting it

Closes #28541
Closes #28610
This commit is contained in:
Shauren
2022-12-20 18:30:30 +01:00
parent 3596d1c8f1
commit dfd2e6d901
2 changed files with 16 additions and 12 deletions

View File

@@ -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())

View File

@@ -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);