Merge branch 'master' into 303

This commit is contained in:
tomrus88 2008-11-17 01:50:37 +03:00
commit 52b0ab1f89
20 changed files with 294 additions and 128 deletions

View file

@ -31,7 +31,9 @@ template <class TO, class FROM> class RefManager : public LinkedListHead
virtual ~RefManager() { clearReferences(); }
Reference<TO, FROM>* getFirst() { return ((Reference<TO, FROM>*) LinkedListHead::getFirst()); }
Reference<TO, FROM> const* getFirst() const { return ((Reference<TO, FROM> const*) LinkedListHead::getFirst()); }
Reference<TO, FROM>* getLast() { return ((Reference<TO, FROM>*) LinkedListHead::getLast()); }
Reference<TO, FROM> const* getLast() const { return ((Reference<TO, FROM> const*) LinkedListHead::getLast()); }
iterator begin() { return iterator(getFirst()); }
iterator end() { return iterator(NULL); }

View file

@ -72,6 +72,7 @@ template <class TO, class FROM> class Reference : public LinkedListElement
}
Reference<TO,FROM>* next() { return((Reference<TO,FROM>*)LinkedListElement::next()); }
Reference<TO,FROM>const* next() const { return((Reference<TO,FROM> const*)LinkedListElement::next()); }
Reference<TO,FROM>* prev() { return((Reference<TO,FROM>*)LinkedListElement::prev()); }
inline TO* operator ->() const { return iRefTo; }

View file

