[9405] Make all movements instant applied.

* Drop delayed moves list in Map code
* Apply movement coords update always at call including movement to different cell/grid.
* Instead removed functionality mark creature as need move notify broadcast at next tick, do it.

This must resolve porblesm with CreatureRelocation in past not always update position to new expected at call
And in resul next code fail or work in strange way. Mark creature for notifier call at next Update
let safe main part remopved functionality implemented in another way: prevent cascade (or infinity chain)
in move updates. In fiture possible implement move notify call not at each tick for save time.
This commit is contained in:
VladimirMangos 2010-02-18 01:03:53 +03:00
parent e74f62ea31
commit 5af05a314e
12 changed files with 68 additions and 106 deletions

View file

@ -118,7 +118,8 @@ m_lootMoney(0), m_lootRecipient(0),
m_deathTimer(0), m_respawnTime(0), m_respawnDelay(25), m_corpseDelay(60), m_respawnradius(0.0f),
m_subtype(subtype), m_defaultMovementType(IDLE_MOTION_TYPE), m_DBTableGuid(0), m_equipmentId(0),
m_AlreadyCallAssistance(false), m_AlreadySearchedAssistance(false),
m_regenHealth(true), m_AI_locked(false), m_isDeadByDefault(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL),
m_regenHealth(true), m_AI_locked(false), m_isDeadByDefault(false), m_needNotify(false),
m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL),
m_creatureInfo(NULL), m_isActiveObject(false), m_splineFlags(SPLINEFLAG_WALKMODE)
{
m_regenTimer = 200;
@ -334,6 +335,15 @@ void Creature::Update(uint32 diff)
else
m_GlobalCooldown -= diff;
if (m_needNotify)
{
m_needNotify = false;
RelocationNotify();
if (!IsInWorld())
return;
}
switch( m_deathState )
{
case JUST_ALIVED:
@ -2066,3 +2076,22 @@ void Creature::SendAreaSpiritHealerQueryOpcode(Player *pl)
data << GetGUID() << next_resurrect;
pl->SendDirectMessage(&data);
}
void Creature::RelocationNotify()
{
CellPair new_val = MaNGOS::ComputeCellPair(GetPositionX(), GetPositionY());
Cell cell(new_val);
CellPair cellpair = cell.cellPair();
MaNGOS::CreatureRelocationNotifier relocationNotifier(*this);
cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate(); // not trigger load unloaded grids at notifier call
TypeContainerVisitor<MaNGOS::CreatureRelocationNotifier, WorldTypeMapContainer > c2world_relocation(relocationNotifier);
TypeContainerVisitor<MaNGOS::CreatureRelocationNotifier, GridTypeMapContainer > c2grid_relocation(relocationNotifier);
float radius = MAX_CREATURE_ATTACK_RADIUS * sWorld.getConfig(CONFIG_FLOAT_RATE_CREATURE_AGGRO);
cell.Visit(cellpair, c2world_relocation, *GetMap(), *this, radius);
cell.Visit(cellpair, c2grid_relocation, *GetMap(), *this, radius);
}

View file

@ -615,11 +615,14 @@ class MANGOS_DLL_SPEC Creature : public Unit
bool isActiveObject() const { return m_isActiveObject || HasAuraType(SPELL_AURA_BIND_SIGHT) || HasAuraType(SPELL_AURA_FAR_SIGHT); }
void SetActiveObjectState(bool on);
void SetNeedNotify() { m_needNotify = true; }
void SendAreaSpiritHealerQueryOpcode(Player *pl);
protected:
bool CreateFromProto(uint32 guidlow,uint32 Entry,uint32 team, const CreatureData *data = NULL);
bool InitEntry(uint32 entry, uint32 team=ALLIANCE, const CreatureData* data=NULL);
void RelocationNotify();
// vendor items
VendorItemCounts m_vendorItemCounts;
@ -652,6 +655,7 @@ 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;

View file

@ -40,8 +40,6 @@
#include "InstanceSaveMgr.h"
#include "VMapFactory.h"
#define MAX_CREATURE_ATTACK_RADIUS (45.0f * sWorld.getConfig(CONFIG_FLOAT_RATE_CREATURE_AGGRO))
GridState* si_GridStates[MAX_GRID_STATE];
static char const* MAP_MAGIC = "MAPS";
@ -344,9 +342,9 @@ void Map::AddNotifier(Player* obj, Cell const& cell, CellPair const& cellpair)
}
template<>
void Map::AddNotifier(Creature* obj, Cell const& cell, CellPair const& cellpair)
void Map::AddNotifier(Creature* obj, Cell const&, CellPair const&)
{
CreatureRelocationNotify(obj,cell,cellpair);
obj->SetNeedNotify();
}
void
@ -904,62 +902,38 @@ Map::CreatureRelocation(Creature *creature, float x, float y, float z, float ang
if ((sLog.getLogFilter() & LOG_FILTER_CREATURE_MOVES) == 0)
sLog.outDebug("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());
#endif
AddCreatureToMoveList(creature, x, y, z, ang);
// in diffcell/diffgrid case notifiers called at finishing move creature in Map::MoveAllCreaturesInMoveList
}
else
{
creature->Relocate(x, y, z, ang);
CreatureRelocationNotify(creature, new_cell, new_val);
}
assert(CheckGridIntegrity(creature,true));
}
void Map::AddCreatureToMoveList(Creature *c, float x, float y, float z, float ang)
{
if(!c)
return;
i_creaturesToMove[c] = CreatureMover(x, y, z, ang);
}
void Map::MoveAllCreaturesInMoveList()
{
while(!i_creaturesToMove.empty())
{
// get data and remove element;
CreatureMoveList::iterator iter = i_creaturesToMove.begin();
Creature* c = iter->first;
CreatureMover cm = iter->second;
i_creaturesToMove.erase(iter);
// calculate cells
CellPair new_val = MaNGOS::ComputeCellPair(cm.x, cm.y);
Cell new_cell(new_val);
// do move or do move to respawn or remove creature if previous all fail
if(CreatureCellRelocation(c,new_cell))
if(CreatureCellRelocation(creature,new_cell))
{
// update pos
c->Relocate(cm.x, cm.y, cm.z, cm.ang);
CreatureRelocationNotify(c, new_cell, new_cell.cellPair());
creature->Relocate(x, y, z, ang);
// in diffcell/diffgrid case notifiers called in Creature::Update
creature->SetNeedNotify();
}
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
if(!CreatureRespawnRelocation(c))
if(!CreatureRespawnRelocation(creature))
{
// ... or unload (if respawn grid also not loaded)
#ifdef MANGOS_DEBUG
if((sLog.getLogFilter() & LOG_FILTER_CREATURE_MOVES)==0)
sLog.outDebug("Creature (GUID: %u Entry: %u ) can't be move to unloaded respawn grid.",c->GetGUIDLow(),c->GetEntry());
sLog.outDebug("Creature (GUID: %u Entry: %u ) can't be move to unloaded respawn grid.",creature->GetGUIDLow(),creature->GetEntry());
#endif
AddObjectToRemoveList(c);
creature->SetNeedNotify();
}
}
}
else
{
creature->Relocate(x, y, z, ang);
creature->SetNeedNotify();
}
assert(CheckGridIntegrity(creature,true));
}
bool Map::CreatureCellRelocation(Creature *c, Cell new_cell)
@ -1055,7 +1029,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
CreatureRelocationNotify(c,resp_cell,resp_cell.cellPair());
c->SetNeedNotify();
return true;
}
else
@ -1074,15 +1048,15 @@ bool Map::UnloadGrid(const uint32 &x, const uint32 &y, bool pForce)
DEBUG_LOG("Unloading grid[%u,%u] for map %u", x,y, i_id);
ObjectGridUnloader unloader(*grid);
// Finish creature moves, remove and delete all creatures with delayed remove before moving to respawn grids
// Finish remove and delete all creatures with delayed remove before moving to respawn grids
// Must know real mob position before move
DoDelayedMovesAndRemoves();
RemoveAllObjectsInRemoveList();
// move creatures to respawn grids if this is diff.grid or to remove list
unloader.MoveToRespawnN();
// Finish creature moves, remove and delete all creatures with delayed remove before unload
DoDelayedMovesAndRemoves();
// Finish remove and delete all creatures with delayed remove before unload
RemoveAllObjectsInRemoveList();
unloader.UnloadN();
delete getNGrid(x, y);
@ -1115,9 +1089,6 @@ bool Map::UnloadGrid(const uint32 &x, const uint32 &y, bool pForce)
void Map::UnloadAll(bool pForce)
{
// clear all delayed moves, useless anyway do this moves before map unload.
i_creaturesToMove.clear();
for (GridRefManager<NGridType>::iterator i = GridRefManager<NGridType>::begin(); i != GridRefManager<NGridType>::end(); )
{
NGridType &grid(*i->getSource());
@ -2066,21 +2037,10 @@ void Map::PlayerRelocationNotify( Player* player, Cell cell, CellPair cellpair )
TypeContainerVisitor<MaNGOS::PlayerRelocationNotifier, GridTypeMapContainer > p2grid_relocation(relocationNotifier);
TypeContainerVisitor<MaNGOS::PlayerRelocationNotifier, WorldTypeMapContainer > p2world_relocation(relocationNotifier);
cell.Visit(cellpair, p2grid_relocation, *this, *player, MAX_CREATURE_ATTACK_RADIUS);
cell.Visit(cellpair, p2world_relocation, *this, *player, MAX_CREATURE_ATTACK_RADIUS);
}
float radius = MAX_CREATURE_ATTACK_RADIUS * sWorld.getConfig(CONFIG_FLOAT_RATE_CREATURE_AGGRO);
void Map::CreatureRelocationNotify(Creature *creature, Cell cell, CellPair cellpair)
{
MaNGOS::CreatureRelocationNotifier relocationNotifier(*creature);
cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate(); // not trigger load unloaded grids at notifier call
TypeContainerVisitor<MaNGOS::CreatureRelocationNotifier, WorldTypeMapContainer > c2world_relocation(relocationNotifier);
TypeContainerVisitor<MaNGOS::CreatureRelocationNotifier, GridTypeMapContainer > c2grid_relocation(relocationNotifier);
cell.Visit(cellpair, c2world_relocation, *this, *creature, MAX_CREATURE_ATTACK_RADIUS);
cell.Visit(cellpair, c2grid_relocation, *this, *creature, MAX_CREATURE_ATTACK_RADIUS);
cell.Visit(cellpair, p2grid_relocation, *this, *player, radius);
cell.Visit(cellpair, p2world_relocation, *this, *player, radius);
}
void Map::SendInitSelf( Player * player )
@ -2175,12 +2135,6 @@ inline void Map::setNGrid(NGridType *grid, uint32 x, uint32 y)
i_grids[x][y] = grid;
}
void Map::DoDelayedMovesAndRemoves()
{
MoveAllCreaturesInMoveList();
RemoveAllObjectsInRemoveList();
}
void Map::AddObjectToRemoveList(WorldObject *obj)
{
assert(obj->GetMapId()==GetId() && obj->GetInstanceId()==GetInstanceId());

View file

@ -180,14 +180,6 @@ public:
ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData *data = 0);
};
struct CreatureMover
{
CreatureMover() : x(0), y(0), z(0), ang(0) {}
CreatureMover(float _x, float _y, float _z, float _ang) : x(_x), y(_y), z(_z), ang(_ang) {}
float x, y, z, ang;
};
// GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push,N), also any gcc version not support it at some platform
#if defined( __GNUC__ )
#pragma pack(1)
@ -219,8 +211,6 @@ enum LevelRequirementVsMode
#pragma pack(pop)
#endif
typedef UNORDERED_MAP<Creature*, CreatureMover> CreatureMoveList;
#define MAX_HEIGHT 100000.0f // can be use for find ground height at surface
#define INVALID_HEIGHT -100000.0f // for check, must be equal to VMAP_INVALID_HEIGHT, real value for unknown height is VMAP_INVALID_HEIGHT_VALUE
#define MIN_UNLOAD_DELAY 1 // immediate unload
@ -327,10 +317,9 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
GetZoneAndAreaIdByAreaFlag(zoneid,areaid,GetAreaFlag(x,y,z),i_id);
}
virtual void MoveAllCreaturesInMoveList();
virtual void RemoveAllObjectsInRemoveList();
bool CreatureRespawnRelocation(Creature *c); // used only in MoveAllCreaturesInMoveList and ObjectGridUnloader
bool CreatureRespawnRelocation(Creature *c); // used only in CreatureRelocation and ObjectGridUnloader
// assert print helper
bool CheckGridIntegrity(Creature* c, bool moved) const;
@ -371,7 +360,6 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
}
void AddObjectToRemoveList(WorldObject *obj);
void DoDelayedMovesAndRemoves();
virtual bool RemoveBones(uint64 guid, float x, float y);
@ -445,13 +433,9 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
void SendRemoveTransports( Player * player );
void PlayerRelocationNotify(Player* player, Cell cell, CellPair cellpair);
void CreatureRelocationNotify(Creature *creature, Cell newcell, CellPair newval);
bool CreatureCellRelocation(Creature *creature, Cell new_cell);
void AddCreatureToMoveList(Creature *c, float x, float y, float z, float ang);
CreatureMoveList i_creaturesToMove;
bool loaded(const GridPair &) const;
void EnsureGridCreated(const GridPair &);
bool EnsureGridLoaded(Cell const&);

