aboutsummaryrefslogtreecommitdiff
path: root/src/server/game
diff options
context:
space:
mode:
authorRat <gmstreetrat@gmail.com>2015-03-29 19:31:28 +0200
committerRat <gmstreetrat@gmail.com>2015-03-29 19:31:28 +0200
commitec99b191999a5da783f070ff3e1ebf05f9871219 (patch)
tree7d604fc051ff9c79e2b9b7b33e25a14035b5bb38 /src/server/game
parent833d57fa27c782c2e9a211ec19c554d057431243 (diff)
parent17bd724559808b5e327a9a541063b56f21712841 (diff)
Merge pull request #14389 from streetrat/6.x
Core/Phases: Added new phasing system
Diffstat (limited to 'src/server/game')
-rw-r--r--src/server/game/Conditions/ConditionMgr.cpp62
-rw-r--r--src/server/game/Conditions/ConditionMgr.h11
-rw-r--r--src/server/game/Entities/AreaTrigger/AreaTrigger.cpp3
-rw-r--r--src/server/game/Entities/Corpse/Corpse.cpp38
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp6
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp7
-rw-r--r--src/server/game/Entities/GameObject/GameObject.h2
-rw-r--r--src/server/game/Entities/Object/Object.cpp244
-rw-r--r--src/server/game/Entities/Object/Object.h22
-rw-r--r--src/server/game/Entities/Pet/Pet.cpp16
-rw-r--r--src/server/game/Entities/Pet/Pet.h4
-rw-r--r--src/server/game/Entities/Player/Player.cpp26
-rw-r--r--src/server/game/Entities/Player/Player.h2
-rw-r--r--src/server/game/Entities/Transport/Transport.cpp7
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp15
-rw-r--r--src/server/game/Entities/Unit/Unit.h2
-rw-r--r--src/server/game/Globals/ObjectAccessor.cpp2
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp208
-rw-r--r--src/server/game/Globals/ObjectMgr.h50
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp51
-rw-r--r--src/server/game/Instances/InstanceScript.cpp2
-rw-r--r--src/server/game/Maps/Map.cpp4
-rw-r--r--src/server/game/Movement/PathGenerator.cpp4
-rw-r--r--src/server/game/Server/Packets/MiscPackets.cpp27
-rw-r--r--src/server/game/Server/Packets/MiscPackets.h15
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp2
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp4
-rw-r--r--src/server/game/Spells/SpellEffects.cpp18
-rw-r--r--src/server/game/World/World.cpp20
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();