Core/Phases:
- Implemented CONDITION_SOURCE_TYPE_PHASE (26) - Implemented phase_area DB table to link phases to specific areas using conditions - updated logic to correctly handle phases gained from auras and areas (they should not remove each other's phases)
This commit is contained in:
1 parent
9690b54f75
commit
50228fc9da
13 files changed
+169
-15
No files matched your search
@@ -0,0 +1,7 @@
|
||||
DROP TABLE IF EXISTS `phase_area`;
|
||||
CREATE TABLE `phase_area` (
|
||||
`AreaId` int(10) unsigned NOT NULL,
|
||||
`PhaseId` int(10) unsigned NOT NULL,
|
||||
`Comment` varchar(255) DEFAULT NULL,
|
||||
PRIMARY KEY (`AreaId`,`PhaseId`)
|
||||
);
|
||||
@@ -1535,6 +1535,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond)
|
||||
case CONDITION_SOURCE_TYPE_SMART_EVENT:
|
||||
case CONDITION_SOURCE_TYPE_NONE:
|
||||
case CONDITION_SOURCE_TYPE_TERRAIN_SWAP:
|
||||
case CONDITION_SOURCE_TYPE_PHASE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -130,7 +130,8 @@ enum ConditionSourceType
|
||||
CONDITION_SOURCE_TYPE_NPC_VENDOR = 23,
|
||||
CONDITION_SOURCE_TYPE_SPELL_PROC = 24,
|
||||
CONDITION_SOURCE_TYPE_TERRAIN_SWAP = 25,
|
||||
CONDITION_SOURCE_TYPE_MAX = 26 // MAX
|
||||
CONDITION_SOURCE_TYPE_PHASE = 26,
|
||||
CONDITION_SOURCE_TYPE_MAX = 27 // MAX
|
||||
};
|
||||
|
||||
enum RelationType
|
||||
|
||||
@@ -2150,11 +2150,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)
|
||||
|
||||
@@ -739,7 +739,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, uint32 lowguid = 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);
|
||||
|
||||
@@ -2718,19 +2718,119 @@ void WorldObject::SetPhaseMask(uint32 newPhaseMask, bool update)
|
||||
UpdateObjectVisibility();
|
||||
}
|
||||
|
||||
void WorldObject::SetInPhase(uint32 id, bool update, bool apply)
|
||||
bool WorldObject::HasInPhaseList(uint32 phase)
|
||||
{
|
||||
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 = 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)
|
||||
@@ -2757,14 +2857,10 @@ void WorldObject::ClearPhases(bool update)
|
||||
|
||||
bool WorldObject::IsInPhase(WorldObject const* obj) const
|
||||
{
|
||||
// if object has no phasing it should be always visible
|
||||
if (obj->GetPhases().empty())
|
||||
return true;
|
||||
|
||||
// PhaseId 169 is the default fallback phase
|
||||
if (_phases.empty() && obj->GetPhases().empty())
|
||||
return true;
|
||||
|
||||
// PhaseId 169 is the default fallback phase in dbc
|
||||
if (_phases.empty() && obj->IsInPhase(169))
|
||||
return true;
|
||||
|
||||
@@ -2960,6 +3056,8 @@ void WorldObject::RebuildTerrainSwaps()
|
||||
if (sConditionMgr->IsObjectMeetToConditions(this, conditions))
|
||||
_terrainSwaps.insert(swap);
|
||||
}
|
||||
|
||||
// online players have a game client with world map display
|
||||
if (GetTypeId() == TYPEID_PLAYER)
|
||||
RebuildWorldMapAreaSwaps();
|
||||
}
|
||||
|
||||
@@ -592,11 +592,13 @@ 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 IsInPhase(uint32 phase) const { return _phases.find(phase) != _phases.end(); }
|
||||
bool IsInPhase(WorldObject const* obj) const;
|
||||
|
||||
@@ -7883,6 +7883,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
|
||||
|
||||
@@ -14734,12 +14734,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()))
|
||||
{
|
||||
@@ -14782,6 +14782,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)
|
||||
|
||||
@@ -1936,7 +1936,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];
|
||||
|
||||
@@ -9382,6 +9382,37 @@ void ObjectMgr::LoadTerrainWorldMaps()
|
||||
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)
|
||||
{
|
||||
GameObjectTemplateContainer::const_iterator itr = _gameObjectTemplateStore.find(entry);
|
||||
|
||||
@@ -687,6 +687,7 @@ struct HotfixInfo
|
||||
typedef std::vector<HotfixInfo> HotfixData;
|
||||
|
||||
typedef std::unordered_map<uint32, std::list<uint32>> TerrainPhaseInfo;
|
||||
typedef std::unordered_map<uint32, std::list<uint32>> PhaseInfo;
|
||||
|
||||
class PlayerDumpReader;
|
||||
|
||||
@@ -1031,6 +1032,7 @@ class ObjectMgr
|
||||
void LoadTerrainPhaseInfo();
|
||||
void LoadTerrainSwapDefaults();
|
||||
void LoadTerrainWorldMaps();
|
||||
void LoadAreaPhases();
|
||||
|
||||
std::string GeneratePetName(uint32 entry);
|
||||
uint32 GetBaseXP(uint8 level);
|
||||
@@ -1291,6 +1293,8 @@ class ObjectMgr
|
||||
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;
|
||||
@@ -1410,6 +1414,7 @@ class ObjectMgr
|
||||
TerrainPhaseInfo _terrainPhaseInfoStore;
|
||||
TerrainPhaseInfo _terrainMapDefaultStore;
|
||||
TerrainPhaseInfo _terrainWorldMapStore;
|
||||
PhaseInfo _phases;
|
||||
|
||||
private:
|
||||
void LoadScripts(ScriptsType type);
|
||||
|
||||
@@ -1739,6 +1739,9 @@ void World::SetInitialWorldSettings()
|
||||
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();
|
||||
|
||||
|
||||
Reference in new issue
Block a user