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