2 * Copyright (C) 2005,2006 MaNGOS <http://www.mangosproject.org/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include "WorldPacket.h"
26 #include "ObjectMgr.h"
27 #include "WorldSession.h"
28 #include "UpdateData.h"
30 #include "MapManager.h"
31 #include "ObjectAccessor.h"
38 m_objectTypeId
= TYPEID_OBJECT
;
39 m_objectType
= TYPE_OBJECT
;
57 m_moveType
= MOVE_STOP
;
59 mSemaphoreTeleport
= false;
61 m_objectUpdated
= false;
68 ObjectAccessor::Instance().RemoveUpdateObject(this);
72 //DEBUG_LOG("Object desctr 1 check (%p)",(void*)this);
73 delete [] m_uint32Values
;
74 //DEBUG_LOG("Object desctr 2 check (%p)",(void*)this);
78 void Object::_Create( uint32 guidlow
, uint32 guidhigh
)
80 if(!m_uint32Values
) _InitValues();
82 SetUInt32Value( OBJECT_FIELD_GUID
, guidlow
);
83 SetUInt32Value( OBJECT_FIELD_GUID
+1, guidhigh
);
84 SetUInt32Value( OBJECT_FIELD_TYPE
, m_objectType
);
85 _SetPackGUID(&m_PackGUID
,GetGUID());
88 void Object::_Create( uint32 guidlow
, uint32 guidhigh
, uint32 mapid
, float x
, float y
, float z
, float ang
, uint32 nameId
)
90 _Create(guidlow
, guidhigh
);
92 SetUInt32Value( OBJECT_FIELD_ENTRY
,nameId
);
101 void Object::BuildMovementUpdateBlock(UpdateData
* data
, uint32 flags
) const
105 buf
<< uint8( UPDATETYPE_MOVEMENT
);
108 _BuildMovementUpdate(&buf
, flags
, 0x00000000);
110 data
->AddUpdateBlock(buf
);
113 void Object::BuildCreateUpdateBlockForPlayer(UpdateData
*data
, Player
*target
) const
118 buf
<< uint8( UPDATETYPE_CREATE_OBJECT
);
119 buf
<< uint8( 0xFF );
121 buf
<< m_objectTypeId
;
123 switch(m_objectTypeId
)
125 case TYPEID_OBJECT
: //do nothing
128 case TYPEID_CONTAINER
:
129 _BuildMovementUpdate( &buf
, 0x10, 0x0 );
132 _BuildMovementUpdate( &buf
, 0x70, 0x800000 );
136 if( target
== this ) //build for self
139 buf
<< uint8( UPDATETYPE_CREATE_OBJECT2
);
140 buf
<< uint8( 0xFF );
142 buf
<< m_objectTypeId
;
143 _BuildMovementUpdate( &buf
, 0x71, 0x2000 );
145 //build for other player
148 _BuildMovementUpdate( &buf
, 0x70, 0x0 );
152 case TYPEID_GAMEOBJECT
:
153 case TYPEID_DYNAMICOBJECT
:
155 if(GUID_HIPART(GetGUID())==HIGHGUID_PLAYER_CORPSE
)
156 _BuildMovementUpdate( &buf
, 0x52, 0x0 );
158 _BuildMovementUpdate( &buf
, 0x50, 0x0 );
160 //case TYPEID_AIGROUP:
161 //case TYPEID_AREATRIGGER:
164 sLog
.outDetail("Unknow Object Type %u Create Update Block.\n", m_objectTypeId
);
168 UpdateMask updateMask
;
169 updateMask
.SetCount( m_valuesCount
);
170 _SetCreateBits( &updateMask
, target
);
171 _BuildValuesUpdate( &buf
, &updateMask
);
172 data
->AddUpdateBlock(buf
);
176 void Object::SendUpdateToPlayer(Player
* player
) const
178 //if (!player->IsInWorld()) return;
184 BuildCreateUpdateBlockForPlayer(&upd
, player
);
185 upd
.BuildPacket(&packet
);
186 player
->GetSession()->SendPacket(&packet
);
189 void Object::BuildValuesUpdateBlockForPlayer(UpdateData
*data
, Player
*target
) const
193 buf
<< (uint8
) UPDATETYPE_VALUES
;
197 UpdateMask updateMask
;
198 updateMask
.SetCount( m_valuesCount
);
199 _SetUpdateBits( &updateMask
, target
);
200 _BuildValuesUpdate( &buf
, &updateMask
);
202 data
->AddUpdateBlock(buf
);
205 void Object::BuildOutOfRangeUpdateBlock(UpdateData
* data
) const
207 data
->AddOutOfRangeGUID(GetGUID());
210 void Object::DestroyForPlayer(Player
*target
) const
215 data
.Initialize( SMSG_DESTROY_OBJECT
);
218 target
->GetSession()->SendPacket( &data
);
221 void Object::_BuildMovementUpdate(ByteBuffer
* data
, uint8 flags
, uint32 flags2
) const
223 *data
<< (uint8
)flags
;
224 if( m_objectTypeId
==TYPEID_PLAYER
)
226 *data
<< (uint32
)flags2
;
227 *data
<< (uint32
)0xB74D85D1;
228 *data
<< (float)m_positionX
;
229 *data
<< (float)m_positionY
;
230 *data
<< (float)m_positionZ
;
231 *data
<< (float)m_orientation
;
233 if(flags2
== 0x2000) //update self
240 *data
<< GetSpeed( MOVE_WALK
);
241 *data
<< GetSpeed( MOVE_RUN
);
242 *data
<< GetSpeed( MOVE_SWIMBACK
);
243 *data
<< GetSpeed( MOVE_SWIM
);
244 *data
<< GetSpeed( MOVE_WALKBACK
);
245 *data
<< GetSpeed( MOVE_TURN
);
247 if( m_objectTypeId
==TYPEID_UNIT
)
249 *data
<< (uint32
)flags2
;
250 *data
<< (uint32
)0xB5771D7F;
251 *data
<< (float)m_positionX
;
252 *data
<< (float)m_positionY
;
253 *data
<< (float)m_positionZ
;
254 *data
<< (float)m_orientation
;
256 *data
<< GetSpeed( MOVE_WALK
);
257 *data
<< GetSpeed( MOVE_RUN
);
258 *data
<< GetSpeed( MOVE_SWIMBACK
);
259 *data
<< GetSpeed( MOVE_SWIM
);
260 *data
<< GetSpeed( MOVE_WALKBACK
);
261 *data
<< GetSpeed( MOVE_TURN
);
263 if(flags2
& 0x400000)
265 *data
<< (uint32
)0x0;
266 *data
<< (uint32
)0x659;
267 *data
<< (uint32
)0xB7B;
268 *data
<< (uint32
)0xFDA0B4;
269 *data
<< (uint32
)PosCount
;
270 for(int i
=0;i
<PosCount
+1;i
++)
272 *data
<< (float)0; //x
273 *data
<< (float)0; //y
274 *data
<< (float)0; //z
278 if( (m_objectTypeId
==TYPEID_CORPSE
) || (m_objectTypeId
==TYPEID_GAMEOBJECT
) || (m_objectTypeId
==TYPEID_DYNAMICOBJECT
))
280 *data
<< (float)m_positionX
;
281 *data
<< (float)m_positionY
;
282 *data
<< (float)m_positionZ
;
283 *data
<< (float)m_orientation
;
286 *data
<< (uint32
)0x6297848C;
288 if( GUID_HIPART(GetGUID()) == HIGHGUID_PLAYER_CORPSE
)
289 *data
<< (uint32
)0xBD38BA14; //fix me
292 void Object::_BuildValuesUpdate(ByteBuffer
* data
, UpdateMask
*updateMask
) const
294 WPAssert(updateMask
&& updateMask
->GetCount() == m_valuesCount
);
296 *data
<< (uint8
)updateMask
->GetBlockCount();
297 data
->append( updateMask
->GetMask(), updateMask
->GetLength() );
299 for( uint16 index
= 0; index
< m_valuesCount
; index
++ )
301 if( updateMask
->GetBit( index
) )
303 // Some values at server stored in float format but must be sended to client in uint32 format
304 if( isType(TYPE_UNIT
) && (
305 index
>= UNIT_FIELD_POWER1
&& index
<= UNIT_FIELD_MAXPOWER5
||
306 index
>= UNIT_FIELD_BASEATTACKTIME
&& index
<= UNIT_FIELD_RANGEDATTACKTIME
||
307 index
>= UNIT_FIELD_STR
&& index
<= UNIT_FIELD_RESISTANCES_06
)
308 || isType(TYPE_PLAYER
) &&
309 index
>= PLAYER_FIELD_POSSTAT0
&& index
<= PLAYER_FIELD_RESISTANCEBUFFMODSNEGATIVE_06
)
311 // convert from float to uint32 and send
312 *data
<< uint32(m_floatValues
[ index
]);
316 // send in current format (float as float, uint32 as uint32)
317 *data
<< m_uint32Values
[ index
];
323 void Object::BuildHeartBeatMsg(WorldPacket
*data
) const
325 data
->Initialize(MSG_MOVE_HEARTBEAT
); //2
327 *data
<< GetGUID(); //8
328 *data
<< uint32(0); //4
329 *data
<< uint32(0); //4
331 *data
<< m_positionX
; //4
332 *data
<< m_positionY
; //4
333 *data
<< m_positionZ
; //4
335 *data
<< m_orientation
; //4
338 void Object::BuildTeleportAckMsg(WorldPacket
*data
, float x
, float y
, float z
, float ang
) const
340 data
->Initialize(MSG_MOVE_TELEPORT_ACK
);
341 *data
<< uint8(0xFF);
343 *data
<< uint32(0x800000);
344 *data
<< uint16(0x67EE);
345 *data
<< uint16(0xD1EB);
346 *data
<< m_orientation
; // instead of *data << z;
349 *data
<< z
; // instead of *data << ang;
351 *data
<< uint32(0x0);
354 void Object::SendMessageToSet(WorldPacket
*data
, bool bToSelf
)
356 MapManager::Instance().GetMap(m_mapId
)->MessageBoardcast(this, data
);
359 bool Object::LoadValues(const char* data
)
361 if(!m_uint32Values
) _InitValues();
363 vector
<string
> tokens
= StrSplit(data
, " ");
365 if(tokens
.size() != m_valuesCount
)
368 vector
<string
>::iterator iter
;
371 for (iter
= tokens
.begin(), index
= 0; index
< m_valuesCount
; ++iter
, ++index
)
373 m_uint32Values
[index
] = atol((*iter
).c_str());
378 void Object::_SetUpdateBits(UpdateMask
*updateMask
, Player
*target
) const
380 *updateMask
= m_updateMask
;
383 void Object::_SetCreateBits(UpdateMask
*updateMask
, Player
*target
) const
385 for( uint16 index
= 0; index
< m_valuesCount
; index
++ )
387 if(GetUInt32Value(index
) != 0)
388 updateMask
->SetBit(index
);
392 void Object::SetUInt32Value( uint16 index
, uint32 value
)
394 ASSERT( index
< m_valuesCount
|| PrintIndexError( index
, true ) );
395 if(m_uint32Values
[ index
] != value
)
397 m_uint32Values
[ index
] = value
;
401 m_updateMask
.SetBit( index
);
405 ObjectAccessor::Instance().AddUpdateObject(this);
406 m_objectUpdated
= true;
412 void Object::SetUInt64Value( uint16 index
, const uint64
&value
)
414 ASSERT( index
+ 1 < m_valuesCount
|| PrintIndexError( index
, true ) );
415 if(*((uint64
*)&(m_uint32Values
[ index
])) != value
)
417 m_uint32Values
[ index
] = *((uint32
*)&value
);
418 m_uint32Values
[ index
+ 1 ] = *(((uint32
*)&value
) + 1);
422 m_updateMask
.SetBit( index
);
423 m_updateMask
.SetBit( index
+ 1 );
427 ObjectAccessor::Instance().AddUpdateObject(this);
428 m_objectUpdated
= true;
434 void Object::SetFloatValue( uint16 index
, float value
)
436 ASSERT( index
+ 1 < m_valuesCount
|| PrintIndexError( index
, true ) );
437 if(m_floatValues
[ index
] != value
)
439 m_floatValues
[ index
] = value
;
443 m_updateMask
.SetBit( index
);
447 ObjectAccessor::Instance().AddUpdateObject(this);
448 m_objectUpdated
= true;
454 void Object::ApplyModUInt32Value(uint16 index
, int32 val
, bool apply
)
456 int32 cur
= GetUInt32Value(index
);
457 cur
+= (apply
? val
: -val
);
460 SetUInt32Value(index
,cur
);
463 void Object::ApplyModFloatValue(uint16 index
, float val
, bool apply
)
465 float cur
= GetFloatValue(index
);
466 cur
+= (apply
? val
: -val
);
469 SetFloatValue(index
,cur
);
472 void Object::SetFlag( uint16 index
, uint32 newFlag
)
474 ASSERT( index
< m_valuesCount
|| PrintIndexError( index
, true ) );
475 uint32 oldval
= m_uint32Values
[ index
];
476 uint32 newval
= oldval
| newFlag
;
480 m_uint32Values
[ index
] = newval
;
484 m_updateMask
.SetBit( index
);
488 ObjectAccessor::Instance().AddUpdateObject(this);
489 m_objectUpdated
= true;
495 void Object::RemoveFlag( uint16 index
, uint32 oldFlag
)
497 ASSERT( index
< m_valuesCount
|| PrintIndexError( index
, true ) );
498 uint32 oldval
= m_uint32Values
[ index
];
499 uint32 newval
= oldval
& ~oldFlag
;
503 m_uint32Values
[ index
] = newval
;
507 m_updateMask
.SetBit( index
);
511 ObjectAccessor::Instance().AddUpdateObject(this);
512 m_objectUpdated
= true;
518 uint32
Object::GetZoneId() const
520 return MapManager::Instance().GetMap(m_mapId
)->GetZoneId(m_positionX
,m_positionY
);
523 uint32
Object::GetAreaId() const
525 return MapManager::Instance().GetMap(m_mapId
)->GetAreaId(m_positionX
,m_positionY
);
528 float Object::GetDistanceSq(const Object
* obj
) const //slow
530 float dx
= GetPositionX() - obj
->GetPositionX();
531 float dy
= GetPositionY() - obj
->GetPositionY();
532 float dz
= GetPositionZ() - obj
->GetPositionZ();
533 float sizefactor
= GetObjectSize() + obj
->GetObjectSize();
534 float dist
= sqrt((dx
*dx
) + (dy
*dy
) + (dz
*dz
)) - sizefactor
;
535 return ( dist
> 0 ? dist
* dist
: 0);
538 float Object::GetDistanceSq(const float x
, const float y
, const float z
) const
540 float dx
= GetPositionX() - x
;
541 float dy
= GetPositionY() - y
;
542 float dz
= GetPositionZ() - z
;
543 float sizefactor
= GetObjectSize();
544 float dist
= sqrt((dx
*dx
) + (dy
*dy
) + (dz
*dz
)) - sizefactor
;
545 return ( dist
> 0 ? dist
* dist
: 0);
548 float Object::GetDistance2dSq(const Object
* obj
) const //slow
550 float dx
= GetPositionX() - obj
->GetPositionX();
551 float dy
= GetPositionY() - obj
->GetPositionY();
552 float sizefactor
= GetObjectSize() + obj
->GetObjectSize();
553 float dist
= sqrt((dx
*dx
) + (dy
*dy
)) - sizefactor
;
554 return ( dist
> 0 ? dist
* dist
: 0);
557 float Object::GetDistanceZ(const Object
* obj
) const
559 float dz
= fabs(GetPositionZ() - obj
->GetPositionZ());
560 float sizefactor
= GetObjectSize() + obj
->GetObjectSize();
561 float dist
= dz
- sizefactor
;
562 return ( dist
> 0 ? dist
: 0);
565 bool Object::IsWithinDistInMap(const Object
* obj
, const float dist2compare
) const
567 if (GetMapId()!=obj
->GetMapId()) return false;
568 return IsWithinDist(obj
, dist2compare
);
571 bool Object::IsWithinDist(const Object
* obj
, const float dist2compare
) const
573 float dx
= GetPositionX() - obj
->GetPositionX();
574 float dy
= GetPositionY() - obj
->GetPositionY();
575 float dz
= GetPositionZ() - obj
->GetPositionZ();
576 float distsq
= dx
*dx
+ dy
*dy
+ dz
*dz
;
577 float sizefactor
= GetObjectSize() + obj
->GetObjectSize();
578 float maxdist
= dist2compare
+ sizefactor
;
579 return distsq
< maxdist
* maxdist
;
582 float Object::GetAngle(const Object
* obj
) const
585 return GetAngle( obj
->GetPositionX(), obj
->GetPositionY() );
588 // Retirn angle in range 0..2*pi
589 float Object::GetAngle( const float x
, const float y
) const
591 float dx
= x
- GetPositionX();
592 float dy
= y
- GetPositionY();
594 float ang
= atan2(dy
, dx
);
595 ang
= (ang
>= 0) ? ang
: 2 * M_PI
+ ang
;
599 bool Object::HasInArc(const float arcangle
, const Object
* obj
) const
601 float arc
= arcangle
;
603 // move arc to range 0.. 2*pi
604 while( arc
> 2.0f
* M_PI
)
609 float angle
= GetAngle( obj
);
610 angle
-= m_orientation
;
612 // move angle to range -pi ... +pi
614 angle
-= 2.0f
* M_PI
;
616 angle
+= 2.0f
* M_PI
;
618 float lborder
= -1 * (arc
/2.0f
); // in range -pi..0
619 float rborder
= (arc
/2.0f
); // in range 0..pi
620 return (( angle
>= lborder
) && ( angle
<= rborder
));
623 void Object::GetContactPoint( const Object
* obj
, float &x
, float &y
, float &z
) const
625 float angle
= GetAngle( obj
);
626 x
= GetPositionX() + (GetObjectSize() + obj
->GetObjectSize() + OBJECT_CONTACT_DISTANCE
) * cos(angle
);
627 y
= GetPositionY() + (GetObjectSize() + obj
->GetObjectSize() + OBJECT_CONTACT_DISTANCE
) * sin(angle
);
631 void Object::GetClosePoint( const Object
* victim
, float &x
, float &y
, float &z
) const
634 GetClosePoint( victim
->GetPositionX(), victim
->GetPositionY(), victim
->GetPositionZ(), x
, y
, z
);
636 GetClosePoint( 0, 0, 0, x
, y
, z
);
639 void Object::GetClosePoint( const float ox
, const float oy
, const float oz
, float &x
, float &y
, float &z
) const
642 if( ox
== 0 && oy
== 0 )
643 angle
= GetOrientation();
645 angle
= GetAngle( ox
, oy
);
646 x
= GetPositionX() + GetObjectSize() * cos(angle
);
647 y
= GetPositionY() + GetObjectSize() * sin(angle
);
652 bool Object::IsPositionValid() const
654 return MaNGOS::IsValidMapCoord(m_positionX
) && MaNGOS::IsValidMapCoord(m_positionY
);
657 bool Object::hasQuest(uint32 quest_id
)
659 for( std::list
<Quest
*>::iterator i
= mQuests
.begin( ); i
!= mQuests
.end( ); i
++ )
661 if ((*i
)->GetQuestInfo()->QuestId
== quest_id
)
668 bool Object::hasInvolvedQuest(uint32 quest_id
)
670 for( std::list
<Quest
*>::iterator i
= mInvolvedQuests
.begin( ); i
!= mInvolvedQuests
.end( ); i
++ )
672 if ((*i
)->GetQuestInfo()->QuestId
== quest_id
)
679 bool Object::PrintIndexError(uint32 index
, bool set
) const
681 sLog
.outError("ERROR: 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
);
683 // assert must fail after function call
687 void Object::_SetPackGUID(ByteBuffer
*buffer
, const uint64
&guid64
) const
689 size_t mask_position
= buffer
->wpos();
691 for(uint8 i
= 0; i
< 8; i
++)
693 if(((uint8
*)&guid64
)[i
])
695 const_cast<uint8
*>(buffer
->contents())[mask_position
] |= (1<<i
);
696 *buffer
<< ((uint8
*)&guid64
)[i
];