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

1
NEWS
View file

@ -17,6 +17,7 @@ Version 0.16
* Under discussion. * Under discussion.
* OpenSSL lib upgrade to OpenSSL 1.0.0. * OpenSSL lib upgrade to OpenSSL 1.0.0.
* Sockets lib use dropped. * Sockets lib use dropped.
* dotconfpp lib use dropped.
* Upgrade to client version 3.3.3a (build 11723). * Upgrade to client version 3.3.3a (build 11723).
Version 0.15 Version 0.15

View file

@ -24,7 +24,7 @@ CREATE TABLE `db_version` (
`version` varchar(120) default NULL, `version` varchar(120) default NULL,
`creature_ai_version` varchar(120) default NULL, `creature_ai_version` varchar(120) default NULL,
`cache_id` int(10) default '0', `cache_id` int(10) default '0',
`required_10045_01_mangos_spell_proc_event` bit(1) default NULL `required_10089_01_mangos_game_event_pool` bit(1) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes';
-- --
@ -577,6 +577,7 @@ INSERT INTO `command` VALUES
('gm ingame',0,'Syntax: .gm ingame\r\n\r\nDisplay a list of available in game Game Masters.'), ('gm ingame',0,'Syntax: .gm ingame\r\n\r\nDisplay a list of available in game Game Masters.'),
('gm list',3,'Syntax: .gm list\r\n\r\nDisplay a list of all Game Masters accounts and security levels.'), ('gm list',3,'Syntax: .gm list\r\n\r\nDisplay a list of all Game Masters accounts and security levels.'),
('gm visible',1,'Syntax: .gm visible on/off\r\n\r\nOutput current visibility state or make GM visible(on) and invisible(off) for other players.'), ('gm visible',1,'Syntax: .gm visible on/off\r\n\r\nOutput current visibility state or make GM visible(on) and invisible(off) for other players.'),
('go',1,'Syntax: .go [$playername|pointlink|#x #y #z [#mapid]]\r\nTeleport your character to point with coordinates of player $playername, or coordinates of one from shift-link types: player, tele, taxinode, creature, gameobject, or explicit #x #y #z #mapid coordinates.'),
('go creature',1,'Syntax: .go creature #creature_guid\r\nTeleport your character to creature with guid #creature_guid.\r\n.gocreature #creature_name\r\nTeleport your character to creature with this name.\r\n.gocreature id #creature_id\r\nTeleport your character to a creature that was spawned from the template with this entry.\r\n*If* more than one creature is found, then you are teleported to the first that is found inside the database.'), ('go creature',1,'Syntax: .go creature #creature_guid\r\nTeleport your character to creature with guid #creature_guid.\r\n.gocreature #creature_name\r\nTeleport your character to creature with this name.\r\n.gocreature id #creature_id\r\nTeleport your character to a creature that was spawned from the template with this entry.\r\n*If* more than one creature is found, then you are teleported to the first that is found inside the database.'),
('go graveyard',1,'Syntax: .go graveyard #graveyardId\r\n Teleport to graveyard with the graveyardId specified.'), ('go graveyard',1,'Syntax: .go graveyard #graveyardId\r\n Teleport to graveyard with the graveyardId specified.'),
('go grid',1,'Syntax: .go grid #gridX #gridY [#mapId]\r\n\r\nTeleport the gm to center of grid with provided indexes at map #mapId (or current map if it not provided).'), ('go grid',1,'Syntax: .go grid #gridX #gridY [#mapId]\r\n\r\nTeleport the gm to center of grid with provided indexes at map #mapId (or current map if it not provided).'),
@ -1571,7 +1572,7 @@ UNLOCK TABLES;
DROP TABLE IF EXISTS `game_event_creature`; DROP TABLE IF EXISTS `game_event_creature`;
CREATE TABLE `game_event_creature` ( CREATE TABLE `game_event_creature` (
`guid` int(10) unsigned NOT NULL, `guid` int(10) unsigned NOT NULL,
`event` smallint(6) NOT NULL default '0' COMMENT 'Put negatives values to remove during event', `event` smallint(6) NOT NULL default '0' COMMENT 'Negatives value to remove during event and ignore pool grouping, positive value for spawn during event and if guid is part of pool then al pool memebers must be listed as part of event spawn.',
PRIMARY KEY (`guid`) PRIMARY KEY (`guid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8; ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
@ -1612,7 +1613,7 @@ UNLOCK TABLES;
DROP TABLE IF EXISTS `game_event_gameobject`; DROP TABLE IF EXISTS `game_event_gameobject`;
CREATE TABLE `game_event_gameobject` ( CREATE TABLE `game_event_gameobject` (
`guid` int(10) unsigned NOT NULL, `guid` int(10) unsigned NOT NULL,
`event` smallint(6) NOT NULL default '0' COMMENT 'Put negatives values to remove during event', `event` smallint(6) NOT NULL default '0' COMMENT 'Negatives value to remove during event and ignore pool grouping, positive value for spawn during event and if guid is part of pool then al pool memebers must be listed as part of event spawn.',
PRIMARY KEY (`guid`) PRIMARY KEY (`guid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8; ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
@ -13704,26 +13705,6 @@ LOCK TABLES `pool_template` WRITE;
/*!40000 ALTER TABLE `pool_template` ENABLE KEYS */; /*!40000 ALTER TABLE `pool_template` ENABLE KEYS */;
UNLOCK TABLES; UNLOCK TABLES;
--
-- Table structure for table `game_event_pool`
--
DROP TABLE IF EXISTS `game_event_pool`;
CREATE TABLE `game_event_pool` (
`pool_entry` mediumint(8) unsigned NOT NULL default '0' COMMENT 'Id of the pool',
`event` smallint(6) NOT NULL default '0' COMMENT 'Put negatives values to remove during event',
PRIMARY KEY (`pool_entry`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
--
-- Dumping data for table `game_event_pool`
--
LOCK TABLES `game_event_pool` WRITE;
/*!40000 ALTER TABLE `game_event_pool` DISABLE KEYS */;
/*!40000 ALTER TABLE `game_event_pool` ENABLE KEYS */;
UNLOCK TABLES;
-- --
-- Table structure for table `prospecting_loot_template` -- Table structure for table `prospecting_loot_template`
-- --
@ -17930,6 +17911,7 @@ INSERT INTO `spell_proc_event` VALUES
(31244, 0x00, 8, 0x003E0000, 0x00000009, 0x00000000, 0x00000000, 0x00002034, 0.000000, 0.000000, 0), (31244, 0x00, 8, 0x003E0000, 0x00000009, 0x00000000, 0x00000000, 0x00002034, 0.000000, 0.000000, 0),
(31394, 0x20, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (31394, 0x20, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(31569, 0x00, 3, 0x00010000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (31569, 0x00, 3, 0x00010000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(31571, 0x00, 3, 0x00000000, 0x00000000, 0x00000008, 0x00004000, 0x00000000, 0.000000, 0.000000, 0),
(31785, 0x00, 0, 0x00000000, 0x00000000, 0x00000000, 0x00008800, 0x00000000, 0.000000, 0.000000, 0), (31785, 0x00, 0, 0x00000000, 0x00000000, 0x00000000, 0x00008800, 0x00000000, 0.000000, 0.000000, 0),
(31794, 0x00, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00010000, 0.000000, 0.000000, 0), (31794, 0x00, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00010000, 0.000000, 0.000000, 0),
(31801, 0x01, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (31801, 0x01, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
@ -18290,7 +18272,7 @@ INSERT INTO `spell_proc_event` VALUES
(61618, 0x00, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45), (61618, 0x00, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45),
(61846, 0x00, 9, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (61846, 0x00, 9, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(62600, 0x00, 7, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (62600, 0x00, 7, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0),
(63108, 0x00, 5, 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (63108, 0x00, 5, 0x00000002, 0x00000000, 0x00000000, 0x00040000, 0x00000000, 0.000000, 0.000000, 0),
(63156, 0x00, 0, 0x00000001, 0x00000040, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (63156, 0x00, 0, 0x00000001, 0x00000040, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(63280, 0x00, 11, 0x20000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (63280, 0x00, 11, 0x20000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0),
(63320, 0x00, 5, 0x00040000, 0x00000000, 0x00008000, 0x00004000, 0x00000001, 0.000000, 0.000000, 0), (63320, 0x00, 5, 0x00040000, 0x00000000, 0x00008000, 0x00004000, 0x00000001, 0.000000, 0.000000, 0),

View file

@ -0,0 +1,5 @@
ALTER TABLE db_version CHANGE COLUMN required_10045_01_mangos_spell_proc_event required_10056_01_mangos_spell_proc_event bit;
DELETE FROM spell_proc_event WHERE entry IN (31571, 31572);
INSERT INTO spell_proc_event VALUES
(31571, 0x00, 3, 0x00000000, 0x00000000, 0x00000008, 0x00004000, 0x00000000, 0.000000, 0.000000, 0);

View file

@ -0,0 +1,5 @@
ALTER TABLE db_version CHANGE COLUMN required_10056_01_mangos_spell_proc_event required_10086_01_mangos_command bit;
DELETE FROM command WHERE name IN('go');
INSERT INTO command (name, security, help) VALUES
('go',1,'Syntax: .go [$playername|pointlink|#x #y #z [#mapid]]\r\nTeleport your character to point with coordinates of player $playername, or coordinates of one from shift-link types: player, tele, taxinode, creature, gameobject, or explicit #x #y #z #mapid coordinates.');

View file

@ -0,0 +1,3 @@
ALTER TABLE db_version CHANGE COLUMN required_10086_01_mangos_command required_10089_01_mangos_game_event_pool bit;
DROP TABLE IF EXISTS `game_event_pool`;

View file

@ -88,6 +88,9 @@ pkgdata_DATA = \
10044_02_mangos_spell_proc_event.sql \ 10044_02_mangos_spell_proc_event.sql \
10045_01_mangos_spell_proc_event.sql \ 10045_01_mangos_spell_proc_event.sql \
10051_01_characters_character_aura.sql \ 10051_01_characters_character_aura.sql \
10056_01_mangos_spell_proc_event.sql \
10086_01_mangos_command.sql \
10089_01_mangos_game_event_pool.sql \
README README
## Additional files to include when running 'make dist' ## Additional files to include when running 'make dist'
@ -156,4 +159,7 @@ EXTRA_DIST = \
10044_02_mangos_spell_proc_event.sql \ 10044_02_mangos_spell_proc_event.sql \
10045_01_mangos_spell_proc_event.sql \ 10045_01_mangos_spell_proc_event.sql \
10051_01_characters_character_aura.sql \ 10051_01_characters_character_aura.sql \
10056_01_mangos_spell_proc_event.sql \
10086_01_mangos_command.sql \
10089_01_mangos_game_event_pool.sql \
README README

View file

@ -109,7 +109,7 @@ class MANGOS_DLL_DECL NGrid
} }
const uint32& GetGridId() const { return i_gridId; } 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; } grid_state_t GetGridState() const { return i_cellstate; }
void SetGridState(grid_state_t s) { i_cellstate = s; } void SetGridState(grid_state_t s) { i_cellstate = s; }
uint32 getX() const { return i_x; } 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::AchievementChatBuilder say_builder(*GetPlayer(), CHAT_MSG_ACHIEVEMENT, LANG_ACHIEVEMENT_EARNED,achievement->ID);
MaNGOS::LocalizedPacketDo<MaNGOS::AchievementChatBuilder> say_do(say_builder); 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)); 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)) 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()); AreaTrigger const* at = sObjectMgr.GetGoBackTrigger(pCurrChar->GetMapId());
if(at) if(at)
pCurrChar->TeleportTo(at->target_mapId, at->target_X, at->target_Y, at->target_Z, pCurrChar->GetOrientation()); 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 }, { "zonexy", SEC_MODERATOR, false, &ChatHandler::HandleGoZoneXYCommand, "", NULL },
{ "xy", SEC_MODERATOR, false, &ChatHandler::HandleGoXYCommand, "", NULL }, { "xy", SEC_MODERATOR, false, &ChatHandler::HandleGoXYCommand, "", NULL },
{ "xyz", SEC_MODERATOR, false, &ChatHandler::HandleGoXYZCommand, "", 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 } { 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 // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r
char* cId = extractKeyFromLink(text,"Htele"); char* cId = extractKeyFromLink(text,"Htele");
if(!cId) if(!cId)
return false; return NULL;
// id case (explicit or from shift link) // id case (explicit or from shift link)
if(cId[0] >= '0' || cId[0] >= '9') if(cId[0] >= '0' || cId[0] >= '9')
@ -2079,7 +2079,7 @@ static char const* const guidKeys[] =
"Hplayer", "Hplayer",
"Hcreature", "Hcreature",
"Hgameobject", "Hgameobject",
0 NULL
}; };
uint64 ChatHandler::extractGuidFromLink(char* text) uint64 ChatHandler::extractGuidFromLink(char* text)
@ -2133,6 +2133,130 @@ uint64 ChatHandler::extractGuidFromLink(char* text)
return 0; 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) std::string ChatHandler::extractPlayerNameFromLink(char* text)
{ {
// |color|Hplayer:name|h[name]|h|r // |color|Hplayer:name|h[name]|h|r
@ -2229,7 +2353,7 @@ char* ChatHandler::extractQuotedArg( char* args )
{ {
char* space = strtok(args, "\""); char* space = strtok(args, "\"");
if(!space) if(!space)
return false; return NULL;
return strtok(NULL, "\""); return strtok(NULL, "\"");
} }
} }

View file

@ -535,6 +535,7 @@ class ChatHandler
uint32 extractSpellIdFromLink(char* text); uint32 extractSpellIdFromLink(char* text);
uint64 extractGuidFromLink(char* text); uint64 extractGuidFromLink(char* text);
GameTele const* extractGameTeleFromLink(char* text); GameTele const* extractGameTeleFromLink(char* text);
bool extractLocationFromLink(char* text, uint32& mapid, float& x, float& y, float& z);
std::string extractPlayerNameFromLink(char* text); std::string extractPlayerNameFromLink(char* text);
// select by arg (name/link) or in-game selection online/offline player // 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); 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 HandleCharacterLevel(Player* player, uint64 player_guid, uint32 oldlevel, uint32 newlevel);
void HandleLearnSkillRecipesHelper(Player* player,uint32 skill_id); void HandleLearnSkillRecipesHelper(Player* player,uint32 skill_id);
void ShowSpellListHelper(Player* target, SpellEntry const* spellInfo, LocaleConstant loc); 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 * 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::EmoteChatBuilder emote_builder(*GetPlayer(), text_emote, emoteNum, unit);
MaNGOS::LocalizedPacketDo<MaNGOS::EmoteChatBuilder > emote_do(emote_builder); 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)); Cell::VisitWorldObjects(GetPlayer(), emote_worker, sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_TEXTEMOTE));
GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote, 0, unit); 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; } GridReference<Corpse> &GetGridRef() { return m_gridRef; }
bool isActiveObject() const { return false; }
bool IsExpired(time_t t) const; bool IsExpired(time_t t) const;
private: private:
GridReference<Corpse> m_gridRef; 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_AlreadyCallAssistance(false), m_AlreadySearchedAssistance(false),
m_regenHealth(true), m_AI_locked(false), m_isDeadByDefault(false), m_needNotify(false), m_regenHealth(true), m_AI_locked(false), m_isDeadByDefault(false), m_needNotify(false),
m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), 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_regenTimer = 200;
m_valuesCount = UNIT_END; 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); SetByteValue(UNIT_FIELD_BYTES_0, 2, minfo->gender);
// Load creature equipment // Load creature equipment
if(!data || data->equipmentId == 0) if (!data || data->equipmentId == 0)
{ // use default from the template {
LoadEquipment(cinfo->equipmentId); 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 { // override, -1 means no equipment
LoadEquipment(data->equipmentId); LoadEquipment(data->equipmentId);
} }
@ -788,29 +791,6 @@ bool Creature::isCanTrainingAndResetTalentsOf(Player* pPlayer) const
&& pPlayer->getClass() == GetCreatureInfo()->trainer_class; && 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() void Creature::PrepareBodyLootState()
{ {
loot.clear(); loot.clear();
@ -2218,4 +2198,4 @@ void Creature::RelocationNotify()
MaNGOS::CreatureRelocationNotifier relocationNotifier(*this); MaNGOS::CreatureRelocationNotifier relocationNotifier(*this);
float radius = MAX_CREATURE_ATTACK_RADIUS * sWorld.getConfig(CONFIG_FLOAT_RATE_CREATURE_AGGRO); float radius = MAX_CREATURE_ATTACK_RADIUS * sWorld.getConfig(CONFIG_FLOAT_RATE_CREATURE_AGGRO);
Cell::VisitAllObjects(this, relocationNotifier, radius); Cell::VisitAllObjects(this, relocationNotifier, radius);
} }

View file

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

View file

@ -36,7 +36,7 @@ CanCastResult CreatureAI::CanCastSpell(Unit* pTarget, const SpellEntry *pSpell,
if (!isTriggered) if (!isTriggered)
{ {
// State does not allow // 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; return CAST_FAIL_STATE;
if (pSpell->PreventionType == SPELL_PREVENTION_TYPE_SILENCE && m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED)) 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()); MovementGeneratorRegistry &mv_registry(MovementGeneratorRepository::Instance());
ASSERT( creature->GetCreatureInfo() != NULL ); 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 ) /* if( mv_factory == NULL )
{ {

View file

@ -1319,7 +1319,7 @@ bool CreatureEventAI::CanCast(Unit* Target, SpellEntry const *Spell, bool Trigge
return false; return false;
//Silenced so we can't cast //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))) m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED)))
return false; 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_totalTravelTime = traveller.GetTotalTrevelTimeTo(i_destX,i_destY,i_destZ);
i_timeElapsed = 0; i_timeElapsed = 0;
if(sendMove) 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; return i_totalTravelTime;
} }

View file

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

View file

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

View file

@ -171,6 +171,13 @@ void GameEventMgr::LoadFromDB()
sLog.outString( ">> Loaded %u game events", count ); 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); mGameEventCreatureGuids.resize(mGameEvent.size()*2-1);
// 1 2 // 1 2
result = WorldDatabase.Query("SELECT creature.guid, game_event_creature.event " result = WorldDatabase.Query("SELECT creature.guid, game_event_creature.event "
@ -198,6 +205,12 @@ void GameEventMgr::LoadFromDB()
uint32 guid = fields[0].GetUInt32(); uint32 guid = fields[0].GetUInt32();
int16 event_id = fields[1].GetInt16(); 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; int32 internal_event_id = mGameEvent.size() + event_id - 1;
if(internal_event_id < 0 || (size_t)internal_event_id >= mGameEventCreatureGuids.size()) if(internal_event_id < 0 || (size_t)internal_event_id >= mGameEventCreatureGuids.size())
@ -207,6 +220,32 @@ void GameEventMgr::LoadFromDB()
} }
++count; ++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]; GuidList& crelist = mGameEventCreatureGuids[internal_event_id];
crelist.push_back(guid); crelist.push_back(guid);
@ -244,6 +283,12 @@ void GameEventMgr::LoadFromDB()
uint32 guid = fields[0].GetUInt32(); uint32 guid = fields[0].GetUInt32();
int16 event_id = fields[1].GetInt16(); 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; int32 internal_event_id = mGameEvent.size() + event_id - 1;
if(internal_event_id < 0 || (size_t)internal_event_id >= mGameEventGameobjectGuids.size()) if(internal_event_id < 0 || (size_t)internal_event_id >= mGameEventGameobjectGuids.size())
@ -253,6 +298,32 @@ void GameEventMgr::LoadFromDB()
} }
++count; ++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]; GuidList& golist = mGameEventGameobjectGuids[internal_event_id];
golist.push_back(guid); golist.push_back(guid);
@ -263,6 +334,15 @@ void GameEventMgr::LoadFromDB()
sLog.outString( ">> Loaded %u gameobjects in game events", count ); 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()); mGameEventModelEquip.resize(mGameEvent.size());
// 0 1 2 // 0 1 2
result = WorldDatabase.Query("SELECT creature.guid, game_event_model_equip.event, game_event_model_equip.modelid," 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();
sLog.outString( ">> Loaded %u quests additions in game events", count ); 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 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); CreatureData const* data = sObjectMgr.GetCreatureData(*itr);
if (data) 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); sObjectMgr.AddCreatureToGrid(*itr, data);
// Spawn if necessary (loaded grids only) // Spawn if necessary (loaded grids only)
@ -549,7 +590,20 @@ void GameEventMgr::GameEventSpawn(int16 event_id)
GameObjectData const* data = sObjectMgr.GetGOData(*itr); GameObjectData const* data = sObjectMgr.GetGOData(*itr);
if (data) 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); sObjectMgr.AddGameobjectToGrid(*itr, data);
// Spawn if necessary (loaded grids only) // Spawn if necessary (loaded grids only)
// this base map checked as non-instanced and then only existed // this base map checked as non-instanced and then only existed
Map* map = const_cast<Map*>(sMapMgr.CreateBaseMap(data->mapid)); 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()); if((size_t)event_id >= mGameEventSpawnPoolIds.size())
return; {
} 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) for (IdList::iterator itr = mGameEventSpawnPoolIds[event_id].begin();itr != mGameEventSpawnPoolIds[event_id].end();++itr)
sPoolMgr.SpawnPool(*itr, true); sPoolMgr.SpawnPool(*itr, true);
}
} }
void GameEventMgr::GameEventUnspawn(int16 event_id) void GameEventMgr::GameEventUnspawn(int16 event_id)
@ -596,6 +653,17 @@ void GameEventMgr::GameEventUnspawn(int16 event_id)
// Remove the creature from grid // Remove the creature from grid
if( CreatureData const* data = sObjectMgr.GetCreatureData(*itr) ) 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); sObjectMgr.RemoveCreatureFromGrid(*itr, data);
if (Creature* pCreature = ObjectAccessor::GetCreatureInWorld(ObjectGuid(HIGHGUID_UNIT, data->id, *itr))) 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 // Remove the gameobject from grid
if(GameObjectData const* data = sObjectMgr.GetGOData(*itr)) 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); sObjectMgr.RemoveGameobjectFromGrid(*itr, data);
if( GameObject* pGameobject = ObjectAccessor::GetGameObjectInWorld(ObjectGuid(HIGHGUID_GAMEOBJECT, data->id, *itr)) ) if( GameObject* pGameobject = ObjectAccessor::GetGameObjectInWorld(ObjectGuid(HIGHGUID_GAMEOBJECT, data->id, *itr)) )
pGameobject->AddObjectToRemoveList(); 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::pair<uint32, uint32> QuestRelation;
typedef std::list<QuestRelation> QuestRelList; typedef std::list<QuestRelation> QuestRelList;
typedef std::vector<QuestRelList> GameEventQuestMap; typedef std::vector<QuestRelList> GameEventQuestMap;
GameEventQuestMap mGameEventQuests; GameEventQuestMap mGameEventQuests; // events*2-1
GameEventModelEquipMap mGameEventModelEquip; GameEventModelEquipMap mGameEventModelEquip; // events*2-1
GameEventGuidMap mGameEventCreatureGuids; GameEventGuidMap mGameEventCreatureGuids; // events*2-1
GameEventGuidMap mGameEventGameobjectGuids; GameEventGuidMap mGameEventGameobjectGuids; // events*2-1
GameEventIdMap mGameEventPoolIds; GameEventIdMap mGameEventSpawnPoolIds; // events size, only positive event case
GameEventDataMap mGameEvent; GameEventDataMap mGameEvent;
ActiveEvents m_ActiveEvents; ActiveEvents m_ActiveEvents;
bool m_IsGameEventsInit; bool m_IsGameEventsInit;

View file

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

View file

@ -31,6 +31,7 @@ class DynamicObject;
class GameObject; class GameObject;
class Pet; class Pet;
class Player; class Player;
class Camera;
#define MAX_NUMBER_OF_GRIDS 64 #define MAX_NUMBER_OF_GRIDS 64
@ -56,10 +57,12 @@ class Player;
#define MAP_HALFSIZE (MAP_SIZE/2) #define MAP_HALFSIZE (MAP_SIZE/2)
// Creature used instead pet to simplify *::Visit templates (not required duplicate code for Creature->Pet case) // 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_4(GameObject, Creature/*except pets*/, DynamicObject, Corpse/*Bones*/) AllGridObjectTypes;
typedef TYPELIST_5(Creature, Pet, Vehicle, GameObject, DynamicObject) AllMapStoredObjectTypes; typedef TYPELIST_5(Creature, Pet, Vehicle, GameObject, DynamicObject) AllMapStoredObjectTypes;
typedef GridRefManager<Camera> CameraMapType;
typedef GridRefManager<Corpse> CorpseMapType; typedef GridRefManager<Corpse> CorpseMapType;
typedef GridRefManager<Creature> CreatureMapType; typedef GridRefManager<Creature> CreatureMapType;
typedef GridRefManager<DynamicObject> DynamicObjectMapType; typedef GridRefManager<DynamicObject> DynamicObjectMapType;

