2010-10-07 15:35:36 +02:00
/*
* Copyright (C) 2008-2010 TrinityCore <http://www.trinitycore.org/>
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
2008-10-11 14:16:25 -05:00
*/
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
#include "Common.h"
#include "SharedDefines.h"
#include "WorldPacket.h"
#include "Opcodes.h"
#include "Log.h"
#include "World.h"
#include "Object.h"
#include "Creature.h"
#include "Player.h"
2009-03-09 17:06:13 -06:00
#include "Vehicle.h"
2008-10-11 14:16:25 -05:00
#include "ObjectMgr.h"
#include "UpdateData.h"
#include "UpdateMask.h"
#include "Util.h"
#include "MapManager.h"
#include "ObjectAccessor.h"
#include "Log.h"
2010-06-07 23:40:17 +02:00
#include "Transport.h"
2008-10-11 14:16:25 -05:00
#include "TargetedMovementGenerator.h"
#include "WaypointMovementGenerator.h"
#include "VMapFactory.h"
#include "CellImpl.h"
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
2010-01-10 01:23:15 +01:00
#include "SpellAuraEffects.h"
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
#include "TemporarySummon.h"
2009-03-20 14:01:46 -06:00
#include "Totem.h"
2009-05-30 22:15:05 -05:00
#include "OutdoorPvPMgr.h"
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 ;
2010-04-07 23:25:02 +02:00
//case HIGHGUID_CONTAINER: return TYPEID_CONTAINER; HIGHGUID_CONTAINER == HIGHGUID_ITEM currently
2008-10-11 14:16:25 -05:00
case HIGHGUID_UNIT : return TYPEID_UNIT ;
case HIGHGUID_PET : return TYPEID_UNIT ;
case HIGHGUID_PLAYER : return TYPEID_PLAYER ;
case HIGHGUID_GAMEOBJECT : return TYPEID_GAMEOBJECT ;
case HIGHGUID_DYNAMICOBJECT : return TYPEID_DYNAMICOBJECT ;
case HIGHGUID_CORPSE : return TYPEID_CORPSE ;
case HIGHGUID_MO_TRANSPORT : return TYPEID_GAMEOBJECT ;
2009-01-24 11:28:00 -06:00
case HIGHGUID_VEHICLE : return TYPEID_UNIT ;
2008-10-11 14:16:25 -05:00
}
2009-05-31 15:56:51 -05:00
return NUM_CLIENT_OBJECT_TYPES ; // unknown
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
Object :: Object () : m_PackGUID ( sizeof ( uint64 ) + 1 )
2008-10-11 14:16:25 -05:00
{
m_objectTypeId = TYPEID_OBJECT ;
m_objectType = TYPEMASK_OBJECT ;
2009-10-17 15:51:44 -07:00
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
2010-04-07 19:14:10 +02:00
if ( m_isWorldObject && m_currMap )
2009-08-11 16:33:33 -05:00
{
2010-04-07 19:14:10 +02:00
if ( GetTypeId () == TYPEID_CORPSE )
2009-08-13 17:02:17 -05:00
{
sLog . outCrash ( "Object::~Object Corpse guid=" UI64FMTD ", type=%d, entry=%u deleted but still in map!!" , GetGUID (), (( Corpse * ) this ) -> GetType (), GetEntry ());
2010-07-30 20:04:28 +02:00
ASSERT ( false );
2009-08-13 17:02:17 -05:00
}
2009-08-11 16:33:33 -05:00
ResetMap ();
}
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
Object ::~ Object ()
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( IsInWorld ())
2008-10-11 14:16:25 -05:00
{
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 ());
2010-04-07 19:14:10 +02:00
if ( isType ( TYPEMASK_ITEM ))
2010-08-06 03:00:39 +02:00
sLog . outCrash ( "Item slot %u" , (( Item * ) this ) -> GetSlot ());
2010-07-30 20:04:28 +02:00
ASSERT ( false );
2009-06-17 09:57:22 -05:00
RemoveFromWorld ();
2009-04-09 17:15:40 -05:00
}
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( m_objectUpdated )
2009-06-16 17:58:44 -05:00
{
sLog . outCrash ( "Object::~Object - guid=" UI64FMTD ", typeid=%d, entry=%u deleted but still in update list!!" , GetGUID (), GetTypeId (), GetEntry ());
2010-07-30 20:04:28 +02:00
ASSERT ( false );
2010-06-25 00:18:01 +02:00
sObjectAccessor . RemoveUpdateObject ( this );
2009-06-16 17:58:44 -05:00
}
2009-10-17 15:51:44 -07:00
2010-06-21 23:20:58 +02:00
delete [] m_uint32Values ;
delete [] m_uint32Values_mirror ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Object :: _InitValues ()
{
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
2010-04-07 22:59:46 +02:00
void Object :: _Create ( uint32 guidlow , uint32 entry , HighGuid guidhigh )
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( ! m_uint32Values ) _InitValues ();
2009-10-17 15:51:44 -07:00
2009-05-31 15:56:51 -05:00
uint64 guid = MAKE_NEW_GUID ( guidlow , entry , guidhigh );
2010-04-07 22:59:46 +02:00
SetUInt64Value ( OBJECT_FIELD_GUID , guid );
2009-06-13 09:18:54 -05:00
uint32 type = 0 ;
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 ;
}
2010-04-07 22:59:46 +02:00
SetUInt32Value ( OBJECT_FIELD_TYPE , type );
//SetUInt32Value(OBJECT_FIELD_TYPE, m_objectType);
2009-06-01 12:15:43 -05:00
m_PackGUID . wpos ( 0 );
2008-10-11 14:16:25 -05:00
m_PackGUID . appendPackGUID ( GetGUID ());
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void Object :: BuildMovementUpdateBlock ( UpdateData * data , uint32 flags ) const
2008-10-11 14:16:25 -05:00
{
2009-06-11 00:45:59 -05:00
ByteBuffer buf ( 500 );
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
buf << uint8 ( UPDATETYPE_MOVEMENT );
2009-06-05 17:44:27 -05:00
buf . append ( GetPackGUID ());
2009-10-17 15:51:44 -07:00
2009-04-22 17:50:26 -05:00
_BuildMovementUpdate ( & buf , flags );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
data -> AddUpdateBlock ( buf );
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Object :: BuildCreateUpdateBlockForPlayer ( UpdateData * data , Player * target ) const
{
2010-04-07 19:14:10 +02:00
if ( ! target )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint8 updatetype = UPDATETYPE_CREATE_OBJECT ;
2009-06-11 00:45:59 -05:00
uint16 flags = m_updateFlag ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
/** lower flag1 **/
2010-04-07 19:14:10 +02:00
if ( target == this ) // building packet for yourself
2008-10-11 14:16:25 -05:00
flags |= UPDATEFLAG_SELF ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( flags & UPDATEFLAG_HAS_POSITION )
2008-10-11 14:16:25 -05:00
{
// UPDATETYPE_CREATE_OBJECT2 dynamic objects, corpses...
2010-04-07 19:14:10 +02:00
if ( isType ( TYPEMASK_DYNAMICOBJECT ) || isType ( TYPEMASK_CORPSE ) || isType ( TYPEMASK_PLAYER ))
2008-10-11 14:16:25 -05:00
updatetype = UPDATETYPE_CREATE_OBJECT2 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// UPDATETYPE_CREATE_OBJECT2 for pets...
2010-04-07 19:14:10 +02:00
if ( target -> GetPetGUID () == GetGUID ())
2008-10-11 14:16:25 -05:00
updatetype = UPDATETYPE_CREATE_OBJECT2 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// UPDATETYPE_CREATE_OBJECT2 for some gameobject types...
2010-04-07 19:14:10 +02:00
if ( isType ( TYPEMASK_GAMEOBJECT ))
2008-10-11 14:16:25 -05:00
{
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
2010-04-07 19:14:10 +02:00
if ( isType ( TYPEMASK_UNIT ))
2008-12-24 09:58:26 -06:00
{
2010-04-07 19:14:10 +02:00
if ((( Unit * ) this ) -> getVictim ())
2008-12-24 09:58:26 -06:00
flags |= UPDATEFLAG_HAS_TARGET ;
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
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 ;
2010-04-07 22:59:46 +02:00
updateMask . SetCount ( m_valuesCount );
_SetCreateBits ( & updateMask , target );
2009-05-31 15:56:51 -05:00
_BuildValuesUpdate ( updatetype , & buf , & updateMask , target );
2008-10-11 14:16:25 -05:00
data -> AddUpdateBlock ( buf );
}
2009-10-17 15:51:44 -07:00
2009-12-19 19:46:07 +01:00
void Object :: SendUpdateToPlayer ( Player * player )
2008-10-11 14:16:25 -05:00
{
// send create update to player
UpdateData upd ;
WorldPacket packet ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
BuildCreateUpdateBlockForPlayer ( & upd , player );
upd . BuildPacket ( & packet );
player -> GetSession () -> SendPacket ( & packet );
}
2009-10-17 15:51:44 -07:00
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 ;
2010-04-07 22:59:46 +02:00
updateMask . SetCount ( m_valuesCount );
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
_SetUpdateBits ( & updateMask , target );
2009-05-31 15:56:51 -05:00
_BuildValuesUpdate ( UPDATETYPE_VALUES , & buf , & updateMask , target );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
data -> AddUpdateBlock ( buf );
}
2009-10-17 15:51:44 -07:00
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
2010-04-07 22:59:46 +02:00
void Object :: DestroyForPlayer ( Player * target , bool anim ) const
2008-10-11 14:16:25 -05:00
{
ASSERT ( target );
2009-10-17 15:51:44 -07:00
2010-02-03 16:53:40 +02:00
WorldPacket data ( SMSG_DESTROY_OBJECT , 8 + 1 );
2009-05-31 15:56:51 -05:00
data << uint64 ( GetGUID ());
2009-07-30 10:26:15 +08:00
data << uint8 ( anim ? 1 : 0 ); // WotLK (bool), may be despawn animation
2010-04-07 22:59:46 +02:00
target -> GetSession () -> SendPacket ( & data );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-06-11 00:45:59 -05:00
void Object :: _BuildMovementUpdate ( ByteBuffer * data , uint16 flags ) const
2008-10-11 14:16:25 -05:00
{
2009-06-11 00:45:59 -05:00
* data << ( uint16 ) flags ; // update flags
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// 0x20
if ( flags & UPDATEFLAG_LIVING )
{
2009-04-21 15:43:03 -05:00
(( Unit * ) this ) -> BuildMovementPacket ( data );
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
* data << (( Unit * ) this ) -> GetSpeed ( MOVE_WALK );
* data << (( Unit * ) this ) -> GetSpeed ( MOVE_RUN );
* data << (( Unit * ) this ) -> GetSpeed ( MOVE_SWIM_BACK );
* data << (( Unit * ) this ) -> GetSpeed ( MOVE_SWIM );
* 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 );
* data << (( Unit * ) this ) -> GetSpeed ( MOVE_PITCH_RATE );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// 0x08000000
2010-04-07 19:14:10 +02:00
if ( GetTypeId () == TYPEID_PLAYER && this -> ToPlayer () -> isInFlight ())
2008-10-11 14:16:25 -05:00
{
2010-04-07 17:24:07 +02:00
//WPAssert(this->ToPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE);
2009-10-17 15:51:44 -07:00
2010-06-23 00:57:16 +02:00
Player * player = const_cast < Object *> ( this ) -> ToPlayer ();
if ( ! player )
return ;
FlightPathMovementGenerator * fmg = ( FlightPathMovementGenerator * )( player -> GetMotionMaster () -> top ());
2009-10-17 15:51:44 -07:00
2010-08-04 14:39:45 +02:00
uint32 flags3 = SPLINEFLAG_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
2010-04-07 19:14:10 +02: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
{
2010-04-07 19:14:10 +02:00
if ( flags3 & 0x8000 ) // probably x,y,z coords there
2009-06-11 00:45:59 -05:00
{
* data << ( float ) 0 ;
* data << ( float ) 0 ;
* data << ( float ) 0 ;
}
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( flags3 & 0x10000 ) // probably guid there
2009-06-11 00:45:59 -05:00
{
* data << uint64 ( 0 );
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2010-06-23 00:57:16 +02:00
TaxiPathNodeList & path = const_cast < TaxiPathNodeList &> ( fmg -> GetPath ());
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
float x , y , z ;
2010-06-23 00:57:16 +02:00
player -> 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
2010-06-23 00:57:16 +02: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
{
2010-06-23 00:57:16 +02:00
* data << float ( path [ i ]. x );
* data << float ( path [ i ]. y );
* data << float ( path [ i ]. z );
2008-10-11 14:16:25 -05:00
}
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
2010-06-23 00:57:16 +02:00
* data << float ( path [ poscount - 1 ]. x );
* data << float ( path [ poscount - 1 ]. y );
* data << float ( path [ poscount - 1 ]. z );
2009-06-11 00:45:59 -05:00
}
}
else
{
2010-04-07 19:14:10 +02:00
if ( flags & UPDATEFLAG_POSITION )
2009-06-11 00:45:59 -05:00
{
* data << uint8 ( 0 ); // unk PGUID!
* data << (( WorldObject * ) this ) -> GetPositionX ();
* data << (( WorldObject * ) this ) -> GetPositionY ();
* data << (( WorldObject * ) this ) -> GetPositionZ ();
* data << (( WorldObject * ) this ) -> GetPositionX ();
* data << (( WorldObject * ) this ) -> GetPositionY ();
* data << (( WorldObject * ) this ) -> GetPositionZ ();
* data << (( WorldObject * ) this ) -> GetOrientation ();
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( GetTypeId () == TYPEID_CORPSE )
2009-06-11 00:45:59 -05:00
* data << float ((( WorldObject * ) this ) -> GetOrientation ());
else
* data << float ( 0 );
}
else
{
// 0x40
if ( flags & UPDATEFLAG_HAS_POSITION )
{
// 0x02
2010-04-07 19:14:10 +02:00
if ( flags & UPDATEFLAG_TRANSPORT && (( GameObject * ) this ) -> GetGoType () == GAMEOBJECT_TYPE_MO_TRANSPORT )
2009-06-11 00:45:59 -05:00
{
* data << ( float ) 0 ;
* data << ( float ) 0 ;
* data << ( float ) 0 ;
* 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
2010-04-07 19:14:10 +02:00
if ( flags & UPDATEFLAG_LOWGUID )
2008-10-11 14:16:25 -05:00
{
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 :
2009-12-20 17:38:09 +01:00
{
2010-04-07 19:14:10 +02:00
if ( this -> ToCreature () -> canFly ())
2009-12-20 17:38:09 +01:00
flags |= MOVEMENTFLAG_LEVITATING ;
2008-10-11 14:16:25 -05:00
* data << uint32 ( 0x0000000B ); // unk, can be 0xB or 0xC
break ;
2009-12-20 17:38:09 +01:00
}
2008-10-11 14:16:25 -05:00
case TYPEID_PLAYER :
2010-04-07 19:14:10 +02:00
if ( flags & UPDATEFLAG_SELF )
2008-12-24 09:58:26 -06:00
* data << uint32 ( 0x0000002F ); // unk, can be 0x15 or 0x22
2008-10-11 14:16:25 -05:00
else
* data << uint32 ( 0x00000008 ); // unk, can be 0x7 or 0x8
break ;
default :
* data << uint32 ( 0x00000000 ); // unk
break ;
}
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// 0x10
2010-04-07 19:14:10 +02:00
if ( flags & UPDATEFLAG_HIGHGUID )
2008-10-11 14:16:25 -05:00
{
2009-06-13 09:18:54 -05:00
// not high guid
* 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
2010-04-07 19:14:10 +02:00
if ( flags & UPDATEFLAG_HAS_TARGET ) // packed guid (current target guid)
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( Unit * victim = (( Unit * ) this ) -> getVictim ())
2008-12-24 09:58:26 -06:00
data -> append ( victim -> GetPackGUID ());
else
* data << uint8 ( 0 );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// 0x2
2010-04-07 19:14:10 +02:00
if ( flags & UPDATEFLAG_TRANSPORT )
2008-10-11 14:16:25 -05:00
{
* data << uint32 ( getMSTime ()); // ms time
}
2009-10-17 15:51:44 -07:00
2008-12-24 09:58:26 -06:00
// 0x80
2010-04-07 19:14:10 +02:00
if ( flags & UPDATEFLAG_VEHICLE ) // unused for now
2008-12-24 09:58:26 -06:00
{
2009-08-23 22:09:43 -05:00
* data << uint32 ((( Unit * ) this ) -> GetVehicleKit () -> GetVehicleInfo () -> m_ID ); // vehicle id
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
2010-04-07 19:14:10 +02:00
if ( flags & UPDATEFLAG_ROTATION )
2009-06-11 00:45:59 -05:00
{
* 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
{
2010-04-07 19:14:10 +02:00
if ( ! target )
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bool IsActivateToQuest = false ;
if ( updatetype == UPDATETYPE_CREATE_OBJECT || updatetype == UPDATETYPE_CREATE_OBJECT2 )
{
2009-11-27 01:41:26 +01:00
if ( isType ( TYPEMASK_GAMEOBJECT ) && ! (( GameObject * ) this ) -> IsDynTransport ())
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
if ((( GameObject * ) this ) -> ActivateToQuest ( target ) || target -> isGameMaster ())
2008-10-11 14:16:25 -05:00
IsActivateToQuest = true ;
2009-10-17 15:51:44 -07:00
2009-09-04 05:11:27 +02:00
updateMask -> SetBit ( GAMEOBJECT_DYNAMIC );
2009-10-17 15:51:44 -07:00
2009-01-04 17:14:34 -06:00
if ((( GameObject * ) this ) -> GetGoArtKit ())
updateMask -> SetBit ( GAMEOBJECT_BYTES_1 );
2008-10-11 14:16:25 -05:00
}
2009-07-30 17:16:56 +02:00
else if ( isType ( TYPEMASK_UNIT ))
{
2010-04-07 22:59:46 +02:00
if ((( Unit * ) this ) -> HasFlag ( UNIT_FIELD_AURASTATE , PER_CASTER_AURA_STATE_MASK ))
2009-07-30 17:16:56 +02:00
{
updateMask -> SetBit ( UNIT_FIELD_AURASTATE );
}
}
2008-10-11 14:16:25 -05:00
}
2009-05-31 15:56:51 -05:00
else // case UPDATETYPE_VALUES
2008-10-11 14:16:25 -05:00
{
if ( isType ( TYPEMASK_GAMEOBJECT ) && ! (( GameObject * ) this ) -> IsTransport ())
{
2010-04-07 22:59:46 +02:00
if ((( GameObject * ) this ) -> ActivateToQuest ( target ) || target -> isGameMaster ())
2008-10-11 14:16:25 -05:00
{
IsActivateToQuest = true ;
}
2008-12-24 09:58:26 -06:00
updateMask -> SetBit ( GAMEOBJECT_DYNAMIC );
updateMask -> SetBit ( GAMEOBJECT_BYTES_1 );
2008-10-11 14:16:25 -05:00
}
2009-07-30 17:16:56 +02:00
else if ( isType ( TYPEMASK_UNIT ))
{
2010-04-07 22:59:46 +02:00
if ((( Unit * ) this ) -> HasFlag ( UNIT_FIELD_AURASTATE , PER_CASTER_AURA_STATE_MASK ))
2009-07-30 17:16:56 +02:00
{
updateMask -> SetBit ( UNIT_FIELD_AURASTATE );
}
}
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
WPAssert ( updateMask && updateMask -> GetCount () == m_valuesCount );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
* data << ( uint8 ) updateMask -> GetBlockCount ();
2010-04-07 22:59:46 +02:00
data -> append ( updateMask -> GetMask (), updateMask -> GetLength ());
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// 2 specialized loops for speed optimization in non-unit case
2010-04-07 19:14:10 +02:00
if ( isType ( TYPEMASK_UNIT )) // unit (creature/player) case
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
for ( uint16 index = 0 ; index < m_valuesCount ; ++ index )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
if ( updateMask -> GetBit ( index ))
2008-10-11 14:16:25 -05:00
{
2010-03-14 00:22:53 +01:00
if ( index == UNIT_NPC_FLAGS )
2009-05-05 16:56:15 -05:00
{
// remove custom flag before sending
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 )
{
2010-03-07 18:30:53 +01:00
if ( ! target -> canSeeSpellClickOn ( this -> ToCreature ()))
2009-12-19 18:29:09 +01:00
appendValue &= ~ UNIT_NPC_FLAG_SPELLCLICK ;
if ( appendValue & UNIT_NPC_FLAG_TRAINER )
{
2010-03-07 18:30:53 +01:00
if ( ! this -> ToCreature () -> isCanTrainingOf ( target , false ))
2009-12-19 18:29:09 +01:00
appendValue &= ~ ( UNIT_NPC_FLAG_TRAINER | UNIT_NPC_FLAG_TRAINER_CLASS | UNIT_NPC_FLAG_TRAINER_PROFESSION );
}
}
2009-10-17 15:51:44 -07:00
2009-05-05 16:56:15 -05:00
* data << uint32 ( appendValue );
}
2009-07-30 17:16:56 +02:00
else if ( index == UNIT_FIELD_AURASTATE )
{
// Check per caster aura states to not enable using a pell in client if specified aura is not by target
* data << (( Unit * ) this ) -> BuildAuraStateUpdateForTarget ( target );
}
2008-10-11 14:16:25 -05:00
// FIXME: Some values at server stored in float format but must be sent to client in uint32 format
2010-03-14 00:22:53 +01:00
else if ( index >= UNIT_FIELD_BASEATTACKTIME && index <= UNIT_FIELD_RANGEDATTACKTIME )
2008-10-11 14:16:25 -05:00
{
// convert from float to uint32 and send
* 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
2010-04-07 19:14:10 +02:00
else if ( index == UNIT_FIELD_FLAGS )
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( target -> isGameMaster ())
2009-05-24 12:56:09 -05:00
* 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
2010-04-07 19:14:10 +02:00
else if ( index == UNIT_FIELD_DISPLAYID )
2008-10-20 13:41:05 -05:00
{
2010-04-07 19:14:10 +02:00
if ( GetTypeId () == TYPEID_UNIT )
2008-10-20 13:41:05 -05:00
{
2010-03-07 18:30:53 +01:00
const CreatureInfo * cinfo = this -> ToCreature () -> GetCreatureInfo ();
2010-04-07 19:14:10 +02:00
if ( cinfo -> flags_extra & CREATURE_FLAG_EXTRA_TRIGGER )
2008-11-09 14:54:13 -06:00
{
2010-04-07 19:14:10 +02:00
if ( target -> isGameMaster ())
2009-05-24 12:56:09 -05:00
{
2010-04-07 19:14:10 +02:00
if ( cinfo -> Modelid1 )
2010-04-21 13:55:43 +02:00
* data << cinfo -> Modelid1 ; //Modelid1 is a visible model for gms
2009-05-24 12:56:09 -05:00
else
* data << 17519 ; // world invisible trigger's model
}
2008-11-09 14:54:13 -06:00
else
2009-05-24 12:56:09 -05:00
{
2010-04-21 13:55:43 +02:00
if ( cinfo -> Modelid2 )
* data << cinfo -> Modelid2 ; //Modelid2 is an invisible model for players
2009-05-24 12:56:09 -05:00
else
* data << 11686 ; // world invisible trigger's model
}
2008-11-09 14:54:13 -06:00
}
2008-10-20 13:41:05 -05:00
else
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
2010-03-14 00:22:53 +01:00
else if ( index == UNIT_DYNAMIC_FLAGS )
2008-10-11 14:16:25 -05:00
{
2010-03-14 00:22:53 +01:00
uint32 dynamicFlags = m_uint32Values [ index ];
if ( const Creature * creature = ToCreature ())
2009-05-24 12:56:09 -05:00
{
2010-03-14 00:22:53 +01:00
if ( creature -> hasLootRecipient ())
{
if ( creature -> isTappedBy ( target ))
{
dynamicFlags |= ( UNIT_DYNFLAG_TAPPED | UNIT_DYNFLAG_TAPPED_BY_PLAYER );
}
else
{
dynamicFlags |= UNIT_DYNFLAG_TAPPED ;
dynamicFlags &= ~ UNIT_DYNFLAG_TAPPED_BY_PLAYER ;
}
}
2009-05-24 12:56:09 -05:00
else
2010-03-14 00:22:53 +01:00
{
dynamicFlags &= ~ UNIT_DYNFLAG_TAPPED ;
dynamicFlags &= ~ UNIT_DYNFLAG_TAPPED_BY_PLAYER ;
}
2010-08-02 17:28:47 +02:00
if ( ! target -> isAllowedToLoot ( creature ))
2010-03-14 00:22:53 +01:00
dynamicFlags &= ~ UNIT_DYNFLAG_LOOTABLE ;
2009-05-24 12:56:09 -05:00
}
2010-03-14 00:22:53 +01:00
* data << dynamicFlags ;
2008-10-11 14:16:25 -05:00
}
2009-01-15 21:29:32 -05:00
// FG: pretend that OTHER players in own group are friendly ("blue")
2010-04-07 19:14:10 +02:00
else if ( index == UNIT_FIELD_BYTES_2 || index == UNIT_FIELD_FACTIONTEMPLATE )
2009-01-15 21:29:32 -05:00
{
2010-08-23 19:56:47 -07:00
if ((( Unit * ) this ) -> IsControlledByPlayer () && target != this && sWorld . getBoolConfig ( 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 ();
2010-04-07 19:14:10 +02:00
if ( ft1 && ft2 && ! ft1 -> IsFriendlyTo ( * ft2 ))
2009-01-15 21:29:32 -05:00
{
2010-04-07 19:14:10 +02:00
if ( index == UNIT_FIELD_BYTES_2 )
2009-01-15 21:29:32 -05:00
{
2009-05-24 12:56:09 -05:00
// Allow targetting opposite faction in party when enabled in config
2010-04-07 22:59:46 +02:00
* data << ( m_uint32Values [ index ] & (( UNIT_BYTE2_FLAG_SANCTUARY /*| UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5*/ ) << 8 )); // this flag is at uint8 offset 1 !!
2009-05-24 12:56:09 -05:00
}
else
{
// pretend that all other HOSTILE players have own faction, to allow follow, heal, rezz (trade wont work)
uint32 faction = target -> getFaction ();
2009-01-15 21:29:32 -05:00
* data << uint32 ( faction );
}
}
2009-05-24 12:56:09 -05:00
else
* 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 ];
}
}
}
}
2010-04-07 19:14:10 +02:00
else if ( isType ( TYPEMASK_GAMEOBJECT )) // gameobject case
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
for ( uint16 index = 0 ; index < m_valuesCount ; ++ index )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
if ( updateMask -> GetBit ( index ))
2008-10-11 14:16:25 -05:00
{
// send in current format (float as float, uint32 as uint32)
2010-04-07 22:59:46 +02:00
if ( index == GAMEOBJECT_DYNAMIC )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
if ( IsActivateToQuest )
2008-10-11 14:16:25 -05:00
{
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 :
2010-10-06 16:19:12 -06:00
* data << uint16 ( 9 );
2009-09-04 05:11:27 +02:00
* data << uint16 ( - 1 );
2008-10-11 14:16:25 -05:00
break ;
default :
2009-09-04 05:11:27 +02:00
// unknown, not happen.
* data << uint16 ( 0 );
* data << uint16 ( - 1 );
2008-10-11 14:16:25 -05:00
break ;
}
}
else
2009-09-04 05:11:27 +02:00
{
// disable quest object
* data << uint16 ( 0 );
* data << uint16 ( - 1 );
}
2008-10-11 14:16:25 -05:00
}
else
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)
{
2010-04-07 22:59:46 +02:00
for ( uint16 index = 0 ; index < m_valuesCount ; ++ index )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
if ( updateMask -> GetBit ( index ))
2008-10-11 14:16:25 -05:00
{
// send in current format (float as float, uint32 as uint32)
* 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
2010-04-07 19:14:10 +02:00
if ( m_objectUpdated )
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( remove )
2010-06-25 00:18:01 +02:00
sObjectAccessor . RemoveUpdateObject ( this );
2008-10-11 14:16:25 -05:00
m_objectUpdated = false ;
}
}
2009-10-17 15:51:44 -07:00
2010-02-03 16:53:40 +02:00
void Object :: BuildFieldsUpdate ( Player * pl , UpdateDataMapType & data_map ) const
2009-12-19 19:46:07 +01:00
{
2010-02-03 16:53:40 +02:00
UpdateDataMapType :: iterator iter = data_map . find ( pl );
2009-12-19 19:46:07 +01:00
2010-04-07 22:59:46 +02:00
if ( iter == data_map . end ())
2010-02-03 16:53:40 +02:00
{
2010-04-07 22:59:46 +02:00
std :: pair < UpdateDataMapType :: iterator , bool > p = data_map . insert ( UpdateDataMapType :: value_type ( pl , UpdateData ()));
2010-07-30 20:04:28 +02:00
ASSERT ( p . second );
2010-02-03 16:53:40 +02:00
iter = p . first ;
}
2009-12-19 19:46:07 +01:00
2010-02-03 16:53:40 +02:00
BuildValuesUpdateBlockForPlayer ( & iter -> second , iter -> first );
2009-12-19 19:46:07 +01:00
}
2008-10-11 14:16:25 -05:00
bool Object :: LoadValues ( const char * data )
{
2010-04-07 19:14:10 +02:00
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
2010-04-07 19:14:10 +02:00
if ( tokens . size () != m_valuesCount )
2008-10-11 14:16:25 -05:00
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
2010-07-30 13:15:31 +02:00
void Object :: _LoadIntoDataField ( const char * data , uint32 startOffset , uint32 count )
{
if ( ! data )
return ;
Tokens tokens = StrSplit ( data , " " );
if ( tokens . size () != count )
return ;
Tokens :: iterator iter ;
uint32 index ;
for ( iter = tokens . begin (), index = 0 ; index < count ; ++ iter , ++ index )
{
m_uint32Values [ startOffset + index ] = atol (( * iter ). c_str ());
}
}
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
{
2010-04-07 19:14:10 +02: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
{
2010-04-07 19:14:10 +02:00
if ( * value )
2008-10-11 14:16:25 -05:00
updateMask -> SetBit ( index );
}
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void Object :: SetInt32Value ( uint16 index , int32 value )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
ASSERT ( index < m_valuesCount || PrintIndexError ( index , true ));
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( m_int32Values [ index ] != value )
2008-10-11 14:16:25 -05:00
{
m_int32Values [ index ] = value ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( m_inWorld )
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( ! m_objectUpdated )
2008-10-11 14:16:25 -05:00
{
2010-06-25 00:18:01 +02:00
sObjectAccessor . AddUpdateObject ( this );
2008-10-11 14:16:25 -05:00
m_objectUpdated = true ;
}
}
}
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void Object :: SetUInt32Value ( uint16 index , uint32 value )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
ASSERT ( index < m_valuesCount || PrintIndexError ( index , true ));
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( m_uint32Values [ index ] != value )
2008-10-11 14:16:25 -05:00
{
m_uint32Values [ index ] = value ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( m_inWorld )
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( ! m_objectUpdated )
2008-10-11 14:16:25 -05:00
{
2010-06-25 00:18:01 +02:00
sObjectAccessor . AddUpdateObject ( this );
2008-10-11 14:16:25 -05:00
m_objectUpdated = true ;
}
}
}
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void Object :: UpdateUInt32Value ( uint16 index , uint32 value )
2009-09-02 15:05:18 -05:00
{
2010-04-07 22:59:46 +02:00
ASSERT ( index < m_valuesCount || PrintIndexError ( index , true ));
2009-10-17 15:51:44 -07:00
2009-09-02 15:05:18 -05:00
m_uint32Values [ index ] = value ;
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void Object :: SetUInt64Value ( uint16 index , const uint64 & value )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
ASSERT ( index + 1 < m_valuesCount || PrintIndexError ( index , true ));
2010-04-07 19:14:10 +02:00
if ( * (( uint64 * ) & ( m_uint32Values [ index ])) != value )
2008-10-11 14:16:25 -05:00
{
m_uint32Values [ index ] = * (( uint32 * ) & value );
m_uint32Values [ index + 1 ] = * ((( uint32 * ) & value ) + 1 );
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( m_inWorld )
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( ! m_objectUpdated )
2008-10-11 14:16:25 -05:00
{
2010-06-25 00:18:01 +02:00
sObjectAccessor . AddUpdateObject ( this );
2008-10-11 14:16:25 -05:00
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 )
{
2010-04-07 22:59:46 +02:00
ASSERT ( index + 1 < m_valuesCount || PrintIndexError ( index , true ));
2010-04-07 19:14:10 +02:00
if ( value && !* (( uint64 * ) & ( m_uint32Values [ index ])))
2009-03-23 20:13:37 -06:00
{
m_uint32Values [ index ] = * (( uint32 * ) & value );
m_uint32Values [ index + 1 ] = * ((( uint32 * ) & value ) + 1 );
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( m_inWorld )
2009-03-23 20:13:37 -06:00
{
2010-04-07 19:14:10 +02:00
if ( ! m_objectUpdated )
2009-03-23 20:13:37 -06:00
{
2010-06-25 00:18:01 +02:00
sObjectAccessor . AddUpdateObject ( this );
2009-03-23 20:13:37 -06:00
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 )
{
2010-04-07 22:59:46 +02:00
ASSERT ( index + 1 < m_valuesCount || PrintIndexError ( index , true ));
2010-04-07 19:14:10 +02:00
if ( value && * (( uint64 * ) & ( m_uint32Values [ index ])) == value )
2009-03-23 20:13:37 -06:00
{
m_uint32Values [ index ] = 0 ;
m_uint32Values [ index + 1 ] = 0 ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( m_inWorld )
2009-03-23 20:13:37 -06:00
{
2010-04-07 19:14:10 +02:00
if ( ! m_objectUpdated )
2009-03-23 20:13:37 -06:00
{
2010-06-25 00:18:01 +02:00
sObjectAccessor . AddUpdateObject ( this );
2009-03-23 20:13:37 -06:00
m_objectUpdated = true ;
}
}
return true ;
}
return false ;
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void Object :: SetFloatValue ( uint16 index , float value )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
ASSERT ( index < m_valuesCount || PrintIndexError ( index , true ));
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( m_floatValues [ index ] != value )
2008-10-11 14:16:25 -05:00
{
m_floatValues [ index ] = value ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( m_inWorld )
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( ! m_objectUpdated )
2008-10-11 14:16:25 -05:00
{
2010-06-25 00:18:01 +02:00
sObjectAccessor . AddUpdateObject ( this );
2008-10-11 14:16:25 -05:00
m_objectUpdated = true ;
}
}
}
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void Object :: SetByteValue ( uint16 index , uint8 offset , uint8 value )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
ASSERT ( index < m_valuesCount || PrintIndexError ( index , true ));
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( offset > 4 )
2008-10-11 14:16:25 -05:00
{
sLog . outError ( "Object::SetByteValue: wrong offset %u" , offset );
return ;
}
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( uint8 ( m_uint32Values [ index ] >> ( offset * 8 )) != value )
2008-10-11 14:16:25 -05:00
{
m_uint32Values [ index ] &= ~ uint32 ( uint32 ( 0xFF ) << ( offset * 8 ));
m_uint32Values [ index ] |= uint32 ( uint32 ( value ) << ( offset * 8 ));
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( m_inWorld )
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( ! m_objectUpdated )
2008-10-11 14:16:25 -05:00
{
2010-06-25 00:18:01 +02:00
sObjectAccessor . AddUpdateObject ( this );
2008-10-11 14:16:25 -05:00
m_objectUpdated = true ;
}
}
}
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void Object :: SetUInt16Value ( uint16 index , uint8 offset , uint16 value )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
ASSERT ( index < m_valuesCount || PrintIndexError ( index , true ));
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( offset > 2 )
2008-10-11 14:16:25 -05:00
{
sLog . outError ( "Object::SetUInt16Value: wrong offset %u" , offset );
return ;
}
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02: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
2010-04-07 19:14:10 +02:00
if ( m_inWorld )
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( ! m_objectUpdated )
2008-10-11 14:16:25 -05:00
{
2010-06-25 00:18:01 +02:00
sObjectAccessor . AddUpdateObject ( this );
2008-10-11 14:16:25 -05:00
m_objectUpdated = true ;
}
}
}
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void Object :: SetStatFloatValue ( uint16 index , float value )
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( value < 0 )
2008-10-11 14:16:25 -05:00
value = 0.0f ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
SetFloatValue ( index , value );
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void Object :: SetStatInt32Value ( uint16 index , int32 value )
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( value < 0 )
2008-10-11 14:16:25 -05:00
value = 0 ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
SetUInt32Value ( index , uint32 ( value ));
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Object :: ApplyModUInt32Value ( uint16 index , int32 val , bool apply )
{
int32 cur = GetUInt32Value ( index );
cur += ( apply ? val : - val );
2010-04-07 19:14:10 +02:00
if ( cur < 0 )
2008-10-11 14:16:25 -05:00
cur = 0 ;
2009-05-31 15:56:51 -05:00
SetUInt32Value ( index , cur );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Object :: ApplyModInt32Value ( uint16 index , int32 val , bool apply )
{
int32 cur = GetInt32Value ( index );
cur += ( apply ? val : - val );
2009-05-31 15:56:51 -05:00
SetInt32Value ( index , cur );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Object :: ApplyModSignedFloatValue ( uint16 index , float val , bool apply )
{
float cur = GetFloatValue ( index );
cur += ( apply ? val : - val );
2009-05-31 15:56:51 -05:00
SetFloatValue ( index , cur );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void Object :: ApplyModPositiveFloatValue ( uint16 index , float val , bool apply )
{
float cur = GetFloatValue ( index );
cur += ( apply ? val : - val );
2010-04-07 19:14:10 +02:00
if ( cur < 0 )
2008-10-11 14:16:25 -05:00
cur = 0 ;
2009-05-31 15:56:51 -05:00
SetFloatValue ( index , cur );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void Object :: SetFlag ( uint16 index , uint32 newFlag )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
ASSERT ( index < m_valuesCount || PrintIndexError ( index , true ));
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
2010-04-07 19:14:10 +02:00
if ( oldval != newval )
2008-10-11 14:16:25 -05:00
{
m_uint32Values [ index ] = newval ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( m_inWorld )
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( ! m_objectUpdated )
2008-10-11 14:16:25 -05:00
{
2010-06-25 00:18:01 +02:00
sObjectAccessor . AddUpdateObject ( this );
2008-10-11 14:16:25 -05:00
m_objectUpdated = true ;
}
}
}
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void Object :: RemoveFlag ( uint16 index , uint32 oldFlag )
2008-10-11 14:16:25 -05:00
{
2010-04-07 22:59:46 +02:00
ASSERT ( index < m_valuesCount || PrintIndexError ( index , true ));
2010-09-21 19:26:59 -07:00
ASSERT ( m_uint32Values );
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
2010-04-07 19:14:10 +02:00
if ( oldval != newval )
2008-10-11 14:16:25 -05:00
{
m_uint32Values [ index ] = newval ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( m_inWorld )
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( ! m_objectUpdated )
2008-10-11 14:16:25 -05:00
{
2010-06-25 00:18:01 +02:00
sObjectAccessor . AddUpdateObject ( this );
2008-10-11 14:16:25 -05:00
m_objectUpdated = true ;
}
}
}
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void Object :: SetByteFlag ( uint16 index , uint8 offset , uint8 newFlag )
2008-12-12 11:21:28 -06:00
{
2010-04-07 22:59:46 +02:00
ASSERT ( index < m_valuesCount || PrintIndexError ( index , true ));
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( offset > 4 )
2008-12-12 11:21:28 -06:00
{
sLog . outError ( "Object::SetByteFlag: wrong offset %u" , offset );
return ;
}
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( ! ( uint8 ( m_uint32Values [ index ] >> ( offset * 8 )) & newFlag ))
2008-12-12 11:21:28 -06:00
{
m_uint32Values [ index ] |= uint32 ( uint32 ( newFlag ) << ( offset * 8 ));
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( m_inWorld )
2008-12-12 11:21:28 -06:00
{
2010-04-07 19:14:10 +02:00
if ( ! m_objectUpdated )
2008-12-12 11:21:28 -06:00
{
2010-06-25 00:18:01 +02:00
sObjectAccessor . AddUpdateObject ( this );
2008-12-12 11:21:28 -06:00
m_objectUpdated = true ;
}
}
}
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void Object :: RemoveByteFlag ( uint16 index , uint8 offset , uint8 oldFlag )
2008-12-12 11:21:28 -06:00
{
2010-04-07 22:59:46 +02:00
ASSERT ( index < m_valuesCount || PrintIndexError ( index , true ));
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( offset > 4 )
2008-12-12 11:21:28 -06:00
{
sLog . outError ( "Object::RemoveByteFlag: wrong offset %u" , offset );
return ;
}
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( uint8 ( m_uint32Values [ index ] >> ( offset * 8 )) & oldFlag )
2008-12-12 11:21:28 -06:00
{
m_uint32Values [ index ] &= ~ uint32 ( uint32 ( oldFlag ) << ( offset * 8 ));
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( m_inWorld )
2008-12-12 11:21:28 -06:00
{
2010-04-07 19:14:10 +02:00
if ( ! m_objectUpdated )
2008-12-12 11:21:28 -06:00
{
2010-06-25 00:18:01 +02:00
sObjectAccessor . AddUpdateObject ( this );
2008-12-12 11:21:28 -06:00
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
2010-07-30 20:04:28 +02:00
// ASSERT must fail after function call
2008-10-11 14:16:25 -05:00
return false ;
}
2009-10-17 15:51:44 -07:00
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
{
2010-02-14 19:13:14 -07:00
if ( ! HasInArc ( M_PI , target ) || ! target -> IsWithinDist3d ( m_positionX , m_positionY , m_positionZ , distance ))
return false ;
2009-08-29 14:58:45 -05:00
width += target -> GetObjectSize ();
float angle = GetRelativeAngle ( target );
return abs ( sin ( angle )) * GetExactDist2d ( target -> GetPositionX (), target -> GetPositionY ()) < width ;
}
2009-10-17 15:51:44 -07:00
2010-08-08 20:32:14 +02:00
std :: string Position :: ToString () const
{
std :: stringstream sstr ;
sstr << "X: " << m_positionX << " Y: " << m_positionY << " Z: " << m_positionZ << " O: " << m_orientation ;
return sstr . str ();
}
2010-08-04 14:39:45 +02:00
ByteBuffer & operator >> ( ByteBuffer & buf , Position :: PositionXYZOStreamer const & streamer )
{
float x , y , z , o ;
buf >> x >> y >> z >> o ;
streamer . m_pos -> Relocate ( x , y , z , o );
return buf ;
}
ByteBuffer & operator << ( ByteBuffer & buf , Position :: PositionXYZStreamer const & streamer )
{
float x , y , z ;
streamer . m_pos -> GetPosition ( x , y , z );
buf << x << y << z ;
return buf ;
}
ByteBuffer & operator >> ( ByteBuffer & buf , Position :: PositionXYZStreamer const & streamer )
{
float x , y , z ;
buf >> x >> y >> z ;
streamer . m_pos -> Relocate ( x , y , z );
return buf ;
}
ByteBuffer & operator << ( ByteBuffer & buf , Position :: PositionXYZOStreamer const & streamer )
{
float x , y , z , o ;
streamer . m_pos -> GetPosition ( x , y , z , o );
buf << x << y << z << o ;
return buf ;
}
2010-08-08 20:32:14 +02:00
void MovementInfo :: OutDebug ()
{
sLog . outString ( "MOVEMENT INFO" );
sLog . outString ( "guid " UI64FMTD , guid );
sLog . outString ( "flags %u" , flags );
sLog . outString ( "flags2 %u" , flags2 );
2010-08-31 10:23:22 +02:00
sLog . outString ( "time %u current time " UI64FMTD "" , flags2 , uint64 ( :: time ( NULL )));
2010-08-08 20:32:14 +02:00
sLog . outString ( "position: `%s`" , pos . ToString (). c_str ());
if ( flags & MOVEMENTFLAG_ONTRANSPORT )
{
sLog . outString ( "TRANSPORT:" );
sLog . outString ( "guid: " UI64FMTD , t_guid );
sLog . outString ( "position: `%s`" , t_pos . ToString (). c_str ());
sLog . outString ( "seat: %i" , t_seat );
sLog . outString ( "time: %u" , t_time );
if ( flags2 & MOVEMENTFLAG2_INTERPOLATED_MOVEMENT )
sLog . outString ( "time2: %u" , t_time2 );
}
if (( flags & ( MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING )) || ( flags2 & MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING ))
{
sLog . outString ( "pitch: %f" , pitch );
}
sLog . outString ( "fallTime: %u" , fallTime );
if ( flags & MOVEMENTFLAG_JUMPING )
{
sLog . outString ( "j_zspeed: %f j_sinAngle: %f j_cosAngle: %f j_xyspeed: %f" , j_zspeed , j_sinAngle , j_cosAngle , j_xyspeed );
}
if ( flags & MOVEMENTFLAG_SPLINE_ELEVATION )
{
sLog . outString ( "splineElevation: %f" , splineElevation );
}
}
2010-09-12 01:40:27 +02:00
WorldObject :: WorldObject () : WorldLocation (),
2010-08-21 20:08:47 +02:00
m_isWorldObject ( false ), m_name ( "" ), m_isActive ( false ), m_zoneScript ( NULL ),
m_transport ( NULL ), m_currMap ( NULL ), m_InstanceId ( 0 ),
m_phaseMask ( PHASEMASK_NORMAL ), m_notifyflags ( 0 ), m_executed_notifies ( 0 )
{}
2009-10-17 15:51:44 -07:00
2009-02-26 16:29:55 -06:00
void WorldObject :: SetWorldObject ( bool on )
2008-10-27 08:41:55 -05:00
{
2010-04-07 19:14:10 +02:00
if ( ! IsInWorld ())
2009-02-26 16:29:55 -06:00
return ;
2009-10-17 15:51:44 -07:00
2009-04-06 21:14:51 +02:00
GetMap () -> AddObjectToSwitchList ( this , on );
2009-02-26 16:29:55 -06:00
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void WorldObject :: setActive ( bool on )
2008-10-27 08:41:55 -05:00
{
2010-04-07 19:14:10 +02:00
if ( m_isActive == on )
2008-10-27 08:41:55 -05:00
return ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( GetTypeId () == TYPEID_PLAYER )
2008-10-27 08:41:55 -05:00
return ;
2009-10-17 15:51:44 -07:00
2009-03-25 21:32:34 -06:00
m_isActive = on ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( ! IsInWorld ())
2009-03-25 21:32:34 -06:00
return ;
2009-10-17 15:51:44 -07:00
2009-03-25 21:32:34 -06:00
Map * map = FindMap ();
2010-04-07 19:14:10 +02:00
if ( ! map )
2009-03-25 21:32:34 -06:00
return ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( on )
2009-02-25 20:52:20 -06:00
{
2010-04-07 19:14:10 +02:00
if ( GetTypeId () == TYPEID_UNIT )
2010-03-07 18:30:53 +01:00
map -> AddToActive ( this -> ToCreature ());
2010-04-07 19:14:10 +02:00
else if ( GetTypeId () == TYPEID_DYNAMICOBJECT )
2009-02-26 10:42:37 -06:00
map -> AddToActive (( DynamicObject * ) this );
2008-10-27 08:41:55 -05:00
}
2009-03-25 21:32:34 -06:00
else
{
2010-04-07 19:14:10 +02:00
if ( GetTypeId () == TYPEID_UNIT )
2010-03-07 18:30:53 +01:00
map -> RemoveFromActive ( this -> ToCreature ());
2010-04-07 19:14:10 +02:00
else if ( GetTypeId () == TYPEID_DYNAMICOBJECT )
2009-03-25 21:32:34 -06:00
map -> RemoveFromActive (( DynamicObject * ) this );
}
2008-10-27 08:41:55 -05:00
}
2009-10-17 15:51:44 -07:00
2010-04-19 09:26:37 +02:00
void WorldObject :: CleanupsBeforeDelete ( bool /*finalCleanup*/ )
2009-07-01 18:23:36 -05:00
{
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void WorldObject :: _Create ( uint32 guidlow , HighGuid guidhigh , uint32 phaseMask )
2008-10-11 14:16:25 -05:00
{
Object :: _Create ( guidlow , 0 , guidhigh );
2009-01-31 16:38:50 -06:00
m_phaseMask = phaseMask ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 WorldObject :: GetZoneId () const
{
2009-06-16 11:19:59 -05:00
return GetBaseMap () -> GetZoneId ( m_positionX , m_positionY , m_positionZ );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
uint32 WorldObject :: GetAreaId () const
{
2009-06-16 11:19:59 -05:00
return GetBaseMap () -> GetAreaId ( m_positionX , m_positionY , m_positionZ );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-03-11 16:17:37 -06:00
void WorldObject :: GetZoneAndAreaId ( uint32 & zoneid , uint32 & areaid ) const
{
2009-06-16 11:19:59 -05:00
GetBaseMap () -> GetZoneAndAreaId ( zoneid , areaid , m_positionX , m_positionY , m_positionZ );
2009-03-11 16:17:37 -06:00
}
2009-10-17 15:51:44 -07:00
2010-08-08 22:54:58 +06:00
InstanceScript * WorldObject :: GetInstanceScript ()
2008-10-11 14:16:25 -05:00
{
2008-12-24 09:58:26 -06:00
Map * map = GetMap ();
2010-08-08 22:54:58 +06:00
return map -> IsDungeon () ? (( InstanceMap * ) map ) -> GetInstanceScript () : NULL ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
float WorldObject :: GetDistanceZ ( const WorldObject * obj ) const
{
float dz = fabs ( GetPositionZ () - obj -> GetPositionZ ());
float sizefactor = GetObjectSize () + obj -> GetObjectSize ();
float dist = dz - sizefactor ;
2010-04-07 22:59:46 +02:00
return ( dist > 0 ? dist : 0 );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
bool WorldObject :: _IsWithinDist ( WorldObject const * obj , float dist2compare , bool is3D ) const
{
2010-07-30 21:54:46 -07:00
float sizefactor = GetObjectSize () + obj -> GetObjectSize ();
float maxdist = dist2compare + sizefactor ;
if ( m_transport && obj -> GetTransport () && obj -> GetTransport () -> GetGUIDLow () == m_transport -> GetGUIDLow ())
{
2010-08-04 14:39:45 +02:00
float dtx = m_movementInfo . t_pos . m_positionX - obj -> m_movementInfo . t_pos . m_positionX ;
float dty = m_movementInfo . t_pos . m_positionY - obj -> m_movementInfo . t_pos . m_positionY ;
2010-07-30 21:54:46 -07:00
float disttsq = dtx * dtx + dty * dty ;
if ( is3D )
{
2010-08-04 14:39:45 +02:00
float dtz = m_movementInfo . t_pos . m_positionZ - obj -> m_movementInfo . t_pos . m_positionZ ;
2010-07-30 21:54:46 -07:00
disttsq += dtz * dtz ;
}
return disttsq < ( maxdist * maxdist );
}
2008-10-11 14:16:25 -05:00
float dx = GetPositionX () - obj -> GetPositionX ();
float dy = GetPositionY () - obj -> GetPositionY ();
2008-12-06 14:01:44 -06:00
float distsq = dx * dx + dy * dy ;
2010-04-07 19:14:10 +02:00
if ( is3D )
2008-12-06 14:01:44 -06:00
{
float dz = GetPositionZ () - obj -> GetPositionZ ();
distsq += dz * dz ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
return distsq < maxdist * maxdist ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
bool WorldObject :: IsWithinLOSInMap ( const WorldObject * obj ) const
{
if ( ! IsInMap ( obj )) return false ;
float ox , oy , oz ;
obj -> GetPosition ( ox , oy , oz );
2010-04-07 22:59:46 +02:00
return ( IsWithinLOS ( ox , oy , oz ));
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
bool WorldObject :: IsWithinLOS ( float ox , float oy , float oz ) const
2008-10-11 14:16:25 -05:00
{
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 ;
2010-04-07 19:14:10 +02:00
if ( is3D )
2009-05-14 16:50:47 -05:00
{
float dz1 = GetPositionZ () - obj1 -> GetPositionZ ();
distsq1 += dz1 * dz1 ;
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
float dx2 = GetPositionX () - obj2 -> GetPositionX ();
float dy2 = GetPositionY () - obj2 -> GetPositionY ();
float distsq2 = dx2 * dx2 + dy2 * dy2 ;
2010-04-07 19:14:10 +02:00
if ( is3D )
2009-05-14 16:50:47 -05:00
{
float dz2 = GetPositionZ () - obj2 -> GetPositionZ ();
distsq2 += dz2 * dz2 ;
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
return distsq1 < distsq2 ;
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
bool WorldObject :: IsInRange ( WorldObject const * obj , float minRange , float maxRange , bool is3D /* = true */ ) const
{
float dx = GetPositionX () - obj -> GetPositionX ();
float dy = GetPositionY () - obj -> GetPositionY ();
float distsq = dx * dx + dy * dy ;
2010-04-07 19:14:10 +02:00
if ( is3D )
2009-05-14 16:50:47 -05:00
{
float dz = GetPositionZ () - obj -> GetPositionZ ();
distsq += dz * dz ;
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
float sizefactor = GetObjectSize () + obj -> GetObjectSize ();
2009-10-17 15:51:44 -07:00
2009-05-17 10:09:06 -05:00
// check only for real range
2010-04-07 19:14:10 +02:00
if ( minRange > 0.0f )
2009-05-17 10:09:06 -05:00
{
float mindist = minRange + sizefactor ;
2010-04-07 19:14:10 +02:00
if ( distsq < mindist * mindist )
2009-05-17 10:09:06 -05:00
return false ;
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
float maxdist = maxRange + sizefactor ;
return distsq < maxdist * maxdist ;
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
bool WorldObject :: IsInRange2d ( float x , float y , float minRange , float maxRange ) const
{
float dx = GetPositionX () - x ;
float dy = GetPositionY () - y ;
float distsq = dx * dx + dy * dy ;
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
float sizefactor = GetObjectSize ();
2009-10-17 15:51:44 -07:00
2009-05-17 10:09:06 -05:00
// check only for real range
2010-04-07 19:14:10 +02:00
if ( minRange > 0.0f )
2009-05-17 10:09:06 -05:00
{
float mindist = minRange + sizefactor ;
2010-04-07 19:14:10 +02:00
if ( distsq < mindist * mindist )
2009-05-17 10:09:06 -05:00
return false ;
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
float maxdist = maxRange + sizefactor ;
return distsq < maxdist * maxdist ;
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
bool WorldObject :: IsInRange3d ( float x , float y , float z , float minRange , float maxRange ) const
{
float dx = GetPositionX () - x ;
float dy = GetPositionY () - y ;
float dz = GetPositionZ () - z ;
float distsq = dx * dx + dy * dy + dz * dz ;
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
float sizefactor = GetObjectSize ();
2009-10-17 15:51:44 -07:00
2009-05-17 10:09:06 -05:00
// check only for real range
2010-04-07 19:14:10 +02:00
if ( minRange > 0.0f )
2009-05-17 10:09:06 -05:00
{
float mindist = minRange + sizefactor ;
2010-04-07 19:14:10 +02:00
if ( distsq < mindist * mindist )
2009-05-17 10:09:06 -05:00
return false ;
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
float maxdist = maxRange + sizefactor ;
return distsq < maxdist * maxdist ;
}
2009-10-17 15:51:44 -07:00
2010-09-12 01:40:27 +02:00
void Position :: RelocateOffset ( const Position & offset )
2010-08-08 20:32:14 +02:00
{
m_positionX = GetPositionX () + ( offset . GetPositionX () * cos ( GetOrientation ()) + offset . GetPositionY () * sin ( GetOrientation () + M_PI ));
m_positionY = GetPositionY () + ( offset . GetPositionY () * cos ( GetOrientation ()) + offset . GetPositionX () * sin ( GetOrientation ()));
m_positionZ = GetPositionZ () + offset . GetPositionZ ();
m_orientation = GetOrientation () + offset . GetOrientation ();
}
void Position :: GetPositionOffsetTo ( const Position & endPos , Position & retOffset ) const
{
float dx = endPos . GetPositionX () - GetPositionX ();
float dy = endPos . GetPositionY () - GetPositionY ();
retOffset . m_positionX = dx * cos ( GetOrientation ()) + dy * sin ( GetOrientation ());
retOffset . m_positionY = dy * cos ( GetOrientation ()) - dx * sin ( GetOrientation ());
retOffset . m_positionZ = endPos . GetPositionZ () - GetPositionZ ();
retOffset . m_orientation = endPos . GetOrientation () - GetOrientation ();
}
2009-08-29 14:58:45 -05:00
float Position :: GetAngle ( const Position * obj ) const
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( ! obj ) return 0 ;
2010-04-07 22:59:46 +02:00
return GetAngle ( obj -> GetPositionX (), obj -> GetPositionY ());
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// Return angle in range 0..2*pi
2010-04-07 22:59:46 +02:00
float Position :: GetAngle ( const float x , const float y ) const
2008-10-11 14:16:25 -05:00
{
float dx = x - GetPositionX ();
float dy = y - GetPositionY ();
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
float ang = atan2 ( dy , dx );
ang = ( ang >= 0 ) ? ang : 2 * M_PI + ang ;
return ang ;
}
2009-10-17 15:51:44 -07:00
2009-08-29 14:58:45 -05:00
void Position :: GetSinCos ( const float x , const float y , float & vsin , float & vcos ) const
2009-03-23 15:26:13 -06:00
{
float dx = GetPositionX () - x ;
float dy = GetPositionY () - y ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( dx < 0.001f && dy < 0.001f )
2009-03-23 15:26:13 -06:00
{
2010-08-22 12:39:39 -07:00
float angle = ( float ) rand_norm () * static_cast < float > ( 2 * M_PI );
2009-03-23 15:26:13 -06:00
vcos = cos ( angle );
vsin = sin ( angle );
}
else
{
float dist = sqrt (( dx * dx ) + ( dy * dy ));
vcos = dx / dist ;
vsin = dy / dist ;
}
}
2009-10-17 15:51:44 -07:00
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
2010-04-07 19:14:10 +02:00
if ( obj == this )
2009-03-28 16:36:54 -06:00
return true ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// move arc to range 0.. 2*pi
2010-06-24 17:32:50 +02:00
arc = MapManager :: NormalizeOrientation ( arc );
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
float angle = GetAngle ( obj );
2008-10-11 14:16:25 -05:00
angle -= m_orientation ;
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// move angle to range -pi ... +pi
2010-06-24 17:32:50 +02:00
angle = MapManager :: NormalizeOrientation ( angle );
if ( 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
2010-04-07 22:59:46 +02:00
return (( angle >= lborder ) && ( angle <= rborder ));
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-05-09 10:50:41 -05:00
bool WorldObject :: IsInBetween ( const WorldObject * obj1 , const WorldObject * obj2 , float size ) const
{
2010-04-07 19:14:10 +02:00
if ( GetPositionX () > std :: max ( obj1 -> GetPositionX (), obj2 -> GetPositionX ())
2009-05-09 10:50:41 -05:00
|| 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
2010-04-07 19:14:10 +02:00
if ( ! size )
2009-05-09 10:50:41 -05:00
size = GetObjectSize () / 2 ;
2009-10-17 15:51:44 -07:00
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
{
2010-04-07 22:59:46 +02:00
return IsWithinDist ( target , distance ) && HasInArc ( arc , target );
2009-12-17 19:09:40 +01:00
}
bool WorldObject :: isInBack ( WorldObject const * target , float distance , float arc ) const
{
2010-04-07 22:59:46 +02:00
return IsWithinDist ( target , distance ) && ! HasInArc ( 2 * M_PI - arc , target );
2009-12-17 19:09:40 +01:00
}
2009-08-29 23:20:16 -05:00
void WorldObject :: GetRandomPoint ( const Position & pos , float distance , float & rand_x , float & rand_y , float & rand_z ) const
2008-10-11 14:16:25 -05:00
{
2010-04-07 19:14:10 +02:00
if ( ! distance )
2008-10-11 14:16:25 -05:00
{
2009-08-29 23:20:16 -05:00
pos . GetPosition ( rand_x , rand_y , rand_z );
2008-10-11 14:16:25 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
// angle to face `obj` to `this`
2010-08-22 12:39:39 -07:00
float angle = ( float ) rand_norm () * static_cast < float > ( 2 * M_PI );
float new_dist = ( float ) rand_norm () * static_cast < float > ( distance );
2009-10-17 15:51:44 -07:00
2009-08-29 23:20:16 -05:00
rand_x = pos . m_positionX + new_dist * cos ( angle );
rand_y = pos . m_positionY + new_dist * sin ( angle );
rand_z = pos . m_positionZ ;
2009-10-17 15:51:44 -07:00
2008-10-14 11:57:03 -05:00
Trinity :: NormalizeMapCoord ( rand_x );
Trinity :: NormalizeMapCoord ( rand_y );
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 );
2010-04-07 19:14:10 +02:00
if ( new_z > INVALID_HEIGHT )
2008-10-11 14:16:25 -05:00
z = new_z + 0.05f ; // just to be sure that we are not a few pixel under the surface
}
2009-10-17 15:51:44 -07:00
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 );
2010-08-23 19:56:47 -07:00
SendMessageToSetInRange ( & data , sWorld . getFloatConfig ( CONFIG_LISTEN_RANGE_SAY ), true );
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 ( const char * text , uint32 language , uint64 TargetGuid )
{
WorldPacket data ( SMSG_MESSAGECHAT , 200 );
BuildMonsterChat ( & data , CHAT_MSG_MONSTER_YELL , text , language , GetName (), TargetGuid );
2010-08-23 19:56:47 -07:00
SendMessageToSetInRange ( & data , sWorld . getFloatConfig ( CONFIG_LISTEN_RANGE_YELL ), true );
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 :: 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 );
2010-08-23 19:56:47 -07:00
SendMessageToSetInRange ( & data , sWorld . getFloatConfig ( CONFIG_LISTEN_RANGE_TEXTEMOTE ), true );
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 ( const char * text , uint64 receiver , bool IsBossWhisper )
{
2010-08-08 05:25:45 +02:00
Player * player = sObjectMgr . GetPlayer ( receiver );
2010-04-07 19:14:10 +02:00
if ( ! player || ! player -> GetSession ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
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 )
2010-04-07 22:59:46 +02:00
this -> ToPlayer () -> GetSession () -> SendPacket ( & data );
2008-10-11 14:16:25 -05:00
else
2010-04-07 22:59:46 +02:00
SendMessageToSet ( & data , true ); // ToSelf ignored in this case
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-01-15 21:29:32 -05:00
void Object :: ForceValuesUpdateAtIndex ( uint32 i )
{
m_uint32Values_mirror [ i ] = GetUInt32Value ( i ) + 1 ; // makes server think the field changed
2010-04-07 19:14:10 +02:00
if ( m_inWorld )
2009-03-31 09:18:39 -06:00
{
2010-04-07 19:14:10 +02:00
if ( ! m_objectUpdated )
2009-03-31 09:18:39 -06:00
{
2010-06-25 00:18:01 +02:00
sObjectAccessor . AddUpdateObject ( this );
2009-01-15 21:29:32 -05:00
m_objectUpdated = true ;
}
2009-03-31 09:18:39 -06:00
}
2009-01-15 21:29:32 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-14 11:57:03 -05:00
namespace Trinity
2008-10-11 14:16:25 -05:00
{
2009-02-21 17:00:47 -06:00
class MonsterChatBuilder
2008-10-11 14:16:25 -05:00
{
public :
2009-02-21 17:00:47 -06:00
MonsterChatBuilder ( WorldObject const & obj , ChatMsg msgtype , int32 textId , uint32 language , uint64 targetGUID )
: i_object ( obj ), i_msgtype ( msgtype ), i_textId ( textId ), i_language ( language ), i_targetGUID ( targetGUID ) {}
2010-09-17 07:04:29 +02:00
void operator ()( WorldPacket & data , LocaleConstant loc_idx )
2008-10-11 14:16:25 -05:00
{
2010-08-08 05:25:45 +02:00
char const * text = sObjectMgr . GetTrinityString ( i_textId , loc_idx );
2009-10-17 15:51:44 -07:00
2009-02-21 17:00:47 -06:00
// TODO: i_object.GetName() also must be localized?
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-12-20 15:20:04 +01:00
Trinity :: MonsterChatBuilder say_build ( * this , CHAT_MSG_MONSTER_SAY , textId , language , TargetGuid );
Trinity :: LocalizedPacketDo < Trinity :: MonsterChatBuilder > say_do ( say_build );
2010-08-23 19:56:47 -07:00
Trinity :: PlayerDistWorker < Trinity :: LocalizedPacketDo < Trinity :: MonsterChatBuilder > > say_worker ( this , sWorld . getFloatConfig ( CONFIG_LISTEN_RANGE_SAY ), say_do );
2009-12-20 15:20:04 +01:00
TypeContainerVisitor < Trinity :: PlayerDistWorker < Trinity :: LocalizedPacketDo < Trinity :: MonsterChatBuilder > > , WorldTypeMapContainer > message ( say_worker );
2010-08-23 19:56:47 -07:00
cell . Visit ( p , message , * GetMap (), * this , sWorld . getFloatConfig ( CONFIG_LISTEN_RANGE_SAY ));
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
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-12-20 15:20:04 +01:00
Trinity :: MonsterChatBuilder say_build ( * this , CHAT_MSG_MONSTER_YELL , textId , language , TargetGuid );
Trinity :: LocalizedPacketDo < Trinity :: MonsterChatBuilder > say_do ( say_build );
2010-08-23 19:56:47 -07:00
Trinity :: PlayerDistWorker < Trinity :: LocalizedPacketDo < Trinity :: MonsterChatBuilder > > say_worker ( this , sWorld . getFloatConfig ( CONFIG_LISTEN_RANGE_YELL ), say_do );
2009-12-20 15:20:04 +01:00
TypeContainerVisitor < Trinity :: PlayerDistWorker < Trinity :: LocalizedPacketDo < Trinity :: MonsterChatBuilder > > , WorldTypeMapContainer > message ( say_worker );
2010-08-23 19:56:47 -07:00
cell . Visit ( p , message , * GetMap (), * this , sWorld . getFloatConfig ( CONFIG_LISTEN_RANGE_YELL ));
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-03-28 18:03:56 -06:00
void WorldObject :: MonsterYellToZone ( int32 textId , uint32 language , uint64 TargetGuid )
{
2009-12-20 15:20:04 +01:00
Trinity :: MonsterChatBuilder say_build ( * this , CHAT_MSG_MONSTER_YELL , textId , language , TargetGuid );
Trinity :: LocalizedPacketDo < Trinity :: MonsterChatBuilder > say_do ( say_build );
2009-10-17 15:51:44 -07:00
2009-03-29 17:15:37 -06:00
uint32 zoneid = GetZoneId ();
2009-10-17 15:51:44 -07:00
2009-03-29 17:15:37 -06:00
Map :: PlayerList const & pList = GetMap () -> GetPlayers ();
2009-10-17 16:20:24 -07:00
for ( Map :: PlayerList :: const_iterator itr = pList . begin (); itr != pList . end (); ++ itr )
2010-04-07 23:25:02 +02:00
if ( itr -> getSource () -> GetZoneId () == zoneid )
2009-03-29 17:15:37 -06:00
say_do ( itr -> getSource ());
2009-03-28 18:03:56 -06:00
}
2009-10-17 15:51:44 -07:00
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-12-20 15:20:04 +01:00
Trinity :: MonsterChatBuilder say_build ( * this , IsBossEmote ? CHAT_MSG_RAID_BOSS_EMOTE : CHAT_MSG_MONSTER_EMOTE , textId , LANG_UNIVERSAL , TargetGuid );
Trinity :: LocalizedPacketDo < Trinity :: MonsterChatBuilder > say_do ( say_build );
2010-08-23 19:56:47 -07:00
Trinity :: PlayerDistWorker < Trinity :: LocalizedPacketDo < Trinity :: MonsterChatBuilder > > say_worker ( this , sWorld . getFloatConfig ( CONFIG_LISTEN_RANGE_TEXTEMOTE ), say_do );
2009-12-20 15:20:04 +01:00
TypeContainerVisitor < Trinity :: PlayerDistWorker < Trinity :: LocalizedPacketDo < Trinity :: MonsterChatBuilder > > , WorldTypeMapContainer > message ( say_worker );
2010-08-23 19:56:47 -07:00
cell . Visit ( p , message , * GetMap (), * this , sWorld . getFloatConfig ( CONFIG_LISTEN_RANGE_TEXTEMOTE ));
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void WorldObject :: MonsterWhisper ( int32 textId , uint64 receiver , bool IsBossWhisper )
{
2010-08-08 05:25:45 +02:00
Player * player = sObjectMgr . GetPlayer ( receiver );
2010-04-07 19:14:10 +02:00
if ( ! player || ! player -> GetSession ())
2008-10-11 14:16:25 -05:00
return ;
2009-10-17 15:51:44 -07:00
2010-09-17 07:04:29 +02:00
LocaleConstant loc_idx = player -> GetSession () -> GetSessionDbLocaleIndex ();
2010-08-27 00:57:49 +06:00
char const * text = sObjectMgr . GetTrinityString ( textId , loc_idx );
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
WorldPacket data ( SMSG_MESSAGECHAT , 200 );
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
2010-04-07 22:59:46 +02:00
if ( targetGuid && ! IS_PLAYER_GUID ( targetGuid ))
2008-10-11 14:16:25 -05:00
{
* data << ( uint32 ) 1 ; // target name length
* data << ( uint8 ) 0 ; // target name
}
2009-07-20 11:53:26 +08:00
* data << ( uint32 )( strlen ( text ) + 1 );
2008-10-11 14:16:25 -05:00
* data << text ;
* data << ( uint8 ) 0 ; // ChatTag
}
2009-10-17 15:51:44 -07:00
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
2010-04-04 03:46:38 +03:00
void WorldObject :: SendMessageToSet ( WorldPacket * data , Player const * skipped_rcvr )
{
Trinity :: MessageDistDeliverer notifier ( this , data , GetMap () -> GetVisibilityDistance (), false , skipped_rcvr );
VisitNearbyWorldObject ( GetMap () -> GetVisibilityDistance (), notifier );
}
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 );
2010-04-07 19:14:10 +02:00
if ( m_currMap == map ) // command add npc: first create, than loadfromdb
2009-08-12 13:03:44 -05:00
return ;
2010-04-07 19:14:10 +02:00
if ( m_currMap )
2009-08-26 19:35:20 -05:00
{
sLog . outCrash ( "WorldObject::SetMap: obj %u new map %u %u, old map %u %u" , ( uint32 ) GetTypeId (), map -> GetId (), map -> GetInstanceId (), m_currMap -> GetId (), m_currMap -> GetInstanceId ());
2010-07-30 20:04:28 +02:00
ASSERT ( false );
2009-08-26 19:35:20 -05:00
}
2009-07-16 11:49:00 +08:00
m_currMap = map ;
2009-08-25 11:42:18 -05:00
m_mapId = map -> GetId ();
m_InstanceId = map -> GetInstanceId ();
2010-04-07 19:14:10 +02:00
if ( m_isWorldObject )
2009-08-11 16:33:33 -05:00
m_currMap -> AddWorldObject ( this );
2009-03-24 09:06:49 -06:00
}
2009-10-17 15:51:44 -07:00
2009-08-10 23:47:47 -05:00
void WorldObject :: ResetMap ()
{
ASSERT ( m_currMap );
2009-08-12 23:12:33 -05:00
ASSERT ( ! IsInWorld ());
2010-04-07 19:14:10 +02:00
if ( m_isWorldObject )
2009-08-11 16:33:33 -05:00
m_currMap -> RemoveWorldObject ( this );
2009-08-10 23:47:47 -05:00
m_currMap = NULL ;
2009-08-25 19:22:45 -05:00
//maybe not for corpse
//m_mapId = 0;
//m_InstanceId = 0;
2009-08-10 23:47:47 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
Map const * WorldObject :: GetBaseMap () const
{
2009-07-16 11:49:00 +08:00
ASSERT ( m_currMap );
return m_currMap -> GetParent ();
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2008-10-11 14:16:25 -05:00
void WorldObject :: AddObjectToRemoveList ()
{
2010-07-30 20:04:28 +02:00
ASSERT ( m_uint32Values );
2009-10-17 15:51:44 -07:00
2009-04-08 17:23:57 -05:00
Map * map = FindMap ();
2010-04-07 19:14:10 +02:00
if ( ! map )
2008-10-11 14:16:25 -05:00
{
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 ;
2010-04-07 19:14:10 +02:00
if ( properties )
2009-03-20 14:01:46 -06:00
{
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 :
2010-04-07 19:14:10 +02:00
if ( properties -> Flags & 512 ) // Mirror Image, Summon Gargoyle
2009-08-26 19:28:21 -05:00
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 ;
2010-04-07 19:14:10 +02:00
if ( summoner )
2009-03-20 14:01:46 -06:00
{
phase = summoner -> GetPhaseMask ();
2010-04-07 19:14:10 +02:00
if ( summoner -> GetTypeId () == TYPEID_PLAYER )
2010-03-07 15:20:19 +01:00
team = summoner -> ToPlayer () -> GetTeam ();
2009-03-20 14:01:46 -06:00
}
2009-10-17 15:51:44 -07:00
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
2010-08-08 05:25:45 +02:00
if ( ! summon -> Create ( sObjectMgr . GenerateLowGuid ( HIGHGUID_UNIT ), this , phase , entry , vehId , team , pos . GetPositionX (), pos . GetPositionY (), pos . GetPositionZ (), pos . GetOrientation ()))
2008-10-11 14:16:25 -05:00
{
2009-03-20 14:01:46 -06:00
delete summon ;
2008-10-11 14:16:25 -05:00
return NULL ;
}
2009-10-17 15:51:44 -07:00
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 );
2010-03-07 18:30:53 +01:00
Add ( summon -> ToCreature ());
2009-05-06 13:34:11 -05:00
summon -> InitSummon ();
2009-10-17 15:51:44 -07:00
2009-05-03 11:06:48 -05:00
//ObjectAccessor::UpdateObjectVisibility(summon);
2009-10-17 15:51:44 -07:00
2009-03-20 14:01:46 -06:00
return summon ;
}
2009-10-17 15:51:44 -07:00
2009-05-30 22:15:05 -05:00
void WorldObject :: SetZoneScript ()
{
2010-04-07 19:14:10 +02:00
if ( Map * map = FindMap ())
2009-05-30 22:15:05 -05:00
{
2010-04-07 19:14:10 +02:00
if ( map -> IsDungeon ())
2010-08-08 22:54:58 +06:00
m_zoneScript = ( ZoneScript * )(( InstanceMap * ) map ) -> GetInstanceScript ();
2010-08-08 04:37:24 +02:00
else if ( ! map -> IsBattlegroundOrArena ())
2009-05-30 22:15:05 -05:00
m_zoneScript = sOutdoorPvPMgr . GetZoneScript ( GetZoneId ());
}
}
2009-10-17 15:51:44 -07:00
2010-04-19 09:26:37 +02:00
TempSummon * WorldObject :: SummonCreature ( uint32 entry , const Position & pos , TempSummonType spwtype , uint32 duration , uint32 /*vehId*/ ) const
2009-03-20 14:01:46 -06:00
{
2010-04-07 19:14:10 +02:00
if ( Map * map = FindMap ())
2009-08-29 14:58:45 -05:00
{
2010-04-07 19:14:10 +02:00
if ( TempSummon * summon = map -> SummonCreature ( entry , pos , NULL , duration , isType ( TYPEMASK_UNIT ) ? ( Unit * ) this : NULL ))
2009-08-29 14:58:45 -05:00
{
summon -> SetTempSummonType ( spwtype );
return summon ;
}
}
2009-10-17 15:51:44 -07:00
2009-08-29 14:58:45 -05:00
return NULL ;
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2009-02-19 18:30:03 -06:00
Pet * Player :: SummonPet ( uint32 entry , float x , float y , float z , float ang , PetType petType , uint32 duration )
{
2009-03-25 21:32:34 -06:00
Pet * pet = new Pet ( this , petType );
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( petType == SUMMON_PET && pet -> LoadPetFromDB ( this , entry ))
2009-02-24 20:05:29 -06:00
{
2009-02-24 20:52:55 -06:00
// Remove Demonic Sacrifice auras (known pet)
2010-01-10 01:23:15 +01:00
Unit :: AuraEffectList const & auraClassScripts = GetAuraEffectsByType ( SPELL_AURA_OVERRIDE_CLASS_SCRIPTS );
2010-04-08 08:20:08 +02:00
for ( Unit :: AuraEffectList :: const_iterator itr = auraClassScripts . begin (); itr != auraClassScripts . end ();)
2009-02-24 20:52:55 -06:00
{
2010-04-07 23:25:02 +02:00
if (( * itr ) -> GetMiscValue () == 2228 )
2009-02-24 20:52:55 -06:00
{
RemoveAurasDueToSpell (( * itr ) -> GetId ());
itr = auraClassScripts . begin ();
}
else
++ itr ;
}
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( duration > 0 )
2009-02-24 20:05:29 -06:00
pet -> SetDuration ( duration );
2009-10-17 15:51:44 -07:00
2009-02-24 20:52:55 -06:00
return NULL ;
}
2009-10-17 15:51:44 -07:00
2010-04-07 23:25:02 +02:00
// petentry == 0 for hunter "call pet" (current pet summoned if any)
2010-04-07 19:14:10 +02:00
if ( ! entry )
2009-02-24 20:52:55 -06:00
{
delete pet ;
2009-02-24 20:05:29 -06:00
return NULL ;
}
2009-10-17 15:51:44 -07:00
2009-08-26 19:28:21 -05:00
pet -> Relocate ( x , y , z , ang );
2010-04-07 19:14:10 +02:00
if ( ! pet -> IsPositionValid ())
2009-02-19 18:30:03 -06:00
{
2010-07-31 03:12:51 +02:00
sLog . outError ( "Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)" , pet -> GetGUIDLow (), pet -> GetEntry (), pet -> GetPositionX (), pet -> GetPositionY ());
2009-02-24 20:05:29 -06:00
delete pet ;
2009-02-19 18:30:03 -06:00
return NULL ;
}
2009-10-17 15:51:44 -07:00
2009-08-26 19:28:21 -05:00
Map * map = GetMap ();
2010-08-08 05:25:45 +02:00
uint32 pet_number = sObjectMgr . GeneratePetNumber ();
if ( ! pet -> Create ( sObjectMgr . GenerateLowGuid ( HIGHGUID_PET ), map , GetPhaseMask (), entry , pet_number ))
2009-02-19 18:30:03 -06:00
{
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 );
2010-08-26 01:20:57 +06:00
pet -> SetFullHealth ();
2009-02-24 20:52:55 -06:00
pet -> SetPower ( POWER_MANA , pet -> GetMaxPower ( POWER_MANA ));
2010-09-03 21:55:57 -07:00
pet -> SetUInt32Value ( UNIT_FIELD_PET_NAME_TIMESTAMP , uint32 ( time ( NULL ))); // cast can't be helped in this case
2009-05-06 13:34:11 -05:00
break ;
2010-08-21 20:08:47 +02:00
default :
break ;
2009-05-06 13:34:11 -05:00
}
2009-10-17 15:51:44 -07:00
2010-03-07 18:30:53 +01:00
map -> Add ( pet -> ToCreature ());
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 ;
2010-08-21 20:08:47 +02:00
default :
break ;
2009-02-24 20:52:55 -06:00
}
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( petType == SUMMON_PET )
2009-02-24 20:52:55 -06:00
{
// Remove Demonic Sacrifice auras (known pet)
2010-01-10 01:23:15 +01:00
Unit :: AuraEffectList const & auraClassScripts = GetAuraEffectsByType ( SPELL_AURA_OVERRIDE_CLASS_SCRIPTS );
2010-04-08 08:20:08 +02:00
for ( Unit :: AuraEffectList :: const_iterator itr = auraClassScripts . begin (); itr != auraClassScripts . end ();)
2009-02-24 20:52:55 -06:00
{
2010-04-07 23:25:02 +02:00
if (( * itr ) -> GetMiscValue () == 2228 )
2009-02-24 20:52:55 -06:00
{
RemoveAurasDueToSpell (( * itr ) -> GetId ());
itr = auraClassScripts . begin ();
}
else
++ itr ;
}
2009-02-24 20:05:29 -06:00
}
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( duration > 0 )
2009-02-24 20:52:55 -06:00
pet -> SetDuration ( duration );
2009-10-17 15:51:44 -07:00
2009-05-03 11:06:48 -05:00
//ObjectAccessor::UpdateObjectVisibility(pet);
2009-10-17 15:51:44 -07:00
2009-02-24 20:05:29 -06:00
return pet ;
2009-02-19 18:30:03 -06:00
}
2009-10-17 15:51:44 -07:00
2008-10-17 18:13:04 -05:00
GameObject * WorldObject :: SummonGameObject ( uint32 entry , float x , float y , float z , float ang , float rotation0 , float rotation1 , float rotation2 , float rotation3 , uint32 respawnTime )
{
2010-04-07 19:14:10 +02:00
if ( ! IsInWorld ())
2008-10-17 18:13:04 -05:00
return NULL ;
2009-10-17 15:51:44 -07:00
2010-08-08 05:25:45 +02:00
GameObjectInfo const * goinfo = sObjectMgr . GetGameObjectInfo ( entry );
2010-04-07 19:14:10 +02:00
if ( ! goinfo )
2008-10-17 18:13:04 -05:00
{
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 ();
2010-08-08 05:25:45 +02:00
if ( ! go -> Create ( sObjectMgr . GenerateLowGuid ( HIGHGUID_GAMEOBJECT ), entry , map , GetPhaseMask (), x , y , z , ang , rotation0 , rotation1 , rotation2 , rotation3 , 100 , GO_STATE_READY ))
2009-04-01 21:17:59 -06:00
{
delete go ;
2008-10-17 18:13:04 -05:00
return NULL ;
2009-04-01 21:17:59 -06:00
}
2008-10-17 18:13:04 -05:00
go -> SetRespawnTime ( respawnTime );
2010-04-07 19:14:10 +02:00
if ( GetTypeId () == TYPEID_PLAYER || GetTypeId () == TYPEID_UNIT ) //not sure how to handle this
2008-10-18 19:59:34 -05:00
(( Unit * ) this ) -> AddGameObject ( go );
else
go -> SetSpawnedByDefault ( false );
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 );
2010-04-07 19:14:10 +02:00
if ( ! summon )
2008-12-10 20:25:47 -06:00
return NULL ;
2009-10-17 15:51:44 -07:00
2008-12-10 20:25:47 -06:00
//summon->SetName(GetName());
2010-04-07 19:14:10 +02:00
if ( GetTypeId () == TYPEID_PLAYER || GetTypeId () == TYPEID_UNIT )
2008-12-10 20:25:47 -06:00
{
summon -> setFaction ((( Unit * ) this ) -> getFaction ());
summon -> SetLevel ((( Unit * ) this ) -> getLevel ());
}
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( GetAI )
2008-12-10 20:25:47 -06:00
summon -> AIM_Initialize ( GetAI ( summon ));
return summon ;
}
2009-10-17 15:51:44 -07:00
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 );
2010-08-26 22:05:57 +02:00
VisitNearbyGridObject ( range , searcher );
2009-12-17 11:40:23 +01:00
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 );
2010-01-23 22:24:41 +01:00
cell . Visit ( pair , 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
2010-01-23 22:24:41 +01:00
cell . Visit ( pair , 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
/*
2009-12-20 15:20:04 +01:00
namespace Trinity
2009-05-14 16:50:47 -05:00
{
class NearUsedPosDo
{
public:
NearUsedPosDo(WorldObject const& obj, WorldObject const* searcher, float angle, ObjectPosSelector& selector)
: i_object(obj), i_searcher(searcher), i_angle(angle), i_selector(selector) {}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
void operator()(Corpse*) const {}
void operator()(DynamicObject*) const {}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
void operator()(Creature* c) const
{
// skip self or target
2010-04-07 23:25:02 +02:00
if (c == i_searcher || c == &i_object)
2009-05-14 16:50:47 -05:00
return;
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
float x,y,z;
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
if (!c->isAlive() || c->hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED) ||
!c->GetMotionMaster()->GetDestination(x,y,z))
2009-05-14 16:50:47 -05:00
{
x = c->GetPositionX();
y = c->GetPositionY();
}
2009-10-17 15:51:44 -07:00
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
2010-04-07 23:25:02 +02:00
if (u == i_searcher || u == &i_object)
2009-05-14 16:50:47 -05:00
return;
2009-10-17 15:51:44 -07:00
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
2010-04-07 19:14:10 +02:00
if (!i_object.IsInRange2d(x,y,i_selector.m_dist - i_selector.m_size,i_selector.m_dist + i_selector.m_size))
2009-05-14 16:50:47 -05:00
return;
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
float angle = i_object.GetAngle(u)-i_angle;
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
// move angle to range -pi ... +pi
2010-04-07 22:59:46 +02:00
while (angle > M_PI)
2009-05-14 16:50:47 -05:00
angle -= 2.0f * M_PI;
2010-04-07 19:13:19 +02:00
while (angle < -M_PI)
2009-05-14 16:50:47 -05:00
angle += 2.0f * M_PI;
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
// dist include size of u
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;
};
2009-12-20 15:20:04 +01:00
} // namespace Trinity
2009-05-14 16:50:47 -05:00
*/
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
//===================================================================================================
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void WorldObject :: GetNearPoint2D ( float & x , float & y , float distance2d , float absAngle ) const
2008-10-11 14:16:25 -05:00
{
x = GetPositionX () + ( GetObjectSize () + distance2d ) * cos ( absAngle );
y = GetPositionY () + ( GetObjectSize () + distance2d ) * sin ( absAngle );
2009-10-17 15:51:44 -07:00
2008-10-14 11:57:03 -05:00
Trinity :: NormalizeMapCoord ( x );
Trinity :: NormalizeMapCoord ( y );
2008-10-11 14:16:25 -05:00
}
2009-10-17 15:51:44 -07:00
2010-04-19 09:26:37 +02:00
void WorldObject :: GetNearPoint ( WorldObject const * /*searcher*/ , float & x , float & y , float & z , float searcher_size , float distance2d , float absAngle ) const
2008-10-11 14:16:25 -05:00
{
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
2010-08-23 19:56:47 -07:00
if (!sWorld.getIntConfig(CONFIG_DETECT_POS_COLLISION))
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
// 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
{
2009-12-20 15:20:04 +01:00
CellPair p(Trinity::ComputeCellPair(GetPositionX(), GetPositionY()));
2009-05-14 16:50:47 -05:00
Cell cell(p);
cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate();
2009-10-17 15:51:44 -07:00
2009-12-20 15:20:04 +01:00
Trinity::NearUsedPosDo u_do(*this,searcher,absAngle,selector);
Trinity::WorldObjectWorker<Trinity::NearUsedPosDo> worker(this,u_do);
2009-10-17 15:51:44 -07:00
2009-12-20 15:20:04 +01:00
TypeContainerVisitor<Trinity::WorldObjectWorker<Trinity::NearUsedPosDo>, GridTypeMapContainer > grid_obj_worker(worker);
TypeContainerVisitor<Trinity::WorldObjectWorker<Trinity::NearUsedPosDo>, WorldTypeMapContainer > world_obj_worker(worker);
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
CellLock<GridReadGuard> cell_lock(cell, p);
2009-09-27 02:24:25 -07:00
cell_lock->Visit(cell_lock, grid_obj_worker, *GetMap(), *this, distance2d);
cell_lock->Visit(cell_lock, world_obj_worker, *GetMap(), *this, distance2d);
2009-05-14 16:50:47 -05:00
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
// maybe can just place in primary position
2010-04-07 22:59:46 +02:00
if (selector.CheckOriginal())
2009-05-14 16:50:47 -05:00
{
UpdateGroundPositionZ(x,y,z); // update to LOS height if available
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if (IsWithinLOS(x,y,z))
2009-05-14 16:50:47 -05:00
return;
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
first_los_conflict = true; // first point have LOS problems
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
float angle; // candidate of angle for free pos
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
// special case when one from list empty and then empty side preferred
2010-04-07 19:14:10 +02:00
if (selector.FirstAngle(angle))
2009-05-14 16:50:47 -05:00
{
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
2010-04-07 19:14:10 +02:00
if (IsWithinLOS(x,y,z))
2009-05-14 16:50:47 -05:00
return;
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
// set first used pos in lists
selector.InitializeAngle();
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
// select in positions after current nodes (selection one by one)
2010-04-07 19:13:19 +02:00
while (selector.NextAngle(angle)) // angle for free pos
2009-05-14 16:50:47 -05:00
{
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
2010-04-07 19:14:10 +02:00
if (IsWithinLOS(x,y,z))
2009-05-14 16:50:47 -05:00
return;
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
// BAD NEWS: not free pos (or used or have LOS problems)
// Attempt find _used_ pos without LOS problem
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if (!first_los_conflict)
2009-05-14 16:50:47 -05:00
{
x = first_x;
y = first_y;
2009-10-17 15:51:44 -07:00
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
2010-04-07 22:59:46 +02:00
if (selector.IsNonBalanced())
2009-05-14 16:50:47 -05:00
{
2010-04-07 19:14:10 +02:00
if (!selector.FirstAngle(angle)) // _used_ pos
2009-05-14 16:50:47 -05:00
{
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
2010-04-07 19:14:10 +02:00
if (IsWithinLOS(x,y,z))
2009-05-14 16:50:47 -05:00
return;
}
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
// set first used pos in lists
selector.InitializeAngle();
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
// select in positions after current nodes (selection one by one)
2010-04-07 19:13:19 +02:00
while (selector.NextUsedAngle(angle)) // angle for used pos but maybe without LOS problem
2009-05-14 16:50:47 -05:00
{
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
2010-04-07 19:14:10 +02:00
if (IsWithinLOS(x,y,z))
2009-05-14 16:50:47 -05:00
return;
}
2009-10-17 15:51:44 -07:00
2009-05-14 16:50:47 -05:00
// BAD BAD NEWS: all found pos (free and used) have LOS problem :(
x = first_x;
y = first_y;
2009-10-17 15:51:44 -07:00
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
2010-07-21 02:06:51 +02:00
void WorldObject :: MovePositionToFirstCollision ( Position & pos , float dist , float angle )
{
angle += m_orientation ;
float destx , desty , destz , ground , floor ;
destx = pos . m_positionX + dist * cos ( angle );
desty = pos . m_positionY + dist * sin ( angle );
ground = GetMap () -> GetHeight ( destx , desty , MAX_HEIGHT , true );
floor = GetMap () -> GetHeight ( destx , desty , pos . m_positionZ , true );
destz = fabs ( ground - pos . m_positionZ ) <= fabs ( floor - pos . m_positionZ ) ? ground : floor ;
bool col = VMAP :: VMapFactory :: createOrGetVMapManager () -> getObjectHitPos ( GetMapId (), pos . m_positionX , pos . m_positionY , pos . m_positionZ + 0.5f , destx , desty , destz + 0.5f , destx , desty , destz , - 0.5f );
// collision occured
if ( col )
{
// move back a bit
destx -= CONTACT_DISTANCE * cos ( angle );
desty -= CONTACT_DISTANCE * sin ( angle );
dist = sqrt (( pos . m_positionX - destx ) * ( pos . m_positionX - destx ) + ( pos . m_positionY - desty ) * ( pos . m_positionY - desty ));
}
float step = dist / 10.0f ;
2010-08-30 15:25:15 +02:00
for ( uint8 j = 0 ; j < 10 ; ++ j )
2010-07-21 02:06:51 +02:00
{
// do not allow too big z changes
if ( fabs ( pos . m_positionZ - destz ) > 6 )
{
destx -= step * cos ( angle );
desty -= step * sin ( angle );
ground = GetMap () -> GetHeight ( destx , desty , MAX_HEIGHT , true );
floor = GetMap () -> GetHeight ( destx , desty , pos . m_positionZ , true );
destz = fabs ( ground - pos . m_positionZ ) <= fabs ( floor - pos . m_positionZ ) ? ground : floor ;
}
// we have correct destz now
else
{
pos . Relocate ( destx , desty , destz );
break ;
}
}
Trinity :: NormalizeMapCoord ( pos . m_positionX );
Trinity :: NormalizeMapCoord ( pos . m_positionY );
UpdateGroundPositionZ ( pos . m_positionX , pos . m_positionY , pos . m_positionZ );
pos . m_orientation = m_orientation ;
}
2009-01-31 16:38:50 -06:00
void WorldObject :: SetPhaseMask ( uint32 newPhaseMask , bool update )
{
m_phaseMask = newPhaseMask ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( update && IsInWorld ())
2010-02-03 16:53:40 +02:00
UpdateObjectVisibility ();
2009-01-31 16:38:50 -06:00
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void WorldObject :: PlayDistanceSound ( uint32 sound_id , Player * target /*= NULL*/ )
2009-03-22 19:20:03 -06:00
{
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 )
2010-04-07 22:59:46 +02:00
target -> SendDirectMessage ( & data );
2009-03-22 19:20:03 -06:00
else
2010-04-07 22:59:46 +02:00
SendMessageToSet ( & data , true );
2009-03-22 19:20:03 -06:00
}
2009-10-17 15:51:44 -07:00
2010-04-07 22:59:46 +02:00
void WorldObject :: PlayDirectSound ( uint32 sound_id , Player * target /*= NULL*/ )
2009-03-22 19:20:03 -06:00
{
WorldPacket data ( SMSG_PLAY_SOUND , 4 );
data << uint32 ( sound_id );
if ( target )
2010-04-07 22:59:46 +02:00
target -> SendDirectMessage ( & data );
2009-03-22 19:20:03 -06:00
else
2010-04-07 22:59:46 +02:00
SendMessageToSet ( & data , true );
2009-03-22 19:20:03 -06:00
}
2009-10-17 15:51:44 -07:00
2009-08-28 14:19:14 -05:00
void WorldObject :: DestroyForNearbyPlayers ()
{
2010-04-07 19:14:10 +02:00
if ( ! IsInWorld ())
2009-08-28 14:19:14 -05:00
return ;
2009-10-17 15:51:44 -07:00
2010-03-14 00:22:53 +01:00
std :: list < Player *> targets ;
Trinity :: AnyPlayerInObjectRangeCheck check ( this , GetMap () -> GetVisibilityDistance ());
Trinity :: PlayerListSearcher < Trinity :: AnyPlayerInObjectRangeCheck > searcher ( this , targets , check );
2009-09-27 02:24:25 -07:00
VisitNearbyWorldObject ( GetMap () -> GetVisibilityDistance (), searcher );
2010-03-14 00:22:53 +01:00
for ( std :: list < Player *>:: const_iterator iter = targets . begin (); iter != targets . end (); ++ iter )
2009-08-28 14:19:14 -05:00
{
2010-03-14 00:22:53 +01:00
Player * plr = ( * iter );
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( plr == this )
2009-08-28 14:19:14 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( ! plr -> HaveAtClient ( this ))
2009-08-28 14:19:14 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( isType ( TYPEMASK_UNIT ) && (( Unit * ) this ) -> GetCharmerGUID () == plr -> GetGUID ()) // TODO: this is for puppet
2009-08-28 14:19:14 -05:00
continue ;
2009-10-17 16:20:24 -07:00
DestroyForPlayer ( plr );
plr -> m_clientGUIDs . erase ( GetGUID ());
2009-08-28 14:19:14 -05:00
}
}
2010-02-03 16:53:40 +02:00
2010-02-27 15:25:14 +02:00
void WorldObject :: UpdateObjectVisibility ( bool /*forced*/ )
2010-02-03 16:53:40 +02:00
{
2010-02-27 15:25:14 +02:00
//updates object's visibility for nearby players
Trinity :: VisibleChangesNotifier notifier ( * this );
VisitNearbyWorldObject ( GetMap () -> GetVisibilityDistance (), notifier );
2010-02-03 16:53:40 +02:00
}
struct WorldObjectChangeAccumulator
{
UpdateDataMapType & i_updateDatas ;
WorldObject & i_object ;
std :: set < uint64 > plr_list ;
WorldObjectChangeAccumulator ( WorldObject & obj , UpdateDataMapType & d ) : i_updateDatas ( d ), i_object ( obj ) {}
void Visit ( PlayerMapType & m )
{
for ( PlayerMapType :: iterator iter = m . begin (); iter != m . end (); ++ iter )
{
BuildPacket ( iter -> getSource ());
if ( ! iter -> getSource () -> GetSharedVisionList (). empty ())
{
SharedVisionList :: const_iterator it = iter -> getSource () -> GetSharedVisionList (). begin ();
for (; it != iter -> getSource () -> GetSharedVisionList (). end (); ++ it )
BuildPacket ( * it );
}
}
}
void Visit ( CreatureMapType & m )
{
for ( CreatureMapType :: iterator iter = m . begin (); iter != m . end (); ++ iter )
{
if ( ! iter -> getSource () -> GetSharedVisionList (). empty ())
{
SharedVisionList :: const_iterator it = iter -> getSource () -> GetSharedVisionList (). begin ();
for (; it != iter -> getSource () -> GetSharedVisionList (). end (); ++ it )
BuildPacket ( * it );
}
}
}
void Visit ( DynamicObjectMapType & m )
{
for ( DynamicObjectMapType :: iterator iter = m . begin (); iter != m . end (); ++ iter )
{
uint64 guid = iter -> getSource () -> GetCasterGUID ();
2010-04-07 19:14:10 +02:00
if ( IS_PLAYER_GUID ( guid ))
2010-02-03 16:53:40 +02:00
{
//Caster may be NULL if DynObj is in removelist
2010-04-07 19:14:10 +02:00
if ( Player * caster = ObjectAccessor :: FindPlayer ( guid ))
2010-02-03 16:53:40 +02:00
if ( caster -> GetUInt64Value ( PLAYER_FARSIGHT ) == iter -> getSource () -> GetGUID ())
BuildPacket ( caster );
}
}
}
void BuildPacket ( Player * plr )
{
// Only send update once to a player
if ( plr_list . find ( plr -> GetGUID ()) == plr_list . end () && plr -> HaveAtClient ( & i_object ))
{
i_object . BuildFieldsUpdate ( plr , i_updateDatas );
plr_list . insert ( plr -> GetGUID ());
}
}
template < class SKIP > void Visit ( GridRefManager < SKIP > & ) {}
};
void WorldObject :: BuildUpdate ( UpdateDataMapType & data_map )
{
CellPair p = Trinity :: ComputeCellPair ( GetPositionX (), GetPositionY ());
Cell cell ( p );
cell . data . Part . reserved = ALL_DISTRICT ;
cell . SetNoCreate ();
WorldObjectChangeAccumulator notifier ( * this , data_map );
TypeContainerVisitor < WorldObjectChangeAccumulator , WorldTypeMapContainer > player_notifier ( notifier );
Map & map = * GetMap ();
//we must build packets for all visible players
cell . Visit ( p , player_notifier , map , * this , map . GetVisibilityDistance ());
ClearUpdateMask ( false );
}
2010-08-08 20:32:14 +02:00
uint64 WorldObject :: GetTransGUID () const
{
if ( GetTransport ())
return GetTransport () -> GetGUID ();
return 0 ;
2010-08-21 20:08:47 +02:00
}