diff options
| author | Rat <gmstreetrat@gmail.com> | 2015-03-29 19:31:28 +0200 |
|---|---|---|
| committer | Rat <gmstreetrat@gmail.com> | 2015-03-29 19:31:28 +0200 |
| commit | ec99b191999a5da783f070ff3e1ebf05f9871219 (patch) | |
| tree | 7d604fc051ff9c79e2b9b7b33e25a14035b5bb38 /src/server/game | |
| parent | 833d57fa27c782c2e9a211ec19c554d057431243 (diff) | |
| parent | 17bd724559808b5e327a9a541063b56f21712841 (diff) | |
Merge pull request #14389 from streetrat/6.x
Core/Phases: Added new phasing system
Diffstat (limited to 'src/server/game')
29 files changed, 582 insertions, 292 deletions
diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp index b0a878aff3f..c5e3d26b00a 100644 --- a/src/server/game/Conditions/ConditionMgr.cpp +++ b/src/server/game/Conditions/ConditionMgr.cpp @@ -424,6 +424,11 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo) condMeets = true; break; } + case CONDITION_TERRAIN_SWAP: + { + condMeets = object->IsInTerrainSwap(ConditionValue1); + break; + } default: condMeets = false; break; @@ -596,6 +601,9 @@ uint32 Condition::GetSearcherTypeMaskForCondition() case CONDITION_REALM_ACHIEVEMENT: mask |= GRID_MAP_TYPE_MASK_ALL; break; + case CONDITION_TERRAIN_SWAP: + mask |= GRID_MAP_TYPE_MASK_ALL; + break; default: ASSERT(false && "Condition::GetSearcherTypeMaskForCondition - missing condition handling!"); break; @@ -795,7 +803,6 @@ bool ConditionMgr::CanHaveSourceGroupSet(ConditionSourceType sourceType) sourceType == CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET || sourceType == CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT || sourceType == CONDITION_SOURCE_TYPE_SMART_EVENT || - sourceType == CONDITION_SOURCE_TYPE_PHASE_DEFINITION || sourceType == CONDITION_SOURCE_TYPE_NPC_VENDOR); } @@ -871,22 +878,6 @@ ConditionList ConditionMgr::GetConditionsForSmartEvent(int64 entryOrGuid, uint32 return cond; } -ConditionList const* ConditionMgr::GetConditionsForPhaseDefinition(uint32 zone, uint32 entry) -{ - PhaseDefinitionConditionContainer::const_iterator itr = PhaseDefinitionsConditionStore.find(zone); - if (itr != PhaseDefinitionsConditionStore.end()) - { - ConditionTypeContainer::const_iterator i = itr->second.find(entry); - if (i != itr->second.end()) - { - TC_LOG_DEBUG("condition", "GetConditionsForPhaseDefinition: found conditions for zone %u entry %u", zone, entry); - return &i->second; - } - } - - return NULL; -} - ConditionList ConditionMgr::GetConditionsForNpcVendorEvent(uint32 creatureId, uint32 itemId) { ConditionList cond; @@ -1126,13 +1117,6 @@ void ConditionMgr::LoadConditions(bool isReload) ++count; continue; } - case CONDITION_SOURCE_TYPE_PHASE_DEFINITION: - { - PhaseDefinitionsConditionStore[cond->SourceGroup][cond->SourceEntry].push_back(cond); - valid = true; - ++count; - continue; - } case CONDITION_SOURCE_TYPE_NPC_VENDOR: { NpcVendorConditionContainerStore[cond->SourceGroup][cond->SourceEntry].push_back(cond); @@ -1661,13 +1645,6 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) return false; } break; - case CONDITION_SOURCE_TYPE_PHASE_DEFINITION: - /*if (!PhaseMgr::IsConditionTypeSupported(cond->ConditionType)) - { - TC_LOG_ERROR("sql.sql", "Condition source type `CONDITION_SOURCE_TYPE_PHASE_DEFINITION` does not support condition type %u, ignoring.", cond->ConditionType); - return false; - }*/ - break; case CONDITION_SOURCE_TYPE_NPC_VENDOR: { if (!sObjectMgr->GetCreatureTemplate(cond->SourceGroup)) @@ -1687,6 +1664,8 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) case CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION: case CONDITION_SOURCE_TYPE_SMART_EVENT: case CONDITION_SOURCE_TYPE_NONE: + case CONDITION_SOURCE_TYPE_TERRAIN_SWAP: + case CONDITION_SOURCE_TYPE_PHASE: default: break; } @@ -2086,6 +2065,14 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) } break; } + case CONDITION_TERRAIN_SWAP: + { + if (cond->ConditionValue2) + TC_LOG_ERROR("sql.sql", "Terrain swap condition has useless data in value2 (%u)!", cond->ConditionValue2); + if (cond->ConditionValue3) + TC_LOG_ERROR("sql.sql", "Terrain swap condition has useless data in value3 (%u)!", cond->ConditionValue3); + break; + } case CONDITION_TITLE: { CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(cond->ConditionValue1); @@ -2219,19 +2206,6 @@ void ConditionMgr::Clean() SpellClickEventConditionStore.clear(); - for (PhaseDefinitionConditionContainer::iterator itr = PhaseDefinitionsConditionStore.begin(); itr != PhaseDefinitionsConditionStore.end(); ++itr) - { - for (ConditionTypeContainer::iterator it = itr->second.begin(); it != itr->second.end(); ++it) - { - for (ConditionList::const_iterator i = it->second.begin(); i != it->second.end(); ++i) - delete *i; - it->second.clear(); - } - itr->second.clear(); - } - - PhaseDefinitionsConditionStore.clear(); - for (NpcVendorConditionContainer::iterator itr = NpcVendorConditionContainerStore.begin(); itr != NpcVendorConditionContainerStore.end(); ++itr) { for (ConditionTypeContainer::iterator it = itr->second.begin(); it != itr->second.end(); ++it) diff --git a/src/server/game/Conditions/ConditionMgr.h b/src/server/game/Conditions/ConditionMgr.h index d96a1aaf83b..26c958cd92e 100644 --- a/src/server/game/Conditions/ConditionMgr.h +++ b/src/server/game/Conditions/ConditionMgr.h @@ -73,7 +73,8 @@ enum ConditionTypes CONDITION_HP_VAL = 37, // hpVal ComparisonType 0 true if unit's hp matches given value CONDITION_HP_PCT = 38, // hpPct ComparisonType 0 true if unit's hp matches given pct CONDITION_REALM_ACHIEVEMENT = 39, // achievement_id 0 0 true if realm achievement is complete - CONDITION_MAX = 40 // MAX + CONDITION_TERRAIN_SWAP = 40, // terrainSwap 0 0 true if object is in terrainswap + CONDITION_MAX = 41 // MAX }; /*! Documentation on implementing a new ConditionSourceType: @@ -130,8 +131,9 @@ enum ConditionSourceType CONDITION_SOURCE_TYPE_SMART_EVENT = 22, CONDITION_SOURCE_TYPE_NPC_VENDOR = 23, CONDITION_SOURCE_TYPE_SPELL_PROC = 24, - CONDITION_SOURCE_TYPE_PHASE_DEFINITION = 25, // only 4.3.4 - CONDITION_SOURCE_TYPE_MAX = 26 // MAX + CONDITION_SOURCE_TYPE_TERRAIN_SWAP = 25, + CONDITION_SOURCE_TYPE_PHASE = 26, + CONDITION_SOURCE_TYPE_MAX = 27 // MAX }; enum RelationType @@ -222,7 +224,6 @@ typedef std::map<ConditionSourceType, ConditionTypeContainer> ConditionContainer typedef std::map<uint32, ConditionTypeContainer> CreatureSpellConditionContainer; typedef std::map<uint32, ConditionTypeContainer> NpcVendorConditionContainer; typedef std::map<std::pair<int32, uint32 /*SAI source_type*/>, ConditionTypeContainer> SmartEventConditionContainer; -typedef std::map<int32 /*zoneId*/, ConditionTypeContainer> PhaseDefinitionConditionContainer; typedef std::map<uint32, ConditionList> ConditionReferenceContainer;//only used for references @@ -253,7 +254,6 @@ class ConditionMgr ConditionList GetConditionsForSpellClickEvent(uint32 creatureId, uint32 spellId); ConditionList GetConditionsForSmartEvent(int64 entryOrGuid, uint32 eventId, uint32 sourceType); ConditionList GetConditionsForVehicleSpell(uint32 creatureId, uint32 spellId); - ConditionList const* GetConditionsForPhaseDefinition(uint32 zone, uint32 entry); ConditionList GetConditionsForNpcVendorEvent(uint32 creatureId, uint32 itemId); struct ConditionTypeInfo @@ -285,7 +285,6 @@ class ConditionMgr CreatureSpellConditionContainer SpellClickEventConditionStore; NpcVendorConditionContainer NpcVendorConditionContainerStore; SmartEventConditionContainer SmartEventConditionStore; - PhaseDefinitionConditionContainer PhaseDefinitionsConditionStore; }; #define sConditionMgr ConditionMgr::instance() diff --git a/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp b/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp index 67c245ac04b..8850392a13e 100644 --- a/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp +++ b/src/server/game/Entities/AreaTrigger/AreaTrigger.cpp @@ -78,8 +78,7 @@ bool AreaTrigger::CreateAreaTrigger(ObjectGuid::LowType guidlow, uint32 triggerE SetUInt32Value(AREATRIGGER_SPELLVISUALID, spell->SpellVisual[0]); SetUInt32Value(AREATRIGGER_DURATION, spell->GetDuration()); - for (auto phase : caster->GetPhases()) - SetInPhase(phase, false, true); + CopyPhaseFrom(caster); if (!GetMap()->AddToMap(this)) return false; diff --git a/src/server/game/Entities/Corpse/Corpse.cpp b/src/server/game/Entities/Corpse/Corpse.cpp index 99cbd75cb29..6be200b8887 100644 --- a/src/server/game/Entities/Corpse/Corpse.cpp +++ b/src/server/game/Entities/Corpse/Corpse.cpp @@ -94,6 +94,8 @@ bool Corpse::Create(ObjectGuid::LowType guidlow, Player* owner) _gridCoord = Trinity::ComputeGridCoord(GetPositionX(), GetPositionY()); + CopyPhaseFrom(owner); + return true; } @@ -121,9 +123,20 @@ void Corpse::SaveToDB() stmt->setUInt32(index++, uint32(m_time)); // time stmt->setUInt8 (index++, GetType()); // corpseType stmt->setUInt32(index++, GetInstanceId()); // instanceId - stmt->setUInt32(index++, GetPhaseMask()); // phaseMask trans->Append(stmt); + for (uint32 phaseId : GetPhases()) + { + index = 0; + stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CORPSE_PHASES); + stmt->setUInt32(index++, GetGUID().GetCounter()); // Guid (corpse's) + stmt->setUInt32(index++, phaseId); // PhaseId + stmt->setUInt32(index++, GetOwnerGUID().GetCounter()); // OwnerGuid + stmt->setUInt32(index++, uint32(m_time)); // Time + stmt->setUInt8(index++, GetType()); // CorpseType + trans->Append(stmt); + } + CharacterDatabase.CommitTransaction(trans); } @@ -148,21 +161,31 @@ void Corpse::DeleteFromDB(SQLTransaction& trans) { // Only specific bones stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CORPSE); - stmt->setUInt64(0, GetGUID().GetCounter()); + stmt->setUInt32(0, GetGUID().GetCounter()); + trans->Append(stmt); + + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CORPSE_PHASES); + stmt->setUInt32(0, GetGUID().GetCounter()); + trans->Append(stmt); } else { // all corpses (not bones) stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PLAYER_CORPSES); - stmt->setUInt64(0, GetOwnerGUID().GetCounter()); + stmt->setUInt32(0, GetOwnerGUID().GetCounter()); + trans->Append(stmt); + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PLAYER_CORPSES_PHASES); + stmt->setUInt32(0, GetOwnerGUID().GetCounter()); + trans->Append(stmt); } - trans->Append(stmt); } bool Corpse::LoadCorpseFromDB(ObjectGuid::LowType guid, Field* fields) { - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 - // SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, flags, dynFlags, time, corpseType, instanceId, phaseMask, corpseGuid, guid FROM corpse WHERE corpseType <> 0 + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + // SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, flags, dynFlags, time, corpseType, instanceId, corpseGuid, guid FROM corpse WHERE corpseType <> 0 float posX = fields[0].GetFloat(); float posY = fields[1].GetFloat(); @@ -178,12 +201,11 @@ bool Corpse::LoadCorpseFromDB(ObjectGuid::LowType guid, Field* fields) SetUInt32Value(CORPSE_FIELD_BYTES_2, fields[8].GetUInt32()); SetUInt32Value(CORPSE_FIELD_FLAGS, fields[9].GetUInt8()); SetUInt32Value(CORPSE_FIELD_DYNAMIC_FLAGS, fields[10].GetUInt8()); - SetGuidValue(CORPSE_FIELD_OWNER, ObjectGuid::Create<HighGuid::Player>(fields[16].GetUInt64())); + SetGuidValue(CORPSE_FIELD_OWNER, ObjectGuid::Create<HighGuid::Player>(fields[15].GetUInt64())); m_time = time_t(fields[11].GetUInt32()); uint32 instanceId = fields[13].GetUInt32(); - //uint32 phaseMask = fields[14].GetUInt32(); // place SetLocationInstanceId(instanceId); diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 11c88d4922e..c27fc6e2088 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -1011,6 +1011,9 @@ void Creature::SaveToDB(uint32 mapid, uint32 spawnMask, uint32 phaseMask) data.npcflag = npcflag; data.unit_flags = unit_flags; data.dynamicflags = dynamicflags; + + data.phaseid = GetDBPhase() > 0 ? GetDBPhase() : 0; + data.phaseGroup = GetDBPhase() < 0 ? abs(GetDBPhase()) : 0; // update in DB SQLTransaction trans = WorldDatabase.BeginTransaction(); @@ -1026,7 +1029,8 @@ void Creature::SaveToDB(uint32 mapid, uint32 spawnMask, uint32 phaseMask) stmt->setUInt32(index++, GetEntry()); stmt->setUInt16(index++, uint16(mapid)); stmt->setUInt32(index++, spawnMask); - stmt->setUInt32(index++, GetPhaseMask()); + stmt->setUInt32(index++, data.phaseid); + stmt->setUInt32(index++, data.phaseGroup); stmt->setUInt32(index++, displayId); stmt->setUInt8(index++, GetCurrentEquipmentId()); stmt->setFloat(index++, GetPositionX()); diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index b1a8ae1bbb2..1914b641c5f 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -819,7 +819,6 @@ void GameObject::SaveToDB(uint32 mapid, uint32 spawnMask, uint32 phaseMask) stmt->setUInt32(index++, GetEntry()); stmt->setUInt16(index++, uint16(mapid)); stmt->setUInt8(index++, spawnMask); - stmt->setUInt32(index++, GetPhaseMask()); stmt->setFloat(index++, GetPositionX()); stmt->setFloat(index++, GetPositionY()); stmt->setFloat(index++, GetPositionZ()); @@ -2164,11 +2163,13 @@ void GameObject::SetDisplayId(uint32 displayid) UpdateModel(); } -void GameObject::SetInPhase(uint32 id, bool update, bool apply) +bool GameObject::SetInPhase(uint32 id, bool update, bool apply) { - WorldObject::SetInPhase(id, update, apply); + bool res = WorldObject::SetInPhase(id, update, apply); if (m_model && m_model->isEnabled()) EnableCollision(true); + + return res; } void GameObject::EnableCollision(bool enable) diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h index 42b19771387..8ff2a941901 100644 --- a/src/server/game/Entities/GameObject/GameObject.h +++ b/src/server/game/Entities/GameObject/GameObject.h @@ -952,7 +952,7 @@ class GameObject : public WorldObject, public GridObject<GameObject>, public Map void SetGoAnimProgress(uint8 animprogress) { SetByteValue(GAMEOBJECT_BYTES_1, 3, animprogress); } static void SetGoArtKit(uint8 artkit, GameObject* go, ObjectGuid::LowType lowguid = UI64LIT(0)); - void SetInPhase(uint32 id, bool update, bool apply); + bool SetInPhase(uint32 id, bool update, bool apply); void EnableCollision(bool enable); void Use(Unit* user); diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index a9b314357f7..3fbe9fbf63a 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(); @@ -3020,19 +3140,16 @@ bool WorldObject::IsInPhase(WorldObject const* obj) const if (_phases.empty() && obj->GetPhases().empty()) return true; - if (_phases.empty() && obj->IsInPhase(169)) + if (_phases.empty() && obj->IsInPhase(DEFAULT_PHASE)) return true; - if (obj->GetPhases().empty() && IsInPhase(169)) + if (obj->GetPhases().empty() && IsInPhase(DEFAULT_PHASE)) 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); + } + } + } +} diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index e8022df5462..ab0c6f0da70 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -46,6 +46,8 @@ #define NOMINAL_MELEE_RANGE 5.0f #define MELEE_RANGE (NOMINAL_MELEE_RANGE - MIN_MELEE_REACH * 2) //center to center for players +#define DEFAULT_PHASE 169 + enum TempSummonType { TEMPSUMMON_TIMED_OR_DEAD_DESPAWN = 1, // despawns after a specified time OR when the creature disappears @@ -612,13 +614,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 +804,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; diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index 7b732ade823..87ca9110e24 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -176,11 +176,10 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c } Map* map = owner->GetMap(); - if (!Create(sObjectMgr->GetGenerator<HighGuid::Pet>()->Generate(), map, owner->GetPhaseMask(), petEntry)) + if (!Create(sObjectMgr->GetGenerator<HighGuid::Pet>()->Generate(), map, petEntry)) return false; - for (auto itr : owner->GetPhases()) - SetInPhase(itr, false, true); + CopyPhaseFrom(owner); setPetType(petType); setFaction(owner->getFaction()); @@ -732,7 +731,7 @@ bool Pet::CreateBaseAtCreature(Creature* creature) { ASSERT(creature); - if (!CreateBaseAtTamed(creature->GetCreatureTemplate(), creature->GetMap(), creature->GetPhaseMask())) + if (!CreateBaseAtTamed(creature->GetCreatureTemplate(), creature->GetMap())) return false; Relocate(creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ(), creature->GetOrientation()); @@ -763,7 +762,7 @@ bool Pet::CreateBaseAtCreature(Creature* creature) bool Pet::CreateBaseAtCreatureInfo(CreatureTemplate const* cinfo, Unit* owner) { - if (!CreateBaseAtTamed(cinfo, owner->GetMap(), owner->GetPhaseMask())) + if (!CreateBaseAtTamed(cinfo, owner->GetMap())) return false; if (CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cinfo->family)) @@ -774,10 +773,10 @@ bool Pet::CreateBaseAtCreatureInfo(CreatureTemplate const* cinfo, Unit* owner) return true; } -bool Pet::CreateBaseAtTamed(CreatureTemplate const* cinfo, Map* map, uint32 phaseMask) +bool Pet::CreateBaseAtTamed(CreatureTemplate const* cinfo, Map* map) { TC_LOG_DEBUG("entities.pet", "Pet::CreateBaseForTamed"); - if (!Create(sObjectMgr->GetGenerator<HighGuid::Pet>()->Generate(), map, phaseMask, cinfo->Entry)) + if (!Create(sObjectMgr->GetGenerator<HighGuid::Pet>()->Generate(), map, cinfo->Entry)) return false; setPowerType(POWER_FOCUS); @@ -1800,12 +1799,11 @@ bool Pet::IsPermanentPetFor(Player* owner) const } } -bool Pet::Create(ObjectGuid::LowType guidlow, Map* map, uint32 phaseMask, uint32 Entry) +bool Pet::Create(ObjectGuid::LowType guidlow, Map* map, uint32 Entry) { ASSERT(map); SetMap(map); - SetPhaseMask(phaseMask, false); Object::_Create(ObjectGuid::Create<HighGuid::Pet>(map->GetId(), Entry, guidlow)); m_DBTableGuid = guidlow; diff --git a/src/server/game/Entities/Pet/Pet.h b/src/server/game/Entities/Pet/Pet.h index b349b79a6bd..494db54208d 100644 --- a/src/server/game/Entities/Pet/Pet.h +++ b/src/server/game/Entities/Pet/Pet.h @@ -55,10 +55,10 @@ class Pet : public Guardian bool IsPermanentPetFor(Player* owner) const; // pet have tab in character windows and set UNIT_FIELD_PETNUMBER - bool Create(ObjectGuid::LowType guidlow, Map* map, uint32 phaseMask, uint32 Entry); + bool Create(ObjectGuid::LowType guidlow, Map* map, uint32 Entry); bool CreateBaseAtCreature(Creature* creature); bool CreateBaseAtCreatureInfo(CreatureTemplate const* cinfo, Unit* owner); - bool CreateBaseAtTamed(CreatureTemplate const* cinfo, Map* map, uint32 phaseMask); + bool CreateBaseAtTamed(CreatureTemplate const* cinfo, Map* map); bool LoadPetFromDB(Player* owner, uint32 petentry = 0, uint32 petnumber = 0, bool current = false); bool IsLoading() const override { return m_loading;} void SavePetToDB(PetSaveMode mode); diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index e06535c0c34..b594e694416 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -7431,6 +7431,8 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea) UpdateLocalChannels(newZone); UpdateZoneDependentAuras(newZone); + + UpdateAreaPhase(); } //If players are too far away from the duel flag... they lose the duel @@ -15445,6 +15447,7 @@ void Player::SendQuestUpdate(uint32 questId) } UpdateForQuestWorldObjects(); + SendUpdatePhasing(); } QuestGiverStatus Player::GetQuestDialogStatus(Object* questgiver) @@ -26201,15 +26204,15 @@ Pet* Player::SummonPet(uint32 entry, float x, float y, float z, float ang, PetTy Map* map = GetMap(); uint32 pet_number = sObjectMgr->GeneratePetNumber(); - if (!pet->Create(sObjectMgr->GetGenerator<HighGuid::Pet>()->Generate(), map, GetPhaseMask(), entry)) + + if (!pet->Create(sObjectMgr->GetGenerator<HighGuid::Pet>()->Generate(), map, entry)) { TC_LOG_ERROR("misc", "no such creature entry %u", entry); delete pet; return NULL; } - for (auto itr : GetPhases()) - pet->SetInPhase(itr, false, true); + pet->CopyPhaseFrom(this); pet->SetCreatorGUID(GetGUID()); pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, getFaction()); @@ -26579,25 +26582,14 @@ void Player::ReadMovementInfo(WorldPacket& data, MovementInfo* mi, Movement::Ext #undef REMOVE_VIOLATING_FLAGS } -void Player::UpdatePhasing() +void Player::SendUpdatePhasing() { if (!IsInWorld()) return; - std::set<uint32> phaseIds; - std::set<uint32> terrainswaps; - std::set<uint32> worldAreaSwaps; - - for (auto phase : GetPhases()) - { - PhaseInfo const* info = sObjectMgr->GetPhaseInfo(phase); - if (!info) - continue; - terrainswaps.insert(info->terrainSwapMap); - worldAreaSwaps.insert(info->worldMapAreaSwap); - } + RebuildTerrainSwaps(); // to set default map swaps - GetSession()->SendSetPhaseShift(GetPhases(), terrainswaps, worldAreaSwaps); + GetSession()->SendSetPhaseShift(GetPhases(), GetTerrainSwaps(), GetWorldMapAreaSwaps()); } void Player::SendSupercededSpell(uint32 oldSpell, uint32 newSpell) diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 596693e5da4..cdd12792fd0 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -2449,7 +2449,7 @@ class Player : public Unit, public GridObject<Player> void UpdateVisibilityOf(WorldObject* target); void UpdateTriggerVisibility(); - void UpdatePhasing(); + void SendUpdatePhasing(); template<class T> void UpdateVisibilityOf(T* target, UpdateData& data, std::set<Unit*>& visibleNow); diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp index 68d50b1861a..6ad2bd52130 100644 --- a/src/server/game/Entities/Transport/Transport.cpp +++ b/src/server/game/Entities/Transport/Transport.cpp @@ -318,8 +318,7 @@ Creature* Transport::CreateNPCPassenger(ObjectGuid::LowType guid, CreatureData c for (auto phase : sDB2Manager.GetPhasesForGroup(data->phaseGroup)) creature->SetInPhase(phase, false, true); else - for (auto phase : GetPhases()) // Set the creature to the transport's phases - creature->SetInPhase(phase, false, true); + creature->CopyPhaseFrom(this); if (!map->AddToMap(creature)) { @@ -463,8 +462,8 @@ TempSummon* Transport::SummonPassenger(uint32 entry, Position const& pos, TempSu return NULL; } - for (auto itr : phases) - summon->SetInPhase(itr, false, true); + for (uint32 phase : phases) + summon->SetInPhase(phase, false, true); summon->SetUInt32Value(UNIT_CREATED_BY_SPELL, spellId); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 2ecb456a6de..324cd209afc 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -3660,7 +3660,7 @@ void Unit::RemoveNotOwnSingleTargetAuras(uint32 newPhase, bool phaseid) else { Unit* caster = aura->GetCaster(); - if (!caster || (newPhase && !caster->InSamePhase(newPhase)) || (!newPhase && !caster->IsInPhase(this))) + if (!caster || (newPhase && !caster->IsInPhase(newPhase)) || (!newPhase && !caster->IsInPhase(this))) RemoveAura(iter); else ++iter; @@ -3675,7 +3675,7 @@ void Unit::RemoveNotOwnSingleTargetAuras(uint32 newPhase, bool phaseid) for (AuraList::iterator iter = scAuras.begin(); iter != scAuras.end();) { Aura* aura = *iter; - if (aura->GetUnitOwner() != this && !aura->GetUnitOwner()->InSamePhase(newPhase)) + if (aura->GetUnitOwner() != this && !aura->GetUnitOwner()->IsInPhase(newPhase)) { aura->Remove(); iter = scAuras.begin(); @@ -11563,6 +11563,7 @@ void Unit::AddToWorld() { WorldObject::AddToWorld(); } + RebuildTerrainSwaps(); } void Unit::RemoveFromWorld() @@ -13091,6 +13092,8 @@ bool Unit::InitTamedPet(Pet* pet, uint8 level, uint32 spell_id) return false; } + pet->CopyPhaseFrom(this); + pet->GetCharmInfo()->SetPetNumber(sObjectMgr->GeneratePetNumber(), true); // this enables pet details window (Shift+P) pet->InitPetCreateSpells(); @@ -14421,12 +14424,12 @@ float Unit::MeleeSpellMissChance(const Unit* victim, WeaponAttackType attType, u return missChance; } -void Unit::SetInPhase(uint32 id, bool update, bool apply) +bool Unit::SetInPhase(uint32 id, bool update, bool apply) { - WorldObject::SetInPhase(id, update, apply); + bool res = WorldObject::SetInPhase(id, update, apply); if (!IsInWorld()) - return; + return res; if (GetTypeId() == TYPEID_UNIT || (!ToPlayer()->IsGameMaster() && !ToPlayer()->GetSession()->PlayerLogout())) { @@ -14469,6 +14472,8 @@ void Unit::SetInPhase(uint32 id, bool update, bool apply) summon->SetInPhase(id, true, apply); RemoveNotOwnSingleTargetAuras(0, true); + + return res; } void Unit::UpdateObjectVisibility(bool forced) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 2b88083dfa8..080dd7e322e 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1957,7 +1957,7 @@ class Unit : public WorldObject void SetVisible(bool x); // common function for visibility checks for player/creatures with detection code - void SetInPhase(uint32 id, bool update, bool apply); + bool SetInPhase(uint32 id, bool update, bool apply); void UpdateObjectVisibility(bool forced = true) override; SpellImmuneList m_spellImmune[MAX_SPELL_IMMUNITY]; diff --git a/src/server/game/Globals/ObjectAccessor.cpp b/src/server/game/Globals/ObjectAccessor.cpp index e38c14046c4..44e7271ca70 100644 --- a/src/server/game/Globals/ObjectAccessor.cpp +++ b/src/server/game/Globals/ObjectAccessor.cpp @@ -411,6 +411,8 @@ Corpse* ObjectAccessor::ConvertCorpseForPlayer(ObjectGuid player_guid, bool insi bones->SetUInt32Value(CORPSE_FIELD_ITEM + i, 0); } + bones->CopyPhaseFrom(corpse); + // add bones in grid store if grid loaded where corpse placed map->AddToMap(bones); } diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 2523f316cec..d042fd31e27 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -1650,8 +1650,8 @@ void ObjectMgr::LoadCreatures() // 0 1 2 3 4 5 6 7 8 9 10 QueryResult result = WorldDatabase.Query("SELECT creature.guid, id, map, modelid, equipment_id, position_x, position_y, position_z, orientation, spawntimesecs, spawndist, " - // 11 12 13 14 15 16 17 18 19 20 21 22 23 - "currentwaypoint, curhealth, curmana, MovementType, spawnMask, phaseMask, eventEntry, pool_entry, creature.npcflag, creature.unit_flags, creature.dynamicflags, creature.phaseid, creature.phasegroup " + // 11 12 13 14 15 16 17 18 19 20 21 22 + "currentwaypoint, curhealth, curmana, MovementType, spawnMask, eventEntry, pool_entry, creature.npcflag, creature.unit_flags, creature.dynamicflags, creature.phaseid, creature.phasegroup " "FROM creature " "LEFT OUTER JOIN game_event_creature ON creature.guid = game_event_creature.guid " "LEFT OUTER JOIN pool_creature ON creature.guid = pool_creature.guid"); @@ -1701,14 +1701,13 @@ void ObjectMgr::LoadCreatures() data.curmana = fields[13].GetUInt32(); data.movementType = fields[14].GetUInt8(); data.spawnMask = fields[15].GetUInt32(); - data.phaseMask = fields[16].GetUInt32(); - int16 gameEvent = fields[17].GetInt8(); - uint32 PoolId = fields[18].GetUInt32(); - data.npcflag = fields[19].GetUInt32(); - data.unit_flags = fields[20].GetUInt32(); - data.dynamicflags = fields[21].GetUInt32(); - data.phaseid = fields[22].GetUInt32(); - data.phaseGroup = fields[23].GetUInt32(); + int16 gameEvent = fields[16].GetInt8(); + uint32 PoolId = fields[17].GetUInt32(); + data.npcflag = fields[18].GetUInt32(); + data.unit_flags = fields[19].GetUInt32(); + data.dynamicflags = fields[20].GetUInt32(); + data.phaseid = fields[21].GetUInt32(); + data.phaseGroup = fields[22].GetUInt32(); MapEntry const* mapEntry = sMapStore.LookupEntry(data.mapid); if (!mapEntry) @@ -1778,11 +1777,7 @@ void ObjectMgr::LoadCreatures() data.orientation = Position::NormalizeOrientation(data.orientation); } - if (data.phaseMask == 0) - { - TC_LOG_ERROR("sql.sql", "Table `creature` has creature (GUID: " UI64FMTD " Entry: %u) with `phaseMask`=0 (not visible for anyone), set to 1.", guid, data.id); - data.phaseMask = 1; - } + data.phaseMask = 1; if (data.phaseGroup && data.phaseid) { @@ -1984,8 +1979,8 @@ void ObjectMgr::LoadGameobjects() // 0 1 2 3 4 5 6 QueryResult result = WorldDatabase.Query("SELECT gameobject.guid, id, map, position_x, position_y, position_z, orientation, " - // 7 8 9 10 11 12 13 14 15 16 17 18 19 - "rotation0, rotation1, rotation2, rotation3, spawntimesecs, animprogress, state, spawnMask, phaseMask, eventEntry, pool_entry, phaseid, phasegroup " + // 7 8 9 10 11 12 13 14 15 16 17 18 + "rotation0, rotation1, rotation2, rotation3, spawntimesecs, animprogress, state, spawnMask, eventEntry, pool_entry, phaseid, phasegroup " "FROM gameobject LEFT OUTER JOIN game_event_gameobject ON gameobject.guid = game_event_gameobject.guid " "LEFT OUTER JOIN pool_gameobject ON gameobject.guid = pool_gameobject.guid"); @@ -2081,11 +2076,10 @@ void ObjectMgr::LoadGameobjects() if (!IsTransportMap(data.mapid) && data.spawnMask & ~spawnMasks[data.mapid]) TC_LOG_ERROR("sql.sql", "Table `gameobject` has gameobject (GUID: " UI64FMTD " Entry: %u) that has wrong spawn mask %u including unsupported difficulty modes for map (Id: %u), skip", guid, data.id, data.spawnMask, data.mapid); - data.phaseMask = fields[15].GetUInt32(); - int16 gameEvent = fields[16].GetInt8(); - uint32 PoolId = fields[17].GetUInt32(); - data.phaseid = fields[18].GetUInt32(); - data.phaseGroup = fields[19].GetUInt32(); + int16 gameEvent = fields[15].GetInt8(); + uint32 PoolId = fields[16].GetUInt32(); + data.phaseid = fields[17].GetUInt32(); + data.phaseGroup = fields[18].GetUInt32(); if (data.phaseGroup && data.phaseid) { @@ -2117,11 +2111,7 @@ void ObjectMgr::LoadGameobjects() continue; } - if (data.phaseMask == 0) - { - TC_LOG_ERROR("sql.sql", "Table `gameobject` has gameobject (GUID: " UI64FMTD " Entry: %u) with `phaseMask`=0 (not visible for anyone), set to 1.", guid, data.id); - data.phaseMask = 1; - } + data.phaseMask = 1; if (sWorld->getBoolConfig(CONFIG_CALCULATE_GAMEOBJECT_ZONE_AREA_DATA)) { @@ -6448,11 +6438,28 @@ uint64 ObjectMgr::GenerateVoidStorageItemId() void ObjectMgr::LoadCorpses() { - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 - // SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, flags, dynFlags, time, corpseType, instanceId, phaseMask, corpseGuid, guid FROM corpse WHERE corpseType <> 0 - uint32 oldMSTime = getMSTime(); + std::unordered_map<uint32, std::list<uint32>> phases; + + // 0 1 + // SELECT Guid, PhaseId FROM corpse_phases + PreparedQueryResult phaseResult = CharacterDatabase.Query(CharacterDatabase.GetPreparedStatement(CHAR_SEL_CORPSE_PHASES)); + if (phaseResult) + { + do + { + Field* fields = phaseResult->Fetch(); + uint32 guid = fields[0].GetUInt32(); + uint32 phaseId = fields[1].GetUInt32(); + + phases[guid].push_back(phaseId); + + } while (phaseResult->NextRow()); + } + + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + // SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, flags, dynFlags, time, corpseType, instanceId, corpseGuid, guid FROM corpse WHERE corpseType <> 0 PreparedQueryResult result = CharacterDatabase.Query(CharacterDatabase.GetPreparedStatement(CHAR_SEL_CORPSES)); if (!result) { @@ -6464,11 +6471,11 @@ void ObjectMgr::LoadCorpses() do { Field* fields = result->Fetch(); - ObjectGuid::LowType guid = fields[15].GetUInt64(); + uint32 guid = fields[14].GetUInt32(); CorpseType type = CorpseType(fields[12].GetUInt8()); if (type >= MAX_CORPSE_TYPE) { - TC_LOG_ERROR("misc", "Corpse (guid: " UI64FMTD ") have wrong corpse type (%u), not loading.", guid, type); + TC_LOG_ERROR("misc", "Corpse (guid: %u) have wrong corpse type (%u), not loading.", guid, type); continue; } @@ -6479,6 +6486,9 @@ void ObjectMgr::LoadCorpses() continue; } + for (auto phaseId : phases[guid]) + corpse->SetInPhase(phaseId, false, true); + sObjectAccessor->AddCorpse(corpse); ++count; } @@ -8527,60 +8537,64 @@ void ObjectMgr::LoadFactionChangeTitles() TC_LOG_INFO("server.loading", ">> Loaded %u faction change title pairs in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } -void ObjectMgr::LoadPhaseDefinitions() +void ObjectMgr::LoadTerrainSwapDefaults() { - _PhaseDefinitionStore.clear(); + _terrainMapDefaultStore.clear(); uint32 oldMSTime = getMSTime(); - // 0 1 2 3 - QueryResult result = WorldDatabase.Query("SELECT zoneId, entry, phaseId, phaseGroup FROM `phase_definitions` ORDER BY `entry` ASC"); + // 0 1 + QueryResult result = WorldDatabase.Query("SELECT MapId, TerrainSwapMap FROM `terrain_swap_defaults`"); if (!result) { - TC_LOG_INFO("server.loading", ">> Loaded 0 phasing definitions. DB table `phase_definitions` is empty."); + TC_LOG_INFO("server.loading", ">> Loaded 0 terrain swap defaults. DB table `terrain_swap_defaults` is empty."); return; } uint32 count = 0; - do { Field* fields = result->Fetch(); - PhaseDefinition PhaseDefinition; + uint32 mapId = fields[0].GetUInt32(); + + MapEntry const* map = sMapStore.LookupEntry(mapId); + if (!map) + { + TC_LOG_ERROR("sql.sql", "Map %u defined in `terrain_swap_defaults` does not exist, skipped.", mapId); + continue; + } - PhaseDefinition.zoneId = fields[0].GetUInt32(); - PhaseDefinition.entry = fields[1].GetUInt32(); - PhaseDefinition.phaseId = fields[2].GetUInt32(); - PhaseDefinition.phaseGroup = fields[3].GetUInt32(); + uint32 terrainSwap = fields[1].GetUInt32(); - if (PhaseDefinition.phaseGroup && PhaseDefinition.phaseId) + map = sMapStore.LookupEntry(terrainSwap); + if (!map) { - TC_LOG_ERROR("sql.sql", "Phase definition for zone %u (Entry: %u) has phaseGroup and phaseId set, phaseGroup set to 0", PhaseDefinition.zoneId, PhaseDefinition.entry); - PhaseDefinition.phaseGroup = 0; + TC_LOG_ERROR("sql.sql", "TerrainSwapMap %u defined in `terrain_swap_defaults` does not exist, skipped.", terrainSwap); + continue; } - _PhaseDefinitionStore[PhaseDefinition.zoneId].push_back(PhaseDefinition); + + _terrainMapDefaultStore[mapId].push_back(terrainSwap); ++count; - } - while (result->NextRow()); + } while (result->NextRow()); - TC_LOG_INFO("server.loading", ">> Loaded %u phasing definitions in %u ms.", count, GetMSTimeDiffToNow(oldMSTime)); + TC_LOG_INFO("server.loading", ">> Loaded %u terrain swap defaults in %u ms.", count, GetMSTimeDiffToNow(oldMSTime)); } -void ObjectMgr::LoadPhaseInfo() +void ObjectMgr::LoadTerrainPhaseInfo() { - _PhaseInfoStore.clear(); + _terrainPhaseInfoStore.clear(); uint32 oldMSTime = getMSTime(); - // 0 1 2 - QueryResult result = WorldDatabase.Query("SELECT id, worldmapareaswap, terrainswapmap FROM `phase_info`"); + // 0 1 + QueryResult result = WorldDatabase.Query("SELECT Id, TerrainSwapMap FROM `terrain_phase_info`"); if (!result) { - TC_LOG_INFO("server.loading", ">> Loaded 0 phase infos. DB table `phase_info` is empty."); + TC_LOG_INFO("server.loading", ">> Loaded 0 terrain phase infos. DB table `terrain_phase_info` is empty."); return; } @@ -8589,25 +8603,93 @@ void ObjectMgr::LoadPhaseInfo() { Field* fields = result->Fetch(); - PhaseInfo phaseInfo; - phaseInfo.phaseId = fields[0].GetUInt32(); + uint32 phaseId = fields[0].GetUInt32(); - PhaseEntry const* phase = sPhaseStore.LookupEntry(phaseInfo.phaseId); + PhaseEntry const* phase = sPhaseStore.LookupEntry(phaseId); if (!phase) { - TC_LOG_ERROR("sql.sql", "Phase %u defined in `phase_info` does not exists, skipped.", phaseInfo.phaseId); + TC_LOG_ERROR("sql.sql", "Phase %u defined in `terrain_phase_info` does not exist, skipped.", phaseId); continue; } - phaseInfo.worldMapAreaSwap = fields[1].GetUInt32(); - phaseInfo.terrainSwapMap = fields[2].GetUInt32(); + uint32 terrainSwap = fields[1].GetUInt32(); - _PhaseInfoStore[phaseInfo.phaseId] = phaseInfo; + _terrainPhaseInfoStore[phaseId].push_back(terrainSwap); ++count; } while (result->NextRow()); - TC_LOG_INFO("server.loading", ">> Loaded %u phase infos in %u ms.", count, GetMSTimeDiffToNow(oldMSTime)); + + TC_LOG_INFO("server.loading", ">> Loaded %u terrain phase infos in %u ms.", count, GetMSTimeDiffToNow(oldMSTime)); +} + +void ObjectMgr::LoadTerrainWorldMaps() +{ + _terrainWorldMapStore.clear(); + + uint32 oldMSTime = getMSTime(); + + // 0 1 + QueryResult result = WorldDatabase.Query("SELECT TerrainSwapMap, WorldMapArea FROM `terrain_worldmap`"); + + if (!result) + { + TC_LOG_INFO("server.loading", ">> Loaded 0 terrain world maps. DB table `terrain_worldmap` is empty."); + return; + } + + uint32 count = 0; + do + { + Field* fields = result->Fetch(); + + uint32 mapId = fields[0].GetUInt32(); + + if (!sMapStore.LookupEntry(mapId)) + { + TC_LOG_ERROR("sql.sql", "TerrainSwapMap %u defined in `terrain_worldmap` does not exist, skipped.", mapId); + continue; + } + + uint32 worldMapArea = fields[1].GetUInt32(); + + _terrainWorldMapStore[mapId].push_back(worldMapArea); + + ++count; + } while (result->NextRow()); + + TC_LOG_INFO("server.loading", ">> Loaded %u terrain world maps in %u ms.", count, GetMSTimeDiffToNow(oldMSTime)); +} + +void ObjectMgr::LoadAreaPhases() +{ + _phases.clear(); + + uint32 oldMSTime = getMSTime(); + + // 0 1 + QueryResult result = WorldDatabase.Query("SELECT AreaId, PhaseId FROM `phase_area`"); + + if (!result) + { + TC_LOG_INFO("server.loading", ">> Loaded 0 phase areas. DB table `phase_area` is empty."); + return; + } + + uint32 count = 0; + do + { + Field* fields = result->Fetch(); + + uint32 area = fields[0].GetUInt32(); + uint32 phase = fields[1].GetUInt32(); + + _phases[area].push_back(phase); + + ++count; + } while (result->NextRow()); + + TC_LOG_INFO("server.loading", ">> Loaded %u phase areas in %u ms.", count, GetMSTimeDiffToNow(oldMSTime)); } GameObjectTemplate const* ObjectMgr::GetGameObjectTemplate(uint32 entry) diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index e9ec98f3e98..dca58857f9c 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -129,34 +129,6 @@ typedef std::map<uint32, PageText> PageTextContainer; // Benchmarked: Faster than std::map (insert/find) typedef std::unordered_map<uint16, InstanceTemplate> InstanceTemplateContainer; -// Phasing (visibility) -enum PhasingFlags -{ - PHASE_FLAG_OVERWRITE_EXISTING = 0x01, // don't stack with existing phases, overwrites existing phases - PHASE_FLAG_NO_MORE_PHASES = 0x02, // stop calculating phases after this phase was applied (no more phases will be applied) - PHASE_FLAG_NEGATE_PHASE = 0x04 // negate instead to add the phasemask -}; - -struct PhaseInfo -{ - uint32 phaseId; - uint32 worldMapAreaSwap; - uint32 terrainSwapMap; -}; - -typedef std::unordered_map<uint32, PhaseInfo> PhaseInfoContainer; - -struct PhaseDefinition -{ - uint32 zoneId; - uint32 entry; - uint32 phaseId; - uint32 phaseGroup; -}; - -typedef std::list<PhaseDefinition> PhaseDefinitionContainer; -typedef std::unordered_map<uint32 /*zoneId*/, PhaseDefinitionContainer> PhaseDefinitionStore; - struct GameTele { float position_x; @@ -672,6 +644,9 @@ struct DungeonEncounter typedef std::list<DungeonEncounter const*> DungeonEncounterList; typedef std::unordered_map<uint64, DungeonEncounterList> DungeonEncounterContainer; +typedef std::unordered_map<uint32, std::list<uint32>> TerrainPhaseInfo; +typedef std::unordered_map<uint32, std::list<uint32>> PhaseInfo; + class PlayerDumpReader; class ObjectMgr @@ -1008,8 +983,10 @@ class ObjectMgr void LoadTrainerSpell(); void AddSpellToTrainer(uint32 entry, uint32 spell, uint32 spellCost, uint32 reqSkill, uint32 reqSkillValue, uint32 reqLevel); - void LoadPhaseDefinitions(); - void LoadPhaseInfo(); + void LoadTerrainPhaseInfo(); + void LoadTerrainSwapDefaults(); + void LoadTerrainWorldMaps(); + void LoadAreaPhases(); std::string GeneratePetName(uint32 entry); uint32 GetBaseXP(uint8 level); @@ -1243,7 +1220,12 @@ class ObjectMgr return _gossipMenuItemsStore.equal_range(uiMenuId); } - PhaseInfo const* GetPhaseInfo(uint32 phase) { return _PhaseInfoStore.find(phase) != _PhaseInfoStore.end() ? &_PhaseInfoStore[phase] : nullptr; } + std::list<uint32>& GetPhaseTerrainSwaps(uint32 phaseid) { return _terrainPhaseInfoStore[phaseid]; } + std::list<uint32>& GetDefaultTerrainSwaps(uint32 mapid) { return _terrainMapDefaultStore[mapid]; } + std::list<uint32>& GetTerrainWorldMaps(uint32 terrainId) { return _terrainWorldMapStore[terrainId]; } + TerrainPhaseInfo& GetDefaultTerrainSwapStore() { return _terrainMapDefaultStore; } + std::list<uint32>& GetPhasesForArea(uint32 area) { return _phases[area]; } + PhaseInfo& GetAreaPhases() { return _phases; } // for wintergrasp only GraveYardContainer GraveYardStore; @@ -1369,8 +1351,10 @@ class ObjectMgr PageTextContainer _pageTextStore; InstanceTemplateContainer _instanceTemplateStore; - PhaseDefinitionStore _PhaseDefinitionStore; - PhaseInfoContainer _PhaseInfoStore; + TerrainPhaseInfo _terrainPhaseInfoStore; + TerrainPhaseInfo _terrainMapDefaultStore; + TerrainPhaseInfo _terrainWorldMapStore; + PhaseInfo _phases; private: void LoadScripts(ScriptsType type); diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index 8554a027e73..e8e6febbe34 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -1399,50 +1399,13 @@ void WorldSession::HandleUITimeRequest(WorldPackets::Misc::UITimeRequest& /*requ void WorldSession::SendSetPhaseShift(std::set<uint32> const& phaseIds, std::set<uint32> const& terrainswaps, std::set<uint32> const& worldMapAreaSwaps) { - ObjectGuid guid = _player->GetGUID(); - - WorldPacket data(SMSG_PHASE_SHIFT_CHANGE, 1 + 8 + 4 + 4 + 4 + 4 + 2 * phaseIds.size() + 4 + terrainswaps.size() * 2); - data.WriteBit(guid[2]); - data.WriteBit(guid[3]); - data.WriteBit(guid[1]); - data.WriteBit(guid[6]); - data.WriteBit(guid[4]); - data.WriteBit(guid[5]); - data.WriteBit(guid[0]); - data.WriteBit(guid[7]); - - data.WriteByteSeq(guid[7]); - data.WriteByteSeq(guid[4]); - - data << uint32(worldMapAreaSwaps.size()); - for (auto mapSwap : worldMapAreaSwaps) - data << uint16(mapSwap); // WorldMapArea.dbc id (controls map display) - - data.WriteByteSeq(guid[1]); - - data << uint32(phaseIds.size() ? 0 : 8); // flags (not phasemask) - - data.WriteByteSeq(guid[2]); - data.WriteByteSeq(guid[6]); - - data << uint32(0); // Inactive terrain swaps - //for (uint8 i = 0; i < inactiveSwapsCount; ++i) - // data << uint16(0); - - data << uint32(phaseIds.size()) * 2; // Phase.dbc ids - for (std::set<uint32>::const_iterator itr = phaseIds.begin(); itr != phaseIds.end(); ++itr) - data << uint16(*itr); - - data.WriteByteSeq(guid[3]); - data.WriteByteSeq(guid[0]); - - data << uint32(terrainswaps.size()) * 2; // Active terrain swaps - for (std::set<uint32>::const_iterator itr = terrainswaps.begin(); itr != terrainswaps.end(); ++itr) - data << uint16(*itr); - - data.WriteByteSeq(guid[5]); - - SendPacket(&data); + WorldPackets::Misc::PhaseShift phaseShift; + phaseShift.ClientGUID = _player->GetGUID(); + phaseShift.PersonalGUID = _player->GetGUID(); + phaseShift.PhaseShifts = phaseIds; + phaseShift.VisibleMapIDs = terrainswaps; + phaseShift.UiWorldMapAreaIDSwaps = worldMapAreaSwaps; + SendPacket(phaseShift.Write()); } // Battlefield and Battleground diff --git a/src/server/game/Instances/InstanceScript.cpp b/src/server/game/Instances/InstanceScript.cpp index ab5943ac485..c151183da8a 100644 --- a/src/server/game/Instances/InstanceScript.cpp +++ b/src/server/game/Instances/InstanceScript.cpp @@ -633,5 +633,5 @@ void InstanceScript::UpdatePhasing() Map::PlayerList const& players = instance->GetPlayers(); for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) if (Player* player = itr->GetSource()) - player->UpdatePhasing(); + player->SendUpdatePhasing(); } diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 076daa969db..c2bec063223 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -498,6 +498,8 @@ bool Map::AddPlayerToMap(Player* player) player->m_clientGUIDs.clear(); player->UpdateObjectVisibility(false); + player->SendUpdatePhasing(); + sScriptMgr->OnPlayerEnterMap(this, player); return true; } @@ -556,6 +558,8 @@ bool Map::AddToMap(T* obj) if (obj->isActiveObject()) AddToActive(obj); + obj->RebuildTerrainSwaps(); + //something, such as vehicle, needs to be update immediately //also, trigger needs to cast spell, if not update, cannot see visual obj->UpdateObjectVisibility(true); diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index e041ed9c6e6..0e436715622 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -42,8 +42,8 @@ PathGenerator::PathGenerator(const Unit* owner) : if (DisableMgr::IsPathfindingEnabled(mapId)) { MMAP::MMapManager* mmap = MMAP::MMapFactory::createOrGetMMapManager(); - _navMesh = mmap->GetNavMesh(mapId); - _navMeshQuery = mmap->GetNavMeshQuery(mapId, _sourceUnit->GetInstanceId()); + _navMesh = mmap->GetNavMesh(mapId, _sourceUnit->GetTerrainSwaps()); + _navMeshQuery = mmap->GetNavMeshQuery(mapId, _sourceUnit->GetInstanceId(), _sourceUnit->GetTerrainSwaps()); } CreateFilter(); diff --git a/src/server/game/Server/Packets/MiscPackets.cpp b/src/server/game/Server/Packets/MiscPackets.cpp index 1905ab3e3ce..009f1d901d5 100644 --- a/src/server/game/Server/Packets/MiscPackets.cpp +++ b/src/server/game/Server/Packets/MiscPackets.cpp @@ -379,3 +379,30 @@ WorldPacket const* WorldPackets::Misc::RandomRoll::Write() return &_worldPacket; } + +WorldPacket const* WorldPackets::Misc::PhaseShift::Write() +{ + _worldPacket << ClientGUID; // CLientGUID + _worldPacket << uint32(PhaseShifts.size() ? 0 : 8); // PhaseShiftFlags + _worldPacket << uint32(PhaseShifts.size()); // PhaseShiftCount + _worldPacket << PersonalGUID; // PersonalGUID + for (uint32 phase : PhaseShifts) + { + _worldPacket << uint16(1); // PhaseFlags + _worldPacket << uint16(phase); // PhaseID + } + + _worldPacket << uint32(VisibleMapIDs.size() * 2); // Active terrain swaps size + for (uint32 map : VisibleMapIDs) + _worldPacket << uint16(map); // Active terrain swap map id + + _worldPacket << uint32(PreloadMapIDs.size() * 2); // Inactive terrain swaps size + for (uint32 map : PreloadMapIDs) + _worldPacket << uint16(map); // Inactive terrain swap map id + + _worldPacket << uint32(UiWorldMapAreaIDSwaps.size() * 2); // UI map swaps size + for (uint32 map : UiWorldMapAreaIDSwaps) + _worldPacket << uint16(map); // UI map id, WorldMapArea.dbc, controls map display + + return &_worldPacket; +} diff --git a/src/server/game/Server/Packets/MiscPackets.h b/src/server/game/Server/Packets/MiscPackets.h index 15dd164f994..b41e1cb8b50 100644 --- a/src/server/game/Server/Packets/MiscPackets.h +++ b/src/server/game/Server/Packets/MiscPackets.h @@ -538,6 +538,21 @@ namespace WorldPackets WorldPacket const* Write() override { return &_worldPacket; } }; + + class PhaseShift final : public ServerPacket + { + public: + PhaseShift() : ServerPacket(SMSG_PHASE_SHIFT_CHANGE, 4) { } + + WorldPacket const* Write() override; + + ObjectGuid ClientGUID; + ObjectGuid PersonalGUID; + std::set<uint32> PhaseShifts; + std::set<uint32> PreloadMapIDs; + std::set<uint32> UiWorldMapAreaIDSwaps; + std::set<uint32> VisibleMapIDs; + }; } } diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index a254c32854b..5c844f1e3aa 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -1522,7 +1522,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_STABLE_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_TAME_FAILURE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_PET_UNLEARNED_SPELLS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_PHASE_SHIFT_CHANGE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_PHASE_SHIFT_CHANGE, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_PLAYED_TIME, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_PLAYER_BOUND, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_PLAYER_SAVE_GUILD_EMBLEM, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 82a6913773f..83e9dcbc2ef 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -1738,7 +1738,7 @@ void AuraEffect::HandlePhase(AuraApplication const* aurApp, uint8 mode, bool app { if (player->IsInWorld()) player->GetMap()->SendUpdateTransportVisibility(player, oldPhases); - player->UpdatePhasing(); + player->SendUpdatePhasing(); } // need triggering visibility update base at phase update of not GM invisible (other GMs anyway see in any phases) @@ -1770,7 +1770,7 @@ void AuraEffect::HandlePhaseGroup(AuraApplication const* aurApp, uint8 mode, boo { if (player->IsInWorld()) player->GetMap()->SendUpdateTransportVisibility(player, oldPhases); - player->UpdatePhasing(); + player->SendUpdatePhasing(); } // need triggering visibility update base at phase update of not GM invisible (other GMs anyway see in any phases) diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 67ef2c73811..61634e2be7c 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -3218,8 +3218,7 @@ void Spell::EffectSummonObjectWild(SpellEffIndex effIndex) return; } - for (auto phase : m_caster->GetPhases()) - pGameObj->SetInPhase(phase, false, true); + pGameObj->CopyPhaseFrom(m_caster); int32 duration = m_spellInfo->GetDuration(); @@ -3242,8 +3241,7 @@ void Spell::EffectSummonObjectWild(SpellEffIndex effIndex) if (linkedGO->Create(sObjectMgr->GetGenerator<HighGuid::GameObject>()->Generate(), linkedEntry, map, m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY)) { - for (auto phase : m_caster->GetPhases()) - linkedGO->SetInPhase(phase, false, true); + linkedGO->CopyPhaseFrom(m_caster); linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILLISECONDS : 0); linkedGO->SetSpellId(m_spellInfo->Id); @@ -3877,8 +3875,7 @@ void Spell::EffectDuel(SpellEffIndex effIndex) return; } - for (auto phase : m_caster->GetPhases()) - pGameObj->SetInPhase(phase, false, true); + pGameObj->CopyPhaseFrom(m_caster); pGameObj->SetUInt32Value(GAMEOBJECT_FACTION, m_caster->getFaction()); pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()+1); @@ -4250,8 +4247,7 @@ void Spell::EffectSummonObject(SpellEffIndex effIndex) return; } - for (auto phase : m_caster->GetPhases()) - go->SetInPhase(phase, false, true); + go->CopyPhaseFrom(m_caster); //pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()); int32 duration = m_spellInfo->GetDuration(); @@ -4888,8 +4884,7 @@ void Spell::EffectTransmitted(SpellEffIndex effIndex) return; } - for (auto phase : m_caster->GetPhases()) - pGameObj->SetInPhase(phase, false, true); + pGameObj->CopyPhaseFrom(m_caster); int32 duration = m_spellInfo->GetDuration(); @@ -4953,8 +4948,7 @@ void Spell::EffectTransmitted(SpellEffIndex effIndex) if (linkedGO->Create(sObjectMgr->GetGenerator<HighGuid::GameObject>()->Generate(), linkedEntry, cMap, 0, fx, fy, fz, m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY)) { - for (auto phase : m_caster->GetPhases()) - linkedGO->SetInPhase(phase, false, true); + linkedGO->CopyPhaseFrom(m_caster); linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILLISECONDS : 0); //linkedGO->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()); diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index c34ce2640c7..6eb11499a4d 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1460,6 +1460,10 @@ void World::SetInitialWorldSettings() stmt->setUInt32(0, 3 * DAY); CharacterDatabase.Execute(stmt); + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_OLD_CORPSE_PHASES); + stmt->setUInt32(0, 3 * DAY); + CharacterDatabase.Execute(stmt); + ///- Load the DBC files TC_LOG_INFO("server.loading", "Initialize data stores..."); LoadDBCStores(m_dataPath); @@ -1550,9 +1554,6 @@ void World::SetInitialWorldSettings() TC_LOG_INFO("server.loading", "Loading Spell Group Stack Rules..."); sSpellMgr->LoadSpellGroupStackRules(); - TC_LOG_INFO("server.loading", "Loading Spell Phase Dbc Info..."); - sObjectMgr->LoadPhaseInfo(); - TC_LOG_INFO("server.loading", "Loading NPC Texts..."); sObjectMgr->LoadGossipText(); @@ -1801,8 +1802,17 @@ void World::SetInitialWorldSettings() TC_LOG_INFO("server.loading", "Loading World States..."); // must be loaded before battleground, outdoor PvP and conditions LoadWorldStates(); - TC_LOG_INFO("server.loading", "Loading Phase definitions..."); - sObjectMgr->LoadPhaseDefinitions(); + TC_LOG_INFO("server.loading", "Loading Terrain Phase definitions..."); + sObjectMgr->LoadTerrainPhaseInfo(); + + TC_LOG_INFO("server.loading", "Loading Terrain Swap Default definitions..."); + sObjectMgr->LoadTerrainSwapDefaults(); + + TC_LOG_INFO("server.loading", "Loading Terrain World Map definitions..."); + sObjectMgr->LoadTerrainWorldMaps(); + + TC_LOG_INFO("server.loading", "Loading Phase Area definitions..."); + sObjectMgr->LoadAreaPhases(); TC_LOG_INFO("server.loading", "Loading Conditions..."); sConditionMgr->LoadConditions(); |