View file

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

View file

@ -28,32 +28,29 @@
using namespace MaNGOS; using namespace MaNGOS;
void 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(); iter->getSource()->UpdateVisibilityOf(&i_object);
if(player == &i_object)
continue;
player->UpdateVisibilityOf(player->GetViewPoint(),&i_object);
} }
} }
void void
VisibleNotifier::Notify() VisibleNotifier::Notify()
{ {
Player& player = *i_camera.GetOwner();
// at this moment i_clientGUIDs have guids that not iterate at grid level checks // 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 // 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) 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 // ignore far sight case
(*itr)->UpdateVisibilityOf((*itr),&i_player); (*itr)->UpdateVisibilityOf(*itr, &player);
i_player.UpdateVisibilityOf(&i_player,(*itr),i_data,i_visibleNow); player.UpdateVisibilityOf(&player, *itr, i_data, i_visibleNow);
i_clientGUIDs.erase((*itr)->GetGUID()); i_clientGUIDs.erase((*itr)->GetGUID());
} }
} }
@ -63,27 +60,28 @@ VisibleNotifier::Notify()
i_data.AddOutOfRangeGUID(i_clientGUIDs); i_data.AddOutOfRangeGUID(i_clientGUIDs);
for(ObjectGuidSet::iterator itr = i_clientGUIDs.begin();itr!=i_clientGUIDs.end();++itr) 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) // send create/outofrange packet to player (except player create updates that already sent using SendUpdateToPlayer)
WorldPacket packet; WorldPacket packet;
i_data.BuildPacket(&packet); i_data.BuildPacket(&packet);
i_player.GetSession()->SendPacket(&packet); player.GetSession()->SendPacket(&packet);
// send out of range to other players if need // send out of range to other players if need
ObjectGuidSet const& oor = i_data.GetOutOfRangeGUIDs(); ObjectGuidSet const& oor = i_data.GetOutOfRangeGUIDs();
for(ObjectGuidSet::const_iterator iter = oor.begin(); iter != oor.end(); ++iter) for(ObjectGuidSet::const_iterator iter = oor.begin(); iter != oor.end(); ++iter)
{ {
if(!iter->IsPlayer()) if (!iter->IsPlayer())
continue; continue;
if (Player* plr = ObjectAccessor::FindPlayer(*iter)) 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) 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 // target aura duration for caster show only if target exist at caster client
if((*vItr)!=&i_player && (*vItr)->isType(TYPEMASK_UNIT)) if ((*vItr) != &player && (*vItr)->isType(TYPEMASK_UNIT))
i_player.SendAurasForTarget((Unit*)(*vItr)); player.SendAurasForTarget((Unit*)(*vItr));
// non finished movements show to player // non finished movements show to player
if((*vItr)->GetTypeId()==TYPEID_UNIT && ((Creature*)(*vItr))->isAlive()) if ((*vItr)->GetTypeId()==TYPEID_UNIT && ((Creature*)(*vItr))->isAlive())
((Creature*)(*vItr))->SendMonsterMoveWithSpeedToCurrentDestination(&i_player); ((Creature*)(*vItr))->SendMonsterMoveWithSpeedToCurrentDestination(&player);
} }
} }
void 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; continue;
if(WorldSession* session = iter->getSource()->GetSession()) if (WorldSession* session = owner->GetSession())
session->SendPacket(i_message); 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(); Player* owner = iter->getSource()->GetOwner();
if(!player->InSamePhase(i_phaseMask) || player == i_skipped_receiver)
if (!owner->InSamePhase(i_phaseMask) || owner == i_skipped_receiver)
continue; continue;
if (WorldSession* session = player->GetSession()) if (WorldSession* session = owner->GetSession())
session->SendPacket(i_message); session->SendPacket(i_message);
} }
} }
void 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; continue;
if(WorldSession* session = iter->getSource()->GetSession()) if(WorldSession* session = iter->getSource()->GetOwner()->GetSession())
session->SendPacket(i_message); session->SendPacket(i_message);
} }
} }
void 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 ) && Player * owner = iter->getSource()->GetOwner();
(!i_ownTeamOnly || iter->getSource()->GetTeam() == i_player.GetTeam() ) &&
(!i_dist || iter->getSource()->IsWithinDist(&i_player,i_dist))) 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; continue;
if (WorldSession* session = iter->getSource()->GetSession()) if (WorldSession* session = owner->GetSession())
session->SendPacket(i_message); session->SendPacket(i_message);
} }
} }
} }
void 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; continue;
if (WorldSession* session = iter->getSource()->GetSession()) if (WorldSession* session = iter->getSource()->GetOwner()->GetSession())
session->SendPacket(i_message); session->SendPacket(i_message);
} }
} }

