2010-10-07 15:35:36 +02:00
/*
2012-12-31 23:15:50 +01:00
* Copyright (C) 2008-2013 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
2013-03-25 10:36:30 +01:00
#include "Object.h"
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 "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"
2012-07-22 14:20:26 +02:00
#include "UpdateFieldFlags.h"
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"
2012-02-03 16:03:52 -05:00
#include "DynamicTree.h"
2012-07-14 23:39:12 +02:00
#include "Unit.h"
2012-07-22 14:20:26 +02:00
#include "Group.h"
2012-08-20 16:23:24 -04:00
#include "Battlefield.h"
#include "BattlefieldMgr.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 ;
2013-05-26 04:28:19 +03:00
case HIGHGUID_AREATRIGGER : return TYPEID_AREATRIGGER ;
2008-10-11 14:16:25 -05:00
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 ;
2008-10-11 14:16:25 -05:00
m_valuesCount = 0 ;
2012-07-22 14:20:26 +02:00
_fieldNotifyFlags = UF_FLAG_DYNAMIC ;
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
{
2013-05-13 15:07:36 +02:00
TC_LOG_FATAL ( LOG_FILTER_GENERAL , "Object::~Object Corpse guid=" UI64FMTD ", type=%d, entry=%u deleted but still in map!!" ,
2012-10-24 13:29:34 +02:00
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
{
2013-05-13 15:07:36 +02:00
TC_LOG_FATAL ( LOG_FILTER_GENERAL , "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 ))
2013-05-13 15:07:36 +02:00
TC_LOG_FATAL ( LOG_FILTER_GENERAL , "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
{
2013-05-13 15:07:36 +02:00
TC_LOG_FATAL ( LOG_FILTER_GENERAL , "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 ;
2013-03-04 16:30:54 +01:00
m_uint32Values = 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
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
2013-01-22 18:45:09 +01:00
_changesMask . SetCount ( m_valuesCount );
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 );
2012-07-23 13:43:57 +02:00
SetUInt16Value ( OBJECT_FIELD_TYPE , 0 , m_objectType );
2012-07-29 23:44:30 +02:00
m_PackGUID . clear ();
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 :: 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
2012-08-07 13:27:33 +02: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
2012-07-28 19:18:47 +02:00
uint32 valCount = m_valuesCount ;
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 ;
2012-07-28 19:18:47 +02:00
else if ( GetTypeId () == TYPEID_PLAYER )
valCount = PLAYER_END_NOT_SELF ;
2009-10-17 15:51:44 -07:00
2012-08-07 13:27:33 +02:00
switch ( GetGUIDHigh ())
2008-10-11 14:16:25 -05:00
{
2012-08-07 13:27:33 +02:00
case HIGHGUID_PLAYER :
case HIGHGUID_PET :
case HIGHGUID_CORPSE :
case HIGHGUID_DYNAMICOBJECT :
2013-05-26 04:28:19 +03:00
case HIGHGUID_AREATRIGGER :
2012-08-07 13:27:33 +02:00
updateType = UPDATETYPE_CREATE_OBJECT2 ;
break ;
case HIGHGUID_UNIT :
2013-04-09 17:26:02 +02:00
case HIGHGUID_VEHICLE :
{
2013-03-25 14:34:22 +01:00
if ( TempSummon const * summon = ToUnit () -> ToTempSummon ())
if ( IS_PLAYER_GUID ( summon -> GetSummonerGUID ()))
updateType = UPDATETYPE_CREATE_OBJECT2 ;
2013-04-09 17:26:02 +02:00
2012-08-07 13:27:33 +02:00
break ;
2013-04-09 17:26:02 +02:00
}
2012-08-07 13:27:33 +02:00
case HIGHGUID_GAMEOBJECT :
2013-04-09 17:26:02 +02:00
{
2012-08-07 13:27:33 +02:00
if ( IS_PLAYER_GUID ( ToGameObject () -> GetOwnerGUID ()))
updateType = UPDATETYPE_CREATE_OBJECT2 ;
break ;
2013-04-09 17:26:02 +02:00
}
default :
break ;
2012-08-07 13:27:33 +02:00
}
2009-10-17 15:51:44 -07:00
2012-08-07 13:27:33 +02:00
if ( flags & UPDATEFLAG_STATIONARY_POSITION )
{
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
{
2013-03-25 10:36:30 +01:00
switch ( ToGameObject () -> 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 :
2012-08-07 13:27:33 +02:00
updateType = UPDATETYPE_CREATE_OBJECT2 ;
2008-10-11 14:16:25 -05:00
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
2013-03-25 14:34:22 +01:00
if ( Unit const * unit = ToUnit ())
if ( unit -> getVictim ())
flags |= UPDATEFLAG_HAS_TARGET ;
2009-06-11 00:45:59 -05:00
ByteBuffer buf ( 500 );
2012-08-07 13:27:33 +02:00
buf << uint8 ( updateType );
2009-06-05 17:44:27 -05:00
buf . append ( GetPackGUID ());
2012-07-28 19:18:47 +02: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 ;
2012-07-28 19:18:47 +02:00
updateMask . SetCount ( valCount );
2010-04-07 22:59:46 +02:00
_SetCreateBits ( & updateMask , target );
2012-08-07 13:27:33 +02: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
2011-11-27 16:06:29 +01:00
UpdateData upd ( player -> GetMapId ());
2008-10-11 14:16:25 -05:00
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
2012-07-28 19:18:47 +02: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 ;
2012-07-28 19:18:47 +02:00
uint32 valCount = m_valuesCount ;
if ( GetTypeId () == TYPEID_PLAYER && target != this )
valCount = PLAYER_END_NOT_SELF ;
updateMask . SetCount ( valCount );
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
2012-05-30 08:01:02 +02:00
void Object :: DestroyForPlayer ( Player * target , bool onDeath ) const
2008-10-11 14:16:25 -05:00
{
ASSERT ( target );
2009-10-17 15:51:44 -07:00
2012-12-26 04:02:42 +01:00
if ( isType ( TYPEMASK_UNIT ) || isType ( TYPEMASK_PLAYER ))
{
if ( Battleground * bg = target -> GetBattleground ())
{
if ( bg -> isArena ())
{
WorldPacket data ( SMSG_ARENA_UNIT_DESTROYED , 8 );
data << uint64 ( GetGUID ());
target -> GetSession () -> SendPacket ( & data );
}
}
}
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 ());
2012-05-30 08:01:02 +02:00
//! If the following bool is true, the client will call "void CGUnit_C::OnDeath()" for this object.
//! OnDeath() does for eg trigger death animation and interrupts certain spells/missiles/auras/sounds...
data << uint8 ( onDeath ? 1 : 0 );
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
2013-03-04 11:45:57 +01:00
int32 Object :: GetInt32Value ( uint16 index ) const
{
ASSERT ( index < m_valuesCount || PrintIndexError ( index , false ));
return m_int32Values [ index ];
}
uint32 Object :: GetUInt32Value ( uint16 index ) const
{
ASSERT ( index < m_valuesCount || PrintIndexError ( index , false ));
return m_uint32Values [ index ];
}
uint64 Object :: GetUInt64Value ( uint16 index ) const
{
ASSERT ( index + 1 < m_valuesCount || PrintIndexError ( index , false ));
return * (( uint64 * ) & ( m_uint32Values [ index ]));
}
float Object :: GetFloatValue ( uint16 index ) const
{
ASSERT ( index < m_valuesCount || PrintIndexError ( index , false ));
return m_floatValues [ index ];
}
uint8 Object :: GetByteValue ( uint16 index , uint8 offset ) const
{
ASSERT ( index < m_valuesCount || PrintIndexError ( index , false ));
ASSERT ( offset < 4 );
return * ((( uint8 * ) & m_uint32Values [ index ]) + offset );
}
uint16 Object :: GetUInt16Value ( uint16 index , uint8 offset ) const
{
ASSERT ( index < m_valuesCount || PrintIndexError ( index , false ));
ASSERT ( offset < 2 );
return * ((( uint16 * ) & m_uint32Values [ index ]) + offset );
}
2012-05-30 08:01:02 +02:00
void Object :: _BuildMovementUpdate ( ByteBuffer * data , uint16 flags ) const
2008-10-11 14:16:25 -05:00
{
2013-03-25 14:34:22 +01:00
Unit const * self = NULL ;
ObjectGuid guid = GetGUID ();
uint32 movementFlags = 0 ;
uint16 movementFlagsExtra = 0 ;
2013-04-01 14:45:47 +02:00
bool hasTransportTime2 = false ;
bool hasTransportTime3 = false ;
2013-03-25 14:34:22 +01:00
bool hasFallDirection = false ;
bool hasFallData = false ;
bool hasPitch = false ;
bool hasSpline = false ;
bool hasSplineElevation = false ;
2012-07-12 21:20:34 +02:00
uint32 unkLoopCounter = 0 ;
// Bit content
data -> WriteBit ( 0 );
data -> WriteBit ( 0 );
data -> WriteBit ( flags & UPDATEFLAG_ROTATION );
data -> WriteBit ( flags & UPDATEFLAG_ANIMKITS );
data -> WriteBit ( flags & UPDATEFLAG_HAS_TARGET );
data -> WriteBit ( flags & UPDATEFLAG_SELF );
data -> WriteBit ( flags & UPDATEFLAG_VEHICLE );
data -> WriteBit ( flags & UPDATEFLAG_LIVING );
data -> WriteBits ( unkLoopCounter , 24 );
data -> WriteBit ( 0 );
data -> WriteBit ( flags & UPDATEFLAG_GO_TRANSPORT_POSITION );
data -> WriteBit ( flags & UPDATEFLAG_STATIONARY_POSITION );
2012-07-24 15:28:41 +02:00
data -> WriteBit ( flags & UPDATEFLAG_UNK5 );
2012-07-12 21:20:34 +02:00
data -> WriteBit ( 0 );
data -> WriteBit ( flags & UPDATEFLAG_TRANSPORT );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( flags & UPDATEFLAG_LIVING )
{
2013-03-25 14:34:22 +01:00
self = ToUnit ();
movementFlags = self -> m_movementInfo . GetMovementFlags ();
movementFlagsExtra = self -> m_movementInfo . GetExtraMovementFlags ();
hasSpline = self -> IsSplineEnabled ();
2013-04-01 14:45:47 +02:00
if ( GetTypeId () == TYPEID_PLAYER )
{
hasTransportTime2 = self -> m_movementInfo . bits . hasTransportTime2 ;
hasTransportTime3 = self -> m_movementInfo . bits . hasTransportTime3 ;
hasPitch = self -> m_movementInfo . bits . hasPitch ;
hasFallData = self -> m_movementInfo . bits . hasFallData ;
hasFallDirection = self -> m_movementInfo . bits . hasFallDirection ;
hasSplineElevation = self -> m_movementInfo . bits . hasSplineElevation ;
}
else
{
hasTransportTime2 = self -> HasExtraUnitMovementFlag ( MOVEMENTFLAG2_INTERPOLATED_MOVEMENT );
hasPitch = (( movementFlags & ( MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING )) ||
( movementFlagsExtra & MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING ));
hasFallDirection = movementFlags & MOVEMENTFLAG_FALLING ;
hasFallData = hasFallDirection ; // FallDirection implies that FallData is set as well
hasSplineElevation = movementFlags & MOVEMENTFLAG_SPLINE_ELEVATION ;
2012-08-10 14:10:57 +02:00
movementFlags &= MOVEMENTFLAG_MASK_CREATURE_ALLOWED ;
2013-04-01 14:45:47 +02:00
}
2012-07-12 21:20:34 +02:00
data -> WriteBit ( ! movementFlags );
2012-07-23 13:43:57 +02:00
data -> WriteBit ( G3D :: fuzzyEq ( self -> GetOrientation (), 0.0f )); // Has Orientation
2012-07-12 21:20:34 +02:00
data -> WriteBit ( guid [ 7 ]);
data -> WriteBit ( guid [ 3 ]);
data -> WriteBit ( guid [ 2 ]);
if ( movementFlags )
data -> WriteBits ( movementFlags , 30 );
data -> WriteBit ( 0 );
2013-03-25 14:34:22 +01:00
data -> WriteBit ( ! hasPitch ); // Has pitch
data -> WriteBit ( hasSpline ); // Has spline data
data -> WriteBit ( hasFallData ); // Has fall data
data -> WriteBit ( ! hasSplineElevation ); // Has spline elevation
2012-07-12 21:20:34 +02:00
data -> WriteBit ( guid [ 5 ]);
2012-07-14 23:39:12 +02:00
data -> WriteBit ( self -> m_movementInfo . t_guid ); // Has transport data
2012-07-12 21:20:34 +02:00
data -> WriteBit ( 0 ); // Is missing time
2013-03-25 14:34:22 +01:00
2012-07-14 23:39:12 +02:00
if ( self -> m_movementInfo . t_guid )
2012-07-12 21:20:34 +02:00
{
ObjectGuid transGuid = self -> m_movementInfo . t_guid ;
data -> WriteBit ( transGuid [ 1 ]);
2012-07-28 19:18:47 +02:00
data -> WriteBit ( 0 ); // Has transport time 2
2012-07-12 21:20:34 +02:00
data -> WriteBit ( transGuid [ 4 ]);
data -> WriteBit ( transGuid [ 0 ]);
data -> WriteBit ( transGuid [ 6 ]);
data -> WriteBit ( 0 ); // Has transport time 3
data -> WriteBit ( transGuid [ 7 ]);
data -> WriteBit ( transGuid [ 5 ]);
data -> WriteBit ( transGuid [ 3 ]);
data -> WriteBit ( transGuid [ 2 ]);
}
2011-11-27 16:06:29 +01:00
2012-07-12 21:20:34 +02:00
data -> WriteBit ( guid [ 4 ]);
2009-10-17 15:51:44 -07:00
2013-03-25 14:34:22 +01:00
if ( hasSpline )
2012-08-10 14:10:57 +02:00
Movement :: PacketBuilder :: WriteCreateBits ( * self -> movespline , * data );
2009-10-17 15:51:44 -07:00
2012-07-12 21:20:34 +02:00
data -> WriteBit ( guid [ 6 ]);
2013-03-25 14:34:22 +01:00
if ( hasFallData )
data -> WriteBit ( hasFallDirection );
2012-07-12 21:20:34 +02:00
data -> WriteBit ( guid [ 0 ]);
data -> WriteBit ( guid [ 1 ]);
data -> WriteBit ( 0 );
data -> WriteBit ( ! movementFlagsExtra );
if ( movementFlagsExtra )
data -> WriteBits ( movementFlagsExtra , 12 );
2009-06-11 00:45:59 -05:00
}
2012-07-12 21:20:34 +02:00
if ( flags & UPDATEFLAG_GO_TRANSPORT_POSITION )
{
WorldObject const * self = static_cast < WorldObject const *> ( this );
ObjectGuid transGuid = self -> m_movementInfo . t_guid ;
data -> WriteBit ( transGuid [ 5 ]);
data -> WriteBit ( 0 ); // Has GO transport time 3
data -> WriteBit ( transGuid [ 0 ]);
data -> WriteBit ( transGuid [ 3 ]);
data -> WriteBit ( transGuid [ 6 ]);
data -> WriteBit ( transGuid [ 1 ]);
data -> WriteBit ( transGuid [ 4 ]);
data -> WriteBit ( transGuid [ 2 ]);
data -> WriteBit ( 0 ); // Has GO transport time 2
data -> WriteBit ( transGuid [ 7 ]);
}
if ( flags & UPDATEFLAG_HAS_TARGET )
2009-06-11 00:45:59 -05:00
{
2013-03-25 14:34:22 +01:00
ObjectGuid victimGuid = self -> getVictim () -> GetGUID (); // checked in BuildCreateUpdateBlockForPlayer
2012-07-12 21:20:34 +02:00
data -> WriteBit ( victimGuid [ 2 ]);
data -> WriteBit ( victimGuid [ 7 ]);
data -> WriteBit ( victimGuid [ 0 ]);
data -> WriteBit ( victimGuid [ 4 ]);
data -> WriteBit ( victimGuid [ 5 ]);
data -> WriteBit ( victimGuid [ 6 ]);
data -> WriteBit ( victimGuid [ 1 ]);
data -> WriteBit ( victimGuid [ 3 ]);
}
if ( flags & UPDATEFLAG_ANIMKITS )
{
data -> WriteBit ( 1 ); // Missing AnimKit1
data -> WriteBit ( 1 ); // Missing AnimKit2
data -> WriteBit ( 1 ); // Missing AnimKit3
}
data -> FlushBits ();
// Data
for ( uint32 i = 0 ; i < unkLoopCounter ; ++ i )
* data << uint32 ( 0 );
if ( flags & UPDATEFLAG_LIVING )
{
data -> WriteByteSeq ( guid [ 4 ]);
* data << self -> GetSpeed ( MOVE_RUN_BACK );
2009-10-17 15:51:44 -07:00
2013-03-25 14:34:22 +01:00
if ( hasFallData )
2009-06-11 00:45:59 -05:00
{
2013-03-25 14:34:22 +01:00
if ( hasFallDirection )
2012-05-30 08:01:02 +02:00
{
2012-07-12 21:20:34 +02:00
* data << float ( self -> m_movementInfo . j_cosAngle );
* data << float ( self -> m_movementInfo . j_xyspeed );
* data << float ( self -> m_movementInfo . j_sinAngle );
2012-05-30 08:01:02 +02:00
}
2009-10-17 15:51:44 -07:00
2012-07-12 21:20:34 +02:00
* data << uint32 ( self -> m_movementInfo . fallTime );
* data << float ( self -> m_movementInfo . j_zspeed );
2009-06-11 00:45:59 -05:00
}
2012-07-12 21:20:34 +02:00
* data << self -> GetSpeed ( MOVE_SWIM_BACK );
2013-03-25 14:34:22 +01:00
if ( hasSplineElevation )
2012-07-12 21:20:34 +02:00
* data << float ( self -> m_movementInfo . splineElevation );
2013-03-25 14:34:22 +01:00
if ( hasSpline )
2012-08-10 14:10:57 +02:00
Movement :: PacketBuilder :: WriteCreateData ( * self -> movespline , * data );
2012-07-12 21:20:34 +02:00
* data << float ( self -> GetPositionZMinusOffset ());
data -> WriteByteSeq ( guid [ 5 ]);
2013-03-25 14:34:22 +01:00
2012-07-14 23:39:12 +02:00
if ( self -> m_movementInfo . t_guid )
2009-06-11 00:45:59 -05:00
{
2012-07-12 21:20:34 +02:00
ObjectGuid transGuid = self -> m_movementInfo . t_guid ;
data -> WriteByteSeq ( transGuid [ 5 ]);
data -> WriteByteSeq ( transGuid [ 7 ]);
* data << uint32 ( self -> GetTransTime ());
* data << float ( self -> GetTransOffsetO ());
2013-04-01 14:45:47 +02:00
if ( hasTransportTime2 )
* data << uint32 ( self -> m_movementInfo . t_time2 );
2012-07-12 21:20:34 +02:00
* data << float ( self -> GetTransOffsetY ());
* data << float ( self -> GetTransOffsetX ());
data -> WriteByteSeq ( transGuid [ 3 ]);
* data << float ( self -> GetTransOffsetZ ());
data -> WriteByteSeq ( transGuid [ 0 ]);
2013-04-01 14:45:47 +02:00
if ( hasTransportTime3 )
* data << uint32 ( self -> m_movementInfo . t_time3 );
2012-07-12 21:20:34 +02:00
* data << int8 ( self -> GetTransSeat ());
data -> WriteByteSeq ( transGuid [ 1 ]);
data -> WriteByteSeq ( transGuid [ 6 ]);
data -> WriteByteSeq ( transGuid [ 2 ]);
data -> WriteByteSeq ( transGuid [ 4 ]);
2008-10-11 14:16:25 -05:00
}
2012-07-12 21:20:34 +02:00
* data << float ( self -> GetPositionX ());
* data << self -> GetSpeed ( MOVE_PITCH_RATE );
data -> WriteByteSeq ( guid [ 3 ]);
2012-07-31 17:59:33 +03:00
data -> WriteByteSeq ( guid [ 0 ]);
2012-07-12 21:20:34 +02:00
* data << self -> GetSpeed ( MOVE_SWIM );
2012-07-13 11:59:27 +02:00
* data << float ( self -> GetPositionY ());
2012-07-12 21:20:34 +02:00
data -> WriteByteSeq ( guid [ 7 ]);
data -> WriteByteSeq ( guid [ 1 ]);
data -> WriteByteSeq ( guid [ 2 ]);
* data << self -> GetSpeed ( MOVE_WALK );
//if (true) // Has time, controlled by bit just after HasTransport
* data << uint32 ( getMSTime ());
* data << self -> GetSpeed ( MOVE_FLIGHT_BACK );
data -> WriteByteSeq ( guid [ 6 ]);
* data << self -> GetSpeed ( MOVE_TURN_RATE );
2012-07-23 13:43:57 +02:00
if ( ! G3D :: fuzzyEq ( self -> GetOrientation (), 0.0f ))
* data << float ( self -> GetOrientation ());
2012-07-12 21:20:34 +02:00
* data << self -> GetSpeed ( MOVE_RUN );
2013-03-25 14:34:22 +01:00
if ( hasPitch )
2012-07-12 21:20:34 +02:00
* data << float ( self -> m_movementInfo . pitch );
* data << self -> GetSpeed ( MOVE_FLIGHT );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2012-07-12 21:20:34 +02:00
if ( flags & UPDATEFLAG_VEHICLE )
2008-10-11 14:16:25 -05:00
{
2012-07-12 21:20:34 +02:00
* data << float ( self -> GetOrientation ());
* data << uint32 ( self -> GetVehicleKit () -> GetVehicleInfo () -> m_ID );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2012-07-12 21:20:34 +02:00
if ( flags & UPDATEFLAG_GO_TRANSPORT_POSITION )
{
WorldObject const * self = static_cast < WorldObject const *> ( this );
ObjectGuid transGuid = self -> m_movementInfo . t_guid ;
data -> WriteBit ( transGuid [ 0 ]);
data -> WriteBit ( transGuid [ 5 ]);
2013-04-01 14:45:47 +02:00
if ( hasTransportTime3 )
* data << uint32 ( self -> m_movementInfo . t_time3 );
2012-07-12 21:20:34 +02:00
data -> WriteBit ( transGuid [ 3 ]);
* data << float ( self -> GetTransOffsetX ());
data -> WriteBit ( transGuid [ 4 ]);
data -> WriteBit ( transGuid [ 6 ]);
data -> WriteBit ( transGuid [ 1 ]);
* data << uint32 ( self -> GetTransTime ());
* data << float ( self -> GetTransOffsetY ());
data -> WriteBit ( transGuid [ 2 ]);
data -> WriteBit ( transGuid [ 7 ]);
* data << float ( self -> GetTransOffsetZ ());
* data << int8 ( self -> GetTransSeat ());
* data << float ( self -> GetTransOffsetO ());
2013-04-01 14:45:47 +02:00
if ( hasTransportTime2 )
* data << uint32 ( self -> m_movementInfo . t_time2 );
2012-07-12 21:20:34 +02:00
}
2009-10-17 15:51:44 -07:00
2012-07-12 21:20:34 +02:00
if ( flags & UPDATEFLAG_ROTATION )
* data << uint64 ( ToGameObject () -> GetRotation ());
2012-07-24 15:28:41 +02:00
if ( flags & UPDATEFLAG_UNK5 )
{
* data << float ( 0.0f );
* data << float ( 0.0f );
* data << float ( 0.0f );
* data << float ( 0.0f );
* data << uint8 ( 0 );
* data << float ( 0.0f );
* data << float ( 0.0f );
* data << float ( 0.0f );
* data << float ( 0.0f );
* data << float ( 0.0f );
* data << float ( 0.0f );
* data << float ( 0.0f );
* data << float ( 0.0f );
* data << float ( 0.0f );
* data << float ( 0.0f );
* data << float ( 0.0f );
* data << float ( 0.0f );
}
2012-07-12 21:20:34 +02:00
if ( flags & UPDATEFLAG_STATIONARY_POSITION )
2008-12-24 09:58:26 -06:00
{
2012-07-12 21:20:34 +02:00
WorldObject const * self = static_cast < WorldObject const *> ( this );
* data << float ( self -> GetOrientation ());
* data << float ( self -> GetPositionX ());
* data << float ( self -> GetPositionY ());
if ( Unit const * unit = ToUnit ())
* data << float ( unit -> GetPositionZMinusOffset ());
else
* data << float ( self -> GetPositionZ ());
2008-12-24 09:58:26 -06:00
}
2009-10-17 15:51:44 -07:00
2012-07-12 21:20:34 +02:00
if ( flags & UPDATEFLAG_HAS_TARGET )
{
2013-03-25 14:34:22 +01:00
ObjectGuid victimGuid = self -> getVictim () -> GetGUID (); // checked in BuildCreateUpdateBlockForPlayer
2012-07-28 19:18:47 +02:00
data -> WriteByteSeq ( victimGuid [ 4 ]);
2012-07-12 21:20:34 +02:00
data -> WriteByteSeq ( victimGuid [ 0 ]);
data -> WriteByteSeq ( victimGuid [ 3 ]);
data -> WriteByteSeq ( victimGuid [ 5 ]);
data -> WriteByteSeq ( victimGuid [ 7 ]);
data -> WriteByteSeq ( victimGuid [ 6 ]);
data -> WriteByteSeq ( victimGuid [ 2 ]);
data -> WriteByteSeq ( victimGuid [ 1 ]);
}
2012-01-20 20:31:59 +01:00
2012-07-12 21:20:34 +02:00
//if (flags & UPDATEFLAG_ANIMKITS)
//{
// if (hasAnimKit1)
// *data << uint16(animKit1);
// if (hasAnimKit2)
// *data << uint16(animKit2);
// if (hasAnimKit3)
// *data << uint16(animKit3);
//}
2011-11-27 16:06:29 +01:00
2012-07-12 21:20:34 +02:00
if ( flags & UPDATEFLAG_TRANSPORT )
* data << uint32 ( getMSTime ()); // Unknown - getMSTime is wrong.
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2013-03-25 10:36:30 +01: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 ;
2009-10-17 15:51:44 -07:00
2013-03-25 10:36:30 +01:00
// Before trying to convert to each type there is a check, so safe
Unit const * unit = ToUnit ();
GameObject const * go = ToGameObject ();
if ( unit )
{
if ( unit -> HasFlag ( UNIT_FIELD_AURASTATE , PER_CASTER_AURA_STATE_MASK ))
updateMask -> SetBit ( UNIT_FIELD_AURASTATE );
2008-10-11 14:16:25 -05:00
}
2013-03-25 10:36:30 +01:00
else if ( go )
2008-10-11 14:16:25 -05:00
{
2013-03-25 10:36:30 +01:00
if ( updateType == UPDATETYPE_CREATE_OBJECT || updateType == UPDATETYPE_CREATE_OBJECT2 )
2008-10-11 14:16:25 -05:00
{
2013-03-25 10:36:30 +01:00
if ( ! go -> IsDynTransport ())
{
if ( go -> ActivateToQuest ( target ) || target -> isGameMaster ())
IsActivateToQuest = true ;
2012-05-30 08:01:02 +02:00
2013-03-25 10:36:30 +01:00
if ( go -> GetGoArtKit ())
updateMask -> SetBit ( GAMEOBJECT_BYTES_1 );
}
2008-10-11 14:16:25 -05:00
}
2013-03-25 10:36:30 +01:00
else
2009-07-30 17:16:56 +02:00
{
2013-03-25 10:36:30 +01:00
if ( ! go -> IsTransport ())
{
if ( go -> ActivateToQuest ( target ) || target -> isGameMaster ())
IsActivateToQuest = true ;
updateMask -> SetBit ( GAMEOBJECT_BYTES_1 );
if ( go -> GetGoType () == GAMEOBJECT_TYPE_CHEST && go -> GetGOInfo () -> chest . groupLootRules &&
go -> HasLootRecipient ())
{
updateMask -> SetBit ( GAMEOBJECT_FLAGS );
}
}
2009-07-30 17:16:56 +02:00
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2012-07-28 19:18:47 +02:00
uint32 valCount = m_valuesCount ;
if ( GetTypeId () == TYPEID_PLAYER && target != this )
valCount = PLAYER_END_NOT_SELF ;
2013-03-25 14:34:22 +01:00
ASSERT ( updateMask && updateMask -> GetCount () == valCount );
2009-10-17 15:51:44 -07:00
2013-03-25 10:36:30 +01:00
* data << uint8 ( updateMask -> GetBlockCount ());
2013-02-09 23:59:09 +01:00
updateMask -> AppendToPacket ( data );
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
2013-03-25 10:36:30 +01:00
if ( unit ) // unit (creature/player) case
2008-10-11 14:16:25 -05:00
{
2013-03-25 10:36:30 +01:00
Creature const * creature = ToCreature ();
2012-07-29 23:44:30 +02:00
for ( uint16 index = 0 ; index < valCount ; ++ 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 )
{
2013-03-25 10:36:30 +01:00
if ( ! creature -> 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 )
{
2013-03-25 10:36:30 +01:00
// Check per caster aura states to not enable using a spell in client if specified aura is not by target
* data << unit -> BuildAuraStateUpdateForTarget ( target );
2009-07-30 17:16:56 +02:00
}
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
{
2013-03-25 10:36:30 +01:00
CreatureTemplate const * cinfo = creature -> GetCreatureTemplate ();
2011-08-28 17:36:02 +02:00
// 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 ];
2013-03-25 10:36:30 +01:00
if ( creature )
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
2012-05-30 08:01:02 +02:00
// unit UNIT_DYNFLAG_TRACK_UNIT should only be sent to caster of SPELL_AURA_MOD_STALKED auras
2013-03-25 10:36:30 +01:00
if ( dynamicFlags & UNIT_DYNFLAG_TRACK_UNIT )
if ( ! unit -> HasAuraTypeWithCaster ( SPELL_AURA_MOD_STALKED , target -> GetGUID ()))
dynamicFlags &= ~ UNIT_DYNFLAG_TRACK_UNIT ;
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
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
}
}
}
}
2013-03-25 10:36:30 +01:00
else if ( go ) // gameobject case
2008-10-11 14:16:25 -05:00
{
2012-07-29 23:44:30 +02:00
for ( uint16 index = 0 ; index < valCount ; ++ 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
{
2013-03-25 10:36:30 +01:00
switch ( go -> 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 );
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-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 );
2008-10-11 14:16:25 -05:00
break ;
default :
2012-07-29 23:44:30 +02:00
* data << uint16 ( 0 ); // unknown, not happen.
2008-10-11 14:16:25 -05:00
break ;
}
}
else
2012-07-29 23:44:30 +02:00
* data << uint16 ( 0 ); // disable quest object
* data << uint16 ( - 1 );
2008-10-11 14:16:25 -05:00
}
2012-05-30 08:01:02 +02:00
else if ( index == GAMEOBJECT_FLAGS )
{
uint32 flags = m_uint32Values [ index ];
2013-03-25 10:36:30 +01:00
if ( go -> GetGoType () == GAMEOBJECT_TYPE_CHEST )
if ( go -> GetGOInfo () -> chest . groupLootRules && ! go -> IsLootAllowedFor ( target ))
2012-05-30 08:01:02 +02:00
flags |= GO_FLAG_LOCKED | GO_FLAG_NOT_SELECTABLE ;
* data << flags ;
}
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)
{
2012-07-29 23:44:30 +02:00
for ( uint16 index = 0 ; index < valCount ; ++ 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 )
{
2013-01-22 18:45:09 +01:00
_changesMask . Clear ();
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-27 16:06:29 +01:00
std :: pair < UpdateDataMapType :: iterator , bool > p = data_map . insert ( UpdateDataMapType :: value_type ( player , UpdateData ( player -> GetMapId ())));
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
}
2013-02-03 12:16:10 +01:00
uint32 Object :: GetUpdateFieldData ( Player const * target , uint32 *& flags ) const
2012-07-22 14:20:26 +02:00
{
2013-02-03 12:16:10 +01:00
uint32 visibleFlag = UF_FLAG_PUBLIC ;
if ( target == this )
visibleFlag |= UF_FLAG_PRIVATE ;
2012-07-22 14:20:26 +02:00
switch ( GetTypeId ())
{
case TYPEID_ITEM :
case TYPEID_CONTAINER :
flags = ItemUpdateFieldFlags ;
2013-02-03 12:16:10 +01:00
if ((( Item * ) this ) -> GetOwnerGUID () == target -> GetGUID ())
visibleFlag |= UF_FLAG_OWNER | UF_FLAG_ITEM_OWNER ;
2012-07-22 14:20:26 +02:00
break ;
case TYPEID_UNIT :
case TYPEID_PLAYER :
{
Player * plr = ToUnit () -> GetCharmerOrOwnerPlayerOrPlayerItself ();
flags = UnitUpdateFieldFlags ;
2013-02-03 12:16:10 +01:00
if ( ToUnit () -> GetOwnerGUID () == target -> GetGUID ())
visibleFlag |= UF_FLAG_OWNER ;
2013-02-03 12:23:28 +01:00
if ( HasFlag ( UNIT_DYNAMIC_FLAGS , UNIT_DYNFLAG_SPECIALINFO ))
if ( ToUnit () -> HasAuraTypeWithCaster ( SPELL_AURA_EMPATHY , target -> GetGUID ()))
visibleFlag |= UF_FLAG_SPECIAL_INFO ;
2013-02-03 12:16:10 +01:00
2013-02-03 12:23:28 +01:00
if ( plr && plr -> IsInSameRaidWith ( target ))
2013-02-03 12:16:10 +01:00
visibleFlag |= UF_FLAG_PARTY_MEMBER ;
2012-07-22 14:20:26 +02:00
break ;
}
case TYPEID_GAMEOBJECT :
flags = GameObjectUpdateFieldFlags ;
2013-02-03 12:16:10 +01:00
if ( ToGameObject () -> GetOwnerGUID () == target -> GetGUID ())
visibleFlag |= UF_FLAG_OWNER ;
2012-07-22 14:20:26 +02:00
break ;
case TYPEID_DYNAMICOBJECT :
flags = DynamicObjectUpdateFieldFlags ;
2013-02-03 12:16:10 +01:00
if ((( DynamicObject * ) this ) -> GetCasterGUID () == target -> GetGUID ())
visibleFlag |= UF_FLAG_OWNER ;
2012-07-22 14:20:26 +02:00
break ;
case TYPEID_CORPSE :
flags = CorpseUpdateFieldFlags ;
2013-02-03 12:16:10 +01:00
if ( ToCorpse () -> GetOwnerGUID () == target -> GetGUID ())
visibleFlag |= UF_FLAG_OWNER ;
2012-07-22 14:20:26 +02:00
break ;
2013-05-26 04:28:19 +03:00
case TYPEID_AREATRIGGER :
flags = AreaTriggerUpdateFieldFlags ;
break ;
2012-07-30 10:07:26 +02:00
case TYPEID_OBJECT :
break ;
2012-07-22 14:20:26 +02:00
}
2013-02-03 12:16:10 +01:00
return visibleFlag ;
2012-07-22 14:20:26 +02:00
}
2012-10-24 13:29:34 +02:00
void Object :: _LoadIntoDataField ( std :: string const & data , uint32 startOffset , uint32 count )
{
if ( data . empty ())
return ;
Tokenizer tokens ( data , ' ' , count );
if ( tokens . size () != count )
return ;
for ( uint32 index = 0 ; index < count ; ++ index )
{
m_uint32Values [ startOffset + index ] = atol ( tokens [ index ]);
2013-01-22 18:45:09 +01:00
_changesMask . SetBit ( startOffset + index );
2012-10-24 13:29:34 +02:00
}
}
2012-07-22 14:20:26 +02:00
void Object :: _SetUpdateBits ( UpdateMask * updateMask , Player * target ) const
2008-10-11 14:16:25 -05:00
{
2012-07-22 14:20:26 +02:00
uint32 * flags = NULL ;
2013-02-03 12:16:10 +01:00
uint32 visibleFlag = GetUpdateFieldData ( target , flags );
2012-07-28 19:18:47 +02:00
uint32 valCount = m_valuesCount ;
if ( GetTypeId () == TYPEID_PLAYER && target != this )
valCount = PLAYER_END_NOT_SELF ;
2013-01-28 01:04:37 +00:00
for ( uint16 index = 0 ; index < valCount ; ++ index )
2013-02-03 12:16:10 +01:00
if ( _fieldNotifyFlags & flags [ index ] || (( flags [ index ] & visibleFlag ) & UF_FLAG_SPECIAL_INFO ) || ( _changesMask . GetBit ( index ) && ( flags [ index ] & visibleFlag )))
2008-10-11 14:16:25 -05:00
updateMask -> SetBit ( index );
}
2009-10-17 15:51:44 -07:00
2012-07-22 14:20:26 +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 ;
2012-07-22 14:20:26 +02:00
uint32 * flags = NULL ;
2013-02-03 12:16:10 +01:00
uint32 visibleFlag = GetUpdateFieldData ( target , flags );
2012-07-28 19:18:47 +02:00
uint32 valCount = m_valuesCount ;
if ( GetTypeId () == TYPEID_PLAYER && target != this )
valCount = PLAYER_END_NOT_SELF ;
for ( uint16 index = 0 ; index < valCount ; ++ index , ++ value )
2013-02-03 12:16:10 +01:00
if ( _fieldNotifyFlags & flags [ index ] || (( flags [ index ] & visibleFlag ) & UF_FLAG_SPECIAL_INFO ) || ( * value && ( flags [ index ] & visibleFlag )))
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 ;
2013-01-22 18:45:09 +01:00
_changesMask . SetBit ( index );
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 ;
2013-01-22 18:45:09 +01:00
_changesMask . SetBit ( index );
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 ;
2013-01-22 18:45:09 +01:00
_changesMask . SetBit ( index );
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 );
2013-01-22 18:45:09 +01:00
_changesMask . SetBit ( index );
_changesMask . SetBit ( index + 1 );
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 );
2013-01-22 18:45:09 +01:00
_changesMask . SetBit ( index );
_changesMask . SetBit ( index + 1 );
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 ;
2013-01-22 18:45:09 +01:00
_changesMask . SetBit ( index );
_changesMask . SetBit ( index + 1 );
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 ;
2013-01-22 18:45:09 +01:00
_changesMask . SetBit ( index );
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
{
2013-05-13 15:07:36 +02:00
TC_LOG_ERROR ( LOG_FILTER_GENERAL , "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 ));
2013-01-22 18:45:09 +01:00
_changesMask . SetBit ( index );
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
{
2013-05-13 15:07:36 +02:00
TC_LOG_ERROR ( LOG_FILTER_GENERAL , "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 ));
2013-01-22 18:45:09 +01:00
_changesMask . SetBit ( index );
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
2013-03-04 11:45:57 +01:00
void Object :: ApplyPercentModFloatValue ( uint16 index , float val , bool apply )
{
float value = GetFloatValue ( index );
ApplyPercentModFloatVar ( value , val , apply );
SetFloatValue ( index , value );
}
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 ;
2013-01-22 18:45:09 +01:00
_changesMask . SetBit ( index );
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 ;
2013-01-22 18:45:09 +01:00
_changesMask . SetBit ( index );
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
2013-03-04 11:45:57 +01:00
void Object :: ToggleFlag ( uint16 index , uint32 flag )
{
if ( HasFlag ( index , flag ))
RemoveFlag ( index , flag );
else
SetFlag ( index , flag );
}
bool Object :: HasFlag ( uint16 index , uint32 flag ) const
{
if ( index >= m_valuesCount && ! PrintIndexError ( index , false ))
return false ;
return ( m_uint32Values [ index ] & flag ) != 0 ;
}
void Object :: ApplyModFlag ( uint16 index , uint32 flag , bool apply )
{
if ( apply ) SetFlag ( index , flag ); else RemoveFlag ( index , flag );
}
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
{
2013-05-13 15:07:36 +02:00
TC_LOG_ERROR ( LOG_FILTER_GENERAL , "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 ));
2013-01-22 18:45:09 +01:00
_changesMask . SetBit ( index );
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
{
2013-05-13 15:07:36 +02:00
TC_LOG_ERROR ( LOG_FILTER_GENERAL , "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 ));
2013-01-22 18:45:09 +01:00
_changesMask . SetBit ( index );
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
2013-03-04 11:45:57 +01:00
void Object :: ToggleByteFlag ( uint16 index , uint8 offset , uint8 flag )
{
if ( HasByteFlag ( index , offset , flag ))
RemoveByteFlag ( index , offset , flag );
else
SetByteFlag ( index , offset , flag );
}
bool Object :: HasByteFlag ( uint16 index , uint8 offset , uint8 flag ) const
{
ASSERT ( index < m_valuesCount || PrintIndexError ( index , false ));
ASSERT ( offset < 4 );
return ((( uint8 * ) & m_uint32Values [ index ])[ offset ] & flag ) != 0 ;
}
void Object :: SetFlag64 ( uint16 index , uint64 newFlag )
{
uint64 oldval = GetUInt64Value ( index );
uint64 newval = oldval | newFlag ;
SetUInt64Value ( index , newval );
}
void Object :: RemoveFlag64 ( uint16 index , uint64 oldFlag )
{
uint64 oldval = GetUInt64Value ( index );
uint64 newval = oldval & ~ oldFlag ;
SetUInt64Value ( index , newval );
}
void Object :: ToggleFlag64 ( uint16 index , uint64 flag )
{
if ( HasFlag64 ( index , flag ))
RemoveFlag64 ( index , flag );
else
SetFlag64 ( index , flag );
}
bool Object :: HasFlag64 ( uint16 index , uint64 flag ) const
{
ASSERT ( index < m_valuesCount || PrintIndexError ( index , false ));
return ( GetUInt64Value ( index ) & flag ) != 0 ;
}
void Object :: ApplyModFlag64 ( uint16 index , uint64 flag , bool apply )
{
if ( apply ) SetFlag64 ( index , flag ); else RemoveFlag64 ( index , flag );
}
2008-10-11 14:16:25 -05:00
bool Object :: PrintIndexError ( uint32 index , bool set ) const
{
2013-05-13 15:07:36 +02:00
TC_LOG_ERROR ( LOG_FILTER_GENERAL , "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
2013-03-25 10:36:30 +01:00
bool Position :: operator == ( Position const & a )
{
return ( G3D :: fuzzyEq ( a . m_positionX , m_positionX ) &&
G3D :: fuzzyEq ( a . m_positionY , m_positionY ) &&
G3D :: fuzzyEq ( a . m_positionZ , m_positionZ ) &&
G3D :: fuzzyEq ( a . m_orientation , m_orientation ));
}
2012-02-21 20:03:27 +01:00
bool Position :: HasInLine ( WorldObject const * target , float width ) const
2009-08-29 14:58:45 -05:00
{
2012-02-21 20:03:27 +01:00
if ( ! HasInArc ( M_PI , target ))
2010-02-14 19:13:14 -07:00
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 ()
{
2013-05-13 15:07:36 +02:00
TC_LOG_INFO ( LOG_FILTER_GENERAL , "MOVEMENT INFO" );
TC_LOG_INFO ( LOG_FILTER_GENERAL , "guid " UI64FMTD , guid );
2013-05-21 09:55:09 +02:00
TC_LOG_INFO ( LOG_FILTER_GENERAL , "flags %s (%u)" , Movement :: MovementFlags_ToString ( flags ). c_str (), flags );
TC_LOG_INFO ( LOG_FILTER_GENERAL , "flags2 %s (%u)" , Movement :: MovementFlagsExtra_ToString ( flags2 ). c_str (), flags2 );
TC_LOG_INFO ( LOG_FILTER_GENERAL , "time %u current time %u" , time , getMSTime ());
2013-05-13 15:07:36 +02:00
TC_LOG_INFO ( LOG_FILTER_GENERAL , "position: `%s`" , pos . ToString (). c_str ());
2012-07-14 23:39:12 +02:00
if ( t_guid )
2010-08-08 20:32:14 +02:00
{
2013-05-13 15:07:36 +02:00
TC_LOG_INFO ( LOG_FILTER_GENERAL , "TRANSPORT:" );
TC_LOG_INFO ( LOG_FILTER_GENERAL , "guid: " UI64FMTD , t_guid );
TC_LOG_INFO ( LOG_FILTER_GENERAL , "position: `%s`" , t_pos . ToString (). c_str ());
TC_LOG_INFO ( LOG_FILTER_GENERAL , "seat: %i" , t_seat );
TC_LOG_INFO ( LOG_FILTER_GENERAL , "time: %u" , t_time );
2010-08-08 20:32:14 +02:00
if ( flags2 & MOVEMENTFLAG2_INTERPOLATED_MOVEMENT )
2013-05-13 15:07:36 +02:00
TC_LOG_INFO ( LOG_FILTER_GENERAL , "time2: %u" , t_time2 );
2013-04-01 14:45:47 +02:00
if ( bits . hasTransportTime3 )
2013-05-21 09:55:09 +02:00
TC_LOG_INFO ( LOG_FILTER_GENERAL , "time3: %u" , t_time3 );
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 ))
2013-05-13 15:07:36 +02:00
TC_LOG_INFO ( LOG_FILTER_GENERAL , "pitch: %f" , pitch );
2011-08-28 17:36:02 +02:00
2013-04-01 14:45:47 +02:00
if ( flags & MOVEMENTFLAG_FALLING || bits . hasFallData )
{
2013-05-21 09:55:09 +02:00
TC_LOG_INFO ( LOG_FILTER_GENERAL , "fallTime: %u j_zspeed: %f" , fallTime , j_zspeed );
2013-04-01 14:45:47 +02:00
if ( flags & MOVEMENTFLAG_FALLING )
2013-05-21 09:55:09 +02:00
TC_LOG_INFO ( LOG_FILTER_GENERAL , "j_sinAngle: %f j_cosAngle: %f j_xyspeed: %f" , j_sinAngle , j_cosAngle , j_xyspeed );
2013-04-01 14:45:47 +02:00
}
2011-08-28 17:36:02 +02:00
2010-08-08 20:32:14 +02:00
if ( flags & MOVEMENTFLAG_SPLINE_ELEVATION )
2013-05-13 15:07:36 +02:00
TC_LOG_INFO ( LOG_FILTER_GENERAL , "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-27 10:05:49 +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
2013-03-04 12:41:17 +01:00
void WorldObject :: RemoveFromWorld ()
2013-03-04 11:45:57 +01:00
{
if ( ! IsInWorld ())
return ;
DestroyForNearbyPlayers ();
Object :: RemoveFromWorld ();
}
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 );
2012-02-03 16:03:52 -05:00
return IsWithinLOS ( ox , oy , oz );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2013-03-04 11:45:57 +01:00
float WorldObject :: GetDistance ( const WorldObject * obj ) const
{
float d = GetExactDist ( obj ) - GetObjectSize () - obj -> GetObjectSize ();
return d > 0.0f ? d : 0.0f ;
}
float WorldObject :: GetDistance ( const Position & pos ) const
{
float d = GetExactDist ( & pos ) - GetObjectSize ();
return d > 0.0f ? d : 0.0f ;
}
float WorldObject :: GetDistance ( float x , float y , float z ) const
{
float d = GetExactDist ( x , y , z ) - GetObjectSize ();
return d > 0.0f ? d : 0.0f ;
}
float WorldObject :: GetDistance2d ( const WorldObject * obj ) const
{
float d = GetExactDist2d ( obj ) - GetObjectSize () - obj -> GetObjectSize ();
return d > 0.0f ? d : 0.0f ;
}
float WorldObject :: GetDistance2d ( float x , float y ) const
{
float d = GetExactDist2d ( x , y ) - GetObjectSize ();
return d > 0.0f ? d : 0.0f ;
}
bool WorldObject :: IsSelfOrInSameMap ( const WorldObject * obj ) const
{
if ( this == obj )
return true ;
return IsInMap ( obj );
}
bool WorldObject :: IsInMap ( const WorldObject * obj ) const
{
if ( obj )
return IsInWorld () && obj -> IsInWorld () && ( GetMap () == obj -> GetMap ());
return false ;
}
bool WorldObject :: IsWithinDist3d ( float x , float y , float z , float dist ) const
{
return IsInDist ( x , y , z , dist + GetObjectSize ());
}
bool WorldObject :: IsWithinDist3d ( const Position * pos , float dist ) const
2013-03-04 19:14:58 +01:00
{
return IsInDist ( pos , dist + GetObjectSize ());
2013-03-04 11:45:57 +01:00
}
bool WorldObject :: IsWithinDist2d ( float x , float y , float dist ) const
{
2013-03-04 19:14:58 +01:00
return IsInDist2d ( x , y , dist + GetObjectSize ());
2013-03-04 11:45:57 +01:00
}
bool WorldObject :: IsWithinDist2d ( const Position * pos , float dist ) const
2013-03-04 19:14:58 +01:00
{
return IsInDist2d ( pos , dist + GetObjectSize ());
2013-03-04 11:45:57 +01:00
}
2013-03-04 13:00:02 +01:00
bool WorldObject :: IsWithinDist ( WorldObject const * obj , float dist2compare , bool is3D /*= true*/ ) const
2013-03-04 11:45:57 +01:00
{
return obj && _IsWithinDist ( obj , dist2compare , is3D );
}
2013-03-04 13:00:02 +01:00
bool WorldObject :: IsWithinDistInMap ( WorldObject const * obj , float dist2compare , bool is3D /*= true*/ ) const
2013-03-04 11:45:57 +01:00
{
return obj && IsInMap ( obj ) && InSamePhase ( obj ) && _IsWithinDist ( obj , dist2compare , is3D );
}
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
{
2012-02-03 16:03:52 -05:00
/*float x, y, z;
2011-04-29 20:47:02 +02:00
GetPosition(x, y, z);
2011-09-15 14:08:17 +02:00
VMAP::IVMapManager* vMapManager = VMAP::VMapFactory::createOrGetVMapManager();
2012-02-03 16:03:52 -05:00
return vMapManager->isInLineOfSight(GetMapId(), x, y, z+2.0f, ox, oy, oz+2.0f);*/
if ( IsInWorld ())
return GetMap () -> isInLineOfSight ( GetPositionX (), GetPositionY (), GetPositionZ () + 2.f , ox , oy , oz + 2.f , GetPhaseMask ());
return true ;
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 :: 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
{
2012-10-02 15:06:19 +02:00
m_positionX = GetPositionX () + ( offset . GetPositionX () * std :: cos ( GetOrientation ()) + offset . GetPositionY () * std :: sin ( GetOrientation () + M_PI ));
m_positionY = GetPositionY () + ( offset . GetPositionY () * std :: cos ( GetOrientation ()) + offset . GetPositionX () * std :: sin ( GetOrientation ()));
2010-08-08 20:32:14 +02:00
m_positionZ = GetPositionZ () + offset . GetPositionZ ();
2012-08-20 10:44:14 +02:00
SetOrientation ( GetOrientation () + offset . GetOrientation ());
2010-08-08 20:32:14 +02:00
}
void Position :: GetPositionOffsetTo ( const Position & endPos , Position & retOffset ) const
{
float dx = endPos . GetPositionX () - GetPositionX ();
float dy = endPos . GetPositionY () - GetPositionY ();
2012-10-02 15:06:19 +02:00
retOffset . m_positionX = dx * std :: cos ( GetOrientation ()) + dy * std :: sin ( GetOrientation ());
retOffset . m_positionY = dy * std :: cos ( GetOrientation ()) - dx * std :: sin ( GetOrientation ());
2010-08-08 20:32:14 +02:00
retOffset . m_positionZ = endPos . GetPositionZ () - GetPositionZ ();
2012-08-20 10:44:14 +02:00
retOffset . SetOrientation ( endPos . GetOrientation () - GetOrientation ());
2010-08-08 20:32:14 +02:00
}
2011-09-15 14:08:17 +02:00
float Position :: GetAngle ( const Position * obj ) const
2008-10-11 14:16:25 -05:00
{
2012-05-30 08:01:02 +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 );
2012-10-02 15:06:19 +02:00
vcos = std :: cos ( angle );
vsin = std :: sin ( angle );
2009-03-23 15:26:13 -06:00
}
else
{
float dist = sqrt (( dx * dx ) + ( dy * dy ));
vcos = dx / dist ;
vsin = dy / dist ;
}
}
2009-10-17 15:51:44 -07:00
2013-01-02 13:30:51 +01:00
bool Position :: HasInArc ( float arc , const Position * obj , float border ) 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
2012-08-20 10:44:14 +02:00
arc = 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
2012-08-20 10:44:14 +02:00
angle = 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
2013-01-02 13:30:51 +01:00
float lborder = - 1 * ( arc / border ); // in range -pi..0
float rborder = ( arc / border ); // 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
2012-10-02 15:06:19 +02:00
return ( size * size ) >= GetExactDist2dSq ( obj1 -> GetPositionX () + std :: cos ( angle ) * dist , obj1 -> GetPositionY () + std :: sin ( angle ) * dist );
2009-05-09 10:50:41 -05:00
}
2009-10-17 15:51:44 -07:00
2012-02-21 20:03:27 +01:00
bool WorldObject :: isInFront ( WorldObject const * target , float arc ) const
2009-12-17 19:09:40 +01:00
{
2012-02-21 20:03:27 +01:00
return HasInArc ( arc , target );
2009-12-17 19:09:40 +01:00
}
2012-02-21 20:03:27 +01:00
bool WorldObject :: isInBack ( WorldObject const * target , float arc ) const
2009-12-17 19:09:40 +01:00
{
2012-02-21 20:03:27 +01:00
return ! 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
2012-10-02 15:06:19 +02:00
rand_x = pos . m_positionX + new_dist * std :: cos ( angle );
rand_y = pos . m_positionY + new_dist * std :: sin ( angle );
2009-08-29 23:20:16 -05:00
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
2013-03-04 15:56:00 +01:00
void WorldObject :: GetRandomPoint ( const Position & srcPos , float distance , Position & pos ) const
{
float x , y , z ;
GetRandomPoint ( srcPos , distance , x , y , z );
pos . Relocate ( x , y , z , GetOrientation ());
}
2008-10-11 14:16:25 -05:00
void WorldObject :: UpdateGroundPositionZ ( float x , float y , float & z ) const
{
2012-02-03 16:03:52 -05:00
float new_z = GetBaseMap () -> GetHeight ( GetPhaseMask (), 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-05-30 08:01:02 +02: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-02-03 16:03:52 -05:00
: (( ground_z = GetBaseMap () -> GetHeight ( GetPhaseMask (), x , y , z , true )));
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
{
2012-02-03 16:03:52 -05:00
float ground_z = GetBaseMap () -> GetHeight ( GetPhaseMask (), x , y , z , true );
2012-01-14 15:34:41 +01:00
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-05-30 08:01:02 +02:00
if ( ! ToPlayer () -> CanFly ())
2012-01-14 15:34:41 +01:00
{
float ground_z = z ;
2012-02-02 13:15:44 -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
{
2012-02-03 16:03:52 -05:00
float ground_z = GetBaseMap () -> GetHeight ( GetPhaseMask (), x , y , z , true );
2012-01-14 15:34:41 +01:00
if ( z < ground_z )
z = ground_z ;
}
break ;
}
default :
{
2012-02-03 16:03:52 -05:00
float ground_z = GetBaseMap () -> GetHeight ( GetPhaseMask (), x , y , z , true );
2012-05-30 08:01:02 +02:00
if ( ground_z > INVALID_HEIGHT )
2012-01-14 15:34:41 +01:00
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 corpseVisibility = false ;
if ( distanceCheck )
{
2012-08-30 22:44:33 +01:00
bool corpseCheck = false ;
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 ;
}
2013-03-04 19:14:58 +01:00
bool WorldObject :: CanNeverSee ( WorldObject const * obj ) const
{
return GetMap () != obj -> GetMap () || ! InSamePhase ( obj );
2013-03-04 11:45:57 +01:00
}
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
2013-03-25 10:36:30 +01:00
if ( Unit const * thisUnit = ToUnit ())
2010-11-13 17:18:09 +01:00
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 ;
2012-11-17 19:46:05 -05:00
if ( ! ignoreStealth && ! 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 ;
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 ;
2013-03-25 10:36:30 +01:00
Unit const * unit = ToUnit ();
if ( unit )
combatReach = unit -> GetCombatReach ();
2010-11-13 17:18:09 +01:00
if ( distance < combatReach )
return true ;
if ( ! HasInArc ( M_PI , obj ))
return false ;
2013-03-25 10:36:30 +01:00
GameObject const * go = ToGameObject ();
2010-11-13 17:18:09 +01:00
for ( uint32 i = 0 ; i < TOTAL_STEALTH_TYPES ; ++ i )
{
if ( ! ( obj -> m_stealth . GetFlags () & ( 1 << i )))
continue ;
2013-03-25 10:36:30 +01:00
if ( unit && unit -> HasAuraTypeWithMiscvalue ( SPELL_AURA_DETECT_STEALTH , i ))
return true ;
2010-11-13 17:18:09 +01:00
// 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
2012-01-08 18:22:46 +01:00
// not in the DBCs of the client.
2010-11-13 17:18:09 +01:00
detectionValue += int32 ( getLevelForTarget ( obj ) - 1 ) * 5 ;
// Apply modifiers
detectionValue += m_stealthDetect . GetValue ( StealthType ( i ));
2013-03-25 10:36:30 +01:00
if ( go )
if ( Unit * owner = go -> GetOwner ())
2012-01-08 18:22:46 +01:00
detectionValue -= int32 ( owner -> getLevelForTarget ( this ) - 1 ) * 5 ;
2010-11-13 17:18:09 +01:00
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 );
2013-06-01 17:49:33 +02:00
data << uint32 ( Sound );
data << uint64 ( GetGUID ());
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 )
{
2013-01-22 18:45:09 +01:00
_changesMask . SetBit ( i );
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
2013-03-08 21:41:30 +01: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 )
{
2013-03-08 21:41:30 +01:00
/// @todo i_object.GetName() also must be localized?
2011-05-30 20:47:33 +07:00
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
2012-10-24 13:29:34 +02:00
void WorldObject :: BuildMonsterChat ( WorldPacket * data , uint8 msgtype , char const * text , uint32 language , std :: string 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
2012-10-24 13:29:34 +02:00
* data << ( uint32 )( name . size () + 1 );
2008-10-11 14:16:25 -05:00
* 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
2012-12-23 18:31:30 -05:00
if ( msgtype == CHAT_MSG_RAID_BOSS_EMOTE || msgtype == CHAT_MSG_RAID_BOSS_WHISPER )
2012-12-23 18:15:15 -05:00
{
* data << float ( 0 );
* data << uint8 ( 0 );
}
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
{
2013-05-13 15:07:36 +02:00
TC_LOG_FATAL ( LOG_FILTER_GENERAL , "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
{
2013-05-13 15:07:36 +02:00
TC_LOG_ERROR ( LOG_FILTER_GENERAL , "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 :
2012-12-26 04:34:40 +01:00
case SUMMON_TYPE_LIGHTWELL :
2011-05-19 22:27:18 +02:00
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
2013-02-23 01:50:52 +01:00
/**
* Summons group of creatures.
*
* @param group Id of group to summon.
* @param list List to store pointers to summoned creatures.
*/
2013-02-26 02:33:08 +01:00
void Map :: SummonCreatureGroup ( uint8 group , std :: list < TempSummon *>* list /*= NULL*/ )
2013-02-23 01:50:52 +01:00
{
std :: vector < TempSummonData > const * data = sObjectMgr -> GetSummonGroup ( GetId (), SUMMONER_TYPE_MAP , group );
if ( ! data )
return ;
for ( std :: vector < TempSummonData >:: const_iterator itr = data -> begin (); itr != data -> end (); ++ itr )
if ( TempSummon * summon = SummonCreature ( itr -> entry , itr -> pos , NULL , itr -> time ))
2013-02-26 02:33:08 +01:00
if ( list )
list -> push_back ( summon );
2013-02-23 01:50:52 +01: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 ())
2012-03-02 22:00:26 -03:00
{
if ( Battlefield * bf = sBattlefieldMgr -> GetBattlefieldToZoneId ( GetZoneId ()))
m_zoneScript = bf ;
else
2012-12-19 12:55:51 +01:00
m_zoneScript = sOutdoorPvPMgr -> GetZoneScript ( GetZoneId ());
2012-03-02 22:00:26 -03:00
}
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
2013-03-04 13:00:02 +01:00
TempSummon * WorldObject :: SummonCreature ( uint32 id , float x , float y , float z , float ang /*= 0*/ , TempSummonType spwtype /*= TEMPSUMMON_MANUAL_DESPAWN*/ , uint32 despwtime /*= 0*/ ) const
2013-03-04 11:45:57 +01:00
{
if ( ! x && ! y && ! z )
{
GetClosePoint ( x , y , z , GetObjectSize ());
ang = GetOrientation ();
}
Position pos ;
pos . Relocate ( x , y , z , ang );
return SummonCreature ( id , pos , spwtype , despwtime , 0 );
}
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
{
2013-05-13 15:07:36 +02:00
TC_LOG_ERROR ( LOG_FILTER_SQL , "Gameobject template %u not found in database!" , entry );
2008-10-17 18:13:04 -05:00
return NULL ;
}
2012-12-31 20:43:14 +01:00
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
}
2012-12-31 20:43:14 +01: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
2012-12-31 20:43:14 +01:00
ToUnit () -> AddGameObject ( go );
2008-10-18 19:59:34 -05:00
else
go -> SetSpawnedByDefault ( false );
2009-10-17 15:51:44 -07:00
2012-12-31 20:43:14 +01:00
map -> AddToMap ( go );
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
2013-02-23 01:50:52 +01:00
/**
* Summons group of creatures. Should be called only by instances of Creature and GameObject classes.
*
* @param group Id of group to summon.
* @param list List to store pointers to summoned creatures.
*/
2013-02-26 02:33:08 +01:00
void WorldObject :: SummonCreatureGroup ( uint8 group , std :: list < TempSummon *>* list /*= NULL*/ )
2013-02-23 01:50:52 +01:00
{
ASSERT (( GetTypeId () == TYPEID_GAMEOBJECT || GetTypeId () == TYPEID_UNIT ) && "Only GOs and creatures can summon npc groups!" );
std :: vector < TempSummonData > const * data = sObjectMgr -> GetSummonGroup ( GetEntry (), GetTypeId () == TYPEID_GAMEOBJECT ? SUMMONER_TYPE_GAMEOBJECT : SUMMONER_TYPE_CREATURE , group );
if ( ! data )
return ;
for ( std :: vector < TempSummonData >:: const_iterator itr = data -> begin (); itr != data -> end (); ++ itr )
if ( TempSummon * summon = SummonCreature ( itr -> entry , itr -> pos , itr -> type , itr -> time ))
2013-02-26 02:33:08 +01:00
if ( list )
list -> push_back ( summon );
2013-02-23 01:50:52 +01: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 ;
}
2012-09-08 23:15:29 +01:00
GameObject * WorldObject :: FindNearestGameObjectOfType ( GameobjectTypes type , float range ) const
{
GameObject * go = NULL ;
Trinity :: NearestGameObjectTypeInObjectRangeCheck checker ( * this , type , range );
Trinity :: GameObjectLastSearcher < Trinity :: NearestGameObjectTypeInObjectRangeCheck > searcher ( this , go , checker );
VisitNearbyGridObject ( range , searcher );
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
2012-02-03 19:12:41 +02:00
if (!c->isAlive() || c->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_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
{
2012-10-02 15:06:19 +02:00
x = GetPositionX () + ( GetObjectSize () + distance2d ) * std :: cos ( absAngle );
y = GetPositionY () + ( GetObjectSize () + distance2d ) * std :: 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
2013-03-04 13:00:02 +01:00
void WorldObject :: GetClosePoint ( float & x , float & y , float & z , float size , float distance2d /*= 0*/ , float angle /*= 0*/ ) const
2013-03-04 11:45:57 +01:00
{
// angle calculated from current orientation
GetNearPoint ( NULL , x , y , z , size , distance2d , GetOrientation () + angle );
}
void WorldObject :: GetNearPosition ( Position & pos , float dist , float angle )
{
GetPosition ( & pos );
MovePosition ( pos , dist , angle );
}
void WorldObject :: GetFirstCollisionPosition ( Position & pos , float dist , float angle )
{
GetPosition ( & pos );
MovePositionToFirstCollision ( pos , dist , angle );
}
void WorldObject :: GetRandomNearPosition ( Position & pos , float radius )
{
GetPosition ( & pos );
MovePosition ( pos , radius * ( float ) rand_norm (), ( float ) rand_norm () * static_cast < float > ( 2 * M_PI ));
}
2013-03-04 13:00:02 +01:00
void WorldObject :: GetContactPoint ( const WorldObject * obj , float & x , float & y , float & z , float distance2d /*= CONTACT_DISTANCE*/ ) const
2013-03-04 11:45:57 +01:00
{
// angle to face `obj` to `this` using distance includes size of `obj`
GetNearPoint ( obj , x , y , z , obj -> GetObjectSize (), distance2d , GetAngle ( obj ));
}
float WorldObject :: GetObjectSize () const
{
return ( m_valuesCount > UNIT_FIELD_COMBATREACH ) ? m_floatValues [ UNIT_FIELD_COMBATREACH ] : DEFAULT_WORLD_OBJECT_SIZE ;
}
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
{
2012-08-20 10:44:14 +02:00
angle += GetOrientation ();
2012-05-30 08:01:02 +02:00
float destx , desty , destz , ground , floor ;
2012-10-02 15:06:19 +02:00
destx = pos . m_positionX + dist * std :: cos ( angle );
desty = pos . m_positionY + dist * std :: sin ( angle );
2012-05-30 08:01:02 +02:00
// Prevent invalid coordinates here, position is unchanged
2012-09-07 04:21:11 +02:00
if ( ! Trinity :: IsValidMapCoord ( destx , desty , pos . m_positionZ ))
2012-05-30 08:01:02 +02:00
{
2013-05-13 15:07:36 +02:00
TC_LOG_FATAL ( LOG_FILTER_GENERAL , "WorldObject::MovePosition invalid coordinates X: %f and Y: %f were passed!" , destx , desty );
2012-05-30 08:01:02 +02:00
return ;
}
ground = GetMap () -> GetHeight ( GetPhaseMask (), destx , desty , MAX_HEIGHT , true );
floor = GetMap () -> GetHeight ( GetPhaseMask (), destx , desty , pos . m_positionZ , true );
destz = fabs ( ground - pos . m_positionZ ) <= fabs ( floor - pos . m_positionZ ) ? ground : floor ;
float step = dist / 10.0f ;
for ( uint8 j = 0 ; j < 10 ; ++ j )
{
// do not allow too big z changes
if ( fabs ( pos . m_positionZ - destz ) > 6 )
{
2012-10-02 15:06:19 +02:00
destx -= step * std :: cos ( angle );
desty -= step * std :: sin ( angle );
2012-05-30 08:01:02 +02:00
ground = GetMap () -> GetHeight ( GetPhaseMask (), destx , desty , MAX_HEIGHT , true );
floor = GetMap () -> GetHeight ( GetPhaseMask (), 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 ;
}
}
2009-08-29 23:20:16 -05:00
Trinity :: NormalizeMapCoord ( pos . m_positionX );
Trinity :: NormalizeMapCoord ( pos . m_positionY );
UpdateGroundPositionZ ( pos . m_positionX , pos . m_positionY , pos . m_positionZ );
2012-08-20 10:44:14 +02:00
pos . SetOrientation ( GetOrientation ());
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 )
{
2012-08-20 10:44:14 +02:00
angle += GetOrientation ();
2010-07-21 02:06:51 +02:00
float destx , desty , destz , ground , floor ;
2012-02-11 19:23:18 -05:00
pos . m_positionZ += 2.0f ;
2012-10-02 15:06:19 +02:00
destx = pos . m_positionX + dist * std :: cos ( angle );
desty = pos . m_positionY + dist * std :: sin ( angle );
2012-05-30 08:01:02 +02:00
// Prevent invalid coordinates here, position is unchanged
if ( ! Trinity :: IsValidMapCoord ( destx , desty ))
{
2013-05-13 15:07:36 +02:00
TC_LOG_FATAL ( LOG_FILTER_GENERAL , "WorldObject::MovePositionToFirstCollision invalid coordinates X: %f and Y: %f were passed!" , destx , desty );
2012-05-30 08:01:02 +02:00
return ;
}
2012-02-03 16:03:52 -05:00
ground = GetMap () -> GetHeight ( GetPhaseMask (), destx , desty , MAX_HEIGHT , true );
floor = GetMap () -> GetHeight ( GetPhaseMask (), destx , desty , pos . m_positionZ , true );
2010-07-21 02:06:51 +02:00
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
2012-10-02 15:06:19 +02:00
destx -= CONTACT_DISTANCE * std :: cos ( angle );
desty -= CONTACT_DISTANCE * std :: sin ( angle );
2010-07-21 02:06:51 +02:00
dist = sqrt (( pos . m_positionX - destx ) * ( pos . m_positionX - destx ) + ( pos . m_positionY - desty ) * ( pos . m_positionY - desty ));
}
2012-02-11 19:23:18 -05:00
// check dynamic collision
col = GetMap () -> getObjectHitPos ( GetPhaseMask (), pos . m_positionX , pos . m_positionY , pos . m_positionZ + 0.5f , destx , desty , destz + 0.5f , destx , desty , destz , - 0.5f );
// Collided with a gameobject
if ( col )
{
2012-10-02 15:06:19 +02:00
destx -= CONTACT_DISTANCE * std :: cos ( angle );
desty -= CONTACT_DISTANCE * std :: sin ( angle );
2012-02-11 19:23:18 -05:00
dist = sqrt (( pos . m_positionX - destx ) * ( pos . m_positionX - destx ) + ( pos . m_positionY - desty ) * ( pos . m_positionY - desty ));
}
2010-07-21 02:06:51 +02:00
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 )
{
2012-10-02 15:06:19 +02:00
destx -= step * std :: cos ( angle );
desty -= step * std :: sin ( angle );
2012-02-03 16:03:52 -05:00
ground = GetMap () -> GetHeight ( GetPhaseMask (), destx , desty , MAX_HEIGHT , true );
floor = GetMap () -> GetHeight ( GetPhaseMask (), destx , desty , pos . m_positionZ , true );
2010-07-21 02:06:51 +02:00
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 );
2012-02-11 19:23:18 -05:00
UpdateAllowedPositionZ ( pos . m_positionX , pos . m_positionY , pos . m_positionZ );
2012-08-20 10:44:14 +02:00
pos . SetOrientation ( GetOrientation ());
2010-07-21 02:06:51 +02:00
}
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
2013-03-04 19:14:58 +01:00
bool WorldObject :: InSamePhase ( WorldObject const * obj ) const
2013-03-04 11:45:57 +01:00
{
return InSamePhase ( obj -> GetPhaseMask ());
}
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 );
2013-06-01 17:49:33 +02: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
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
2013-03-08 21:41:30 +01: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
}