Merge pull request #3399 from megamage/master
Fix the relocation of creatures across cells. Try to fix #3054.
This commit is contained in:
@@ -143,7 +143,8 @@ m_PlayerDamageReq(0), m_lootMoney(0), m_lootRecipient(0), m_lootRecipientGroup(0
|
|||||||
m_respawnDelay(300), m_corpseDelay(60), m_respawnradius(0.0f), m_reactState(REACT_AGGRESSIVE),
|
m_respawnDelay(300), m_corpseDelay(60), m_respawnradius(0.0f), m_reactState(REACT_AGGRESSIVE),
|
||||||
m_defaultMovementType(IDLE_MOTION_TYPE), m_DBTableGuid(0), m_equipmentId(0), m_AlreadyCallAssistance(false),
|
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_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL),
|
m_AlreadySearchedAssistance(false), m_regenHealth(true), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL),
|
||||||
m_creatureInfo(NULL), m_creatureData(NULL), m_formation(NULL)
|
m_creatureInfo(NULL), m_creatureData(NULL), m_formation(NULL),
|
||||||
|
MapCreature()
|
||||||
{
|
{
|
||||||
m_regenTimer = CREATURE_REGEN_INTERVAL;
|
m_regenTimer = CREATURE_REGEN_INTERVAL;
|
||||||
m_valuesCount = UNIT_END;
|
m_valuesCount = UNIT_END;
|
||||||
|
|||||||
@@ -407,7 +407,36 @@ typedef std::map<uint32, time_t> CreatureSpellCooldowns;
|
|||||||
|
|
||||||
#define MAX_VENDOR_ITEMS 150 // Limitation in 3.x.x item count in SMSG_LIST_INVENTORY
|
#define MAX_VENDOR_ITEMS 150 // Limitation in 3.x.x item count in SMSG_LIST_INVENTORY
|
||||||
|
|
||||||
class Creature : public Unit, public GridObject<Creature>
|
enum CreatureCellMoveState
|
||||||
|
{
|
||||||
|
CREATURE_CELL_MOVE_NONE, //not in move list
|
||||||
|
CREATURE_CELL_MOVE_ACTIVE, //in move list
|
||||||
|
CREATURE_CELL_MOVE_INACTIVE, //in move list but should not move
|
||||||
|
};
|
||||||
|
|
||||||
|
class MapCreature
|
||||||
|
{
|
||||||
|
friend class Map; //map for moving creatures
|
||||||
|
friend class ObjectGridLoader; //grid loader for loading creatures
|
||||||
|
|
||||||
|
public:
|
||||||
|
MapCreature() : _moveState(CREATURE_CELL_MOVE_NONE) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Cell _currentCell;
|
||||||
|
Cell const& GetCurrentCell() const { return _currentCell; }
|
||||||
|
void SetCurrentCell(Cell const& cell) { _currentCell = cell; }
|
||||||
|
|
||||||
|
CreatureCellMoveState _moveState;
|
||||||
|
Position _newPosition;
|
||||||
|
void SetNewCellPosition(float x, float y, float z, float o)
|
||||||
|
{
|
||||||
|
_moveState = CREATURE_CELL_MOVE_ACTIVE;
|
||||||
|
_newPosition.Relocate(x, y, z, o);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Creature : public Unit, public GridObject<Creature>, public MapCreature
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -598,10 +627,6 @@ class Creature : public Unit, public GridObject<Creature>
|
|||||||
MovementGeneratorType GetDefaultMovementType() const { return m_defaultMovementType; }
|
MovementGeneratorType GetDefaultMovementType() const { return m_defaultMovementType; }
|
||||||
void SetDefaultMovementType(MovementGeneratorType mgt) { m_defaultMovementType = mgt; }
|
void SetDefaultMovementType(MovementGeneratorType mgt) { m_defaultMovementType = mgt; }
|
||||||
|
|
||||||
// for use only in LoadHelper, Map::Add Map::CreatureCellRelocation
|
|
||||||
Cell const& GetCurrentCell() const { return m_currentCell; }
|
|
||||||
void SetCurrentCell(Cell const& cell) { m_currentCell = cell; }
|
|
||||||
|
|
||||||
void RemoveCorpse(bool setSpawnTime = true);
|
void RemoveCorpse(bool setSpawnTime = true);
|
||||||
|
|
||||||
void ForcedDespawn(uint32 timeMSToDespawn = 0);
|
void ForcedDespawn(uint32 timeMSToDespawn = 0);
|
||||||
@@ -703,7 +728,6 @@ class Creature : public Unit, public GridObject<Creature>
|
|||||||
void RegenerateHealth();
|
void RegenerateHealth();
|
||||||
void Regenerate(Powers power);
|
void Regenerate(Powers power);
|
||||||
MovementGeneratorType m_defaultMovementType;
|
MovementGeneratorType m_defaultMovementType;
|
||||||
Cell m_currentCell; // store current cell where creature listed
|
|
||||||
uint32 m_DBTableGuid; ///< For new or temporary creatures is 0 for saved it is lowguid
|
uint32 m_DBTableGuid; ///< For new or temporary creatures is 0 for saved it is lowguid
|
||||||
uint32 m_equipmentId;
|
uint32 m_equipmentId;
|
||||||
|
|
||||||
|
|||||||
@@ -57,20 +57,8 @@ ObjectGridRespawnMover::Visit(CreatureMapType &m)
|
|||||||
Creature* c = iter->getSource();
|
Creature* c = iter->getSource();
|
||||||
++iter;
|
++iter;
|
||||||
|
|
||||||
ASSERT(!c->isPet() && "ObjectGridRespawnMover don't must be called for pets");
|
ASSERT(!c->isPet() && "ObjectGridRespawnMover must not be called for pets");
|
||||||
|
c->GetMap()->CreatureRespawnRelocation(c, true);
|
||||||
Cell const& cur_cell = c->GetCurrentCell();
|
|
||||||
|
|
||||||
float resp_x, resp_y, resp_z;
|
|
||||||
c->GetRespawnCoord(resp_x, resp_y, resp_z);
|
|
||||||
CellPair resp_val = Trinity::ComputeCellPair(resp_x, resp_y);
|
|
||||||
Cell resp_cell(resp_val);
|
|
||||||
|
|
||||||
if (cur_cell.DiffGrid(resp_cell))
|
|
||||||
{
|
|
||||||
c->GetMap()->CreatureRespawnRelocation(c);
|
|
||||||
// false result ignored: will be unload with other creatures at grid
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,11 +82,11 @@ class ObjectWorldLoader
|
|||||||
uint32 i_corpses;
|
uint32 i_corpses;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T> void AddUnitState(T* /*obj*/, CellPair const& /*cell_pair*/)
|
template<class T> static void ObjectGridLoader::SetObjectCell(T* /*obj*/, CellPair const& /*cell_pair*/)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> void AddUnitState(Creature* obj, CellPair const& cell_pair)
|
template<> static void ObjectGridLoader::SetObjectCell(Creature* obj, CellPair const& cell_pair)
|
||||||
{
|
{
|
||||||
Cell cell(cell_pair);
|
Cell cell(cell_pair);
|
||||||
|
|
||||||
@@ -109,7 +97,7 @@ template <class T>
|
|||||||
void AddObjectHelper(CellPair &cell, GridRefManager<T> &m, uint32 &count, Map* map, T *obj)
|
void AddObjectHelper(CellPair &cell, GridRefManager<T> &m, uint32 &count, Map* map, T *obj)
|
||||||
{
|
{
|
||||||
obj->GetGridRef().link(&m, obj);
|
obj->GetGridRef().link(&m, obj);
|
||||||
AddUnitState(obj, cell);
|
ObjectGridLoader::SetObjectCell(obj, cell);
|
||||||
obj->AddToWorld();
|
obj->AddToWorld();
|
||||||
if (obj->isActiveObject())
|
if (obj->isActiveObject())
|
||||||
map->AddToActive(obj);
|
map->AddToActive(obj);
|
||||||
|
|||||||
@@ -40,11 +40,12 @@ class ObjectGridLoader
|
|||||||
void Visit(GameObjectMapType &m);
|
void Visit(GameObjectMapType &m);
|
||||||
void Visit(CreatureMapType &m);
|
void Visit(CreatureMapType &m);
|
||||||
void Visit(CorpseMapType &) const {}
|
void Visit(CorpseMapType &) const {}
|
||||||
|
|
||||||
void Visit(DynamicObjectMapType&) const {}
|
void Visit(DynamicObjectMapType&) const {}
|
||||||
|
|
||||||
void LoadN(void);
|
void LoadN(void);
|
||||||
|
|
||||||
|
template<class T> static void SetObjectCell(T* obj, CellPair const& cellPair);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Cell i_cell;
|
Cell i_cell;
|
||||||
NGridType &i_grid;
|
NGridType &i_grid;
|
||||||
|
|||||||
@@ -205,7 +205,8 @@ Map::Map(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode, Map* _par
|
|||||||
i_mapEntry (sMapStore.LookupEntry(id)), i_spawnMode(SpawnMode), i_InstanceId(InstanceId),
|
i_mapEntry (sMapStore.LookupEntry(id)), i_spawnMode(SpawnMode), i_InstanceId(InstanceId),
|
||||||
m_unloadTimer(0), m_VisibleDistance(DEFAULT_VISIBILITY_DISTANCE),
|
m_unloadTimer(0), m_VisibleDistance(DEFAULT_VISIBILITY_DISTANCE),
|
||||||
m_VisibilityNotifyPeriod(DEFAULT_VISIBILITY_NOTIFY_PERIOD),
|
m_VisibilityNotifyPeriod(DEFAULT_VISIBILITY_NOTIFY_PERIOD),
|
||||||
m_activeNonPlayersIter(m_activeNonPlayers.end()), i_gridExpiry(expiry), i_scriptLock(false)
|
m_activeNonPlayersIter(m_activeNonPlayers.end()), i_gridExpiry(expiry),
|
||||||
|
i_scriptLock(false), _creatureToMoveLock(false)
|
||||||
{
|
{
|
||||||
m_parentMap = (_parent ? _parent : this);
|
m_parentMap = (_parent ? _parent : this);
|
||||||
for (unsigned int idx=0; idx < MAX_NUMBER_OF_GRIDS; ++idx)
|
for (unsigned int idx=0; idx < MAX_NUMBER_OF_GRIDS; ++idx)
|
||||||
@@ -434,6 +435,17 @@ bool Map::Add(Player* player)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
void Map::InitializeObject(T* obj)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
void Map::InitializeObject(Creature* obj)
|
||||||
|
{
|
||||||
|
obj->_moveState = CREATURE_CELL_MOVE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
void
|
void
|
||||||
Map::Add(T *obj)
|
Map::Add(T *obj)
|
||||||
@@ -463,6 +475,7 @@ Map::Add(T *obj)
|
|||||||
AddToGrid(obj, grid, cell);
|
AddToGrid(obj, grid, cell);
|
||||||
//obj->SetMap(this);
|
//obj->SetMap(this);
|
||||||
obj->AddToWorld();
|
obj->AddToWorld();
|
||||||
|
InitializeObject(obj);
|
||||||
|
|
||||||
if (obj->isActiveObject())
|
if (obj->isActiveObject())
|
||||||
AddToActive(obj);
|
AddToActive(obj);
|
||||||
@@ -791,6 +804,7 @@ Map::CreatureRelocation(Creature* creature, float x, float y, float z, float ang
|
|||||||
{
|
{
|
||||||
creature->Relocate(x, y, z, ang);
|
creature->Relocate(x, y, z, ang);
|
||||||
creature->UpdateObjectVisibility(false);
|
creature->UpdateObjectVisibility(false);
|
||||||
|
RemoveCreatureFromMoveList(creature);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(CheckGridIntegrity(creature, true));
|
ASSERT(CheckGridIntegrity(creature, true));
|
||||||
@@ -798,26 +812,47 @@ Map::CreatureRelocation(Creature* creature, float x, float y, float z, float ang
|
|||||||
|
|
||||||
void Map::AddCreatureToMoveList(Creature* c, float x, float y, float z, float ang)
|
void Map::AddCreatureToMoveList(Creature* c, float x, float y, float z, float ang)
|
||||||
{
|
{
|
||||||
if (!c)
|
if (_creatureToMoveLock) //can this happen?
|
||||||
return;
|
return;
|
||||||
|
|
||||||
i_creaturesToMove[c] = CreatureMover(x, y, z, ang);
|
if(c->_moveState == CREATURE_CELL_MOVE_NONE)
|
||||||
|
_creaturesToMove.push_back(c);
|
||||||
|
c->SetNewCellPosition(x, y, z, ang);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Map::RemoveCreatureFromMoveList(Creature* c)
|
||||||
|
{
|
||||||
|
if (_creatureToMoveLock) //can this happen?
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(c->_moveState == CREATURE_CELL_MOVE_ACTIVE)
|
||||||
|
c->_moveState = CREATURE_CELL_MOVE_INACTIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Map::MoveAllCreaturesInMoveList()
|
void Map::MoveAllCreaturesInMoveList()
|
||||||
{
|
{
|
||||||
while (!i_creaturesToMove.empty())
|
_creatureToMoveLock = true;
|
||||||
|
for(std::vector<Creature*>::iterator itr = _creaturesToMove.begin(); itr != _creaturesToMove.end(); ++itr)
|
||||||
{
|
{
|
||||||
// get data and remove element;
|
Creature* c = *itr;
|
||||||
CreatureMoveList::iterator iter = i_creaturesToMove.begin();
|
if(c->FindMap() != this) //pet is teleported to another map
|
||||||
Creature* c = iter->first;
|
continue;
|
||||||
const CreatureMover &cm = iter->second;
|
|
||||||
|
if(c->_moveState != CREATURE_CELL_MOVE_ACTIVE)
|
||||||
|
{
|
||||||
|
c->_moveState = CREATURE_CELL_MOVE_NONE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->_moveState = CREATURE_CELL_MOVE_NONE;
|
||||||
|
if(!c->IsInWorld())
|
||||||
|
continue;
|
||||||
|
|
||||||
// do move or do move to respawn or remove creature if previous all fail
|
// do move or do move to respawn or remove creature if previous all fail
|
||||||
if (CreatureCellRelocation(c, Cell(Trinity::ComputeCellPair(cm.x, cm.y))))
|
if (CreatureCellRelocation(c, Cell(Trinity::ComputeCellPair(c->_newPosition.m_positionX, c->_newPosition.m_positionY))))
|
||||||
{
|
{
|
||||||
// update pos
|
// update pos
|
||||||
c->Relocate(cm.x, cm.y, cm.z, cm.ang);
|
c->Relocate(c->_newPosition);
|
||||||
//CreatureRelocationNotify(c, new_cell, new_cell.cellPair());
|
//CreatureRelocationNotify(c, new_cell, new_cell.cellPair());
|
||||||
c->UpdateObjectVisibility(false);
|
c->UpdateObjectVisibility(false);
|
||||||
}
|
}
|
||||||
@@ -825,7 +860,7 @@ void Map::MoveAllCreaturesInMoveList()
|
|||||||
{
|
{
|
||||||
// if creature can't be move in new cell/grid (not loaded) move it to repawn cell/grid
|
// 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
|
// creature coordinates will be updated and notifiers send
|
||||||
if (!CreatureRespawnRelocation(c))
|
if (!CreatureRespawnRelocation(c, false))
|
||||||
{
|
{
|
||||||
// ... or unload (if respawn grid also not loaded)
|
// ... or unload (if respawn grid also not loaded)
|
||||||
#ifdef TRINITY_DEBUG
|
#ifdef TRINITY_DEBUG
|
||||||
@@ -843,9 +878,9 @@ void Map::MoveAllCreaturesInMoveList()
|
|||||||
AddObjectToRemoveList(c);
|
AddObjectToRemoveList(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i_creaturesToMove.erase(iter);
|
|
||||||
}
|
}
|
||||||
|
_creaturesToMove.clear();
|
||||||
|
_creatureToMoveLock = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Map::CreatureCellRelocation(Creature* c, Cell new_cell)
|
bool Map::CreatureCellRelocation(Creature* c, Cell new_cell)
|
||||||
@@ -909,14 +944,17 @@ bool Map::CreatureCellRelocation(Creature* c, Cell new_cell)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Map::CreatureRespawnRelocation(Creature* c)
|
bool Map::CreatureRespawnRelocation(Creature* c, bool diffGridOnly)
|
||||||
{
|
{
|
||||||
float resp_x, resp_y, resp_z, resp_o;
|
float resp_x, resp_y, resp_z, resp_o;
|
||||||
c->GetRespawnCoord(resp_x, resp_y, resp_z, &resp_o);
|
c->GetRespawnCoord(resp_x, resp_y, resp_z, &resp_o);
|
||||||
|
|
||||||
CellPair resp_val = Trinity::ComputeCellPair(resp_x, resp_y);
|
CellPair resp_val = Trinity::ComputeCellPair(resp_x, resp_y);
|
||||||
Cell resp_cell(resp_val);
|
Cell resp_cell(resp_val);
|
||||||
|
|
||||||
|
//creature will be unloaded with grid
|
||||||
|
if(diffGridOnly && !c->GetCurrentCell().DiffGrid(resp_cell))
|
||||||
|
return true;
|
||||||
|
|
||||||
c->CombatStop();
|
c->CombatStop();
|
||||||
c->GetMotionMaster()->Clear();
|
c->GetMotionMaster()->Clear();
|
||||||
|
|
||||||
@@ -1020,7 +1058,7 @@ void Map::RemoveAllPlayers()
|
|||||||
void Map::UnloadAll()
|
void Map::UnloadAll()
|
||||||
{
|
{
|
||||||
// clear all delayed moves, useless anyway do this moves before map unload.
|
// clear all delayed moves, useless anyway do this moves before map unload.
|
||||||
i_creaturesToMove.clear();
|
_creaturesToMove.clear();
|
||||||
|
|
||||||
for (GridRefManager<NGridType>::iterator i = GridRefManager<NGridType>::begin(); i != GridRefManager<NGridType>::end();)
|
for (GridRefManager<NGridType>::iterator i = GridRefManager<NGridType>::begin(); i != GridRefManager<NGridType>::end();)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -193,14 +193,6 @@ public:
|
|||||||
ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data = 0);
|
ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data = 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CreatureMover
|
|
||||||
{
|
|
||||||
CreatureMover() : x(0.0f), y(0.0f), z(0.0f), ang(0.0f) {}
|
|
||||||
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
|
// 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__)
|
#if defined(__GNUC__)
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
@@ -226,8 +218,6 @@ enum LevelRequirementVsMode
|
|||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef UNORDERED_MAP<Creature*, CreatureMover> CreatureMoveList;
|
|
||||||
|
|
||||||
#define MAX_HEIGHT 100000.0f // can be use for find ground height at surface
|
#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 INVALID_HEIGHT -100000.0f // for check, must be equal to VMAP_INVALID_HEIGHT, real value for unknown height is VMAP_INVALID_HEIGHT_VALUE
|
||||||
#define MAX_FALL_DISTANCE 250000.0f // "unlimited fall" to find VMap ground if it is available, just larger than MAX_HEIGHT - INVALID_HEIGHT
|
#define MAX_FALL_DISTANCE 250000.0f // "unlimited fall" to find VMap ground if it is available, just larger than MAX_HEIGHT - INVALID_HEIGHT
|
||||||
@@ -344,7 +334,8 @@ class Map : public GridRefManager<NGridType>
|
|||||||
void RemoveAllObjectsInRemoveList();
|
void RemoveAllObjectsInRemoveList();
|
||||||
virtual void RemoveAllPlayers();
|
virtual void RemoveAllPlayers();
|
||||||
|
|
||||||
bool CreatureRespawnRelocation(Creature* c); // used only in MoveAllCreaturesInMoveList and ObjectGridUnloader
|
// used only in MoveAllCreaturesInMoveList and ObjectGridUnloader
|
||||||
|
bool CreatureRespawnRelocation(Creature* c, bool diffGridOnly);
|
||||||
|
|
||||||
// assert print helper
|
// assert print helper
|
||||||
bool CheckGridIntegrity(Creature* c, bool moved) const;
|
bool CheckGridIntegrity(Creature* c, bool moved) const;
|
||||||
@@ -449,8 +440,11 @@ class Map : public GridRefManager<NGridType>
|
|||||||
|
|
||||||
bool CreatureCellRelocation(Creature* creature, Cell new_cell);
|
bool CreatureCellRelocation(Creature* creature, Cell new_cell);
|
||||||
|
|
||||||
|
template<class T> void InitializeObject(T* obj);
|
||||||
void AddCreatureToMoveList(Creature* c, float x, float y, float z, float ang);
|
void AddCreatureToMoveList(Creature* c, float x, float y, float z, float ang);
|
||||||
CreatureMoveList i_creaturesToMove;
|
void RemoveCreatureFromMoveList(Creature* c);
|
||||||
|
bool _creatureToMoveLock;
|
||||||
|
std::vector<Creature*> _creaturesToMove;
|
||||||
|
|
||||||
bool loaded(const GridPair &) const;
|
bool loaded(const GridPair &) const;
|
||||||
void EnsureGridCreated(const GridPair &);
|
void EnsureGridCreated(const GridPair &);
|
||||||
|
|||||||
Reference in New Issue
Block a user