View file

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

View file

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

View file

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

View file

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

View file

@ -2226,6 +2226,51 @@ bool ChatHandler::HandleGroupgoCommand(const char* args)
return true; 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) bool ChatHandler::HandleGoTaxinodeCommand(const char* args)
{ {
Player* _player = m_session->GetPlayer(); Player* _player = m_session->GetPlayer();
@ -2249,28 +2294,55 @@ bool ChatHandler::HandleGoTaxinodeCommand(const char* args)
return false; return false;
} }
if ((node->x == 0.0f && node->y == 0.0f && node->z == 0.0f) || if (node->x == 0.0f && node->y == 0.0f && node->z == 0.0f)
!MapManager::IsValidMapCoord(node->map_id,node->x,node->y,node->z))
{ {
PSendSysMessage(LANG_INVALID_TARGET_COORD,node->x,node->y,node->map_id); PSendSysMessage(LANG_INVALID_TARGET_COORD,node->x,node->y,node->map_id);
SetSentErrorMessage(true); SetSentErrorMessage(true);
return false; return false;
} }
// stop flight if need return HandleGoHelper(_player, node->map_id, node->x, node->y, &node->z);
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;
} }
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 //teleport at coordinates
bool ChatHandler::HandleGoXYCommand(const char* args) bool ChatHandler::HandleGoXYCommand(const char* args)
{ {
@ -2293,29 +2365,7 @@ bool ChatHandler::HandleGoXYCommand(const char* args)
mapid = (uint32)atoi(pmapid); mapid = (uint32)atoi(pmapid);
else mapid = _player->GetMapId(); else mapid = _player->GetMapId();
if(!MapManager::IsValidMapCoord(mapid,x,y)) return HandleGoHelper(_player, 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;
} }
//teleport at coordinates, including Z //teleport at coordinates, including Z
@ -2343,26 +2393,7 @@ bool ChatHandler::HandleGoXYZCommand(const char* args)
else else
mapid = _player->GetMapId(); mapid = _player->GetMapId();
if(!MapManager::IsValidMapCoord(mapid,x,y,z)) return HandleGoHelper(_player, 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;
} }
//teleport at coordinates //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) // update to parent zone if exist (client map show only zones without parents)
AreaTableEntry const* zoneEntry = areaEntry->zone ? GetAreaEntryByAreaID(areaEntry->zone) : areaEntry; 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); SetSentErrorMessage(true);
return false; return false;
} }
if (!Zone2MapCoordinates(x,y,zoneEntry->ID)) 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); SetSentErrorMessage(true);
return false; return false;
} }
if(!MapManager::IsValidMapCoord(zoneEntry->mapid,x,y)) return HandleGoHelper(_player, mapEntry->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;
} }
//teleport to grid //teleport to grid
bool ChatHandler::HandleGoGridCommand(const char* args) bool ChatHandler::HandleGoGridCommand(const char* args)
{ {
if(!*args) return false; if (!*args)
return false;
Player* _player = m_session->GetPlayer(); Player* _player = m_session->GetPlayer();
char* px = strtok((char*)args, " "); char* px = strtok((char*)args, " ");
@ -2457,37 +2472,13 @@ bool ChatHandler::HandleGoGridCommand(const char* args)
float grid_x = (float)atof(px); float grid_x = (float)atof(px);
float grid_y = (float)atof(py); float grid_y = (float)atof(py);
uint32 mapid; uint32 mapid = pmapid ? (uint32)atoi(pmapid) : _player->GetMapId();
if (pmapid)
mapid = (uint32)atoi(pmapid);
else mapid = _player->GetMapId();
// center of grid // center of grid
float x = (grid_x-CENTER_GRID_ID+0.5f)*SIZE_OF_GRIDS; float x = (grid_x-CENTER_GRID_ID+0.5f)*SIZE_OF_GRIDS;
float y = (grid_y-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)) return HandleGoHelper(_player, 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;
} }
bool ChatHandler::HandleModifyDrunkCommand(const char* args) bool ChatHandler::HandleModifyDrunkCommand(const char* args)

View file

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

View file

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

View file

