Merge remote branch 'origin/master' into 335

This commit is contained in:
tomrus88 2010-06-21 13:52:09 +04:00
commit af0402789e
101 changed files with 1749 additions and 2180 deletions

View file

@ -109,7 +109,7 @@ class MANGOS_DLL_DECL NGrid
}
const uint32& GetGridId() const { return i_gridId; }
void SetGridId(const uint32 id) const { i_gridId = id; }
void SetGridId(const uint32 id) { i_gridId = id; }
grid_state_t GetGridState() const { return i_cellstate; }
void SetGridState(grid_state_t s) { i_cellstate = s; }
uint32 getX() const { return i_x; }

View file

@ -639,7 +639,7 @@ void AchievementMgr::SendAchievementEarned(AchievementEntry const* achievement)
{
MaNGOS::AchievementChatBuilder say_builder(*GetPlayer(), CHAT_MSG_ACHIEVEMENT, LANG_ACHIEVEMENT_EARNED,achievement->ID);
MaNGOS::LocalizedPacketDo<MaNGOS::AchievementChatBuilder> say_do(say_builder);
MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::AchievementChatBuilder> > say_worker(GetPlayer(),sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_SAY),say_do);
MaNGOS::CameraDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::AchievementChatBuilder> > say_worker(GetPlayer(),sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_SAY),say_do);
Cell::VisitWorldObjects(GetPlayer(), say_worker, sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_SAY));
}

141
src/game/Camera.cpp Normal file
View file

@ -0,0 +1,141 @@
#include "Camera.h"
#include "GridNotifiersImpl.h"
#include "CellImpl.h"
#include "Log.h"
#include "Errors.h"
#include "Player.h"
Camera::Camera(Player* pl) : m_owner(*pl), m_source(pl)
{
m_source->GetViewPoint().Attach(this);
}
Camera::~Camera()
{
// view of camera should be already reseted to owner (RemoveFromWorld -> Event_RemovedFromWorld -> ResetView)
ASSERT(m_source == &m_owner);
// for symmetry with constructor and way to make viewpoint's list empty
m_source->GetViewPoint().Detach(this);
}
void Camera::ReceivePacket(WorldPacket *data)
{
m_owner.SendDirectMessage(data);
}
void Camera::UpdateForCurrentViewPoint()
{
m_gridRef.unlink();
if (GridType* grid = m_source->GetViewPoint().m_grid)
grid->AddWorldObject(this);
m_owner.SetUInt64Value(PLAYER_FARSIGHT, (m_source == &m_owner ? 0 : m_source->GetGUID()));
UpdateVisibilityForOwner();
}
void Camera::SetView(WorldObject *obj)
{
ASSERT(obj);
if (m_source == obj)
return;
if (!m_owner.IsInMap(obj))
{
sLog.outError("Camera::SetView, viewpoint is not in map with camera's owner");
return;
}
if (!obj->isType(TYPEMASK_DYNAMICOBJECT | TYPEMASK_UNIT))
{
sLog.outError("Camera::SetView, viewpoint type is not available for client");
return;
}
// detach and deregister from active objects if there are no more reasons to be active
m_source->GetViewPoint().Detach(this);
if (!m_source->isActiveObject())
m_source->GetMap()->RemoveFromActive(m_source);
m_source = obj;
if (!m_source->isActiveObject())
m_source->GetMap()->AddToActive(m_source);
m_source->GetViewPoint().Attach(this);
UpdateForCurrentViewPoint();
}
void Camera::Event_ViewPointVisibilityChanged()
{
if (!m_owner.HaveAtClient(m_source))
ResetView();
}
void Camera::ResetView()
{
SetView(&m_owner);
}
void Camera::Event_AddedToWorld()
{
GridType* grid = m_source->GetViewPoint().m_grid;
ASSERT(grid);
grid->AddWorldObject(this);
UpdateVisibilityForOwner();
}
void Camera::Event_RemovedFromWorld()
{
if (m_source == &m_owner)
{
m_gridRef.unlink();
return;
}
ResetView();
}
void Camera::Event_Moved()
{
m_gridRef.unlink();
m_source->GetViewPoint().m_grid->AddWorldObject(this);
}
void Camera::UpdateVisibilityOf(WorldObject* target)
{
m_owner.UpdateVisibilityOf(m_source, target);
}
template<class T>
void Camera::UpdateVisibilityOf(T * target, UpdateData &data, std::set<WorldObject*>& vis)
{
m_owner.template UpdateVisibilityOf<T>(m_source, target,data,vis);
}
template void Camera::UpdateVisibilityOf(Player* , UpdateData& , std::set<WorldObject*>& );
template void Camera::UpdateVisibilityOf(Creature* , UpdateData& , std::set<WorldObject*>& );
template void Camera::UpdateVisibilityOf(Corpse* , UpdateData& , std::set<WorldObject*>& );
template void Camera::UpdateVisibilityOf(GameObject* , UpdateData& , std::set<WorldObject*>& );
template void Camera::UpdateVisibilityOf(DynamicObject* , UpdateData& , std::set<WorldObject*>& );
void Camera::UpdateVisibilityForOwner()
{
MaNGOS::VisibleNotifier notifier(*this);
Cell::VisitAllObjects(m_source, notifier, m_source->GetMap()->GetVisibilityDistance(), false);
notifier.Notify();
}
//////////////////
ViewPoint::~ViewPoint()
{
if (!m_cameras.empty())
{
sLog.outError("ViewPoint destructor called, but some cameras referenced to it");
}
}

132
src/game/Camera.h Normal file
View file

@ -0,0 +1,132 @@
#ifndef MANGOSSERVER_CAMERA_H
#define MANGOSSERVER_CAMERA_H
#include "GridDefines.h"
class ViewPoint;
class WorldObject;
class UpdateData;
class WorldPacket;
class Player;
/// Camera - object-receiver. Receives broadcast packets from nearby worldobjects, object visibility changes and sends them to client
class MANGOS_DLL_SPEC Camera
{
friend class ViewPoint;
public:
explicit Camera(Player* pl);
~Camera();
WorldObject* GetBody() { return m_source;}
Player* GetOwner() { return &m_owner;}
// set camera's view to any worldobject
// Note: this worldobject must be in same map, in same phase with camera's owner(player)
// client supports only unit and dynamic objects as farsight objects
void SetView(WorldObject *obj);
// set view to camera's owner
void ResetView();
template<class T>
void UpdateVisibilityOf(T * obj, UpdateData &d, std::set<WorldObject*>& vis);
void UpdateVisibilityOf(WorldObject* obj);
void ReceivePacket(WorldPacket *data);
// updates visibility of worldobjects around viewpoint for camera's owner
void UpdateVisibilityForOwner();
private:
// called when viewpoint changes visibility state
void Event_AddedToWorld();
void Event_RemovedFromWorld();
void Event_Moved();
void Event_ViewPointVisibilityChanged();
Player& m_owner;
WorldObject* m_source;
void UpdateForCurrentViewPoint();
public:
GridReference<Camera>& GetGridRef() { return m_gridRef; }
bool isActiveObject() const { return false; }
private:
GridReference<Camera> m_gridRef;
};
/// Object-observer, notifies farsight object state to cameras that attached to it
class MANGOS_DLL_SPEC ViewPoint
{
friend class Camera;
std::list<Camera*> m_cameras;
std::list<Camera*>::iterator m_camera_iter;
GridType * m_grid;
void Attach(Camera* c) { m_cameras.push_back(c); }
void Detach(Camera* c)
{
if (m_camera_iter != m_cameras.end() && *m_camera_iter == c) // detach called during the loop
m_camera_iter = m_cameras.erase(m_camera_iter);
else
m_cameras.remove(c);
}
void CameraCall(void (Camera::*handler)())
{
if (!m_cameras.empty())
{
for(m_camera_iter = m_cameras.begin(); m_camera_iter != m_cameras.end(); ++m_camera_iter)
{
((*m_camera_iter)->*handler)();
// can be end() after handler
if (m_camera_iter == m_cameras.end())
break;
}
}
}
public:
ViewPoint() : m_grid(0), m_camera_iter(m_cameras.end()) {}
~ViewPoint();
bool hasViewers() const { return !m_cameras.empty(); }
// these events are called when viewpoint changes visibility state
void Event_AddedToWorld(GridType *grid)
{
m_grid = grid;
CameraCall(&Camera::Event_AddedToWorld);
}
void Event_RemovedFromWorld()
{
m_grid = NULL;
CameraCall(&Camera::Event_RemovedFromWorld);
}
void Event_GridChanged(GridType *grid)
{
m_grid = grid;
CameraCall(&Camera::Event_Moved);
}
void Event_ViewPointVisibilityChanged()
{
CameraCall(&Camera::Event_ViewPointVisibilityChanged);
}
void Call_UpdateVisibilityForOwner()
{
CameraCall(&Camera::UpdateVisibilityForOwner);
}
};
#endif

View file

@ -703,6 +703,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder *holder)
if (!pCurrChar->GetMap()->Add(pCurrChar))
{
// normal delayed teleport protection not applied (and this correct) for this case (Player object just created)
AreaTrigger const* at = sObjectMgr.GetGoBackTrigger(pCurrChar->GetMapId());
if(at)
pCurrChar->TeleportTo(at->target_mapId, at->target_X, at->target_Y, at->target_Z, pCurrChar->GetOrientation());

View file

@ -216,7 +216,7 @@ ChatCommand * ChatHandler::getCommandTable()
{ "zonexy", SEC_MODERATOR, false, &ChatHandler::HandleGoZoneXYCommand, "", NULL },
{ "xy", SEC_MODERATOR, false, &ChatHandler::HandleGoXYCommand, "", NULL },
{ "xyz", SEC_MODERATOR, false, &ChatHandler::HandleGoXYZCommand, "", NULL },
{ "", SEC_MODERATOR, false, &ChatHandler::HandleGoXYZCommand, "", NULL },
{ "", SEC_MODERATOR, false, &ChatHandler::HandleGoCommand, "", NULL },
{ NULL, 0, false, NULL, "", NULL }
};
@ -2057,7 +2057,7 @@ GameTele const* ChatHandler::extractGameTeleFromLink(char* text)
// id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r
char* cId = extractKeyFromLink(text,"Htele");
if(!cId)
return false;
return NULL;
// id case (explicit or from shift link)
if(cId[0] >= '0' || cId[0] >= '9')
@ -2079,7 +2079,7 @@ static char const* const guidKeys[] =
"Hplayer",
"Hcreature",
"Hgameobject",
0
NULL
};
uint64 ChatHandler::extractGuidFromLink(char* text)
@ -2133,6 +2133,130 @@ uint64 ChatHandler::extractGuidFromLink(char* text)
return 0;
}
enum LocationLinkType
{
LOCATION_LINK_PLAYER = 0, // must be first for selection in not link case
LOCATION_LINK_TELE = 1,
LOCATION_LINK_TAXINODE = 2,
LOCATION_LINK_CREATURE = 3,
LOCATION_LINK_GAMEOBJECT = 4
};
static char const* const locationKeys[] =
{
"Htele",
"Htaxinode",
"Hplayer",
"Hcreature",
"Hgameobject",
NULL
};
bool ChatHandler::extractLocationFromLink(char* text, uint32& mapid, float& x, float& y, float& z)
{
int type = 0;
// |color|Hplayer:name|h[name]|h|r
// |color|Htele:id|h[name]|h|r
// |color|Htaxinode:id|h[name]|h|r
// |color|Hcreature:creature_guid|h[name]|h|r
// |color|Hgameobject:go_guid|h[name]|h|r
char* idS = extractKeyFromLink(text,locationKeys,&type);
if(!idS)
return false;
switch(type)
{
// it also fail case
case LOCATION_LINK_PLAYER:
{
// not link and not name, possible coordinates/etc
if (isNumeric(idS[0]))
return false;
std::string name = idS;
if(!normalizePlayerName(name))
return false;
if(Player* player = sObjectMgr.GetPlayer(name.c_str()))
{
mapid = player->GetMapId();
x = player->GetPositionX();
y = player->GetPositionY();
z = player->GetPositionZ();
return true;
}
if(uint64 guid = sObjectMgr.GetPlayerGUIDByName(name))
{
// to point where player stay (if loaded)
float o;
bool in_flight;
return Player::LoadPositionFromDB(mapid, x, y, z, o, in_flight, guid);
}
return false;
}
case LOCATION_LINK_TELE:
{
uint32 id = (uint32)atol(idS);
GameTele const* tele = sObjectMgr.GetGameTele(id);
if (!tele)
return false;
mapid = tele->mapId;
x = tele->position_x;
y = tele->position_y;
z = tele->position_z;
return true;
}
case LOCATION_LINK_TAXINODE:
{
uint32 id = (uint32)atol(idS);
TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(id);
if (!node)
return false;
mapid = node->map_id;
x = node->x;
y = node->y;
z = node->z;
return true;
}
case LOCATION_LINK_CREATURE:
{
uint32 lowguid = (uint32)atol(idS);
if(CreatureData const* data = sObjectMgr.GetCreatureData(lowguid) )
{
mapid = data->mapid;
x = data->posX;
y = data->posY;
z = data->posZ;
return true;
}
else
return false;
}
case LOCATION_LINK_GAMEOBJECT:
{
uint32 lowguid = (uint32)atol(idS);
if(GameObjectData const* data = sObjectMgr.GetGOData(lowguid) )
{
mapid = data->mapid;
x = data->posX;
y = data->posY;
z = data->posZ;
return true;
}
else
return false;
}
}
// unknown type?
return false;
}
std::string ChatHandler::extractPlayerNameFromLink(char* text)
{
// |color|Hplayer:name|h[name]|h|r
@ -2229,7 +2353,7 @@ char* ChatHandler::extractQuotedArg( char* args )
{
char* space = strtok(args, "\"");
if(!space)
return false;
return NULL;
return strtok(NULL, "\"");
}
}

View file

@ -535,6 +535,7 @@ class ChatHandler
uint32 extractSpellIdFromLink(char* text);
uint64 extractGuidFromLink(char* text);
GameTele const* extractGameTeleFromLink(char* text);
bool extractLocationFromLink(char* text, uint32& mapid, float& x, float& y, float& z);
std::string extractPlayerNameFromLink(char* text);
// select by arg (name/link) or in-game selection online/offline player
bool extractPlayerTarget(char* args, Player** player, uint64* player_guid = NULL, std::string* player_name = NULL);
@ -558,6 +559,8 @@ class ChatHandler
void HandleCharacterLevel(Player* player, uint64 player_guid, uint32 oldlevel, uint32 newlevel);
void HandleLearnSkillRecipesHelper(Player* player,uint32 skill_id);
void ShowSpellListHelper(Player* target, SpellEntry const* spellInfo, LocaleConstant loc);
bool HandleGoHelper(Player* _player, uint32 mapid, float x, float y, float const* zPtr = NULL);
/**
* Stores informations about a deleted character

View file

@ -574,7 +574,7 @@ void WorldSession::HandleTextEmoteOpcode( WorldPacket & recv_data )
MaNGOS::EmoteChatBuilder emote_builder(*GetPlayer(), text_emote, emoteNum, unit);
MaNGOS::LocalizedPacketDo<MaNGOS::EmoteChatBuilder > emote_do(emote_builder);
MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::EmoteChatBuilder > > emote_worker(GetPlayer(), sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_TEXTEMOTE), emote_do);
MaNGOS::CameraDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::EmoteChatBuilder > > emote_worker(GetPlayer(), sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_TEXTEMOTE), emote_do);
Cell::VisitWorldObjects(GetPlayer(), emote_worker, sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_TEXTEMOTE));
GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote, 0, unit);

View file

@ -90,8 +90,6 @@ class Corpse : public WorldObject
GridReference<Corpse> &GetGridRef() { return m_gridRef; }
bool isActiveObject() const { return false; }
bool IsExpired(time_t t) const;
private:
GridReference<Corpse> m_gridRef;

View file

@ -117,7 +117,7 @@ m_subtype(subtype), m_defaultMovementType(IDLE_MOTION_TYPE), m_DBTableGuid(0), m
m_AlreadyCallAssistance(false), m_AlreadySearchedAssistance(false),
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_creatureInfo(NULL), m_splineFlags(SPLINEFLAG_WALKMODE)
{
m_regenTimer = 200;
m_valuesCount = UNIT_END;
@ -248,11 +248,14 @@ bool Creature::InitEntry(uint32 Entry, uint32 team, const CreatureData *data )
SetByteValue(UNIT_FIELD_BYTES_0, 2, minfo->gender);
// Load creature equipment
if(!data || data->equipmentId == 0)
{ // use default from the template
LoadEquipment(cinfo->equipmentId);
if (!data || data->equipmentId == 0)
{
if (cinfo->equipmentId == 0)
LoadEquipment(normalInfo->equipmentId); // use default from normal template if diff does not have any
else
LoadEquipment(cinfo->equipmentId); // else use from diff template
}
else if(data && data->equipmentId != -1)
else if (data && data->equipmentId != -1)
{ // override, -1 means no equipment
LoadEquipment(data->equipmentId);
}
@ -788,29 +791,6 @@ bool Creature::isCanTrainingAndResetTalentsOf(Player* pPlayer) const
&& pPlayer->getClass() == GetCreatureInfo()->trainer_class;
}
void Creature::AI_SendMoveToPacket(float x, float y, float z, uint32 time, SplineFlags flags, SplineType type)
{
/* uint32 timeElap = getMSTime();
if ((timeElap - m_startMove) < m_moveTime)
{
oX = (dX - oX) * ( (timeElap - m_startMove) / m_moveTime );
oY = (dY - oY) * ( (timeElap - m_startMove) / m_moveTime );
}
else
{
oX = dX;
oY = dY;
}
dX = x;
dY = y;
m_orientation = atan2((oY - dY), (oX - dX));
m_startMove = getMSTime();
m_moveTime = time;*/
SendMonsterMove(x, y, z, type, flags, time);
}
void Creature::PrepareBodyLootState()
{
loot.clear();
@ -2218,4 +2198,4 @@ 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);
}
}

View file

@ -444,7 +444,6 @@ class MANGOS_DLL_SPEC Creature : public Unit
bool AIM_Initialize();
void AI_SendMoveToPacket(float x, float y, float z, uint32 time, SplineFlags MovementFlags, SplineType type);
CreatureAI* AI() { return i_AI; }
void AddSplineFlag(SplineFlags f)
@ -627,7 +626,6 @@ class MANGOS_DLL_SPEC Creature : public Unit
void SetDeadByDefault (bool death_state) { m_isDeadByDefault = death_state; }
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; }
@ -692,7 +690,6 @@ class MANGOS_DLL_SPEC Creature : public Unit
private:
GridReference<Creature> m_gridRef;
CreatureInfo const* m_creatureInfo; // in difficulty mode > 0 can different from ObjMgr::GetCreatureTemplate(GetEntry())
bool m_isActiveObject;
SplineFlags m_splineFlags;
};

View file

