2010-10-07 15:35:36 +02:00
/*
2012-01-01 00:32:13 +01:00
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
2010-10-07 15:35:36 +02:00
* Copyright (C) 2005-2009 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, see <http://www.gnu.org/licenses/>.
2008-10-11 14:16:25 -05:00
*/
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
#include "Common.h"
#include "SharedDefines.h"
#include "WorldPacket.h"
#include "Opcodes.h"
#include "Log.h"
#include "World.h"
#include "Object.h"
#include "Creature.h"
#include "Player.h"
2009-03-09 17:06:13 -06:00
#include "Vehicle.h"
2008-10-11 14:16:25 -05:00
#include "ObjectMgr.h"
#include "UpdateData.h"
#include "UpdateMask.h"
#include "Util.h"
#include "MapManager.h"
#include "ObjectAccessor.h"
#include "Log.h"
2010-06-07 23:40:17 +02:00
#include "Transport.h"
2008-10-11 14:16:25 -05:00
#include "TargetedMovementGenerator.h"
#include "WaypointMovementGenerator.h"
#include "VMapFactory.h"
#include "CellImpl.h"
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
2010-01-10 01:23:15 +01:00
#include "SpellAuraEffects.h"
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
#include "TemporarySummon.h"
2009-03-20 14:01:46 -06:00
#include "Totem.h"
2009-05-30 22:15:05 -05:00
#include "OutdoorPvPMgr.h"
2012-01-14 15:34:41 +01:00
#include "MovementPacketBuilder.h"
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 GuidHigh2TypeId ( uint32 guid_hi )
{
2011-09-29 12:43:05 +02:00
switch ( guid_hi )
2008-10-11 14:16:25 -05:00
{
case HIGHGUID_ITEM : return TYPEID_ITEM ;
2010-04-07 23:25:02 +02:00
//case HIGHGUID_CONTAINER: return TYPEID_CONTAINER; HIGHGUID_CONTAINER == HIGHGUID_ITEM currently
2008-10-11 14:16:25 -05:00
case HIGHGUID_UNIT : return TYPEID_UNIT ;
case HIGHGUID_PET : return TYPEID_UNIT ;
case HIGHGUID_PLAYER : return TYPEID_PLAYER ;
case HIGHGUID_GAMEOBJECT : return TYPEID_GAMEOBJECT ;
case HIGHGUID_DYNAMICOBJECT : return TYPEID_DYNAMICOBJECT ;
case HIGHGUID_CORPSE : return TYPEID_CORPSE ;
case HIGHGUID_MO_TRANSPORT : return TYPEID_GAMEOBJECT ;
2009-01-24 11:28:00 -06:00
case HIGHGUID_VEHICLE : return TYPEID_UNIT ;
2008-10-11 14:16:25 -05:00
}
2009-05-31 15:56:51 -05:00
return NUM_CLIENT_OBJECT_TYPES ; // unknown
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
Object :: Object () : m_PackGUID ( sizeof ( uint64 ) + 1 )
2008-10-11 14:16:25 -05:00
{
m_objectTypeId = TYPEID_OBJECT ;
m_objectType = TYPEMASK_OBJECT ;
2009-10-17 15:51:44 -07:00
2011-08-28 18:31:37 +02:00
m_uint32Values = NULL ;
_changedFields = NULL ;
2008-10-11 14:16:25 -05:00
m_valuesCount = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
m_inWorld = false ;
m_objectUpdated = false ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
m_PackGUID . appendPackGUID ( 0 );
}
2009-10-17 15:51:44 -07:00
2009-08-11 16:33:33 -05:00
WorldObject ::~ WorldObject ()
{
2009-08-13 17:02:17 -05:00
// this may happen because there are many !create/delete
2011-12-20 17:05:08 -05:00
if ( IsWorldObject () && m_currMap )
2009-08-11 16:33:33 -05:00
{
2010-04-07 19:14:10 +02:00
if ( GetTypeId () == TYPEID_CORPSE )
2009-08-13 17:02:17 -05:00
{
2010-12-23 23:25:44 +01:00
sLog -> outCrash ( "Object::~Object Corpse guid=" UI64FMTD ", type=%d, entry=%u deleted but still in map!!" , GetGUID (), (( Corpse * ) this ) -> GetType (), GetEntry ());
2010-07-30 20:04:28 +02:00
ASSERT ( false );
2009-08-13 17:02:17 -05:00
}
2009-08-11 16:33:33 -05:00
ResetMap ();
}
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
Object ::~ Object ()
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( IsInWorld ())
2008-10-11 14:16:25 -05:00
{
2010-12-23 23:25:44 +01:00
sLog -> outCrash ( "Object::~Object - guid=" UI64FMTD ", typeid=%d, entry=%u deleted but still in world!!" , GetGUID (), GetTypeId (), GetEntry ());
2010-04-07 19:14:10 +02:00
if ( isType ( TYPEMASK_ITEM ))
2010-12-23 23:25:44 +01:00
sLog -> outCrash ( "Item slot %u" , (( Item * ) this ) -> GetSlot ());
2010-07-30 20:04:28 +02:00
ASSERT ( false );
2009-06-17 09:57:22 -05:00
RemoveFromWorld ();
2009-04-09 17:15:40 -05:00
}
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( m_objectUpdated )
2009-06-16 17:58:44 -05:00
{
2010-12-23 23:25:44 +01:00
sLog -> outCrash ( "Object::~Object - guid=" UI64FMTD ", typeid=%d, entry=%u deleted but still in update list!!" , GetGUID (), GetTypeId (), GetEntry ());
2010-07-30 20:04:28 +02:00
ASSERT ( false );
2010-12-23 23:25:44 +01:00
sObjectAccessor -> RemoveUpdateObject ( this );
2009-06-16 17:58:44 -05:00
}
2009-10-17 15:51:44 -07:00
2010-06-21 23:20:58 +02:00
delete [] m_uint32Values ;
2011-08-28 18:31:37 +02:00
delete [] _changedFields ;
2010-06-21 23:20:58 +02:00
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Object :: _InitValues ()
{
2011-08-28 18:31:37 +02:00
m_uint32Values = new uint32 [ m_valuesCount ];
2008-10-11 14:16:25 -05:00
memset ( m_uint32Values , 0 , m_valuesCount * sizeof ( uint32 ));
2009-10-17 15:51:44 -07:00
2011-08-28 18:31:37 +02:00
_changedFields = new bool [ m_valuesCount ];
2011-08-30 12:58:10 +02:00
memset ( _changedFields , 0 , m_valuesCount * sizeof ( bool ));
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
m_objectUpdated = false ;
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void Object :: _Create ( uint32 guidlow , uint32 entry , HighGuid guidhigh )
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( ! m_uint32Values ) _InitValues ();
2009-10-17 15:51:44 -07:00
2009-05-31 15:56:51 -05:00
uint64 guid = MAKE_NEW_GUID ( guidlow , entry , guidhigh );
2010-04-07 22:59:46 +02:00
SetUInt64Value ( OBJECT_FIELD_GUID , guid );
2009-06-13 09:18:54 -05:00
uint32 type = 0 ;
2011-09-29 12:43:05 +02:00
switch ( m_objectType )
2009-06-13 09:18:54 -05:00
{
//case TYPEID_ITEM: type = 3; break;
//case TYPEID_CONTAINER: type = 7; break; //+4
//case TYPEID_UNIT: type = 9; break; //+2
//case TYPEID_PLAYER: type = 25; break; //+16
//case TYPEID_GAMEOBJECT: type = 33; break; //+8
case TYPEID_DYNAMICOBJECT : type = 65 ; break ; //+32
//case TYPEID_CORPSE: type = 129; break; //+64
default : type = m_objectType ; break ;
}
2010-04-07 22:59:46 +02:00
SetUInt32Value ( OBJECT_FIELD_TYPE , type );
//SetUInt32Value(OBJECT_FIELD_TYPE, m_objectType);
2009-06-01 12:15:43 -05:00
m_PackGUID . wpos ( 0 );
2008-10-11 14:16:25 -05:00
m_PackGUID . appendPackGUID ( GetGUID ());
}
2009-10-17 15:51:44 -07:00
2011-04-11 14:39:00 +06:00
std :: string Object :: _ConcatFields ( uint16 startIndex , uint16 size ) const
{
std :: ostringstream ss ;
for ( uint16 index = 0 ; index < size ; ++ index )
2011-07-29 14:18:28 +02:00
ss << GetUInt32Value ( index + startIndex ) << ' ' ;
2011-04-11 14:39:00 +06:00
return ss . str ();
}
2011-08-30 13:46:36 +02:00
void Object :: AddToWorld ()
{
if ( m_inWorld )
return ;
ASSERT ( m_uint32Values );
m_inWorld = true ;
// synchronize values mirror with values array (changes will send in updatecreate opcode any way
ClearUpdateMask ( true );
}
void Object :: RemoveFromWorld ()
{
if ( ! m_inWorld )
return ;
m_inWorld = false ;
// if we remove from world then sending changes not required
ClearUpdateMask ( true );
}
2011-09-15 14:08:17 +02:00
void Object :: BuildMovementUpdateBlock ( UpdateData * data , uint32 flags ) const
2008-10-11 14:16:25 -05:00
{
2009-06-11 00:45:59 -05:00
ByteBuffer buf ( 500 );
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
buf << uint8 ( UPDATETYPE_MOVEMENT );
2009-06-05 17:44:27 -05:00
buf . append ( GetPackGUID ());
2009-10-17 15:51:44 -07:00
2009-04-22 17:50:26 -05:00
_BuildMovementUpdate ( & buf , flags );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
data -> AddUpdateBlock ( buf );
}
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
void Object :: BuildCreateUpdateBlockForPlayer ( UpdateData * data , Player * target ) const
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( ! target )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint8 updatetype = UPDATETYPE_CREATE_OBJECT ;
2009-06-11 00:45:59 -05:00
uint16 flags = m_updateFlag ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
/** lower flag1 **/
2010-04-07 19:14:10 +02:00
if ( target == this ) // building packet for yourself
2008-10-11 14:16:25 -05:00
flags |= UPDATEFLAG_SELF ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( flags & UPDATEFLAG_HAS_POSITION )
2008-10-11 14:16:25 -05:00
{
// UPDATETYPE_CREATE_OBJECT2 dynamic objects, corpses...
2010-04-07 19:14:10 +02:00
if ( isType ( TYPEMASK_DYNAMICOBJECT ) || isType ( TYPEMASK_CORPSE ) || isType ( TYPEMASK_PLAYER ))
2008-10-11 14:16:25 -05:00
updatetype = UPDATETYPE_CREATE_OBJECT2 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// UPDATETYPE_CREATE_OBJECT2 for pets...
2010-04-07 19:14:10 +02:00
if ( target -> GetPetGUID () == GetGUID ())
2008-10-11 14:16:25 -05:00
updatetype = UPDATETYPE_CREATE_OBJECT2 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// UPDATETYPE_CREATE_OBJECT2 for some gameobject types...
2010-04-07 19:14:10 +02:00
if ( isType ( TYPEMASK_GAMEOBJECT ))
2008-10-11 14:16:25 -05:00
{
2011-09-29 12:43:05 +02:00
switch ((( GameObject * ) this ) -> GetGoType ())
2008-10-11 14:16:25 -05:00
{
case GAMEOBJECT_TYPE_TRAP :
case GAMEOBJECT_TYPE_DUEL_ARBITER :
case GAMEOBJECT_TYPE_FLAGSTAND :
case GAMEOBJECT_TYPE_FLAGDROP :
updatetype = UPDATETYPE_CREATE_OBJECT2 ;
break ;
case GAMEOBJECT_TYPE_TRANSPORT :
flags |= UPDATEFLAG_TRANSPORT ;
break ;
2009-05-03 22:21:46 -05:00
default :
break ;
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( isType ( TYPEMASK_UNIT ))
2008-12-24 09:58:26 -06:00
{
2010-04-07 19:14:10 +02:00
if ((( Unit * ) this ) -> getVictim ())
2008-12-24 09:58:26 -06:00
flags |= UPDATEFLAG_HAS_TARGET ;
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2010-12-23 23:25:44 +01:00
//sLog->outDebug("BuildCreateUpdate: update-type: %u, object-type: %u got flags: %X, flags2: %X", updatetype, m_objectTypeId, flags, flags2);
2009-10-17 15:51:44 -07:00
2009-06-11 00:45:59 -05:00
ByteBuffer buf ( 500 );
2008-10-11 14:16:25 -05:00
buf << ( uint8 ) updatetype ;
2009-06-05 17:44:27 -05:00
buf . append ( GetPackGUID ());
2008-10-11 14:16:25 -05:00
buf << ( uint8 ) m_objectTypeId ;
2009-10-17 15:51:44 -07:00
2009-04-22 17:50:26 -05:00
_BuildMovementUpdate ( & buf , flags );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
UpdateMask updateMask ;
2010-04-07 22:59:46 +02:00
updateMask . SetCount ( m_valuesCount );
_SetCreateBits ( & updateMask , target );
2009-05-31 15:56:51 -05:00
_BuildValuesUpdate ( updatetype , & buf , & updateMask , target );
2008-10-11 14:16:25 -05:00
data -> AddUpdateBlock ( buf );
}
2009-10-17 15:51:44 -07:00
2009-12-19 19:46:07 +01:00
void Object :: SendUpdateToPlayer ( Player * player )
2008-10-11 14:16:25 -05:00
{
// send create update to player
UpdateData upd ;
WorldPacket packet ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
BuildCreateUpdateBlockForPlayer ( & upd , player );
upd . BuildPacket ( & packet );
player -> GetSession () -> SendPacket ( & packet );
}
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
void Object :: BuildValuesUpdateBlockForPlayer ( UpdateData * data , Player * target ) const
2008-10-11 14:16:25 -05:00
{
2009-06-11 00:45:59 -05:00
ByteBuffer buf ( 500 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
buf << ( uint8 ) UPDATETYPE_VALUES ;
2009-06-05 17:44:27 -05:00
buf . append ( GetPackGUID ());
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
UpdateMask updateMask ;
2010-04-07 22:59:46 +02:00
updateMask . SetCount ( m_valuesCount );
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
_SetUpdateBits ( & updateMask , target );
2009-05-31 15:56:51 -05:00
_BuildValuesUpdate ( UPDATETYPE_VALUES , & buf , & updateMask , target );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
data -> AddUpdateBlock ( buf );
}
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
void Object :: BuildOutOfRangeUpdateBlock ( UpdateData * data ) const
2008-10-11 14:16:25 -05:00
{
data -> AddOutOfRangeGUID ( GetGUID ());
}
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
void Object :: DestroyForPlayer ( Player * target , bool anim ) const
2008-10-11 14:16:25 -05:00
{
ASSERT ( target );
2009-10-17 15:51:44 -07:00
2010-02-03 16:53:40 +02:00
WorldPacket data ( SMSG_DESTROY_OBJECT , 8 + 1 );
2009-05-31 15:56:51 -05:00
data << uint64 ( GetGUID ());
2009-07-30 10:26:15 +08:00
data << uint8 ( anim ? 1 : 0 ); // WotLK (bool), may be despawn animation
2010-04-07 22:59:46 +02:00
target -> GetSession () -> SendPacket ( & data );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-06-11 00:45:59 -05:00
void Object :: _BuildMovementUpdate ( ByteBuffer * data , uint16 flags ) const
2008-10-11 14:16:25 -05:00
{
2009-06-11 00:45:59 -05:00
* data << ( uint16 ) flags ; // update flags
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// 0x20
if ( flags & UPDATEFLAG_LIVING )
{
2009-04-21 15:43:03 -05:00
(( Unit * ) this ) -> BuildMovementPacket ( data );
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
* data << (( Unit * ) this ) -> GetSpeed ( MOVE_WALK );
* data << (( Unit * ) this ) -> GetSpeed ( MOVE_RUN );
* data << (( Unit * ) this ) -> GetSpeed ( MOVE_RUN_BACK );
2012-01-14 15:34:41 +01:00
* data << (( Unit * ) this ) -> GetSpeed ( MOVE_SWIM );
* data << (( Unit * ) this ) -> GetSpeed ( MOVE_SWIM_BACK );
2010-04-07 22:59:46 +02:00
* data << (( Unit * ) this ) -> GetSpeed ( MOVE_FLIGHT );
* data << (( Unit * ) this ) -> GetSpeed ( MOVE_FLIGHT_BACK );
* data << (( Unit * ) this ) -> GetSpeed ( MOVE_TURN_RATE );
* data << (( Unit * ) this ) -> GetSpeed ( MOVE_PITCH_RATE );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// 0x08000000
2012-01-14 15:34:41 +01:00
if ((( Unit * ) this ) -> m_movementInfo . GetMovementFlags () & MOVEMENTFLAG_SPLINE_ENABLED )
Movement :: PacketBuilder :: WriteCreate ( * (( Unit * ) this ) -> movespline , * data );
2009-06-11 00:45:59 -05:00
}
else
{
2010-04-07 19:14:10 +02:00
if ( flags & UPDATEFLAG_POSITION )
2009-06-11 00:45:59 -05:00
{
* data << uint8 ( 0 ); // unk PGUID!
* data << (( WorldObject * ) this ) -> GetPositionX ();
* data << (( WorldObject * ) this ) -> GetPositionY ();
* data << (( WorldObject * ) this ) -> GetPositionZ ();
* data << (( WorldObject * ) this ) -> GetPositionX ();
* data << (( WorldObject * ) this ) -> GetPositionY ();
* data << (( WorldObject * ) this ) -> GetPositionZ ();
* data << (( WorldObject * ) this ) -> GetOrientation ();
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( GetTypeId () == TYPEID_CORPSE )
2009-06-11 00:45:59 -05:00
* data << float ((( WorldObject * ) this ) -> GetOrientation ());
else
* data << float ( 0 );
}
else
{
// 0x40
if ( flags & UPDATEFLAG_HAS_POSITION )
{
// 0x02
2010-04-07 19:14:10 +02:00
if ( flags & UPDATEFLAG_TRANSPORT && (( GameObject * ) this ) -> GetGoType () == GAMEOBJECT_TYPE_MO_TRANSPORT )
2009-06-11 00:45:59 -05:00
{
* data << ( float ) 0 ;
* data << ( float ) 0 ;
* data << ( float ) 0 ;
2011-09-29 09:32:55 +02:00
* data << (( WorldObject * ) this ) -> GetOrientation ();
2009-06-11 00:45:59 -05:00
}
else
{
2011-09-29 09:32:55 +02:00
* data << (( WorldObject * ) this ) -> GetPositionX ();
* data << (( WorldObject * ) this ) -> GetPositionY ();
* data << (( WorldObject * ) this ) -> GetPositionZ ();
* data << (( WorldObject * ) this ) -> GetOrientation ();
2009-06-11 00:45:59 -05:00
}
}
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// 0x8
2010-04-07 19:14:10 +02:00
if ( flags & UPDATEFLAG_LOWGUID )
2008-10-11 14:16:25 -05:00
{
2011-09-29 12:43:05 +02:00
switch ( GetTypeId ())
2008-10-11 14:16:25 -05:00
{
case TYPEID_OBJECT :
case TYPEID_ITEM :
case TYPEID_CONTAINER :
case TYPEID_GAMEOBJECT :
case TYPEID_DYNAMICOBJECT :
case TYPEID_CORPSE :
* data << uint32 ( GetGUIDLow ()); // GetGUIDLow()
break ;
case TYPEID_UNIT :
* data << uint32 ( 0x0000000B ); // unk, can be 0xB or 0xC
break ;
case TYPEID_PLAYER :
2010-04-07 19:14:10 +02:00
if ( flags & UPDATEFLAG_SELF )
2008-12-24 09:58:26 -06:00
* data << uint32 ( 0x0000002F ); // unk, can be 0x15 or 0x22
2008-10-11 14:16:25 -05:00
else
* data << uint32 ( 0x00000008 ); // unk, can be 0x7 or 0x8
break ;
default :
* data << uint32 ( 0x00000000 ); // unk
break ;
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// 0x10
2010-04-07 19:14:10 +02:00
if ( flags & UPDATEFLAG_HIGHGUID )
2008-10-11 14:16:25 -05:00
{
2009-06-13 09:18:54 -05:00
// not high guid
2011-07-04 13:47:23 +02:00
* data << uint32 ( GetUInt32Value ( OBJECT_FIELD_GUID )); // unk
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// 0x4
2010-04-07 19:14:10 +02:00
if ( flags & UPDATEFLAG_HAS_TARGET ) // packed guid (current target guid)
2008-10-11 14:16:25 -05:00
{
2011-06-12 01:47:45 +02:00
if ( Unit * victim = (( Unit * ) this ) -> getVictim ())
2008-12-24 09:58:26 -06:00
data -> append ( victim -> GetPackGUID ());
else
* data << uint8 ( 0 );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// 0x2
2010-04-07 19:14:10 +02:00
if ( flags & UPDATEFLAG_TRANSPORT )
2008-10-11 14:16:25 -05:00
{
* data << uint32 ( getMSTime ()); // ms time
}
2009-10-17 15:51:44 -07:00
2008-12-24 09:58:26 -06:00
// 0x80
2010-04-07 19:14:10 +02:00
if ( flags & UPDATEFLAG_VEHICLE ) // unused for now
2008-12-24 09:58:26 -06:00
{
2009-08-23 22:09:43 -05:00
* data << uint32 ((( Unit * ) this ) -> GetVehicleKit () -> GetVehicleInfo () -> m_ID ); // vehicle id
2010-12-17 13:22:17 +01:00
* data << float ((( Creature * ) this ) -> GetOrientation ()); // facing adjustment
2008-12-24 09:58:26 -06:00
}
2009-10-17 15:51:44 -07:00
2009-06-11 00:45:59 -05:00
// 0x200
2010-04-07 19:14:10 +02:00
if ( flags & UPDATEFLAG_ROTATION )
2009-06-11 00:45:59 -05:00
{
2012-01-14 15:34:41 +01:00
* data << int64 ((( GameObject * ) this ) -> GetRotation ());
2009-06-11 00:45:59 -05:00
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
void Object :: _BuildValuesUpdate ( uint8 updatetype , ByteBuffer * data , UpdateMask * updateMask , Player * target ) const
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( ! target )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bool IsActivateToQuest = false ;
if ( updatetype == UPDATETYPE_CREATE_OBJECT || updatetype == UPDATETYPE_CREATE_OBJECT2 )
{
2009-11-27 01:41:26 +01:00
if ( isType ( TYPEMASK_GAMEOBJECT ) && ! (( GameObject * ) this ) -> IsDynTransport ())
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
if ((( GameObject * ) this ) -> ActivateToQuest ( target ) || target -> isGameMaster ())
2008-10-11 14:16:25 -05:00
IsActivateToQuest = true ;
2009-10-17 15:51:44 -07:00
2009-09-04 05:11:27 +02:00
updateMask -> SetBit ( GAMEOBJECT_DYNAMIC );
2009-10-17 15:51:44 -07:00
2009-01-04 17:14:34 -06:00
if ((( GameObject * ) this ) -> GetGoArtKit ())
updateMask -> SetBit ( GAMEOBJECT_BYTES_1 );
2008-10-11 14:16:25 -05:00
}
2009-07-30 17:16:56 +02:00
else if ( isType ( TYPEMASK_UNIT ))
{
2010-04-07 22:59:46 +02:00
if ((( Unit * ) this ) -> HasFlag ( UNIT_FIELD_AURASTATE , PER_CASTER_AURA_STATE_MASK ))
2009-07-30 17:16:56 +02:00
{
updateMask -> SetBit ( UNIT_FIELD_AURASTATE );
}
}
2008-10-11 14:16:25 -05:00
}
2009-05-31 15:56:51 -05:00
else // case UPDATETYPE_VALUES
2008-10-11 14:16:25 -05:00
{
if ( isType ( TYPEMASK_GAMEOBJECT ) && ! (( GameObject * ) this ) -> IsTransport ())
{
2010-04-07 22:59:46 +02:00
if ((( GameObject * ) this ) -> ActivateToQuest ( target ) || target -> isGameMaster ())
2008-10-11 14:16:25 -05:00
{
IsActivateToQuest = true ;
}
2008-12-24 09:58:26 -06:00
updateMask -> SetBit ( GAMEOBJECT_DYNAMIC );
updateMask -> SetBit ( GAMEOBJECT_BYTES_1 );
2008-10-11 14:16:25 -05:00
}
2009-07-30 17:16:56 +02:00
else if ( isType ( TYPEMASK_UNIT ))
{
2010-04-07 22:59:46 +02:00
if ((( Unit * ) this ) -> HasFlag ( UNIT_FIELD_AURASTATE , PER_CASTER_AURA_STATE_MASK ))
2009-07-30 17:16:56 +02:00
{
updateMask -> SetBit ( UNIT_FIELD_AURASTATE );
}
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
WPAssert ( updateMask && updateMask -> GetCount () == m_valuesCount );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
* data << ( uint8 ) updateMask -> GetBlockCount ();
2010-04-07 22:59:46 +02:00
data -> append ( updateMask -> GetMask (), updateMask -> GetLength ());
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// 2 specialized loops for speed optimization in non-unit case
2010-04-07 19:14:10 +02:00
if ( isType ( TYPEMASK_UNIT )) // unit (creature/player) case
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
for ( uint16 index = 0 ; index < m_valuesCount ; ++ index )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
if ( updateMask -> GetBit ( index ))
2008-10-11 14:16:25 -05:00
{
2010-03-14 00:22:53 +01:00
if ( index == UNIT_NPC_FLAGS )
2009-05-05 16:56:15 -05:00
{
// remove custom flag before sending
2011-08-28 17:36:02 +02:00
uint32 appendValue = m_uint32Values [ index ];
2009-10-17 15:51:44 -07:00
2009-12-19 18:29:09 +01:00
if ( GetTypeId () == TYPEID_UNIT )
{
2010-03-07 18:30:53 +01:00
if ( ! target -> canSeeSpellClickOn ( this -> ToCreature ()))
2009-12-19 18:29:09 +01:00
appendValue &= ~ UNIT_NPC_FLAG_SPELLCLICK ;
if ( appendValue & UNIT_NPC_FLAG_TRAINER )
{
2010-03-07 18:30:53 +01:00
if ( ! this -> ToCreature () -> isCanTrainingOf ( target , false ))
2009-12-19 18:29:09 +01:00
appendValue &= ~ ( UNIT_NPC_FLAG_TRAINER | UNIT_NPC_FLAG_TRAINER_CLASS | UNIT_NPC_FLAG_TRAINER_PROFESSION );
}
}
2009-10-17 15:51:44 -07:00
2009-05-05 16:56:15 -05:00
* data << uint32 ( appendValue );
}
2009-07-30 17:16:56 +02:00
else if ( index == UNIT_FIELD_AURASTATE )
{
// Check per caster aura states to not enable using a pell in client if specified aura is not by target
* data << (( Unit * ) this ) -> BuildAuraStateUpdateForTarget ( target );
}
2008-10-11 14:16:25 -05:00
// FIXME: Some values at server stored in float format but must be sent to client in uint32 format
2010-03-14 00:22:53 +01:00
else if ( index >= UNIT_FIELD_BASEATTACKTIME && index <= UNIT_FIELD_RANGEDATTACKTIME )
2008-10-11 14:16:25 -05:00
{
// convert from float to uint32 and send
2011-08-28 17:36:02 +02:00
* data << uint32 ( m_floatValues [ index ] < 0 ? 0 : m_floatValues [ index ]);
2008-10-11 14:16:25 -05:00
}
// there are some float values which may be negative or can't get negative due to other checks
2009-05-03 22:21:46 -05:00
else if (( index >= UNIT_FIELD_NEGSTAT0 && index <= UNIT_FIELD_NEGSTAT4 ) ||
( index >= UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE && index <= ( UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE + 6 )) ||
( index >= UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE && index <= ( UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE + 6 )) ||
( index >= UNIT_FIELD_POSSTAT0 && index <= UNIT_FIELD_POSSTAT4 ))
2008-10-11 14:16:25 -05:00
{
2011-08-28 17:36:02 +02:00
* data << uint32 ( m_floatValues [ index ]);
2008-10-11 14:16:25 -05:00
}
// Gamemasters should be always able to select units - remove not selectable flag
2010-04-07 19:14:10 +02:00
else if ( index == UNIT_FIELD_FLAGS )
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( target -> isGameMaster ())
2011-08-28 17:36:02 +02:00
* data << ( m_uint32Values [ index ] & ~ UNIT_FLAG_NOT_SELECTABLE );
2009-05-24 12:56:09 -05:00
else
2011-08-28 17:36:02 +02:00
* data << m_uint32Values [ index ];
2008-10-11 14:16:25 -05:00
}
2008-10-20 13:41:05 -05:00
// use modelid_a if not gm, _h if gm for CREATURE_FLAG_EXTRA_TRIGGER creatures
2010-04-07 19:14:10 +02:00
else if ( index == UNIT_FIELD_DISPLAYID )
2008-10-20 13:41:05 -05:00
{
2010-04-07 19:14:10 +02:00
if ( GetTypeId () == TYPEID_UNIT )
2008-10-20 13:41:05 -05:00
{
2011-08-28 17:36:02 +02:00
CreatureTemplate const * cinfo = ToCreature () -> GetCreatureInfo ();
// this also applies for transform auras
if ( SpellInfo const * transform = sSpellMgr -> GetSpellInfo ( ToUnit () -> getTransForm ()))
for ( uint8 i = 0 ; i < MAX_SPELL_EFFECTS ; ++ i )
if ( transform -> Effects [ i ]. IsAura ( SPELL_AURA_TRANSFORM ))
if ( CreatureTemplate const * transformInfo = sObjectMgr -> GetCreatureTemplate ( transform -> Effects [ i ]. MiscValue ))
{
cinfo = transformInfo ;
break ;
}
2010-04-07 19:14:10 +02:00
if ( cinfo -> flags_extra & CREATURE_FLAG_EXTRA_TRIGGER )
2008-11-09 14:54:13 -06:00
{
2010-04-07 19:14:10 +02:00
if ( target -> isGameMaster ())
2009-05-24 12:56:09 -05:00
{
2010-04-07 19:14:10 +02:00
if ( cinfo -> Modelid1 )
2010-04-21 13:55:43 +02:00
* data << cinfo -> Modelid1 ; //Modelid1 is a visible model for gms
2009-05-24 12:56:09 -05:00
else
* data << 17519 ; // world invisible trigger's model
}
2008-11-09 14:54:13 -06:00
else
2009-05-24 12:56:09 -05:00
{
2010-04-21 13:55:43 +02:00
if ( cinfo -> Modelid2 )
* data << cinfo -> Modelid2 ; //Modelid2 is an invisible model for players
2009-05-24 12:56:09 -05:00
else
* data << 11686 ; // world invisible trigger's model
}
2008-11-09 14:54:13 -06:00
}
2008-10-20 13:41:05 -05:00
else
2011-08-28 17:36:02 +02:00
* data << m_uint32Values [ index ];
2008-10-20 13:41:05 -05:00
}
else
2011-08-28 17:36:02 +02:00
* data << m_uint32Values [ index ];
2008-10-20 13:41:05 -05:00
}
2008-10-11 14:16:25 -05:00
// hide lootable animation for unallowed players
2010-03-14 00:22:53 +01:00
else if ( index == UNIT_DYNAMIC_FLAGS )
2008-10-11 14:16:25 -05:00
{
2010-03-14 00:22:53 +01:00
uint32 dynamicFlags = m_uint32Values [ index ];
if ( const Creature * creature = ToCreature ())
2009-05-24 12:56:09 -05:00
{
2010-03-14 00:22:53 +01:00
if ( creature -> hasLootRecipient ())
{
if ( creature -> isTappedBy ( target ))
{
2011-08-28 17:36:02 +02:00
dynamicFlags |= ( UNIT_DYNFLAG_TAPPED | UNIT_DYNFLAG_TAPPED_BY_PLAYER );
2010-03-14 00:22:53 +01:00
}
else
{
dynamicFlags |= UNIT_DYNFLAG_TAPPED ;
dynamicFlags &= ~ UNIT_DYNFLAG_TAPPED_BY_PLAYER ;
}
}
2009-05-24 12:56:09 -05:00
else
2010-03-14 00:22:53 +01:00
{
dynamicFlags &= ~ UNIT_DYNFLAG_TAPPED ;
dynamicFlags &= ~ UNIT_DYNFLAG_TAPPED_BY_PLAYER ;
}
2010-08-02 17:28:47 +02:00
if ( ! target -> isAllowedToLoot ( creature ))
2010-03-14 00:22:53 +01:00
dynamicFlags &= ~ UNIT_DYNFLAG_LOOTABLE ;
2009-05-24 12:56:09 -05:00
}
2010-03-14 00:22:53 +01:00
* data << dynamicFlags ;
2008-10-11 14:16:25 -05:00
}
2009-01-15 21:29:32 -05:00
// FG: pretend that OTHER players in own group are friendly ("blue")
2010-04-07 19:14:10 +02:00
else if ( index == UNIT_FIELD_BYTES_2 || index == UNIT_FIELD_FACTIONTEMPLATE )
2009-01-15 21:29:32 -05:00
{
2011-08-28 17:36:02 +02:00
Unit const * unit = ToUnit ();
if ( unit -> IsControlledByPlayer () && target != this && sWorld -> getBoolConfig ( CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP ) && unit -> IsInRaidWith ( target ))
2009-01-15 21:29:32 -05:00
{
2011-08-28 17:36:02 +02:00
FactionTemplateEntry const * ft1 = unit -> getFactionTemplateEntry ();
FactionTemplateEntry const * ft2 = target -> getFactionTemplateEntry ();
2010-04-07 19:14:10 +02:00
if ( ft1 && ft2 && ! ft1 -> IsFriendlyTo ( * ft2 ))
2009-01-15 21:29:32 -05:00
{
2010-04-07 19:14:10 +02:00
if ( index == UNIT_FIELD_BYTES_2 )
2009-01-15 21:29:32 -05:00
{
2009-05-24 12:56:09 -05:00
// Allow targetting opposite faction in party when enabled in config
2011-08-28 17:36:02 +02:00
* data << ( m_uint32Values [ index ] & (( UNIT_BYTE2_FLAG_SANCTUARY /*| UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5*/ ) << 8 )); // this flag is at uint8 offset 1 !!
2009-05-24 12:56:09 -05:00
}
else
{
// pretend that all other HOSTILE players have own faction, to allow follow, heal, rezz (trade wont work)
uint32 faction = target -> getFaction ();
2009-01-15 21:29:32 -05:00
* data << uint32 ( faction );
}
}
2009-05-24 12:56:09 -05:00
else
2011-08-28 17:36:02 +02:00
* data << m_uint32Values [ index ];
2009-01-15 21:29:32 -05:00
}
2009-05-24 12:56:09 -05:00
else
2011-08-28 17:36:02 +02:00
* data << m_uint32Values [ index ];
2009-10-17 16:20:24 -07:00
}
2008-10-11 14:16:25 -05:00
else
{
// send in current format (float as float, uint32 as uint32)
2011-08-28 17:36:02 +02:00
* data << m_uint32Values [ index ];
2008-10-11 14:16:25 -05:00
}
}
}
}
2010-04-07 19:14:10 +02:00
else if ( isType ( TYPEMASK_GAMEOBJECT )) // gameobject case
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
for ( uint16 index = 0 ; index < m_valuesCount ; ++ index )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
if ( updateMask -> GetBit ( index ))
2008-10-11 14:16:25 -05:00
{
// send in current format (float as float, uint32 as uint32)
2010-04-07 22:59:46 +02:00
if ( index == GAMEOBJECT_DYNAMIC )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
if ( IsActivateToQuest )
2008-10-11 14:16:25 -05:00
{
2011-08-28 17:36:02 +02:00
switch ( ToGameObject () -> GetGoType ())
2008-10-11 14:16:25 -05:00
{
case GAMEOBJECT_TYPE_CHEST :
2010-10-08 17:48:44 -06:00
if ( target -> isGameMaster ())
2010-10-08 18:38:58 -06:00
* data << uint16 ( GO_DYNFLAG_LO_ACTIVATE );
2010-10-08 17:48:44 -06:00
else
2010-10-08 18:38:58 -06:00
* data << uint16 ( GO_DYNFLAG_LO_ACTIVATE | GO_DYNFLAG_LO_SPARKLE );
2010-10-09 01:48:32 -06:00
* data << uint16 ( - 1 );
2008-10-11 14:16:25 -05:00
break ;
2010-10-06 16:36:50 -06:00
case GAMEOBJECT_TYPE_GENERIC :
2010-10-08 17:48:44 -06:00
if ( target -> isGameMaster ())
* data << uint16 ( 0 );
else
2010-10-08 18:38:58 -06:00
* data << uint16 ( GO_DYNFLAG_LO_SPARKLE );
2010-10-09 01:48:32 -06:00
* data << uint16 ( - 1 );
2010-10-06 16:36:50 -06:00
break ;
2008-10-11 14:16:25 -05:00
case GAMEOBJECT_TYPE_GOOBER :
2010-10-08 17:48:44 -06:00
if ( target -> isGameMaster ())
2010-10-08 18:38:58 -06:00
* data << uint16 ( GO_DYNFLAG_LO_ACTIVATE );
2010-10-08 17:48:44 -06:00
else
2010-10-08 18:38:58 -06:00
* data << uint16 ( GO_DYNFLAG_LO_ACTIVATE | GO_DYNFLAG_LO_SPARKLE );
2010-10-09 01:48:32 -06:00
* data << uint16 ( - 1 );
2008-10-11 14:16:25 -05:00
break ;
default :
2009-09-04 05:11:27 +02:00
// unknown, not happen.
* data << uint16 ( 0 );
* data << uint16 ( - 1 );
2008-10-11 14:16:25 -05:00
break ;
}
}
else
2009-09-04 05:11:27 +02:00
{
// disable quest object
* data << uint16 ( 0 );
* data << uint16 ( - 1 );
}
2008-10-11 14:16:25 -05:00
}
else
2011-08-28 17:36:02 +02:00
* data << m_uint32Values [ index ]; // other cases
2008-10-11 14:16:25 -05:00
}
}
}
else // other objects case (no special index checks)
{
2010-04-07 22:59:46 +02:00
for ( uint16 index = 0 ; index < m_valuesCount ; ++ index )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
if ( updateMask -> GetBit ( index ))
2008-10-11 14:16:25 -05:00
{
// send in current format (float as float, uint32 as uint32)
2011-08-28 17:36:02 +02:00
* data << m_uint32Values [ index ];
2008-10-11 14:16:25 -05:00
}
}
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Object :: ClearUpdateMask ( bool remove )
{
2011-08-30 12:38:41 +02:00
memset ( _changedFields , 0 , m_valuesCount * sizeof ( bool ));
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( m_objectUpdated )
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( remove )
2010-12-23 23:25:44 +01:00
sObjectAccessor -> RemoveUpdateObject ( this );
2008-10-11 14:16:25 -05:00
m_objectUpdated = false ;
}
}
2009-10-17 15:51:44 -07:00
2011-11-07 11:18:00 -06:00
void Object :: BuildFieldsUpdate ( Player * player , UpdateDataMapType & data_map ) const
2009-12-19 19:46:07 +01:00
{
2011-11-07 11:18:00 -06:00
UpdateDataMapType :: iterator iter = data_map . find ( player );
2009-12-19 19:46:07 +01:00
2010-04-07 22:59:46 +02:00
if ( iter == data_map . end ())
2010-02-03 16:53:40 +02:00
{
2011-11-07 11:18:00 -06:00
std :: pair < UpdateDataMapType :: iterator , bool > p = data_map . insert ( UpdateDataMapType :: value_type ( player , UpdateData ()));
2010-07-30 20:04:28 +02:00
ASSERT ( p . second );
2010-02-03 16:53:40 +02:00
iter = p . first ;
}
2009-12-19 19:46:07 +01:00
2010-02-03 16:53:40 +02:00
BuildValuesUpdateBlockForPlayer ( & iter -> second , iter -> first );
2009-12-19 19:46:07 +01:00
}
2011-08-28 18:31:37 +02:00
void Object :: _LoadIntoDataField ( char const * data , uint32 startOffset , uint32 count )
2010-07-30 13:15:31 +02:00
{
if ( ! data )
return ;
2010-10-21 16:56:51 +02:00
Tokens tokens ( data , ' ' , count );
2010-07-30 13:15:31 +02:00
if ( tokens . size () != count )
return ;
2010-10-21 16:56:51 +02:00
for ( uint32 index = 0 ; index < count ; ++ index )
2011-08-28 18:31:37 +02:00
{
2010-10-21 16:56:51 +02:00
m_uint32Values [ startOffset + index ] = atol ( tokens [ index ]);
2011-08-28 18:31:37 +02:00
_changedFields [ startOffset + index ] = true ;
}
2010-07-30 13:15:31 +02:00
}
2011-08-28 17:36:02 +02:00
void Object :: _SetUpdateBits ( UpdateMask * updateMask , Player * /*target*/ ) const
2008-10-11 14:16:25 -05:00
{
2011-08-28 18:31:37 +02:00
bool * indexes = _changedFields ;
2009-10-17 15:51:44 -07:00
2011-08-28 18:31:37 +02:00
for ( uint16 index = 0 ; index < m_valuesCount ; ++ index , ++ indexes )
2008-10-11 14:16:25 -05:00
{
2011-08-28 18:31:37 +02:00
if ( * indexes )
2008-10-11 14:16:25 -05:00
updateMask -> SetBit ( index );
}
}
2009-10-17 15:51:44 -07:00
2011-08-28 17:36:02 +02:00
void Object :: _SetCreateBits ( UpdateMask * updateMask , Player * /*target*/ ) const
2008-10-11 14:16:25 -05:00
{
2011-08-28 17:36:02 +02:00
uint32 * value = m_uint32Values ;
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( uint16 index = 0 ; index < m_valuesCount ; ++ index , ++ value )
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( * value )
2008-10-11 14:16:25 -05:00
updateMask -> SetBit ( index );
}
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void Object :: SetInt32Value ( uint16 index , int32 value )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
ASSERT ( index < m_valuesCount || PrintIndexError ( index , true ));
2009-10-17 15:51:44 -07:00
2011-08-28 18:31:37 +02:00
if ( m_int32Values [ index ] != value )
2008-10-11 14:16:25 -05:00
{
2011-08-28 18:31:37 +02:00
m_int32Values [ index ] = value ;
_changedFields [ index ] = true ;
2009-10-17 15:51:44 -07:00
2011-08-30 13:46:36 +02:00
if ( m_inWorld && ! m_objectUpdated )
2008-10-11 14:16:25 -05:00
{
2011-08-30 13:46:36 +02:00
sObjectAccessor -> AddUpdateObject ( this );
m_objectUpdated = true ;
2008-10-11 14:16:25 -05:00
}
}
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void Object :: SetUInt32Value ( uint16 index , uint32 value )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
ASSERT ( index < m_valuesCount || PrintIndexError ( index , true ));
2009-10-17 15:51:44 -07:00
2011-08-28 18:31:37 +02:00
if ( m_uint32Values [ index ] != value )
2008-10-11 14:16:25 -05:00
{
2011-08-28 18:31:37 +02:00
m_uint32Values [ index ] = value ;
_changedFields [ index ] = true ;
2009-10-17 15:51:44 -07:00
2011-08-30 13:46:36 +02:00
if ( m_inWorld && ! m_objectUpdated )
2008-10-11 14:16:25 -05:00
{
2011-08-30 13:46:36 +02:00
sObjectAccessor -> AddUpdateObject ( this );
m_objectUpdated = true ;
2008-10-11 14:16:25 -05:00
}
}
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void Object :: UpdateUInt32Value ( uint16 index , uint32 value )
2009-09-02 15:05:18 -05:00
{
2010-04-07 22:59:46 +02:00
ASSERT ( index < m_valuesCount || PrintIndexError ( index , true ));
2009-10-17 15:51:44 -07:00
2011-08-28 18:31:37 +02:00
m_uint32Values [ index ] = value ;
_changedFields [ index ] = true ;
2009-09-02 15:05:18 -05:00
}
2009-10-17 15:51:44 -07:00
2011-08-30 13:46:36 +02:00
void Object :: SetUInt64Value ( uint16 index , uint64 value )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
ASSERT ( index + 1 < m_valuesCount || PrintIndexError ( index , true ));
2011-08-28 18:31:37 +02:00
if ( * (( uint64 * ) & ( m_uint32Values [ index ])) != value )
2008-10-11 14:16:25 -05:00
{
2011-08-30 13:46:36 +02:00
m_uint32Values [ index ] = PAIR64_LOPART ( value );
m_uint32Values [ index + 1 ] = PAIR64_HIPART ( value );
2011-08-28 18:31:37 +02:00
_changedFields [ index ] = true ;
_changedFields [ index + 1 ] = true ;
2009-10-17 15:51:44 -07:00
2011-08-30 13:46:36 +02:00
if ( m_inWorld && ! m_objectUpdated )
2008-10-11 14:16:25 -05:00
{
2011-08-30 13:46:36 +02:00
sObjectAccessor -> AddUpdateObject ( this );
m_objectUpdated = true ;
2008-10-11 14:16:25 -05:00
}
}
}
2009-10-17 15:51:44 -07:00
2011-08-30 13:46:36 +02:00
bool Object :: AddUInt64Value ( uint16 index , uint64 value )
2009-03-23 20:13:37 -06:00
{
2011-09-29 12:43:05 +02:00
ASSERT ( index + 1 < m_valuesCount || PrintIndexError ( index , true ));
2010-04-07 19:14:10 +02:00
if ( value && !* (( uint64 * ) & ( m_uint32Values [ index ])))
2009-03-23 20:13:37 -06:00
{
2011-08-30 13:46:36 +02:00
m_uint32Values [ index ] = PAIR64_LOPART ( value );
m_uint32Values [ index + 1 ] = PAIR64_HIPART ( value );
2011-08-28 18:31:37 +02:00
_changedFields [ index ] = true ;
_changedFields [ index + 1 ] = true ;
2009-10-17 15:51:44 -07:00
2011-08-30 13:46:36 +02:00
if ( m_inWorld && ! m_objectUpdated )
2009-03-23 20:13:37 -06:00
{
2011-08-30 13:46:36 +02:00
sObjectAccessor -> AddUpdateObject ( this );
m_objectUpdated = true ;
2009-03-23 20:13:37 -06:00
}
2011-08-30 13:46:36 +02:00
2009-03-23 20:13:37 -06:00
return true ;
}
2011-08-30 13:46:36 +02:00
2009-03-23 20:13:37 -06:00
return false ;
}
2009-10-17 15:51:44 -07:00
2011-08-30 13:46:36 +02:00
bool Object :: RemoveUInt64Value ( uint16 index , uint64 value )
2009-03-23 20:13:37 -06:00
{
2011-09-29 12:43:05 +02:00
ASSERT ( index + 1 < m_valuesCount || PrintIndexError ( index , true ));
2010-04-07 19:14:10 +02:00
if ( value && * (( uint64 * ) & ( m_uint32Values [ index ])) == value )
2009-03-23 20:13:37 -06:00
{
2011-08-28 18:31:37 +02:00
m_uint32Values [ index ] = 0 ;
m_uint32Values [ index + 1 ] = 0 ;
_changedFields [ index ] = true ;
_changedFields [ index + 1 ] = true ;
2009-10-17 15:51:44 -07:00
2011-08-30 13:46:36 +02:00
if ( m_inWorld && ! m_objectUpdated )
2009-03-23 20:13:37 -06:00
{
2011-08-30 13:46:36 +02:00
sObjectAccessor -> AddUpdateObject ( this );
m_objectUpdated = true ;
2009-03-23 20:13:37 -06:00
}
2011-08-28 17:36:02 +02:00
2009-03-23 20:13:37 -06:00
return true ;
}
2011-08-28 17:36:02 +02:00
2009-03-23 20:13:37 -06:00
return false ;
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void Object :: SetFloatValue ( uint16 index , float value )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
ASSERT ( index < m_valuesCount || PrintIndexError ( index , true ));
2009-10-17 15:51:44 -07:00
2011-08-28 18:31:37 +02:00
if ( m_floatValues [ index ] != value )
2008-10-11 14:16:25 -05:00
{
2011-08-28 18:31:37 +02:00
m_floatValues [ index ] = value ;
_changedFields [ index ] = true ;
2009-10-17 15:51:44 -07:00
2011-08-30 13:46:36 +02:00
if ( m_inWorld && ! m_objectUpdated )
2008-10-11 14:16:25 -05:00
{
2011-08-30 13:46:36 +02:00
sObjectAccessor -> AddUpdateObject ( this );
m_objectUpdated = true ;
2008-10-11 14:16:25 -05:00
}
}
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void Object :: SetByteValue ( uint16 index , uint8 offset , uint8 value )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
ASSERT ( index < m_valuesCount || PrintIndexError ( index , true ));
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( offset > 4 )
2008-10-11 14:16:25 -05:00
{
2010-12-23 23:25:44 +01:00
sLog -> outError ( "Object::SetByteValue: wrong offset %u" , offset );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2011-08-28 18:31:37 +02:00
if ( uint8 ( m_uint32Values [ index ] >> ( offset * 8 )) != value )
2008-10-11 14:16:25 -05:00
{
2011-08-28 18:31:37 +02:00
m_uint32Values [ index ] &= ~ uint32 ( uint32 ( 0xFF ) << ( offset * 8 ));
m_uint32Values [ index ] |= uint32 ( uint32 ( value ) << ( offset * 8 ));
_changedFields [ index ] = true ;
2009-10-17 15:51:44 -07:00
2011-08-30 13:46:36 +02:00
if ( m_inWorld && ! m_objectUpdated )
2008-10-11 14:16:25 -05:00
{
2011-08-30 13:46:36 +02:00
sObjectAccessor -> AddUpdateObject ( this );
m_objectUpdated = true ;
2008-10-11 14:16:25 -05:00
}
}
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void Object :: SetUInt16Value ( uint16 index , uint8 offset , uint16 value )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
ASSERT ( index < m_valuesCount || PrintIndexError ( index , true ));
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( offset > 2 )
2008-10-11 14:16:25 -05:00
{
2010-12-23 23:25:44 +01:00
sLog -> outError ( "Object::SetUInt16Value: wrong offset %u" , offset );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2011-08-28 18:31:37 +02:00
if ( uint16 ( m_uint32Values [ index ] >> ( offset * 16 )) != value )
2008-10-11 14:16:25 -05:00
{
2011-08-28 18:31:37 +02:00
m_uint32Values [ index ] &= ~ uint32 ( uint32 ( 0xFFFF ) << ( offset * 16 ));
m_uint32Values [ index ] |= uint32 ( uint32 ( value ) << ( offset * 16 ));
_changedFields [ index ] = true ;
2009-10-17 15:51:44 -07:00
2011-08-30 13:46:36 +02:00
if ( m_inWorld && ! m_objectUpdated )
2008-10-11 14:16:25 -05:00
{
2011-08-30 13:46:36 +02:00
sObjectAccessor -> AddUpdateObject ( this );
m_objectUpdated = true ;
2008-10-11 14:16:25 -05:00
}
}
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void Object :: SetStatFloatValue ( uint16 index , float value )
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( value < 0 )
2008-10-11 14:16:25 -05:00
value = 0.0f ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
SetFloatValue ( index , value );
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void Object :: SetStatInt32Value ( uint16 index , int32 value )
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( value < 0 )
2008-10-11 14:16:25 -05:00
value = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
SetUInt32Value ( index , uint32 ( value ));
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Object :: ApplyModUInt32Value ( uint16 index , int32 val , bool apply )
{
int32 cur = GetUInt32Value ( index );
cur += ( apply ? val : - val );
2010-04-07 19:14:10 +02:00
if ( cur < 0 )
2008-10-11 14:16:25 -05:00
cur = 0 ;
2009-05-31 15:56:51 -05:00
SetUInt32Value ( index , cur );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Object :: ApplyModInt32Value ( uint16 index , int32 val , bool apply )
{
int32 cur = GetInt32Value ( index );
cur += ( apply ? val : - val );
2009-05-31 15:56:51 -05:00
SetInt32Value ( index , cur );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Object :: ApplyModSignedFloatValue ( uint16 index , float val , bool apply )
{
float cur = GetFloatValue ( index );
cur += ( apply ? val : - val );
2009-05-31 15:56:51 -05:00
SetFloatValue ( index , cur );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Object :: ApplyModPositiveFloatValue ( uint16 index , float val , bool apply )
{
float cur = GetFloatValue ( index );
cur += ( apply ? val : - val );
2010-04-07 19:14:10 +02:00
if ( cur < 0 )
2008-10-11 14:16:25 -05:00
cur = 0 ;
2009-05-31 15:56:51 -05:00
SetFloatValue ( index , cur );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void Object :: SetFlag ( uint16 index , uint32 newFlag )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
ASSERT ( index < m_valuesCount || PrintIndexError ( index , true ));
2011-08-28 18:31:37 +02:00
uint32 oldval = m_uint32Values [ index ];
2008-10-11 14:16:25 -05:00
uint32 newval = oldval | newFlag ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( oldval != newval )
2008-10-11 14:16:25 -05:00
{
2011-08-28 18:31:37 +02:00
m_uint32Values [ index ] = newval ;
_changedFields [ index ] = true ;
2009-10-17 15:51:44 -07:00
2011-08-30 13:46:36 +02:00
if ( m_inWorld && ! m_objectUpdated )
2008-10-11 14:16:25 -05:00
{
2011-08-30 13:46:36 +02:00
sObjectAccessor -> AddUpdateObject ( this );
m_objectUpdated = true ;
2008-10-11 14:16:25 -05:00
}
}
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void Object :: RemoveFlag ( uint16 index , uint32 oldFlag )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
ASSERT ( index < m_valuesCount || PrintIndexError ( index , true ));
2010-09-21 19:26:59 -07:00
ASSERT ( m_uint32Values );
2011-08-28 18:31:37 +02:00
uint32 oldval = m_uint32Values [ index ];
2008-10-11 14:16:25 -05:00
uint32 newval = oldval & ~ oldFlag ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( oldval != newval )
2008-10-11 14:16:25 -05:00
{
2011-08-28 18:31:37 +02:00
m_uint32Values [ index ] = newval ;
_changedFields [ index ] = true ;
2009-10-17 15:51:44 -07:00
2011-08-30 13:46:36 +02:00
if ( m_inWorld && ! m_objectUpdated )
2008-10-11 14:16:25 -05:00
{
2011-08-30 13:46:36 +02:00
sObjectAccessor -> AddUpdateObject ( this );
m_objectUpdated = true ;
2008-10-11 14:16:25 -05:00
}
}
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void Object :: SetByteFlag ( uint16 index , uint8 offset , uint8 newFlag )
2008-12-12 11:21:28 -06:00
{
2010-04-07 22:59:46 +02:00
ASSERT ( index < m_valuesCount || PrintIndexError ( index , true ));
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( offset > 4 )
2008-12-12 11:21:28 -06:00
{
2010-12-23 23:25:44 +01:00
sLog -> outError ( "Object::SetByteFlag: wrong offset %u" , offset );
2008-12-12 11:21:28 -06:00
return ;
}
2009-10-17 15:51:44 -07:00
2011-08-28 18:31:37 +02:00
if ( ! ( uint8 ( m_uint32Values [ index ] >> ( offset * 8 )) & newFlag ))
2008-12-12 11:21:28 -06:00
{
2011-08-28 18:31:37 +02:00
m_uint32Values [ index ] |= uint32 ( uint32 ( newFlag ) << ( offset * 8 ));
_changedFields [ index ] = true ;
2009-10-17 15:51:44 -07:00
2011-08-30 13:46:36 +02:00
if ( m_inWorld && ! m_objectUpdated )
2008-12-12 11:21:28 -06:00
{
2011-08-30 13:46:36 +02:00
sObjectAccessor -> AddUpdateObject ( this );
m_objectUpdated = true ;
2008-12-12 11:21:28 -06:00
}
}
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void Object :: RemoveByteFlag ( uint16 index , uint8 offset , uint8 oldFlag )
2008-12-12 11:21:28 -06:00
{
2010-04-07 22:59:46 +02:00
ASSERT ( index < m_valuesCount || PrintIndexError ( index , true ));
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( offset > 4 )
2008-12-12 11:21:28 -06:00
{
2010-12-23 23:25:44 +01:00
sLog -> outError ( "Object::RemoveByteFlag: wrong offset %u" , offset );
2008-12-12 11:21:28 -06:00
return ;
}
2009-10-17 15:51:44 -07:00
2011-08-28 18:31:37 +02:00
if ( uint8 ( m_uint32Values [ index ] >> ( offset * 8 )) & oldFlag )
2008-12-12 11:21:28 -06:00
{
2011-08-28 18:31:37 +02:00
m_uint32Values [ index ] &= ~ uint32 ( uint32 ( oldFlag ) << ( offset * 8 ));
_changedFields [ index ] = true ;
2009-10-17 15:51:44 -07:00
2011-08-30 13:46:36 +02:00
if ( m_inWorld && ! m_objectUpdated )
2008-12-12 11:21:28 -06:00
{
2011-08-30 13:46:36 +02:00
sObjectAccessor -> AddUpdateObject ( this );
m_objectUpdated = true ;
2008-12-12 11:21:28 -06:00
}
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bool Object :: PrintIndexError ( uint32 index , bool set ) const
{
2011-04-29 20:47:02 +02:00
sLog -> outError ( "Attempt %s non-existed value field: %u (count: %u) for object typeid: %u type mask: %u" , ( set ? "set value to" : "get value from" ), index , m_valuesCount , GetTypeId (), m_objectType );
2009-10-17 15:51:44 -07:00
2010-07-30 20:04:28 +02:00
// ASSERT must fail after function call
2008-10-11 14:16:25 -05:00
return false ;
}
2009-10-17 15:51:44 -07:00
2011-08-28 17:36:02 +02:00
bool Position :: HasInLine ( Unit const * target , float distance , float width ) const
2009-08-29 14:58:45 -05:00
{
2010-02-14 19:13:14 -07:00
if ( ! HasInArc ( M_PI , target ) || ! target -> IsWithinDist3d ( m_positionX , m_positionY , m_positionZ , distance ))
return false ;
2009-08-29 14:58:45 -05:00
width += target -> GetObjectSize ();
float angle = GetRelativeAngle ( target );
2011-02-15 17:09:46 +01:00
return fabs ( sin ( angle )) * GetExactDist2d ( target -> GetPositionX (), target -> GetPositionY ()) < width ;
2009-08-29 14:58:45 -05:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 20:32:14 +02:00
std :: string Position :: ToString () const
{
std :: stringstream sstr ;
sstr << "X: " << m_positionX << " Y: " << m_positionY << " Z: " << m_positionZ << " O: " << m_orientation ;
return sstr . str ();
}
2011-08-28 17:36:02 +02:00
ByteBuffer & operator >> ( ByteBuffer & buf , Position :: PositionXYZOStreamer const & streamer )
2010-08-04 14:39:45 +02:00
{
float x , y , z , o ;
buf >> x >> y >> z >> o ;
streamer . m_pos -> Relocate ( x , y , z , o );
return buf ;
}
2011-08-28 17:36:02 +02:00
ByteBuffer & operator << ( ByteBuffer & buf , Position :: PositionXYZStreamer const & streamer )
2010-08-04 14:39:45 +02:00
{
float x , y , z ;
streamer . m_pos -> GetPosition ( x , y , z );
buf << x << y << z ;
return buf ;
}
2011-08-28 17:36:02 +02:00
ByteBuffer & operator >> ( ByteBuffer & buf , Position :: PositionXYZStreamer const & streamer )
2010-08-04 14:39:45 +02:00
{
float x , y , z ;
buf >> x >> y >> z ;
streamer . m_pos -> Relocate ( x , y , z );
return buf ;
}
2011-08-28 17:36:02 +02:00
ByteBuffer & operator << ( ByteBuffer & buf , Position :: PositionXYZOStreamer const & streamer )
2010-08-04 14:39:45 +02:00
{
float x , y , z , o ;
streamer . m_pos -> GetPosition ( x , y , z , o );
buf << x << y << z << o ;
return buf ;
}
2010-08-08 20:32:14 +02:00
void MovementInfo :: OutDebug ()
{
2010-12-23 23:25:44 +01:00
sLog -> outString ( "MOVEMENT INFO" );
sLog -> outString ( "guid " UI64FMTD , guid );
sLog -> outString ( "flags %u" , flags );
sLog -> outString ( "flags2 %u" , flags2 );
sLog -> outString ( "time %u current time " UI64FMTD "" , flags2 , uint64 ( :: time ( NULL )));
sLog -> outString ( "position: `%s`" , pos . ToString (). c_str ());
2010-08-08 20:32:14 +02:00
if ( flags & MOVEMENTFLAG_ONTRANSPORT )
{
2010-12-23 23:25:44 +01:00
sLog -> outString ( "TRANSPORT:" );
sLog -> outString ( "guid: " UI64FMTD , t_guid );
sLog -> outString ( "position: `%s`" , t_pos . ToString (). c_str ());
sLog -> outString ( "seat: %i" , t_seat );
sLog -> outString ( "time: %u" , t_time );
2010-08-08 20:32:14 +02:00
if ( flags2 & MOVEMENTFLAG2_INTERPOLATED_MOVEMENT )
2010-12-23 23:25:44 +01:00
sLog -> outString ( "time2: %u" , t_time2 );
2010-08-08 20:32:14 +02:00
}
2011-08-28 17:36:02 +02:00
2010-08-08 20:32:14 +02:00
if (( flags & ( MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING )) || ( flags2 & MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING ))
2010-12-23 23:25:44 +01:00
sLog -> outString ( "pitch: %f" , pitch );
2011-08-28 17:36:02 +02:00
2010-12-23 23:25:44 +01:00
sLog -> outString ( "fallTime: %u" , fallTime );
2010-08-08 20:32:14 +02:00
if ( flags & MOVEMENTFLAG_JUMPING )
2010-12-23 23:25:44 +01:00
sLog -> outString ( "j_zspeed: %f j_sinAngle: %f j_cosAngle: %f j_xyspeed: %f" , j_zspeed , j_sinAngle , j_cosAngle , j_xyspeed );
2011-08-28 17:36:02 +02:00
2010-08-08 20:32:14 +02:00
if ( flags & MOVEMENTFLAG_SPLINE_ELEVATION )
2010-12-23 23:25:44 +01:00
sLog -> outString ( "splineElevation: %f" , splineElevation );
2010-08-08 20:32:14 +02:00
}
2011-12-20 17:05:08 -05:00
WorldObject :: WorldObject ( bool isWorldObject ) : WorldLocation (),
2011-12-28 11:00:27 +01:00
m_name ( "" ), m_isActive ( false ), m_isWorldObject ( isWorldObject ), m_zoneScript ( NULL ),
2010-08-21 20:08:47 +02:00
m_transport ( NULL ), m_currMap ( NULL ), m_InstanceId ( 0 ),
m_phaseMask ( PHASEMASK_NORMAL ), m_notifyflags ( 0 ), m_executed_notifies ( 0 )
2010-11-13 17:18:09 +01:00
{
m_serverSideVisibility . SetValue ( SERVERSIDE_VISIBILITY_GHOST , GHOST_VISIBILITY_ALIVE | GHOST_VISIBILITY_GHOST );
m_serverSideVisibilityDetect . SetValue ( SERVERSIDE_VISIBILITY_GHOST , GHOST_VISIBILITY_ALIVE );
}
2009-10-17 15:51:44 -07:00
2009-02-26 16:29:55 -06:00
void WorldObject :: SetWorldObject ( bool on )
2008-10-27 08:41:55 -05:00
{
2010-04-07 19:14:10 +02:00
if ( ! IsInWorld ())
2009-02-26 16:29:55 -06:00
return ;
2009-10-17 15:51:44 -07:00
2009-04-06 21:14:51 +02:00
GetMap () -> AddObjectToSwitchList ( this , on );
2009-02-26 16:29:55 -06:00
}
2009-10-17 15:51:44 -07:00
2011-12-20 17:05:08 -05:00
bool WorldObject :: IsWorldObject () const
{
if ( m_isWorldObject )
return true ;
if ( ToCreature () && ToCreature () -> m_isTempWorldObject )
return true ;
return false ;
}
2010-04-07 22:59:46 +02:00
void WorldObject :: setActive ( bool on )
2008-10-27 08:41:55 -05:00
{
2010-04-07 19:14:10 +02:00
if ( m_isActive == on )
2008-10-27 08:41:55 -05:00
return ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( GetTypeId () == TYPEID_PLAYER )
2008-10-27 08:41:55 -05:00
return ;
2009-10-17 15:51:44 -07:00
2009-03-25 21:32:34 -06:00
m_isActive = on ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( ! IsInWorld ())
2009-03-25 21:32:34 -06:00
return ;
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
Map * map = FindMap ();
2010-04-07 19:14:10 +02:00
if ( ! map )
2009-03-25 21:32:34 -06:00
return ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( on )
2009-02-25 20:52:20 -06:00
{
2010-04-07 19:14:10 +02:00
if ( GetTypeId () == TYPEID_UNIT )
2010-03-07 18:30:53 +01:00
map -> AddToActive ( this -> ToCreature ());
2010-04-07 19:14:10 +02:00
else if ( GetTypeId () == TYPEID_DYNAMICOBJECT )
2009-02-26 10:42:37 -06:00
map -> AddToActive (( DynamicObject * ) this );
2008-10-27 08:41:55 -05:00
}
2009-03-25 21:32:34 -06:00
else
{
2010-04-07 19:14:10 +02:00
if ( GetTypeId () == TYPEID_UNIT )
2010-03-07 18:30:53 +01:00
map -> RemoveFromActive ( this -> ToCreature ());
2010-04-07 19:14:10 +02:00
else if ( GetTypeId () == TYPEID_DYNAMICOBJECT )
2009-03-25 21:32:34 -06:00
map -> RemoveFromActive (( DynamicObject * ) this );
}
2008-10-27 08:41:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-04-19 09:26:37 +02:00
void WorldObject :: CleanupsBeforeDelete ( bool /*finalCleanup*/ )
2009-07-01 18:23:36 -05:00
{
2011-11-11 14:11:58 -05:00
if ( IsInWorld ())
RemoveFromWorld ();
2009-07-01 18:23:36 -05:00
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void WorldObject :: _Create ( uint32 guidlow , HighGuid guidhigh , uint32 phaseMask )
2008-10-11 14:16:25 -05:00
{
Object :: _Create ( guidlow , 0 , guidhigh );
2009-01-31 16:38:50 -06:00
m_phaseMask = phaseMask ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 WorldObject :: GetZoneId () const
{
2009-06-16 11:19:59 -05:00
return GetBaseMap () -> GetZoneId ( m_positionX , m_positionY , m_positionZ );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 WorldObject :: GetAreaId () const
{
2009-06-16 11:19:59 -05:00
return GetBaseMap () -> GetAreaId ( m_positionX , m_positionY , m_positionZ );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-03-11 16:17:37 -06:00
void WorldObject :: GetZoneAndAreaId ( uint32 & zoneid , uint32 & areaid ) const
{
2009-06-16 11:19:59 -05:00
GetBaseMap () -> GetZoneAndAreaId ( zoneid , areaid , m_positionX , m_positionY , m_positionZ );
2009-03-11 16:17:37 -06:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 22:54:58 +06:00
InstanceScript * WorldObject :: GetInstanceScript ()
2008-10-11 14:16:25 -05:00
{
2011-09-15 14:08:17 +02:00
Map * map = GetMap ();
2010-08-08 22:54:58 +06:00
return map -> IsDungeon () ? (( InstanceMap * ) map ) -> GetInstanceScript () : NULL ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
float WorldObject :: GetDistanceZ ( const WorldObject * obj ) const
{
float dz = fabs ( GetPositionZ () - obj -> GetPositionZ ());
float sizefactor = GetObjectSize () + obj -> GetObjectSize ();
float dist = dz - sizefactor ;
2010-04-07 22:59:46 +02:00
return ( dist > 0 ? dist : 0 );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
bool WorldObject :: _IsWithinDist ( WorldObject const * obj , float dist2compare , bool is3D ) const
{
2010-07-30 21:54:46 -07:00
float sizefactor = GetObjectSize () + obj -> GetObjectSize ();
float maxdist = dist2compare + sizefactor ;
if ( m_transport && obj -> GetTransport () && obj -> GetTransport () -> GetGUIDLow () == m_transport -> GetGUIDLow ())
{
2010-08-04 14:39:45 +02:00
float dtx = m_movementInfo . t_pos . m_positionX - obj -> m_movementInfo . t_pos . m_positionX ;
float dty = m_movementInfo . t_pos . m_positionY - obj -> m_movementInfo . t_pos . m_positionY ;
2010-07-30 21:54:46 -07:00
float disttsq = dtx * dtx + dty * dty ;
if ( is3D )
{
2010-08-04 14:39:45 +02:00
float dtz = m_movementInfo . t_pos . m_positionZ - obj -> m_movementInfo . t_pos . m_positionZ ;
2010-07-30 21:54:46 -07:00
disttsq += dtz * dtz ;
}
return disttsq < ( maxdist * maxdist );
}
2008-10-11 14:16:25 -05:00
float dx = GetPositionX () - obj -> GetPositionX ();
float dy = GetPositionY () - obj -> GetPositionY ();
2008-12-06 14:01:44 -06:00
float distsq = dx * dx + dy * dy ;
2010-04-07 19:14:10 +02:00
if ( is3D )
2008-12-06 14:01:44 -06:00
{
float dz = GetPositionZ () - obj -> GetPositionZ ();
distsq += dz * dz ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return distsq < maxdist * maxdist ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bool WorldObject :: IsWithinLOSInMap ( const WorldObject * obj ) const
{
2011-08-30 13:46:36 +02:00
if ( ! IsInMap ( obj ))
return false ;
2011-04-29 20:47:02 +02:00
float ox , oy , oz ;
obj -> GetPosition ( ox , oy , oz );
2010-04-07 22:59:46 +02:00
return ( IsWithinLOS ( ox , oy , oz ));
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
bool WorldObject :: IsWithinLOS ( float ox , float oy , float oz ) const
2008-10-11 14:16:25 -05:00
{
2011-04-29 20:47:02 +02:00
float x , y , z ;
GetPosition ( x , y , z );
2011-09-15 14:08:17 +02:00
VMAP :: IVMapManager * vMapManager = VMAP :: VMapFactory :: createOrGetVMapManager ();
2008-10-11 14:16:25 -05:00
return vMapManager -> isInLineOfSight ( GetMapId (), x , y , z + 2.0f , ox , oy , oz + 2.0f );
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
bool WorldObject :: GetDistanceOrder ( WorldObject const * obj1 , WorldObject const * obj2 , bool is3D /* = true */ ) const
{
float dx1 = GetPositionX () - obj1 -> GetPositionX ();
float dy1 = GetPositionY () - obj1 -> GetPositionY ();
float distsq1 = dx1 * dx1 + dy1 * dy1 ;
2010-04-07 19:14:10 +02:00
if ( is3D )
2009-05-14 16:50:47 -05:00
{
float dz1 = GetPositionZ () - obj1 -> GetPositionZ ();
distsq1 += dz1 * dz1 ;
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
float dx2 = GetPositionX () - obj2 -> GetPositionX ();
float dy2 = GetPositionY () - obj2 -> GetPositionY ();
float distsq2 = dx2 * dx2 + dy2 * dy2 ;
2010-04-07 19:14:10 +02:00
if ( is3D )
2009-05-14 16:50:47 -05:00
{
float dz2 = GetPositionZ () - obj2 -> GetPositionZ ();
distsq2 += dz2 * dz2 ;
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
return distsq1 < distsq2 ;
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
bool WorldObject :: IsInRange ( WorldObject const * obj , float minRange , float maxRange , bool is3D /* = true */ ) const
{
float dx = GetPositionX () - obj -> GetPositionX ();
float dy = GetPositionY () - obj -> GetPositionY ();
float distsq = dx * dx + dy * dy ;
2010-04-07 19:14:10 +02:00
if ( is3D )
2009-05-14 16:50:47 -05:00
{
float dz = GetPositionZ () - obj -> GetPositionZ ();
distsq += dz * dz ;
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
float sizefactor = GetObjectSize () + obj -> GetObjectSize ();
2009-10-17 15:51:44 -07:00
2009-05-17 10:09:06 -05:00
// check only for real range
2010-04-07 19:14:10 +02:00
if ( minRange > 0.0f )
2009-05-17 10:09:06 -05:00
{
float mindist = minRange + sizefactor ;
2010-04-07 19:14:10 +02:00
if ( distsq < mindist * mindist )
2009-05-17 10:09:06 -05:00
return false ;
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
float maxdist = maxRange + sizefactor ;
return distsq < maxdist * maxdist ;
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
bool WorldObject :: IsInRange2d ( float x , float y , float minRange , float maxRange ) const
{
float dx = GetPositionX () - x ;
float dy = GetPositionY () - y ;
float distsq = dx * dx + dy * dy ;
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
float sizefactor = GetObjectSize ();
2009-10-17 15:51:44 -07:00
2009-05-17 10:09:06 -05:00
// check only for real range
2010-04-07 19:14:10 +02:00
if ( minRange > 0.0f )
2009-05-17 10:09:06 -05:00
{
float mindist = minRange + sizefactor ;
2010-04-07 19:14:10 +02:00
if ( distsq < mindist * mindist )
2009-05-17 10:09:06 -05:00
return false ;
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
float maxdist = maxRange + sizefactor ;
return distsq < maxdist * maxdist ;
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
bool WorldObject :: IsInRange3d ( float x , float y , float z , float minRange , float maxRange ) const
{
float dx = GetPositionX () - x ;
float dy = GetPositionY () - y ;
float dz = GetPositionZ () - z ;
float distsq = dx * dx + dy * dy + dz * dz ;
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
float sizefactor = GetObjectSize ();
2009-10-17 15:51:44 -07:00
2009-05-17 10:09:06 -05:00
// check only for real range
2010-04-07 19:14:10 +02:00
if ( minRange > 0.0f )
2009-05-17 10:09:06 -05:00
{
float mindist = minRange + sizefactor ;
2010-04-07 19:14:10 +02:00
if ( distsq < mindist * mindist )
2009-05-17 10:09:06 -05:00
return false ;
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
float maxdist = maxRange + sizefactor ;
return distsq < maxdist * maxdist ;
}
2009-10-17 15:51:44 -07:00
2010-09-12 01:40:27 +02:00
void Position :: RelocateOffset ( const Position & offset )
2010-08-08 20:32:14 +02:00
{
m_positionX = GetPositionX () + ( offset . GetPositionX () * cos ( GetOrientation ()) + offset . GetPositionY () * sin ( GetOrientation () + M_PI ));
m_positionY = GetPositionY () + ( offset . GetPositionY () * cos ( GetOrientation ()) + offset . GetPositionX () * sin ( GetOrientation ()));
m_positionZ = GetPositionZ () + offset . GetPositionZ ();
m_orientation = GetOrientation () + offset . GetOrientation ();
}
void Position :: GetPositionOffsetTo ( const Position & endPos , Position & retOffset ) const
{
float dx = endPos . GetPositionX () - GetPositionX ();
float dy = endPos . GetPositionY () - GetPositionY ();
retOffset . m_positionX = dx * cos ( GetOrientation ()) + dy * sin ( GetOrientation ());
retOffset . m_positionY = dy * cos ( GetOrientation ()) - dx * sin ( GetOrientation ());
retOffset . m_positionZ = endPos . GetPositionZ () - GetPositionZ ();
retOffset . m_orientation = endPos . GetOrientation () - GetOrientation ();
}
2011-09-15 14:08:17 +02:00
float Position :: GetAngle ( const Position * obj ) const
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( ! obj ) return 0 ;
2010-04-07 22:59:46 +02:00
return GetAngle ( obj -> GetPositionX (), obj -> GetPositionY ());
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// Return angle in range 0..2*pi
2010-04-07 22:59:46 +02:00
float Position :: GetAngle ( const float x , const float y ) const
2008-10-11 14:16:25 -05:00
{
float dx = x - GetPositionX ();
float dy = y - GetPositionY ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
float ang = atan2 ( dy , dx );
ang = ( ang >= 0 ) ? ang : 2 * M_PI + ang ;
return ang ;
}
2009-10-17 15:51:44 -07:00
2009-08-29 14:58:45 -05:00
void Position :: GetSinCos ( const float x , const float y , float & vsin , float & vcos ) const
2009-03-23 15:26:13 -06:00
{
float dx = GetPositionX () - x ;
float dy = GetPositionY () - y ;
2009-10-17 15:51:44 -07:00
2011-09-30 18:24:12 +02:00
if ( fabs ( dx ) < 0.001f && fabs ( dy ) < 0.001f )
2009-03-23 15:26:13 -06:00
{
2010-08-22 12:39:39 -07:00
float angle = ( float ) rand_norm () * static_cast < float > ( 2 * M_PI );
2009-03-23 15:26:13 -06:00
vcos = cos ( angle );
vsin = sin ( angle );
}
else
{
float dist = sqrt (( dx * dx ) + ( dy * dy ));
vcos = dx / dist ;
vsin = dy / dist ;
}
}
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
bool Position :: HasInArc ( float arc , const Position * obj ) const
2008-10-11 14:16:25 -05:00
{
2009-03-28 16:36:54 -06:00
// always have self in arc
2010-04-07 19:14:10 +02:00
if ( obj == this )
2009-03-28 16:36:54 -06:00
return true ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// move arc to range 0.. 2*pi
2010-06-24 17:32:50 +02:00
arc = MapManager :: NormalizeOrientation ( arc );
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
float angle = GetAngle ( obj );
2008-10-11 14:16:25 -05:00
angle -= m_orientation ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// move angle to range -pi ... +pi
2010-06-24 17:32:50 +02:00
angle = MapManager :: NormalizeOrientation ( angle );
2011-06-12 02:30:32 +02:00
if ( angle > M_PI )
2010-06-24 17:32:50 +02:00
angle -= 2.0f * M_PI ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
float lborder = - 1 * ( arc / 2.0f ); // in range -pi..0
float rborder = ( arc / 2.0f ); // in range 0..pi
2010-04-07 22:59:46 +02:00
return (( angle >= lborder ) && ( angle <= rborder ));
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
bool WorldObject :: IsInBetween ( const WorldObject * obj1 , const WorldObject * obj2 , float size ) const
2009-05-09 10:50:41 -05:00
{
2011-09-20 17:48:13 -03:00
if ( ! obj1 || ! obj2 )
return false ;
float dist = GetExactDist2d ( obj1 -> GetPositionX (), obj1 -> GetPositionY ());
// not using sqrt() for performance
if (( dist * dist ) >= obj1 -> GetExactDist2dSq ( obj2 -> GetPositionX (), obj2 -> GetPositionY ()))
2009-05-09 10:50:41 -05:00
return false ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( ! size )
2009-05-09 10:50:41 -05:00
size = GetObjectSize () / 2 ;
2009-10-17 15:51:44 -07:00
2011-09-20 17:48:13 -03:00
float angle = obj1 -> GetAngle ( obj2 );
// not using sqrt() for performance
return ( size * size ) >= GetExactDist2dSq ( obj1 -> GetPositionX () + cos ( angle ) * dist , obj1 -> GetPositionY () + sin ( angle ) * dist );
2009-05-09 10:50:41 -05:00
}
2009-10-17 15:51:44 -07:00
2009-12-17 19:09:40 +01:00
bool WorldObject :: isInFront ( WorldObject const * target , float distance , float arc ) const
{
2010-04-07 22:59:46 +02:00
return IsWithinDist ( target , distance ) && HasInArc ( arc , target );
2009-12-17 19:09:40 +01:00
}
bool WorldObject :: isInBack ( WorldObject const * target , float distance , float arc ) const
{
2010-04-07 22:59:46 +02:00
return IsWithinDist ( target , distance ) && ! HasInArc ( 2 * M_PI - arc , target );
2009-12-17 19:09:40 +01:00
}
2009-08-29 23:20:16 -05:00
void WorldObject :: GetRandomPoint ( const Position & pos , float distance , float & rand_x , float & rand_y , float & rand_z ) const
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( ! distance )
2008-10-11 14:16:25 -05:00
{
2009-08-29 23:20:16 -05:00
pos . GetPosition ( rand_x , rand_y , rand_z );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// angle to face `obj` to `this`
2010-08-22 12:39:39 -07:00
float angle = ( float ) rand_norm () * static_cast < float > ( 2 * M_PI );
float new_dist = ( float ) rand_norm () * static_cast < float > ( distance );
2009-10-17 15:51:44 -07:00
2009-08-29 23:20:16 -05:00
rand_x = pos . m_positionX + new_dist * cos ( angle );
rand_y = pos . m_positionY + new_dist * sin ( angle );
rand_z = pos . m_positionZ ;
2009-10-17 15:51:44 -07:00
2008-10-14 11:57:03 -05:00
Trinity :: NormalizeMapCoord ( rand_x );
Trinity :: NormalizeMapCoord ( rand_y );
2011-04-29 20:47:02 +02:00
UpdateGroundPositionZ ( rand_x , rand_y , rand_z ); // update to LOS height if available
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void WorldObject :: UpdateGroundPositionZ ( float x , float y , float & z ) const
{
2011-04-29 20:47:02 +02:00
float new_z = GetBaseMap () -> GetHeight ( x , y , z , true );
2010-04-07 19:14:10 +02:00
if ( new_z > INVALID_HEIGHT )
2008-10-11 14:16:25 -05:00
z = new_z + 0.05f ; // just to be sure that we are not a few pixel under the surface
}
2009-10-17 15:51:44 -07:00
2012-01-14 15:34:41 +01:00
void WorldObject :: UpdateAllowedPositionZ ( float x , float y , float & z ) const
{
switch ( GetTypeId ())
{
case TYPEID_UNIT :
{
// non fly unit don't must be in air
// non swim unit must be at ground (mostly speedup, because it don't must be in water and water level check less fast
2012-02-02 13:03:54 -05:00
if ( ! ToCreature () -> canFly ())
2012-01-14 15:34:41 +01:00
{
2012-02-02 13:03:54 -05:00
bool canSwim = ToCreature () -> canSwim ();
2012-01-14 15:34:41 +01:00
float ground_z = z ;
float max_z = canSwim
2012-02-02 13:03:54 -05:00
? GetBaseMap () -> GetWaterOrGroundLevel ( x , y , z , & ground_z , ! ToUnit () -> HasAuraType ( SPELL_AURA_WATER_WALK ))
2012-01-14 15:34:41 +01:00
: (( ground_z = GetBaseMap () -> GetHeight ( x , y , z , true )));
if ( max_z > INVALID_HEIGHT )
{
if ( z > max_z )
z = max_z ;
else if ( z < ground_z )
z = ground_z ;
}
}
else
{
float ground_z = GetBaseMap () -> GetHeight ( x , y , z , true );
if ( z < ground_z )
z = ground_z ;
}
break ;
}
case TYPEID_PLAYER :
{
// for server controlled moves playr work same as creature (but it can always swim)
2012-02-02 13:03:54 -05:00
if ( ! ToPlayer () -> canFly ())
2012-01-14 15:34:41 +01:00
{
float ground_z = z ;
2012-02-02 13:03:54 -05:00
float max_z = GetBaseMap () -> GetWaterOrGroundLevel ( x , y , z , & ground_z , ! ( ToUnit () -> HasAuraType ( SPELL_AURA_WATER_WALK ));
2012-01-14 15:34:41 +01:00
if ( max_z > INVALID_HEIGHT )
{
if ( z > max_z )
z = max_z ;
else if ( z < ground_z )
z = ground_z ;
}
}
else
{
float ground_z = GetBaseMap () -> GetHeight ( x , y , z , true );
if ( z < ground_z )
z = ground_z ;
}
break ;
}
default :
{
float ground_z = GetBaseMap () -> GetHeight ( x , y , z , true );
if ( ground_z > INVALID_HEIGHT )
z = ground_z ;
break ;
}
}
}
2009-08-29 14:58:45 -05:00
bool Position :: IsPositionValid () const
2008-10-11 14:16:25 -05:00
{
2011-04-29 20:47:02 +02:00
return Trinity :: IsValidMapCoord ( m_positionX , m_positionY , m_positionZ , m_orientation );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2010-11-13 17:18:09 +01:00
float WorldObject :: GetGridActivationRange () const
{
if ( ToPlayer ())
return GetMap () -> GetVisibilityRange ();
else if ( ToCreature ())
return ToCreature () -> m_SightDistance ;
else
return 0.0f ;
}
float WorldObject :: GetVisibilityRange () const
{
if ( isActiveObject () && ! ToPlayer ())
return MAX_VISIBILITY_DISTANCE ;
else
return GetMap () -> GetVisibilityRange ();
}
float WorldObject :: GetSightRange ( const WorldObject * target ) const
{
if ( ToUnit ())
{
if ( ToPlayer ())
{
2010-11-14 17:49:10 +01:00
if ( target && target -> isActiveObject () && ! target -> ToPlayer ())
2010-11-13 17:18:09 +01:00
return MAX_VISIBILITY_DISTANCE ;
else
return GetMap () -> GetVisibilityRange ();
}
else if ( ToCreature ())
return ToCreature () -> m_SightDistance ;
else
return SIGHT_RANGE_UNIT ;
}
return 0.0f ;
}
bool WorldObject :: canSeeOrDetect ( WorldObject const * obj , bool ignoreStealth , bool distanceCheck ) const
{
if ( this == obj )
return true ;
2011-10-13 17:01:55 -04:00
if ( obj -> IsNeverVisible () || CanNeverSee ( obj ))
2010-11-13 17:18:09 +01:00
return false ;
2011-10-13 17:01:55 -04:00
if ( obj -> IsAlwaysVisibleFor ( this ) || CanAlwaysSee ( obj ))
2010-11-13 17:18:09 +01:00
return true ;
bool corpseCheck = false ;
bool corpseVisibility = false ;
if ( distanceCheck )
{
2011-12-10 13:48:41 +01:00
if ( Player const * thisPlayer = ToPlayer ())
2010-11-13 17:18:09 +01:00
{
if ( thisPlayer -> isDead () && thisPlayer -> GetHealth () > 0 && // Cheap way to check for ghost state
! ( obj -> m_serverSideVisibility . GetValue ( SERVERSIDE_VISIBILITY_GHOST ) & m_serverSideVisibility . GetValue ( SERVERSIDE_VISIBILITY_GHOST ) & GHOST_VISIBILITY_GHOST ))
{
if ( Corpse * corpse = thisPlayer -> GetCorpse ())
{
corpseCheck = true ;
if ( corpse -> IsWithinDist ( thisPlayer , GetSightRange ( obj ), false ))
if ( corpse -> IsWithinDist ( obj , GetSightRange ( obj ), false ))
corpseVisibility = true ;
}
}
}
2012-01-02 16:33:14 -03:00
WorldObject const * viewpoint = this ;
if ( Player const * player = this -> ToPlayer ())
viewpoint = player -> GetViewpoint ();
2012-01-03 16:34:05 -03:00
if ( ! viewpoint )
viewpoint = this ;
2012-01-02 16:33:14 -03:00
if ( ! corpseCheck && ! viewpoint -> IsWithinDist ( obj , GetSightRange ( obj ), false ))
2010-11-13 17:18:09 +01:00
return false ;
}
// GM visibility off or hidden NPC
if ( ! obj -> m_serverSideVisibility . GetValue ( SERVERSIDE_VISIBILITY_GM ))
{
// Stop checking other things for GMs
if ( m_serverSideVisibilityDetect . GetValue ( SERVERSIDE_VISIBILITY_GM ))
return true ;
}
else
return m_serverSideVisibilityDetect . GetValue ( SERVERSIDE_VISIBILITY_GM ) >= obj -> m_serverSideVisibility . GetValue ( SERVERSIDE_VISIBILITY_GM );
// Ghost players, Spirit Healers, and some other NPCs
if ( ! corpseVisibility && ! ( obj -> m_serverSideVisibility . GetValue ( SERVERSIDE_VISIBILITY_GHOST ) & m_serverSideVisibilityDetect . GetValue ( SERVERSIDE_VISIBILITY_GHOST )))
{
// Alive players can see dead players in some cases, but other objects can't do that
2011-12-10 13:48:41 +01:00
if ( Player const * thisPlayer = ToPlayer ())
2010-11-13 17:18:09 +01:00
{
2011-12-10 13:48:41 +01:00
if ( Player const * objPlayer = obj -> ToPlayer ())
2010-11-13 17:18:09 +01:00
{
if ( thisPlayer -> GetTeam () != objPlayer -> GetTeam () || ! thisPlayer -> IsGroupVisibleFor ( objPlayer ))
return false ;
}
else
return false ;
}
else
return false ;
}
2011-10-13 13:26:27 -04:00
if ( obj -> IsInvisibleDueToDespawn ())
2010-11-13 17:18:09 +01:00
return false ;
2011-10-13 17:01:55 -04:00
if ( ! CanDetect ( obj , ignoreStealth ))
2010-11-13 17:18:09 +01:00
return false ;
return true ;
}
2011-10-13 17:01:55 -04:00
bool WorldObject :: CanDetect ( WorldObject const * obj , bool ignoreStealth ) const
2010-11-13 17:18:09 +01:00
{
const WorldObject * seer = this ;
// Pets don't have detection, they use the detection of their masters
if ( const Unit * thisUnit = ToUnit ())
if ( Unit * controller = thisUnit -> GetCharmerOrOwner ())
seer = controller ;
2011-10-13 14:02:07 -04:00
if ( obj -> IsAlwaysDetectableFor ( seer ))
2010-11-13 17:18:09 +01:00
return true ;
2011-10-13 17:01:55 -04:00
if ( ! seer -> CanDetectInvisibilityOf ( obj ))
2010-11-13 17:18:09 +01:00
return false ;
2011-10-13 17:01:55 -04:00
if ( ! ignoreStealth && ! seer -> CanDetectStealthOf ( obj ))
2010-11-13 17:18:09 +01:00
return false ;
return true ;
}
2011-10-13 17:01:55 -04:00
bool WorldObject :: CanDetectInvisibilityOf ( WorldObject const * obj ) const
2010-11-13 17:18:09 +01:00
{
uint32 mask = obj -> m_invisibility . GetFlags () & m_invisibilityDetect . GetFlags ();
// Check for not detected types
if ( mask != obj -> m_invisibility . GetFlags ())
return false ;
// It isn't possible in invisibility to detect something that can't detect the invisible object
// (it's at least true for spell: 66)
// It seems like that only Units are affected by this check (couldn't see arena doors with preparation invisibility)
if ( obj -> ToUnit ())
if (( m_invisibility . GetFlags () & obj -> m_invisibilityDetect . GetFlags ()) != m_invisibility . GetFlags ())
return false ;
for ( uint32 i = 0 ; i < TOTAL_INVISIBILITY_TYPES ; ++ i )
{
if ( ! ( mask & ( 1 << i )))
continue ;
int32 objInvisibilityValue = obj -> m_invisibility . GetValue ( InvisibilityType ( i ));
int32 ownInvisibilityDetectValue = m_invisibilityDetect . GetValue ( InvisibilityType ( i ));
// Too low value to detect
if ( ownInvisibilityDetectValue < objInvisibilityValue )
return false ;
}
return true ;
}
2011-10-13 17:01:55 -04:00
bool WorldObject :: CanDetectStealthOf ( WorldObject const * obj ) const
2010-11-13 17:18:09 +01:00
{
// Combat reach is the minimal distance (both in front and behind),
// and it is also used in the range calculation.
// One stealth point increases the visibility range by 0.3 yard.
if ( ! obj -> m_stealth . GetFlags ())
return true ;
float distance = GetExactDist ( obj );
float combatReach = 0.0f ;
if ( isType ( TYPEMASK_UNIT ))
combatReach = (( Unit * ) this ) -> GetCombatReach ();
if ( distance < combatReach )
return true ;
if ( ! HasInArc ( M_PI , obj ))
return false ;
for ( uint32 i = 0 ; i < TOTAL_STEALTH_TYPES ; ++ i )
{
if ( ! ( obj -> m_stealth . GetFlags () & ( 1 << i )))
continue ;
if ( isType ( TYPEMASK_UNIT ))
if ((( Unit * ) this ) -> HasAuraTypeWithMiscvalue ( SPELL_AURA_DETECT_STEALTH , i ))
return true ;
// Starting points
int32 detectionValue = 30 ;
// Level difference: 5 point / level, starting from level 1.
// There may be spells for this and the starting points too, but
// not in the DBCs of the client.
detectionValue += int32 ( getLevelForTarget ( obj ) - 1 ) * 5 ;
// Apply modifiers
detectionValue += m_stealthDetect . GetValue ( StealthType ( i ));
detectionValue -= obj -> m_stealth . GetValue ( StealthType ( i ));
// Calculate max distance
float visibilityRange = float ( detectionValue ) * 0.3f + combatReach ;
if ( visibilityRange > MAX_PLAYER_STEALTH_DETECT_RANGE )
visibilityRange = MAX_PLAYER_STEALTH_DETECT_RANGE ;
if ( distance > visibilityRange )
return false ;
}
return true ;
}
2008-10-11 14:16:25 -05:00
void WorldObject :: SendPlaySound ( uint32 Sound , bool OnlySelf )
{
WorldPacket data ( SMSG_PLAY_SOUND , 4 );
data << Sound ;
2009-10-31 16:00:47 -07:00
if ( OnlySelf && GetTypeId () == TYPEID_PLAYER )
2010-04-07 22:59:46 +02:00
this -> ToPlayer () -> GetSession () -> SendPacket ( & data );
2008-10-11 14:16:25 -05:00
else
2010-04-07 22:59:46 +02:00
SendMessageToSet ( & data , true ); // ToSelf ignored in this case
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-01-15 21:29:32 -05:00
void Object :: ForceValuesUpdateAtIndex ( uint32 i )
{
2011-08-28 18:31:37 +02:00
_changedFields [ i ] = true ;
2011-08-30 13:46:36 +02:00
if ( m_inWorld && ! m_objectUpdated )
2009-03-31 09:18:39 -06:00
{
2011-08-30 13:46:36 +02:00
sObjectAccessor -> AddUpdateObject ( this );
m_objectUpdated = true ;
2009-03-31 09:18:39 -06:00
}
2009-01-15 21:29:32 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-14 11:57:03 -05:00
namespace Trinity
2008-10-11 14:16:25 -05:00
{
2009-02-21 17:00:47 -06:00
class MonsterChatBuilder
2008-10-11 14:16:25 -05:00
{
public :
2009-02-21 17:00:47 -06:00
MonsterChatBuilder ( WorldObject const & obj , ChatMsg msgtype , int32 textId , uint32 language , uint64 targetGUID )
: i_object ( obj ), i_msgtype ( msgtype ), i_textId ( textId ), i_language ( language ), i_targetGUID ( targetGUID ) {}
2010-09-17 07:04:29 +02:00
void operator ()( WorldPacket & data , LocaleConstant loc_idx )
2008-10-11 14:16:25 -05:00
{
2011-04-29 20:47:02 +02:00
char const * text = sObjectMgr -> GetTrinityString ( i_textId , loc_idx );
2009-10-17 15:51:44 -07:00
2009-02-21 17:00:47 -06:00
// TODO: i_object.GetName() also must be localized?
2011-04-29 20:47:02 +02:00
i_object . BuildMonsterChat ( & data , i_msgtype , text , i_language , i_object . GetNameForLocaleIdx ( loc_idx ), i_targetGUID );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
private :
WorldObject const & i_object ;
ChatMsg i_msgtype ;
int32 i_textId ;
uint32 i_language ;
uint64 i_targetGUID ;
};
2011-05-30 20:47:33 +07:00
class MonsterCustomChatBuilder
{
public :
MonsterCustomChatBuilder ( WorldObject const & obj , ChatMsg msgtype , const char * text , uint32 language , uint64 targetGUID )
: i_object ( obj ), i_msgtype ( msgtype ), i_text ( text ), i_language ( language ), i_targetGUID ( targetGUID ) {}
void operator ()( WorldPacket & data , LocaleConstant loc_idx )
{
// TODO: i_object.GetName() also must be localized?
i_object . BuildMonsterChat ( & data , i_msgtype , i_text , i_language , i_object . GetNameForLocaleIdx ( loc_idx ), i_targetGUID );
}
private :
WorldObject const & i_object ;
ChatMsg i_msgtype ;
const char * i_text ;
uint32 i_language ;
uint64 i_targetGUID ;
};
2008-10-14 11:57:03 -05:00
} // namespace Trinity
2009-10-17 15:51:44 -07:00
2011-05-30 20:47:33 +07:00
void WorldObject :: MonsterSay ( const char * text , uint32 language , uint64 TargetGuid )
{
2011-10-18 10:53:34 -04:00
CellCoord p = Trinity :: ComputeCellCoord ( GetPositionX (), GetPositionY ());
2011-05-30 20:47:33 +07:00
Cell cell ( p );
cell . SetNoCreate ();
Trinity :: MonsterCustomChatBuilder say_build ( * this , CHAT_MSG_MONSTER_SAY , text , language , TargetGuid );
Trinity :: LocalizedPacketDo < Trinity :: MonsterCustomChatBuilder > say_do ( say_build );
Trinity :: PlayerDistWorker < Trinity :: LocalizedPacketDo < Trinity :: MonsterCustomChatBuilder > > say_worker ( this , sWorld -> getFloatConfig ( CONFIG_LISTEN_RANGE_SAY ), say_do );
TypeContainerVisitor < Trinity :: PlayerDistWorker < Trinity :: LocalizedPacketDo < Trinity :: MonsterCustomChatBuilder > > , WorldTypeMapContainer > message ( say_worker );
cell . Visit ( p , message , * GetMap (), * this , sWorld -> getFloatConfig ( CONFIG_LISTEN_RANGE_SAY ));
}
2008-10-11 14:16:25 -05:00
void WorldObject :: MonsterSay ( int32 textId , uint32 language , uint64 TargetGuid )
{
2011-10-18 10:53:34 -04:00
CellCoord p = Trinity :: ComputeCellCoord ( GetPositionX (), GetPositionY ());
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Cell cell ( p );
cell . SetNoCreate ();
2009-10-17 15:51:44 -07:00
2011-04-29 20:47:02 +02:00
Trinity :: MonsterChatBuilder say_build ( * this , CHAT_MSG_MONSTER_SAY , textId , language , TargetGuid );
2009-12-20 15:20:04 +01:00
Trinity :: LocalizedPacketDo < Trinity :: MonsterChatBuilder > say_do ( say_build );
2011-04-29 20:47:02 +02:00
Trinity :: PlayerDistWorker < Trinity :: LocalizedPacketDo < Trinity :: MonsterChatBuilder > > say_worker ( this , sWorld -> getFloatConfig ( CONFIG_LISTEN_RANGE_SAY ), say_do );
2009-12-20 15:20:04 +01:00
TypeContainerVisitor < Trinity :: PlayerDistWorker < Trinity :: LocalizedPacketDo < Trinity :: MonsterChatBuilder > > , WorldTypeMapContainer > message ( say_worker );
2010-12-23 23:25:44 +01:00
cell . Visit ( p , message , * GetMap (), * this , sWorld -> getFloatConfig ( CONFIG_LISTEN_RANGE_SAY ));
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2011-05-30 20:47:33 +07:00
void WorldObject :: MonsterYell ( const char * text , uint32 language , uint64 TargetGuid )
{
2011-10-18 10:53:34 -04:00
CellCoord p = Trinity :: ComputeCellCoord ( GetPositionX (), GetPositionY ());
2011-05-30 20:47:33 +07:00
Cell cell ( p );
cell . SetNoCreate ();
Trinity :: MonsterCustomChatBuilder say_build ( * this , CHAT_MSG_MONSTER_YELL , text , language , TargetGuid );
Trinity :: LocalizedPacketDo < Trinity :: MonsterCustomChatBuilder > say_do ( say_build );
Trinity :: PlayerDistWorker < Trinity :: LocalizedPacketDo < Trinity :: MonsterCustomChatBuilder > > say_worker ( this , sWorld -> getFloatConfig ( CONFIG_LISTEN_RANGE_YELL ), say_do );
TypeContainerVisitor < Trinity :: PlayerDistWorker < Trinity :: LocalizedPacketDo < Trinity :: MonsterCustomChatBuilder > > , WorldTypeMapContainer > message ( say_worker );
cell . Visit ( p , message , * GetMap (), * this , sWorld -> getFloatConfig ( CONFIG_LISTEN_RANGE_YELL ));
}
2008-10-11 14:16:25 -05:00
void WorldObject :: MonsterYell ( int32 textId , uint32 language , uint64 TargetGuid )
{
2011-10-18 10:53:34 -04:00
CellCoord p = Trinity :: ComputeCellCoord ( GetPositionX (), GetPositionY ());
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Cell cell ( p );
cell . SetNoCreate ();
2009-10-17 15:51:44 -07:00
2011-04-29 20:47:02 +02:00
Trinity :: MonsterChatBuilder say_build ( * this , CHAT_MSG_MONSTER_YELL , textId , language , TargetGuid );
2009-12-20 15:20:04 +01:00
Trinity :: LocalizedPacketDo < Trinity :: MonsterChatBuilder > say_do ( say_build );
2011-04-29 20:47:02 +02:00
Trinity :: PlayerDistWorker < Trinity :: LocalizedPacketDo < Trinity :: MonsterChatBuilder > > say_worker ( this , sWorld -> getFloatConfig ( CONFIG_LISTEN_RANGE_YELL ), say_do );
2009-12-20 15:20:04 +01:00
TypeContainerVisitor < Trinity :: PlayerDistWorker < Trinity :: LocalizedPacketDo < Trinity :: MonsterChatBuilder > > , WorldTypeMapContainer > message ( say_worker );
2010-12-23 23:25:44 +01:00
cell . Visit ( p , message , * GetMap (), * this , sWorld -> getFloatConfig ( CONFIG_LISTEN_RANGE_YELL ));
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-03-28 18:03:56 -06:00
void WorldObject :: MonsterYellToZone ( int32 textId , uint32 language , uint64 TargetGuid )
{
2011-04-29 20:47:02 +02:00
Trinity :: MonsterChatBuilder say_build ( * this , CHAT_MSG_MONSTER_YELL , textId , language , TargetGuid );
2009-12-20 15:20:04 +01:00
Trinity :: LocalizedPacketDo < Trinity :: MonsterChatBuilder > say_do ( say_build );
2009-10-17 15:51:44 -07:00
2009-03-29 17:15:37 -06:00
uint32 zoneid = GetZoneId ();
2009-10-17 15:51:44 -07:00
2009-03-29 17:15:37 -06:00
Map :: PlayerList const & pList = GetMap () -> GetPlayers ();
2009-10-17 16:20:24 -07:00
for ( Map :: PlayerList :: const_iterator itr = pList . begin (); itr != pList . end (); ++ itr )
2010-04-07 23:25:02 +02:00
if ( itr -> getSource () -> GetZoneId () == zoneid )
2009-03-29 17:15:37 -06:00
say_do ( itr -> getSource ());
2009-03-28 18:03:56 -06:00
}
2009-10-17 15:51:44 -07:00
2011-05-30 20:47:33 +07:00
void WorldObject :: MonsterTextEmote ( const char * text , uint64 TargetGuid , bool IsBossEmote )
{
WorldPacket data ( SMSG_MESSAGECHAT , 200 );
BuildMonsterChat ( & data , IsBossEmote ? CHAT_MSG_RAID_BOSS_EMOTE : CHAT_MSG_MONSTER_EMOTE , text , LANG_UNIVERSAL , GetName (), TargetGuid );
SendMessageToSetInRange ( & data , sWorld -> getFloatConfig ( CONFIG_LISTEN_RANGE_TEXTEMOTE ), true );
}
2008-10-11 14:16:25 -05:00
void WorldObject :: MonsterTextEmote ( int32 textId , uint64 TargetGuid , bool IsBossEmote )
{
2011-10-18 10:53:34 -04:00
CellCoord p = Trinity :: ComputeCellCoord ( GetPositionX (), GetPositionY ());
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Cell cell ( p );
cell . SetNoCreate ();
2009-10-17 15:51:44 -07:00
2011-04-29 20:47:02 +02:00
Trinity :: MonsterChatBuilder say_build ( * this , IsBossEmote ? CHAT_MSG_RAID_BOSS_EMOTE : CHAT_MSG_MONSTER_EMOTE , textId , LANG_UNIVERSAL , TargetGuid );
2009-12-20 15:20:04 +01:00
Trinity :: LocalizedPacketDo < Trinity :: MonsterChatBuilder > say_do ( say_build );
2011-04-29 20:47:02 +02:00
Trinity :: PlayerDistWorker < Trinity :: LocalizedPacketDo < Trinity :: MonsterChatBuilder > > say_worker ( this , sWorld -> getFloatConfig ( CONFIG_LISTEN_RANGE_TEXTEMOTE ), say_do );
2009-12-20 15:20:04 +01:00
TypeContainerVisitor < Trinity :: PlayerDistWorker < Trinity :: LocalizedPacketDo < Trinity :: MonsterChatBuilder > > , WorldTypeMapContainer > message ( say_worker );
2010-12-23 23:25:44 +01:00
cell . Visit ( p , message , * GetMap (), * this , sWorld -> getFloatConfig ( CONFIG_LISTEN_RANGE_TEXTEMOTE ));
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2011-05-30 20:47:33 +07:00
void WorldObject :: MonsterWhisper ( const char * text , uint64 receiver , bool IsBossWhisper )
{
2011-07-27 12:14:27 +02:00
Player * player = ObjectAccessor :: FindPlayer ( receiver );
2011-05-30 20:47:33 +07:00
if ( ! player || ! player -> GetSession ())
return ;
LocaleConstant loc_idx = player -> GetSession () -> GetSessionDbLocaleIndex ();
WorldPacket data ( SMSG_MESSAGECHAT , 200 );
BuildMonsterChat ( & data , IsBossWhisper ? CHAT_MSG_RAID_BOSS_WHISPER : CHAT_MSG_MONSTER_WHISPER , text , LANG_UNIVERSAL , GetNameForLocaleIdx ( loc_idx ), receiver );
player -> GetSession () -> SendPacket ( & data );
}
2008-10-11 14:16:25 -05:00
void WorldObject :: MonsterWhisper ( int32 textId , uint64 receiver , bool IsBossWhisper )
{
2011-07-27 12:14:27 +02:00
Player * player = ObjectAccessor :: FindPlayer ( receiver );
2010-04-07 19:14:10 +02:00
if ( ! player || ! player -> GetSession ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2010-09-17 07:04:29 +02:00
LocaleConstant loc_idx = player -> GetSession () -> GetSessionDbLocaleIndex ();
2010-12-22 21:25:23 +01:00
char const * text = sObjectMgr -> GetTrinityString ( textId , loc_idx );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
WorldPacket data ( SMSG_MESSAGECHAT , 200 );
2011-04-29 20:47:02 +02:00
BuildMonsterChat ( & data , IsBossWhisper ? CHAT_MSG_RAID_BOSS_WHISPER : CHAT_MSG_MONSTER_WHISPER , text , LANG_UNIVERSAL , GetNameForLocaleIdx ( loc_idx ), receiver );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
player -> GetSession () -> SendPacket ( & data );
}
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
void WorldObject :: BuildMonsterChat ( WorldPacket * data , uint8 msgtype , char const * text , uint32 language , char const * name , uint64 targetGuid ) const
2008-10-11 14:16:25 -05:00
{
* data << ( uint8 ) msgtype ;
* data << ( uint32 ) language ;
* data << ( uint64 ) GetGUID ();
2009-05-31 15:56:51 -05:00
* data << ( uint32 ) 0 ; // 2.1.0
2008-10-11 14:16:25 -05:00
* data << ( uint32 )( strlen ( name ) + 1 );
* data << name ;
2009-05-31 15:56:51 -05:00
* data << ( uint64 ) targetGuid ; // Unit Target
2010-04-07 22:59:46 +02:00
if ( targetGuid && ! IS_PLAYER_GUID ( targetGuid ))
2008-10-11 14:16:25 -05:00
{
* data << ( uint32 ) 1 ; // target name length
* data << ( uint8 ) 0 ; // target name
}
2009-07-20 11:53:26 +08:00
* data << ( uint32 )( strlen ( text ) + 1 );
2008-10-11 14:16:25 -05:00
* data << text ;
* data << ( uint8 ) 0 ; // ChatTag
}
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
void Unit :: BuildHeartBeatMsg ( WorldPacket * data ) const
2008-10-11 14:16:25 -05:00
{
data -> Initialize ( MSG_MOVE_HEARTBEAT , 32 );
data -> append ( GetPackGUID ());
2009-06-13 09:18:54 -05:00
BuildMovementPacket ( data );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
void WorldObject :: SendMessageToSet ( WorldPacket * data , bool self )
2011-08-30 13:46:36 +02:00
{
2012-01-14 15:34:41 +01:00
if ( IsInWorld ())
SendMessageToSetInRange ( data , GetVisibilityRange (), self );
2011-08-30 13:46:36 +02:00
}
2011-09-15 14:08:17 +02:00
void WorldObject :: SendMessageToSetInRange ( WorldPacket * data , float dist , bool /*self*/ )
2008-10-11 14:16:25 -05:00
{
2009-08-12 23:23:53 -05:00
Trinity :: MessageDistDeliverer notifier ( this , data , dist );
VisitNearbyWorldObject ( dist , notifier );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
void WorldObject :: SendMessageToSet ( WorldPacket * data , Player const * skipped_rcvr )
2010-04-04 03:46:38 +03:00
{
2010-11-13 17:18:09 +01:00
Trinity :: MessageDistDeliverer notifier ( this , data , GetVisibilityRange (), false , skipped_rcvr );
VisitNearbyWorldObject ( GetVisibilityRange (), notifier );
2010-04-04 03:46:38 +03:00
}
2008-10-11 14:16:25 -05:00
void WorldObject :: SendObjectDeSpawnAnim ( uint64 guid )
{
WorldPacket data ( SMSG_GAMEOBJECT_DESPAWN_ANIM , 8 );
2009-07-30 10:26:15 +08:00
data << uint64 ( guid );
2008-10-11 14:16:25 -05:00
SendMessageToSet ( & data , true );
}
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
void WorldObject :: SetMap ( Map * map )
2009-03-24 09:06:49 -06:00
{
2009-07-16 11:49:00 +08:00
ASSERT ( map );
2009-08-11 16:39:35 -05:00
ASSERT ( ! IsInWorld () || GetTypeId () == TYPEID_CORPSE );
2010-04-07 19:14:10 +02:00
if ( m_currMap == map ) // command add npc: first create, than loadfromdb
2009-08-12 13:03:44 -05:00
return ;
2010-04-07 19:14:10 +02:00
if ( m_currMap )
2009-08-26 19:35:20 -05:00
{
2010-12-23 23:25:44 +01:00
sLog -> outCrash ( "WorldObject::SetMap: obj %u new map %u %u, old map %u %u" , ( uint32 ) GetTypeId (), map -> GetId (), map -> GetInstanceId (), m_currMap -> GetId (), m_currMap -> GetInstanceId ());
2010-07-30 20:04:28 +02:00
ASSERT ( false );
2009-08-26 19:35:20 -05:00
}
2009-07-16 11:49:00 +08:00
m_currMap = map ;
2009-08-25 11:42:18 -05:00
m_mapId = map -> GetId ();
m_InstanceId = map -> GetInstanceId ();
2011-12-20 17:05:08 -05:00
if ( IsWorldObject ())
2009-08-11 16:33:33 -05:00
m_currMap -> AddWorldObject ( this );
2009-03-24 09:06:49 -06:00
}
2009-10-17 15:51:44 -07:00
2009-08-10 23:47:47 -05:00
void WorldObject :: ResetMap ()
{
ASSERT ( m_currMap );
2009-08-12 23:12:33 -05:00
ASSERT ( ! IsInWorld ());
2011-12-20 17:05:08 -05:00
if ( IsWorldObject ())
2009-08-11 16:33:33 -05:00
m_currMap -> RemoveWorldObject ( this );
2009-08-10 23:47:47 -05:00
m_currMap = NULL ;
2009-08-25 19:22:45 -05:00
//maybe not for corpse
//m_mapId = 0;
//m_InstanceId = 0;
2009-08-10 23:47:47 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Map const * WorldObject :: GetBaseMap () const
{
2009-07-16 11:49:00 +08:00
ASSERT ( m_currMap );
return m_currMap -> GetParent ();
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void WorldObject :: AddObjectToRemoveList ()
{
2010-07-30 20:04:28 +02:00
ASSERT ( m_uint32Values );
2009-10-17 15:51:44 -07:00
2009-04-08 17:23:57 -05:00
Map * map = FindMap ();
2010-04-07 19:14:10 +02:00
if ( ! map )
2008-10-11 14:16:25 -05:00
{
2011-04-29 20:47:02 +02:00
sLog -> outError ( "Object (TypeId: %u Entry: %u GUID: %u) at attempt add to move list not have valid map (Id: %u)." , GetTypeId (), GetEntry (), GetGUIDLow (), GetMapId ());
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
map -> AddObjectToRemoveList ( this );
}
2009-10-17 15:51:44 -07:00
2011-05-19 22:27:18 +02:00
TempSummon * Map :: SummonCreature ( uint32 entry , Position const & pos , SummonPropertiesEntry const * properties /*= NULL*/ , uint32 duration /*= 0*/ , Unit * summoner /*= NULL*/ , uint32 spellId /*= 0*/ , uint32 vehId /*= 0*/ )
2008-10-11 14:16:25 -05:00
{
2009-08-23 22:09:43 -05:00
uint32 mask = UNIT_MASK_SUMMON ;
2010-04-07 19:14:10 +02:00
if ( properties )
2009-03-20 14:01:46 -06:00
{
2011-05-19 22:27:18 +02:00
switch ( properties -> Category )
2009-08-26 19:28:21 -05:00
{
2011-05-19 22:27:18 +02:00
case SUMMON_CATEGORY_PET :
mask = UNIT_MASK_GUARDIAN ;
break ;
case SUMMON_CATEGORY_PUPPET :
mask = UNIT_MASK_PUPPET ;
break ;
case SUMMON_CATEGORY_VEHICLE :
mask = UNIT_MASK_MINION ;
break ;
case SUMMON_CATEGORY_WILD :
case SUMMON_CATEGORY_ALLY :
case SUMMON_CATEGORY_UNK :
{
switch ( properties -> Type )
2009-08-26 19:28:21 -05:00
{
2011-05-19 22:27:18 +02:00
case SUMMON_TYPE_MINION :
case SUMMON_TYPE_GUARDIAN :
case SUMMON_TYPE_GUARDIAN2 :
mask = UNIT_MASK_GUARDIAN ;
break ;
case SUMMON_TYPE_TOTEM :
mask = UNIT_MASK_TOTEM ;
break ;
case SUMMON_TYPE_VEHICLE :
case SUMMON_TYPE_VEHICLE2 :
mask = UNIT_MASK_SUMMON ;
break ;
case SUMMON_TYPE_MINIPET :
mask = UNIT_MASK_MINION ;
break ;
default :
if ( properties -> Flags & 512 ) // Mirror Image, Summon Gargoyle
mask = UNIT_MASK_GUARDIAN ;
break ;
2009-08-26 19:28:21 -05:00
}
break ;
2011-05-19 22:27:18 +02:00
}
default :
return NULL ;
2009-08-26 19:28:21 -05:00
}
2009-03-20 14:01:46 -06:00
}
2009-10-17 15:51:44 -07:00
2011-05-19 22:27:18 +02:00
uint32 phase = PHASEMASK_NORMAL ;
uint32 team = 0 ;
2010-04-07 19:14:10 +02:00
if ( summoner )
2009-03-20 14:01:46 -06:00
{
phase = summoner -> GetPhaseMask ();
2010-04-07 19:14:10 +02:00
if ( summoner -> GetTypeId () == TYPEID_PLAYER )
2010-03-07 15:20:19 +01:00
team = summoner -> ToPlayer () -> GetTeam ();
2009-03-20 14:01:46 -06:00
}
2009-10-17 15:51:44 -07:00
2011-05-19 22:27:18 +02:00
TempSummon * summon = NULL ;
switch ( mask )
{
case UNIT_MASK_SUMMON :
2011-12-20 17:05:08 -05:00
summon = new TempSummon ( properties , summoner , false );
2011-05-19 22:27:18 +02:00
break ;
case UNIT_MASK_GUARDIAN :
2011-12-20 17:05:08 -05:00
summon = new Guardian ( properties , summoner , false );
2011-05-19 22:27:18 +02:00
break ;
case UNIT_MASK_PUPPET :
summon = new Puppet ( properties , summoner );
break ;
case UNIT_MASK_TOTEM :
summon = new Totem ( properties , summoner );
break ;
case UNIT_MASK_MINION :
2011-12-20 17:05:08 -05:00
summon = new Minion ( properties , summoner , false );
2011-05-19 22:27:18 +02:00
break ;
default :
return NULL ;
2009-03-20 14:01:46 -06:00
}
2009-10-17 15:51:44 -07:00
2010-12-22 21:25:23 +01:00
if ( ! summon -> Create ( sObjectMgr -> GenerateLowGuid ( HIGHGUID_UNIT ), this , phase , entry , vehId , team , pos . GetPositionX (), pos . GetPositionY (), pos . GetPositionZ (), pos . GetOrientation ()))
2008-10-11 14:16:25 -05:00
{
2009-03-20 14:01:46 -06:00
delete summon ;
2008-10-11 14:16:25 -05:00
return NULL ;
}
2009-10-17 15:51:44 -07:00
2011-05-19 22:27:18 +02:00
summon -> SetUInt32Value ( UNIT_CREATED_BY_SPELL , spellId );
2009-08-29 14:58:45 -05:00
summon -> SetHomePosition ( pos );
2009-10-17 15:51:44 -07:00
2009-05-06 13:34:11 -05:00
summon -> InitStats ( duration );
2011-10-10 17:39:34 -04:00
AddToMap ( summon -> ToCreature ());
2009-05-06 13:34:11 -05:00
summon -> InitSummon ();
2009-10-17 15:51:44 -07:00
2009-05-03 11:06:48 -05:00
//ObjectAccessor::UpdateObjectVisibility(summon);
2009-10-17 15:51:44 -07:00
2009-03-20 14:01:46 -06:00
return summon ;
}
2009-10-17 15:51:44 -07:00
2009-05-30 22:15:05 -05:00
void WorldObject :: SetZoneScript ()
{
2011-09-15 14:08:17 +02:00
if ( Map * map = FindMap ())
2009-05-30 22:15:05 -05:00
{
2010-04-07 19:14:10 +02:00
if ( map -> IsDungeon ())
2010-08-08 22:54:58 +06:00
m_zoneScript = ( ZoneScript * )(( InstanceMap * ) map ) -> GetInstanceScript ();
2010-08-08 04:37:24 +02:00
else if ( ! map -> IsBattlegroundOrArena ())
2010-12-22 21:25:23 +01:00
m_zoneScript = sOutdoorPvPMgr -> GetZoneScript ( GetZoneId ());
2009-05-30 22:15:05 -05:00
}
}
2009-10-17 15:51:44 -07:00
2010-04-19 09:26:37 +02:00
TempSummon * WorldObject :: SummonCreature ( uint32 entry , const Position & pos , TempSummonType spwtype , uint32 duration , uint32 /*vehId*/ ) const
2009-03-20 14:01:46 -06:00
{
2011-09-15 14:08:17 +02:00
if ( Map * map = FindMap ())
2009-08-29 14:58:45 -05:00
{
2011-09-15 14:08:17 +02:00
if ( TempSummon * summon = map -> SummonCreature ( entry , pos , NULL , duration , isType ( TYPEMASK_UNIT ) ? ( Unit * ) this : NULL ))
2009-08-29 14:58:45 -05:00
{
summon -> SetTempSummonType ( spwtype );
return summon ;
}
}
2009-10-17 15:51:44 -07:00
2009-08-29 14:58:45 -05:00
return NULL ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-02-19 18:30:03 -06:00
Pet * Player :: SummonPet ( uint32 entry , float x , float y , float z , float ang , PetType petType , uint32 duration )
{
2009-03-25 21:32:34 -06:00
Pet * pet = new Pet ( this , petType );
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( petType == SUMMON_PET && pet -> LoadPetFromDB ( this , entry ))
2009-02-24 20:05:29 -06:00
{
2009-02-24 20:52:55 -06:00
// Remove Demonic Sacrifice auras (known pet)
2010-01-10 01:23:15 +01:00
Unit :: AuraEffectList const & auraClassScripts = GetAuraEffectsByType ( SPELL_AURA_OVERRIDE_CLASS_SCRIPTS );
2010-04-08 08:20:08 +02:00
for ( Unit :: AuraEffectList :: const_iterator itr = auraClassScripts . begin (); itr != auraClassScripts . end ();)
2009-02-24 20:52:55 -06:00
{
2010-04-07 23:25:02 +02:00
if (( * itr ) -> GetMiscValue () == 2228 )
2009-02-24 20:52:55 -06:00
{
RemoveAurasDueToSpell (( * itr ) -> GetId ());
itr = auraClassScripts . begin ();
}
else
++ itr ;
}
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( duration > 0 )
2009-02-24 20:05:29 -06:00
pet -> SetDuration ( duration );
2009-10-17 15:51:44 -07:00
2009-02-24 20:52:55 -06:00
return NULL ;
}
2009-10-17 15:51:44 -07:00
2010-04-07 23:25:02 +02:00
// petentry == 0 for hunter "call pet" (current pet summoned if any)
2010-04-07 19:14:10 +02:00
if ( ! entry )
2009-02-24 20:52:55 -06:00
{
delete pet ;
2009-02-24 20:05:29 -06:00
return NULL ;
}
2009-10-17 15:51:44 -07:00
2009-08-26 19:28:21 -05:00
pet -> Relocate ( x , y , z , ang );
2010-04-07 19:14:10 +02:00
if ( ! pet -> IsPositionValid ())
2009-02-19 18:30:03 -06:00
{
2011-04-29 20:47:02 +02:00
sLog -> outError ( "Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)" , pet -> GetGUIDLow (), pet -> GetEntry (), pet -> GetPositionX (), pet -> GetPositionY ());
2009-02-24 20:05:29 -06:00
delete pet ;
2009-02-19 18:30:03 -06:00
return NULL ;
}
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
Map * map = GetMap ();
2010-12-22 21:25:23 +01:00
uint32 pet_number = sObjectMgr -> GeneratePetNumber ();
if ( ! pet -> Create ( sObjectMgr -> GenerateLowGuid ( HIGHGUID_PET ), map , GetPhaseMask (), entry , pet_number ))
2009-02-19 18:30:03 -06:00
{
2010-12-23 23:25:44 +01:00
sLog -> outError ( "no such creature entry %u" , entry );
2009-02-24 20:05:29 -06:00
delete pet ;
2009-02-19 18:30:03 -06:00
return NULL ;
}
2009-10-17 15:51:44 -07:00
2009-02-24 20:05:29 -06:00
pet -> SetCreatorGUID ( GetGUID ());
pet -> SetUInt32Value ( UNIT_FIELD_FACTIONTEMPLATE , getFaction ());
2009-10-17 15:51:44 -07:00
2009-02-24 20:52:55 -06:00
pet -> setPowerType ( POWER_MANA );
2011-09-29 12:43:05 +02:00
pet -> SetUInt32Value ( UNIT_NPC_FLAGS , 0 );
2011-04-29 20:47:02 +02:00
pet -> SetUInt32Value ( UNIT_FIELD_BYTES_1 , 0 );
2009-02-24 20:52:55 -06:00
pet -> InitStatsForLevel ( getLevel ());
2009-10-17 15:51:44 -07:00
2009-05-02 19:24:22 -05:00
SetMinion ( pet , true );
2009-10-17 15:51:44 -07:00
2011-09-29 12:43:05 +02:00
switch ( petType )
2009-02-24 20:05:29 -06:00
{
2009-02-24 20:52:55 -06:00
case SUMMON_PET :
2009-05-24 12:28:26 -05:00
// this enables pet details window (Shift+P)
pet -> GetCharmInfo () -> SetPetNumber ( pet_number , true );
2009-02-24 20:52:55 -06:00
pet -> SetUInt32Value ( UNIT_FIELD_BYTES_0 , 2048 );
pet -> SetUInt32Value ( UNIT_FIELD_PETEXPERIENCE , 0 );
pet -> SetUInt32Value ( UNIT_FIELD_PETNEXTLEVELEXP , 1000 );
2010-08-26 01:20:57 +06:00
pet -> SetFullHealth ();
2009-02-24 20:52:55 -06:00
pet -> SetPower ( POWER_MANA , pet -> GetMaxPower ( POWER_MANA ));
2010-09-03 21:55:57 -07:00
pet -> SetUInt32Value ( UNIT_FIELD_PET_NAME_TIMESTAMP , uint32 ( time ( NULL ))); // cast can't be helped in this case
2009-05-06 13:34:11 -05:00
break ;
2010-08-21 20:08:47 +02:00
default :
break ;
2009-05-06 13:34:11 -05:00
}
2009-10-17 15:51:44 -07:00
2011-10-10 17:39:34 -04:00
map -> AddToMap ( pet -> ToCreature ());
2009-10-17 15:51:44 -07:00
2011-09-29 12:43:05 +02:00
switch ( petType )
2009-05-06 13:34:11 -05:00
{
case SUMMON_PET :
2009-02-24 20:52:55 -06:00
pet -> InitPetCreateSpells ();
2009-05-08 17:15:19 -05:00
pet -> InitTalentForLevel ();
2009-02-24 20:52:55 -06:00
pet -> SavePetToDB ( PET_SAVE_AS_CURRENT );
PetSpellInitialize ();
break ;
2010-08-21 20:08:47 +02:00
default :
break ;
2009-02-24 20:52:55 -06:00
}
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( petType == SUMMON_PET )
2009-02-24 20:52:55 -06:00
{
// Remove Demonic Sacrifice auras (known pet)
2010-01-10 01:23:15 +01:00
Unit :: AuraEffectList const & auraClassScripts = GetAuraEffectsByType ( SPELL_AURA_OVERRIDE_CLASS_SCRIPTS );
2010-04-08 08:20:08 +02:00
for ( Unit :: AuraEffectList :: const_iterator itr = auraClassScripts . begin (); itr != auraClassScripts . end ();)
2009-02-24 20:52:55 -06:00
{
2010-04-07 23:25:02 +02:00
if (( * itr ) -> GetMiscValue () == 2228 )
2009-02-24 20:52:55 -06:00
{
RemoveAurasDueToSpell (( * itr ) -> GetId ());
itr = auraClassScripts . begin ();
}
else
++ itr ;
}
2009-02-24 20:05:29 -06:00
}
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( duration > 0 )
2009-02-24 20:52:55 -06:00
pet -> SetDuration ( duration );
2009-10-17 15:51:44 -07:00
2009-05-03 11:06:48 -05:00
//ObjectAccessor::UpdateObjectVisibility(pet);
2009-10-17 15:51:44 -07:00
2009-02-24 20:05:29 -06:00
return pet ;
2009-02-19 18:30:03 -06:00
}
2009-10-17 15:51:44 -07:00
2008-10-17 18:13:04 -05:00
GameObject * WorldObject :: SummonGameObject ( uint32 entry , float x , float y , float z , float ang , float rotation0 , float rotation1 , float rotation2 , float rotation3 , uint32 respawnTime )
{
2010-04-07 19:14:10 +02:00
if ( ! IsInWorld ())
2008-10-17 18:13:04 -05:00
return NULL ;
2009-10-17 15:51:44 -07:00
2011-04-28 22:54:30 +02:00
GameObjectTemplate const * goinfo = sObjectMgr -> GetGameObjectTemplate ( entry );
2010-04-07 19:14:10 +02:00
if ( ! goinfo )
2008-10-17 18:13:04 -05:00
{
2010-12-23 23:25:44 +01:00
sLog -> outErrorDb ( "Gameobject template %u not found in database!" , entry );
2008-10-17 18:13:04 -05:00
return NULL ;
}
2011-09-15 14:08:17 +02:00
Map * map = GetMap ();
GameObject * go = new GameObject ();
2011-04-29 20:47:02 +02:00
if ( ! go -> Create ( sObjectMgr -> GenerateLowGuid ( HIGHGUID_GAMEOBJECT ), entry , map , GetPhaseMask (), x , y , z , ang , rotation0 , rotation1 , rotation2 , rotation3 , 100 , GO_STATE_READY ))
2009-04-01 21:17:59 -06:00
{
delete go ;
2008-10-17 18:13:04 -05:00
return NULL ;
2009-04-01 21:17:59 -06:00
}
2008-10-17 18:13:04 -05:00
go -> SetRespawnTime ( respawnTime );
2010-04-07 19:14:10 +02:00
if ( GetTypeId () == TYPEID_PLAYER || GetTypeId () == TYPEID_UNIT ) //not sure how to handle this
2008-10-18 19:59:34 -05:00
(( Unit * ) this ) -> AddGameObject ( go );
else
go -> SetSpawnedByDefault ( false );
2011-10-10 17:39:34 -04:00
map -> AddToMap ( go );
2009-10-17 15:51:44 -07:00
2008-10-17 18:13:04 -05:00
return go ;
}
2009-10-17 15:51:44 -07:00
2008-12-10 20:25:47 -06:00
Creature * WorldObject :: SummonTrigger ( float x , float y , float z , float ang , uint32 duration , CreatureAI * ( * GetAI )( Creature * ))
{
TempSummonType summonType = ( duration == 0 ) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN ;
2008-12-15 15:38:02 -06:00
Creature * summon = SummonCreature ( WORLD_TRIGGER , x , y , z , ang , summonType , duration );
2010-04-07 19:14:10 +02:00
if ( ! summon )
2008-12-10 20:25:47 -06:00
return NULL ;
2009-10-17 15:51:44 -07:00
2008-12-10 20:25:47 -06:00
//summon->SetName(GetName());
2010-04-07 19:14:10 +02:00
if ( GetTypeId () == TYPEID_PLAYER || GetTypeId () == TYPEID_UNIT )
2008-12-10 20:25:47 -06:00
{
summon -> setFaction ((( Unit * ) this ) -> getFaction ());
summon -> SetLevel ((( Unit * ) this ) -> getLevel ());
}
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( GetAI )
2008-12-10 20:25:47 -06:00
summon -> AIM_Initialize ( GetAI ( summon ));
return summon ;
}
2009-10-17 15:51:44 -07:00
2011-08-30 13:46:36 +02:00
Creature * WorldObject :: FindNearestCreature ( uint32 entry , float range , bool alive ) const
2009-05-29 16:49:28 -05:00
{
2011-09-15 14:08:17 +02:00
Creature * creature = NULL ;
2009-12-17 11:40:23 +01:00
Trinity :: NearestCreatureEntryWithLiveStateInObjectRangeCheck checker ( * this , entry , alive , range );
Trinity :: CreatureLastSearcher < Trinity :: NearestCreatureEntryWithLiveStateInObjectRangeCheck > searcher ( this , creature , checker );
VisitNearbyObject ( range , searcher );
return creature ;
2009-05-29 16:49:28 -05:00
}
2009-10-17 15:51:44 -07:00
2011-08-30 13:46:36 +02:00
GameObject * WorldObject :: FindNearestGameObject ( uint32 entry , float range ) const
2009-05-29 16:49:28 -05:00
{
2011-09-15 14:08:17 +02:00
GameObject * go = NULL ;
2009-12-17 11:40:23 +01:00
Trinity :: NearestGameObjectEntryInObjectRangeCheck checker ( * this , entry , range );
Trinity :: GameObjectLastSearcher < Trinity :: NearestGameObjectEntryInObjectRangeCheck > searcher ( this , go , checker );
2010-08-26 22:05:57 +02:00
VisitNearbyGridObject ( range , searcher );
2009-12-17 11:40:23 +01:00
return go ;
}
2011-10-19 17:40:44 +01:00
void WorldObject :: GetGameObjectListWithEntryInGrid ( std :: list < GameObject *>& gameobjectList , uint32 entry , float maxSearchRange ) const
2009-12-17 11:40:23 +01:00
{
2011-10-18 10:53:34 -04:00
CellCoord pair ( Trinity :: ComputeCellCoord ( this -> GetPositionX (), this -> GetPositionY ()));
2009-12-17 11:40:23 +01:00
Cell cell ( pair );
cell . SetNoCreate ();
2011-10-19 17:40:44 +01:00
Trinity :: AllGameObjectsWithEntryInRange check ( this , entry , maxSearchRange );
Trinity :: GameObjectListSearcher < Trinity :: AllGameObjectsWithEntryInRange > searcher ( this , gameobjectList , check );
2009-12-17 11:40:23 +01:00
TypeContainerVisitor < Trinity :: GameObjectListSearcher < Trinity :: AllGameObjectsWithEntryInRange > , GridTypeMapContainer > visitor ( searcher );
2011-10-19 17:40:44 +01:00
cell . Visit ( pair , visitor , * ( this -> GetMap ()), * this , maxSearchRange );
2009-07-24 05:27:49 +02:00
}
2009-10-17 15:51:44 -07:00
2011-10-19 17:40:44 +01:00
void WorldObject :: GetCreatureListWithEntryInGrid ( std :: list < Creature *>& creatureList , uint32 entry , float maxSearchRange ) const
2009-07-24 05:27:49 +02:00
{
2011-10-18 10:53:34 -04:00
CellCoord pair ( Trinity :: ComputeCellCoord ( this -> GetPositionX (), this -> GetPositionY ()));
2009-12-17 11:40:23 +01:00
Cell cell ( pair );
cell . SetNoCreate ();
2011-10-19 17:40:44 +01:00
Trinity :: AllCreaturesOfEntryInRange check ( this , entry , maxSearchRange );
Trinity :: CreatureListSearcher < Trinity :: AllCreaturesOfEntryInRange > searcher ( this , creatureList , check );
2009-07-24 05:27:49 +02:00
TypeContainerVisitor < Trinity :: CreatureListSearcher < Trinity :: AllCreaturesOfEntryInRange > , GridTypeMapContainer > visitor ( searcher );
2009-10-17 15:51:44 -07:00
2011-10-19 17:40:44 +01:00
cell . Visit ( pair , visitor , * ( this -> GetMap ()), * this , maxSearchRange );
2009-07-24 05:27:49 +02:00
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
/*
2009-12-20 15:20:04 +01:00
namespace Trinity
2009-05-14 16:50:47 -05:00
{
class NearUsedPosDo
{
public:
NearUsedPosDo(WorldObject const& obj, WorldObject const* searcher, float angle, ObjectPosSelector& selector)
: i_object(obj), i_searcher(searcher), i_angle(angle), i_selector(selector) {}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
void operator()(Corpse*) const {}
void operator()(DynamicObject*) const {}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
void operator()(Creature* c) const
{
// skip self or target
2010-04-07 23:25:02 +02:00
if (c == i_searcher || c == &i_object)
2009-05-14 16:50:47 -05:00
return;
2009-10-17 15:51:44 -07:00
2011-04-29 20:47:02 +02:00
float x, y, z;
2009-10-17 15:51:44 -07:00
2010-12-17 13:43:24 +01:00
if (!c->isAlive() || c->HasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED) ||
2011-04-29 20:47:02 +02:00
!c->GetMotionMaster()->GetDestination(x, y, z))
2009-05-14 16:50:47 -05:00
{
x = c->GetPositionX();
y = c->GetPositionY();
}
2009-10-17 15:51:44 -07:00
2011-04-29 20:47:02 +02:00
add(c, x, y);
2009-05-14 16:50:47 -05:00
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
template<class T>
void operator()(T* u) const
{
// skip self or target
2010-04-07 23:25:02 +02:00
if (u == i_searcher || u == &i_object)
2009-05-14 16:50:47 -05:00
return;
2009-10-17 15:51:44 -07:00
2011-04-29 20:47:02 +02:00
float x, y;
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
x = u->GetPositionX();
y = u->GetPositionY();
2009-10-17 15:51:44 -07:00
2011-04-29 20:47:02 +02:00
add(u, x, y);
2009-05-14 16:50:47 -05:00
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
// we must add used pos that can fill places around center
void add(WorldObject* u, float x, float y) const
{
// u is too nearest/far away to i_object
2011-04-29 20:47:02 +02:00
if (!i_object.IsInRange2d(x, y, i_selector.m_dist - i_selector.m_size, i_selector.m_dist + i_selector.m_size))
2009-05-14 16:50:47 -05:00
return;
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
float angle = i_object.GetAngle(u)-i_angle;
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
// move angle to range -pi ... +pi
2010-04-07 22:59:46 +02:00
while (angle > M_PI)
2009-05-14 16:50:47 -05:00
angle -= 2.0f * M_PI;
2010-04-07 19:13:19 +02:00
while (angle < -M_PI)
2009-05-14 16:50:47 -05:00
angle += 2.0f * M_PI;
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
// dist include size of u
2011-04-29 20:47:02 +02:00
float dist2d = i_object.GetDistance2d(x, y);
i_selector.AddUsedPos(u->GetObjectSize(), angle, dist2d + i_object.GetObjectSize());
2009-05-14 16:50:47 -05:00
}
private:
WorldObject const& i_object;
WorldObject const* i_searcher;
float i_angle;
ObjectPosSelector& i_selector;
};
2009-12-20 15:20:04 +01:00
} // namespace Trinity
2009-05-14 16:50:47 -05:00
*/
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
//===================================================================================================
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void WorldObject :: GetNearPoint2D ( float & x , float & y , float distance2d , float absAngle ) const
2008-10-11 14:16:25 -05:00
{
x = GetPositionX () + ( GetObjectSize () + distance2d ) * cos ( absAngle );
y = GetPositionY () + ( GetObjectSize () + distance2d ) * sin ( absAngle );
2009-10-17 15:51:44 -07:00
2008-10-14 11:57:03 -05:00
Trinity :: NormalizeMapCoord ( x );
Trinity :: NormalizeMapCoord ( y );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2010-04-19 09:26:37 +02:00
void WorldObject :: GetNearPoint ( WorldObject const * /*searcher*/ , float & x , float & y , float & z , float searcher_size , float distance2d , float absAngle ) const
2008-10-11 14:16:25 -05:00
{
2011-04-29 20:47:02 +02:00
GetNearPoint2D ( x , y , distance2d + searcher_size , absAngle );
2009-02-09 08:16:34 -05:00
z = GetPositionZ ();
2012-01-29 15:28:19 -05:00
UpdateAllowedPositionZ ( x , y , z );
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
/*
// if detection disabled, return first point
2010-12-23 23:25:44 +01:00
if (!sWorld->getIntConfig(CONFIG_DETECT_POS_COLLISION))
2009-05-14 16:50:47 -05:00
{
2011-04-29 20:47:02 +02:00
UpdateGroundPositionZ(x, y, z); // update to LOS height if available
2009-05-14 16:50:47 -05:00
return;
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
// or remember first point
float first_x = x;
float first_y = y;
bool first_los_conflict = false; // first point LOS problems
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
// prepare selector for work
2011-04-29 20:47:02 +02:00
ObjectPosSelector selector(GetPositionX(), GetPositionY(), GetObjectSize(), distance2d+searcher_size);
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
// adding used positions around object
{
2011-10-18 10:53:34 -04:00
CellCoord p(Trinity::ComputeCellCoord(GetPositionX(), GetPositionY()));
2009-05-14 16:50:47 -05:00
Cell cell(p);
cell.SetNoCreate();
2009-10-17 15:51:44 -07:00
2011-04-29 20:47:02 +02:00
Trinity::NearUsedPosDo u_do(*this, searcher, absAngle, selector);
Trinity::WorldObjectWorker<Trinity::NearUsedPosDo> worker(this, u_do);
2009-10-17 15:51:44 -07:00
2009-12-20 15:20:04 +01:00
TypeContainerVisitor<Trinity::WorldObjectWorker<Trinity::NearUsedPosDo>, GridTypeMapContainer > grid_obj_worker(worker);
TypeContainerVisitor<Trinity::WorldObjectWorker<Trinity::NearUsedPosDo>, WorldTypeMapContainer > world_obj_worker(worker);
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
CellLock<GridReadGuard> cell_lock(cell, p);
2009-09-27 02:24:25 -07:00
cell_lock->Visit(cell_lock, grid_obj_worker, *GetMap(), *this, distance2d);
cell_lock->Visit(cell_lock, world_obj_worker, *GetMap(), *this, distance2d);
2009-05-14 16:50:47 -05:00
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
// maybe can just place in primary position
2010-04-07 22:59:46 +02:00
if (selector.CheckOriginal())
2009-05-14 16:50:47 -05:00
{
2011-04-29 20:47:02 +02:00
UpdateGroundPositionZ(x, y, z); // update to LOS height if available
2009-10-17 15:51:44 -07:00
2011-04-29 20:47:02 +02:00
if (IsWithinLOS(x, y, z))
2009-05-14 16:50:47 -05:00
return;
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
first_los_conflict = true; // first point have LOS problems
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
float angle; // candidate of angle for free pos
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
// special case when one from list empty and then empty side preferred
2010-04-07 19:14:10 +02:00
if (selector.FirstAngle(angle))
2009-05-14 16:50:47 -05:00
{
2011-04-29 20:47:02 +02:00
GetNearPoint2D(x, y, distance2d, absAngle+angle);
2009-05-14 16:50:47 -05:00
z = GetPositionZ();
2011-04-29 20:47:02 +02:00
UpdateGroundPositionZ(x, y, z); // update to LOS height if available
2009-10-17 15:51:44 -07:00
2011-04-29 20:47:02 +02:00
if (IsWithinLOS(x, y, z))
2009-05-14 16:50:47 -05:00
return;
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
// set first used pos in lists
selector.InitializeAngle();
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
// select in positions after current nodes (selection one by one)
2010-04-07 19:13:19 +02:00
while (selector.NextAngle(angle)) // angle for free pos
2009-05-14 16:50:47 -05:00
{
2011-04-29 20:47:02 +02:00
GetNearPoint2D(x, y, distance2d, absAngle+angle);
2009-05-14 16:50:47 -05:00
z = GetPositionZ();
2011-04-29 20:47:02 +02:00
UpdateGroundPositionZ(x, y, z); // update to LOS height if available
2009-10-17 15:51:44 -07:00
2011-04-29 20:47:02 +02:00
if (IsWithinLOS(x, y, z))
2009-05-14 16:50:47 -05:00
return;
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
// BAD NEWS: not free pos (or used or have LOS problems)
// Attempt find _used_ pos without LOS problem
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if (!first_los_conflict)
2009-05-14 16:50:47 -05:00
{
x = first_x;
y = first_y;
2009-10-17 15:51:44 -07:00
2011-04-29 20:47:02 +02:00
UpdateGroundPositionZ(x, y, z); // update to LOS height if available
2009-05-14 16:50:47 -05:00
return;
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
// special case when one from list empty and then empty side preferred
2010-04-07 22:59:46 +02:00
if (selector.IsNonBalanced())
2009-05-14 16:50:47 -05:00
{
2010-04-07 19:14:10 +02:00
if (!selector.FirstAngle(angle)) // _used_ pos
2009-05-14 16:50:47 -05:00
{
2011-04-29 20:47:02 +02:00
GetNearPoint2D(x, y, distance2d, absAngle+angle);
2009-05-14 16:50:47 -05:00
z = GetPositionZ();
2011-04-29 20:47:02 +02:00
UpdateGroundPositionZ(x, y, z); // update to LOS height if available
2009-10-17 15:51:44 -07:00
2011-04-29 20:47:02 +02:00
if (IsWithinLOS(x, y, z))
2009-05-14 16:50:47 -05:00
return;
}
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
// set first used pos in lists
selector.InitializeAngle();
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
// select in positions after current nodes (selection one by one)
2010-04-07 19:13:19 +02:00
while (selector.NextUsedAngle(angle)) // angle for used pos but maybe without LOS problem
2009-05-14 16:50:47 -05:00
{
2011-04-29 20:47:02 +02:00
GetNearPoint2D(x, y, distance2d, absAngle+angle);
2009-05-14 16:50:47 -05:00
z = GetPositionZ();
2011-04-29 20:47:02 +02:00
UpdateGroundPositionZ(x, y, z); // update to LOS height if available
2009-10-17 15:51:44 -07:00
2011-04-29 20:47:02 +02:00
if (IsWithinLOS(x, y, z))
2009-05-14 16:50:47 -05:00
return;
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
// BAD BAD NEWS: all found pos (free and used) have LOS problem :(
x = first_x;
y = first_y;
2009-10-17 15:51:44 -07:00
2011-04-29 20:47:02 +02:00
UpdateGroundPositionZ(x, y, z); // update to LOS height if available
2009-05-14 16:50:47 -05:00
*/
2008-12-24 09:58:26 -06:00
}
2009-10-17 15:51:44 -07:00
2009-08-29 23:20:16 -05:00
void WorldObject :: MovePosition ( Position & pos , float dist , float angle )
2009-01-08 14:22:15 -06:00
{
2009-08-29 23:20:16 -05:00
angle += m_orientation ;
pos . m_positionX += dist * cos ( angle );
pos . m_positionY += dist * sin ( angle );
Trinity :: NormalizeMapCoord ( pos . m_positionX );
Trinity :: NormalizeMapCoord ( pos . m_positionY );
UpdateGroundPositionZ ( pos . m_positionX , pos . m_positionY , pos . m_positionZ );
pos . m_orientation = m_orientation ;
2009-01-08 14:22:15 -06:00
}
2009-10-17 15:51:44 -07:00
2010-07-21 02:06:51 +02:00
void WorldObject :: MovePositionToFirstCollision ( Position & pos , float dist , float angle )
{
angle += m_orientation ;
float destx , desty , destz , ground , floor ;
destx = pos . m_positionX + dist * cos ( angle );
desty = pos . m_positionY + dist * sin ( angle );
ground = GetMap () -> GetHeight ( destx , desty , MAX_HEIGHT , true );
floor = GetMap () -> GetHeight ( destx , desty , pos . m_positionZ , true );
destz = fabs ( ground - pos . m_positionZ ) <= fabs ( floor - pos . m_positionZ ) ? ground : floor ;
2011-04-29 20:47:02 +02:00
bool col = VMAP :: VMapFactory :: createOrGetVMapManager () -> getObjectHitPos ( GetMapId (), pos . m_positionX , pos . m_positionY , pos . m_positionZ + 0.5f , destx , desty , destz + 0.5f , destx , desty , destz , - 0.5f );
2010-07-21 02:06:51 +02:00
// collision occured
if ( col )
{
// move back a bit
destx -= CONTACT_DISTANCE * cos ( angle );
desty -= CONTACT_DISTANCE * sin ( angle );
dist = sqrt (( pos . m_positionX - destx ) * ( pos . m_positionX - destx ) + ( pos . m_positionY - desty ) * ( pos . m_positionY - desty ));
}
float step = dist / 10.0f ;
2010-08-30 15:25:15 +02:00
for ( uint8 j = 0 ; j < 10 ; ++ j )
2010-07-21 02:06:51 +02:00
{
// do not allow too big z changes
if ( fabs ( pos . m_positionZ - destz ) > 6 )
{
destx -= step * cos ( angle );
desty -= step * sin ( angle );
ground = GetMap () -> GetHeight ( destx , desty , MAX_HEIGHT , true );
floor = GetMap () -> GetHeight ( destx , desty , pos . m_positionZ , true );
destz = fabs ( ground - pos . m_positionZ ) <= fabs ( floor - pos . m_positionZ ) ? ground : floor ;
}
// we have correct destz now
else
{
pos . Relocate ( destx , desty , destz );
break ;
}
}
Trinity :: NormalizeMapCoord ( pos . m_positionX );
Trinity :: NormalizeMapCoord ( pos . m_positionY );
UpdateGroundPositionZ ( pos . m_positionX , pos . m_positionY , pos . m_positionZ );
pos . m_orientation = m_orientation ;
}
2009-01-31 16:38:50 -06:00
void WorldObject :: SetPhaseMask ( uint32 newPhaseMask , bool update )
{
m_phaseMask = newPhaseMask ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( update && IsInWorld ())
2010-02-03 16:53:40 +02:00
UpdateObjectVisibility ();
2009-01-31 16:38:50 -06:00
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void WorldObject :: PlayDistanceSound ( uint32 sound_id , Player * target /*= NULL*/ )
2009-03-22 19:20:03 -06:00
{
2011-04-29 20:47:02 +02:00
WorldPacket data ( SMSG_PLAY_OBJECT_SOUND , 4 + 8 );
2009-03-22 19:20:03 -06:00
data << uint32 ( sound_id );
2009-05-31 15:56:51 -05:00
data << uint64 ( GetGUID ());
2009-03-22 19:20:03 -06:00
if ( target )
2010-04-07 22:59:46 +02:00
target -> SendDirectMessage ( & data );
2009-03-22 19:20:03 -06:00
else
2010-04-07 22:59:46 +02:00
SendMessageToSet ( & data , true );
2009-03-22 19:20:03 -06:00
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void WorldObject :: PlayDirectSound ( uint32 sound_id , Player * target /*= NULL*/ )
2009-03-22 19:20:03 -06:00
{
WorldPacket data ( SMSG_PLAY_SOUND , 4 );
data << uint32 ( sound_id );
if ( target )
2010-04-07 22:59:46 +02:00
target -> SendDirectMessage ( & data );
2009-03-22 19:20:03 -06:00
else
2010-04-07 22:59:46 +02:00
SendMessageToSet ( & data , true );
2009-03-22 19:20:03 -06:00
}
2009-10-17 15:51:44 -07:00
2009-08-28 14:19:14 -05:00
void WorldObject :: DestroyForNearbyPlayers ()
{
2010-04-07 19:14:10 +02:00
if ( ! IsInWorld ())
2009-08-28 14:19:14 -05:00
return ;
2009-10-17 15:51:44 -07:00
2010-03-14 00:22:53 +01:00
std :: list < Player *> targets ;
2011-07-31 21:57:23 +02:00
Trinity :: AnyPlayerInObjectRangeCheck check ( this , GetVisibilityRange (), false );
2010-03-14 00:22:53 +01:00
Trinity :: PlayerListSearcher < Trinity :: AnyPlayerInObjectRangeCheck > searcher ( this , targets , check );
2010-11-13 17:18:09 +01:00
VisitNearbyWorldObject ( GetVisibilityRange (), searcher );
2010-03-14 00:22:53 +01:00
for ( std :: list < Player *>:: const_iterator iter = targets . begin (); iter != targets . end (); ++ iter )
2009-08-28 14:19:14 -05:00
{
2011-11-07 11:06:39 -06:00
Player * player = ( * iter );
2009-10-17 15:51:44 -07:00
2011-11-07 11:06:39 -06:00
if ( player == this )
2009-08-28 14:19:14 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2011-11-07 11:06:39 -06:00
if ( ! player -> HaveAtClient ( this ))
2009-08-28 14:19:14 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2011-11-07 11:06:39 -06:00
if ( isType ( TYPEMASK_UNIT ) && (( Unit * ) this ) -> GetCharmerGUID () == player -> GetGUID ()) // TODO: this is for puppet
2009-08-28 14:19:14 -05:00
continue ;
2009-10-17 16:20:24 -07:00
2011-11-07 11:06:39 -06:00
DestroyForPlayer ( player );
player -> m_clientGUIDs . erase ( GetGUID ());
2009-08-28 14:19:14 -05:00
}
}
2010-02-03 16:53:40 +02:00
2010-02-27 15:25:14 +02:00
void WorldObject :: UpdateObjectVisibility ( bool /*forced*/ )
2010-02-03 16:53:40 +02:00
{
2010-02-27 15:25:14 +02:00
//updates object's visibility for nearby players
Trinity :: VisibleChangesNotifier notifier ( * this );
2010-11-13 17:18:09 +01:00
VisitNearbyWorldObject ( GetVisibilityRange (), notifier );
2010-02-03 16:53:40 +02:00
}
struct WorldObjectChangeAccumulator
{
2011-08-30 13:46:36 +02:00
UpdateDataMapType & i_updateDatas ;
WorldObject & i_object ;
2010-02-03 16:53:40 +02:00
std :: set < uint64 > plr_list ;
WorldObjectChangeAccumulator ( WorldObject & obj , UpdateDataMapType & d ) : i_updateDatas ( d ), i_object ( obj ) {}
void Visit ( PlayerMapType & m )
{
2011-08-30 13:46:36 +02:00
Player * source = NULL ;
2010-02-03 16:53:40 +02:00
for ( PlayerMapType :: iterator iter = m . begin (); iter != m . end (); ++ iter )
{
2011-08-30 13:46:36 +02:00
source = iter -> getSource ();
BuildPacket ( source );
if ( ! source -> GetSharedVisionList (). empty ())
2010-02-03 16:53:40 +02:00
{
2011-08-30 13:46:36 +02:00
SharedVisionList :: const_iterator it = source -> GetSharedVisionList (). begin ();
for (; it != source -> GetSharedVisionList (). end (); ++ it )
2010-02-03 16:53:40 +02:00
BuildPacket ( * it );
}
}
}
void Visit ( CreatureMapType & m )
{
2011-08-30 13:46:36 +02:00
Creature * source = NULL ;
2010-02-03 16:53:40 +02:00
for ( CreatureMapType :: iterator iter = m . begin (); iter != m . end (); ++ iter )
{
2011-08-30 13:46:36 +02:00
source = iter -> getSource ();
if ( ! source -> GetSharedVisionList (). empty ())
2010-02-03 16:53:40 +02:00
{
2011-08-30 13:46:36 +02:00
SharedVisionList :: const_iterator it = source -> GetSharedVisionList (). begin ();
for (; it != source -> GetSharedVisionList (). end (); ++ it )
2010-02-03 16:53:40 +02:00
BuildPacket ( * it );
}
}
}
2011-08-30 13:46:36 +02:00
2010-02-03 16:53:40 +02:00
void Visit ( DynamicObjectMapType & m )
{
2011-08-30 13:46:36 +02:00
DynamicObject * source = NULL ;
2010-02-03 16:53:40 +02:00
for ( DynamicObjectMapType :: iterator iter = m . begin (); iter != m . end (); ++ iter )
{
2011-08-30 13:46:36 +02:00
source = iter -> getSource ();
uint64 guid = source -> GetCasterGUID ();
2010-04-07 19:14:10 +02:00
if ( IS_PLAYER_GUID ( guid ))
2010-02-03 16:53:40 +02:00
{
//Caster may be NULL if DynObj is in removelist
2011-09-15 14:08:17 +02:00
if ( Player * caster = ObjectAccessor :: FindPlayer ( guid ))
2011-08-30 13:46:36 +02:00
if ( caster -> GetUInt64Value ( PLAYER_FARSIGHT ) == source -> GetGUID ())
2010-02-03 16:53:40 +02:00
BuildPacket ( caster );
}
}
}
2011-08-30 13:46:36 +02:00
2011-11-07 11:06:39 -06:00
void BuildPacket ( Player * player )
2010-02-03 16:53:40 +02:00
{
// Only send update once to a player
2011-11-07 11:06:39 -06:00
if ( plr_list . find ( player -> GetGUID ()) == plr_list . end () && player -> HaveAtClient ( & i_object ))
2010-02-03 16:53:40 +02:00
{
2011-11-07 11:06:39 -06:00
i_object . BuildFieldsUpdate ( player , i_updateDatas );
plr_list . insert ( player -> GetGUID ());
2010-02-03 16:53:40 +02:00
}
}
template < class SKIP > void Visit ( GridRefManager < SKIP > & ) {}
};
void WorldObject :: BuildUpdate ( UpdateDataMapType & data_map )
{
2011-10-18 10:53:34 -04:00
CellCoord p = Trinity :: ComputeCellCoord ( GetPositionX (), GetPositionY ());
2010-02-03 16:53:40 +02:00
Cell cell ( p );
cell . SetNoCreate ();
WorldObjectChangeAccumulator notifier ( * this , data_map );
TypeContainerVisitor < WorldObjectChangeAccumulator , WorldTypeMapContainer > player_notifier ( notifier );
Map & map = * GetMap ();
//we must build packets for all visible players
2010-11-13 17:18:09 +01:00
cell . Visit ( p , player_notifier , map , * this , GetVisibilityRange ());
2010-02-03 16:53:40 +02:00
ClearUpdateMask ( false );
}
2010-08-08 20:32:14 +02:00
uint64 WorldObject :: GetTransGUID () const
{
if ( GetTransport ())
return GetTransport () -> GetGUID ();
return 0 ;
2010-08-21 20:08:47 +02:00
}