@ -26,7 +26,6 @@
#include "InstanceData.h" #include "InstanceData.h"
#include "Map.h" #include "Map.h"
#include "GridNotifiersImpl.h" #include "GridNotifiersImpl.h"
#include "Config/ConfigEnv.h"
#include "Transports.h" #include "Transports.h"
#include "ObjectAccessor.h" #include "ObjectAccessor.h"
#include "ObjectMgr.h" #include "ObjectMgr.h"
@ -367,8 +366,9 @@ bool Map::Add(Player *player)
SendInitSelf(player); SendInitSelf(player);
SendInitTransports(player); SendInitTransports(player);
NGridType* grid = getNGrid(cell.GridX(), cell.GridY());
player->GetViewPoint().Event_AddedToWorld(&(*grid)(cell.CellX(), cell.CellY()));
UpdateObjectVisibility(player,cell,p); UpdateObjectVisibility(player,cell,p);
UpdateObjectsVisibilityFor(player,cell,p);
AddNotifier(player,cell,p); AddNotifier(player,cell,p);
return true; 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()); 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); UpdateObjectVisibility(obj,cell,p);
AddNotifier(obj,cell,p); AddNotifier(obj,cell,p);
@ -682,7 +683,6 @@ void Map::Remove(Player *player, bool remove)
SendRemoveTransports(player); SendRemoveTransports(player);
UpdateObjectVisibility(player,cell,p); UpdateObjectVisibility(player,cell,p);
UpdateObjectsVisibilityFor(player,cell,p);
player->ResetMap(); player->ResetMap();
if( remove ) if( remove )
@ -716,10 +716,9 @@ Map::Remove(T *obj, bool remove)
else else
obj->RemoveFromWorld(); 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); RemoveFromGrid(obj,grid,cell);
UpdateObjectVisibility(obj,cell,p);
obj->ResetMap(); obj->ResetMap();
if( remove ) if( remove )
{ {
@ -759,10 +758,13 @@ Map::PlayerRelocation(Player *player, float x, float y, float z, float orientati
AddToGrid(player, oldGrid,new_cell); AddToGrid(player, oldGrid,new_cell);
else else
EnsureGridLoadedAtEnter(new_cell, player); 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 // if move then update what player see and who seen
UpdateObjectsVisibilityFor(player,new_cell,new_val);
UpdateObjectVisibility(player, new_cell, new_val); UpdateObjectVisibility(player, new_cell, new_val);
PlayerRelocationNotify(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->SetNeedNotify();
} }
creature->GetViewPoint().Call_UpdateVisibilityForOwner();
ASSERT(CheckGridIntegrity(creature,true)); 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()); 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);
{
RemoveFromGrid(c,getNGrid(old_cell.GridX(), old_cell.GridY()),old_cell); NGridType* new_grid = getNGrid(new_cell.GridX(), new_cell.GridY());
AddToGrid(c,getNGrid(new_cell.GridX(), new_cell.GridY()),new_cell); AddToGrid(c,new_grid,new_cell);
c->SetCurrentCell(new_cell);
} c->GetViewPoint().Event_GridChanged( &(*new_grid)(new_cell.CellX(),new_cell.CellY()) );
} }
else 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()); 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); 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; 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); RemoveFromGrid(c,getNGrid(old_cell.GridX(), old_cell.GridY()),old_cell);
{ {
EnsureGridCreated(GridPair(new_cell.GridX(), new_cell.GridY())); 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; return true;
@ -1420,21 +1428,6 @@ void Map::UpdateObjectVisibility( WorldObject* obj, Cell cell, CellPair cellpair
cell.Visit(cellpair, player_notifier, *this, *obj, GetVisibilityDistance()); 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 ) void Map::PlayerRelocationNotify( Player* player, Cell cell, CellPair cellpair )
{ {
MaNGOS::PlayerRelocationNotifier relocationNotifier(*player); MaNGOS::PlayerRelocationNotifier relocationNotifier(*player);
@ -1646,44 +1639,63 @@ bool Map::ActiveObjectsNearGrid(uint32 x, uint32 y) const
return false; 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 // 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; Creature* c= (Creature*)obj;
c->GetRespawnCoord(x,y,z);
GridPair p = MaNGOS::ComputeGridPair(x, y); if (!c->isPet() && c->GetDBTableGUIDLow())
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()); float x,y,z;
sLog.outError("Active creature (GUID: %u Entry: %u) added to grid[%u,%u] but spawn grid[%u,%u] not loaded.", c->GetRespawnCoord(x,y,z);
c->GetGUIDLow(), c->GetEntry(), p.x_coord, p.y_coord, p2.x_coord, p2.y_coord); 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 // also allow unloading spawn grid
if(!c->isPet() && c->GetDBTableGUIDLow()) if (obj->GetTypeId()==TYPEID_UNIT)
{ {
float x,y,z; Creature* c= (Creature*)obj;
c->GetRespawnCoord(x,y,z);
GridPair p = MaNGOS::ComputeGridPair(x, y); if(!c->isPet() && c->GetDBTableGUIDLow())
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()); float x,y,z;
sLog.outError("Active creature (GUID: %u Entry: %u) removed from grid[%u,%u] but spawn grid[%u,%u] not loaded.", c->GetRespawnCoord(x,y,z);
c->GetGUIDLow(), c->GetEntry(), p.x_coord, p.y_coord, p2.x_coord, p2.y_coord); 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> class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::ObjectLevelLockable<Map, ACE_Thread_Mutex>
{ {
friend class MapReference; friend class MapReference;
friend class ObjectGridLoader;
friend class ObjectWorldLoader;
public: public:
Map(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode, Map* _parent = NULL); Map(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode, Map* _parent = NULL);
virtual ~Map(); virtual ~Map();
@ -211,7 +213,6 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
void AddObjectToRemoveList(WorldObject *obj); void AddObjectToRemoveList(WorldObject *obj);
void UpdateObjectVisibility(WorldObject* obj, Cell cell, CellPair cellpair); void UpdateObjectVisibility(WorldObject* obj, Cell cell, CellPair cellpair);
void UpdateObjectsVisibilityFor(Player* player, Cell cell, CellPair cellpair);
void resetMarkedCells() { marked_cells.reset(); } void resetMarkedCells() { marked_cells.reset(); }
bool isCellMarked(uint32 pCellId) { return marked_cells.test(pCellId); } 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); void ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* source, Object* target);
// must called with AddToWorld // must called with AddToWorld
template<class T> void AddToActive(WorldObject* obj);
void AddToActive(T* obj) { AddToActiveHelper(obj); }
void AddToActive(Creature* obj);
// must called with RemoveFromWorld // must called with RemoveFromWorld
template<class T> void RemoveFromActive(WorldObject* obj);
void RemoveFromActive(T* obj) { RemoveFromActiveHelper(obj); }
void RemoveFromActive(Creature* obj);
Creature* GetCreature(ObjectGuid guid); Creature* GetCreature(ObjectGuid guid);
Vehicle* GetVehicle(ObjectGuid guid); Vehicle* GetVehicle(ObjectGuid guid);
@ -357,27 +351,6 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
template<class T> template<class T>
void DeleteFromWorld(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 enum InstanceResetMethod

View file

@ -1293,10 +1293,10 @@ void WorldSession::HandleFarSightOpcode( WorldPacket & recv_data )
//WorldPacket data(SMSG_CLEAR_FAR_SIGHT_IMMEDIATE, 0) //WorldPacket data(SMSG_CLEAR_FAR_SIGHT_IMMEDIATE, 0)
//SendPacket(&data); //SendPacket(&data);
//_player->SetUInt64Value(PLAYER_FARSIGHT, 0); //_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; break;
case 1: 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; break;
} }
} }

View file

@ -40,11 +40,15 @@ inline bool isStatic(MovementGenerator *mv)
void void
MotionMaster::Initialize() MotionMaster::Initialize()
{ {
// stop current move
if (!i_owner->IsStopped())
i_owner->StopMoving();
// clear ALL movement generators (including default) // clear ALL movement generators (including default)
Clear(false,true); Clear(false,true);
// set new default movement generator // 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); MovementGenerator* movement = FactorySelector::selectMovementGenerator((Creature*)i_owner);
push(movement == NULL ? &si_idleMovement : movement); push(movement == NULL ? &si_idleMovement : movement);
@ -226,7 +230,7 @@ void MotionMaster::MoveRandom()
void void
MotionMaster::MoveTargetedHome() MotionMaster::MoveTargetedHome()
{ {
if(i_owner->hasUnitState(UNIT_STAT_FLEEING)) if(i_owner->hasUnitState(UNIT_STAT_LOST_CONTROL))
return; return;
Clear(false); Clear(false);
@ -281,6 +285,9 @@ MotionMaster::MoveChase(Unit* target, float dist, float angle)
void void
MotionMaster::MoveFollow(Unit* target, float dist, float angle) MotionMaster::MoveFollow(Unit* target, float dist, float angle)
{ {
if(i_owner->hasUnitState(UNIT_STAT_LOST_CONTROL))
return;
Clear(); Clear();
// ignore movement request if target not exist // 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("Guid: %s", guid.GetString().c_str());
DEBUG_LOG("Flags %u, time %u", flags, time/IN_MILLISECONDS); 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; Player *plMover = mover->GetTypeId() == TYPEID_PLAYER ? (Player*)mover : NULL;
if(!plMover || !plMover->IsBeingTeleportedNear()) 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); DEBUG_LOG("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode);
recv_data.hexlike(); recv_data.hexlike();
Unit *mover = _player->m_mover; Unit *mover = _player->GetMover();
Player *plMover = mover->GetTypeId() == TYPEID_PLAYER ? (Player*)mover : NULL; Player *plMover = mover->GetTypeId() == TYPEID_PLAYER ? (Player*)mover : NULL;
// ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck // 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 // TODO: discard movement packets after the player is rooted
if(plMover->isAlive()) 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 // pl can be alive if GM/etc
if(!plMover->isAlive()) if(!plMover->isAlive())
{ {
@ -434,12 +434,13 @@ void WorldSession::HandleSetActiveMoverOpcode(WorldPacket &recv_data)
DEBUG_LOG("WORLD: Recvd CMSG_SET_ACTIVE_MOVER"); DEBUG_LOG("WORLD: Recvd CMSG_SET_ACTIVE_MOVER");
recv_data.hexlike(); recv_data.hexlike();
uint64 guid; ObjectGuid guid;
recv_data >> 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; return;
} }
} }
@ -455,9 +456,12 @@ void WorldSession::HandleMoveNotActiveMover(WorldPacket &recv_data)
recv_data >> old_mover_guid.ReadAsPacked(); recv_data >> old_mover_guid.ReadAsPacked();
recv_data >> mi; 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 recv_data.rpos(recv_data.wpos()); // prevent warnings spam
return; return;
} }

View file

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

View file

@ -1084,7 +1084,7 @@ void Object::BuildUpdateData( UpdateDataMapType& /*update_players */)
} }
WorldObject::WorldObject() 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) 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::MonsterChatBuilder say_build(*this, CHAT_MSG_MONSTER_SAY, textId,language,TargetGuid);
MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> say_do(say_build); 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)); 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::MonsterChatBuilder say_build(*this, CHAT_MSG_MONSTER_YELL, textId,language,TargetGuid);
MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> say_do(say_build); 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)); 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::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::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); Cell::VisitWorldObjects(this, say_worker, range);
} }
@ -1864,7 +1864,10 @@ void WorldObject::SetPhaseMask(uint32 newPhaseMask, bool update)
m_phaseMask = newPhaseMask; m_phaseMask = newPhaseMask;
if(update && IsInWorld()) if(update && IsInWorld())
{
UpdateObjectVisibility(); UpdateObjectVisibility();
GetViewPoint().Event_ViewPointVisibilityChanged();
}
} }
void WorldObject::PlayDistanceSound( uint32 sound_id, Player* target /*= NULL*/ ) void WorldObject::PlayDistanceSound( uint32 sound_id, Player* target /*= NULL*/ )
@ -1910,12 +1913,22 @@ struct WorldObjectChangeAccumulator
{ {
UpdateDataMapType &i_updateDatas; UpdateDataMapType &i_updateDatas;
WorldObject &i_object; WorldObject &i_object;
WorldObjectChangeAccumulator(WorldObject &obj, UpdateDataMapType &d) : i_updateDatas(d), i_object(obj) {} WorldObjectChangeAccumulator(WorldObject &obj, UpdateDataMapType &d) : i_updateDatas(d), i_object(obj)
void Visit(PlayerMapType &m)
{ {
for(PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter) // send self fields changes in another way, otherwise
if(iter->getSource()->HaveAtClient(&i_object)) // with new camera system when player's camera too far from player, camera wouldn't receive packets and changes from player
i_object.BuildUpdateDataForPlayer(iter->getSource(), i_updateDatas); 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> &) {} template<class SKIP> void Visit(GridRefManager<SKIP> &) {}

View file

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

View file

@ -25,6 +25,7 @@
#include "Corpse.h" #include "Corpse.h"
#include "World.h" #include "World.h"
#include "CellImpl.h" #include "CellImpl.h"
#include "GridDefines.h"
class MANGOS_DLL_DECL ObjectGridRespawnMover class MANGOS_DLL_DECL ObjectGridRespawnMover
{ {
@ -105,7 +106,7 @@ template<> void addUnitState(Creature *obj, CellPair const& cell_pair)
} }
template <class T> 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; BattleGround* bg = map->IsBattleGroundOrArena() ? ((BattleGroundMap*)map)->GetBG() : NULL;
@ -121,13 +122,16 @@ void LoadHelper(CellGuidSet const& guid_set, CellPair &cell, GridRefManager<T> &
continue; continue;
} }
obj->GetGridRef().link(&m, obj); grid.AddGridObject(obj);
addUnitState(obj,cell); addUnitState(obj,cell);
obj->SetMap(map); obj->SetMap(map);
obj->AddToWorld(); obj->AddToWorld();
if(obj->isActiveObject()) if(obj->isActiveObject())
map->AddToActive(obj); map->AddToActive(obj);
obj->GetViewPoint().Event_AddedToWorld(&grid);
if (bg) if (bg)
bg->OnObjectDBLoad(obj); 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()) if(cell_corpses.empty())
return; return;
@ -151,7 +155,7 @@ void LoadHelper(CellCorpseSet const& cell_corpses, CellPair &cell, CorpseMapType
if(!obj) if(!obj)
continue; continue;
obj->GetGridRef().link(&m, obj); grid.AddWorldObject(obj);
addUnitState(obj,cell); addUnitState(obj,cell);
obj->SetMap(map); 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); 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 void
@ -186,7 +191,8 @@ ObjectGridLoader::Visit(CreatureMapType &m)
CellObjectGuids const& cell_guids = sObjectMgr.GetCellObjectGuids(i_map->GetId(), i_map->GetSpawnMode(), cell_id); 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 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 // 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); 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 void

View file

@ -929,7 +929,8 @@ void ObjectMgr::LoadEquipmentTemplates()
dbcitem->InventoryType != INVTYPE_WEAPONOFFHAND && dbcitem->InventoryType != INVTYPE_WEAPONOFFHAND &&
dbcitem->InventoryType != INVTYPE_HOLDABLE && dbcitem->InventoryType != INVTYPE_HOLDABLE &&
dbcitem->InventoryType != INVTYPE_THROWN && 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); 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; 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 }, /*0x14A*/ { "SMSG_ATTACKERSTATEUPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x14B*/ { "SMSG_BATTLEFIELD_PORT_DENIED", 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 }, /*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 }, /*0x14E*/ { "SMSG_CANCEL_COMBAT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x14F*/ { "SMSG_SPELLBREAKLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, /*0x14F*/ { "SMSG_SPELLBREAKLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x150*/ { "SMSG_SPELLHEALLOG", 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 }, /*0x21B*/ { "SMSG_GMTICKET_SYSTEMSTATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x21C*/ { "CMSG_SPIRIT_HEALER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleSpiritHealerActivateOpcode}, /*0x21C*/ { "CMSG_SPIRIT_HEALER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleSpiritHealerActivateOpcode},
/*0x21D*/ { "CMSG_SET_STAT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, /*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 }, /*0x21F*/ { "CMSG_SKILL_BUY_STEP", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x220*/ { "CMSG_SKILL_BUY_RANK", STATUS_NEVER, &WorldSession::Handle_NULL }, /*0x220*/ { "CMSG_SKILL_BUY_RANK", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x221*/ { "CMSG_XP_CHEAT", 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 }, /*0x45D*/ { "CMSG_FORCE_PITCH_RATE_CHANGE_ACK", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x45E*/ { "SMSG_SPLINE_SET_PITCH_RATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, /*0x45E*/ { "SMSG_SPLINE_SET_PITCH_RATE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x45F*/ { "SMSG_MOVE_ABANDON_TRANSPORT", 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 }, /*0x460*/ { "SMSG_CALENDAR_UPDATE_INVITE_LIST", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x461*/ { "CMSG_MOVE_ABANDON_TRANSPORT_ACK", 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 }, /*0x462*/ { "CMSG_UPDATE_MISSILE_TRAJECTORY", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x463*/ { "SMSG_UPDATE_ACCOUNT_DATA_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, /*0x463*/ { "SMSG_UPDATE_ACCOUNT_DATA_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x464*/ { "SMSG_TRIGGER_MOVIE", 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 }, /*0x46E*/ { "CMSG_COMPLETE_ACHIEVEMENT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x46F*/ { "SMSG_QUESTUPDATE_ADD_PVP_KILL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, /*0x46F*/ { "SMSG_QUESTUPDATE_ADD_PVP_KILL", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x470*/ { "CMSG_SET_CRITERIA_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, /*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 }, /*0x472*/ { "CMSG_UNITANIMTIER_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x473*/ { "CMSG_CHAR_CUSTOMIZE", STATUS_AUTHED, &WorldSession::HandleCharCustomize }, /*0x473*/ { "CMSG_CHAR_CUSTOMIZE", STATUS_AUTHED, &WorldSession::HandleCharCustomize },
/*0x474*/ { "SMSG_CHAR_CUSTOMIZE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, /*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 }, /*0x4CB*/ { "UMSG_UNKNOWN_1227", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x4CC*/ { "UMSG_UNKNOWN_1228", STATUS_NEVER, &WorldSession::Handle_NULL }, /*0x4CC*/ { "UMSG_UNKNOWN_1228", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x4CD*/ { "SMSG_MULTIPLE_PACKETS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, /*0x4CD*/ { "SMSG_MULTIPLE_PACKETS", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x4CE*/ { "SMSG_UNKNOWN_1230", STATUS_NEVER, &WorldSession::Handle_ServerSide }, /*0x4CE*/ { "SMSG_FORCE_UNK1_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x4CF*/ { "CMSG_UNKNOWN_1231_ACK", STATUS_NEVER, &WorldSession::Handle_NULL }, /*0x4CF*/ { "CMSG_FORCE_UNK1_SPEED_CHANGE_ACK", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x4D0*/ { "SMSG_UNKNOWN_1232", STATUS_NEVER, &WorldSession::Handle_ServerSide }, /*0x4D0*/ { "SMSG_FORCE_UNK2_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x4D1*/ { "CMSG_UNKNOWN_1233_ACK", STATUS_NEVER, &WorldSession::Handle_NULL }, /*0x4D1*/ { "CMSG_FORCE_UNK2_SPEED_CHANGE_ACK", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x4D2*/ { "SMSG_UNKNOWN_1234", STATUS_NEVER, &WorldSession::Handle_ServerSide }, /*0x4D2*/ { "MSG_MOVE_UNKNOWN_1234", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x4D3*/ { "SMSG_UNKNOWN_1235", STATUS_NEVER, &WorldSession::Handle_ServerSide }, /*0x4D3*/ { "SMSG_SPLINE_MOVE_UNKNOWN_1235", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x4D4*/ { "SMSG_UNKNOWN_1236", 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 }, /*0x4D5*/ { "CMSG_EQUIPMENT_SET_USE", STATUS_LOGGEDIN, &WorldSession::HandleEquipmentSetUse },
/*0x4D6*/ { "SMSG_EQUIPMENT_SET_USE_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, /*0x4D6*/ { "SMSG_EQUIPMENT_SET_USE_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x4D7*/ { "UMSG_UNKNOWN_1239", STATUS_NEVER, &WorldSession::Handle_NULL }, /*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 }, /*0x4DC*/ { "UMSG_UNKNOWN_1244", STATUS_NEVER, &WorldSession::Handle_NULL },
/*0x4DD*/ { "UMSG_UNKNOWN_1245", 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 }, /*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 }, /*0x4E0*/ { "SMSG_BATTLEFIELD_MGR_ENTERED", STATUS_NEVER, &WorldSession::Handle_ServerSide },
/*0x4E1*/ { "SMSG_BATTLEFIELD_MGR_QUEUE_INVITE", 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 }, /*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 SMSG_ITEM_REFUND_RESULT = 0x4B5, // refund item result
CMSG_CORPSE_MAP_POSITION_QUERY = 0x4B6, // CMSG, uint32 CMSG_CORPSE_MAP_POSITION_QUERY = 0x4B6, // CMSG, uint32
SMSG_CORPSE_MAP_POSITION_QUERY_RESPONSE = 0x4B7, // SMSG, 3*float+float 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 UMSG_UNKNOWN_1209 = 0x4B9, // not found
CMSG_CALENDAR_CONTEXT_EVENT_SIGNUP = 0x4BA, // CMSG, uint64, lua: CalendarContextEventSignUp CMSG_CALENDAR_CONTEXT_EVENT_SIGNUP = 0x4BA, // CMSG, uint64, lua: CalendarContextEventSignUp
SMSG_CALENDAR_ACTION_PENDING = 0x4BB, // SMSG, calendar related EVENT_CALENDAR_ACTION_PENDING 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(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; newspell.active = ACT_PASSIVE;
else else
newspell.active = ACT_DISABLED; newspell.active = ACT_DISABLED;
@ -1369,7 +1369,7 @@ bool Pet::addSpell(uint32 spell_id,ActiveStates active /*= ACT_DECIDE*/, PetSpel
m_spells[spell_id] = newspell; m_spells[spell_id] = newspell;
if (IsPassiveSpell(spell_id)) if (IsPassiveSpell(spellInfo))
CastSpell(this, spell_id, true); CastSpell(this, spell_id, true);
else else
m_charmInfo->AddSpellToActionBar(spell_id, ActiveStates(newspell.active)); 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 case COMMAND_STAY: //flat=1792 //STAY
pet->StopMoving(); pet->StopMoving();
pet->GetMotionMaster()->Clear(); pet->GetMotionMaster()->Clear(false);
pet->GetMotionMaster()->MoveIdle(); pet->GetMotionMaster()->MoveIdle();
charmInfo->SetCommandState( COMMAND_STAY ); charmInfo->SetCommandState( COMMAND_STAY );
break; break;
@ -191,7 +191,7 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data )
} }
// do not cast not learned spells // do not cast not learned spells
if(!pet->HasSpell(spellid) || IsPassiveSpell(spellid)) if(!pet->HasSpell(spellid) || IsPassiveSpell(spellInfo))
return; return;
pet->clearUnitState(UNIT_STAT_MOVING); pet->clearUnitState(UNIT_STAT_MOVING);
@ -626,7 +626,7 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket )
} }
// do not cast not learned spells // do not cast not learned spells
if (!pet->HasSpell(spellid) || IsPassiveSpell(spellid)) if (!pet->HasSpell(spellid) || IsPassiveSpell(spellInfo))
return; return;
SpellCastTargets targets; SpellCastTargets targets;

View file

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

View file

@ -1128,8 +1128,6 @@ class MANGOS_DLL_SPEC Player : public Unit
Creature* GetNPCIfCanInteractWith(ObjectGuid guid, uint32 npcflagmask); Creature* GetNPCIfCanInteractWith(ObjectGuid guid, uint32 npcflagmask);
GameObject* GetGameObjectIfCanInteractWith(ObjectGuid guid, uint32 gameobject_type = MAX_GAMEOBJECT_TYPE) const; GameObject* GetGameObjectIfCanInteractWith(ObjectGuid guid, uint32 gameobject_type = MAX_GAMEOBJECT_TYPE) const;
void UpdateVisibilityForPlayer();
bool ToggleAFK(); bool ToggleAFK();
bool ToggleDND(); bool ToggleDND();
bool isAFK() const { return HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_AFK); } 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 RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent = false);
void RemoveMiniPet(); void RemoveMiniPet();
Pet* GetMiniPet(); Pet* GetMiniPet() const;
void SetMiniPet(Pet* pet) { m_miniPet = pet->GetGUID(); } void SetMiniPet(Pet* pet) { m_miniPet = pet->GetGUID(); }
template<typename Func> template<typename Func>
@ -1666,6 +1664,9 @@ class MANGOS_DLL_SPEC Player : public Unit
SpellCooldowns const& GetSpellCooldownMap() const { return m_spellCooldowns; } 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); void AddSpellMod(SpellModifier* mod, bool apply);
bool IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod, Spell const* spell = NULL); 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); 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 bool HasMovementFlag(MovementFlags f) const; // for script access to m_movementInfo.HasMovementFlag
void UpdateFallInformationIfNeed(MovementInfo const& minfo,uint16 opcode); void UpdateFallInformationIfNeed(MovementInfo const& minfo,uint16 opcode);
Unit *m_mover;
void SetFallInformation(uint32 time, float z) void SetFallInformation(uint32 time, float z)
{ {
m_lastFallTime = time; m_lastFallTime = time;
@ -2210,12 +2210,13 @@ class MANGOS_DLL_SPEC Player : public Unit
void SetClientControl(Unit* target, uint8 allowMove); void SetClientControl(Unit* target, uint8 allowMove);
void SetMover(Unit* target) { m_mover = target ? target : this; } 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 EnterVehicle(Vehicle *vehicle);
void ExitVehicle(Vehicle *vehicle); void ExitVehicle(Vehicle *vehicle);
uint64 GetFarSight() const { return GetUInt64Value(PLAYER_FARSIGHT); } ObjectGuid const& GetFarSightGuid() const { return GetGuidValue(PLAYER_FARSIGHT); }
void SetFarSightGUID(uint64 guid);
// Transports // Transports
Transport * GetTransport() const { return m_transport; } 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(); } 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 IsVisibleInGridForPlayer(Player* pl) const;
bool IsVisibleGloballyFor(Player* pl) const; bool IsVisibleGloballyFor(Player* pl) const;
@ -2262,6 +2262,8 @@ class MANGOS_DLL_SPEC Player : public Unit
// Stealth detection system // Stealth detection system
void HandleStealthedUnitsDetection(); void HandleStealthedUnitsDetection();
Camera& GetCamera() { return m_camera; }
uint8 m_forced_speed_changes[MAX_MOVE_TYPE]; uint8 m_forced_speed_changes[MAX_MOVE_TYPE];
bool HasAtLoginFlag(AtLoginFlags f) const { return m_atLoginFlags & f; } 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); } bool HasTitle(CharTitlesEntry const* title) { return HasTitle(title->bit_index); }
void SetTitle(CharTitlesEntry const* title, bool lost = false); void SetTitle(CharTitlesEntry const* title, bool lost = false);
bool isActiveObject() const { return true; }
bool canSeeSpellClickOn(Creature const* creature) const; bool canSeeSpellClickOn(Creature const* creature) const;
protected: protected:
@ -2592,17 +2593,30 @@ class MANGOS_DLL_SPEC Player : public Unit
int32 CalculateReputationGain(uint32 creatureOrQuestLevel, int32 rep, int32 faction, bool for_quest); int32 CalculateReputationGain(uint32 creatureOrQuestLevel, int32 rep, int32 faction, bool for_quest);
void AdjustQuestReqItemCount( Quest const* pQuest, QuestStatusData& questStatusData ); void AdjustQuestReqItemCount( Quest const* pQuest, QuestStatusData& questStatusData );
bool IsCanDelayTeleport() const { return m_bCanDelayTeleport; }
void SetCanDelayTeleport(bool setting) { m_bCanDelayTeleport = setting; } void SetCanDelayTeleport(bool setting) { m_bCanDelayTeleport = setting; }
bool IsHasDelayedTeleport() const { return m_bHasDelayedTeleport; } bool IsHasDelayedTeleport() const
void SetDelayedTeleportFlag(bool setting) { m_bHasDelayedTeleport = setting; } {
// 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) void ScheduleDelayedOperation(uint32 operation)
{ {
if(operation < DELAYED_END) if (operation < DELAYED_END)
m_DelayedOperations |= operation; m_DelayedOperations |= operation;
} }
Unit *m_mover;
Camera m_camera;
GridReference<Player> m_gridRef; GridReference<Player> m_gridRef;
MapReference m_mapRef; MapReference m_mapRef;
@ -2630,6 +2644,7 @@ class MANGOS_DLL_SPEC Player : public Unit
uint32 m_DelayedOperations; uint32 m_DelayedOperations;
bool m_bCanDelayTeleport; bool m_bCanDelayTeleport;
bool m_bHasDelayedTeleport; bool m_bHasDelayedTeleport;
bool m_bHasBeenAliveAtDelayedTeleport;
uint32 m_DetectInvTimer; 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 bool Player::CheckAllControlledUnits(Func const& func, bool withTotems, bool withGuardians, bool withCharms, bool withMiniPet) const
{ {
if (withMiniPet) if (withMiniPet)
if(Unit* mini = GetMiniPet()) if(Unit const* mini = GetMiniPet())
if (func(mini)) if (func(mini))
return true; return true;

View file

@ -106,6 +106,30 @@ void SpawnedPoolData::RemoveSpawn<Pool>(uint32 sub_pool_id, uint32 pool_id)
--val; --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 // Methods of template class PoolGroup
@ -134,6 +158,40 @@ bool PoolGroup<T>::CheckPool() const
return true; 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> template <class T>
PoolObject* PoolGroup<T>::RollOne(SpawnedPoolData& spawns, uint32 triggerFrom) PoolObject* PoolGroup<T>::RollOne(SpawnedPoolData& spawns, uint32 triggerFrom)
{ {
@ -146,7 +204,7 @@ PoolObject* PoolGroup<T>::RollOne(SpawnedPoolData& spawns, uint32 triggerFrom)
roll -= ExplicitlyChanced[i].chance; roll -= ExplicitlyChanced[i].chance;
// Triggering object is marked as spawned at this time and can be also rolled (respawn case) // Triggering object is marked as spawned at this time and can be also rolled (respawn case)
// so this need explicit check for this 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]; return &ExplicitlyChanced[i];
} }
} }
@ -156,7 +214,7 @@ PoolObject* PoolGroup<T>::RollOne(SpawnedPoolData& spawns, uint32 triggerFrom)
int32 index = irand(0, EqualChanced.size()-1); int32 index = irand(0, EqualChanced.size()-1);
// Triggering object is marked as spawned at this time and can be also rolled (respawn case) // Triggering object is marked as spawned at this time and can be also rolled (respawn case)
// so this need explicit check for this 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]; 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 // and also counted into m_SpawnedPoolAmount so we need increase count to be
// spawned by 1 // spawned by 1
if (triggerFrom) if (triggerFrom)
++count; {
if (spawns.IsSpawnedObject<T>(triggerFrom))
++count;
else
triggerFrom = 0;
}
// This will try to spawn the rest of pool, not guaranteed // This will try to spawn the rest of pool, not guaranteed
for (int i = 0; i < count; ++i) for (int i = 0; i < count; ++i)
@ -462,6 +525,7 @@ void PoolManager::LoadFromDB()
PoolTemplateData& pPoolTemplate = mPoolTemplate[pool_id]; PoolTemplateData& pPoolTemplate = mPoolTemplate[pool_id];
pPoolTemplate.MaxLimit = fields[1].GetUInt32(); pPoolTemplate.MaxLimit = fields[1].GetUInt32();
pPoolTemplate.AutoSpawn = true; // will update and later data loading
} while (result->NextRow()); } while (result->NextRow());
@ -661,6 +725,9 @@ void PoolManager::LoadFromDB()
SearchPair p(child_pool_id, mother_pool_id); SearchPair p(child_pool_id, mother_pool_id);
mPoolSearchMap.insert(p); mPoolSearchMap.insert(p);
// update top independent pool flag
mPoolTemplate[child_pool_id].AutoSpawn = false;
} while( result->NextRow() ); } while( result->NextRow() );
// Now check for circular reference // 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() 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;
uint32 count=0;
if (result) 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)) 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); 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); SpawnPool(pool_entry, true);
count++; count++;
} while (result->NextRow()); }
delete result;
} }
BASIC_LOG("Pool handling system initialized, %u pools spawned.", count); 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(); 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 // 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 // Here we cache only the creature/gameobject whose guid is passed as parameter
// Then the spawn pool call will use this cache to decide // Then the spawn pool call will use this cache to decide