@ -36,7 +36,7 @@ CanCastResult CreatureAI::CanCastSpell(Unit* pTarget, const SpellEntry *pSpell,
if (!isTriggered)
{
// State does not allow
if (m_creature->hasUnitState(UNIT_STAT_CAN_NOT_REACT))
if (m_creature->hasUnitState(UNIT_STAT_CAN_NOT_REACT_OR_LOST_CONTROL))
return CAST_FAIL_STATE;
if (pSpell->PreventionType == SPELL_PREVENTION_TYPE_SILENCE && m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED))

View file

@ -90,7 +90,8 @@ namespace FactorySelector
{
MovementGeneratorRegistry &mv_registry(MovementGeneratorRepository::Instance());
ASSERT( creature->GetCreatureInfo() != NULL );
const MovementGeneratorCreator *mv_factory = mv_registry.GetRegistryItem( creature->GetDefaultMovementType());
MovementGeneratorCreator const * mv_factory = mv_registry.GetRegistryItem(
IS_PLAYER_GUID(creature->GetOwnerGUID()) ? FOLLOW_MOTION_TYPE : creature->GetDefaultMovementType());
/* if( mv_factory == NULL )
{

View file

@ -1319,7 +1319,7 @@ bool CreatureEventAI::CanCast(Unit* Target, SpellEntry const *Spell, bool Trigge
return false;
//Silenced so we can't cast
if (!Triggered && (m_creature->hasUnitState(UNIT_STAT_CAN_NOT_REACT) ||
if (!Triggered && (m_creature->hasUnitState(UNIT_STAT_CAN_NOT_REACT_OR_LOST_CONTROL) ||
m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED)))
return false;

View file

@ -86,7 +86,12 @@ DestinationHolder<TRAVELLER>::StartTravel(TRAVELLER &traveller, bool sendMove)
i_totalTravelTime = traveller.GetTotalTrevelTimeTo(i_destX,i_destY,i_destZ);
i_timeElapsed = 0;
if(sendMove)
traveller.MoveTo(i_destX, i_destY, i_destZ, i_totalTravelTime);
{
if (i_totalTravelTime)
traveller.MoveTo(i_destX, i_destY, i_destZ, i_totalTravelTime);
else
traveller.Stop();
}
return i_totalTravelTime;
}

View file

@ -27,7 +27,7 @@
#include "GridNotifiersImpl.h"
#include "SpellMgr.h"
DynamicObject::DynamicObject() : WorldObject(), m_isActiveObject(false)
DynamicObject::DynamicObject() : WorldObject()
{
m_objectType |= TYPEMASK_DYNAMICOBJECT;
m_objectTypeId = TYPEID_DYNAMICOBJECT;
@ -50,7 +50,10 @@ void DynamicObject::RemoveFromWorld()
{
///- Remove the dynamicObject from the accessor
if(IsInWorld())
{
GetMap()->GetObjectsStore().erase<DynamicObject>(GetGUID(), (DynamicObject*)NULL);
GetViewPoint().Event_RemovedFromWorld();
}
Object::RemoveFromWorld();
}
@ -80,10 +83,6 @@ bool DynamicObject::Create( uint32 guidlow, Unit *caster, uint32 spellId, SpellE
m_effIndex = effIndex;
m_spellId = spellId;
// set to active for far sight case
if(SpellEntry const* spellEntry = sSpellStore.LookupEntry(spellId))
m_isActiveObject = IsSpellHaveEffect(spellEntry,SPELL_EFFECT_ADD_FARSIGHT);
return true;
}

View file

@ -61,7 +61,6 @@ class DynamicObject : public WorldObject
GridReference<DynamicObject> &GetGridRef() { return m_gridRef; }
bool isActiveObject() const { return m_isActiveObject; }
protected:
uint32 m_spellId;
SpellEffectIndex m_effIndex;
@ -70,6 +69,5 @@ class DynamicObject : public WorldObject
AffectedSet m_affected;
private:
GridReference<DynamicObject> m_gridRef;
bool m_isActiveObject;
};
#endif

View file

@ -171,6 +171,13 @@ void GameEventMgr::LoadFromDB()
sLog.outString( ">> Loaded %u game events", count );
}
std::map<uint16,int16> pool2event; // for check unique spawn event associated with pool
std::map<uint32,int16> creature2event; // for check unique spawn event associated with creature
std::map<uint32,int16> go2event; // for check unique spawn event associated with gameobject
// list only positive event top pools, filled at creature/gameobject loading
mGameEventSpawnPoolIds.resize(mGameEvent.size());
mGameEventCreatureGuids.resize(mGameEvent.size()*2-1);
// 1 2
result = WorldDatabase.Query("SELECT creature.guid, game_event_creature.event "
@ -198,6 +205,12 @@ void GameEventMgr::LoadFromDB()
uint32 guid = fields[0].GetUInt32();
int16 event_id = fields[1].GetInt16();
if (event_id == 0)
{
sLog.outErrorDb("`game_event_creature` game event id (%i) not allowed",event_id);
continue;
}
int32 internal_event_id = mGameEvent.size() + event_id - 1;
if(internal_event_id < 0 || (size_t)internal_event_id >= mGameEventCreatureGuids.size())
@ -207,6 +220,32 @@ void GameEventMgr::LoadFromDB()
}
++count;
// spawn objects at event can be grouped in pools and then affected pools have stricter requirements for this case
if (event_id > 0)
{
creature2event[guid] = event_id;
// not list explicitly creatures from pools in event creature list
if (uint16 topPoolId = sPoolMgr.IsPartOfTopPool<Creature>(guid))
{
int16& eventRef = pool2event[topPoolId];
if (eventRef != 0)
{
if (eventRef != event_id)
sLog.outErrorDb("`game_event_creature` have creature (GUID: %u) for event %i from pool or subpool of pool (ID: %u) but pool have already content from event %i. Pool don't must have content for different events!", guid, event_id, topPoolId, eventRef);
}
else
{
eventRef = event_id;
mGameEventSpawnPoolIds[event_id].push_back(topPoolId);
sPoolMgr.RemoveAutoSpawnForPool(topPoolId);
}
continue;
}
}
GuidList& crelist = mGameEventCreatureGuids[internal_event_id];
crelist.push_back(guid);
@ -244,6 +283,12 @@ void GameEventMgr::LoadFromDB()
uint32 guid = fields[0].GetUInt32();
int16 event_id = fields[1].GetInt16();
if (event_id == 0)
{
sLog.outErrorDb("`game_event_gameobject` game event id (%i) not allowed",event_id);
continue;
}
int32 internal_event_id = mGameEvent.size() + event_id - 1;
if(internal_event_id < 0 || (size_t)internal_event_id >= mGameEventGameobjectGuids.size())
@ -253,6 +298,32 @@ void GameEventMgr::LoadFromDB()
}
++count;
// spawn objects at event can be grouped in pools and then affected pools have stricter requirements for this case
if (event_id > 0)
{
go2event[guid] = event_id;
// not list explicitly gameobjects from pools in event gameobject list
if (uint16 topPoolId = sPoolMgr.IsPartOfTopPool<GameObject>(guid))
{
int16& eventRef = pool2event[topPoolId];
if (eventRef != 0)
{
if (eventRef != event_id)
sLog.outErrorDb("`game_event_gameobject` have gameobject (GUID: %u) for event %i from pool or subpool of pool (ID: %u) but pool have already content from event %i. Pool don't must have content for different events!", guid, event_id, topPoolId, eventRef);
}
else
{
eventRef = event_id;
mGameEventSpawnPoolIds[event_id].push_back(topPoolId);
sPoolMgr.RemoveAutoSpawnForPool(topPoolId);
}
continue;
}
}
GuidList& golist = mGameEventGameobjectGuids[internal_event_id];
golist.push_back(guid);
@ -263,6 +334,15 @@ void GameEventMgr::LoadFromDB()
sLog.outString( ">> Loaded %u gameobjects in game events", count );
}
// now recheck that all eventPools linked with events after our skip pools with parents
for(std::map<uint16,int16>::const_iterator itr = pool2event.begin(); itr != pool2event.end(); ++itr)
{
uint16 pool_id = itr->first;
int16 event_id = itr->second;
sPoolMgr.CheckEventLinkAndReport(pool_id, event_id, creature2event, go2event);
}
mGameEventModelEquip.resize(mGameEvent.size());
// 0 1 2
result = WorldDatabase.Query("SELECT creature.guid, game_event_model_equip.event, game_event_model_equip.modelid,"
@ -365,57 +445,6 @@ void GameEventMgr::LoadFromDB()
sLog.outString();
sLog.outString( ">> Loaded %u quests additions in game events", count );
}
mGameEventPoolIds.resize(mGameEvent.size()*2-1);
// 1 2
result = WorldDatabase.Query("SELECT pool_template.entry, game_event_pool.event "
"FROM pool_template JOIN game_event_pool ON pool_template.entry = game_event_pool.pool_entry");
count = 0;
if( !result )
{
barGoLink bar2(1);
bar2.step();
sLog.outString();
sLog.outString(">> Loaded %u pools in game events", count );
}
else
{
barGoLink bar2( (int)result->GetRowCount() );
do
{
Field *fields = result->Fetch();
bar2.step();
uint32 entry = fields[0].GetUInt16();
int16 event_id = fields[1].GetInt16();
int32 internal_event_id = mGameEvent.size() + event_id - 1;
if (internal_event_id < 0 || (size_t)internal_event_id >= mGameEventPoolIds.size())
{
sLog.outErrorDb("`game_event_pool` game event id (%i) is out of range compared to max event id in `game_event`",event_id);
continue;
}
if (!sPoolMgr.CheckPool(entry))
{
sLog.outErrorDb("Pool Id (%u) has all creatures or gameobjects with explicit chance sum <>100 and no equal chance defined. The pool system cannot pick one to spawn.", entry);
continue;
}
++count;
IdList& poollist = mGameEventPoolIds[internal_event_id];
poollist.push_back(entry);
} while( result->NextRow() );
sLog.outString();
sLog.outString( ">> Loaded %u pools in game events", count );
delete result;
}
}
uint32 GameEventMgr::Initialize() // return the next event delay in ms
@ -516,6 +545,18 @@ void GameEventMgr::GameEventSpawn(int16 event_id)
CreatureData const* data = sObjectMgr.GetCreatureData(*itr);
if (data)
{
// negative event id for pool element meaning allow be used in next pool spawn
if (event_id < 0)
{
if (uint16 pool_id = sPoolMgr.IsPartOfAPool<Creature>(*itr))
{
// will have chance at next pool update
sPoolMgr.SetExcludeObject<Creature>(pool_id, *itr, false);
sPoolMgr.UpdatePool<Creature>(pool_id);
continue;
}
}
sObjectMgr.AddCreatureToGrid(*itr, data);
// Spawn if necessary (loaded grids only)
@ -549,7 +590,20 @@ void GameEventMgr::GameEventSpawn(int16 event_id)
GameObjectData const* data = sObjectMgr.GetGOData(*itr);
if (data)
{
// negative event id for pool element meaning allow be used in next pool spawn
if (event_id < 0)
{
if (uint16 pool_id = sPoolMgr.IsPartOfAPool<GameObject>(*itr))
{
// will have chance at next pool update
sPoolMgr.SetExcludeObject<GameObject>(pool_id, *itr, false);
sPoolMgr.UpdatePool<GameObject>(pool_id);
continue;
}
}
sObjectMgr.AddGameobjectToGrid(*itr, data);
// Spawn if necessary (loaded grids only)
// this base map checked as non-instanced and then only existed
Map* map = const_cast<Map*>(sMapMgr.CreateBaseMap(data->mapid));
@ -571,14 +625,17 @@ void GameEventMgr::GameEventSpawn(int16 event_id)
}
}
if (internal_event_id < 0 || (size_t)internal_event_id >= mGameEventPoolIds.size())
if (event_id > 0)
{
sLog.outError("GameEventMgr::GameEventSpawn attempt access to out of range mGameEventPoolIds element %i (size: " SIZEFMTD ")",internal_event_id,mGameEventPoolIds.size());
return;
}
if((size_t)event_id >= mGameEventSpawnPoolIds.size())
{
sLog.outError("GameEventMgr::GameEventSpawn attempt access to out of range mGameEventSpawnPoolIds element %i (size: " SIZEFMTD ")", event_id, mGameEventSpawnPoolIds.size());
return;
}
for (IdList::iterator itr = mGameEventPoolIds[internal_event_id].begin();itr != mGameEventPoolIds[internal_event_id].end();++itr)
sPoolMgr.SpawnPool(*itr, true);
for (IdList::iterator itr = mGameEventSpawnPoolIds[event_id].begin();itr != mGameEventSpawnPoolIds[event_id].end();++itr)
sPoolMgr.SpawnPool(*itr, true);
}
}
void GameEventMgr::GameEventUnspawn(int16 event_id)
@ -596,6 +653,17 @@ void GameEventMgr::GameEventUnspawn(int16 event_id)
// Remove the creature from grid
if( CreatureData const* data = sObjectMgr.GetCreatureData(*itr) )
{
// negative event id for pool element meaning unspawn in pool and exclude for next spawns
if (event_id < 0)
{
if (uint16 poolid = sPoolMgr.IsPartOfAPool<Creature>(*itr))
{
sPoolMgr.SetExcludeObject<Creature>(poolid, *itr, true);
sPoolMgr.UpdatePool<Creature>(poolid, *itr);
continue;
}
}
sObjectMgr.RemoveCreatureFromGrid(*itr, data);
if (Creature* pCreature = ObjectAccessor::GetCreatureInWorld(ObjectGuid(HIGHGUID_UNIT, data->id, *itr)))
@ -614,21 +682,36 @@ void GameEventMgr::GameEventUnspawn(int16 event_id)
// Remove the gameobject from grid
if(GameObjectData const* data = sObjectMgr.GetGOData(*itr))
{
// negative event id for pool element meaning unspawn in pool and exclude for next spawns
if (event_id < 0)
{
if (uint16 poolid = sPoolMgr.IsPartOfAPool<GameObject>(*itr))
{
sPoolMgr.SetExcludeObject<GameObject>(poolid, *itr, true);
sPoolMgr.UpdatePool<GameObject>(poolid, *itr);
continue;
}
}
sObjectMgr.RemoveGameobjectFromGrid(*itr, data);
if( GameObject* pGameobject = ObjectAccessor::GetGameObjectInWorld(ObjectGuid(HIGHGUID_GAMEOBJECT, data->id, *itr)) )
pGameobject->AddObjectToRemoveList();
}
}
if (internal_event_id < 0 || (size_t)internal_event_id >= mGameEventPoolIds.size())
{
sLog.outError("GameEventMgr::GameEventUnspawn attempt access to out of range mGameEventPoolIds element %i (size: " SIZEFMTD ")",internal_event_id,mGameEventPoolIds.size());
return;
}
for (IdList::iterator itr = mGameEventPoolIds[internal_event_id].begin();itr != mGameEventPoolIds[internal_event_id].end();++itr)
if (event_id > 0)
{
sPoolMgr.DespawnPool(*itr);
if ((size_t)event_id >= mGameEventSpawnPoolIds.size())
{
sLog.outError("GameEventMgr::GameEventUnspawn attempt access to out of range mGameEventSpawnPoolIds element %i (size: " SIZEFMTD ")", event_id, mGameEventSpawnPoolIds.size());
return;
}
for (IdList::iterator itr = mGameEventSpawnPoolIds[event_id].begin();itr != mGameEventSpawnPoolIds[event_id].end();++itr)
{
sPoolMgr.DespawnPool(*itr);
}
}
}

View file

@ -88,11 +88,11 @@ class GameEventMgr
typedef std::pair<uint32, uint32> QuestRelation;
typedef std::list<QuestRelation> QuestRelList;
typedef std::vector<QuestRelList> GameEventQuestMap;
GameEventQuestMap mGameEventQuests;
GameEventModelEquipMap mGameEventModelEquip;
GameEventGuidMap mGameEventCreatureGuids;
GameEventGuidMap mGameEventGameobjectGuids;
GameEventIdMap mGameEventPoolIds;
GameEventQuestMap mGameEventQuests; // events*2-1
GameEventModelEquipMap mGameEventModelEquip; // events*2-1
GameEventGuidMap mGameEventCreatureGuids; // events*2-1
GameEventGuidMap mGameEventGameobjectGuids; // events*2-1
GameEventIdMap mGameEventSpawnPoolIds; // events size, only positive event case
GameEventDataMap mGameEvent;
ActiveEvents m_ActiveEvents;
bool m_IsGameEventsInit;

View file

@ -703,7 +703,6 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject
GridReference<GameObject> &GetGridRef() { return m_gridRef; }
bool isActiveObject() const { return false; }
uint64 GetRotation() const { return m_rotation; }
protected:
uint32 m_spellId;

View file

@ -31,6 +31,7 @@ class DynamicObject;
class GameObject;
class Pet;
class Player;
class Camera;
#define MAX_NUMBER_OF_GRIDS 64
@ -56,10 +57,12 @@ class Player;
#define MAP_HALFSIZE (MAP_SIZE/2)
// Creature used instead pet to simplify *::Visit templates (not required duplicate code for Creature->Pet case)
typedef TYPELIST_3(Player, Creature/*pets*/, Corpse/*resurrectable*/) AllWorldObjectTypes;
// Cameras in world list just because linked with Player objects
typedef TYPELIST_4(Player, Creature/*pets*/, Corpse/*resurrectable*/, Camera) AllWorldObjectTypes;
typedef TYPELIST_4(GameObject, Creature/*except pets*/, DynamicObject, Corpse/*Bones*/) AllGridObjectTypes;
typedef TYPELIST_5(Creature, Pet, Vehicle, GameObject, DynamicObject) AllMapStoredObjectTypes;
typedef GridRefManager<Camera> CameraMapType;
typedef GridRefManager<Corpse> CorpseMapType;
typedef GridRefManager<Creature> CreatureMapType;
typedef GridRefManager<DynamicObject> DynamicObjectMapType;

View file

@ -21,7 +21,6 @@
#include "GridStates.h"
#include "CellImpl.h"
#include "Map.h"
#include "Config/ConfigEnv.h"
#include "DBCEnums.h"
#include "DBCStores.h"
#include "GridMap.h"

View file

@ -28,32 +28,29 @@
using namespace MaNGOS;
void
VisibleChangesNotifier::Visit(PlayerMapType &m)
VisibleChangesNotifier::Visit(CameraMapType &m)
{
for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
for(CameraMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
{
Player* player = iter->getSource();
if(player == &i_object)
continue;
player->UpdateVisibilityOf(player->GetViewPoint(),&i_object);
iter->getSource()->UpdateVisibilityOf(&i_object);
}
}
void
VisibleNotifier::Notify()
{
Player& player = *i_camera.GetOwner();
// at this moment i_clientGUIDs have guids that not iterate at grid level checks
// but exist one case when this possible and object not out of range: transports
if(Transport* transport = i_player.GetTransport())
if(Transport* transport = player.GetTransport())
{
for(Transport::PlayerSet::const_iterator itr = transport->GetPassengers().begin();itr!=transport->GetPassengers().end();++itr)
{
if(i_clientGUIDs.find((*itr)->GetGUID())!=i_clientGUIDs.end())
if (i_clientGUIDs.find((*itr)->GetGUID()) != i_clientGUIDs.end())
{
// ignore far sight case
(*itr)->UpdateVisibilityOf((*itr),&i_player);
i_player.UpdateVisibilityOf(&i_player,(*itr),i_data,i_visibleNow);
(*itr)->UpdateVisibilityOf(*itr, &player);
player.UpdateVisibilityOf(&player, *itr, i_data, i_visibleNow);
i_clientGUIDs.erase((*itr)->GetGUID());
}
}
@ -63,27 +60,28 @@ VisibleNotifier::Notify()
i_data.AddOutOfRangeGUID(i_clientGUIDs);
for(ObjectGuidSet::iterator itr = i_clientGUIDs.begin();itr!=i_clientGUIDs.end();++itr)
{
i_player.m_clientGUIDs.erase(*itr);
player.m_clientGUIDs.erase(*itr);
DEBUG_FILTER_LOG(LOG_FILTER_VISIBILITY_CHANGES, "%s is out of range (no in active cells set) now for player %u",itr->GetString().c_str(),i_player.GetGUIDLow());
DEBUG_FILTER_LOG(LOG_FILTER_VISIBILITY_CHANGES, "%s is out of range (no in active cells set) now for %s",
itr->GetString().c_str(), player.GetObjectGuid().GetString().c_str());
}
if( i_data.HasData() )
if (i_data.HasData())
{
// send create/outofrange packet to player (except player create updates that already sent using SendUpdateToPlayer)
WorldPacket packet;
i_data.BuildPacket(&packet);
i_player.GetSession()->SendPacket(&packet);
player.GetSession()->SendPacket(&packet);
// send out of range to other players if need
ObjectGuidSet const& oor = i_data.GetOutOfRangeGUIDs();
for(ObjectGuidSet::const_iterator iter = oor.begin(); iter != oor.end(); ++iter)
{
if(!iter->IsPlayer())
if (!iter->IsPlayer())
continue;
if (Player* plr = ObjectAccessor::FindPlayer(*iter))
plr->UpdateVisibilityOf(plr->GetViewPoint(),&i_player);
plr->UpdateVisibilityOf(plr->GetCamera().GetBody(), &player);
}
}
@ -93,87 +91,92 @@ VisibleNotifier::Notify()
for(std::set<WorldObject*>::const_iterator vItr = i_visibleNow.begin(); vItr != i_visibleNow.end(); ++vItr)
{
// target aura duration for caster show only if target exist at caster client
if((*vItr)!=&i_player && (*vItr)->isType(TYPEMASK_UNIT))
i_player.SendAurasForTarget((Unit*)(*vItr));
if ((*vItr) != &player && (*vItr)->isType(TYPEMASK_UNIT))
player.SendAurasForTarget((Unit*)(*vItr));
// non finished movements show to player
if((*vItr)->GetTypeId()==TYPEID_UNIT && ((Creature*)(*vItr))->isAlive())
((Creature*)(*vItr))->SendMonsterMoveWithSpeedToCurrentDestination(&i_player);
if ((*vItr)->GetTypeId()==TYPEID_UNIT && ((Creature*)(*vItr))->isAlive())
((Creature*)(*vItr))->SendMonsterMoveWithSpeedToCurrentDestination(&player);
}
}
void
MessageDeliverer::Visit(PlayerMapType &m)
MessageDeliverer::Visit(CameraMapType &m)
{
for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
for(CameraMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
{
if (i_toSelf || iter->getSource() != &i_player)
Player* owner = iter->getSource()->GetOwner();
if (i_toSelf || owner != &i_player)
{
if (!i_player.InSamePhase(iter->getSource()))
if (!i_player.InSamePhase(iter->getSource()->GetBody()))
continue;
if(WorldSession* session = iter->getSource()->GetSession())
if (WorldSession* session = owner->GetSession())
session->SendPacket(i_message);
}
}
}
void MessageDelivererExcept::Visit(PlayerMapType &m)
void MessageDelivererExcept::Visit(CameraMapType &m)
{
for(PlayerMapType::iterator it = m.begin(); it!= m.end(); ++it)
for(CameraMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
{
Player* player = it->getSource();
if(!player->InSamePhase(i_phaseMask) || player == i_skipped_receiver)
Player* owner = iter->getSource()->GetOwner();
if (!owner->InSamePhase(i_phaseMask) || owner == i_skipped_receiver)
continue;
if (WorldSession* session = player->GetSession())
if (WorldSession* session = owner->GetSession())
session->SendPacket(i_message);
}
}
void
ObjectMessageDeliverer::Visit(PlayerMapType &m)
ObjectMessageDeliverer::Visit(CameraMapType &m)
{
for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
for(CameraMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
{
if(!iter->getSource()->InSamePhase(i_phaseMask))
if(!iter->getSource()->GetBody()->InSamePhase(i_phaseMask))
continue;
if(WorldSession* session = iter->getSource()->GetSession())
if(WorldSession* session = iter->getSource()->GetOwner()->GetSession())
session->SendPacket(i_message);
}
}
void
MessageDistDeliverer::Visit(PlayerMapType &m)
MessageDistDeliverer::Visit(CameraMapType &m)
{
for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
for(CameraMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
{
if ((i_toSelf || iter->getSource() != &i_player ) &&
(!i_ownTeamOnly || iter->getSource()->GetTeam() == i_player.GetTeam() ) &&
(!i_dist || iter->getSource()->IsWithinDist(&i_player,i_dist)))
Player * owner = iter->getSource()->GetOwner();
if ((i_toSelf || owner != &i_player) &&
(!i_ownTeamOnly || owner->GetTeam() == i_player.GetTeam()) &&
(!i_dist || iter->getSource()->GetBody()->IsWithinDist(&i_player,i_dist)))
{
if (!i_player.InSamePhase(iter->getSource()))
if (!i_player.InSamePhase(iter->getSource()->GetBody()))
continue;
if (WorldSession* session = iter->getSource()->GetSession())
if (WorldSession* session = owner->GetSession())
session->SendPacket(i_message);
}
}
}
void
ObjectMessageDistDeliverer::Visit(PlayerMapType &m)
ObjectMessageDistDeliverer::Visit(CameraMapType &m)
{
for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
for(CameraMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
{
if (!i_dist || iter->getSource()->IsWithinDist(&i_object,i_dist))
if (!i_dist || iter->getSource()->GetBody()->IsWithinDist(&i_object,i_dist))
{
if (!i_object.InSamePhase(iter->getSource()))
if (!i_object.InSamePhase(iter->getSource()->GetBody()))
continue;
if (WorldSession* session = iter->getSource()->GetSession())
if (WorldSession* session = iter->getSource()->GetOwner()->GetSession())
session->SendPacket(i_message);
}
}

View file

@ -38,13 +38,14 @@ namespace MaNGOS
{
struct MANGOS_DLL_DECL VisibleNotifier
{
Player &i_player;
Camera& i_camera;
UpdateData i_data;
ObjectGuidSet i_clientGUIDs;
std::set<WorldObject*> i_visibleNow;
explicit VisibleNotifier(Player &player) : i_player(player),i_clientGUIDs(player.m_clientGUIDs) {}
explicit VisibleNotifier(Camera &c) : i_camera(c), i_clientGUIDs(c.GetOwner()->m_clientGUIDs) {}
template<class T> void Visit(GridRefManager<T> &m);
void Visit(CameraMapType &m) {}
void Notify(void);
};
@ -54,7 +55,7 @@ namespace MaNGOS
explicit VisibleChangesNotifier(WorldObject &object) : i_object(object) {}
template<class T> void Visit(GridRefManager<T> &) {}
void Visit(PlayerMapType &);
void Visit(CameraMapType &);
};
struct MANGOS_DLL_DECL GridUpdater
@ -82,7 +83,7 @@ namespace MaNGOS
WorldPacket *i_message;
bool i_toSelf;
MessageDeliverer(Player &pl, WorldPacket *msg, bool to_self) : i_player(pl), i_message(msg), i_toSelf(to_self) {}
void Visit(PlayerMapType &m);
void Visit(CameraMapType &m);
template<class SKIP> void Visit(GridRefManager<SKIP> &) {}
};
@ -95,7 +96,7 @@ namespace MaNGOS
MessageDelivererExcept(WorldObject const* obj, WorldPacket *msg, Player const* skipped)
: i_phaseMask(obj->GetPhaseMask()), i_message(msg), i_skipped_receiver(skipped) {}
void Visit(PlayerMapType &m);
void Visit(CameraMapType &m);
template<class SKIP> void Visit(GridRefManager<SKIP> &) {}
};
@ -105,7 +106,7 @@ namespace MaNGOS
WorldPacket *i_message;
explicit ObjectMessageDeliverer(WorldObject& obj, WorldPacket *msg)
: i_phaseMask(obj.GetPhaseMask()), i_message(msg) {}
void Visit(PlayerMapType &m);
void Visit(CameraMapType &m);
template<class SKIP> void Visit(GridRefManager<SKIP> &) {}
};
@ -119,7 +120,7 @@ namespace MaNGOS
MessageDistDeliverer(Player &pl, WorldPacket *msg, float dist, bool to_self, bool ownTeamOnly)
: i_player(pl), i_message(msg), i_toSelf(to_self), i_ownTeamOnly(ownTeamOnly), i_dist(dist) {}
void Visit(PlayerMapType &m);
void Visit(CameraMapType &m);
template<class SKIP> void Visit(GridRefManager<SKIP> &) {}
};
@ -129,7 +130,7 @@ namespace MaNGOS
WorldPacket *i_message;
float i_dist;
ObjectMessageDistDeliverer(WorldObject &obj, WorldPacket *msg, float dist) : i_object(obj), i_message(msg), i_dist(dist) {}
void Visit(PlayerMapType &m);
void Visit(CameraMapType &m);
template<class SKIP> void Visit(GridRefManager<SKIP> &) {}
};
@ -140,6 +141,7 @@ namespace MaNGOS
template<class T> void Visit(GridRefManager<T> &m);
void Visit(PlayerMapType &) {}
void Visit(CorpseMapType &) {}
void Visit(CameraMapType &) {}
void Visit(CreatureMapType &);
};
@ -476,22 +478,21 @@ namespace MaNGOS
};
template<class Do>
struct MANGOS_DLL_DECL PlayerDistWorker
struct MANGOS_DLL_DECL CameraDistWorker
{
WorldObject const* i_searcher;
float i_dist;
Do& i_do;
PlayerDistWorker(WorldObject const* searcher, float _dist, Do& _do)
CameraDistWorker(WorldObject const* searcher, float _dist, Do& _do)
: i_searcher(searcher), i_dist(_dist), i_do(_do) {}
void Visit(PlayerMapType &m)
void Visit(CameraMapType &m)
{
for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
if (itr->getSource()->InSamePhase(i_searcher) && itr->getSource()->IsWithinDist(i_searcher,i_dist))
i_do(itr->getSource());
for(CameraMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
if (itr->getSource()->GetBody()->InSamePhase(i_searcher) && itr->getSource()->GetBody()->IsWithinDist(i_searcher,i_dist))
i_do(itr->getSource()->GetOwner());
}
template<class NOT_INTERESTED> void Visit(GridRefManager<NOT_INTERESTED> &) {}
};

View file

@ -31,11 +31,9 @@
template<class T>
inline void MaNGOS::VisibleNotifier::Visit(GridRefManager<T> &m)
{
WorldObject const* viewPoint = i_player.GetViewPoint();
for(typename GridRefManager<T>::iterator iter = m.begin(); iter != m.end(); ++iter)
{
i_player.UpdateVisibilityOf(viewPoint,iter->getSource(), i_data, i_visibleNow);
i_camera.UpdateVisibilityOf(iter->getSource(), i_data, i_visibleNow);
i_clientGUIDs.erase(iter->getSource()->GetGUID());
}
}
@ -69,7 +67,7 @@ inline void PlayerCreatureRelocationWorker(Player* pl, WorldObject const* viewPo
pl->UpdateVisibilityOf(viewPoint,c);
// Creature AI reaction
if (!c->hasUnitState(UNIT_STAT_FLEEING))
if (!c->hasUnitState(UNIT_STAT_LOST_CONTROL))
{
if (c->AI() && c->AI()->IsVisible(pl) && !c->IsInEvadeMode())
c->AI()->MoveInLineOfSight(pl);
@ -78,13 +76,13 @@ inline void PlayerCreatureRelocationWorker(Player* pl, WorldObject const* viewPo
inline void CreatureCreatureRelocationWorker(Creature* c1, Creature* c2)
{
if (!c1->hasUnitState(UNIT_STAT_FLEEING))
if (!c1->hasUnitState(UNIT_STAT_LOST_CONTROL))
{
if (c1->AI() && c1->AI()->IsVisible(c2) && !c1->IsInEvadeMode())
c1->AI()->MoveInLineOfSight(c2);
}
if (!c2->hasUnitState(UNIT_STAT_FLEEING))
if (!c2->hasUnitState(UNIT_STAT_LOST_CONTROL))
{
if (c2->AI() && c2->AI()->IsVisible(c1) && !c2->IsInEvadeMode())
c2->AI()->MoveInLineOfSight(c1);
@ -96,7 +94,7 @@ inline void MaNGOS::PlayerRelocationNotifier::Visit(CreatureMapType &m)
if (!i_player.isAlive() || i_player.isInFlight())
return;
WorldObject const* viewPoint = i_player.GetViewPoint();
WorldObject const* viewPoint = i_player.GetCamera().GetBody();
for(CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
if (iter->getSource()->isAlive())
@ -106,13 +104,13 @@ inline void MaNGOS::PlayerRelocationNotifier::Visit(CreatureMapType &m)
template<>
inline void MaNGOS::CreatureRelocationNotifier::Visit(PlayerMapType &m)
{
if(!i_creature.isAlive())
if (!i_creature.isAlive())
return;
for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
if (Player* player = iter->getSource())
if (player->isAlive() && !player->isInFlight())
PlayerCreatureRelocationWorker(player, player->GetViewPoint(), &i_creature);
PlayerCreatureRelocationWorker(player, player->GetCamera().GetBody(), &i_creature);
}
template<>

View file

@ -771,7 +771,7 @@ void Group::CountTheRoll(Rolls::iterator& rollI)
if (itr->second != ROLL_NEED)
continue;
uint8 randomN = urand(1, 99);
uint8 randomN = urand(1, 100);
SendLootRoll(itr->first, randomN, ROLL_NEED, *roll);
if (maxresul < randomN)
{
@ -819,7 +819,7 @@ void Group::CountTheRoll(Rolls::iterator& rollI)
if (itr->second != ROLL_GREED && itr->second != ROLL_DISENCHANT)
continue;
uint8 randomN = urand(1, 99);
uint8 randomN = urand(1, 100);
SendLootRoll(itr->first, randomN, itr->second, *roll);
if (maxresul < randomN)
{

View file

@ -30,7 +30,6 @@
#include "InstanceSaveMgr.h"
#include "Timer.h"
#include "GridNotifiersImpl.h"
#include "Config/ConfigEnv.h"
#include "Transports.h"
#include "ObjectMgr.h"
#include "World.h"

View file

@ -2226,6 +2226,51 @@ bool ChatHandler::HandleGroupgoCommand(const char* args)
return true;
}
bool ChatHandler::HandleGoHelper( Player* player, uint32 mapid, float x, float y, float const* zPtr )
{
float z;
if (zPtr)
{
z = *zPtr;
// check full provided coordinates
if(!MapManager::IsValidMapCoord(mapid,x,y,z))
{
PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid);
SetSentErrorMessage(true);
return false;
}
}
else
{
// we need check x,y before ask Z or can crash at invalide coordinates
if(!MapManager::IsValidMapCoord(mapid,x,y))
{
PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid);
SetSentErrorMessage(true);
return false;
}
Map const *map = sMapMgr.CreateBaseMap(mapid);
z = std::max(map->GetHeight(x, y, MAX_HEIGHT), map->GetWaterLevel(x, y));
}
// stop flight if need
if(player->isInFlight())
{
player->GetMotionMaster()->MovementExpired();
player->m_taxi.ClearTaxiDestinations();
}
// save only in non-flight case
else
player->SaveRecallPosition();
player->TeleportTo(mapid, x, y, z, player->GetOrientation());
return true;
}
bool ChatHandler::HandleGoTaxinodeCommand(const char* args)
{
Player* _player = m_session->GetPlayer();
@ -2249,28 +2294,55 @@ bool ChatHandler::HandleGoTaxinodeCommand(const char* args)
return false;
}
if ((node->x == 0.0f && node->y == 0.0f && node->z == 0.0f) ||
!MapManager::IsValidMapCoord(node->map_id,node->x,node->y,node->z))
if (node->x == 0.0f && node->y == 0.0f && node->z == 0.0f)
{
PSendSysMessage(LANG_INVALID_TARGET_COORD,node->x,node->y,node->map_id);
SetSentErrorMessage(true);
return false;
}
// stop flight if need
if (_player->isInFlight())
{
_player->GetMotionMaster()->MovementExpired();
_player->m_taxi.ClearTaxiDestinations();
}
// save only in non-flight case
else
_player->SaveRecallPosition();
_player->TeleportTo(node->map_id, node->x, node->y, node->z, _player->GetOrientation());
return true;
return HandleGoHelper(_player, node->map_id, node->x, node->y, &node->z);
}
bool ChatHandler::HandleGoCommand(const char* args)
{
if(!*args)
return false;
Player* _player = m_session->GetPlayer();
uint32 mapid;
float x, y, z;
// raw coordinates case
if (isNumeric(args[0]))
{
char* px = strtok((char*)args, " ");
char* py = strtok(NULL, " ");
char* pz = strtok(NULL, " ");
char* pmapid = strtok(NULL, " ");
if (!px || !py || !pz)
return false;
x = (float)atof(px);
y = (float)atof(py);
z = (float)atof(pz);
if (pmapid)
mapid = (uint32)atoi(pmapid);
else
mapid = _player->GetMapId();
}
// link case
else if (!extractLocationFromLink((char*)args, mapid, x, y, z))
return false;
return HandleGoHelper(_player, mapid, x, y, &z);
}
//teleport at coordinates
bool ChatHandler::HandleGoXYCommand(const char* args)
{
@ -2293,29 +2365,7 @@ bool ChatHandler::HandleGoXYCommand(const char* args)
mapid = (uint32)atoi(pmapid);
else mapid = _player->GetMapId();
if(!MapManager::IsValidMapCoord(mapid,x,y))
{
PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid);
SetSentErrorMessage(true);
return false;
}
// stop flight if need
if(_player->isInFlight())
{
_player->GetMotionMaster()->MovementExpired();
_player->m_taxi.ClearTaxiDestinations();
}
// save only in non-flight case
else
_player->SaveRecallPosition();
Map const *map = sMapMgr.CreateBaseMap(mapid);
float z = std::max(map->GetHeight(x, y, MAX_HEIGHT), map->GetWaterLevel(x, y));
_player->TeleportTo(mapid, x, y, z, _player->GetOrientation());
return true;
return HandleGoHelper(_player, mapid, x, y);
}
//teleport at coordinates, including Z
@ -2343,26 +2393,7 @@ bool ChatHandler::HandleGoXYZCommand(const char* args)
else
mapid = _player->GetMapId();
if(!MapManager::IsValidMapCoord(mapid,x,y,z))
{
PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid);
SetSentErrorMessage(true);
return false;
}
// stop flight if need
if(_player->isInFlight())
{
_player->GetMotionMaster()->MovementExpired();
_player->m_taxi.ClearTaxiDestinations();
}
// save only in non-flight case
else
_player->SaveRecallPosition();
_player->TeleportTo(mapid, x, y, z, _player->GetOrientation());
return true;
return HandleGoHelper(_player, mapid, x, y, &z);
}
//teleport at coordinates
@ -2403,49 +2434,33 @@ bool ChatHandler::HandleGoZoneXYCommand(const char* args)
// update to parent zone if exist (client map show only zones without parents)
AreaTableEntry const* zoneEntry = areaEntry->zone ? GetAreaEntryByAreaID(areaEntry->zone) : areaEntry;
Map const *map = sMapMgr.CreateBaseMap(zoneEntry->mapid);
MapEntry const *mapEntry = sMapStore.LookupEntry(zoneEntry->mapid);
if(map->Instanceable())
if (mapEntry->Instanceable())
{
PSendSysMessage(LANG_INVALID_ZONE_MAP,areaEntry->ID,areaEntry->area_name[GetSessionDbcLocale()],map->GetId(),map->GetMapName());
PSendSysMessage(LANG_INVALID_ZONE_MAP, areaEntry->ID, areaEntry->area_name[GetSessionDbcLocale()],
mapEntry->MapID, mapEntry->name[GetSessionDbcLocale()]);
SetSentErrorMessage(true);
return false;
}
if (!Zone2MapCoordinates(x,y,zoneEntry->ID))
{
PSendSysMessage(LANG_INVALID_ZONE_MAP,areaEntry->ID,areaEntry->area_name[GetSessionDbcLocale()],map->GetId(),map->GetMapName());
PSendSysMessage(LANG_INVALID_ZONE_MAP, areaEntry->ID, areaEntry->area_name[GetSessionDbcLocale()],
mapEntry->MapID, mapEntry->name[GetSessionDbcLocale()]);
SetSentErrorMessage(true);
return false;
}
if(!MapManager::IsValidMapCoord(zoneEntry->mapid,x,y))
{
PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,zoneEntry->mapid);
SetSentErrorMessage(true);
return false;
}
// stop flight if need
if(_player->isInFlight())
{
_player->GetMotionMaster()->MovementExpired();
_player->m_taxi.ClearTaxiDestinations();
}
// save only in non-flight case
else
_player->SaveRecallPosition();
float z = std::max(map->GetHeight(x, y, MAX_HEIGHT), map->GetWaterLevel(x, y));
_player->TeleportTo(zoneEntry->mapid, x, y, z, _player->GetOrientation());
return true;
return HandleGoHelper(_player, mapEntry->MapID, x, y);
}
//teleport to grid
bool ChatHandler::HandleGoGridCommand(const char* args)
{
if(!*args) return false;
if (!*args)
return false;
Player* _player = m_session->GetPlayer();
char* px = strtok((char*)args, " ");
@ -2457,37 +2472,13 @@ bool ChatHandler::HandleGoGridCommand(const char* args)
float grid_x = (float)atof(px);
float grid_y = (float)atof(py);
uint32 mapid;
if (pmapid)
mapid = (uint32)atoi(pmapid);
else mapid = _player->GetMapId();
uint32 mapid = pmapid ? (uint32)atoi(pmapid) : _player->GetMapId();
// center of grid
float x = (grid_x-CENTER_GRID_ID+0.5f)*SIZE_OF_GRIDS;
float y = (grid_y-CENTER_GRID_ID+0.5f)*SIZE_OF_GRIDS;
if(!MapManager::IsValidMapCoord(mapid,x,y))
{
PSendSysMessage(LANG_INVALID_TARGET_COORD,x,y,mapid);
SetSentErrorMessage(true);
return false;
}
// stop flight if need
if(_player->isInFlight())
{
_player->GetMotionMaster()->MovementExpired();
_player->m_taxi.ClearTaxiDestinations();
}
// save only in non-flight case
else
_player->SaveRecallPosition();
Map const *map = sMapMgr.CreateBaseMap(mapid);
float z = std::max(map->GetHeight(x, y, MAX_HEIGHT), map->GetWaterLevel(x, y));
_player->TeleportTo(mapid, x, y, z, _player->GetOrientation());
return true;
return HandleGoHelper(_player, mapid, x, y);
}
bool ChatHandler::HandleModifyDrunkCommand(const char* args)

View file

@ -43,7 +43,7 @@
#include "SkillDiscovery.h"
#include "SkillExtraItems.h"
#include "SystemConfig.h"
#include "Config/ConfigEnv.h"
#include "Config/Config.h"
#include "Mail.h"
#include "Util.h"
#include "ItemEnchantmentMgr.h"
@ -2832,7 +2832,7 @@ void ChatHandler::ShowSpellListHelper(Player* target, SpellEntry const* spellInf
uint32 talentCost = GetTalentSpellCost(id);
bool talent = (talentCost > 0);
bool passive = IsPassiveSpell(id);
bool passive = IsPassiveSpell(spellInfo);
bool active = target && target->HasAura(id);
// unit32 used to prevent interpreting uint8 as char at output

View file

@ -76,6 +76,8 @@ libmangosgame_a_SOURCES = \
Calendar.cpp \
Calendar.h \
CalendarHandler.cpp \
Camera.cpp \
Camera.h \
Cell.h \
CellImpl.h \
Channel.cpp \

View file

@ -26,7 +26,6 @@
#include "InstanceData.h"
#include "Map.h"
#include "GridNotifiersImpl.h"
#include "Config/ConfigEnv.h"
#include "Transports.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
@ -367,8 +366,9 @@ bool Map::Add(Player *player)
SendInitSelf(player);
SendInitTransports(player);
NGridType* grid = getNGrid(cell.GridX(), cell.GridY());
player->GetViewPoint().Event_AddedToWorld(&(*grid)(cell.CellX(), cell.CellY()));
UpdateObjectVisibility(player,cell,p);
UpdateObjectsVisibilityFor(player,cell,p);
AddNotifier(player,cell,p);
return true;
@ -406,6 +406,7 @@ Map::Add(T *obj)
DEBUG_LOG("Object %u enters grid[%u,%u]", GUID_LOPART(obj->GetGUID()), cell.GridX(), cell.GridY());
obj->GetViewPoint().Event_AddedToWorld(&(*grid)(cell.CellX(), cell.CellY()));
UpdateObjectVisibility(obj,cell,p);
AddNotifier(obj,cell,p);
@ -682,7 +683,6 @@ void Map::Remove(Player *player, bool remove)
SendRemoveTransports(player);
UpdateObjectVisibility(player,cell,p);
UpdateObjectsVisibilityFor(player,cell,p);
player->ResetMap();
if( remove )
@ -716,10 +716,9 @@ Map::Remove(T *obj, bool remove)
else
obj->RemoveFromWorld();
UpdateObjectVisibility(obj,cell,p); // i think will be better to call this function while object still in grid, this changes nothing but logically is better(as for me)
RemoveFromGrid(obj,grid,cell);
UpdateObjectVisibility(obj,cell,p);
obj->ResetMap();
if( remove )
{
@ -759,10 +758,13 @@ Map::PlayerRelocation(Player *player, float x, float y, float z, float orientati
AddToGrid(player, oldGrid,new_cell);
else
EnsureGridLoadedAtEnter(new_cell, player);
NGridType* newGrid = getNGrid(new_cell.GridX(), new_cell.GridY());
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
UpdateObjectsVisibilityFor(player,new_cell,new_val);
UpdateObjectVisibility(player, new_cell, new_val);
PlayerRelocationNotify(player,new_cell,new_val);
@ -816,6 +818,7 @@ Map::CreatureRelocation(Creature *creature, float x, float y, float z, float ang
creature->SetNeedNotify();
}
creature->GetViewPoint().Call_UpdateVisibilityForOwner();
ASSERT(CheckGridIntegrity(creature,true));
}
@ -829,12 +832,12 @@ bool Map::CreatureCellRelocation(Creature *c, Cell new_cell)
{
DEBUG_FILTER_LOG(LOG_FILTER_CREATURE_MOVES, "Creature (GUID: %u Entry: %u) moved in grid[%u,%u] from cell[%u,%u] to cell[%u,%u].", c->GetGUIDLow(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.CellX(), new_cell.CellY());
if( !old_cell.DiffGrid(new_cell) )
{
RemoveFromGrid(c,getNGrid(old_cell.GridX(), old_cell.GridY()),old_cell);
AddToGrid(c,getNGrid(new_cell.GridX(), new_cell.GridY()),new_cell);
c->SetCurrentCell(new_cell);
}
RemoveFromGrid(c,getNGrid(old_cell.GridX(), old_cell.GridY()),old_cell);
NGridType* new_grid = getNGrid(new_cell.GridX(), new_cell.GridY());
AddToGrid(c,new_grid,new_cell);
c->GetViewPoint().Event_GridChanged( &(*new_grid)(new_cell.CellX(),new_cell.CellY()) );
}
else
{
@ -852,7 +855,10 @@ bool Map::CreatureCellRelocation(Creature *c, Cell new_cell)
DEBUG_FILTER_LOG(LOG_FILTER_CREATURE_MOVES, "Active creature (GUID: %u Entry: %u) moved from grid[%u,%u]cell[%u,%u] to grid[%u,%u]cell[%u,%u].", c->GetGUIDLow(), c->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());
RemoveFromGrid(c,getNGrid(old_cell.GridX(), old_cell.GridY()),old_cell);
AddToGrid(c,getNGrid(new_cell.GridX(), new_cell.GridY()),new_cell);
NGridType* new_grid = getNGrid(new_cell.GridX(), new_cell.GridY());
AddToGrid(c,new_grid,new_cell);
c->GetViewPoint().Event_GridChanged( &(*new_grid)(new_cell.CellX(),new_cell.CellY()) );
return true;
}
@ -865,7 +871,9 @@ bool Map::CreatureCellRelocation(Creature *c, Cell new_cell)
RemoveFromGrid(c,getNGrid(old_cell.GridX(), old_cell.GridY()),old_cell);
{
EnsureGridCreated(GridPair(new_cell.GridX(), new_cell.GridY()));
AddToGrid(c,getNGrid(new_cell.GridX(), new_cell.GridY()),new_cell);
NGridType* new_grid = getNGrid(new_cell.GridX(), new_cell.GridY());
AddToGrid(c,new_grid,new_cell);
c->GetViewPoint().Event_GridChanged( &(*new_grid)(new_cell.CellX(),new_cell.CellY()) );
}
return true;
@ -1420,21 +1428,6 @@ void Map::UpdateObjectVisibility( WorldObject* obj, Cell cell, CellPair cellpair
cell.Visit(cellpair, player_notifier, *this, *obj, GetVisibilityDistance());
}
void Map::UpdateObjectsVisibilityFor( Player* player, Cell cell, CellPair cellpair )
{
MaNGOS::VisibleNotifier notifier(*player);
cell.data.Part.reserved = ALL_DISTRICT;
//cell.SetNoCreate(); need trigger cell loading around the player
TypeContainerVisitor<MaNGOS::VisibleNotifier, WorldTypeMapContainer > world_notifier(notifier);
TypeContainerVisitor<MaNGOS::VisibleNotifier, GridTypeMapContainer > grid_notifier(notifier);
cell.Visit(cellpair, world_notifier, *this, *player, GetVisibilityDistance());
cell.Visit(cellpair, grid_notifier, *this, *player, GetVisibilityDistance());
// send data
notifier.Notify();
}
void Map::PlayerRelocationNotify( Player* player, Cell cell, CellPair cellpair )
{
MaNGOS::PlayerRelocationNotifier relocationNotifier(*player);
@ -1646,44 +1639,63 @@ bool Map::ActiveObjectsNearGrid(uint32 x, uint32 y) const
return false;
}
void Map::AddToActive( Creature* c )
void Map::AddToActive( WorldObject* obj )
{
AddToActiveHelper(c);
m_activeNonPlayers.insert(obj);
// also not allow unloading spawn grid to prevent creating creature clone at load
if(!c->isPet() && c->GetDBTableGUIDLow())
if (obj->GetTypeId()==TYPEID_UNIT)
{
float x,y,z;
c->GetRespawnCoord(x,y,z);
GridPair p = MaNGOS::ComputeGridPair(x, y);
if(getNGrid(p.x_coord, p.y_coord))
getNGrid(p.x_coord, p.y_coord)->incUnloadActiveLock();
else
Creature* c= (Creature*)obj;
if (!c->isPet() && c->GetDBTableGUIDLow())
{
GridPair p2 = MaNGOS::ComputeGridPair(c->GetPositionX(), c->GetPositionY());
sLog.outError("Active creature (GUID: %u Entry: %u) added to grid[%u,%u] but spawn grid[%u,%u] not loaded.",
c->GetGUIDLow(), c->GetEntry(), p.x_coord, p.y_coord, p2.x_coord, p2.y_coord);
float x,y,z;
c->GetRespawnCoord(x,y,z);
GridPair p = MaNGOS::ComputeGridPair(x, y);
if(getNGrid(p.x_coord, p.y_coord))
getNGrid(p.x_coord, p.y_coord)->incUnloadActiveLock();
else
{
GridPair p2 = MaNGOS::ComputeGridPair(c->GetPositionX(), c->GetPositionY());
sLog.outError("Active creature (GUID: %u Entry: %u) added to grid[%u,%u] but spawn grid[%u,%u] not loaded.",
c->GetGUIDLow(), c->GetEntry(), p.x_coord, p.y_coord, p2.x_coord, p2.y_coord);
}
}
}
}
void Map::RemoveFromActive( Creature* c )
void Map::RemoveFromActive( WorldObject* obj )
{
RemoveFromActiveHelper(c);
// Map::Update for active object in proccess
if(m_activeNonPlayersIter != m_activeNonPlayers.end())
{
ActiveNonPlayers::iterator itr = m_activeNonPlayers.find(obj);
if(itr==m_activeNonPlayersIter)
++m_activeNonPlayersIter;
m_activeNonPlayers.erase(itr);
}
else
m_activeNonPlayers.erase(obj);
// also allow unloading spawn grid
if(!c->isPet() && c->GetDBTableGUIDLow())
if (obj->GetTypeId()==TYPEID_UNIT)
{
float x,y,z;
c->GetRespawnCoord(x,y,z);
GridPair p = MaNGOS::ComputeGridPair(x, y);
if(getNGrid(p.x_coord, p.y_coord))
getNGrid(p.x_coord, p.y_coord)->decUnloadActiveLock();
else
Creature* c= (Creature*)obj;
if(!c->isPet() && c->GetDBTableGUIDLow())
{
GridPair p2 = MaNGOS::ComputeGridPair(c->GetPositionX(), c->GetPositionY());
sLog.outError("Active creature (GUID: %u Entry: %u) removed from grid[%u,%u] but spawn grid[%u,%u] not loaded.",
c->GetGUIDLow(), c->GetEntry(), p.x_coord, p.y_coord, p2.x_coord, p2.y_coord);
float x,y,z;
c->GetRespawnCoord(x,y,z);
GridPair p = MaNGOS::ComputeGridPair(x, y);
if(getNGrid(p.x_coord, p.y_coord))
getNGrid(p.x_coord, p.y_coord)->decUnloadActiveLock();
else
{
GridPair p2 = MaNGOS::ComputeGridPair(c->GetPositionX(), c->GetPositionY());
sLog.outError("Active creature (GUID: %u Entry: %u) removed from grid[%u,%u] but spawn grid[%u,%u] not loaded.",
c->GetGUIDLow(), c->GetEntry(), p.x_coord, p.y_coord, p2.x_coord, p2.y_coord);
}
}
}
}

View file

@ -84,6 +84,8 @@ enum LevelRequirementVsMode
class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::ObjectLevelLockable<Map, ACE_Thread_Mutex>
{
friend class MapReference;
friend class ObjectGridLoader;
friend class ObjectWorldLoader;
public:
Map(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode, Map* _parent = NULL);
virtual ~Map();
@ -211,7 +213,6 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
void AddObjectToRemoveList(WorldObject *obj);
void UpdateObjectVisibility(WorldObject* obj, Cell cell, CellPair cellpair);
void UpdateObjectsVisibilityFor(Player* player, Cell cell, CellPair cellpair);
void resetMarkedCells() { marked_cells.reset(); }
bool isCellMarked(uint32 pCellId) { return marked_cells.test(pCellId); }
@ -231,16 +232,9 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
void ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* source, Object* target);
// must called with AddToWorld
template<class T>
void AddToActive(T* obj) { AddToActiveHelper(obj); }
void AddToActive(Creature* obj);
void AddToActive(WorldObject* obj);
// must called with RemoveFromWorld
template<class T>
void RemoveFromActive(T* obj) { RemoveFromActiveHelper(obj); }
void RemoveFromActive(Creature* obj);
void RemoveFromActive(WorldObject* obj);
Creature* GetCreature(ObjectGuid guid);
Vehicle* GetVehicle(ObjectGuid guid);
@ -357,27 +351,6 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
template<class T>
void DeleteFromWorld(T*);
template<class T>
void AddToActiveHelper(T* obj)
{
m_activeNonPlayers.insert(obj);
}
template<class T>
void RemoveFromActiveHelper(T* obj)
{
// Map::Update for active object in proccess
if(m_activeNonPlayersIter != m_activeNonPlayers.end())
{
ActiveNonPlayers::iterator itr = m_activeNonPlayers.find(obj);
if(itr==m_activeNonPlayersIter)
++m_activeNonPlayersIter;
m_activeNonPlayers.erase(itr);
}
else
m_activeNonPlayers.erase(obj);
}
};
enum InstanceResetMethod

View file

@ -1293,10 +1293,10 @@ void WorldSession::HandleFarSightOpcode( WorldPacket & recv_data )
//WorldPacket data(SMSG_CLEAR_FAR_SIGHT_IMMEDIATE, 0)
//SendPacket(&data);
//_player->SetUInt64Value(PLAYER_FARSIGHT, 0);
DEBUG_LOG("Removed FarSight from player %u", _player->GetGUIDLow());
DEBUG_LOG("Removed FarSight from %s", _player->GetObjectGuid().GetString().c_str());
break;
case 1:
DEBUG_LOG("Added FarSight (GUID:%u TypeId:%u) to player %u", GUID_LOPART(_player->GetFarSight()), GuidHigh2TypeId(GUID_HIPART(_player->GetFarSight())), _player->GetGUIDLow());
DEBUG_LOG("Added FarSight %s to %s", _player->GetFarSightGuid().GetString().c_str(), _player->GetObjectGuid().GetString().c_str());
break;
}
}

View file

@ -40,11 +40,15 @@ inline bool isStatic(MovementGenerator *mv)
void
MotionMaster::Initialize()
{
// stop current move
if (!i_owner->IsStopped())
i_owner->StopMoving();
// clear ALL movement generators (including default)
Clear(false,true);
// set new default movement generator
if (i_owner->GetTypeId() == TYPEID_UNIT)
if (i_owner->GetTypeId() == TYPEID_UNIT && !i_owner->hasUnitState(UNIT_STAT_CONTROLLED))
{
MovementGenerator* movement = FactorySelector::selectMovementGenerator((Creature*)i_owner);
push(movement == NULL ? &si_idleMovement : movement);
@ -226,7 +230,7 @@ void MotionMaster::MoveRandom()
void
MotionMaster::MoveTargetedHome()
{
if(i_owner->hasUnitState(UNIT_STAT_FLEEING))
if(i_owner->hasUnitState(UNIT_STAT_LOST_CONTROL))
return;
Clear(false);
@ -281,6 +285,9 @@ MotionMaster::MoveChase(Unit* target, float dist, float angle)
void
MotionMaster::MoveFollow(Unit* target, float dist, float angle)
{
if(i_owner->hasUnitState(UNIT_STAT_LOST_CONTROL))
return;
Clear();
// ignore movement request if target not exist

View file

@ -181,7 +181,7 @@ void WorldSession::HandleMoveTeleportAck(WorldPacket& recv_data)
DEBUG_LOG("Guid: %s", guid.GetString().c_str());
DEBUG_LOG("Flags %u, time %u", flags, time/IN_MILLISECONDS);
Unit *mover = _player->m_mover;
Unit *mover = _player->GetMover();
Player *plMover = mover->GetTypeId() == TYPEID_PLAYER ? (Player*)mover : NULL;
if(!plMover || !plMover->IsBeingTeleportedNear())
@ -223,7 +223,7 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
DEBUG_LOG("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode);
recv_data.hexlike();
Unit *mover = _player->m_mover;
Unit *mover = _player->GetMover();
Player *plMover = mover->GetTypeId() == TYPEID_PLAYER ? (Player*)mover : NULL;
// ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck
@ -335,7 +335,7 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
// TODO: discard movement packets after the player is rooted
if(plMover->isAlive())
{
plMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth());
plMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, plMover->GetMaxHealth());
// pl can be alive if GM/etc
if(!plMover->isAlive())
{
@ -434,12 +434,13 @@ void WorldSession::HandleSetActiveMoverOpcode(WorldPacket &recv_data)
DEBUG_LOG("WORLD: Recvd CMSG_SET_ACTIVE_MOVER");
recv_data.hexlike();
uint64 guid;
ObjectGuid guid;
recv_data >> guid;
if(_player->m_mover->GetGUID() != guid)
if(_player->GetMover()->GetObjectGuid() != guid)
{
sLog.outError("HandleSetActiveMoverOpcode: incorrect mover guid: mover is " I64FMT " and should be " I64FMT, _player->m_mover->GetGUID(), guid);
sLog.outError("HandleSetActiveMoverOpcode: incorrect mover guid: mover is %s and should be %s",
_player->GetMover()->GetObjectGuid().GetString().c_str(), guid.GetString().c_str());
return;
}
}
@ -455,9 +456,12 @@ void WorldSession::HandleMoveNotActiveMover(WorldPacket &recv_data)
recv_data >> old_mover_guid.ReadAsPacked();
recv_data >> mi;
if(_player->m_mover->GetObjectGuid() == old_mover_guid)
if(_player->GetMover()->GetObjectGuid() == old_mover_guid)
{
sLog.outError("HandleMoveNotActiveMover: incorrect mover guid: mover is " I64FMT " and should be " I64FMT " instead of " UI64FMTD, _player->m_mover->GetGUID(), _player->GetGUID(), old_mover_guid.GetRawValue());
sLog.outError("HandleMoveNotActiveMover: incorrect mover guid: mover is %s and should be %s instead of %s",
_player->GetMover()->GetObjectGuid().GetString().c_str(),
_player->GetObjectGuid().GetString().c_str(),
old_mover_guid.GetString().c_str());
recv_data.rpos(recv_data.wpos()); // prevent warnings spam
return;
}

View file

@ -397,11 +397,17 @@ void WorldSession::SendSpiritResurrect()
_player->TeleportTo(corpseGrave->map_id, corpseGrave->x, corpseGrave->y, corpseGrave->z, _player->GetOrientation());
// or update at original position
else
_player->UpdateVisibilityForPlayer();
{
_player->GetCamera().UpdateVisibilityForOwner();
_player->UpdateObjectVisibility();
}
}
// or update at original position
else
_player->UpdateVisibilityForPlayer();
{
_player->GetCamera().UpdateVisibilityForOwner();
_player->UpdateObjectVisibility();
}
}
void WorldSession::HandleBinderActivateOpcode( WorldPacket & recv_data )

View file

@ -1084,7 +1084,7 @@ void Object::BuildUpdateData( UpdateDataMapType& /*update_players */)
}
WorldObject::WorldObject()
: m_currMap(NULL), m_mapId(0), m_InstanceId(0), m_phaseMask(PHASEMASK_NORMAL),
: m_isActiveObject(false), m_currMap(NULL), m_mapId(0), m_InstanceId(0), m_phaseMask(PHASEMASK_NORMAL),
m_positionX(0.0f), m_positionY(0.0f), m_positionZ(0.0f), m_orientation(0.0f)
{
}
@ -1496,7 +1496,7 @@ void WorldObject::MonsterSay(int32 textId, uint32 language, uint64 TargetGuid)
{
MaNGOS::MonsterChatBuilder say_build(*this, CHAT_MSG_MONSTER_SAY, textId,language,TargetGuid);
MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> say_do(say_build);
MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> > say_worker(this,sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_SAY),say_do);
MaNGOS::CameraDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> > say_worker(this,sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_SAY),say_do);
Cell::VisitWorldObjects(this, say_worker, sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_SAY));
}
@ -1507,7 +1507,7 @@ void WorldObject::MonsterYell(int32 textId, uint32 language, uint64 TargetGuid)
MaNGOS::MonsterChatBuilder say_build(*this, CHAT_MSG_MONSTER_YELL, textId,language,TargetGuid);
MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> say_do(say_build);
MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> > say_worker(this,range,say_do);
MaNGOS::CameraDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> > say_worker(this,range,say_do);
Cell::VisitWorldObjects(this, say_worker, sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_YELL));
}
@ -1530,7 +1530,7 @@ void WorldObject::MonsterTextEmote(int32 textId, uint64 TargetGuid, bool IsBossE
MaNGOS::MonsterChatBuilder say_build(*this, IsBossEmote ? CHAT_MSG_RAID_BOSS_EMOTE : CHAT_MSG_MONSTER_EMOTE, textId,LANG_UNIVERSAL,TargetGuid);
MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> say_do(say_build);
MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> > say_worker(this,range,say_do);
MaNGOS::CameraDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> > say_worker(this,range,say_do);
Cell::VisitWorldObjects(this, say_worker, range);
}
@ -1864,7 +1864,10 @@ void WorldObject::SetPhaseMask(uint32 newPhaseMask, bool update)
m_phaseMask = newPhaseMask;
if(update && IsInWorld())
{
UpdateObjectVisibility();
GetViewPoint().Event_ViewPointVisibilityChanged();
}
}
void WorldObject::PlayDistanceSound( uint32 sound_id, Player* target /*= NULL*/ )
@ -1910,12 +1913,22 @@ struct WorldObjectChangeAccumulator
{
UpdateDataMapType &i_updateDatas;
WorldObject &i_object;
WorldObjectChangeAccumulator(WorldObject &obj, UpdateDataMapType &d) : i_updateDatas(d), i_object(obj) {}
void Visit(PlayerMapType &m)
WorldObjectChangeAccumulator(WorldObject &obj, UpdateDataMapType &d) : i_updateDatas(d), i_object(obj)
{
for(PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
if(iter->getSource()->HaveAtClient(&i_object))
i_object.BuildUpdateDataForPlayer(iter->getSource(), i_updateDatas);
// send self fields changes in another way, otherwise
// with new camera system when player's camera too far from player, camera wouldn't receive packets and changes from player
if(i_object.isType(TYPEMASK_PLAYER))
i_object.BuildUpdateDataForPlayer((Player*)&i_object, i_updateDatas);
}
void Visit(CameraMapType &m)
{
for(CameraMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
{
Player* owner = iter->getSource()->GetOwner();
if(owner != &i_object && owner->HaveAtClient(&i_object))
i_object.BuildUpdateDataForPlayer(owner, i_updateDatas);
}
}
template<class SKIP> void Visit(GridRefManager<SKIP> &) {}

View file

@ -23,8 +23,8 @@
#include "ByteBuffer.h"
#include "UpdateFields.h"
#include "UpdateData.h"
#include "GameSystem/GridReference.h"
#include "ObjectGuid.h"
#include "Camera.h"
#include <set>
#include <string>
@ -108,11 +108,11 @@ class MANGOS_DLL_SPEC Object
m_inWorld = false;
}
ObjectGuid const& GetObjectGuid() const { return *reinterpret_cast<ObjectGuid const*>(&GetUInt64Value(0)); }
const uint64& GetGUID() const { return GetUInt64Value(0); }
uint32 GetGUIDLow() const { return GUID_LOPART(GetUInt64Value(0)); }
ObjectGuid const& GetObjectGuid() const { return GetGuidValue(OBJECT_FIELD_GUID); }
const uint64& GetGUID() const { return GetUInt64Value(OBJECT_FIELD_GUID); }
uint32 GetGUIDLow() const { return GUID_LOPART(GetUInt64Value(OBJECT_FIELD_GUID)); }
PackedGuid const& GetPackGUID() const { return m_PackGUID; }
uint32 GetEntry() const { return GetUInt32Value(OBJECT_FIELD_ENTRY); }
void SetEntry(uint32 entry) { SetUInt32Value(OBJECT_FIELD_ENTRY, entry); }
@ -171,6 +171,8 @@ class MANGOS_DLL_SPEC Object
return *(((uint16*)&m_uint32Values[ index ])+offset);
}
ObjectGuid const& GetGuidValue( uint16 index ) const { return *reinterpret_cast<ObjectGuid const*>(&GetUInt64Value(index)); }
void SetInt32Value( uint16 index, int32 value );
void SetUInt32Value( uint16 index, uint32 value );
void SetUInt64Value( uint16 index, const uint64 &value );
@ -178,6 +180,7 @@ class MANGOS_DLL_SPEC Object
void SetByteValue( uint16 index, uint8 offset, uint8 value );
void SetUInt16Value( uint16 index, uint8 offset, uint16 value );
void SetInt16Value( uint16 index, uint8 offset, int16 value ) { SetUInt16Value(index,offset,(uint16)value); }
void SetGuidValue( uint16 index, ObjectGuid const& value ) { SetUInt64Value(index, value.GetRawValue()); }
void SetStatFloatValue( uint16 index, float value);
void SetStatInt32Value( uint16 index, int32 value);
@ -476,6 +479,10 @@ class MANGOS_DLL_SPEC WorldObject : public Object
void BuildUpdateData(UpdateDataMapType &);
Creature* SummonCreature(uint32 id, float x, float y, float z, float ang,TempSummonType spwtype,uint32 despwtime);
bool isActiveObject() const { return m_isActiveObject || m_viewPoint.hasViewers(); }
ViewPoint& GetViewPoint() { return m_viewPoint; }
protected:
explicit WorldObject();
@ -487,6 +494,7 @@ class MANGOS_DLL_SPEC WorldObject : public Object
std::string m_name;
bool m_isActiveObject;
private:
Map * m_currMap; //current object's Map location
@ -498,6 +506,8 @@ class MANGOS_DLL_SPEC WorldObject : public Object
float m_positionY;
float m_positionZ;
float m_orientation;
ViewPoint m_viewPoint;
};
#endif

