2 * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
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
23 #include "ByteBuffer.h"
24 #include "UpdateFields.h"
25 #include "UpdateData.h"
26 #include "ObjectGuid.h"
32 #define CONTACT_DISTANCE 0.5f
33 #define INTERACTION_DISTANCE 5.0f
34 #define ATTACK_DISTANCE 5.0f
35 #define MAX_VISIBILITY_DISTANCE 333.0f // max distance for visible object show, limited in 333 yards
36 #define DEFAULT_VISIBILITY_DISTANCE 90.0f // default visible distance, 90 yards on continents
37 #define DEFAULT_VISIBILITY_INSTANCE 120.0f // default visible distance in instances, 120 yards
38 #define DEFAULT_VISIBILITY_BGARENAS 180.0f // default visible distance in BG/Arenas, 180 yards
40 #define DEFAULT_WORLD_OBJECT_SIZE 0.388999998569489f // player size, also currently used (correctly?) for any non Unit world objects
41 #define MAX_STEALTH_DETECT_RANGE 45.0f
43 uint32
GuidHigh2TypeId(uint32 guid_hi
);
47 TEMPSUMMON_TIMED_OR_DEAD_DESPAWN
= 1, // despawns after a specified time OR when the creature disappears
48 TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN
= 2, // despawns after a specified time OR when the creature dies
49 TEMPSUMMON_TIMED_DESPAWN
= 3, // despawns after a specified time
50 TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT
= 4, // despawns after a specified time after the creature is out of combat
51 TEMPSUMMON_CORPSE_DESPAWN
= 5, // despawns instantly after death
52 TEMPSUMMON_CORPSE_TIMED_DESPAWN
= 6, // despawns after a specified time after death
53 TEMPSUMMON_DEAD_DESPAWN
= 7, // despawns when the creature disappears
54 TEMPSUMMON_MANUAL_DESPAWN
= 8 // despawns when UnSummon() is called
59 PHASEMASK_NORMAL
= 0x00000001,
60 PHASEMASK_ANYWHERE
= 0xFFFFFFFF
73 typedef UNORDERED_MAP
<Player
*, UpdateData
> UpdateDataMapType
;
82 explicit WorldLocation(uint32 _mapid
= 0, float _x
= 0, float _y
= 0, float _z
= 0, float _o
= 0)
83 : mapid(_mapid
), coord_x(_x
), coord_y(_y
), coord_z(_z
), orientation(_o
) {}
84 WorldLocation(WorldLocation
const &loc
)
85 : mapid(loc
.mapid
), coord_x(loc
.coord_x
), coord_y(loc
.coord_y
), coord_z(loc
.coord_z
), orientation(loc
.orientation
) {}
88 class MANGOS_DLL_SPEC Object
93 const bool& IsInWorld() const { return m_inWorld
; }
94 virtual void AddToWorld()
101 // synchronize values mirror with values array (changes will send in updatecreate opcode any way
102 ClearUpdateMask(false); // false - we can't have update dat in update queue before adding to world
104 virtual void RemoveFromWorld()
106 // if we remove from world then sending changes not required
107 ClearUpdateMask(true);
111 ObjectGuid
const& GetObjectGuid() const { return *reinterpret_cast<ObjectGuid
const*>(&GetUInt64Value(0)); }
113 const uint64
& GetGUID() const { return GetUInt64Value(0); }
114 uint32
GetGUIDLow() const { return GUID_LOPART(GetUInt64Value(0)); }
115 PackedGuid
const& GetPackGUID() const { return m_PackGUID
; }
116 uint32
GetEntry() const { return GetUInt32Value(OBJECT_FIELD_ENTRY
); }
117 void SetEntry(uint32 entry
) { SetUInt32Value(OBJECT_FIELD_ENTRY
, entry
); }
119 uint8
GetTypeId() const { return m_objectTypeId
; }
120 bool isType(uint16 mask
) const { return (mask
& m_objectType
); }
122 virtual void BuildCreateUpdateBlockForPlayer( UpdateData
*data
, Player
*target
) const;
123 void SendCreateUpdateToPlayer(Player
* player
);
125 // must be overwrite in appropriate subclasses (WorldObject, Item currently), or will crash
126 virtual void AddToClientUpdateList();
127 virtual void RemoveFromClientUpdateList();
128 virtual void BuildUpdateData(UpdateDataMapType
& update_players
);
130 void BuildValuesUpdateBlockForPlayer( UpdateData
*data
, Player
*target
) const;
131 void BuildOutOfRangeUpdateBlock( UpdateData
*data
) const;
132 void BuildMovementUpdateBlock( UpdateData
* data
, uint16 flags
= 0 ) const;
134 virtual void DestroyForPlayer( Player
*target
, bool anim
= false ) const;
136 const int32
& GetInt32Value( uint16 index
) const
138 ASSERT( index
< m_valuesCount
|| PrintIndexError( index
, false) );
139 return m_int32Values
[ index
];
142 const uint32
& GetUInt32Value( uint16 index
) const
144 ASSERT( index
< m_valuesCount
|| PrintIndexError( index
, false) );
145 return m_uint32Values
[ index
];
148 const uint64
& GetUInt64Value( uint16 index
) const
150 ASSERT( index
+ 1 < m_valuesCount
|| PrintIndexError( index
, false) );
151 return *((uint64
*)&(m_uint32Values
[ index
]));
154 const float& GetFloatValue( uint16 index
) const
156 ASSERT( index
< m_valuesCount
|| PrintIndexError( index
, false ) );
157 return m_floatValues
[ index
];
160 uint8
GetByteValue( uint16 index
, uint8 offset
) const
162 ASSERT( index
< m_valuesCount
|| PrintIndexError( index
, false) );
163 ASSERT( offset
< 4 );
164 return *(((uint8
*)&m_uint32Values
[ index
])+offset
);
167 uint16
GetUInt16Value( uint16 index
, uint8 offset
) const
169 ASSERT( index
< m_valuesCount
|| PrintIndexError( index
, false) );
170 ASSERT( offset
< 2 );
171 return *(((uint16
*)&m_uint32Values
[ index
])+offset
);
174 void SetInt32Value( uint16 index
, int32 value
);
175 void SetUInt32Value( uint16 index
, uint32 value
);
176 void SetUInt64Value( uint16 index
, const uint64
&value
);
177 void SetFloatValue( uint16 index
, float value
);
178 void SetByteValue( uint16 index
, uint8 offset
, uint8 value
);
179 void SetUInt16Value( uint16 index
, uint8 offset
, uint16 value
);
180 void SetInt16Value( uint16 index
, uint8 offset
, int16 value
) { SetUInt16Value(index
,offset
,(uint16
)value
); }
181 void SetStatFloatValue( uint16 index
, float value
);
182 void SetStatInt32Value( uint16 index
, int32 value
);
184 void ApplyModUInt32Value(uint16 index
, int32 val
, bool apply
);
185 void ApplyModInt32Value(uint16 index
, int32 val
, bool apply
);
186 void ApplyModUInt64Value(uint16 index
, int32 val
, bool apply
);
187 void ApplyModPositiveFloatValue( uint16 index
, float val
, bool apply
);
188 void ApplyModSignedFloatValue( uint16 index
, float val
, bool apply
);
190 void ApplyPercentModFloatValue(uint16 index
, float val
, bool apply
)
192 val
= val
!= -100.0f
? val
: -99.9f
;
193 SetFloatValue(index
, GetFloatValue(index
) * (apply
?(100.0f
+val
)/100.0f
: 100.0f
/ (100.0f
+val
)) );
196 void SetFlag( uint16 index
, uint32 newFlag
);
197 void RemoveFlag( uint16 index
, uint32 oldFlag
);
199 void ToggleFlag( uint16 index
, uint32 flag
)
201 if(HasFlag(index
, flag
))
202 RemoveFlag(index
, flag
);
204 SetFlag(index
, flag
);
207 bool HasFlag( uint16 index
, uint32 flag
) const
209 ASSERT( index
< m_valuesCount
|| PrintIndexError( index
, false ) );
210 return (m_uint32Values
[ index
] & flag
) != 0;
213 void SetByteFlag( uint16 index
, uint8 offset
, uint8 newFlag
);
214 void RemoveByteFlag( uint16 index
, uint8 offset
, uint8 newFlag
);
216 void ToggleFlag( uint16 index
, uint8 offset
, uint8 flag
)
218 if(HasByteFlag(index
, offset
, flag
))
219 RemoveByteFlag(index
, offset
, flag
);
221 SetByteFlag(index
, offset
, flag
);
224 bool HasByteFlag( uint16 index
, uint8 offset
, uint8 flag
) const
226 ASSERT( index
< m_valuesCount
|| PrintIndexError( index
, false ) );
227 ASSERT( offset
< 4 );
228 return (((uint8
*)&m_uint32Values
[index
])[offset
] & flag
) != 0;
231 void ApplyModFlag( uint16 index
, uint32 flag
, bool apply
)
233 if(apply
) SetFlag(index
,flag
); else RemoveFlag(index
,flag
);
236 void SetFlag64( uint16 index
, uint64 newFlag
)
238 uint64 oldval
= GetUInt64Value(index
);
239 uint64 newval
= oldval
| newFlag
;
240 SetUInt64Value(index
,newval
);
243 void RemoveFlag64( uint16 index
, uint64 oldFlag
)
245 uint64 oldval
= GetUInt64Value(index
);
246 uint64 newval
= oldval
& ~oldFlag
;
247 SetUInt64Value(index
,newval
);
250 void ToggleFlag64( uint16 index
, uint64 flag
)
252 if(HasFlag64(index
, flag
))
253 RemoveFlag64(index
, flag
);
255 SetFlag64(index
, flag
);
258 bool HasFlag64( uint16 index
, uint64 flag
) const
260 ASSERT( index
< m_valuesCount
|| PrintIndexError( index
, false ) );
261 return (GetUInt64Value( index
) & flag
) != 0;
264 void ApplyModFlag64( uint16 index
, uint64 flag
, bool apply
)
266 if(apply
) SetFlag64(index
,flag
); else RemoveFlag64(index
, flag
);
269 void ClearUpdateMask(bool remove
);
271 bool LoadValues(const char* data
);
273 uint16
GetValuesCount() const { return m_valuesCount
; }
275 void InitValues() { _InitValues(); }
277 virtual bool hasQuest(uint32
/* quest_id */) const { return false; }
278 virtual bool hasInvolvedQuest(uint32
/* quest_id */) const { return false; }
284 void _Create (uint32 guidlow
, uint32 entry
, HighGuid guidhigh
);
286 virtual void _SetUpdateBits(UpdateMask
*updateMask
, Player
*target
) const;
288 virtual void _SetCreateBits(UpdateMask
*updateMask
, Player
*target
) const;
290 void BuildMovementUpdate(ByteBuffer
* data
, uint16 updateFlags
) const;
291 void BuildValuesUpdate(uint8 updatetype
, ByteBuffer
*data
, UpdateMask
*updateMask
, Player
*target
) const;
292 void BuildUpdateDataForPlayer(Player
* pl
, UpdateDataMapType
& update_players
);
296 uint8 m_objectTypeId
;
301 int32
*m_int32Values
;
302 uint32
*m_uint32Values
;
303 float *m_floatValues
;
306 uint32
*m_uint32Values_mirror
;
308 uint16 m_valuesCount
;
310 bool m_objectUpdated
;
315 PackedGuid m_PackGUID
;
317 // for output helpfull error messages from ASSERTs
318 bool PrintIndexError(uint32 index
, bool set
) const;
319 Object(const Object
&); // prevent generation copy constructor
320 Object
& operator=(Object
const&); // prevent generation assigment operator
323 struct WorldObjectChangeAccumulator
;
325 class MANGOS_DLL_SPEC WorldObject
: public Object
327 friend struct WorldObjectChangeAccumulator
;
330 virtual ~WorldObject ( ) {}
332 virtual void Update ( uint32
/*time_diff*/ ) { }
334 void _Create( uint32 guidlow
, HighGuid guidhigh
, uint32 phaseMask
);
336 void Relocate(float x
, float y
, float z
, float orientation
);
337 void Relocate(float x
, float y
, float z
);
339 void SetOrientation(float orientation
) { m_orientation
= orientation
; }
341 float GetPositionX( ) const { return m_positionX
; }
342 float GetPositionY( ) const { return m_positionY
; }
343 float GetPositionZ( ) const { return m_positionZ
; }
344 void GetPosition( float &x
, float &y
, float &z
) const
345 { x
= m_positionX
; y
= m_positionY
; z
= m_positionZ
; }
346 void GetPosition( WorldLocation
&loc
) const
347 { loc
.mapid
= m_mapId
; GetPosition(loc
.coord_x
, loc
.coord_y
, loc
.coord_z
); loc
.orientation
= GetOrientation(); }
348 float GetOrientation( ) const { return m_orientation
; }
349 void GetNearPoint2D( float &x
, float &y
, float distance
, float absAngle
) const;
350 void GetNearPoint( WorldObject
const* searcher
, float &x
, float &y
, float &z
, float searcher_size
, float distance2d
,float absAngle
) const;
351 void GetClosePoint(float &x
, float &y
, float &z
, float size
, float distance2d
= 0, float angle
= 0) const
353 // angle calculated from current orientation
354 GetNearPoint(NULL
,x
,y
,z
,size
,distance2d
,GetOrientation() + angle
);
356 void GetContactPoint( const WorldObject
* obj
, float &x
, float &y
, float &z
, float distance2d
= CONTACT_DISTANCE
) const
358 // angle to face `obj` to `this` using distance includes size of `obj`
359 GetNearPoint(obj
,x
,y
,z
,obj
->GetObjectSize(),distance2d
,GetAngle( obj
));
362 float GetObjectSize() const
364 return ( m_valuesCount
> UNIT_FIELD_BOUNDINGRADIUS
) ? m_floatValues
[UNIT_FIELD_BOUNDINGRADIUS
] : DEFAULT_WORLD_OBJECT_SIZE
;
366 bool IsPositionValid() const;
367 void UpdateGroundPositionZ(float x
, float y
, float &z
) const;
369 void GetRandomPoint( float x
, float y
, float z
, float distance
, float &rand_x
, float &rand_y
, float &rand_z
) const;
371 uint32
GetMapId() const { return m_mapId
; }
372 uint32
GetInstanceId() const { return m_InstanceId
; }
374 virtual void SetPhaseMask(uint32 newPhaseMask
, bool update
);
375 uint32
GetPhaseMask() const { return m_phaseMask
; }
376 bool InSamePhase(WorldObject
const* obj
) const { return InSamePhase(obj
->GetPhaseMask()); }
377 bool InSamePhase(uint32 phasemask
) const { return (GetPhaseMask() & phasemask
); }
379 uint32
GetZoneId() const;
380 uint32
GetAreaId() const;
381 void GetZoneAndAreaId(uint32
& zoneid
, uint32
& areaid
) const;
383 InstanceData
* GetInstanceData() const;
385 const char* GetName() const { return m_name
.c_str(); }
386 void SetName(const std::string
& newname
) { m_name
=newname
; }
388 virtual const char* GetNameForLocaleIdx(int32
/*locale_idx*/) const { return GetName(); }
390 float GetDistance( const WorldObject
* obj
) const;
391 float GetDistance(float x
, float y
, float z
) const;
392 float GetDistance2d(const WorldObject
* obj
) const;
393 float GetDistance2d(float x
, float y
) const;
394 float GetDistanceZ(const WorldObject
* obj
) const;
395 bool IsInMap(const WorldObject
* obj
) const
397 return IsInWorld() && obj
->IsInWorld() && (GetMap() == obj
->GetMap()) && InSamePhase(obj
);
399 bool IsWithinDist3d(float x
, float y
, float z
, float dist2compare
) const;
400 bool IsWithinDist2d(float x
, float y
, float dist2compare
) const;
401 bool _IsWithinDist(WorldObject
const* obj
, float dist2compare
, bool is3D
) const;
403 // use only if you will sure about placing both object at same map
404 bool IsWithinDist(WorldObject
const* obj
, float dist2compare
, bool is3D
= true) const
406 return obj
&& _IsWithinDist(obj
,dist2compare
,is3D
);
409 bool IsWithinDistInMap(WorldObject
const* obj
, float dist2compare
, bool is3D
= true) const
411 return obj
&& IsInMap(obj
) && _IsWithinDist(obj
,dist2compare
,is3D
);
413 bool IsWithinLOS(float x
, float y
, float z
) const;
414 bool IsWithinLOSInMap(const WorldObject
* obj
) const;
415 bool GetDistanceOrder(WorldObject
const* obj1
, WorldObject
const* obj2
, bool is3D
= true) const;
416 bool IsInRange(WorldObject
const* obj
, float minRange
, float maxRange
, bool is3D
= true) const;
417 bool IsInRange2d(float x
, float y
, float minRange
, float maxRange
) const;
418 bool IsInRange3d(float x
, float y
, float z
, float minRange
, float maxRange
) const;
420 float GetAngle( const WorldObject
* obj
) const;
421 float GetAngle( const float x
, const float y
) const;
422 bool HasInArc( const float arcangle
, const WorldObject
* obj
) const;
423 bool isInFrontInMap(WorldObject
const* target
,float distance
, float arc
= M_PI
) const;
424 bool isInBackInMap(WorldObject
const* target
, float distance
, float arc
= M_PI
) const;
425 bool isInFront(WorldObject
const* target
,float distance
, float arc
= M_PI
) const;
426 bool isInBack(WorldObject
const* target
, float distance
, float arc
= M_PI
) const;
428 virtual void CleanupsBeforeDelete(); // used in destructor or explicitly before mass creature delete to remove cross-references to already deleted units
430 virtual void SendMessageToSet(WorldPacket
*data
, bool self
);
431 virtual void SendMessageToSetInRange(WorldPacket
*data
, float dist
, bool self
);
432 void SendMessageToSetExcept(WorldPacket
*data
, Player
const* skipped_receiver
);
434 void MonsterSay(const char* text
, uint32 language
, uint64 TargetGuid
);
435 void MonsterYell(const char* text
, uint32 language
, uint64 TargetGuid
);
436 void MonsterTextEmote(const char* text
, uint64 TargetGuid
, bool IsBossEmote
= false);
437 void MonsterWhisper(const char* text
, uint64 receiver
, bool IsBossWhisper
= false);
438 void MonsterSay(int32 textId
, uint32 language
, uint64 TargetGuid
);
439 void MonsterYell(int32 textId
, uint32 language
, uint64 TargetGuid
);
440 void MonsterTextEmote(int32 textId
, uint64 TargetGuid
, bool IsBossEmote
= false);
441 void MonsterWhisper(int32 textId
, uint64 receiver
, bool IsBossWhisper
= false);
442 void MonsterYellToZone(int32 textId
, uint32 language
, uint64 TargetGuid
);
443 void BuildMonsterChat(WorldPacket
*data
, uint8 msgtype
, char const* text
, uint32 language
, char const* name
, uint64 TargetGuid
) const;
445 void PlayDistanceSound(uint32 sound_id
, Player
* target
= NULL
);
446 void PlayDirectSound(uint32 sound_id
, Player
* target
= NULL
);
448 void SendObjectDeSpawnAnim(uint64 guid
);
449 void SendGameObjectCustomAnim(uint64 guid
);
451 virtual bool IsHostileTo(Unit
const* unit
) const =0;
452 virtual bool IsFriendlyTo(Unit
const* unit
) const =0;
453 bool IsControlledByPlayer() const;
455 virtual void SaveRespawnTime() {}
456 void AddObjectToRemoveList();
458 void UpdateObjectVisibility();
460 // main visibility check function in normal case (ignore grey zone distance check)
461 bool isVisibleFor(Player
const* u
, WorldObject
const* viewPoint
) const { return isVisibleForInState(u
,viewPoint
,false); }
463 // low level function for visibility change code, must be define in all main world object subclasses
464 virtual bool isVisibleForInState(Player
const* u
, WorldObject
const* viewPoint
, bool inVisibleList
) const = 0;
466 void SetMap(Map
* map
);
467 Map
* GetMap() const { ASSERT(m_currMap
); return m_currMap
; }
468 //used to check all object's GetMap() calls when object is not in world!
469 void ResetMap() { m_currMap
= NULL
; }
471 //this function should be removed in nearest time...
472 Map
const* GetBaseMap() const;
474 void AddToClientUpdateList();
475 void RemoveFromClientUpdateList();
476 void BuildUpdateData(UpdateDataMapType
&);
478 Creature
* SummonCreature(uint32 id
, float x
, float y
, float z
, float ang
,TempSummonType spwtype
,uint32 despwtime
);
480 ViewPoint
& GetViewPoint() { return m_viewPoint
; }
482 explicit WorldObject();
484 //these functions are used mostly for Relocate() and Corpse/Player specific stuff...
485 //use them ONLY in LoadFromDB()/Create() funcs and nowhere else!
486 //mapId/instanceId should be set in SetMap() function!
487 void SetLocationMapId(uint32 _mapId
) { m_mapId
= _mapId
; }
488 void SetLocationInstanceId(uint32 _instanceId
) { m_InstanceId
= _instanceId
; }
493 Map
* m_currMap
; //current object's Map location
495 uint32 m_mapId
; // object at map with map_id
496 uint32 m_InstanceId
; // in map copy with instance id
497 uint32 m_phaseMask
; // in area phase state
504 ViewPoint m_viewPoint
;