View file

@ -27,13 +27,19 @@
struct PoolTemplateData struct PoolTemplateData
{ {
uint32 MaxLimit; uint32 MaxLimit;
bool AutoSpawn; // spawn at pool system start (not part of another pool and not part of event spawn)
}; };
struct PoolObject struct PoolObject
{ {
uint32 guid; uint32 guid;
float chance; 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 class Pool // for Pool of Pool case
@ -73,10 +79,12 @@ class PoolGroup
bool isEmpty() const { return ExplicitlyChanced.empty() && EqualChanced.empty(); } bool isEmpty() const { return ExplicitlyChanced.empty() && EqualChanced.empty(); }
void AddEntry(PoolObject& poolitem, uint32 maxentries); void AddEntry(PoolObject& poolitem, uint32 maxentries);
bool CheckPool() const; 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); PoolObject* RollOne(SpawnedPoolData& spawns, uint32 triggerFrom);
void DespawnObject(SpawnedPoolData& spawns, uint32 guid=0); void DespawnObject(SpawnedPoolData& spawns, uint32 guid=0);
void Despawn1Object(uint32 guid); void Despawn1Object(uint32 guid);
void SpawnObject(SpawnedPoolData& spawns, uint32 limit, uint32 triggerFrom, bool instantly); void SpawnObject(SpawnedPoolData& spawns, uint32 limit, uint32 triggerFrom, bool instantly);
void SetExcludeObject(uint32 guid, bool state);
void Spawn1Object(PoolObject* obj, bool instantly); void Spawn1Object(PoolObject* obj, bool instantly);
void ReSpawn1Object(PoolObject* obj); void ReSpawn1Object(PoolObject* obj);
@ -99,17 +107,37 @@ class PoolManager
template<typename T> template<typename T>
uint16 IsPartOfAPool(uint32 db_guid_or_pool_id) const; 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> template<typename T>
bool IsSpawnedObject(uint32 db_guid_or_pool_id) const { return mSpawnedData.IsSpawnedObject<T>(db_guid_or_pool_id); } 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; 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 SpawnPool(uint16 pool_id, bool instantly);
void DespawnPool(uint16 pool_id); void DespawnPool(uint16 pool_id);
template<typename T> 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: protected:
template<typename T> template<typename T>
void SpawnPoolGroup(uint16 pool_id, uint32 db_guid_or_pool_id, bool instantly); 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 // auto selection spell rank implemented in WorldSession::HandleCastSpellOpcode
// this case can be triggered if rank not found (too low-level target for first rank) // 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) // spell expected to be auto-downranking in cast handle, so must be same
{ if (m_spellInfo != sSpellMgr.SelectAuraRankForLevel(m_spellInfo, target->getLevel()))
// check only spell that apply positive auras return SPELL_FAILED_LOWLEVEL;
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;
}
}
} }
} }
else if (m_caster == target) 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) // not let players cast spells at mount (and let do it to creatures)
if (m_caster->IsMounted() && m_caster->GetTypeId()==TYPEID_PLAYER && !m_IsTriggeredSpell && 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()) if (m_caster->isInFlight())
return SPELL_FAILED_NOT_ON_TAXI; 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) // 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(); SpellCastResult castResult = CheckItems();
if(castResult != SPELL_CAST_OK) if(castResult != SPELL_CAST_OK)

View file

