[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:
gvcoman
2008-11-14 20:40:35 -06:00
parent 3085e66b96
commit 5deef1bb59
21 changed files with 329 additions and 74 deletions
+4
View File
@@ -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.');
+2
View File
@@ -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 }
};
+2
View File
@@ -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();
+4 -1
View File
@@ -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))*/;
}
+1 -1
View File
@@ -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
View File
@@ -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);
}
+7 -7
View File
@@ -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); }
};
+23
View File
@@ -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
View File
@@ -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)
+20 -8
View File
@@ -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 )
+28 -4
View File
@@ -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
+1
View File
@@ -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
View File
@@ -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
+9
View File
@@ -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
View File
@@ -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)
+15 -2
View File
@@ -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)
+10 -5
View File
@@ -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();
}
+2
View File
@@ -30,6 +30,8 @@ enum TotemType
TOTEM_STATUE = 2
};
#define SENTRY_TOTEM_ENTRY 3968
class Totem : public Creature
{
public:
+9
View File
@@ -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
View File
@@ -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)
+7
View File
@@ -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;