OregonCore  revision be9e804-git
Your Favourite TBC server
GameObject.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 <https://www.gnu.org/licenses/>.
16  */
17 
18 #include "Common.h"
19 #include "QuestDef.h"
20 #include "GameObjectAI.h"
21 #include "GameObject.h"
22 #include "ObjectMgr.h"
23 #include "PoolMgr.h"
24 #include "SpellMgr.h"
25 #include "ScriptMgr.h"
26 #include "Spell.h"
27 #include "UpdateMask.h"
28 #include "Opcodes.h"
29 #include "WorldPacket.h"
30 #include "WorldSession.h"
31 #include "World.h"
32 #include "Database/DatabaseEnv.h"
33 #include "MapManager.h"
34 #include "LootMgr.h"
35 #include "GridNotifiers.h"
36 #include "GridNotifiersImpl.h"
37 #include "CellImpl.h"
38 #include "CreatureAISelector.h"
39 #include "InstanceData.h"
40 #include "Battleground.h"
41 #include "Utilities/Util.h"
42 #include "OutdoorPvPMgr.h"
43 #include "BattlegroundAV.h"
44 #include "GameObjectModel.h"
45 #include "DynamicTree.h"
46 #include "Transports.h"
47 
48 GameObject::GameObject() : WorldObject(false), m_model(NULL), m_AI(NULL)
49 {
52  // 2.3.2 - 0x58
54 
56  m_respawnTime = 0;
57  m_respawnDelayTime = 25;
59  m_spawnedByDefault = true;
60  m_usetimes = 0;
61  m_spellId = 0;
62  m_cooldownTime = 0;
63  m_goInfo = NULL;
65  m_goData = NULL;
66 
67  m_DBTableGuid = 0;
68 }
69 
71 {
72  delete m_model;
73  delete m_AI;
74 }
75 
77 {
78  delete m_AI;
79 
81 
82  if (!m_AI)
83  return false;
84 
85  m_AI->InitializeAI();
86  return true;
87 }
88 
90 {
91  if (IsInWorld())
93 
94  if (m_uint32Values) // field array can be not exist if GameOBject not loaded
95  {
96  // Possible crash at access to deleted GO in Unit::m_gameobj
97  if (uint64 owner_guid = GetOwnerGUID())
98  {
99  Unit* owner = ObjectAccessor::GetUnit(*this, owner_guid);
100  if (owner)
101  owner->RemoveGameObject(this, false);
102  else
103  {
104  const char* ownerType = "creature";
105  if (IS_PLAYER_GUID(owner_guid))
106  ownerType = "player";
107  else if (IS_PET_GUID(owner_guid))
108  ownerType = "pet";
109 
110  sLog.outError("Delete GameObject (GUID: %u Entry: %u SpellId %u LinkedGO %u) that lost references to owner (GUID %u Type '%s') GO list. Crash possible later.",
111  GetGUIDLow(), GetGOInfo()->id, m_spellId, GetGOInfo()->GetLinkedGameObjectEntry(), GUID_LOPART(owner_guid), ownerType);
112  }
113  }
114  }
115 }
116 
118 {
119  // Register the gameobject for guid lookup
120  if (!IsInWorld())
121  {
122  if (m_zoneScript)
123  m_zoneScript->OnGameObjectCreate(this, true);
124 
126 
127  // The state can be changed after GameObject::Create but before GameObject::AddToWorld
128  bool toggledState = GetGoType() == GAMEOBJECT_TYPE_CHEST ? getLootState () == GO_READY : (GetGoState() == GO_STATE_READY || IsTransport());
129  if (m_model)
130  {
131  if (Transport* trans = ToTransport())
132  trans->SetDelayedAddModelToMap();
133  else
134  GetMap()->Insert(*m_model);
135  }
136  EnableCollision(toggledState);
138  }
139 }
140 
142 {
143  // Remove the gameobject from the accessor
144  if (IsInWorld())
145  {
146  if (m_zoneScript)
147  m_zoneScript->OnGameObjectCreate(this, false);
148 
149  // Possible crash at access to deleted GO in Unit::m_gameobj
150  if (uint64 owner_guid = GetOwnerGUID())
151  {
152  if (Unit* owner = GetOwner())
153  owner->RemoveGameObject(this, false);
154  else
155  sLog.outError("Delete GameObject (GUID: %u Entry: %u) that has references in invalid creature %u GO list. Crash possible.", GetGUIDLow(), GetGOInfo()->id, GUID_LOPART(owner_guid));
156  }
157 
158  if (m_model)
159  if (GetMap()->Contains(*m_model))
160  GetMap()->Remove(*m_model);
163  }
164 }
165 
166 bool GameObject::Create(uint32 guidlow, uint32 name_id, Map* map, uint32 phaseMask, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, GOState go_state, uint32 artKit)
167 {
168  ASSERT(map);
169  SetMap(map);
170 
171  Relocate(x, y, z, ang);
172 
173  if (!IsPositionValid())
174  {
175  sLog.outError("Gameobject (GUID: %u Entry: %u) not created. Suggested coordinates isn't valid (X: %f Y: %f)", guidlow, name_id, x, y);
176  return false;
177  }
178 
179  GameObjectInfo const* goinfo = sObjectMgr.GetGameObjectInfo(name_id);
180  if (!goinfo)
181  {
182  sLog.outErrorDb("Gameobject (GUID: %u Entry: %u) not created: Invalid entry in gameobject_template. Map: %u (X: %f Y: %f Z: %f) ang: %f rotation0: %f rotation1: %f rotation2: %f rotation3: %f", guidlow, name_id, map->GetId(), x, y, z, ang, rotation0, rotation1, rotation2, rotation3);
183  return false;
184  }
185 
186  Object::_Create(guidlow, goinfo->id, HIGHGUID_GAMEOBJECT);
187 
188  m_goInfo = goinfo;
189 
190  if (goinfo->type >= MAX_GAMEOBJECT_TYPE)
191  {
192  sLog.outErrorDb("Gameobject (GUID: %u Entry: %u) not created: Invalid GO type '%u' in gameobject_template. It will crash the client if created.", guidlow, name_id, goinfo->type);
193  return false;
194  }
195 
196  SetPhaseMask(phaseMask, false);
200 
201  SetFloatValue(GAMEOBJECT_ROTATION + 0, rotation0);
202  SetFloatValue(GAMEOBJECT_ROTATION + 1, rotation1);
203 
204  UpdateRotationFields(rotation2, rotation3); // GAMEOBJECT_FACING, GAMEOBJECT_ROTATION, GAMEOBJECT_PARENTROTATION+2/3
205 
206  SetObjectScale(goinfo->size);
207 
210 
212 
214 
216  SetGoType(GameobjectTypes(goinfo->type));
217  SetGoState(go_state);
218 
219  SetGoAnimProgress(animprogress);
220 
222 
223  SetZoneScript();
224 
225  AIM_Initialize();
226 
227  // Check if GameObject is Large
228  if (goinfo->IsLargeGameObject())
230 
231  return true;
232 }
233 
235 {
236  if (IS_MO_TRANSPORT(GetGUID()))
237  {
238  //((Transport*)this)->Update(p_time);
239  return;
240  }
241 
242  if (AI())
243  AI()->UpdateAI(diff);
244  else if (!AIM_Initialize())
245  sLog.outError("Could not initialize GameObjectAI");
246 
247  switch (m_lootState)
248  {
249  case GO_NOT_READY:
250  {
251  switch (GetGoType())
252  {
254  {
255  // Arming Time for GAMEOBJECT_TYPE_TRAP (6)
256  Unit* owner = GetOwner();
257  if (owner && owner->IsInCombat())
258  m_cooldownTime = time(NULL) + GetGOInfo()->trap.cooldown;
260  break;
261  }
263  {
264  // fishing code (bobber ready)
265  if (time(NULL) > m_respawnTime - FISHING_BOBBER_READY_TIME)
266  {
267  // splash bobber (bobber ready now)
268  Unit* caster = GetOwner();
269  if (caster && caster->GetTypeId() == TYPEID_PLAYER)
270  {
273 
274  UpdateData udata;
275  WorldPacket packet;
276  BuildValuesUpdateBlockForPlayer(&udata, caster->ToPlayer());
277  udata.BuildPacket(&packet);
278  caster->ToPlayer()->GetSession()->SendPacket(&packet);
279 
281  }
282 
283  m_lootState = GO_READY; // can be successfully open with some chance
284  }
285  return;
286  }
287  default:
288  m_lootState = GO_READY; // for other GOis same switched without delay to GO_READY
289  break;
290  }
291  // NO BREAK for switch (m_lootState)
292  }
293  case GO_READY:
294  {
295  if (m_respawnTime > 0) // timer on
296  {
297  if (m_respawnTime <= time(NULL)) // timer expired
298  {
299  m_respawnTime = 0;
300  m_SkillupList.clear();
301  m_usetimes = 0;
302 
303  switch (GetGoType())
304  {
305  case GAMEOBJECT_TYPE_FISHINGNODE: // can't fish now
306  {
307  Unit* caster = GetOwner();
308  if (caster && caster->GetTypeId() == TYPEID_PLAYER)
309  {
311 
313  caster->ToPlayer()->GetSession()->SendPacket(&data);
314  }
315  // can be delete
317  return;
318  }
321  //we need to open doors if they are closed (add there another condition if this code breaks some usage, but it need to be here for battlegrounds)
322  if (GetGoState() != GO_STATE_READY)
324  break;
325  default:
326  break;
327  }
328 
329  // Despawn timer
330  if (!m_spawnedByDefault)
331  {
332  // Can be despawned or destroyed
334  return;
335  }
336 
337  // Respawn timer
338  uint32 poolid = GetDBTableGUIDLow() ? sPoolMgr.IsPartOfAPool<GameObject>(GetDBTableGUIDLow()) : 0;
339  if (poolid)
340  sPoolMgr.UpdatePool<GameObject>(poolid, GetDBTableGUIDLow());
341  else
342  GetMap()->AddToMap(this);
343  }
344  }
345 
346  if (isSpawned())
347  {
348  GameObjectInfo const* goInfo = GetGOInfo();
349  if (goInfo->type == GAMEOBJECT_TYPE_TRAP)
350  {
351  if (m_cooldownTime >= time(NULL))
352  break;
353 
354  // traps
355  Unit* owner = GetOwner();
356  Unit* ok = NULL; // pointer to appropriate target if found any
357 
358  bool IsBattlegroundTrap = false;
359  //FIXME: this is activation radius (in different casting radius that must be selected from spell data)
360  //@todo move activated state code (cast itself) to GO_ACTIVATED, in this place only check activating and set state
361  float radius = (float)(goInfo->trap.radius) / 2; // TODO rename radius to diameter (goInfo->trap.radius) should be (goInfo->trap.diameter)
362  if (!radius)
363  {
364  if (goInfo->trap.cooldown != 3) // cast in other case (at some triggering/linked go/etc explicit call)
365  {
366  // try to read radius from trap spell
367  if (const SpellEntry* spellEntry = sSpellStore.LookupEntry(goInfo->trap.spellId))
368  radius = GetSpellRadius(spellEntry, 0, false);
369  // radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(spellEntry->EffectRadiusIndex[0]));
370 
371  if (!radius)
372  break;
373  }
374  else
375  {
376  if (m_respawnTime > 0)
377  break;
378 
379  radius = goInfo->trap.cooldown; // battlegrounds gameobjects has data2 == 0 && data5 == 3
380  IsBattlegroundTrap = true;
381  }
382  }
383 
385  if (owner)
386  {
387  // Hunter trap: Search units which are unfriendly to the trap's owner
388  Oregon::AnyUnfriendlyNoTotemUnitInObjectRangeCheck checker(this, owner, radius);
390  VisitNearbyGridObject(radius, searcher);
391  if (!ok)
392  VisitNearbyWorldObject(radius, searcher);
393  }
394  else
395  {
396  // Environmental trap: Any player
397  Player* player = NULL;
398  Oregon::AnyPlayerInObjectRangeCheck checker(this, radius);
399  Oregon::PlayerSearcher<Oregon::AnyPlayerInObjectRangeCheck> searcher(this, player, checker);
400  VisitNearbyWorldObject(radius, searcher);
401  ok = player;
402  }
403 
404  if (ok)
405  {
406  // some traps do not have spell but should be triggered
407  if (goInfo->trap.spellId)
408  CastSpell(ok, goInfo->trap.spellId);
409 
410  m_cooldownTime = time(NULL) + (goInfo->trap.cooldown ? goInfo->trap.cooldown : uint32(4));
411 
412  if (goInfo->trap.type == 1)
414 
415  if (IsBattlegroundTrap && ok->GetTypeId() == TYPEID_PLAYER)
416  {
417  //Battleground gameobjects case
418  if (ok->ToPlayer()->InBattleground())
419  if (Battleground* bg = ok->ToPlayer()->GetBattleground())
420  bg->HandleTriggerBuff(GetGUID());
421  }
422  }
423  }
424  else if (uint32 max_charges = goInfo->GetCharges())
425  {
426  if (m_usetimes >= max_charges)
427  {
428  m_usetimes = 0;
429  SetLootState(GO_JUST_DEACTIVATED); // can be despawned or destroyed
430  }
431  }
432  }
433 
434  break;
435  }
436  case GO_ACTIVATED:
437  {
438  switch (GetGoType())
439  {
442  if (GetGOInfo()->GetAutoCloseTime() && (m_cooldownTime < time(NULL)))
444  break;
446  if (m_cooldownTime < time(NULL))
447  {
449 
451  m_cooldownTime = 0;
452  }
453  break;
456  {
457  if (diff <= m_groupLootTimer)
458  m_groupLootTimer -= diff;
459  else
460  {
461  Group* group = sObjectMgr.GetGroupByLeader(lootingGroupLeaderGUID);
462  if (group)
463  group->EndRoll();
464  m_groupLootTimer = 0;
466  }
467  }
468  break;
469  default:
470  break;
471  }
472  break;
473  }
474  case GO_JUST_DEACTIVATED:
475  {
476  //if Gameobject should cast spell, then this, but some GOs (type = 10) should be destroyed
478  {
479  uint32 spellId = GetGOInfo()->goober.spellId;
480 
481  if (spellId)
482  {
483  for (std::set<uint64>::const_iterator it = m_unique_users.begin(); it != m_unique_users.end(); ++it)
484  // m_unique_users can contain only player GUIDs
485  if (Player* owner = ObjectAccessor::GetPlayer(*this, *it))
486  owner->CastSpell(owner, spellId, false);
487 
488  m_unique_users.clear();
489  m_usetimes = 0;
490  }
491 
493 
494  //any return here in case battleground traps
495  if (GetGOInfo()->flags & GO_FLAG_NODESPAWN)
496  return;
497  }
498 
499  loot.clear();
500 
503  if (GetSpellId() || GetOwnerGUID())
504  {
505  //Don't delete spell spawned chests, which are not consumed on loot
506  if (m_respawnTime > 0 && GetGoType() == GAMEOBJECT_TYPE_CHEST && !GetGOInfo()->IsDespawnAtAction())
507  {
510  }
511  else
512  {
513  SetRespawnTime(0);
514  Delete();
515  }
516  return;
517  }
518 
520 
521  //burning flags in some battlegrounds, if you find better condition, just add it
522  if (GetGOInfo()->IsDespawnAtAction() || GetGoAnimProgress() > 0)
523  {
525  //reset flags
526  if (GetMap()->Instanceable())
527  {
528  // In Instances GO_FLAG_LOCKED, GO_FLAG_INTERACT_COND or GO_FLAG_NO_INTERACT are not changed
530  SetUInt32Value(GAMEOBJECT_FLAGS, (GetGOInfo()->flags & ~(GO_FLAG_LOCKED | GO_FLAG_INTERACT_COND | GO_FLAG_NOT_SELECTABLE)) | currentLockOrInteractFlags);
531  }
532  else
534  }
535 
536  if (!m_respawnDelayTime)
537  return;
538 
539  if (!m_spawnedByDefault)
540  {
541  m_respawnTime = 0;
542  Delete();
543  return;
544  }
545 
546  m_respawnTime = time(NULL) + m_respawnDelayTime;
547 
548  // if option not set then object will be saved at grid unload
550  SaveRespawnTime();
551 
553 
554  break;
555  }
556  }
557 }
558 
560 {
561  // not refresh despawned not casted GO (despawned casted GO destroyed in all cases anyway)
563  return;
564 
565  if (isSpawned())
566  GetMap()->AddToMap(this);
567 }
568 
570 {
571  if (m_unique_users.find(player->GetGUIDLow()) != m_unique_users.end())
572  return;
573  AddUse();
574  m_unique_users.insert(player->GetGUID());
575 }
576 
578 {
580 
582 
585 
586  uint32 poolid = GetDBTableGUIDLow() ? sPoolMgr.IsPartOfAPool<GameObject>(GetDBTableGUIDLow()) : 0;
587  if (poolid)
588  sPoolMgr.UpdatePool<GameObject>(poolid, GetDBTableGUIDLow());
589  else
591 }
592 
593 void GameObject::getFishLoot(Loot* fishloot, Player* loot_owner)
594 {
595  fishloot->clear();
596 
597  uint32 subzone = GetAreaId();
598 
599  // if subzone loot exist use it
600  if (LootTemplates_Fishing.HaveLootFor(subzone))
601  fishloot->FillLoot(subzone, LootTemplates_Fishing, loot_owner, true);
602  // else use zone loot
603  else
604  fishloot->FillLoot(GetZoneId(), LootTemplates_Fishing, loot_owner, true);
605 }
606 
608 {
609  // this should only be used when the gameobject has already been loaded
610  // preferably after adding to map, because mapid may not be valid otherwise
611  GameObjectData const* data = sObjectMgr.GetGOData(m_DBTableGuid);
612  if (!data)
613  {
614  sLog.outError("GameObject::SaveToDB failed, cannot get gameobject data!");
615  return;
616  }
617 
618  SaveToDB(GetMapId(), data->spawnMask, data->phaseMask);
619 }
620 
621 void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask)
622 {
623  const GameObjectInfo* goI = GetGOInfo();
624 
625  if (!goI)
626  return;
627 
628  if (!m_DBTableGuid)
630  // update in loaded data (changing data only in this place)
631  GameObjectData& data = sObjectMgr.NewGOData(m_DBTableGuid);
632 
633  // data->guid = guid don't must be update at save
634  data.id = GetEntry();
635  data.mapid = mapid;
636  data.zoneId = GetZoneId();
637  data.areaId = GetAreaId();
638  data.spawnMask = spawnMask;
639  data.phaseMask = phaseMask;
650  data.go_state = GetGoState();
651 
652  // updated in DB
653  std::ostringstream ss;
654  ss << "INSERT INTO gameobject VALUES ("
655  << m_DBTableGuid << ", "
657  << mapid << ", "
658  << (uint32)GetZoneId() << ", "
659  << (uint32)GetAreaId() << ", "
660  << (uint32)spawnMask << ", "
661  << (uint32)phaseMask << ", "
662  << GetFloatValue(GAMEOBJECT_POS_X) << ", "
663  << GetFloatValue(GAMEOBJECT_POS_Y) << ", "
664  << GetFloatValue(GAMEOBJECT_POS_Z) << ", "
665  << GetFloatValue(GAMEOBJECT_FACING) << ", "
667  << GetFloatValue(GAMEOBJECT_ROTATION + 1) << ", "
668  << GetFloatValue(GAMEOBJECT_ROTATION + 2) << ", "
669  << GetFloatValue(GAMEOBJECT_ROTATION + 3) << ", "
670  << m_respawnDelayTime << ", "
671  << uint32(GetGoAnimProgress()) << ", "
672  << uint32(GetGoState()) << ")";
673 
675  WorldDatabase.PExecuteLog("DELETE FROM gameobject WHERE guid = '%u'", m_DBTableGuid);
676  WorldDatabase.PExecuteLog("%s", ss.str().c_str());
678 }
679 
680 bool GameObject::LoadGameObjectFromDB(uint32 guid, Map* map, bool addToMap)
681 {
682  GameObjectData const* data = sObjectMgr.GetGOData(guid);
683 
684  if (!data)
685  {
686  sLog.outErrorDb("ERROR: Gameobject (GUID: %u) not found in table gameobject, can't load. ", guid);
687  return false;
688  }
689 
690  uint32 entry = data->id;
691  //uint32 map_id = data->mapid;
692  uint32 phaseMask = data->phaseMask;
693  float x = data->posX;
694  float y = data->posY;
695  float z = data->posZ;
696  float ang = data->orientation;
697 
698  float rotation0 = data->rotation0;
699  float rotation1 = data->rotation1;
700  float rotation2 = data->rotation2;
701  float rotation3 = data->rotation3;
702 
703  uint32 animprogress = data->animprogress;
704  GOState go_state = data->go_state;
705  uint32 artKit = data->artKit;
706 
707  m_DBTableGuid = guid;
708  if (map->GetInstanceId() != 0) guid = sObjectMgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT);
709 
710  if (!Create(guid, entry, map, phaseMask, x, y, z, ang, rotation0, rotation1, rotation2, rotation3, animprogress, go_state, artKit))
711  return false;
712 
713  if (data->spawntimesecs >= 0)
714  {
715  m_spawnedByDefault = true;
716 
717  if (!GetGOInfo()->GetDespawnPossibility() && !GetGOInfo()->IsDespawnAtAction())
718  {
720  m_respawnDelayTime = 0;
721  m_respawnTime = 0;
722  }
723  else
724  {
726  m_respawnTime = sObjectMgr.GetGORespawnTime(m_DBTableGuid, map->GetInstanceId());
727 
728  // ready to respawn
729  if (m_respawnTime && m_respawnTime <= time(NULL))
730  {
731  m_respawnTime = 0;
732  sObjectMgr.SaveGORespawnTime(m_DBTableGuid, GetInstanceId(), 0);
733  }
734  }
735  }
736  else
737  {
738  m_spawnedByDefault = false;
740  m_respawnTime = 0;
741  }
742 
743  m_goData = data;
744 
745  if (addToMap && !GetMap()->AddToMap(this))
746  return false;
747 
748  return true;
749 }
750 
752 {
753  sObjectMgr.SaveGORespawnTime(m_DBTableGuid, GetInstanceId(), 0);
754  sObjectMgr.DeleteGOData(m_DBTableGuid);
755  WorldDatabase.PExecuteLog("DELETE FROM gameobject WHERE guid = '%u'", m_DBTableGuid);
756  WorldDatabase.PExecuteLog("DELETE FROM game_event_gameobject WHERE guid = '%u'", m_DBTableGuid);
757 }
758 
760 {
761  return object.GetMap()->GetGameObject(guid);
762 }
763 
764 /*********************************************************/
765 /*** QUEST SYSTEM ***/
766 /*********************************************************/
767 bool GameObject::hasQuest(uint32 quest_id) const
768 {
769  QuestRelations const& qr = sObjectMgr.mGOQuestRelations;
770  for (QuestRelations::const_iterator itr = qr.lower_bound(GetEntry()); itr != qr.upper_bound(GetEntry()); ++itr)
771  {
772  if (itr->second == quest_id)
773  return true;
774  }
775  return false;
776 }
777 
779 {
780  QuestRelations const& qr = sObjectMgr.mGOQuestInvolvedRelations;
781  for (QuestRelations::const_iterator itr = qr.lower_bound(GetEntry()); itr != qr.upper_bound(GetEntry()); ++itr)
782  {
783  if (itr->second == quest_id)
784  return true;
785  }
786  return false;
787 }
788 
790 {
791  // If something is marked as a transport, don't transmit an out of range packet for it.
792  GameObjectInfo const* gInfo = GetGOInfo();
793  if (!gInfo)
794  return false;
795 
796  return gInfo->type == GAMEOBJECT_TYPE_TRANSPORT || gInfo->type == GAMEOBJECT_TYPE_MO_TRANSPORT;
797 }
798 
800 {
801  return ObjectAccessor::GetUnit(*this, GetOwnerGUID());
802 }
803 
805 {
806  if (m_goData && m_goData->dbData && m_respawnTime > time(NULL) && m_spawnedByDefault)
807  sObjectMgr.SaveGORespawnTime(m_DBTableGuid, GetInstanceId(), m_respawnTime);
808 }
809 
811 {
813  return true;
814 
815  if (GetGoType() == GAMEOBJECT_TYPE_SPELL_FOCUS && GetGOInfo()->spellFocus.serverOnly == 1)
816  return true;
817 
818  return false;
819 }
820 
822 {
824  return true;
825 
826  if (IsTransport())
827  return true;
828 
829  if (!seer)
830  return false;
831 
832  // Always seen by owner and friendly units
833  if (ObjectGuid guid = GetOwnerGUID())
834  {
835  if (seer->GetGUID() == guid)
836  return true;
837 
838  Unit* owner = GetOwner();
839  if (Unit const* unitSeer = seer->ToUnit())
840  if (owner && owner->IsFriendlyTo(unitSeer))
841  return true;
842  }
843 
844  return false;
845 }
846 
848 {
850  return true;
851 
852  // Despawned
853  if (!isSpawned())
854  return true;
855 
856  return false;
857 }
858 
860 {
862  {
863  m_respawnTime = time(NULL);
864  sObjectMgr.SaveGORespawnTime(m_DBTableGuid, GetInstanceId(), 0);
865  }
866 }
867 
869 {
870  if (pTarget->HasQuestForGO(GetEntry()))
871  return true;
872 
873  if (!sObjectMgr.IsGameObjectForQuests(GetEntry()))
874  return false;
875 
876  switch (GetGoType())
877  {
878  // scan GO chest with loot including quest items
880  {
881  if (LootTemplates_Gameobject.HaveQuestLootForPlayer(GetGOInfo()->GetLootId(), pTarget))
882  {
883  //@todo fix this hack
884  //look for battlegroundAV for some objects which are only activated after mine gots captured by own team
886  if (Battleground* bg = pTarget->GetBattleground())
887  if (bg->GetTypeID() == BATTLEGROUND_AV && !(((BattlegroundAV*)bg)->PlayerCanDoMineQuest(GetEntry(), pTarget->GetTeam())))
888  return false;
889  return true;
890  }
891  break;
892  }
894  {
895  if (GetGOInfo()->_generic.questID == -1 || pTarget->GetQuestStatus(GetGOInfo()->_generic.questID) == QUEST_STATUS_INCOMPLETE)
896  return true;
897  break;
898  }
900  {
901  if (GetGOInfo()->goober.questId == -1 || pTarget->GetQuestStatus(GetGOInfo()->goober.questId) == QUEST_STATUS_INCOMPLETE)
902  return true;
903  break;
904  }
905  default:
906  break;
907  }
908 
909  return false;
910 }
911 
913 {
914  GameObjectInfo const* trapInfo = sGOStorage.LookupEntry<GameObjectInfo>(trapEntry);
915  if (!trapInfo || trapInfo->type != GAMEOBJECT_TYPE_TRAP)
916  return;
917 
918  SpellEntry const* trapSpell = sSpellStore.LookupEntry(trapInfo->trap.spellId);
919  if (!trapSpell) // checked at load already
920  return;
921 
922  float range = GetSpellMaxRange(sSpellRangeStore.LookupEntry(trapSpell->rangeIndex));
923  if (range < CONTACT_DISTANCE)
924  range = CONTACT_DISTANCE;
925 
926  // search nearest linked GO
927  GameObject* trapGO = NULL;
928  {
929  // using original GO distance
931  Cell cell(p);
932 
933  Oregon::NearestGameObjectEntryInObjectRangeCheck go_check(*target, trapEntry, range);
935 
937  cell.Visit(p, object_checker, *GetMap(), *target, range);
938  }
939 
940  // found correct GO
941  // FIXME: when GO casting will be implemented trap must cast spell to target
942  if (trapGO)
943  target->CastSpell(target, trapSpell, true);
944 }
945 
947 {
948  GameObject* ok = NULL;
949 
951  Cell cell(p);
952  Oregon::NearestGameObjectFishingHole u_check(*this, range);
954 
956  cell.Visit(p, grid_object_checker, *GetMap(), *this, range);
957 
958  return ok;
959 }
960 
962 {
964  return;
965 
966  SwitchDoorOrButton(false);
968  m_cooldownTime = 0;
969 }
970 
971 void GameObject::UseDoorOrButton(uint32 time_to_restore, bool alternative /* = false */, Unit* user /*=NULL*/)
972 {
973  if (m_lootState != GO_READY)
974  return;
975 
976  if (!time_to_restore)
977  time_to_restore = GetGOInfo()->GetAutoCloseTime();
978 
979  SwitchDoorOrButton(true, alternative);
980  SetLootState(GO_ACTIVATED, user);
981 
982  m_cooldownTime = time_to_restore ? (time(NULL) + time_to_restore) : 0;
983 }
984 
986 {
988  GameObjectData* data = const_cast<GameObjectData*>(sObjectMgr.GetGOData(m_DBTableGuid));
989  if (data)
990  data->artKit = kit;
991 }
992 
993 void GameObject::SwitchDoorOrButton(bool activate, bool alternative /* = false */)
994 {
995  if (activate)
997  else
999 
1000  if (GetGoState() == GO_STATE_READY) //if closed -> open
1002  else //if open -> close
1004 }
1005 
1007 {
1008  // by default spell caster is user
1009  Unit* spellCaster = user;
1010  uint32 spellId = 0;
1011  bool triggered = false;
1012 
1013  if (Player* playerUser = user->ToPlayer())
1014  {
1015  if (sScriptMgr.GOHello(playerUser, this))
1016  return;
1017 
1018  if (AI()->GossipHello(playerUser))
1019  return;
1020  }
1021 
1022  // If cooldown data present in template
1023  if (uint32 cooldown = GetCooldown())
1024  {
1025  if (m_cooldownTime > sWorld.GetGameTime())
1026  return;
1027 
1028  m_cooldownTime = sWorld.GetGameTime() + cooldown;
1029  }
1030 
1031  switch (GetGoType())
1032  {
1033  case GAMEOBJECT_TYPE_DOOR: //0
1034  case GAMEOBJECT_TYPE_BUTTON: //1
1035  //doors/buttons never really despawn, only reset to default state/flags
1036  UseDoorOrButton(0, false, user);
1037 
1038  // activate script
1039  GetMap()->ScriptsStart(sGameObjectScripts, GetDBTableGUIDLow(), spellCaster, this);
1040  return;
1041 
1042  case GAMEOBJECT_TYPE_QUESTGIVER: //2
1043  {
1044  if (user->GetTypeId() != TYPEID_PLAYER)
1045  return;
1046 
1047  Player* player = user->ToPlayer();
1048 
1049  player->PrepareGossipMenu(this, GetGOInfo()->questgiver.gossipID);
1050  player->SendPreparedGossip(this);
1051  return;
1052  }
1053  //Sitting: Wooden bench, chairs enzz
1054  case GAMEOBJECT_TYPE_CHAIR: //7
1055  {
1056  GameObjectInfo const* info = GetGOInfo();
1057  if (!info)
1058  return;
1059 
1060  // a chair may have n slots. we have to calculate their positions and teleport the player to the nearest one
1061 
1062  // check if the db is sane
1063  if (info->chair.slots > 0)
1064  {
1065  float lowestDist = DEFAULT_VISIBILITY_DISTANCE;
1066 
1067  float x_lowest = GetPositionX();
1068  float y_lowest = GetPositionY();
1069 
1070  // the object orientation + 1/2 pi
1071  // every slot will be on that straight line
1072  float orthogonalOrientation = GetOrientation() + M_PI * 0.5f;
1073  // find nearest slot
1074  for (uint32 i = 0; i < info->chair.slots; i++)
1075  {
1076  // the distance between this slot and the center of the go - imagine a 1D space
1077  float relativeDistance = (info->size * i) - (info->size * (info->chair.slots - 1) / 2.0f);
1078 
1079  float x_i = GetPositionX() + relativeDistance * cos(orthogonalOrientation);
1080  float y_i = GetPositionY() + relativeDistance * sin(orthogonalOrientation);
1081 
1082  // calculate the distance between the player and this slot
1083  float thisDistance = user->GetDistance2d(x_i, y_i);
1084 
1085  /* debug code. It will spawn a npc on each slot to visualize them.
1086  Creature* helper = player->SummonCreature(14496, x_i, y_i, GetPositionZ(), GetOrientation(), TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 10000);
1087  std::ostringstream output;
1088  output << i << ": thisDist: " << thisDistance;
1089  helper->MonsterSay(output.str().c_str(), LANG_UNIVERSAL, 0);
1090  */
1091 
1092  if (thisDistance <= lowestDist)
1093  {
1094  lowestDist = thisDistance;
1095  x_lowest = x_i;
1096  y_lowest = y_i;
1097  }
1098  }
1100  }
1101  else
1102  {
1103  // fallback, will always work
1105  }
1106  user->SetStandState(UNIT_STAND_STATE_SIT_LOW_CHAIR + info->chair.height);
1107  return;
1108  }
1109  //big gun, its a spell/aura
1110  case GAMEOBJECT_TYPE_GOOBER: //10
1111  {
1112  GameObjectInfo const* info = GetGOInfo();
1113 
1114  if (user->GetTypeId() == TYPEID_PLAYER)
1115  {
1116  Player* player = user->ToPlayer();
1117 
1118  if (info->goober.pageId) // show page...
1119  {
1121  data << GetGUID();
1122  player->GetSession()->SendPacket(&data);
1123  }
1124  else if (info->goober.gossipID)
1125  {
1126  player->PrepareGossipMenu(this, info->goober.gossipID);
1127  player->SendPreparedGossip(this);
1128  }
1129 
1130  if (info->goober.eventId)
1131  GetMap()->ScriptsStart(sEventScripts, info->goober.eventId, player, this);
1132 
1133  // possible quest objective for active quests
1134  if (info->goober.questId && sObjectMgr.GetQuestTemplate(info->goober.questId))
1135  {
1136  //Quest require to be active for GO using
1137  if (player->GetQuestStatus(info->goober.questId) != QUEST_STATUS_INCOMPLETE)
1138  break;
1139  }
1140 
1141  player->CastedCreatureOrGO(info->id, GetGUID(), 0);
1142  }
1143 
1145  SetLootState(GO_ACTIVATED, user);
1146 
1147  // this appear to be ok, however others exist in addition to this that should have custom (ex: 190510, 188692, 187389)
1148  if (info->goober.customAnim)
1150  else
1152 
1153  m_cooldownTime = time(NULL) + GetGOInfo()->GetAutoCloseTime();
1154 
1155  // cast this spell later if provided
1156  spellId = info->goober.spellId;
1157 
1158  break;
1159  }
1160  case GAMEOBJECT_TYPE_CAMERA: //13
1161  {
1162  GameObjectInfo const* info = GetGOInfo();
1163  if (!info)
1164  return;
1165 
1166  if (user->GetTypeId() != TYPEID_PLAYER)
1167  return;
1168 
1169  Player* player = user->ToPlayer();
1170 
1171  if (info->camera.cinematicId)
1172  player->SendCinematicStart(info->camera.cinematicId);
1173 
1174  if (info->camera.eventID)
1175  GetMap()->ScriptsStart(sEventScripts, info->camera.eventID, player, this);
1176 
1177  if (GetEntry() == 187578)
1179 
1180  return;
1181  }
1182  //fishing bobber
1183  case GAMEOBJECT_TYPE_FISHINGNODE: //17
1184  {
1185  if (user->GetTypeId() != TYPEID_PLAYER)
1186  return;
1187 
1188  Player* player = user->ToPlayer();
1189 
1190  if (player->GetGUID() != GetOwnerGUID())
1191  return;
1192 
1193  switch (getLootState())
1194  {
1195  case GO_READY: // ready for loot
1196  {
1197  // 1) skill must be >= base_zone_skill
1198  // 2) if skill == base_zone_skill => 5% chance
1199  // 3) chance is linear dependence from (base_zone_skill-skill)
1200 
1201  uint32 subzone = GetAreaId();
1202 
1203  int32 zone_skill = sObjectMgr.GetFishingBaseSkillLevel(subzone);
1204  if (!zone_skill)
1205  zone_skill = sObjectMgr.GetFishingBaseSkillLevel(GetZoneId());
1206 
1207  //provide error, no fishable zone or area should be 0
1208  if (!zone_skill)
1209  sLog.outErrorDb("Fishable areaId %u is not properly defined in skill_fishing_base_level.", subzone);
1210 
1211  int32 skill = player->GetSkillValue(SKILL_FISHING);
1212  int32 chance = skill - zone_skill + 5;
1213  int32 roll = irand(1, 100);
1214 
1215  DEBUG_LOG("Fishing check (skill: %i zone min skill: %i chance %i roll: %i", skill, zone_skill, chance, roll);
1216 
1217  if (skill >= zone_skill && chance >= roll)
1218  {
1219  // prevent removing GO at spell cancel
1220  player->RemoveGameObject(this, false);
1221  SetOwnerGUID(player->GetGUID());
1222  SetSpellId(0); // prevent removing unintended auras at Unit::RemoveGameObject
1223 
1224  //fish caught
1225  player->UpdateFishingSkill();
1226 
1228  if (ok)
1229  {
1230  player->SendLoot(ok->GetGUID(), LOOT_FISHINGHOLE);
1232  }
1233  else
1234  player->SendLoot(GetGUID(), LOOT_FISHING);
1235  }
1236  else
1237  {
1238  // fish escaped, can be deleted now
1240 
1241  WorldPacket data(SMSG_FISH_ESCAPED, 0);
1242  player->GetSession()->SendPacket(&data);
1243  }
1244  break;
1245  }
1246  case GO_JUST_DEACTIVATED: // nothing to do, will be deleted at next update
1247  break;
1248  default:
1249  {
1251 
1253  player->GetSession()->SendPacket(&data);
1254  break;
1255  }
1256  }
1257 
1259  return;
1260  }
1261 
1263  {
1264  if (user->GetTypeId() != TYPEID_PLAYER)
1265  return;
1266 
1267  Player* player = user->ToPlayer();
1268 
1269  Unit* owner = GetOwner();
1270 
1271  GameObjectInfo const* info = GetGOInfo();
1272 
1273  Player* m_ritualOwner = NULL;
1274  if (m_ritualOwnerGUID)
1276 
1277  // ritual owner is set for GO's without owner (not summoned)
1278  if (!m_ritualOwner && !owner)
1279  {
1280  m_ritualOwnerGUID = player->GetGUID();
1281  m_ritualOwner = player;
1282  }
1283 
1284  if (owner)
1285  {
1286  if (owner->GetTypeId() != TYPEID_PLAYER)
1287  return;
1288 
1289  // accept only use by player from same group as owner, excluding owner itself (unique use already added in spell effect)
1290  if (player == owner->ToPlayer() || (info->summoningRitual.castersGrouped && !player->IsInSameRaidWith(owner->ToPlayer())))
1291  return;
1292 
1293  // expect owner to already be channeling, so if not...
1295  return;
1296 
1297  // in case summoning ritual caster is GO creator
1298  spellCaster = owner;
1299  }
1300  else
1301  {
1302  if (player != m_ritualOwner && (info->summoningRitual.castersGrouped && !player->IsInSameRaidWith(m_ritualOwner)))
1303  return;
1304 
1305  spellCaster = player;
1306  }
1307 
1308  AddUniqueUse(player);
1309 
1310  if (info->summoningRitual.animSpell)
1311  {
1312  player->CastSpell(player, info->summoningRitual.animSpell, false);
1313 
1314  // for this case, summoningRitual.spellId is always triggered
1315  triggered = true;
1316  }
1317 
1318  // full amount unique participants including original summoner
1319  if (GetUniqueUseCount() == info->summoningRitual.reqParticipants)
1320  {
1321  if (m_ritualOwner)
1322  spellCaster = m_ritualOwner;
1323 
1324  spellId = info->summoningRitual.spellId;
1325 
1326  // finish owners spell
1327  if (owner)
1329 
1330  // can be deleted now, if
1331  if (!info->summoningRitual.ritualPersistent)
1333  else
1334  {
1335  // reset ritual for this GO
1336  m_ritualOwnerGUID = 0;
1337  m_unique_users.clear();
1338  m_usetimes = 0;
1339  }
1340  }
1341  else
1342  return;
1343 
1344  // go to end function to spell casting
1345  break;
1346  }
1347  case GAMEOBJECT_TYPE_SPELLCASTER: //22
1348  {
1349  GameObjectInfo const* info = GetGOInfo();
1350  if (!info)
1351  return;
1352 
1353  if (info->spellcaster.partyOnly)
1354  {
1355  Unit* caster = GetOwner();
1356  if (!caster || caster->GetTypeId() != TYPEID_PLAYER)
1357  return;
1358 
1359  if (user->GetTypeId() != TYPEID_PLAYER || !user->ToPlayer()->IsInSameRaidWith(caster->ToPlayer()))
1360  return;
1361  }
1362 
1365  spellId = info->spellcaster.spellId;
1366 
1367  break;
1368  }
1369  case GAMEOBJECT_TYPE_MEETINGSTONE: //23
1370  {
1371  GameObjectInfo const* info = GetGOInfo();
1372 
1373  if (user->GetTypeId() != TYPEID_PLAYER)
1374  return;
1375 
1376  Player* player = user->ToPlayer();
1377 
1378  Player* targetPlayer = ObjectAccessor::FindPlayer(player->GetTarget());
1379 
1380  // accept only use by player from same group for caster except caster itself
1381  if (!targetPlayer || targetPlayer == player || !targetPlayer->IsInSameRaidWith(player))
1382  return;
1383 
1384  //required lvl checks!
1385  uint8 level = player->getLevel();
1386  if (level < info->meetingstone.minLevel || level > info->meetingstone.maxLevel)
1387  return;
1388  level = targetPlayer->getLevel();
1389  if (level < info->meetingstone.minLevel || level > info->meetingstone.maxLevel)
1390  return;
1391 
1392  spellId = 23598;
1393 
1394  break;
1395  }
1396 
1397  case GAMEOBJECT_TYPE_FLAGSTAND: // 24
1398  {
1399  if (user->GetTypeId() != TYPEID_PLAYER)
1400  return;
1401 
1402  Player* player = user->ToPlayer();
1403 
1404  if (player->CanUseBattlegroundObject(this))
1405  {
1406  // in battleground check
1407  Battleground* bg = player->GetBattleground();
1408  if (!bg)
1409  return;
1410 
1413  // BG flag click
1414  // AB:
1415  // 15001
1416  // 15002
1417  // 15003
1418  // 15004
1419  // 15005
1420  bg->EventPlayerClickedOnFlag(player, this);
1421  return; //we don;t need to delete flag ... it is despawned!
1422  }
1423  break;
1424  }
1425  case GAMEOBJECT_TYPE_FLAGDROP: // 26
1426  {
1427  if (user->GetTypeId() != TYPEID_PLAYER)
1428  return;
1429 
1430  Player* player = user->ToPlayer();
1431 
1432  if (player->CanUseBattlegroundObject(this))
1433  {
1434  // in battleground check
1435  Battleground* bg = player->GetBattleground();
1436  if (!bg)
1437  return;
1438 
1441  // BG flag dropped
1442  // WS:
1443  // 179785 - Silverwing Flag
1444  // 179786 - Warsong Flag
1445  // EotS:
1446  // 184142 - Netherstorm Flag
1447  GameObjectInfo const* info = GetGOInfo();
1448  if (info)
1449  {
1450  switch (info->id)
1451  {
1452  case 179785: // Silverwing Flag
1453  case 179786: // Warsong Flag
1454  if (bg->GetTypeID() == BATTLEGROUND_WS)
1455  bg->EventPlayerClickedOnFlag(player, this);
1456  break;
1457  case 184142: // Netherstorm Flag
1458  if (bg->GetTypeID() == BATTLEGROUND_EY)
1459  bg->EventPlayerClickedOnFlag(player, this);
1460  break;
1461  }
1462  }
1463  //this cause to call return, all flags must be deleted here!!
1464  spellId = 0;
1465  Delete();
1466  }
1467  break;
1468  }
1469  default:
1470  sLog.outDebug("Unknown Object Type %u", GetGoType());
1471  break;
1472  }
1473 
1474  if (!spellId)
1475  return;
1476 
1477  SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellId);
1478  if (!spellInfo)
1479  {
1480  if (user->GetTypeId() != TYPEID_PLAYER || !sOutdoorPvPMgr.HandleCustomSpell(user->ToPlayer(), spellId, this))
1481  sLog.outError("WORLD: unknown spell id %u at use action for gameobject (Entry: %u GoType: %u)", spellId, GetEntry(), GetGoType());
1482  else
1483  sLog.outDebug("WORLD: %u non-dbc spell was handled by OutdoorPvP", spellId);
1484  return;
1485  }
1486 
1487  if (Player* player = user->ToPlayer())
1488  sOutdoorPvPMgr.HandleCustomSpell(player, spellId, this);
1489 
1490  Spell* spell = new Spell(spellCaster, spellInfo, triggered);
1491 
1492  // Check cast is OK, and only add use if we are really casting the spell
1493  // to prevent taking charges on spell fail
1494  if (spell->CheckCast(true) != SPELL_CAST_OK)
1495  return;
1496 
1497  AddUse();
1498 
1499  if (spellCaster)
1500  spellCaster->CastSpell(user, spellInfo, triggered);
1501  else
1502  CastSpell(user, spellId);
1503 }
1504 
1506 {
1507  m_lootState = s;
1508 
1509  AI()->OnStateChanged(s, unit);
1510  if (m_model)
1511  {
1512  bool collision = false;
1513  // Use the current go state
1514  if ((GetGoState() != GO_STATE_READY && (s == GO_ACTIVATED || s == GO_JUST_DEACTIVATED)) || s == GO_READY)
1515  collision = !collision;
1516 
1517  EnableCollision(collision);
1518  }
1519 }
1520 
1521 void GameObject::CastSpell(Unit* target, uint32 spellId, bool triggered /*= true*/)
1522 {
1523  SpellEntry const* spellProto = sSpellStore.LookupEntry(spellId);
1524  if (!spellProto)
1525  return;
1526 
1527  bool self = false;
1528  for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
1529  {
1530  if (spellProto->EffectImplicitTargetA[i] == TARGET_UNIT_CASTER)
1531  {
1532  self = true;
1533  break;
1534  }
1535  }
1536 
1537  if (self)
1538  {
1539  if (target)
1540  target->CastSpell(target, spellProto, triggered);
1541  return;
1542  }
1543 
1544  //summon world trigger
1545  Creature* trigger = SummonTrigger(GetPositionX(), GetPositionY(), GetPositionZ(), 0, GetSpellCastTime(spellProto) + 100);
1546  if (!trigger)
1547  return;
1548 
1549  // remove immunity flags, to allow spell to target anything
1551 
1552  if (Unit* owner = GetOwner())
1553  {
1554  trigger->SetFaction(owner->GetFaction());
1555  if (owner->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE))
1557  trigger->CastSpell(target ? target : trigger, spellId, triggered, 0, 0, owner->GetGUID());
1558  }
1559  else
1560  {
1561  trigger->SetFaction(IsPositiveSpell(spellId) ? 35 : 14);
1562  // Set owner guid for target if no owner available - needed by trigger auras
1563  trigger->CastSpell(target ? target : trigger, spellProto, triggered, nullptr, nullptr, target ? target->GetGUID() : 0);
1564  }
1565 }
1566 
1567 // overwrite WorldObject function for proper name localization
1568 const char* GameObject::GetNameForLocaleIdx(int32 loc_idx) const
1569 {
1570  if (loc_idx >= 0)
1571  if (GameObjectLocale const* cl = sObjectMgr.GetGameObjectLocale(GetEntry()))
1572  if (cl->Name.size() > uint32(loc_idx) && !cl->Name[loc_idx].empty())
1573  return cl->Name[loc_idx].c_str();
1574 
1575  return GetName();
1576 }
1577 
1578 void GameObject::UpdateRotationFields(float rotation2 /*=0.0f*/, float rotation3 /*=0.0f*/)
1579 {
1580  static double const atan_pow = atan(pow(2.0f, -20.0f));
1581 
1582  double f_rot1 = std::sin(GetOrientation() / 2.0f);
1583  double f_rot2 = std::cos(GetOrientation() / 2.0f);
1584 
1585  int64 i_rot1 = int64(f_rot1 / atan_pow *(f_rot2 >= 0 ? 1.0f : -1.0f));
1586  int64 rotation = (i_rot1 << 43 >> 43) & 0x00000000001FFFFF;
1587 
1589 
1590  if (rotation2 == 0.0f && rotation3 == 0.0f)
1591  {
1592  rotation2 = sin(GetOrientation() / 2);
1593  rotation3 = cos(GetOrientation() / 2);
1594  }
1595 
1596  SetFloatValue(GAMEOBJECT_ROTATION+2, rotation2);
1597  SetFloatValue(GAMEOBJECT_ROTATION+3, rotation3);
1598 }
1599 
1600 std::string GameObject::GetAIName() const
1601 {
1602  if (m_goInfo)
1603  return m_goInfo->AIName;
1604 
1605  return "";
1606 }
1607 
1609 {
1611  if (m_model && !IsTransport())
1612  {
1613  if (!IsInWorld())
1614  return;
1615 
1616  // startOpen determines whether we are going to add or remove the LoS on activation
1617  bool collision = false;
1618  if (state == GO_STATE_READY)
1619  collision = !collision;
1620 
1621  EnableCollision(collision);
1622  }
1623 }
1624 
1626 {
1627  switch (GetGoType())
1628  {
1630  // gameobjects like guildbanks and mailboxes - 10.0 is a just an abitrary choosen number
1633  return 10.0f;
1636  return 20.0f + CONTACT_DISTANCE; // max spell range
1637  default:
1638  return INTERACTION_DISTANCE;
1639  }
1640 }
1641 
1643 {
1644  if (!m_model)
1645  return;
1646 
1647  if (GetMap()->Contains(*m_model))
1648  {
1649  GetMap()->Remove(*m_model);
1650  m_model->Relocate(*this);
1651  GetMap()->Insert(*m_model);
1652  }
1653 }
1654 
1656 {
1658  UpdateModel();
1659 }
1660 
1661 void GameObject::SetPhaseMask(uint32 newPhaseMask, bool update)
1662 {
1663  WorldObject::SetPhaseMask(newPhaseMask, update);
1664 }
1665 
1667 {
1668  if (!m_model)
1669  return;
1670 
1671  m_model->enable(enable);
1672 }
1673 
1675 {
1676  if (!IsInWorld())
1677  return;
1678  if (m_model)
1679  if (GetMap()->Contains(*m_model))
1680  GetMap()->Remove(*m_model);
1681  delete m_model;
1683  if (m_model)
1684  GetMap()->Insert(*m_model);
1685 }
void SendLoot(uint64 guid, LootType loot_type)
Definition: Player.cpp:7292
#define INTERACTION_DISTANCE
Definition: Object.h:35
#define MAX_GAMEOBJECT_TYPE
GameobjectTypes
struct GameObjectInfo::@59::@80 meetingstone
bool BuildPacket(WorldPacket *packet, bool hasTransport=false)
Definition: UpdateData.cpp:103
void CastedCreatureOrGO(uint32 entry, uint64 guid, uint32 spell_id)
Definition: Player.cpp:13919
uint32 GetCooldown() const
Definition: GameObject.h:819
uint32 questId
Definition: GameObject.h:96
struct GameObjectInfo::@59::@73 camera
struct GameObjectInfo::@59::@66 trap
LootState m_lootState
Definition: GameObject.h:865
bool AddToMap(T *)
Definition: Map.cpp:424
void UpdateModel()
GameObjectAI * AI() const
Definition: GameObject.h:857
void SwitchDoorOrButton(bool activate, bool alternative=false)
Definition: GameObject.cpp:993
GameObjectInfo const * m_goInfo
Definition: GameObject.h:876
bool AIM_Initialize()
Definition: GameObject.cpp:76
struct GameObjectInfo::@59::@76 summoningRitual
const char * GetNameForLocaleIdx(int32 locale_idx) const override
bool IsLargeGameObject() const
Definition: GameObject.h:507
const uint32 & GetUInt32Value(uint16 index) const
Definition: Object.h:210
virtual bool IsNeverVisible() const
Definition: Object.h:792
Unit * GetOwner() const
Definition: GameObject.cpp:799
QuestStatus GetQuestStatus(uint32 quest_id) const
Definition: Player.cpp:13635
virtual void SetPhaseMask(uint32 newPhaseMask, bool update)
Definition: Object.cpp:2587
void ResetDoorOrButton()
Definition: GameObject.cpp:961
#define GUID_LOPART(x)
Definition: ObjectGuid.h:110
void SetStandState(uint8 state)
Definition: Unit.cpp:11986
virtual void OnStateChanged(uint32, Unit *)
Definition: GameObjectAI.h:54
Battleground * GetBattleground() const
Definition: Player.cpp:19415
void ScriptsStart(std::map< uint32, std::multimap< uint32, ScriptInfo > > const &scripts, uint32 id, Object *source, Object *target)
Definition: MapScripts.cpp:33
GOState GetGoState() const
Definition: GameObject.h:745
uint32 * m_uint32Values
Definition: Object.h:408
#define sOutdoorPvPMgr
Definition: OutdoorPvPMgr.h:79
LootState
Definition: GameObject.h:580
LootState getLootState() const
Definition: GameObject.h:765
Map * GetMap() const
Definition: Object.h:817
DatabaseType WorldDatabase
Accessor to the world database.
Definition: Main.cpp:53
void SendObjectCustomAnim(uint64 guid, uint32 anim=0)
Definition: Object.cpp:1973
int32 spawntimesecs
Definition: GameObject.h:568
uint32 m_usetimes
Definition: GameObject.h:873
bool BeginTransaction()
Definition: Database.cpp:533
unsupported by client, sending LOOT_FISHING instead
Definition: LootMgr.h:67
bool UpdateFishingSkill()
Definition: Player.cpp:5140
uint32 m_respawnDelayTime
Definition: GameObject.h:864
uint32 serverOnly
Definition: GameObject.h:111
void SetGoType(GameobjectTypes type)
Definition: GameObject.h:741
void BuildValuesUpdateBlockForPlayer(UpdateData *data, Player *target) const
Definition: Object.cpp:218
uint32 questID
Definition: GameObject.h:114
void SetObjectScale(float scale)
Definition: Object.h:190
uint64 GetOwnerGUID() const
Definition: GameObject.h:681
void TriggeringLinkedGameObject(uint32 trapEntry, Unit *target)
Definition: GameObject.cpp:912
void getFishLoot(Loot *loot, Player *loot_owner)
Definition: GameObject.cpp:593
uint64 lootingGroupLeaderGUID
Definition: Object.h:888
LootStore LootTemplates_Gameobject("gameobject_loot_template","gameobject entry")
uint32 GetZoneId() const
Definition: Object.cpp:1202
bool IsInCombat() const
Definition: Unit.h:1243
bool HasQuestForGO(int32 GOId)
Definition: Player.cpp:19515
void DeleteFromDB()
Definition: GameObject.cpp:751
GameObjectAI * m_AI
Definition: GameObject.h:884
virtual void SetMap(Map *map)
Definition: Object.cpp:1981
int32 irand(int32 min, int32 max)
Definition: Util.cpp:28
void AddObject(T *object)
#define sLog
Log class singleton.
Definition: Log.h:187
void Remove(const GameObjectModel &mdl)
Definition: Map.h:533
uint32 gossipID
Definition: GameObject.h:77
void SetUInt32Value(uint16 index, uint32 value)
Definition: Object.cpp:777
ACE_INT32 int32
Definition: Define.h:67
uint32 displayId
Definition: GameObject.h:40
NULL Dbg ErrDB Arena Chat Char Map MMap false
Definition: Log.cpp:556
struct GameObjectInfo::@59::@65 _generic
void AddToWorld() override
Definition: GameObject.cpp:117
void Refresh()
Definition: GameObject.cpp:559
uint32 GetSpellCastTime(SpellEntry const *spellInfo, Spell const *spell)
Definition: SpellMgr.cpp:248
bool Relocate(GameObject const &go)
void SetRespawnTime(int32 respawn)
Definition: GameObject.h:710
uint32 GetGUIDLow() const
Definition: Object.h:178
void Respawn()
Definition: GameObject.cpp:859
GameObjectData const * m_goData
Definition: GameObject.h:877
std::string GetAIName() const
void SetFlag(uint16 index, uint32 newFlag)
Definition: Object.cpp:983
static Player * GetPlayer(WorldObject const &, uint64 guid)
void clear()
Definition: LootMgr.h:327
float orientation
Definition: GameObject.h:563
uint16 m_objectType
Definition: Object.h:400
bool ActivateToQuest(Player *pTarget) const
Definition: GameObject.cpp:868
#define sObjectMgr
Definition: ObjectMgr.h:1317
void SendPacket(WorldPacket const *packet)
static GameObject * GetGameObject(WorldObject &object, uint64 guid)
Definition: GameObject.cpp:759
bool CommitTransaction()
Definition: Database.cpp:551
void RemoveFromWorld() override
Definition: GameObject.cpp:141
DBCStorage< SpellEntry > sSpellStore(SpellEntryfmt)
#define IS_PET_GUID(Guid)
Definition: ObjectGuid.h:67
time_t m_cooldownTime
Definition: GameObject.h:867
bool PExecuteLog(const char *format,...) ATTR_PRINTF(2
Definition: Database.cpp:221
char const * AIName
Definition: GameObject.h:366
uint32 rangeIndex
Definition: DBCStructure.h:714
void VisitNearbyGridObject(float const &radius, NOTIFIER &notifier) const
Definition: Object.h:885
Player * ToPlayer()
Definition: Object.h:368
float GetDistance2d(const WorldObject *obj) const
Definition: Object.h:709
uint8 getLevel() const
Definition: Unit.h:1057
virtual void UpdateAI(uint32)
Definition: GameObjectAI.h:36
void FillLoot(uint32 loot_id, LootStore const &store, Player *loot_owner, bool personal)
Definition: LootMgr.cpp:375
virtual bool IsInvisibleDueToDespawn() const
Definition: Object.h:794
uint8 m_objectTypeId
Definition: Object.h:402
uint32 GetId(void) const
Definition: Map.h:333
uint64 GetGUID() const
Definition: Object.h:177
uint32 GetGoAnimProgress() const
Definition: GameObject.h:754
bool HaveQuestLootForPlayer(uint32 loot_id, Player *player) const
Definition: LootMgr.cpp:160
#define IS_PLAYER_GUID(Guid)
Definition: ObjectGuid.h:69
void PrepareGossipMenu(WorldObject *source, uint32 menuId=0, bool showQuests=false)
Definition: Player.cpp:12111
void SetLootState(LootState s, Unit *unit=NULL)
uint8 GetTypeId() const
Definition: Object.h:192
void _Create(uint32 guidlow, uint32 entry, HighGuid guidhigh)
Definition: Object.cpp:125
void SetDisplayId(uint32 displayid)
time_t m_respawnTime
Definition: GameObject.h:863
ACE_UINT8 uint8
Definition: Define.h:73
GameObjectModel * m_model
Definition: GameObject.h:880
float GetOrientation() const
Definition: Position.h:100
void Relocate(float x, float y)
Definition: Position.h:65
virtual bool IsAlwaysVisibleFor(WorldObject const *) const
Definition: Object.h:793
uint64 GetTarget() const
Definition: Unit.h:1590
bool CanUseBattlegroundObject(GameObject *gameobject)
Definition: Player.cpp:20489
virtual bool GossipHello(Player *)
Definition: GameObjectAI.h:44
void Insert(const GameObjectModel &mdl)
Definition: Map.h:534
const bool & IsInWorld() const
Definition: Object.h:150
std::multimap< uint32, uint32 > QuestRelations
Definition: ObjectMgr.h:391
uint32 GetCharges() const
Definition: GameObject.h:380
#define FISHING_BOBBER_READY_TIME
Definition: GameObject.h:594
#define sPoolMgr
Definition: PoolMgr.h:162
ZoneScript * m_zoneScript
Definition: Object.h:897
void AddObjectToRemoveList()
Definition: Object.cpp:2017
void SendPreparedGossip(WorldObject *source)
Definition: Player.cpp:12264
void NearTeleportTo(float x, float y, float z, float orientation, bool casting=false)
Definition: Unit.cpp:12638
void SendCinematicStart(uint32 CinematicSequenceId)
Definition: Player.cpp:5722
Definition: LootMgr.h:290
uint64 m_ritualOwnerGUID
Definition: GameObject.h:871
void RemoveAurasByType(AuraType auraType, uint64 casterGUID=0, Aura *except=NULL, bool negative=true, bool positive=true)
Definition: Unit.cpp:4426
float GetPositionY() const
Definition: Position.h:98
uint8 m_updateFlag
Definition: Object.h:403
float GetInteractionDistance() const
bool IsAlwaysVisibleFor(WorldObject const *seer) const override
Definition: GameObject.cpp:821
void CastSpell(Unit *Victim, uint32 spellId, bool triggered, Item *castItem=NULL, Aura *triggeredByAura=NULL, uint64 originalCaster=0)
Definition: Unit.cpp:1260
virtual void RemoveFromWorld() override
Definition: Object.cpp:1192
uint32 m_DBTableGuid
Definition: GameObject.h:875
static Player * FindPlayer(uint64, bool force=false)
uint32 GetInstanceId() const
Definition: Object.h:664
Spell * GetCurrentSpell(CurrentSpellTypes spellType) const
Definition: Unit.h:1593
float GetPositionZ() const
Definition: Position.h:99
bool IsNeverVisible() const override
Definition: GameObject.cpp:810
uint16 GetSkillValue(uint32 skill) const
Definition: Player.cpp:5480
virtual void EventPlayerClickedOnFlag(Player *, GameObject *)
Definition: Battleground.h:654
bool IsFriendlyTo(Unit const *unit) const
Definition: Unit.cpp:7374
uint32 EffectImplicitTargetA[MAX_SPELL_EFFECTS]
Definition: DBCStructure.h:731
Transport * ToTransport()
Definition: GameObject.h:847
bool IsTransport() const
Definition: GameObject.cpp:789
#define DEBUG_LOG(...)
Definition: Log.h:194
void EnableCollision(bool enable)
void UpdateModelPosition()
uint32 GetMapId() const
Definition: Object.h:567
uint32 GetAutoCloseTime() const
Definition: GameObject.h:391
uint32 GetAreaId() const
Definition: Object.cpp:1207
Definition: Map.h:266
void SetGoAnimProgress(uint32 animprogress)
Definition: GameObject.h:758
std::set< uint64 > m_unique_users
Definition: GameObject.h:872
bool HaveLootFor(uint32 loot_id) const
Definition: LootMgr.h:184
bool IsPositiveSpell(uint32 spellId)
Definition: SpellMgr.cpp:773
CellCoord ComputeCellCoord(float x, float y)
Definition: GridDefines.h:167
void UseDoorOrButton(uint32 time_to_restore=0, bool alternative=false, Unit *user=NULL)
Definition: GameObject.cpp:971
const char * GetName() const
Definition: Object.h:680
void Use(Unit *user)
void RemoveObject(T *object)
GOState
Definition: GameObject.h:542
void SetGoState(GOState state)
void RemoveFlag(uint16 index, uint32 oldFlag)
Definition: Object.cpp:1004
ACE_UINT64 uint64
Definition: Define.h:70
Definition: Cell.h:46
bool IsInSameRaidWith(Player const *p) const
Definition: Player.h:1805
T const * LookupEntry(uint32 id) const
Definition: SQLStorage.h:52
float GetSpellRadius(SpellEntry const *spellInfo, uint32 effectIdx, bool positive)
Definition: SpellMgr.h:176
bool InBattleground() const
Definition: Player.h:2195
virtual void AddToWorld()
Definition: Object.h:154
bool isSpawned() const
Definition: GameObject.h:716
LootStore LootTemplates_Fishing("fishing_loot_template","area id")
ScriptMapMap sGameObjectScripts
Definition: ObjectMgr.cpp:51
SpellCastResult CheckCast(bool strict)
Definition: Spell.cpp:3735
void RemoveGameObject(GameObject *gameObj, bool del)
Definition: Unit.cpp:4760
#define IS_MO_TRANSPORT(Guid)
Definition: ObjectGuid.h:75
uint32 GetTypeID() const
Definition: Battleground.h:305
void SetPhaseMask(uint32 newPhaseMask, bool update) override
bool m_spawnedByDefault
Definition: GameObject.h:866
GameobjectTypes GetGoType() const
Definition: GameObject.h:737
virtual void InitializeAI()
Definition: GameObjectAI.h:38
void SetOwnerGUID(uint64 owner)
Definition: GameObject.h:673
void AddUniqueUse(Player *player)
Definition: GameObject.cpp:569
void SendObjectDeSpawnAnim(uint64 guid)
Definition: Object.cpp:1966
uint32 m_spellId
Definition: GameObject.h:862
void EndRoll()
Definition: Group.cpp:761
ScriptMapMap sEventScripts
Definition: ObjectMgr.cpp:52
void AddUse()
Definition: GameObject.h:787
void CastSpell(Unit *target, uint32 spellId, bool triggered=true)
ACE_INT64 int64
Definition: Define.h:66
virtual void UpdateObjectVisibility(bool forced=true)
Definition: Object.cpp:2650
void SetZoneScript()
Definition: Object.cpp:2129
void SetFaction(uint32 faction)
Definition: Unit.h:1117
GameObjectInfo const * GetGOInfo() const
Definition: GameObject.h:609
~GameObject() override
Definition: GameObject.cpp:70
uint32 animprogress
Definition: GameObject.h:569
void SetSpellId(uint32 id)
Definition: GameObject.h:687
Creature * SummonTrigger(float x, float y, float z, float ang, uint32 dur, CreatureAI *(*GetAI)(Creature *)=NULL)
Definition: Object.cpp:2280
void SetFloatValue(uint16 index, float value)
Definition: Object.cpp:857
void SaveRespawnTime() override
Definition: GameObject.cpp:804
uint16 m_valuesCount
Definition: Object.h:414
bool Create(uint32 guidlow, uint32 name_id, Map *map, uint32 phaseMask, 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
void Update(uint32 diff) override
Definition: GameObject.cpp:234
uint32 GetTeam() const
Definition: Player.h:2066
struct GameObjectInfo::@59::@79 spellcaster
uint32 flags
Definition: GameObject.h:44
void FinishSpell(CurrentSpellTypes spellType, bool ok=true)
Definition: Unit.cpp:3566
#define ASSERT
Definition: Errors.h:29
GameObjectAI * SelectGameObjectAI(GameObject *go)
#define MAX_SPELL_EFFECTS
Definition: DBCStructure.h:670
std::list< uint32 > m_SkillupList
Definition: GameObject.h:869
#define sScriptMgr
Definition: Group.h:526
bool hasInvolvedQuest(uint32 quest_id) const override
Definition: GameObject.cpp:778
static Unit * GetUnit(WorldObject const &, uint64 guid)
uint32 GetUniqueUseCount() const
Definition: GameObject.h:796
bool IsInvisibleDueToDespawn() const override
Definition: GameObject.cpp:847
uint32 GetSpellId() const
Definition: GameObject.h:692
uint32 GetEntry() const
Definition: Object.h:186
bool IsPositionValid() const
Definition: Position.cpp:40
WorldSession * GetSession() const
Definition: Player.h:1947
uint32 GetDBTableGUIDLow() const
Definition: GameObject.h:624
bool hasQuest(uint32 quest_id) const override
Definition: GameObject.cpp:767
#define sWorld
Definition: World.h:860
void SetVisibilityDistanceOverride(VisibilityDistanceType type)
Definition: Object.cpp:1155
#define CONTACT_DISTANCE
Definition: Object.h:34
SQLStorage sGOStorage
ACE_UINT32 uint32
Definition: Define.h:71
float GetPositionX() const
Definition: Position.h:97
static GameObjectModel * Create(const GameObject &go)
uint32 faction
Definition: GameObject.h:43
GameObject * GetGameObject(uint64 guid)
Definition: Map.cpp:2636
void SaveToDB()
Definition: GameObject.cpp:607
struct GameObjectInfo::@59::@70 goober
Definition: Unit.h:908
void CleanupsBeforeDelete() override
Definition: GameObject.cpp:89
uint32 phaseMask
Definition: GameObject.h:557
Definition: Player.h:923
uint32 GetInstanceId() const
Definition: Map.h:390
uint32 m_groupLootTimer
Definition: Object.h:887
void Visit(CellCoord const &, TypeContainerVisitor< T, CONTAINER > &visitor, Map &, WorldObject const &, float) const
Definition: CellImpl.h:121
void SetGoArtKit(uint32 artkit)
Definition: GameObject.cpp:985
DBCStorage< SpellRangeEntry > sSpellRangeStore(SpellRangefmt)
struct GameObjectInfo::@59::@67 chair
void enable(bool enable)
Unit * ToUnit()
Definition: Object.h:374
GameObject * LookupFishingHoleAround(float range)
Definition: GameObject.cpp:946
void VisitNearbyWorldObject(const float &radius, NOTIFIER &notifier) const
Definition: Object.h:883
GOState go_state
Definition: GameObject.h:570
Definition: Group.h:154
bool LoadGameObjectFromDB(uint32 guid, Map *map, bool addToMap=true)
Definition: GameObject.cpp:680
void UpdateRotationFields(float rotation2=0.0f, float rotation3=0.0f)
virtual void OnGameObjectCreate(GameObject *, bool)
Definition: ZoneScript.h:45
void Delete()
Definition: GameObject.cpp:577
#define DEFAULT_VISIBILITY_DISTANCE
Definition: Object.h:45
float GetSpellMaxRange(SpellRangeEntry const *range)
Definition: SpellMgr.h:143
const float & GetFloatValue(uint16 index) const
Definition: Object.h:222
Definition: Spell.h:249