View file

@ -66,16 +66,6 @@ void MapInstanced::Update(const uint32& t)
}
}
void MapInstanced::MoveAllCreaturesInMoveList()
{
for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); ++i)
{
i->second->MoveAllCreaturesInMoveList();
}
Map::MoveAllCreaturesInMoveList();
}
void MapInstanced::RemoveAllObjectsInRemoveList()
{
for (InstancedMaps::iterator i = m_InstancedMaps.begin(); i != m_InstancedMaps.end(); ++i)

View file

@ -34,7 +34,6 @@ class MANGOS_DLL_DECL MapInstanced : public Map
// functions overwrite Map versions
void Update(const uint32&);
void MoveAllCreaturesInMoveList();
void RemoveAllObjectsInRemoveList();
bool RemoveBones(uint64 guid, float x, float y);
void UnloadAll(bool pForce);

View file

@ -271,10 +271,10 @@ MapManager::Update(uint32 diff)
i_timer.SetCurrent(0);
}
void MapManager::DoDelayedMovesAndRemoves()
void MapManager::RemoveAllObjectsInRemoveList()
{
for(MapMapType::iterator iter=i_maps.begin(); iter != i_maps.end(); ++iter)
iter->second->DoDelayedMovesAndRemoves();
iter->second->RemoveAllObjectsInRemoveList();
}
bool MapManager::ExistMapAndVMap(uint32 mapid, float x,float y)

