diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 3d1a336f8..138bfda42 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -125,7 +125,7 @@ m_lootMoney(0), m_lootGroupRecipientId(0), m_corpseDecayTimer(0), m_respawnTime(0), m_respawnDelay(25), m_corpseDelay(60), m_respawnradius(5.0f), m_subtype(subtype), m_defaultMovementType(IDLE_MOTION_TYPE), m_equipmentId(0), m_AlreadyCallAssistance(false), m_AlreadySearchedAssistance(false), -m_regenHealth(true), m_AI_locked(false), m_isDeadByDefault(false), m_needNotify(false), +m_regenHealth(true), m_AI_locked(false), m_isDeadByDefault(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_creatureInfo(NULL), m_splineFlags(SPLINEFLAG_WALKMODE) { @@ -426,15 +426,6 @@ uint32 Creature::ChooseDisplayId(const CreatureInfo *cinfo, const CreatureData * void Creature::Update(uint32 update_diff, uint32 diff) { - if (m_needNotify) - { - m_needNotify = false; - RelocationNotify(); - - if (!IsInWorld()) - return; - } - switch( m_deathState ) { case JUST_ALIVED: @@ -2352,13 +2343,6 @@ void Creature::SendAreaSpiritHealerQueryOpcode(Player *pl) pl->SendDirectMessage(&data); } -void Creature::RelocationNotify() -{ - MaNGOS::CreatureRelocationNotifier relocationNotifier(*this); - float radius = MAX_CREATURE_ATTACK_RADIUS * sWorld.getConfig(CONFIG_FLOAT_RATE_CREATURE_AGGRO); - Cell::VisitAllObjects(this, relocationNotifier, radius); -} - void Creature::ApplyGameEventSpells(GameEventCreatureData const* eventData, bool activated) { uint32 cast_spell = activated ? eventData->spell_id_start : eventData->spell_id_end; diff --git a/src/game/Creature.h b/src/game/Creature.h index 14b6cdb41..de24aa183 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -647,14 +647,11 @@ class MANGOS_DLL_SPEC Creature : public Unit void SetActiveObjectState(bool on); - void SetNeedNotify() { m_needNotify = true; } - void SendAreaSpiritHealerQueryOpcode(Player *pl); protected: bool CreateFromProto(uint32 guidlow,uint32 Entry, Team team, const CreatureData *data = NULL, GameEventCreatureData const* eventData =NULL); bool InitEntry(uint32 entry, const CreatureData* data = NULL, GameEventCreatureData const* eventData = NULL); - void RelocationNotify(); uint32 m_groupLootTimer; // (msecs)timer used for group loot uint32 m_groupLootId; // used to find group which is looting corpse @@ -691,7 +688,6 @@ class MANGOS_DLL_SPEC Creature : public Unit bool m_regenHealth; bool m_AI_locked; bool m_isDeadByDefault; - bool m_needNotify; SpellSchoolMask m_meleeDamageSchoolMask; uint32 m_originalEntry; diff --git a/src/game/GridNotifiersImpl.h b/src/game/GridNotifiersImpl.h index 74bbf0fa0..151a03ea5 100644 --- a/src/game/GridNotifiersImpl.h +++ b/src/game/GridNotifiersImpl.h @@ -47,11 +47,8 @@ inline void MaNGOS::ObjectUpdater::Visit(CreatureMapType &m) } } -inline void PlayerCreatureRelocationWorker(Player* pl, WorldObject const* viewPoint, Creature* c) +inline void PlayerCreatureRelocationWorker(Player* pl, Creature* c) { - // update creature visibility at player/creature move - pl->UpdateVisibilityOf(viewPoint,c); - // Creature AI reaction if (!c->hasUnitState(UNIT_STAT_LOST_CONTROL)) { @@ -80,11 +77,12 @@ inline void MaNGOS::PlayerRelocationNotifier::Visit(CreatureMapType &m) if (!i_player.isAlive() || i_player.IsTaxiFlying()) return; - WorldObject const* viewPoint = i_player.GetCamera().GetBody(); - for(CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter) - if (iter->getSource()->isAlive()) - PlayerCreatureRelocationWorker(&i_player, viewPoint, iter->getSource()); + { + Creature* c = iter->getSource(); + if (c->isAlive()) + PlayerCreatureRelocationWorker(&i_player, c); + } } template<> @@ -94,9 +92,11 @@ inline void MaNGOS::CreatureRelocationNotifier::Visit(PlayerMapType &m) return; for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) - if (Player* player = iter->getSource()) - if (player->isAlive() && !player->IsTaxiFlying()) - PlayerCreatureRelocationWorker(player, player->GetCamera().GetBody(), &i_creature); + { + Player* player = iter->getSource(); + if (player->isAlive() && !player->IsTaxiFlying()) + PlayerCreatureRelocationWorker(player, &i_creature); + } } template<> diff --git a/src/game/Map.cpp b/src/game/Map.cpp index d7c83603f..3851275c3 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -207,13 +207,13 @@ void Map::AddNotifier(T* , Cell const& , CellPair const& ) template<> void Map::AddNotifier(Player* obj, Cell const& cell, CellPair const& cellpair) { - PlayerRelocationNotify(obj,cell,cellpair); + obj->SheduleAINotify(0); } template<> void Map::AddNotifier(Creature* obj, Cell const&, CellPair const&) { - obj->SetNeedNotify(); + obj->SheduleAINotify(0); } void @@ -708,10 +708,7 @@ Map::PlayerRelocation(Player *player, float x, float y, float z, float orientati player->GetViewPoint().Event_GridChanged(&(*newGrid)(new_cell.CellX(),new_cell.CellY())); } - player->GetViewPoint().Call_UpdateVisibilityForOwner(); - // if move then update what player see and who seen - UpdateObjectVisibility(player, new_cell, new_val); - PlayerRelocationNotify(player,new_cell,new_val); + player->OnRelocated(); NGridType* newGrid = getNGrid(new_cell.GridX(), new_cell.GridY()); if( !same_cell && newGrid->GetGridState()!= GRID_STATE_ACTIVE ) @@ -731,39 +728,31 @@ Map::CreatureRelocation(Creature *creature, float x, float y, float z, float ang CellPair new_val = MaNGOS::ComputeCellPair(x, y); Cell new_cell(new_val); - // delay creature move for grid/cell to grid/cell moves if (old_cell.DiffCell(new_cell) || old_cell.DiffGrid(new_cell)) { DEBUG_FILTER_LOG(LOG_FILTER_CREATURE_MOVES, "Creature (GUID: %u Entry: %u) added to moving list from grid[%u,%u]cell[%u,%u] to grid[%u,%u]cell[%u,%u].", creature->GetGUIDLow(), creature->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY()); // do move or do move to respawn or remove creature if previous all fail - if(CreatureCellRelocation(creature,new_cell)) + if (CreatureCellRelocation(creature,new_cell)) { // update pos creature->Relocate(x, y, z, ang); - - // in diffcell/diffgrid case notifiers called in Creature::Update - creature->SetNeedNotify(); + creature->OnRelocated(); } - else + // if creature can't be move in new cell/grid (not loaded) move it to repawn cell/grid + // creature coordinates will be updated and notifiers send + else if (!CreatureRespawnRelocation(creature)) { - // if creature can't be move in new cell/grid (not loaded) move it to repawn cell/grid - // creature coordinates will be updated and notifiers send - if(!CreatureRespawnRelocation(creature)) - { - // ... or unload (if respawn grid also not loaded) - DEBUG_FILTER_LOG(LOG_FILTER_CREATURE_MOVES, "Creature (GUID: %u Entry: %u ) can't be move to unloaded respawn grid.",creature->GetGUIDLow(),creature->GetEntry()); - creature->SetNeedNotify(); - } + // ... or unload (if respawn grid also not loaded) + DEBUG_FILTER_LOG(LOG_FILTER_CREATURE_MOVES, "Creature (GUID: %u Entry: %u ) can't be move to unloaded respawn grid.",creature->GetGUIDLow(),creature->GetEntry()); } } else { creature->Relocate(x, y, z, ang); - creature->SetNeedNotify(); + creature->OnRelocated(); } - creature->GetViewPoint().Call_UpdateVisibilityForOwner(); MANGOS_ASSERT(CheckGridIntegrity(creature,true)); } @@ -847,7 +836,7 @@ bool Map::CreatureRespawnRelocation(Creature *c) { c->Relocate(resp_x, resp_y, resp_z, resp_o); c->GetMotionMaster()->Initialize(); // prevent possible problems with default move generators - c->SetNeedNotify(); + c->OnRelocated(); return true; } else diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 93f025e19..0d68bdb42 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -218,6 +218,7 @@ Unit::Unit() m_AuraFlags = 0; m_Visibility = VISIBILITY_ON; + m_AINotifySheduled = false; m_detectInvisibilityMask = 0; m_invisibilityMask = 0; @@ -8089,12 +8090,9 @@ void Unit::SetVisibility(UnitVisibility x) } } - Map *m = GetMap(); - - if(GetTypeId()==TYPEID_PLAYER) - m->PlayerRelocation((Player*)this,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation()); - else - m->CreatureRelocation((Creature*)this,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation()); + GetViewPoint().Call_UpdateVisibilityForOwner(); + UpdateObjectVisibility(); + SheduleAINotify(0); GetViewPoint().Event_ViewPointVisibilityChanged(); } @@ -10827,3 +10825,62 @@ bool Unit::IsAllowedDamageInArea(Unit* pVictim) const return true; } + +class RelocationNotifyEvent : public BasicEvent +{ +public: + RelocationNotifyEvent(Unit& owner) : BasicEvent(), m_owner(owner) + { + m_owner._SetAINotifySheduled(true); + } + + bool Execute(uint64 /*e_time*/, uint32 /*p_time*/) + { + float radius = MAX_CREATURE_ATTACK_RADIUS * sWorld.getConfig(CONFIG_FLOAT_RATE_CREATURE_AGGRO); + if (m_owner.GetTypeId() == TYPEID_PLAYER) + { + MaNGOS::PlayerRelocationNotifier notify((Player&)m_owner); + Cell::VisitAllObjects(&m_owner,notify,radius); + } + else //if(m_owner.GetTypeId() == TYPEID_UNIT) + { + MaNGOS::CreatureRelocationNotifier notify((Creature&)m_owner); + Cell::VisitAllObjects(&m_owner,notify,radius); + } + m_owner._SetAINotifySheduled(false); + return true; + } + + void Abort(uint64) + { + m_owner._SetAINotifySheduled(false); + } + +private: + Unit& m_owner; +}; + +void Unit::SheduleAINotify(uint32 delay) +{ + if (!IsAINotifySheduled()) + m_Events.AddEvent(new RelocationNotifyEvent(*this), m_Events.CalculateTime(delay)); +} + +void Unit::OnRelocated() +{ + // switch to use G3D::Vector3 is good idea, maybe + float dx = m_last_notified_position.x - GetPositionX(); + float dy = m_last_notified_position.y - GetPositionY(); + float dz = m_last_notified_position.z - GetPositionZ(); + float distsq = dx*dx+dy*dy+dz*dz; + if (distsq > World::GetRelocationLowerLimitSq()) + { + m_last_notified_position.x = GetPositionX(); + m_last_notified_position.y = GetPositionY(); + m_last_notified_position.z = GetPositionZ(); + + GetViewPoint().Call_UpdateVisibilityForOwner(); + UpdateObjectVisibility(); + } + SheduleAINotify(World::GetRelocationAINotifyDelay()); +} diff --git a/src/game/Unit.h b/src/game/Unit.h index c745c9edf..43b78747d 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -1954,6 +1954,11 @@ class MANGOS_DLL_SPEC Unit : public WorldObject // Movement info MovementInfo m_movementInfo; + void SheduleAINotify(uint32 delay); + bool IsAINotifySheduled() const { return m_AINotifySheduled;} + void _SetAINotifySheduled(bool on) { m_AINotifySheduled = on;} // only for call from RelocationNotifyEvent class code + void OnRelocated(); + protected: explicit Unit (); @@ -2020,6 +2025,8 @@ class MANGOS_DLL_SPEC Unit : public WorldObject uint32 m_castCounter; // count casts chain of triggered spells for prevent infinity cast crashes UnitVisibility m_Visibility; + Position m_last_notified_position; + bool m_AINotifySheduled; Diminishing m_Diminishing; // Manage all Units threatening us diff --git a/src/game/World.cpp b/src/game/World.cpp index 9ad52400c..5823e2265 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -77,6 +77,9 @@ float World::m_MaxVisibleDistanceInFlight = DEFAULT_VISIBILITY_DISTANCE; float World::m_VisibleUnitGreyDistance = 0; float World::m_VisibleObjectGreyDistance = 0; +float World::m_relocation_lower_limit_sq = 10.f * 10.f; +uint32 World::m_relocation_ai_notify_delay = 1000u; + /// World constructor World::World() { @@ -768,6 +771,9 @@ void World::LoadConfigSettings(bool reload) setConfig(CONFIG_BOOL_PET_UNSUMMON_AT_MOUNT, "PetUnsummonAtMount", true); + m_relocation_ai_notify_delay = sConfig.GetIntDefault("Visibility.AIRelocationNotifyDelay", 1000u); + m_relocation_lower_limit_sq = pow(sConfig.GetFloatDefault("Visibility.RelocationLowerLimit",10), 2); + m_VisibleUnitGreyDistance = sConfig.GetFloatDefault("Visibility.Distance.Grey.Unit", 1); if(m_VisibleUnitGreyDistance > MAX_VISIBILITY_DISTANCE) { diff --git a/src/game/World.h b/src/game/World.h index e96c0532d..f486fb9f5 100644 --- a/src/game/World.h +++ b/src/game/World.h @@ -565,6 +565,9 @@ class World static float GetVisibleUnitGreyDistance() { return m_VisibleUnitGreyDistance; } static float GetVisibleObjectGreyDistance() { return m_VisibleObjectGreyDistance; } + static float GetRelocationLowerLimitSq() { return m_relocation_lower_limit_sq; } + static uint32 GetRelocationAINotifyDelay() { return m_relocation_ai_notify_delay; } + void ProcessCliCommands(); void QueueCliCommand(CliCommandHolder* commandHolder) { cliCmdQueue.add(commandHolder); } @@ -654,6 +657,9 @@ class World static float m_VisibleUnitGreyDistance; static float m_VisibleObjectGreyDistance; + static float m_relocation_lower_limit_sq; + static uint32 m_relocation_ai_notify_delay; + // CLI command holder to be thread safe ACE_Based::LockedQueue cliCmdQueue; diff --git a/src/mangosd/mangosd.conf.dist.in b/src/mangosd/mangosd.conf.dist.in index cedbdc644..730edacfb 100644 --- a/src/mangosd/mangosd.conf.dist.in +++ b/src/mangosd/mangosd.conf.dist.in @@ -1138,6 +1138,14 @@ GM.AllowAchievementGain = 1 # Visibility grey distance for dynobjects/gameobjects/corpses/creature bodies # Default: 10 (yards) # +# Visibility.RelocationLowerLimit +# Object's visibility update called, when distance between current object's position and position, +# where visiblity was updated last time, reaches RelocationLoverLimit value +# Default: 10 (yards) +# +# Visibility.AIRelocationNotifyDelay +# Delay time between creature AI reactions on nearby movements +# Default: 1000 (milliseconds) # ################################################################################################################### @@ -1148,6 +1156,8 @@ Visibility.Distance.BGArenas = 180 Visibility.Distance.InFlight = 100 Visibility.Distance.Grey.Unit = 1 Visibility.Distance.Grey.Object = 10 +Visibility.RelocationLowerLimit = 10 +Visibility.AIRelocationNotifyDelay = 1000 ################################################################################################################### # SERVER RATES diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 55c3ec769..dc50974bf 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "11192" + #define REVISION_NR "11193" #endif // __REVISION_NR_H__