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