2008-10-11 14:16:25 -05:00
/*
2009-02-04 12:42:26 +01:00
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
2008-10-14 11:57:03 -05:00
*
2009-02-04 12:04:12 +01:00
* Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/>
2008-10-11 14:16:25 -05:00
*
* 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
2008-10-14 11:57:03 -05:00
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2008-10-11 14:16:25 -05:00
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
2008-10-14 11:57:03 -05:00
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2008-10-11 14:16:25 -05:00
*/
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
#include "Common.h"
#include "SharedDefines.h"
#include "WorldPacket.h"
#include "Opcodes.h"
#include "Log.h"
#include "World.h"
#include "Object.h"
#include "Creature.h"
#include "Player.h"
2009-03-09 17:06:13 -06:00
#include "Vehicle.h"
2008-10-11 14:16:25 -05:00
#include "ObjectMgr.h"
#include "UpdateData.h"
#include "UpdateMask.h"
#include "Util.h"
#include "MapManager.h"
#include "ObjectAccessor.h"
#include "Log.h"
#include "Transports.h"
#include "TargetedMovementGenerator.h"
#include "WaypointMovementGenerator.h"
#include "VMapFactory.h"
#include "CellImpl.h"
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
#include "TemporarySummon.h"
2009-03-20 14:01:46 -06:00
#include "Totem.h"
2009-05-30 22:15:05 -05:00
#include "OutdoorPvPMgr.h"
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 GuidHigh2TypeId ( uint32 guid_hi )
{
switch ( guid_hi )
{
case HIGHGUID_ITEM : return TYPEID_ITEM ;
//case HIGHGUID_CONTAINER: return TYPEID_CONTAINER; HIGHGUID_CONTAINER==HIGHGUID_ITEM currently
case HIGHGUID_UNIT : return TYPEID_UNIT ;
case HIGHGUID_PET : return TYPEID_UNIT ;
case HIGHGUID_PLAYER : return TYPEID_PLAYER ;
case HIGHGUID_GAMEOBJECT : return TYPEID_GAMEOBJECT ;
case HIGHGUID_DYNAMICOBJECT : return TYPEID_DYNAMICOBJECT ;
case HIGHGUID_CORPSE : return TYPEID_CORPSE ;
case HIGHGUID_MO_TRANSPORT : return TYPEID_GAMEOBJECT ;
2009-01-24 11:28:00 -06:00
case HIGHGUID_VEHICLE : return TYPEID_UNIT ;
2008-10-11 14:16:25 -05:00
}
2009-05-31 15:56:51 -05:00
return NUM_CLIENT_OBJECT_TYPES ; // unknown
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-06-01 12:15:43 -05: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
2008-10-11 14:16:25 -05:00
m_uint32Values = 0 ;
m_uint32Values_mirror = 0 ;
m_valuesCount = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
m_inWorld = false ;
m_objectUpdated = false ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
m_PackGUID . appendPackGUID ( 0 );
}
2009-10-17 15:51:44 -07:00
2009-08-11 16:33:33 -05:00
WorldObject ::~ WorldObject ()
{
2009-08-13 17:02:17 -05:00
// this may happen because there are many !create/delete
2009-08-13 11:47:38 -05:00
if ( m_isWorldObject && m_currMap )
2009-08-11 16:33:33 -05:00
{
2009-08-13 17:02:17 -05:00
if ( GetTypeId () == TYPEID_CORPSE )
{
sLog . outCrash ( "Object::~Object Corpse guid=" UI64FMTD ", type=%d, entry=%u deleted but still in map!!" , GetGUID (), (( Corpse * ) this ) -> GetType (), GetEntry ());
assert ( false );
}
2009-08-11 16:33:33 -05:00
ResetMap ();
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Object ::~ Object ( )
{
2009-04-09 17:15:40 -05:00
if ( IsInWorld ())
2008-10-11 14:16:25 -05:00
{
2009-06-16 17:58:44 -05:00
sLog . outCrash ( "Object::~Object - guid=" UI64FMTD ", typeid=%d, entry=%u deleted but still in world!!" , GetGUID (), GetTypeId (), GetEntry ());
2009-06-17 09:57:22 -05:00
if ( isType ( TYPEMASK_ITEM ))
sLog . outCrash ( "Item slot %u" , (( Item * ) this ) -> GetSlot ());
2009-04-09 17:15:40 -05: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
2009-06-16 17:58:44 -05:00
if ( m_objectUpdated )
{
sLog . outCrash ( "Object::~Object - guid=" UI64FMTD ", typeid=%d, entry=%u deleted but still in update list!!" , GetGUID (), GetTypeId (), GetEntry ());
assert ( false );
2009-06-17 09:57:22 -05:00
ObjectAccessor :: Instance (). RemoveUpdateObject ( this );
2009-06-16 17:58:44 -05:00
}
2009-10-17 15:51:44 -07:00
2009-04-09 17:15:40 -05:00
if ( m_uint32Values )
{
2008-10-11 14:16:25 -05:00
//DEBUG_LOG("Object desctr 1 check (%p)",(void*)this);
delete [] m_uint32Values ;
delete [] m_uint32Values_mirror ;
//DEBUG_LOG("Object desctr 2 check (%p)",(void*)this);
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Object :: _InitValues ()
{
m_uint32Values = new uint32 [ m_valuesCount ];
memset ( m_uint32Values , 0 , m_valuesCount * sizeof ( uint32 ));
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
m_uint32Values_mirror = new uint32 [ m_valuesCount ];
memset ( m_uint32Values_mirror , 0 , m_valuesCount * sizeof ( uint32 ));
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
2008-10-11 14:16:25 -05:00
void Object :: _Create ( uint32 guidlow , uint32 entry , HighGuid guidhigh )
{
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 );
2008-10-11 14:16:25 -05:00
SetUInt64Value ( OBJECT_FIELD_GUID , guid );
2009-06-13 09:18:54 -05:00
uint32 type = 0 ;
switch ( m_objectType )
{
//case TYPEID_ITEM: type = 3; break;
//case TYPEID_CONTAINER: type = 7; break; //+4
//case TYPEID_UNIT: type = 9; break; //+2
//case TYPEID_PLAYER: type = 25; break; //+16
//case TYPEID_GAMEOBJECT: type = 33; break; //+8
case TYPEID_DYNAMICOBJECT : type = 65 ; break ; //+32
//case TYPEID_CORPSE: type = 129; break; //+64
default : type = m_objectType ; break ;
}
SetUInt32Value ( OBJECT_FIELD_TYPE , type );
//SetUInt32Value( OBJECT_FIELD_TYPE, m_objectType );
2009-06-01 12:15:43 -05:00
m_PackGUID . wpos ( 0 );
2008-10-11 14:16:25 -05:00
m_PackGUID . appendPackGUID ( GetGUID ());
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Object :: BuildMovementUpdateBlock ( UpdateData * data , uint32 flags ) const
{
2009-06-11 00:45:59 -05:00
ByteBuffer buf ( 500 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
buf << uint8 ( UPDATETYPE_MOVEMENT );
2009-06-05 17:44:27 -05:00
buf . append ( GetPackGUID ());
2009-10-17 15:51:44 -07:00
2009-04-22 17:50:26 -05:00
_BuildMovementUpdate ( & buf , flags );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
data -> AddUpdateBlock ( buf );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Object :: BuildCreateUpdateBlockForPlayer ( UpdateData * data , Player * target ) const
{
if ( ! target )
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint8 updatetype = UPDATETYPE_CREATE_OBJECT ;
2009-06-11 00:45:59 -05:00
uint16 flags = m_updateFlag ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
/** lower flag1 **/
2009-05-31 15:56:51 -05:00
if ( target == this ) // building packet for yourself
2008-10-11 14:16:25 -05:00
flags |= UPDATEFLAG_SELF ;
2009-10-17 15:51:44 -07:00
2008-12-24 09:58:26 -06:00
if ( flags & UPDATEFLAG_HAS_POSITION )
2008-10-11 14:16:25 -05:00
{
// UPDATETYPE_CREATE_OBJECT2 dynamic objects, corpses...
if ( isType ( TYPEMASK_DYNAMICOBJECT ) || isType ( TYPEMASK_CORPSE ) || isType ( TYPEMASK_PLAYER ))
updatetype = UPDATETYPE_CREATE_OBJECT2 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// UPDATETYPE_CREATE_OBJECT2 for pets...
if ( target -> GetPetGUID () == GetGUID ())
updatetype = UPDATETYPE_CREATE_OBJECT2 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// UPDATETYPE_CREATE_OBJECT2 for some gameobject types...
if ( isType ( TYPEMASK_GAMEOBJECT ))
{
switch ((( GameObject * ) this ) -> GetGoType ())
{
case GAMEOBJECT_TYPE_TRAP :
case GAMEOBJECT_TYPE_DUEL_ARBITER :
case GAMEOBJECT_TYPE_FLAGSTAND :
case GAMEOBJECT_TYPE_FLAGDROP :
updatetype = UPDATETYPE_CREATE_OBJECT2 ;
break ;
case GAMEOBJECT_TYPE_TRANSPORT :
flags |= UPDATEFLAG_TRANSPORT ;
break ;
2009-05-03 22:21:46 -05:00
default :
break ;
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2008-12-24 09:58:26 -06:00
if ( isType ( TYPEMASK_UNIT ))
{
if ((( Unit * ) this ) -> getVictim ())
flags |= UPDATEFLAG_HAS_TARGET ;
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
//sLog.outDebug("BuildCreateUpdate: update-type: %u, object-type: %u got flags: %X, flags2: %X", updatetype, m_objectTypeId, flags, flags2);
2009-10-17 15:51:44 -07:00
2009-06-11 00:45:59 -05:00
ByteBuffer buf ( 500 );
2008-10-11 14:16:25 -05:00
buf << ( uint8 ) updatetype ;
2009-06-05 17:44:27 -05:00
buf . append ( GetPackGUID ());
2008-10-11 14:16:25 -05:00
buf << ( uint8 ) m_objectTypeId ;
2009-10-17 15:51:44 -07:00
2009-04-22 17:50:26 -05:00
_BuildMovementUpdate ( & buf , flags );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
UpdateMask updateMask ;
updateMask . SetCount ( m_valuesCount );
_SetCreateBits ( & updateMask , target );
2009-05-31 15:56:51 -05:00
_BuildValuesUpdate ( updatetype , & buf , & updateMask , target );
2008-10-11 14:16:25 -05:00
data -> AddUpdateBlock ( buf );
}
2009-10-17 15:51:44 -07:00
2009-12-19 17:58:45 +01:00
void Object :: SendCreateUpdateToPlayer ( Player * player )
2008-10-11 14:16:25 -05:00
{
// send create update to player
UpdateData upd ;
WorldPacket packet ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
BuildCreateUpdateBlockForPlayer ( & upd , player );
upd . BuildPacket ( & packet );
player -> GetSession () -> SendPacket ( & packet );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Object :: BuildValuesUpdateBlockForPlayer ( UpdateData * data , Player * target ) const
{
2009-06-11 00:45:59 -05:00
ByteBuffer buf ( 500 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
buf << ( uint8 ) UPDATETYPE_VALUES ;
2009-06-05 17:44:27 -05:00
buf . append ( GetPackGUID ());
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
UpdateMask updateMask ;
updateMask . SetCount ( m_valuesCount );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05: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
2008-10-11 14:16:25 -05:00
void Object :: BuildOutOfRangeUpdateBlock ( UpdateData * data ) const
{
data -> AddOutOfRangeGUID ( GetGUID ());
}
2009-10-17 15:51:44 -07:00
2009-07-30 10:26:15 +08:00
void Object :: DestroyForPlayer ( Player * target , bool anim ) const
2008-10-11 14:16:25 -05:00
{
ASSERT ( target );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
WorldPacket data ( SMSG_DESTROY_OBJECT , 8 );
2009-05-31 15:56:51 -05:00
data << uint64 ( GetGUID ());
2009-07-30 10:26:15 +08:00
data << uint8 ( anim ? 1 : 0 ); // WotLK (bool), may be despawn animation
2008-10-11 14:16:25 -05:00
target -> GetSession () -> SendPacket ( & data );
}
2009-10-17 15:51:44 -07:00
2009-06-11 00:45:59 -05:00
void Object :: _BuildMovementUpdate ( ByteBuffer * data , uint16 flags ) const
2008-10-11 14:16:25 -05:00
{
2009-06-11 00:45:59 -05:00
* data << ( uint16 ) flags ; // update flags
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// 0x20
if ( flags & UPDATEFLAG_LIVING )
{
2009-04-21 15:43:03 -05:00
(( Unit * ) this ) -> BuildMovementPacket ( data );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
* data << (( Unit * ) this ) -> GetSpeed ( MOVE_WALK );
* data << (( Unit * ) this ) -> GetSpeed ( MOVE_RUN );
2008-12-12 11:21:28 -06:00
* data << (( Unit * ) this ) -> GetSpeed ( MOVE_SWIM_BACK );
2008-10-11 14:16:25 -05:00
* data << (( Unit * ) this ) -> GetSpeed ( MOVE_SWIM );
2008-12-12 11:21:28 -06:00
* data << (( Unit * ) this ) -> GetSpeed ( MOVE_RUN_BACK );
* data << (( Unit * ) this ) -> GetSpeed ( MOVE_FLIGHT );
* data << (( Unit * ) this ) -> GetSpeed ( MOVE_FLIGHT_BACK );
* data << (( Unit * ) this ) -> GetSpeed ( MOVE_TURN_RATE );
2008-12-24 09:58:26 -06:00
* data << (( Unit * ) this ) -> GetSpeed ( MOVE_PITCH_RATE );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// 0x08000000
2009-04-22 17:50:26 -05:00
if ( GetTypeId () == TYPEID_PLAYER && (( Player * ) this ) -> isInFlight ())
2008-10-11 14:16:25 -05:00
{
WPAssert ((( Player * ) this ) -> GetMotionMaster () -> GetCurrentMovementGeneratorType () == FLIGHT_MOTION_TYPE );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
FlightPathMovementGenerator * fmg = ( FlightPathMovementGenerator * )((( Player * ) this ) -> GetMotionMaster () -> top ());
2009-10-17 15:51:44 -07:00
2009-06-11 00:45:59 -05:00
uint32 flags3 = MOVEFLAG_GLIDE ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
* data << uint32 ( flags3 ); // splines flag?
2009-10-17 15:51:44 -07:00
2009-06-11 00:45:59 -05:00
if ( flags3 & 0x20000 ) // may be orientation
2008-10-11 14:16:25 -05:00
{
* data << ( float ) 0 ;
}
2009-06-11 00:45:59 -05:00
else
2008-10-11 14:16:25 -05:00
{
2009-06-11 00:45:59 -05:00
if ( flags3 & 0x8000 ) // probably x,y,z coords there
{
* data << ( float ) 0 ;
* data << ( float ) 0 ;
* data << ( float ) 0 ;
}
2009-10-17 15:51:44 -07:00
2009-06-11 00:45:59 -05:00
if ( flags3 & 0x10000 ) // probably guid there
{
* data << uint64 ( 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
Path & path = fmg -> GetPath ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
float x , y , z ;
(( Player * ) this ) -> GetPosition ( x , y , z );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 inflighttime = uint32 ( path . GetPassedLength ( fmg -> GetCurrentNode (), x , y , z ) * 32 );
uint32 traveltime = uint32 ( path . GetTotalLength () * 32 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
* data << uint32 ( inflighttime ); // passed move time?
* data << uint32 ( traveltime ); // full move time?
* data << uint32 ( 0 ); // ticks count?
2009-10-17 15:51:44 -07:00
2009-06-11 00:45:59 -05:00
* data << float ( 0 ); // added in 3.1
* data << float ( 0 ); // added in 3.1
* data << float ( 0 ); // added in 3.1
2009-10-17 15:51:44 -07:00
2009-06-11 00:45:59 -05:00
* data << uint32 ( 0 ); // added in 3.1
2009-10-17 15:51:44 -07:00
2009-06-11 00:45:59 -05:00
uint32 poscount = uint32 ( path . Size ());
2008-10-11 14:16:25 -05:00
* data << uint32 ( poscount ); // points count
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( uint32 i = 0 ; i < poscount ; ++ i )
2008-10-11 14:16:25 -05:00
{
* data << path . GetNodes ()[ i ]. x ;
* data << path . GetNodes ()[ i ]. y ;
* data << path . GetNodes ()[ i ]. z ;
}
2009-10-17 15:51:44 -07:00
2009-02-02 09:51:51 -06:00
* data << uint8 ( 0 ); // added in 3.0.8
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
* data << path . GetNodes ()[ poscount - 1 ]. x ;
* data << path . GetNodes ()[ poscount - 1 ]. y ;
* data << path . GetNodes ()[ poscount - 1 ]. z ;
2009-06-11 00:45:59 -05:00
}
}
else
{
if ( flags & UPDATEFLAG_POSITION )
{
* data << uint8 ( 0 ); // unk PGUID!
* data << (( WorldObject * ) this ) -> GetPositionX ();
* data << (( WorldObject * ) this ) -> GetPositionY ();
* data << (( WorldObject * ) this ) -> GetPositionZ ();
* data << (( WorldObject * ) this ) -> GetPositionX ();
* data << (( WorldObject * ) this ) -> GetPositionY ();
* data << (( WorldObject * ) this ) -> GetPositionZ ();
* data << (( WorldObject * ) this ) -> GetOrientation ();
2009-10-17 15:51:44 -07:00
2009-06-11 00:45:59 -05:00
if ( GetTypeId () == TYPEID_CORPSE )
* data << float ((( WorldObject * ) this ) -> GetOrientation ());
else
* data << float ( 0 );
}
else
{
// 0x40
if ( flags & UPDATEFLAG_HAS_POSITION )
{
// 0x02
if ( flags & UPDATEFLAG_TRANSPORT && (( GameObject * ) this ) -> GetGoType () == GAMEOBJECT_TYPE_MO_TRANSPORT )
{
* data << ( float ) 0 ;
* data << ( float ) 0 ;
* data << ( float ) 0 ;
* data << (( WorldObject * ) this ) -> GetOrientation ();
}
else
{
* data << (( WorldObject * ) this ) -> GetPositionX ();
* data << (( WorldObject * ) this ) -> GetPositionY ();
* data << (( WorldObject * ) this ) -> GetPositionZ ();
* data << (( WorldObject * ) this ) -> GetOrientation ();
}
}
2008-10-11 14:16:25 -05:00
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// 0x8
if ( flags & UPDATEFLAG_LOWGUID )
{
switch ( GetTypeId ())
{
case TYPEID_OBJECT :
case TYPEID_ITEM :
case TYPEID_CONTAINER :
case TYPEID_GAMEOBJECT :
case TYPEID_DYNAMICOBJECT :
case TYPEID_CORPSE :
* data << uint32 ( GetGUIDLow ()); // GetGUIDLow()
break ;
case TYPEID_UNIT :
* data << uint32 ( 0x0000000B ); // unk, can be 0xB or 0xC
break ;
case TYPEID_PLAYER :
if ( flags & UPDATEFLAG_SELF )
2008-12-24 09:58:26 -06:00
* data << uint32 ( 0x0000002F ); // unk, can be 0x15 or 0x22
2008-10-11 14:16:25 -05:00
else
* data << uint32 ( 0x00000008 ); // unk, can be 0x7 or 0x8
break ;
default :
* data << uint32 ( 0x00000000 ); // unk
break ;
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// 0x10
if ( flags & UPDATEFLAG_HIGHGUID )
{
2009-06-13 09:18:54 -05:00
// not high guid
* data << uint32 ( 0x00000000 ); // unk
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// 0x4
2008-12-24 09:58:26 -06:00
if ( flags & UPDATEFLAG_HAS_TARGET ) // packed guid (current target guid)
2008-10-11 14:16:25 -05:00
{
2008-12-24 09:58:26 -06:00
if ( Unit * victim = (( Unit * ) this ) -> getVictim ())
data -> append ( victim -> GetPackGUID ());
else
* data << uint8 ( 0 );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// 0x2
if ( flags & UPDATEFLAG_TRANSPORT )
{
* data << uint32 ( getMSTime ()); // ms time
}
2009-10-17 15:51:44 -07:00
2008-12-24 09:58:26 -06:00
// 0x80
if ( flags & UPDATEFLAG_VEHICLE ) // unused for now
{
2009-08-23 22:09:43 -05:00
* data << uint32 ((( Unit * ) this ) -> GetVehicleKit () -> GetVehicleInfo () -> m_ID ); // vehicle id
2008-12-24 09:58:26 -06:00
* data << float ( 0 ); // facing adjustment
}
2009-10-17 15:51:44 -07:00
2009-06-11 00:45:59 -05:00
// 0x200
if ( flags & UPDATEFLAG_ROTATION )
{
* data << uint64 ((( GameObject * ) this ) -> GetRotation ());
}
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 :: _BuildValuesUpdate ( uint8 updatetype , ByteBuffer * data , UpdateMask * updateMask , Player * target ) const
{
if ( ! target )
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bool IsActivateToQuest = false ;
if ( updatetype == UPDATETYPE_CREATE_OBJECT || updatetype == UPDATETYPE_CREATE_OBJECT2 )
{
2009-11-27 01:41:26 +01:00
if ( isType ( TYPEMASK_GAMEOBJECT ) && ! (( GameObject * ) this ) -> IsDynTransport ())
2008-10-11 14:16:25 -05:00
{
if ( (( GameObject * ) this ) -> ActivateToQuest ( target ) || target -> isGameMaster ())
IsActivateToQuest = true ;
2009-10-17 15:51:44 -07:00
2009-09-04 05:11:27 +02:00
updateMask -> SetBit ( GAMEOBJECT_DYNAMIC );
2009-10-17 15:51:44 -07:00
2009-01-04 17:14:34 -06:00
if ((( GameObject * ) this ) -> GetGoArtKit ())
updateMask -> SetBit ( GAMEOBJECT_BYTES_1 );
2008-10-11 14:16:25 -05:00
}
2009-07-30 17:16:56 +02:00
else if ( isType ( TYPEMASK_UNIT ))
{
if ( (( Unit * ) this ) -> HasFlag ( UNIT_FIELD_AURASTATE , PER_CASTER_AURA_STATE_MASK ))
{
updateMask -> SetBit ( UNIT_FIELD_AURASTATE );
}
}
2008-10-11 14:16:25 -05:00
}
2009-05-31 15:56:51 -05:00
else // case UPDATETYPE_VALUES
2008-10-11 14:16:25 -05:00
{
if ( isType ( TYPEMASK_GAMEOBJECT ) && ! (( GameObject * ) this ) -> IsTransport ())
{
if ( (( GameObject * ) this ) -> ActivateToQuest ( target ) || target -> isGameMaster ())
{
IsActivateToQuest = true ;
}
2008-12-24 09:58:26 -06:00
updateMask -> SetBit ( GAMEOBJECT_DYNAMIC );
updateMask -> SetBit ( GAMEOBJECT_BYTES_1 );
2008-10-11 14:16:25 -05:00
}
2009-07-30 17:16:56 +02:00
else if ( isType ( TYPEMASK_UNIT ))
{
if ( (( Unit * ) this ) -> HasFlag ( UNIT_FIELD_AURASTATE , PER_CASTER_AURA_STATE_MASK ))
{
updateMask -> SetBit ( UNIT_FIELD_AURASTATE );
}
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
WPAssert ( updateMask && updateMask -> GetCount () == m_valuesCount );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
* data << ( uint8 ) updateMask -> GetBlockCount ();
data -> append ( updateMask -> GetMask (), updateMask -> GetLength () );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// 2 specialized loops for speed optimization in non-unit case
if ( isType ( TYPEMASK_UNIT )) // unit (creature/player) case
{
2009-10-17 16:20:24 -07:00
for ( uint16 index = 0 ; index < m_valuesCount ; ++ index )
2008-10-11 14:16:25 -05:00
{
if ( updateMask -> GetBit ( index ) )
{
if ( index == UNIT_NPC_FLAGS )
2009-05-05 16:56:15 -05:00
{
// remove custom flag before sending
uint32 appendValue = m_uint32Values [ index ] & ~ ( UNIT_NPC_FLAG_GUARD + UNIT_NPC_FLAG_OUTDOORPVP );
2009-10-17 15:51:44 -07:00
2009-12-19 18:29:09 +01:00
if ( GetTypeId () == TYPEID_UNIT )
{
if ( ! target -> canSeeSpellClickOn (( Creature * ) this ))
appendValue &= ~ UNIT_NPC_FLAG_SPELLCLICK ;
if ( appendValue & UNIT_NPC_FLAG_TRAINER )
{
if ( ! (( Creature * ) this ) -> isCanTrainingOf ( target , false ))
appendValue &= ~ ( UNIT_NPC_FLAG_TRAINER | UNIT_NPC_FLAG_TRAINER_CLASS | UNIT_NPC_FLAG_TRAINER_PROFESSION );
}
}
2009-10-17 15:51:44 -07:00
2009-05-05 16:56:15 -05:00
* data << uint32 ( appendValue );
}
2009-07-30 17:16:56 +02:00
else if ( index == UNIT_FIELD_AURASTATE )
{
// Check per caster aura states to not enable using a pell in client if specified aura is not by target
* data << (( Unit * ) this ) -> BuildAuraStateUpdateForTarget ( target );
}
2008-10-11 14:16:25 -05:00
// FIXME: Some values at server stored in float format but must be sent to client in uint32 format
else if ( index >= UNIT_FIELD_BASEATTACKTIME && index <= UNIT_FIELD_RANGEDATTACKTIME )
{
// convert from float to uint32 and send
* data << uint32 ( m_floatValues [ index ] < 0 ? 0 : m_floatValues [ index ]);
}
// 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
{
* data << uint32 ( m_floatValues [ index ]);
}
// Gamemasters should be always able to select units - remove not selectable flag
2009-05-24 12:56:09 -05:00
else if ( index == UNIT_FIELD_FLAGS )
2008-10-11 14:16:25 -05:00
{
2009-05-24 12:56:09 -05:00
if ( target -> isGameMaster ())
* data << ( m_uint32Values [ index ] & ~ UNIT_FLAG_NOT_SELECTABLE );
else
* 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
2009-05-24 12:56:09 -05:00
else if ( index == UNIT_FIELD_DISPLAYID )
2008-10-20 13:41:05 -05:00
{
2009-05-24 12:56:09 -05:00
if ( GetTypeId () == TYPEID_UNIT )
2008-10-20 13:41:05 -05:00
{
2009-05-24 12:56:09 -05:00
const CreatureInfo * cinfo = (( Creature * ) this ) -> GetCreatureInfo ();
if ( cinfo -> flags_extra & CREATURE_FLAG_EXTRA_TRIGGER )
2008-11-09 14:54:13 -06:00
{
2009-05-24 12:56:09 -05:00
if ( target -> isGameMaster ())
{
2009-09-21 07:52:16 +02:00
if ( cinfo -> Modelid1 )
* data << cinfo -> Modelid1 ;
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
{
2009-09-21 07:52:16 +02:00
if ( cinfo -> Modelid3 )
* data << cinfo -> Modelid3 ;
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
2009-05-24 12:56:09 -05:00
* data << m_uint32Values [ index ];
2008-10-20 13:41:05 -05:00
}
else
* data << m_uint32Values [ index ];
}
2008-10-11 14:16:25 -05:00
// hide lootable animation for unallowed players
2009-05-24 12:56:09 -05:00
else if ( index == UNIT_DYNAMIC_FLAGS )
2008-10-11 14:16:25 -05:00
{
2009-05-24 12:56:09 -05:00
if ( GetTypeId () == TYPEID_UNIT )
{
if ( ! target -> isAllowedToLoot (( Creature * ) this ))
* data << ( m_uint32Values [ index ] & ~ UNIT_DYNFLAG_LOOTABLE );
else
* data << ( m_uint32Values [ index ] & ~ UNIT_DYNFLAG_OTHER_TAGGER );
}
2008-10-11 14:16:25 -05:00
else
2009-05-24 12:56:09 -05:00
* data << m_uint32Values [ index ];
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")
else if ( index == UNIT_FIELD_BYTES_2 || index == UNIT_FIELD_FACTIONTEMPLATE )
{
2009-05-24 12:56:09 -05:00
if ((( Unit * ) this ) -> IsControlledByPlayer () && target != this && sWorld . getConfig ( CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP ) && (( Unit * ) this ) -> IsInRaidWith ( target ))
2009-01-15 21:29:32 -05:00
{
2009-05-24 12:56:09 -05:00
FactionTemplateEntry const * ft1 , * ft2 ;
ft1 = (( Unit * ) this ) -> getFactionTemplateEntry ();
ft2 = target -> getFactionTemplateEntry ();
if ( ft1 && ft2 && ! ft1 -> IsFriendlyTo ( * ft2 ))
2009-01-15 21:29:32 -05:00
{
2009-05-24 12:56:09 -05: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
DEBUG_LOG ( "-- VALUES_UPDATE: Sending '%s' the blue-group-fix from '%s' (flag)" , target -> GetName (), (( Player * ) this ) -> GetName ());
* data << ( m_uint32Values [ index ] & (( UNIT_BYTE2_FLAG_SANCTUARY /*| UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5*/ ) << 8 ) ); // this flag is at uint8 offset 1 !!
}
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
DEBUG_LOG ( "-- VALUES_UPDATE: Sending '%s' the blue-group-fix from '%s' (faction %u)" , target -> GetName (), (( Player * ) this ) -> GetName (), faction );
* data << uint32 ( faction );
}
}
2009-05-24 12:56:09 -05:00
else
* data << m_uint32Values [ index ];
2009-01-15 21:29:32 -05:00
}
2009-05-24 12:56:09 -05:00
else
2009-01-15 21:29:32 -05: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)
* data << m_uint32Values [ index ];
}
}
}
}
else if ( isType ( TYPEMASK_GAMEOBJECT )) // gameobject case
{
2009-10-17 16:20:24 -07:00
for ( uint16 index = 0 ; index < m_valuesCount ; ++ index )
2008-10-11 14:16:25 -05:00
{
if ( updateMask -> GetBit ( index ) )
{
// send in current format (float as float, uint32 as uint32)
2009-05-23 10:08:35 -05:00
if ( index == GAMEOBJECT_DYNAMIC )
2008-10-11 14:16:25 -05:00
{
if ( IsActivateToQuest )
{
switch ((( GameObject * ) this ) -> GetGoType ())
{
case GAMEOBJECT_TYPE_CHEST :
2009-09-04 05:11:27 +02:00
// enable quest object. Represent 9, but 1 for client before 2.3.0
* data << uint16 ( 9 );
* data << uint16 ( - 1 );
2008-10-11 14:16:25 -05:00
break ;
case GAMEOBJECT_TYPE_GOOBER :
2009-09-04 05:11:27 +02:00
* data << uint16 ( 1 );
* data << uint16 ( - 1 );
2008-10-11 14:16:25 -05:00
break ;
default :
2009-09-04 05:11:27 +02:00
// unknown, not happen.
* data << uint16 ( 0 );
* data << uint16 ( - 1 );
2008-10-11 14:16:25 -05:00
break ;
}
}
else
2009-09-04 05:11:27 +02:00
{
// disable quest object
* data << uint16 ( 0 );
* data << uint16 ( - 1 );
}
2008-10-11 14:16:25 -05:00
}
else
2009-09-03 23:40:14 +02:00
* data << m_uint32Values [ index ]; // other cases
2008-10-11 14:16:25 -05:00
}
}
}
else // other objects case (no special index checks)
{
2009-10-17 16:20:24 -07:00
for ( uint16 index = 0 ; index < m_valuesCount ; ++ index )
2008-10-11 14:16:25 -05:00
{
if ( updateMask -> GetBit ( index ) )
{
// send in current format (float as float, uint32 as uint32)
* data << m_uint32Values [ index ];
}
}
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Object :: ClearUpdateMask ( bool remove )
{
2009-04-11 12:00:43 -05:00
memcpy ( m_uint32Values_mirror , m_uint32Values , m_valuesCount * sizeof ( uint32 ));
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( m_objectUpdated )
{
if ( remove )
ObjectAccessor :: Instance (). RemoveUpdateObject ( this );
m_objectUpdated = false ;
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bool Object :: LoadValues ( const char * data )
{
if ( ! m_uint32Values ) _InitValues ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Tokens tokens = StrSplit ( data , " " );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( tokens . size () != m_valuesCount )
return false ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Tokens :: iterator iter ;
int index ;
for ( iter = tokens . begin (), index = 0 ; index < m_valuesCount ; ++ iter , ++ index )
{
m_uint32Values [ index ] = atol (( * iter ). c_str ());
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return true ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Object :: _SetUpdateBits ( UpdateMask * updateMask , Player * /*target*/ ) const
{
2009-04-11 12:00:43 -05:00
uint32 * value = m_uint32Values ;
uint32 * mirror = m_uint32Values_mirror ;
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( uint16 index = 0 ; index < m_valuesCount ; ++ index , ++ value , ++ mirror )
2008-10-11 14:16:25 -05:00
{
2009-04-11 12:00:43 -05:00
if ( * mirror != * value )
2008-10-11 14:16:25 -05:00
updateMask -> SetBit ( index );
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Object :: _SetCreateBits ( UpdateMask * updateMask , Player * /*target*/ ) const
{
2009-04-11 12:00:43 -05:00
uint32 * value = m_uint32Values ;
2009-10-17 15:51:44 -07:00
2009-10-17 16:20:24 -07:00
for ( uint16 index = 0 ; index < m_valuesCount ; ++ index , ++ value )
2008-10-11 14:16:25 -05:00
{
2009-04-11 12:00:43 -05:00
if ( * value )
2008-10-11 14:16:25 -05:00
updateMask -> SetBit ( index );
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Object :: SetInt32Value ( uint16 index , int32 value )
{
2009-07-30 10:26:15 +08:00
ASSERT ( index < m_valuesCount || PrintIndexError ( index , true ) );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( m_int32Values [ index ] != value )
{
m_int32Values [ index ] = value ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( m_inWorld )
{
if ( ! m_objectUpdated )
{
ObjectAccessor :: Instance (). AddUpdateObject ( this );
m_objectUpdated = true ;
}
}
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Object :: SetUInt32Value ( uint16 index , uint32 value )
{
2009-07-30 10:26:15 +08:00
ASSERT ( index < m_valuesCount || PrintIndexError ( index , true ) );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( m_uint32Values [ index ] != value )
{
m_uint32Values [ index ] = value ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( m_inWorld )
{
if ( ! m_objectUpdated )
{
ObjectAccessor :: Instance (). AddUpdateObject ( this );
m_objectUpdated = true ;
}
}
}
}
2009-10-17 15:51:44 -07:00
2009-09-02 15:05:18 -05:00
void Object :: UpdateUInt32Value ( uint16 index , uint32 value )
{
ASSERT ( index < m_valuesCount || PrintIndexError ( index , true ) );
2009-10-17 15:51:44 -07:00
2009-09-02 15:05:18 -05:00
m_uint32Values [ index ] = value ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Object :: SetUInt64Value ( uint16 index , const uint64 & value )
{
2009-07-30 10:26:15 +08:00
ASSERT ( index + 1 < m_valuesCount || PrintIndexError ( index , true ) );
2008-10-11 14:16:25 -05:00
if ( * (( uint64 * ) & ( m_uint32Values [ index ])) != value )
{
m_uint32Values [ index ] = * (( uint32 * ) & value );
m_uint32Values [ index + 1 ] = * ((( uint32 * ) & value ) + 1 );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( m_inWorld )
{
if ( ! m_objectUpdated )
{
ObjectAccessor :: Instance (). AddUpdateObject ( this );
m_objectUpdated = true ;
}
}
}
}
2009-10-17 15:51:44 -07:00
2009-03-23 20:13:37 -06:00
bool Object :: AddUInt64Value ( uint16 index , const uint64 & value )
{
ASSERT ( index + 1 < m_valuesCount || PrintIndexError ( index , true ) );
if ( value && !* (( uint64 * ) & ( m_uint32Values [ index ])))
{
m_uint32Values [ index ] = * (( uint32 * ) & value );
m_uint32Values [ index + 1 ] = * ((( uint32 * ) & value ) + 1 );
2009-10-17 15:51:44 -07:00
2009-03-23 20:13:37 -06:00
if ( m_inWorld )
{
if ( ! m_objectUpdated )
{
ObjectAccessor :: Instance (). AddUpdateObject ( this );
m_objectUpdated = true ;
}
}
return true ;
}
return false ;
}
2009-10-17 15:51:44 -07:00
2009-03-23 20:13:37 -06:00
bool Object :: RemoveUInt64Value ( uint16 index , const uint64 & value )
{
ASSERT ( index + 1 < m_valuesCount || PrintIndexError ( index , true ) );
if ( value && * (( uint64 * ) & ( m_uint32Values [ index ])) == value )
{
m_uint32Values [ index ] = 0 ;
m_uint32Values [ index + 1 ] = 0 ;
2009-10-17 15:51:44 -07:00
2009-03-23 20:13:37 -06:00
if ( m_inWorld )
{
if ( ! m_objectUpdated )
{
ObjectAccessor :: Instance (). AddUpdateObject ( this );
m_objectUpdated = true ;
}
}
return true ;
}
return false ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Object :: SetFloatValue ( uint16 index , float value )
{
2009-07-30 10:26:15 +08:00
ASSERT ( index < m_valuesCount || PrintIndexError ( index , true ) );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( m_floatValues [ index ] != value )
{
m_floatValues [ index ] = value ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( m_inWorld )
{
if ( ! m_objectUpdated )
{
ObjectAccessor :: Instance (). AddUpdateObject ( this );
m_objectUpdated = true ;
}
}
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Object :: SetByteValue ( uint16 index , uint8 offset , uint8 value )
{
2009-07-30 10:26:15 +08:00
ASSERT ( index < m_valuesCount || PrintIndexError ( index , true ) );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( offset > 4 )
{
sLog . outError ( "Object::SetByteValue: wrong offset %u" , offset );
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( uint8 ( m_uint32Values [ index ] >> ( offset * 8 )) != value )
{
m_uint32Values [ index ] &= ~ uint32 ( uint32 ( 0xFF ) << ( offset * 8 ));
m_uint32Values [ index ] |= uint32 ( uint32 ( value ) << ( offset * 8 ));
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( m_inWorld )
{
if ( ! m_objectUpdated )
{
ObjectAccessor :: Instance (). AddUpdateObject ( this );
m_objectUpdated = true ;
}
}
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Object :: SetUInt16Value ( uint16 index , uint8 offset , uint16 value )
{
2009-07-30 10:26:15 +08:00
ASSERT ( index < m_valuesCount || PrintIndexError ( index , true ) );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( offset > 2 )
{
sLog . outError ( "Object::SetUInt16Value: wrong offset %u" , offset );
return ;
}
2009-10-17 15:51:44 -07:00
2009-06-11 00:45:59 -05:00
if ( uint16 ( m_uint32Values [ index ] >> ( offset * 16 )) != value )
2008-10-11 14:16:25 -05:00
{
m_uint32Values [ index ] &= ~ uint32 ( uint32 ( 0xFFFF ) << ( offset * 16 ));
m_uint32Values [ index ] |= uint32 ( uint32 ( value ) << ( offset * 16 ));
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( m_inWorld )
{
if ( ! m_objectUpdated )
{
ObjectAccessor :: Instance (). AddUpdateObject ( this );
m_objectUpdated = true ;
}
}
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Object :: SetStatFloatValue ( uint16 index , float value )
{
if ( value < 0 )
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
2008-10-11 14:16:25 -05:00
void Object :: SetStatInt32Value ( uint16 index , int32 value )
{
if ( value < 0 )
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 );
if ( cur < 0 )
cur = 0 ;
2009-05-31 15:56:51 -05:00
SetUInt32Value ( index , cur );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Object :: ApplyModInt32Value ( uint16 index , int32 val , bool apply )
{
int32 cur = GetInt32Value ( index );
cur += ( apply ? val : - val );
2009-05-31 15:56:51 -05:00
SetInt32Value ( index , cur );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Object :: ApplyModSignedFloatValue ( uint16 index , float val , bool apply )
{
float cur = GetFloatValue ( index );
cur += ( apply ? val : - val );
2009-05-31 15:56:51 -05:00
SetFloatValue ( index , cur );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Object :: ApplyModPositiveFloatValue ( uint16 index , float val , bool apply )
{
float cur = GetFloatValue ( index );
cur += ( apply ? val : - val );
if ( cur < 0 )
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
2008-10-11 14:16:25 -05:00
void Object :: SetFlag ( uint16 index , uint32 newFlag )
{
2009-07-30 10:26:15 +08:00
ASSERT ( index < m_valuesCount || PrintIndexError ( index , true ) );
2008-10-11 14:16:25 -05:00
uint32 oldval = m_uint32Values [ index ];
uint32 newval = oldval | newFlag ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( oldval != newval )
{
m_uint32Values [ index ] = newval ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( m_inWorld )
{
if ( ! m_objectUpdated )
{
ObjectAccessor :: Instance (). AddUpdateObject ( this );
m_objectUpdated = true ;
}
}
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Object :: RemoveFlag ( uint16 index , uint32 oldFlag )
{
2009-07-30 10:26:15 +08:00
ASSERT ( index < m_valuesCount || PrintIndexError ( index , true ) );
2008-10-11 14:16:25 -05:00
uint32 oldval = m_uint32Values [ index ];
uint32 newval = oldval & ~ oldFlag ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( oldval != newval )
{
m_uint32Values [ index ] = newval ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
if ( m_inWorld )
{
if ( ! m_objectUpdated )
{
ObjectAccessor :: Instance (). AddUpdateObject ( this );
m_objectUpdated = true ;
}
}
}
}
2009-10-17 15:51:44 -07:00
2008-12-12 11:21:28 -06:00
void Object :: SetByteFlag ( uint16 index , uint8 offset , uint8 newFlag )
{
2009-07-30 10:26:15 +08:00
ASSERT ( index < m_valuesCount || PrintIndexError ( index , true ) );
2009-10-17 15:51:44 -07:00
2008-12-12 11:21:28 -06:00
if ( offset > 4 )
{
sLog . outError ( "Object::SetByteFlag: wrong offset %u" , offset );
return ;
}
2009-10-17 15:51:44 -07:00
2008-12-12 11:21:28 -06:00
if ( ! ( uint8 ( m_uint32Values [ index ] >> ( offset * 8 )) & newFlag ))
{
m_uint32Values [ index ] |= uint32 ( uint32 ( newFlag ) << ( offset * 8 ));
2009-10-17 15:51:44 -07:00
2008-12-12 11:21:28 -06:00
if ( m_inWorld )
{
if ( ! m_objectUpdated )
{
ObjectAccessor :: Instance (). AddUpdateObject ( this );
m_objectUpdated = true ;
}
}
}
}
2009-10-17 15:51:44 -07:00
2008-12-12 11:21:28 -06:00
void Object :: RemoveByteFlag ( uint16 index , uint8 offset , uint8 oldFlag )
{
2009-07-30 10:26:15 +08:00
ASSERT ( index < m_valuesCount || PrintIndexError ( index , true ) );
2009-10-17 15:51:44 -07:00
2008-12-12 11:21:28 -06:00
if ( offset > 4 )
{
sLog . outError ( "Object::RemoveByteFlag: wrong offset %u" , offset );
return ;
}
2009-10-17 15:51:44 -07:00
2008-12-12 11:21:28 -06:00
if ( uint8 ( m_uint32Values [ index ] >> ( offset * 8 )) & oldFlag )
{
m_uint32Values [ index ] &= ~ uint32 ( uint32 ( oldFlag ) << ( offset * 8 ));
2009-10-17 15:51:44 -07:00
2008-12-12 11:21:28 -06:00
if ( m_inWorld )
{
if ( ! m_objectUpdated )
{
ObjectAccessor :: Instance (). AddUpdateObject ( this );
m_objectUpdated = true ;
}
}
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bool Object :: PrintIndexError ( uint32 index , bool set ) const
{
2009-03-21 14:28:02 -06:00
sLog . outError ( "Attempt %s non-existed value field: %u (count: %u) for object typeid: %u type mask: %u" ,( set ? "set value to" : "get value from" ), index , m_valuesCount , GetTypeId (), m_objectType );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// assert must fail after function call
return false ;
}
2009-10-17 15:51:44 -07:00
2009-08-29 23:20:16 -05:00
bool Position :: HasInLine ( const Unit * const target , float distance , float width ) const
2009-08-29 14:58:45 -05:00
{
if ( ! HasInArc ( M_PI , target ) || ! target -> IsWithinDist3d ( m_positionX , m_positionY , m_positionZ , distance )) return false ;
width += target -> GetObjectSize ();
float angle = GetRelativeAngle ( target );
return abs ( sin ( angle )) * GetExactDist2d ( target -> GetPositionX (), target -> GetPositionY ()) < width ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
WorldObject :: WorldObject ()
2009-08-29 14:58:45 -05:00
: WorldLocation (), m_InstanceId ( 0 ), m_phaseMask ( PHASEMASK_NORMAL ), m_currMap ( NULL )
2009-07-16 11:49:00 +08:00
, m_zoneScript ( NULL )
2009-08-11 16:14:45 -05:00
, m_isActive ( false ), m_isWorldObject ( false )
2009-05-30 22:15:05 -05:00
, m_name ( "" )
2009-12-19 10:12:40 +01:00
, m_notifyflags ( 0 ), m_executed_notifies ( 0 )
2008-10-11 14:16:25 -05:00
{
2008-10-27 08:41:55 -05:00
}
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
{
2009-02-26 16:29:55 -06:00
if ( ! IsInWorld ())
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
2009-02-25 20:52:20 -06:00
void WorldObject :: setActive ( bool on )
2008-10-27 08:41:55 -05:00
{
2009-03-25 21:32:34 -06:00
if ( m_isActive == on )
2008-10-27 08:41:55 -05:00
return ;
2009-10-17 15:51:44 -07:00
2009-02-26 16:29:55 -06: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
2009-03-25 21:32:34 -06:00
if ( ! IsInWorld ())
return ;
2009-10-17 15:51:44 -07:00
2009-03-25 21:32:34 -06:00
Map * map = FindMap ();
if ( ! map )
return ;
2009-10-17 15:51:44 -07:00
2009-03-25 21:32:34 -06:00
if ( on )
2009-02-25 20:52:20 -06:00
{
if ( GetTypeId () == TYPEID_UNIT )
2009-02-26 10:42:37 -06:00
map -> AddToActive (( Creature * ) this );
2009-02-25 20:52:20 -06: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
{
if ( GetTypeId () == TYPEID_UNIT )
map -> RemoveFromActive (( Creature * ) this );
else if ( GetTypeId () == TYPEID_DYNAMICOBJECT )
map -> RemoveFromActive (( DynamicObject * ) this );
}
2008-10-27 08:41:55 -05:00
}
2009-10-17 15:51:44 -07:00
2009-07-01 18:23:36 -05:00
void WorldObject :: CleanupsBeforeDelete ()
{
}
2009-10-17 15:51:44 -07:00
2009-07-16 11:49:00 +08:00
void WorldObject :: _Create ( uint32 guidlow , HighGuid guidhigh , uint32 phaseMask )
2008-10-11 14:16:25 -05:00
{
Object :: _Create ( guidlow , 0 , guidhigh );
2009-01-31 16:38:50 -06:00
m_phaseMask = phaseMask ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 WorldObject :: GetZoneId () const
{
2009-06-16 11:19:59 -05:00
return GetBaseMap () -> GetZoneId ( m_positionX , m_positionY , m_positionZ );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 WorldObject :: GetAreaId () const
{
2009-06-16 11:19:59 -05:00
return GetBaseMap () -> GetAreaId ( m_positionX , m_positionY , m_positionZ );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-03-11 16:17:37 -06:00
void WorldObject :: GetZoneAndAreaId ( uint32 & zoneid , uint32 & areaid ) const
{
2009-06-16 11:19:59 -05:00
GetBaseMap () -> GetZoneAndAreaId ( zoneid , areaid , m_positionX , m_positionY , m_positionZ );
2009-03-11 16:17:37 -06:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
InstanceData * WorldObject :: GetInstanceData ()
{
2008-12-24 09:58:26 -06:00
Map * map = GetMap ();
2008-10-11 14:16:25 -05:00
return map -> IsDungeon () ? (( InstanceMap * ) map ) -> GetInstanceData () : NULL ;
}
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 ;
return ( dist > 0 ? dist : 0 );
}
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
{
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 ;
if ( is3D )
{
float dz = GetPositionZ () - obj -> GetPositionZ ();
distsq += dz * dz ;
}
2008-10-11 14:16:25 -05:00
float sizefactor = GetObjectSize () + obj -> GetObjectSize ();
float maxdist = dist2compare + sizefactor ;
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
{
if ( ! IsInMap ( obj )) return false ;
float ox , oy , oz ;
obj -> GetPosition ( ox , oy , oz );
return ( IsWithinLOS ( ox , oy , oz ));
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
bool WorldObject :: IsWithinLOS ( float ox , float oy , float oz ) const
2008-10-11 14:16:25 -05:00
{
float x , y , z ;
GetPosition ( x , y , z );
VMAP :: IVMapManager * vMapManager = VMAP :: VMapFactory :: createOrGetVMapManager ();
return vMapManager -> isInLineOfSight ( GetMapId (), x , y , z + 2.0f , ox , oy , oz + 2.0f );
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
bool WorldObject :: GetDistanceOrder ( WorldObject const * obj1 , WorldObject const * obj2 , bool is3D /* = true */ ) const
{
float dx1 = GetPositionX () - obj1 -> GetPositionX ();
float dy1 = GetPositionY () - obj1 -> GetPositionY ();
float distsq1 = dx1 * dx1 + dy1 * dy1 ;
if ( is3D )
{
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 ;
if ( is3D )
{
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 ;
if ( is3D )
{
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
if ( minRange > 0.0f )
{
float mindist = minRange + sizefactor ;
if ( distsq < mindist * mindist )
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
if ( minRange > 0.0f )
{
float mindist = minRange + sizefactor ;
if ( distsq < mindist * mindist )
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
if ( minRange > 0.0f )
{
float mindist = minRange + sizefactor ;
if ( distsq < mindist * mindist )
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-08-29 14:58:45 -05:00
float Position :: GetAngle ( const Position * obj ) const
2008-10-11 14:16:25 -05:00
{
if ( ! obj ) return 0 ;
return GetAngle ( obj -> GetPositionX (), obj -> GetPositionY () );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// Return angle in range 0..2*pi
2009-08-29 14:58:45 -05: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
2009-03-23 15:26:13 -06:00
if ( dx < 0.001f && dy < 0.001f )
{
float angle = rand_norm () * 2 * M_PI ;
vcos = cos ( angle );
vsin = sin ( angle );
}
else
{
float dist = sqrt (( dx * dx ) + ( dy * dy ));
vcos = dx / dist ;
vsin = dy / dist ;
}
}
2009-10-17 15:51:44 -07:00
2009-08-29 14:58:45 -05:00
bool Position :: HasInArc ( float arc , const Position * obj ) const
2008-10-11 14:16:25 -05:00
{
2009-03-28 16:36:54 -06:00
// always have self in arc
if ( obj == this )
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
while ( arc >= 2.0f * M_PI )
arc -= 2.0f * M_PI ;
while ( arc < 0 )
arc += 2.0f * M_PI ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
float angle = GetAngle ( obj );
angle -= m_orientation ;
2009-10-17 15:51:44 -07:00
2009-05-29 12:08:06 -05:00
//if(angle > 100 || angle < -100)
//{
// sLog.outCrash("Invalid Angle %f: this %u %u %f %f %f %f, that %u %u %f %f %f %f", angle,
// GetEntry(), GetGUIDLow(), GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation(),
// obj->GetEntry(), obj->GetGUIDLow(), obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), obj->GetOrientation());
// assert(false);
// return false;
//}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// move angle to range -pi ... +pi
while ( angle > M_PI )
angle -= 2.0f * M_PI ;
while ( angle < - M_PI )
angle += 2.0f * M_PI ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
float lborder = - 1 * ( arc / 2.0f ); // in range -pi..0
float rborder = ( arc / 2.0f ); // in range 0..pi
return (( angle >= lborder ) && ( angle <= rborder ));
}
2009-10-17 15:51:44 -07:00
2009-05-09 10:50:41 -05:00
bool WorldObject :: IsInBetween ( const WorldObject * obj1 , const WorldObject * obj2 , float size ) const
{
if ( GetPositionX () > std :: max ( obj1 -> GetPositionX (), obj2 -> GetPositionX ())
|| GetPositionX () < std :: min ( obj1 -> GetPositionX (), obj2 -> GetPositionX ())
|| GetPositionY () > std :: max ( obj1 -> GetPositionY (), obj2 -> GetPositionY ())
|| GetPositionY () < std :: min ( obj1 -> GetPositionY (), obj2 -> GetPositionY ()))
return false ;
2009-10-17 15:51:44 -07:00
2009-05-09 10:50:41 -05:00
if ( ! size )
size = GetObjectSize () / 2 ;
2009-10-17 15:51:44 -07:00
2009-05-09 10:50:41 -05:00
float angle = obj1 -> GetAngle ( this ) - obj1 -> GetAngle ( obj2 );
2009-08-29 14:58:45 -05:00
return abs ( sin ( angle )) * GetExactDist2d ( obj1 -> GetPositionX (), obj1 -> GetPositionY ()) < size ;
2009-05-09 10:50:41 -05:00
}
2009-10-17 15:51:44 -07:00
2009-12-17 19:09:40 +01:00
bool WorldObject :: isInFront ( WorldObject const * target , float distance , float arc ) const
{
return IsWithinDist ( target , distance ) && HasInArc ( arc , target );
}
bool WorldObject :: isInBack ( WorldObject const * target , float distance , float arc ) const
{
return IsWithinDist ( target , distance ) && ! HasInArc ( 2 * M_PI - arc , target );
}
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
{
2009-08-29 23:20:16 -05: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`
float angle = rand_norm () * 2 * M_PI ;
float new_dist = rand_norm () * distance ;
2009-10-17 15:51:44 -07:00
2009-08-29 23:20:16 -05:00
rand_x = pos . m_positionX + new_dist * cos ( angle );
rand_y = pos . m_positionY + new_dist * sin ( angle );
rand_z = pos . m_positionZ ;
2009-10-17 15:51:44 -07:00
2008-10-14 11:57:03 -05:00
Trinity :: NormalizeMapCoord ( rand_x );
Trinity :: NormalizeMapCoord ( rand_y );
2008-10-11 14:16:25 -05:00
UpdateGroundPositionZ ( rand_x , rand_y , rand_z ); // update to LOS height if available
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void WorldObject :: UpdateGroundPositionZ ( float x , float y , float & z ) const
{
2009-06-16 11:19:59 -05:00
float new_z = GetBaseMap () -> GetHeight ( x , y , z , true );
2008-10-11 14:16:25 -05:00
if ( new_z > INVALID_HEIGHT )
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
2009-08-29 14:58:45 -05:00
bool Position :: IsPositionValid () const
2008-10-11 14:16:25 -05:00
{
2008-10-14 11:57:03 -05: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
2008-10-11 14:16:25 -05:00
void WorldObject :: MonsterSay ( const char * text , uint32 language , uint64 TargetGuid )
{
WorldPacket data ( SMSG_MESSAGECHAT , 200 );
BuildMonsterChat ( & data , CHAT_MSG_MONSTER_SAY , text , language , GetName (), TargetGuid );
SendMessageToSetInRange ( & data , sWorld . getConfig ( CONFIG_LISTEN_RANGE_SAY ), true );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void WorldObject :: MonsterYell ( const char * text , uint32 language , uint64 TargetGuid )
{
WorldPacket data ( SMSG_MESSAGECHAT , 200 );
BuildMonsterChat ( & data , CHAT_MSG_MONSTER_YELL , text , language , GetName (), TargetGuid );
SendMessageToSetInRange ( & data , sWorld . getConfig ( CONFIG_LISTEN_RANGE_YELL ), true );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05: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 . getConfig ( CONFIG_LISTEN_RANGE_TEXTEMOTE ), true );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void WorldObject :: MonsterWhisper ( const char * text , uint64 receiver , bool IsBossWhisper )
{
Player * player = objmgr . GetPlayer ( receiver );
if ( ! player || ! player -> GetSession ())
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
WorldPacket data ( SMSG_MESSAGECHAT , 200 );
BuildMonsterChat ( & data , IsBossWhisper ? CHAT_MSG_RAID_BOSS_WHISPER : CHAT_MSG_MONSTER_WHISPER , text , LANG_UNIVERSAL , GetName (), 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
2008-10-11 14:16:25 -05:00
void WorldObject :: SendPlaySound ( uint32 Sound , bool OnlySelf )
{
WorldPacket data ( SMSG_PLAY_SOUND , 4 );
data << Sound ;
2009-10-31 16:00:47 -07:00
if ( OnlySelf && GetTypeId () == TYPEID_PLAYER )
2008-10-11 14:16:25 -05:00
(( Player * ) this ) -> GetSession () -> SendPacket ( & data );
else
SendMessageToSet ( & data , true ); // ToSelf ignored in this case
}
2009-10-17 15:51:44 -07:00
2009-01-15 21:29:32 -05:00
void Object :: ForceValuesUpdateAtIndex ( uint32 i )
{
m_uint32Values_mirror [ i ] = GetUInt32Value ( i ) + 1 ; // makes server think the field changed
if ( m_inWorld )
2009-03-31 09:18:39 -06:00
{
2009-01-15 21:29:32 -05:00
if ( ! m_objectUpdated )
2009-03-31 09:18:39 -06:00
{
2009-01-15 21:29:32 -05:00
ObjectAccessor :: Instance (). 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 ) {}
void operator ()( WorldPacket & data , int32 loc_idx )
2008-10-11 14:16:25 -05:00
{
2009-02-21 17:00:47 -06:00
char const * text = objmgr . GetMangosString ( i_textId , loc_idx );
2009-10-17 15:51:44 -07:00
2009-02-21 17:00:47 -06:00
// TODO: i_object.GetName() also must be localized?
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 ;
};
2008-10-14 11:57:03 -05:00
} // namespace Trinity
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void WorldObject :: MonsterSay ( int32 textId , uint32 language , uint64 TargetGuid )
{
2008-10-14 11:57:03 -05:00
CellPair p = Trinity :: ComputeCellPair ( GetPositionX (), GetPositionY ());
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Cell cell ( p );
cell . data . Part . reserved = ALL_DISTRICT ;
cell . SetNoCreate ();
2009-10-17 15:51:44 -07:00
2009-02-21 17:00:47 -06:00
MaNGOS :: MonsterChatBuilder say_build ( * this , CHAT_MSG_MONSTER_SAY , textId , language , TargetGuid );
MaNGOS :: LocalizedPacketDo < MaNGOS :: MonsterChatBuilder > say_do ( say_build );
MaNGOS :: PlayerDistWorker < MaNGOS :: LocalizedPacketDo < MaNGOS :: MonsterChatBuilder > > say_worker ( this , sWorld . getConfig ( CONFIG_LISTEN_RANGE_SAY ), say_do );
TypeContainerVisitor < MaNGOS :: PlayerDistWorker < MaNGOS :: LocalizedPacketDo < MaNGOS :: MonsterChatBuilder > > , WorldTypeMapContainer > message ( say_worker );
2008-10-11 14:16:25 -05:00
CellLock < GridReadGuard > cell_lock ( cell , p );
2009-09-27 02:24:25 -07:00
cell_lock -> Visit ( cell_lock , message , * GetMap (), * this , sWorld . getConfig ( CONFIG_LISTEN_RANGE_SAY ));
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 :: MonsterYell ( int32 textId , uint32 language , uint64 TargetGuid )
{
2008-10-14 11:57:03 -05:00
CellPair p = Trinity :: ComputeCellPair ( GetPositionX (), GetPositionY ());
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Cell cell ( p );
cell . data . Part . reserved = ALL_DISTRICT ;
cell . SetNoCreate ();
2009-10-17 15:51:44 -07:00
2009-02-21 17:00:47 -06:00
MaNGOS :: MonsterChatBuilder say_build ( * this , CHAT_MSG_MONSTER_YELL , textId , language , TargetGuid );
MaNGOS :: LocalizedPacketDo < MaNGOS :: MonsterChatBuilder > say_do ( say_build );
MaNGOS :: PlayerDistWorker < MaNGOS :: LocalizedPacketDo < MaNGOS :: MonsterChatBuilder > > say_worker ( this , sWorld . getConfig ( CONFIG_LISTEN_RANGE_YELL ), say_do );
TypeContainerVisitor < MaNGOS :: PlayerDistWorker < MaNGOS :: LocalizedPacketDo < MaNGOS :: MonsterChatBuilder > > , WorldTypeMapContainer > message ( say_worker );
2008-10-11 14:16:25 -05:00
CellLock < GridReadGuard > cell_lock ( cell , p );
2009-09-27 02:24:25 -07:00
cell_lock -> Visit ( cell_lock , message , * GetMap (), * this , sWorld . getConfig ( 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 )
{
2009-03-29 17:15:37 -06:00
MaNGOS :: MonsterChatBuilder say_build ( * this , CHAT_MSG_MONSTER_YELL , textId , language , TargetGuid );
MaNGOS :: LocalizedPacketDo < MaNGOS :: 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 )
2009-03-29 17:15:37 -06:00
if ( itr -> getSource () -> GetZoneId () == zoneid )
say_do ( itr -> getSource ());
2009-03-28 18:03:56 -06:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void WorldObject :: MonsterTextEmote ( int32 textId , uint64 TargetGuid , bool IsBossEmote )
{
2008-10-14 11:57:03 -05:00
CellPair p = Trinity :: ComputeCellPair ( GetPositionX (), GetPositionY ());
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Cell cell ( p );
cell . data . Part . reserved = ALL_DISTRICT ;
cell . SetNoCreate ();
2009-10-17 15:51:44 -07:00
2009-02-21 17:00:47 -06:00
MaNGOS :: MonsterChatBuilder say_build ( * this , IsBossEmote ? CHAT_MSG_RAID_BOSS_EMOTE : CHAT_MSG_MONSTER_EMOTE , textId , LANG_UNIVERSAL , TargetGuid );
MaNGOS :: LocalizedPacketDo < MaNGOS :: MonsterChatBuilder > say_do ( say_build );
MaNGOS :: PlayerDistWorker < MaNGOS :: LocalizedPacketDo < MaNGOS :: MonsterChatBuilder > > say_worker ( this , sWorld . getConfig ( CONFIG_LISTEN_RANGE_TEXTEMOTE ), say_do );
TypeContainerVisitor < MaNGOS :: PlayerDistWorker < MaNGOS :: LocalizedPacketDo < MaNGOS :: MonsterChatBuilder > > , WorldTypeMapContainer > message ( say_worker );
2008-10-11 14:16:25 -05:00
CellLock < GridReadGuard > cell_lock ( cell , p );
2009-09-27 02:24:25 -07:00
cell_lock -> Visit ( cell_lock , message , * GetMap (), * this , sWorld . getConfig ( CONFIG_LISTEN_RANGE_TEXTEMOTE ));
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 :: MonsterWhisper ( int32 textId , uint64 receiver , bool IsBossWhisper )
{
Player * player = objmgr . GetPlayer ( receiver );
if ( ! player || ! player -> GetSession ())
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 loc_idx = player -> GetSession () -> GetSessionDbLocaleIndex ();
2008-10-14 11:57:03 -05:00
char const * text = objmgr . 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 );
2009-02-20 15:20:14 -06: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
2008-10-11 14:16:25 -05:00
void WorldObject :: BuildMonsterChat ( WorldPacket * data , uint8 msgtype , char const * text , uint32 language , char const * name , uint64 targetGuid ) const
{
* data << ( uint8 ) msgtype ;
* data << ( uint32 ) language ;
* data << ( uint64 ) GetGUID ();
2009-05-31 15:56:51 -05:00
* data << ( uint32 ) 0 ; // 2.1.0
2008-10-11 14:16:25 -05:00
* data << ( uint32 )( strlen ( name ) + 1 );
* data << name ;
2009-05-31 15:56:51 -05:00
* data << ( uint64 ) targetGuid ; // Unit Target
2008-10-11 14:16:25 -05:00
if ( targetGuid && ! IS_PLAYER_GUID ( targetGuid ) )
{
* data << ( uint32 ) 1 ; // target name length
* data << ( uint8 ) 0 ; // target name
}
2009-07-20 11:53:26 +08:00
* data << ( uint32 )( strlen ( text ) + 1 );
2008-10-11 14:16:25 -05:00
* data << text ;
* data << ( uint8 ) 0 ; // ChatTag
}
2009-10-17 15:51:44 -07:00
2009-06-13 09:18:54 -05:00
void Unit :: BuildHeartBeatMsg ( WorldPacket * data ) const
2008-10-11 14:16:25 -05:00
{
data -> Initialize ( MSG_MOVE_HEARTBEAT , 32 );
data -> append ( GetPackGUID ());
2009-06-13 09:18:54 -05:00
BuildMovementPacket ( data );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-05-27 09:09:22 -05:00
void WorldObject :: SendMessageToSet ( WorldPacket * data , bool /*fake*/ )
2008-10-11 14:16:25 -05:00
{
2009-09-27 02:24:25 -07:00
Trinity :: MessageDistDeliverer notifier ( this , data , GetMap () -> GetVisibilityDistance ());
VisitNearbyWorldObject ( GetMap () -> GetVisibilityDistance (), notifier );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-05-27 09:09:22 -05:00
void WorldObject :: SendMessageToSetInRange ( WorldPacket * data , float dist , bool /*bToSelf*/ )
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
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
2009-07-16 11:49:00 +08: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 );
2009-08-12 13:03:44 -05:00
if ( m_currMap == map ) // command add npc: first create, than loadfromdb
return ;
2009-08-26 19:35:20 -05:00
if ( m_currMap )
{
sLog . outCrash ( "WorldObject::SetMap: obj %u new map %u %u, old map %u %u" , ( uint32 ) GetTypeId (), map -> GetId (), map -> GetInstanceId (), m_currMap -> GetId (), m_currMap -> GetInstanceId ());
assert ( false );
}
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 ();
2009-08-11 16:33:33 -05:00
if ( m_isWorldObject )
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 ());
2009-08-11 16:33:33 -05:00
if ( m_isWorldObject )
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 ()
{
2009-04-08 17:23:57 -05:00
assert ( m_uint32Values );
2009-10-17 15:51:44 -07:00
2009-04-08 17:23:57 -05:00
Map * map = FindMap ();
2008-10-11 14:16:25 -05:00
if ( ! map )
{
sLog . outError ( "Object (TypeId: %u Entry: %u GUID: %u) at attempt add to move list not have valid map (Id: %u)." , GetTypeId (), GetEntry (), GetGUIDLow (), GetMapId ());
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
2009-08-29 14:58:45 -05:00
TempSummon * Map :: SummonCreature ( uint32 entry , const Position & pos , SummonPropertiesEntry const * properties , uint32 duration , Unit * summoner , uint32 vehId )
2008-10-11 14:16:25 -05:00
{
2009-08-23 22:09:43 -05:00
uint32 mask = UNIT_MASK_SUMMON ;
2009-03-20 14:01:46 -06:00
if ( properties )
{
2009-08-26 19:28:21 -05:00
switch ( properties -> Category )
{
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 ;
default :
switch ( properties -> Type )
{
case SUMMON_TYPE_MINION :
case SUMMON_TYPE_GUARDIAN :
2009-12-14 01:51:12 +01:00
case SUMMON_TYPE_GUARDIAN2 :
2009-08-26 19:28:21 -05:00
mask = UNIT_MASK_GUARDIAN ; break ;
case SUMMON_TYPE_TOTEM :
mask = UNIT_MASK_TOTEM ; break ;
case SUMMON_TYPE_VEHICLE :
case SUMMON_TYPE_VEHICLE2 :
mask = UNIT_MASK_SUMMON ; break ;
case SUMMON_TYPE_MINIPET :
mask = UNIT_MASK_MINION ; break ;
default :
if ( properties -> Flags & 512 ) // Mirror Image, Summon Gargoyle
mask = UNIT_MASK_GUARDIAN ;
break ;
}
break ;
}
2009-03-20 14:01:46 -06:00
}
2009-10-17 15:51:44 -07:00
2009-03-20 14:01:46 -06:00
uint32 phase = PHASEMASK_NORMAL , team = 0 ;
if ( summoner )
{
phase = summoner -> GetPhaseMask ();
if ( summoner -> GetTypeId () == TYPEID_PLAYER )
team = (( Player * ) summoner ) -> GetTeam ();
}
2009-10-17 15:51:44 -07:00
2009-03-21 09:48:44 -06:00
TempSummon * summon = NULL ;
2009-03-20 14:01:46 -06:00
switch ( mask )
2008-10-11 14:16:25 -05:00
{
2009-08-23 22:09:43 -05:00
case UNIT_MASK_SUMMON : summon = new TempSummon ( properties , summoner ); break ;
case UNIT_MASK_GUARDIAN : summon = new Guardian ( properties , summoner ); 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 : summon = new Minion ( properties , summoner ); break ;
2009-03-21 09:48:44 -06:00
default : return NULL ;
2009-03-20 14:01:46 -06:00
}
2009-10-17 15:51:44 -07:00
2009-08-29 14:58:45 -05:00
if ( ! summon -> Create ( objmgr . 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
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 );
2009-03-20 14:01:46 -06:00
Add (( Creature * ) summon );
2009-05-06 13:34:11 -05:00
summon -> InitSummon ();
2009-10-17 15:51:44 -07:00
2009-05-03 11:06:48 -05:00
//ObjectAccessor::UpdateObjectVisibility(summon);
2009-10-17 15:51:44 -07:00
2009-03-20 14:01:46 -06:00
return summon ;
}
2009-10-17 15:51:44 -07:00
2009-05-30 22:15:05 -05:00
void WorldObject :: SetZoneScript ()
{
if ( Map * map = FindMap ())
{
if ( map -> IsDungeon ())
m_zoneScript = ( ZoneScript * )(( InstanceMap * ) map ) -> GetInstanceData ();
else if ( ! map -> IsBattleGroundOrArena ())
m_zoneScript = sOutdoorPvPMgr . GetZoneScript ( GetZoneId ());
}
}
2009-10-17 15:51:44 -07:00
2009-08-29 14:58:45 -05:00
TempSummon * WorldObject :: SummonCreature ( uint32 entry , const Position & pos , TempSummonType spwtype , uint32 duration , uint32 vehId ) const
2009-03-20 14:01:46 -06:00
{
2009-08-29 14:58:45 -05:00
if ( Map * map = FindMap ())
{
if ( TempSummon * summon = map -> SummonCreature ( entry , pos , NULL , duration , isType ( TYPEMASK_UNIT ) ? ( Unit * ) this : NULL ))
{
summon -> SetTempSummonType ( spwtype );
return summon ;
}
}
2009-10-17 15:51:44 -07:00
2009-08-29 14:58:45 -05:00
return NULL ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-02-19 18:30:03 -06:00
Pet * Player :: SummonPet ( uint32 entry , float x , float y , float z , float ang , PetType petType , uint32 duration )
{
2009-03-25 21:32:34 -06:00
Pet * pet = new Pet ( this , petType );
2009-10-17 15:51:44 -07:00
2009-02-24 20:05:29 -06:00
if ( petType == SUMMON_PET && pet -> LoadPetFromDB ( this , entry ))
{
2009-02-24 20:52:55 -06:00
// Remove Demonic Sacrifice auras (known pet)
2009-04-06 13:31:14 +02:00
Unit :: AuraEffectList const & auraClassScripts = GetAurasByType ( SPELL_AURA_OVERRIDE_CLASS_SCRIPTS );
2009-11-20 19:11:28 -08:00
for ( Unit :: AuraEffectList :: const_iterator itr = auraClassScripts . begin (); itr != auraClassScripts . end ();)
2009-02-24 20:52:55 -06:00
{
2009-04-06 13:31:14 +02:00
if (( * itr ) -> GetMiscValue () == 2228 )
2009-02-24 20:52:55 -06:00
{
RemoveAurasDueToSpell (( * itr ) -> GetId ());
itr = auraClassScripts . begin ();
}
else
++ itr ;
}
2009-10-17 15:51:44 -07:00
2009-02-24 20:05:29 -06:00
if ( duration > 0 )
pet -> SetDuration ( duration );
2009-10-17 15:51:44 -07:00
2009-02-24 20:52:55 -06:00
return NULL ;
}
2009-10-17 15:51:44 -07:00
2009-02-24 20:52:55 -06:00
// petentry==0 for hunter "call pet" (current pet summoned if any)
if ( ! entry )
{
delete pet ;
2009-02-24 20:05:29 -06:00
return NULL ;
}
2009-10-17 15:51:44 -07:00
2009-08-26 19:28:21 -05:00
pet -> Relocate ( x , y , z , ang );
if ( ! pet -> IsPositionValid ())
2009-02-19 18:30:03 -06:00
{
2009-08-26 19:28:21 -05:00
sLog . outError ( "ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)" , pet -> GetGUIDLow (), pet -> GetEntry (), pet -> GetPositionX (), pet -> GetPositionY ());
2009-02-24 20:05:29 -06:00
delete pet ;
2009-02-19 18:30:03 -06:00
return NULL ;
}
2009-10-17 15:51:44 -07:00
2009-08-26 19:28:21 -05:00
Map * map = GetMap ();
uint32 pet_number = objmgr . GeneratePetNumber ();
if ( ! pet -> Create ( objmgr . GenerateLowGuid ( HIGHGUID_PET ), map , GetPhaseMask (), entry , pet_number ))
2009-02-19 18:30:03 -06:00
{
2009-08-26 19:28:21 -05:00
sLog . outError ( "no such creature entry %u" , entry );
2009-02-24 20:05:29 -06:00
delete pet ;
2009-02-19 18:30:03 -06:00
return NULL ;
}
2009-10-17 15:51:44 -07:00
2009-02-24 20:05:29 -06:00
pet -> SetCreatorGUID ( GetGUID ());
pet -> SetUInt32Value ( UNIT_FIELD_FACTIONTEMPLATE , getFaction ());
2009-10-17 15:51:44 -07:00
2009-02-24 20:52:55 -06:00
pet -> setPowerType ( POWER_MANA );
pet -> SetUInt32Value ( UNIT_NPC_FLAGS , 0 );
pet -> SetUInt32Value ( UNIT_FIELD_BYTES_1 , 0 );
pet -> InitStatsForLevel ( getLevel ());
2009-10-17 15:51:44 -07:00
2009-05-02 19:24:22 -05:00
SetMinion ( pet , true );
2009-10-17 15:51:44 -07:00
2009-02-24 20:05:29 -06:00
switch ( petType )
{
2009-02-24 20:52:55 -06:00
case SUMMON_PET :
2009-05-24 12:28:26 -05:00
// this enables pet details window (Shift+P)
pet -> GetCharmInfo () -> SetPetNumber ( pet_number , true );
2009-02-24 20:52:55 -06:00
pet -> SetUInt32Value ( UNIT_FIELD_BYTES_0 , 2048 );
pet -> SetUInt32Value ( UNIT_FIELD_PETEXPERIENCE , 0 );
pet -> SetUInt32Value ( UNIT_FIELD_PETNEXTLEVELEXP , 1000 );
pet -> SetHealth ( pet -> GetMaxHealth ());
pet -> SetPower ( POWER_MANA , pet -> GetMaxPower ( POWER_MANA ));
2009-05-08 17:15:19 -05:00
pet -> SetUInt32Value ( UNIT_FIELD_PET_NAME_TIMESTAMP , time ( NULL ));
2009-05-06 13:34:11 -05:00
break ;
}
2009-10-17 15:51:44 -07:00
2009-05-06 13:34:11 -05:00
map -> Add (( Creature * ) pet );
2009-10-17 15:51:44 -07:00
2009-05-06 13:34:11 -05:00
switch ( petType )
{
case SUMMON_PET :
2009-02-24 20:52:55 -06:00
pet -> InitPetCreateSpells ();
2009-05-08 17:15:19 -05:00
pet -> InitTalentForLevel ();
2009-02-24 20:52:55 -06:00
pet -> SavePetToDB ( PET_SAVE_AS_CURRENT );
PetSpellInitialize ();
break ;
}
2009-10-17 15:51:44 -07:00
2009-02-24 20:52:55 -06:00
if ( petType == SUMMON_PET )
{
// Remove Demonic Sacrifice auras (known pet)
2009-04-06 13:31:14 +02:00
Unit :: AuraEffectList const & auraClassScripts = GetAurasByType ( SPELL_AURA_OVERRIDE_CLASS_SCRIPTS );
2009-11-20 19:11:28 -08:00
for ( Unit :: AuraEffectList :: const_iterator itr = auraClassScripts . begin (); itr != auraClassScripts . end ();)
2009-02-24 20:52:55 -06:00
{
2009-04-06 13:31:14 +02:00
if (( * itr ) -> GetMiscValue () == 2228 )
2009-02-24 20:52:55 -06:00
{
RemoveAurasDueToSpell (( * itr ) -> GetId ());
itr = auraClassScripts . begin ();
}
else
++ itr ;
}
2009-02-24 20:05:29 -06:00
}
2009-10-17 15:51:44 -07:00
2009-02-24 20:52:55 -06:00
if ( duration > 0 )
pet -> SetDuration ( duration );
2009-10-17 15:51:44 -07:00
2009-05-03 11:06:48 -05:00
//ObjectAccessor::UpdateObjectVisibility(pet);
2009-10-17 15:51:44 -07:00
2009-02-24 20:05:29 -06:00
return pet ;
2009-02-19 18:30:03 -06:00
}
2009-10-17 15:51:44 -07:00
2008-10-17 18:13:04 -05:00
GameObject * WorldObject :: SummonGameObject ( uint32 entry , float x , float y , float z , float ang , float rotation0 , float rotation1 , float rotation2 , float rotation3 , uint32 respawnTime )
{
if ( ! IsInWorld ())
return NULL ;
2009-10-17 15:51:44 -07:00
2008-10-17 18:13:04 -05:00
GameObjectInfo const * goinfo = objmgr . GetGameObjectInfo ( entry );
if ( ! goinfo )
{
sLog . outErrorDb ( "Gameobject template %u not found in database!" , entry );
return NULL ;
}
2009-01-31 16:38:50 -06:00
Map * map = GetMap ();
2008-10-17 18:13:04 -05:00
GameObject * go = new GameObject ();
2009-04-27 18:36:10 -05:00
if ( ! go -> Create ( objmgr . GenerateLowGuid ( HIGHGUID_GAMEOBJECT ), entry , map , GetPhaseMask (), x , y , z , ang , rotation0 , rotation1 , rotation2 , rotation3 , 100 , GO_STATE_READY ))
2009-04-01 21:17:59 -06:00
{
delete go ;
2008-10-17 18:13:04 -05:00
return NULL ;
2009-04-01 21:17:59 -06:00
}
2008-10-17 18:13:04 -05:00
go -> SetRespawnTime ( respawnTime );
2009-11-20 19:11:28 -08:00
if ( GetTypeId () == TYPEID_PLAYER || GetTypeId () == TYPEID_UNIT ) //not sure how to handle this
2008-10-18 19:59:34 -05:00
(( Unit * ) this ) -> AddGameObject ( go );
else
go -> SetSpawnedByDefault ( false );
2008-10-17 18:13:04 -05:00
map -> Add ( go );
2009-10-17 15:51:44 -07:00
2008-10-17 18:13:04 -05:00
return go ;
}
2009-10-17 15:51:44 -07:00
2008-12-10 20:25:47 -06:00
Creature * WorldObject :: SummonTrigger ( float x , float y , float z , float ang , uint32 duration , CreatureAI * ( * GetAI )( Creature * ))
{
TempSummonType summonType = ( duration == 0 ) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN ;
2008-12-15 15:38:02 -06:00
Creature * summon = SummonCreature ( WORLD_TRIGGER , x , y , z , ang , summonType , duration );
2008-12-10 20:25:47 -06:00
if ( ! summon )
return NULL ;
2009-10-17 15:51:44 -07:00
2008-12-10 20:25:47 -06:00
//summon->SetName(GetName());
2009-11-20 19:11:28 -08: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
2008-12-10 20:25:47 -06:00
if ( GetAI )
summon -> AIM_Initialize ( GetAI ( summon ));
return summon ;
}
2009-10-17 15:51:44 -07:00
2009-12-17 11:40:23 +01:00
Creature * WorldObject :: FindNearestCreature ( uint32 entry , float range , bool alive )
2009-05-29 16:49:28 -05:00
{
2009-12-17 11:40:23 +01:00
Creature * creature = NULL ;
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
2009-12-17 11:40:23 +01:00
GameObject * WorldObject :: FindNearestGameObject ( uint32 entry , float range )
2009-05-29 16:49:28 -05:00
{
2009-12-17 11:40:23 +01:00
GameObject * go = NULL ;
Trinity :: NearestGameObjectEntryInObjectRangeCheck checker ( * this , entry , range );
Trinity :: GameObjectLastSearcher < Trinity :: NearestGameObjectEntryInObjectRangeCheck > searcher ( this , go , checker );
VisitNearbyGridObject ( range , searcher );
return go ;
}
void WorldObject :: GetGameObjectListWithEntryInGrid ( std :: list < GameObject *>& lList , uint32 uiEntry , float fMaxSearchRange )
{
CellPair pair ( Trinity :: ComputeCellPair ( this -> GetPositionX (), this -> GetPositionY ()));
Cell cell ( pair );
cell . data . Part . reserved = ALL_DISTRICT ;
cell . SetNoCreate ();
Trinity :: AllGameObjectsWithEntryInRange check ( this , uiEntry , fMaxSearchRange );
Trinity :: GameObjectListSearcher < Trinity :: AllGameObjectsWithEntryInRange > searcher ( this , lList , check );
TypeContainerVisitor < Trinity :: GameObjectListSearcher < Trinity :: AllGameObjectsWithEntryInRange > , GridTypeMapContainer > visitor ( searcher );
CellLock < GridReadGuard > cell_lock ( cell , pair );
cell_lock -> Visit ( cell_lock , visitor , * ( this -> GetMap ()));
2009-07-24 05:27:49 +02:00
}
2009-10-17 15:51:44 -07:00
2009-07-24 05:27:49 +02:00
void WorldObject :: GetCreatureListWithEntryInGrid ( std :: list < Creature *>& lList , uint32 uiEntry , float fMaxSearchRange )
{
2009-12-17 11:40:23 +01:00
CellPair pair ( Trinity :: ComputeCellPair ( this -> GetPositionX (), this -> GetPositionY ()));
Cell cell ( pair );
cell . data . Part . reserved = ALL_DISTRICT ;
cell . SetNoCreate ();
2009-07-24 05:27:49 +02:00
Trinity :: AllCreaturesOfEntryInRange check ( this , uiEntry , fMaxSearchRange );
Trinity :: CreatureListSearcher < Trinity :: AllCreaturesOfEntryInRange > searcher ( this , lList , check );
TypeContainerVisitor < Trinity :: CreatureListSearcher < Trinity :: AllCreaturesOfEntryInRange > , GridTypeMapContainer > visitor ( searcher );
2009-10-17 15:51:44 -07:00
2009-12-17 11:40:23 +01:00
CellLock < GridReadGuard > cell_lock ( cell , pair );
cell_lock -> Visit ( cell_lock , visitor , * ( this -> GetMap ()));
2009-07-24 05:27:49 +02:00
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
/*
namespace MaNGOS
{
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
if(c==i_searcher || c==&i_object)
return;
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
float x,y,z;
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
if( !c->isAlive() || c->hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED) ||
!c->GetMotionMaster()->GetDestination(x,y,z) )
{
x = c->GetPositionX();
y = c->GetPositionY();
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
add(c,x,y);
}
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
if(u==i_searcher || u==&i_object)
return;
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05: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
2009-05-14 16:50:47 -05:00
add(u,x,y);
}
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
if(!i_object.IsInRange2d(x,y,i_selector.m_dist - i_selector.m_size,i_selector.m_dist + i_selector.m_size))
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
while( angle > M_PI)
angle -= 2.0f * M_PI;
while(angle < -M_PI)
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
float dist2d = i_object.GetDistance2d(x,y);
i_selector.AddUsedPos(u->GetObjectSize(),angle,dist2d + i_object.GetObjectSize());
}
private:
WorldObject const& i_object;
WorldObject const* i_searcher;
float i_angle;
ObjectPosSelector& i_selector;
};
} // namespace MaNGOS
*/
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
//===================================================================================================
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void WorldObject :: GetNearPoint2D ( float & x , float & y , float distance2d , float absAngle ) const
{
x = GetPositionX () + ( GetObjectSize () + distance2d ) * cos ( absAngle );
y = GetPositionY () + ( GetObjectSize () + distance2d ) * sin ( absAngle );
2009-10-17 15:51:44 -07:00
2008-10-14 11:57:03 -05:00
Trinity :: NormalizeMapCoord ( x );
Trinity :: NormalizeMapCoord ( y );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void WorldObject :: GetNearPoint ( WorldObject const * searcher , float & x , float & y , float & z , float searcher_size , float distance2d , float absAngle ) const
{
GetNearPoint2D ( x , y , distance2d + searcher_size , absAngle );
2009-02-09 08:16:34 -05:00
z = GetPositionZ ();
UpdateGroundPositionZ ( 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
if(!sWorld.getConfig(CONFIG_DETECT_POS_COLLISION))
{
UpdateGroundPositionZ(x,y,z); // update to LOS height if available
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
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
{
CellPair p(MaNGOS::ComputeCellPair(GetPositionX(), GetPositionY()));
Cell cell(p);
cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate();
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
MaNGOS::NearUsedPosDo u_do(*this,searcher,absAngle,selector);
MaNGOS::WorldObjectWorker<MaNGOS::NearUsedPosDo> worker(this,u_do);
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
TypeContainerVisitor<MaNGOS::WorldObjectWorker<MaNGOS::NearUsedPosDo>, GridTypeMapContainer > grid_obj_worker(worker);
TypeContainerVisitor<MaNGOS::WorldObjectWorker<MaNGOS::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
if( selector.CheckOriginal() )
{
UpdateGroundPositionZ(x,y,z); // update to LOS height if available
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
if(IsWithinLOS(x,y,z))
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
if(selector.FirstAngle(angle))
{
GetNearPoint2D(x,y,distance2d,absAngle+angle);
z = GetPositionZ();
UpdateGroundPositionZ(x,y,z); // update to LOS height if available
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
if(IsWithinLOS(x,y,z))
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)
while(selector.NextAngle(angle)) // angle for free pos
{
GetNearPoint2D(x,y,distance2d,absAngle+angle);
z = GetPositionZ();
UpdateGroundPositionZ(x,y,z); // update to LOS height if available
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
if(IsWithinLOS(x,y,z))
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
2009-05-14 16:50:47 -05:00
if(!first_los_conflict)
{
x = first_x;
y = first_y;
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
UpdateGroundPositionZ(x,y,z); // update to LOS height if available
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
if( selector.IsNonBalanced() )
{
if(!selector.FirstAngle(angle)) // _used_ pos
{
GetNearPoint2D(x,y,distance2d,absAngle+angle);
z = GetPositionZ();
UpdateGroundPositionZ(x,y,z); // update to LOS height if available
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
if(IsWithinLOS(x,y,z))
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)
while(selector.NextUsedAngle(angle)) // angle for used pos but maybe without LOS problem
{
GetNearPoint2D(x,y,distance2d,absAngle+angle);
z = GetPositionZ();
UpdateGroundPositionZ(x,y,z); // update to LOS height if available
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
if(IsWithinLOS(x,y,z))
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
2009-05-14 16:50:47 -05:00
UpdateGroundPositionZ(x,y,z); // update to LOS height if available
*/
2008-12-24 09:58:26 -06:00
}
2009-10-17 15:51:44 -07:00
2009-08-29 23:20:16 -05:00
void WorldObject :: MovePosition ( Position & pos , float dist , float angle )
2009-01-08 14:22:15 -06:00
{
2009-08-29 23:20:16 -05:00
angle += m_orientation ;
pos . m_positionX += dist * cos ( angle );
pos . m_positionY += dist * sin ( angle );
Trinity :: NormalizeMapCoord ( pos . m_positionX );
Trinity :: NormalizeMapCoord ( pos . m_positionY );
UpdateGroundPositionZ ( pos . m_positionX , pos . m_positionY , pos . m_positionZ );
pos . m_orientation = m_orientation ;
2009-01-08 14:22:15 -06:00
}
2009-10-17 15:51:44 -07:00
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
2009-01-31 16:38:50 -06:00
if ( update && IsInWorld ())
ObjectAccessor :: UpdateObjectVisibility ( this );
}
2009-10-17 15:51:44 -07:00
2009-03-22 19:20:03 -06:00
void WorldObject :: PlayDistanceSound ( uint32 sound_id , Player * target /*= NULL*/ )
{
WorldPacket data ( SMSG_PLAY_OBJECT_SOUND , 4 + 8 );
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 )
target -> SendDirectMessage ( & data );
else
SendMessageToSet ( & data , true );
}
2009-10-17 15:51:44 -07:00
2009-03-22 19:20:03 -06:00
void WorldObject :: PlayDirectSound ( uint32 sound_id , Player * target /*= NULL*/ )
{
WorldPacket data ( SMSG_PLAY_SOUND , 4 );
data << uint32 ( sound_id );
if ( target )
target -> SendDirectMessage ( & data );
else
SendMessageToSet ( & data , true );
}
2009-10-17 15:51:44 -07:00
2009-08-28 14:19:14 -05:00
void WorldObject :: DestroyForNearbyPlayers ()
{
if ( ! IsInWorld ())
return ;
2009-10-17 15:51:44 -07:00
2009-08-28 14:19:14 -05:00
std :: list < Unit *> targets ;
2009-09-27 02:24:25 -07:00
Trinity :: AnyUnitInObjectRangeCheck check ( this , GetMap () -> GetVisibilityDistance ());
2009-08-28 14:19:14 -05:00
Trinity :: UnitListSearcher < Trinity :: AnyUnitInObjectRangeCheck > searcher ( this , targets , check );
2009-09-27 02:24:25 -07:00
VisitNearbyWorldObject ( GetMap () -> GetVisibilityDistance (), searcher );
2009-10-17 16:20:24 -07:00
for ( std :: list < Unit *>:: const_iterator iter = targets . begin (); iter != targets . end (); ++ iter )
2009-08-28 14:19:14 -05:00
{
Player * plr = dynamic_cast < Player *> ( * iter );
if ( ! plr )
continue ;
2009-10-17 15:51:44 -07:00
2009-08-28 14:19:14 -05:00
if ( plr == this )
continue ;
2009-10-17 15:51:44 -07:00
2009-08-28 14:19:14 -05:00
if ( ! plr -> HaveAtClient ( this ))
continue ;
2009-10-17 15:51:44 -07:00
2009-08-28 14:19:14 -05:00
if ( isType ( TYPEMASK_UNIT ) && (( Unit * ) this ) -> GetCharmerGUID () == plr -> GetGUID ()) // TODO: this is for puppet
continue ;
2009-10-17 16:20:24 -07:00
DestroyForPlayer ( plr );
plr -> m_clientGUIDs . erase ( GetGUID ());
2009-08-28 14:19:14 -05:00
}
}