Core/Entities: Phase Rework (main commit)

This commit is contained in:
Ovahlord committed 2018-03-08 22:58:50 +01:00
1 parent 4a268b3fd3
commit e44bb5f387
79 files changed
+1738 -851

No files matched your search

+19 -237
View File
@@ -45,6 +45,7 @@
#include "TemporarySummon.h"
#include "Totem.h"
#include "OutdoorPvPMgr.h"
#include "PhasingHandler.h"
#include "MovementPacketBuilder.h"
#include "DynamicTree.h"
#include "Unit.h"
@@ -1446,7 +1447,7 @@ bool WorldObject::IsWithinLOS(float ox, float oy, float oz, LineOfSightChecks ch
else
GetHitSpherePointFor({ ox, oy, oz }, x, y, z);
return GetMap()->isInLineOfSight(x, y, z + 2.0f, ox, oy, oz + 2.0f, GetPhases(), checks, ignoreFlags);
return GetMap()->isInLineOfSight(GetPhaseShift(), x, y, z + 2.0f, ox, oy, oz + 2.0f, checks, ignoreFlags);
}
return true;
@@ -1621,7 +1622,7 @@ Position WorldObject::GetRandomPoint(const Position &srcPos, float distance) con
void WorldObject::UpdateGroundPositionZ(float x, float y, float &z) const
{
float new_z = GetMap()->GetHeight(GetPhases(), x, y, z + 2.0f, true);
float new_z = GetMap()->GetHeight(GetPhaseShift(), x, y, z + 2.0f, true);
if (new_z > INVALID_HEIGHT)
z = new_z + 0.05f; // just to be sure that we are not a few pixel under the surface
}
@@ -1643,8 +1644,8 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const
bool canSwim = ToCreature()->CanSwim();
float ground_z = z;
float max_z = canSwim
? GetMap()->GetWaterOrGroundLevel(GetPhases(), x, y, z, &ground_z, !ToUnit()->HasAuraType(SPELL_AURA_WATER_WALK))
: ((ground_z = GetMap()->GetHeight(GetPhases(), x, y, z, true)));
? GetMap()->GetWaterOrGroundLevel(GetPhaseShift(), x, y, z, &ground_z, !ToUnit()->HasAuraType(SPELL_AURA_WATER_WALK))
: ((ground_z = GetMap()->GetHeight(GetPhaseShift(), x, y, z, true)));
if (max_z > INVALID_HEIGHT)
{
if (z > max_z)
@@ -1655,7 +1656,7 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const
}
else
{
float ground_z = GetMap()->GetHeight(GetPhases(), x, y, z, true);
float ground_z = GetMap()->GetHeight(GetPhaseShift(), x, y, z, true);
if (z < ground_z)
z = ground_z;
}
@@ -1667,7 +1668,7 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const
if (!ToPlayer()->CanFly())
{
float ground_z = z;
float max_z = GetMap()->GetWaterOrGroundLevel(GetPhases(), x, y, z, &ground_z, !ToUnit()->HasAuraType(SPELL_AURA_WATER_WALK));
float max_z = GetMap()->GetWaterOrGroundLevel(GetPhaseShift(), x, y, z, &ground_z, !ToUnit()->HasAuraType(SPELL_AURA_WATER_WALK));
if (max_z > INVALID_HEIGHT)
{
if (z > max_z)
@@ -1678,7 +1679,7 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const
}
else
{
float ground_z = GetMap()->GetHeight(GetPhases(), x, y, z, true);
float ground_z = GetMap()->GetHeight(GetPhaseShift(), x, y, z, true);
if (z < ground_z)
z = ground_z;
}
@@ -1686,7 +1687,7 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const
}
default:
{
float ground_z = GetMap()->GetHeight(GetPhases(), x, y, z, true);
float ground_z = GetMap()->GetHeight(GetPhaseShift(), x, y, z, true);
if (ground_z > INVALID_HEIGHT)
z = ground_z;
break;
@@ -2100,7 +2101,7 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert
}
// Set the summon to the summoner's phase
summon->CopyPhaseFrom(summoner);
PhasingHandler::InheritPhaseShift(summon, summoner);
summon->SetUInt32Value(UNIT_CREATED_BY_SPELL, spellId);
@@ -2204,7 +2205,7 @@ GameObject* WorldObject::SummonGameObject(uint32 entry, Position const& pos, G3D
return nullptr;
}
go->CopyPhaseFrom(this);
PhasingHandler::InheritPhaseShift(go, this);
go->SetRespawnTime(respawnTime);
if (GetTypeId() == TYPEID_PLAYER || (GetTypeId() == TYPEID_UNIT && summonType == GO_SUMMON_TIMED_OR_CORPSE_DESPAWN)) //not sure how to handle this
@@ -2430,8 +2431,8 @@ void WorldObject::MovePosition(Position &pos, float dist, float angle)
return;
}
ground = GetMap()->GetHeight(GetPhases(), destx, desty, MAX_HEIGHT, true);
floor = GetMap()->GetHeight(GetPhases(), destx, desty, pos.m_positionZ, true);
ground = GetMap()->GetHeight(GetPhaseShift(), destx, desty, MAX_HEIGHT, true);
floor = GetMap()->GetHeight(GetPhaseShift(), destx, desty, pos.m_positionZ, true);
destz = std::fabs(ground - pos.m_positionZ) <= std::fabs(floor - pos.m_positionZ) ? ground : floor;
float step = dist/10.0f;
@@ -2443,8 +2444,8 @@ void WorldObject::MovePosition(Position &pos, float dist, float angle)
{
destx -= step * std::cos(angle);
desty -= step * std::sin(angle);
ground = GetMap()->GetHeight(GetPhases(), destx, desty, MAX_HEIGHT, true);
floor = GetMap()->GetHeight(GetPhases(), destx, desty, pos.m_positionZ, true);
ground = GetMap()->GetHeight(GetPhaseShift(), destx, desty, MAX_HEIGHT, true);
floor = GetMap()->GetHeight(GetPhaseShift(), destx, desty, pos.m_positionZ, true);
destz = std::fabs(ground - pos.m_positionZ) <= std::fabs(floor - pos.m_positionZ) ? ground : floor;
}
// we have correct destz now
@@ -2464,8 +2465,8 @@ void WorldObject::MovePosition(Position &pos, float dist, float angle)
// @todo: replace with WorldObject::UpdateAllowedPositionZ
float NormalizeZforCollision(WorldObject* obj, float x, float y, float z)
{
float ground = obj->GetMap()->GetHeight(obj->GetPhases(), x, y, MAX_HEIGHT, true);
float floor = obj->GetMap()->GetHeight(obj->GetPhases(), x, y, z + 2.0f, true);
float ground = obj->GetMap()->GetHeight(obj->GetPhaseShift(), x, y, MAX_HEIGHT, true);
float floor = obj->GetMap()->GetHeight(obj->GetPhaseShift(), x, y, z + 2.0f, true);
float helper = std::fabs(ground - z) <= std::fabs(floor - z) ? ground : floor;
if (z > helper) // must be above ground
{
@@ -2514,7 +2515,7 @@ void WorldObject::MovePositionToFirstCollision(Position &pos, float dist, float
}
// check dynamic collision
col = GetMap()->getObjectHitPos(GetPhases(), pos.m_positionX, pos.m_positionY, pos.m_positionZ + 0.5f, destx, desty, destz + 0.5f, destx, desty, destz, -0.5f);
col = GetMap()->getObjectHitPos(GetPhaseShift(), pos.m_positionX, pos.m_positionY, pos.m_positionZ + 0.5f, destx, desty, destz + 0.5f, destx, desty, destz, -0.5f);
// Collided with a gameobject
if (col)
@@ -2557,165 +2558,6 @@ void WorldObject::SetPhaseMask(uint32 newPhaseMask, bool update)
UpdateObjectVisibility();
}
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 const& phases = sObjectMgr->GetAreaPhases();
for (PhaseInfo::const_iterator itr = phases.begin(); itr != phases.end(); ++itr)
{
uint32 areaId = itr->first;
for (PhaseInfoStruct const& phase : itr->second)
{
if (areaId == GetAreaId())
{
if (sConditionMgr->IsObjectMeetToConditions(this, phase.Conditions))
{
// add new phase if condition passed, true if it wasnt added before
bool up = SetInPhase(phase.Id, false, true);
if (!updateNeeded && up)
updateNeeded = true;
}
else
{
// condition failed, remove phase, true if there was something removed
bool up = SetInPhase(phase.Id, false, false);
if (!updateNeeded && up)
updateNeeded = true;
}
}
else
{
// not in area, remove phase, true if there was something removed
bool up = SetInPhase(phase.Id, 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
{
// 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
PhaseInfo const& phases = sObjectMgr->GetAreaPhases();
for (PhaseInfo::const_iterator itr = phases.begin(); itr != phases.end(); ++itr)
if (itr->first == GetAreaId() || itr->first == GetZoneId())
for (PhaseInfoStruct const& phase : itr->second)
if (id == phase.Id)
if (sConditionMgr->IsObjectMeetToConditions(this, phase.Conditions))
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();
}
bool WorldObject::IsInPhase(std::set<uint32> const& phases) const
{
// PhaseId 169 is the default fallback phase
if (_phases.empty() && phases.empty())
return true;
if (_phases.empty() && phases.count(DEFAULT_PHASE) > 0)
return true;
if (phases.empty() && _phases.count(DEFAULT_PHASE) > 0)
return true;
return Trinity::Containers::Intersects(_phases.begin(), _phases.end(), phases.begin(), phases.end());
}
bool WorldObject::IsInPhase(WorldObject const* obj) const
{
if (GetTypeId() == TYPEID_PLAYER && ToPlayer()->IsGameMaster())
return true;
return IsInPhase(obj->GetPhases());
}
void WorldObject::PlayDistanceSound(uint32 sound_id, Player* target /*= NULL*/)
{
WorldPacket data(SMSG_PLAY_OBJECT_SOUND, 4 + 8);
@@ -2882,7 +2724,7 @@ float WorldObject::GetFloorZ() const
{
if (!IsInWorld())
return m_staticFloorZ;
return std::max<float>(m_staticFloorZ, GetMap()->GetGameObjectFloor(GetPhases(), GetPositionX(), GetPositionY(), GetPositionZ()));
return std::max<float>(m_staticFloorZ, GetMap()->GetGameObjectFloor(GetPhaseShift(), GetPositionX(), GetPositionY(), GetPositionZ()));
}
template TC_GAME_API void WorldObject::GetGameObjectListWithEntryInGrid(std::list<GameObject*>&, uint32, float) const;
@@ -2944,63 +2786,3 @@ void WorldObject::SetMeleeAnimKitId(uint16 animKitId)
data << uint16(animKitId);
SendMessageToSet(&data, true);
}
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();
// Check all applied phases for terrain swap and add it only once
for (uint32 phaseId : _phases)
{
if (std::vector<uint32> const* swaps = sObjectMgr->GetPhaseTerrainSwaps(phaseId))
{
for (uint32 const& swap : *swaps)
{
// only add terrain swaps for current map
MapEntry const* mapEntry = sMapStore.LookupEntry(swap);
if (!mapEntry || mapEntry->rootPhaseMap != int32(GetMapId()))
continue;
if (sConditionMgr->IsObjectMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_TERRAIN_SWAP, swap, this))
_terrainSwaps.insert(swap);
}
}
}
// get default terrain swaps, only for current map always
if (std::vector<uint32> const* mapSwaps = sObjectMgr->GetDefaultTerrainSwaps(GetMapId()))
for (uint32 const& swap : *mapSwaps)
if (sConditionMgr->IsObjectMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_TERRAIN_SWAP, swap, this))
_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 const& defaults = sObjectMgr->GetDefaultTerrainSwapStore();
for (TerrainPhaseInfo::const_iterator itr = defaults.begin(); itr != defaults.end(); ++itr)
for (uint32 const& swap : itr->second)
if (std::vector<uint32> const* uiMapSwaps = sObjectMgr->GetTerrainWorldMaps(swap))
if (sConditionMgr->IsObjectMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_TERRAIN_SWAP, swap, this))
for (uint32 worldMapAreaId : *uiMapSwaps)
_worldMapAreaSwaps.insert(worldMapAreaId);
// Check all applied phases for world map area swaps
for (uint32 phaseId : _phases)
if (std::vector<uint32> const* swaps = sObjectMgr->GetPhaseTerrainSwaps(phaseId))
for (uint32 const& swap : *swaps)
if (std::vector<uint32> const* uiMapSwaps = sObjectMgr->GetTerrainWorldMaps(swap))
if (sConditionMgr->IsObjectMeetingNotGroupedConditions(CONDITION_SOURCE_TYPE_TERRAIN_SWAP, swap, this))
for (uint32 worldMapAreaId : *uiMapSwaps)
_worldMapAreaSwaps.insert(worldMapAreaId);
}