@ -23,11 +23,14 @@
#include "SharedDefines.h" #include "SharedDefines.h"
#include "DBCEnums.h" #include "DBCEnums.h"
#include "ObjectGuid.h" #include "ObjectGuid.h"
#include "LootMgr.h"
#include "Unit.h"
#include "Player.h"
class WorldSession; class WorldSession;
class Unit; class WorldPacket;
class DynamicObj; class DynamicObj;
class Player; class Item;
class GameObject; class GameObject;
class Group; class Group;
class Aura; class Aura;
@ -808,6 +811,7 @@ namespace MaNGOS
template<> inline void Visit(CorpseMapType & ) {} template<> inline void Visit(CorpseMapType & ) {}
template<> inline void Visit(GameObjectMapType & ) {} template<> inline void Visit(GameObjectMapType & ) {}
template<> inline void Visit(DynamicObjectMapType & ) {} template<> inline void Visit(DynamicObjectMapType & ) {}
template<> inline void Visit(CameraMapType & ) {}
#endif #endif
}; };
@ -815,6 +819,7 @@ namespace MaNGOS
template<> inline void SpellNotifierCreatureAndPlayer::Visit(CorpseMapType& ) {} template<> inline void SpellNotifierCreatureAndPlayer::Visit(CorpseMapType& ) {}
template<> inline void SpellNotifierCreatureAndPlayer::Visit(GameObjectMapType& ) {} template<> inline void SpellNotifierCreatureAndPlayer::Visit(GameObjectMapType& ) {}
template<> inline void SpellNotifierCreatureAndPlayer::Visit(DynamicObjectMapType& ) {} template<> inline void SpellNotifierCreatureAndPlayer::Visit(DynamicObjectMapType& ) {}
template<> inline void SpellNotifierCreatureAndPlayer::Visit(CameraMapType& ) {}
#endif #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_currentBasePoints = currentBasePoints ? *currentBasePoints : m_spellProto->CalculateSimpleValue(eff);
m_isPassive = IsPassiveSpell(GetId()); m_isPassive = IsPassiveSpell(GetSpellProto());
m_positive = IsPositiveEffect(GetId(), m_effIndex); m_positive = IsPositiveEffect(GetId(), m_effIndex);
m_isSingleTargetAura = IsSingleTargetSpell(m_spellProto); m_isSingleTargetAura = IsSingleTargetSpell(m_spellProto);
@ -633,7 +633,7 @@ void Aura::Update(uint32 diff)
Unit* caster = GetCaster(); Unit* caster = GetCaster();
if(!caster) if(!caster)
{ {
m_target->RemoveAura(GetId(), GetEffIndex()); m_target->RemoveAurasByCasterSpell(GetId(), GetEffIndex(), GetCasterGUID());
return; return;
} }
@ -648,7 +648,7 @@ void Aura::Update(uint32 diff)
if(!caster->IsWithinDistInMap(m_target, max_range)) if(!caster->IsWithinDistInMap(m_target, max_range))
{ {
m_target->RemoveAura(GetId(), GetEffIndex()); m_target->RemoveAurasByCasterSpell(GetId(), GetEffIndex(), GetCasterGUID());
return; return;
} }
} }
@ -813,7 +813,7 @@ void AreaAura::Update(uint32 diff)
if(!apply) if(!apply)
continue; continue;
if(SpellEntry const *actualSpellInfo = sSpellMgr.SelectAuraRankForPlayerLevel(GetSpellProto(), (*tIter)->getLevel())) if(SpellEntry const *actualSpellInfo = sSpellMgr.SelectAuraRankForLevel(GetSpellProto(), (*tIter)->getLevel()))
{ {
int32 actualBasePoints = m_currentBasePoints; int32 actualBasePoints = m_currentBasePoints;
// recalculate basepoints for lower rank (all AreaAura spell not use custom basepoints?) // 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))) (GetSpellProto()->EffectApplyAuraName[EFFECT_INDEX_0] == 1 || GetSpellProto()->EffectApplyAuraName[EFFECT_INDEX_0] == 128)))
{ {
// spells with SpellEffect=72 and aura=4: 6196, 6197, 21171, 21425 // 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); WorldPacket data(SMSG_CLEAR_FAR_SIGHT_IMMEDIATE, 0);
((Player*)target)->GetSession()->SendPacket(&data); ((Player*)target)->GetSession()->SendPacket(&data);
return; return;
@ -3543,7 +3543,11 @@ void Aura::HandleBindSight(bool apply, bool /*Real*/)
if(!caster || caster->GetTypeId() != TYPEID_PLAYER) if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
return; 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*/) void Aura::HandleFarSight(bool apply, bool /*Real*/)
@ -3552,7 +3556,11 @@ void Aura::HandleFarSight(bool apply, bool /*Real*/)
if(!caster || caster->GetTypeId() != TYPEID_PLAYER) if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
return; 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*/) void Aura::HandleAuraTrackCreatures(bool apply, bool /*Real*/)
@ -3607,10 +3615,12 @@ void Aura::HandleModPossess(bool apply, bool Real)
return; return;
Player* p_caster = (Player*)caster; Player* p_caster = (Player*)caster;
Camera& camera = p_caster->GetCamera();
if( apply ) if( apply )
{ {
target->addUnitState(UNIT_STAT_CONTROLLED);
target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED);
target->SetCharmerGUID(p_caster->GetGUID()); target->SetCharmerGUID(p_caster->GetGUID());
@ -3618,35 +3628,39 @@ void Aura::HandleModPossess(bool apply, bool Real)
p_caster->SetCharm(target); p_caster->SetCharm(target);
p_caster->SetFarSightGUID(target->GetGUID()); camera.SetView(target);
p_caster->SetClientControl(target, 1); p_caster->SetClientControl(target, 1);
p_caster->SetMover(target); p_caster->SetMover(target);
target->CombatStop(); target->CombatStop(true);
target->DeleteThreatList(); 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) if(target->GetTypeId() == TYPEID_UNIT)
{ {
target->StopMoving(); ((Creature*)target)->AIM_Initialize();
target->GetMotionMaster()->Clear();
target->GetMotionMaster()->MoveIdle();
} }
else if(target->GetTypeId() == TYPEID_PLAYER) else if(target->GetTypeId() == TYPEID_PLAYER)
{ {
((Player*)target)->SetClientControl(target, 0); ((Player*)target)->SetClientControl(target, 0);
} }
if(CharmInfo *charmInfo = target->InitCharmInfo(target))
charmInfo->InitPossessCreateSpells();
p_caster->PossessSpellInitialize();
} }
else else
{ {
p_caster->InterruptSpell(CURRENT_CHANNELED_SPELL); // the spell is not automatically canceled when interrupted, do it now p_caster->InterruptSpell(CURRENT_CHANNELED_SPELL); // the spell is not automatically canceled when interrupted, do it now
p_caster->SetCharm(NULL); p_caster->SetCharm(NULL);
p_caster->SetFarSightGUID(0); camera.ResetView();
p_caster->SetClientControl(target, 0); p_caster->SetClientControl(target, 0);
p_caster->SetMover(NULL); p_caster->SetMover(NULL);
@ -3656,6 +3670,12 @@ void Aura::HandleModPossess(bool apply, bool Real)
if(m_removeMode == AURA_REMOVE_BY_DELETE) if(m_removeMode == AURA_REMOVE_BY_DELETE)
return; return;
target->clearUnitState(UNIT_STAT_CONTROLLED);
target->CombatStop(true);
target->DeleteThreatList();
target->getHostileRefManager().deleteReferences();
target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED);
target->SetCharmerGUID(0); target->SetCharmerGUID(0);
@ -3690,30 +3710,40 @@ void Aura::HandleModPossessPet(bool apply, bool Real)
if(!caster || caster->GetTypeId() != TYPEID_PLAYER) if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
return; return;
Pet *pet = caster->GetPet(); Unit* target = GetTarget();
if(!pet || pet != GetTarget()) if (target->GetTypeId() != TYPEID_UNIT)
return; return;
Creature* pet = (Creature*)target; // not need more stricted type check
Player* p_caster = (Player*)caster; Player* p_caster = (Player*)caster;
Camera& camera = p_caster->GetCamera();
if(apply) 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)
{ {
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->StopMoving();
pet->GetMotionMaster()->Clear(); pet->GetMotionMaster()->Clear(false);
pet->GetMotionMaster()->MoveIdle(); pet->GetMotionMaster()->MoveIdle();
} }
else 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->AttackStop();
pet->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); pet->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
pet->AddSplineFlag(SPLINEFLAG_WALKMODE); pet->AddSplineFlag(SPLINEFLAG_WALKMODE);
@ -3758,8 +3788,9 @@ void Aura::HandleModCharm(bool apply, bool Real)
target->CastStop(target == caster ? GetId() : 0); target->CastStop(target == caster ? GetId() : 0);
caster->SetCharm(target); caster->SetCharm(target);
target->CombatStop(); target->CombatStop(true);
target->DeleteThreatList(); target->DeleteThreatList();
target->getHostileRefManager().deleteReferences();
if(target->GetTypeId() == TYPEID_UNIT) if(target->GetTypeId() == TYPEID_UNIT)
{ {
@ -3834,6 +3865,10 @@ void Aura::HandleModCharm(bool apply, bool Real)
if(caster->GetTypeId() == TYPEID_PLAYER) if(caster->GetTypeId() == TYPEID_PLAYER)
((Player*)caster)->RemovePetActionBar(); ((Player*)caster)->RemovePetActionBar();
target->CombatStop(true);
target->DeleteThreatList();
target->getHostileRefManager().deleteReferences();
if(target->GetTypeId() == TYPEID_UNIT) if(target->GetTypeId() == TYPEID_UNIT)
{ {
((Creature*)target)->AIM_Initialize(); ((Creature*)target)->AIM_Initialize();
@ -4182,7 +4217,7 @@ void Aura::HandleInvisibilityDetect(bool apply, bool Real)
target->m_detectInvisibilityMask |= (1 << m_modifier.m_miscvalue); target->m_detectInvisibilityMask |= (1 << m_modifier.m_miscvalue);
} }
if(Real && target->GetTypeId()==TYPEID_PLAYER) if(Real && target->GetTypeId()==TYPEID_PLAYER)
((Player*)target)->UpdateVisibilityForPlayer(); ((Player*)target)->GetCamera().UpdateVisibilityForOwner();
} }
void Aura::HandleAuraModRoot(bool apply, bool Real) void Aura::HandleAuraModRoot(bool apply, bool Real)
@ -4924,16 +4959,6 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real)
} }
break; 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: case SPELLFAMILY_DRUID:
{ {
// Rake // Rake
@ -8241,9 +8266,13 @@ void Aura::HandleAuraControlVehicle(bool apply, bool Real)
if(!Real) if(!Real)
return; return;
Unit* target = GetTarget();
if (target->GetTypeId() != TYPEID_UNIT || !((Creature*)target)->isVehicle())
return;
Vehicle* vehicle = (Vehicle*)target;
Unit *player = GetCaster(); Unit *player = GetCaster();
Vehicle *vehicle = dynamic_cast<Vehicle*>(GetTarget()); if(!player || player->GetTypeId() != TYPEID_PLAYER)
if(!player || player->GetTypeId() != TYPEID_PLAYER || !vehicle)
return; return;
if (apply) if (apply)

View file

@ -4244,7 +4244,8 @@ void Spell::EffectAddFarsight(SpellEffectIndex eff_idx)
dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x80000002); dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x80000002);
m_caster->AddDynObject(dynObj); m_caster->AddDynObject(dynObj);
m_caster->GetMap()->Add(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) void Spell::DoSummonWild(SpellEffectIndex eff_idx, uint32 forceFaction)

View file

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

View file