View file

@ -108,7 +108,7 @@ class MANGOS_DLL_DECL MapManager : public MaNGOS::Singleton<MapManager, MaNGOS::
return IsValidMapCoord(loc.mapid,loc.coord_x,loc.coord_y,loc.coord_z,loc.orientation);
}
void DoDelayedMovesAndRemoves();
void RemoveAllObjectsInRemoveList();
void LoadTransports();

View file

@ -13382,9 +13382,10 @@ void Unit::KnockBackFrom(Unit* target, float horizintalSpeed, float verticalSpee
fx = fx2;
fy = fy2;
fz = fz2;
UpdateGroundPositionZ(fx, fy, fz);
}
UpdateGroundPositionZ(fx, fy, fz);
//FIXME: this mostly hack, must exist some packet for proper creature move at client side
// with CreatureRelocation at server side
NearTeleportTo(fx, fy, fz, GetOrientation(), this == target);

View file

@ -1056,6 +1056,7 @@ typedef std::set<uint64> GuardianPetList;
// delay time next attack to prevent client attack animation problems
#define ATTACK_DISPLAY_DELAY 200
#define MAX_PLAYER_STEALTH_DETECT_RANGE 45.0f // max distance for detection targets by player
#define MAX_CREATURE_ATTACK_RADIUS 45.0f // max distance for creature aggro (use with CONFIG_FLOAT_RATE_CREATURE_AGGRO)
// Regeneration defines
#define REGEN_TIME_FULL 2000 // For this time difference is computed regen value

View file

@ -1429,7 +1429,7 @@ void World::Update(uint32 diff)
/// </ul>
///- Move all creatures with "delayed move" and remove and delete all objects with "delayed remove"
sMapMgr.DoDelayedMovesAndRemoves();
sMapMgr.RemoveAllObjectsInRemoveList();
// update the instance reset times
sInstanceSaveMgr.Update();

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "9404"
#define REVISION_NR "9405"
#endif // __REVISION_NR_H__