server/src/game/GridNotifiers.cpp
VladimirMangos 7fb5d850bf [9510] Gameobject casting improvements.
* Add IsHostileTo/IsFriendlyTo and implement expected way checks for diff. world object types.
  For controlled object check redirected to specific owner, for wild gameobject base at gameobject faction.
  If faction not set expected to be hostile to anyone.
* Update grid searchers to be usable with world object instead only unit case.
  Some grid searches lost redundent second object arg, AnyAoETargetUnitInObjectRangeCheck lost hitHidden arg
  (for hitHidden==true case added new AnyAoEVisibleTargetUnitInObjectRangeCheck)
* Updated grid searchers used with gameobject area casts now.
  Note: Gameobject area spell cast animation will still wrong show around cast triggering target instead
  center around gameobject.
* In case gameobject aura apply to target for restored use target itself as caster because
  we not have currently another way apply aura form wild gameobject.
2010-03-04 07:38:26 +03:00

242 lines
7.7 KiB
C++

/*
* 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
*/
#include "GridNotifiers.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include "UpdateData.h"
#include "Item.h"
#include "Map.h"
#include "Transports.h"
#include "ObjectAccessor.h"
using namespace MaNGOS;
void
MaNGOS::PlayerNotifier::Visit(PlayerMapType &m)
{
WorldObject const* viewPoint = i_player.GetViewPoint();
for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
{
Player* player = iter->getSource();
if( player == &i_player )
continue;
player->UpdateVisibilityOf(player->GetViewPoint(),&i_player);
i_player.UpdateVisibilityOf(viewPoint,player);
}
}
void
VisibleChangesNotifier::Visit(PlayerMapType &m)
{
for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
{
Player* player = iter->getSource();
if(player == &i_object)
continue;
player->UpdateVisibilityOf(player->GetViewPoint(),&i_object);
}
}
void
VisibleNotifier::Visit(PlayerMapType &m)
{
WorldObject const* viewPoint = i_player.GetViewPoint();
for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
{
Player* player = iter->getSource();
if( player == &i_player )
continue;
player->UpdateVisibilityOf(player->GetViewPoint(),&i_player);
i_player.UpdateVisibilityOf(viewPoint,player,i_data,i_data_updates,i_visibleNow);
i_clientGUIDs.erase(player->GetGUID());
}
}
void
VisibleNotifier::Notify()
{
// at this moment i_clientGUIDs have guids that not iterate at grid level checks
// but exist one case when this possible and object not out of range: transports
if(Transport* transport = i_player.GetTransport())
{
for(Transport::PlayerSet::const_iterator itr = transport->GetPassengers().begin();itr!=transport->GetPassengers().end();++itr)
{
if(i_clientGUIDs.find((*itr)->GetGUID())!=i_clientGUIDs.end())
{
// ignore far sight case
(*itr)->UpdateVisibilityOf((*itr),&i_player);
i_player.UpdateVisibilityOf(&i_player,(*itr),i_data,i_data_updates,i_visibleNow);
i_clientGUIDs.erase((*itr)->GetGUID());
}
}
}
// generate outOfRange for not iterate objects
i_data.AddOutOfRangeGUID(i_clientGUIDs);
for(Player::ClientGUIDs::iterator itr = i_clientGUIDs.begin();itr!=i_clientGUIDs.end();++itr)
{
i_player.m_clientGUIDs.erase(*itr);
#ifdef MANGOS_DEBUG
if((sLog.getLogFilter() & LOG_FILTER_VISIBILITY_CHANGES)==0)
sLog.outDebug("Object %u (Type: %u) is out of range (no in active cells set) now for player %u",GUID_LOPART(*itr),GuidHigh2TypeId(GUID_HIPART(*itr)),i_player.GetGUIDLow());
#endif
}
// send update to other players (except player updates that already sent using SendUpdateToPlayer)
for(UpdateDataMapType::iterator iter = i_data_updates.begin(); iter != i_data_updates.end(); ++iter)
{
if(iter->first==&i_player)
continue;
WorldPacket packet;
iter->second.BuildPacket(&packet);
iter->first->GetSession()->SendPacket(&packet);
}
if( i_data.HasData() )
{
// send create/outofrange packet to player (except player create updates that already sent using SendUpdateToPlayer)
WorldPacket packet;
i_data.BuildPacket(&packet);
i_player.GetSession()->SendPacket(&packet);
// send out of range to other players if need
std::set<uint64> const& oor = i_data.GetOutOfRangeGUIDs();
for(std::set<uint64>::const_iterator iter = oor.begin(); iter != oor.end(); ++iter)
{
if(!IS_PLAYER_GUID(*iter))
continue;
if (Player* plr = ObjectAccessor::FindPlayer(*iter))
plr->UpdateVisibilityOf(plr->GetViewPoint(),&i_player);
}
}
// Now do operations that required done at object visibility change to visible
// send data at target visibility change (adding to client)
for(std::set<WorldObject*>::const_iterator vItr = i_visibleNow.begin(); vItr != i_visibleNow.end(); ++vItr)
{
// target aura duration for caster show only if target exist at caster client
if((*vItr)!=&i_player && (*vItr)->isType(TYPEMASK_UNIT))
i_player.SendAurasForTarget((Unit*)(*vItr));
// non finished movements show to player
if((*vItr)->GetTypeId()==TYPEID_UNIT && ((Creature*)(*vItr))->isAlive())
((Creature*)(*vItr))->SendMonsterMoveWithSpeedToCurrentDestination(&i_player);
}
}
void
MessageDeliverer::Visit(PlayerMapType &m)
{
for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
{
if (i_toSelf || iter->getSource() != &i_player)
{
if (!i_player.InSamePhase(iter->getSource()))
continue;
if(WorldSession* session = iter->getSource()->GetSession())
session->SendPacket(i_message);
}
}
}
void
ObjectMessageDeliverer::Visit(PlayerMapType &m)
{
for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
{
if(!iter->getSource()->InSamePhase(i_phaseMask))
continue;
if(WorldSession* session = iter->getSource()->GetSession())
session->SendPacket(i_message);
}
}
void
MessageDistDeliverer::Visit(PlayerMapType &m)
{
for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
{
if ((i_toSelf || iter->getSource() != &i_player ) &&
(!i_ownTeamOnly || iter->getSource()->GetTeam() == i_player.GetTeam() ) &&
(!i_dist || iter->getSource()->IsWithinDist(&i_player,i_dist)))
{
if (!i_player.InSamePhase(iter->getSource()))
continue;
if (WorldSession* session = iter->getSource()->GetSession())
session->SendPacket(i_message);
}
}
}
void
ObjectMessageDistDeliverer::Visit(PlayerMapType &m)
{
for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
{
if (!i_dist || iter->getSource()->IsWithinDist(&i_object,i_dist))
{
if (!i_object.InSamePhase(iter->getSource()))
continue;
if (WorldSession* session = iter->getSource()->GetSession())
session->SendPacket(i_message);
}
}
}
template<class T> void
ObjectUpdater::Visit(GridRefManager<T> &m)
{
for(typename GridRefManager<T>::iterator iter = m.begin(); iter != m.end(); ++iter)
{
iter->getSource()->Update(i_timeDiff);
}
}
bool CannibalizeObjectCheck::operator()(Corpse* u)
{
// ignore bones
if(u->GetType()==CORPSE_BONES)
return false;
Player* owner = ObjectAccessor::FindPlayer(u->GetOwnerGUID());
if( !owner || i_fobj->IsFriendlyTo(owner))
return false;
if(i_fobj->IsWithinDistInMap(u, i_range) )
return true;
return false;
}
template void ObjectUpdater::Visit<GameObject>(GameObjectMapType &);
template void ObjectUpdater::Visit<DynamicObject>(DynamicObjectMapType &);