@ -34,7 +34,7 @@ ActiveState::Update(Map &m, NGridType &grid, GridInfo & info, const uint32 &x, c
info.UpdateTimeTracker(t_diff);
if( info.getTimeTracker().Passed() )
{
if( grid.ActiveObjectsInGrid() == 0 && !ObjectAccessor::Instance().PlayersNearGrid(x, y, m.GetId(), m.GetInstanceId()) )
if( grid.ActiveObjectsInGrid() == 0 && !m.PlayersNearGrid(x, y) )
{
ObjectGridStoper stoper(grid);
stoper.StopN();

View file

@ -160,6 +160,8 @@ libmangosgame_a_SOURCES = \
MapInstanced.h \
MapManager.cpp \
MapManager.h \
MapReference.h \
MapRefManager.h \
MiscHandler.cpp \
MotionMaster.cpp \
MotionMaster.h \

View file

@ -33,6 +33,7 @@
#include "World.h"
#include "ScriptCalls.h"
#include "Group.h"
#include "MapRefManager.h"
#include "MapInstanced.h"
#include "InstanceSaveMgr.h"
@ -418,6 +419,8 @@ Map::LoadGrid(const Cell& cell, bool no_unload)
bool Map::Add(Player *player)
{
player->GetMapRef().link(this, player);
player->SetInstanceId(GetInstanceId());
// update player state for other player and visa-versa
@ -570,22 +573,13 @@ void Map::Update(const uint32 &t_diff)
// for pets
TypeContainerVisitor<MaNGOS::ObjectUpdater, WorldTypeMapContainer > world_object_update(updater);
//TODO: Player guard
HashMapHolder<Player>::MapType& playerMap = HashMapHolder<Player>::GetContainer();
for(HashMapHolder<Player>::MapType::iterator iter = playerMap.begin(); iter != playerMap.end(); ++iter)
for(MapRefManager::iterator iter = m_mapRefManager.begin(); iter != m_mapRefManager.end(); ++iter)
{
WorldObject* obj = iter->second;
if(!obj->IsInWorld())
Player* plr = iter->getSource();
if(!plr->IsInWorld())
continue;
if(obj->GetMapId() != GetId())
continue;
if(obj->GetInstanceId() != GetInstanceId())
continue;
CellPair standing_cell(MaNGOS::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()));
CellPair standing_cell(MaNGOS::ComputeCellPair(plr->GetPositionX(), plr->GetPositionY()));
// Check for correctness of standing_cell, it also avoids problems with update_cell
if (standing_cell.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || standing_cell.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP)
@ -637,6 +631,7 @@ void Map::Update(const uint32 &t_diff)
void Map::Remove(Player *player, bool remove)
{
player->GetMapRef().unlink();
CellPair p = MaNGOS::ComputeCellPair(player->GetPositionX(), player->GetPositionY());
if(p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP)
{
@ -925,7 +920,7 @@ bool Map::UnloadGrid(const uint32 &x, const uint32 &y, bool pForce)
assert( grid != NULL);
{
if(!pForce && ObjectAccessor::Instance().PlayersNearGrid(x, y, i_id, i_InstanceId) )
if(!pForce && PlayersNearGrid(x, y) )
return false;
DEBUG_LOG("Unloading grid[%u,%u] for map %u", x,y, i_id);
@ -1434,6 +1429,43 @@ bool Map::CanUnload(const uint32 &diff)
return false;
}
uint32 Map::GetPlayersCountExceptGMs() const
{
uint32 count = 0;
for(MapRefManager::const_iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr)
if(!itr->getSource()->isGameMaster())
++count;
return count;
}
void Map::SendToPlayers(WorldPacket const* data) const
{
for(MapRefManager::const_iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr)
itr->getSource()->GetSession()->SendPacket(data);
}
bool Map::PlayersNearGrid(uint32 x, uint32 y) const
{
CellPair cell_min(x*MAX_NUMBER_OF_CELLS, y*MAX_NUMBER_OF_CELLS);
CellPair cell_max(cell_min.x_coord + MAX_NUMBER_OF_CELLS, cell_min.y_coord+MAX_NUMBER_OF_CELLS);
cell_min << 2;
cell_min -= 2;
cell_max >> 2;
cell_max += 2;
for(MapRefManager::const_iterator iter = m_mapRefManager.begin(); iter != m_mapRefManager.end(); ++iter)
{
Player* plr = iter->getSource();
CellPair p = MaNGOS::ComputeCellPair(plr->GetPositionX(), plr->GetPositionY());
if( (cell_min.x_coord <= p.x_coord && p.x_coord <= cell_max.x_coord) &&
(cell_min.y_coord <= p.y_coord && p.y_coord <= cell_max.y_coord) )
return true;
}
return false;
}
template void Map::Add(Corpse *);
template void Map::Add(Creature *);
template void Map::Add(GameObject *);
@ -1469,7 +1501,7 @@ InstanceMap::~InstanceMap()
*/
bool InstanceMap::CanEnter(Player *player)
{
if(std::find(i_Players.begin(),i_Players.end(),player)!=i_Players.end())
if(player->GetMapRef().getTarget() == this)
{
sLog.outError("InstanceMap::CanEnter - player %s(%u) already in map %d,%d,%d!", player->GetName(), player->GetGUIDLow(), GetId(), GetInstanceId(), GetSpawnMode());
assert(false);
@ -1586,7 +1618,6 @@ bool InstanceMap::Add(Player *player)
if(i_data) i_data->OnPlayerEnter(player);
SetResetSchedule(false);
i_Players.push_back(player);
player->SendInitWorldStates();
sLog.outDetail("MAP: Player '%s' entered the instance '%u' of map '%s'", player->GetName(), GetInstanceId(), GetMapName());
// initialize unload state
@ -1611,9 +1642,9 @@ void InstanceMap::Update(const uint32& t_diff)
void InstanceMap::Remove(Player *player, bool remove)
{
sLog.outDetail("MAP: Removing player '%s' from instance '%u' of map '%s' before relocating to other map", player->GetName(), GetInstanceId(), GetMapName());
i_Players.remove(player);
SetResetSchedule(true);
if(!m_unloadTimer && i_Players.empty())
//if last player set unload timer
if(!m_unloadTimer && m_mapRefManager.getSize() == 1)
m_unloadTimer = m_unloadWhenEmpty ? MIN_UNLOAD_DELAY : std::max(sWorld.getConfig(CONFIG_INSTANCE_UNLOAD_DELAY), (uint32)MIN_UNLOAD_DELAY);
Map::Remove(player, remove);
}
@ -1664,21 +1695,21 @@ bool InstanceMap::Reset(uint8 method)
// note: since the map may not be loaded when the instance needs to be reset
// the instance must be deleted from the DB by InstanceSaveManager
if(!i_Players.empty())
if(HavePlayers())
{
if(method == INSTANCE_RESET_ALL)
{
// notify the players to leave the instance so it can be reset
for(PlayerList::iterator itr = i_Players.begin(); itr != i_Players.end(); ++itr)
(*itr)->SendResetFailedNotify(GetId());
for(MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr)
itr->getSource()->SendResetFailedNotify(GetId());
}
else
{
if(method == INSTANCE_RESET_GLOBAL)
{
// set the homebind timer for players inside (1 minute)
for(PlayerList::iterator itr = i_Players.begin(); itr != i_Players.end(); ++itr)
(*itr)->m_InstanceValid = false;
for(MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr)
itr->getSource()->m_InstanceValid = false;
}
// the unload timer is not started
@ -1694,16 +1725,7 @@ bool InstanceMap::Reset(uint8 method)
m_resetAfterUnload = true;
}
return i_Players.empty();
}
uint32 InstanceMap::GetPlayersCountExceptGMs() const
{
uint32 count = 0;
for(PlayerList::const_iterator itr = i_Players.begin(); itr != i_Players.end(); ++itr)
if(!(*itr)->isGameMaster())
++count;
return count;
return m_mapRefManager.isEmpty();
}
void InstanceMap::PermBindAllPlayers(Player *player)
@ -1717,27 +1739,25 @@ void InstanceMap::PermBindAllPlayers(Player *player)
Group *group = player->GetGroup();
// group members outside the instance group don't get bound
for(PlayerList::iterator itr = i_Players.begin(); itr != i_Players.end(); ++itr)
{
if(*itr)
for(MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr)
{
Player* plr = itr->getSource();
// players inside an instance cannot be bound to other instances
// some players may already be permanently bound, in this case nothing happens
InstancePlayerBind *bind = (*itr)->GetBoundInstance(save->GetMapId(), save->GetDifficulty());
InstancePlayerBind *bind = plr->GetBoundInstance(save->GetMapId(), save->GetDifficulty());
if(!bind || !bind->perm)
{
(*itr)->BindToInstance(save, true);
plr->BindToInstance(save, true);
WorldPacket data(SMSG_INSTANCE_SAVE_CREATED, 4);
data << uint32(0);
(*itr)->GetSession()->SendPacket(&data);
plr->GetSession()->SendPacket(&data);
}
// if the leader is not in the instance the group will not get a perm bind
if(group && group->GetLeaderGUID() == (*itr)->GetGUID())
if(group && group->GetLeaderGUID() == plr->GetGUID())
group->BindToInstance(save, true);
}
}
}
time_t InstanceMap::GetResetTime()
{
@ -1747,11 +1767,14 @@ time_t InstanceMap::GetResetTime()
void InstanceMap::UnloadAll(bool pForce)
{
if(!i_Players.empty())
if(HavePlayers())
{
sLog.outError("InstanceMap::UnloadAll: there are still players in the instance at unload, should not happen!");
for(PlayerList::iterator itr = i_Players.begin(); itr != i_Players.end(); ++itr)
if(*itr) (*itr)->TeleportTo((*itr)->m_homebindMapId, (*itr)->m_homebindX, (*itr)->m_homebindY, (*itr)->m_homebindZ, (*itr)->GetOrientation());
for(MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr)
{
Player* plr = itr->getSource();
plr->TeleportTo(plr->m_homebindMapId, plr->m_homebindX, plr->m_homebindY, plr->m_homebindZ, plr->GetOrientation());
}
}
if(m_resetAfterUnload == true)
@ -1762,8 +1785,8 @@ void InstanceMap::UnloadAll(bool pForce)
void InstanceMap::SendResetWarnings(uint32 timeLeft)
{
for(PlayerList::iterator itr = i_Players.begin(); itr != i_Players.end(); ++itr)
(*itr)->SendInstanceResetWarning(GetId(), timeLeft);
for(MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr)
itr->getSource()->SendInstanceResetWarning(GetId(), timeLeft);
}
void InstanceMap::SetResetSchedule(bool on)
@ -1771,7 +1794,7 @@ void InstanceMap::SetResetSchedule(bool on)
// only for normal instances
// the reset time is only scheduled when there are no payers inside
// it is assumed that the reset time will rarely (if ever) change while the reset is scheduled
if(i_Players.empty() && !IsRaid() && !IsHeroic())
if(!HavePlayers() && !IsRaid() && !IsHeroic())
{
InstanceSave *save = sInstanceSaveManager.GetInstanceSave(GetInstanceId());
if(!save) sLog.outError("InstanceMap::SetResetSchedule: cannot turn schedule %s, no save available for instance %d of %d", on ? "on" : "off", GetInstanceId(), GetId());
@ -1779,12 +1802,6 @@ void InstanceMap::SetResetSchedule(bool on)
}
}
void InstanceMap::SendToPlayers(WorldPacket const* data) const
{
for(PlayerList::const_iterator itr = i_Players.begin(); itr != i_Players.end(); ++itr)
(*itr)->GetSession()->SendPacket(data);
}
/* ******* Battleground Instance Maps ******* */
BattleGroundMap::BattleGroundMap(uint32 id, time_t expiry, uint32 InstanceId)
@ -1798,7 +1815,7 @@ BattleGroundMap::~BattleGroundMap()
bool BattleGroundMap::CanEnter(Player * player)
{
if(std::find(i_Players.begin(),i_Players.end(),player)!=i_Players.end())
if(player->GetMapRef().getTarget() == this)
{
sLog.outError("BGMap::CanEnter - player %u already in map!", player->GetGUIDLow());
assert(false);
@ -1819,7 +1836,6 @@ bool BattleGroundMap::Add(Player * player)
Guard guard(*this);
if(!CanEnter(player))
return false;
i_Players.push_back(player);
// reset instance validity, battleground maps do not homebind
player->m_InstanceValid = true;
}
@ -1829,7 +1845,6 @@ bool BattleGroundMap::Add(Player * player)
void BattleGroundMap::Remove(Player *player, bool remove)
{
sLog.outDetail("MAP: Removing player '%s' from bg '%u' of map '%s' before relocating to other map", player->GetName(), GetInstanceId(), GetMapName());
i_Players.remove(player);
Map::Remove(player, remove);
}
@ -1840,15 +1855,14 @@ void BattleGroundMap::SetUnload()
void BattleGroundMap::UnloadAll(bool pForce)
{
while(!i_Players.empty())
while(HavePlayers())
{
PlayerList::iterator itr = i_Players.begin();
Player * plr = *itr;
if(plr) (plr)->TeleportTo((*itr)->m_homebindMapId, (*itr)->m_homebindX, (*itr)->m_homebindY, (*itr)->m_homebindZ, (*itr)->GetOrientation());
Player * plr = m_mapRefManager.getFirst()->getSource();
if(plr) (plr)->TeleportTo(plr->m_homebindMapId, plr->m_homebindX, plr->m_homebindY, plr->m_homebindZ, plr->GetOrientation());
// TeleportTo removes the player from this map (if the map exists) -> calls BattleGroundMap::Remove -> invalidates the iterator.
// just in case, remove the player from the list explicitly here as well to prevent a possible infinite loop
// note that this remove is not needed if the code works well in other places
i_Players.remove(plr);
plr->GetMapRef().unlink();
}
Map::UnloadAll(pForce);

View file

@ -31,6 +31,7 @@
#include "Timer.h"
#include "SharedDefines.h"
#include "GameSystem/GridRefManager.h"
#include "MapRefManager.h"
#include <bitset>
#include <list>
@ -244,6 +245,14 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
bool isCellMarked(uint32 pCellId) { return marked_cells.test(pCellId); }
void markCell(uint32 pCellId) { marked_cells.set(pCellId); }
bool HavePlayers() const { return !m_mapRefManager.isEmpty(); }
uint32 GetPlayersCountExceptGMs() const;
bool PlayersNearGrid(uint32 x,uint32 y) const;
void SendToPlayers(WorldPacket const* data) const;
MapRefManager m_mapRefManager;
private:
void LoadVMap(int pX, int pY);
void LoadMap(uint32 mapid, uint32 instanceid, int x,int y);
@ -343,13 +352,9 @@ class MANGOS_DLL_SPEC InstanceMap : public Map
uint32 GetScriptId() { return i_script_id; }
InstanceData* GetInstanceData() { return i_data; }
void PermBindAllPlayers(Player *player);
PlayerList const& GetPlayers() const { return i_Players;}
void SendToPlayers(WorldPacket const* data) const;
time_t GetResetTime();
void UnloadAll(bool pForce);
bool CanEnter(Player* player);
uint32 GetPlayersCountExceptGMs() const;
uint32 HavePlayers() const { return !i_Players.empty(); }
void SendResetWarnings(uint32 timeLeft);
void SetResetSchedule(bool on);
private:
@ -357,16 +362,11 @@ class MANGOS_DLL_SPEC InstanceMap : public Map
bool m_unloadWhenEmpty;
InstanceData* i_data;
uint32 i_script_id;
// only online players that are inside the instance currently
// TODO ? - use the grid instead to access the players
PlayerList i_Players;
};
class MANGOS_DLL_SPEC BattleGroundMap : public Map
{
public:
typedef std::list<Player *> PlayerList; // online players only
BattleGroundMap(uint32 id, time_t, uint32 InstanceId);
~BattleGroundMap();
@ -375,8 +375,6 @@ class MANGOS_DLL_SPEC BattleGroundMap : public Map
bool CanEnter(Player* player);
void SetUnload();
void UnloadAll(bool pForce);
private:
PlayerList i_Players;
};
/*inline

View file

@ -337,7 +337,7 @@ uint32 MapManager::GetNumPlayersInInstances()
MapInstanced::InstancedMaps &maps = ((MapInstanced *)map)->GetInstancedMaps();
for(MapInstanced::InstancedMaps::iterator mitr = maps.begin(); mitr != maps.end(); ++mitr)
if(mitr->second->IsDungeon())
ret += ((InstanceMap*)mitr->second)->GetPlayers().size();
ret += ((InstanceMap*)mitr->second)->m_mapRefManager.getSize();
}
return ret;
}

44
src/game/MapRefManager.h Normal file
View file

@ -0,0 +1,44 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _MAPREFMANAGER
#define _MAPREFMANAGER
#include "Utilities/LinkedReference/RefManager.h"
class MapReference;
class MapRefManager : public RefManager<Map, Player>
{
public:
typedef LinkedListHead::Iterator< MapReference > iterator;
typedef LinkedListHead::Iterator< MapReference const > const_iterator;
MapReference* getFirst() { return (MapReference*)RefManager<Map, Player>::getFirst(); }
MapReference const* getFirst() const { return (MapReference const*)RefManager<Map, Player>::getFirst(); }
MapReference* getLast() { return (MapReference*)RefManager<Map, Player>::getLast(); }
MapReference const* getLast() const { return (MapReference const*)RefManager<Map, Player>::getLast(); }
iterator begin() { return iterator(getFirst()); }
iterator end() { return iterator(NULL); }
iterator rbegin() { return iterator(getLast()); }
iterator rend() { return iterator(NULL); }
const_iterator begin() const { return const_iterator(getFirst()); }
const_iterator end() const { return const_iterator(getLast()); }
};
#endif

50
src/game/MapReference.h Normal file
View file

@ -0,0 +1,50 @@
/*
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _MAPREFERENCE_H
#define _MAPREFERENCE_H
#include "Utilities/LinkedReference/Reference.h"
#include "Map.h"
class MANGOS_DLL_SPEC MapReference : public Reference<Map, Player>
{
protected:
void targetObjectBuildLink()
{
// called from link()
getTarget()->m_mapRefManager.insertFirst(this);
getTarget()->m_mapRefManager.incSize();
}
void targetObjectDestroyLink()
{
// called from unlink()
if(isValid()) getTarget()->m_mapRefManager.decSize();
}
void sourceObjectDestroyLink()
{
// called from invalidate()
getTarget()->m_mapRefManager.decSize();
}
public:
MapReference() : Reference<Map, Player>() {}
~MapReference() { unlink(); }
MapReference *next() { return (MapReference*)Reference<Map, Player>::next(); }
MapReference const *next() const { return (MapReference const*)Reference<Map, Player>::next(); }
};
#endif

View file

@ -519,32 +519,6 @@ ObjectAccessor::UpdatePlayers(uint32 diff)
iter->second->Update(diff);
}
bool
ObjectAccessor::PlayersNearGrid(uint32 x, uint32 y, uint32 m_id, uint32 i_id) const
{
CellPair cell_min(x*MAX_NUMBER_OF_CELLS, y*MAX_NUMBER_OF_CELLS);
CellPair cell_max(cell_min.x_coord + MAX_NUMBER_OF_CELLS, cell_min.y_coord+MAX_NUMBER_OF_CELLS);
cell_min << 2;
cell_min -= 2;
cell_max >> 2;
cell_max += 2;
//TODO: Guard player
HashMapHolder<Player>::MapType& playerMap = HashMapHolder<Player>::GetContainer();
for(HashMapHolder<Player>::MapType::const_iterator iter=playerMap.begin(); iter != playerMap.end(); ++iter)
{
if( m_id != iter->second->GetMapId() || i_id != iter->second->GetInstanceId() )
continue;
CellPair p = MaNGOS::ComputeCellPair(iter->second->GetPositionX(), iter->second->GetPositionY());
if( (cell_min.x_coord <= p.x_coord && p.x_coord <= cell_max.x_coord) &&
(cell_min.y_coord <= p.y_coord && p.y_coord <= cell_max.y_coord) )
return true;
}
return false;
}
void
ObjectAccessor::WorldObjectChangeAccumulator::Visit(PlayerMapType &m)
{

View file

@ -194,8 +194,6 @@ class MANGOS_DLL_DECL ObjectAccessor : public MaNGOS::Singleton<ObjectAccessor,
void AddCorpsesToGrid(GridPair const& gridpair,GridType& grid,Map* map);
Corpse* ConvertCorpseForPlayer(uint64 player_guid);
bool PlayersNearGrid(uint32 x,uint32 y,uint32 m_id,uint32 i_id) const;
static void UpdateObject(Object* obj, Player* exceptPlayer);
static void _buildUpdateObject(Object* obj, UpdateDataMapType &);

View file

@ -31,6 +31,7 @@
#include "Bag.h"
#include "WorldSession.h"
#include "Pet.h"
#include "MapReference.h"
#include "Util.h" // for Tokens typedef
#include "AchievementMgr.h"
@ -2057,6 +2058,8 @@ class MANGOS_DLL_SPEC Player : public Unit
Player* GetNextRandomRaidMember(float radius);
GridReference<Player> &GetGridRef() { return m_gridRef; }
MapReference &GetMapRef() { return m_mapRef; }
bool isAllowedToLoot(Creature* creature);
WorldLocation& GetTeleportDest() { return m_teleport_dest; }
@ -2303,6 +2306,7 @@ class MANGOS_DLL_SPEC Player : public Unit
Item* _StoreItem( uint16 pos, Item *pItem, uint32 count, bool clone, bool update );
GridReference<Player> m_gridRef;
MapReference m_mapRef;
};
void AddItemsSetItem(Player*player,Item *item);

View file

@ -2035,6 +2035,17 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
caster->CastSpell(m_target,finalSpelId,true,NULL,this);
return;
}
// Waiting to Resurrect
if(GetId()==2584)
{
// Waiting to resurrect spell cancel, we must remove player from resurrect queue
if(m_target->GetTypeId() == TYPEID_PLAYER)
if(BattleGround *bg = ((Player*)m_target)->GetBattleGround())
bg->RemovePlayerFromResurrectQueue(m_target->GetGUID());
return;
}
// Dark Fiend
if(GetId()==45934)
{

View file

@ -363,16 +363,24 @@ void WorldSession::HandleCancelAuraOpcode( WorldPacket& recvPacket)
if(!IsPositiveSpell(spellId) || (spellInfo->Attributes & SPELL_ATTR_CANT_CANCEL))
return;
_player->RemoveAurasDueToSpellByCancel(spellId);
if (spellId == 2584) // Waiting to resurrect spell cancel, we must remove player from resurrect queue
// channeled spell case (it currently casted then)
if(IsChanneledSpell(spellInfo))
{
BattleGround *bg = _player->GetBattleGround();
if(!bg)
return;
bg->RemovePlayerFromResurrectQueue(_player->GetGUID());
if(Spell* spell = _player->m_currentSpells[CURRENT_CHANNELED_SPELL])
{
if(spell->m_spellInfo->Id==spellId)
{
spell->cancel();
spell->SetReferencedFromCurrent(false);
_player->m_currentSpells[CURRENT_CHANNELED_SPELL] = NULL;
}
}
return;
}
// non channeled case
_player->RemoveAurasDueToSpellByCancel(spellId);
}
void WorldSession::HandlePetCancelAuraOpcode( WorldPacket& recvPacket)
{

View file

@ -4105,12 +4105,17 @@ void Unit::RemoveNotOwnSingleTargetAuras()
void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode)
{
if (IsSingleTargetSpell((*i).second->GetSpellProto()))
Aura* Aur = i->second;
SpellEntry const* AurSpellInfo = Aur->GetSpellProto();
Unit* caster = NULL;
if (IsSingleTargetSpell(AurSpellInfo))
{
if(Unit* caster = (*i).second->GetCaster())
caster = Aur->GetCaster();
if(!caster)
{
AuraList& scAuras = caster->GetSingleCastAuras();
scAuras.remove((*i).second);
scAuras.remove(Aur);
}
else
{
@ -4119,13 +4124,12 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode)
}
}
if ((*i).second->GetModifier()->m_auraname < TOTAL_AURAS)
// remove from list before mods removing (prevent cyclic calls, mods added before including to aura list - use reverse order)
if (Aur->GetModifier()->m_auraname < TOTAL_AURAS)
{
m_modAuras[(*i).second->GetModifier()->m_auraname].remove((*i).second);
m_modAuras[Aur->GetModifier()->m_auraname].remove(Aur);
}
// remove from list before mods removing (prevent cyclic calls, mods added before including to aura list - use reverse order)
Aura* Aur = i->second;
// Set remove mode
Aur->SetRemoveMode(mode);
// some ShapeshiftBoosts at remove trigger removing other auras including parent Shapeshift aura
@ -4135,16 +4139,29 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode)
// Statue unsummoned at aura remove
Totem* statue = NULL;
if(IsChanneledSpell(Aur->GetSpellProto()))
if(Unit* caster = Aur->GetCaster())
bool caster_channeled = false;
if(IsChanneledSpell(AurSpellInfo))
{
if(!caster) // can be already located for IsSingleTargetSpell case
caster = Aur->GetCaster();
if(caster)
{
if(caster->GetTypeId()==TYPEID_UNIT && ((Creature*)caster)->isTotem() && ((Totem*)caster)->GetTotemType()==TOTEM_STATUE)
statue = ((Totem*)caster);
else
caster_channeled = caster==this;
}
}
sLog.outDebug("Aura %u now is remove mode %d",Aur->GetModifier()->m_auraname, mode);
Aur->ApplyModifier(false,true);
Aur->_RemoveAura();
delete Aur;
if(caster_channeled)
RemoveAurasAtChanneledTarget (AurSpellInfo);
if(statue)
statue->UnSummon();
@ -10919,3 +10936,23 @@ bool Unit::HandleMeandingAuraProc( Aura* triggeredByAura )
CastCustomSpell(this,33110,&heal,NULL,NULL,true,NULL,NULL,caster_guid);
return true;
}
void Unit::RemoveAurasAtChanneledTarget(SpellEntry const* spellInfo)
{
uint64 target_guid = GetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT);
if(!IS_UNIT_GUID(target_guid))
return;
Unit* target = ObjectAccessor::GetUnit(*this, target_guid);
if(!target)
return;
for (AuraMap::iterator iter = target->GetAuras().begin(); iter != target->GetAuras().end(); )
{
if (iter->second->GetId() == spellInfo->Id && iter->second->GetCasterGUID()==GetGUID())
target->RemoveAura(iter);
else
++iter;
}
}

View file

@ -1031,6 +1031,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
void RemoveAurasDueToSpellByDispel(uint32 spellId, uint64 casterGUID, Unit *dispeler);
void RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit *stealer);
void RemoveAurasDueToSpellByCancel(uint32 spellId);
void RemoveAurasAtChanneledTarget(SpellEntry const* spellInfo);
void RemoveNotOwnSingleTargetAuras();
void RemoveSpellsCausingAura(AuraType auraType);

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "6832"
#define REVISION_NR "6833"
#endif // __REVISION_NR_H__

View file

@ -876,6 +876,12 @@
<File
RelativePath="..\..\src\game\HostilRefManager.h">
</File>
<File
RelativePath="..\..\src\game\MapReference.h">
</File>
<File
RelativePath="..\..\src\game\MapRefManager.h">
</File>
<File
RelativePath="..\..\src\game\ThreatManager.cpp">
</File>

View file

@ -1338,6 +1338,14 @@
RelativePath="..\..\src\game\HostilRefManager.h"
>
</File>
<File
RelativePath="..\..\src\game\MapRefManager.h"
>
</File>
<File
RelativePath="..\..\src\game\MapReference.h"
>
</File>
<File
RelativePath="..\..\src\game\ThreatManager.cpp"
>

View file

@ -1340,6 +1340,14 @@
RelativePath="..\..\src\game\HostilRefManager.h"
>
</File>
<File
RelativePath="..\..\src\game\MapRefManager.h"
>
</File>
<File
RelativePath="..\..\src\game\MapReference.h"
>
</File>
<File
RelativePath="..\..\src\game\ThreatManager.cpp"
>