diff options
| author | Rat <gmstreetrat@gmail.com> | 2015-03-16 07:28:49 +0100 |
|---|---|---|
| committer | Rat <gmstreetrat@gmail.com> | 2015-03-16 07:28:49 +0100 |
| commit | 8f3a80c1cf39978056979a0bcbcb7321e510c101 (patch) | |
| tree | fb935f44c86ea9ae84a232f499757b97728e86c4 /src/server/game/Entities/Object | |
| parent | 8366ed5a720047102fc44a7ae89adc8ed83f9076 (diff) | |
Core/Phases: Ported new phasing system from 4.3.4 branch and fixed some map swap logic
Diffstat (limited to 'src/server/game/Entities/Object')
| -rw-r--r-- | src/server/game/Entities/Object/Object.cpp | 240 | ||||
| -rw-r--r-- | src/server/game/Entities/Object/Object.h | 20 |
2 files changed, 237 insertions, 23 deletions
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index cb504f6cb19..953d3b9d596 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -1557,7 +1557,7 @@ void MovementInfo::OutDebug() WorldObject::WorldObject(bool isWorldObject) : WorldLocation(), LastUsedScriptID(0), m_name(""), m_isActive(false), m_isWorldObject(isWorldObject), m_zoneScript(NULL), m_transport(NULL), m_currMap(NULL), m_InstanceId(0), -m_phaseMask(PHASEMASK_NORMAL), m_notifyflags(0), m_executed_notifies(0) +m_phaseMask(PHASEMASK_NORMAL), _dbPhase(0), m_notifyflags(0), m_executed_notifies(0) { m_serverSideVisibility.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_ALIVE | GHOST_VISIBILITY_GHOST); m_serverSideVisibilityDetect.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_ALIVE); @@ -2463,10 +2463,6 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert } } - std::set<uint32> phases; - if (summoner) - phases = summoner->GetPhases(); - TempSummon* summon = NULL; switch (mask) { @@ -2494,8 +2490,7 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert } // Set the summon to the summoner's phase - for (auto phaseId : phases) - summon->SetInPhase(phaseId, false, true); + summon->CopyPhaseFrom(summoner); summon->SetUInt32Value(UNIT_CREATED_BY_SPELL, spellId); @@ -2591,8 +2586,7 @@ GameObject* WorldObject::SummonGameObject(uint32 entry, float x, float y, float return NULL; } - for (auto phase : GetPhases()) - go->SetInPhase(phase, false, true); + go->CopyPhaseFrom(this); go->SetRespawnTime(respawnTime); if (GetTypeId() == TYPEID_PLAYER || GetTypeId() == TYPEID_UNIT) //not sure how to handle this @@ -3003,12 +2997,138 @@ void WorldObject::SetPhaseMask(uint32 newPhaseMask, bool update) UpdateObjectVisibility(); } -void WorldObject::SetInPhase(uint32 id, bool update, bool apply) +bool WorldObject::HasInPhaseList(uint32 phase) { - if (apply) - _phases.insert(id); - else - _phases.erase(id); + return _phases.find(phase) != _phases.end(); +} + +// Updates Area based phases, does not remove phases from auras +// Phases from gm commands are not taken into calculations, they can be lost!! +void WorldObject::UpdateAreaPhase() +{ + bool updateNeeded = false; + PhaseInfo phases = sObjectMgr->GetAreaPhases(); + for (PhaseInfo::const_iterator itr = phases.begin(); itr != phases.end(); ++itr) + { + uint32 areaId = itr->first; + for (uint32 phaseId : itr->second) + { + if (areaId == GetAreaId()) + { + ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_PHASE, phaseId); + if (sConditionMgr->IsObjectMeetToConditions(this, conditions)) + { + // add new phase if condition passed, true if it wasnt added before + bool up = SetInPhase(phaseId, false, true); + if (!updateNeeded && up) + updateNeeded = true; + } + else + { + // condition failed, remove phase, true if there was something removed + bool up = SetInPhase(phaseId, false, false); + if (!updateNeeded && up) + updateNeeded = true; + } + } + else + { + // not in area, remove phase, true if there was something removed + bool up = SetInPhase(phaseId, false, false); + if (!updateNeeded && up) + updateNeeded = true; + } + } + } + + // do not remove a phase if it would be removed by an area but we have the same phase from an aura + if (Unit* unit = ToUnit()) + { + Unit::AuraEffectList const& auraPhaseList = unit->GetAuraEffectsByType(SPELL_AURA_PHASE); + for (Unit::AuraEffectList::const_iterator itr = auraPhaseList.begin(); itr != auraPhaseList.end(); ++itr) + { + uint32 phase = uint32((*itr)->GetMiscValueB()); + bool up = SetInPhase(phase, false, true); + if (!updateNeeded && up) + updateNeeded = true; + } + Unit::AuraEffectList const& auraPhaseGroupList = unit->GetAuraEffectsByType(SPELL_AURA_PHASE_GROUP); + for (Unit::AuraEffectList::const_iterator itr = auraPhaseGroupList.begin(); itr != auraPhaseGroupList.end(); ++itr) + { + bool up = false; + uint32 phaseGroup = uint32((*itr)->GetMiscValueB()); + std::set<uint32> const& phases = sDB2Manager.GetPhasesForGroup(phaseGroup); + for (uint32 phase : phases) + up = SetInPhase(phase, false, true); + if (!updateNeeded && up) + updateNeeded = true; + } + } + + // only update visibility and send packets if there was a change in the phase list + + if (updateNeeded && GetTypeId() == TYPEID_PLAYER && IsInWorld()) + ToPlayer()->GetSession()->SendSetPhaseShift(GetPhases(), GetTerrainSwaps(), GetWorldMapAreaSwaps()); + + // only update visibilty once, to prevent objects appearing for a moment while adding in multiple phases + if (updateNeeded && IsInWorld()) + UpdateObjectVisibility(); +} + +bool WorldObject::SetInPhase(uint32 id, bool update, bool apply) +{ + if (id) + { + if (apply) + { + if (HasInPhaseList(id)) // do not run the updates if we are already in this phase + return false; + _phases.insert(id); + } + else + { + for (uint32 phaseId : sObjectMgr->GetPhasesForArea(GetAreaId())) + { + if (id == phaseId) + { + ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_PHASE, phaseId); + if (sConditionMgr->IsObjectMeetToConditions(this, conditions)) + { + // if area phase passes the condition we should not remove it (ie: if remove called from aura remove) + // this however breaks the .mod phase command, you wont be able to remove any area based phases with it + return false; + } + } + } + if (!HasInPhaseList(id)) // do not run the updates if we are not in this phase + return false; + _phases.erase(id); + } + } + RebuildTerrainSwaps(); + + if (update && IsInWorld()) + UpdateObjectVisibility(); + return true; +} + +void WorldObject::CopyPhaseFrom(WorldObject* obj, bool update) +{ + if (!obj) + return; + + for (uint32 phase : obj->GetPhases()) + SetInPhase(phase, false, true); + + if (update && IsInWorld()) + UpdateObjectVisibility(); +} + +void WorldObject::ClearPhases(bool update) +{ + _phases.clear(); + + RebuildTerrainSwaps(); if (update && IsInWorld()) UpdateObjectVisibility(); @@ -3026,13 +3146,10 @@ bool WorldObject::IsInPhase(WorldObject const* obj) const if (obj->GetPhases().empty() && IsInPhase(169)) return true; - return Trinity::Containers::Intersects(_phases.begin(), _phases.end(), obj->GetPhases().begin(), obj->GetPhases().end()); -} + if (GetTypeId() == TYPEID_PLAYER && ToPlayer()->IsGameMaster()) + return true; -bool WorldObject::InSamePhase(WorldObject const* obj) const -{ - return IsInPhase(obj); - // return InSamePhase(obj->GetPhaseMask()); + return Trinity::Containers::Intersects(_phases.begin(), _phases.end(), obj->GetPhases().begin(), obj->GetPhases().end()); } void WorldObject::PlayDistanceSound(uint32 sound_id, Player* target /*= NULL*/) @@ -3181,3 +3298,86 @@ ObjectGuid WorldObject::GetTransGUID() const return GetTransport()->GetGUID(); return ObjectGuid::Empty; } + +void WorldObject::RebuildTerrainSwaps() +{ + // Clear all terrain swaps, will be rebuilt below + // Reason for this is, multiple phases can have the same terrain swap, we should not remove the swap if another phase still use it + _terrainSwaps.clear(); + ConditionList conditions; + + // Check all applied phases for terrain swap and add it only once + for (uint32 phaseId : _phases) + { + std::list<uint32>& swaps = sObjectMgr->GetPhaseTerrainSwaps(phaseId); + + for (uint32 swap : swaps) + { + // only add terrain swaps for current map + MapEntry const* mapEntry = sMapStore.LookupEntry(swap); + if (!mapEntry || mapEntry->ParentMapID != GetMapId()) + continue; + + conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_TERRAIN_SWAP, swap); + + if (sConditionMgr->IsObjectMeetToConditions(this, conditions)) + _terrainSwaps.insert(swap); + } + } + + // get default terrain swaps, only for current map always + std::list<uint32>& mapSwaps = sObjectMgr->GetDefaultTerrainSwaps(GetMapId()); + + for (uint32 swap : mapSwaps) + { + conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_TERRAIN_SWAP, swap); + + if (sConditionMgr->IsObjectMeetToConditions(this, conditions)) + _terrainSwaps.insert(swap); + } + + // online players have a game client with world map display + if (GetTypeId() == TYPEID_PLAYER) + RebuildWorldMapAreaSwaps(); +} + +void WorldObject::RebuildWorldMapAreaSwaps() +{ + // Clear all world map area swaps, will be rebuilt below + _worldMapAreaSwaps.clear(); + + // get ALL default terrain swaps, if we are using it (condition is true) + // send the worldmaparea for it, to see swapped worldmaparea in client from other maps too, not just from our current + TerrainPhaseInfo defaults = sObjectMgr->GetDefaultTerrainSwapStore(); + for (TerrainPhaseInfo::const_iterator itr = defaults.begin(); itr != defaults.end(); ++itr) + { + for (uint32 swap : itr->second) + { + ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_TERRAIN_SWAP, swap); + if (sConditionMgr->IsObjectMeetToConditions(this, conditions)) + { + for (uint32 map : sObjectMgr->GetTerrainWorldMaps(swap)) + _worldMapAreaSwaps.insert(map); + } + } + } + + // Check all applied phases for world map area swaps + for (uint32 phaseId : _phases) + { + std::list<uint32>& swaps = sObjectMgr->GetPhaseTerrainSwaps(phaseId); + + for (uint32 swap : swaps) + { + // add world map swaps for ANY map + + ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_TERRAIN_SWAP, swap); + + if (sConditionMgr->IsObjectMeetToConditions(this, conditions)) + { + for (uint32 map : sObjectMgr->GetTerrainWorldMaps(swap)) + _worldMapAreaSwaps.insert(map); + } + } + } +}
\ No newline at end of file diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index e8022df5462..54fd48fa4b9 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -612,13 +612,24 @@ class WorldObject : public Object, public WorldLocation uint32 GetInstanceId() const { return m_InstanceId; } virtual void SetPhaseMask(uint32 newPhaseMask, bool update); - virtual void SetInPhase(uint32 id, bool update, bool apply); + virtual bool SetInPhase(uint32 id, bool update, bool apply); + void CopyPhaseFrom(WorldObject* obj, bool update = false); + void UpdateAreaPhase(); + void ClearPhases(bool update = false); + void RebuildTerrainSwaps(); + void RebuildWorldMapAreaSwaps(); + bool HasInPhaseList(uint32 phase); uint32 GetPhaseMask() const { return m_phaseMask; } - bool InSamePhase(WorldObject const* obj) const; - bool InSamePhase(uint32 phasemask) const { return (GetPhaseMask() & phasemask) != 0; } bool IsInPhase(uint32 phase) const { return _phases.find(phase) != _phases.end(); } bool IsInPhase(WorldObject const* obj) const; + bool IsInTerrainSwap(uint32 terrainSwap) const { return _terrainSwaps.find(terrainSwap) != _terrainSwaps.end(); } std::set<uint32> const& GetPhases() const { return _phases; } + std::set<uint32> const& GetTerrainSwaps() const { return _terrainSwaps; } + std::set<uint32> const& GetWorldMapAreaSwaps() const { return _worldMapAreaSwaps; } + int32 GetDBPhase() { return _dbPhase; } + + // if negative it is used as PhaseGroupId + void SetDBPhase(int32 p) { _dbPhase = p; } uint32 GetZoneId() const; uint32 GetAreaId() const; @@ -791,6 +802,9 @@ class WorldObject : public Object, public WorldLocation uint32 m_InstanceId; // in map copy with instance id uint32 m_phaseMask; // in area phase state std::set<uint32> _phases; + std::set<uint32> _terrainSwaps; + std::set<uint32> _worldMapAreaSwaps; + int32 _dbPhase; uint16 m_notifyflags; uint16 m_executed_notifies; |