View file

@ -25,6 +25,7 @@
#include "Corpse.h"
#include "World.h"
#include "CellImpl.h"
#include "GridDefines.h"
class MANGOS_DLL_DECL ObjectGridRespawnMover
{
@ -105,7 +106,7 @@ template<> void addUnitState(Creature *obj, CellPair const& cell_pair)
}
template <class T>
void LoadHelper(CellGuidSet const& guid_set, CellPair &cell, GridRefManager<T> &m, uint32 &count, Map* map)
void LoadHelper(CellGuidSet const& guid_set, CellPair &cell, GridRefManager<T> &m, uint32 &count, Map* map, GridType& grid)
{
BattleGround* bg = map->IsBattleGroundOrArena() ? ((BattleGroundMap*)map)->GetBG() : NULL;
@ -121,13 +122,16 @@ void LoadHelper(CellGuidSet const& guid_set, CellPair &cell, GridRefManager<T> &
continue;
}
obj->GetGridRef().link(&m, obj);
grid.AddGridObject(obj);
addUnitState(obj,cell);
obj->SetMap(map);
obj->AddToWorld();
if(obj->isActiveObject())
map->AddToActive(obj);
obj->GetViewPoint().Event_AddedToWorld(&grid);
if (bg)
bg->OnObjectDBLoad(obj);
@ -135,7 +139,7 @@ void LoadHelper(CellGuidSet const& guid_set, CellPair &cell, GridRefManager<T> &
}
}
void LoadHelper(CellCorpseSet const& cell_corpses, CellPair &cell, CorpseMapType &m, uint32 &count, Map* map)
void LoadHelper(CellCorpseSet const& cell_corpses, CellPair &cell, CorpseMapType &m, uint32 &count, Map* map, GridType& grid)
{
if(cell_corpses.empty())
return;
@ -151,7 +155,7 @@ void LoadHelper(CellCorpseSet const& cell_corpses, CellPair &cell, CorpseMapType
if(!obj)
continue;
obj->GetGridRef().link(&m, obj);
grid.AddWorldObject(obj);
addUnitState(obj,cell);
obj->SetMap(map);
@ -173,7 +177,8 @@ ObjectGridLoader::Visit(GameObjectMapType &m)
CellObjectGuids const& cell_guids = sObjectMgr.GetCellObjectGuids(i_map->GetId(), i_map->GetSpawnMode(), cell_id);
LoadHelper(cell_guids.gameobjects, cell_pair, m, i_gameObjects, i_map);
GridType& grid = (*i_map->getNGrid(i_cell.GridX(),i_cell.GridY())) (i_cell.CellX(),i_cell.CellY());
LoadHelper(cell_guids.gameobjects, cell_pair, m, i_gameObjects, i_map, grid);
}
void
@ -186,7 +191,8 @@ ObjectGridLoader::Visit(CreatureMapType &m)
CellObjectGuids const& cell_guids = sObjectMgr.GetCellObjectGuids(i_map->GetId(), i_map->GetSpawnMode(), cell_id);
LoadHelper(cell_guids.creatures, cell_pair, m, i_creatures, i_map);
GridType& grid = (*i_map->getNGrid(i_cell.GridX(),i_cell.GridY())) (i_cell.CellX(),i_cell.CellY());
LoadHelper(cell_guids.creatures, cell_pair, m, i_creatures, i_map, grid);
}
void
@ -199,7 +205,8 @@ ObjectWorldLoader::Visit(CorpseMapType &m)
// corpses are always added to spawn mode 0 and they are spawned by their instance id
CellObjectGuids const& cell_guids = sObjectMgr.GetCellObjectGuids(i_map->GetId(), 0, cell_id);
LoadHelper(cell_guids.corpses, cell_pair, m, i_corpses, i_map);
GridType& grid = (*i_map->getNGrid(i_cell.GridX(),i_cell.GridY())) (i_cell.CellX(),i_cell.CellY());
LoadHelper(cell_guids.corpses, cell_pair, m, i_corpses, i_map, grid);
}
void

