[svn] * Reimplemented packet/update forwarding in more generic way
* Implemented far sight spells (Far Sight, Eagle Eye, etc) at unlimited range and properly forward packets * Implemented bind vision spells (Mind Vision, etc) to forward packets at unlimited distance * Implemented Sentry Totem (both vision switching/forwarding and alerting) * Other misc possession fixes * Added .bindsight and .unbindsight commands Please test out the above spells (including Mind Control) and report any issues on the forums. --HG-- branch : trunk
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
DELETE FROM `command` WHERE name IN ('bindsight', 'unbindsight');
|
||||
INSERT INTO `command` (name,security,help) VALUES
|
||||
('bindsight',3,'Syntax: .bindsight\r\n\r\nBinds vision to the selected unit indefinitely. Cannot be used while currently possessing a target.'),
|
||||
('unbindsight',3,'Syntax: .unbindsight\r\n\r\nRemoves bound vision. Cannot be used while currently possessing a target.');
|
||||
@@ -565,6 +565,8 @@ ChatCommand * ChatHandler::getCommandTable()
|
||||
{ "flusharenapoints", SEC_ADMINISTRATOR, false, &ChatHandler::HandleFlushArenaPointsCommand, "", NULL },
|
||||
{ "possess", SEC_ADMINISTRATOR, false, &ChatHandler::HandlePossessCommand, "", NULL },
|
||||
{ "unpossess", SEC_ADMINISTRATOR, false, &ChatHandler::HandleUnPossessCommand, "", NULL },
|
||||
{ "bindsight", SEC_ADMINISTRATOR, false, &ChatHandler::HandleBindSightCommand, "", NULL },
|
||||
{ "unbindsight", SEC_ADMINISTRATOR, false, &ChatHandler::HandleUnbindSightCommand, "", NULL },
|
||||
|
||||
{ NULL, 0, false, NULL, "", NULL }
|
||||
};
|
||||
|
||||
@@ -453,6 +453,8 @@ class ChatHandler
|
||||
bool HandleDebugHostilRefList(const char * args);
|
||||
bool HandlePossessCommand(const char* args);
|
||||
bool HandleUnPossessCommand(const char* args);
|
||||
bool HandleBindSightCommand(const char* args);
|
||||
bool HandleUnbindSightCommand(const char* args);
|
||||
|
||||
Player* getSelectedPlayer();
|
||||
Creature* getSelectedCreature();
|
||||
|
||||
@@ -136,6 +136,9 @@ void DynamicObject::Update(uint32 p_time)
|
||||
|
||||
void DynamicObject::Delete()
|
||||
{
|
||||
// Make sure the object is back to grid container for removal as farsight targets
|
||||
// are switched to world container on creation
|
||||
GetMap()->SwitchGridContainers(this, false);
|
||||
SendObjectDeSpawnAnim(GetGUID());
|
||||
AddObjectToRemoveList();
|
||||
}
|
||||
@@ -150,5 +153,5 @@ void DynamicObject::Delay(int32 delaytime)
|
||||
|
||||
bool DynamicObject::isVisibleForInState(Player const* u, bool inVisibleList) const
|
||||
{
|
||||
return IsInWorld() && u->IsInWorld() && IsWithinDistInMap(u,World::GetMaxVisibleDistanceForObject()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f));
|
||||
return IsInWorld() && u->IsInWorld() /*&& IsWithinDistInMap(u,World::GetMaxVisibleDistanceForObject()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f))*/;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ class Player;
|
||||
#define MAP_HALFSIZE (MAP_SIZE/2)
|
||||
|
||||
// Creature used instead pet to simplify *::Visit templates (not required duplicate code for Creature->Pet case)
|
||||
typedef TYPELIST_3(Player, Creature/*pets*/, Corpse/*resurrectable*/) AllWorldObjectTypes;
|
||||
typedef TYPELIST_4(Player, Creature/*pets*/, Corpse/*resurrectable*/, DynamicObject/*farsight target*/) AllWorldObjectTypes;
|
||||
typedef TYPELIST_4(GameObject, Creature/*except pets*/, DynamicObject, Corpse/*Bones*/) AllGridObjectTypes;
|
||||
|
||||
typedef GridRefManager<Corpse> CorpseMapType;
|
||||
|
||||
+42
-12
@@ -40,8 +40,10 @@ Trinity::PlayerNotifier::Visit(PlayerMapType &m)
|
||||
|
||||
iter->getSource()->UpdateVisibilityOf(&i_player);
|
||||
i_player.UpdateVisibilityOf(iter->getSource());
|
||||
if (i_player.isPossessedByPlayer())
|
||||
((Player*)i_player.GetCharmer())->UpdateVisibilityOf(iter->getSource());
|
||||
|
||||
if (!i_player.GetSharedVisionList().empty())
|
||||
for (SharedVisionList::const_iterator it = i_player.GetSharedVisionList().begin(); it != i_player.GetSharedVisionList().end(); ++it)
|
||||
(*it)->UpdateVisibilityOf(iter->getSource());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,9 +150,14 @@ Deliverer::Visit(PlayerMapType &m)
|
||||
{
|
||||
if (!i_dist || iter->getSource()->GetDistance(&i_source) <= i_dist)
|
||||
{
|
||||
// Send packet to possessor
|
||||
if (iter->getSource()->isPossessedByPlayer())
|
||||
SendPacket((Player*)iter->getSource()->GetCharmer());
|
||||
// Send packet to all who are sharing the player's vision
|
||||
if (!iter->getSource()->GetSharedVisionList().empty())
|
||||
{
|
||||
SharedVisionList::const_iterator it = iter->getSource()->GetSharedVisionList().begin();
|
||||
for ( ; it != iter->getSource()->GetSharedVisionList().end(); ++it)
|
||||
SendPacket(*it);
|
||||
}
|
||||
|
||||
VisitObject(iter->getSource());
|
||||
}
|
||||
}
|
||||
@@ -163,9 +170,29 @@ Deliverer::Visit(CreatureMapType &m)
|
||||
{
|
||||
if (!i_dist || iter->getSource()->GetDistance(&i_source) <= i_dist)
|
||||
{
|
||||
// Send packet to possessor
|
||||
if (iter->getSource()->isPossessedByPlayer())
|
||||
SendPacket((Player*)iter->getSource()->GetCharmer());
|
||||
// Send packet to all who are sharing the creature's vision
|
||||
if (!iter->getSource()->GetSharedVisionList().empty())
|
||||
{
|
||||
SharedVisionList::const_iterator it = iter->getSource()->GetSharedVisionList().begin();
|
||||
for ( ; it != iter->getSource()->GetSharedVisionList().end(); ++it)
|
||||
SendPacket(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Deliverer::Visit(DynamicObjectMapType &m)
|
||||
{
|
||||
for (DynamicObjectMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
|
||||
{
|
||||
if (IS_PLAYER_GUID(iter->getSource()->GetCasterGUID()))
|
||||
{
|
||||
// Send packet back to the caster if the caster has vision of dynamic object
|
||||
Player* caster = (Player*)iter->getSource()->GetCaster();
|
||||
if (caster->GetUInt64Value(PLAYER_FARSIGHT) == iter->getSource()->GetGUID() &&
|
||||
(!i_dist || iter->getSource()->GetDistance(&i_source) <= i_dist))
|
||||
SendPacket(caster);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -175,6 +202,11 @@ Deliverer::SendPacket(Player* plr)
|
||||
{
|
||||
if (!plr)
|
||||
return;
|
||||
|
||||
// Don't send the packet to self if not supposed to
|
||||
if (!i_toSelf && plr == &i_source)
|
||||
return;
|
||||
|
||||
// Don't send the packet to possesor if not supposed to
|
||||
if (!i_toPossessor && plr->isPossessing() && plr->GetCharmGUID() == i_source.GetGUID())
|
||||
return;
|
||||
@@ -190,15 +222,13 @@ Deliverer::SendPacket(Player* plr)
|
||||
void
|
||||
MessageDeliverer::VisitObject(Player* plr)
|
||||
{
|
||||
if (i_toSelf || plr != &i_source)
|
||||
SendPacket(plr);
|
||||
SendPacket(plr);
|
||||
}
|
||||
|
||||
void
|
||||
MessageDistDeliverer::VisitObject(Player* plr)
|
||||
{
|
||||
if( (i_toSelf || plr != &i_source ) &&
|
||||
(!i_ownTeamOnly || (i_source.GetTypeId() == TYPEID_PLAYER && plr->GetTeam() == ((Player&)i_source).GetTeam())) )
|
||||
if( !i_ownTeamOnly || (i_source.GetTypeId() == TYPEID_PLAYER && plr->GetTeam() == ((Player&)i_source).GetTeam()) )
|
||||
{
|
||||
SendPacket(plr);
|
||||
}
|
||||
|
||||
@@ -95,10 +95,12 @@ namespace Trinity
|
||||
WorldPacket *i_message;
|
||||
std::set<uint64> plr_list;
|
||||
bool i_toPossessor;
|
||||
bool i_toSelf;
|
||||
float i_dist;
|
||||
Deliverer(WorldObject &src, WorldPacket *msg, bool to_possessor, float dist = 0.0f) : i_source(src), i_message(msg), i_toPossessor(to_possessor), i_dist(dist) {}
|
||||
Deliverer(WorldObject &src, WorldPacket *msg, bool to_possessor, bool to_self, float dist = 0.0f) : i_source(src), i_message(msg), i_toPossessor(to_possessor), i_toSelf(to_self), i_dist(dist) {}
|
||||
void Visit(PlayerMapType &m);
|
||||
void Visit(CreatureMapType &m);
|
||||
void Visit(DynamicObjectMapType &m);
|
||||
virtual void VisitObject(Player* plr) = 0;
|
||||
void SendPacket(Player* plr);
|
||||
template<class SKIP> void Visit(GridRefManager<SKIP> &) {}
|
||||
@@ -106,28 +108,26 @@ namespace Trinity
|
||||
|
||||
struct TRINITY_DLL_DECL MessageDeliverer : public Deliverer
|
||||
{
|
||||
bool i_toSelf;
|
||||
MessageDeliverer(Player &pl, WorldPacket *msg, bool to_possessor, bool to_self) : Deliverer(pl, msg, to_possessor), i_toSelf(to_self) {}
|
||||
MessageDeliverer(Player &pl, WorldPacket *msg, bool to_possessor, bool to_self) : Deliverer(pl, msg, to_possessor, to_self) {}
|
||||
void VisitObject(Player* plr);
|
||||
};
|
||||
|
||||
struct TRINITY_DLL_DECL ObjectMessageDeliverer : public Deliverer
|
||||
{
|
||||
explicit ObjectMessageDeliverer(WorldObject &src, WorldPacket *msg, bool to_possessor) : Deliverer(src, msg, to_possessor) {}
|
||||
explicit ObjectMessageDeliverer(WorldObject &src, WorldPacket *msg, bool to_possessor) : Deliverer(src, msg, to_possessor, false) {}
|
||||
void VisitObject(Player* plr) { SendPacket(plr); }
|
||||
};
|
||||
|
||||
struct TRINITY_DLL_DECL MessageDistDeliverer : public Deliverer
|
||||
{
|
||||
bool i_toSelf;
|
||||
bool i_ownTeamOnly;
|
||||
MessageDistDeliverer(Player &pl, WorldPacket *msg, bool to_possessor, float dist, bool to_self, bool ownTeamOnly) : Deliverer(pl, msg, to_possessor, dist), i_toSelf(to_self), i_ownTeamOnly(ownTeamOnly) {}
|
||||
MessageDistDeliverer(Player &pl, WorldPacket *msg, bool to_possessor, float dist, bool to_self, bool ownTeamOnly) : Deliverer(pl, msg, to_possessor, to_self, dist), i_ownTeamOnly(ownTeamOnly) {}
|
||||
void VisitObject(Player* plr);
|
||||
};
|
||||
|
||||
struct TRINITY_DLL_DECL ObjectMessageDistDeliverer : public Deliverer
|
||||
{
|
||||
ObjectMessageDistDeliverer(WorldObject &obj, WorldPacket *msg, bool to_possessor, float dist) : Deliverer(obj, msg, to_possessor, dist) {}
|
||||
ObjectMessageDistDeliverer(WorldObject &obj, WorldPacket *msg, bool to_possessor, float dist) : Deliverer(obj, msg, to_possessor, false, dist) {}
|
||||
void VisitObject(Player* plr) { SendPacket(plr); }
|
||||
};
|
||||
|
||||
|
||||
@@ -6815,3 +6815,26 @@ bool ChatHandler::HandleUnPossessCommand(const char* args)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChatHandler::HandleBindSightCommand(const char* args)
|
||||
{
|
||||
Unit* pUnit = getSelectedUnit();
|
||||
if (!pUnit)
|
||||
return false;
|
||||
|
||||
if (m_session->GetPlayer()->isPossessing())
|
||||
return false;
|
||||
|
||||
pUnit->AddPlayerToVision(m_session->GetPlayer());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChatHandler::HandleUnbindSightCommand(const char* args)
|
||||
{
|
||||
if (m_session->GetPlayer()->isPossessing())
|
||||
return false;
|
||||
|
||||
m_session->GetPlayer()->RemoveFarsightTarget();
|
||||
return true;
|
||||
}
|
||||
|
||||
+13
-5
@@ -315,21 +315,29 @@ void Map::SwitchGridContainers(T* obj, bool active)
|
||||
{
|
||||
CellPair pair = Trinity::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY());
|
||||
Cell cell(pair);
|
||||
NGridType *grid = getNGrid(cell.GridX(), cell.GridY());
|
||||
NGridType *ngrid = getNGrid(cell.GridX(), cell.GridY());
|
||||
GridType &grid = (*ngrid)(cell.CellX(), cell.CellY());
|
||||
|
||||
if (active)
|
||||
{
|
||||
(*grid)(cell.CellX(), cell.CellY()).RemoveGridObject<T>(obj, obj->GetGUID());
|
||||
(*grid)(cell.CellX(), cell.CellY()).AddWorldObject<T>(obj, obj->GetGUID());
|
||||
if (!grid.GetWorldObject(obj->GetGUID(), obj))
|
||||
{
|
||||
grid.RemoveGridObject<T>(obj, obj->GetGUID());
|
||||
grid.AddWorldObject<T>(obj, obj->GetGUID());
|
||||
}
|
||||
} else
|
||||
{
|
||||
(*grid)(cell.CellX(), cell.CellY()).RemoveWorldObject<T>(obj, obj->GetGUID());
|
||||
(*grid)(cell.CellX(), cell.CellY()).AddGridObject<T>(obj, obj->GetGUID());
|
||||
if (!grid.GetGridObject(obj->GetGUID(), obj))
|
||||
{
|
||||
grid.RemoveWorldObject<T>(obj, obj->GetGUID());
|
||||
grid.AddGridObject<T>(obj, obj->GetGUID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template void Map::SwitchGridContainers(Creature *, bool);
|
||||
template void Map::SwitchGridContainers(Corpse *, bool);
|
||||
template void Map::SwitchGridContainers(DynamicObject *, bool);
|
||||
|
||||
template<class T>
|
||||
void Map::DeleteFromWorld(T* obj)
|
||||
|
||||
@@ -1391,21 +1391,33 @@ void WorldSession::HandleFarSightOpcode( WorldPacket & recv_data )
|
||||
sLog.outDebug("WORLD: CMSG_FAR_SIGHT");
|
||||
//recv_data.hexlike();
|
||||
|
||||
uint8 unk;
|
||||
recv_data >> unk;
|
||||
uint8 apply;
|
||||
recv_data >> apply;
|
||||
|
||||
switch(unk)
|
||||
CellPair pair;
|
||||
|
||||
switch(apply)
|
||||
{
|
||||
case 0:
|
||||
//WorldPacket data(SMSG_CLEAR_FAR_SIGHT_IMMEDIATE, 0)
|
||||
//SendPacket(&data);
|
||||
//_player->SetUInt64Value(PLAYER_FARSIGHT, 0);
|
||||
sLog.outDebug("Removed FarSight from player %u", _player->GetGUIDLow());
|
||||
_player->SetFarsightVision(false);
|
||||
pair = Trinity::ComputeCellPair(_player->GetPositionX(), _player->GetPositionY());
|
||||
sLog.outDebug("Player %u set vision to himself", _player->GetGUIDLow());
|
||||
break;
|
||||
case 1:
|
||||
sLog.outDebug("Added FarSight " I64FMTD " to player %u", _player->GetUInt64Value(PLAYER_FARSIGHT), _player->GetGUIDLow());
|
||||
_player->SetFarsightVision(true);
|
||||
if (WorldObject* obj = _player->GetFarsightTarget())
|
||||
pair = Trinity::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY());
|
||||
else
|
||||
return;
|
||||
sLog.outDebug("Player %u set vision to farsight target " I64FMTD ".", _player->GetGUIDLow(), _player->GetUInt64Value(PLAYER_FARSIGHT));
|
||||
break;
|
||||
default:
|
||||
sLog.outDebug("Unhandled mode in CMSG_FAR_SIGHT: %u", apply);
|
||||
return;
|
||||
}
|
||||
// Update visibility after vision change
|
||||
Cell cell(pair);
|
||||
GetPlayer()->GetMap()->UpdateObjectsVisibilityFor(_player, cell, pair);
|
||||
}
|
||||
|
||||
void WorldSession::HandleChooseTitleOpcode( WorldPacket & recv_data )
|
||||
|
||||
@@ -624,8 +624,12 @@ ObjectAccessor::WorldObjectChangeAccumulator::Visit(PlayerMapType &m)
|
||||
for(PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
|
||||
{
|
||||
BuildPacket(iter->getSource());
|
||||
if (iter->getSource()->isPossessedByPlayer())
|
||||
BuildPacket((Player*)iter->getSource()->GetCharmer());
|
||||
if (!iter->getSource()->GetSharedVisionList().empty())
|
||||
{
|
||||
SharedVisionList::const_iterator it = iter->getSource()->GetSharedVisionList().begin();
|
||||
for ( ; it != iter->getSource()->GetSharedVisionList().end(); ++it)
|
||||
BuildPacket(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -633,8 +637,28 @@ void
|
||||
ObjectAccessor::WorldObjectChangeAccumulator::Visit(CreatureMapType &m)
|
||||
{
|
||||
for(CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
|
||||
if (iter->getSource()->isPossessedByPlayer())
|
||||
BuildPacket((Player*)iter->getSource()->GetCharmer());
|
||||
{
|
||||
if (!iter->getSource()->GetSharedVisionList().empty())
|
||||
{
|
||||
SharedVisionList::const_iterator it = iter->getSource()->GetSharedVisionList().begin();
|
||||
for ( ; it != iter->getSource()->GetSharedVisionList().end(); ++it)
|
||||
BuildPacket(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ObjectAccessor::WorldObjectChangeAccumulator::Visit(DynamicObjectMapType &m)
|
||||
{
|
||||
for(DynamicObjectMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
|
||||
{
|
||||
if (IS_PLAYER_GUID(iter->getSource()->GetCasterGUID()))
|
||||
{
|
||||
Player* caster = (Player*)iter->getSource()->GetCaster();
|
||||
if (caster->GetUInt64Value(PLAYER_FARSIGHT) == iter->getSource()->GetGUID())
|
||||
BuildPacket(caster);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -212,6 +212,7 @@ class TRINITY_DLL_DECL ObjectAccessor : public Trinity::Singleton<ObjectAccessor
|
||||
WorldObjectChangeAccumulator(WorldObject &obj, UpdateDataMapType &d) : i_updateDatas(d), i_object(obj) {}
|
||||
void Visit(PlayerMapType &);
|
||||
void Visit(CreatureMapType &);
|
||||
void Visit(DynamicObjectMapType &);
|
||||
void BuildPacket(Player* plr);
|
||||
template<class SKIP> void Visit(GridRefManager<SKIP> &) {}
|
||||
};
|
||||
|
||||
+67
-15
@@ -427,6 +427,8 @@ Player::Player (WorldSession *session): Unit()
|
||||
m_declinedname = NULL;
|
||||
|
||||
m_isActive = true;
|
||||
|
||||
m_farsightVision = false;
|
||||
}
|
||||
|
||||
Player::~Player ()
|
||||
@@ -1291,6 +1293,12 @@ void Player::setDeathState(DeathState s)
|
||||
RemoveMiniPet();
|
||||
RemoveGuardians();
|
||||
|
||||
// remove possession
|
||||
if(isPossessing())
|
||||
RemovePossess(false);
|
||||
else
|
||||
RemoveFarsightTarget();
|
||||
|
||||
// save value before aura remove in Unit::setDeathState
|
||||
ressSpellId = GetUInt32Value(PLAYER_SELF_RES_SPELL);
|
||||
|
||||
@@ -1544,7 +1552,15 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
|
||||
if (isPossessedByPlayer())
|
||||
((Player*)GetCharmer())->RemovePossess();
|
||||
|
||||
// The player was ported to another map and looses the duel immediately.
|
||||
// Remove player's possession before teleporting
|
||||
if (isPossessing())
|
||||
RemovePossess(false);
|
||||
|
||||
// Empty vision list and clear farsight (if it hasn't already been cleared by RemovePossess) before teleporting
|
||||
RemoveAllFromVision();
|
||||
RemoveFarsightTarget();
|
||||
|
||||
// The player was ported to another map and looses the duel immediatly.
|
||||
// We have to perform this check before the teleport, otherwise the
|
||||
// ObjectAccessor won't find the flag.
|
||||
if (duel && GetMapId()!=mapid)
|
||||
@@ -1762,6 +1778,7 @@ void Player::RemoveFromWorld()
|
||||
UnsummonAllTotems();
|
||||
RemoveMiniPet();
|
||||
RemoveGuardians();
|
||||
RemoveFarsightTarget();
|
||||
}
|
||||
|
||||
for(int i = PLAYER_SLOT_START; i < PLAYER_SLOT_END; i++)
|
||||
@@ -17293,8 +17310,10 @@ bool Player::canSeeOrDetect(Unit const* u, bool detect, bool inVisibleList) cons
|
||||
if(!u->IsVisibleInGridForPlayer(this))
|
||||
return false;
|
||||
|
||||
// If the player is currently possessing, update visibility from the possessed unit's location
|
||||
const Unit* target = isPossessing() ? GetCharm() : this;
|
||||
// If the player is currently channeling vision, update visibility from the target unit's location
|
||||
const WorldObject* target = GetFarsightTarget();
|
||||
if (!target || !HasFarsightVision()) // Vision needs to be on the farsight target
|
||||
target = this;
|
||||
|
||||
// different visible distance checks
|
||||
if(isInFlight()) // what see player in flight
|
||||
@@ -18743,20 +18762,17 @@ void Player::Possess(Unit *target)
|
||||
// Update the proper unit fields
|
||||
SetPossessedTarget(target);
|
||||
|
||||
// Start channeling packets to possessor
|
||||
target->AddPlayerToVision(this);
|
||||
|
||||
target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, getFaction());
|
||||
target->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE);
|
||||
target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5);
|
||||
target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
|
||||
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
|
||||
SetUInt64Value(PLAYER_FARSIGHT, target->GetGUID());
|
||||
|
||||
if(target->GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
// Set target to active in the grid and place it in the world container to be picked up by all regular player cell visits
|
||||
Map* map = target->GetMap();
|
||||
map->SwitchGridContainers((Creature*)target, true);
|
||||
target->setActive(true);
|
||||
|
||||
((Creature*)target)->InitPossessedAI(); // Initialize the possessed AI
|
||||
target->StopMoving();
|
||||
target->GetMotionMaster()->Clear(false);
|
||||
@@ -18809,15 +18825,13 @@ void Player::RemovePossess(bool attack)
|
||||
|
||||
RemovePossessedTarget();
|
||||
|
||||
// Stop channeling packets back to possessor
|
||||
target->RemovePlayerFromVision(this);
|
||||
|
||||
if(target->GetTypeId() == TYPEID_PLAYER)
|
||||
((Player*)target)->setFactionForRace(target->getRace());
|
||||
else if(target->GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
// Set creature to inactive in grid and place it back into the grid container
|
||||
Map* map = target->GetMap();
|
||||
target->setActive(false);
|
||||
map->SwitchGridContainers((Creature*)target, false);
|
||||
|
||||
if(((Creature*)target)->isPet())
|
||||
{
|
||||
if(Unit* owner = target->GetOwner())
|
||||
@@ -18831,7 +18845,6 @@ void Player::RemovePossess(bool attack)
|
||||
|
||||
target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5);
|
||||
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
|
||||
SetUInt64Value(PLAYER_FARSIGHT, 0);
|
||||
|
||||
// Remove pet spell action bar
|
||||
WorldPacket data(SMSG_PET_SPELLS, 8);
|
||||
@@ -18897,6 +18910,45 @@ void Player::SetViewport(uint64 guid, bool moveable)
|
||||
sLog.outDetail("Viewport for "I64FMT" (%s) changed to "I64FMT, GetGUID(), GetName(), guid);
|
||||
}
|
||||
|
||||
WorldObject* Player::GetFarsightTarget() const
|
||||
{
|
||||
// Players can have in farsight field another player's guid, a creature's guid, or a dynamic object's guid
|
||||
if (uint64 guid = GetUInt64Value(PLAYER_FARSIGHT))
|
||||
return (WorldObject*)ObjectAccessor::GetObjectByTypeMask(*this, guid, TYPEMASK_PLAYER | TYPEMASK_UNIT | TYPEMASK_DYNAMICOBJECT);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Player::RemoveFarsightTarget()
|
||||
{
|
||||
if (WorldObject* fTarget = GetFarsightTarget())
|
||||
{
|
||||
if (fTarget->isType(TYPEMASK_PLAYER | TYPEMASK_UNIT))
|
||||
((Unit*)fTarget)->RemovePlayerFromVision(this);
|
||||
}
|
||||
ClearFarsight();
|
||||
}
|
||||
|
||||
void Player::ClearFarsight()
|
||||
{
|
||||
if (GetUInt64Value(PLAYER_FARSIGHT))
|
||||
{
|
||||
SetUInt64Value(PLAYER_FARSIGHT, 0);
|
||||
WorldPacket data(SMSG_CLEAR_FAR_SIGHT_IMMEDIATE, 0);
|
||||
GetSession()->SendPacket(&data);
|
||||
}
|
||||
}
|
||||
|
||||
void Player::SetFarsightTarget(WorldObject* obj)
|
||||
{
|
||||
if (!obj || !obj->isType(TYPEMASK_PLAYER | TYPEMASK_UNIT | TYPEMASK_DYNAMICOBJECT))
|
||||
return;
|
||||
|
||||
// Remove the current target if there is one
|
||||
RemoveFarsightTarget();
|
||||
|
||||
SetUInt64Value(PLAYER_FARSIGHT, obj->GetGUID());
|
||||
}
|
||||
|
||||
bool Player::isAllowUseBattleGroundObject()
|
||||
{
|
||||
return ( //InBattleGround() && // in battleground - not need, check in other cases
|
||||
|
||||
@@ -902,6 +902,13 @@ class TRINITY_DLL_SPEC Player : public Unit
|
||||
void SetViewport(uint64 guid, bool movable);
|
||||
void Possess(Unit *target);
|
||||
void RemovePossess(bool attack = true);
|
||||
WorldObject* GetFarsightTarget() const;
|
||||
void ClearFarsight();
|
||||
void RemoveFarsightTarget();
|
||||
void SetFarsightTarget(WorldObject* target);
|
||||
// Controls if vision is currently on farsight object, updated in FAR_SIGHT opcode
|
||||
void SetFarsightVision(bool apply) { m_farsightVision = apply; }
|
||||
bool HasFarsightVision() const { return m_farsightVision; }
|
||||
|
||||
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options = 0);
|
||||
|
||||
@@ -2289,6 +2296,8 @@ class TRINITY_DLL_SPEC Player : public Unit
|
||||
// Far Teleport
|
||||
WorldLocation m_teleport_dest;
|
||||
|
||||
bool m_farsightVision;
|
||||
|
||||
DeclinedName *m_declinedname;
|
||||
private:
|
||||
// internal common parts for CanStore/StoreItem functions
|
||||
|
||||
+24
-7
@@ -1964,14 +1964,10 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
|
||||
// AT REMOVE
|
||||
else
|
||||
{
|
||||
if( m_target->GetTypeId() == TYPEID_PLAYER &&
|
||||
( GetSpellProto()->Effect[0]==72 || GetSpellProto()->Effect[0]==6 &&
|
||||
( GetSpellProto()->EffectApplyAuraName[0]==1 || GetSpellProto()->EffectApplyAuraName[0]==128 ) ) )
|
||||
if( m_target->GetTypeId() == TYPEID_PLAYER && GetSpellProto()->Effect[0]==72 )
|
||||
{
|
||||
// spells with SpellEffect=72 and aura=4: 6196, 6197, 21171, 21425
|
||||
m_target->SetUInt64Value(PLAYER_FARSIGHT, 0);
|
||||
WorldPacket data(SMSG_CLEAR_FAR_SIGHT_IMMEDIATE, 0);
|
||||
((Player*)m_target)->GetSession()->SendPacket(&data);
|
||||
((Player*)m_target)->ClearFarsight();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2229,6 +2225,24 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
|
||||
((Player*)m_target)->AddSpellMod(m_spellmod, apply);
|
||||
return;
|
||||
}
|
||||
|
||||
// Sentry Totem
|
||||
if (GetId() == 6495 && caster->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
if (apply)
|
||||
{
|
||||
uint64 guid = caster->m_TotemSlot[3];
|
||||
if (guid)
|
||||
{
|
||||
Creature *totem = ObjectAccessor::GetCreature(*caster, guid);
|
||||
if (totem && totem->isTotem())
|
||||
totem->AddPlayerToVision((Player*)caster);
|
||||
}
|
||||
}
|
||||
else
|
||||
((Player*)caster)->RemoveFarsightTarget();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2830,7 +2844,10 @@ void Aura::HandleBindSight(bool apply, bool Real)
|
||||
if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
caster->SetUInt64Value(PLAYER_FARSIGHT,apply ? m_target->GetGUID() : 0);
|
||||
if (apply)
|
||||
m_target->AddPlayerToVision((Player*)caster);
|
||||
else
|
||||
m_target->RemovePlayerFromVision((Player*)caster);
|
||||
}
|
||||
|
||||
void Aura::HandleFarSight(bool apply, bool Real)
|
||||
|
||||
@@ -3490,6 +3490,9 @@ void Spell::EffectPickPocket(uint32 /*i*/)
|
||||
|
||||
void Spell::EffectAddFarsight(uint32 i)
|
||||
{
|
||||
if (m_caster->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
|
||||
float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
|
||||
int32 duration = GetSpellDuration(m_spellInfo);
|
||||
DynamicObject* dynObj = new DynamicObject;
|
||||
@@ -3501,8 +3504,18 @@ void Spell::EffectAddFarsight(uint32 i)
|
||||
dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
|
||||
dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x80000002);
|
||||
m_caster->AddDynObject(dynObj);
|
||||
MapManager::Instance().GetMap(dynObj->GetMapId(), dynObj)->Add(dynObj);
|
||||
m_caster->SetUInt64Value(PLAYER_FARSIGHT, dynObj->GetGUID());
|
||||
|
||||
CellPair pair = Trinity::ComputeCellPair(dynObj->GetPositionX(), dynObj->GetPositionY());
|
||||
Cell cell(pair);
|
||||
Map* map = MapManager::Instance().GetMap(dynObj->GetMapId(), dynObj);
|
||||
map->LoadGrid(cell); // In case the spell is casted into a different grid by player
|
||||
map->Add(dynObj);
|
||||
map->SwitchGridContainers(dynObj, true); // Needed for forwarding player packets
|
||||
dynObj->setActive(true); // Keep the grid updated even if there are no players in it
|
||||
|
||||
// Need to update visibility of object for client to accept farsight guid
|
||||
((Player*)m_caster)->UpdateVisibilityOf(dynObj);
|
||||
((Player*)m_caster)->SetFarsightTarget(dynObj);
|
||||
}
|
||||
|
||||
void Spell::EffectSummonWild(uint32 i)
|
||||
|
||||
@@ -352,18 +352,22 @@ void WorldSession::HandleCancelAuraOpcode( WorldPacket& recvPacket)
|
||||
if (!spellInfo)
|
||||
return;
|
||||
|
||||
// Remove possess/charm aura from the possessed/charmed as well
|
||||
// Remove possess/charm/sight aura from the possessed/charmed as well
|
||||
// TODO: Remove this once the ability to cancel aura sets at once is implemented
|
||||
if(_player->GetCharm())
|
||||
if(_player->GetCharm() || _player->GetFarsightTarget())
|
||||
{
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
if (spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_POSSESS ||
|
||||
spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_POSSESS_PET ||
|
||||
spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_CHARM)
|
||||
spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_CHARM ||
|
||||
spellInfo->EffectApplyAuraName[i] == SPELL_AURA_BIND_SIGHT)
|
||||
{
|
||||
_player->RemoveAurasDueToSpellByCancel(spellId);
|
||||
_player->GetCharm()->RemoveAurasDueToSpellByCancel(spellId);
|
||||
if (_player->GetCharm())
|
||||
_player->GetCharm()->RemoveAurasDueToSpellByCancel(spellId);
|
||||
else if (_player->GetFarsightTarget()->GetTypeId() != TYPEID_DYNAMICOBJECT)
|
||||
((Unit*)_player->GetFarsightTarget())->RemoveAurasDueToSpellByCancel(spellId);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -464,7 +468,8 @@ void WorldSession::HandleTotemDestroy( WorldPacket& recvPacket)
|
||||
return;
|
||||
|
||||
Creature* totem = ObjectAccessor::GetCreature(*_player,_player->m_TotemSlot[slotId]);
|
||||
if(totem && totem->isTotem())
|
||||
// Don't unsummon sentry totem
|
||||
if(totem && totem->isTotem() && totem->GetEntry() != SENTRY_TOTEM_ENTRY)
|
||||
((Totem*)totem)->UnSummon();
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,8 @@ enum TotemType
|
||||
TOTEM_STATUE = 2
|
||||
};
|
||||
|
||||
#define SENTRY_TOTEM_ENTRY 3968
|
||||
|
||||
class Totem : public Creature
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -122,4 +122,13 @@ TotemAI::IsVisible(Unit *) const
|
||||
void
|
||||
TotemAI::AttackStart(Unit *)
|
||||
{
|
||||
// Sentry totem sends ping on attack
|
||||
if (i_totem.GetEntry() == SENTRY_TOTEM_ENTRY && i_totem.GetOwner()->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
WorldPacket data(MSG_MINIMAP_PING, (8+4+4));
|
||||
data << i_totem.GetGUID();
|
||||
data << i_totem.GetPositionX();
|
||||
data << i_totem.GetPositionY();
|
||||
((Player*)i_totem.GetOwner())->GetSession()->SendPacket(&data);
|
||||
}
|
||||
}
|
||||
|
||||
+39
-7
@@ -828,13 +828,6 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa
|
||||
he->DuelComplete(DUEL_INTERUPTED);
|
||||
}
|
||||
|
||||
// Possessed unit died, restore control to possessor
|
||||
pVictim->UnpossessSelf(false);
|
||||
|
||||
// Possessor died, remove possession
|
||||
if(pVictim->GetTypeId() == TYPEID_PLAYER && pVictim->isPossessing())
|
||||
((Player*)pVictim)->RemovePossess(false);
|
||||
|
||||
// battleground things (do this at the end, so the death state flag will be properly set to handle in the bg->handlekill)
|
||||
if(pVictim->GetTypeId() == TYPEID_PLAYER && (((Player*)pVictim)->InBattleGround()))
|
||||
{
|
||||
@@ -7183,6 +7176,38 @@ void Unit::SetCharm(Unit* charmed)
|
||||
SetUInt64Value(UNIT_FIELD_CHARM,charmed ? charmed->GetGUID() : 0);
|
||||
}
|
||||
|
||||
void Unit::AddPlayerToVision(Player* plr)
|
||||
{
|
||||
if (m_sharedVision.empty() && GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
setActive(true);
|
||||
GetMap()->SwitchGridContainers((Creature*)this, true);
|
||||
}
|
||||
m_sharedVision.push_back(plr);
|
||||
plr->SetFarsightTarget(this);
|
||||
}
|
||||
|
||||
void Unit::RemovePlayerFromVision(Player* plr)
|
||||
{
|
||||
m_sharedVision.remove(plr);
|
||||
if (m_sharedVision.empty() && GetTypeId() == TYPEID_UNIT)
|
||||
{
|
||||
setActive(false);
|
||||
GetMap()->SwitchGridContainers((Creature*)this, false);
|
||||
}
|
||||
plr->ClearFarsight();
|
||||
}
|
||||
|
||||
void Unit::RemoveAllFromVision()
|
||||
{
|
||||
while (!m_sharedVision.empty())
|
||||
{
|
||||
Player* plr = *m_sharedVision.begin();
|
||||
m_sharedVision.erase(m_sharedVision.begin());
|
||||
plr->ClearFarsight();
|
||||
}
|
||||
}
|
||||
|
||||
void Unit::UncharmSelf()
|
||||
{
|
||||
if (!GetCharmer())
|
||||
@@ -8935,6 +8960,10 @@ void Unit::setDeathState(DeathState s)
|
||||
RemoveAllAurasOnDeath();
|
||||
UnsummonAllTotems();
|
||||
|
||||
// Possessed unit died, restore control to possessor
|
||||
UnpossessSelf(false);
|
||||
RemoveAllFromVision();
|
||||
|
||||
ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false);
|
||||
ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, false);
|
||||
// remove aurastates allowing special moves
|
||||
@@ -9756,10 +9785,13 @@ void Unit::CleanupsBeforeDelete()
|
||||
GetMotionMaster()->Clear(false); // remove different non-standard movement generators.
|
||||
|
||||
UnpossessSelf(false);
|
||||
RemoveAllFromVision();
|
||||
}
|
||||
RemoveFromWorld();
|
||||
}
|
||||
|
||||
|
||||
|
||||
CharmInfo* Unit::InitCharmInfo(Unit *charm)
|
||||
{
|
||||
if(!m_charmInfo)
|
||||
|
||||
@@ -638,6 +638,8 @@ struct CharmSpellEntry
|
||||
uint16 active;
|
||||
};
|
||||
|
||||
typedef std::list<Player*> SharedVisionList;
|
||||
|
||||
struct CharmInfo
|
||||
{
|
||||
public:
|
||||
@@ -1018,6 +1020,10 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
|
||||
|
||||
CharmInfo* GetCharmInfo() { return m_charmInfo; }
|
||||
CharmInfo* InitCharmInfo(Unit* charm);
|
||||
SharedVisionList const& GetSharedVisionList() { return m_sharedVision; }
|
||||
void AddPlayerToVision(Player* plr);
|
||||
void RemovePlayerFromVision(Player* plr);
|
||||
void RemoveAllFromVision();
|
||||
void UncharmSelf();
|
||||
void UnpossessSelf(bool attack);
|
||||
|
||||
@@ -1350,6 +1356,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
|
||||
|
||||
CharmInfo *m_charmInfo;
|
||||
bool m_isPossessed;
|
||||
SharedVisionList m_sharedVision;
|
||||
|
||||
virtual SpellSchoolMask GetMeleeDamageSchoolMask() const;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user