@ -283,6 +283,11 @@ bool IsPassiveSpell(uint32 spellId)
SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId);
if (!spellInfo) if (!spellInfo)
return false; return false;
return IsPassiveSpell(spellInfo);
}
bool IsPassiveSpell(SpellEntry const *spellInfo)
{
return (spellInfo->Attributes & SPELL_ATTR_PASSIVE) != 0; 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) bool SpellMgr::canStackSpellRanks(SpellEntry const *spellInfo)
{ {
if(IsPassiveSpell(spellInfo->Id)) // ranked passive spell if(IsPassiveSpell(spellInfo)) // ranked passive spell
return false; return false;
if(spellInfo->powerType != POWER_MANA && spellInfo->powerType != POWER_HEALTH) if(spellInfo->powerType != POWER_MANA && spellInfo->powerType != POWER_HEALTH)
return false; return false;
@ -2211,37 +2216,44 @@ bool SpellMgr::IsSkillBonusSpell(uint32 spellId) const
return false; 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 // fast case
if(IsPassiveSpell(spellInfo->Id)) if (level + 10 >= spellInfo->spellLevel)
return spellInfo;
// ignore selection for passive spells
if (IsPassiveSpell(spellInfo))
return spellInfo; return spellInfo;
bool needRankSelection = false; bool needRankSelection = false;
for(int i = 0; i < MAX_EFFECT_INDEX; ++i) for(int i = 0; i < MAX_EFFECT_INDEX; ++i)
{ {
if (IsPositiveEffect(spellInfo->Id, SpellEffectIndex(i)) && ( // for simple aura in check apply to any non caster based targets, in rank search mode to any explicit targets
spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA || 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_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; needRankSelection = true;
break; break;
} }
} }
// not required // not required (rank check more slow so check it here)
if(!needRankSelection) if (!needRankSelection || GetSpellRank(spellInfo->Id) == 0)
return spellInfo; return spellInfo;
for(uint32 nextSpellId = spellInfo->Id; nextSpellId != 0; nextSpellId = GetPrevSpellInChain(nextSpellId)) for(uint32 nextSpellId = spellInfo->Id; nextSpellId != 0; nextSpellId = GetPrevSpellInChain(nextSpellId))
{ {
SpellEntry const *nextSpellInfo = sSpellStore.LookupEntry(nextSpellId); SpellEntry const *nextSpellInfo = sSpellStore.LookupEntry(nextSpellId);
if(!nextSpellInfo) if (!nextSpellInfo)
break; break;
// if found appropriate level // if found appropriate level
if(playerLevel + 10 >= nextSpellInfo->spellLevel) if (level + 10 >= spellInfo->spellLevel)
return nextSpellInfo; return nextSpellInfo;
// one rank less then // 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, // 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) // pet teaching spells don't must be dependent learning (casted)
// other required explicit dependent learning // 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); 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]); SpellEntry const* spellEntry = sSpellStore.LookupEntry(spellDiff->spellId[difficulty]);
return spellEntry; return spellEntry;
} }

View file

@ -210,10 +210,11 @@ bool IsSingleFromSpellSpecificSpellRanksPerTarget(SpellSpecific spellSpec1,Spell
bool IsSingleFromSpellSpecificPerTarget(SpellSpecific spellSpec1,SpellSpecific spellSpec2); bool IsSingleFromSpellSpecificPerTarget(SpellSpecific spellSpec1,SpellSpecific spellSpec2);
bool IsPassiveSpell(uint32 spellId); bool IsPassiveSpell(uint32 spellId);
bool IsPassiveSpell(SpellEntry const* spellProto);
inline bool IsPassiveSpellStackableWithRanks(SpellEntry const* spellProto) inline bool IsPassiveSpellStackableWithRanks(SpellEntry const* spellProto)
{ {
if(!IsPassiveSpell(spellProto->Id)) if(!IsPassiveSpell(spellProto))
return false; return false;
return !IsSpellHaveEffect(spellProto,SPELL_EFFECT_APPLY_AURA); return !IsSpellHaveEffect(spellProto,SPELL_EFFECT_APPLY_AURA);
@ -319,6 +320,25 @@ inline bool IsPointEffectTarget( Targets target )
return false; 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 ) inline bool IsAreaEffectTarget( Targets target )
{ {
switch (target ) switch (target )
@ -371,12 +391,9 @@ inline bool IsAreaAuraEffect(uint32 effect)
inline bool IsDispelSpell(SpellEntry const *spellInfo) inline bool IsDispelSpell(SpellEntry const *spellInfo)
{ {
if (spellInfo->Effect[EFFECT_INDEX_0] == SPELL_EFFECT_DISPEL || return IsSpellHaveEffect(spellInfo, SPELL_EFFECT_DISPEL);
spellInfo->Effect[EFFECT_INDEX_1] == SPELL_EFFECT_DISPEL ||
spellInfo->Effect[EFFECT_INDEX_2] == SPELL_EFFECT_DISPEL )
return true;
return false;
} }
inline bool isSpellBreakStealth(SpellEntry const* spellInfo) inline bool isSpellBreakStealth(SpellEntry const* spellInfo)
{ {
return !(spellInfo->AttributesEx & SPELL_ATTR_EX_NOT_BREAK_STEALTH); return !(spellInfo->AttributesEx & SPELL_ATTR_EX_NOT_BREAK_STEALTH);
@ -906,7 +923,7 @@ class SpellMgr
static bool canStackSpellRanks(SpellEntry const *spellInfo); static bool canStackSpellRanks(SpellEntry const *spellInfo);
bool IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) const; 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 // Spell learning
SpellLearnSkillNode const* GetSpellLearnSkill(uint32 spell_id) const SpellLearnSkillNode const* GetSpellLearnSkill(uint32 spell_id) const
@ -1064,4 +1081,4 @@ class SpellMgr
}; };
#define sSpellMgr SpellMgr::Instance() #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)) if (owner.hasUnitState(UNIT_STAT_NOT_MOVE))
return; return;
float x, y, z;
// prevent redundant micro-movement for pets, other followers. // prevent redundant micro-movement for pets, other followers.
if (i_offset && i_target->IsWithinDistInMap(&owner,2*i_offset)) if (i_offset && i_target->IsWithinDistInMap(&owner,2*i_offset))
return; {
if (i_destinationHolder.HasDestination())
return;
float x, y, z; owner.GetPosition(x, y, z);
if (!i_offset) }
else if (!i_offset)
{ {
// to nearest contact position // to nearest contact position
i_target->GetContactPoint( &owner, x, y, z ); 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, float orientation) {}
void Relocation(float x, float y, float z) { Relocation(x, y, z, i_traveller.GetOrientation()); } 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 MoveTo(float x, float y, float z, uint32 t) {}
void Stop() {}
}; };
template<class T> template<class T>
@ -102,7 +103,13 @@ inline float Traveller<Creature>::GetMoveDestinationTo(float x, float y, float z
template<> template<>
inline void Traveller<Creature>::MoveTo(float x, float y, float z, uint32 t) 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 // 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); 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<Creature> CreatureTraveller;
typedef Traveller<Player> PlayerTraveller; typedef Traveller<Player> PlayerTraveller;
#endif #endif

View file

@ -382,12 +382,7 @@ void Unit::SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, SplineTy
break; break;
} }
data << uint32(flags); data << uint32(flags); // splineflags
// enable me if things goes wrong or looks ugly, it is however an old hack
// if(flags & SPLINEFLAG_WALKMODE)
// moveTime *= 1.05f;
data << uint32(moveTime); // Time in between points data << uint32(moveTime); // Time in between points
data << uint32(1); // 1 single waypoint data << uint32(1); // 1 single waypoint
data << NewPosX << NewPosY << NewPosZ; // the single waypoint Point B data << NewPosX << NewPosY << NewPosZ; // the single waypoint Point B
@ -4011,7 +4006,7 @@ bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur)
SpellEffectIndex effIndex = Aur->GetEffIndex(); SpellEffectIndex effIndex = Aur->GetEffIndex();
// passive spell special case (only non stackable with ranks) // passive spell special case (only non stackable with ranks)
if(IsPassiveSpell(spellId)) if(IsPassiveSpell(spellProto))
{ {
if(IsPassiveSpellStackableWithRanks(spellProto)) if(IsPassiveSpellStackableWithRanks(spellProto))
return true; return true;
@ -4034,7 +4029,7 @@ bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur)
uint32 i_spellId = i_spellProto->Id; uint32 i_spellId = i_spellProto->Id;
// early checks that spellId is passive non stackable spell // 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 // passive non-stackable spells not stackable only for same caster
if(Aur->GetCasterGUID()!=i->second->GetCasterGUID()) 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); 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 // 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); Aur->ApplyModifier(false,true);
if (Aur->_RemoveAura()) if (Aur->_RemoveAura())
@ -8549,7 +8557,7 @@ void Unit::CombatStopWithPets(bool includingCast)
struct IsAttackingPlayerHelper struct IsAttackingPlayerHelper
{ {
explicit IsAttackingPlayerHelper() {} explicit IsAttackingPlayerHelper() {}
bool operator()(Unit* unit) const { return unit->isAttackingPlayer(); } bool operator()(Unit const* unit) const { return unit->isAttackingPlayer(); }
}; };
bool Unit::isAttackingPlayer() const bool Unit::isAttackingPlayer() const
@ -8615,7 +8623,7 @@ void Unit::ModifyAuraState(AuraState flag, bool apply)
{ {
if(itr->second.state == PLAYERSPELL_REMOVED) continue; if(itr->second.state == PLAYERSPELL_REMOVED) continue;
SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first); SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
if (!spellInfo || !IsPassiveSpell(itr->first)) continue; if (!spellInfo || !IsPassiveSpell(spellInfo)) continue;
if (spellInfo->CasterAuraState == flag) if (spellInfo->CasterAuraState == flag)
CastSpell(this, itr->first, true, NULL); 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) // apply ap bonus at done part calculation only (it flat total mod so common with taken)
if (donePart && bonus->ap_bonus) 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 // Default calculation
else if (benefit) else if (benefit)
@ -9158,7 +9177,15 @@ uint32 Unit::SpellDamageBonusDone(Unit *pVictim, SpellEntry const *spellProto, u
break; break;
} }
case SPELLFAMILY_WARLOCK: case SPELLFAMILY_WARLOCK:
{
// Drain Soul
if (spellProto->SpellFamilyFlags & UI64LIT(0x0000000000004000))
{
if (pVictim->GetHealth() * 100 / pVictim->GetMaxHealth() <= 25)
DoneTotalMod *= 4;
}
break; break;
}
case SPELLFAMILY_PRIEST: case SPELLFAMILY_PRIEST:
{ {
// Glyph of Smite // Glyph of Smite
@ -10579,10 +10606,6 @@ bool Unit::isVisibleForOrDetect(Unit const* u, WorldObject const* viewPoint, boo
return false; return false;
} }
// always seen by far sight caster
if (u->GetTypeId()==TYPEID_PLAYER && ((Player*)u)->GetFarSight()==GetGUID())
return true;
// different visible distance checks // different visible distance checks
if (u->isInFlight()) // what see player in flight if (u->isInFlight()) // what see player in flight
{ {
@ -10781,12 +10804,41 @@ void Unit::SetVisibility(UnitVisibility x)
if(IsInWorld()) 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(); Map *m = GetMap();
if(GetTypeId()==TYPEID_PLAYER) if(GetTypeId()==TYPEID_PLAYER)
m->PlayerRelocation((Player*)this,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation()); m->PlayerRelocation((Player*)this,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation());
else else
m->CreatureRelocation((Creature*)this,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation()); m->CreatureRelocation((Creature*)this,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation());
GetViewPoint().Event_ViewPointVisibilityChanged();
} }
} }
@ -12039,6 +12091,7 @@ void Unit::RemoveFromWorld()
RemoveAllGameObjects(); RemoveAllGameObjects();
RemoveAllDynObjects(); RemoveAllDynObjects();
CleanupDeletedAuras(); CleanupDeletedAuras();
GetViewPoint().Event_RemovedFromWorld();
} }
Object::RemoveFromWorld(); Object::RemoveFromWorld();
@ -12740,9 +12793,13 @@ void Unit::StopMoving()
{ {
clearUnitState(UNIT_STAT_MOVING); clearUnitState(UNIT_STAT_MOVING);
// not need send any packets if not in world
if (!IsInWorld())
return;
// send explicit stop packet // send explicit stop packet
// player expected for correct work SPLINEFLAG_WALKMODE // 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 // update position and orientation for near players
WorldPacket data; WorldPacket data;
@ -13710,4 +13767,4 @@ bool Unit::CheckAndIncreaseCastCounter()
++m_castCounter; ++m_castCounter;
return true; return true;
} }

View file

@ -420,24 +420,25 @@ enum UnitState
UNIT_STAT_STUNNED = 0x00000008, // Aura::HandleAuraModStun UNIT_STAT_STUNNED = 0x00000008, // Aura::HandleAuraModStun
UNIT_STAT_ROOT = 0x00000010, // Aura::HandleAuraModRoot UNIT_STAT_ROOT = 0x00000010, // Aura::HandleAuraModRoot
UNIT_STAT_ISOLATED = 0x00000020, // area auras do not affect other players, Aura::HandleAuraModSchoolImmunity 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) // 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_IN_FLIGHT = 0x00000080, // player is in flight mode (in fact interrupted at far teleport until next map telport landing)
UNIT_STAT_DISTRACTED = 0x00000080, // DistractedMovementGenerator active UNIT_STAT_DISTRACTED = 0x00000100, // DistractedMovementGenerator active
// persistent movement generator state with non-persistent mirror states for stop support // persistent movement generator state with non-persistent mirror states for stop support
// (can be removed temporary by stop command or another movement generator apply) // (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 // 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 = 0x00000200, // ConfusedMovementGenerator active/onstack
UNIT_STAT_CONFUSED_MOVE = 0x00000200, UNIT_STAT_CONFUSED_MOVE = 0x00000400,
UNIT_STAT_ROAMING = 0x00000400, // RandomMovementGenerator/PointMovementGenerator/WaypointMovementGenerator active (now always set) UNIT_STAT_ROAMING = 0x00000800, // RandomMovementGenerator/PointMovementGenerator/WaypointMovementGenerator active (now always set)
UNIT_STAT_ROAMING_MOVE = 0x00000800, UNIT_STAT_ROAMING_MOVE = 0x00001000,
UNIT_STAT_CHASE = 0x00001000, // ChaseMovementGenerator active UNIT_STAT_CHASE = 0x00002000, // ChaseMovementGenerator active
UNIT_STAT_CHASE_MOVE = 0x00002000, UNIT_STAT_CHASE_MOVE = 0x00004000,
UNIT_STAT_FOLLOW = 0x00004000, // FollowMovementGenerator active UNIT_STAT_FOLLOW = 0x00008000, // FollowMovementGenerator active
UNIT_STAT_FOLLOW_MOVE = 0x00008000, UNIT_STAT_FOLLOW_MOVE = 0x00010000,
UNIT_STAT_FLEEING = 0x00010000, // FleeMovementGenerator/TimedFleeingMovementGenerator active/onstack UNIT_STAT_FLEEING = 0x00020000, // FleeMovementGenerator/TimedFleeingMovementGenerator active/onstack
UNIT_STAT_FLEEING_MOVE = 0x00020000, UNIT_STAT_FLEEING_MOVE = 0x00040000,
// masks (only for check) // masks (only for check)
@ -457,6 +458,12 @@ enum UnitState
UNIT_STAT_CAN_NOT_REACT = UNIT_STAT_STUNNED | UNIT_STAT_DIED | UNIT_STAT_CAN_NOT_REACT = UNIT_STAT_STUNNED | UNIT_STAT_DIED |
UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING, 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) // masks (for check or reset)
// for real move using movegen check and stop (except unstoppable flight) // 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> template<typename Func>
bool Unit::CheckAllControlledUnits(Func const& func, bool withTotems, bool withGuardians, bool withCharms) const 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)) if (func(pet))
return true; return true;
if (withGuardians) if (withGuardians)
{ {
for(GuardianPetList::const_iterator itr = m_guardianPets.begin(); itr != m_guardianPets.end(); ++itr) 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)) if (func(guardian))
return true; return true;
@ -1959,13 +1966,13 @@ bool Unit::CheckAllControlledUnits(Func const& func, bool withTotems, bool withG
if (withTotems) if (withTotems)
{ {
for (int i = 0; i < MAX_TOTEM_SLOT; ++i) 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)) if (func(totem))
return true; return true;
} }
if (withCharms) if (withCharms)
if(Unit* charm = GetCharm()) if(Unit const* charm = GetCharm())
if (func(charm)) if (func(charm))
return true; return true;

View file

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

View file

