[2771] Applied MaNGOS coding style (see trunk/bcpp.cfg).
[mangos-git.git] / src / game / Object.cpp
blob761602fbb5f2bf3532412060f3f4b36502816b53
1 /*
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
19 #include "Common.h"
20 #include "WorldPacket.h"
21 #include "Opcodes.h"
22 #include "Log.h"
23 #include "World.h"
24 #include "Object.h"
25 #include "Player.h"
26 #include "ObjectMgr.h"
27 #include "WorldSession.h"
28 #include "UpdateData.h"
29 #include "Util.h"
30 #include "MapManager.h"
31 #include "ObjectAccessor.h"
32 #include "Log.h"
33 #include "Transports.h"
35 using namespace std;
37 Object::Object( )
39 m_objectTypeId = TYPEID_OBJECT;
40 m_objectType = TYPE_OBJECT;
42 m_positionX = 0.0f;
43 m_positionY = 0.0f;
44 m_positionZ = 0.0f;
45 m_orientation = 0.0f;
47 m_mapId = 0;
49 m_uint32Values = 0;
51 m_inWorld = false;
53 m_minZ = -500;
55 m_valuesCount = 0;
57 m_speed = 1.0f;
58 m_moveType = MOVE_STOP;
60 mSemaphoreTeleport = false;
61 m_inWorld = false;
62 m_objectUpdated = false;
65 Object::~Object( )
68 if(m_objectUpdated)
69 ObjectAccessor::Instance().RemoveUpdateObject(this);
71 if(m_uint32Values)
73 //DEBUG_LOG("Object desctr 1 check (%p)",(void*)this);
74 delete [] m_uint32Values;
75 //DEBUG_LOG("Object desctr 2 check (%p)",(void*)this);
79 void Object::_Create( uint32 guidlow, uint32 guidhigh )
81 if(!m_uint32Values) _InitValues();
83 SetUInt32Value( OBJECT_FIELD_GUID, guidlow );
84 SetUInt32Value( OBJECT_FIELD_GUID+1, guidhigh );
85 SetUInt32Value( OBJECT_FIELD_TYPE, m_objectType );
86 _SetPackGUID(&m_PackGUID,GetGUID());
89 void Object::_Create( uint32 guidlow, uint32 guidhigh, uint32 mapid, float x, float y, float z, float ang, uint32 nameId )
91 _Create(guidlow, guidhigh);
93 SetUInt32Value( OBJECT_FIELD_ENTRY,nameId);
95 m_mapId = mapid;
96 m_positionX = x;
97 m_positionY = y;
98 m_positionZ = z;
99 m_orientation = ang;
102 void Object::BuildMovementUpdateBlock(UpdateData * data, uint32 flags ) const
104 ByteBuffer buf(500);
106 buf << uint8( UPDATETYPE_MOVEMENT );
107 buf << GetGUID();
109 _BuildMovementUpdate(&buf, flags, 0x00000000);
111 data->AddUpdateBlock(buf);
114 void Object::BuildCreateUpdateBlockForPlayer(UpdateData *data, Player *target) const
116 if(!target) return;
118 ByteBuffer buf(500);
119 buf << uint8( UPDATETYPE_CREATE_OBJECT );
120 buf << uint8( 0xFF );
121 buf << GetGUID() ;
122 buf << m_objectTypeId;
124 switch(m_objectTypeId)
126 case TYPEID_OBJECT: //do nothing
127 break;
128 case TYPEID_ITEM:
129 case TYPEID_CONTAINER:
130 _BuildMovementUpdate( &buf, 0x10, 0x0 );
131 break;
132 case TYPEID_UNIT:
133 _BuildMovementUpdate( &buf, 0x70, 0x800000 );
134 break;
135 case TYPEID_PLAYER:
137 if( target == this ) //build for self
139 buf.clear();
140 buf << uint8( UPDATETYPE_CREATE_OBJECT2 );
141 buf << uint8( 0xFF ); // must be packet GUID ?
142 buf << GetGUID() ;
143 buf << m_objectTypeId;
144 _BuildMovementUpdate( &buf, 0x71, 0x2000 );
146 //build for other player
147 else
149 _BuildMovementUpdate( &buf, 0x70, 0x0 );
151 }break;
152 case TYPEID_CORPSE:
153 case TYPEID_GAMEOBJECT:
154 case TYPEID_DYNAMICOBJECT:
156 if ((GUID_HIPART(GetGUID())==HIGHGUID_PLAYER_CORPSE) || (GUID_HIPART(GetGUID()) == HIGHGUID_TRANSPORT))
157 _BuildMovementUpdate( &buf, 0x52, 0x0 );
158 else
159 _BuildMovementUpdate( &buf, 0x50, 0x0 );
160 }break;
161 //case TYPEID_AIGROUP:
162 //case TYPEID_AREATRIGGER:
163 //break;
164 default: //know type
165 sLog.outDetail("Unknown Object Type %u Create Update Block.\n", m_objectTypeId);
166 break;
169 UpdateMask updateMask;
170 updateMask.SetCount( m_valuesCount );
171 _SetCreateBits( &updateMask, target );
172 _BuildValuesUpdate( &buf, &updateMask );
173 data->AddUpdateBlock(buf);
177 void Object::SendUpdateToPlayer(Player* player) const
179 //if (!player->IsInWorld()) return;
181 UpdateData upd;
182 WorldPacket packet;
184 upd.Clear();
185 BuildCreateUpdateBlockForPlayer(&upd, player);
186 upd.BuildPacket(&packet);
187 player->GetSession()->SendPacket(&packet);
190 void Object::BuildValuesUpdateBlockForPlayer(UpdateData *data, Player *target) const
192 ByteBuffer buf(500);
194 buf << (uint8) UPDATETYPE_VALUES;
195 buf << (uint8) 0xFF; // must be packed GUID ?
196 buf << GetGUID();
198 UpdateMask updateMask;
199 updateMask.SetCount( m_valuesCount );
200 _SetUpdateBits( &updateMask, target );
201 _BuildValuesUpdate( &buf, &updateMask );
203 data->AddUpdateBlock(buf);
206 void Object::BuildOutOfRangeUpdateBlock(UpdateData * data) const
208 data->AddOutOfRangeGUID(GetGUID());
211 void Object::DestroyForPlayer(Player *target) const
213 ASSERT(target);
215 WorldPacket data;
216 data.Initialize( SMSG_DESTROY_OBJECT );
217 data << GetGUID();
219 target->GetSession()->SendPacket( &data );
222 void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2 ) const
224 *data << (uint8)flags;
225 if( m_objectTypeId==TYPEID_PLAYER )
227 if(((Player*)this)->GetTransport())
229 flags2 |= 0x02000000;
231 *data << (uint32)flags2;
233 *data << (uint32)getMSTime();
235 if (!((Player *)this)->GetTransport())
237 *data << (float)m_positionX;
238 *data << (float)m_positionY;
239 *data << (float)m_positionZ;
240 *data << (float)m_orientation;
242 else
244 //*data << ((Player *)this)->m_transport->GetPositionX() + (float)((Player *)this)->m_transX;
245 //*data << ((Player *)this)->m_transport->GetPositionY() + (float)((Player *)this)->m_transY;
246 //*data << ((Player *)this)->m_transport->GetPositionZ() + (float)((Player *)this)->m_transZ;
248 *data << ((Player *)this)->GetTransport()->GetPositionX();
249 *data << ((Player *)this)->GetTransport()->GetPositionY();
250 *data << ((Player *)this)->GetTransport()->GetPositionZ();
251 *data << ((Player *)this)->GetTransport()->GetOrientation();
253 *data << (uint64)(((Player *)this)->GetTransport()->GetGUID());
254 *data << ((Player *)this)->GetTransOffsetX();
255 *data << ((Player *)this)->GetTransOffsetY();
256 *data << ((Player *)this)->GetTransOffsetZ();
257 *data << ((Player *)this)->GetTransOffsetO();
260 *data << (float)0;
262 if(flags2 & 0x2000) //update self
264 *data << (float)0;
265 *data << (float)1.0;
266 *data << (float)0;
267 *data << (float)0;
269 *data << GetSpeed( MOVE_WALK );
270 *data << GetSpeed( MOVE_RUN );
271 *data << GetSpeed( MOVE_SWIMBACK );
272 *data << GetSpeed( MOVE_SWIM );
273 *data << GetSpeed( MOVE_WALKBACK );
274 *data << GetSpeed( MOVE_TURN );
276 if( m_objectTypeId==TYPEID_UNIT )
278 *data << (uint32)flags2;
279 *data << (uint32)0xB5771D7F;
280 *data << (float)m_positionX;
281 *data << (float)m_positionY;
282 *data << (float)m_positionZ;
283 *data << (float)m_orientation;
284 *data << (float)0;
285 *data << GetSpeed( MOVE_WALK );
286 *data << GetSpeed( MOVE_RUN );
287 *data << GetSpeed( MOVE_SWIMBACK );
288 *data << GetSpeed( MOVE_SWIM );
289 *data << GetSpeed( MOVE_WALKBACK );
290 *data << GetSpeed( MOVE_TURN );
291 uint8 PosCount=0;
292 if(flags2 & 0x400000)
294 *data << (uint32)0x0;
295 *data << (uint32)0x659;
296 *data << (uint32)0xB7B;
297 *data << (uint32)0xFDA0B4;
298 *data << (uint32)PosCount;
299 for(int i=0;i<PosCount+1;i++)
301 *data << (float)0; //x
302 *data << (float)0; //y
303 *data << (float)0; //z
307 if( (m_objectTypeId==TYPEID_CORPSE) || (m_objectTypeId==TYPEID_GAMEOBJECT) || (m_objectTypeId==TYPEID_DYNAMICOBJECT))
309 if(GUID_HIPART(GetGUID()) != HIGHGUID_TRANSPORT)
311 *data << (float)m_positionX;
312 *data << (float)m_positionY;
313 *data << (float)m_positionZ;
315 else
317 *data << (uint32)0;
318 *data << (uint32)0;
319 *data << (uint32)0;
321 *data << (float)m_orientation;
324 *data << (uint32)0x1;
326 if ((GUID_HIPART(GetGUID()) == HIGHGUID_TRANSPORT))
328 uint32 updT = (uint32)getMSTime();
329 *data << (uint32)updT;
332 if( GUID_HIPART(GetGUID()) == HIGHGUID_PLAYER_CORPSE)
333 *data << (uint32)0xBD38BA14; //fix me
336 void Object::_BuildValuesUpdate(ByteBuffer * data, UpdateMask *updateMask) const
338 WPAssert(updateMask && updateMask->GetCount() == m_valuesCount);
340 *data << (uint8)updateMask->GetBlockCount();
341 data->append( updateMask->GetMask(), updateMask->GetLength() );
343 for( uint16 index = 0; index < m_valuesCount; index ++ )
345 if( updateMask->GetBit( index ) )
347 // Some values at server stored in float format but must be sended to client in uint32 format
348 if( isType(TYPE_UNIT) && (
349 index >= UNIT_FIELD_POWER1 && index <= UNIT_FIELD_MAXPOWER5 ||
350 index >= UNIT_FIELD_BASEATTACKTIME && index <= UNIT_FIELD_RANGEDATTACKTIME ||
351 index >= UNIT_FIELD_STR && index <= UNIT_FIELD_RESISTANCES_06 )
352 || isType(TYPE_PLAYER) &&
353 index >= PLAYER_FIELD_POSSTAT0 && index <= PLAYER_FIELD_RESISTANCEBUFFMODSNEGATIVE_06 )
355 // convert from float to uint32 and send
356 *data << uint32(m_floatValues[ index ]);
358 else
360 // send in current format (float as float, uint32 as uint32)
361 *data << m_uint32Values[ index ];
367 void Object::BuildHeartBeatMsg(WorldPacket *data) const
369 data->Initialize(MSG_MOVE_HEARTBEAT); //2
371 *data << GetGUID(); //8
372 *data << uint32(0); //4
373 *data << uint32(0); //4
375 *data << m_positionX; //4
376 *data << m_positionY; //4
377 *data << m_positionZ; //4
379 *data << m_orientation; //4
382 void Object::BuildTeleportAckMsg(WorldPacket *data, float x, float y, float z, float ang) const
384 data->Initialize(MSG_MOVE_TELEPORT_ACK);
385 *data << uint8(0xFF);
386 *data << GetGUID();
387 *data << uint32(0x800000);
388 *data << uint16(0x67EE);
389 *data << uint16(0xD1EB);
390 *data << m_orientation; // instead of *data << z;
391 *data << x;
392 *data << y;
393 *data << z; // instead of *data << ang;
394 *data << ang;
395 *data << uint32(0x0);
398 void Object::SendMessageToSet(WorldPacket *data, bool bToSelf)
400 MapManager::Instance().GetMap(m_mapId)->MessageBoardcast(this, data);
403 bool Object::LoadValues(const char* data)
405 if(!m_uint32Values) _InitValues();
407 vector<string> tokens = StrSplit(data, " ");
409 if(tokens.size() != m_valuesCount)
410 return false;
412 vector<string>::iterator iter;
413 int index;
415 for (iter = tokens.begin(), index = 0; index < m_valuesCount; ++iter, ++index)
417 m_uint32Values[index] = atol((*iter).c_str());
419 return true;
422 void Object::_SetUpdateBits(UpdateMask *updateMask, Player *target) const
424 *updateMask = m_updateMask;
427 void Object::_SetCreateBits(UpdateMask *updateMask, Player *target) const
429 for( uint16 index = 0; index < m_valuesCount; index++ )
431 if(GetUInt32Value(index) != 0)
432 updateMask->SetBit(index);
436 void Object::SetUInt32Value( uint16 index, uint32 value )
438 ASSERT( index < m_valuesCount || PrintIndexError( index , true ) );
439 if(m_uint32Values[ index ] != value)
441 m_uint32Values[ index ] = value;
443 if(m_inWorld)
445 m_updateMask.SetBit( index );
447 if(!m_objectUpdated)
449 ObjectAccessor::Instance().AddUpdateObject(this);
450 m_objectUpdated = true;
456 void Object::SetUInt64Value( uint16 index, const uint64 &value )
458 ASSERT( index + 1 < m_valuesCount || PrintIndexError( index , true ) );
459 if(*((uint64*)&(m_uint32Values[ index ])) != value)
461 m_uint32Values[ index ] = *((uint32*)&value);
462 m_uint32Values[ index + 1 ] = *(((uint32*)&value) + 1);
464 if(m_inWorld)
466 m_updateMask.SetBit( index );
467 m_updateMask.SetBit( index + 1 );
469 if(!m_objectUpdated)
471 ObjectAccessor::Instance().AddUpdateObject(this);
472 m_objectUpdated = true;
478 void Object::SetFloatValue( uint16 index, float value )
480 ASSERT( index + 1 < m_valuesCount || PrintIndexError( index , true ) );
481 if(m_floatValues[ index ] != value)
483 m_floatValues[ index ] = value;
485 if(m_inWorld)
487 m_updateMask.SetBit( index );
489 if(!m_objectUpdated)
491 ObjectAccessor::Instance().AddUpdateObject(this);
492 m_objectUpdated = true;
498 void Object::ApplyModUInt32Value(uint16 index, int32 val, bool apply)
500 int32 cur = GetUInt32Value(index);
501 cur += (apply ? val : -val);
502 if(cur < 0)
503 cur = 0;
504 SetUInt32Value(index,cur);
507 void Object::ApplyModFloatValue(uint16 index, float val, bool apply)
509 float cur = GetFloatValue(index);
510 cur += (apply ? val : -val);
511 if(cur < 0)
512 cur = 0;
513 SetFloatValue(index,cur);
516 void Object::SetFlag( uint16 index, uint32 newFlag )
518 ASSERT( index < m_valuesCount || PrintIndexError( index , true ) );
519 uint32 oldval = m_uint32Values[ index ];
520 uint32 newval = oldval | newFlag;
522 if(oldval != newval)
524 m_uint32Values[ index ] = newval;
526 if(m_inWorld)
528 m_updateMask.SetBit( index );
530 if(!m_objectUpdated)
532 ObjectAccessor::Instance().AddUpdateObject(this);
533 m_objectUpdated = true;
539 void Object::RemoveFlag( uint16 index, uint32 oldFlag )
541 ASSERT( index < m_valuesCount || PrintIndexError( index , true ) );
542 uint32 oldval = m_uint32Values[ index ];
543 uint32 newval = oldval & ~oldFlag;
545 if(oldval != newval)
547 m_uint32Values[ index ] = newval;
549 if(m_inWorld)
551 m_updateMask.SetBit( index );
553 if(!m_objectUpdated)
555 ObjectAccessor::Instance().AddUpdateObject(this);
556 m_objectUpdated = true;
562 uint32 Object::GetZoneId() const
564 return MapManager::Instance().GetMap(m_mapId)->GetZoneId(m_positionX,m_positionY);
567 uint32 Object::GetAreaId() const
569 return MapManager::Instance().GetMap(m_mapId)->GetAreaId(m_positionX,m_positionY);
572 float Object::GetDistanceSq(const Object* obj) const //slow
574 float dx = GetPositionX() - obj->GetPositionX();
575 float dy = GetPositionY() - obj->GetPositionY();
576 float dz = GetPositionZ() - obj->GetPositionZ();
577 float sizefactor = GetObjectSize() + obj->GetObjectSize();
578 float dist = sqrt((dx*dx) + (dy*dy) + (dz*dz)) - sizefactor;
579 return ( dist > 0 ? dist * dist : 0);
582 float Object::GetDistanceSq(const float x, const float y, const float z) const
584 float dx = GetPositionX() - x;
585 float dy = GetPositionY() - y;
586 float dz = GetPositionZ() - z;
587 float sizefactor = GetObjectSize();
588 float dist = sqrt((dx*dx) + (dy*dy) + (dz*dz)) - sizefactor;
589 return ( dist > 0 ? dist * dist : 0);
592 float Object::GetDistance2dSq(const Object* obj) const //slow
594 float dx = GetPositionX() - obj->GetPositionX();
595 float dy = GetPositionY() - obj->GetPositionY();
596 float sizefactor = GetObjectSize() + obj->GetObjectSize();
597 float dist = sqrt((dx*dx) + (dy*dy)) - sizefactor;
598 return ( dist > 0 ? dist * dist : 0);
601 float Object::GetDistanceZ(const Object* obj) const
603 float dz = fabs(GetPositionZ() - obj->GetPositionZ());
604 float sizefactor = GetObjectSize() + obj->GetObjectSize();
605 float dist = dz - sizefactor;
606 return ( dist > 0 ? dist : 0);
609 bool Object::IsWithinDistInMap(const Object* obj, const float dist2compare) const
611 if (GetMapId()!=obj->GetMapId()) return false;
612 return IsWithinDist(obj, dist2compare);
615 bool Object::IsWithinDist(const Object* obj, const float dist2compare) const
617 float dx = GetPositionX() - obj->GetPositionX();
618 float dy = GetPositionY() - obj->GetPositionY();
619 float dz = GetPositionZ() - obj->GetPositionZ();
620 float distsq = dx*dx + dy*dy + dz*dz;
621 float sizefactor = GetObjectSize() + obj->GetObjectSize();
622 float maxdist = dist2compare + sizefactor;
623 return distsq < maxdist * maxdist;
626 float Object::GetAngle(const Object* obj) const
628 if(!obj) return 0;
629 return GetAngle( obj->GetPositionX(), obj->GetPositionY() );
632 // Retirn angle in range 0..2*pi
633 float Object::GetAngle( const float x, const float y ) const
635 float dx = x - GetPositionX();
636 float dy = y - GetPositionY();
638 float ang = atan2(dy, dx);
639 ang = (ang >= 0) ? ang : 2 * M_PI + ang;
640 return ang;
643 bool Object::HasInArc(const float arcangle, const Object* obj) const
645 float arc = arcangle;
647 // move arc to range 0.. 2*pi
648 while( arc >= 2.0f * M_PI )
649 arc -= 2.0f * M_PI;
650 while( arc < 0 )
651 arc += 2.0f * M_PI;
653 float angle = GetAngle( obj );
654 angle -= m_orientation;
656 // move angle to range -pi ... +pi
657 while( angle > M_PI)
658 angle -= 2.0f * M_PI;
659 while(angle < -M_PI)
660 angle += 2.0f * M_PI;
662 float lborder = -1 * (arc/2.0f); // in range -pi..0
663 float rborder = (arc/2.0f); // in range 0..pi
664 return (( angle >= lborder ) && ( angle <= rborder ));
667 void Object::GetContactPoint( const Object* obj, float &x, float &y, float &z ) const
669 float angle = GetAngle( obj );
670 x = GetPositionX() + (GetObjectSize() + obj->GetObjectSize() + OBJECT_CONTACT_DISTANCE) * cos(angle);
671 y = GetPositionY() + (GetObjectSize() + obj->GetObjectSize() + OBJECT_CONTACT_DISTANCE) * sin(angle);
672 z = GetPositionZ();
675 void Object::GetClosePoint( const Object* victim, float &x, float &y, float &z ) const
677 if( victim )
678 GetClosePoint( victim->GetPositionX(), victim->GetPositionY(), victim->GetPositionZ(), x, y, z);
679 else
680 GetClosePoint( 0, 0, 0, x, y, z);
683 void Object::GetClosePoint( const float ox, const float oy, const float oz, float &x, float &y, float &z ) const
685 float angle;
686 if( ox == 0 && oy == 0 )
687 angle = GetOrientation();
688 else
689 angle = GetAngle( ox, oy );
690 x = GetPositionX() + GetObjectSize() * cos(angle);
691 y = GetPositionY() + GetObjectSize() * sin(angle);
692 z = GetPositionZ();
696 bool Object::IsPositionValid() const
698 return MaNGOS::IsValidMapCoord(m_positionX) && MaNGOS::IsValidMapCoord(m_positionY);
701 bool Object::hasQuest(uint32 quest_id)
703 return (find(mQuests.begin(), mQuests.end(), quest_id) != mQuests.end());
706 bool Object::hasInvolvedQuest(uint32 quest_id)
708 return (find(mInvolvedQuests.begin(), mInvolvedQuests.end(), quest_id) != mInvolvedQuests.end());
711 bool Object::PrintIndexError(uint32 index, bool set) const
713 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);
715 // assert must fail after function call
716 return false;
719 void Object::_SetPackGUID(ByteBuffer *buffer, const uint64 &guid64) const
721 size_t mask_position = buffer->wpos();
722 *buffer << uint8(0);
723 for(uint8 i = 0; i < 8; i++)
725 if(((uint8*)&guid64)[i])
727 const_cast<uint8*>(buffer->contents())[mask_position] |= (1<<i);
728 *buffer << ((uint8*)&guid64)[i];