diff options
-rwxr-xr-x | src/server/game/Entities/GameObject/GameObject.cpp | 63 | ||||
-rwxr-xr-x | src/server/game/Entities/GameObject/GameObject.h | 1 | ||||
-rwxr-xr-x | src/server/game/Entities/Unit/Unit.cpp | 10 | ||||
-rwxr-xr-x | src/server/game/Entities/Unit/Unit.h | 4 |
4 files changed, 37 insertions, 41 deletions
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index a894ee16c2d..9e514ad34bb 100755 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -91,27 +91,31 @@ void GameObject::CleanupsBeforeDelete(bool /*finalCleanup*/) RemoveFromWorld(); if (m_uint32Values) // field array can be not exist if GameOBject not loaded - { - // Possible crash at access to deleted GO in Unit::m_gameobj - if (uint64 owner_guid = GetOwnerGUID()) - { - Unit* owner = ObjectAccessor::GetUnit(*this, owner_guid); + RemoveFromOwner(); +} - if (owner) - owner->RemoveGameObject(this, false); - else - { - const char * ownerType = "creature"; - if (IS_PLAYER_GUID(owner_guid)) - ownerType = "player"; - else if (IS_PET_GUID(owner_guid)) - ownerType = "pet"; - - sLog->outError("Delete GameObject (GUID: %u Entry: %u SpellId %u LinkedGO %u) that lost references to owner (GUID %u Type '%s') GO list. Crash possible later.", - GetGUIDLow(), GetGOInfo()->entry, m_spellId, GetGOInfo()->GetLinkedGameObjectEntry(), GUID_LOPART(owner_guid), ownerType); - } - } +void GameObject::RemoveFromOwner() +{ + uint64 ownerGUID = GetOwnerGUID(); + if (!ownerGUID) + return; + + if (Unit* owner = ObjectAccessor::GetUnit(*this, ownerGUID)) + { + owner->RemoveGameObject(this, false); + ASSERT(!GetOwnerGUID()); + return; } + + const char * ownerType = "creature"; + if (IS_PLAYER_GUID(ownerGUID)) + ownerType = "player"; + else if (IS_PET_GUID(ownerGUID)) + ownerType = "pet"; + + sLog->outCrash("Delete GameObject (GUID: %u Entry: %u SpellId %u LinkedGO %u) that lost references to owner (GUID %u Type '%s') GO list. Crash possible later.", + GetGUIDLow(), GetGOInfo()->entry, m_spellId, GetGOInfo()->GetLinkedGameObjectEntry(), GUID_LOPART(ownerGUID), ownerType); + SetOwnerGUID(0); } void GameObject::AddToWorld() @@ -135,14 +139,7 @@ void GameObject::RemoveFromWorld() if (m_zoneScript) m_zoneScript->OnGameObjectRemove(this); - // Possible crash at access to deleted GO in Unit::m_gameobj - if (uint64 owner_guid = GetOwnerGUID()) - { - if (Unit* owner = GetOwner()) - owner->RemoveGameObject(this, false); - else - sLog->outError("Delete GameObject (GUID: %u Entry: %u, Name: %s) that have references in not found creature %u GO list. Crash possible later.", GetGUIDLow(), GetGOInfo()->entry, GetGOInfo()->name.c_str(), GUID_LOPART(owner_guid)); - } + RemoveFromOwner(); WorldObject::RemoveFromWorld(); sObjectAccessor->RemoveObject(this); } @@ -601,15 +598,8 @@ void GameObject::AddUniqueUse(Player* player) void GameObject::Delete() { SetLootState(GO_NOT_READY); - if (GetOwnerGUID()) - { - if (Unit* owner = GetOwner()) - owner->RemoveGameObject(this, false); - else //! Owner not in world anymore - SetOwnerGUID(0); - } + RemoveFromOwner(); - ASSERT (!GetOwnerGUID()); SendObjectDeSpawnAnim(GetGUID()); SetGoState(GO_STATE_READY); @@ -1284,8 +1274,9 @@ void GameObject::Use(Unit* user) { player->UpdateFishingSkill(); + //TODO: I do not understand this hack. Need some explanation. // prevent removing GO at spell cancel - player->RemoveGameObject(this, false); + RemoveFromOwner(); SetOwnerGUID(player->GetGUID()); //TODO: find reasonable value for fishing hole search diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h index 13b410d7373..9167b40d285 100755 --- a/src/server/game/Entities/GameObject/GameObject.h +++ b/src/server/game/Entities/GameObject/GameObject.h @@ -815,6 +815,7 @@ class GameObject : public WorldObject, public GridObject<GameObject> uint16 m_LootMode; // bitmask, default LOOT_MODE_DEFAULT, determines what loot will be lootable private: + void RemoveFromOwner(); void SwitchDoorOrButton(bool activate, bool alternative = false); //! Object distance/size - overridden from Object::_IsWithinDist. Needs to take in account proper GO size. diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 7c3fecb83e1..a01848a7228 100755 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -181,7 +181,8 @@ m_vehicleKit(NULL), m_unitTypeMask(UNIT_MASK_NONE), m_HostileRefManager(this) for (uint8 i = 0; i < MAX_SUMMON_SLOT; ++i) m_SummonSlot[i] = 0; - m_ObjectSlot[0] = m_ObjectSlot[1] = m_ObjectSlot[2] = m_ObjectSlot[3] = 0; + for (uint8 i = 0; i < MAX_GAMEOBJECT_SLOT; ++i) + m_ObjectSlot[i] = 0; m_auraUpdateIterator = m_ownedAuras.end(); @@ -4661,7 +4662,7 @@ void Unit::RemoveGameObject(GameObject* gameObj, bool del) gameObj->SetOwnerGUID(0); - for (uint32 i = 0; i < 4; ++i) + for (uint8 i = 0; i < MAX_GAMEOBJECT_SLOT; ++i) { if (m_ObjectSlot[i] == gameObj->GetGUID()) { @@ -4721,12 +4722,13 @@ void Unit::RemoveGameObject(uint32 spellid, bool del) void Unit::RemoveAllGameObjects() { // remove references to unit - for (GameObjectList::iterator i = m_gameObj.begin(); i != m_gameObj.end();) + while (!m_gameObj.empty()) { + GameObjectList::iterator i = m_gameObj.begin(); (*i)->SetOwnerGUID(0); (*i)->SetRespawnTime(0); (*i)->Delete(); - i = m_gameObj.erase(i); + m_gameObj.erase(i); } } diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 7d485a049d7..bbfe565e342 100755 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1208,6 +1208,8 @@ enum ReactiveType #define SUMMON_SLOT_QUEST 6 #define MAX_SUMMON_SLOT 7 +#define MAX_GAMEOBJECT_SLOT 4 + enum PlayerTotemType { SUMMON_TYPE_TOTEM_FIRE = 63, @@ -1891,7 +1893,7 @@ class Unit : public WorldObject uint32 m_addDmgOnce; uint64 m_SummonSlot[MAX_SUMMON_SLOT]; - uint64 m_ObjectSlot[4]; + uint64 m_ObjectSlot[MAX_GAMEOBJECT_SLOT]; ShapeshiftForm GetShapeshiftForm() const { return ShapeshiftForm(GetByteValue(UNIT_FIELD_BYTES_2, 3)); } void SetShapeshiftForm(ShapeshiftForm form) |