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:
Rat committed 2014-11-01 19:36:05 +01:00
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;
}
+2 -1
View File
@@ -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);
+104 -6
View File
@@ -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();
}
+3 -1
View File
@@ -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
+5 -3
View File
@@ -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)
+1 -1
View File
@@ -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];
+31
View File
@@ -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);
+5
View File
@@ -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);
+3
View File
@@ -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();