@ -171,7 +171,7 @@ bool WorldSession::Update(uint32 /*diff*/)
packet->GetOpcode()); packet->GetOpcode());
#endif*/ #endif*/
OpcodeHandler& opHandle = opcodeTable[packet->GetOpcode()]; OpcodeHandler const& opHandle = opcodeTable[packet->GetOpcode()];
try try
{ {
switch (opHandle.status) switch (opHandle.status)
@ -184,11 +184,8 @@ bool WorldSession::Update(uint32 /*diff*/)
LogUnexpectedOpcode(packet, "the player has not logged in yet"); LogUnexpectedOpcode(packet, "the player has not logged in yet");
} }
else if(_player->IsInWorld()) else if(_player->IsInWorld())
{ ExecuteOpcode(opHandle, packet);
(this->*opHandle.handler)(*packet);
if (packet->rpos() < packet->wpos() && sLog.HasLogLevelOrHigher(LOG_LVL_DEBUG))
LogUnprocessedTail(packet);
}
// lag can cause STATUS_LOGGEDIN opcodes to arrive after the player started a transfer // lag can cause STATUS_LOGGEDIN opcodes to arrive after the player started a transfer
break; break;
case STATUS_LOGGEDIN_OR_RECENTLY_LOGGEDOUT: 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"); LogUnexpectedOpcode(packet, "the player has not logged in yet and not recently logout");
} }
else else
{
// not expected _player or must checked in packet hanlder // not expected _player or must checked in packet hanlder
(this->*opHandle.handler)(*packet); ExecuteOpcode(opHandle, packet);
if (packet->rpos() < packet->wpos() && sLog.HasLogLevelOrHigher(LOG_LVL_DEBUG))
LogUnprocessedTail(packet);
}
break; break;
case STATUS_TRANSFER: case STATUS_TRANSFER:
if(!_player) if(!_player)
@ -210,11 +203,7 @@ bool WorldSession::Update(uint32 /*diff*/)
else if(_player->IsInWorld()) else if(_player->IsInWorld())
LogUnexpectedOpcode(packet, "the player is still in world"); LogUnexpectedOpcode(packet, "the player is still in world");
else else
{ ExecuteOpcode(opHandle, packet);
(this->*opHandle.handler)(*packet);
if (packet->rpos() < packet->wpos() && sLog.HasLogLevelOrHigher(LOG_LVL_DEBUG))
LogUnprocessedTail(packet);
}
break; break;
case STATUS_AUTHED: case STATUS_AUTHED:
// prevent cheating with skip queue wait // prevent cheating with skip queue wait
@ -229,9 +218,7 @@ bool WorldSession::Update(uint32 /*diff*/)
if (packet->GetOpcode() != CMSG_SET_ACTIVE_VOICE_CHANNEL) if (packet->GetOpcode() != CMSG_SET_ACTIVE_VOICE_CHANNEL)
m_playerRecentlyLogout = false; m_playerRecentlyLogout = false;
(this->*opHandle.handler)(*packet); ExecuteOpcode(opHandle, packet);
if (packet->rpos() < packet->wpos() && sLog.HasLogLevelOrHigher(LOG_LVL_DEBUG))
LogUnprocessedTail(packet);
break; break;
case STATUS_NEVER: case STATUS_NEVER:
sLog.outError( "SESSION: received not allowed opcode %s (0x%.4X)", sLog.outError( "SESSION: received not allowed opcode %s (0x%.4X)",
@ -872,3 +859,27 @@ void WorldSession::SendRedirectClient(std::string& ip, uint16 port)
SendPacket(&pkt); 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 CharacterHandler;
class GMTicket; class GMTicket;
struct OpcodeHandler;
enum AccountDataType enum AccountDataType
{ {
GLOBAL_CONFIG_CACHE = 0, // 0x01 g GLOBAL_CONFIG_CACHE = 0, // 0x01 g
@ -773,6 +775,8 @@ class MANGOS_DLL_SPEC WorldSession
// private trade methods // private trade methods
void moveItems(Item* myItems[], Item* hisItems[]); void moveItems(Item* myItems[], Item* hisItems[]);
void ExecuteOpcode( OpcodeHandler const& opHandle, WorldPacket* packet );
// logging helper // logging helper
void LogUnexpectedOpcode(WorldPacket *packet, const char * reason); void LogUnexpectedOpcode(WorldPacket *packet, const char * reason);
void LogUnprocessedTail(WorldPacket *packet); void LogUnprocessedTail(WorldPacket *packet);

View file

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

View file

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

View file

@ -22,7 +22,7 @@
#include "Common.h" #include "Common.h"
#include "Database/DatabaseEnv.h" #include "Database/DatabaseEnv.h"
#include "Config/ConfigEnv.h" #include "Config/Config.h"
#include "Log.h" #include "Log.h"
#include "Master.h" #include "Master.h"
#include "SystemConfig.h" #include "SystemConfig.h"
@ -31,6 +31,7 @@
#include <openssl/opensslv.h> #include <openssl/opensslv.h>
#include <openssl/crypto.h> #include <openssl/crypto.h>
#include <ace/Version.h> #include <ace/Version.h>
#include <ace/Get_Opt.h>
#ifdef WIN32 #ifdef WIN32
#include "ServiceWin32.h" #include "ServiceWin32.h"
@ -56,11 +57,11 @@ uint32 realmID; ///< Id of the realm
void usage(const char *prog) void usage(const char *prog)
{ {
sLog.outString("Usage: \n %s [<options>]\n" 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" " -c config_file use config_file as configuration file\n\r"
#ifdef WIN32 #ifdef WIN32
" Running as service functions:\n\r" " 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 install install service\n\r"
" -s uninstall uninstall service\n\r" " -s uninstall uninstall service\n\r"
#endif #endif
@ -75,69 +76,69 @@ extern int main(int argc, char **argv)
//char *leak = new char[1000]; // test leak detection //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; 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"); const char *mode = cmd_opts.opt_arg();
usage(argv[0]);
return 1; 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 #endif
cfg_file = argv[c]; case ':':
} sLog.outError("Runtime-Error: -%c option requires an input argument", cmd_opts.opt_opt());
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");
usage(argv[0]); usage(argv[0]);
Log::WaitBeforeContinueIfNeed(); Log::WaitBeforeContinueIfNeed();
return 1; return 1;
} default:
if( strcmp(argv[c],"install") == 0) sLog.outError("Runtime-Error: bad format of commandline arguments");
{
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]);
usage(argv[0]); usage(argv[0]);
Log::WaitBeforeContinueIfNeed(); Log::WaitBeforeContinueIfNeed();
return 1; return 1;
}
} }
if( strcmp(argv[c],"--service") == 0)
{
WinServiceRun();
}
////
#endif
++c;
} }
if (!sConfig.SetSource(cfg_file)) if (!sConfig.SetSource(cfg_file))

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -19,10 +19,11 @@
#ifndef CONFIG_H #ifndef CONFIG_H
#define CONFIG_H #define CONFIG_H
#include "Common.h"
#include <Policies/Singleton.h> #include <Policies/Singleton.h>
#include "Platform/Define.h" #include "Platform/Define.h"
class DOTCONFDocument; class ACE_Configuration_Heap;
class MANGOS_DLL_SPEC Config class MANGOS_DLL_SPEC Config
{ {
@ -31,7 +32,7 @@ class MANGOS_DLL_SPEC Config
Config(); Config();
~Config(); ~Config();
bool SetSource(const char *file, bool ignorecase = true); bool SetSource(const char *file);
bool Reload(); bool Reload();
std::string GetStringDefault(const char* name, const char* def); std::string GetStringDefault(const char* name, const char* def);
@ -44,8 +45,7 @@ class MANGOS_DLL_SPEC Config
private: private:
std::string mFilename; std::string mFilename;
bool mIgnoreCase; ACE_Configuration_Heap *mConf;
DOTCONFDocument *mConf;
}; };
#define sConfig MaNGOS::Singleton<Config>::Instance() #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 ## Sub-directories to parse
## CPP flags for includes, defines, etc. ## 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. ## Build MaNGOS shared library and its parts as convenience library.
# All libraries will be convenience libraries. Might be changed to shared # 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 noinst_LIBRARIES = libmangosconfig.a
libmangosconfig_a_SOURCES = \ libmangosconfig_a_SOURCES = \
dotconfpp/dotconfpp.cpp \
dotconfpp/dotconfpp.h \
dotconfpp/mempool.cpp \
dotconfpp/mempool.h \
Config.cpp \ Config.cpp \
Config.h \ Config.h
ConfigEnv.h
# VC++ project workspace for dotconfpp
EXTRA_DIST = \
ConfigLibrary.vcproj

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 "DatabaseEnv.h"
#include "Config/ConfigEnv.h" #include "Config/Config.h"
#include <ctime> #include <ctime>
#include <iostream> #include <iostream>

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,6 +1,6 @@
#ifndef __REVISION_SQL_H__ #ifndef __REVISION_SQL_H__
#define __REVISION_SQL_H__ #define __REVISION_SQL_H__
#define REVISION_DB_CHARACTERS "required_10051_01_characters_character_aura" #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" #define REVISION_DB_REALMD "required_10008_01_realmd_realmd_db_version"
#endif // __REVISION_SQL_H__ #endif // __REVISION_SQL_H__

View file

@ -370,6 +370,7 @@
<ClCompile Include="..\..\src\game\BattleGroundWS.cpp" /> <ClCompile Include="..\..\src\game\BattleGroundWS.cpp" />
<ClCompile Include="..\..\src\game\Calendar.cpp" /> <ClCompile Include="..\..\src\game\Calendar.cpp" />
<ClCompile Include="..\..\src\game\CalendarHandler.cpp" /> <ClCompile Include="..\..\src\game\CalendarHandler.cpp" />
<ClCompile Include="..\..\src\game\Camera.cpp" />
<ClCompile Include="..\..\src\game\Channel.cpp" /> <ClCompile Include="..\..\src\game\Channel.cpp" />
<ClCompile Include="..\..\src\game\ChannelHandler.cpp" /> <ClCompile Include="..\..\src\game\ChannelHandler.cpp" />
<ClCompile Include="..\..\src\game\ChannelMgr.cpp" /> <ClCompile Include="..\..\src\game\ChannelMgr.cpp" />
@ -517,6 +518,7 @@
<ClInclude Include="..\..\src\game\BattleGroundSA.h" /> <ClInclude Include="..\..\src\game\BattleGroundSA.h" />
<ClInclude Include="..\..\src\game\BattleGroundWS.h" /> <ClInclude Include="..\..\src\game\BattleGroundWS.h" />
<ClInclude Include="..\..\src\game\Calendar.h" /> <ClInclude Include="..\..\src\game\Calendar.h" />
<ClInclude Include="..\..\src\game\Camera.h" />
<ClInclude Include="..\..\src\game\Cell.h" /> <ClInclude Include="..\..\src\game\Cell.h" />
<ClInclude Include="..\..\src\game\CellImpl.h" /> <ClInclude Include="..\..\src\game\CellImpl.h" />
<ClInclude Include="..\..\src\game\Channel.h" /> <ClInclude Include="..\..\src\game\Channel.h" />

View file

@ -442,6 +442,9 @@
<ClCompile Include="..\..\src\game\CharacterDatabaseCleaner.cpp"> <ClCompile Include="..\..\src\game\CharacterDatabaseCleaner.cpp">
<Filter>Tool</Filter> <Filter>Tool</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\game\Camera.cpp">
<Filter>Object</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\..\src\game\AccountMgr.h"> <ClInclude Include="..\..\src\game\AccountMgr.h">
@ -832,5 +835,8 @@
<ClInclude Include="..\..\src\game\CharacterDatabaseCleaner.h"> <ClInclude Include="..\..\src\game\CharacterDatabaseCleaner.h">
<Filter>Tool</Filter> <Filter>Tool</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\game\Camera.h">
<Filter>Object</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -437,8 +437,6 @@
<ClCompile Include="..\..\src\shared\Auth\Sha1.cpp" /> <ClCompile Include="..\..\src\shared\Auth\Sha1.cpp" />
<ClCompile Include="..\..\src\shared\Common.cpp" /> <ClCompile Include="..\..\src\shared\Common.cpp" />
<ClCompile Include="..\..\src\shared\Config\Config.cpp" /> <ClCompile Include="..\..\src\shared\Config\Config.cpp" />
<ClCompile Include="..\..\src\shared\Config\dotconfpp\dotconfpp.cpp" />
<ClCompile Include="..\..\src\shared\Config\dotconfpp\mempool.cpp" />
<ClCompile Include="..\..\src\shared\Database\Database.cpp" /> <ClCompile Include="..\..\src\shared\Database\Database.cpp" />
<ClCompile Include="..\..\src\shared\Database\DatabaseMysql.cpp" /> <ClCompile Include="..\..\src\shared\Database\DatabaseMysql.cpp" />
<ClCompile Include="..\..\src\shared\Database\DBCFileLoader.cpp" /> <ClCompile Include="..\..\src\shared\Database\DBCFileLoader.cpp" />
@ -475,9 +473,6 @@
<ClInclude Include="..\..\src\shared\WorldPacket.h" /> <ClInclude Include="..\..\src\shared\WorldPacket.h" />
<ClInclude Include="..\..\src\shared\Common.h" /> <ClInclude Include="..\..\src\shared\Common.h" />
<ClInclude Include="..\..\src\shared\Config\Config.h" /> <ClInclude Include="..\..\src\shared\Config\Config.h" />
<ClInclude Include="..\..\src\shared\Config\ConfigEnv.h" />
<ClInclude Include="..\..\src\shared\Config\dotconfpp\dotconfpp.h" />
<ClInclude Include="..\..\src\shared\Config\dotconfpp\mempool.h" />
<ClInclude Include="..\..\src\shared\Database\Database.h" /> <ClInclude Include="..\..\src\shared\Database\Database.h" />
<ClInclude Include="..\..\src\shared\Database\DatabaseEnv.h" /> <ClInclude Include="..\..\src\shared\Database\DatabaseEnv.h" />
<ClInclude Include="..\..\src\shared\Database\DatabaseImpl.h" /> <ClInclude Include="..\..\src\shared\Database\DatabaseImpl.h" />

View file

@ -16,9 +16,6 @@
<Filter Include="Config"> <Filter Include="Config">
<UniqueIdentifier>{adb98dec-d22a-40b3-84be-51eaf2974a15}</UniqueIdentifier> <UniqueIdentifier>{adb98dec-d22a-40b3-84be-51eaf2974a15}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="Config\dotconfpp">
<UniqueIdentifier>{dff0e90b-cab5-4d0b-bd5d-3cacbb638630}</UniqueIdentifier>
</Filter>
<Filter Include="Auth"> <Filter Include="Auth">
<UniqueIdentifier>{e35fd108-bd39-46ae-83f9-09cf1ebf4ea8}</UniqueIdentifier> <UniqueIdentifier>{e35fd108-bd39-46ae-83f9-09cf1ebf4ea8}</UniqueIdentifier>
</Filter> </Filter>
@ -66,12 +63,6 @@
<ClCompile Include="..\..\src\shared\Config\Config.cpp"> <ClCompile Include="..\..\src\shared\Config\Config.cpp">
<Filter>Config</Filter> <Filter>Config</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\shared\Config\dotconfpp\dotconfpp.cpp">
<Filter>Config\dotconfpp</Filter>
</ClCompile>
<ClCompile Include="..\..\src\shared\Config\dotconfpp\mempool.cpp">
<Filter>Config\dotconfpp</Filter>
</ClCompile>
<ClCompile Include="..\..\src\shared\Auth\AuthCrypt.cpp"> <ClCompile Include="..\..\src\shared\Auth\AuthCrypt.cpp">
<Filter>Auth</Filter> <Filter>Auth</Filter>
</ClCompile> </ClCompile>
@ -194,15 +185,6 @@
<ClInclude Include="..\..\src\shared\Config\Config.h"> <ClInclude Include="..\..\src\shared\Config\Config.h">
<Filter>Config</Filter> <Filter>Config</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\shared\Config\ConfigEnv.h">
<Filter>Config</Filter>
</ClInclude>
<ClInclude Include="..\..\src\shared\Config\dotconfpp\dotconfpp.h">
<Filter>Config\dotconfpp</Filter>
</ClInclude>
<ClInclude Include="..\..\src\shared\Config\dotconfpp\mempool.h">
<Filter>Config\dotconfpp</Filter>
</ClInclude>
<ClInclude Include="..\..\src\shared\Auth\AuthCrypt.h"> <ClInclude Include="..\..\src\shared\Auth\AuthCrypt.h">
<Filter>Auth</Filter> <Filter>Auth</Filter>
</ClInclude> </ClInclude>

View file

@ -669,6 +669,14 @@
RelativePath="..\..\src\game\CalendarHandler.cpp" RelativePath="..\..\src\game\CalendarHandler.cpp"
> >
</File> </File>
<File
RelativePath="..\..\src\game\Camera.cpp"
>
</File>
<File
RelativePath="..\..\src\game\Camera.h"
>
</File>
<File <File
RelativePath="..\..\src\game\Cell.h" RelativePath="..\..\src\game\Cell.h"
> >

View file

@ -672,30 +672,6 @@
RelativePath="..\..\src\shared\Config\Config.h" RelativePath="..\..\src\shared\Config\Config.h"
> >
</File> </File>
<File
RelativePath="..\..\src\shared\Config\ConfigEnv.h"
>
</File>
<Filter
Name="dotconfpp"
>
<File
RelativePath="..\..\src\shared\Config\dotconfpp\dotconfpp.cpp"
>
</File>
<File
RelativePath="..\..\src\shared\Config\dotconfpp\dotconfpp.h"
>
</File>
<File
RelativePath="..\..\src\shared\Config\dotconfpp\mempool.cpp"
>
</File>
<File
RelativePath="..\..\src\shared\Config\dotconfpp\mempool.h"
>
</File>
</Filter>
</Filter> </Filter>
<Filter <Filter
Name="Auth" Name="Auth"

View file

@ -1162,6 +1162,14 @@
RelativePath="..\..\src\game\Calendar.h" RelativePath="..\..\src\game\Calendar.h"
> >
</File> </File>
<File
RelativePath="..\..\src\game\Camera.cpp"
>
</File>
<File
RelativePath="..\..\src\game\Camera.h"
>
</File>
<File <File
RelativePath="..\..\src\game\Corpse.cpp" RelativePath="..\..\src\game\Corpse.cpp"
> >

Some files were not shown because too many files have changed in this diff Show more