View file

@ -929,7 +929,8 @@ void ObjectMgr::LoadEquipmentTemplates()
dbcitem->InventoryType != INVTYPE_WEAPONOFFHAND &&
dbcitem->InventoryType != INVTYPE_HOLDABLE &&
dbcitem->InventoryType != INVTYPE_THROWN &&
dbcitem->InventoryType != INVTYPE_RANGEDRIGHT)
dbcitem->InventoryType != INVTYPE_RANGEDRIGHT &&
dbcitem->InventoryType != INVTYPE_RELIC)
{
sLog.outErrorDb("Item (entry=%u) in creature_equip_template.equipentry%u for entry = %u is not equipable in a hand, forced to 0.", eqInfo->equipentry[j], j+1, i);
const_cast<EquipmentInfo*>(eqInfo)->equipentry[j] = 0;

View file

@ -359,7 +359,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
/*0x14A*/ { "SMSG_ATTACKERSTATEUPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x14B*/ { "SMSG_BATTLEFIELD_PORT_DENIED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x14C*/ { "SMSG_DAMAGE_DONE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x14D*/ { "SMSG_DAMAGE_TAKEN_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x14D*/ { "SMSG_UNIT_SPELLCAST_START", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x14E*/ { "SMSG_CANCEL_COMBAT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x14F*/ { "SMSG_SPELLBREAKLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x150*/ { "SMSG_SPELLHEALLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
@ -568,7 +568,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
/*0x21B*/ { "SMSG_GMTICKET_SYSTEMSTATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x21C*/ { "CMSG_SPIRIT_HEALER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleSpiritHealerActivateOpcode},
/*0x21D*/ { "CMSG_SET_STAT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x21E*/ { "SMSG_SET_REST_START_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x21E*/ { "SMSG_QUEST_FORCE_REMOVE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x21F*/ { "CMSG_SKILL_BUY_STEP", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x220*/ { "CMSG_SKILL_BUY_RANK", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x221*/ { "CMSG_XP_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
@ -1146,8 +1146,8 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
/*0x45D*/ { "CMSG_FORCE_PITCH_RATE_CHANGE_ACK", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x45E*/ { "SMSG_SPLINE_SET_PITCH_RATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x45F*/ { "SMSG_MOVE_ABANDON_TRANSPORT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x460*/ { "MSG_MOVE_ABANDON_TRANSPORT", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x461*/ { "CMSG_MOVE_ABANDON_TRANSPORT_ACK", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x460*/ { "SMSG_CALENDAR_UPDATE_INVITE_LIST", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x461*/ { "SMSG_CALENDAR_UPDATE_INVITE_LIST2", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x462*/ { "CMSG_UPDATE_MISSILE_TRAJECTORY", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x463*/ { "SMSG_UPDATE_ACCOUNT_DATA_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x464*/ { "SMSG_TRIGGER_MOVIE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
@ -1163,7 +1163,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
/*0x46E*/ { "CMSG_COMPLETE_ACHIEVEMENT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x46F*/ { "SMSG_QUESTUPDATE_ADD_PVP_KILL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x470*/ { "CMSG_SET_CRITERIA_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x471*/ { "SMSG_GROUP_SWAP_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x471*/ { "SMSG_CALENDAR_UPDATE_INVITE_LIST3", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x472*/ { "CMSG_UNITANIMTIER_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x473*/ { "CMSG_CHAR_CUSTOMIZE", STATUS_AUTHED, &WorldSession::HandleCharCustomize },
/*0x474*/ { "SMSG_CHAR_CUSTOMIZE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
@ -1256,13 +1256,13 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
/*0x4CB*/ { "UMSG_UNKNOWN_1227", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x4CC*/ { "UMSG_UNKNOWN_1228", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x4CD*/ { "SMSG_MULTIPLE_PACKETS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x4CE*/ { "SMSG_UNKNOWN_1230", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x4CF*/ { "CMSG_UNKNOWN_1231_ACK", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x4D0*/ { "SMSG_UNKNOWN_1232", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x4D1*/ { "CMSG_UNKNOWN_1233_ACK", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x4D2*/ { "SMSG_UNKNOWN_1234", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x4D3*/ { "SMSG_UNKNOWN_1235", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x4D4*/ { "SMSG_UNKNOWN_1236", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x4CE*/ { "SMSG_FORCE_UNK1_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x4CF*/ { "CMSG_FORCE_UNK1_SPEED_CHANGE_ACK", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x4D0*/ { "SMSG_FORCE_UNK2_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x4D1*/ { "CMSG_FORCE_UNK2_SPEED_CHANGE_ACK", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x4D2*/ { "MSG_MOVE_UNKNOWN_1234", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x4D3*/ { "SMSG_SPLINE_MOVE_UNKNOWN_1235", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x4D4*/ { "SMSG_SPLINE_MOVE_UNKNOWN_1236", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x4D5*/ { "CMSG_EQUIPMENT_SET_USE", STATUS_LOGGEDIN, &WorldSession::HandleEquipmentSetUse },
/*0x4D6*/ { "SMSG_EQUIPMENT_SET_USE_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x4D7*/ { "UMSG_UNKNOWN_1239", STATUS_NEVER, &WorldSession::Handle_NULL },
@ -1273,7 +1273,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
/*0x4DC*/ { "UMSG_UNKNOWN_1244", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x4DD*/ { "UMSG_UNKNOWN_1245", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x4DE*/ { "SMSG_BATTLEFIELD_MGR_ENTRY_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x4DF*/ { "CMSG_BATTLEFIELD_MGR_ENTRY_INVITE_RESPONS", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x4DF*/ { "CMSG_BATTLEFIELD_MGR_ENTRY_INVITE_RESPONSE", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x4E0*/ { "SMSG_BATTLEFIELD_MGR_ENTERED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x4E1*/ { "SMSG_BATTLEFIELD_MGR_QUEUE_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x4E2*/ { "CMSG_BATTLEFIELD_MGR_QUEUE_INVITE_RESPONSE", STATUS_NEVER, &WorldSession::Handle_NULL },

View file

@ -1242,7 +1242,7 @@ enum Opcodes
SMSG_ITEM_REFUND_RESULT = 0x4B5, // refund item result
CMSG_CORPSE_MAP_POSITION_QUERY = 0x4B6, // CMSG, uint32
SMSG_CORPSE_MAP_POSITION_QUERY_RESPONSE = 0x4B7, // SMSG, 3*float+float
UMSG_UNKNOWN_1208 = 0x4B8, // not found
CMSG_LFG_SET_ROLES_2 = 0x4B8, // not found
UMSG_UNKNOWN_1209 = 0x4B9, // not found
CMSG_CALENDAR_CONTEXT_EVENT_SIGNUP = 0x4BA, // CMSG, uint64, lua: CalendarContextEventSignUp
SMSG_CALENDAR_ACTION_PENDING = 0x4BB, // SMSG, calendar related EVENT_CALENDAR_ACTION_PENDING

View file

@ -1313,7 +1313,7 @@ bool Pet::addSpell(uint32 spell_id,ActiveStates active /*= ACT_DECIDE*/, PetSpel
if(active == ACT_DECIDE) //active was not used before, so we save it's autocast/passive state here
{
if(IsPassiveSpell(spell_id))
if(IsPassiveSpell(spellInfo))
newspell.active = ACT_PASSIVE;
else
newspell.active = ACT_DISABLED;
@ -1369,7 +1369,7 @@ bool Pet::addSpell(uint32 spell_id,ActiveStates active /*= ACT_DECIDE*/, PetSpel
m_spells[spell_id] = newspell;
if (IsPassiveSpell(spell_id))
if (IsPassiveSpell(spellInfo))
CastSpell(this, spell_id, true);
else
m_charmInfo->AddSpellToActionBar(spell_id, ActiveStates(newspell.active));

View file

@ -86,7 +86,7 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
{
case COMMAND_STAY: //flat=1792 //STAY
pet->StopMoving();
pet->GetMotionMaster()->Clear();
pet->GetMotionMaster()->Clear(false);
pet->GetMotionMaster()->MoveIdle();
charmInfo->SetCommandState( COMMAND_STAY );
break;
@ -191,7 +191,7 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
}
// do not cast not learned spells
if(!pet->HasSpell(spellid) || IsPassiveSpell(spellid))
if(!pet->HasSpell(spellid) || IsPassiveSpell(spellInfo))
return;
pet->clearUnitState(UNIT_STAT_MOVING);
@ -626,7 +626,7 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket )
}
// do not cast not learned spells
if (!pet->HasSpell(spellid) || IsPassiveSpell(spellid))
if (!pet->HasSpell(spellid) || IsPassiveSpell(spellInfo))
return;
SpellCastTargets targets;

View file

@ -405,7 +405,7 @@ void TradeData::SetAccepted(bool state, bool crosssend /*= false*/)
UpdateMask Player::updateVisualBits;
Player::Player (WorldSession *session): Unit(), m_achievementMgr(this), m_reputationMgr(this)
Player::Player (WorldSession *session): Unit(), m_achievementMgr(this), m_reputationMgr(this), m_mover(this), m_camera(this)
{
m_transport = 0;
@ -417,6 +417,8 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this), m_reputa
m_valuesCount = PLAYER_END;
m_isActiveObject = true; // player is always active object
m_session = session;
m_divider = 0;
@ -478,6 +480,7 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this), m_reputa
m_DelayedOperations = 0;
m_bCanDelayTeleport = false;
m_bHasDelayedTeleport = false;
m_bHasBeenAliveAtDelayedTeleport = true; // overwrite always at setup teleport data, so not used infact
m_teleport_options = 0;
m_trade = NULL;
@ -584,8 +587,6 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this), m_reputa
m_summon_y = 0.0f;
m_summon_z = 0.0f;
m_mover = this;
m_miniPet = 0;
m_contestedPvPTimer = 0;
@ -1474,9 +1475,7 @@ void Player::Update( uint32 p_time )
RemovePet(pet, PET_SAVE_NOT_IN_SLOT, true);
}
//we should execute delayed teleports only for alive(!) players
//because we don't want player's ghost teleported from graveyard
if(IsHasDelayedTeleport() && isAlive())
if (IsHasDelayedTeleport())
TeleportTo(m_teleport_dest, m_teleport_options);
}
@ -1775,10 +1774,9 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
//lets reset far teleport flag if it wasn't reset during chained teleports
SetSemaphoreTeleportFar(false);
//setup delayed teleport flag
SetDelayedTeleportFlag(IsCanDelayTeleport());
//if teleport spell is casted in Unit::Update() func
//then we need to delay it until update process will be finished
if(IsHasDelayedTeleport())
if (SetDelayedTeleportFlagIfCan())
{
SetSemaphoreTeleportNear(true);
//lets save teleport destination for player
@ -1794,7 +1792,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
UnsummonPetTemporaryIfAny();
}
if(!(options & TELE_TO_NOT_LEAVE_COMBAT))
if (!(options & TELE_TO_NOT_LEAVE_COMBAT))
CombatStop();
// this will be used instead of the current location in SaveToDB
@ -1831,10 +1829,9 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
//lets reset near teleport flag if it wasn't reset during chained teleports
SetSemaphoreTeleportNear(false);
//setup delayed teleport flag
SetDelayedTeleportFlag(IsCanDelayTeleport());
//if teleport spell is casted in Unit::Update() func
//then we need to delay it until update process will be finished
if(IsHasDelayedTeleport())
if (SetDelayedTeleportFlagIfCan())
{
SetSemaphoreTeleportFar(true);
//lets save teleport destination for player
@ -1850,7 +1847,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
ResetContestedPvP();
// remove player from battleground on far teleport (when changing maps)
if(BattleGround const* bg = GetBattleGround())
if (BattleGround const* bg = GetBattleGround())
{
// Note: at battleground join battleground id set before teleport
// and we already will found "current" battleground
@ -1868,14 +1865,14 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
// stop spellcasting
// not attempt interrupt teleportation spell at caster teleport
if(!(options & TELE_TO_SPELL))
if(IsNonMeleeSpellCasted(true))
if (!(options & TELE_TO_SPELL))
if (IsNonMeleeSpellCasted(true))
InterruptNonMeleeSpells(true);
//remove auras before removing from map...
RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CHANGE_MAP | AURA_INTERRUPT_FLAG_MOVE | AURA_INTERRUPT_FLAG_TURNING);
if(!GetSession()->PlayerLogout())
if (!GetSession()->PlayerLogout())
{
// send transfer packets
WorldPacket data(SMSG_TRANSFER_PENDING, (4+4+4));
@ -1909,7 +1906,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
}
// remove from old map now
if(oldmap)
if (oldmap)
oldmap->Remove(this, false);
// new final coordinates
@ -1918,7 +1915,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
float final_z = z;
float final_o = orientation;
if(m_transport)
if (m_transport)
{
final_x += m_movementInfo.GetTransportPos()->x;
final_y += m_movementInfo.GetTransportPos()->y;
@ -2236,7 +2233,7 @@ Creature* Player::GetNPCIfCanInteractWith(ObjectGuid guid, uint32 npcflagmask)
return NULL;
// not in interactive state
if (hasUnitState(UNIT_STAT_CAN_NOT_REACT))
if (hasUnitState(UNIT_STAT_CAN_NOT_REACT_OR_LOST_CONTROL))
return NULL;
// exist (we need look pets also for some interaction (quest/etc)
@ -2290,7 +2287,7 @@ GameObject* Player::GetGameObjectIfCanInteractWith(ObjectGuid guid, uint32 gameo
return NULL;
// not in interactive state
if (hasUnitState(UNIT_STAT_CAN_NOT_REACT))
if (hasUnitState(UNIT_STAT_CAN_NOT_REACT_OR_LOST_CONTROL))
return NULL;
if (GameObject *go = GetMap()->GetGameObject(guid))
@ -2409,7 +2406,8 @@ void Player::SetGameMaster(bool on)
getHostileRefManager().setOnlineOfflineState(true);
}
UpdateVisibilityForPlayer();
m_camera.UpdateVisibilityForOwner();
UpdateObjectVisibility();
}
void Player::SetGMVisible(bool on)
@ -3062,7 +3060,7 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
if(active)
{
if (IsPassiveSpell(spell_id) && IsNeedCastPassiveSpellAtLearn(spellInfo))
if (IsPassiveSpell(spellInfo) && IsNeedCastPassiveSpellAtLearn(spellInfo))
CastSpell (this, spell_id, true);
}
else if(IsInWorld())
@ -3253,7 +3251,7 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependen
CastSpell(this, spell_id, true);
}
// also cast passive spells (including all talents without SPELL_EFFECT_LEARN_SPELL) with additional checks
else if (IsPassiveSpell(spell_id))
else if (IsPassiveSpell(spellInfo))
{
if (IsNeedCastPassiveSpellAtLearn(spellInfo))
CastSpell(this, spell_id, true);
@ -4490,8 +4488,10 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness)
GetZoneAndAreaId(newzone,newarea);
UpdateZone(newzone,newarea);
// update visibility
UpdateVisibilityForPlayer();
// update visibility of world around viewpoint
m_camera.UpdateVisibilityForOwner();
// update visibility of player for nearby cameras
UpdateObjectVisibility();
if(!applySickness)
return;
@ -6073,42 +6073,30 @@ void Player::SaveRecallPosition()
void Player::SendMessageToSet(WorldPacket *data, bool self)
{
Map * _map = IsInWorld() ? GetMap() : sMapMgr.FindMap(GetMapId(), GetInstanceId());
if(_map)
{
_map->MessageBroadcast(this, data, self);
return;
}
if (Map * _map = IsInWorld() ? GetMap() : sMapMgr.FindMap(GetMapId(), GetInstanceId()))
_map->MessageBroadcast(this, data, false);
//if player is not in world and map in not created/already destroyed
//no need to create one, just send packet for itself!
if(self)
if (self)
GetSession()->SendPacket(data);
}
void Player::SendMessageToSetInRange(WorldPacket *data, float dist, bool self)
{
Map * _map = IsInWorld() ? GetMap() : sMapMgr.FindMap(GetMapId(), GetInstanceId());
if(_map)
{
_map->MessageDistBroadcast(this, data, dist, self);
return;
}
if (Map * _map = IsInWorld() ? GetMap() : sMapMgr.FindMap(GetMapId(), GetInstanceId()))
_map->MessageDistBroadcast(this, data, dist, false);
if(self)
if (self)
GetSession()->SendPacket(data);
}
void Player::SendMessageToSetInRange(WorldPacket *data, float dist, bool self, bool own_team_only)
{
Map * _map = IsInWorld() ? GetMap() : sMapMgr.FindMap(GetMapId(), GetInstanceId());
if(_map)
{
_map->MessageDistBroadcast(this, data, dist, self, own_team_only);
return;
}
if (Map * _map = IsInWorld() ? GetMap() : sMapMgr.FindMap(GetMapId(), GetInstanceId()))
_map->MessageDistBroadcast(this, data, dist, false, own_team_only);
if(self)
if (self)
GetSession()->SendPacket(data);
}
@ -13547,10 +13535,6 @@ void Player::IncompleteQuest( uint32 quest_id )
void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver, bool announce )
{
//this THING should be here to protect code from quest, which cast on player far teleport as a reward
//should work fine, cause far teleport will be executed in Player::Update()
SetCanDelayTeleport(true);
uint32 quest_id = pQuest->GetQuestId();
for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i )
@ -13702,9 +13686,6 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver
if (!HasAura(itr->second->spellId, EFFECT_INDEX_0))
CastSpell(this,itr->second->spellId,true);
}
//lets remove flag for delayed teleports
SetCanDelayTeleport(false);
}
void Player::FailQuest(uint32 questId)
@ -15322,7 +15303,8 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
SetCreatorGUID(0);
// reset some aura modifiers before aura apply
SetFarSightGUID(0);
SetUInt64Value(PLAYER_FARSIGHT, 0);
SetUInt32Value(PLAYER_TRACK_CREATURES, 0 );
SetUInt32Value(PLAYER_TRACK_RESOURCES, 0 );
@ -17605,7 +17587,7 @@ void Player::RemoveMiniPet()
}
}
Pet* Player::GetMiniPet()
Pet* Player::GetMiniPet() const
{
if (!m_miniPet)
return NULL;
@ -18058,7 +18040,7 @@ void Player::HandleStealthedUnitsDetection()
MaNGOS::UnitListSearcher<MaNGOS::AnyStealthedCheck > searcher(this,stealthedUnits, u_check);
Cell::VisitAllObjects(this, searcher, MAX_PLAYER_STEALTH_DETECT_RANGE);
WorldObject const* viewPoint = GetViewPoint();
WorldObject const* viewPoint = GetCamera().GetBody();
for (std::list<Unit*>::const_iterator i = stealthedUnits.begin(); i != stealthedUnits.end(); ++i)
{
@ -19154,17 +19136,6 @@ void Player::ReportedAfkBy(Player* reporter)
}
}
WorldObject const* Player::GetViewPoint() const
{
if(uint64 far_sight = GetFarSight())
{
WorldObject const* viewPoint = GetMap()->GetWorldObject(far_sight);
return viewPoint ? viewPoint : this; // always expected not NULL
}
else
return this;
}
bool Player::IsVisibleInGridForPlayer( Player* pl ) const
{
// gamemaster in GM mode see all, including ghosts
@ -19461,7 +19432,7 @@ void Player::SendInitialPacketsBeforeAddToMap()
if(HasAuraType(SPELL_AURA_MOD_FLIGHT_SPEED_MOUNTED) || HasAuraType(SPELL_AURA_FLY) || isInFlight())
m_movementInfo.AddMovementFlag(MOVEFLAG_FLYING);
m_mover = this;
SetMover(this);
}
void Player::SendInitialPacketsAfterAddToMap()
@ -20736,7 +20707,7 @@ void Player::EnterVehicle(Vehicle *vehicle)
vehicle->setFaction(getFaction());
SetCharm(vehicle); // charm
SetFarSightGUID(vehicle->GetGUID()); // set view
m_camera.SetView(vehicle); // set view
SetClientControl(vehicle, 1); // redirect controls to vehicle
SetMover(vehicle);
@ -20788,7 +20759,7 @@ void Player::ExitVehicle(Vehicle *vehicle)
vehicle->setFaction((GetTeam() == ALLIANCE) ? vehicle->GetCreatureInfo()->faction_A : vehicle->GetCreatureInfo()->faction_H);
SetCharm(NULL);
SetFarSightGUID(0);
m_camera.ResetView();
SetClientControl(vehicle, 0);
SetMover(NULL);
@ -21230,6 +21201,23 @@ void Player::UpdateAchievementCriteria( AchievementCriteriaTypes type, uint32 mi
GetAchievementMgr().UpdateAchievementCriteria(type, miscvalue1,miscvalue2,unit,time);
}
PlayerTalent const* Player::GetKnownTalentById(int32 talentId) const
{
PlayerTalentMap::const_iterator itr = m_talents[m_activeSpec].find(talentId);
if (itr != m_talents[m_activeSpec].end() && itr->second.state != PLAYERSPELL_REMOVED)
return &itr->second;
else
return NULL;
}
SpellEntry const* Player::GetKnownTalentRankById(int32 talentId) const
{
if (PlayerTalent const* talent = GetKnownTalentById(talentId))
return sSpellStore.LookupEntry(talent->m_talentEntry->RankID[talent->currentRank]);
else
return NULL;
}
void Player::LearnTalent(uint32 talentId, uint32 talentRank)
{
uint32 CurTalentPoints = GetFreeTalentPoints();
@ -21256,9 +21244,8 @@ void Player::LearnTalent(uint32 talentId, uint32 talentRank)
// find current max talent rank
uint32 curtalent_maxrank = 0;
PlayerTalentMap::iterator itr = m_talents[m_activeSpec].find(talentId);
if (itr != m_talents[m_activeSpec].end() && itr->second.state != PLAYERSPELL_REMOVED)
curtalent_maxrank = itr->second.currentRank + 1;
if (PlayerTalent const* talent = GetKnownTalentById(talentId))
curtalent_maxrank = talent->currentRank + 1;
// we already have same or higher talent rank learned
if(curtalent_maxrank >= (talentRank + 1))
@ -21894,17 +21881,16 @@ void Player::ActivateSpec(uint8 specNum)
// learn talent spells if they not in new spec (old spec copy)
// and if they have different rank
PlayerTalentMap::iterator specIter = m_talents[m_activeSpec].find(tempIter->first);
if (specIter != m_talents[m_activeSpec].end() && specIter->second.state != PLAYERSPELL_REMOVED)
if (PlayerTalent const* cur_talent = GetKnownTalentById(tempIter->first))
{
if ((*specIter).second.currentRank != talent.currentRank)
if (cur_talent->currentRank != talent.currentRank)
learnSpell(talentSpellId, false);
}
else
learnSpell(talentSpellId, false);
// sync states - original state is changed in addSpell that learnSpell calls
specIter = m_talents[m_activeSpec].find(tempIter->first);
PlayerTalentMap::iterator specIter = m_talents[m_activeSpec].find(tempIter->first);
if (specIter != m_talents[m_activeSpec].end())
(*specIter).second.state = talent.state;
else
@ -21925,11 +21911,20 @@ void Player::ActivateSpec(uint8 specNum)
// recheck action buttons (not checked at loading/spec copy)
ActionButtonList const& currentActionButtonList = m_actionButtons[m_activeSpec];
for(ActionButtonList::const_iterator itr = currentActionButtonList.begin(); itr != currentActionButtonList.end(); ++itr)
for(ActionButtonList::const_iterator itr = currentActionButtonList.begin(); itr != currentActionButtonList.end(); )
{
if (itr->second.uState != ACTIONBUTTON_DELETED)
{
// remove broken without any output (it can be not correct because talents not copied at spec creating)
if (!IsActionButtonDataValid(itr->first,itr->second.GetAction(),itr->second.GetType(), this, false))
{
removeActionButton(m_activeSpec,itr->first);
itr = currentActionButtonList.begin();
continue;
}
}
++itr;
}
ResummonPetTemporaryUnSummonedIfAny();
@ -22022,38 +22017,6 @@ bool Player::HasMovementFlag( MovementFlags f ) const
return m_movementInfo.HasMovementFlag(f);
}
void Player::SetFarSightGUID( uint64 guid )
{
if(GetFarSight() == guid)
return;
SetUInt64Value(PLAYER_FARSIGHT, guid);
// need triggering load grids around new view point
UpdateVisibilityForPlayer();
}
void Player::UpdateVisibilityForPlayer()
{
WorldObject const* viewPoint = GetViewPoint();
Map* m = GetMap();
CellPair p(MaNGOS::ComputeCellPair(GetPositionX(), GetPositionY()));
Cell cell(p);
m->UpdateObjectVisibility(this, cell, p);
if (this != viewPoint)
{
CellPair pView(MaNGOS::ComputeCellPair(viewPoint->GetPositionX(), viewPoint->GetPositionY()));
Cell cellView(pView);
m->UpdateObjectsVisibilityFor(this, cellView, pView);
}
else
m->UpdateObjectsVisibilityFor(this, cell, p);
}
void Player::ResetTimeSync()
{
m_timeSyncCounter = 0;

View file

@ -1128,8 +1128,6 @@ class MANGOS_DLL_SPEC Player : public Unit
Creature* GetNPCIfCanInteractWith(ObjectGuid guid, uint32 npcflagmask);
GameObject* GetGameObjectIfCanInteractWith(ObjectGuid guid, uint32 gameobject_type = MAX_GAMEOBJECT_TYPE) const;
void UpdateVisibilityForPlayer();
bool ToggleAFK();
bool ToggleDND();
bool isAFK() const { return HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_AFK); }
@ -1191,7 +1189,7 @@ class MANGOS_DLL_SPEC Player : public Unit
void RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent = false);
void RemoveMiniPet();
Pet* GetMiniPet();
Pet* GetMiniPet() const;
void SetMiniPet(Pet* pet) { m_miniPet = pet->GetGUID(); }
template<typename Func>
@ -1666,6 +1664,9 @@ class MANGOS_DLL_SPEC Player : public Unit
SpellCooldowns const& GetSpellCooldownMap() const { return m_spellCooldowns; }
PlayerTalent const* GetKnownTalentById(int32 talentId) const;
SpellEntry const* GetKnownTalentRankById(int32 talentId) const;
void AddSpellMod(SpellModifier* mod, bool apply);
bool IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod, Spell const* spell = NULL);
template <class T> T ApplySpellMod(uint32 spellId, SpellModOp op, T &basevalue, Spell const* spell = NULL);
@ -2191,7 +2192,6 @@ class MANGOS_DLL_SPEC Player : public Unit
/*********************************************************/
bool HasMovementFlag(MovementFlags f) const; // for script access to m_movementInfo.HasMovementFlag
void UpdateFallInformationIfNeed(MovementInfo const& minfo,uint16 opcode);
Unit *m_mover;
void SetFallInformation(uint32 time, float z)
{
m_lastFallTime = time;
@ -2210,12 +2210,13 @@ class MANGOS_DLL_SPEC Player : public Unit
void SetClientControl(Unit* target, uint8 allowMove);
void SetMover(Unit* target) { m_mover = target ? target : this; }
Unit* GetMover() const { return m_mover; }
bool IsSelfMover() const { return m_mover == this; }// normal case for player not controlling other unit
void EnterVehicle(Vehicle *vehicle);
void ExitVehicle(Vehicle *vehicle);
uint64 GetFarSight() const { return GetUInt64Value(PLAYER_FARSIGHT); }
void SetFarSightGUID(uint64 guid);
ObjectGuid const& GetFarSightGuid() const { return GetGuidValue(PLAYER_FARSIGHT); }
// Transports
Transport * GetTransport() const { return m_transport; }
@ -2250,7 +2251,6 @@ class MANGOS_DLL_SPEC Player : public Unit
bool HaveAtClient(WorldObject const* u) { return u==this || m_clientGUIDs.find(u->GetGUID())!=m_clientGUIDs.end(); }
WorldObject const* GetViewPoint() const;
bool IsVisibleInGridForPlayer(Player* pl) const;
bool IsVisibleGloballyFor(Player* pl) const;
@ -2262,6 +2262,8 @@ class MANGOS_DLL_SPEC Player : public Unit
// Stealth detection system
void HandleStealthedUnitsDetection();
Camera& GetCamera() { return m_camera; }
uint8 m_forced_speed_changes[MAX_MOVE_TYPE];
bool HasAtLoginFlag(AtLoginFlags f) const { return m_atLoginFlags & f; }
@ -2353,7 +2355,6 @@ class MANGOS_DLL_SPEC Player : public Unit
bool HasTitle(CharTitlesEntry const* title) { return HasTitle(title->bit_index); }
void SetTitle(CharTitlesEntry const* title, bool lost = false);
bool isActiveObject() const { return true; }
bool canSeeSpellClickOn(Creature const* creature) const;
protected:
@ -2592,17 +2593,30 @@ class MANGOS_DLL_SPEC Player : public Unit
int32 CalculateReputationGain(uint32 creatureOrQuestLevel, int32 rep, int32 faction, bool for_quest);
void AdjustQuestReqItemCount( Quest const* pQuest, QuestStatusData& questStatusData );
bool IsCanDelayTeleport() const { return m_bCanDelayTeleport; }
void SetCanDelayTeleport(bool setting) { m_bCanDelayTeleport = setting; }
bool IsHasDelayedTeleport() const { return m_bHasDelayedTeleport; }
void SetDelayedTeleportFlag(bool setting) { m_bHasDelayedTeleport = setting; }
bool IsHasDelayedTeleport() const
{
// we should not execute delayed teleports for now dead players but has been alive at teleport
// because we don't want player's ghost teleported from graveyard
return m_bHasDelayedTeleport && (isAlive() || !m_bHasBeenAliveAtDelayedTeleport);
}
bool SetDelayedTeleportFlagIfCan()
{
m_bHasDelayedTeleport = m_bCanDelayTeleport;
m_bHasBeenAliveAtDelayedTeleport = isAlive();
return m_bHasDelayedTeleport;
}
void ScheduleDelayedOperation(uint32 operation)
{
if(operation < DELAYED_END)
if (operation < DELAYED_END)
m_DelayedOperations |= operation;
}
Unit *m_mover;
Camera m_camera;
GridReference<Player> m_gridRef;
MapReference m_mapRef;
@ -2630,6 +2644,7 @@ class MANGOS_DLL_SPEC Player : public Unit
uint32 m_DelayedOperations;
bool m_bCanDelayTeleport;
bool m_bHasDelayedTeleport;
bool m_bHasBeenAliveAtDelayedTeleport;
uint32 m_DetectInvTimer;
@ -2710,7 +2725,7 @@ template<typename Func>
bool Player::CheckAllControlledUnits(Func const& func, bool withTotems, bool withGuardians, bool withCharms, bool withMiniPet) const
{
if (withMiniPet)
if(Unit* mini = GetMiniPet())
if(Unit const* mini = GetMiniPet())
if (func(mini))
return true;

View file

@ -106,6 +106,30 @@ void SpawnedPoolData::RemoveSpawn<Pool>(uint32 sub_pool_id, uint32 pool_id)
--val;
}
////////////////////////////////////////////////////////////
// Methods of class PoolObject
template<>
void PoolObject::CheckEventLinkAndReport<Creature>(uint32 poolId, int16 event_id, std::map<uint32, int16> const& creature2event, std::map<uint32, int16> const& /*go2event*/) const
{
std::map<uint32, int16>::const_iterator itr = creature2event.find(guid);
if (itr == creature2event.end() || itr->second != event_id)
sLog.outErrorDb("Creature (GUID: %u) expected to be listed in `game_event_creature` for event %u as part pool %u", guid, event_id, poolId);
}
template<>
void PoolObject::CheckEventLinkAndReport<GameObject>(uint32 poolId, int16 event_id, std::map<uint32, int16> const& /*creature2event*/, std::map<uint32, int16> const& go2event) const
{
std::map<uint32, int16>::const_iterator itr = go2event.find(guid);
if (itr == go2event.end() || itr->second != event_id)
sLog.outErrorDb("Gameobject (GUID: %u) expected to be listed in `game_event_gameobject` for event %u as part pool %u", guid, event_id, poolId);
}
template<>
void PoolObject::CheckEventLinkAndReport<Pool>(uint32 poolId, int16 event_id, std::map<uint32, int16> const& creature2event, std::map<uint32, int16> const& go2event) const
{
sPoolMgr.CheckEventLinkAndReport(guid, event_id, creature2event, go2event);
}
////////////////////////////////////////////////////////////
// Methods of template class PoolGroup
@ -134,6 +158,40 @@ bool PoolGroup<T>::CheckPool() const
return true;
}
// Method to check event linking
template <class T>
void PoolGroup<T>::CheckEventLinkAndReport(int16 event_id, std::map<uint32, int16> const& creature2event, std::map<uint32, int16> const& go2event) const
{
for (uint32 i=0; i < EqualChanced.size(); ++i)
EqualChanced[i].CheckEventLinkAndReport<T>(poolId, event_id, creature2event, go2event);
for (uint32 i=0; i<ExplicitlyChanced.size(); ++i)
ExplicitlyChanced[i].CheckEventLinkAndReport<T>(poolId, event_id, creature2event, go2event);
}
template <class T>
void PoolGroup<T>::SetExcludeObject(uint32 guid, bool state)
{
for (uint32 i=0; i < EqualChanced.size(); ++i)
{
if (EqualChanced[i].guid == guid)
{
EqualChanced[i].exclude = state;
return;
}
}
for (uint32 i=0; i<ExplicitlyChanced.size(); ++i)
{
if (ExplicitlyChanced[i].guid == guid)
{
ExplicitlyChanced[i].exclude = state;
return;
}
}
}
template <class T>
PoolObject* PoolGroup<T>::RollOne(SpawnedPoolData& spawns, uint32 triggerFrom)
{
@ -146,7 +204,7 @@ PoolObject* PoolGroup<T>::RollOne(SpawnedPoolData& spawns, uint32 triggerFrom)
roll -= ExplicitlyChanced[i].chance;
// Triggering object is marked as spawned at this time and can be also rolled (respawn case)
// so this need explicit check for this case
if (roll < 0 && (ExplicitlyChanced[i].guid == triggerFrom || !spawns.IsSpawnedObject<T>(ExplicitlyChanced[i].guid)))
if (roll < 0 && !ExplicitlyChanced[i].exclude && (ExplicitlyChanced[i].guid == triggerFrom || !spawns.IsSpawnedObject<T>(ExplicitlyChanced[i].guid)))
return &ExplicitlyChanced[i];
}
}
@ -156,7 +214,7 @@ PoolObject* PoolGroup<T>::RollOne(SpawnedPoolData& spawns, uint32 triggerFrom)
int32 index = irand(0, EqualChanced.size()-1);
// Triggering object is marked as spawned at this time and can be also rolled (respawn case)
// so this need explicit check for this case
if (EqualChanced[index].guid == triggerFrom || !spawns.IsSpawnedObject<T>(EqualChanced[index].guid))
if (!EqualChanced[index].exclude && (EqualChanced[index].guid == triggerFrom || !spawns.IsSpawnedObject<T>(EqualChanced[index].guid)))
return &EqualChanced[index];
}
@ -263,7 +321,12 @@ void PoolGroup<T>::SpawnObject(SpawnedPoolData& spawns, uint32 limit, uint32 tri
// and also counted into m_SpawnedPoolAmount so we need increase count to be
// spawned by 1
if (triggerFrom)
++count;
{
if (spawns.IsSpawnedObject<T>(triggerFrom))
++count;
else
triggerFrom = 0;
}
// This will try to spawn the rest of pool, not guaranteed
for (int i = 0; i < count; ++i)
@ -462,6 +525,7 @@ void PoolManager::LoadFromDB()
PoolTemplateData& pPoolTemplate = mPoolTemplate[pool_id];
pPoolTemplate.MaxLimit = fields[1].GetUInt32();
pPoolTemplate.AutoSpawn = true; // will update and later data loading
} while (result->NextRow());
@ -661,6 +725,9 @@ void PoolManager::LoadFromDB()
SearchPair p(child_pool_id, mother_pool_id);
mPoolSearchMap.insert(p);
// update top independent pool flag
mPoolTemplate[child_pool_id].AutoSpawn = false;
} while( result->NextRow() );
// Now check for circular reference
@ -692,17 +759,15 @@ void PoolManager::LoadFromDB()
}
}
// The initialize method will spawn all pools not in an event and not in another pool, this is why there is 2 left joins with 2 null checks
// The initialize method will spawn all pools not in an event and not in another pool
void PoolManager::Initialize()
{
QueryResult *result = WorldDatabase.Query("SELECT DISTINCT pool_template.entry FROM pool_template LEFT JOIN game_event_pool ON pool_template.entry=game_event_pool.pool_entry LEFT JOIN pool_pool ON pool_template.entry=pool_pool.pool_id WHERE game_event_pool.pool_entry IS NULL AND pool_pool.pool_id IS NULL");
uint32 count=0;
if (result)
uint32 count = 0;
for(uint16 pool_entry = 0; pool_entry < mPoolTemplate.size(); ++pool_entry)
{
do
if (mPoolTemplate[pool_entry].AutoSpawn)
{
Field *fields = result->Fetch();
uint16 pool_entry = fields[0].GetUInt16();
if (!CheckPool(pool_entry))
{
sLog.outErrorDb("Pool Id (%u) has all creatures or gameobjects with explicit chance sum <>100 and no equal chance defined. The pool system cannot pick one to spawn.", pool_entry);
@ -710,8 +775,7 @@ void PoolManager::Initialize()
}
SpawnPool(pool_entry, true);
count++;
} while (result->NextRow());
delete result;
}
}
BASIC_LOG("Pool handling system initialized, %u pools spawned.", count);
@ -775,6 +839,27 @@ bool PoolManager::CheckPool(uint16 pool_id) const
mPoolPoolGroups[pool_id].CheckPool();
}
// Method that check linking all elements to event
void PoolManager::CheckEventLinkAndReport(uint16 pool_id, int16 event_id, std::map<uint32, int16> const& creature2event, std::map<uint32, int16> const& go2event) const
{
mPoolGameobjectGroups[pool_id].CheckEventLinkAndReport(event_id, creature2event, go2event);
mPoolCreatureGroups[pool_id].CheckEventLinkAndReport(event_id, creature2event, go2event);
mPoolPoolGroups[pool_id].CheckEventLinkAndReport(event_id, creature2event, go2event);
}
// Method that exclude some elements from next spawn
template<>
void PoolManager::SetExcludeObject<Creature>(uint16 pool_id, uint32 db_guid_or_pool_id, bool state)
{
mPoolCreatureGroups[pool_id].SetExcludeObject(db_guid_or_pool_id, state);
}
template<>
void PoolManager::SetExcludeObject<GameObject>(uint16 pool_id, uint32 db_guid_or_pool_id, bool state)
{
mPoolGameobjectGroups[pool_id].SetExcludeObject(db_guid_or_pool_id, state);
}
// Call to update the pool when a gameobject/creature part of pool [pool_id] is ready to respawn
// Here we cache only the creature/gameobject whose guid is passed as parameter
// Then the spawn pool call will use this cache to decide

View file

@ -27,13 +27,19 @@
struct PoolTemplateData
{
uint32 MaxLimit;
bool AutoSpawn; // spawn at pool system start (not part of another pool and not part of event spawn)
};
struct PoolObject
{
uint32 guid;
float chance;
PoolObject(uint32 _guid, float _chance): guid(_guid), chance(fabs(_chance)) {}
bool exclude;
PoolObject(uint32 _guid, float _chance): guid(_guid), chance(fabs(_chance)), exclude(false) {}
template<typename T>
void CheckEventLinkAndReport(uint32 poolId, int16 event_id, std::map<uint32, int16> const& creature2event, std::map<uint32, int16> const& go2event) const;
};
class Pool // for Pool of Pool case
@ -73,10 +79,12 @@ class PoolGroup
bool isEmpty() const { return ExplicitlyChanced.empty() && EqualChanced.empty(); }
void AddEntry(PoolObject& poolitem, uint32 maxentries);
bool CheckPool() const;
void CheckEventLinkAndReport(int16 event_id, std::map<uint32, int16> const& creature2event, std::map<uint32, int16> const& go2event) const;
PoolObject* RollOne(SpawnedPoolData& spawns, uint32 triggerFrom);
void DespawnObject(SpawnedPoolData& spawns, uint32 guid=0);
void Despawn1Object(uint32 guid);
void SpawnObject(SpawnedPoolData& spawns, uint32 limit, uint32 triggerFrom, bool instantly);
void SetExcludeObject(uint32 guid, bool state);
void Spawn1Object(PoolObject* obj, bool instantly);
void ReSpawn1Object(PoolObject* obj);
@ -99,17 +107,37 @@ class PoolManager
template<typename T>
uint16 IsPartOfAPool(uint32 db_guid_or_pool_id) const;
// Method that tell if the creature/gameobject/pool is part of top level pool and return the pool id if yes
template<typename T>
uint16 IsPartOfTopPool(uint32 db_guid_or_pool_id) const
{
if (uint16 pool_id = IsPartOfAPool<T>(db_guid_or_pool_id))
{
if (uint16 top_pool_id = IsPartOfTopPool<Pool>(pool_id))
return top_pool_id;
return pool_id;
}
return 0;
}
template<typename T>
bool IsSpawnedObject(uint32 db_guid_or_pool_id) const { return mSpawnedData.IsSpawnedObject<T>(db_guid_or_pool_id); }
template<typename T>
void SetExcludeObject(uint16 pool_id, uint32 db_guid_or_pool_id, bool state);
bool CheckPool(uint16 pool_id) const;
void CheckEventLinkAndReport(uint16 pool_id, int16 event_id, std::map<uint32, int16> const& creature2event, std::map<uint32, int16> const& go2event) const;
void SpawnPool(uint16 pool_id, bool instantly);
void DespawnPool(uint16 pool_id);
template<typename T>
void UpdatePool(uint16 pool_id, uint32 db_guid_or_pool_id);
void UpdatePool(uint16 pool_id, uint32 db_guid_or_pool_id = 0);
void RemoveAutoSpawnForPool(uint16 pool_id) { mPoolTemplate[pool_id].AutoSpawn = false; }
protected:
template<typename T>
void SpawnPoolGroup(uint16 pool_id, uint32 db_guid_or_pool_id, bool instantly);

View file

@ -4253,21 +4253,11 @@ SpellCastResult Spell::CheckCast(bool strict)
// auto selection spell rank implemented in WorldSession::HandleCastSpellOpcode
// this case can be triggered if rank not found (too low-level target for first rank)
if (m_caster->GetTypeId() == TYPEID_PLAYER && !IsPassiveSpell(m_spellInfo->Id) && !m_CastItem)
if (m_caster->GetTypeId() == TYPEID_PLAYER && !m_CastItem && !m_IsTriggeredSpell)
{
for(int i = 0; i < MAX_EFFECT_INDEX; ++i)
{
// check only spell that apply positive auras
if (m_spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA &&
IsPositiveEffect(m_spellInfo->Id, SpellEffectIndex(i)) &&
// at not self target
!IsCasterSourceTarget(m_spellInfo->EffectImplicitTargetA[i]) &&
// and target low level
target->getLevel() + 10 < m_spellInfo->spellLevel)
{
return SPELL_FAILED_LOWLEVEL;
}
}
// spell expected to be auto-downranking in cast handle, so must be same
if (m_spellInfo != sSpellMgr.SelectAuraRankForLevel(m_spellInfo, target->getLevel()))
return SPELL_FAILED_LOWLEVEL;
}
}
else if (m_caster == target)
@ -4448,7 +4438,7 @@ SpellCastResult Spell::CheckCast(bool strict)
// not let players cast spells at mount (and let do it to creatures)
if (m_caster->IsMounted() && m_caster->GetTypeId()==TYPEID_PLAYER && !m_IsTriggeredSpell &&
!IsPassiveSpell(m_spellInfo->Id) && !(m_spellInfo->Attributes & SPELL_ATTR_CASTABLE_WHILE_MOUNTED))
!IsPassiveSpell(m_spellInfo) && !(m_spellInfo->Attributes & SPELL_ATTR_CASTABLE_WHILE_MOUNTED))
{
if (m_caster->isInFlight())
return SPELL_FAILED_NOT_ON_TAXI;
@ -4457,7 +4447,7 @@ SpellCastResult Spell::CheckCast(bool strict)
}
// always (except passive spells) check items (focus object can be required for any type casts)
if (!IsPassiveSpell(m_spellInfo->Id))
if (!IsPassiveSpell(m_spellInfo))
{
SpellCastResult castResult = CheckItems();
if(castResult != SPELL_CAST_OK)

View file

@ -23,11 +23,14 @@
#include "SharedDefines.h"
#include "DBCEnums.h"
#include "ObjectGuid.h"
#include "LootMgr.h"
#include "Unit.h"
#include "Player.h"
class WorldSession;
class Unit;
class WorldPacket;
class DynamicObj;
class Player;
class Item;
class GameObject;
class Group;
class Aura;
@ -808,6 +811,7 @@ namespace MaNGOS
template<> inline void Visit(CorpseMapType & ) {}
template<> inline void Visit(GameObjectMapType & ) {}
template<> inline void Visit(DynamicObjectMapType & ) {}
template<> inline void Visit(CameraMapType & ) {}
#endif
};
@ -815,6 +819,7 @@ namespace MaNGOS
template<> inline void SpellNotifierCreatureAndPlayer::Visit(CorpseMapType& ) {}
template<> inline void SpellNotifierCreatureAndPlayer::Visit(GameObjectMapType& ) {}
template<> inline void SpellNotifierCreatureAndPlayer::Visit(DynamicObjectMapType& ) {}
template<> inline void SpellNotifierCreatureAndPlayer::Visit(CameraMapType& ) {}
#endif
}

View file

@ -386,7 +386,7 @@ m_isRemovedOnShapeLost(true), m_in_use(0), m_deleted(false)
m_currentBasePoints = currentBasePoints ? *currentBasePoints : m_spellProto->CalculateSimpleValue(eff);
m_isPassive = IsPassiveSpell(GetId());
m_isPassive = IsPassiveSpell(GetSpellProto());
m_positive = IsPositiveEffect(GetId(), m_effIndex);
m_isSingleTargetAura = IsSingleTargetSpell(m_spellProto);
@ -633,7 +633,7 @@ void Aura::Update(uint32 diff)
Unit* caster = GetCaster();
if(!caster)
{
m_target->RemoveAura(GetId(), GetEffIndex());
m_target->RemoveAurasByCasterSpell(GetId(), GetEffIndex(), GetCasterGUID());
return;
}
@ -648,7 +648,7 @@ void Aura::Update(uint32 diff)
if(!caster->IsWithinDistInMap(m_target, max_range))
{
m_target->RemoveAura(GetId(), GetEffIndex());
m_target->RemoveAurasByCasterSpell(GetId(), GetEffIndex(), GetCasterGUID());
return;
}
}
@ -813,7 +813,7 @@ void AreaAura::Update(uint32 diff)
if(!apply)
continue;
if(SpellEntry const *actualSpellInfo = sSpellMgr.SelectAuraRankForPlayerLevel(GetSpellProto(), (*tIter)->getLevel()))
if(SpellEntry const *actualSpellInfo = sSpellMgr.SelectAuraRankForLevel(GetSpellProto(), (*tIter)->getLevel()))
{
int32 actualBasePoints = m_currentBasePoints;
// recalculate basepoints for lower rank (all AreaAura spell not use custom basepoints?)
@ -2380,7 +2380,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
(GetSpellProto()->EffectApplyAuraName[EFFECT_INDEX_0] == 1 || GetSpellProto()->EffectApplyAuraName[EFFECT_INDEX_0] == 128)))
{
// spells with SpellEffect=72 and aura=4: 6196, 6197, 21171, 21425
((Player*)target)->SetFarSightGUID(0);
((Player*)target)->GetCamera().ResetView();
WorldPacket data(SMSG_CLEAR_FAR_SIGHT_IMMEDIATE, 0);
((Player*)target)->GetSession()->SendPacket(&data);
return;
@ -3543,7 +3543,11 @@ void Aura::HandleBindSight(bool apply, bool /*Real*/)
if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
return;
((Player*)caster)->SetFarSightGUID(apply ? GetTarget()->GetGUID() : 0);
Camera& camera = ((Player*)caster)->GetCamera();
if (apply)
camera.SetView(m_target);
else
camera.ResetView();
}
void Aura::HandleFarSight(bool apply, bool /*Real*/)
@ -3552,7 +3556,11 @@ void Aura::HandleFarSight(bool apply, bool /*Real*/)
if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
return;
((Player*)caster)->SetFarSightGUID(apply ? GetTarget()->GetGUID() : 0);
Camera& camera = ((Player*)caster)->GetCamera();
if (apply)
camera.SetView(GetTarget());
else
camera.ResetView();
}
void Aura::HandleAuraTrackCreatures(bool apply, bool /*Real*/)
@ -3607,10 +3615,12 @@ void Aura::HandleModPossess(bool apply, bool Real)
return;
Player* p_caster = (Player*)caster;
Camera& camera = p_caster->GetCamera();
if( apply )
{
target->addUnitState(UNIT_STAT_CONTROLLED);
target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED);
target->SetCharmerGUID(p_caster->GetGUID());
@ -3618,35 +3628,39 @@ void Aura::HandleModPossess(bool apply, bool Real)
p_caster->SetCharm(target);
p_caster->SetFarSightGUID(target->GetGUID());
camera.SetView(target);
p_caster->SetClientControl(target, 1);
p_caster->SetMover(target);
target->CombatStop();
target->CombatStop(true);
target->DeleteThreatList();
target->getHostileRefManager().deleteReferences();
if(CharmInfo *charmInfo = target->InitCharmInfo(target))
{
charmInfo->InitPossessCreateSpells();
charmInfo->SetReactState(REACT_PASSIVE);
charmInfo->SetCommandState(COMMAND_STAY);
}
p_caster->PossessSpellInitialize();
if(target->GetTypeId() == TYPEID_UNIT)
{
target->StopMoving();
target->GetMotionMaster()->Clear();
target->GetMotionMaster()->MoveIdle();
((Creature*)target)->AIM_Initialize();
}
else if(target->GetTypeId() == TYPEID_PLAYER)
{
((Player*)target)->SetClientControl(target, 0);
}
if(CharmInfo *charmInfo = target->InitCharmInfo(target))
charmInfo->InitPossessCreateSpells();
p_caster->PossessSpellInitialize();
}
else
{
p_caster->InterruptSpell(CURRENT_CHANNELED_SPELL); // the spell is not automatically canceled when interrupted, do it now
p_caster->SetCharm(NULL);
p_caster->SetFarSightGUID(0);
camera.ResetView();
p_caster->SetClientControl(target, 0);
p_caster->SetMover(NULL);
@ -3656,6 +3670,12 @@ void Aura::HandleModPossess(bool apply, bool Real)
if(m_removeMode == AURA_REMOVE_BY_DELETE)
return;
target->clearUnitState(UNIT_STAT_CONTROLLED);
target->CombatStop(true);
target->DeleteThreatList();
target->getHostileRefManager().deleteReferences();
target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED);
target->SetCharmerGUID(0);
@ -3690,30 +3710,40 @@ void Aura::HandleModPossessPet(bool apply, bool Real)
if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
return;
Pet *pet = caster->GetPet();
if(!pet || pet != GetTarget())
Unit* target = GetTarget();
if (target->GetTypeId() != TYPEID_UNIT)
return;
Creature* pet = (Creature*)target; // not need more stricted type check
Player* p_caster = (Player*)caster;
Camera& camera = p_caster->GetCamera();
if(apply)
pet->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED);
else
pet->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED);
p_caster->SetFarSightGUID(apply ? pet->GetGUID() : 0);
p_caster->SetCharm(apply ? pet : NULL);
p_caster->SetClientControl(pet, apply ? 1 : 0);
((Player*)caster)->SetMover(apply ? pet : NULL);
if(apply)
if (apply)
{
camera.SetView(pet);
p_caster->SetCharm(pet);
p_caster->SetClientControl(pet, 1);
((Player*)caster)->SetMover(pet);
pet->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED);
pet->StopMoving();
pet->GetMotionMaster()->Clear();
pet->GetMotionMaster()->Clear(false);
pet->GetMotionMaster()->MoveIdle();
}
else
{
camera.ResetView();
p_caster->SetCharm(NULL);
p_caster->SetClientControl(pet, 0);
p_caster->SetMover(NULL);
// on delete only do caster related effects
if(m_removeMode == AURA_REMOVE_BY_DELETE)
return;
pet->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED);
pet->AttackStop();
pet->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
pet->AddSplineFlag(SPLINEFLAG_WALKMODE);
@ -3758,8 +3788,9 @@ void Aura::HandleModCharm(bool apply, bool Real)
target->CastStop(target == caster ? GetId() : 0);
caster->SetCharm(target);
target->CombatStop();
target->CombatStop(true);
target->DeleteThreatList();
target->getHostileRefManager().deleteReferences();
if(target->GetTypeId() == TYPEID_UNIT)
{
@ -3834,6 +3865,10 @@ void Aura::HandleModCharm(bool apply, bool Real)
if(caster->GetTypeId() == TYPEID_PLAYER)
((Player*)caster)->RemovePetActionBar();
target->CombatStop(true);
target->DeleteThreatList();
target->getHostileRefManager().deleteReferences();
if(target->GetTypeId() == TYPEID_UNIT)
{
((Creature*)target)->AIM_Initialize();
@ -4182,7 +4217,7 @@ void Aura::HandleInvisibilityDetect(bool apply, bool Real)
target->m_detectInvisibilityMask |= (1 << m_modifier.m_miscvalue);
}
if(Real && target->GetTypeId()==TYPEID_PLAYER)
((Player*)target)->UpdateVisibilityForPlayer();
((Player*)target)->GetCamera().UpdateVisibilityForOwner();
}
void Aura::HandleAuraModRoot(bool apply, bool Real)
@ -4924,16 +4959,6 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real)
}
break;
}
case SPELLFAMILY_WARLOCK:
{
// Drain Soul
if (spellProto->SpellFamilyFlags & UI64LIT(0x0000000000004000))
{
if (target->GetHealth() * 100 / target->GetMaxHealth() <= 25)
m_modifier.m_amount *= 4;
}
break;
}
case SPELLFAMILY_DRUID:
{
// Rake
@ -8241,9 +8266,13 @@ void Aura::HandleAuraControlVehicle(bool apply, bool Real)
if(!Real)
return;
Unit* target = GetTarget();
if (target->GetTypeId() != TYPEID_UNIT || !((Creature*)target)->isVehicle())
return;
Vehicle* vehicle = (Vehicle*)target;
Unit *player = GetCaster();
Vehicle *vehicle = dynamic_cast<Vehicle*>(GetTarget());
if(!player || player->GetTypeId() != TYPEID_PLAYER || !vehicle)
if(!player || player->GetTypeId() != TYPEID_PLAYER)
return;
if (apply)

View file

@ -4244,7 +4244,8 @@ void Spell::EffectAddFarsight(SpellEffectIndex eff_idx)
dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x80000002);
m_caster->AddDynObject(dynObj);
m_caster->GetMap()->Add(dynObj);
((Player*)m_caster)->SetFarSightGUID(dynObj->GetGUID());
((Player*)m_caster)->GetCamera().SetView(dynObj);
}
void Spell::DoSummonWild(SpellEffectIndex eff_idx, uint32 forceFaction)

View file

@ -31,13 +31,6 @@
void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
{
// TODO: add targets.read() check
Player* pUser = _player;
// ignore for remote control state
if(pUser->m_mover != pUser)
return;
uint8 bagIndex, slot;
uint8 unk_flags; // flags (if 0x02 - some additional data are received)
uint8 cast_count; // next cast if exists (single or not)
@ -47,9 +40,20 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
recvPacket >> bagIndex >> slot >> cast_count >> spellid >> item_guid >> glyphIndex >> unk_flags;
// TODO: add targets.read() check
Player* pUser = _player;
// ignore for remote control state
if (!pUser->IsSelfMover())
{
recvPacket.rpos(recvPacket.wpos()); // prevent spam at not read packet tail
return;
}
// reject fake data
if (glyphIndex >= MAX_GLYPH_SLOT_INDEX)
{
recvPacket.rpos(recvPacket.wpos()); // prevent spam at not read packet tail
pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
return;
}
@ -57,12 +61,14 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
Item *pItem = pUser->GetItemByPos(bagIndex, slot);
if (!pItem)
{
recvPacket.rpos(recvPacket.wpos()); // prevent spam at not read packet tail
pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
return;
}
if (pItem->GetGUID() != item_guid)
{
recvPacket.rpos(recvPacket.wpos()); // prevent spam at not read packet tail
pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
return;
}
@ -72,6 +78,7 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
ItemPrototype const *proto = pItem->GetProto();
if (!proto)
{
recvPacket.rpos(recvPacket.wpos()); // prevent spam at not read packet tail
pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItem, NULL );
return;
}
@ -79,6 +86,7 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
// some item classes can be used only in equipped state
if (proto->InventoryType != INVTYPE_NON_EQUIP && !pItem->IsEquipped())
{
recvPacket.rpos(recvPacket.wpos()); // prevent spam at not read packet tail
pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, pItem, NULL );
return;
}
@ -86,6 +94,7 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
uint8 msg = pUser->CanUseItem(pItem);
if (msg != EQUIP_ERR_OK)
{
recvPacket.rpos(recvPacket.wpos()); // prevent spam at not read packet tail
pUser->SendEquipError( msg, pItem, NULL );
return;
}
@ -95,6 +104,7 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
!(proto->Flags & ITEM_FLAGS_USEABLE_IN_ARENA) &&
pUser->InArena())
{
recvPacket.rpos(recvPacket.wpos()); // prevent spam at not read packet tail
pUser->SendEquipError(EQUIP_ERR_NOT_DURING_ARENA_MATCH,pItem,NULL);
return;
}
@ -107,6 +117,7 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
{
if (IsNonCombatSpell(spellInfo))
{
recvPacket.rpos(recvPacket.wpos()); // prevent spam at not read packet tail
pUser->SendEquipError(EQUIP_ERR_NOT_IN_COMBAT,pItem,NULL);
return;
}
@ -116,6 +127,7 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket)
// Prevent potion drink if another potion in processing (client have potions disabled in like case)
if (pItem->IsPotion() && pUser->GetLastPotionId())
{
recvPacket.rpos(recvPacket.wpos()); // prevent spam at not read packet tail
pUser->SendEquipError(EQUIP_ERR_OBJECT_IS_BUSY,pItem,NULL);
return;
}
@ -174,18 +186,18 @@ void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket)
{
DETAIL_LOG("WORLD: CMSG_OPEN_ITEM packet, data length = %i",(uint32)recvPacket.size());
Player* pUser = _player;
// ignore for remote control state
if(pUser->m_mover != pUser)
return;
uint8 bagIndex, slot;
recvPacket >> bagIndex >> slot;
DETAIL_LOG("bagIndex: %u, slot: %u",bagIndex,slot);
Player* pUser = _player;
// ignore for remote control state
if (!pUser->IsSelfMover())
return;
Item *pItem = pUser->GetItemByPos(bagIndex, slot);
if(!pItem)
{
@ -257,7 +269,7 @@ void WorldSession::HandleGameObjectUseOpcode( WorldPacket & recv_data )
DEBUG_LOG( "WORLD: Recvd CMSG_GAMEOBJ_USE Message [guid=%u]", GUID_LOPART(guid));
// ignore for remote control state
if(_player->m_mover != _player)
if (!_player->IsSelfMover())
return;
GameObject *obj = GetPlayer()->GetMap()->GetGameObject(guid);
@ -276,7 +288,7 @@ void WorldSession::HandleGameobjectReportUse(WorldPacket& recvPacket)
DEBUG_LOG( "WORLD: Recvd CMSG_GAMEOBJ_REPORT_USE Message [in game guid: %u]", GUID_LOPART(guid));
// ignore for remote control state
if(_player->m_mover != _player)
if (!_player->IsSelfMover())
return;
GameObject* go = GetPlayer()->GetMap()->GetGameObject(guid);
@ -298,8 +310,8 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
recvPacket >> unk_flags; // flags (if 0x02 - some additional data are received)
// ignore for remote control state (for player case)
Unit* mover = _player->m_mover;
if(mover != _player && mover->GetTypeId()==TYPEID_PLAYER)
Unit* mover = _player->GetMover();
if (mover != _player && mover->GetTypeId()==TYPEID_PLAYER)
{
recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet
return;
@ -317,10 +329,10 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
return;
}
if(mover->GetTypeId()==TYPEID_PLAYER)
if (mover->GetTypeId()==TYPEID_PLAYER)
{
// not have spell in spellbook or spell passive and not casted by client
if (!((Player*)mover)->HasActiveSpell (spellId) || IsPassiveSpell(spellId) )
if (!((Player*)mover)->HasActiveSpell (spellId) || IsPassiveSpell(spellInfo))
{
sLog.outError("World: Player %u casts spell %u which he shouldn't have", mover->GetGUIDLow(), spellId);
//cheater? kick? ban?
@ -331,7 +343,7 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
else
{
// not have spell in spellbook or spell passive and not casted by client
if (!((Creature*)mover)->HasSpell(spellId) || IsPassiveSpell(spellId) )
if (!((Creature*)mover)->HasSpell(spellId) || IsPassiveSpell(spellInfo))
{
//cheater? kick? ban?
recvPacket.rpos(recvPacket.wpos()); // prevent spam at ignore packet
@ -364,12 +376,10 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
}
// auto-selection buff level base at target level (in spellInfo)
if(targets.getUnitTarget())
if (Unit* target = targets.getUnitTarget())
{
SpellEntry const *actualSpellInfo = sSpellMgr.SelectAuraRankForPlayerLevel(spellInfo,targets.getUnitTarget()->getLevel());
// if rank not found then function return NULL but in explicit cast case original spell can be casted and later failed with appropriate error message
if(actualSpellInfo)
if (SpellEntry const *actualSpellInfo = sSpellMgr.SelectAuraRankForLevel(spellInfo, target->getLevel()))
spellInfo = actualSpellInfo;
}
@ -380,16 +390,16 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket)
void WorldSession::HandleCancelCastOpcode(WorldPacket& recvPacket)
{
// ignore for remote control state (for player case)
Unit* mover = _player->m_mover;
if(mover != _player && mover->GetTypeId()==TYPEID_PLAYER)
return;
uint32 spellId;
recvPacket.read_skip<uint8>(); // counter, increments with every CANCEL packet, don't use for now
recvPacket >> spellId;
// ignore for remote control state (for player case)
Unit* mover = _player->GetMover();
if (mover != _player && mover->GetTypeId()==TYPEID_PLAYER)
return;
//FIXME: hack, ignore unexpected client cancel Deadly Throw cast
if(spellId==26679)
return;
@ -410,10 +420,13 @@ void WorldSession::HandleCancelAuraOpcode( WorldPacket& recvPacket)
if (spellInfo->Attributes & SPELL_ATTR_CANT_CANCEL)
return;
if(!IsPositiveSpell(spellId))
if (IsPassiveSpell(spellInfo))
return;
if (!IsPositiveSpell(spellId))
{
// ignore for remote control state
if (_player->m_mover != _player)
if (!_player->IsSelfMover())
{
// except own aura spells
bool allow = false;
@ -450,16 +463,16 @@ void WorldSession::HandleCancelAuraOpcode( WorldPacket& recvPacket)
void WorldSession::HandlePetCancelAuraOpcode( WorldPacket& recvPacket)
{
// ignore for remote control state
if(_player->m_mover != _player)
return;
uint64 guid;
uint32 spellId;
recvPacket >> guid;
recvPacket >> spellId;
// ignore for remote control state
if (!_player->IsSelfMover())
return;
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId );
if(!spellInfo)
{
@ -501,7 +514,7 @@ void WorldSession::HandleCancelAutoRepeatSpellOpcode( WorldPacket& /*recvPacket*
{
// cancel and prepare for deleting
// do not send SMSG_CANCEL_AUTO_REPEAT! client will send this Opcode again (loop)
_player->m_mover->InterruptSpell(CURRENT_AUTOREPEAT_SPELL, true, false);
_player->GetMover()->InterruptSpell(CURRENT_AUTOREPEAT_SPELL, true, false);
}
void WorldSession::HandleCancelChanneling( WorldPacket & recv_data)
@ -509,8 +522,8 @@ void WorldSession::HandleCancelChanneling( WorldPacket & recv_data)
recv_data.read_skip<uint32>(); // spellid, not used
// ignore for remote control state (for player case)
Unit* mover = _player->m_mover;
if(mover != _player && mover->GetTypeId()==TYPEID_PLAYER)
Unit* mover = _player->GetMover();
if (mover != _player && mover->GetTypeId()==TYPEID_PLAYER)
return;
mover->InterruptSpell(CURRENT_CHANNELED_SPELL);
@ -518,14 +531,14 @@ void WorldSession::HandleCancelChanneling( WorldPacket & recv_data)
void WorldSession::HandleTotemDestroyed( WorldPacket& recvPacket)
{
// ignore for remote control state
if(_player->m_mover != _player)
return;
uint8 slotId;
recvPacket >> slotId;
// ignore for remote control state
if (!_player->IsSelfMover())
return;
if (int(slotId) >= MAX_TOTEM_SLOT)
return;

View file

@ -283,6 +283,11 @@ bool IsPassiveSpell(uint32 spellId)
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId);
if (!spellInfo)
return false;
return IsPassiveSpell(spellInfo);
}
bool IsPassiveSpell(SpellEntry const *spellInfo)
{
return (spellInfo->Attributes & SPELL_ATTR_PASSIVE) != 0;
}
@ -1607,7 +1612,7 @@ bool SpellMgr::IsRankSpellDueToSpell(SpellEntry const *spellInfo_1,uint32 spellI
bool SpellMgr::canStackSpellRanks(SpellEntry const *spellInfo)
{
if(IsPassiveSpell(spellInfo->Id)) // ranked passive spell
if(IsPassiveSpell(spellInfo)) // ranked passive spell
return false;
if(spellInfo->powerType != POWER_MANA && spellInfo->powerType != POWER_HEALTH)
return false;
@ -2211,37 +2216,44 @@ bool SpellMgr::IsSkillBonusSpell(uint32 spellId) const
return false;
}
SpellEntry const* SpellMgr::SelectAuraRankForPlayerLevel(SpellEntry const* spellInfo, uint32 playerLevel) const
SpellEntry const* SpellMgr::SelectAuraRankForLevel(SpellEntry const* spellInfo, uint32 level) const
{
// ignore passive spells
if(IsPassiveSpell(spellInfo->Id))
// fast case
if (level + 10 >= spellInfo->spellLevel)
return spellInfo;
// ignore selection for passive spells
if (IsPassiveSpell(spellInfo))
return spellInfo;
bool needRankSelection = false;
for(int i = 0; i < MAX_EFFECT_INDEX; ++i)
{
if (IsPositiveEffect(spellInfo->Id, SpellEffectIndex(i)) && (
spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA ||
// for simple aura in check apply to any non caster based targets, in rank search mode to any explicit targets
if (((spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA &&
(IsExplicitPositiveTarget(spellInfo->EffectImplicitTargetA[i]) ||
IsAreaEffectPossitiveTarget(Targets(spellInfo->EffectImplicitTargetA[i])))) ||
spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_PARTY ||
spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_RAID))
spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_RAID) &&
IsPositiveEffect(spellInfo->Id, SpellEffectIndex(i)))
{
needRankSelection = true;
break;
}
}
// not required
if(!needRankSelection)
// not required (rank check more slow so check it here)
if (!needRankSelection || GetSpellRank(spellInfo->Id) == 0)
return spellInfo;
for(uint32 nextSpellId = spellInfo->Id; nextSpellId != 0; nextSpellId = GetPrevSpellInChain(nextSpellId))
{
SpellEntry const *nextSpellInfo = sSpellStore.LookupEntry(nextSpellId);
if(!nextSpellInfo)
if (!nextSpellInfo)
break;
// if found appropriate level
if(playerLevel + 10 >= nextSpellInfo->spellLevel)
if (level + 10 >= spellInfo->spellLevel)
return nextSpellInfo;
// one rank less then
@ -2588,7 +2600,7 @@ void SpellMgr::LoadSpellLearnSpells()
// talent or passive spells or skill-step spells auto-casted and not need dependent learning,
// pet teaching spells don't must be dependent learning (casted)
// other required explicit dependent learning
dbc_node.autoLearned = entry->EffectImplicitTargetA[i]==TARGET_PET || GetTalentSpellCost(spell) > 0 || IsPassiveSpell(spell) || IsSpellHaveEffect(entry,SPELL_EFFECT_SKILL_STEP);
dbc_node.autoLearned = entry->EffectImplicitTargetA[i]==TARGET_PET || GetTalentSpellCost(spell) > 0 || IsPassiveSpell(entry) || IsSpellHaveEffect(entry,SPELL_EFFECT_SKILL_STEP);
SpellLearnSpellMapBounds db_node_bounds = GetSpellLearnSpellMapBounds(spell);
@ -3974,4 +3986,4 @@ SpellEntry const* GetSpellEntryByDifficulty(uint32 id, Difficulty difficulty)
SpellEntry const* spellEntry = sSpellStore.LookupEntry(spellDiff->spellId[difficulty]);
return spellEntry;
}
}

View file

@ -210,10 +210,11 @@ bool IsSingleFromSpellSpecificSpellRanksPerTarget(SpellSpecific spellSpec1,Spell
bool IsSingleFromSpellSpecificPerTarget(SpellSpecific spellSpec1,SpellSpecific spellSpec2);
bool IsPassiveSpell(uint32 spellId);
bool IsPassiveSpell(SpellEntry const* spellProto);
inline bool IsPassiveSpellStackableWithRanks(SpellEntry const* spellProto)
{
if(!IsPassiveSpell(spellProto->Id))
if(!IsPassiveSpell(spellProto))
return false;
return !IsSpellHaveEffect(spellProto,SPELL_EFFECT_APPLY_AURA);
@ -319,6 +320,25 @@ inline bool IsPointEffectTarget( Targets target )
return false;
}
inline bool IsAreaEffectPossitiveTarget( Targets target )
{
switch (target )
{
case TARGET_ALL_PARTY_AROUND_CASTER:
case TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER:
case TARGET_ALL_FRIENDLY_UNITS_IN_AREA:
case TARGET_ALL_PARTY:
case TARGET_ALL_PARTY_AROUND_CASTER_2:
case TARGET_AREAEFFECT_PARTY:
case TARGET_ALL_RAID_AROUND_CASTER:
case TARGET_AREAEFFECT_PARTY_AND_CLASS:
return true;
default:
break;
}
return false;
}
inline bool IsAreaEffectTarget( Targets target )
{
switch (target )
@ -371,12 +391,9 @@ inline bool IsAreaAuraEffect(uint32 effect)
inline bool IsDispelSpell(SpellEntry const *spellInfo)
{
if (spellInfo->Effect[EFFECT_INDEX_0] == SPELL_EFFECT_DISPEL ||
spellInfo->Effect[EFFECT_INDEX_1] == SPELL_EFFECT_DISPEL ||
spellInfo->Effect[EFFECT_INDEX_2] == SPELL_EFFECT_DISPEL )
return true;
return false;
return IsSpellHaveEffect(spellInfo, SPELL_EFFECT_DISPEL);
}
inline bool isSpellBreakStealth(SpellEntry const* spellInfo)
{
return !(spellInfo->AttributesEx & SPELL_ATTR_EX_NOT_BREAK_STEALTH);
@ -906,7 +923,7 @@ class SpellMgr
static bool canStackSpellRanks(SpellEntry const *spellInfo);
bool IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) const;
SpellEntry const* SelectAuraRankForPlayerLevel(SpellEntry const* spellInfo, uint32 playerLevel) const;
SpellEntry const* SelectAuraRankForLevel(SpellEntry const* spellInfo, uint32 Level) const;
// Spell learning
SpellLearnSkillNode const* GetSpellLearnSkill(uint32 spell_id) const
@ -1064,4 +1081,4 @@ class SpellMgr
};
#define sSpellMgr SpellMgr::Instance()
#endif
#endif

View file

@ -37,12 +37,17 @@ void TargetedMovementGeneratorMedium<T,D>::_setTargetLocation(T &owner)
if (owner.hasUnitState(UNIT_STAT_NOT_MOVE))
return;
float x, y, z;
// prevent redundant micro-movement for pets, other followers.
if (i_offset && i_target->IsWithinDistInMap(&owner,2*i_offset))
return;
{
if (i_destinationHolder.HasDestination())
return;
float x, y, z;
if (!i_offset)
owner.GetPosition(x, y, z);
}
else if (!i_offset)
{
// to nearest contact position
i_target->GetContactPoint( &owner, x, y, z );

View file

@ -55,6 +55,7 @@ struct MANGOS_DLL_DECL Traveller
void Relocation(float x, float y, float z, float orientation) {}
void Relocation(float x, float y, float z) { Relocation(x, y, z, i_traveller.GetOrientation()); }
void MoveTo(float x, float y, float z, uint32 t) {}
void Stop() {}
};
template<class T>
@ -102,7 +103,13 @@ inline float Traveller<Creature>::GetMoveDestinationTo(float x, float y, float z
template<>
inline void Traveller<Creature>::MoveTo(float x, float y, float z, uint32 t)
{
i_traveller.AI_SendMoveToPacket(x, y, z, t, i_traveller.GetSplineFlags(), SPLINETYPE_NORMAL);
i_traveller.SendMonsterMove(x, y, z, SPLINETYPE_NORMAL, i_traveller.GetSplineFlags(), t);
}
template<>
inline void Traveller<Creature>::Stop()
{
i_traveller.SendMonsterMove(i_traveller.GetPositionX(), i_traveller.GetPositionY(), i_traveller.GetPositionZ(), SPLINETYPE_STOP, i_traveller.GetSplineFlags(), 0);
}
// specialization for players
@ -141,6 +148,13 @@ inline void Traveller<Player>::MoveTo(float x, float y, float z, uint32 t)
i_traveller.SendMonsterMove(x, y, z, SPLINETYPE_NORMAL, SPLINEFLAG_WALKMODE, t);
}
template<>
inline void Traveller<Player>::Stop()
{
//Only send SPLINEFLAG_WALKMODE, client has strange issues with other move flags
i_traveller.SendMonsterMove(i_traveller.GetPositionX(), i_traveller.GetPositionY(), i_traveller.GetPositionZ(), SPLINETYPE_STOP, SPLINEFLAG_WALKMODE, 0);
}
typedef Traveller<Creature> CreatureTraveller;
typedef Traveller<Player> PlayerTraveller;
#endif

View file

@ -382,12 +382,7 @@ void Unit::SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, SplineTy
break;
}
data << uint32(flags);
// enable me if things goes wrong or looks ugly, it is however an old hack
// if(flags & SPLINEFLAG_WALKMODE)
// moveTime *= 1.05f;
data << uint32(flags); // splineflags
data << uint32(moveTime); // Time in between points
data << uint32(1); // 1 single waypoint
data << NewPosX << NewPosY << NewPosZ; // the single waypoint Point B
@ -4011,7 +4006,7 @@ bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur)
SpellEffectIndex effIndex = Aur->GetEffIndex();
// passive spell special case (only non stackable with ranks)
if(IsPassiveSpell(spellId))
if(IsPassiveSpell(spellProto))
{
if(IsPassiveSpellStackableWithRanks(spellProto))
return true;
@ -4034,7 +4029,7 @@ bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur)
uint32 i_spellId = i_spellProto->Id;
// early checks that spellId is passive non stackable spell
if(IsPassiveSpell(i_spellId))
if(IsPassiveSpell(i_spellProto))
{
// passive non-stackable spells not stackable only for same caster
if(Aur->GetCasterGUID()!=i->second->GetCasterGUID())
@ -4516,7 +4511,20 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode)
DEBUG_FILTER_LOG(LOG_FILTER_SPELL_CAST, "Aura %u now is remove mode %d",Aur->GetModifier()->m_auraname, mode);
// some auras also need to apply modifier (on caster) on remove
if (mode != AURA_REMOVE_BY_DELETE || Aur->GetModifier()->m_auraname == SPELL_AURA_MOD_POSSESS)
if (mode == AURA_REMOVE_BY_DELETE)
{
switch (Aur->GetModifier()->m_auraname)
{
// need properly undo any auras with player-caster mover set (or will crash at next caster move packet)
case SPELL_AURA_MOD_POSSESS:
case SPELL_AURA_MOD_POSSESS_PET:
case SPELL_AURA_CONTROL_VEHICLE:
Aur->ApplyModifier(false,true);
break;
default: break;
}
}
else
Aur->ApplyModifier(false,true);
if (Aur->_RemoveAura())
@ -8549,7 +8557,7 @@ void Unit::CombatStopWithPets(bool includingCast)
struct IsAttackingPlayerHelper
{
explicit IsAttackingPlayerHelper() {}
bool operator()(Unit* unit) const { return unit->isAttackingPlayer(); }
bool operator()(Unit const* unit) const { return unit->isAttackingPlayer(); }
};
bool Unit::isAttackingPlayer() const
@ -8615,7 +8623,7 @@ void Unit::ModifyAuraState(AuraState flag, bool apply)
{
if(itr->second.state == PLAYERSPELL_REMOVED) continue;
SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
if (!spellInfo || !IsPassiveSpell(itr->first)) continue;
if (!spellInfo || !IsPassiveSpell(spellInfo)) continue;
if (spellInfo->CasterAuraState == flag)
CastSpell(this, itr->first, true, NULL);
}
@ -8925,7 +8933,18 @@ int32 Unit::SpellBonusWithCoeffs(SpellEntry const *spellProto, int32 total, int3
// apply ap bonus at done part calculation only (it flat total mod so common with taken)
if (donePart && bonus->ap_bonus)
total += int32(bonus->ap_bonus * (GetTotalAttackPowerValue(BASE_ATTACK) + ap_benefit));
{
float ap_bonus = bonus->ap_bonus;
// Impurity
if (GetTypeId() == TYPEID_PLAYER && spellProto->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT)
{
if (SpellEntry const* spell = ((Player*)this)->GetKnownTalentRankById(2005))
ap_bonus += ((spell->CalculateSimpleValue(EFFECT_INDEX_0) * ap_bonus) / 100.0f);
}
total += int32(ap_bonus * (GetTotalAttackPowerValue(BASE_ATTACK) + ap_benefit));
}
}
// Default calculation
else if (benefit)
@ -9158,7 +9177,15 @@ uint32 Unit::SpellDamageBonusDone(Unit *pVictim, SpellEntry const *spellProto, u
break;
}
case SPELLFAMILY_WARLOCK:
{
// Drain Soul
if (spellProto->SpellFamilyFlags & UI64LIT(0x0000000000004000))
{
if (pVictim->GetHealth() * 100 / pVictim->GetMaxHealth() <= 25)
DoneTotalMod *= 4;
}
break;
}
case SPELLFAMILY_PRIEST:
{
// Glyph of Smite
@ -10579,10 +10606,6 @@ bool Unit::isVisibleForOrDetect(Unit const* u, WorldObject const* viewPoint, boo
return false;
}
// always seen by far sight caster
if (u->GetTypeId()==TYPEID_PLAYER && ((Player*)u)->GetFarSight()==GetGUID())
return true;
// different visible distance checks
if (u->isInFlight()) // what see player in flight
{
@ -10781,12 +10804,41 @@ void Unit::SetVisibility(UnitVisibility x)
if(IsInWorld())
{
// some auras requires visible target
if(m_Visibility == VISIBILITY_GROUP_NO_DETECT || m_Visibility == VISIBILITY_OFF)
{
static const AuraType auratypes[] = {SPELL_AURA_BIND_SIGHT, SPELL_AURA_FAR_SIGHT, SPELL_AURA_NONE};
for (AuraType const* type = &auratypes[0]; *type != SPELL_AURA_NONE; ++type)
{
AuraList& alist = m_modAuras[*type];
if(alist.empty())
continue;
for (AuraList::iterator it = alist.begin(); it != alist.end();)
{
Aura* aura = (*it);
Unit* owner = aura->GetCaster();
if (!owner || !isVisibleForOrDetect(owner,this,false))
{
alist.erase(it);
RemoveAura(aura);
it = alist.begin();
}
else
++it;
}
}
}
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().Event_ViewPointVisibilityChanged();
}
}
@ -12039,6 +12091,7 @@ void Unit::RemoveFromWorld()
RemoveAllGameObjects();
RemoveAllDynObjects();
CleanupDeletedAuras();
GetViewPoint().Event_RemovedFromWorld();
}
Object::RemoveFromWorld();
@ -12740,9 +12793,13 @@ void Unit::StopMoving()
{
clearUnitState(UNIT_STAT_MOVING);
// not need send any packets if not in world
if (!IsInWorld())
return;
// send explicit stop packet
// player expected for correct work SPLINEFLAG_WALKMODE
SendMonsterMove(GetPositionX(), GetPositionY(), GetPositionZ(), SPLINETYPE_NORMAL, GetTypeId() == TYPEID_PLAYER ? SPLINEFLAG_WALKMODE : SPLINEFLAG_NONE, 0);
SendMonsterMove(GetPositionX(), GetPositionY(), GetPositionZ(), SPLINETYPE_STOP, GetTypeId() == TYPEID_PLAYER ? SPLINEFLAG_WALKMODE : SPLINEFLAG_NONE, 0);
// update position and orientation for near players
WorldPacket data;
@ -13710,4 +13767,4 @@ bool Unit::CheckAndIncreaseCastCounter()
++m_castCounter;
return true;
}
}

View file

@ -420,24 +420,25 @@ enum UnitState
UNIT_STAT_STUNNED = 0x00000008, // Aura::HandleAuraModStun
UNIT_STAT_ROOT = 0x00000010, // Aura::HandleAuraModRoot
UNIT_STAT_ISOLATED = 0x00000020, // area auras do not affect other players, Aura::HandleAuraModSchoolImmunity
UNIT_STAT_CONTROLLED = 0x00000040, // Aura::HandleAuraModPossess
// persistent movement generator state (all time while movement generator applied to unit (independent from top state of movegen)
UNIT_STAT_IN_FLIGHT = 0x00000040, // player is in flight mode (in fact interrupted at far teleport until next map telport landing)
UNIT_STAT_DISTRACTED = 0x00000080, // DistractedMovementGenerator active
UNIT_STAT_IN_FLIGHT = 0x00000080, // player is in flight mode (in fact interrupted at far teleport until next map telport landing)
UNIT_STAT_DISTRACTED = 0x00000100, // DistractedMovementGenerator active
// persistent movement generator state with non-persistent mirror states for stop support
// (can be removed temporary by stop command or another movement generator apply)
// not use _MOVE versions for generic movegen state, it can be removed temporary for unit stop and etc
UNIT_STAT_CONFUSED = 0x00000100, // ConfusedMovementGenerator active/onstack
UNIT_STAT_CONFUSED_MOVE = 0x00000200,
UNIT_STAT_ROAMING = 0x00000400, // RandomMovementGenerator/PointMovementGenerator/WaypointMovementGenerator active (now always set)
UNIT_STAT_ROAMING_MOVE = 0x00000800,
UNIT_STAT_CHASE = 0x00001000, // ChaseMovementGenerator active
UNIT_STAT_CHASE_MOVE = 0x00002000,
UNIT_STAT_FOLLOW = 0x00004000, // FollowMovementGenerator active
UNIT_STAT_FOLLOW_MOVE = 0x00008000,
UNIT_STAT_FLEEING = 0x00010000, // FleeMovementGenerator/TimedFleeingMovementGenerator active/onstack
UNIT_STAT_FLEEING_MOVE = 0x00020000,
UNIT_STAT_CONFUSED = 0x00000200, // ConfusedMovementGenerator active/onstack
UNIT_STAT_CONFUSED_MOVE = 0x00000400,
UNIT_STAT_ROAMING = 0x00000800, // RandomMovementGenerator/PointMovementGenerator/WaypointMovementGenerator active (now always set)
UNIT_STAT_ROAMING_MOVE = 0x00001000,
UNIT_STAT_CHASE = 0x00002000, // ChaseMovementGenerator active
UNIT_STAT_CHASE_MOVE = 0x00004000,
UNIT_STAT_FOLLOW = 0x00008000, // FollowMovementGenerator active
UNIT_STAT_FOLLOW_MOVE = 0x00010000,
UNIT_STAT_FLEEING = 0x00020000, // FleeMovementGenerator/TimedFleeingMovementGenerator active/onstack
UNIT_STAT_FLEEING_MOVE = 0x00040000,
// masks (only for check)
@ -457,6 +458,12 @@ enum UnitState
UNIT_STAT_CAN_NOT_REACT = UNIT_STAT_STUNNED | UNIT_STAT_DIED |
UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING,
// AI disabled by some reason
UNIT_STAT_LOST_CONTROL = UNIT_STAT_FLEEING | UNIT_STAT_CONTROLLED,
// above 2 state cases
UNIT_STAT_CAN_NOT_REACT_OR_LOST_CONTROL = UNIT_STAT_CAN_NOT_REACT | UNIT_STAT_LOST_CONTROL,
// masks (for check or reset)
// for real move using movegen check and stop (except unstoppable flight)
@ -1943,14 +1950,14 @@ void Unit::CallForAllControlledUnits(Func const& func, bool withTotems, bool wit
template<typename Func>
bool Unit::CheckAllControlledUnits(Func const& func, bool withTotems, bool withGuardians, bool withCharms) const
{
if (Pet* pet = GetPet())
if (Pet const* pet = GetPet())
if (func(pet))
return true;
if (withGuardians)
{
for(GuardianPetList::const_iterator itr = m_guardianPets.begin(); itr != m_guardianPets.end(); ++itr)
if (Unit* guardian = Unit::GetUnit(*this,*itr))
if (Unit const* guardian = Unit::GetUnit(*this,*itr))
if (func(guardian))
return true;
@ -1959,13 +1966,13 @@ bool Unit::CheckAllControlledUnits(Func const& func, bool withTotems, bool withG
if (withTotems)
{
for (int i = 0; i < MAX_TOTEM_SLOT; ++i)
if (Unit *totem = _GetTotem(TotemSlot(i)))
if (Unit const* totem = _GetTotem(TotemSlot(i)))
if (func(totem))
return true;
}
if (withCharms)
if(Unit* charm = GetCharm())
if(Unit const* charm = GetCharm())
if (func(charm))
return true;

View file

@ -22,7 +22,7 @@
#include "Common.h"
#include "Database/DatabaseEnv.h"
#include "Config/ConfigEnv.h"
#include "Config/Config.h"
#include "SystemConfig.h"
#include "Log.h"
#include "Opcodes.h"
@ -402,9 +402,9 @@ Weather* World::AddWeather(uint32 zone_id)
/// Initialize config values
void World::LoadConfigSettings(bool reload)
{
if(reload)
if (reload)
{
if(!sConfig.Reload())
if (!sConfig.Reload())
{
sLog.outError("World settings reload fail: can't read settings from %s.",sConfig.GetFilename().c_str());
return;
@ -413,7 +413,7 @@ void World::LoadConfigSettings(bool reload)
///- Read the version of the configuration file and warn the user in case of emptiness or mismatch
uint32 confVersion = sConfig.GetIntDefault("ConfVersion", 0);
if(!confVersion)
if (!confVersion)
{
sLog.outError("*****************************************************************************");
sLog.outError(" WARNING: mangosd.conf does not include a ConfVersion variable.");
@ -1032,7 +1032,7 @@ void World::SetInitialWorldSettings()
sLog.outString( "Loading Objects Pooling Data...");
sPoolMgr.LoadFromDB();
sLog.outString( "Loading Game Event Data...");
sLog.outString( "Loading Game Event Data..."); // must be after sPoolMgr.LoadFromDB for proper load pool events
sLog.outString();
sGameEventMgr.LoadFromDB();
sLog.outString( ">>> Game Event Data loaded" );

View file

@ -171,7 +171,7 @@ bool WorldSession::Update(uint32 /*diff*/)
packet->GetOpcode());
#endif*/
OpcodeHandler& opHandle = opcodeTable[packet->GetOpcode()];
OpcodeHandler const& opHandle = opcodeTable[packet->GetOpcode()];
try
{
switch (opHandle.status)
@ -184,11 +184,8 @@ bool WorldSession::Update(uint32 /*diff*/)
LogUnexpectedOpcode(packet, "the player has not logged in yet");
}
else if(_player->IsInWorld())
{
(this->*opHandle.handler)(*packet);
if (packet->rpos() < packet->wpos() && sLog.HasLogLevelOrHigher(LOG_LVL_DEBUG))
LogUnprocessedTail(packet);
}
ExecuteOpcode(opHandle, packet);
// lag can cause STATUS_LOGGEDIN opcodes to arrive after the player started a transfer
break;
case STATUS_LOGGEDIN_OR_RECENTLY_LOGGEDOUT:
@ -197,12 +194,8 @@ bool WorldSession::Update(uint32 /*diff*/)
LogUnexpectedOpcode(packet, "the player has not logged in yet and not recently logout");
}
else
{
// not expected _player or must checked in packet hanlder
(this->*opHandle.handler)(*packet);
if (packet->rpos() < packet->wpos() && sLog.HasLogLevelOrHigher(LOG_LVL_DEBUG))
LogUnprocessedTail(packet);
}
ExecuteOpcode(opHandle, packet);
break;
case STATUS_TRANSFER:
if(!_player)
@ -210,11 +203,7 @@ bool WorldSession::Update(uint32 /*diff*/)
else if(_player->IsInWorld())
LogUnexpectedOpcode(packet, "the player is still in world");
else
{
(this->*opHandle.handler)(*packet);
if (packet->rpos() < packet->wpos() && sLog.HasLogLevelOrHigher(LOG_LVL_DEBUG))
LogUnprocessedTail(packet);
}
ExecuteOpcode(opHandle, packet);
break;
case STATUS_AUTHED:
// prevent cheating with skip queue wait
@ -229,9 +218,7 @@ bool WorldSession::Update(uint32 /*diff*/)
if (packet->GetOpcode() != CMSG_SET_ACTIVE_VOICE_CHANNEL)
m_playerRecentlyLogout = false;
(this->*opHandle.handler)(*packet);
if (packet->rpos() < packet->wpos() && sLog.HasLogLevelOrHigher(LOG_LVL_DEBUG))
LogUnprocessedTail(packet);
ExecuteOpcode(opHandle, packet);
break;
case STATUS_NEVER:
sLog.outError( "SESSION: received not allowed opcode %s (0x%.4X)",
@ -872,3 +859,27 @@ void WorldSession::SendRedirectClient(std::string& ip, uint16 port)
SendPacket(&pkt);
}
void WorldSession::ExecuteOpcode( OpcodeHandler const& opHandle, WorldPacket* packet )
{
// need prevent do internal far teleports in handlers because some handlers do lot steps
// or call code that can do far teleports in some conditions unexpectedly for generic way work code
if (_player)
_player->SetCanDelayTeleport(true);
(this->*opHandle.handler)(*packet);
if (_player)
{
// can be not set in fact for login opcode, but this not create porblems.
_player->SetCanDelayTeleport(false);
//we should execute delayed teleports only for alive(!) players
//because we don't want player's ghost teleported from graveyard
if (_player->IsHasDelayedTeleport())
_player->TeleportTo(_player->m_teleport_dest, _player->m_teleport_options);
}
if (packet->rpos() < packet->wpos() && sLog.HasLogLevelOrHigher(LOG_LVL_DEBUG))
LogUnprocessedTail(packet);
}

View file

@ -43,6 +43,8 @@ class LoginQueryHolder;
class CharacterHandler;
class GMTicket;
struct OpcodeHandler;
enum AccountDataType
{
GLOBAL_CONFIG_CACHE = 0, // 0x01 g
@ -773,6 +775,8 @@ class MANGOS_DLL_SPEC WorldSession
// private trade methods
void moveItems(Item* myItems[], Item* hisItems[]);
void ExecuteOpcode( OpcodeHandler const& opHandle, WorldPacket* packet );
// logging helper
void LogUnexpectedOpcode(WorldPacket *packet, const char * reason);
void LogUnprocessedTail(WorldPacket *packet);

View file

@ -40,7 +40,7 @@
#include "Log.h"
#include "Common.h"
#include "Config/ConfigEnv.h"
#include "Config/Config.h"
#include "Database/DatabaseEnv.h"
#include "WorldSocket.h"

View file

@ -27,7 +27,7 @@
#include "ScriptCalls.h"
#include "ObjectMgr.h"
#include "WorldSession.h"
#include "Config/ConfigEnv.h"
#include "Config/Config.h"
#include "Util.h"
#include "AccountMgr.h"
#include "CliRunnable.h"
@ -593,7 +593,7 @@ bool ChatHandler::HandleServerLogLevelCommand(const char *args)
{
if(!*args)
{
PSendSysMessage("Log level: %u");
PSendSysMessage("Log level: %u", sLog.GetLogLevel());
return true;
}
@ -629,7 +629,7 @@ void CliRunnable::run()
///- Display the list of available CLI functions then beep
sLog.outString();
if(sConfig.GetBoolDefault("BeepAtStart", true))
if (sConfig.GetBoolDefault("BeepAtStart", true))
printf("\a"); // \a = Alert
// print this here the first time

View file

@ -22,7 +22,7 @@
#include "Common.h"
#include "Database/DatabaseEnv.h"
#include "Config/ConfigEnv.h"
#include "Config/Config.h"
#include "Log.h"
#include "Master.h"
#include "SystemConfig.h"
@ -31,6 +31,7 @@
#include <openssl/opensslv.h>
#include <openssl/crypto.h>
#include <ace/Version.h>
#include <ace/Get_Opt.h>
#ifdef WIN32
#include "ServiceWin32.h"
@ -56,11 +57,11 @@ uint32 realmID; ///< Id of the realm
void usage(const char *prog)
{
sLog.outString("Usage: \n %s [<options>]\n"
" --version print version and exist\n\r"
" -v, --version print version and exist\n\r"
" -c config_file use config_file as configuration file\n\r"
#ifdef WIN32
" Running as service functions:\n\r"
" --service run as service\n\r"
" -s run run as service\n\r"
" -s install install service\n\r"
" -s uninstall uninstall service\n\r"
#endif
@ -75,69 +76,69 @@ extern int main(int argc, char **argv)
//char *leak = new char[1000]; // test leak detection
///- Command line parsing to get the configuration file name
///- Command line parsing
char const* cfg_file = _MANGOSD_CONFIG;
int c=1;
while( c < argc )
#ifdef WIN32
char const *options = ":c:s:";
#else
char const *options = ":c:";
#endif
ACE_Get_Opt cmd_opts(argc, argv, options);
cmd_opts.long_option("version", 'v');
int option;
while ((option = cmd_opts()) != EOF)
{
if( strcmp(argv[c],"-c") == 0)
switch (option)
{
if( ++c >= argc )
case 'c':
cfg_file = cmd_opts.opt_arg();
break;
case 'v':
printf("%s\n", _FULLVERSION(REVISION_DATE,REVISION_TIME,REVISION_NR,REVISION_ID));
return 0;
#ifdef WIN32
case 's':
{
sLog.outError("Runtime-Error: -c option requires an input argument");
usage(argv[0]);
return 1;
const char *mode = cmd_opts.opt_arg();
if (!strcmp(mode, "install"))
{
if (WinServiceInstall())
sLog.outString("Installing service");
return 1;
}
else if (!strcmp(mode, "uninstall"))
{
if (WinServiceUninstall())
sLog.outString("Uninstalling service");
return 1;
}
else if (!strcmp(mode, "run"))
WinServiceRun();
else
{
sLog.outError("Runtime-Error: -%c unsupported argument %s", cmd_opts.opt_opt(), mode);
usage(argv[0]);
Log::WaitBeforeContinueIfNeed();
return 1;
}
break;
}
else
cfg_file = argv[c];
}
if( strcmp(argv[c],"--version") == 0)
{
printf("%s\n", _FULLVERSION(REVISION_DATE,REVISION_TIME,REVISION_NR,REVISION_ID));
return 0;
}
#ifdef WIN32
////////////
//Services//
////////////
if( strcmp(argv[c],"-s") == 0)
{
if( ++c >= argc )
{
sLog.outError("Runtime-Error: -s option requires an input argument");
#endif
case ':':
sLog.outError("Runtime-Error: -%c option requires an input argument", cmd_opts.opt_opt());
usage(argv[0]);
Log::WaitBeforeContinueIfNeed();
return 1;
}
if( strcmp(argv[c],"install") == 0)
{
if (WinServiceInstall())
sLog.outString("Installing service");
return 1;
}
else if( strcmp(argv[c],"uninstall") == 0)
{
if(WinServiceUninstall())
sLog.outString("Uninstalling service");
return 1;
}
else
{
sLog.outError("Runtime-Error: unsupported option %s",argv[c]);
default:
sLog.outError("Runtime-Error: bad format of commandline arguments");
usage(argv[0]);
Log::WaitBeforeContinueIfNeed();
return 1;
}
}
if( strcmp(argv[c],"--service") == 0)
{
WinServiceRun();
}
////
#endif
++c;
}
if (!sConfig.SetSource(cfg_file))

View file

@ -30,7 +30,7 @@
#include "Timer.h"
#include "Policies/SingletonImp.h"
#include "SystemConfig.h"
#include "Config/ConfigEnv.h"
#include "Config/Config.h"
#include "Database/DatabaseEnv.h"
#include "CliRunnable.h"
#include "RASocket.h"

View file

@ -25,7 +25,7 @@
#include "Log.h"
#include "RASocket.h"
#include "World.h"
#include "Config/ConfigEnv.h"
#include "Config/Config.h"
#include "Util.h"
#include "AccountMgr.h"
#include "Language.h"

View file

@ -1,7 +1,9 @@
#####################################
# MaNGOS Configuration file #
#####################################
ConfVersion=2010051901
[MangosdConf]
ConfVersion=2010062001
###################################################################################################################
# CONNECTIONS AND DIRECTORIES

View file

@ -22,7 +22,7 @@
#include "Common.h"
#include "Database/DatabaseEnv.h"
#include "Config/ConfigEnv.h"
#include "Config/Config.h"
#include "Log.h"
#include "RealmList.h"
#include "AuthSocket.h"

View file

@ -24,7 +24,7 @@
#include "Database/DatabaseEnv.h"
#include "RealmList.h"
#include "Config/ConfigEnv.h"
#include "Config/Config.h"
#include "Log.h"
#include "AuthSocket.h"
#include "SystemConfig.h"
@ -35,6 +35,7 @@
#include <openssl/opensslv.h>
#include <openssl/crypto.h>
#include <ace/Get_Opt.h>
#include <ace/Dev_Poll_Reactor.h>
#include <ace/TP_Reactor.h>
#include <ace/ACE.h>
@ -67,11 +68,11 @@ DatabaseType loginDatabase; ///< Accessor to the
void usage(const char *prog)
{
sLog.outString("Usage: \n %s [<options>]\n"
" --version print version and exist\n\r"
" -v, --version print version and exist\n\r"
" -c config_file use config_file as configuration file\n\r"
#ifdef WIN32
" Running as service functions:\n\r"
" --service run as service\n\r"
" -s run run as service\n\r"
" -s install install service\n\r"
" -s uninstall uninstall service\n\r"
#endif
@ -81,70 +82,69 @@ void usage(const char *prog)
/// Launch the realm server
extern int main(int argc, char **argv)
{
///- Command line parsing to get the configuration file name
///- Command line parsing
char const* cfg_file = _REALMD_CONFIG;
int c=1;
while( c < argc )
#ifdef WIN32
char const *options = ":c:s:";
#else
char const *options = ":c:";
#endif
ACE_Get_Opt cmd_opts(argc, argv, options);
cmd_opts.long_option("version", 'v');
int option;
while ((option = cmd_opts()) != EOF)
{
if( strcmp(argv[c],"-c") == 0)
switch (option)
{
if( ++c >= argc )
case 'c':
cfg_file = cmd_opts.opt_arg();
break;
case 'v':
printf("%s\n", _FULLVERSION(REVISION_DATE,REVISION_TIME,REVISION_NR,REVISION_ID));
return 0;
#ifdef WIN32
case 's':
{
sLog.outError("Runtime-Error: -c option requires an input argument");
usage(argv[0]);
Log::WaitBeforeContinueIfNeed();
return 1;
}
else
cfg_file = argv[c];
}
const char *mode = cmd_opts.opt_arg();
if( strcmp(argv[c],"--version") == 0)
{
printf("%s\n", _FULLVERSION(REVISION_DATE,REVISION_TIME,REVISION_NR,REVISION_ID));
return 0;
}
#ifdef WIN32
////////////
//Services//
////////////
if( strcmp(argv[c],"-s") == 0)
{
if( ++c >= argc )
{
sLog.outError("Runtime-Error: -s option requires an input argument");
if (!strcmp(mode, "install"))
{
if (WinServiceInstall())
sLog.outString("Installing service");
return 1;
}
else if (!strcmp(mode, "uninstall"))
{
if (WinServiceUninstall())
sLog.outString("Uninstalling service");
return 1;
}
else if (!strcmp(mode, "run"))
WinServiceRun();
else
{
sLog.outError("Runtime-Error: -%c unsupported argument %s", cmd_opts.opt_opt(), mode);
usage(argv[0]);
Log::WaitBeforeContinueIfNeed();
return 1;
}
break;
}
#endif
case ':':
sLog.outError("Runtime-Error: -%c option requires an input argument", cmd_opts.opt_opt());
usage(argv[0]);
Log::WaitBeforeContinueIfNeed();
return 1;
}
if( strcmp(argv[c],"install") == 0)
{
if (WinServiceInstall())
sLog.outString("Installing service");
return 1;
}
else if( strcmp(argv[c],"uninstall") == 0)
{
if(WinServiceUninstall())
sLog.outString("Uninstalling service");
return 1;
}
else
{
sLog.outError("Runtime-Error: unsupported option %s",argv[c]);
default:
sLog.outError("Runtime-Error: bad format of commandline arguments");
usage(argv[0]);
Log::WaitBeforeContinueIfNeed();
return 1;
}
}
if( strcmp(argv[c],"--service") == 0)
{
WinServiceRun();
}
////
#endif
++c;
}
if (!sConfig.SetSource(cfg_file))

View file

@ -1,7 +1,9 @@
############################################
# MaNGOS realmd configuration file #
############################################
ConfVersion=2007062001
[RealmdConf]
ConfVersion=2010062001
###################################################################################################################
# REALMD SETTINGS

View file

@ -16,13 +16,36 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "ConfigEnv.h"
#include "Config.h"
#include "ace/Configuration_Import_Export.h"
#include "Policies/SingletonImp.h"
INSTANTIATE_SINGLETON_1(Config);
static bool GetValueHelper(ACE_Configuration_Heap *mConf, const char *name, ACE_TString &result)
{
if (!mConf)
return false;
ACE_TString section_name;
ACE_Configuration_Section_Key section_key;
ACE_Configuration_Section_Key root_key = mConf->root_section();
int i = 0;
while (mConf->enumerate_sections(root_key, i, section_name) == 0)
{
mConf->open_section(root_key, section_name.c_str(), 0, section_key);
if (mConf->get_string_value(section_key, name, result) == 0)
return true;
++i;
}
return false;
}
Config::Config()
: mIgnoreCase(true), mConf(NULL)
: mConf(NULL)
{
}
@ -31,9 +54,8 @@ Config::~Config()
delete mConf;
}
bool Config::SetSource(const char *file, bool ignorecase)
bool Config::SetSource(const char *file)
{
mIgnoreCase = ignorecase;
mFilename = file;
return Reload();
@ -42,43 +64,33 @@ bool Config::SetSource(const char *file, bool ignorecase)
bool Config::Reload()
{
delete mConf;
mConf = new ACE_Configuration_Heap;
mConf = new DOTCONFDocument(mIgnoreCase ?
DOTCONFDocument::CASEINSENSETIVE :
DOTCONFDocument::CASESENSITIVE);
if (mConf->setContent(mFilename.c_str()) == -1)
if (mConf->open() == 0)
{
delete mConf;
mConf = NULL;
return false;
ACE_Ini_ImpExp config_importer(*mConf);
if (config_importer.import_config(mFilename.c_str()) == 0)
return true;
}
return true;
delete mConf;
mConf = NULL;
return false;
}
std::string Config::GetStringDefault(const char* name, const char* def)
{
if (!mConf)
return std::string(def);
DOTCONFDocumentNode const *node = mConf->findNode(name);
if (!node || !node->getValue())
return std::string(def);
return std::string(node->getValue());
ACE_TString val;
return GetValueHelper(mConf, name, val) ? val.c_str() : def;
}
bool Config::GetBoolDefault(const char* name, bool def)
{
if (!mConf)
ACE_TString val;
if (!GetValueHelper(mConf, name, val))
return def;
DOTCONFDocumentNode const *node = mConf->findNode(name);
if (!node || !node->getValue())
return def;
const char* str = node->getValue();
const char* str = val.c_str();
if (strcmp(str, "true") == 0 || strcmp(str, "TRUE") == 0 ||
strcmp(str, "yes") == 0 || strcmp(str, "YES") == 0 ||
strcmp(str, "1") == 0)
@ -90,25 +102,13 @@ bool Config::GetBoolDefault(const char* name, bool def)
int32 Config::GetIntDefault(const char* name, int32 def)
{
if (!mConf)
return def;
DOTCONFDocumentNode const *node = mConf->findNode(name);
if (!node || !node->getValue())
return def;
return atoi(node->getValue());
ACE_TString val;
return GetValueHelper(mConf, name, val) ? atoi(val.c_str()) : def;
}
float Config::GetFloatDefault(const char* name, float def)
{
if (!mConf)
return def;
DOTCONFDocumentNode const *node = mConf->findNode(name);
if (!node || !node->getValue())
return def;
return (float)atof(node->getValue());
ACE_TString val;
return GetValueHelper(mConf, name, val) ? (float)atof(val.c_str()) : def;
}

View file

@ -19,10 +19,11 @@
#ifndef CONFIG_H
#define CONFIG_H
#include "Common.h"
#include <Policies/Singleton.h>
#include "Platform/Define.h"
class DOTCONFDocument;
class ACE_Configuration_Heap;
class MANGOS_DLL_SPEC Config
{
@ -31,7 +32,7 @@ class MANGOS_DLL_SPEC Config
Config();
~Config();
bool SetSource(const char *file, bool ignorecase = true);
bool SetSource(const char *file);
bool Reload();
std::string GetStringDefault(const char* name, const char* def);
@ -44,8 +45,7 @@ class MANGOS_DLL_SPEC Config
private:
std::string mFilename;
bool mIgnoreCase;
DOTCONFDocument *mConf;
ACE_Configuration_Heap *mConf;
};
#define sConfig MaNGOS::Singleton<Config>::Instance()

View file

@ -1,27 +0,0 @@
/*
* Copyright (C) 2005-2010 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
*/
#if !defined(CONFIGENVIRONMENT_H)
#define CONFIGENVIRONMENT_H
#include "Common.h"
#include "dotconfpp/dotconfpp.h"
#include "Config.h"
#endif

View file

@ -1,137 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="ConfigLibrary"
ProjectGUID="{C849D54F-32A6-4025-95BE-E64D1CF0686E}"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
IntermediateDirectory="Debug"
ConfigurationType="4"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)/ConfigLibrary.lib"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
IntermediateDirectory="Release"
ConfigurationType="4"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)/ConfigLibrary.lib"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
<File
RelativePath=".\Config.cpp">
</File>
<File
RelativePath=".\dotconfpp\dotconfpp.cpp">
</File>
<File
RelativePath=".\dotconfpp\mempool.cpp">
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
<File
RelativePath=".\Config.h">
</File>
<File
RelativePath=".\ConfigEnv.h">
</File>
<File
RelativePath=".\dotconfpp\dotconfpp.h">
</File>
<File
RelativePath=".\dotconfpp\mempool.h">
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View file

@ -19,7 +19,7 @@
## Sub-directories to parse
## CPP flags for includes, defines, etc.
AM_CPPFLAGS = $(MANGOS_INCLUDES) -I$(top_builddir)/src/shared -I$(srcdir) -I$(srcdir)/../../../dep/include -I$(srcdir)/../../framework -I$(srcdir)/../../shared -I$(srcdir)/../../../dep/include/g3dlite
AM_CPPFLAGS = $(MANGOS_INCLUDES) -I$(top_builddir)/src/shared -I$(srcdir) -I$(srcdir)/../../../dep/include -I$(srcdir)/../../framework -I$(srcdir)/../../shared
## Build MaNGOS shared library and its parts as convenience library.
# All libraries will be convenience libraries. Might be changed to shared
@ -27,14 +27,5 @@ AM_CPPFLAGS = $(MANGOS_INCLUDES) -I$(top_builddir)/src/shared -I$(srcdir) -I$(sr
noinst_LIBRARIES = libmangosconfig.a
libmangosconfig_a_SOURCES = \
dotconfpp/dotconfpp.cpp \
dotconfpp/dotconfpp.h \
dotconfpp/mempool.cpp \
dotconfpp/mempool.h \
Config.cpp \
Config.h \
ConfigEnv.h
# VC++ project workspace for dotconfpp
EXTRA_DIST = \
ConfigLibrary.vcproj
Config.h

View file

@ -1,703 +0,0 @@
#include "Common.h"
#include "dotconfpp.h"
#include <ace/OS_NS_stdlib.h>
#ifdef WIN32
# define strcasecmp stricmp
# include <io.h>
#else
# include <unistd.h>
# include <limits.h>
# include <stdint.h>
# include <strings.h>
#endif
#if !defined(R_OK)
# define R_OK 04
#endif
DOTCONFDocumentNode::DOTCONFDocumentNode()
: previousNode(NULL), nextNode(NULL), parentNode(NULL), childNode(NULL),
values(NULL), valuesCount(0), name(NULL), lineNum(0),
fileName(NULL), closed(true)
{
}
DOTCONFDocumentNode::~DOTCONFDocumentNode()
{
free(name);
if (values != NULL)
{
for (int i = 0; i < valuesCount; ++i)
free(values[i]);
free(values);
}
}
void DOTCONFDocumentNode::pushValue(char* _value)
{
++valuesCount;
values = (char**)realloc(values, valuesCount * sizeof(char*));
values[valuesCount - 1] = strdup(_value);
}
const char* DOTCONFDocumentNode::getValue(int index) const
{
if (index >= valuesCount)
return NULL;
return values[index];
}
DOTCONFDocument::DOTCONFDocument(DOTCONFDocument::CaseSensitive caseSensitivity)
: mempool(NULL), curParent(NULL), curPrev(NULL), curLine(0), file(NULL), fileName(NULL)
{
switch (caseSensitivity)
{
case CASESENSITIVE:
cmp_func = strcmp;
break;
case CASEINSENSETIVE:
cmp_func = strcasecmp;
break;
}
mempool = new AsyncDNSMemPool(1024);
mempool->initialize();
}
DOTCONFDocument::~DOTCONFDocument()
{
for (NodeList::iterator i = nodeTree.begin(); i != nodeTree.end(); ++i)
delete(*i);
for (CharList::iterator i = requiredOptions.begin(); i != requiredOptions.end(); ++i)
free(*i);
for (CharList::iterator i = processedFiles.begin(); i != processedFiles.end(); ++i)
free(*i);
free(fileName);
delete mempool;
}
int DOTCONFDocument::cleanupLine(char* line)
{
char* start = line;
char* bg = line;
bool multiline = false;
bool concat = false;
char* word = NULL;
if (!words.empty() && quoted)
concat = true;
while (*line)
{
if ((*line == '#' || *line == ';') && !quoted)
{
*bg = 0;
if (strlen(start))
{
if (concat)
{
word = (char*)mempool->Alloc(strlen(words.back()) + strlen(start) + 1);
strcpy(word, words.back());
strcat(word, start);
words.pop_back();
concat = false;
}
else
word = mempool->Strdup(start);
words.push_back(word);
}
break;
}
if (*line == '=' && !quoted)
{
*line = ' ';
continue;
}
// Allowing \" in there causes problems with directory paths
// like "C:\MaNGOS\"
//if(*line == '\\' && (*(line+1) == '"' || *(line+1) == '\'')){
if (*line == '\\' && (*(line + 1) == '\''))
{
*bg++ = *(line + 1);
line += 2;
continue;
}
if (*line == '\\' && *(line + 1) == 'n')
{
*bg++ = '\n';
line += 2;
continue;
}
if (*line == '\\' && *(line + 1) == 'r')
{
*bg++ = '\r';
line += 2;
continue;
}
if (*line == '\\' && (*(line + 1) == '\n' || *(line + 1) == '\r'))
{
*bg = 0;
if (strlen(start))
{
if (concat)
{
word = (char*)mempool->Alloc(strlen(words.back()) + strlen(start) + 1);
strcpy(word, words.back());
strcat(word, start);
words.pop_back();
concat = false;
}
else
word = mempool->Strdup(start);
words.push_back(word);
}
multiline = true;
break;
}
if (*line == '"' || *line == '\'')
{
quoted = !quoted;
++line;
continue;
}
if (isspace((unsigned char)*line) && !quoted)
{
*bg++ = 0;
if (strlen(start))
{
if (concat)
{
word = (char*)mempool->Alloc(strlen(words.back()) + strlen(start) + 1);
strcpy(word, words.back());
strcat(word, start);
words.pop_back();
concat = false;
}
else
word = mempool->Strdup(start);
words.push_back(word);
}
start = bg;
while (isspace((unsigned char)*++line))
{
}
continue;
}
*bg++ = *line++;
}
if (quoted && !multiline)
{
error(curLine, fileName, "unterminated quote");
return -1;
}
return multiline ? 1 : 0;
}
int DOTCONFDocument::parseLine()
{
char* word = NULL;
char* nodeName = NULL;
char* nodeValue = NULL;
DOTCONFDocumentNode* tagNode = NULL;
bool newNode = false;
for (CharList::iterator i = words.begin(); i != words.end(); ++i)
{
word = *i;
if (*word == '<')
newNode = true;
if (newNode)
{
nodeValue = NULL;
nodeName = NULL;
newNode = false;
}
size_t wordLen = strlen(word);
if (word[wordLen - 1] == '>')
{
word[wordLen - 1] = 0;
newNode = true;
}
if (nodeName == NULL)
{
nodeName = word;
bool closed = true;
if (*nodeName == '<')
{
if (*(nodeName + 1) != '/')
{
++nodeName;
closed = false;
}
else
{
NodeList::reverse_iterator itr = nodeTree.rbegin();
nodeName += 2;
for (; itr != nodeTree.rend(); ++itr)
{
if (!cmp_func(nodeName, (*itr)->name) && !(*itr)->closed)
{
(*itr)->closed = true;
curParent = (*itr)->parentNode;
curPrev = *itr;
break;
}
}
if(itr == nodeTree.rend())
{
error(curLine, fileName, "not matched closing tag </%s>", nodeName);
return -1;
}
continue;
}
}
tagNode = new DOTCONFDocumentNode;
tagNode->name = strdup(nodeName);
tagNode->document = this;
tagNode->fileName = processedFiles.back();
tagNode->lineNum = curLine;
tagNode->closed = closed;
if(!nodeTree.empty())
{
DOTCONFDocumentNode* prev = nodeTree.back();
if (prev->closed)
{
curPrev->nextNode = tagNode;
tagNode->previousNode = curPrev;
tagNode->parentNode = curParent;
}
else
{
prev->childNode = tagNode;
tagNode->parentNode = prev;
curParent = prev;
}
}
nodeTree.push_back(tagNode);
curPrev = tagNode;
}
else
{
nodeValue = word;
tagNode->pushValue(nodeValue);
}
}
return 0;
}
int DOTCONFDocument::parseFile(DOTCONFDocumentNode* _parent)
{
char str[512];
int ret = 0;
curLine = 0;
curParent = _parent;
quoted = false;
size_t slen = 0;
while (fgets(str, 511, file))
{
++curLine;
slen = strlen(str);
if (slen >= 510)
error(curLine, fileName, "warning: line too long");
if (str[slen - 1] != '\n')
{
str[slen] = '\n';
str[slen + 1] = 0;
}
if ((ret = cleanupLine(str)) == -1)
break;
if (ret == 0)
{
if (!words.empty())
{
ret = parseLine();
mempool->Free();
words.clear();
if(ret == -1)
break;
}
}
}
return ret;
}
int DOTCONFDocument::checkConfig(const NodeList::iterator& from)
{
int ret = 0;
DOTCONFDocumentNode* tagNode = NULL;
int vi = 0;
for (NodeList::iterator i = from; i != nodeTree.end(); ++i)
{
tagNode = *i;
if (!tagNode->closed)
{
error(tagNode->lineNum, tagNode->fileName, "unclosed tag %s", tagNode->name);
ret = -1;
break;
}
vi = 0;
while (vi < tagNode->valuesCount)
{
if (strstr(tagNode->values[vi], "${") && strchr(tagNode->values[vi], '}'))
{
ret = macroSubstitute(tagNode, vi);
mempool->Free();
if (ret == -1)
break;
}
++vi;
}
if (ret == -1)
break;
}
return ret;
}
int DOTCONFDocument::setContent(const char* _fileName)
{
int ret = 0;
char realpathBuf[MANGOS_PATH_MAX];
if (ACE_OS::realpath(_fileName, realpathBuf) == NULL)
{
error(0, NULL, "realpath (%s) failed: %s", _fileName, strerror(errno));
return -1;
}
fileName = strdup(realpathBuf);
processedFiles.push_back(strdup(realpathBuf));
if ((file = fopen(fileName, "r")) == NULL)
{
error(0, NULL, "failed to open file '%s': %s", fileName, strerror(errno));
return -1;
}
// Try read utf8 header and skip it if exist
unsigned int utf8header = 0;
fgets((char*)&utf8header, 4, file); // Try read header
if (utf8header != 0x00BFBBEF) // If not exist
fseek(file, 0, SEEK_SET); // Reset read position
ret = parseFile();
fclose(file);
if (!ret)
{
if ((ret = checkConfig(nodeTree.begin())) == -1)
return -1;
NodeList::iterator from;
DOTCONFDocumentNode* tagNode = NULL;
int vi = 0;
for (NodeList::iterator i = nodeTree.begin(); i != nodeTree.end(); ++i)
{
tagNode = *i;
if (!cmp_func("DOTCONFPPIncludeFile", tagNode->name))
{
vi = 0;
while (vi < tagNode->valuesCount)
{
if (access(tagNode->values[vi], R_OK) == -1)
{
error(tagNode->lineNum, tagNode->fileName, "%s: %s", tagNode->values[vi], strerror(errno));
return -1;
}
if (ACE_OS::realpath(tagNode->values[vi], realpathBuf) == NULL)
{
error(tagNode->lineNum, tagNode->fileName, "realpath (%s) failed: %s", tagNode->values[vi], strerror(errno));
return -1;
}
bool processed = false;
for (CharList::const_iterator itInode = processedFiles.begin(); itInode != processedFiles.end(); ++itInode)
{
if (!strcmp(*itInode, realpathBuf))
{
processed = true;
break;
}
}
if(processed)
break;
processedFiles.push_back(strdup(realpathBuf));
file = fopen(tagNode->values[vi], "r");
if(file == NULL)
{
error(tagNode->lineNum, fileName, "failed to open file '%s': %s", tagNode->values[vi], strerror(errno));
return -1;
}
fileName = strdup(realpathBuf);
from = nodeTree.end();
--from;
ret = parseFile();
fclose(file);
if (ret == -1)
return -1;
if (checkConfig(++from) == -1)
return -1;
++vi;
}
}
}
if (!requiredOptions.empty())
ret = checkRequiredOptions();
}
return ret;
}
int DOTCONFDocument::checkRequiredOptions()
{
for (CharList::const_iterator ci = requiredOptions.begin(); ci != requiredOptions.end(); ++ci)
{
bool matched = false;
for (NodeList::iterator i = nodeTree.begin(); i != nodeTree.end(); ++i)
{
if (!cmp_func((*i)->name, *ci))
{
matched = true;
break;
}
}
if(!matched)
{
error(0, NULL, "required option '%s' not specified", *ci);
return -1;
}
}
return 0;
}
void DOTCONFDocument::error(int lineNum, const char* fileName_, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
size_t len = (lineNum != 0 ? strlen(fileName_) : 0) + strlen(fmt) + 50;
char* buf = (char*)mempool->Alloc(len);
if (lineNum)
snprintf(buf, len, "DOTCONF++: file '%s', line %d: %s\n", fileName_, lineNum, fmt);
else
snprintf(buf, len, "DOTCONF++: %s\n", fmt);
vfprintf(stderr, buf, args);
va_end(args);
}
char* DOTCONFDocument::getSubstitution(char* macro, int lineNum)
{
char* buf = NULL;
char* variable = macro + 2;
char* endBr = strchr(macro, '}');
if (!endBr)
{
error(lineNum, fileName, "unterminated '{'");
return NULL;
}
*endBr = 0;
char* defaultValue = strchr(variable, ':');
if (defaultValue)
{
*defaultValue++ = 0;
if (*defaultValue != '-')
{
error(lineNum, fileName, "incorrect macro substitution syntax");
return NULL;
}
++defaultValue;
if (*defaultValue == '"' || *defaultValue == '\'')
{
++defaultValue;
defaultValue[strlen(defaultValue) - 1] = 0;
}
}
else
defaultValue = NULL;
char* subs = getenv(variable);
if (subs)
buf = mempool->Strdup(subs);
else
{
NodeList::iterator i = nodeTree.begin();
DOTCONFDocumentNode* tagNode = NULL;
for (; i != nodeTree.end(); ++i)
{
tagNode = *i;
if (!cmp_func(tagNode->name, variable))
{
if (tagNode->valuesCount != 0)
{
buf = mempool->Strdup(tagNode->values[0]);
break;
}
}
}
if (i == nodeTree.end())
{
if (defaultValue)
buf = mempool->Strdup(defaultValue);
else
{
error(lineNum, fileName, "substitution not found and default value not given");
return NULL;
}
}
}
return buf;
}
int DOTCONFDocument::macroSubstitute(DOTCONFDocumentNode* tagNode, int valueIndex)
{
int ret = 0;
char* macro = tagNode->values[valueIndex];
size_t valueLen = strlen(tagNode->values[valueIndex]) + 1;
char* value = (char*)mempool->Alloc(valueLen);
char* v = value;
char* subs = NULL;
while (*macro)
{
if (*macro == '$' && *(macro + 1) == '{')
{
char* m = strchr(macro, '}');
subs = getSubstitution(macro, tagNode->lineNum);
if(subs == NULL)
{
ret = -1;
break;
}
macro = m + 1;
*v = 0;
v = (char*)mempool->Alloc(strlen(value) + strlen(subs) + valueLen);
strcpy(v, value);
value = strcat(v, subs);
v = value + strlen(value);
continue;
}
*v++ = *macro++;
}
*v = 0;
free(tagNode->values[valueIndex]);
tagNode->values[valueIndex] = strdup(value);
return ret;
}
const DOTCONFDocumentNode* DOTCONFDocument::getFirstNode() const
{
if (!nodeTree.empty())
return *nodeTree.begin();
else
return NULL;
}
const DOTCONFDocumentNode* DOTCONFDocument::findNode(const char* nodeName, const DOTCONFDocumentNode* parentNode, const DOTCONFDocumentNode* startNode) const
{
NodeList::const_iterator i = nodeTree.begin();
if (startNode == NULL)
startNode = parentNode;
if (startNode != NULL)
{
while (i != nodeTree.end() && (*i) != startNode)
++i;
if (i != nodeTree.end())
++i;
}
for (; i != nodeTree.end(); ++i)
{
if ((*i)->parentNode != parentNode)
continue;
if (!cmp_func(nodeName, (*i)->name))
return *i;
}
return NULL;
}
void DOTCONFDocument::setRequiredOptionNames(const char** requiredOptionNames)
{
while (*requiredOptionNames)
{
requiredOptions.push_back(strdup(*requiredOptionNames));
++requiredOptionNames;
}
}

View file

@ -1,111 +0,0 @@
#ifndef DOTCONFPP_H
#define DOTCONFPP_H
#include <list>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "mempool.h"
class DOTCONFDocument;
class DOTCONFDocumentNode
{
friend class DOTCONFDocument;
private:
DOTCONFDocumentNode* previousNode;
DOTCONFDocumentNode* nextNode;
DOTCONFDocumentNode* parentNode;
DOTCONFDocumentNode* childNode;
char** values;
int valuesCount;
char* name;
const DOTCONFDocument* document;
int lineNum;
char* fileName;
bool closed;
void pushValue(char* _value);
public:
DOTCONFDocumentNode();
~DOTCONFDocumentNode();
const char* getConfigurationFileName() const { return fileName; }
int getConfigurationLineNumber() const { return lineNum; }
const DOTCONFDocumentNode* getNextNode() const { return nextNode; }
const DOTCONFDocumentNode* getPreviuosNode() const { return previousNode; }
const DOTCONFDocumentNode* getParentNode() const { return parentNode; }
const DOTCONFDocumentNode* getChildNode() const { return childNode; }
const char* getValue(int index = 0) const;
const char* getName() const { return name; }
const DOTCONFDocument * getDocument() const { return document; }
};
class DOTCONFDocument
{
public:
enum CaseSensitive
{
CASESENSITIVE,
CASEINSENSETIVE
};
protected:
AsyncDNSMemPool* mempool;
private:
typedef std::list<char*> CharList;
typedef std::list<DOTCONFDocumentNode*> NodeList;
DOTCONFDocumentNode* curParent;
DOTCONFDocumentNode* curPrev;
int curLine;
bool quoted;
NodeList nodeTree;
CharList requiredOptions;
CharList processedFiles;
FILE* file;
char* fileName;
CharList words;
int (*cmp_func)(const char*, const char*);
int checkRequiredOptions();
int parseLine();
int parseFile(DOTCONFDocumentNode* _parent = NULL);
int checkConfig(const NodeList::iterator& from);
int cleanupLine(char* line);
char* getSubstitution(char* macro, int lineNum);
int macroSubstitute(DOTCONFDocumentNode* tagNode, int valueIndex);
protected:
virtual void error(int lineNum, const char* fileName, const char* fmt, ...) ATTR_PRINTF(4,5);
public:
DOTCONFDocument(CaseSensitive caseSensitivity = CASESENSITIVE);
virtual ~DOTCONFDocument();
int setContent(const char* _fileName);
void setRequiredOptionNames(const char** requiredOptionNames);
const DOTCONFDocumentNode * getFirstNode() const;
const DOTCONFDocumentNode * findNode(const char* nodeName, const DOTCONFDocumentNode* parentNode = NULL, const DOTCONFDocumentNode* startNode = NULL) const;
};
#endif

View file

@ -1,106 +0,0 @@
#include "mempool.h"
AsyncDNSMemPool::PoolChunk::PoolChunk(size_t _size)
: pool(NULL), pos(0), size(_size)
{
pool = malloc(size);
}
AsyncDNSMemPool::PoolChunk::~PoolChunk()
{
::free(pool);
}
AsyncDNSMemPool::AsyncDNSMemPool(size_t _defaultSize)
: chunks(NULL), chunksCount(0), defaultSize(_defaultSize),
poolUsage(0), poolUsageCounter(0)
{
}
AsyncDNSMemPool::~AsyncDNSMemPool()
{
for (size_t i = 0; i < chunksCount; ++i)
delete chunks[i];
::free(chunks);
}
bool AsyncDNSMemPool::initialize()
{
chunksCount = 1;
chunks = (PoolChunk**)malloc(sizeof(PoolChunk*));
if (chunks == NULL)
return false;
chunks[chunksCount - 1] = new PoolChunk(defaultSize);
return true;
}
void AsyncDNSMemPool::addNewChunk(size_t size)
{
++chunksCount;
chunks = (PoolChunk**)realloc(chunks, chunksCount * sizeof(PoolChunk*));
if (size <= defaultSize)
chunks[chunksCount - 1] = new PoolChunk(defaultSize);
else
chunks[chunksCount - 1] = new PoolChunk(size);
}
void* AsyncDNSMemPool::Alloc(size_t size)
{
PoolChunk* chunk = NULL;
for (size_t i = 0; i < chunksCount; ++i)
{
chunk = chunks[i];
if ((chunk->size - chunk->pos) >= size)
{
chunk->pos += size;
return ((char*)chunk->pool) + chunk->pos - size;
}
}
addNewChunk(size);
chunks[chunksCount - 1]->pos = size;
return chunks[chunksCount - 1]->pool;
}
void AsyncDNSMemPool::Free()
{
size_t pu = 0;
size_t psz = 0;
++poolUsageCounter;
for (size_t i = 0; i < chunksCount; ++i)
{
pu += chunks[i]->pos;
psz += chunks[i]->size;
chunks[i]->pos = 0;
}
poolUsage = poolUsage > pu ? poolUsage : pu;
if (poolUsageCounter >= 10 && chunksCount > 1)
{
psz -= chunks[chunksCount - 1]->size;
if (poolUsage < psz)
{
--chunksCount;
delete chunks[chunksCount];
}
poolUsage = 0;
poolUsageCounter = 0;
}
}
void* AsyncDNSMemPool::Calloc(size_t size)
{
return ::memset(Alloc(size), 0, size);
}
char* AsyncDNSMemPool::Strdup(const char *str)
{
return ::strcpy((char*)Alloc(strlen(str) + 1), str);
}

View file

@ -1,43 +0,0 @@
#ifndef ASYNC_DNS_MEMPOOL_H
#define ASYNC_DNS_MEMPOOL_H
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
class AsyncDNSMemPool
{
private:
struct PoolChunk
{
void* pool;
size_t pos;
size_t size;
PoolChunk(size_t _size);
~PoolChunk();
};
PoolChunk** chunks;
size_t chunksCount;
size_t defaultSize;
size_t poolUsage;
size_t poolUsageCounter;
void addNewChunk(size_t size);
public:
AsyncDNSMemPool(size_t _defaultSize = 4096);
virtual ~AsyncDNSMemPool();
bool initialize();
void Free();
void* Alloc(size_t size);
void* Calloc(size_t size);
char* Strdup(const char *str);
};
#endif

View file

@ -17,7 +17,7 @@
*/
#include "DatabaseEnv.h"
#include "Config/ConfigEnv.h"
#include "Config/Config.h"
#include <ctime>
#include <iostream>

View file

@ -62,7 +62,6 @@ if (!(CONDITION)) \
#define WPWarning(CONDITION) \
if (!(CONDITION)) \
{ \
ACE_Stack_Trace st; \
printf("%s:%i: Warning: Assertion in %s failed: %s",\
__FILE__, __LINE__, __FUNCTION__, STRINGIZE(CONDITION)); \
}

View file

@ -19,7 +19,7 @@
#include "Common.h"
#include "Log.h"
#include "Policies/SingletonImp.h"
#include "Config/ConfigEnv.h"
#include "Config/Config.h"
#include "Util.h"
#include "ByteBuffer.h"
#include "ProgressBar.h"

View file

@ -57,7 +57,7 @@ bool WinServiceInstall()
if (GetModuleFileName( 0, path, sizeof(path)/sizeof(path[0]) ) > 0)
{
SC_HANDLE service;
std::strcat(path, " --service");
std::strcat(path, " -s run");
service = CreateService(serviceControlManager,
serviceName, // name of service
serviceLongName, // service name to display

View file

@ -36,10 +36,10 @@
// Format is YYYYMMDDRR where RR is the change in the conf file
// for that day.
#ifndef _MANGOSDCONFVERSION
# define _MANGOSDCONFVERSION 2010051901
# define _MANGOSDCONFVERSION 2010062001
#endif
#ifndef _REALMDCONFVERSION
# define _REALMDCONFVERSION 2007062001
# define _REALMDCONFVERSION 2010062001
#endif
#if MANGOS_ENDIAN == MANGOS_BIGENDIAN

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "10051"
#define REVISION_NR "10091"
#endif // __REVISION_NR_H__

View file

@ -1,6 +1,6 @@
#ifndef __REVISION_SQL_H__
#define __REVISION_SQL_H__
#define REVISION_DB_CHARACTERS "required_10051_01_characters_character_aura"
#define REVISION_DB_MANGOS "required_10045_01_mangos_spell_proc_event"
#define REVISION_DB_MANGOS "required_10089_01_mangos_game_event_pool"
#define REVISION_DB_REALMD "required_10008_01_realmd_realmd_db_version"
#endif // __REVISION_SQL_H__