OregonCore  revision 3611e8a-git
Your Favourite TBC server
Object.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the OregonCore Project. See AUTHORS file for Copyright information
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation; either version 2 of the License, or (at your
7  * option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "Common.h"
19 #include "SharedDefines.h"
20 #include "WorldPacket.h"
21 #include "Opcodes.h"
22 #include "World.h"
23 #include "Object.h"
24 #include "Creature.h"
25 #include "Player.h"
26 #include "ObjectMgr.h"
27 #include "WorldSession.h"
28 #include "UpdateData.h"
29 #include "UpdateMask.h"
30 #include "Util.h"
31 #include "ObjectAccessor.h"
32 #include "Transports.h"
33 #include "VMapFactory.h"
34 #include "CellImpl.h"
35 #include "GridNotifiers.h"
36 #include "GridNotifiersImpl.h"
37 #include "TemporarySummon.h"
38 #include "Totem.h"
39 #include "OutdoorPvPMgr.h"
40 #include "packet_builder.h"
41 #include "MapManager.h"
42 
44 {
45  switch (guid_hi)
46  {
47  case HIGHGUID_ITEM:
48  return TYPEID_ITEM;
49  //case HIGHGUID_CONTAINER: return TYPEID_CONTAINER; HIGHGUID_CONTAINER == HIGHGUID_ITEM currently
50  case HIGHGUID_UNIT:
51  return TYPEID_UNIT;
52  case HIGHGUID_PET:
53  return TYPEID_UNIT;
54  case HIGHGUID_PLAYER:
55  return TYPEID_PLAYER;
57  return TYPEID_GAMEOBJECT;
59  return TYPEID_DYNAMICOBJECT;
60  case HIGHGUID_CORPSE:
61  return TYPEID_CORPSE;
63  return TYPEID_GAMEOBJECT;
64  }
65  return TYPEID_OBJECT; // unknown
66 }
67 
69 {
72 
73  m_uint32Values = 0;
75  m_valuesCount = 0;
76 
77  m_inWorld = false;
78  m_objectUpdated = false;
79 }
80 
82 {
83  // this may happen because there are many !create/delete
84  if (IsWorldObject() && m_currMap)
85  {
86  if (GetTypeId() == TYPEID_CORPSE)
87  {
88  sLog.outError("Crash alert! Object::~Object Corpse guid=" UI64FMTD ", type=%d, entry=%u deleted but still in map!!", GetGUID(), ((Corpse*)this)->GetType(), GetEntry());
89  ASSERT(false);
90  }
91  ResetMap();
92  }
93 }
94 
96 {
97  if (IsInWorld())
98  {
99  // Do NOT call RemoveFromWorld here, if the object is a player it will crash
100  sLog.outError("Crash alert! Object::~Object (GUID: %u TypeId: %u) deleted but still in world!!", GetGUIDLow(), GetTypeId());
101  ASSERT(false);
102  }
103 
104  if (m_objectUpdated)
105  {
106  sLog.outError("Crash alert! Object::~Object (GUID: %u TypeId: %u) deleted but still has updated status!!", GetGUIDLow(), GetTypeId());
107  ASSERT(false);
108  }
109 
110  delete [] m_uint32Values;
111  delete [] m_uint32Values_mirror;
112 }
113 
115 {
117  memset(m_uint32Values, 0, m_valuesCount * sizeof(uint32));
118 
120  memset(m_uint32Values_mirror, 0, m_valuesCount * sizeof(uint32));
121 
122  m_objectUpdated = false;
123 }
124 
125 void Object::_Create(uint32 guidlow, uint32 entry, HighGuid guidhigh)
126 {
127  if (!m_uint32Values)
128  _InitValues();
129 
130  uint64 guid = MAKE_NEW_GUID(guidlow, entry, guidhigh);
133  m_PackGUID.Set(guid);
134 }
135 
137 {
138  ByteBuffer buf(500);
139 
140  buf << uint8(UPDATETYPE_MOVEMENT);
141  buf << GetGUID();
142 
143  _BuildMovementUpdate(&buf, flags);
144 
145  data->AddUpdateBlock(buf);
146 }
147 
149 {
150  if (!target)
151  return;
152 
153  uint8 updatetype = UPDATETYPE_CREATE_OBJECT;
154  uint8 flags = m_updateFlag;
155 
157  if (target == this) // building packet for oneself
158  flags |= UPDATEFLAG_SELF;
159 
160  if (flags & UPDATEFLAG_HAS_POSITION)
161  {
162  // UPDATETYPE_CREATE_OBJECT2 dynamic objects, corpses...
164  updatetype = UPDATETYPE_CREATE_OBJECT2;
165 
166  // UPDATETYPE_CREATE_OBJECT2 for pets...
167  if (target->GetPetGUID() == GetGUID())
168  updatetype = UPDATETYPE_CREATE_OBJECT2;
169 
170  // UPDATETYPE_CREATE_OBJECT2 for some gameobject types...
172  {
173  switch (((GameObject*)this)->GetGoType())
174  {
179  updatetype = UPDATETYPE_CREATE_OBJECT2;
180  break;
182  flags |= UPDATEFLAG_TRANSPORT;
183  break;
184  default:
185  break;
186  }
187  }
188  }
189 
190  //sLog.outDebug("BuildCreateUpdate: update-type: %u, object-type: %u got flags: %X, flags2: %X", updatetype, m_objectTypeId, flags, flags2);
191 
192  ByteBuffer buf(500);
193  buf << (uint8)updatetype;
194  //buf << GetPackGUID(); //client crashes when using this
195  buf << (uint8)0xFF << GetGUID();
196  buf << (uint8)m_objectTypeId;
197 
198  _BuildMovementUpdate(&buf, flags);
199 
200  UpdateMask updateMask;
201  updateMask.SetCount(m_valuesCount);
202  _SetCreateBits(&updateMask, target);
203  _BuildValuesUpdate(updatetype, &buf, &updateMask, target);
204  data->AddUpdateBlock(buf);
205 }
206 
208 {
209  // send create update to player
210  UpdateData upd;
211  WorldPacket packet;
212 
213  BuildCreateUpdateBlockForPlayer(&upd, player);
214  upd.BuildPacket(&packet);
215  player->GetSession()->SendPacket(&packet);
216 }
217 
219 {
220  ByteBuffer buf(500);
221 
222  buf << (uint8) UPDATETYPE_VALUES;
223  //buf << GetPackGUID(); //client crashes when using this. but not have crash in debug mode
224  buf << (uint8)0xFF;
225  buf << GetGUID();
226 
227  UpdateMask updateMask;
228  updateMask.SetCount(m_valuesCount);
229 
230  _SetUpdateBits(&updateMask, target);
231  _BuildValuesUpdate(UPDATETYPE_VALUES, &buf, &updateMask, target);
232 
233  data->AddUpdateBlock(buf);
234 }
235 
237 {
238  data->AddOutOfRangeGUID(GetGUID());
239 }
240 
241 void Object::DestroyForPlayer(Player* target, bool onDeath) const
242 {
243  ASSERT(target);
244 
245  WorldPacket data(SMSG_DESTROY_OBJECT, 8 + 1);
246  data << uint64(GetGUID());
249  data << uint8(onDeath ? 1 : 0);
250  target->GetSession()->SendPacket(&data);
251 }
252 
253 void Object::_BuildMovementUpdate(ByteBuffer* data, uint8 updateFlags) const
254 {
255  uint32 moveFlags = MOVEMENTFLAG_NONE;
256 
257  *data << uint8(updateFlags); // update flags
258 
259  if (updateFlags & UPDATEFLAG_LIVING)
260  {
261  switch (GetTypeId())
262  {
263  case TYPEID_UNIT:
264  {
265  moveFlags = ((Unit*)this)->GetUnitMovementFlags();
266  moveFlags &= ~MOVEMENTFLAG_ONTRANSPORT;
267  }
268  break;
269  case TYPEID_PLAYER:
270  {
271  moveFlags = ToPlayer()->GetUnitMovementFlags();
272 
273  if (ToPlayer()->GetTransport())
274  moveFlags |= MOVEMENTFLAG_ONTRANSPORT;
275  else
276  moveFlags &= ~MOVEMENTFLAG_ONTRANSPORT;
277 
278  }
279  break;
280  }
281 
282  *data << uint32(moveFlags); // movement flags
283  *data << uint8(0); // movemoveFlags
284  *data << uint32(getMSTime()); // time (in milliseconds)
285  }
286 
287  // 0x40
288  if (updateFlags & UPDATEFLAG_HAS_POSITION)
289  {
290  // 0x02
291  if (updateFlags & UPDATEFLAG_TRANSPORT && ((GameObject*)this)->GetGoType() == GAMEOBJECT_TYPE_MO_TRANSPORT)
292  {
293  *data << float(0);
294  *data << float(0);
295  *data << float(0);
296  *data << float(((WorldObject*)this)->GetOrientation());
297  }
298  else
299  {
300  *data << float(((WorldObject*)this)->GetPositionX());
301  *data << float(((WorldObject*)this)->GetPositionY());
302  *data << float(((WorldObject*)this)->GetPositionZ());
303  *data << float(((WorldObject*)this)->GetOrientation());
304  }
305  }
306 
307  // 0x20
308  if (updateFlags & UPDATEFLAG_LIVING)
309  {
310  // 0x00000200
311  if (moveFlags & MOVEMENTFLAG_ONTRANSPORT)
312  {
313  if (GetTypeId() == TYPEID_PLAYER)
314  {
315  *data << (uint64)ToPlayer()->GetTransport()->GetGUID();
316  *data << (float)ToPlayer()->GetTransOffsetX();
317  *data << (float)ToPlayer()->GetTransOffsetY();
318  *data << (float)ToPlayer()->GetTransOffsetZ();
319  *data << (float)ToPlayer()->GetTransOffsetO();
320  *data << (uint32)ToPlayer()->GetTransTime();
321  }
322  //Oregon currently not have support for other than player on transport
323  }
324 
325  // 0x02200000
326  if (moveFlags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING2))
327  {
328  if (GetTypeId() == TYPEID_PLAYER)
329  *data << (float)ToPlayer()->m_movementInfo.s_pitch;
330  else
331  *data << float(0); // is't part of movement packet, we must store and send it...
332  }
333 
334  if (GetTypeId() == TYPEID_PLAYER)
335  *data << (uint32)ToPlayer()->m_movementInfo.GetFallTime();
336  else
337  *data << uint32(0); // last fall time
338 
339  // 0x00001000
340  if (moveFlags & MOVEMENTFLAG_FALLING)
341  {
342  if (GetTypeId() == TYPEID_PLAYER)
343  {
344  *data << float(ToPlayer()->m_movementInfo.j_velocity);
345  *data << float(ToPlayer()->m_movementInfo.j_sinAngle);
346  *data << float(ToPlayer()->m_movementInfo.j_cosAngle);
347  *data << float(ToPlayer()->m_movementInfo.j_xyspeed);
348  }
349  else
350  {
351  *data << float(0);
352  *data << float(0);
353  *data << float(0);
354  *data << float(0);
355  }
356  }
357 
358  // 0x04000000
359  if (moveFlags & MOVEMENTFLAG_SPLINE_ELEVATION)
360  {
361  if (GetTypeId() == TYPEID_PLAYER)
362  *data << float(ToPlayer()->m_movementInfo.u_unk1);
363  else
364  *data << float(0);
365  }
366 
367  // Unit speeds
368  *data << ((Unit*)this)->GetSpeed(MOVE_WALK);
369  *data << ((Unit*)this)->GetSpeed(MOVE_RUN);
370  *data << ((Unit*)this)->GetSpeed(MOVE_RUN_BACK);
371  *data << ((Unit*)this)->GetSpeed(MOVE_SWIM);
372  *data << ((Unit*)this)->GetSpeed(MOVE_SWIM_BACK);
373  *data << ((Unit*)this)->GetSpeed(MOVE_FLIGHT);
374  *data << ((Unit*)this)->GetSpeed(MOVE_FLIGHT_BACK);
375  *data << ((Unit*)this)->GetSpeed(MOVE_TURN_RATE);
376 
377  // 0x08000000
378  if (moveFlags & MOVEMENTFLAG_SPLINE_ENABLED)
379  Movement::PacketBuilder::WriteCreate(*((Unit*)this)->movespline, *data);
380  }
381 
382  // 0x8
383  if (updateFlags & UPDATEFLAG_LOWGUID)
384  {
385  switch (GetTypeId())
386  {
387  case TYPEID_OBJECT:
388  case TYPEID_ITEM:
389  case TYPEID_CONTAINER:
390  case TYPEID_GAMEOBJECT:
392  case TYPEID_CORPSE:
393  *data << uint32(GetGUIDLow()); // GetGUIDLow()
394  break;
395  case TYPEID_UNIT:
396  *data << uint32(0x0000000B); // unk, can be 0xB or 0xC
397  break;
398  case TYPEID_PLAYER:
399  if (updateFlags & UPDATEFLAG_SELF)
400  *data << uint32(0x00000015); // unk, can be 0x15 or 0x22
401  else
402  *data << uint32(0x00000008); // unk, can be 0x7 or 0x8
403  break;
404  default:
405  *data << uint32(0x00000000); // unk
406  break;
407  }
408  }
409 
410  // 0x10
411  if (updateFlags & UPDATEFLAG_HIGHGUID)
412  {
413  switch (GetTypeId())
414  {
415  case TYPEID_OBJECT:
416  case TYPEID_ITEM:
417  case TYPEID_CONTAINER:
418  case TYPEID_GAMEOBJECT:
420  case TYPEID_CORPSE:
421  *data << uint32(GetGUIDHigh()); // GetGUIDHigh()
422  break;
423  default:
424  *data << uint32(0x00000000); // unk
425  break;
426  }
427  }
428 
429  // 0x4
430  if (updateFlags & UPDATEFLAG_HAS_ATTACKING_TARGET) // packed guid (probably target guid)
431  {
432  if (Unit const* me = ToUnit())
433  {
434  if (me->GetVictim())
435  *data << me->GetVictim()->GetPackGUID();
436  else
437  *data << uint8(0);
438  }
439  else
440  *data << uint8(0);
441  }
442 
443  // 0x2
444  if (updateFlags & UPDATEFLAG_TRANSPORT)
445  {
446  *data << uint32(getMSTime()); // ms time
447  }
448 }
449 
450 void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer* data, UpdateMask* updateMask, Player* target) const
451 {
452  if (!target)
453  return;
454 
455  bool IsActivateToQuest = false;
456  if (updatetype == UPDATETYPE_CREATE_OBJECT || updatetype == UPDATETYPE_CREATE_OBJECT2)
457  {
458  if (isType(TYPEMASK_GAMEOBJECT) && !((GameObject*)this)->IsTransport())
459  {
460  if (((GameObject*)this)->ActivateToQuest(target) || target->IsGameMaster())
461  IsActivateToQuest = true;
462 
463  updateMask->SetBit(GAMEOBJECT_DYN_FLAGS);
464 
466  updateMask->SetBit(GAMEOBJECT_ARTKIT);
467  }
468  }
469  else //case UPDATETYPE_VALUES
470  {
471  if (isType(TYPEMASK_GAMEOBJECT) && !((GameObject*)this)->IsTransport())
472  {
473  if (((GameObject*)this)->ActivateToQuest(target) || target->IsGameMaster())
474  IsActivateToQuest = true;
475 
476  updateMask->SetBit(GAMEOBJECT_DYN_FLAGS);
477  updateMask->SetBit(GAMEOBJECT_ANIMPROGRESS);
478  }
479  }
480 
481  ASSERT(updateMask && updateMask->GetCount() == m_valuesCount);
482 
483  *data << (uint8)updateMask->GetBlockCount();
484  data->append(updateMask->GetMask(), updateMask->GetLength());
485 
486  // 2 specialized loops for speed optimization in non-unit case
487  if (isType(TYPEMASK_UNIT)) // unit (creature/player) case
488  {
489  for (uint16 index = 0; index < m_valuesCount; index ++)
490  {
491  if (updateMask->GetBit(index))
492  {
493  // remove custom flag before send
494  if (index == UNIT_NPC_FLAGS)
495  *data << uint32(m_uint32Values[index]);
496  // FIXME: Some values at server stored in float format but must be sent to client in uint32 format
497  else if (index >= UNIT_FIELD_BASEATTACKTIME && index <= UNIT_FIELD_RANGEDATTACKTIME)
498  {
499  // convert from float to uint32 and send
500  *data << uint32(m_floatValues[ index ] < 0 ? 0 : m_floatValues[ index ]);
501  }
502  // there are some float values which may be negative or can't get negative due to other checks
503  else if ((index >= UNIT_FIELD_NEGSTAT0 && index <= UNIT_FIELD_NEGSTAT4) ||
506  (index >= UNIT_FIELD_POSSTAT0 && index <= UNIT_FIELD_POSSTAT4))
507  *data << uint32(m_floatValues[ index ]);
508  // Gamemasters should be always able to select units - remove not selectable flag
509  else if (index == UNIT_FIELD_FLAGS && target->IsGameMaster())
510  *data << (m_uint32Values[ index ] & ~UNIT_FLAG_NOT_SELECTABLE);
511  // use modelid_a if not gm, _h if gm for CREATURE_FLAG_EXTRA_TRIGGER creatures
512  else if (index == UNIT_FIELD_DISPLAYID && GetTypeId() == TYPEID_UNIT)
513  {
514  const CreatureInfo* cinfo = ToCreature()->GetCreatureTemplate();
516  {
517  if (target->IsGameMaster())
518  {
519  if (cinfo->modelid1)
520  *data << cinfo->modelid1;
521  else
522  *data << 17519; // world invisible trigger's model
523  }
524  else
525  {
526  *data << 11686; // world invisible trigger's model
527  }
528  }
529  else
530  *data << m_uint32Values[ index ];
531  }
532  // hide lootable animation for unallowed players
533  else if (index == UNIT_DYNAMIC_FLAGS && GetTypeId() == TYPEID_UNIT)
534  {
535  Creature const* creature = ToCreature();
536 
537  if (creature)
538  {
539  if (!creature->isDead())
540  {
541  //sLog.outError("MOB ALIVE!");
542  if (creature->isTappedBy(target))
543  *data << (m_uint32Values[index] & ~UNIT_DYNFLAG_OTHER_TAGGER);
544  else
545  *data << (m_uint32Values[index] | UNIT_DYNFLAG_OTHER_TAGGER);
546  }
547  else
548  {
549  //sLog.outError("MOB DEAD!");
550  if (!target->isAllowedToLoot(creature))
551  *data << (m_uint32Values[index] & ~UNIT_DYNFLAG_LOOTABLE);
552  else
553  *data << (m_uint32Values[index] | UNIT_DYNFLAG_LOOTABLE);
554  }
555  }
556 
557  }
558 
559  // hide RAF menu to non-RAF linked friends
560  else if (index == UNIT_DYNAMIC_FLAGS && GetTypeId() == TYPEID_PLAYER)
561  {
562  if (sObjectMgr.GetRAFLinkStatus(target->ToPlayer(), this->ToPlayer()) != RAF_LINK_NONE)
563  *data << (m_uint32Values[ index ]);
564  else
565  *data << (m_uint32Values[ index ] & ~UNIT_DYNFLAG_REFER_A_FRIEND);
566  }
567  // FG: pretend that OTHER players in own group are friendly ("blue")
568  else if (index == UNIT_FIELD_BYTES_2 || index == UNIT_FIELD_FACTIONTEMPLATE)
569  {
570  bool ch = false;
571  if (target->GetTypeId() == TYPEID_PLAYER && GetTypeId() == TYPEID_PLAYER && target != this)
572  {
573  if (target->IsInSameGroupWith(ToPlayer()) || target->IsInSameRaidWith(ToPlayer()))
574  {
575  if (index == UNIT_FIELD_BYTES_2)
576  {
577  DEBUG_LOG("-- VALUES_UPDATE: Sending '%s' the blue-group-fix from '%s' (flag)", target->GetName(), ToPlayer()->GetName());
578  *data << (m_uint32Values[ index ] & ((UNIT_BYTE2_FLAG_SANCTUARY | UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5) << 8)); // this flag is at uint8 offset 1 !!
579 
580  ch = true;
581  }
582  else if (index == UNIT_FIELD_FACTIONTEMPLATE)
583  {
584  FactionTemplateEntry const* ft1, *ft2;
586  ft2 = target->ToPlayer()->GetFactionTemplateEntry();
587  if (ft1 && ft2 && !ft1->IsFriendlyTo(*ft2))
588  {
589  uint32 faction = target->ToPlayer()->getFaction(); // pretend that all other HOSTILE players have own faction, to allow follow, heal, rezz (trade wont work)
590  DEBUG_LOG("-- VALUES_UPDATE: Sending '%s' the blue-group-fix from '%s' (faction %u)", target->GetName(), ToPlayer()->GetName(), faction);
591  *data << uint32(faction);
592  ch = true;
593  }
594  }
595  }
596  }
597  if (!ch)
598  *data << m_uint32Values[ index ];
599  }
600  else if (index == UNIT_FIELD_HEALTH)
601  {
602  if (GetTypeId() == TYPEID_UNIT || GetTypeId() == TYPEID_PLAYER)
603  {
604  const Unit* me = reinterpret_cast<const Unit*>(this);
605  if (me->ShouldRevealHealthTo(target))
606  *data << m_uint32Values[ index ];
607  else
608  *data << uint32(std::ceil(me->GetHealthPct()));
609  }
610  else
611  *data << m_uint32Values[ index ];
612  }
613  else if (index == UNIT_FIELD_MAXHEALTH)
614  {
615  if (GetTypeId() == TYPEID_UNIT || GetTypeId() == TYPEID_PLAYER)
616  {
617  const Unit* me = reinterpret_cast<const Unit*>(this);
618  if (me->ShouldRevealHealthTo(target))
619  *data << m_uint32Values[ index ];
620  else
621  *data << uint32(100);
622  }
623  else
624  *data << m_uint32Values[ index ];
625  }
626  else
627  {
628  // send in current format (float as float, uint32 as uint32)
629  *data << m_uint32Values[ index ];
630  }
631  }
632  }
633  }
634  else if (isType(TYPEMASK_GAMEOBJECT)) // gameobject case
635  {
636  for (uint16 index = 0; index < m_valuesCount; ++index)
637  {
638  if (updateMask->GetBit(index))
639  {
640  // send in current format (float as float, uint32 as uint32)
641  if (index == GAMEOBJECT_DYN_FLAGS)
642  {
643  if (IsActivateToQuest)
644  {
645  switch (((GameObject*)this)->GetGoType())
646  {
650  *data << uint16(-1);
651  break;
652  default:
653  *data << uint32(0); // unknown, not happen.
654  break;
655  }
656  }
657  else
658  *data << uint32(0); // disable quest object
659  }
660  else
661  *data << m_uint32Values[ index ]; // other cases
662  }
663  }
664  }
665  else // other objects case (no special index checks)
666  {
667  for (uint16 index = 0; index < m_valuesCount; ++index)
668  {
669  if (updateMask->GetBit(index))
670  {
671  // send in current format (float as float, uint32 as uint32)
672  *data << m_uint32Values[ index ];
673  }
674  }
675  }
676 }
677 
678 void Object::ClearUpdateMask(bool remove)
679 {
681 
682  if (m_objectUpdated)
683  {
684  if (remove)
686  m_objectUpdated = false;
687  }
688 }
689 
691 {
692  UpdateDataMapType::iterator iter = data_map.find(pl);
693 
694  if (iter == data_map.end())
695  {
696  std::pair<UpdateDataMapType::iterator, bool> p = data_map.insert(UpdateDataMapType::value_type(pl, UpdateData()));
697  ASSERT(p.second);
698  iter = p.first;
699  }
700 
701  BuildValuesUpdateBlockForPlayer(&iter->second, iter->first);
702 }
703 
704 bool Object::LoadValues(const char* data)
705 {
706  if (!m_uint32Values) _InitValues();
707 
708  Tokens tokens = StrSplit(data, " ");
709 
710  if (tokens.size() != m_valuesCount)
711  return false;
712 
713  Tokens::iterator iter;
714  int index;
715  for (iter = tokens.begin(), index = 0; index < m_valuesCount; ++iter, ++index)
716  m_uint32Values[index] = atol((*iter).c_str());
717 
718  return true;
719 }
720 
721 void Object::_LoadIntoDataField(const char* data, uint32 startOffset, uint32 count)
722 {
723  if (!data)
724  return;
725 
726  Tokens tokens = StrSplit(data, " ");
727 
728  if (tokens.size() != count)
729  return;
730 
731  Tokens::iterator iter;
732  uint32 index;
733  for (iter = tokens.begin(), index = 0; index < count; ++iter, ++index)
734  m_uint32Values[startOffset + index] = atol((*iter).c_str());
735 }
736 
737 void Object::_SetUpdateBits(UpdateMask* updateMask, Player* /*target*/) const
738 {
740  uint32* mirror = m_uint32Values_mirror;
741 
742  for (uint16 index = 0; index < m_valuesCount; ++index, ++value, ++mirror)
743  {
744  if (*mirror != *value)
745  updateMask->SetBit(index);
746  }
747 }
748 
749 void Object::_SetCreateBits(UpdateMask* updateMask, Player* /*target*/) const
750 {
752 
753  for (uint16 index = 0; index < m_valuesCount; ++index, ++value)
754  {
755  if (*value)
756  updateMask->SetBit(index);
757  }
758 }
759 
761 {
762  ASSERT(index < m_valuesCount || PrintIndexError(index, true));
763 
764  if (m_int32Values[ index ] != value)
765  {
766  m_int32Values[ index ] = value;
767 
768  if (m_inWorld)
769  {
770  if (!m_objectUpdated)
771  {
773  m_objectUpdated = true;
774  }
775  }
776  }
777 }
778 
780 {
781  ASSERT(index < m_valuesCount || PrintIndexError(index, true));
782 
783  if (m_uint32Values[ index ] != value)
784  {
785  m_uint32Values[ index ] = value;
786 
787  if (m_inWorld)
788  {
789  if (!m_objectUpdated)
790  {
792  m_objectUpdated = true;
793  }
794  }
795  }
796 }
797 
799 {
800  ASSERT(index + 1 < m_valuesCount || PrintIndexError(index, true));
801  if (*((uint64*) & (m_uint32Values[ index ])) != value)
802  {
803  m_uint32Values[ index ] = *((uint32*)&value);
804  m_uint32Values[ index + 1 ] = *(((uint32*)&value) + 1);
805 
806  if (m_inWorld)
807  {
808  if (!m_objectUpdated)
809  {
811  m_objectUpdated = true;
812  }
813  }
814  }
815 }
816 
818 {
819  ASSERT(index + 1 < m_valuesCount || PrintIndexError(index , true));
820  if (value && !*((uint64*) & (m_uint32Values[index])))
821  {
822  m_uint32Values[ index ] = *((uint32*)&value);
823  m_uint32Values[ index + 1 ] = *(((uint32*)&value) + 1);
824 
825  if (m_inWorld)
826  {
827  if (!m_objectUpdated)
828  {
830  m_objectUpdated = true;
831  }
832  }
833  return true;
834  }
835  return false;
836 }
837 
839 {
840  ASSERT(index + 1 < m_valuesCount || PrintIndexError(index , true));
841  if (value && *((uint64*) & (m_uint32Values[index])) == value)
842  {
843  m_uint32Values[ index ] = 0;
844  m_uint32Values[ index + 1 ] = 0;
845 
846  if (m_inWorld)
847  {
848  if (!m_objectUpdated)
849  {
851  m_objectUpdated = true;
852  }
853  }
854  return true;
855  }
856  return false;
857 }
858 
860 {
861  ASSERT(index < m_valuesCount || PrintIndexError(index, true));
862 
863  if (m_floatValues[ index ] != value)
864  {
865  m_floatValues[ index ] = value;
866 
867  if (m_inWorld)
868  {
869  if (!m_objectUpdated)
870  {
872  m_objectUpdated = true;
873  }
874  }
875  }
876 }
877 
879 {
880  ASSERT(index < m_valuesCount || PrintIndexError(index, true));
881 
882  if (offset > 4)
883  {
884  sLog.outError("Object::SetByteValue: wrong offset %u", offset);
885  return;
886  }
887 
888  if (uint8(m_uint32Values[ index ] >> (offset * 8)) != value)
889  {
890  m_uint32Values[ index ] &= ~uint32(uint32(0xFF) << (offset * 8));
891  m_uint32Values[ index ] |= uint32(uint32(value) << (offset * 8));
892 
893  if (m_inWorld)
894  {
895  if (!m_objectUpdated)
896  {
898  m_objectUpdated = true;
899  }
900  }
901  }
902 }
903 
905 {
906  ASSERT(index < m_valuesCount || PrintIndexError(index, true));
907 
908  if (offset > 2)
909  {
910  sLog.outError("Object::SetUInt16Value: wrong offset %u", offset);
911  return;
912  }
913 
914  if (uint16(m_uint32Values[ index ] >> (offset * 16)) != value)
915  {
916  m_uint32Values[ index ] &= ~uint32(uint32(0xFFFF) << (offset * 16));
917  m_uint32Values[ index ] |= uint32(uint32(value) << (offset * 16));
918 
919  if (m_inWorld)
920  {
921  if (!m_objectUpdated)
922  {
924  m_objectUpdated = true;
925  }
926  }
927  }
928 }
929 
931 {
932  if (value < 0)
933  value = 0.0f;
934 
935  SetFloatValue(index, value);
936 }
937 
939 {
940  if (value < 0)
941  value = 0;
942 
943  SetUInt32Value(index, uint32(value));
944 }
945 
947 {
948  int32 cur = GetUInt32Value(index);
949  cur += (apply ? val : -val);
950  if (cur < 0)
951  cur = 0;
952  SetUInt32Value(index, cur);
953 }
954 
956 {
957  int32 cur = GetInt32Value(index);
958  cur += (apply ? val : -val);
959  SetInt32Value(index, cur);
960 }
961 
962 void Object::ApplyModSignedFloatValue(uint16 index, float val, bool apply)
963 {
964  float cur = GetFloatValue(index);
965  cur += (apply ? val : -val);
966  SetFloatValue(index, cur);
967 }
968 
969 void Object::ApplyPercentModFloatValue(uint16 index, float val, bool apply)
970 {
971  float value = GetFloatValue(index);
972  ApplyPercentModFloatVar(value, val, apply);
973  SetFloatValue(index, value);
974 }
975 
976 void Object::ApplyModPositiveFloatValue(uint16 index, float val, bool apply)
977 {
978  float cur = GetFloatValue(index);
979  cur += (apply ? val : -val);
980  if (cur < 0)
981  cur = 0;
982  SetFloatValue(index, cur);
983 }
984 
985 void Object::SetFlag(uint16 index, uint32 newFlag)
986 {
987  ASSERT(index < m_valuesCount || PrintIndexError(index, true));
988  uint32 oldval = m_uint32Values[ index ];
989  uint32 newval = oldval | newFlag;
990 
991  if (oldval != newval)
992  {
993  m_uint32Values[ index ] = newval;
994 
995  if (m_inWorld)
996  {
997  if (!m_objectUpdated)
998  {
1000  m_objectUpdated = true;
1001  }
1002  }
1003  }
1004 }
1005 
1006 void Object::RemoveFlag(uint16 index, uint32 oldFlag)
1007 {
1008  ASSERT(index < m_valuesCount || PrintIndexError(index, true));
1010 
1011  uint32 oldval = m_uint32Values[ index ];
1012  uint32 newval = oldval & ~oldFlag;
1013 
1014  if (oldval != newval)
1015  {
1016  m_uint32Values[ index ] = newval;
1017 
1018  if (m_inWorld)
1019  {
1020  if (!m_objectUpdated)
1021  {
1023  m_objectUpdated = true;
1024  }
1025  }
1026  }
1027 }
1028 
1029 void Object::SetByteFlag(uint16 index, uint8 offset, uint8 newFlag)
1030 {
1031  ASSERT(index < m_valuesCount || PrintIndexError(index, true));
1032 
1033  if (offset > 4)
1034  {
1035  sLog.outError("Object::SetByteFlag: wrong offset %u", offset);
1036  return;
1037  }
1038 
1039  if (!(uint8(m_uint32Values[ index ] >> (offset * 8)) & newFlag))
1040  {
1041  m_uint32Values[ index ] |= uint32(uint32(newFlag) << (offset * 8));
1042 
1043  if (m_inWorld)
1044  {
1045  if (!m_objectUpdated)
1046  {
1048  m_objectUpdated = true;
1049  }
1050  }
1051  }
1052 }
1053 
1054 void Object::RemoveByteFlag(uint16 index, uint8 offset, uint8 oldFlag)
1055 {
1056  ASSERT(index < m_valuesCount || PrintIndexError(index, true));
1057 
1058  if (offset > 4)
1059  {
1060  sLog.outError("Object::RemoveByteFlag: wrong offset %u", offset);
1061  return;
1062  }
1063 
1064  if (uint8(m_uint32Values[ index ] >> (offset * 8)) & oldFlag)
1065  {
1066  m_uint32Values[ index ] &= ~uint32(uint32(oldFlag) << (offset * 8));
1067 
1068  if (m_inWorld)
1069  {
1070  if (!m_objectUpdated)
1071  {
1073  m_objectUpdated = true;
1074  }
1075  }
1076  }
1077 }
1078 
1079 bool Object::PrintIndexError(uint32 index, bool set) const
1080 {
1081  sLog.outError("Attempt %s invalid 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);
1082 
1083  // assert must fail after function call
1084  return false;
1085 }
1086 
1087 WorldObject::WorldObject(bool isWorldObject):
1088  WorldLocation()
1089  , m_groupLootTimer(0)
1090  , lootingGroupLeaderGUID(0)
1091  , m_isWorldObject(isWorldObject)
1092  , m_name("")
1093  , m_isActive(false)
1094  , m_zoneScript(NULL)
1095  , m_currMap(NULL)
1096  , m_InstanceId(0)
1097  , m_notifyflags(0), m_executed_notifies(0)
1098 {
1101 }
1102 
1104 {
1105  if (!IsInWorld())
1106  return;
1107 
1108  GetMap()->AddObjectToSwitchList(this, on);
1109 }
1110 
1112 {
1113  if (m_isWorldObject)
1114  return true;
1115 
1116  if (ToCreature() && ToCreature()->m_isTempWorldObject)
1117  return true;
1118 
1119  return false;
1120 }
1121 
1123 {
1124  if (m_isActive == on)
1125  return;
1126 
1127  if (GetTypeId() == TYPEID_PLAYER)
1128  return;
1129 
1130  m_isActive = on;
1131 
1132  if (!IsInWorld())
1133  return;
1134 
1135  Map* map = FindMap();
1136  if (!map)
1137  return;
1138 
1139  if (on)
1140  {
1141  if (GetTypeId() == TYPEID_UNIT)
1142  map->AddToActive(ToCreature());
1143  else if (GetTypeId() == TYPEID_DYNAMICOBJECT)
1144  map->AddToActive((DynamicObject*)this);
1145  }
1146  else
1147  {
1148  if (GetTypeId() == TYPEID_UNIT)
1149  map->RemoveFromActive(ToCreature());
1150  else if (GetTypeId() == TYPEID_DYNAMICOBJECT)
1151  map->RemoveFromActive((DynamicObject*)this);
1152  }
1153 }
1154 
1156 {
1157  if (IsInWorld())
1158  RemoveFromWorld();
1159 }
1160 
1161 void WorldObject::_Create(uint32 guidlow, HighGuid guidhigh)
1162 {
1163  Object::_Create(guidlow, 0, guidhigh);
1164 }
1165 
1167 {
1168  if (!IsInWorld())
1169  return;
1170 
1172 
1174 }
1175 
1177 {
1179 }
1180 
1182 {
1184 }
1185 
1187 {
1188  Map* map = GetMap();
1189  return map->IsDungeon() ? ((InstanceMap*)map)->GetInstanceData() : NULL;
1190 }
1191 
1193 {
1194  float dz = fabs(GetPositionZ() - obj->GetPositionZ());
1195  float sizefactor = GetObjectSize() + obj->GetObjectSize();
1196  float dist = dz - sizefactor;
1197  return (dist > 0 ? dist : 0);
1198 }
1199 
1200 float WorldObject::GetDistanceSqr(float x, float y, float z) const
1201 {
1202  float dx = GetPositionX() - x;
1203  float dy = GetPositionY() - y;
1204  float dz = GetPositionZ() - z;
1205  float sizefactor = GetObjectSize();
1206  float dist = dx * dx + dy * dy + dz * dz - sizefactor;
1207  return (dist > 0 ? dist : 0);
1208 }
1209 
1210 bool WorldObject::_IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D) const
1211 {
1212  float dx = GetPositionX() - obj->GetPositionX();
1213  float dy = GetPositionY() - obj->GetPositionY();
1214  float distsq = dx * dx + dy * dy;
1215  if (is3D)
1216  {
1217  float dz = GetPositionZ() - obj->GetPositionZ();
1218  distsq += dz * dz;
1219  }
1220  float sizefactor = GetObjectSize() + obj->GetObjectSize();
1221  float maxdist = dist2compare + sizefactor;
1222 
1223  return distsq < maxdist * maxdist;
1224 }
1225 
1227 {
1228  if (!IsInMap(obj))
1229  return false;
1230 
1231  float x, y, z;
1232  if (obj->GetTypeId() == TYPEID_PLAYER)
1233  obj->GetPosition(x, y, z);
1234  else
1235  obj->GetHitSpherePointFor(GetPosition(), x, y, z);
1236 
1237  return IsWithinLOS(x, y, z);
1238 }
1239 
1240 bool WorldObject::IsWithinLOS(float ox, float oy, float oz) const
1241 {
1242  if (IsInWorld())
1243  {
1244  float x, y, z;
1245  if (GetTypeId() == TYPEID_PLAYER)
1246  GetPosition(x, y, z);
1247  else
1248  GetHitSpherePointFor({ ox, oy, oz }, x, y, z);
1249 
1250  return GetMap()->isInLineOfSight(x, y, z + 2.0f, ox, oy, oz + 2.0f);
1251  }
1252 
1253  return true;
1254 }
1255 
1257 {
1258  G3D::Vector3 vThis(GetPositionX(), GetPositionY(), GetPositionZ());
1259  G3D::Vector3 vObj(dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ());
1260  G3D::Vector3 contactPoint = vThis + (vObj - vThis).directionOrZero() * GetObjectSize();
1261 
1262  return Position(contactPoint.x, contactPoint.y, contactPoint.z, GetAngle(contactPoint.x, contactPoint.y));
1263 }
1264 
1265 void WorldObject::GetHitSpherePointFor(Position const& dest, float& x, float& y, float& z) const
1266 {
1267  Position pos = GetHitSpherePointFor(dest);
1268  x = pos.GetPositionX();
1269  y = pos.GetPositionY();
1270  z = pos.GetPositionZ();
1271 }
1272 
1273 bool WorldObject::GetDistanceOrder(WorldObject const* obj1, WorldObject const* obj2, bool is3D /* = true */) const
1274 {
1275  float dx1 = GetPositionX() - obj1->GetPositionX();
1276  float dy1 = GetPositionY() - obj1->GetPositionY();
1277  float distsq1 = dx1 * dx1 + dy1 * dy1;
1278  if (is3D)
1279  {
1280  float dz1 = GetPositionZ() - obj1->GetPositionZ();
1281  distsq1 += dz1 * dz1;
1282  }
1283 
1284  float dx2 = GetPositionX() - obj2->GetPositionX();
1285  float dy2 = GetPositionY() - obj2->GetPositionY();
1286  float distsq2 = dx2 * dx2 + dy2 * dy2;
1287  if (is3D)
1288  {
1289  float dz2 = GetPositionZ() - obj2->GetPositionZ();
1290  distsq2 += dz2 * dz2;
1291  }
1292 
1293  return distsq1 < distsq2;
1294 }
1295 
1296 bool WorldObject::IsInRange(WorldObject const* obj, float minRange, float maxRange, bool is3D /* = true */) const
1297 {
1298  float dx = GetPositionX() - obj->GetPositionX();
1299  float dy = GetPositionY() - obj->GetPositionY();
1300  float distsq = dx * dx + dy * dy;
1301  if (is3D)
1302  {
1303  float dz = GetPositionZ() - obj->GetPositionZ();
1304  distsq += dz * dz;
1305  }
1306 
1307  float sizefactor = GetObjectSize() + obj->GetObjectSize();
1308 
1309  // check only for real range
1310  if (minRange > 0.0f)
1311  {
1312  float mindist = minRange + sizefactor;
1313  if (distsq < mindist * mindist)
1314  return false;
1315  }
1316 
1317  float maxdist = maxRange + sizefactor;
1318  return distsq < maxdist * maxdist;
1319 }
1320 
1321 bool WorldObject::IsInRange2d(float x, float y, float minRange, float maxRange) const
1322 {
1323  float dx = GetPositionX() - x;
1324  float dy = GetPositionY() - y;
1325  float distsq = dx * dx + dy * dy;
1326 
1327  float sizefactor = GetObjectSize();
1328 
1329  // check only for real range
1330  if (minRange > 0.0f)
1331  {
1332  float mindist = minRange + sizefactor;
1333  if (distsq < mindist * mindist)
1334  return false;
1335  }
1336 
1337  float maxdist = maxRange + sizefactor;
1338  return distsq < maxdist * maxdist;
1339 }
1340 
1341 bool WorldObject::IsInRange3d(float x, float y, float z, float minRange, float maxRange) const
1342 {
1343  float dx = GetPositionX() - x;
1344  float dy = GetPositionY() - y;
1345  float dz = GetPositionZ() - z;
1346  float distsq = dx * dx + dy * dy + dz * dz;
1347 
1348  float sizefactor = GetObjectSize();
1349 
1350  // check only for real range
1351  if (minRange > 0.0f)
1352  {
1353  float mindist = minRange + sizefactor;
1354  if (distsq < mindist * mindist)
1355  return false;
1356  }
1357 
1358  float maxdist = maxRange + sizefactor;
1359  return distsq < maxdist * maxdist;
1360 }
1361 
1362 bool WorldObject::HasInArc(const float arcangle, const float x, const float y) const
1363 {
1364  // always have self in arc
1365  if (x == m_positionX && y == m_positionY)
1366  return true;
1367 
1368  float arc = arcangle;
1369 
1370  // move arc to range 0.. 2*pi
1371  while ( arc >= 2.0f * float(M_PI) )
1372  arc -= 2.0f * float(M_PI);
1373  while ( arc < 0 )
1374  arc += 2.0f * float(M_PI);
1375 
1376  float angle = GetAngle( x, y );
1377  angle -= GetOrientation();
1378 
1379  // move angle to range -pi ... +pi
1380  while ( angle > float(M_PI))
1381  angle -= 2.0f * float(M_PI);
1382  while (angle < -M_PI)
1383  angle += 2.0f * float(M_PI);
1384 
1385  float lborder = -1 * (arc / 2.0f); // in range -pi..0
1386  float rborder = (arc / 2.0f); // in range 0..pi
1387  return (( angle >= lborder ) && ( angle <= rborder ));
1388 }
1389 
1390 bool WorldObject::HasInArc(float arc, const Position* obj) const
1391 {
1392  return this->HasInArc(arc, obj->GetPositionX(), obj->GetPositionY());
1393 }
1394 
1395 void WorldObject::GetRandomPoint(const Position& pos, float distance, float& rand_x, float& rand_y, float& rand_z) const
1396 {
1397  if (!distance)
1398  {
1399  pos.GetPosition(rand_x, rand_y, rand_z);
1400  return;
1401  }
1402 
1403  // angle to face `obj` to `this`
1404  float angle = rand_norm() * 2 * M_PI;
1405  float new_dist = rand_norm() * distance;
1406 
1407  rand_x = pos.m_positionX + new_dist * cos(angle);
1408  rand_y = pos.m_positionY + new_dist * sin(angle);
1409  rand_z = pos.m_positionZ;
1410 
1411  Oregon::NormalizeMapCoord(rand_x);
1412  Oregon::NormalizeMapCoord(rand_y);
1413  UpdateGroundPositionZ(rand_x, rand_y, rand_z); // update to LOS height if available
1414 }
1415 
1416 void WorldObject::UpdateAllowedPositionZ(float x, float y, float& z) const
1417 {
1418  switch (GetTypeId())
1419  {
1420  case TYPEID_UNIT:
1421  {
1422  // non fly unit don't must be in air
1423  // non swim unit must be at ground (mostly speedup, because it don't must be in water and water level check less fast
1424  if (!((Creature const*)this)->canFly())
1425  {
1426  bool canSwim = ((Creature const*)this)->canSwim();
1427  float ground_z = z;
1428  float max_z = canSwim
1429  ? GetBaseMap()->GetWaterOrGroundLevel(x, y, z, &ground_z, !((Unit const*)this)->HasAuraType(SPELL_AURA_WATER_WALK))
1430  : ((ground_z = GetBaseMap()->GetHeight(x, y, z, true)));
1431  if (max_z > INVALID_HEIGHT)
1432  {
1433  if (z > max_z)
1434  z = max_z;
1435  else if (z < ground_z)
1436  z = ground_z;
1437  }
1438  }
1439  else
1440  {
1441  float ground_z = GetBaseMap()->GetHeight(x, y, z, true);
1442  if (z < ground_z)
1443  z = ground_z;
1444  }
1445  break;
1446  }
1447  case TYPEID_PLAYER:
1448  {
1449  // for server controlled moves playr work same as creature (but it can always swim)
1450  if (!((Player const*)this)->CanFly())
1451  {
1452  float ground_z = z;
1453  float max_z = GetBaseMap()->GetWaterOrGroundLevel(x, y, z, &ground_z, !((Unit const*)this)->HasAuraType(SPELL_AURA_WATER_WALK));
1454  if (max_z > INVALID_HEIGHT)
1455  {
1456  if (z > max_z)
1457  z = max_z;
1458  else if (z < ground_z)
1459  z = ground_z;
1460  }
1461  }
1462  else
1463  {
1464  float ground_z = GetBaseMap()->GetHeight(x, y, z, true);
1465  if (z < ground_z)
1466  z = ground_z;
1467  }
1468  break;
1469  }
1470  default:
1471  {
1472  float ground_z = GetBaseMap()->GetHeight(x, y, z, true);
1473  if (ground_z > INVALID_HEIGHT)
1474  z = ground_z;
1475  break;
1476  }
1477  }
1478 }
1479 
1480 void WorldObject::UpdateGroundPositionZ(float x, float y, float& z) const
1481 {
1482  float new_z = GetBaseMap()->GetHeight(x, y, z, true);
1483  if (new_z > INVALID_HEIGHT)
1484  z = new_z + 0.05f; // just to be sure that we are not a few pixel under the surface
1485 }
1486 
1487 void WorldObject::MonsterSay(const char* text, uint32 language, uint64 TargetGuid)
1488 {
1489  WorldPacket data(SMSG_MESSAGECHAT, 200);
1490  BuildMonsterChat(&data, CHAT_MSG_MONSTER_SAY, text, language, GetName(), TargetGuid);
1491  SendMessageToSetInRange(&data, sWorld.getConfig(CONFIG_LISTEN_RANGE_SAY), true);
1492 }
1493 
1494 void WorldObject::MonsterYell(const char* text, uint32 language, uint64 TargetGuid)
1495 {
1496  WorldPacket data(SMSG_MESSAGECHAT, 200);
1497  BuildMonsterChat(&data, CHAT_MSG_MONSTER_YELL, text, language, GetName(), TargetGuid);
1498  SendMessageToSetInRange(&data, sWorld.getConfig(CONFIG_LISTEN_RANGE_YELL), true);
1499 }
1500 
1501 void WorldObject::MonsterTextEmote(const char* text, uint64 TargetGuid, bool IsBossEmote)
1502 {
1503  WorldPacket data(SMSG_MESSAGECHAT, 200);
1504  BuildMonsterChat(&data, IsBossEmote ? CHAT_MSG_RAID_BOSS_EMOTE : CHAT_MSG_MONSTER_EMOTE, text, LANG_UNIVERSAL, GetName(), TargetGuid);
1506 }
1507 
1508 void WorldObject::MonsterWhisper(const char* text, uint64 receiver, bool IsBossWhisper)
1509 {
1510  Player* player = sObjectMgr.GetPlayer(receiver);
1511  if (!player || !player->GetSession())
1512  return;
1513 
1514  WorldPacket data(SMSG_MESSAGECHAT, 200);
1515  BuildMonsterChat(&data, IsBossWhisper ? CHAT_MSG_RAID_BOSS_WHISPER : CHAT_MSG_MONSTER_WHISPER, text, LANG_UNIVERSAL, GetName(), receiver);
1516 
1517  player->GetSession()->SendPacket(&data);
1518 }
1519 
1521 {
1522  if (!IsInWorld())
1523  return false;
1524 
1525  return true;
1526 }
1527 
1529 {
1530  if (ToPlayer())
1531  {
1532  if (ToPlayer()->GetCinematicMgr()->IsOnCinematic())
1534  return GetMap()->GetVisibilityRange();
1535  }
1536  else if (ToCreature())
1537  return ToCreature()->m_SightDistance;
1538  else if (ToDynObject())
1539  {
1540  if (isActiveObject())
1541  return GetMap()->GetVisibilityRange();
1542  else
1543  return 0.0f;
1544  }
1545  else
1546  return 0.0f;
1547 }
1548 
1550 {
1551  if (isActiveObject() && !ToPlayer())
1552  return MAX_VISIBILITY_DISTANCE;
1553  else
1554  return GetMap()->GetVisibilityRange();
1555 }
1556 
1557 float WorldObject::GetSightRange(const WorldObject* target) const
1558 {
1559  if (ToUnit())
1560  {
1561  if (ToPlayer())
1562  {
1563  if (target && target->isActiveObject() && !target->ToPlayer())
1564  return MAX_VISIBILITY_DISTANCE;
1565  else if (ToPlayer()->GetCinematicMgr()->IsOnCinematic())
1567  else
1568  return GetMap()->GetVisibilityRange();
1569  }
1570  else if (ToCreature())
1571  return ToCreature()->m_SightDistance;
1572  else
1573  return SIGHT_RANGE_UNIT;
1574  }
1575 
1576  if (ToDynObject() && isActiveObject())
1577  return GetMap()->GetVisibilityRange();
1578 
1579  return 0.0f;
1580 }
1581 
1582 bool WorldObject::CanSeeOrDetect(WorldObject const* obj, bool ignoreStealth, bool distanceCheck, bool checkAlert) const
1583 {
1584  if (this == obj)
1585  return true;
1586 
1587  if (obj->IsNeverVisible() || CanNeverSee(obj))
1588  return false;
1589 
1590  if (obj->IsAlwaysVisibleFor(this) || CanAlwaysSee(obj))
1591  return true;
1592 
1593  bool corpseVisibility = false;
1594  if (distanceCheck)
1595  {
1596  bool corpseCheck = false;
1597  if (const Player* thisPlayer = ToPlayer())
1598  {
1599  if (thisPlayer->isDead() && thisPlayer->GetHealth() > 0 && // Cheap way to check for ghost state
1601  {
1602  if (Corpse* corpse = thisPlayer->GetCorpse())
1603  {
1604  corpseCheck = true;
1605  if (corpse->IsWithinDist(thisPlayer, GetSightRange(obj), false))
1606  if (corpse->IsWithinDist(obj, GetSightRange(obj), false))
1607  corpseVisibility = true;
1608  }
1609  }
1610  }
1611 
1612  WorldObject const* viewpoint = this;
1613  if (Player const* player = this->ToPlayer())
1614  viewpoint = player->GetViewpoint();
1615 
1616  if (!viewpoint)
1617  viewpoint = this;
1618 
1619  if (!corpseCheck && !viewpoint->IsWithinDist(obj, GetSightRange(obj), false))
1620  return false;
1621  }
1622 
1623  // GM visibility off or hidden NPC
1625  {
1626  // Stop checking other things for GMs
1628  return true;
1629  }
1630  else
1632 
1633  // Ghost players, Spirit Healers, and some other NPCs
1635  {
1636  // Alive players can see dead players in some cases, but other objects can't do that
1637  if (const Player* thisPlayer = ToPlayer())
1638  {
1639  if (const Player* objPlayer = obj->ToPlayer())
1640  {
1641  if (thisPlayer->GetTeam() != objPlayer->GetTeam() || !thisPlayer->IsGroupVisibleFor(objPlayer))
1642  return false;
1643  }
1644  else
1645  return false;
1646  }
1647  else
1648  return false;
1649  }
1650 
1651  if (obj->IsInvisibleDueToDespawn())
1652  return false;
1653 
1654  if (!CanDetect(obj, ignoreStealth, checkAlert))
1655  return false;
1656 
1657  return true;
1658 }
1659 
1661 {
1662  return GetMap() != obj->GetMap();
1663 }
1664 
1665 bool WorldObject::CanDetect(WorldObject const* obj, bool ignoreStealth, bool checkAlert) const
1666 {
1667  const WorldObject* seer = this;
1668 
1669  // Pets don't have detection, they use the detection of their masters
1670  if (const Unit* thisUnit = ToUnit())
1671  if (Unit* controller = thisUnit->GetCharmerOrOwner())
1672  seer = controller;
1673 
1674  if (obj->IsAlwaysDetectableFor(seer))
1675  return true;
1676 
1677  if (!ignoreStealth && !seer->CanDetectInvisibilityOf(obj))
1678  return false;
1679 
1680  if (!ignoreStealth && !seer->CanDetectStealthOf(obj, checkAlert))
1681  return false;
1682 
1683  return true;
1684 }
1685 
1687 {
1689 
1690  // Check for not detected types
1691  if (mask != obj->m_invisibility.GetFlags())
1692  return false;
1693 
1694  // It isn't possible in invisibility to detect something that can't detect the invisible object
1695  // (it's at least true for spell: 66)
1696  // It seems like that only Units are affected by this check (couldn't see arena doors with preparation invisibility)
1697  if (obj->ToUnit())
1699  return false;
1700 
1701  for (uint32 i = 0; i < TOTAL_INVISIBILITY_TYPES; ++i)
1702  {
1703  if (!(mask & (1 << i)))
1704  continue;
1705 
1706  int32 objInvisibilityValue = obj->m_invisibility.GetValue(InvisibilityType(i));
1707  int32 ownInvisibilityDetectValue = m_invisibilityDetect.GetValue(InvisibilityType(i));
1708 
1709  // Too low value to detect
1710  if (ownInvisibilityDetectValue < objInvisibilityValue)
1711  return false;
1712  }
1713 
1714  return true;
1715 }
1716 
1717 bool WorldObject::CanDetectStealthOf(WorldObject const* obj, bool checkAlert) const
1718 {
1719  // Combat reach is the minimal distance (both in front and behind),
1720  // and it is also used in the range calculation.
1721  // One stealth point increases the visibility range by 0.3 yard.
1722 
1723  if (!obj->m_stealth.GetFlags())
1724  return true;
1725 
1726  float distance = GetExactDist(obj);
1727  float combatReach = 0.0f;
1728 
1729  Unit const* unit = ToUnit();
1730  if (unit)
1731  combatReach = unit->GetCombatReach();
1732 
1733  if (distance < combatReach)
1734  return true;
1735 
1736  if (!HasInArc(float(M_PI), obj))
1737  return false;
1738 
1739  GameObject const* go = ToGameObject();
1740  for (uint32 i = 0; i < TOTAL_STEALTH_TYPES; ++i)
1741  {
1742  if (!(obj->m_stealth.GetFlags() & (1 << i)))
1743  continue;
1744 
1746  return true;
1747 
1748  // Starting points
1749  int32 detectionValue = 30;
1750 
1751  // Level difference: 5 point / level, starting from level 1.
1752  // There may be spells for this and the starting points too, but
1753  // not in the DBCs of the client.
1754  detectionValue += int32(getLevelForTarget(obj) - 1) * 5;
1755 
1756  // Apply modifiers
1757  detectionValue += m_stealthDetect.GetValue(StealthType(i));
1758  if (go)
1759  if (Unit* owner = go->GetOwner())
1760  detectionValue -= int32(owner->getLevelForTarget(this) - 1) * 5;
1761 
1762  detectionValue -= obj->m_stealth.GetValue(StealthType(i));
1763 
1764  // Calculate max distance
1765  float visibilityRange = float(detectionValue) * 0.3f + combatReach;
1766 
1767  // If this unit is an NPC then player detect range doesn't apply
1768  if (unit && unit->GetTypeId() == TYPEID_PLAYER && visibilityRange > MAX_PLAYER_STEALTH_DETECT_RANGE)
1769  visibilityRange = MAX_PLAYER_STEALTH_DETECT_RANGE;
1770 
1771  // When checking for alert state, look 8% further, and then 1.5 yards more than that.
1772  if (checkAlert)
1773  visibilityRange += (visibilityRange * 0.08f) + 1.5f;
1774 
1775  // If checking for alert, and creature's visibility range is greater than aggro distance, No alert
1776  Unit const* tunit = obj->ToUnit();
1777  if (checkAlert && unit && unit->ToCreature() && visibilityRange >= unit->ToCreature()->GetAttackDistance(tunit) + unit->ToCreature()->m_CombatDistance)
1778  return false;
1779 
1780  if (distance > visibilityRange)
1781  return false;
1782  }
1783 
1784  return true;
1785 }
1786 
1787 void WorldObject::SendPlaySound(uint32 Sound, bool OnlySelf)
1788 {
1789  WorldPacket data(SMSG_PLAY_SOUND, 4);
1790  data << Sound;
1791  if (OnlySelf && GetTypeId() == TYPEID_PLAYER)
1792  ToPlayer()->GetSession()->SendPacket(&data);
1793  else
1794  SendMessageToSet(&data, true); // ToSelf ignored in this case
1795 }
1796 
1798 {
1799  m_uint32Values_mirror[i] = GetUInt32Value(i) + 1; // makes server think the field changed
1800  if (m_inWorld)
1801  {
1802  if (!m_objectUpdated)
1803  {
1805  m_objectUpdated = true;
1806  }
1807  }
1808 }
1809 
1810 namespace Oregon
1811 {
1813 {
1814  public:
1815  MonsterChatBuilder(WorldObject const& obj, ChatMsg msgtype, int32 textId, uint32 language, uint64 targetGUID)
1816  : i_object(obj), i_msgtype(msgtype), i_textId(textId), i_language(language), i_targetGUID(targetGUID) {}
1817  void operator()(WorldPacket& data, int32 loc_idx)
1818  {
1819  char const* text = sObjectMgr.GetOregonString(i_textId, loc_idx);
1820 
1821  // @todo i_object.GetName() also must be localized?
1822  i_object.BuildMonsterChat(&data, i_msgtype, text, i_language, i_object.GetNameForLocaleIdx(loc_idx), i_targetGUID);
1823  }
1824 
1825  private:
1831 };
1832 } // namespace Oregon
1833 
1834 void WorldObject::MonsterSay(int32 textId, uint32 language, uint64 TargetGuid)
1835 {
1837 
1838  Cell cell(p);
1839  cell.SetNoCreate();
1840 
1841  Oregon::MonsterChatBuilder say_build(*this, CHAT_MSG_MONSTER_SAY, textId, language, TargetGuid);
1845  cell.Visit(p, message, *GetMap(), *this, sWorld.getConfig(CONFIG_LISTEN_RANGE_SAY));
1846 }
1847 
1848 void WorldObject::MonsterYell(int32 textId, uint32 language, uint64 TargetGuid)
1849 {
1851 
1852  Cell cell(p);
1853  cell.SetNoCreate();
1854 
1855  Oregon::MonsterChatBuilder say_build(*this, CHAT_MSG_MONSTER_YELL, textId, language, TargetGuid);
1859  cell.Visit(p, message, *GetMap(), *this, sWorld.getConfig(CONFIG_LISTEN_RANGE_YELL));
1860 }
1861 
1862 void WorldObject::MonsterYellToZone(int32 textId, uint32 language, uint64 TargetGuid)
1863 {
1864  Oregon::MonsterChatBuilder say_build(*this, CHAT_MSG_MONSTER_YELL, textId, language, TargetGuid);
1866 
1867  uint32 zoneid = GetZoneId();
1868 
1869  Map::PlayerList const& pList = GetMap()->GetPlayers();
1870  for (Map::PlayerList::const_iterator itr = pList.begin(); itr != pList.end(); ++itr)
1871  if (itr->GetSource()->GetZoneId() == zoneid)
1872  say_do(itr->GetSource());
1873 }
1874 
1875 void WorldObject::MonsterTextEmote(int32 textId, uint64 TargetGuid, bool IsBossEmote)
1876 {
1878 
1879  Cell cell(p);
1880  cell.SetNoCreate();
1881 
1882  Oregon::MonsterChatBuilder say_build(*this, IsBossEmote ? CHAT_MSG_RAID_BOSS_EMOTE : CHAT_MSG_MONSTER_EMOTE, textId, LANG_UNIVERSAL, TargetGuid);
1886  cell.Visit(p, message, *GetMap(), *this, sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE));
1887 }
1888 
1889 void WorldObject::MonsterWhisper(int32 textId, uint64 receiver, bool IsBossWhisper)
1890 {
1891  Player* player = sObjectMgr.GetPlayer(receiver);
1892  if (!player || !player->GetSession())
1893  return;
1894 
1895  uint32 loc_idx = player->GetSession()->GetSessionDbLocaleIndex();
1896  char const* text = sObjectMgr.GetOregonString(textId, loc_idx);
1897 
1898  WorldPacket data(SMSG_MESSAGECHAT, 200);
1899  BuildMonsterChat(&data, IsBossWhisper ? CHAT_MSG_RAID_BOSS_WHISPER : CHAT_MSG_MONSTER_WHISPER, text, LANG_UNIVERSAL, GetName(), receiver);
1900 
1901  player->GetSession()->SendPacket(&data);
1902 }
1903 
1904 void WorldObject::BuildMonsterChat(WorldPacket* data, uint8 msgtype, char const* text, uint32 language, char const* name, uint64 targetGuid) const
1905 {
1906  *data << (uint8)msgtype;
1907  *data << (uint32)language;
1908  *data << (uint64)GetGUID();
1909  *data << (uint32)0; //2.1.0
1910  *data << (uint32)(strlen(name) + 1);
1911  *data << name;
1912  *data << (uint64)targetGuid; //Unit Target
1913  if (targetGuid && !IS_PLAYER_GUID(targetGuid))
1914  {
1915  *data << (uint32)1; // target name length
1916  *data << (uint8)0; // target name
1917  }
1918  *data << (uint32)(strlen(text) + 1);
1919  *data << text;
1920  *data << (uint8)0; // ChatTag
1921 }
1922 
1924 {
1925  data->Initialize(MSG_MOVE_HEARTBEAT, 32);
1926  *data << GetPackGUID();
1927  BuildMovementPacket(data);
1928 }
1929 
1930 void WorldObject::SendMessageToSetInRange(WorldPacket* data, float dist, bool /*bToSelf*/)
1931 {
1932  Oregon::MessageDistDeliverer notifier(this, data, dist);
1933  VisitNearbyWorldObject(dist, notifier);
1934 }
1935 
1937 {
1939  data << uint64(guid);
1940  SendMessageToSet(&data, true);
1941 }
1942 
1944 {
1946  data << uint64(guid);
1947  data << uint32(anim);
1948  SendMessageToSet(&data, true);
1949 }
1950 
1952 {
1953  ASSERT(map);
1955  if (m_currMap == map) // command add npc: first create, than loadfromdb
1956  return;
1957  if (m_currMap)
1958  {
1959  sLog.outError("Crash alert! WorldObject::SetMap: obj %u new map %u %u, old map %u %u", (uint32)GetTypeId(), map->GetId(), map->GetInstanceId(), m_currMap->GetId(), m_currMap->GetInstanceId());
1960  ASSERT(false);
1961  }
1962  m_currMap = map;
1963  m_mapId = map->GetId();
1964  m_InstanceId = map->GetInstanceId();
1965  if (IsWorldObject())
1966  m_currMap->AddWorldObject(this);
1967 }
1968 
1970 {
1971  ASSERT(m_currMap);
1972  ASSERT(!IsInWorld());
1973  if (IsWorldObject())
1975  m_currMap = NULL;
1976  //maybe not for corpse
1977  //m_mapId = 0;
1978  //m_InstanceId = 0;
1979 }
1980 
1982 {
1983  ASSERT(m_currMap);
1984  return m_currMap->GetParent();
1985 }
1986 
1988 {
1990 
1991  Map* map = FindMap();
1992  if (!map)
1993  {
1994  sLog.outError("Object (TypeId: %u Entry: %u GUID: %u) at attempt add to move list has invalid map (Id: %u).", GetTypeId(), GetEntry(), GetGUIDLow(), GetMapId());
1995  return;
1996  }
1997 
1998  map->AddObjectToRemoveList(this);
1999 }
2000 
2001 TempSummon* Map::SummonCreature(uint32 entry, const Position& pos, SummonPropertiesEntry const* properties, uint32 duration, Unit* summoner, uint32 spellId, TempSummonType spwType)
2002 {
2003  uint32 mask = UNIT_MASK_SUMMON;
2004  if (properties)
2005  {
2006  switch (properties->Category)
2007  {
2008  case SUMMON_CATEGORY_PET:
2009  mask = UNIT_MASK_GUARDIAN;
2010  break;
2012  mask = UNIT_MASK_PUPPET;
2013  break;
2014  case SUMMON_CATEGORY_WILD:
2015  case SUMMON_CATEGORY_ALLY:
2016  {
2017  switch (properties->Type)
2018  {
2019  case SUMMON_TYPE_MINION:
2020  case SUMMON_TYPE_GUARDIAN:
2021  case SUMMON_TYPE_GUARDIAN2:
2022  mask = UNIT_MASK_GUARDIAN;
2023  break;
2024  case SUMMON_TYPE_TOTEM:
2025  mask = UNIT_MASK_TOTEM;
2026  break;
2027  case SUMMON_TYPE_MINIPET:
2028  mask = UNIT_MASK_MINION;
2029  break;
2030  default:
2031  if (properties->Flags & 512)
2032  mask = UNIT_MASK_GUARDIAN;
2033  break;
2034  }
2035  break;
2036  }
2037  default:
2038  return NULL;
2039  }
2040  }
2041 
2042  uint32 team = 0;
2043  if (summoner && summoner->GetTypeId() == TYPEID_PLAYER)
2044  team = summoner->ToPlayer()->GetTeam();
2045 
2046  TempSummon* summon = NULL;
2047  switch (mask)
2048  {
2049  case UNIT_MASK_SUMMON:
2050  summon = new TempSummon(properties, summoner, false);
2051  break;
2052  case UNIT_MASK_GUARDIAN:
2053  summon = new Guardian(properties, summoner, false);
2054  break;
2055  case UNIT_MASK_PUPPET:
2056  summon = new Puppet(properties, summoner);
2057  break;
2058  case UNIT_MASK_TOTEM:
2059  summon = new Totem(properties, summoner);
2060  break;
2061  case UNIT_MASK_MINION:
2062  summon = new Minion(properties, summoner, false);
2063  break;
2064  default:
2065  return NULL;
2066  }
2067 
2068  if (!summon->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_UNIT), this, entry, team, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation()))
2069  {
2070  delete summon;
2071  return NULL;
2072  }
2073 
2074  summon->SetUInt32Value(UNIT_CREATED_BY_SPELL, spellId);
2075  summon->SetHomePosition(pos);
2076  // CreatureAI::Reset was already called, check if TempSummonType changed, if
2077  // so, don't touch it or we may mess up the script. (Example Script: Inferno)
2078  // TEMPSUMMON_MANUL_DESPAWN is the default one so we check against it.
2080  summon->SetTempSummonType(spwType);
2081  summon->InitStats(duration);
2082  AddToMap(summon->ToCreature());
2083  summon->InitSummon();
2084 
2085  return summon;
2086 }
2087 
2089 {
2090  if (Map* map = FindMap())
2091  {
2092  if (TempSummon* summon = map->SummonCreature(entry, pos, NULL, duration, isType(TYPEMASK_UNIT) ? (Unit*)this : NULL, NULL, spwtype))
2093  return summon;
2094  }
2095 
2096  return NULL;
2097 }
2098 
2100 {
2101  if (Map* map = FindMap())
2102  {
2103  if (map->IsDungeon())
2104  m_zoneScript = (ZoneScript*)((InstanceMap*)map)->GetInstanceData();
2105  else if (!map->IsBattlegroundOrArena())
2106  m_zoneScript = sOutdoorPvPMgr.GetZoneScript(GetZoneId());
2107  }
2108 }
2109 
2110 Pet* Player::SummonPet(uint32 entry, float x, float y, float z, float ang, PetType petType, uint32 duration)
2111 {
2112  Pet* pet = new Pet(this, petType);
2113  SetPetStatus(PET_STATUS_CURRENT);
2114 
2115  if (petType == SUMMON_PET && pet->LoadPetFromDB(this, entry))
2116  {
2117  // Remove Demonic Sacrifice auras (known pet)
2118  Unit::AuraList const& auraClassScripts = GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
2119  for (Unit::AuraList::const_iterator itr = auraClassScripts.begin(); itr != auraClassScripts.end();)
2120  {
2121  if ((*itr)->GetModifier()->m_miscvalue == 2228)
2122  {
2123  RemoveAurasDueToSpell((*itr)->GetId());
2124  itr = auraClassScripts.begin();
2125  }
2126  else
2127  ++itr;
2128  }
2129 
2130  if (duration > 0)
2131  pet->SetDuration(duration);
2132 
2133  return NULL;
2134  }
2135 
2136  // petentry == 0 for hunter "call pet" (current pet summoned if any)
2137  if (!entry)
2138  {
2139  delete pet;
2140  return NULL;
2141  }
2142 
2143  Map* map = GetMap();
2144  uint32 pet_number = sObjectMgr.GeneratePetNumber();
2145  if (!pet->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_PET), map, entry, pet_number))
2146  {
2147  sLog.outError("no such creature entry %u", entry);
2148  delete pet;
2149  return NULL;
2150  }
2151 
2152  pet->Relocate(x, y, z, ang);
2153  if (!pet->IsPositionValid())
2154  {
2155  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());
2156  delete pet;
2157  return NULL;
2158  }
2159 
2160  pet->SetCreatorGUID(GetGUID());
2161  pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, getFaction());
2162 
2163  // this enables pet details window (Shift+P)
2164  pet->GetCharmInfo()->SetPetNumber(pet_number, false);
2165 
2166  pet->setPowerType(POWER_MANA);
2167  pet->SetUInt32Value(UNIT_NPC_FLAGS , 0);
2169  pet->InitStatsForLevel(getLevel());
2170 
2171  SetMinion(pet, true);
2172 
2173  switch (petType)
2174  {
2175  case CLASS_PET:
2176  case SUMMON_PET:
2177  pet->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
2180  pet->SetHealth(pet->GetMaxHealth());
2183  default:
2184  break;
2185  }
2186 
2187  map->AddToMap(pet->ToCreature());
2188 
2189  switch (petType)
2190  {
2191  case CLASS_PET:
2192  case SUMMON_PET:
2193  pet->InitPetCreateSpells();
2195  PetSpellInitialize();
2196  default:
2197  break;
2198  }
2199 
2200  if (petType == SUMMON_PET)
2201  {
2202  // Remove Demonic Sacrifice auras (known pet)
2203  Unit::AuraList const& auraClassScripts = GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
2204  for (Unit::AuraList::const_iterator itr = auraClassScripts.begin(); itr != auraClassScripts.end();)
2205  {
2206  if ((*itr)->GetModifier()->m_miscvalue == 2228)
2207  {
2208  RemoveAurasDueToSpell((*itr)->GetId());
2209  itr = auraClassScripts.begin();
2210  }
2211  else
2212  ++itr;
2213  }
2214  }
2215 
2216  if (duration > 0)
2217  pet->SetDuration(duration);
2218 
2219  return pet;
2220 }
2221 
2222 GameObject* WorldObject::SummonGameObject(uint32 entry, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime)
2223 {
2224  if (!IsInWorld())
2225  return NULL;
2226 
2227  GameObjectInfo const* goinfo = sObjectMgr.GetGameObjectInfo(entry);
2228  if (!goinfo)
2229  {
2230  sLog.outErrorDb("Gameobject template %u not found in database!", entry);
2231  return NULL;
2232  }
2233  Map* map = GetMap();
2234  GameObject* go = new GameObject();
2235  if (!go->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), entry, map, x, y, z, ang, rotation0, rotation1, rotation2, rotation3, 100, GO_STATE_READY))
2236  {
2237  delete go;
2238  return NULL;
2239  }
2240  go->SetRespawnTime(respawnTime);
2241  if (GetTypeId() == TYPEID_PLAYER || GetTypeId() == TYPEID_UNIT) //not sure how to handle this
2242  ((Unit*)this)->AddGameObject(go);
2243  else
2244  go->SetSpawnedByDefault(false);
2245  map->AddToMap(go);
2246 
2247  return go;
2248 }
2249 
2250 Creature* WorldObject::SummonTrigger(float x, float y, float z, float ang, uint32 duration, CreatureAI * (*GetAI)(Creature*))
2251 {
2252  TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN;
2253  Creature* summon = SummonCreature(WORLD_TRIGGER, x, y, z, ang, summonType, duration);
2254  if (!summon)
2255  return NULL;
2256 
2257  //summon->SetName(GetName());
2258  if (GetTypeId() == TYPEID_PLAYER || GetTypeId() == TYPEID_UNIT)
2259  {
2260  summon->setFaction(((Unit*)this)->getFaction());
2261  summon->SetLevel(((Unit*)this)->getLevel());
2262  }
2263 
2264  if (GetAI)
2265  summon->AIM_Initialize(GetAI(summon));
2266  return summon;
2267 }
2268 
2275 void WorldObject::SummonCreatureGroup(uint8 group, std::list<TempSummon*>* list /*= NULL*/)
2276 {
2277  ASSERT((GetTypeId() == TYPEID_GAMEOBJECT || GetTypeId() == TYPEID_UNIT) && "Only GOs and creatures can summon npc groups!");
2278 
2279  std::vector<TempSummonData> const* data = sObjectMgr.GetSummonGroup(GetEntry(), GetTypeId() == TYPEID_GAMEOBJECT ? SUMMONER_TYPE_GAMEOBJECT : SUMMONER_TYPE_CREATURE, group);
2280  if (!data)
2281  return;
2282 
2283  for (std::vector<TempSummonData>::const_iterator itr = data->begin(); itr != data->end(); ++itr)
2284  if (TempSummon* summon = SummonCreature(itr->entry, itr->pos, itr->type, itr->time))
2285  if (list)
2286  list->push_back(summon);
2287 }
2288 
2289 Creature* WorldObject::FindNearestCreature(uint32 entry, float range, bool alive)
2290 {
2291  Creature* creature = NULL;
2292  Oregon::NearestCreatureEntryWithLiveStateInObjectRangeCheck checker(*this, entry, alive, range);
2294  VisitNearbyObject(range, searcher);
2295  return creature;
2296 }
2297 
2299 {
2300  GameObject* go = NULL;
2301  Oregon::NearestGameObjectEntryInObjectRangeCheck checker(*this, entry, range);
2303  VisitNearbyGridObject(range, searcher);
2304  return go;
2305 }
2306 
2308 {
2309  GameObject* go = NULL;
2310  Oregon::NearestGameObjectTypeInObjectRangeCheck checker(*this, type, range);
2312  VisitNearbyGridObject(range, searcher);
2313  return go;
2314 }
2315 
2316 void WorldObject::GetGameObjectListWithEntryInGrid(std::list<GameObject*>& gameobjectList, uint32 entry, float maxSearchRange) const
2317 {
2319  Cell cell(pair);
2320  cell.SetNoCreate();
2321 
2322  Oregon::AllGameObjectsWithEntryInRange check(this, entry, maxSearchRange);
2325 
2326  cell.Visit(pair, visitor, *(this->GetMap()), *this, maxSearchRange);
2327 }
2328 
2329 void WorldObject::GetCreatureListWithEntryInGrid(std::list<Creature*>& creatureList, uint32 entry, float maxSearchRange) const
2330 {
2332  Cell cell(pair);
2333  cell.SetNoCreate();
2334 
2335  Oregon::AllCreaturesOfEntryInRange check(this, entry, maxSearchRange);
2338 
2339  cell.Visit(pair, visitor, *(this->GetMap()), *this, maxSearchRange);
2340 }
2341 
2342 void WorldObject::GetNearPoint2D(float& x, float& y, float distance2d, float absAngle) const
2343 {
2344  x = GetPositionX() + (GetObjectSize() + distance2d) * cos(absAngle);
2345  y = GetPositionY() + (GetObjectSize() + distance2d) * sin(absAngle);
2346 
2349 }
2350 
2351 void WorldObject::GetNearPoint(WorldObject const* /*searcher*/, float& x, float& y, float& z, float searcher_size, float distance2d, float absAngle) const
2352 {
2353  GetNearPoint2D(x, y, distance2d + searcher_size, absAngle);
2354  z = GetPositionZ();
2355  UpdateAllowedPositionZ(x, y, z);
2356 }
2357 
2358 Position WorldObject::GetNearPosition(float dist, float angle)
2359 {
2360  Position pos = GetPosition();
2361  MovePosition(pos, dist, angle);
2362  return pos;
2363 }
2364 
2366 {
2367  Position pos = GetPosition();
2368  MovePositionToFirstCollision(pos, dist, angle);
2369  return pos;
2370 }
2371 
2373 {
2374  Position pos = GetPosition();
2375  MovePosition(pos, radius * (float)rand_norm(), (float)rand_norm() * static_cast<float>(2 * M_PI));
2376  return pos;
2377 }
2378 
2379 // @todo: replace with WorldObject::UpdateAllowedPositionZ
2380 // To use WorldObject::UpdateAllowedPositionZ at the moment causes a caster of
2381 // a leap effect to fall through the ground much too easily.
2382 float WorldObject::GetPositionZTarget(Position& pos, float destx, float desty)
2383 {
2384 
2385  // Added in Bitbucket issue #1105 in order to solve the problem of
2386  // leap effects like Blink taking the caster to the bottom of a body of liquid.
2387 
2388  float bottom, ground, floor;
2389 
2390  ground = GetMap()->GetHeight(destx, desty, MAX_HEIGHT, true);
2391  floor = GetMap()->GetHeight(destx, desty, pos.m_positionZ, true);
2392  // If we were to ignore liquid, the WorldObject would be placed here.
2393  bottom = fabs(ground - pos.m_positionZ) <= fabs(floor - pos.m_positionZ) ? ground : floor;
2394 
2395  if(pos.m_positionZ > bottom)
2396  {
2397 
2398  // We are in the water or in the air.
2399  // Must be at least above ground.
2400 
2401  LiquidData dest_status;
2402  GetMap()->getLiquidStatus(destx, desty, pos.m_positionZ, MAP_ALL_LIQUIDS, &dest_status);
2403 
2404  // Source and destination are underwater.
2405  if(dest_status.level > pos.m_positionZ)
2406  return pos.m_positionZ;
2407 
2408  // When in doubt, send the user to water/ground level.
2409  return fabs(dest_status.level - pos.m_positionZ) <= fabs(bottom - pos.m_positionZ) ? dest_status.level : bottom;
2410 
2411  }
2412  else
2413  {
2414  // Destination is on or under the ground. Use ground Z.
2415  return bottom;
2416  }
2417 }
2418 
2419 void WorldObject::MovePosition(Position& pos, float dist, float angle)
2420 {
2421  angle += GetOrientation();
2422  float destx, desty, destz, ground, floor;
2423  destx = pos.m_positionX + dist * cos(angle);
2424  desty = pos.m_positionY + dist * sin(angle);
2425 
2426  // Prevent invalid coordinates here, position is unchanged
2427  if (!Oregon::IsValidMapCoord(destx, desty, pos.m_positionZ))
2428  {
2429  sLog.outString("WorldObject::MovePosition invalid coordinates X: %f and Y: %f were passed!", destx, desty);
2430  return;
2431  }
2432 
2433  // Prevent invalid coordinates here, position is unchanged
2434  if (!Oregon::IsValidMapCoord(destx, desty))
2435  {
2436  sLog.outError("Crash alert! WorldObject::MovePositionToFirstCollision invalid coordinates X: %f and Y: %f were passed!", destx, desty);
2437  return;
2438  }
2439 
2440  ground = GetMap()->GetHeight(destx, desty, MAX_HEIGHT, true);
2441  floor = GetMap()->GetHeight(destx, desty, pos.m_positionZ, true);
2442  destz = fabs(ground - pos.m_positionZ) <= fabs(floor - pos.m_positionZ) ? ground : floor;
2443 
2444  float step = dist / 10.0f;
2445 
2446  for (uint8 j = 0; j < 10; ++j)
2447  {
2448  // do not allow too big z changes
2449  if (fabs(pos.m_positionZ - destz) > 6)
2450  {
2451  destx -= step * cos(angle);
2452  desty -= step * sin(angle);
2453  ground = GetMap()->GetHeight(destx, desty, MAX_HEIGHT, true);
2454  floor = GetMap()->GetHeight(destx, desty, pos.m_positionZ, true);
2455  destz = fabs(ground - pos.m_positionZ) <= fabs(floor - pos.m_positionZ) ? ground : floor;
2456  }
2457  // we have correct destz now
2458  else
2459  {
2460  pos.Relocate(destx, desty, destz);
2461  break;
2462  }
2463  }
2464 
2469 }
2470 
2471 void WorldObject::MovePositionToFirstCollision(Position& pos, float dist, float angle)
2472 {
2473  angle += GetOrientation();
2474  float destx, desty, destz;
2475  destx = pos.m_positionX + dist * cos(angle);
2476  desty = pos.m_positionY + dist * sin(angle);
2477 
2478  // Prevent invalid coordinates here, position is unchanged
2479  if (!Oregon::IsValidMapCoord(destx, desty))
2480  {
2481  sLog.outFatal("WorldObject::MovePositionToFirstCollision invalid coordinates X: %f and Y: %f were passed!", destx, desty);
2482  return;
2483  }
2484 
2485  destz = GetPositionZTarget(pos, destx, desty);
2486  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);
2487 
2488  // collision occured
2489  if (col)
2490  {
2491  // move back a bit
2492  destx -= CONTACT_DISTANCE * cos(angle);
2493  desty -= CONTACT_DISTANCE * sin(angle);
2494  dist = sqrt((pos.m_positionX - destx) * (pos.m_positionX - destx) + (pos.m_positionY - desty) * (pos.m_positionY - desty));
2495  }
2496 
2497  // check dynamic collision
2498  col = GetMap()->getObjectHitPos(pos.m_positionX, pos.m_positionY, pos.m_positionZ + 0.5f, destx, desty, destz + 0.5f, destx, desty, destz, -0.5f);
2499 
2500  // Collided with a gameobject
2501  if (col)
2502  {
2503  destx -= CONTACT_DISTANCE * cos(angle);
2504  desty -= CONTACT_DISTANCE * sin(angle);
2505  dist = sqrt((pos.m_positionX - destx) * (pos.m_positionX - destx) + (pos.m_positionY - desty) * (pos.m_positionY - desty));
2506  }
2507 
2508  float step = dist / 10.0f;
2509 
2510  for (uint8 j = 0; j < 10; ++j)
2511  {
2512  // do not allow too big z changes
2513  if (fabs(pos.m_positionZ - destz) > 6.0f)
2514  {
2515  destx -= step * cos(angle);
2516  desty -= step * sin(angle);
2517  destz = GetPositionZTarget(pos, destx, desty);
2518  }
2519  // we have correct destz now
2520  else
2521  {
2522  pos.Relocate(destx, desty, destz);
2523  break;
2524  }
2525  }
2526 
2529  pos.m_positionZ = GetPositionZTarget(pos, destx, desty);
2531 }
2532 
2533 void WorldObject::PlayDistanceSound(uint32 sound_id, Player* target /*= NULL*/)
2534 {
2535  WorldPacket data(SMSG_PLAY_OBJECT_SOUND, 4 + 8);
2536  data << uint32(sound_id);
2537  data << uint64(GetGUID());
2538  if (target)
2539  target->SendDirectMessage(&data);
2540  else
2541  SendMessageToSet(&data, true);
2542 }
2543 
2544 void WorldObject::PlayDirectSound(uint32 sound_id, Player* target /*= NULL*/)
2545 {
2546  WorldPacket data(SMSG_PLAY_SOUND, 4);
2547  data << uint32(sound_id);
2548  if (target)
2549  target->SendDirectMessage(&data);
2550  else
2551  SendMessageToSet(&data, true);
2552 }
2553 
2555 {
2556  if (!IsInWorld())
2557  return;
2558 
2559  std::list<Player*> targets;
2563  for (std::list<Player*>::const_iterator iter = targets.begin(); iter != targets.end(); ++iter)
2564  {
2565  Player* player = (*iter);
2566 
2567  if (player == this)
2568  continue;
2569 
2570  if (!player->HaveAtClient(this))
2571  continue;
2572 
2573  if (isType(TYPEMASK_UNIT) && ((Unit*)this)->GetCharmerGUID() == player->GetGUID()) // @todo this is for puppet
2574  continue;
2575 
2576  if (GetTypeId() == TYPEID_UNIT)
2577  {
2578  // at remove from world (destroy) show kill animation
2579  DestroyForPlayer(player, ToUnit()->IsDuringRemoveFromWorld() && ToCreature()->isDead());
2580  }
2581  else
2582  DestroyForPlayer(player);
2583 
2584  player->m_clientGUIDs.erase(GetGUID());
2585  }
2586 }
2587 
2589 {
2590  //updates object's visibility for nearby players
2591  Oregon::VisibleChangesNotifier notifier(*this);
2593 }
2594 
2596 {
2599  std::set<uint64> plr_list;
2600  WorldObjectChangeAccumulator(WorldObject& obj, UpdateDataMapType& d) : i_updateDatas(d), i_object(obj) {}
2602  {
2603  for (PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
2604  {
2605  BuildPacket(iter->GetSource());
2606  if (!iter->GetSource()->GetSharedVisionList().empty())
2607  {
2608  SharedVisionList::const_iterator it = iter->GetSource()->GetSharedVisionList().begin();
2609  for (; it != iter->GetSource()->GetSharedVisionList().end(); ++it)
2610  BuildPacket(*it);
2611  }
2612  }
2613  }
2614 
2616  {
2617  for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
2618  {
2619  if (!iter->GetSource()->GetSharedVisionList().empty())
2620  {
2621  SharedVisionList::const_iterator it = iter->GetSource()->GetSharedVisionList().begin();
2622  for (; it != iter->GetSource()->GetSharedVisionList().end(); ++it)
2623  BuildPacket(*it);
2624  }
2625  }
2626  }
2628  {
2629  for (DynamicObjectMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
2630  {
2631  uint64 guid = iter->GetSource()->GetCasterGUID();
2632  if (IS_PLAYER_GUID(guid))
2633  {
2634  //Caster may be NULL if DynObj is in removelist
2635  if (Player* caster = ObjectAccessor::FindPlayer(guid))
2636  if (caster->GetUInt64Value(PLAYER_FARSIGHT) == iter->GetSource()->GetGUID())
2637  BuildPacket(caster);
2638  }
2639  }
2640  }
2641  void BuildPacket(Player* plr)
2642  {
2643  // Only send update once to a player
2644  if (plr_list.find(plr->GetGUID()) == plr_list.end() && plr->HaveAtClient(&i_object))
2645  {
2646  i_object.BuildFieldsUpdate(plr, i_updateDatas);
2647  plr_list.insert(plr->GetGUID());
2648  }
2649  }
2650 
2651  template<class SKIP> void Visit(GridRefManager<SKIP>&) {}
2652 };
2653 
2655 {
2657  Cell cell(p);
2658  cell.SetNoCreate();
2659  WorldObjectChangeAccumulator notifier(*this, data_map);
2661  Map& map = *GetMap();
2662  //we must build packets for all visible players
2663  cell.Visit(p, player_notifier, map, *this, GetVisibilityRange());
2664 
2665  ClearUpdateMask(false);
2666 }
2667 
despawns when UnSummon() is called
float GetGridActivationRange() const
Definition: Object.cpp:1528
void MovePosition(Position &pos, float dist, float angle)
Definition: Object.cpp:2419
GameobjectTypes
bool BuildPacket(WorldPacket *packet, bool hasTransport=false)
Definition: UpdateData.cpp:103
virtual void ResetMap()
Definition: Object.cpp:1969
bool AddToMap(T *)
Definition: Map.cpp:424
void RemoveUpdateObject(Object *obj)
ClientGUIDs m_clientGUIDs
Definition: Player.h:2471
void SetStatFloatValue(uint16 index, float value)
Definition: Object.cpp:930
GameObject * SummonGameObject(uint32 entry, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime)
Definition: Object.cpp:2222
void SendPlaySound(uint32 Sound, bool OnlySelf)
Definition: Object.cpp:1787
Definition: Corpse.h:48
PetType
Definition: Pet.h:25
float s_pitch
Definition: Object.h:458
const bool m_isWorldObject
Definition: Object.h:921
T_FLAGS GetFlags() const
Definition: Object.h:614
bool GetBit(uint32 index)
Definition: UpdateMask.h:49
bool m_objectUpdated
Definition: Object.h:434
const uint32 & GetUInt32Value(uint16 index) const
Definition: Object.h:228
virtual bool IsNeverVisible() const
Definition: Object.h:804
Unit * GetOwner() const
Definition: GameObject.cpp:778
void ApplyModUInt32Value(uint16 index, int32 val, bool apply)
Definition: Object.cpp:946
void _BuildMovementUpdate(ByteBuffer *data, uint8 updateFlags) const
Definition: Object.cpp:253
Map * m_currMap
Definition: Object.h:937
void ClearUpdateMask(bool remove)
Definition: Object.cpp:678
void SetPetNumber(uint32 petnumber, bool statwindow)
Definition: Unit.cpp:11314
uint32 GetMaxHealth() const
Definition: Unit.h:1052
bool m_inWorld
Definition: Object.h:437
bool _IsWithinDist(WorldObject const *obj, float dist2compare, bool is3D) const
Definition: Object.cpp:1210
bool GetDistanceOrder(WorldObject const *obj1, WorldObject const *obj2, bool is3D=true) const
Definition: Object.cpp:1273
uint32 * m_uint32Values
Definition: Object.h:426
#define sOutdoorPvPMgr
Definition: OutdoorPvPMgr.h:79
void PlayDirectSound(uint32 sound_id, Player *target=NULL)
Definition: Object.cpp:2544
float GetTransOffsetZ() const
Definition: Player.h:2420
int32 * m_int32Values
Definition: Object.h:425
Map * GetMap() const
Definition: Object.h:829
std::vector< std::string > Tokens
Definition: Util.h:26
Pet * SummonPet(uint32 entry, float x, float y, float z, float ang, PetType petType, uint32 despwtime)
Definition: Object.cpp:2110
void SendObjectCustomAnim(uint64 guid, uint32 anim=0)
Definition: Object.cpp:1943
#define DEFAULT_VISIBILITY_INSTANCE
Definition: Object.h:41
bool HasAuraTypeWithMiscvalue(AuraType auratype, int32 miscvalue) const
Definition: Unit.cpp:797
uint32 GetUnitMovementFlags() const
Definition: Unit.h:2015
GameObject * FindNearestGameObjectOfType(GameobjectTypes type, float range) const
Definition: Object.cpp:2307
uint32 getFaction() const
Definition: Unit.h:1111
void Visit(DynamicObjectMapType &m)
Definition: Object.cpp:2627
void MonsterTextEmote(const char *text, uint64 TargetGuid, bool IsBossEmote=false)
Definition: Object.cpp:1501
Position GetFirstCollisionPosition(float dist, float angle)
Definition: Object.cpp:2365
void MonsterSay(const char *text, uint32 language, uint64 TargetGuid)
Definition: Object.cpp:1487
float m_positionY
Definition: Position.h:51
float GetDistanceSqr(float x, float y, float z) const
Definition: Object.cpp:1200
bool LoadValues(const char *data)
Definition: Object.cpp:704
void SetOrientation(float orientation)
Definition: Position.h:92
void _BuildValuesUpdate(uint8 updatetype, ByteBuffer *data, UpdateMask *updateMask, Player *target) const
Definition: Object.cpp:450
void BuildValuesUpdateBlockForPlayer(UpdateData *data, Player *target) const
Definition: Object.cpp:218
MovementInfo m_movementInfo
Definition: Object.h:915
void BuildFieldsUpdate(Player *, UpdateDataMapType &) const
Definition: Object.cpp:690
void SetInt32Value(uint16 index, int32 value)
Definition: Object.cpp:760
std::set< uint64 > plr_list
Definition: Object.cpp:2599
void _Create(uint32 guidlow, HighGuid guidhigh)
Definition: Object.cpp:1161
void UpdateAllowedPositionZ(float x, float y, float &z) const
Definition: Object.cpp:1416
bool isType(uint16 mask) const
Definition: Object.h:208
void setActive(bool isActiveObject)
Definition: Object.cpp:1122
FlaggedValuesArray32< int32, uint32, ServerSideVisibilityType, TOTAL_SERVERSIDE_VISIBILITY_TYPES > m_serverSideVisibility
Definition: Object.h:821
#define WORLD_TRIGGER
Definition: Unit.h:38
uint32 GetZoneId() const
Definition: Object.cpp:1176
TempSummon * SummonCreature(uint32 id, const Position &pos, TempSummonType spwtype=TEMPSUMMON_MANUAL_DESPAWN, uint32 despwtime=0)
Definition: Object.cpp:2088
void BuildMovementUpdateBlock(UpdateData *data, uint32 flags=0) const
Definition: Object.cpp:136
void ApplyModInt32Value(uint16 index, int32 val, bool apply)
Definition: Object.cpp:955
virtual void SetMap(Map *map)
Definition: Object.cpp:1951
bool CanNeverSee(WorldObject const *obj) const
Definition: Object.cpp:1660
uint32 getMSTime()
Definition: Timer.h:32
void _LoadIntoDataField(const char *data, uint32 startOffset, uint32 count)
Definition: Object.cpp:721
float GetHeight(float x, float y, float z, bool checkVMap=true, float maxSearchDist=DEFAULT_HEIGHT_SEARCH) const
Definition: Map.cpp:1590
void SetValue(FLAG_TYPE flag, T_VALUES value)
Definition: Object.h:620
#define sLog
Log class singleton.
Definition: Log.h:187
float GetVisibilityRange() const
Definition: Object.cpp:1549
ChatMsg
virtual void CleanupsBeforeDelete()
Definition: Object.cpp:1155
Transport * GetTransport() const
Definition: Player.h:2403
void GetCreatureListWithEntryInGrid(std::list< Creature * > &creatureList, uint32 entry=GRID_SEARCH_ALL_ENTRIES, float maxSearchRange=250.0f) const
Definition: Object.cpp:2329
Tokens StrSplit(const std::string &src, const std::string &sep)
Definition: Util.cpp:97
void SetUInt32Value(uint16 index, uint32 value)
Definition: Object.cpp:779
ACE_INT32 int32
Definition: Define.h:67
bool IsWithinLOSInMap(const WorldObject *obj) const
Definition: Object.cpp:1226
std::list< Aura * > AuraList
Definition: Unit.h:893
void SetHomePosition(float x, float y, float z, float o)
Definition: Creature.h:794
NULL Dbg ErrDB Arena Chat Char Map MMap false
Definition: Log.cpp:556
bool Create(uint32 guidlow, Map *map, uint32 Entry, uint32 pet_number)
Definition: Pet.cpp:1769
bool IsValidMapCoord(float c)
Definition: GridDefines.h:192
void GetGameObjectListWithEntryInGrid(std::list< GameObject * > &gameobjectList, uint32 entry=GRID_SEARCH_ALL_ENTRIES, float maxSearchRange=250.0f) const
Definition: Object.cpp:2316
bool IsDungeon() const
Definition: Map.h:427
FlaggedValuesArray32< int32, uint32, InvisibilityType, TOTAL_INVISIBILITY_TYPES > m_invisibilityDetect
Definition: Object.h:819
void AddOutOfRangeGUID(std::set< uint64 > &guids)
Definition: UpdateData.cpp:31
float m_positionX
Definition: Position.h:50
void AddObjectToRemoveList(WorldObject *obj)
Definition: Map.cpp:2037
void Initialize(uint16 opcode, size_t newres=200)
Definition: WorldPacket.h:37
bool IsWithinLOS(float x, float y, float z) const
Definition: Object.cpp:1240
bool IsWorldObject() const
Definition: Object.cpp:1111
void SetNoCreate()
Definition: Cell.h:76
void RemoveWorldObject(WorldObject *obj)
Definition: Map.h:483
bool IsGameMaster() const
Definition: Player.h:1009
virtual bool getObjectHitPos(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2, float &rx, float &ry, float &rz, float pModifyDist)=0
void SetRespawnTime(int32 respawn)
Definition: GameObject.h:691
FlaggedValuesArray32< int32, uint32, StealthType, TOTAL_STEALTH_TYPES > m_stealthDetect
Definition: Object.h:816
uint32 GetGUIDLow() const
Definition: Object.h:160
void MonsterYell(const char *text, uint32 language, uint64 TargetGuid)
Definition: Object.cpp:1494
float GetWaterOrGroundLevel(float x, float y, float z, float *ground=NULL, bool swim=false) const
Definition: Map.cpp:1572
void RemoveFromActive(T *obj)
Definition: Map.h:511
DynamicObject * ToDynObject()
Definition: Object.h:401
void SetStatInt32Value(uint16 index, int32 value)
Definition: Object.cpp:938
static uint32 GetAreaId(uint16 areaflag, uint32 map_id)
Definition: Map.cpp:1824
UpdateDataMapType & i_updateDatas
Definition: Object.cpp:2597
#define SIGHT_RANGE_UNIT
Definition: Object.h:39
void SetFlag(uint16 index, uint32 newFlag)
Definition: Object.cpp:985
TempSummonType GetTempSummonType() const
uint32 modelid1
Definition: Creature.h:134
bool AIM_Initialize(CreatureAI *ai=NULL)
Definition: Creature.cpp:741
iterator begin()
Definition: MapRefManager.h:48
void apply(T *val)
Definition: ByteConverter.h:41
float GetTransOffsetX() const
Definition: Player.h:2412
uint16 m_objectType
Definition: Object.h:418
void ApplyPercentModFloatValue(uint16 index, float val, bool apply)
Definition: Object.cpp:969
bool IsInRange3d(float x, float y, float z, float minRange, float maxRange) const
Definition: Object.cpp:1341
#define sObjectMgr
Definition: ObjectMgr.h:1285
void SendPacket(WorldPacket const *packet)
GameObject * ToGameObject()
Definition: Object.h:395
CharmInfo * GetCharmInfo()
Definition: Unit.h:1567
void setPowerType(Powers power)
Definition: Unit.cpp:7089
bool Create(uint32 guidlow, uint32 name_id, Map *map, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, GOState go_state, uint32 ArtKit=0)
Definition: GameObject.cpp:166
virtual void SendMessageToSet(WorldPacket *data, bool self)
Definition: Object.h:777
void VisitNearbyGridObject(float const &radius, NOTIFIER &notifier) const
Definition: Object.h:910
uint32 m_InstanceId
Definition: Object.h:940
virtual void _SetUpdateBits(UpdateMask *updateMask, Player *target) const
Definition: Object.cpp:737
void VisitNearbyObject(float const &radius, NOTIFIER &notifier) const
Definition: Object.h:909
InvisibilityType
Player * ToPlayer()
Definition: Object.h:386
void MonsterWhisper(const char *text, uint64 receiver, bool IsBossWhisper=false)
Definition: Object.cpp:1508
void SetByteFlag(uint16 index, uint8 offset, uint8 newFlag)
Definition: Object.cpp:1029
uint32 flags_extra
Definition: Creature.h:197
virtual void RemoveFromWorld()
Definition: Object.h:145
Definition: Totem.h:31
bool ShouldRevealHealthTo(Player *player) const
Definition: Unit.cpp:10887
virtual uint8 getLevelForTarget(WorldObject const *) const
Definition: Object.h:780
virtual bool IsInvisibleDueToDespawn() const
Definition: Object.h:806
uint8 m_objectTypeId
Definition: Object.h:420
void setFaction(uint32 faction)
Definition: Unit.h:1115
uint32 GetId(void) const
Definition: Map.h:333
bool IsWithinDist(WorldObject const *obj, float dist2compare, bool is3D=true) const
Definition: Object.h:758
despawns when the creature disappears
#define IS_PLAYER_GUID(Guid)
Definition: ObjectGuid.h:69
float GetCombatReach() const
Definition: Unit.h:941
bool IsInRange2d(float x, float y, float minRange, float maxRange) const
Definition: Object.cpp:1321
despawns after a specified time
uint8 * GetMask()
Definition: UpdateMask.h:66
uint8 GetTypeId() const
Definition: Object.h:204
void SavePetToDB(PetSaveMode mode)
Definition: Pet.cpp:364
uint32 m_mapId
Definition: Object.h:590
void _Create(uint32 guidlow, uint32 entry, HighGuid guidhigh)
Definition: Object.cpp:125
Definition: Pet.h:27
float GetPositionZTarget(Position &pos, float destx, float desty)
Definition: Object.cpp:2382
Position GetHitSpherePointFor(Position const &dest) const
Definition: Object.cpp:1256
bool InitStatsForLevel(uint32 level)
Definition: Pet.cpp:966
CinematicMgr * GetCinematicMgr() const
Definition: Player.h:1255
virtual void DestroyForPlayer(Player *target, bool onDeath=false) const
Definition: Object.cpp:241
ACE_UINT8 uint8
Definition: Define.h:73
uint32 GetMaxPower(Powers power) const
Definition: Unit.h:1080
float GetOrientation() const
Definition: Position.h:100
#define UI64FMTD
Definition: Common.h:149
void AddObjectToSwitchList(WorldObject *obj, bool on)
Definition: Map.cpp:2047
void Relocate(float x, float y)
Definition: Position.h:65
Position GetNearPosition(float dist, float angle)
Definition: Object.cpp:2358
PackedGuid m_PackGUID
Definition: Object.h:439
const bool & IsInWorld() const
Definition: Object.h:129
void BuildUpdate(UpdateDataMapType &) override
Definition: Object.cpp:2654
void ApplyModSignedFloatValue(uint16 index, float val, bool apply)
Definition: Object.cpp:962
uint32 GuidHigh2TypeId(uint32 guid_hi)
Definition: Object.cpp:43
HighGuid
Definition: ObjectGuid.h:51
bool IsFriendlyTo(FactionTemplateEntry const &entry) const
Definition: DBCStructure.h:314
float GetTransOffsetO() const
Definition: Player.h:2424
ZoneScript * m_zoneScript
Definition: Object.h:922
void AddObjectToRemoveList()
Definition: Object.cpp:1987
void BuildPacket(Player *plr)
Definition: Object.cpp:2641
ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData *data=0) const
Definition: Map.cpp:1727
uint32 * m_uint32Values_mirror
Definition: Object.h:430
Map * FindMap() const
Definition: Object.h:830
bool RemoveUInt64Value(uint16 index, const uint64 &value)
Definition: Object.cpp:838
TempSummon * SummonCreature(uint32 entry, const Position &pos, SummonPropertiesEntry const *properties=NULL, uint32 duration=0, Unit *summoner=NULL, uint32 spellId=0, TempSummonType spwType=TEMPSUMMON_MANUAL_DESPAWN)
Definition: Object.cpp:2001
void AddUpdateObject(Object *obj)
float GetPositionY() const
Definition: Position.h:98
uint8 m_updateFlag
Definition: Object.h:421
void SetByteValue(uint16 index, uint8 offset, uint8 value)
Definition: Object.cpp:878
virtual bool isValid() const
Definition: Object.cpp:1520
void SetSpawnedByDefault(bool b)
Definition: GameObject.h:707
#define MAKE_NEW_GUID(l, e, h)
Definition: ObjectGuid.h:80
Position GetRandomNearPosition(float radius)
Definition: Object.cpp:2372
void SetUInt16Value(uint16 index, uint8 offset, uint16 value)
Definition: Object.cpp:904
void GetPosition(float &x, float &y) const
Definition: Position.h:102
float level
Definition: Map.h:151
bool m_isActive
Definition: Object.h:920
virtual void RemoveFromWorld() override
Definition: Object.cpp:1166
FlaggedValuesArray32< int32, uint32, ServerSideVisibilityType, TOTAL_SERVERSIDE_VISIBILITY_TYPES > m_serverSideVisibilityDetect
Definition: Object.h:822
Position(float x=0, float y=0, float z=0, float o=0)
Definition: Position.h:27
static Player * FindPlayer(uint64, bool force=false)
etc mysql my cnf *Then change max_allowed_packet to a bigger value
void RemoveByteFlag(uint16 index, uint8 offset, uint8 newFlag)
Definition: Object.cpp:1054
float GetPositionZ() const
Definition: Position.h:99
void ApplyModPositiveFloatValue(uint16 index, float val, bool apply)
Definition: Object.cpp:976
bool isActiveObject() const
Definition: Object.h:899
bool CanDetect(WorldObject const *obj, bool ignoreStealth, bool checkAlert=false) const
Definition: Object.cpp:1665
float GetTransOffsetY() const
Definition: Player.h:2416
float GetAngle(Position const *pos) const
TempSummonType
bool PrintIndexError(uint32 index, bool set) const
Definition: Object.cpp:1079
WorldObjectChangeAccumulator(WorldObject &obj, UpdateDataMapType &d)
Definition: Object.cpp:2600
void SendDirectMessage(WorldPacket *data)
Definition: Player.cpp:5782
static uint32 GetZoneId(uint16 areaflag, uint32 map_id)
Definition: Map.cpp:1834
PackedGuid const & GetPackGUID() const
Definition: Object.h:172
#define DEBUG_LOG(...)
Definition: Log.h:194
virtual bool CanAlwaysSee(WorldObject const *) const
Definition: Object.h:946
void operator()(WorldPacket &data, int32 loc_idx)
Definition: Object.cpp:1817
float GetAttackDistance(Unit const *pl) const
Definition: Creature.cpp:1520
uint32 GetMapId() const
Definition: Object.h:585
float m_positionZ
Definition: Position.h:52
void SetDuration(int32 dur)
Definition: Pet.h:214
Creature * FindNearestCreature(uint32 entry, float range, bool alive=true)
Definition: Object.cpp:2289
Position GetPosition() const
Definition: Position.h:117
bool IsInMap(const WorldObject *obj) const
Definition: Object.h:733
uint32 GetAreaId() const
Definition: Object.cpp:1181
StealthType
UNORDERED_MAP< Player *, UpdateData > UpdateDataMapType
Definition: Object.h:120
iterator end()
Definition: Map.h:266
bool IsOnCinematic() const
Definition: CinematicMgr.h:39
bool isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2) const
Definition: Map.cpp:1804
float GetVisibilityRange() const
Definition: Map.h:291
void SetUInt64Value(uint16 index, const uint64 &value)
Definition: Object.cpp:798
CellCoord ComputeCellCoord(float x, float y)
Definition: GridDefines.h:167
void MonsterYellToZone(int32 textId, uint32 language, uint64 TargetGuid)
Definition: Object.cpp:1862
void GetNearPoint2D(float &x, float &y, float distance, float absAngle) const
Definition: Object.cpp:2342
Object()
Definition: Object.cpp:68
virtual void BuildCreateUpdateBlockForPlayer(UpdateData *data, Player *target) const
Definition: Object.cpp:148
void MovePositionToFirstCollision(Position &pos, float dist, float angle)
Definition: Object.cpp:2471
virtual ~Object()
Definition: Object.cpp:95
void InitPetCreateSpells()
Definition: Pet.cpp:1605
#define MAX_VISIBILITY_DISTANCE
Definition: Object.h:38
const char * GetName() const
Definition: Object.h:692
void ApplyPercentModFloatVar(float &var, float val, bool apply)
Definition: Util.h:94
~WorldObject() override
Definition: Object.cpp:81
void ForceValuesUpdateAtIndex(uint32)
Definition: Object.cpp:1797
void RemoveFlag(uint16 index, uint32 oldFlag)
Definition: Object.cpp:1006
ACE_UINT64 uint64
Definition: Define.h:70
PlayerList const & GetPlayers() const
Definition: Map.h:491
Definition: Cell.h:46
bool IsInSameRaidWith(Player const *p) const
Definition: Player.h:1816
void Visit(CreatureMapType &m)
Definition: Object.cpp:2615
bool IsInRange(WorldObject const *obj, float minRange, float maxRange, bool is3D=true) const
Definition: Object.cpp:1296
uint64 GetPetGUID() const
Definition: Unit.h:1487
bool CanDetectStealthOf(WorldObject const *obj, bool checkAlert=false) const
Definition: Object.cpp:1717
bool isAllowedToLoot(const Creature *creature)
Definition: Player.cpp:15042
#define MAX_PLAYER_STEALTH_DETECT_RANGE
Definition: Unit.h:880
Definition: Unit.h:461
void BuildHeartBeatMsg(WorldPacket *data) const
Definition: Object.cpp:1923
void append(const std::string &str)
Definition: ByteBuffer.h:358
void Set(uint64 const &guid)
Definition: ObjectGuid.h:302
bool HaveAtClient(WorldObject const *u) const
Definition: Player.cpp:18670
bool isDead() const
Definition: Unit.h:1441
bool HasInArc(float arcangle, const Position *pos) const
Definition: Object.cpp:1390
WorldObject(bool isWorldObject)
Definition: Object.cpp:1087
CreatureInfo const * GetCreatureTemplate() const
Definition: Creature.h:598
Unit * GetCharmerOrOwner() const
Definition: Unit.h:1519
void AddUpdateBlock(const ByteBuffer &block)
Definition: UpdateData.cpp:41
virtual bool IsAlwaysVisibleFor(WorldObject const *seer) const
Definition: Object.h:805
virtual void InitSummon()
Map const * GetBaseMap() const
Definition: Object.cpp:1981
#define MAP_ALL_LIQUIDS
Definition: Map.h:142
void SummonCreatureGroup(uint8 group, std::list< TempSummon * > *list=NULL)
Definition: Object.cpp:2275
static void WriteCreate(const MoveSpline &mov, ByteBuffer &data)
void SendObjectDeSpawnAnim(uint64 guid)
Definition: Object.cpp:1936
uint32 GetLength()
Definition: UpdateMask.h:58
int GetSessionDbLocaleIndex() const
Definition: WorldSession.h:237
void BuildMonsterChat(WorldPacket *data, uint8 msgtype, char const *text, uint32 language, char const *name, uint64 TargetGuid) const
Definition: Object.cpp:1904
virtual void _SetCreateBits(UpdateMask *updateMask, Player *target) const
Definition: Object.cpp:749
bool LoadPetFromDB(Player *owner, uint32 petentry=0, uint32 petnumber=0, bool current=false)
Definition: Pet.cpp:131
Creature * ToCreature()
Definition: Object.h:389
virtual void UpdateObjectVisibility(bool forced=true)
Definition: Object.cpp:2588
void SetZoneScript()
Definition: Object.cpp:2099
float m_SightDistance
Definition: Creature.h:864
void AddToActive(T *obj)
Definition: Map.h:502
float * m_floatValues
Definition: Object.h:427
Creature * SummonTrigger(float x, float y, float z, float ang, uint32 dur, CreatureAI *(*GetAI)(Creature *)=NULL)
Definition: Object.cpp:2250
uint32 GetGUIDHigh() const
Definition: Object.h:168
void SetWorldObject(bool apply)
Definition: Object.cpp:1103
void SetFloatValue(uint16 index, float value)
Definition: Object.cpp:859
float GetExactDist(float x, float y, float z) const
Definition: Position.h:150
void GetRandomPoint(const Position &srcPos, float distance, float &rand_x, float &rand_y, float &rand_z) const
Definition: Object.cpp:1395
void SetCount(uint32 valuesCount)
Definition: UpdateMask.h:71
uint16 m_valuesCount
Definition: Object.h:432
iterator begin()
double rand_norm(void)
Definition: Util.cpp:86
virtual void SendMessageToSetInRange(WorldPacket *data, float dist, bool self)
Definition: Object.cpp:1930
uint32 GetFallTime() const
Definition: Object.h:533
uint32 GetTeam() const
Definition: Player.h:2075
void SetPower(Powers power, uint32 val)
Definition: Unit.cpp:10918
FlaggedValuesArray32< int32, uint32, StealthType, TOTAL_STEALTH_TYPES > m_stealth
Definition: Object.h:815
static IVMapManager * createOrGetVMapManager()
bool isTappedBy(Player const *player) const
Definition: Creature.cpp:1032
#define ASSERT
Definition: Errors.h:33
GameObject * FindNearestGameObject(uint32 entry, float range)
Definition: Object.cpp:2298
FlaggedValuesArray32< int32, uint32, InvisibilityType, TOTAL_INVISIBILITY_TYPES > m_invisibility
Definition: Object.h:818
uint32 GetTransTime() const
Definition: Player.h:2428
bool AddUInt64Value(uint16 index, const uint64 &value)
Definition: Object.cpp:817
void SetTempSummonType(TempSummonType type)
void PlayDistanceSound(uint32 sound_id, Player *target=NULL)
Definition: Object.cpp:2533
T_VALUES GetValue(FLAG_TYPE flag) const
Definition: Object.h:619
void DestroyForNearbyPlayers()
Definition: Object.cpp:2554
#define INVALID_HEIGHT
Definition: Map.h:259
void SetLevel(uint32 lvl)
Definition: Unit.cpp:10817
const int32 & GetInt32Value(uint16 index) const
Definition: Object.h:222
virtual void InitStats(uint32 lifetime)
WorldObject const & i_object
Definition: Object.cpp:1826
uint32 GetEntry() const
Definition: Object.h:186
bool IsPositionValid() const
Definition: Position.cpp:40
WorldSession * GetSession() const
Definition: Player.h:1959
#define sWorld
Definition: World.h:860
#define CONTACT_DISTANCE
Definition: Object.h:34
void SetHealth(uint32 val)
Definition: Unit.cpp:10826
void Visit(GridRefManager< SKIP > &)
Definition: Object.cpp:2651
void SetCreatorGUID(uint64 creator)
Definition: Unit.h:1459
void AddWorldObject(WorldObject *obj)
Definition: Map.h:479
ACE_UINT16 uint16
Definition: Define.h:72
float GetDistanceZ(const WorldObject *obj) const
Definition: Object.cpp:1192
void _InitValues()
Definition: Object.cpp:114
FactionTemplateEntry const * GetFactionTemplateEntry() const
Definition: Unit.cpp:7132
bool CanSeeOrDetect(WorldObject const *obj, bool ignoreStealth=false, bool distanceCheck=false, bool checkAlert=false) const
Definition: Object.cpp:1582
virtual bool IsAlwaysDetectableFor(WorldObject const *) const
Definition: Object.h:808
ACE_UINT32 uint32
Definition: Define.h:71
Definition: Pet.h:29
float GetPositionX() const
Definition: Position.h:97
#define MAX_HEIGHT
Definition: Map.h:258
uint32 GetCount()
Definition: UpdateMask.h:62
void SetBit(uint32 index)
Definition: UpdateMask.h:39
bool getObjectHitPos(float x1, float y1, float z1, float x2, float y2, float z2, float &rx, float &ry, float &rz, float modifyDist)
Definition: Map.cpp:1810
Definition: Unit.h:884
float m_CombatDistance
Definition: Creature.h:864
void BuildOutOfRangeUpdateBlock(UpdateData *data) const
Definition: Object.cpp:236
float GetObjectSize() const
Definition: Object.h:663
Map const * GetParent() const
Definition: Map.h:344
void GetNearPoint(WorldObject const *searcher, float &x, float &y, float &z, float searcher_size, float distance2d, float absAngle) const
Definition: Object.cpp:2351
Definition: Player.h:922
bool CanDetectInvisibilityOf(WorldObject const *obj) const
Definition: Object.cpp:1686
uint32 GetInstanceId() const
Definition: Map.h:390
void Visit(PlayerMapType &m)
Definition: Object.cpp:2601
void Visit(CellCoord const &, TypeContainerVisitor< T, CONTAINER > &visitor, Map &, WorldObject const &, float) const
Definition: CellImpl.h:121
void SendUpdateToPlayer(Player *player)
Definition: Object.cpp:207
bool IsInSameGroupWith(Player const *p) const
Definition: Player.cpp:2388
Unit * ToUnit()
Definition: Object.h:392
uint32 GetBlockCount()
Definition: UpdateMask.h:54
float GetSightRange(const WorldObject *target=NULL) const
Definition: Object.cpp:1557
void VisitNearbyWorldObject(const float &radius, NOTIFIER &notifier) const
Definition: Object.h:908
iterator end()
Definition: MapRefManager.h:52
Definition: Pet.h:146
MonsterChatBuilder(WorldObject const &obj, ChatMsg msgtype, int32 textId, uint32 language, uint64 targetGUID)
Definition: Object.cpp:1815
void UpdateGroundPositionZ(float x, float y, float &z) const
Definition: Object.cpp:1480
#define atol(a)
Definition: Common.h:162
float GetHealthPct() const
Definition: Unit.h:1062
const uint64 & GetGUID() const
Definition: Object.h:156
InstanceData * GetInstanceData()
Definition: Object.cpp:1186
const float & GetFloatValue(uint16 index) const
Definition: Object.h:240
bool Create(uint32 guidlow, Map *map, uint32 Entry, uint32 team, float x, float y, float z, float ang, const CreatureData *data=NULL)
Definition: Creature.cpp:759
void NormalizeMapCoord(float &c)
Definition: GridDefines.h:184