Revert Visibility Notifier changes (#17682)

* Revert "fix(Core/Grid): Implement missing GridUnload setting (#17569)"

This reverts commit 79b39f9655.

* Revert "fix(Core/Grid): Address bugs and performance issues introduced by visibility notifier implementation (#17480)"

This reverts commit 60e27511c5.

* Revert "fix(Core): GridCleanUpDelay Log (#17436)"

This reverts commit 90b16ca065.

* Revert "feat(Core/Grids): Implement visibility notifier (#15919)"

This reverts commit 2779833768.
This commit is contained in:
Kitzunu
2023-11-12 00:48:49 +01:00
committed by GitHub
parent 4df0ab3427
commit bbadc32bea
64 changed files with 1074 additions and 1764 deletions
@@ -939,13 +939,6 @@ ClientCacheVersion = 0
SessionAddDelay = 10000 SessionAddDelay = 10000
#
# GridCleanUpDelay
# Description: Time (in milliseconds) grid clean up delay.
# Default: 300000 - (5 minutes)
GridCleanUpDelay = 300000
# #
# CloseIdleConnections # CloseIdleConnections
# Description: Automatically close idle connections. # Description: Automatically close idle connections.
@@ -1251,17 +1244,17 @@ Visibility.GroupMode = 1
# Visibility.Distance.Instances # Visibility.Distance.Instances
# Visibility.Distance.BGArenas # Visibility.Distance.BGArenas
# Description: Visibility distance to see other players or gameobjects. # Description: Visibility distance to see other players or gameobjects.
# Visibility on continents on retail ~100 yards. In BG/Arenas ~533. # Visibility on continents on retail ~90 yards. In BG/Arenas ~180.
# For instances default ~170. # For instances default ~120.
# Max limited by grid size: 533.33333 # Max limited by active player zone: ~ 333
# Min limit is max aggro radius (45) * Rate.Creature.Aggro # Min limit is max aggro radius (45) * Rate.Creature.Aggro
# Default: 100 - (Visibility.Distance.Continents) # Default: 90 - (Visibility.Distance.Continents)
# 170 - (Visibility.Distance.Instances) # 120 - (Visibility.Distance.Instances)
# 533 - (Visibility.Distance.BGArenas) # 180 - (Visibility.Distance.BGArenas)
Visibility.Distance.Continents = 100 Visibility.Distance.Continents = 90
Visibility.Distance.Instances = 170 Visibility.Distance.Instances = 120
Visibility.Distance.BGArenas = 533 Visibility.Distance.BGArenas = 180
# #
# Visibility.Notify.Period.OnContinents # Visibility.Notify.Period.OnContinents
@@ -1372,22 +1365,13 @@ DetectPosCollision = 1
CheckGameObjectLoS = 1 CheckGameObjectLoS = 1
#
# GridUnload
# Description: Unload grids to save memory. Can be disabled if enough memory is available
# to speed up moving players to new grids.
# Default: 1 - (enable, Unload grids)
# 0 - (disable, Do not unload grids)
GridUnload = 1
# #
# PreloadAllNonInstancedMapGrids # PreloadAllNonInstancedMapGrids
# Description: Preload all grids on all non-instanced maps. Requires GridUnload to be disabled. # Description: Preload all grids on all non-instanced maps. This will take a great amount
# This will take a great amount of additional RAM (ca. 9 GB) and causes the server # of additional RAM (ca. 9 GB) and causes the server to take longer to start,
# to take longer to start, but can increase performance if used on a server with a # but can increase performance if used on a server with a high amount of players.
# high amount of players. It will also activate all creatures which are set active # It will also activate all creatures which are set active (e.g. the Fel Reavers
# (e.g. the Fel Reavers in Hellfire Peninsula) on server start. # in Hellfire Peninsula) on server start.
# Default: 0 - (Disabled) # Default: 0 - (Disabled)
# 1 - (Enabled) # 1 - (Enabled)
+2 -2
View File
@@ -815,7 +815,7 @@ Creature* Battlefield::SpawnCreature(uint32 entry, float x, float y, float z, fl
// Set creature in world // Set creature in world
map->AddToMap(creature); map->AddToMap(creature);
creature->SetFarVisible(true); creature->setActive(true);
return creature; return creature;
} }
@@ -840,7 +840,7 @@ GameObject* Battlefield::SpawnGameObject(uint32 entry, float x, float y, float z
// Add to world // Add to world
map->AddToMap(go); map->AddToMap(go);
go->SetFarVisible(true); go->setActive(true);
return go; return go;
} }
@@ -1159,7 +1159,6 @@ struct BfWGGameObjectBuilding
// Rebuild gameobject // Rebuild gameobject
go->SetDestructibleState(GO_DESTRUCTIBLE_REBUILDING, nullptr, true); go->SetDestructibleState(GO_DESTRUCTIBLE_REBUILDING, nullptr, true);
go->SetUInt32Value(GAMEOBJECT_FACTION, WintergraspFaction[m_Team]); go->SetUInt32Value(GAMEOBJECT_FACTION, WintergraspFaction[m_Team]);
go->setActive(false); // Everything is reset, no need keep active at this point.
} }
// Update worldstate // Update worldstate
@@ -1171,10 +1170,6 @@ struct BfWGGameObjectBuilding
// Called when associated gameobject is damaged // Called when associated gameobject is damaged
void Damaged() void Damaged()
{ {
GameObject* go = m_WG->GetGameObject(m_Build);
if (go)
go->setActive(true);
// Update worldstate // Update worldstate
m_State = BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_DAMAGE - (m_Team * 3); m_State = BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_DAMAGE - (m_Team * 3);
m_WG->SendUpdateWorldState(m_WorldState, m_State); m_WG->SendUpdateWorldState(m_WorldState, m_State);
@@ -1198,10 +1193,6 @@ struct BfWGGameObjectBuilding
// Called when associated gameobject is destroyed // Called when associated gameobject is destroyed
void Destroyed() void Destroyed()
{ {
GameObject* go = m_WG->GetGameObject(m_Build);
if (go)
go->setActive(true);
// Update worldstate // Update worldstate
m_State = BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_DESTROY - (m_Team * 3); m_State = BATTLEFIELD_WG_OBJECTSTATE_ALLIANCE_DESTROY - (m_Team * 3);
m_WG->SendUpdateWorldState(m_WorldState, m_State); m_WG->SendUpdateWorldState(m_WorldState, m_State);
@@ -551,6 +551,6 @@ void BattlegroundAB::ApplyPhaseMask()
for (auto const& itr : bgPlayerMap) for (auto const& itr : bgPlayerMap)
{ {
itr.second->SetPhaseMask(phaseMask, false); itr.second->SetPhaseMask(phaseMask, false);
itr.second->UpdateObjectVisibility(true); itr.second->UpdateObjectVisibility(true, false);
} }
} }
+19 -27
View File
@@ -301,6 +301,9 @@ void Creature::RemoveFromWorld()
if (m_formation) if (m_formation)
sFormationMgr->RemoveCreatureFromGroup(m_formation, this); sFormationMgr->RemoveCreatureFromGroup(m_formation, this);
if (Transport* transport = GetTransport())
transport->RemovePassenger(this, true);
Unit::RemoveFromWorld(); Unit::RemoveFromWorld();
if (m_spawnId) if (m_spawnId)
@@ -362,15 +365,17 @@ void Creature::RemoveCorpse(bool setSpawnTime, bool skipVisibility)
//SaveRespawnTime(); //SaveRespawnTime();
} }
float x, y, z, o;
GetRespawnPosition(x, y, z, &o);
SetHomePosition(x, y, z, o);
SetPosition(x, y, z, o);
// xinef: relocate notifier
m_last_notify_position.Relocate(-5000.0f, -5000.0f, -5000.0f, 0.0f);
// pussywizard: if corpse was removed during falling then the falling will continue after respawn, so stop falling is such case // pussywizard: if corpse was removed during falling then the falling will continue after respawn, so stop falling is such case
if (IsFalling()) if (IsFalling())
StopMoving(); StopMoving();
float x, y, z, o;
GetRespawnPosition(x, y, z, &o);
UpdateAllowedPositionZ(x, y, z);
SetHomePosition(x, y, z, o);
GetMap()->CreatureRelocation(this, x, y, z, o);
} }
/** /**
@@ -1823,25 +1828,7 @@ void Creature::DeleteFromDB()
return; return;
} }
CreatureData const* data = sObjectMgr->GetCreatureData(m_spawnId); GetMap()->RemoveCreatureRespawnTime(m_spawnId);
if (!data)
return;
CharacterDatabaseTransaction charTrans = CharacterDatabase.BeginTransaction();
sMapMgr->DoForAllMapsWithMapId(data->mapid,
[this, charTrans](Map* map) -> void
{
// despawn all active creatures, and remove their respawns
std::vector<Creature*> toUnload;
for (auto const& pair : Acore::Containers::MapEqualRange(map->GetCreatureBySpawnIdStore(), m_spawnId))
toUnload.push_back(pair.second);
for (Creature* creature : toUnload)
map->AddObjectToRemoveList(creature);
map->RemoveCreatureRespawnTime(m_spawnId);
}
);
sObjectMgr->DeleteCreatureData(m_spawnId); sObjectMgr->DeleteCreatureData(m_spawnId);
WorldDatabaseTransaction trans = WorldDatabase.BeginTransaction(); WorldDatabaseTransaction trans = WorldDatabase.BeginTransaction();
@@ -2093,7 +2080,9 @@ void Creature::Respawn(bool force)
m_respawnedTime = GameTime::GetGameTime().count(); m_respawnedTime = GameTime::GetGameTime().count();
} }
m_respawnedTime = GameTime::GetGameTime().count(); m_respawnedTime = GameTime::GetGameTime().count();
UpdateObjectVisibility(); // xinef: relocate notifier, fixes npc appearing in corpse position after forced respawn (instead of spawn)
m_last_notify_position.Relocate(-5000.0f, -5000.0f, -5000.0f, 0.0f);
UpdateObjectVisibility(false);
} }
void Creature::ForcedDespawn(uint32 timeMSToDespawn, Seconds forceRespawnTimer) void Creature::ForcedDespawn(uint32 timeMSToDespawn, Seconds forceRespawnTimer)
@@ -3075,7 +3064,10 @@ std::string const& Creature::GetNameForLocaleIdx(LocaleConstant loc_idx) const
void Creature::SetPosition(float x, float y, float z, float o) void Creature::SetPosition(float x, float y, float z, float o)
{ {
UpdatePosition(x, y, z, o, false); if (!Acore::IsValidMapCoord(x, y, z, o))
return;
GetMap()->CreatureRelocation(this, x, y, z, o);
} }
bool Creature::IsDungeonBoss() const bool Creature::IsDungeonBoss() const
@@ -68,7 +68,6 @@ public:
void Update(uint32 time) override; // overwrited Unit::Update void Update(uint32 time) override; // overwrited Unit::Update
void GetRespawnPosition(float& x, float& y, float& z, float* ori = nullptr, float* dist = nullptr) const; void GetRespawnPosition(float& x, float& y, float& z, float* ori = nullptr, float* dist = nullptr) const;
bool IsSpawnedOnTransport() const { return m_creatureData && m_creatureData->mapid != GetMapId(); }
void SetCorpseDelay(uint32 delay) { m_corpseDelay = delay; } void SetCorpseDelay(uint32 delay) { m_corpseDelay = delay; }
void SetCorpseRemoveTime(uint32 delay); void SetCorpseRemoveTime(uint32 delay);
@@ -47,6 +47,14 @@ DynamicObject::~DynamicObject()
void DynamicObject::CleanupsBeforeDelete(bool finalCleanup /* = true */) void DynamicObject::CleanupsBeforeDelete(bool finalCleanup /* = true */)
{ {
if (Transport* transport = GetTransport())
{
transport->RemovePassenger(this);
SetTransport(nullptr);
m_movementInfo.transport.Reset();
m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
}
WorldObject::CleanupsBeforeDelete(finalCleanup); WorldObject::CleanupsBeforeDelete(finalCleanup);
} }
@@ -80,6 +88,9 @@ void DynamicObject::RemoveFromWorld()
UnbindFromCaster(); UnbindFromCaster();
if (Transport* transport = GetTransport())
transport->RemovePassenger(this, true);
WorldObject::RemoveFromWorld(); WorldObject::RemoveFromWorld();
GetMap()->GetObjectsStore().Remove<DynamicObject>(GetGUID()); GetMap()->GetObjectsStore().Remove<DynamicObject>(GetGUID());
@@ -114,15 +125,17 @@ bool DynamicObject::CreateDynamicObject(ObjectGuid::LowType guidlow, Unit* caste
SetFloatValue(DYNAMICOBJECT_RADIUS, radius); SetFloatValue(DYNAMICOBJECT_RADIUS, radius);
SetUInt32Value(DYNAMICOBJECT_CASTTIME, GameTime::GetGameTimeMS().count()); SetUInt32Value(DYNAMICOBJECT_CASTTIME, GameTime::GetGameTimeMS().count());
if (IsWorldObject())
setActive(true); //must before add to map to be put in world container
if (!GetMap()->AddToMap(this, true)) if (!GetMap()->AddToMap(this, true))
{ {
// Returning false will cause the object to be deleted - remove from transport // Returning false will cause the object to be deleted - remove from transport
return false; return false;
} }
if (IsWorldObject())
{
setActive(true);
}
return true; return true;
} }
@@ -27,7 +27,6 @@
#include "GridNotifiersImpl.h" #include "GridNotifiersImpl.h"
#include "Group.h" #include "Group.h"
#include "GroupMgr.h" #include "GroupMgr.h"
#include "MapMgr.h"
#include "ObjectMgr.h" #include "ObjectMgr.h"
#include "OutdoorPvPMgr.h" #include "OutdoorPvPMgr.h"
#include "PoolMgr.h" #include "PoolMgr.h"
@@ -103,9 +102,18 @@ std::string const& GameObject::GetAIName() const
return sObjectMgr->GetGameObjectTemplate(GetEntry())->AIName; return sObjectMgr->GetGameObjectTemplate(GetEntry())->AIName;
} }
void GameObject::CleanupsBeforeDelete(bool finalCleanup) void GameObject::CleanupsBeforeDelete(bool /*finalCleanup*/)
{ {
WorldObject::CleanupsBeforeDelete(finalCleanup); if (GetTransport() && !ToTransport())
{
GetTransport()->RemovePassenger(this);
SetTransport(nullptr);
m_movementInfo.transport.Reset();
m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
}
if (IsInWorld())
RemoveFromWorld();
if (m_uint32Values) // field array can be not exist if GameOBject not loaded if (m_uint32Values) // field array can be not exist if GameOBject not loaded
RemoveFromOwner(); RemoveFromOwner();
@@ -174,6 +182,9 @@ void GameObject::RemoveFromWorld()
if (GetMap()->ContainsGameObjectModel(*m_model)) if (GetMap()->ContainsGameObjectModel(*m_model))
GetMap()->RemoveGameObjectModel(*m_model); GetMap()->RemoveGameObjectModel(*m_model);
if (Transport* transport = GetTransport())
transport->RemovePassenger(this, true);
// If linked trap exists, despawn it // If linked trap exists, despawn it
if (GameObject* linkedTrap = GetLinkedTrap()) if (GameObject* linkedTrap = GetLinkedTrap())
{ {
@@ -877,11 +888,7 @@ void GameObject::Update(uint32 diff)
if (!m_spawnedByDefault) if (!m_spawnedByDefault)
{ {
m_respawnTime = 0; m_respawnTime = 0;
if (m_spawnId)
DestroyForNearbyPlayers(); // xinef: old UpdateObjectVisibility(); DestroyForNearbyPlayers(); // xinef: old UpdateObjectVisibility();
else
Delete();
return; return;
} }
@@ -1177,31 +1184,7 @@ bool GameObject::LoadGameObjectFromDB(ObjectGuid::LowType spawnId, Map* map, boo
void GameObject::DeleteFromDB() void GameObject::DeleteFromDB()
{ {
if (!m_spawnId) GetMap()->RemoveGORespawnTime(m_spawnId);
{
LOG_ERROR("entities.gameobject", "Trying to delete not saved gameobject: {}", GetGUID().ToString());
return;
}
GameObjectData const* data = sObjectMgr->GetGameObjectData(m_spawnId);
if (!data)
return;
CharacterDatabaseTransaction charTrans = CharacterDatabase.BeginTransaction();
sMapMgr->DoForAllMapsWithMapId(data->mapid,
[this, charTrans](Map* map) -> void
{
// despawn all active objects, and remove their respawns
std::vector<GameObject*> toUnload;
for (auto const& pair : Acore::Containers::MapEqualRange(map->GetGameObjectBySpawnIdStore(), m_spawnId))
toUnload.push_back(pair.second);
for (GameObject* obj : toUnload)
map->AddObjectToRemoveList(obj);
map->RemoveGORespawnTime(m_spawnId);
}
);
sObjectMgr->DeleteGOData(m_spawnId); sObjectMgr->DeleteGOData(m_spawnId);
WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_GAMEOBJECT); WorldDatabasePreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_GAMEOBJECT);
@@ -2190,6 +2173,15 @@ bool GameObject::IsInRange(float x, float y, float z, float radius) const
&& dz < (info->maxZ * scale) + radius && dz > (info->minZ * scale) - radius; && dz < (info->maxZ * scale) + radius && dz > (info->minZ * scale) - radius;
} }
void GameObject::SendMessageToSetInRange(WorldPacket const* data, float dist, bool /*self*/, bool includeMargin, Player const* skipped_rcvr) const
{
dist += GetObjectSize();
if (includeMargin)
dist += VISIBILITY_COMPENSATION * 2.0f; // pussywizard: to ensure everyone receives all important packets
Acore::MessageDistDeliverer notifier(this, data, dist, false, skipped_rcvr);
Cell::VisitWorldObjects(this, notifier, dist);
}
void GameObject::EventInform(uint32 eventId) void GameObject::EventInform(uint32 eventId)
{ {
if (!eventId) if (!eventId)
@@ -289,6 +289,8 @@ public:
void SendCustomAnim(uint32 anim); void SendCustomAnim(uint32 anim);
[[nodiscard]] bool IsInRange(float x, float y, float z, float radius) const; [[nodiscard]] bool IsInRange(float x, float y, float z, float radius) const;
void SendMessageToSetInRange(WorldPacket const* data, float dist, bool /*self*/, bool includeMargin = false, Player const* skipped_rcvr = nullptr) const override; // pussywizard!
void ModifyHealth(int32 change, Unit* attackerOrHealer = nullptr, uint32 spellId = 0); void ModifyHealth(int32 change, Unit* attackerOrHealer = nullptr, uint32 spellId = 0);
void SetDestructibleBuildingModifyState(bool allow) { m_allowModifyDestructibleBuilding = allow; } void SetDestructibleBuildingModifyState(bool allow) { m_allowModifyDestructibleBuilding = allow; }
// sets GameObject type 33 destruction flags and optionally default health for that state // sets GameObject type 33 destruction flags and optionally default health for that state
+88 -32
View File
@@ -21,6 +21,7 @@
#include "CellImpl.h" #include "CellImpl.h"
#include "Chat.h" #include "Chat.h"
#include "Creature.h" #include "Creature.h"
#include "DynamicVisibility.h"
#include "GameObjectAI.h" #include "GameObjectAI.h"
#include "GameTime.h" #include "GameTime.h"
#include "GridNotifiers.h" #include "GridNotifiers.h"
@@ -64,7 +65,7 @@ constexpr float VisibilityDistances[AsUnderlyingType(VisibilityDistanceType::Max
VISIBILITY_DISTANCE_SMALL, VISIBILITY_DISTANCE_SMALL,
VISIBILITY_DISTANCE_LARGE, VISIBILITY_DISTANCE_LARGE,
VISIBILITY_DISTANCE_GIGANTIC, VISIBILITY_DISTANCE_GIGANTIC,
MAX_VISIBILITY_DISTANCE VISIBILITY_DISTANCE_INFINITE
}; };
Object::Object() : m_PackGUID(sizeof(uint64) + 1) Object::Object() : m_PackGUID(sizeof(uint64) + 1)
@@ -248,9 +249,6 @@ void Object::SendUpdateToPlayer(Player* player)
UpdateData upd; UpdateData upd;
WorldPacket packet; WorldPacket packet;
if (player->HaveAtClient(this))
BuildValuesUpdateBlockForPlayer(&upd, player);
else
BuildCreateUpdateBlockForPlayer(&upd, player); BuildCreateUpdateBlockForPlayer(&upd, player);
upd.BuildPacket(&packet); upd.BuildPacket(&packet);
player->GetSession()->SendPacket(&packet); player->GetSession()->SendPacket(&packet);
@@ -1050,7 +1048,7 @@ void MovementInfo::OutDebug()
} }
WorldObject::WorldObject(bool isWorldObject) : WorldLocation(), WorldObject::WorldObject(bool isWorldObject) : WorldLocation(),
LastUsedScriptID(0), m_name(""), m_isActive(false), m_isFarVisible(false), m_visibilityDistanceOverride(), m_isWorldObject(isWorldObject), m_zoneScript(nullptr), LastUsedScriptID(0), m_name(""), m_isActive(false), m_visibilityDistanceOverride(), m_isWorldObject(isWorldObject), m_zoneScript(nullptr),
_zoneId(0), _areaId(0), _floorZ(INVALID_HEIGHT), _outdoors(false), _liquidData(), _updatePositionData(false), m_transport(nullptr), _zoneId(0), _areaId(0), _floorZ(INVALID_HEIGHT), _outdoors(false), _liquidData(), _updatePositionData(false), m_transport(nullptr),
m_currMap(nullptr), m_InstanceId(0), m_phaseMask(PHASEMASK_NORMAL), m_useCombinedPhases(true), m_notifyflags(0), m_executed_notifies(0) m_currMap(nullptr), m_InstanceId(0), m_phaseMask(PHASEMASK_NORMAL), m_useCombinedPhases(true), m_notifyflags(0), m_executed_notifies(0)
{ {
@@ -1107,6 +1105,8 @@ void WorldObject::setActive(bool on)
map->AddToActive(this->ToCreature()); map->AddToActive(this->ToCreature());
else if (GetTypeId() == TYPEID_DYNAMICOBJECT) else if (GetTypeId() == TYPEID_DYNAMICOBJECT)
map->AddToActive((DynamicObject*)this); map->AddToActive((DynamicObject*)this);
else if (GetTypeId() == TYPEID_GAMEOBJECT)
map->AddToActive((GameObject*)this);
} }
else else
{ {
@@ -1114,17 +1114,11 @@ void WorldObject::setActive(bool on)
map->RemoveFromActive(this->ToCreature()); map->RemoveFromActive(this->ToCreature());
else if (GetTypeId() == TYPEID_DYNAMICOBJECT) else if (GetTypeId() == TYPEID_DYNAMICOBJECT)
map->RemoveFromActive((DynamicObject*)this); map->RemoveFromActive((DynamicObject*)this);
else if (GetTypeId() == TYPEID_GAMEOBJECT)
map->RemoveFromActive((GameObject*)this);
} }
} }
void WorldObject::SetFarVisible(bool on)
{
if (GetTypeId() == TYPEID_PLAYER)
return;
m_isFarVisible = on;
}
void WorldObject::SetVisibilityDistanceOverride(VisibilityDistanceType type) void WorldObject::SetVisibilityDistanceOverride(VisibilityDistanceType type)
{ {
ASSERT(type < VisibilityDistanceType::Max); ASSERT(type < VisibilityDistanceType::Max);
@@ -1140,9 +1134,6 @@ void WorldObject::CleanupsBeforeDelete(bool /*finalCleanup*/)
{ {
if (IsInWorld()) if (IsInWorld())
RemoveFromWorld(); RemoveFromWorld();
if (Transport* transport = GetTransport())
transport->RemovePassenger(this, true);
} }
void WorldObject::_Create(ObjectGuid::LowType guidlow, HighGuid guidhigh, uint32 phaseMask) void WorldObject::_Create(ObjectGuid::LowType guidlow, HighGuid guidhigh, uint32 phaseMask)
@@ -1635,9 +1626,9 @@ float WorldObject::GetGridActivationRange() const
{ {
if (ToPlayer()->GetCinematicMgr()->IsOnCinematic()) if (ToPlayer()->GetCinematicMgr()->IsOnCinematic())
{ {
return std::max(DEFAULT_VISIBILITY_INSTANCE, GetMap()->GetVisibilityRange()); return DEFAULT_VISIBILITY_INSTANCE;
} }
return IsInWintergrasp() ? VISIBILITY_DISTANCE_LARGE : GetMap()->GetVisibilityRange(); return IsInWintergrasp() ? VISIBILITY_DIST_WINTERGRASP : GetMap()->GetVisibilityRange();
} }
else if (ToCreature()) else if (ToCreature())
{ {
@@ -1653,12 +1644,29 @@ float WorldObject::GetGridActivationRange() const
float WorldObject::GetVisibilityRange() const float WorldObject::GetVisibilityRange() const
{ {
if (IsVisibilityOverridden() && !ToPlayer()) if (IsVisibilityOverridden() && GetTypeId() == TYPEID_UNIT)
{
return *m_visibilityDistanceOverride; return *m_visibilityDistanceOverride;
else if (IsFarVisible() && !ToPlayer()) }
return MAX_VISIBILITY_DISTANCE; else if (GetTypeId() == TYPEID_GAMEOBJECT)
{
{
if (IsInWintergrasp())
{
return VISIBILITY_DIST_WINTERGRASP + VISIBILITY_INC_FOR_GOBJECTS;
}
else if (IsVisibilityOverridden())
{
return *m_visibilityDistanceOverride;
}
else else
return IsInWintergrasp() ? VISIBILITY_DISTANCE_LARGE : GetMap()->GetVisibilityRange(); {
return GetMap()->GetVisibilityRange() + VISIBILITY_INC_FOR_GOBJECTS;
}
}
}
else
return IsInWintergrasp() ? VISIBILITY_DIST_WINTERGRASP : GetMap()->GetVisibilityRange();
} }
float WorldObject::GetSightRange(WorldObject const* target) const float WorldObject::GetSightRange(WorldObject const* target) const
@@ -1667,20 +1675,45 @@ float WorldObject::GetSightRange(WorldObject const* target) const
{ {
if (ToPlayer()) if (ToPlayer())
{ {
if (target && target->IsVisibilityOverridden() && !target->ToPlayer()) if (target)
{
if (target->IsVisibilityOverridden() && target->GetTypeId() == TYPEID_UNIT)
{
return *target->m_visibilityDistanceOverride; return *target->m_visibilityDistanceOverride;
else if (target && target->IsFarVisible() && !target->ToPlayer()) }
return MAX_VISIBILITY_DISTANCE; else if (target->GetTypeId() == TYPEID_GAMEOBJECT)
{
if (IsInWintergrasp() && target->IsInWintergrasp())
{
return VISIBILITY_DIST_WINTERGRASP + VISIBILITY_INC_FOR_GOBJECTS;
}
else if (target->IsVisibilityOverridden())
{
return *target->m_visibilityDistanceOverride;
}
else if (ToPlayer()->GetCinematicMgr()->IsOnCinematic()) else if (ToPlayer()->GetCinematicMgr()->IsOnCinematic())
{
return DEFAULT_VISIBILITY_INSTANCE; return DEFAULT_VISIBILITY_INSTANCE;
}
else else
return IsInWintergrasp() ? VISIBILITY_DISTANCE_LARGE : GetMap()->GetVisibilityRange(); {
return GetMap()->GetVisibilityRange() + VISIBILITY_INC_FOR_GOBJECTS;
}
}
return IsInWintergrasp() && target->IsInWintergrasp() ? VISIBILITY_DIST_WINTERGRASP : GetMap()->GetVisibilityRange();
}
return IsInWintergrasp() ? VISIBILITY_DIST_WINTERGRASP : GetMap()->GetVisibilityRange();
} }
else if (ToCreature()) else if (ToCreature())
{
return ToCreature()->m_SightDistance; return ToCreature()->m_SightDistance;
}
else else
{
return SIGHT_RANGE_UNIT; return SIGHT_RANGE_UNIT;
} }
}
if (ToDynObject() && isActiveObject()) if (ToDynObject() && isActiveObject())
{ {
@@ -2044,8 +2077,11 @@ void Unit::BuildHeartBeatMsg(WorldPacket* data) const
BuildMovementPacket(data); BuildMovementPacket(data);
} }
void WorldObject::SendMessageToSetInRange(WorldPacket const* data, float dist, bool /*self*/, Player const* skipped_rcvr) const void WorldObject::SendMessageToSetInRange(WorldPacket const* data, float dist, bool /*self*/, bool includeMargin, Player const* skipped_rcvr) const
{ {
dist += GetObjectSize();
if (includeMargin)
dist += VISIBILITY_COMPENSATION; // pussywizard: to ensure everyone receives all important packets
Acore::MessageDistDeliverer notifier(this, data, dist, false, skipped_rcvr); Acore::MessageDistDeliverer notifier(this, data, dist, false, skipped_rcvr);
Cell::VisitWorldObjects(this, notifier, dist); Cell::VisitWorldObjects(this, notifier, dist);
} }
@@ -2192,7 +2228,6 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert
return nullptr; return nullptr;
} }
if (!IsGridLoaded(pos.GetPositionX(), pos.GetPositionY()))
EnsureGridLoaded(Cell(pos.GetPositionX(), pos.GetPositionY())); EnsureGridLoaded(Cell(pos.GetPositionX(), pos.GetPositionY()));
if (!summon->Create(GenerateLowGuid<HighGuid::Unit>(), this, phase, entry, vehId, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation())) if (!summon->Create(GenerateLowGuid<HighGuid::Unit>(), this, phase, entry, vehId, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation()))
{ {
@@ -2866,8 +2901,8 @@ void WorldObject::DestroyForNearbyPlayers()
return; return;
std::list<Player*> targets; std::list<Player*> targets;
Acore::AnyPlayerInObjectRangeCheck check(this, GetVisibilityRange(), false); Acore::AnyPlayerInObjectRangeCheck check(this, GetVisibilityRange() + VISIBILITY_COMPENSATION, false);
Acore::PlayerListSearcher<Acore::AnyPlayerInObjectRangeCheck> searcher(this, targets, check); Acore::PlayerListSearcherWithSharedVision<Acore::AnyPlayerInObjectRangeCheck> searcher(this, targets, check);
Cell::VisitWorldObjects(this, searcher, GetVisibilityRange()); Cell::VisitWorldObjects(this, searcher, GetVisibilityRange());
for (std::list<Player*>::const_iterator iter = targets.begin(); iter != targets.end(); ++iter) for (std::list<Player*>::const_iterator iter = targets.begin(); iter != targets.end(); ++iter)
{ {
@@ -2887,7 +2922,7 @@ void WorldObject::DestroyForNearbyPlayers()
} }
} }
void WorldObject::UpdateObjectVisibility(bool /*forced*/) void WorldObject::UpdateObjectVisibility(bool /*forced*/, bool /*fromUpdate*/)
{ {
//updates object's visibility for nearby players //updates object's visibility for nearby players
Acore::VisibleChangesNotifier notifier(*this); Acore::VisibleChangesNotifier notifier(*this);
@@ -2896,8 +2931,29 @@ void WorldObject::UpdateObjectVisibility(bool /*forced*/)
void WorldObject::AddToNotify(uint16 f) void WorldObject::AddToNotify(uint16 f)
{ {
if (!(m_notifyflags & f))
if (Unit* u = ToUnit())
{
if (f & NOTIFY_VISIBILITY_CHANGED)
{
uint32 EVENT_VISIBILITY_DELAY = u->FindMap() ? DynamicVisibilityMgr::GetVisibilityNotifyDelay(u->FindMap()->GetEntry()->map_type) : 1000;
uint32 diff = getMSTimeDiff(u->m_last_notify_mstime, GameTime::GetGameTimeMS().count());
if (diff >= EVENT_VISIBILITY_DELAY / 2)
EVENT_VISIBILITY_DELAY /= 2;
else
EVENT_VISIBILITY_DELAY -= diff;
u->m_delayed_unit_relocation_timer = EVENT_VISIBILITY_DELAY;
u->m_last_notify_mstime = GameTime::GetGameTimeMS().count() + EVENT_VISIBILITY_DELAY - 1;
}
else if (f & NOTIFY_AI_RELOCATION)
{
u->m_delayed_unit_ai_notify_timer = u->FindMap() ? DynamicVisibilityMgr::GetAINotifyDelay(u->FindMap()->GetEntry()->map_type) : 500;
}
m_notifyflags |= f; m_notifyflags |= f;
} }
}
struct WorldObjectChangeAccumulator struct WorldObjectChangeAccumulator
{ {
@@ -2949,7 +3005,7 @@ struct WorldObjectChangeAccumulator
source = iter->GetSource(); source = iter->GetSource();
ObjectGuid guid = source->GetCasterGUID(); ObjectGuid guid = source->GetCasterGUID();
if (guid.IsPlayer()) if (guid)
{ {
//Caster may be nullptr if DynObj is in removelist //Caster may be nullptr if DynObj is in removelist
if (Player* caster = ObjectAccessor::FindPlayer(guid)) if (Player* caster = ObjectAccessor::FindPlayer(guid))
+8 -18
View File
@@ -379,23 +379,14 @@ class MovableMapObject
template<class T> friend class RandomMovementGenerator; template<class T> friend class RandomMovementGenerator;
protected: protected:
MovableMapObject() : _moveState(MAP_OBJECT_CELL_MOVE_NONE) MovableMapObject() = default;
{
_newPosition.Relocate(0.0f, 0.0f, 0.0f, 0.0f);
}
private: private:
Cell _currentCell;
[[nodiscard]] Cell const& GetCurrentCell() const { return _currentCell; } [[nodiscard]] Cell const& GetCurrentCell() const { return _currentCell; }
void SetCurrentCell(Cell const& cell) { _currentCell = cell; } void SetCurrentCell(Cell const& cell) { _currentCell = cell; }
MapObjectCellMoveState _moveState; Cell _currentCell;
Position _newPosition; MapObjectCellMoveState _moveState{MAP_OBJECT_CELL_MOVE_NONE};
void SetNewCellPosition(float x, float y, float z, float o)
{
_moveState = MAP_OBJECT_CELL_MOVE_ACTIVE;
_newPosition.Relocate(x, y, z, o);
}
}; };
class WorldObject : public Object, public WorldLocation class WorldObject : public Object, public WorldLocation
@@ -488,9 +479,9 @@ public:
virtual void CleanupsBeforeDelete(bool finalCleanup = true); // used in destructor or explicitly before mass creature delete to remove cross-references to already deleted units virtual void CleanupsBeforeDelete(bool finalCleanup = true); // used in destructor or explicitly before mass creature delete to remove cross-references to already deleted units
virtual void SendMessageToSet(WorldPacket const* data, bool self) const { if (IsInWorld()) SendMessageToSetInRange(data, GetVisibilityRange(), self); } // pussywizard! virtual void SendMessageToSet(WorldPacket const* data, bool self) const { if (IsInWorld()) SendMessageToSetInRange(data, GetVisibilityRange(), self, true); } // pussywizard!
virtual void SendMessageToSetInRange(WorldPacket const* data, float dist, bool /*self*/, Player const* skipped_rcvr = nullptr) const; // pussywizard! virtual void SendMessageToSetInRange(WorldPacket const* data, float dist, bool /*self*/, bool includeMargin = false, Player const* skipped_rcvr = nullptr) const; // pussywizard!
virtual void SendMessageToSet(WorldPacket const* data, Player const* skipped_rcvr) const { if (IsInWorld()) SendMessageToSetInRange(data, GetVisibilityRange(), false, skipped_rcvr); } // pussywizard! virtual void SendMessageToSet(WorldPacket const* data, Player const* skipped_rcvr) const { if (IsInWorld()) SendMessageToSetInRange(data, GetVisibilityRange(), false, true, skipped_rcvr); } // pussywizard!
virtual uint8 getLevelForTarget(WorldObject const* /*target*/) const { return 1; } virtual uint8 getLevelForTarget(WorldObject const* /*target*/) const { return 1; }
@@ -547,7 +538,7 @@ public:
void GetDeadCreatureListInGrid(std::list<Creature*>& lList, float maxSearchRange, bool alive = false) const; void GetDeadCreatureListInGrid(std::list<Creature*>& lList, float maxSearchRange, bool alive = false) const;
void DestroyForNearbyPlayers(); void DestroyForNearbyPlayers();
virtual void UpdateObjectVisibility(bool forced = true); virtual void UpdateObjectVisibility(bool forced = true, bool fromUpdate = false);
void BuildUpdate(UpdateDataMapType& data_map, UpdatePlayerSet& player_set) override; void BuildUpdate(UpdateDataMapType& data_map, UpdatePlayerSet& player_set) override;
void GetCreaturesWithEntryInRange(std::list<Creature*>& creatureList, float radius, uint32 entry); void GetCreaturesWithEntryInRange(std::list<Creature*>& creatureList, float radius, uint32 entry);
@@ -569,7 +560,6 @@ public:
[[nodiscard]] bool isActiveObject() const { return m_isActive; } [[nodiscard]] bool isActiveObject() const { return m_isActive; }
void setActive(bool isActiveObject); void setActive(bool isActiveObject);
[[nodiscard]] bool IsFarVisible() const { return m_isFarVisible; } [[nodiscard]] bool IsFarVisible() const { return m_isFarVisible; }
void SetFarVisible(bool on);
[[nodiscard]] bool IsVisibilityOverridden() const { return m_visibilityDistanceOverride.has_value(); } [[nodiscard]] bool IsVisibilityOverridden() const { return m_visibilityDistanceOverride.has_value(); }
void SetVisibilityDistanceOverride(VisibilityDistanceType type); void SetVisibilityDistanceOverride(VisibilityDistanceType type);
void SetWorldObject(bool apply); void SetWorldObject(bool apply);
@@ -578,7 +568,7 @@ public:
[[nodiscard]] bool IsInWintergrasp() const [[nodiscard]] bool IsInWintergrasp() const
{ {
return GetMapId() == 571 && GetZoneId() == 4197; return GetMapId() == 571 && GetPositionX() > 3733.33331f && GetPositionX() < 5866.66663f && GetPositionY() > 1599.99999f && GetPositionY() < 4799.99997f;
} }
#ifdef MAP_BASED_RAND_GEN #ifdef MAP_BASED_RAND_GEN
@@ -23,18 +23,23 @@
#define CONTACT_DISTANCE 0.5f #define CONTACT_DISTANCE 0.5f
#define INTERACTION_DISTANCE 5.5f #define INTERACTION_DISTANCE 5.5f
#define ATTACK_DISTANCE 5.0f #define ATTACK_DISTANCE 5.0f
#define VISIBILITY_COMPENSATION 15.0f // increase searchers
#define INSPECT_DISTANCE 28.0f #define INSPECT_DISTANCE 28.0f
#define VISIBILITY_INC_FOR_GOBJECTS 30.0f // pussywizard
#define SPELL_SEARCHER_COMPENSATION 30.0f // increase searchers size in case we have large npc near cell border
#define TRADE_DISTANCE 11.11f #define TRADE_DISTANCE 11.11f
#define MAX_VISIBILITY_DISTANCE SIZE_OF_GRIDS // max distance for visible objects, experimental #define MAX_VISIBILITY_DISTANCE 250.0f // max distance for visible objects, experimental
#define SIGHT_RANGE_UNIT 50.0f #define SIGHT_RANGE_UNIT 50.0f
#define MAX_SEARCHER_DISTANCE 150.0f // pussywizard: replace the use of MAX_VISIBILITY_DISTANCE in searchers, because MAX_VISIBILITY_DISTANCE is quite too big for this purpose #define MAX_SEARCHER_DISTANCE 150.0f // pussywizard: replace the use of MAX_VISIBILITY_DISTANCE in searchers, because MAX_VISIBILITY_DISTANCE is quite too big for this purpose
#define VISIBILITY_DISTANCE_INFINITE 533.0f
#define VISIBILITY_DISTANCE_GIGANTIC 400.0f #define VISIBILITY_DISTANCE_GIGANTIC 400.0f
#define VISIBILITY_DISTANCE_LARGE 200.0f #define VISIBILITY_DISTANCE_LARGE 200.0f
#define VISIBILITY_DISTANCE_NORMAL 100.0f #define VISIBILITY_DISTANCE_NORMAL 100.0f
#define VISIBILITY_DISTANCE_SMALL 50.0f #define VISIBILITY_DISTANCE_SMALL 50.0f
#define VISIBILITY_DISTANCE_TINY 25.0f #define VISIBILITY_DISTANCE_TINY 25.0f
#define DEFAULT_VISIBILITY_DISTANCE VISIBILITY_DISTANCE_NORMAL // default visible distance, 100 yards on continents #define DEFAULT_VISIBILITY_DISTANCE 100.0f // default visible distance, 100 yards on continents
#define DEFAULT_VISIBILITY_INSTANCE 170.0f // default visible distance in instances, 170 yards #define DEFAULT_VISIBILITY_INSTANCE 170.0f // default visible distance in instances, 170 yards
#define VISIBILITY_DIST_WINTERGRASP 175.0f
#define DEFAULT_VISIBILITY_BGARENAS 533.0f // default visible distance in BG/Arenas, roughly 533 yards #define DEFAULT_VISIBILITY_BGARENAS 533.0f // default visible distance in BG/Arenas, roughly 533 yards
#define DEFAULT_WORLD_OBJECT_SIZE 0.388999998569489f // player size, also currently used (correctly?) for any non Unit world objects #define DEFAULT_WORLD_OBJECT_SIZE 0.388999998569489f // player size, also currently used (correctly?) for any non Unit world objects
@@ -134,7 +134,6 @@ class ObjectGuid
ObjectGuid(HighGuid hi, uint32 entry, LowType counter) : _guid(counter ? uint64(counter) | (uint64(entry) << 24) | (uint64(hi) << 48) : 0) { } ObjectGuid(HighGuid hi, uint32 entry, LowType counter) : _guid(counter ? uint64(counter) | (uint64(entry) << 24) | (uint64(hi) << 48) : 0) { }
ObjectGuid(HighGuid hi, LowType counter) : _guid(counter ? uint64(counter) | (uint64(hi) << 48) : 0) { } ObjectGuid(HighGuid hi, LowType counter) : _guid(counter ? uint64(counter) | (uint64(hi) << 48) : 0) { }
operator uint64() const { return _guid; }
PackedGuidReader ReadAsPacked() { return PackedGuidReader(*this); } PackedGuidReader ReadAsPacked() { return PackedGuidReader(*this); }
void Set(uint64 guid) { _guid = guid; } void Set(uint64 guid) { _guid = guid; }
+17 -5
View File
@@ -1353,7 +1353,10 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
if (GetTransport()) if (GetTransport())
{ {
m_transport->RemovePassenger(this, true); m_transport->RemovePassenger(this);
m_transport = nullptr;
m_movementInfo.transport.Reset();
m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
RepopAtGraveyard(); // teleport to near graveyard if on transport, looks blizz like :) RepopAtGraveyard(); // teleport to near graveyard if on transport, looks blizz like :)
} }
@@ -1395,7 +1398,10 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT); AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
else else
{ {
m_transport->RemovePassenger(this, true); m_transport->RemovePassenger(this);
m_transport = nullptr;
m_movementInfo.transport.Reset();
m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
} }
} }
@@ -5575,11 +5581,14 @@ void Player::SaveRecallPosition()
m_recallO = GetOrientation(); m_recallO = GetOrientation();
} }
void Player::SendMessageToSetInRange(WorldPacket const* data, float dist, bool self, Player const* skipped_rcvr) const void Player::SendMessageToSetInRange(WorldPacket const* data, float dist, bool self, bool includeMargin, Player const* skipped_rcvr) const
{ {
if (self) if (self)
GetSession()->SendPacket(data); GetSession()->SendPacket(data);
dist += GetObjectSize();
if (includeMargin)
dist += VISIBILITY_COMPENSATION; // pussywizard: to ensure everyone receives all important packets
Acore::MessageDistDeliverer notifier(this, data, dist, false, skipped_rcvr); Acore::MessageDistDeliverer notifier(this, data, dist, false, skipped_rcvr);
Cell::VisitWorldObjects(this, notifier, dist); Cell::VisitWorldObjects(this, notifier, dist);
} }
@@ -11313,7 +11322,7 @@ WorldLocation Player::GetStartPosition() const
return WorldLocation(mapId, info->positionX, info->positionY, info->positionZ, 0); return WorldLocation(mapId, info->positionX, info->positionY, info->positionZ, 0);
} }
bool Player::HaveAtClient(Object const* u) const bool Player::HaveAtClient(WorldObject const* u) const
{ {
if (u == this) if (u == this)
{ {
@@ -13087,11 +13096,14 @@ void Player::SetViewpoint(WorldObject* target, bool apply)
UpdateVisibilityOf(target); UpdateVisibilityOf(target);
if (target->isType(TYPEMASK_UNIT) && !GetVehicle()) if (target->isType(TYPEMASK_UNIT) && !GetVehicle())
static_cast<Unit*>(target)->AddPlayerToVision(this); ((Unit*)target)->AddPlayerToVision(this);
SetSeer(target); SetSeer(target);
} }
else else
{ {
//must immediately set seer back otherwise may crash
m_seer = this;
LOG_DEBUG("maps", "Player::CreateViewpoint: Player {} remove seer", GetName()); LOG_DEBUG("maps", "Player::CreateViewpoint: Player {} remove seer", GetName());
if (!RemoveGuidValue(PLAYER_FARSIGHT, target->GetGUID())) if (!RemoveGuidValue(PLAYER_FARSIGHT, target->GetGUID()))
+8 -7
View File
@@ -1986,10 +1986,10 @@ public:
void ProcessTerrainStatusUpdate() override; void ProcessTerrainStatusUpdate() override;
void SendMessageToSet(WorldPacket const* data, bool self) const override { SendMessageToSetInRange(data, GetVisibilityRange(), self); } // pussywizard! void SendMessageToSet(WorldPacket const* data, bool self) const override { SendMessageToSetInRange(data, GetVisibilityRange(), self, true); } // pussywizard!
void SendMessageToSetInRange(WorldPacket const* data, float dist, bool self, Player const* skipped_rcvr = nullptr) const override; // pussywizard! void SendMessageToSetInRange(WorldPacket const* data, float dist, bool self, bool includeMargin = false, Player const* skipped_rcvr = nullptr) const override; // pussywizard!
void SendMessageToSetInRange_OwnTeam(WorldPacket const* data, float dist, bool self) const; // pussywizard! void SendMessageToSetInRange_OwnTeam(WorldPacket const* data, float dist, bool self) const; // pussywizard! param includeMargin not needed here
void SendMessageToSet(WorldPacket const* data, Player const* skipped_rcvr) const override { SendMessageToSetInRange(data, GetVisibilityRange(), skipped_rcvr != this, skipped_rcvr); } // pussywizard! void SendMessageToSet(WorldPacket const* data, Player const* skipped_rcvr) const override { SendMessageToSetInRange(data, GetVisibilityRange(), skipped_rcvr != this, true, skipped_rcvr); } // pussywizard!
void SendTeleportAckPacket(); void SendTeleportAckPacket();
@@ -2342,8 +2342,9 @@ public:
// currently visible objects at player client // currently visible objects at player client
GuidUnorderedSet m_clientGUIDs; GuidUnorderedSet m_clientGUIDs;
std::vector<Unit*> m_newVisible; // pussywizard
[[nodiscard]] bool HaveAtClient(Object const* u) const; [[nodiscard]] bool HaveAtClient(WorldObject const* u) const;
[[nodiscard]] bool HaveAtClient(ObjectGuid guid) const; [[nodiscard]] bool HaveAtClient(ObjectGuid guid) const;
[[nodiscard]] bool IsNeverVisible() const override; [[nodiscard]] bool IsNeverVisible() const override;
@@ -2351,13 +2352,13 @@ public:
bool IsVisibleGloballyFor(Player const* player) const; bool IsVisibleGloballyFor(Player const* player) const;
void GetInitialVisiblePackets(Unit* target); void GetInitialVisiblePackets(Unit* target);
void UpdateObjectVisibility(bool forced = true) override; void UpdateObjectVisibility(bool forced = true, bool fromUpdate = false) override;
void UpdateVisibilityForPlayer(bool mapChange = false); void UpdateVisibilityForPlayer(bool mapChange = false);
void UpdateVisibilityOf(WorldObject* target); void UpdateVisibilityOf(WorldObject* target);
void UpdateTriggerVisibility(); void UpdateTriggerVisibility();
template<class T> template<class T>
void UpdateVisibilityOf(T* target, UpdateData& data, std::set<Unit*>& visibleNow); void UpdateVisibilityOf(T* target, UpdateData& data, std::vector<Unit*>& visibleNow);
uint8 m_forced_speed_changes[MAX_MOVE_TYPE]; uint8 m_forced_speed_changes[MAX_MOVE_TYPE];
@@ -412,6 +412,14 @@ void Player::Update(uint32 p_time)
SetHasDelayedTeleport(false); SetHasDelayedTeleport(false);
TeleportTo(teleportStore_dest, teleportStore_options); TeleportTo(teleportStore_dest, teleportStore_options);
} }
if (!IsBeingTeleported() && bRequestForcedVisibilityUpdate)
{
bRequestForcedVisibilityUpdate = false;
UpdateObjectVisibility(true, true);
m_delayed_unit_relocation_timer = 0;
RemoveFromNotify(NOTIFY_VISIBILITY_CHANGED);
}
} }
void Player::UpdateMirrorTimers() void Player::UpdateMirrorTimers()
@@ -1521,11 +1529,17 @@ void Player::UpdatePotionCooldown(Spell* spell)
SetLastPotionId(0); SetLastPotionId(0);
} }
template void Player::UpdateVisibilityOf(Player* target, UpdateData& data, std::set<Unit*>& visibleNow); template void Player::UpdateVisibilityOf(Player* target, UpdateData& data,
template void Player::UpdateVisibilityOf(Creature* target, UpdateData& data, std::set<Unit*>& visibleNow); std::vector<Unit*>& visibleNow);
template void Player::UpdateVisibilityOf(Corpse* target, UpdateData& data, std::set<Unit*>& visibleNow); template void Player::UpdateVisibilityOf(Creature* target, UpdateData& data,
template void Player::UpdateVisibilityOf(GameObject* target, UpdateData& data, std::set<Unit*>& visibleNow); std::vector<Unit*>& visibleNow);
template void Player::UpdateVisibilityOf(DynamicObject* target, UpdateData& data, std::set<Unit*>& visibleNow); template void Player::UpdateVisibilityOf(Corpse* target, UpdateData& data,
std::vector<Unit*>& visibleNow);
template void Player::UpdateVisibilityOf(GameObject* target, UpdateData& data,
std::vector<Unit*>& visibleNow);
template void Player::UpdateVisibilityOf(DynamicObject* target,
UpdateData& data,
std::vector<Unit*>& visibleNow);
void Player::UpdateVisibilityForPlayer(bool mapChange) void Player::UpdateVisibilityForPlayer(bool mapChange)
{ {
@@ -1536,13 +1550,23 @@ void Player::UpdateVisibilityForPlayer(bool mapChange)
m_seer = this; m_seer = this;
} }
// updates visibility of all objects around point of view for current player Acore::VisibleNotifier notifierNoLarge(
Acore::VisibleNotifier notifier(*this); *this, mapChange,
Cell::VisitAllObjects(m_seer, notifier, GetSightRange()); false); // visit only objects which are not large; default distance
notifier.SendToSelf(); // send gathered data Cell::VisitAllObjects(m_seer, notifierNoLarge,
GetSightRange() + VISIBILITY_INC_FOR_GOBJECTS);
notifierNoLarge.SendToSelf();
Acore::VisibleNotifier notifierLarge(
*this, mapChange, true); // visit only large objects; maximum distance
Cell::VisitAllObjects(m_seer, notifierLarge, GetSightRange());
notifierLarge.SendToSelf();
if (mapChange)
m_last_notify_position.Relocate(-5000.0f, -5000.0f, -5000.0f, 0.0f);
} }
void Player::UpdateObjectVisibility(bool forced) void Player::UpdateObjectVisibility(bool forced, bool fromUpdate)
{ {
// Prevent updating visibility if player is not in world (example: LoadFromDB sets drunkstate which updates invisibility while player is not in map) // Prevent updating visibility if player is not in world (example: LoadFromDB sets drunkstate which updates invisibility while player is not in map)
if (!IsInWorld()) if (!IsInWorld())
@@ -1552,19 +1576,26 @@ void Player::UpdateObjectVisibility(bool forced)
AddToNotify(NOTIFY_VISIBILITY_CHANGED); AddToNotify(NOTIFY_VISIBILITY_CHANGED);
else if (!isBeingLoaded()) else if (!isBeingLoaded())
{ {
if (!fromUpdate) // pussywizard:
{
bRequestForcedVisibilityUpdate = true;
return;
}
Unit::UpdateObjectVisibility(true); Unit::UpdateObjectVisibility(true);
UpdateVisibilityForPlayer(); UpdateVisibilityForPlayer();
} }
} }
template <class T> template <class T>
inline void UpdateVisibilityOf_helper(GuidUnorderedSet& s64, T* target, std::set<Unit*>& /*v*/) inline void UpdateVisibilityOf_helper(GuidUnorderedSet& s64, T* target,
std::vector<Unit*>& /*v*/)
{ {
s64.insert(target->GetGUID()); s64.insert(target->GetGUID());
} }
template <> template <>
inline void UpdateVisibilityOf_helper(GuidUnorderedSet& s64, GameObject* target, std::set<Unit*>& /*v*/) inline void UpdateVisibilityOf_helper(GuidUnorderedSet& s64, GameObject* target,
std::vector<Unit*>& /*v*/)
{ {
// @HACK: This is to prevent objects like deeprun tram from disappearing // @HACK: This is to prevent objects like deeprun tram from disappearing
// when player moves far from its spawn point while riding it // when player moves far from its spawn point while riding it
@@ -1573,17 +1604,19 @@ inline void UpdateVisibilityOf_helper(GuidUnorderedSet& s64, GameObject* target,
} }
template <> template <>
inline void UpdateVisibilityOf_helper(GuidUnorderedSet& s64, Creature* target, std::set<Unit*>& v) inline void UpdateVisibilityOf_helper(GuidUnorderedSet& s64, Creature* target,
std::vector<Unit*>& v)
{ {
s64.insert(target->GetGUID()); s64.insert(target->GetGUID());
v.insert(target); v.push_back(target);
} }
template <> template <>
inline void UpdateVisibilityOf_helper(GuidUnorderedSet& s64, Player* target, std::set<Unit*>& v) inline void UpdateVisibilityOf_helper(GuidUnorderedSet& s64, Player* target,
std::vector<Unit*>& v)
{ {
s64.insert(target->GetGUID()); s64.insert(target->GetGUID());
v.insert(target); v.push_back(target);
} }
template <class T> template <class T>
@@ -1599,7 +1632,8 @@ inline void BeforeVisibilityDestroy<Creature>(Creature* t, Player* p)
} }
template <class T> template <class T>
void Player::UpdateVisibilityOf(T* target, UpdateData& data, std::set<Unit*>& visibleNow) void Player::UpdateVisibilityOf(T* target, UpdateData& data,
std::vector<Unit*>& visibleNow)
{ {
if (HaveAtClient(target)) if (HaveAtClient(target))
{ {
@@ -32,7 +32,7 @@
#include "World.h" #include "World.h"
#include "WorldModel.h" #include "WorldModel.h"
MotionTransport::MotionTransport() : Transport(), _transportInfo(nullptr), _isMoving(true), _pendingStop(false), _triggeredArrivalEvent(false), _triggeredDepartureEvent(false), _delayedTeleport(false) MotionTransport::MotionTransport() : Transport(), _transportInfo(nullptr), _isMoving(true), _pendingStop(false), _triggeredArrivalEvent(false), _triggeredDepartureEvent(false), _passengersLoaded(false), _delayedTeleport(false)
{ {
m_updateFlag = UPDATEFLAG_TRANSPORT | UPDATEFLAG_LOWGUID | UPDATEFLAG_STATIONARY_POSITION | UPDATEFLAG_ROTATION; m_updateFlag = UPDATEFLAG_TRANSPORT | UPDATEFLAG_LOWGUID | UPDATEFLAG_STATIONARY_POSITION | UPDATEFLAG_ROTATION;
} }
@@ -230,14 +230,8 @@ void MotionTransport::Update(uint32 diff)
3. transport moves from active to inactive grid 3. transport moves from active to inactive grid
4. the grid that transport is currently in unloads 4. the grid that transport is currently in unloads
*/ */
bool gridActive = GetMap()->IsGridLoaded(GetPositionX(), GetPositionY()); if (_staticPassengers.empty() && GetMap()->IsGridLoaded(GetPositionX(), GetPositionY())) // 2.
if (_staticPassengers.empty() && gridActive) // 2.
LoadStaticPassengers(); LoadStaticPassengers();
else if (!_staticPassengers.empty() && !gridActive)
// 4. - if transports stopped on grid edge, some passengers can remain in active grids
// unload all static passengers otherwise passengers won't load correctly when the grid that transport is currently in becomes active
UnloadStaticPassengers();
} }
} }
@@ -254,27 +248,18 @@ void MotionTransport::DelayedUpdate(uint32 /*diff*/)
void MotionTransport::UpdatePosition(float x, float y, float z, float o) void MotionTransport::UpdatePosition(float x, float y, float z, float o)
{ {
bool newActive = GetMap()->IsGridLoaded(x, y); if (!GetMap()->IsGridLoaded(x, y)) // pussywizard: should not happen, but just in case
Cell oldCell(GetPositionX(), GetPositionY()); GetMap()->LoadGrid(x, y);
Relocate(x, y, z, o); Relocate(x, y, z, o);
UpdateModelPosition(); UpdateModelPosition();
UpdatePassengerPositions(_passengers); UpdatePassengerPositions(_passengers);
/* There are four possible scenarios that trigger loading/unloading passengers: if (_staticPassengers.empty())
1. transport moves from inactive to active grid
2. the grid that transport is currently in becomes active
3. transport moves from active to inactive grid
4. the grid that transport is currently in unloads
*/
if (_staticPassengers.empty() && newActive) // 1.
LoadStaticPassengers(); LoadStaticPassengers();
else if (!_staticPassengers.empty() && !newActive && oldCell.DiffGrid(Cell(GetPositionX(), GetPositionY()))) // 3.
UnloadStaticPassengers();
else else
UpdatePassengerPositions(_staticPassengers); UpdatePassengerPositions(_staticPassengers);
// 4. is handed by grid unload
} }
void MotionTransport::AddPassenger(WorldObject* passenger, bool withAll) void MotionTransport::AddPassenger(WorldObject* passenger, bool withAll)
@@ -321,7 +306,8 @@ void MotionTransport::RemovePassenger(WorldObject* passenger, bool withAll)
{ {
passenger->SetTransport(nullptr); passenger->SetTransport(nullptr);
passenger->m_movementInfo.flags &= ~MOVEMENTFLAG_ONTRANSPORT; passenger->m_movementInfo.flags &= ~MOVEMENTFLAG_ONTRANSPORT;
passenger->m_movementInfo.transport.Reset(); passenger->m_movementInfo.transport.guid.Clear();
passenger->m_movementInfo.transport.pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f);
if (passenger->ToUnit()) if (passenger->ToUnit())
{ {
passenger->ToUnit()->ClearUnitState(UNIT_STATE_IGNORE_PATHFINDING); passenger->ToUnit()->ClearUnitState(UNIT_STATE_IGNORE_PATHFINDING);
@@ -421,6 +407,9 @@ GameObject* MotionTransport::CreateGOPassenger(ObjectGuid::LowType guid, GameObj
void MotionTransport::LoadStaticPassengers() void MotionTransport::LoadStaticPassengers()
{ {
if (PassengersLoaded())
return;
SetPassengersLoaded(true);
if (uint32 mapId = GetGOInfo()->moTransport.mapID) if (uint32 mapId = GetGOInfo()->moTransport.mapID)
{ {
CellObjectGuidsMap const& cells = sObjectMgr->GetMapObjectGuids(mapId, GetMap()->GetSpawnMode()); CellObjectGuidsMap const& cells = sObjectMgr->GetMapObjectGuids(mapId, GetMap()->GetSpawnMode());
@@ -442,6 +431,7 @@ void MotionTransport::LoadStaticPassengers()
void MotionTransport::UnloadStaticPassengers() void MotionTransport::UnloadStaticPassengers()
{ {
SetPassengersLoaded(false);
while (!_staticPassengers.empty()) while (!_staticPassengers.empty())
{ {
WorldObject* obj = *_staticPassengers.begin(); WorldObject* obj = *_staticPassengers.begin();
@@ -552,19 +542,11 @@ void MotionTransport::DelayedTeleportTransport()
_delayedTeleport = false; _delayedTeleport = false;
uint32 newMapId = _nextFrame->Node->mapid; uint32 newMapId = _nextFrame->Node->mapid;
Map* newMap = sMapMgr->CreateBaseMap(newMapId);
GetMap()->RemoveFromMap<MotionTransport>(this, false);
float x = _nextFrame->Node->x, float x = _nextFrame->Node->x,
y = _nextFrame->Node->y, y = _nextFrame->Node->y,
z = _nextFrame->Node->z, z = _nextFrame->Node->z,
o = _nextFrame->InitialOrientation; o = _nextFrame->InitialOrientation;
if (!newMap->IsGridLoaded(x, y) && !_passengers.empty())
newMap->LoadGrid(x, y); // xinef: load before adding passengers to new map
SetMap(newMap);
PassengerSet _passengersCopy = _passengers; PassengerSet _passengersCopy = _passengers;
for (PassengerSet::iterator itr = _passengersCopy.begin(); itr != _passengersCopy.end(); ) for (PassengerSet::iterator itr = _passengersCopy.begin(); itr != _passengersCopy.end(); )
{ {
@@ -610,8 +592,15 @@ void MotionTransport::DelayedTeleportTransport()
} }
} }
Map* newMap = sMapMgr->CreateBaseMap(newMapId);
GetMap()->RemoveFromMap<MotionTransport>(this, false);
newMap->LoadGrid(x, y); // xinef: load before adding passengers to new map
SetMap(newMap);
Relocate(x, y, z, o); Relocate(x, y, z, o);
GetMap()->AddToMap<MotionTransport>(this); GetMap()->AddToMap<MotionTransport>(this);
LoadStaticPassengers();
} }
void MotionTransport::UpdatePassengerPositions(PassengerSet& passengers) void MotionTransport::UpdatePassengerPositions(PassengerSet& passengers)
@@ -642,7 +631,7 @@ void MotionTransport::UpdatePassengerPositions(PassengerSet& passengers)
case TYPEID_UNIT: case TYPEID_UNIT:
{ {
Creature* creature = passenger->ToCreature(); Creature* creature = passenger->ToCreature();
GetMap()->CreatureRelocation(creature, x, y, z, o, false); GetMap()->CreatureRelocation(creature, x, y, z, o);
creature->GetTransportHomePosition(x, y, z, o); creature->GetTransportHomePosition(x, y, z, o);
CalculatePassengerPosition(x, y, z, &o); CalculatePassengerPosition(x, y, z, &o);
@@ -654,7 +643,7 @@ void MotionTransport::UpdatePassengerPositions(PassengerSet& passengers)
GetMap()->PlayerRelocation(passenger->ToPlayer(), x, y, z, o); GetMap()->PlayerRelocation(passenger->ToPlayer(), x, y, z, o);
break; break;
case TYPEID_GAMEOBJECT: case TYPEID_GAMEOBJECT:
GetMap()->GameObjectRelocation(passenger->ToGameObject(), x, y, z, o, false); GetMap()->GameObjectRelocation(passenger->ToGameObject(), x, y, z, o);
break; break;
case TYPEID_DYNAMICOBJECT: case TYPEID_DYNAMICOBJECT:
GetMap()->DynamicObjectRelocation(passenger->ToDynObject(), x, y, z, o); GetMap()->DynamicObjectRelocation(passenger->ToDynObject(), x, y, z, o);
@@ -791,6 +780,7 @@ bool StaticTransport::Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* m
LastUsedScriptID = GetGOInfo()->ScriptId; LastUsedScriptID = GetGOInfo()->ScriptId;
AIM_Initialize(); AIM_Initialize();
this->setActive(true);
return true; return true;
} }
@@ -925,8 +915,7 @@ void StaticTransport::UpdatePosition(float x, float y, float z, float o)
if (!GetMap()->IsGridLoaded(x, y)) // pussywizard: should not happen, but just in case if (!GetMap()->IsGridLoaded(x, y)) // pussywizard: should not happen, but just in case
GetMap()->LoadGrid(x, y); GetMap()->LoadGrid(x, y);
Relocate(x, y, z, o); GetMap()->GameObjectRelocation(this, x, y, z, o); // this also relocates the model
UpdateModelPosition();
UpdatePassengerPositions(); UpdatePassengerPositions();
} }
@@ -953,14 +942,17 @@ void StaticTransport::UpdatePassengerPositions()
switch (passenger->GetTypeId()) switch (passenger->GetTypeId())
{ {
case TYPEID_UNIT: case TYPEID_UNIT:
GetMap()->CreatureRelocation(passenger->ToCreature(), x, y, z, o, false); GetMap()->CreatureRelocation(passenger->ToCreature(), x, y, z, o);
break; break;
case TYPEID_PLAYER: case TYPEID_PLAYER:
if (passenger->IsInWorld()) if (passenger->IsInWorld())
{
GetMap()->PlayerRelocation(passenger->ToPlayer(), x, y, z, o); GetMap()->PlayerRelocation(passenger->ToPlayer(), x, y, z, o);
passenger->ToPlayer()->SetFallInformation(GameTime::GetGameTime().count(), z);
}
break; break;
case TYPEID_GAMEOBJECT: case TYPEID_GAMEOBJECT:
GetMap()->GameObjectRelocation(passenger->ToGameObject(), x, y, z, o, false); GetMap()->GameObjectRelocation(passenger->ToGameObject(), x, y, z, o);
break; break;
case TYPEID_DYNAMICOBJECT: case TYPEID_DYNAMICOBJECT:
GetMap()->DynamicObjectRelocation(passenger->ToDynObject(), x, y, z, o); GetMap()->DynamicObjectRelocation(passenger->ToDynObject(), x, y, z, o);
@@ -1009,7 +1001,8 @@ void StaticTransport::RemovePassenger(WorldObject* passenger, bool withAll)
{ {
passenger->SetTransport(nullptr); passenger->SetTransport(nullptr);
passenger->m_movementInfo.flags &= ~MOVEMENTFLAG_ONTRANSPORT; passenger->m_movementInfo.flags &= ~MOVEMENTFLAG_ONTRANSPORT;
passenger->m_movementInfo.transport.Reset(); passenger->m_movementInfo.transport.guid.Clear();
passenger->m_movementInfo.transport.pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f);
} }
} }
} }
@@ -68,6 +68,8 @@ public:
PassengerSet const& GetStaticPassengers() const { return _staticPassengers; } PassengerSet const& GetStaticPassengers() const { return _staticPassengers; }
void UnloadStaticPassengers(); void UnloadStaticPassengers();
void UnloadNonStaticPassengers(); void UnloadNonStaticPassengers();
void SetPassengersLoaded(bool loaded) { _passengersLoaded = loaded; }
bool PassengersLoaded() const { return _passengersLoaded; }
KeyFrameVec const& GetKeyFrames() const { return _transportInfo->keyFrames; } KeyFrameVec const& GetKeyFrames() const { return _transportInfo->keyFrames; }
void EnableMovement(bool enabled); void EnableMovement(bool enabled);
@@ -102,6 +104,7 @@ private:
PassengerSet _staticPassengers; PassengerSet _staticPassengers;
mutable std::mutex Lock; mutable std::mutex Lock;
bool _passengersLoaded;
bool _delayedTeleport; bool _delayedTeleport;
}; };
+185 -43
View File
@@ -32,6 +32,7 @@
#include "CreatureAIImpl.h" #include "CreatureAIImpl.h"
#include "CreatureGroups.h" #include "CreatureGroups.h"
#include "DisableMgr.h" #include "DisableMgr.h"
#include "DynamicVisibility.h"
#include "Formulas.h" #include "Formulas.h"
#include "GameObjectAI.h" #include "GameObjectAI.h"
#include "GameTime.h" #include "GameTime.h"
@@ -43,7 +44,6 @@
#include "MoveSpline.h" #include "MoveSpline.h"
#include "MoveSplineInit.h" #include "MoveSplineInit.h"
#include "MovementGenerator.h" #include "MovementGenerator.h"
#include "MovementPacketBuilder.h"
#include "ObjectAccessor.h" #include "ObjectAccessor.h"
#include "ObjectMgr.h" #include "ObjectMgr.h"
#include "Opcodes.h" #include "Opcodes.h"
@@ -317,6 +317,12 @@ Unit::Unit(bool isWorldObject) : WorldObject(isWorldObject),
m_serverSideVisibility.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_ALIVE); m_serverSideVisibility.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_ALIVE);
m_last_notify_position.Relocate(-5000.0f, -5000.0f, -5000.0f, 0.0f);
m_last_notify_mstime = 0;
m_delayed_unit_relocation_timer = 0;
m_delayed_unit_ai_notify_timer = 0;
bRequestForcedVisibilityUpdate = false;
m_applyResilience = false; m_applyResilience = false;
_instantCast = false; _instantCast = false;
@@ -405,6 +411,32 @@ void Unit::Update(uint32 p_time)
if (!IsInWorld()) if (!IsInWorld())
return; return;
// pussywizard:
if (GetTypeId() != TYPEID_PLAYER || (!ToPlayer()->IsBeingTeleported() && !bRequestForcedVisibilityUpdate))
{
if (m_delayed_unit_relocation_timer)
{
if (m_delayed_unit_relocation_timer <= p_time)
{
m_delayed_unit_relocation_timer = 0;
//ExecuteDelayedUnitRelocationEvent();
FindMap()->i_objectsForDelayedVisibility.insert(this);
}
else
m_delayed_unit_relocation_timer -= p_time;
}
if (m_delayed_unit_ai_notify_timer)
{
if (m_delayed_unit_ai_notify_timer <= p_time)
{
m_delayed_unit_ai_notify_timer = 0;
ExecuteDelayedUnitAINotifyEvent();
}
else
m_delayed_unit_ai_notify_timer -= p_time;
}
}
_UpdateSpells( p_time ); _UpdateSpells( p_time );
if (CanHaveThreatList() && GetThreatMgr().isNeedUpdateToClient(p_time)) if (CanHaveThreatList() && GetThreatMgr().isNeedUpdateToClient(p_time))
@@ -568,27 +600,14 @@ void Unit::UpdateSplineMovement(uint32 t_diff)
SplineHandler handler(this); SplineHandler handler(this);
movespline->updateState(t_diff, handler); movespline->updateState(t_diff, handler);
// Xinef: Spline was cleared by StopMoving, return // Xinef: Spline was cleared by StopMoving, return
if (!movespline->Initialized()) { if (!movespline->Initialized())
{
DisableSpline(); DisableSpline();
return; return;
} }
bool arrived = movespline->Finalized(); bool arrived = movespline->Finalized();
if (movespline->isCyclic())
{
m_splineSyncTimer.Update(t_diff);
if (m_splineSyncTimer.Passed())
{
m_splineSyncTimer.Reset(5000); // Retail value, do not change
WorldPacket data(SMSG_FLIGHT_SPLINE_SYNC, 4 + GetPackGUID().size());
Movement::PacketBuilder::WriteSplineSync(*movespline, data);
data.appendPackGUID(GetGUID());
SendMessageToSet(&data, true);
}
}
if (arrived) if (arrived)
{ {
DisableSpline(); DisableSpline();
@@ -597,11 +616,17 @@ void Unit::UpdateSplineMovement(uint32 t_diff)
SetByteValue(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_ANIM_TIER, movespline->GetAnimationType()); SetByteValue(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_ANIM_TIER, movespline->GetAnimationType());
} }
// pussywizard: update always! not every 400ms, because movement generators need the actual position
//m_movesplineTimer.Update(t_diff);
//if (m_movesplineTimer.Passed() || arrived)
UpdateSplinePosition(); UpdateSplinePosition();
} }
void Unit::UpdateSplinePosition() void Unit::UpdateSplinePosition()
{ {
//static uint32 const positionUpdateDelay = 400;
//m_movesplineTimer.Reset(positionUpdateDelay);
Movement::Location loc = movespline->ComputePosition(); Movement::Location loc = movespline->ComputePosition();
if (movespline->onTransport) if (movespline->onTransport)
@@ -614,14 +639,16 @@ void Unit::UpdateSplinePosition()
if (TransportBase* transport = GetDirectTransport()) if (TransportBase* transport = GetDirectTransport())
transport->CalculatePassengerPosition(loc.x, loc.y, loc.z, &loc.orientation); transport->CalculatePassengerPosition(loc.x, loc.y, loc.z, &loc.orientation);
else
return;
} }
if (HasUnitState(UNIT_STATE_CANNOT_TURN)) // Xinef: if we had spline running update orientation along with position
loc.orientation = GetOrientation(); //if (HasUnitState(UNIT_STATE_CANNOT_TURN))
// loc.orientation = GetOrientation();
if (GetTypeId() == TYPEID_PLAYER)
UpdatePosition(loc.x, loc.y, loc.z, loc.orientation); UpdatePosition(loc.x, loc.y, loc.z, loc.orientation);
else
ToCreature()->SetPosition(loc.x, loc.y, loc.z, loc.orientation);
} }
void Unit::DisableSpline() void Unit::DisableSpline()
@@ -15714,9 +15741,15 @@ void Unit::CleanupBeforeRemoveFromMap(bool finalCleanup)
void Unit::CleanupsBeforeDelete(bool finalCleanup) void Unit::CleanupsBeforeDelete(bool finalCleanup)
{ {
CleanupBeforeRemoveFromMap(finalCleanup); if (GetTransport())
{
GetTransport()->RemovePassenger(this);
SetTransport(nullptr);
m_movementInfo.transport.Reset();
m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
}
WorldObject::CleanupsBeforeDelete(finalCleanup); CleanupBeforeRemoveFromMap(finalCleanup);
} }
void Unit::UpdateCharmAI() void Unit::UpdateCharmAI()
@@ -17489,17 +17522,13 @@ void Unit::SetContestedPvP(Player* attackedPlayer, bool lookForNearContestedGuar
player->AddUnitState(UNIT_STATE_ATTACK_PLAYER); player->AddUnitState(UNIT_STATE_ATTACK_PLAYER);
player->SetPlayerFlag(PLAYER_FLAGS_CONTESTED_PVP); player->SetPlayerFlag(PLAYER_FLAGS_CONTESTED_PVP);
// call MoveInLineOfSight for nearby contested guards // call MoveInLineOfSight for nearby contested guards
Acore::AIRelocationNotifier notifier(*this); AddToNotify(NOTIFY_AI_RELOCATION);
Cell::VisitWorldObjects(this, notifier, GetVisibilityRange());
} }
for (Unit* unit : m_Controlled) if (!HasUnitState(UNIT_STATE_ATTACK_PLAYER))
{ {
if (!unit->HasUnitState(UNIT_STATE_ATTACK_PLAYER)) AddUnitState(UNIT_STATE_ATTACK_PLAYER);
{ // call MoveInLineOfSight for nearby contested guards
unit->AddUnitState(UNIT_STATE_ATTACK_PLAYER); AddToNotify(NOTIFY_AI_RELOCATION);
Acore::AIRelocationNotifier notifier(*unit);
Cell::VisitWorldObjects(this, notifier, GetVisibilityRange());
}
} }
} }
@@ -19346,7 +19375,7 @@ void Unit::SetPhaseMask(uint32 newPhaseMask, bool update)
} }
} }
void Unit::UpdateObjectVisibility(bool forced) void Unit::UpdateObjectVisibility(bool forced, bool /*fromUpdate*/)
{ {
if (!forced) if (!forced)
AddToNotify(NOTIFY_VISIBILITY_CHANGED); AddToNotify(NOTIFY_VISIBILITY_CHANGED);
@@ -19354,7 +19383,8 @@ void Unit::UpdateObjectVisibility(bool forced)
{ {
WorldObject::UpdateObjectVisibility(true); WorldObject::UpdateObjectVisibility(true);
Acore::AIRelocationNotifier notifier(*this); Acore::AIRelocationNotifier notifier(*this);
Cell::VisitAllObjects(this, notifier, GetVisibilityRange()); float radius = 60.0f;
Cell::VisitAllObjects(this, notifier, radius);
} }
} }
@@ -20252,14 +20282,10 @@ bool Unit::UpdatePosition(float x, float y, float z, float orientation, bool tel
if (!Acore::IsValidMapCoord(x, y, z, orientation)) if (!Acore::IsValidMapCoord(x, y, z, orientation))
return false; return false;
// Check if angular distance changed float old_orientation = GetOrientation();
bool const turn = G3D::fuzzyGt(M_PI - fabs(fabs(GetOrientation() - orientation) - M_PI), 0.0f); float current_z = GetPositionZ();
bool turn = (old_orientation != orientation);
// G3D::fuzzyEq won't help here, in some cases magnitudes differ by a little more than G3D::eps, but should be considered equal bool relocated = (teleport || GetPositionX() != x || GetPositionY() != y || current_z != z);
bool const relocated = (teleport ||
std::fabs(GetPositionX() - x) > 0.001f ||
std::fabs(GetPositionY() - y) > 0.001f ||
std::fabs(GetPositionZ() - z) > 0.001f);
if (!GetVehicle()) if (!GetVehicle())
{ {
@@ -20285,8 +20311,6 @@ bool Unit::UpdatePosition(float x, float y, float z, float orientation, bool tel
UpdateObjectVisibility(false); UpdateObjectVisibility(false);
} }
UpdatePositionData();
return (relocated || turn); return (relocated || turn);
} }
@@ -20717,6 +20741,124 @@ bool ConflagrateAuraStateDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time
return true; return true;
} }
void Unit::ExecuteDelayedUnitRelocationEvent()
{
this->RemoveFromNotify(NOTIFY_VISIBILITY_CHANGED);
if (!this->IsInWorld() || this->IsDuringRemoveFromWorld())
return;
if (this->HasSharedVision())
for (SharedVisionList::const_iterator itr = this->GetSharedVisionList().begin(); itr != this->GetSharedVisionList().end(); ++itr)
if (Player* player = (*itr))
{
if (player->IsOnVehicle(this) || !player->IsInWorld() || player->IsDuringRemoveFromWorld()) // players on vehicles have their own event executed (due to passenger relocation)
continue;
WorldObject* viewPoint = player;
if (player->m_seer && player->m_seer->IsInWorld())
viewPoint = player->m_seer;
if (!viewPoint->IsPositionValid() || !player->IsPositionValid())
continue;
if (Unit* active = viewPoint->ToUnit())
{
//if (active->IsVehicle()) // always check original unit here, last notify position is not relocated
// active = player;
float dx = active->m_last_notify_position.GetPositionX() - active->GetPositionX();
float dy = active->m_last_notify_position.GetPositionY() - active->GetPositionY();
float dz = active->m_last_notify_position.GetPositionZ() - active->GetPositionZ();
float distsq = dx * dx + dy * dy + dz * dz;
float mindistsq = DynamicVisibilityMgr::GetReqMoveDistSq(active->FindMap()->GetEntry()->map_type);
if (distsq < mindistsq)
continue;
// this will be relocated below sharedvision!
//active->m_last_notify_position.Relocate(active->GetPositionX(), active->GetPositionY(), active->GetPositionZ());
}
Acore::PlayerRelocationNotifier relocateNoLarge(*player, false); // visit only objects which are not large; default distance
Cell::VisitAllObjects(viewPoint, relocateNoLarge, player->GetSightRange() + VISIBILITY_INC_FOR_GOBJECTS);
relocateNoLarge.SendToSelf();
Acore::PlayerRelocationNotifier relocateLarge(*player, true); // visit only large objects; maximum distance
Cell::VisitAllObjects(viewPoint, relocateLarge, MAX_VISIBILITY_DISTANCE);
relocateLarge.SendToSelf();
}
if (Player* player = this->ToPlayer())
{
WorldObject* viewPoint = player;
if (player->m_seer && player->m_seer->IsInWorld())
viewPoint = player->m_seer;
if (viewPoint->GetMapId() != player->GetMapId() || !viewPoint->IsPositionValid() || !player->IsPositionValid())
return;
if (Unit* active = viewPoint->ToUnit())
{
if (active->IsVehicle())
active = player;
if (!player->GetFarSightDistance())
{
float dx = active->m_last_notify_position.GetPositionX() - active->GetPositionX();
float dy = active->m_last_notify_position.GetPositionY() - active->GetPositionY();
float dz = active->m_last_notify_position.GetPositionZ() - active->GetPositionZ();
float distsq = dx * dx + dy * dy + dz * dz;
float mindistsq = DynamicVisibilityMgr::GetReqMoveDistSq(active->FindMap()->GetEntry()->map_type);
if (distsq < mindistsq)
return;
active->m_last_notify_position.Relocate(active->GetPositionX(), active->GetPositionY(), active->GetPositionZ());
}
}
Acore::PlayerRelocationNotifier relocateNoLarge(*player, false); // visit only objects which are not large; default distance
Cell::VisitAllObjects(viewPoint, relocateNoLarge, player->GetSightRange() + VISIBILITY_INC_FOR_GOBJECTS);
relocateNoLarge.SendToSelf();
if (!player->GetFarSightDistance())
{
Acore::PlayerRelocationNotifier relocateLarge(*player, true); // visit only large objects; maximum distance
Cell::VisitAllObjects(viewPoint, relocateLarge, MAX_VISIBILITY_DISTANCE);
relocateLarge.SendToSelf();
}
this->AddToNotify(NOTIFY_AI_RELOCATION);
}
else if (Creature* unit = this->ToCreature())
{
if (!unit->IsPositionValid())
return;
float dx = unit->m_last_notify_position.GetPositionX() - unit->GetPositionX();
float dy = unit->m_last_notify_position.GetPositionY() - unit->GetPositionY();
float dz = unit->m_last_notify_position.GetPositionZ() - unit->GetPositionZ();
float distsq = dx * dx + dy * dy + dz * dz;
float mindistsq = DynamicVisibilityMgr::GetReqMoveDistSq(unit->FindMap()->GetEntry()->map_type);
if (distsq < mindistsq)
return;
unit->m_last_notify_position.Relocate(unit->GetPositionX(), unit->GetPositionY(), unit->GetPositionZ());
Acore::CreatureRelocationNotifier relocate(*unit);
Cell::VisitAllObjects(unit, relocate, unit->GetVisibilityRange() + VISIBILITY_COMPENSATION);
this->AddToNotify(NOTIFY_AI_RELOCATION);
}
}
void Unit::ExecuteDelayedUnitAINotifyEvent()
{
this->RemoveFromNotify(NOTIFY_AI_RELOCATION);
if (!this->IsInWorld() || this->IsDuringRemoveFromWorld())
return;
Acore::AIRelocationNotifier notifier(*this);
float radius = 60.0f;
Cell::VisitAllObjects(this, notifier, radius);
}
void Unit::SetInFront(WorldObject const* target) void Unit::SetInFront(WorldObject const* target)
{ {
if (!HasUnitState(UNIT_STATE_CANNOT_TURN)) if (!HasUnitState(UNIT_STATE_CANNOT_TURN))
+10 -2
View File
@@ -2145,7 +2145,7 @@ public:
// common function for visibility checks for player/creatures with detection code // common function for visibility checks for player/creatures with detection code
[[nodiscard]] uint32 GetPhaseByAuras() const; [[nodiscard]] uint32 GetPhaseByAuras() const;
void SetPhaseMask(uint32 newPhaseMask, bool update) override;// overwrite WorldObject::SetPhaseMask void SetPhaseMask(uint32 newPhaseMask, bool update) override;// overwrite WorldObject::SetPhaseMask
void UpdateObjectVisibility(bool forced = true) override; void UpdateObjectVisibility(bool forced = true, bool fromUpdate = false) override;
SpellImmuneList m_spellImmune[MAX_SPELL_IMMUNITY]; SpellImmuneList m_spellImmune[MAX_SPELL_IMMUNITY];
uint32 m_lastSanctuaryTime; uint32 m_lastSanctuaryTime;
@@ -2419,6 +2419,14 @@ public:
void AddPointedBy(SafeUnitPointer* sup) { SafeUnitPointerSet.insert(sup); } void AddPointedBy(SafeUnitPointer* sup) { SafeUnitPointerSet.insert(sup); }
void RemovePointedBy(SafeUnitPointer* sup) { SafeUnitPointerSet.erase(sup); } void RemovePointedBy(SafeUnitPointer* sup) { SafeUnitPointerSet.erase(sup); }
static void HandleSafeUnitPointersOnDelete(Unit* thisUnit); static void HandleSafeUnitPointersOnDelete(Unit* thisUnit);
// Relocation Nofier optimization
Position m_last_notify_position;
uint32 m_last_notify_mstime;
uint16 m_delayed_unit_relocation_timer;
uint16 m_delayed_unit_ai_notify_timer;
bool bRequestForcedVisibilityUpdate;
void ExecuteDelayedUnitRelocationEvent();
void ExecuteDelayedUnitAINotifyEvent();
// cooldowns // cooldowns
[[nodiscard]] virtual bool HasSpellCooldown(uint32 /*spell_id*/) const { return false; } [[nodiscard]] virtual bool HasSpellCooldown(uint32 /*spell_id*/) const { return false; }
@@ -2577,7 +2585,7 @@ private:
uint32 m_state; // Even derived shouldn't modify uint32 m_state; // Even derived shouldn't modify
uint32 m_CombatTimer; uint32 m_CombatTimer;
uint32 m_lastManaUse; // msecs uint32 m_lastManaUse; // msecs
TimeTrackerSmall m_splineSyncTimer; //TimeTrackerSmall m_movesplineTimer;
Diminishing m_Diminishing; Diminishing m_Diminishing;
// Manage all Units that are threatened by us // Manage all Units that are threatened by us
@@ -545,7 +545,6 @@ bool Vehicle::IsVehicleInUse()
void Vehicle::TeleportVehicle(float x, float y, float z, float ang) void Vehicle::TeleportVehicle(float x, float y, float z, float ang)
{ {
if (!_me->GetMap()->IsGridLoaded(x, y))
_me->GetMap()->LoadGrid(x, y); _me->GetMap()->LoadGrid(x, y);
_me->NearTeleportTo(x, y, z, ang, true); _me->NearTeleportTo(x, y, z, ang, true);
-6
View File
@@ -96,12 +96,6 @@ public:
visitor.Visit(i_objects); visitor.Visit(i_objects);
} }
template<class T>
uint32 GetWorldObjectCountInGrid() const
{
return i_objects.template Count<T>();
}
/** Inserts a container type object into the grid. /** Inserts a container type object into the grid.
*/ */
template<class SPECIFIC_OBJECT> void AddGridObject(SPECIFIC_OBJECT* obj) template<class SPECIFIC_OBJECT> void AddGridObject(SPECIFIC_OBJECT* obj)
-65
View File
@@ -1,65 +0,0 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "GridStates.h"
#include "GridNotifiers.h"
#include "Log.h"
#include "Map.h"
#include "ObjectGridLoader.h"
void InvalidState::Update(Map&, NGridType&, GridInfo&, uint32) const
{
}
void ActiveState::Update(Map& map, NGridType& grid, GridInfo& info, uint32 diff) const
{
// Only check grid activity every (grid_expiry/10) ms, because it's really useless to do it every cycle
info.UpdateTimeTracker(diff);
if (info.getTimeTracker().Passed())
{
if (!grid.GetWorldObjectCountInNGrid<Player>() && !map.ActiveObjectsNearGrid(grid))
{
ObjectGridStoper worker;
TypeContainerVisitor<ObjectGridStoper, GridTypeMapContainer> visitor(worker);
grid.VisitAllGrids(visitor);
grid.SetGridState(GRID_STATE_IDLE);
LOG_DEBUG("maps", "Grid[{}, {}] on map {} moved to IDLE state", grid.getX(), grid.getY(), map.GetId());
}
else
map.ResetGridExpiry(grid, 0.1f);
}
}
void IdleState::Update(Map& map, NGridType& grid, GridInfo&, uint32) const
{
map.ResetGridExpiry(grid);
grid.SetGridState(GRID_STATE_REMOVAL);
LOG_DEBUG("maps", "Grid[{}, {}] on map {} moved to REMOVAL state", grid.getX(), grid.getY(), map.GetId());
}
void RemovalState::Update(Map& map, NGridType& grid, GridInfo& info, uint32 diff) const
{
if (!info.getUnloadLock())
{
info.UpdateTimeTracker(diff);
if (info.getTimeTracker().Passed() && !map.UnloadGrid(grid, false))
{
LOG_DEBUG("maps", "Grid[{}, {}] for map {} differed unloading due to players or active objects nearby", grid.getX(), grid.getY(), map.GetId());
map.ResetGridExpiry(grid);
}
}
}
-56
View File
@@ -1,56 +0,0 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ACORE_GRIDSTATES_H
#define ACORE_GRIDSTATES_H
#include "GridDefines.h"
#include "NGrid.h"
class Map;
class AC_GAME_API GridState
{
public:
virtual ~GridState() { };
virtual void Update(Map &, NGridType&, GridInfo &, uint32 t_diff) const = 0;
};
class AC_GAME_API InvalidState : public GridState
{
public:
void Update(Map &, NGridType &, GridInfo &, uint32 t_diff) const override;
};
class AC_GAME_API ActiveState : public GridState
{
public:
void Update(Map &, NGridType &, GridInfo &, uint32 t_diff) const override;
};
class AC_GAME_API IdleState : public GridState
{
public:
void Update(Map &, NGridType &, GridInfo &, uint32 t_diff) const override;
};
class AC_GAME_API RemovalState : public GridState
{
public:
void Update(Map &, NGridType &, GridInfo &, uint32 t_diff) const override;
};
#endif
+4 -65
View File
@@ -26,42 +26,6 @@
#include "Timer.h" #include "Timer.h"
#include "Util.h" #include "Util.h"
#define DEFAULT_VISIBILITY_NOTIFY_PERIOD 1000
class AC_GAME_API GridInfo
{
public:
GridInfo();
GridInfo(time_t expiry, bool unload = true);
TimeTracker const& getTimeTracker() const { return i_timer; }
bool getUnloadLock() const { return i_unloadActiveLockCount || i_unloadExplicitLock || i_unloadReferenceLock; }
void setUnloadExplicitLock(bool on) { i_unloadExplicitLock = on; }
void setUnloadReferenceLock(bool on) { i_unloadReferenceLock = on; }
void incUnloadActiveLock() { ++i_unloadActiveLockCount; }
void decUnloadActiveLock() { if (i_unloadActiveLockCount) --i_unloadActiveLockCount; }
void setTimer(TimeTracker const& pTimer) { i_timer = pTimer; }
void ResetTimeTracker(time_t interval) { i_timer.Reset(interval); }
void UpdateTimeTracker(time_t diff) { i_timer.Update(diff); }
PeriodicTimer& getRelocationTimer() { return vis_Update; }
private:
TimeTracker i_timer;
PeriodicTimer vis_Update;
uint16 i_unloadActiveLockCount : 16; // lock from active object spawn points (prevent clone loading)
bool i_unloadExplicitLock : 1; // explicit manual lock or config setting
bool i_unloadReferenceLock : 1; // lock from instance map copy
};
typedef enum
{
GRID_STATE_INVALID = 0,
GRID_STATE_ACTIVE = 1,
GRID_STATE_IDLE = 2,
GRID_STATE_REMOVAL = 3,
MAX_GRID_STATE = 4
} grid_state_t;
template template
< <
uint32 N, uint32 N,
@@ -73,10 +37,10 @@ class NGrid
{ {
public: public:
typedef Grid<ACTIVE_OBJECT, WORLD_OBJECT_TYPES, GRID_OBJECT_TYPES> GridType; typedef Grid<ACTIVE_OBJECT, WORLD_OBJECT_TYPES, GRID_OBJECT_TYPES> GridType;
NGrid(uint32 id, int32 x, int32 y, time_t expiry, bool unload = true) : NGrid(uint32 id, int32 x, int32 y)
i_gridId(id), i_GridInfo(GridInfo(expiry, unload)), i_x(x), i_y(y), : i_gridId(id), i_x(x), i_y(y), i_GridObjectDataLoaded(false)
i_cellstate(GRID_STATE_INVALID), i_GridObjectDataLoaded(false) {
{ } }
GridType& GetGridType(const uint32 x, const uint32 y) GridType& GetGridType(const uint32 x, const uint32 y)
{ {
@@ -91,9 +55,6 @@ public:
} }
[[nodiscard]] uint32 GetGridId() const { return i_gridId; } [[nodiscard]] uint32 GetGridId() const { return i_gridId; }
void SetGridId(uint32 id) { i_gridId = id; }
[[nodiscard]] grid_state_t GetGridState() const { return i_cellstate; }
void SetGridState(grid_state_t s) { i_cellstate = s; }
[[nodiscard]] int32 getX() const { return i_x; } [[nodiscard]] int32 getX() const { return i_x; }
[[nodiscard]] int32 getY() const { return i_y; } [[nodiscard]] int32 getY() const { return i_y; }
@@ -104,16 +65,6 @@ public:
[[nodiscard]] bool isGridObjectDataLoaded() const { return i_GridObjectDataLoaded; } [[nodiscard]] bool isGridObjectDataLoaded() const { return i_GridObjectDataLoaded; }
void setGridObjectDataLoaded(bool pLoaded) { i_GridObjectDataLoaded = pLoaded; } void setGridObjectDataLoaded(bool pLoaded) { i_GridObjectDataLoaded = pLoaded; }
GridInfo* getGridInfoRef() { return &i_GridInfo; }
TimeTracker const& getTimeTracker() const { return i_GridInfo.getTimeTracker(); }
bool getUnloadLock() const { return i_GridInfo.getUnloadLock(); }
void setUnloadExplicitLock(bool on) { i_GridInfo.setUnloadExplicitLock(on); }
void setUnloadReferenceLock(bool on) { i_GridInfo.setUnloadReferenceLock(on); }
void incUnloadActiveLock() { i_GridInfo.incUnloadActiveLock(); }
void decUnloadActiveLock() { i_GridInfo.decUnloadActiveLock(); }
void ResetTimeTracker(time_t interval) { i_GridInfo.ResetTimeTracker(interval); }
void UpdateTimeTracker(time_t diff) { i_GridInfo.UpdateTimeTracker(diff); }
/* /*
template<class SPECIFIC_OBJECT> void AddWorldObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj) template<class SPECIFIC_OBJECT> void AddWorldObject(const uint32 x, const uint32 y, SPECIFIC_OBJECT *obj)
{ {
@@ -152,23 +103,11 @@ public:
GetGridType(x, y).Visit(visitor); GetGridType(x, y).Visit(visitor);
} }
template<class T>
uint32 GetWorldObjectCountInNGrid() const
{
uint32 count = 0;
for (uint32 x = 0; x < N; ++x)
for (uint32 y = 0; y < N; ++y)
count += i_cells[x][y].template GetWorldObjectCountInGrid<T>();
return count;
}
private: private:
uint32 i_gridId; uint32 i_gridId;
GridInfo i_GridInfo;
GridReference<NGrid<N, ACTIVE_OBJECT, WORLD_OBJECT_TYPES, GRID_OBJECT_TYPES> > i_Reference; GridReference<NGrid<N, ACTIVE_OBJECT, WORLD_OBJECT_TYPES, GRID_OBJECT_TYPES> > i_Reference;
int32 i_x; int32 i_x;
int32 i_y; int32 i_y;
grid_state_t i_cellstate;
GridType i_cells[N][N]; GridType i_cells[N][N];
bool i_GridObjectDataLoaded; bool i_GridObjectDataLoaded;
}; };
@@ -16,7 +16,6 @@
*/ */
#include "GridNotifiers.h" #include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
#include "Map.h" #include "Map.h"
#include "ObjectAccessor.h" #include "ObjectAccessor.h"
#include "SpellInfo.h" #include "SpellInfo.h"
@@ -24,10 +23,22 @@
#include "Transport.h" #include "Transport.h"
#include "UpdateData.h" #include "UpdateData.h"
#include "WorldPacket.h" #include "WorldPacket.h"
#include "CellImpl.h"
using namespace Acore; using namespace Acore;
void VisibleNotifier::Visit(GameObjectMapType& m)
{
for (GameObjectMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
{
GameObject* go = iter->GetSource();
if (i_largeOnly != go->IsVisibilityOverridden())
continue;
vis_guids.erase(go->GetGUID());
i_player.UpdateVisibilityOf(go, i_data, i_visibleNow);
}
}
void VisibleNotifier::SendToSelf() void VisibleNotifier::SendToSelf()
{ {
// at this moment i_clientGUIDs have guids that not iterate at grid level checks // at this moment i_clientGUIDs have guids that not iterate at grid level checks
@@ -35,6 +46,9 @@ void VisibleNotifier::SendToSelf()
if (Transport* transport = i_player.GetTransport()) if (Transport* transport = i_player.GetTransport())
for (Transport::PassengerSet::const_iterator itr = transport->GetPassengers().begin(); itr != transport->GetPassengers().end(); ++itr) for (Transport::PassengerSet::const_iterator itr = transport->GetPassengers().begin(); itr != transport->GetPassengers().end(); ++itr)
{ {
if (i_largeOnly != (*itr)->IsVisibilityOverridden())
continue;
if (vis_guids.find((*itr)->GetGUID()) != vis_guids.end()) if (vis_guids.find((*itr)->GetGUID()) != vis_guids.end())
{ {
vis_guids.erase((*itr)->GetGUID()); vis_guids.erase((*itr)->GetGUID());
@@ -51,9 +65,6 @@ void VisibleNotifier::SendToSelf()
case TYPEID_UNIT: case TYPEID_UNIT:
i_player.UpdateVisibilityOf((*itr)->ToCreature(), i_data, i_visibleNow); i_player.UpdateVisibilityOf((*itr)->ToCreature(), i_data, i_visibleNow);
break; break;
case TYPEID_DYNAMICOBJECT:
i_player.UpdateVisibilityOf((*itr)->ToDynObject(), i_data, i_visibleNow);
break;
default: default:
break; break;
} }
@@ -62,6 +73,12 @@ void VisibleNotifier::SendToSelf()
for (GuidUnorderedSet::const_iterator it = vis_guids.begin(); it != vis_guids.end(); ++it) for (GuidUnorderedSet::const_iterator it = vis_guids.begin(); it != vis_guids.end(); ++it)
{ {
if (WorldObject* obj = ObjectAccessor::GetWorldObject(i_player, *it))
{
if (i_largeOnly != obj->IsVisibilityOverridden())
continue;
}
// pussywizard: static transports are removed only in RemovePlayerFromMap and here if can no longer detect (eg. phase changed) // pussywizard: static transports are removed only in RemovePlayerFromMap and here if can no longer detect (eg. phase changed)
if ((*it).IsTransport()) if ((*it).IsTransport())
if (GameObject* staticTrans = i_player.GetMap()->GetGameObject(*it)) if (GameObject* staticTrans = i_player.GetMap()->GetGameObject(*it))
@@ -86,8 +103,11 @@ void VisibleNotifier::SendToSelf()
i_data.BuildPacket(&packet); i_data.BuildPacket(&packet);
i_player.GetSession()->SendPacket(&packet); i_player.GetSession()->SendPacket(&packet);
for (std::set<Unit*>::const_iterator it = i_visibleNow.begin(); it != i_visibleNow.end(); ++it) for (std::vector<Unit*>::const_iterator it = i_visibleNow.begin(); it != i_visibleNow.end(); ++it)
{ {
if (i_largeOnly != (*it)->IsVisibilityOverridden())
continue;
i_player.GetInitialVisiblePackets(*it); i_player.GetInitialVisiblePackets(*it);
} }
} }
@@ -158,23 +178,6 @@ void PlayerRelocationNotifier::Visit(PlayerMapType& m)
} }
} }
void PlayerRelocationNotifier::Visit(CreatureMapType& m)
{
bool relocated_for_ai = (&i_player == i_player.m_seer);
for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
{
Creature* c = iter->GetSource();
vis_guids.erase(c->GetGUID());
i_player.UpdateVisibilityOf(c, i_data, i_visibleNow);
if (relocated_for_ai && !c->isNeedNotify(NOTIFY_VISIBILITY_CHANGED))
CreatureUnitRelocationWorker(c, &i_player);
}
}
void CreatureRelocationNotifier::Visit(PlayerMapType& m) void CreatureRelocationNotifier::Visit(PlayerMapType& m)
{ {
for (PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter) for (PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
@@ -191,58 +194,6 @@ void CreatureRelocationNotifier::Visit(PlayerMapType& m)
} }
} }
void CreatureRelocationNotifier::Visit(CreatureMapType& m)
{
if (!i_creature.IsAlive())
return;
for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
{
Creature* c = iter->GetSource();
CreatureUnitRelocationWorker(&i_creature, c);
if (!c->isNeedNotify(NOTIFY_VISIBILITY_CHANGED))
CreatureUnitRelocationWorker(c, &i_creature);
}
}
void DelayedUnitRelocation::Visit(CreatureMapType& m)
{
for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
{
Creature* unit = iter->GetSource();
if (!unit->isNeedNotify(NOTIFY_VISIBILITY_CHANGED))
continue;
CreatureRelocationNotifier relocate(*unit);
TypeContainerVisitor<CreatureRelocationNotifier, WorldTypeMapContainer > c2world_relocation(relocate);
TypeContainerVisitor<CreatureRelocationNotifier, GridTypeMapContainer > c2grid_relocation(relocate);
cell.Visit(p, c2world_relocation, i_map, *unit, i_radius);
cell.Visit(p, c2grid_relocation, i_map, *unit, i_radius);
}
}
void DelayedUnitRelocation::Visit(PlayerMapType& m)
{
for (PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
{
Player* player = iter->GetSource();
WorldObject const* viewPoint = player->m_seer;
if (!viewPoint->isNeedNotify(NOTIFY_VISIBILITY_CHANGED))
continue;
if (player != viewPoint && !viewPoint->IsPositionValid())
continue;
PlayerRelocationNotifier relocate(*player);
Cell::VisitAllObjects(viewPoint, relocate, i_radius, false);
relocate.SendToSelf();
}
}
void AIRelocationNotifier::Visit(CreatureMapType& m) void AIRelocationNotifier::Visit(CreatureMapType& m)
{ {
bool self = isCreature && !((Creature*)(&i_unit))->IsMoveInLineOfSightStrictlyDisabled(); bool self = isCreature && !((Creature*)(&i_unit))->IsMoveInLineOfSightStrictlyDisabled();
@@ -390,9 +341,14 @@ void MessageDistDelivererToHostile::Visit(DynamicObjectMapType& m)
template<class T> template<class T>
void ObjectUpdater::Visit(GridRefMgr<T>& m) void ObjectUpdater::Visit(GridRefMgr<T>& m)
{ {
for (typename GridRefMgr<T>::iterator iter = m.begin(); iter != m.end(); ++iter) T* obj;
if (iter->GetSource()->IsInWorld()) for (typename GridRefMgr<T>::iterator iter = m.begin(); iter != m.end(); )
iter->GetSource()->Update(i_timeDiff); {
obj = iter->GetSource();
++iter;
if (obj->IsInWorld() && (i_largeOnly == obj->IsVisibilityOverridden()))
obj->Update(i_timeDiff);
}
} }
bool AnyDeadUnitObjectInRangeCheck::operator()(Player* u) bool AnyDeadUnitObjectInRangeCheck::operator()(Player* u)
+13 -38
View File
@@ -42,10 +42,18 @@ namespace Acore
{ {
Player& i_player; Player& i_player;
GuidUnorderedSet vis_guids; GuidUnorderedSet vis_guids;
std::set<Unit*> i_visibleNow; std::vector<Unit*>& i_visibleNow;
bool i_gobjOnly;
bool i_largeOnly;
UpdateData i_data; UpdateData i_data;
VisibleNotifier(Player& player) : i_player(player), vis_guids(player.m_clientGUIDs) {} VisibleNotifier(Player& player, bool gobjOnly, bool largeOnly) :
i_player(player), vis_guids(player.m_clientGUIDs), i_visibleNow(player.m_newVisible), i_gobjOnly(gobjOnly), i_largeOnly(largeOnly)
{
i_visibleNow.clear();
}
void Visit(GameObjectMapType&);
template<class T> void Visit(GridRefMgr<T>& m); template<class T> void Visit(GridRefMgr<T>& m);
void SendToSelf(void); void SendToSelf(void);
}; };
@@ -63,10 +71,9 @@ namespace Acore
struct PlayerRelocationNotifier : public VisibleNotifier struct PlayerRelocationNotifier : public VisibleNotifier
{ {
PlayerRelocationNotifier(Player& player) : VisibleNotifier(player) { } PlayerRelocationNotifier(Player& player, bool largeOnly): VisibleNotifier(player, false, largeOnly) { }
template<class T> void Visit(GridRefMgr<T>& m) { VisibleNotifier::Visit(m); } template<class T> void Visit(GridRefMgr<T>& m) { VisibleNotifier::Visit(m); }
void Visit(CreatureMapType&);
void Visit(PlayerMapType&); void Visit(PlayerMapType&);
}; };
@@ -75,20 +82,6 @@ namespace Acore
Creature& i_creature; Creature& i_creature;
CreatureRelocationNotifier(Creature& c) : i_creature(c) {} CreatureRelocationNotifier(Creature& c) : i_creature(c) {}
template<class T> void Visit(GridRefMgr<T>&) {} template<class T> void Visit(GridRefMgr<T>&) {}
void Visit(CreatureMapType&);
void Visit(PlayerMapType&);
};
struct DelayedUnitRelocation
{
Map& i_map;
Cell& cell;
CellCoord& p;
const float i_radius;
DelayedUnitRelocation(Cell& c, CellCoord& pair, Map& map, float radius) :
i_map(map), cell(c), p(pair), i_radius(radius) { }
template<class T> void Visit(GridRefMgr<T>&) { }
void Visit(CreatureMapType&);
void Visit(PlayerMapType&); void Visit(PlayerMapType&);
}; };
@@ -101,25 +94,6 @@ namespace Acore
void Visit(CreatureMapType&); void Visit(CreatureMapType&);
}; };
struct GridUpdater
{
GridType& i_grid;
uint32 i_timeDiff;
GridUpdater(GridType& grid, uint32 diff) : i_grid(grid), i_timeDiff(diff) { }
template<class T> void updateObjects(GridRefMgr<T>& m)
{
for (typename GridRefMgr<T>::iterator iter = m.begin(); iter != m.end(); ++iter)
iter->GetSource()->Update(i_timeDiff);
}
void Visit(PlayerMapType& m) { updateObjects<Player>(m); }
void Visit(CreatureMapType& m) { updateObjects<Creature>(m); }
void Visit(GameObjectMapType& m) { updateObjects<GameObject>(m); }
void Visit(DynamicObjectMapType& m) { updateObjects<DynamicObject>(m); }
void Visit(CorpseMapType& m) { updateObjects<Corpse>(m); }
};
struct MessageDistDeliverer struct MessageDistDeliverer
{ {
WorldObject const* i_source; WorldObject const* i_source;
@@ -180,7 +154,8 @@ namespace Acore
struct ObjectUpdater struct ObjectUpdater
{ {
uint32 i_timeDiff; uint32 i_timeDiff;
explicit ObjectUpdater(const uint32 diff) : i_timeDiff(diff) {} bool i_largeOnly;
explicit ObjectUpdater(const uint32 diff, bool largeOnly) : i_timeDiff(diff), i_largeOnly(largeOnly) {}
template<class T> void Visit(GridRefMgr<T>& m); template<class T> void Visit(GridRefMgr<T>& m);
void Visit(PlayerMapType&) {} void Visit(PlayerMapType&) {}
void Visit(CorpseMapType&) {} void Visit(CorpseMapType&) {}
@@ -32,8 +32,15 @@
template<class T> template<class T>
inline void Acore::VisibleNotifier::Visit(GridRefMgr<T>& m) inline void Acore::VisibleNotifier::Visit(GridRefMgr<T>& m)
{ {
// Xinef: Update gameobjects only
if (i_gobjOnly)
return;
for (typename GridRefMgr<T>::iterator iter = m.begin(); iter != m.end(); ++iter) for (typename GridRefMgr<T>::iterator iter = m.begin(); iter != m.end(); ++iter)
{ {
if (i_largeOnly != iter->GetSource()->IsVisibilityOverridden())
continue;
vis_guids.erase(iter->GetSource()->GetGUID()); vis_guids.erase(iter->GetSource()->GetGUID());
i_player.UpdateVisibilityOf(iter->GetSource(), i_data, i_visibleNow); i_player.UpdateVisibilityOf(iter->GetSource(), i_data, i_visibleNow);
} }
+13 -52
View File
@@ -25,36 +25,6 @@
#include "ObjectMgr.h" #include "ObjectMgr.h"
#include "Transport.h" #include "Transport.h"
#include "Vehicle.h" #include "Vehicle.h"
#include "GameTime.h"
void ObjectGridEvacuator::Visit(CreatureMapType& m)
{
// creature in unloading grid can have respawn point in another grid
// if it will be unloaded then it will not respawn in original grid until unload/load original grid
// move to respawn point to prevent this case. For player view in respawn grid this will be normal respawn.
for (CreatureMapType::iterator iter = m.begin(); iter != m.end();)
{
Creature* c = iter->GetSource();
++iter;
ASSERT(!c->IsPet() && "ObjectGridRespawnMover must not be called for pets");
c->GetMap()->CreatureRespawnRelocation(c, true);
}
}
void ObjectGridEvacuator::Visit(GameObjectMapType& m)
{
// gameobject in unloading grid can have respawn point in another grid
// if it will be unloaded then it will not respawn in original grid until unload/load original grid
// move to respawn point to prevent this case. For player view in respawn grid this will be normal respawn.
for (GameObjectMapType::iterator iter = m.begin(); iter != m.end();)
{
GameObject* go = iter->GetSource();
++iter;
go->GetMap()->GameObjectRespawnRelocation(go, true);
}
}
// for loading world object at grid loading (Corpses) // for loading world object at grid loading (Corpses)
//TODO: to implement npc on transport, also need to load npcs at grid loading //TODO: to implement npc on transport, also need to load npcs at grid loading
@@ -114,6 +84,18 @@ void AddObjectHelper(CellCoord& cell, CreatureMapType& m, uint32& count, Map* ma
++count; ++count;
} }
template <>
void AddObjectHelper(CellCoord& cell, GameObjectMapType& m, uint32& count, Map* map, GameObject* obj)
{
obj->AddToGrid(m);
ObjectGridLoader::SetObjectCell(obj, cell);
obj->AddToWorld();
if (obj->isActiveObject())
map->AddToActive(obj);
++count;
}
template <class T> template <class T>
void LoadHelper(CellGuidSet const& /*guid_set*/, CellCoord& /*cell*/, GridRefMgr<T>& /*m*/, uint32& /*count*/, Map* /*map*/) void LoadHelper(CellGuidSet const& /*guid_set*/, CellCoord& /*cell*/, GridRefMgr<T>& /*m*/, uint32& /*count*/, Map* /*map*/)
{ {
@@ -124,13 +106,8 @@ void LoadHelper(CellGuidSet const& guid_set, CellCoord& cell, GridRefMgr<Creatur
{ {
for (CellGuidSet::const_iterator i_guid = guid_set.begin(); i_guid != guid_set.end(); ++i_guid) for (CellGuidSet::const_iterator i_guid = guid_set.begin(); i_guid != guid_set.end(); ++i_guid)
{ {
// Don't spawn at all if there's a respawn timer
ObjectGuid::LowType guid = *i_guid;
time_t now = GameTime::GetGameTime().count();
if (map->GetCreatureRespawnTime(guid) > now)
continue;
Creature* obj = new Creature(); Creature* obj = new Creature();
ObjectGuid::LowType guid = *i_guid;
if (!obj->LoadFromDB(guid, map)) if (!obj->LoadFromDB(guid, map))
{ {
delete obj; delete obj;
@@ -156,12 +133,7 @@ void LoadHelper(CellGuidSet const& guid_set, CellCoord& cell, GridRefMgr<GameObj
{ {
for (CellGuidSet::const_iterator i_guid = guid_set.begin(); i_guid != guid_set.end(); ++i_guid) for (CellGuidSet::const_iterator i_guid = guid_set.begin(); i_guid != guid_set.end(); ++i_guid)
{ {
// Don't spawn at all if there's a respawn timer
ObjectGuid::LowType guid = *i_guid; ObjectGuid::LowType guid = *i_guid;
time_t now = GameTime::GetGameTime().count();
if (map->GetGORespawnTime(guid) > now)
continue;
GameObjectData const* data = sObjectMgr->GetGameObjectData(guid); GameObjectData const* data = sObjectMgr->GetGameObjectData(guid);
GameObject* obj = data && sObjectMgr->IsGameObjectStaticTransport(data->id) ? new StaticTransport() : new GameObject(); GameObject* obj = data && sObjectMgr->IsGameObjectStaticTransport(data->id) ? new StaticTransport() : new GameObject();
@@ -257,17 +229,6 @@ void ObjectGridUnloader::Visit(GridRefMgr<T>& m)
} }
} }
void ObjectGridStoper::Visit(CreatureMapType& m)
{
// stop any fights at grid de-activation and remove dynobjects created at cast by creatures
for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
{
iter->GetSource()->RemoveAllDynObjects();
if (iter->GetSource()->IsInCombat())
iter->GetSource()->CombatStop();
}
}
template<class T> template<class T>
void ObjectGridCleaner::Visit(GridRefMgr<T>& m) void ObjectGridCleaner::Visit(GridRefMgr<T>& m)
{ {
-17
View File
@@ -53,23 +53,6 @@ private:
uint32 i_corpses; uint32 i_corpses;
}; };
//Stop the creatures before unloading the NGrid
class AC_GAME_API ObjectGridStoper
{
public:
void Visit(CreatureMapType& m);
template<class T> void Visit(GridRefMgr<T>&) { }
};
//Move the foreign creatures back to respawn positions before unloading the NGrid
class AC_GAME_API ObjectGridEvacuator
{
public:
void Visit(CreatureMapType& m);
void Visit(GameObjectMapType& m);
template<class T> void Visit(GridRefMgr<T>&) { }
};
//Clean up and remove from world //Clean up and remove from world
class ObjectGridCleaner class ObjectGridCleaner
{ {
+81 -86
View File
@@ -49,20 +49,19 @@ void WorldSession::HandleMoveWorldportAckOpcode(WorldPacket& /*recvData*/)
void WorldSession::HandleMoveWorldportAck() void WorldSession::HandleMoveWorldportAck()
{ {
Player* player = GetPlayer();
// ignore unexpected far teleports // ignore unexpected far teleports
if (!player->IsBeingTeleportedFar()) if (!GetPlayer()->IsBeingTeleportedFar())
return; return;
player->SetSemaphoreTeleportFar(0); GetPlayer()->SetSemaphoreTeleportFar(0);
// get the teleport destination // get the teleport destination
WorldLocation const& loc = player->GetTeleportDest(); WorldLocation const& loc = GetPlayer()->GetTeleportDest();
// possible errors in the coordinate validity check // possible errors in the coordinate validity check
if (!MapMgr::IsValidMapCoord(loc)) if (!MapMgr::IsValidMapCoord(loc))
{ {
LogoutPlayer(false); KickPlayer("!MapMgr::IsValidMapCoord(loc)");
return; return;
} }
@@ -70,202 +69,198 @@ void WorldSession::HandleMoveWorldportAck()
MapEntry const* mEntry = sMapStore.LookupEntry(loc.GetMapId()); MapEntry const* mEntry = sMapStore.LookupEntry(loc.GetMapId());
InstanceTemplate const* mInstance = sObjectMgr->GetInstanceTemplate(loc.GetMapId()); InstanceTemplate const* mInstance = sObjectMgr->GetInstanceTemplate(loc.GetMapId());
Map* oldMap = player->GetMap(); Map* oldMap = GetPlayer()->GetMap();
if (player->IsInWorld()) if (GetPlayer()->IsInWorld())
{ {
LOG_ERROR("network.opcode", "Player (Name {}) is still in world when teleported from map {} to new map {}", player->GetName(), oldMap->GetId(), loc.GetMapId()); LOG_ERROR("network.opcode", "Player (Name {}) is still in world when teleported from map {} to new map {}", GetPlayer()->GetName(), oldMap->GetId(), loc.GetMapId());
oldMap->RemovePlayerFromMap(player, false); oldMap->RemovePlayerFromMap(GetPlayer(), false);
} }
// reset instance validity, except if going to an instance inside an instance // reset instance validity, except if going to an instance inside an instance
if (!player->m_InstanceValid && !mInstance) if (!GetPlayer()->m_InstanceValid && !mInstance)
{ {
player->m_InstanceValid = true; GetPlayer()->m_InstanceValid = true;
// pussywizard: m_InstanceValid can be false only by leaving a group in an instance => so remove temp binds that could not be removed because player was still on the map! // pussywizard: m_InstanceValid can be false only by leaving a group in an instance => so remove temp binds that could not be removed because player was still on the map!
if (!sInstanceSaveMgr->PlayerIsPermBoundToInstance(player->GetGUID(), oldMap->GetId(), oldMap->GetDifficulty())) if (!sInstanceSaveMgr->PlayerIsPermBoundToInstance(GetPlayer()->GetGUID(), oldMap->GetId(), oldMap->GetDifficulty()))
sInstanceSaveMgr->PlayerUnbindInstance(player->GetGUID(), oldMap->GetId(), oldMap->GetDifficulty(), true); sInstanceSaveMgr->PlayerUnbindInstance(GetPlayer()->GetGUID(), oldMap->GetId(), oldMap->GetDifficulty(), true);
} }
// relocate the player to the teleport destination // relocate the player to the teleport destination
Map* newMap = sMapMgr->CreateMap(loc.GetMapId(), player); Map* newMap = sMapMgr->CreateMap(loc.GetMapId(), GetPlayer());
// the CanEnter checks are done in TeleporTo but conditions may change // the CanEnter checks are done in TeleporTo but conditions may change
// while the player is in transit, for example the map may get full // while the player is in transit, for example the map may get full
if (!newMap || newMap->CannotEnter(player, false)) if (!newMap || newMap->CannotEnter(GetPlayer(), false))
{ {
LOG_ERROR("network.opcode", "Map {} could not be created for player {}, porting player to homebind", loc.GetMapId(), player->GetGUID().ToString()); LOG_ERROR("network.opcode", "Map {} could not be created for player {}, porting player to homebind", loc.GetMapId(), GetPlayer()->GetGUID().ToString());
player->TeleportTo(player->m_homebindMapId, player->m_homebindX, player->m_homebindY, player->m_homebindZ, player->m_homebindO); GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->m_homebindO);
return; return;
} }
float z = loc.GetPositionZ() + player->GetHoverHeight(); float z = loc.GetPositionZ() + GetPlayer()->GetHoverHeight();
player->Relocate(loc.GetPositionX(), loc.GetPositionY(), z, loc.GetOrientation()); GetPlayer()->Relocate(loc.GetPositionX(), loc.GetPositionY(), z, loc.GetOrientation());
player->ResetMap(); GetPlayer()->ResetMap();
player->SetMap(newMap); GetPlayer()->SetMap(newMap);
player->UpdatePositionData(); GetPlayer()->UpdatePositionData();
player->SendInitialPacketsBeforeAddToMap(); GetPlayer()->SendInitialPacketsBeforeAddToMap();
if (!player->GetMap()->AddPlayerToMap(player)) if (!GetPlayer()->GetMap()->AddPlayerToMap(GetPlayer()))
{ {
LOG_ERROR("network.opcode", "WORLD: failed to teleport player {} ({}) to map {} because of unknown reason!", LOG_ERROR("network.opcode", "WORLD: failed to teleport player {} ({}) to map {} because of unknown reason!",
player->GetName(), player->GetGUID().ToString(), loc.GetMapId()); GetPlayer()->GetName(), GetPlayer()->GetGUID().ToString(), loc.GetMapId());
player->ResetMap(); GetPlayer()->ResetMap();
player->SetMap(oldMap); GetPlayer()->SetMap(oldMap);
player->TeleportTo(player->m_homebindMapId, player->m_homebindX, player->m_homebindY, player->m_homebindZ, player->m_homebindO); GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->m_homebindO);
return; return;
} }
oldMap->AfterPlayerUnlinkFromMap(); oldMap->AfterPlayerUnlinkFromMap();
// pussywizard: transport teleport couldn't teleport us to the same map (some other teleport pending, reqs not met, etc.), but we still have transport set until player moves! clear it if map differs (crashfix) // pussywizard: transport teleport couldn't teleport us to the same map (some other teleport pending, reqs not met, etc.), but we still have transport set until player moves! clear it if map differs (crashfix)
if (Transport* t = player->GetTransport()) if (Transport* t = _player->GetTransport())
if (!t->IsInMap(player)) if (!t->IsInMap(_player))
{ {
t->RemovePassenger(player); t->RemovePassenger(_player);
player->m_transport = nullptr; _player->m_transport = nullptr;
player->m_movementInfo.transport.Reset(); _player->m_movementInfo.transport.Reset();
player->m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_ONTRANSPORT); _player->m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
} }
if (!player->getHostileRefMgr().IsEmpty()) if (!_player->getHostileRefMgr().IsEmpty())
player->getHostileRefMgr().deleteReferences(true); // pussywizard: multithreading crashfix _player->getHostileRefMgr().deleteReferences(true); // pussywizard: multithreading crashfix
CellCoord pair(Acore::ComputeCellCoord(player->GetPositionX(), player->GetPositionY())); CellCoord pair(Acore::ComputeCellCoord(GetPlayer()->GetPositionX(), GetPlayer()->GetPositionY()));
Cell cell(pair); Cell cell(pair);
if (!GridCoord(cell.GridX(), cell.GridY()).IsCoordValid()) if (!GridCoord(cell.GridX(), cell.GridY()).IsCoordValid())
{ {
LogoutPlayer(false); KickPlayer("!GridCoord(cell.GridX(), cell.GridY()).IsCoordValid()");
return; return;
} }
newMap->LoadGrid(GetPlayer()->GetPositionX(), GetPlayer()->GetPositionY());
if (!newMap->IsGridLoaded(player->GetPositionX(), player->GetPositionY()))
newMap->LoadGrid(player->GetPositionX(), player->GetPositionY());
// pussywizard: player supposed to enter bg map // pussywizard: player supposed to enter bg map
if (player->InBattleground()) if (_player->InBattleground())
{ {
// but landed on another map, cleanup data // but landed on another map, cleanup data
if (!mEntry->IsBattlegroundOrArena()) if (!mEntry->IsBattlegroundOrArena())
player->SetBattlegroundId(0, BATTLEGROUND_TYPE_NONE, PLAYER_MAX_BATTLEGROUND_QUEUES, false, false, TEAM_NEUTRAL); _player->SetBattlegroundId(0, BATTLEGROUND_TYPE_NONE, PLAYER_MAX_BATTLEGROUND_QUEUES, false, false, TEAM_NEUTRAL);
// everything ok // everything ok
else if (Battleground* bg = player->GetBattleground()) else if (Battleground* bg = _player->GetBattleground())
{ {
if (player->IsInvitedForBattlegroundInstance()) // GMs are not invited, so they are not added to participants if (_player->IsInvitedForBattlegroundInstance()) // GMs are not invited, so they are not added to participants
bg->AddPlayer(player); bg->AddPlayer(_player);
} }
} }
// pussywizard: arena spectator stuff // pussywizard: arena spectator stuff
{ {
if (newMap->IsBattleArena() && ((BattlegroundMap*)newMap)->GetBG() && player->HasPendingSpectatorForBG(((BattlegroundMap*)newMap)->GetInstanceId())) if (newMap->IsBattleArena() && ((BattlegroundMap*)newMap)->GetBG() && _player->HasPendingSpectatorForBG(((BattlegroundMap*)newMap)->GetInstanceId()))
{ {
player->ClearReceivedSpectatorResetFor(); _player->ClearReceivedSpectatorResetFor();
player->SetIsSpectator(true); _player->SetIsSpectator(true);
ArenaSpectator::SendCommand(player, "%sENABLE", SPECTATOR_ADDON_PREFIX); ArenaSpectator::SendCommand(_player, "%sENABLE", SPECTATOR_ADDON_PREFIX);
((BattlegroundMap*)newMap)->GetBG()->AddSpectator(player); ((BattlegroundMap*)newMap)->GetBG()->AddSpectator(_player);
ArenaSpectator::HandleResetCommand(player); ArenaSpectator::HandleResetCommand(_player);
} }
else else
player->SetIsSpectator(false); _player->SetIsSpectator(false);
player->SetPendingSpectatorForBG(0); GetPlayer()->SetPendingSpectatorForBG(0);
if (uint32 inviteInstanceId = player->GetPendingSpectatorInviteInstanceId()) if (uint32 inviteInstanceId = _player->GetPendingSpectatorInviteInstanceId())
{ {
if (Battleground* tbg = sBattlegroundMgr->GetBattleground(inviteInstanceId, BATTLEGROUND_TYPE_NONE)) if (Battleground* tbg = sBattlegroundMgr->GetBattleground(inviteInstanceId, BATTLEGROUND_TYPE_NONE))
tbg->RemoveToBeTeleported(player->GetGUID()); tbg->RemoveToBeTeleported(_player->GetGUID());
player->SetPendingSpectatorInviteInstanceId(0); _player->SetPendingSpectatorInviteInstanceId(0);
} }
} }
// xinef: do this again, player can be teleported inside bg->AddPlayer(player)!!!! // xinef: do this again, player can be teleported inside bg->AddPlayer(_player)!!!!
CellCoord pair2(Acore::ComputeCellCoord(player->GetPositionX(), player->GetPositionY())); CellCoord pair2(Acore::ComputeCellCoord(GetPlayer()->GetPositionX(), GetPlayer()->GetPositionY()));
Cell cell2(pair2); Cell cell2(pair2);
if (!GridCoord(cell2.GridX(), cell2.GridY()).IsCoordValid()) if (!GridCoord(cell2.GridX(), cell2.GridY()).IsCoordValid())
{ {
KickPlayer("!GridCoord(cell2.GridX(), cell2.GridY()).IsCoordValid()"); KickPlayer("!GridCoord(cell2.GridX(), cell2.GridY()).IsCoordValid()");
return; return;
} }
newMap->LoadGrid(GetPlayer()->GetPositionX(), GetPlayer()->GetPositionY());
if (!newMap->IsGridLoaded(player->GetPositionX(), player->GetPositionY())) GetPlayer()->SendInitialPacketsAfterAddToMap();
newMap->LoadGrid(player->GetPositionX(), player->GetPositionY());
player->SendInitialPacketsAfterAddToMap();
// flight fast teleport case // flight fast teleport case
if (player->IsInFlight()) if (GetPlayer()->IsInFlight())
{ {
if (!player->InBattleground()) if (!GetPlayer()->InBattleground())
{ {
// short preparations to continue flight // short preparations to continue flight
MovementGenerator* movementGenerator = player->GetMotionMaster()->top(); MovementGenerator* movementGenerator = GetPlayer()->GetMotionMaster()->top();
movementGenerator->Initialize(player); movementGenerator->Initialize(GetPlayer());
return; return;
} }
// battleground state prepare, stop flight // battleground state prepare, stop flight
player->GetMotionMaster()->MovementExpired(); GetPlayer()->GetMotionMaster()->MovementExpired();
player->CleanupAfterTaxiFlight(); GetPlayer()->CleanupAfterTaxiFlight();
} }
// resurrect character at enter into instance where his corpse exist after add to map // resurrect character at enter into instance where his corpse exist after add to map
Corpse* corpse = player->GetMap()->GetCorpseByPlayer(player->GetGUID()); Corpse* corpse = GetPlayer()->GetMap()->GetCorpseByPlayer(GetPlayer()->GetGUID());
if (corpse && corpse->GetType() != CORPSE_BONES) if (corpse && corpse->GetType() != CORPSE_BONES)
{ {
if (mEntry->IsDungeon()) if (mEntry->IsDungeon())
{ {
player->ResurrectPlayer(0.5f); GetPlayer()->ResurrectPlayer(0.5f);
player->SpawnCorpseBones(); GetPlayer()->SpawnCorpseBones();
} }
} }
if (!corpse && mEntry->IsDungeon()) if (!corpse && mEntry->IsDungeon())
{ {
// resurrect character upon entering instance when the corpse is not available anymore // resurrect character upon entering instance when the corpse is not available anymore
if (player->GetCorpseLocation().GetMapId() == mEntry->MapID) if (GetPlayer()->GetCorpseLocation().GetMapId() == mEntry->MapID)
{ {
player->ResurrectPlayer(0.5f); GetPlayer()->ResurrectPlayer(0.5f);
player->RemoveCorpse(); GetPlayer()->RemoveCorpse();
} }
} }
bool allowMount = !mEntry->IsDungeon() || mEntry->IsBattlegroundOrArena(); bool allowMount = !mEntry->IsDungeon() || mEntry->IsBattlegroundOrArena();
if (mInstance) if (mInstance)
{ {
Difficulty diff = player->GetDifficulty(mEntry->IsRaid()); Difficulty diff = GetPlayer()->GetDifficulty(mEntry->IsRaid());
if (MapDifficulty const* mapDiff = GetMapDifficultyData(mEntry->MapID, diff)) if (MapDifficulty const* mapDiff = GetMapDifficultyData(mEntry->MapID, diff))
if (mapDiff->resetTime) if (mapDiff->resetTime)
if (time_t timeReset = sInstanceSaveMgr->GetResetTimeFor(mEntry->MapID, diff)) if (time_t timeReset = sInstanceSaveMgr->GetResetTimeFor(mEntry->MapID, diff))
{ {
uint32 timeleft = uint32(timeReset - GameTime::GetGameTime().count()); uint32 timeleft = uint32(timeReset - GameTime::GetGameTime().count());
player->SendInstanceResetWarning(mEntry->MapID, diff, timeleft, true); GetPlayer()->SendInstanceResetWarning(mEntry->MapID, diff, timeleft, true);
} }
allowMount = mInstance->AllowMount; allowMount = mInstance->AllowMount;
} }
// mount allow check // mount allow check
if (!allowMount) if (!allowMount)
player->RemoveAurasByType(SPELL_AURA_MOUNTED); _player->RemoveAurasByType(SPELL_AURA_MOUNTED);
// update zone immediately, otherwise leave channel will cause crash in mtmap // update zone immediately, otherwise leave channel will cause crash in mtmap
uint32 newzone, newarea; uint32 newzone, newarea;
player->GetZoneAndAreaId(newzone, newarea); GetPlayer()->GetZoneAndAreaId(newzone, newarea);
player->UpdateZone(newzone, newarea); GetPlayer()->UpdateZone(newzone, newarea);
// honorless target // honorless target
if (player->pvpInfo.IsHostile) if (GetPlayer()->pvpInfo.IsHostile)
player->CastSpell(player, 2479, true); GetPlayer()->CastSpell(GetPlayer(), 2479, true);
// in friendly area // in friendly area
else if (player->IsPvP() && !player->HasPlayerFlag(PLAYER_FLAGS_IN_PVP)) else if (GetPlayer()->IsPvP() && !GetPlayer()->HasPlayerFlag(PLAYER_FLAGS_IN_PVP))
player->UpdatePvP(false, false); GetPlayer()->UpdatePvP(false, false);
// resummon pet // resummon pet
player->ResummonPetTemporaryUnSummonedIfAny(); GetPlayer()->ResummonPetTemporaryUnSummonedIfAny();
//lets process all delayed operations on successful teleport //lets process all delayed operations on successful teleport
player->ProcessDelayedOperations(); GetPlayer()->ProcessDelayedOperations();
} }
void WorldSession::HandleMoveTeleportAck(WorldPacket& recvData) void WorldSession::HandleMoveTeleportAck(WorldPacket& recvData)
@@ -20,7 +20,6 @@
#include "Config.h" #include "Config.h"
#include "GameTime.h" #include "GameTime.h"
#include "GridNotifiers.h" #include "GridNotifiers.h"
#include "GridStates.h"
#include "Group.h" #include "Group.h"
#include "InstanceScript.h" #include "InstanceScript.h"
#include "Log.h" #include "Log.h"
File diff suppressed because it is too large Load Diff
+31 -62
View File
@@ -71,6 +71,7 @@ namespace VMAP
namespace Acore namespace Acore
{ {
struct ObjectUpdater; struct ObjectUpdater;
struct LargeObjectUpdater;
} }
struct ScriptAction struct ScriptAction
@@ -311,7 +312,7 @@ class Map : public GridRefMgr<NGridType>
{ {
friend class MapReference; friend class MapReference;
public: public:
Map(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode, Map* _parent = nullptr); Map(uint32 id, uint32 InstanceId, uint8 SpawnMode, Map* _parent = nullptr);
~Map() override; ~Map() override;
[[nodiscard]] MapEntry const* GetEntry() const { return i_mapEntry; } [[nodiscard]] MapEntry const* GetEntry() const { return i_mapEntry; }
@@ -336,7 +337,13 @@ public:
template<class T> void RemoveFromMap(T*, bool); template<class T> void RemoveFromMap(T*, bool);
void VisitNearbyCellsOf(WorldObject* obj, TypeContainerVisitor<Acore::ObjectUpdater, GridTypeMapContainer>& gridVisitor, void VisitNearbyCellsOf(WorldObject* obj, TypeContainerVisitor<Acore::ObjectUpdater, GridTypeMapContainer>& gridVisitor,
TypeContainerVisitor<Acore::ObjectUpdater, WorldTypeMapContainer>& worldVisitor); TypeContainerVisitor<Acore::ObjectUpdater, WorldTypeMapContainer>& worldVisitor,
TypeContainerVisitor<Acore::ObjectUpdater, GridTypeMapContainer>& largeGridVisitor,
TypeContainerVisitor<Acore::ObjectUpdater, WorldTypeMapContainer>& largeWorldVisitor);
void VisitNearbyCellsOfPlayer(Player* player, TypeContainerVisitor<Acore::ObjectUpdater, GridTypeMapContainer>& gridVisitor,
TypeContainerVisitor<Acore::ObjectUpdater, WorldTypeMapContainer>& worldVisitor,
TypeContainerVisitor<Acore::ObjectUpdater, GridTypeMapContainer>& largeGridVisitor,
TypeContainerVisitor<Acore::ObjectUpdater, WorldTypeMapContainer>& largeWorldVisitor);
virtual void Update(const uint32, const uint32, bool thread = true); virtual void Update(const uint32, const uint32, bool thread = true);
@@ -346,22 +353,16 @@ public:
virtual void InitVisibilityDistance(); virtual void InitVisibilityDistance();
void PlayerRelocation(Player*, float x, float y, float z, float o); void PlayerRelocation(Player*, float x, float y, float z, float o);
void CreatureRelocation(Creature* creature, float x, float y, float z, float o, bool respawnRelocationOnFail = true); void CreatureRelocation(Creature* creature, float x, float y, float z, float o);
void GameObjectRelocation(GameObject* go, float x, float y, float z, float o, bool respawnRelocationOnFail = true); void GameObjectRelocation(GameObject* go, float x, float y, float z, float o);
void DynamicObjectRelocation(DynamicObject* go, float x, float y, float z, float o); void DynamicObjectRelocation(DynamicObject* go, float x, float y, float z, float o);
template<class T, class CONTAINER> void Visit(const Cell& cell, TypeContainerVisitor<T, CONTAINER>& visitor); template<class T, class CONTAINER> void Visit(const Cell& cell, TypeContainerVisitor<T, CONTAINER>& visitor);
[[nodiscard]] bool IsActiveGrid(float x, float y) const
{
GridCoord p = Acore::ComputeGridCoord(x, y);
return !getNGrid(p.x_coord, p.y_coord) || getNGrid(p.x_coord, p.y_coord)->GetGridState() == GRID_STATE_ACTIVE;
}
[[nodiscard]] bool IsRemovalGrid(float x, float y) const [[nodiscard]] bool IsRemovalGrid(float x, float y) const
{ {
GridCoord p = Acore::ComputeGridCoord(x, y); GridCoord p = Acore::ComputeGridCoord(x, y);
return !getNGrid(p.x_coord, p.y_coord) || getNGrid(p.x_coord, p.y_coord)->GetGridState() == GRID_STATE_REMOVAL; return !getNGrid(p.x_coord, p.y_coord);
} }
[[nodiscard]] bool IsGridLoaded(float x, float y) const [[nodiscard]] bool IsGridLoaded(float x, float y) const
@@ -369,26 +370,13 @@ public:
return IsGridLoaded(Acore::ComputeGridCoord(x, y)); return IsGridLoaded(Acore::ComputeGridCoord(x, y));
} }
bool GetUnloadLock(GridCoord const& p) const { return getNGrid(p.x_coord, p.y_coord)->getUnloadLock(); }
void SetUnloadLock(GridCoord const& p, bool on) { getNGrid(p.x_coord, p.y_coord)->setUnloadExplicitLock(on); }
void LoadGrid(float x, float y); void LoadGrid(float x, float y);
void LoadAllCells(); void LoadAllCells();
bool UnloadGrid(NGridType& ngrid, bool pForce); bool UnloadGrid(NGridType& ngrid);
void GridMarkNoUnload(uint32 x, uint32 y);
void GridUnmarkNoUnload(uint32 x, uint32 y);
virtual void UnloadAll(); virtual void UnloadAll();
void ResetGridExpiry(NGridType& grid, float factor = 1) const
{
grid.ResetTimeTracker(time_t(float(i_gridExpiry) * factor));
}
[[nodiscard]] time_t GetGridExpiry(void) const { return i_gridExpiry; }
[[nodiscard]] uint32 GetId() const { return i_mapEntry->MapID; } [[nodiscard]] uint32 GetId() const { return i_mapEntry->MapID; }
static void InitStateMachine();
static void DeleteStateMachine();
static bool ExistMap(uint32 mapid, int gx, int gy); static bool ExistMap(uint32 mapid, int gx, int gy);
static bool ExistVMap(uint32 mapid, int gx, int gy); static bool ExistVMap(uint32 mapid, int gx, int gy);
@@ -427,10 +415,6 @@ public:
void RemoveAllObjectsInRemoveList(); void RemoveAllObjectsInRemoveList();
virtual void RemoveAllPlayers(); virtual void RemoveAllPlayers();
// used only in MoveAllCreaturesInMoveList and ObjectGridUnloader
bool CreatureRespawnRelocation(Creature* c, bool diffGridOnly);
bool GameObjectRespawnRelocation(GameObject* go, bool diffGridOnly);
[[nodiscard]] uint32 GetInstanceId() const { return i_InstanceId; } [[nodiscard]] uint32 GetInstanceId() const { return i_InstanceId; }
[[nodiscard]] uint8 GetSpawnMode() const { return (i_spawnMode); } [[nodiscard]] uint8 GetSpawnMode() const { return (i_spawnMode); }
@@ -484,10 +468,12 @@ public:
void resetMarkedCells() { marked_cells.reset(); } void resetMarkedCells() { marked_cells.reset(); }
bool isCellMarked(uint32 pCellId) { return marked_cells.test(pCellId); } bool isCellMarked(uint32 pCellId) { return marked_cells.test(pCellId); }
void markCell(uint32 pCellId) { marked_cells.set(pCellId); } void markCell(uint32 pCellId) { marked_cells.set(pCellId); }
void resetMarkedCellsLarge() { marked_cells_large.reset(); }
bool isCellMarkedLarge(uint32 pCellId) { return marked_cells_large.test(pCellId); }
void markCellLarge(uint32 pCellId) { marked_cells_large.set(pCellId); }
[[nodiscard]] bool HavePlayers() const { return !m_mapRefMgr.IsEmpty(); } [[nodiscard]] bool HavePlayers() const { return !m_mapRefMgr.IsEmpty(); }
[[nodiscard]] uint32 GetPlayersCountExceptGMs() const; [[nodiscard]] uint32 GetPlayersCountExceptGMs() const;
[[nodiscard]] bool ActiveObjectsNearGrid(NGridType const& ngrid) const;
void AddWorldObject(WorldObject* obj) { i_worldObjects.insert(obj); } void AddWorldObject(WorldObject* obj) { i_worldObjects.insert(obj); }
void RemoveWorldObject(WorldObject* obj) { i_worldObjects.erase(obj); } void RemoveWorldObject(WorldObject* obj) { i_worldObjects.erase(obj); }
@@ -674,30 +660,20 @@ private:
// Load MMap Data // Load MMap Data
void LoadMMap(int gx, int gy); void LoadMMap(int gx, int gy);
bool CreatureCellRelocation(Creature* creature, Cell new_cell);
bool GameObjectCellRelocation(GameObject* go, Cell new_cell);
bool DynamicObjectCellRelocation(DynamicObject* go, Cell new_cell);
template<class T> void InitializeObject(T* obj); template<class T> void InitializeObject(T* obj);
void AddCreatureToMoveList(Creature* c, float x, float y, float z, float ang); void AddCreatureToMoveList(Creature* c);
void RemoveCreatureFromMoveList(Creature* c); void RemoveCreatureFromMoveList(Creature* c);
void AddGameObjectToMoveList(GameObject* go, float x, float y, float z, float ang); void AddGameObjectToMoveList(GameObject* go);
void RemoveGameObjectFromMoveList(GameObject* go); void RemoveGameObjectFromMoveList(GameObject* go);
void AddDynamicObjectToMoveList(DynamicObject* go, float x, float y, float z, float ang); void AddDynamicObjectToMoveList(DynamicObject* go);
void RemoveDynamicObjectFromMoveList(DynamicObject* go); void RemoveDynamicObjectFromMoveList(DynamicObject* go);
bool _creatureToMoveLock;
std::vector<Creature*> _creaturesToMove; std::vector<Creature*> _creaturesToMove;
bool _gameObjectsToMoveLock;
std::vector<GameObject*> _gameObjectsToMove; std::vector<GameObject*> _gameObjectsToMove;
bool _dynamicObjectsToMoveLock;
std::vector<DynamicObject*> _dynamicObjectsToMove; std::vector<DynamicObject*> _dynamicObjectsToMove;
[[nodiscard]] bool IsGridLoaded(const GridCoord&) const; [[nodiscard]] bool IsGridLoaded(const GridCoord&) const;
void EnsureGridCreated_i(const GridCoord&); void EnsureGridCreated_i(const GridCoord&);
void EnsureGridLoadedForActiveObject(Cell const&, WorldObject* object);
void buildNGridLinkage(NGridType* pNGridType) { pNGridType->link(this); } void buildNGridLinkage(NGridType* pNGridType) { pNGridType->link(this); }
@@ -708,6 +684,9 @@ private:
} }
bool EnsureGridLoaded(Cell const&); bool EnsureGridLoaded(Cell const&);
[[nodiscard]] bool isGridObjectDataLoaded(uint32 x, uint32 y) const { return getNGrid(x, y)->isGridObjectDataLoaded(); }
void setGridObjectDataLoaded(bool pLoaded, uint32 x, uint32 y) { getNGrid(x, y)->setGridObjectDataLoaded(pLoaded); }
void setNGrid(NGridType* grid, uint32 x, uint32 y); void setNGrid(NGridType* grid, uint32 x, uint32 y);
void ScriptsProcess(); void ScriptsProcess();
@@ -716,8 +695,6 @@ private:
void SendObjectUpdates(); void SendObjectUpdates();
protected: protected:
void SetUnloadReferenceLock(GridCoord const& p, bool on) { getNGrid(p.x_coord, p.y_coord)->setUnloadReferenceLock(on); }
std::mutex Lock; std::mutex Lock;
std::mutex GridLock; std::mutex GridLock;
std::shared_mutex MMapLock; std::shared_mutex MMapLock;
@@ -733,8 +710,6 @@ protected:
MapRefMgr m_mapRefMgr; MapRefMgr m_mapRefMgr;
MapRefMgr::iterator m_mapRefIter; MapRefMgr::iterator m_mapRefIter;
int32 m_VisibilityNotifyPeriod;
typedef std::set<WorldObject*> ActiveNonPlayers; typedef std::set<WorldObject*> ActiveNonPlayers;
ActiveNonPlayers m_activeNonPlayers; ActiveNonPlayers m_activeNonPlayers;
ActiveNonPlayers::iterator m_activeNonPlayersIter; ActiveNonPlayers::iterator m_activeNonPlayersIter;
@@ -753,8 +728,6 @@ private:
void _ScriptProcessDoor(Object* source, Object* target, const ScriptInfo* scriptInfo) const; void _ScriptProcessDoor(Object* source, Object* target, const ScriptInfo* scriptInfo) const;
GameObject* _FindGameObject(WorldObject* pWorldObject, ObjectGuid::LowType guid) const; GameObject* _FindGameObject(WorldObject* pWorldObject, ObjectGuid::LowType guid) const;
time_t i_gridExpiry;
//used for fast base_map (e.g. MapInstanced class object) search for //used for fast base_map (e.g. MapInstanced class object) search for
//InstanceMaps and BattlegroundMaps... //InstanceMaps and BattlegroundMaps...
Map* m_parentMap; Map* m_parentMap;
@@ -762,15 +735,12 @@ private:
NGridType* i_grids[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]; NGridType* i_grids[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS];
GridMap* GridMaps[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS]; GridMap* GridMaps[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS];
std::bitset<TOTAL_NUMBER_OF_CELLS_PER_MAP* TOTAL_NUMBER_OF_CELLS_PER_MAP> marked_cells; std::bitset<TOTAL_NUMBER_OF_CELLS_PER_MAP* TOTAL_NUMBER_OF_CELLS_PER_MAP> marked_cells;
std::bitset<TOTAL_NUMBER_OF_CELLS_PER_MAP* TOTAL_NUMBER_OF_CELLS_PER_MAP> marked_cells_large;
//these functions used to process player/mob aggro reactions and
//visibility calculations. Highly optimized for massive calculations
void ProcessRelocationNotifies(uint32 diff);
bool i_scriptLock; bool i_scriptLock;
std::set<WorldObject*> i_objectsToRemove; std::unordered_set<WorldObject*> i_objectsToRemove;
std::map<WorldObject*, bool> i_objectsToSwitch; std::map<WorldObject*, bool> i_objectsToSwitch;
std::set<WorldObject*> i_worldObjects; std::unordered_set<WorldObject*> i_worldObjects;
typedef std::multimap<time_t, ScriptAction> ScriptScheduleMap; typedef std::multimap<time_t, ScriptAction> ScriptScheduleMap;
ScriptScheduleMap m_scriptSchedule; ScriptScheduleMap m_scriptSchedule;
@@ -842,7 +812,7 @@ enum InstanceResetMethod
class InstanceMap : public Map class InstanceMap : public Map
{ {
public: public:
InstanceMap(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode, Map* _parent); InstanceMap(uint32 id, uint32 InstanceId, uint8 SpawnMode, Map* _parent);
~InstanceMap() override; ~InstanceMap() override;
bool AddPlayerToMap(Player*) override; bool AddPlayerToMap(Player*) override;
void RemovePlayerFromMap(Player*, bool) override; void RemovePlayerFromMap(Player*, bool) override;
@@ -876,7 +846,7 @@ private:
class BattlegroundMap : public Map class BattlegroundMap : public Map
{ {
public: public:
BattlegroundMap(uint32 id, time_t, uint32 InstanceId, Map* _parent, uint8 spawnMode); BattlegroundMap(uint32 id, uint32 InstanceId, Map* _parent, uint8 spawnMode);
~BattlegroundMap() override; ~BattlegroundMap() override;
bool AddPlayerToMap(Player*) override; bool AddPlayerToMap(Player*) override;
@@ -901,12 +871,11 @@ inline void Map::Visit(Cell const& cell, TypeContainerVisitor<T, CONTAINER>& vis
const uint32 cell_x = cell.CellX(); const uint32 cell_x = cell.CellX();
const uint32 cell_y = cell.CellY(); const uint32 cell_y = cell.CellY();
if (!cell.NoCreate()) if (!cell.NoCreate() || IsGridLoaded(GridCoord(x, y)))
{
EnsureGridLoaded(cell); EnsureGridLoaded(cell);
getNGrid(x, y)->VisitGrid(cell_x, cell_y, visitor);
NGridType* grid = getNGrid(x, y); }
if (grid && grid->isGridObjectDataLoaded())
grid->VisitGrid(cell_x, cell_y, visitor);
} }
#endif #endif
+5 -15
View File
@@ -25,12 +25,11 @@
#include "Player.h" #include "Player.h"
#include "ScriptMgr.h" #include "ScriptMgr.h"
#include "VMapFactory.h" #include "VMapFactory.h"
#include "VMapMgr2.h"
MapInstanced::MapInstanced(uint32 id, time_t expiry) : Map(id, expiry, 0, DUNGEON_DIFFICULTY_NORMAL) MapInstanced::MapInstanced(uint32 id) : Map(id, 0, DUNGEON_DIFFICULTY_NORMAL)
{ {
// fill with zero // initialize instanced maps list
memset(&GridMapReference, 0, MAX_NUMBER_OF_GRIDS * MAX_NUMBER_OF_GRIDS * sizeof(uint16)); m_InstancedMaps.clear();
} }
void MapInstanced::InitVisibilityDistance() void MapInstanced::InitVisibilityDistance()
@@ -204,7 +203,7 @@ InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave* save,
LOG_DEBUG("maps", "MapInstanced::CreateInstance: {} map instance {} for {} created with difficulty {}", save ? "" : "new ", InstanceId, GetId(), difficulty ? "heroic" : "normal"); LOG_DEBUG("maps", "MapInstanced::CreateInstance: {} map instance {} for {} created with difficulty {}", save ? "" : "new ", InstanceId, GetId(), difficulty ? "heroic" : "normal");
InstanceMap* map = new InstanceMap(GetId(), GetGridExpiry(), InstanceId, difficulty, this); InstanceMap* map = new InstanceMap(GetId(), InstanceId, difficulty, this);
ASSERT(map->IsDungeon()); ASSERT(map->IsDungeon());
map->LoadRespawnTimes(); map->LoadRespawnTimes();
@@ -238,7 +237,7 @@ BattlegroundMap* MapInstanced::CreateBattleground(uint32 InstanceId, Battlegroun
else else
spawnMode = REGULAR_DIFFICULTY; spawnMode = REGULAR_DIFFICULTY;
BattlegroundMap* map = new BattlegroundMap(GetId(), GetGridExpiry(), InstanceId, this, spawnMode); BattlegroundMap* map = new BattlegroundMap(GetId(), InstanceId, this, spawnMode);
ASSERT(map->IsBattlegroundOrArena()); ASSERT(map->IsBattlegroundOrArena());
map->SetBG(bg); map->SetBG(bg);
bg->SetBgMap(map); bg->SetBgMap(map);
@@ -261,15 +260,6 @@ bool MapInstanced::DestroyInstance(InstancedMaps::iterator& itr)
sScriptMgr->OnDestroyInstance(this, itr->second); sScriptMgr->OnDestroyInstance(this, itr->second);
itr->second->UnloadAll(); itr->second->UnloadAll();
// should only unload VMaps if this is the last instance
if (m_InstancedMaps.size() <= 1)
{
VMAP::VMapFactory::createOrGetVMapMgr()->unloadMap(itr->second->GetId());
MMAP::MMapFactory::createOrGetMMapMgr()->unloadMap(itr->second->GetId());
// in that case, unload grids of the base map, too
// so in the next map creation, (EnsureGridCreated actually) VMaps will be reloaded
Map::UnloadAll();
}
// erase map // erase map
delete itr->second; delete itr->second;
+1 -16
View File
@@ -28,7 +28,7 @@ class MapInstanced : public Map
public: public:
using InstancedMaps = std::unordered_map<uint32, Map*>; using InstancedMaps = std::unordered_map<uint32, Map*>;
MapInstanced(uint32 id, time_t expiry); MapInstanced(uint32 id);
~MapInstanced() override {} ~MapInstanced() override {}
// functions overwrite Map versions // functions overwrite Map versions
@@ -46,19 +46,6 @@ public:
} }
bool DestroyInstance(InstancedMaps::iterator& itr); bool DestroyInstance(InstancedMaps::iterator& itr);
void AddGridMapReference(GridCoord const& p)
{
++GridMapReference[p.x_coord][p.y_coord];
SetUnloadReferenceLock(GridCoord((MAX_NUMBER_OF_GRIDS - 1) - p.x_coord, (MAX_NUMBER_OF_GRIDS - 1) - p.y_coord), true);
}
void RemoveGridMapReference(GridCoord const& p)
{
--GridMapReference[p.x_coord][p.y_coord];
if (!GridMapReference[p.x_coord][p.y_coord])
SetUnloadReferenceLock(GridCoord((MAX_NUMBER_OF_GRIDS - 1) - p.x_coord, (MAX_NUMBER_OF_GRIDS - 1) - p.y_coord), false);
}
InstancedMaps& GetInstancedMaps() { return m_InstancedMaps; } InstancedMaps& GetInstancedMaps() { return m_InstancedMaps; }
void InitVisibilityDistance() override; void InitVisibilityDistance() override;
@@ -67,7 +54,5 @@ private:
BattlegroundMap* CreateBattleground(uint32 InstanceId, Battleground* bg); BattlegroundMap* CreateBattleground(uint32 InstanceId, Battleground* bg);
InstancedMaps m_InstancedMaps; InstancedMaps m_InstancedMaps;
uint16 GridMapReference[MAX_NUMBER_OF_GRIDS][MAX_NUMBER_OF_GRIDS];
}; };
#endif #endif
+4 -9
View File
@@ -36,7 +36,6 @@
MapMgr::MapMgr() MapMgr::MapMgr()
{ {
i_gridCleanUpDelay = sWorld->getIntConfig(CONFIG_INTERVAL_GRIDCLEAN);
i_timer[3].SetInterval(sWorld->getIntConfig(CONFIG_INTERVAL_MAPUPDATE)); i_timer[3].SetInterval(sWorld->getIntConfig(CONFIG_INTERVAL_MAPUPDATE));
mapUpdateStep = 0; mapUpdateStep = 0;
_nextInstanceId = 0; _nextInstanceId = 0;
@@ -54,8 +53,6 @@ MapMgr* MapMgr::instance()
void MapMgr::Initialize() void MapMgr::Initialize()
{ {
Map::InitStateMachine();
int num_threads(sWorld->getIntConfig(CONFIG_NUMTHREADS)); int num_threads(sWorld->getIntConfig(CONFIG_NUMTHREADS));
// Start mtmaps if needed // Start mtmaps if needed
@@ -84,10 +81,10 @@ Map* MapMgr::CreateBaseMap(uint32 id)
ASSERT(entry); ASSERT(entry);
if (entry->Instanceable()) if (entry->Instanceable())
map = new MapInstanced(id, i_gridCleanUpDelay); map = new MapInstanced(id);
else else
{ {
map = new Map(id, i_gridCleanUpDelay, 0, REGULAR_DIFFICULTY); map = new Map(id, 0, REGULAR_DIFFICULTY);
map->LoadRespawnTimes(); map->LoadRespawnTimes();
map->LoadCorpseData(); map->LoadCorpseData();
} }
@@ -303,8 +300,8 @@ bool MapMgr::ExistMapAndVMap(uint32 mapid, float x, float y)
{ {
GridCoord p = Acore::ComputeGridCoord(x, y); GridCoord p = Acore::ComputeGridCoord(x, y);
int gx = (MAX_NUMBER_OF_GRIDS - 1) - p.x_coord; int gx = 63 - p.x_coord;
int gy = (MAX_NUMBER_OF_GRIDS - 1) - p.y_coord; int gy = 63 - p.y_coord;
return Map::ExistMap(mapid, gx, gy) && Map::ExistVMap(mapid, gx, gy); return Map::ExistMap(mapid, gx, gy) && Map::ExistVMap(mapid, gx, gy);
} }
@@ -336,8 +333,6 @@ void MapMgr::UnloadAll()
if (m_updater.activated()) if (m_updater.activated())
m_updater.deactivate(); m_updater.deactivate();
Map::DeleteStateMachine();
} }
void MapMgr::GetNumInstances(uint32& dungeons, uint32& battlegrounds, uint32& arenas) void MapMgr::GetNumInstances(uint32& dungeons, uint32& battlegrounds, uint32& arenas)
-10
View File
@@ -24,7 +24,6 @@
#include "MapInstanced.h" #include "MapInstanced.h"
#include "MapUpdater.h" #include "MapUpdater.h"
#include "Object.h" #include "Object.h"
#include "GridStates.h"
#include <mutex> #include <mutex>
@@ -74,14 +73,6 @@ public:
void Initialize(void); void Initialize(void);
void Update(uint32); void Update(uint32);
void SetGridCleanUpDelay(uint32 t)
{
if (t < MIN_GRID_DELAY)
i_gridCleanUpDelay = MIN_GRID_DELAY;
else
i_gridCleanUpDelay = t;
}
void SetMapUpdateInterval(uint32 t) void SetMapUpdateInterval(uint32 t)
{ {
if (t < MIN_MAP_UPDATE_DELAY) if (t < MIN_MAP_UPDATE_DELAY)
@@ -179,7 +170,6 @@ private:
MapMgr& operator=(const MapMgr&); MapMgr& operator=(const MapMgr&);
std::mutex Lock; std::mutex Lock;
uint32 i_gridCleanUpDelay;
MapMapType i_maps; MapMapType i_maps;
IntervalTimer i_timer[4]; // continents, bgs/arenas, instances, total from the beginning IntervalTimer i_timer[4]; // continents, bgs/arenas, instances, total from the beginning
uint8 mapUpdateStep; uint8 mapUpdateStep;
+2
View File
@@ -411,6 +411,8 @@ MotionTransport* TransportMgr::CreateTransport(uint32 entry, ObjectGuid::LowType
if (map && map->IsDungeon()) if (map && map->IsDungeon())
trans->m_zoneScript = map->ToInstanceMap()->GetInstanceScript(); trans->m_zoneScript = map->ToInstanceMap()->GetInstanceScript();
// xinef: transports are active so passengers can be relocated (grids must be loaded)
trans->setActive(true);
HashMapHolder<MotionTransport>::Insert(trans); HashMapHolder<MotionTransport>::Insert(trans);
trans->GetMap()->AddToMap<MotionTransport>(trans); trans->GetMap()->AddToMap<MotionTransport>(trans);
return trans; return trans;
@@ -15,15 +15,14 @@
* with this program. If not, see <http://www.gnu.org/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "NGrid.h" #include "DynamicVisibility.h"
#include "Random.h"
GridInfo::GridInfo() : i_timer(0), vis_Update(0, irand(0, DEFAULT_VISIBILITY_NOTIFY_PERIOD)), uint8 DynamicVisibilityMgr::visibilitySettingsIndex = 0;
i_unloadActiveLockCount(0), i_unloadExplicitLock(false), i_unloadReferenceLock(false)
{
}
GridInfo::GridInfo(time_t expiry, bool unload /*= true */) : i_timer(expiry), vis_Update(0, irand(0, DEFAULT_VISIBILITY_NOTIFY_PERIOD)), void DynamicVisibilityMgr::Update(uint32 sessionCount)
i_unloadActiveLockCount(0), i_unloadExplicitLock(!unload), i_unloadReferenceLock(false)
{ {
if (sessionCount >= (visibilitySettingsIndex + 1) * ((uint32)VISIBILITY_SETTINGS_PLAYER_INTERVAL) && visibilitySettingsIndex < VISIBILITY_SETTINGS_MAX_INTERVAL_NUM - 1)
++visibilitySettingsIndex;
else if (visibilitySettingsIndex && sessionCount < visibilitySettingsIndex * ((uint32)VISIBILITY_SETTINGS_PLAYER_INTERVAL) - 100)
--visibilitySettingsIndex;
} }
+58
View File
@@ -0,0 +1,58 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __DYNAMICVISIBILITY_H
#define __DYNAMICVISIBILITY_H
#include "Common.h"
struct VisibilitySettingData
{
uint32 visibilityNotifyDelay;
uint32 aiNotifyDelay;
float requiredMoveDistanceSq;
};
// pussywizard: dynamic visibility settings
// 7 player intervals: 0-499, 500-999, 1000-1499, 1500-1999, 2000-2499, 2500-2999, 3000+
// 5 map types: common, instance, raid, bg, arena
// feel free to add more intervals, change existing ones or move to conf file :P
#define VISIBILITY_SETTINGS_PLAYER_INTERVAL 500
#define VISIBILITY_SETTINGS_MAX_INTERVAL_NUM 7
const VisibilitySettingData VisibilitySettings[VISIBILITY_SETTINGS_MAX_INTERVAL_NUM][5] =
{
{ {300, 150, 1.0f}, {300, 150, 1.0f}, {300, 150, 1.0f}, {300, 150, 1.0f}, {300, 150, 1.0f} }, // 0-499
{ {400, 200, 2.25f}, {400, 200, 2.25f}, {400, 200, 2.25f}, {300, 150, 1.0f}, {300, 150, 1.0f} }, // 500-999
{ {500, 250, 4.0f}, {500, 250, 4.0f}, {500, 250, 4.0f}, {400, 200, 2.25f}, {300, 150, 1.0f} }, // 1000-1499
{ {700, 350, 6.25f}, {700, 350, 6.25f}, {700, 350, 6.25f}, {600, 300, 6.25f}, {300, 200, 1.0f} }, // 1500-1999
{ {1000, 500, 16.0f}, {1000, 500, 16.0f}, {1000, 500, 16.0f}, {1000, 500, 16.0f}, {300, 250, 1.0f} }, // 2000-2499
{ {1000, 500, 16.0f}, {1000, 500, 16.0f}, {1000, 500, 16.0f}, {1000, 500, 16.0f}, {300, 350, 1.0f} }, // 2500-2999
{ {1200, 550, 20.0f}, {1200, 550, 25.0f}, {1200, 550, 25.0f}, {1100, 550, 16.0f}, {300, 350, 1.0f} } // 3000+
};
class DynamicVisibilityMgr
{
public:
static void Update(uint32 sessionCount);
static uint32 GetVisibilityNotifyDelay(uint32 map_type) { return VisibilitySettings[visibilitySettingsIndex][map_type].visibilityNotifyDelay; }
static uint32 GetAINotifyDelay(uint32 map_type) { return VisibilitySettings[visibilitySettingsIndex][map_type].aiNotifyDelay; }
static float GetReqMoveDistSq(uint32 map_type) { return VisibilitySettings[visibilitySettingsIndex][map_type].requiredMoveDistanceSq; }
protected:
static uint8 visibilitySettingsIndex;
};
#endif
+6 -40
View File
@@ -125,13 +125,14 @@ namespace Movement
if (args.flags.cyclic) if (args.flags.cyclic)
{ {
uint32 cyclic_point = 0; uint32 cyclic_point = 0;
if (splineflags.enter_cycle) // MoveSplineFlag::Enter_Cycle support dropped
cyclic_point = 1; // shouldn't be modified, came from client //if (splineflags & SPLINEFLAG_ENTER_CYCLE)
spline.init_cyclic_spline(&args.path[0], args.path.size(), modes[args.flags.isSmooth()], cyclic_point, args.initialOrientation); //cyclic_point = 1; // shouldn't be modified, came from client
spline.init_cyclic_spline(&args.path[0], args.path.size(), modes[args.flags.isSmooth()], cyclic_point);
} }
else else
{ {
spline.init_spline(&args.path[0], args.path.size(), modes[args.flags.isSmooth()], args.initialOrientation); spline.init_spline(&args.path[0], args.path.size(), modes[args.flags.isSmooth()]);
} }
// init spline timestamps // init spline timestamps
@@ -203,7 +204,7 @@ namespace Movement
if (!(exp)) \ if (!(exp)) \
{ \ { \
if (unit) \ if (unit) \
LOG_ERROR("misc.movesplineinitargs", "MoveSplineInitArgs::Validate: expression '{}' failed for GUID: {} Entry: {}", #exp, unit->GetGUID().ToString().c_str(), unit->GetEntry());\ LOG_ERROR("misc.movesplineinitargs", "MoveSplineInitArgs::Validate: expression '{}' failed for {}", #exp, unit->GetGUID().ToString()); \
else \ else \
LOG_ERROR("misc.movesplineinitargs", "MoveSplineInitArgs::Validate: expression '{}' failed for cyclic spline continuation", #exp); \ LOG_ERROR("misc.movesplineinitargs", "MoveSplineInitArgs::Validate: expression '{}' failed for cyclic spline continuation", #exp); \
return false;\ return false;\
@@ -272,41 +273,6 @@ namespace Movement
point_Idx = spline.first(); point_Idx = spline.first();
time_passed = time_passed % Duration(); time_passed = time_passed % Duration();
result = Movement::MoveSpline::UpdateResult(Result_NextCycle | Result_JustArrived); result = Movement::MoveSpline::UpdateResult(Result_NextCycle | Result_JustArrived);
// Remove first point from the path after one full cycle.
// That point was the position of the unit prior to entering the cycle and it shouldn't be repeated with continuous cycles.
if (splineflags.enter_cycle)
{
splineflags.enter_cycle = false;
MoveSplineInitArgs args{ (size_t)spline.getPointCount() };
args.path.assign(spline.getPoints().begin() + spline.first() + 1, spline.getPoints().begin() + spline.last());
args.facing = facing;
args.flags = splineflags;
args.path_Idx_offset = point_Idx_offset;
// MoveSplineFlag::Parabolic | MoveSplineFlag::Animation not supported currently
//args.parabolic_amplitude = ?;
//args.time_perc = ?;
args.splineId = m_Id;
args.initialOrientation = initialOrientation;
args.velocity = 1.0f; // Calculated below
args.HasVelocity = true;
args.TransformForTransport = onTransport;
if (args.Validate(nullptr))
{
// New cycle should preserve previous cycle's duration for some weird reason, even though
// the path is really different now. Blizzard is weird. Or this was just a simple oversight.
// Since our splines precalculate length with velocity in mind, if we want to find the desired
// velocity, we have to make a fake spline, calculate its duration and then compare it to the
// desired duration, thus finding out how much the velocity has to be increased for them to match.
MoveSpline tempSpline;
tempSpline.Initialize(args);
args.velocity = (float)tempSpline.Duration() / Duration();
if (args.Validate(nullptr))
init_spline(args);
}
}
} }
else else
{ {
@@ -87,7 +87,6 @@ namespace Movement
// corrent first vertex // corrent first vertex
args.path[0] = real_position; args.path[0] = real_position;
args.initialOrientation = real_position.orientation; args.initialOrientation = real_position.orientation;
args.flags.enter_cycle = args.flags.cyclic;
move_spline.onTransport = transport; move_spline.onTransport = transport;
uint32 moveFlags = unit->m_movementInfo.GetMovementFlags(); uint32 moveFlags = unit->m_movementInfo.GetMovementFlags();
@@ -67,6 +67,10 @@ namespace Movement
break; break;
} }
// add fake Enter_Cycle flag - needed for client-side cyclic movement (client will erase first spline vertex after first cycle done)
// Xinef: this flag breaks cycle for ground movement, client teleports npc between last and first point instead of using smooth movement
if (splineflags & MoveSplineFlag::Flying)
splineflags.enter_cycle = move_spline.isCyclic();
data << uint32(splineflags & uint32(~MoveSplineFlag::Mask_No_Monster_Move)); data << uint32(splineflags & uint32(~MoveSplineFlag::Mask_No_Monster_Move));
if (splineflags.animation) if (splineflags.animation)
@@ -119,12 +123,21 @@ namespace Movement
data.append<Vector3>(&spline.getPoint(2), count); data.append<Vector3>(&spline.getPoint(2), count);
} }
void WriteCatmullRomCyclicPath(const Spline<int32>& spline, ByteBuffer& data) void WriteCatmullRomCyclicPath(const Spline<int32>& spline, ByteBuffer& data, bool flying)
{ {
uint32 count = spline.getPointCount() - 4; uint32 count = spline.getPointCount() - 3;
data << count; data << uint32(count + 1);
if (flying)
{
data << spline.getPoint(1); // fake point, client will erase it from the spline after first cycle done
data.append<Vector3>(&spline.getPoint(2), count); data.append<Vector3>(&spline.getPoint(2), count);
} }
else
{
data.append<Vector3>(&spline.getPoint(2), count);
data << Vector3::zero(); //Xinef: fake point
}
}
void PacketBuilder::WriteMonsterMove(const MoveSpline& move_spline, ByteBuffer& data) void PacketBuilder::WriteMonsterMove(const MoveSpline& move_spline, ByteBuffer& data)
{ {
@@ -135,7 +148,7 @@ namespace Movement
if (splineflags & MoveSplineFlag::Mask_CatmullRom) if (splineflags & MoveSplineFlag::Mask_CatmullRom)
{ {
if (splineflags.cyclic) if (splineflags.cyclic)
WriteCatmullRomCyclicPath(spline, data); WriteCatmullRomCyclicPath(spline, data, splineflags & MoveSplineFlag::Flying);
else else
WriteCatmullRomPath(spline, data); WriteCatmullRomPath(spline, data);
} }
@@ -186,8 +199,4 @@ namespace Movement
data << (move_spline.isCyclic() ? Vector3::zero() : move_spline.FinalDestination()); data << (move_spline.isCyclic() ? Vector3::zero() : move_spline.FinalDestination());
} }
} }
void PacketBuilder::WriteSplineSync(MoveSpline const& move_spline, ByteBuffer& data)
{
data << (float)move_spline.timePassed() / move_spline.Duration();
}
} }
@@ -38,7 +38,6 @@ namespace Movement
static void WriteMonsterMove(const MoveSpline& mov, ByteBuffer& data); static void WriteMonsterMove(const MoveSpline& mov, ByteBuffer& data);
static void WriteStopMovement(Vector3 const& loc, uint32 splineId, ByteBuffer& data); static void WriteStopMovement(Vector3 const& loc, uint32 splineId, ByteBuffer& data);
static void WriteCreate(const MoveSpline& mov, ByteBuffer& data); static void WriteCreate(const MoveSpline& mov, ByteBuffer& data);
static void WriteSplineSync(MoveSpline const& mov, ByteBuffer& data);
}; };
} }
#endif // AC_PACKET_BUILDER_H #endif // AC_PACKET_BUILDER_H
+9 -11
View File
@@ -199,25 +199,23 @@ namespace Movement
return length; return length;
} }
void SplineBase::init_spline(const Vector3* controls, index_type count, EvaluationMode m, float orientation) void SplineBase::init_spline(const Vector3* controls, index_type count, EvaluationMode m)
{ {
m_mode = m; m_mode = m;
cyclic = false; cyclic = false;
initialOrientation = orientation;
(this->*initializers[m_mode])(controls, count, 0); (this->*initializers[m_mode])(controls, count, cyclic, 0);
} }
void SplineBase::init_cyclic_spline(const Vector3* controls, index_type count, EvaluationMode m, index_type cyclic_point, float orientation) void SplineBase::init_cyclic_spline(const Vector3* controls, index_type count, EvaluationMode m, index_type cyclic_point)
{ {
m_mode = m; m_mode = m;
cyclic = true; cyclic = true;
initialOrientation = orientation;
(this->*initializers[m_mode])(controls, count, cyclic_point); (this->*initializers[m_mode])(controls, count, cyclic, cyclic_point);
} }
void SplineBase::InitLinear(const Vector3* controls, index_type count, index_type cyclic_point) void SplineBase::InitLinear(const Vector3* controls, index_type count, bool cyclic, index_type cyclic_point)
{ {
ASSERT(count >= 2); ASSERT(count >= 2);
const int real_size = count + 1; const int real_size = count + 1;
@@ -237,7 +235,7 @@ namespace Movement
index_hi = cyclic ? count : (count - 1); index_hi = cyclic ? count : (count - 1);
} }
void SplineBase::InitCatmullRom(const Vector3* controls, index_type count, index_type cyclic_point) void SplineBase::InitCatmullRom(const Vector3* controls, index_type count, bool cyclic, index_type cyclic_point)
{ {
const int real_size = count + (cyclic ? (1 + 2) : (1 + 1)); const int real_size = count + (cyclic ? (1 + 2) : (1 + 1));
@@ -255,14 +253,14 @@ namespace Movement
if (cyclic_point == 0) if (cyclic_point == 0)
points[0] = controls[count - 1]; points[0] = controls[count - 1];
else else
points[0] = controls[0] - G3D::Vector3{ std::cos(initialOrientation), std::sin(initialOrientation), 0.0f }; points[0] = controls[0].lerp(controls[1], -1);
points[high_index + 1] = controls[cyclic_point]; points[high_index + 1] = controls[cyclic_point];
points[high_index + 2] = controls[cyclic_point + 1]; points[high_index + 2] = controls[cyclic_point + 1];
} }
else else
{ {
points[0] = controls[0] - G3D::Vector3{ std::cos(initialOrientation), std::sin(initialOrientation), 0.0f }; points[0] = controls[0].lerp(controls[1], -1);
points[high_index + 1] = controls[count - 1]; points[high_index + 1] = controls[count - 1];
} }
@@ -270,7 +268,7 @@ namespace Movement
index_hi = high_index + (cyclic ? 1 : 0); index_hi = high_index + (cyclic ? 1 : 0);
} }
void SplineBase::InitBezier3(const Vector3* controls, index_type count, index_type /*cyclic_point*/) void SplineBase::InitBezier3(const Vector3* controls, index_type count, bool /*cyclic*/, index_type /*cyclic_point*/)
{ {
index_type c = count / 3u * 3u; index_type c = count / 3u * 3u;
index_type t = c / 3u; index_type t = c / 3u;
+11 -17
View File
@@ -48,7 +48,6 @@ namespace Movement
uint8 m_mode{UninitializedMode}; uint8 m_mode{UninitializedMode};
bool cyclic{false}; bool cyclic{false};
float initialOrientation{0.f};
enum enum
{ {
@@ -78,15 +77,15 @@ namespace Movement
typedef float (SplineBase::*SegLenghtMethtod)(index_type) const; typedef float (SplineBase::*SegLenghtMethtod)(index_type) const;
static SegLenghtMethtod seglengths[ModesEnd]; static SegLenghtMethtod seglengths[ModesEnd];
void InitLinear(const Vector3*, index_type, index_type); void InitLinear(const Vector3*, index_type, bool, index_type);
void InitCatmullRom(const Vector3*, index_type, index_type); void InitCatmullRom(const Vector3*, index_type, bool, index_type);
void InitBezier3(const Vector3*, index_type, index_type); void InitBezier3(const Vector3*, index_type, bool, index_type);
typedef void (SplineBase::*InitMethtod)(const Vector3*, index_type, index_type); typedef void (SplineBase::*InitMethtod)(const Vector3*, index_type, bool, index_type);
static InitMethtod initializers[ModesEnd]; static InitMethtod initializers[ModesEnd];
void UninitializedSplineEvaluationMethod(index_type, float, Vector3&) const { ABORT(); } void UninitializedSplineEvaluationMethod(index_type, float, Vector3&) const { ABORT(); }
[[nodiscard]] float UninitializedSplineSegLenghtMethod(index_type) const { ABORT(); return 0.0f; } [[nodiscard]] float UninitializedSplineSegLenghtMethod(index_type) const { ABORT(); }
void UninitializedSplineInitMethod(Vector3 const*, index_type, index_type) { ABORT(); } void UninitializedSplineInitMethod(Vector3 const*, index_type, bool, index_type) { ABORT(); }
public: public:
explicit SplineBase() = default; explicit SplineBase() = default;
@@ -117,8 +116,8 @@ namespace Movement
[[nodiscard]] const Vector3& getPoint(index_type i) const { return points[i];} [[nodiscard]] const Vector3& getPoint(index_type i) const { return points[i];}
/** Initializes spline. Don't call other methods while spline not initialized. */ /** Initializes spline. Don't call other methods while spline not initialized. */
void init_spline(const Vector3* controls, index_type count, EvaluationMode m, float orientation); void init_spline(const Vector3* controls, index_type count, EvaluationMode m);
void init_cyclic_spline(const Vector3* controls, index_type count, EvaluationMode m, index_type cyclic_point, float orientation); void init_cyclic_spline(const Vector3* controls, index_type count, EvaluationMode m, index_type cyclic_point);
/** As i can see there are a lot of ways how spline can be initialized /** As i can see there are a lot of ways how spline can be initialized
would be no harm to have some custom initializers. */ would be no harm to have some custom initializers. */
@@ -171,8 +170,8 @@ namespace Movement
void computeIndex(float t, index_type& out_idx, float& out_u) const; void computeIndex(float t, index_type& out_idx, float& out_u) const;
/** Initializes spline. Don't call other methods while spline not initialized. */ /** Initializes spline. Don't call other methods while spline not initialized. */
void init_spline(const Vector3* controls, index_type count, EvaluationMode m, float orientation = 0) { SplineBase::init_spline(controls, count, m, orientation);} void init_spline(const Vector3* controls, index_type count, EvaluationMode m) { SplineBase::init_spline(controls, count, m);}
void init_cyclic_spline(const Vector3* controls, index_type count, EvaluationMode m, index_type cyclic_point, float orientation = 0) { SplineBase::init_cyclic_spline(controls, count, m, cyclic_point, orientation);} void init_cyclic_spline(const Vector3* controls, index_type count, EvaluationMode m, index_type cyclic_point) { SplineBase::init_cyclic_spline(controls, count, m, cyclic_point);}
/** Initializes lengths with SplineBase::SegLength method. */ /** Initializes lengths with SplineBase::SegLength method. */
void initLengths(); void initLengths();
@@ -198,12 +197,7 @@ namespace Movement
} }
/** Returns length of the whole spline. */ /** Returns length of the whole spline. */
[[nodiscard]] length_type length() const [[nodiscard]] length_type length() const { return lengths[index_hi];}
{
if (lengths.empty())
return 0;
return lengths[index_hi];
}
/** Returns length between given nodes. */ /** Returns length between given nodes. */
[[nodiscard]] length_type length(index_type first, index_type last) const { return lengths[last] - lengths[first];} [[nodiscard]] length_type length(index_type first, index_type last) const { return lengths[last] - lengths[first];}
[[nodiscard]] length_type length(index_type Idx) const { return lengths[Idx];} [[nodiscard]] length_type length(index_type Idx) const { return lengths[Idx];}
@@ -1602,8 +1602,8 @@ void AuraEffect::HandleModInvisibility(AuraApplication const* aurApp, uint8 mode
target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION);
} }
if (target->IsInWorld()) target->UpdateObjectVisibility(target->GetTypeId() == TYPEID_PLAYER || target->GetOwnerGUID().IsPlayer() || target->GetMap()->Instanceable(), true);
target->UpdateObjectVisibility(); target->bRequestForcedVisibilityUpdate = false;
} }
void AuraEffect::HandleModStealthDetect(AuraApplication const* aurApp, uint8 mode, bool apply) const void AuraEffect::HandleModStealthDetect(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -1676,8 +1676,8 @@ void AuraEffect::HandleModStealth(AuraApplication const* aurApp, uint8 mode, boo
target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION); target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION);
} }
if (target->IsInWorld()) target->UpdateObjectVisibility(target->GetTypeId() == TYPEID_PLAYER || target->GetOwnerGUID().IsPlayer() || target->GetMap()->Instanceable(), true);
target->UpdateObjectVisibility(); target->bRequestForcedVisibilityUpdate = false;
} }
void AuraEffect::HandleModStealthLevel(AuraApplication const* aurApp, uint8 mode, bool apply) const void AuraEffect::HandleModStealthLevel(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -1841,6 +1841,7 @@ void AuraEffect::HandlePhase(AuraApplication const* aurApp, uint8 mode, bool app
if (!target->GetMap()->Instanceable()) if (!target->GetMap()->Instanceable())
{ {
target->UpdateObjectVisibility(false); target->UpdateObjectVisibility(false);
target->m_last_notify_position.Relocate(-5000.0f, -5000.0f, -5000.0f);
} }
else else
target->UpdateObjectVisibility(); target->UpdateObjectVisibility();
@@ -2821,7 +2822,7 @@ void AuraEffect::HandleFeignDeath(AuraApplication const* aurApp, uint8 mode, boo
*/ */
UnitList targets; UnitList targets;
Acore::AnyUnfriendlyUnitInObjectRangeCheck u_check(target, target, target->GetVisibilityRange()); Acore::AnyUnfriendlyUnitInObjectRangeCheck u_check(target, target, target->GetVisibilityRange()); // no VISIBILITY_COMPENSATION, distance is enough
Acore::UnitListSearcher<Acore::AnyUnfriendlyUnitInObjectRangeCheck> searcher(target, targets, u_check); Acore::UnitListSearcher<Acore::AnyUnfriendlyUnitInObjectRangeCheck> searcher(target, targets, u_check);
Cell::VisitAllObjects(target, searcher, target->GetMap()->GetVisibilityRange()); Cell::VisitAllObjects(target, searcher, target->GetMap()->GetVisibilityRange());
for (UnitList::iterator iter = targets.begin(); iter != targets.end(); ++iter) for (UnitList::iterator iter = targets.begin(); iter != targets.end(); ++iter)
+3 -3
View File
@@ -4048,7 +4048,7 @@ void Spell::EffectSanctuary(SpellEffIndex /*effIndex*/)
} }
UnitList targets; UnitList targets;
Acore::AnyUnfriendlyUnitInObjectRangeCheck u_check(unitTarget, unitTarget, unitTarget->GetVisibilityRange()); Acore::AnyUnfriendlyUnitInObjectRangeCheck u_check(unitTarget, unitTarget, unitTarget->GetVisibilityRange()); // no VISIBILITY_COMPENSATION, distance is enough
Acore::UnitListSearcher<Acore::AnyUnfriendlyUnitInObjectRangeCheck> searcher(unitTarget, targets, u_check); Acore::UnitListSearcher<Acore::AnyUnfriendlyUnitInObjectRangeCheck> searcher(unitTarget, targets, u_check);
Cell::VisitAllObjects(unitTarget, searcher, unitTarget->GetVisibilityRange()); Cell::VisitAllObjects(unitTarget, searcher, unitTarget->GetVisibilityRange());
for (UnitList::iterator iter = targets.begin(); iter != targets.end(); ++iter) for (UnitList::iterator iter = targets.begin(); iter != targets.end(); ++iter)
@@ -4787,7 +4787,7 @@ void Spell::EffectForceDeselect(SpellEffIndex /*effIndex*/)
WorldPacket data(SMSG_CLEAR_TARGET, 8); WorldPacket data(SMSG_CLEAR_TARGET, 8);
data << m_caster->GetGUID(); data << m_caster->GetGUID();
float dist = m_caster->GetVisibilityRange(); float dist = m_caster->GetVisibilityRange() + VISIBILITY_COMPENSATION;
Acore::MessageDistDelivererToHostile notifier(m_caster, &data, dist); Acore::MessageDistDelivererToHostile notifier(m_caster, &data, dist);
Cell::VisitWorldObjects(m_caster, notifier, dist); Cell::VisitWorldObjects(m_caster, notifier, dist);
@@ -4812,7 +4812,7 @@ void Spell::EffectForceDeselect(SpellEffIndex /*effIndex*/)
return; return;
UnitList targets; UnitList targets;
Acore::AnyUnfriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, m_caster->GetVisibilityRange()); Acore::AnyUnfriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, m_caster->GetVisibilityRange()); // no VISIBILITY_COMPENSATION, distance is enough
Acore::UnitListSearcher<Acore::AnyUnfriendlyUnitInObjectRangeCheck> searcher(m_caster, targets, u_check); Acore::UnitListSearcher<Acore::AnyUnfriendlyUnitInObjectRangeCheck> searcher(m_caster, targets, u_check);
Cell::VisitAllObjects(m_caster, searcher, m_caster->GetVisibilityRange()); Cell::VisitAllObjects(m_caster, searcher, m_caster->GetVisibilityRange());
for (UnitList::iterator iter = targets.begin(); iter != targets.end(); ++iter) for (UnitList::iterator iter = targets.begin(); iter != targets.end(); ++iter)
-2
View File
@@ -72,7 +72,6 @@ enum WorldBoolConfigs
CONFIG_ADDON_CHANNEL, CONFIG_ADDON_CHANNEL,
CONFIG_ALLOW_PLAYER_COMMANDS, CONFIG_ALLOW_PLAYER_COMMANDS,
CONFIG_CLEAN_CHARACTER_DB, CONFIG_CLEAN_CHARACTER_DB,
CONFIG_GRID_UNLOAD,
CONFIG_STATS_SAVE_ONLY_ON_LOGOUT, CONFIG_STATS_SAVE_ONLY_ON_LOGOUT,
CONFIG_ALLOW_TWO_SIDE_ACCOUNTS, CONFIG_ALLOW_TWO_SIDE_ACCOUNTS,
CONFIG_ALLOW_TWO_SIDE_INTERACTION_CALENDAR, CONFIG_ALLOW_TWO_SIDE_INTERACTION_CALENDAR,
@@ -209,7 +208,6 @@ enum WorldFloatConfigs
enum WorldIntConfigs enum WorldIntConfigs
{ {
CONFIG_COMPRESSION = 0, CONFIG_COMPRESSION = 0,
CONFIG_INTERVAL_GRIDCLEAN,
CONFIG_INTERVAL_MAPUPDATE, CONFIG_INTERVAL_MAPUPDATE,
CONFIG_INTERVAL_CHANGEWEATHER, CONFIG_INTERVAL_CHANGEWEATHER,
CONFIG_INTERVAL_DISCONNECT_TOLERANCE, CONFIG_INTERVAL_DISCONNECT_TOLERANCE,
+13 -27
View File
@@ -44,6 +44,7 @@
#include "DBCStores.h" #include "DBCStores.h"
#include "DatabaseEnv.h" #include "DatabaseEnv.h"
#include "DisableMgr.h" #include "DisableMgr.h"
#include "DynamicVisibility.h"
#include "GameEventMgr.h" #include "GameEventMgr.h"
#include "GameGraveyard.h" #include "GameGraveyard.h"
#include "GameTime.h" #include "GameTime.h"
@@ -108,10 +109,6 @@ float World::_maxVisibleDistanceOnContinents = DEFAULT_VISIBILITY_DISTANCE;
float World::_maxVisibleDistanceInInstances = DEFAULT_VISIBILITY_INSTANCE; float World::_maxVisibleDistanceInInstances = DEFAULT_VISIBILITY_INSTANCE;
float World::_maxVisibleDistanceInBGArenas = DEFAULT_VISIBILITY_BGARENAS; float World::_maxVisibleDistanceInBGArenas = DEFAULT_VISIBILITY_BGARENAS;
int32 World::m_visibility_notify_periodOnContinents = DEFAULT_VISIBILITY_NOTIFY_PERIOD;
int32 World::m_visibility_notify_periodInInstances = DEFAULT_VISIBILITY_NOTIFY_PERIOD;
int32 World::m_visibility_notify_periodInBGArenas = DEFAULT_VISIBILITY_NOTIFY_PERIOD;
Realm realm; Realm realm;
/// World constructor /// World constructor
@@ -657,14 +654,6 @@ void World::LoadConfigSettings(bool reload)
LOG_ERROR("server.loading", "PlayerSave.Stats.MinLevel ({}) must be in range 0..80. Using default, do not save character stats (0).", _int_configs[CONFIG_MIN_LEVEL_STAT_SAVE]); LOG_ERROR("server.loading", "PlayerSave.Stats.MinLevel ({}) must be in range 0..80. Using default, do not save character stats (0).", _int_configs[CONFIG_MIN_LEVEL_STAT_SAVE]);
_int_configs[CONFIG_MIN_LEVEL_STAT_SAVE] = 0; _int_configs[CONFIG_MIN_LEVEL_STAT_SAVE] = 0;
} }
_int_configs[CONFIG_INTERVAL_GRIDCLEAN] = sConfigMgr->GetOption("GridCleanUpDelay", 5 * MINUTE * IN_MILLISECONDS);
if (_int_configs[CONFIG_INTERVAL_GRIDCLEAN] < MIN_GRID_DELAY)
{
LOG_ERROR("server.loading", "GridCleanUpDelay ({}) must be greater {}. Use this minimal value.", _int_configs[CONFIG_INTERVAL_GRIDCLEAN], MIN_GRID_DELAY);
_int_configs[CONFIG_INTERVAL_GRIDCLEAN] = MIN_GRID_DELAY;
}
if (reload)
sMapMgr->SetGridCleanUpDelay(_int_configs[CONFIG_INTERVAL_GRIDCLEAN]);
_int_configs[CONFIG_INTERVAL_MAPUPDATE] = sConfigMgr->GetOption<int32>("MapUpdateInterval", 10); _int_configs[CONFIG_INTERVAL_MAPUPDATE] = sConfigMgr->GetOption<int32>("MapUpdateInterval", 10);
if (_int_configs[CONFIG_INTERVAL_MAPUPDATE] < MIN_MAP_UPDATE_DELAY) if (_int_configs[CONFIG_INTERVAL_MAPUPDATE] < MIN_MAP_UPDATE_DELAY)
@@ -1259,10 +1248,6 @@ void World::LoadConfigSettings(bool reload)
_maxVisibleDistanceInBGArenas = MAX_VISIBILITY_DISTANCE; _maxVisibleDistanceInBGArenas = MAX_VISIBILITY_DISTANCE;
} }
m_visibility_notify_periodOnContinents = sConfigMgr->GetOption<int32>("Visibility.Notify.Period.OnContinents", DEFAULT_VISIBILITY_NOTIFY_PERIOD);
m_visibility_notify_periodInInstances = sConfigMgr->GetOption<int32>("Visibility.Notify.Period.InInstances", DEFAULT_VISIBILITY_NOTIFY_PERIOD);
m_visibility_notify_periodInBGArenas = sConfigMgr->GetOption<int32>("Visibility.Notify.Period.InBGArenas", DEFAULT_VISIBILITY_NOTIFY_PERIOD);
///- Load the CharDelete related config options ///- Load the CharDelete related config options
_int_configs[CONFIG_CHARDELETE_METHOD] = sConfigMgr->GetOption<int32>("CharDelete.Method", 0); _int_configs[CONFIG_CHARDELETE_METHOD] = sConfigMgr->GetOption<int32>("CharDelete.Method", 0);
_int_configs[CONFIG_CHARDELETE_MIN_LEVEL] = sConfigMgr->GetOption<int32>("CharDelete.MinLevel", 0); _int_configs[CONFIG_CHARDELETE_MIN_LEVEL] = sConfigMgr->GetOption<int32>("CharDelete.MinLevel", 0);
@@ -1420,16 +1405,8 @@ void World::LoadConfigSettings(bool reload)
// Prevent players AFK from being logged out // Prevent players AFK from being logged out
_int_configs[CONFIG_AFK_PREVENT_LOGOUT] = sConfigMgr->GetOption<int32>("PreventAFKLogout", 0); _int_configs[CONFIG_AFK_PREVENT_LOGOUT] = sConfigMgr->GetOption<int32>("PreventAFKLogout", 0);
// Unload grids to save memory. Can be disabled if enough memory is available to speed up moving players to new grids.
_bool_configs[CONFIG_GRID_UNLOAD] = sConfigMgr->GetOption<bool>("GridUnload", true);
// Preload all grids of all non-instanced maps // Preload all grids of all non-instanced maps
_bool_configs[CONFIG_PRELOAD_ALL_NON_INSTANCED_MAP_GRIDS] = sConfigMgr->GetOption<bool>("PreloadAllNonInstancedMapGrids", false); _bool_configs[CONFIG_PRELOAD_ALL_NON_INSTANCED_MAP_GRIDS] = sConfigMgr->GetOption<bool>("PreloadAllNonInstancedMapGrids", false);
if (_bool_configs[CONFIG_PRELOAD_ALL_NON_INSTANCED_MAP_GRIDS] && _bool_configs[CONFIG_GRID_UNLOAD])
{
LOG_ERROR("server.loading", "PreloadAllNonInstancedMapGrids enabled, but GridUnload also enabled. GridUnload must be disabled to enable base map pre-loading. Base map pre-loading disabled");
_bool_configs[CONFIG_PRELOAD_ALL_NON_INSTANCED_MAP_GRIDS] = false;
}
// ICC buff override // ICC buff override
_int_configs[CONFIG_ICC_BUFF_HORDE] = sConfigMgr->GetOption<int32>("ICC.Buff.Horde", 73822); _int_configs[CONFIG_ICC_BUFF_HORDE] = sConfigMgr->GetOption<int32>("ICC.Buff.Horde", 73822);
@@ -2172,14 +2149,21 @@ void World::SetInitialWorldSettings()
{ {
LOG_INFO("server.loading", "Loading All Grids For All Non-Instanced Maps..."); LOG_INFO("server.loading", "Loading All Grids For All Non-Instanced Maps...");
sMapMgr->DoForAllMaps([](Map* map) for (uint32 i = 0; i < sMapStore.GetNumRows(); ++i)
{ {
if (!map->Instanceable()) MapEntry const* mapEntry = sMapStore.LookupEntry(i);
if (mapEntry && !mapEntry->Instanceable())
{
Map* map = sMapMgr->CreateBaseMap(mapEntry->MapID);
if (map)
{ {
LOG_INFO("server.loading", ">> Loading All Grids For Map {}", map->GetId()); LOG_INFO("server.loading", ">> Loading All Grids For Map {}", map->GetId());
map->LoadAllCells(); map->LoadAllCells();
} }
}); }
}
} }
uint32 startupDuration = GetMSTimeDiffToNow(startupBegin); uint32 startupDuration = GetMSTimeDiffToNow(startupBegin);
@@ -2255,6 +2239,8 @@ void World::Update(uint32 diff)
// Record update if recording set in log and diff is greater then minimum set in log // Record update if recording set in log and diff is greater then minimum set in log
sWorldUpdateTime.RecordUpdateTime(GameTime::GetGameTimeMS(), diff, GetActiveSessionCount()); sWorldUpdateTime.RecordUpdateTime(GameTime::GetGameTimeMS(), diff, GetActiveSessionCount());
DynamicVisibilityMgr::Update(GetActiveSessionCount());
///- Update the different timers ///- Update the different timers
for (int i = 0; i < WUPDATE_COUNT; ++i) for (int i = 0; i < WUPDATE_COUNT; ++i)
{ {
-8
View File
@@ -322,10 +322,6 @@ public:
static float GetMaxVisibleDistanceInInstances() { return _maxVisibleDistanceInInstances; } static float GetMaxVisibleDistanceInInstances() { return _maxVisibleDistanceInInstances; }
static float GetMaxVisibleDistanceInBGArenas() { return _maxVisibleDistanceInBGArenas; } static float GetMaxVisibleDistanceInBGArenas() { return _maxVisibleDistanceInBGArenas; }
static int32 GetVisibilityNotifyPeriodOnContinents() { return m_visibility_notify_periodOnContinents; }
static int32 GetVisibilityNotifyPeriodInInstances() { return m_visibility_notify_periodInInstances; }
static int32 GetVisibilityNotifyPeriodInBGArenas() { return m_visibility_notify_periodInBGArenas; }
// our: needed for arena spectator subscriptions // our: needed for arena spectator subscriptions
uint32 GetNextWhoListUpdateDelaySecs() override; uint32 GetNextWhoListUpdateDelaySecs() override;
@@ -413,10 +409,6 @@ private:
static float _maxVisibleDistanceInInstances; static float _maxVisibleDistanceInInstances;
static float _maxVisibleDistanceInBGArenas; static float _maxVisibleDistanceInBGArenas;
static int32 m_visibility_notify_periodOnContinents;
static int32 m_visibility_notify_periodInInstances;
static int32 m_visibility_notify_periodInBGArenas;
std::string _realmName; std::string _realmName;
// CLI command holder to be thread safe // CLI command holder to be thread safe
@@ -327,7 +327,6 @@ public:
if (Creature* nefarian = me->SummonCreature(NPC_NEFARIAN, NefarianSpawn)) if (Creature* nefarian = me->SummonCreature(NPC_NEFARIAN, NefarianSpawn))
{ {
nefarian->setActive(true); nefarian->setActive(true);
nefarian->SetFarVisible(true);
nefarian->SetCanFly(true); nefarian->SetCanFly(true);
nefarian->SetDisableGravity(true); nefarian->SetDisableGravity(true);
nefarian->GetMotionMaster()->MovePath(NEFARIAN_PATH, false); nefarian->GetMotionMaster()->MovePath(NEFARIAN_PATH, false);
@@ -425,7 +425,6 @@ public:
{ {
nefarius->SetPhaseMask(1, true); nefarius->SetPhaseMask(1, true);
nefarius->setActive(true); nefarius->setActive(true);
nefarius->SetFarVisible(true);
nefarius->Respawn(); nefarius->Respawn();
nefarius->GetMotionMaster()->MoveTargetedHome(); nefarius->GetMotionMaster()->MoveTargetedHome();
} }
@@ -105,7 +105,6 @@ struct boss_nightbane : public BossAI
me->SetDisableGravity(_intro); me->SetDisableGravity(_intro);
me->SetWalk(false); me->SetWalk(false);
me->setActive(true); me->setActive(true);
me->SetFarVisible(true);
if (instance) if (instance)
{ {
@@ -55,7 +55,6 @@ public:
void Reset() override void Reset() override
{ {
me->setActive(true); me->setActive(true);
me->SetFarVisible(true);
me->SetVisible(false); me->SetVisible(false);
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
me->SetCanFly(true); me->SetCanFly(true);
+2
View File
@@ -159,6 +159,8 @@ struct npc_midsummer_torch_target : public ScriptedAI
int8 num = urand(0, posVec.size() - 1); int8 num = urand(0, posVec.size() - 1);
Position pos; Position pos;
pos.Relocate(posVec.at(num)); pos.Relocate(posVec.at(num));
me->m_last_notify_position.Relocate(0.0f, 0.0f, 0.0f);
me->m_last_notify_mstime = GameTime::GetGameTimeMS().count() + 10000;
me->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation()); me->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation());
} }
@@ -347,7 +347,6 @@ void hyjalAI::Reset()
{ {
IsDummy = false; IsDummy = false;
me->setActive(true); me->setActive(true);
me->SetFarVisible(true);
// GUIDs // GUIDs
PlayerGUID.Clear(); PlayerGUID.Clear();
BossGUID[0].Clear(); BossGUID[0].Clear();
@@ -494,7 +493,6 @@ void hyjalAI::SummonCreature(uint32 entry, float Base[4][3])
creature->SetWalk(false); creature->SetWalk(false);
creature->setActive(true); creature->setActive(true);
creature->SetFarVisible(true);
switch (entry) switch (entry)
{ {
case NECROMANCER: case NECROMANCER:
@@ -1023,7 +1021,6 @@ void hyjalAI::DoOverrun(uint32 faction, const uint32 diff)
CAST_AI(hyjal_trashAI, unit->AI())->IsOverrun = true; CAST_AI(hyjal_trashAI, unit->AI())->IsOverrun = true;
CAST_AI(hyjal_trashAI, unit->AI())->OverrunType = i; CAST_AI(hyjal_trashAI, unit->AI())->OverrunType = i;
unit->setActive(true); unit->setActive(true);
unit->SetFarVisible(true);
} }
} }
for (uint8 i = 0; i < 3; ++i)//summon 3 abominations for (uint8 i = 0; i < 3; ++i)//summon 3 abominations
@@ -1036,7 +1033,6 @@ void hyjalAI::DoOverrun(uint32 faction, const uint32 diff)
CAST_AI(hyjal_trashAI, unit->AI())->IsOverrun = true; CAST_AI(hyjal_trashAI, unit->AI())->IsOverrun = true;
CAST_AI(hyjal_trashAI, unit->AI())->OverrunType = i; CAST_AI(hyjal_trashAI, unit->AI())->OverrunType = i;
unit->setActive(true); unit->setActive(true);
unit->SetFarVisible(true);
} }
} }
for (uint8 i = 0; i < 5; ++i)//summon 5 gargoyles for (uint8 i = 0; i < 5; ++i)//summon 5 gargoyles
@@ -1049,7 +1045,6 @@ void hyjalAI::DoOverrun(uint32 faction, const uint32 diff)
CAST_AI(hyjal_trashAI, unit->AI())->IsOverrun = true; CAST_AI(hyjal_trashAI, unit->AI())->IsOverrun = true;
CAST_AI(hyjal_trashAI, unit->AI())->OverrunType = i; CAST_AI(hyjal_trashAI, unit->AI())->OverrunType = i;
unit->setActive(true); unit->setActive(true);
unit->SetFarVisible(true);
} }
} }
break; break;
@@ -1067,7 +1062,6 @@ void hyjalAI::DoOverrun(uint32 faction, const uint32 diff)
CAST_AI(hyjal_trashAI, unit->AI())->IsOverrun = true; CAST_AI(hyjal_trashAI, unit->AI())->IsOverrun = true;
CAST_AI(hyjal_trashAI, unit->AI())->OverrunType = i; CAST_AI(hyjal_trashAI, unit->AI())->OverrunType = i;
unit->setActive(true); unit->setActive(true);
unit->SetFarVisible(true);
} }
} }
for (uint8 i = 0; i < 25; ++i)//summon 25 ghouls for (uint8 i = 0; i < 25; ++i)//summon 25 ghouls
@@ -1080,7 +1074,6 @@ void hyjalAI::DoOverrun(uint32 faction, const uint32 diff)
CAST_AI(hyjal_trashAI, unit->AI())->IsOverrun = true; CAST_AI(hyjal_trashAI, unit->AI())->IsOverrun = true;
CAST_AI(hyjal_trashAI, unit->AI())->OverrunType = i; CAST_AI(hyjal_trashAI, unit->AI())->OverrunType = i;
unit->setActive(true); unit->setActive(true);
unit->SetFarVisible(true);
} }
} }
for (uint8 i = 0; i < 5; ++i)//summon 5 abominations for (uint8 i = 0; i < 5; ++i)//summon 5 abominations
@@ -1093,7 +1086,6 @@ void hyjalAI::DoOverrun(uint32 faction, const uint32 diff)
CAST_AI(hyjal_trashAI, unit->AI())->IsOverrun = true; CAST_AI(hyjal_trashAI, unit->AI())->IsOverrun = true;
CAST_AI(hyjal_trashAI, unit->AI())->OverrunType = i; CAST_AI(hyjal_trashAI, unit->AI())->OverrunType = i;
unit->setActive(true); unit->setActive(true);
unit->SetFarVisible(true);
} }
} }
break; break;
@@ -389,7 +389,6 @@ public:
if (action == ACTION_BALTHARUS_DEATH) if (action == ACTION_BALTHARUS_DEATH)
{ {
me->setActive(true); me->setActive(true);
me->SetFarVisible(true);
_isIntro = false; _isIntro = false;
_events.ScheduleEvent(EVENT_XERESTRASZA_EVENT_0, 6s); _events.ScheduleEvent(EVENT_XERESTRASZA_EVENT_0, 6s);
@@ -339,7 +339,6 @@ public:
events.ScheduleEvent(EVENT_ICY_GRIP, 33s + 500ms, EVENT_GROUP_LAND_PHASE); events.ScheduleEvent(EVENT_ICY_GRIP, 33s + 500ms, EVENT_GROUP_LAND_PHASE);
me->setActive(true); me->setActive(true);
me->SetFarVisible(true);
me->SetInCombatWithZone(); me->SetInCombatWithZone();
instance->SetBossState(DATA_SINDRAGOSA, IN_PROGRESS); instance->SetBossState(DATA_SINDRAGOSA, IN_PROGRESS);
@@ -378,7 +377,6 @@ public:
return; return;
me->setActive(true); me->setActive(true);
me->SetFarVisible(true);
me->SetDisableGravity(true); me->SetDisableGravity(true);
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE); me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
me->SetSpeed(MOVE_RUN, 4.28571f); me->SetSpeed(MOVE_RUN, 4.28571f);
@@ -1409,7 +1407,6 @@ public:
return; return;
me->setActive(true); me->setActive(true);
me->SetFarVisible(true);
me->SetImmuneToPC(true); me->SetImmuneToPC(true);
float moveTime = me->GetExactDist(&SpinestalkerFlyPos) / (me->GetSpeed(MOVE_RUN) * 0.001f); float moveTime = me->GetExactDist(&SpinestalkerFlyPos) / (me->GetSpeed(MOVE_RUN) * 0.001f);
me->m_Events.AddEvent(new FrostwyrmLandEvent(*me, SpinestalkerLandPos), me->m_Events.CalculateTime(uint64(moveTime) + 250)); me->m_Events.AddEvent(new FrostwyrmLandEvent(*me, SpinestalkerLandPos), me->m_Events.CalculateTime(uint64(moveTime) + 250));
@@ -1426,7 +1423,6 @@ public:
return; return;
me->setActive(false); me->setActive(false);
me->SetFarVisible(false);
me->SetDisableGravity(false); me->SetDisableGravity(false);
me->SetHomePosition(SpinestalkerLandPos); me->SetHomePosition(SpinestalkerLandPos);
me->SetFacingTo(SpinestalkerLandPos.GetOrientation()); me->SetFacingTo(SpinestalkerLandPos.GetOrientation());
@@ -1542,7 +1538,6 @@ public:
return; return;
me->setActive(true); me->setActive(true);
me->SetFarVisible(true);
me->SetImmuneToPC(true); me->SetImmuneToPC(true);
float moveTime = me->GetExactDist(&RimefangFlyPos) / (me->GetSpeed(MOVE_RUN) * 0.001f); float moveTime = me->GetExactDist(&RimefangFlyPos) / (me->GetSpeed(MOVE_RUN) * 0.001f);
me->m_Events.AddEvent(new FrostwyrmLandEvent(*me, RimefangLandPos), me->m_Events.CalculateTime(uint64(moveTime) + 250)); me->m_Events.AddEvent(new FrostwyrmLandEvent(*me, RimefangLandPos), me->m_Events.CalculateTime(uint64(moveTime) + 250));
@@ -1561,8 +1556,6 @@ public:
if (point == POINT_FROSTWYRM_LAND) if (point == POINT_FROSTWYRM_LAND)
{ {
me->setActive(false); me->setActive(false);
me->SetFarVisible(false);
me->SetFarVisible(false);
me->SetDisableGravity(false); me->SetDisableGravity(false);
me->SetHomePosition(RimefangLandPos); me->SetHomePosition(RimefangLandPos);
me->SetFacingTo(RimefangLandPos.GetOrientation()); me->SetFacingTo(RimefangLandPos.GetOrientation());
@@ -484,7 +484,6 @@ public:
uint32 introDelay = 0; uint32 introDelay = 0;
me->setActive(true); me->setActive(true);
me->SetFarVisible(true);
me->SetInCombatWithZone(); me->SetInCombatWithZone();
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE); me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->SetImmuneToNPC(true); me->SetImmuneToNPC(true);
@@ -175,7 +175,6 @@ public:
{ {
me->SetDisableGravity(true); me->SetDisableGravity(true);
me->setActive(true); me->setActive(true);
me->SetFarVisible(true);
Reset(); Reset();
} }
@@ -517,7 +517,6 @@ public:
if (m_pInstance && !_encounterFinished) if (m_pInstance && !_encounterFinished)
m_pInstance->SetData(TYPE_THORIM, IN_PROGRESS); m_pInstance->SetData(TYPE_THORIM, IN_PROGRESS);
me->setActive(true); me->setActive(true);
me->SetFarVisible(true);
DisableThorim(true); DisableThorim(true);
me->CastSpell(me, SPELL_SHEATH_OF_LIGHTNING, true); me->CastSpell(me, SPELL_SHEATH_OF_LIGHTNING, true);
//me->CastSpell(me, SPELL_TOUCH_OF_DOMINION, true); //me->CastSpell(me, SPELL_TOUCH_OF_DOMINION, true);
@@ -443,6 +443,8 @@ public:
GetUnitOwner()->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE); GetUnitOwner()->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
GetUnitOwner()->SetStandState(UNIT_STAND_STATE_DEAD); GetUnitOwner()->SetStandState(UNIT_STAND_STATE_DEAD);
GetUnitOwner()->m_last_notify_position.Relocate(0.0f, 0.0f, 0.0f);
GetUnitOwner()->m_delayed_unit_relocation_timer = 1000;
} }
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)