TrinityCore
Loading...
Searching...
No Matches
GameObject.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore 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 "GameObject.h"
19#include "Battleground.h"
20#include "CellImpl.h"
21#include "Containers.h"
22#include "CreatureAISelector.h"
23#include "DatabaseEnv.h"
24#include "GameObjectAI.h"
25#include "GameObjectModel.h"
26#include "GameTime.h"
27#include "GossipDef.h"
28#include "GridNotifiersImpl.h"
29#include "Group.h"
30#include "GroupMgr.h"
31#include "Log.h"
32#include "LootMgr.h"
33#include "Map.h"
34#include "MapManager.h"
35#include "ObjectAccessor.h"
36#include "ObjectMgr.h"
37#include "OutdoorPvPMgr.h"
38#include "PoolMgr.h"
39#include "QueryPackets.h"
40#include "ScriptMgr.h"
41#include "SpellMgr.h"
42#include "Transport.h"
43#include "UpdateFieldFlags.h"
44#include "World.h"
45#include <G3D/Box.h>
46#include <G3D/CoordinateFrame.h>
47#include <G3D/Quat.h>
48
50{
51 for (uint8 loc = LOCALE_enUS; loc < TOTAL_LOCALES; ++loc)
52 QueryData[loc] = BuildQueryData(static_cast<LocaleConstant>(loc));
53}
54
56{
58
59 std::string locName = name;
60 std::string locIconName = IconName;
61 std::string locCastBarCaption = castBarCaption;
62
63 if (GameObjectLocale const* gameObjectLocale = sObjectMgr->GetGameObjectLocale(entry))
64 {
65 ObjectMgr::GetLocaleString(gameObjectLocale->Name, loc, locName);
66 ObjectMgr::GetLocaleString(gameObjectLocale->CastBarCaption, loc, locCastBarCaption);
67 }
68
69 queryTemp.GameObjectID = entry;
70 queryTemp.Allow = true;
71
72 queryTemp.Stats.Type = type;
73 queryTemp.Stats.DisplayID = displayId;
74 queryTemp.Stats.Name = locName;
75 queryTemp.Stats.IconName = locIconName;
76 queryTemp.Stats.CastBarCaption = locCastBarCaption;
77 queryTemp.Stats.UnkString = unk1;
78 memcpy(queryTemp.Stats.Data, raw.data, sizeof(uint32) * MAX_GAMEOBJECT_DATA);
79 queryTemp.Stats.Size = size;
80
81 for (uint32 i = 0; i < MAX_GAMEOBJECT_QUEST_ITEMS; ++i)
82 queryTemp.Stats.QuestItems[i] = 0;
83
84 if (std::vector<uint32> const* items = sObjectMgr->GetGameObjectQuestItemList(entry))
85 for (uint32 i = 0; i < MAX_GAMEOBJECT_QUEST_ITEMS; ++i)
86 if (i < items->size())
87 queryTemp.Stats.QuestItems[i] = (*items)[i];
88
89 queryTemp.Write();
90 queryTemp.ShrinkToFit();
91 return queryTemp.Move();
92}
93
95{
96 return fabs(x * x + y * y + z * z + w * w - 1.0f) < 1e-5f;
97}
98
99void QuaternionData::toEulerAnglesZYX(float& Z, float& Y, float& X) const
100{
101 G3D::Matrix3(G3D::Quat(x, y, z, w)).toEulerAnglesZYX(Z, Y, X);
102}
103
105{
106 G3D::Quat quat(G3D::Matrix3::fromEulerAnglesZYX(Z, Y, X));
107 return QuaternionData(quat.x, quat.y, quat.z, quat.w);
108}
109
111 m_model(nullptr), m_goValue(), m_stringIds(), m_AI(nullptr), m_respawnCompatibilityMode(false)
112{
115
117
119 m_respawnTime = 0;
120 m_respawnDelayTime = 300;
121 m_despawnDelay = 0;
123 m_restockTime = 0;
125 m_spawnedByDefault = true;
126 m_usetimes = 0;
127 m_spellId = 0;
128 m_cooldownTime = 0;
130 m_goInfo = nullptr;
131 m_goTemplateAddon = nullptr;
132 m_goData = nullptr;
134
135 m_spawnId = 0;
136
139
140 ResetLootMode(); // restore default loot mode
141 m_stationaryPosition.Relocate(0.0f, 0.0f, 0.0f, 0.0f);
142}
143
145{
146 delete m_AI;
147 delete m_model;
148 //if (m_uint32Values) // field array can be not exist if GameOBject not loaded
149 // CleanupsBeforeDelete();
150}
151
153{
154 delete m_AI;
155 m_AI = nullptr;
156}
157
159{
160 AIM_Destroy();
161
163
164 if (!m_AI)
165 return false;
166
168 return true;
169}
170
171std::string const& GameObject::GetAIName() const
172{
173 return sObjectMgr->GetGameObjectTemplate(GetEntry())->AIName;
174}
175
176void GameObject::CleanupsBeforeDelete(bool finalCleanup)
177{
179
180 if (m_uint32Values) // field array can be not exist if GameOBject not loaded
182}
183
185{
186 ObjectGuid ownerGUID = GetOwnerGUID();
187 if (!ownerGUID)
188 return;
189
190 if (Unit* owner = ObjectAccessor::GetUnit(*this, ownerGUID))
191 {
192 owner->RemoveGameObject(this, false);
194 return;
195 }
196
197 // This happens when a mage portal is despawned after the caster changes map (for example using the portal)
198 TC_LOG_DEBUG("misc", "Removed GameObject ({} Entry: {} SpellId: {} LinkedGO: {}) that just lost any reference to the owner ({}) GO list",
199 GetGUID().ToString(), GetGOInfo()->entry, m_spellId, GetGOInfo()->GetLinkedGameObjectEntry(), ownerGUID.ToString());
201}
202
204{
206 if (!IsInWorld())
207 {
208 if (m_zoneScript)
210
212 if (m_spawnId)
213 GetMap()->GetGameObjectBySpawnIdStore().insert(std::make_pair(m_spawnId, this));
214
215 // The state can be changed after GameObject::Create but before GameObject::AddToWorld
216 bool toggledState = GetGoType() == GAMEOBJECT_TYPE_CHEST ? getLootState() == GO_READY : (GetGoState() == GO_STATE_READY || IsTransport());
217 if (m_model)
218 {
219 if (Transport* trans = ToTransport())
220 trans->SetDelayedAddModelToMap();
221 else
223 }
224
225 EnableCollision(toggledState);
227 }
228}
229
231{
233 if (IsInWorld())
234 {
235 if (m_zoneScript)
237
239 if (m_model)
240 if (GetMap()->ContainsGameObjectModel(*m_model))
242
243 // If linked trap exists, despawn it
244 if (GameObject* linkedTrap = GetLinkedTrap())
245 linkedTrap->DespawnOrUnsummon();
246
248
249 if (m_spawnId)
250 Trinity::Containers::MultimapErasePair(GetMap()->GetGameObjectBySpawnIdStore(), m_spawnId, this);
252 }
253}
254
255bool GameObject::Create(ObjectGuid::LowType guidlow, uint32 name_id, Map* map, uint32 phaseMask, Position const& pos, QuaternionData const& rotation, uint32 animprogress, GOState go_state, uint32 artKit /*= 0*/, bool dynamic, ObjectGuid::LowType spawnid)
256{
257 ASSERT(map);
258 SetMap(map);
259
260 Relocate(pos);
262 if (!IsPositionValid())
263 {
264 TC_LOG_ERROR("misc", "Gameobject (GUID: {} Entry: {}) not created. Suggested coordinates isn't valid (X: {} Y: {})", guidlow, name_id, pos.GetPositionX(), pos.GetPositionY());
265 return false;
266 }
267
268 // Set if this object can handle dynamic spawns
269 if (!dynamic)
271
272 SetPhaseMask(phaseMask, false);
274
276 if (m_zoneScript)
277 {
278 name_id = m_zoneScript->GetGameObjectEntry(guidlow, name_id);
279 if (!name_id)
280 return false;
281 }
282
283 GameObjectTemplate const* goinfo = sObjectMgr->GetGameObjectTemplate(name_id);
284 if (!goinfo)
285 {
286 TC_LOG_ERROR("sql.sql", "Gameobject (GUID: {} Entry: {}) not created: non-existing entry in `gameobject_template`. Map: {} (X: {} Y: {} Z: {})", guidlow, name_id, map->GetId(), pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ());
287 return false;
288 }
289
291 {
292 TC_LOG_ERROR("sql.sql", "Gameobject (GUID: {} Entry: {}) not created: gameobject type GAMEOBJECT_TYPE_MAP_OBJ_TRANSPORT cannot be manually created.", guidlow, name_id);
293 return false;
294 }
295
296 if (goinfo->type == GAMEOBJECT_TYPE_TRANSPORT)
298
299 Object::_Create(ObjectGuid::Create<HighGuid::GameObject>(goinfo->entry, guidlow));
300
301 m_goInfo = goinfo;
302 m_goTemplateAddon = sObjectMgr->GetGameObjectTemplateAddon(name_id);
303
304 if (goinfo->type >= MAX_GAMEOBJECT_TYPE)
305 {
306 TC_LOG_ERROR("sql.sql", "Gameobject (GUID: {} Entry: {}) not created: non-existing GO type '{}' in `gameobject_template`. It will crash client if created.", guidlow, name_id, goinfo->type);
307 return false;
308 }
309
310 SetLocalRotation(rotation.x, rotation.y, rotation.z, rotation.w);
311 GameObjectAddon const* gameObjectAddon = sObjectMgr->GetGameObjectAddon(GetSpawnId());
312
313 // For most of gameobjects is (0, 0, 0, 1) quaternion, there are only some transports with not standard rotation
314 QuaternionData parentRotation;
315 if (gameObjectAddon)
316 parentRotation = gameObjectAddon->ParentRotation;
317
318 SetParentRotation(parentRotation);
319
320 SetObjectScale(goinfo->size);
321
322 if (GameObjectOverride const* goOverride = GetGameObjectOverride())
323 {
324 SetFaction(goOverride->Faction);
325 ReplaceAllFlags(GameObjectFlags(goOverride->Flags));
326 }
327
328 SetEntry(goinfo->entry);
329
330 // set name for logs usage, doesn't affect anything ingame
331 SetName(goinfo->name);
332
333 SetDisplayId(goinfo->displayId);
334
335 CreateModel();
336 // GAMEOBJECT_BYTES_1, index at 0, 1, 2 and 3
338 m_prevGoState = go_state;
339 SetGoState(go_state);
340 SetGoArtKit(artKit);
341
342 switch (goinfo->type)
343 {
345 SetGoAnimProgress(animprogress);
346 m_goValue.FishingHole.MaxOpens = urand(GetGOInfo()->fishinghole.minSuccessOpens, std::max(GetGOInfo()->fishinghole.minSuccessOpens, GetGOInfo()->fishinghole.maxSuccessOpens));
347 break;
352 break;
354 SetLevel(goinfo->transport.pause);
356 SetGoAnimProgress(animprogress);
358 m_goValue.Transport.AnimationInfo = sTransportMgr->GetTransportAnimInfo(goinfo->entry);
360 break;
363 break;
365 if (GetGOInfo()->trap.stealthed)
366 {
369 }
370
371 if (GetGOInfo()->trap.invisible)
372 {
375 }
376
378 if (SpellInfo const* trapSpell = sSpellMgr->GetSpellInfo(goinfo->trap.spellId))
379 {
380 // positive spells may require enemy targets
381 if (trapSpell->IsPositive())
382 {
383 bool targetsAlly = false;
384 bool targetsEnemy = false;
385 auto isAllyTarget = [](SpellImplicitTargetInfo const& targetInfo)
386 {
387 return targetInfo.GetObjectType() == TARGET_OBJECT_TYPE_UNIT && targetInfo.GetCheckType() == TARGET_CHECK_ALLY;
388 };
389 auto isEnemyTarget = [](SpellImplicitTargetInfo const& targetInfo)
390 {
391 return targetInfo.GetObjectType() == TARGET_OBJECT_TYPE_UNIT && targetInfo.GetCheckType() == TARGET_CHECK_ENEMY;
392 };
393 for (SpellEffectInfo const& spellEffectInfo : trapSpell->GetEffects())
394 {
395 if (!spellEffectInfo.IsEffect())
396 continue;
397
398 targetsAlly = targetsAlly || isAllyTarget(spellEffectInfo.TargetA) || isAllyTarget(spellEffectInfo.TargetB);
399 targetsEnemy = targetsEnemy || isEnemyTarget(spellEffectInfo.TargetA) || isEnemyTarget(spellEffectInfo.TargetB);
400 }
401 if (targetsAlly)
403 }
404 }
405 break;
406 default:
407 SetGoAnimProgress(animprogress);
408 break;
409 }
410
411 if (gameObjectAddon && gameObjectAddon->InvisibilityValue)
412 {
413 m_invisibility.AddFlag(gameObjectAddon->invisibilityType);
414 m_invisibility.AddValue(gameObjectAddon->invisibilityType, gameObjectAddon->InvisibilityValue);
415 }
416
418
420
422
423 // Initialize loot duplicate count depending on raid difficulty
424 if (map->Is25ManRaid())
426
427 if (spawnid)
428 m_spawnId = spawnid;
429
430 if (uint32 linkedEntry = GetGOInfo()->GetLinkedGameObjectEntry())
431 {
432 GameObject* linkedGO = new GameObject();
433 if (linkedGO->Create(map->GenerateLowGuid<HighGuid::GameObject>(), linkedEntry, map, phaseMask, pos, rotation, 255, GO_STATE_READY))
434 {
435 SetLinkedTrap(linkedGO);
436 map->AddToMap(linkedGO);
437 }
438 else
439 delete linkedGO;
440 }
441
442 // Check if GameObject is Large
443 if (goinfo->IsLargeGameObject())
445
446 // Check if GameObject is Infinite
447 if (goinfo->IsInfiniteGameObject())
449
450 return true;
451}
452
454{
456
457 if (AI())
458 AI()->UpdateAI(diff);
459 else if (!AIM_Initialize())
460 TC_LOG_ERROR("misc", "Could not initialize GameObjectAI");
461
462 if (m_despawnDelay)
463 {
464 if (m_despawnDelay > diff)
465 m_despawnDelay -= diff;
466 else
467 {
468 m_despawnDelay = 0;
470 }
471 }
472
473 switch (m_lootState)
474 {
475 case GO_NOT_READY:
476 {
477 switch (GetGoType())
478 {
480 {
481 // Arming Time for GAMEOBJECT_TYPE_TRAP (6)
482 GameObjectTemplate const* goInfo = GetGOInfo();
483 // Bombs
484 if (goInfo->trap.type == 2)
485 // Hardcoded tooltip value
487 else if (Unit* owner = GetOwner())
488 if (owner->IsInCombat())
490
492 break;
493 }
495 {
497 break;
498
499 if (GetGoState() == GO_STATE_READY)
500 {
502 /* TODO: Fix movement in unloaded grid - currently GO will just disappear
503 uint32 timer = m_goValue.Transport.PathProgress % m_goValue.Transport.AnimationInfo->TotalTime;
504 TransportAnimationEntry const* node = m_goValue.Transport.AnimationInfo->GetAnimNode(timer);
505 if (node && m_goValue.Transport.CurrentSeg != node->TimeSeg)
506 {
507 m_goValue.Transport.CurrentSeg = node->TimeSeg;
508
509 G3D::Quat rotation;
510 if (TransportRotationEntry const* rot = m_goValue.Transport.AnimationInfo->GetAnimRotation(timer))
511 rotation = G3D::Quat(rot->X, rot->Y, rot->Z, rot->W);
512
513 G3D::Vector3 pos = rotation.toRotationMatrix()
514 * G3D::Matrix3::fromEulerAnglesZYX(GetOrientation(), 0.0f, 0.0f)
515 * G3D::Vector3(node->X, node->Y, node->Z);
516
517 pos += G3D::Vector3(GetStationaryX(), GetStationaryY(), GetStationaryZ());
518
519 G3D::Vector3 src(GetPositionX(), GetPositionY(), GetPositionZ());
520
521 TC_LOG_DEBUG("misc", "Src: {} Dest: {}", src.toString(), pos.toString());
522
523 GetMap()->GameObjectRelocation(this, pos.x, pos.y, pos.z, GetOrientation());
524 }
525 */
526 }
527 break;
528 }
530 {
531 // fishing code (bobber ready)
533 {
534 // splash bobber (bobber ready now)
535 Unit* caster = GetOwner();
536 if (caster && caster->GetTypeId() == TYPEID_PLAYER)
537 {
540
541 UpdateData udata;
542 WorldPacket packet;
543 BuildValuesUpdateBlockForPlayer(&udata, caster->ToPlayer());
544 udata.BuildPacket(&packet);
545 caster->ToPlayer()->SendDirectMessage(&packet);
546
548 }
549
550 m_lootState = GO_READY; // can be successfully open with some chance
551 }
552 return;
553 }
556 return;
557 // If there is no restock timer, or if the restock timer passed, the chest becomes ready to loot
558 m_restockTime = 0;
561 break;
562 default:
563 m_lootState = GO_READY; // for other GOis same switched without delay to GO_READY
564 break;
565 }
566 [[fallthrough]];
567 }
568 case GO_READY:
569 {
571 {
572 if (m_respawnTime > 0) // timer on
573 {
574 time_t now = GameTime::GetGameTime();
575 if (m_respawnTime <= now) // timer expired
576 {
577 ObjectGuid dbtableHighGuid = ObjectGuid::Create<HighGuid::GameObject>(GetEntry(), m_spawnId);
578 time_t linkedRespawntime = GetMap()->GetLinkedRespawnTime(dbtableHighGuid);
579 if (linkedRespawntime) // Can't respawn, the master is dead
580 {
581 ObjectGuid targetGuid = sObjectMgr->GetLinkedRespawnGuid(dbtableHighGuid);
582 if (targetGuid == dbtableHighGuid) // if linking self, never respawn
584 else
585 m_respawnTime = (now > linkedRespawntime ? now : linkedRespawntime) + urand(5, MINUTE); // else copy time from master and add a little
587 return;
588 }
589
590 m_respawnTime = 0;
591 m_SkillupList.clear();
592 m_usetimes = 0;
593
594 switch (GetGoType())
595 {
596 case GAMEOBJECT_TYPE_FISHINGNODE: // can't fish now
597 {
598 Unit* caster = GetOwner();
599 if (caster && caster->GetTypeId() == TYPEID_PLAYER)
600 {
601 caster->ToPlayer()->RemoveGameObject(this, false);
602
604 caster->ToPlayer()->SendDirectMessage(&data);
605 }
606 // can be delete
608 return;
609 }
612 // 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)
613 if (GetGoState() != GO_STATE_READY)
615 break;
617 // Initialize a new max fish count on respawn
618 m_goValue.FishingHole.MaxOpens = urand(GetGOInfo()->fishinghole.minSuccessOpens, std::max(GetGOInfo()->fishinghole.minSuccessOpens, GetGOInfo()->fishinghole.maxSuccessOpens));
619 break;
620 default:
621 break;
622 }
623
624 // Despawn timer
626 {
627 // Can be despawned or destroyed
629 return;
630 }
631
632 // Call AI Reset (required for example in SmartAI to clear one time events)
633 if (AI())
634 AI()->Reset();
635
636 // Respawn timer
637 uint32 poolid = GetSpawnId() ? sPoolMgr->IsPartOfAPool<GameObject>(GetSpawnId()) : 0;
638 if (poolid)
639 sPoolMgr->UpdatePool<GameObject>(poolid, GetSpawnId());
640 else
641 GetMap()->AddToMap(this);
642 }
643 }
644 }
645
646 // Set respawn timer
649
650 if (isSpawned())
651 {
652 GameObjectTemplate const* goInfo = GetGOInfo();
653 if (goInfo->type == GAMEOBJECT_TYPE_TRAP)
654 {
656 break;
657
658 // Type 2 (bomb) does not need to be triggered by a unit and despawns after casting its spell.
659 if (goInfo->trap.type == 2)
660 {
662 break;
663 }
664
665 // Type 0 despawns after being triggered, type 1 does not.
667 float radius;
668 if (!goInfo->trap.diameter)
669 {
670 // Battleground traps: data2 == 0 && data5 == 3
671 if (goInfo->trap.cooldown != 3)
672 break;
673
674 radius = 3.f;
675 }
676 else
677 radius = goInfo->trap.diameter / 2.f;
678
679 // Pointer to appropriate target if found any
680 Unit* target = nullptr;
681
683 if (GetOwner())
684 {
685 // summoned traps: Search targets fit to trap spell data
686 if (SpellInfo const* trapSpell = sSpellMgr->GetSpellInfo(goInfo->trap.spellId))
687 {
688 WorldObject* worldObjectTarget = nullptr;
689 Trinity::WorldObjectSpellNearbyTargetCheck checker(radius, this, trapSpell, m_goValue.Trap.TargetSearcherCheckType, nullptr);
691 Cell::VisitAllObjects(this, searcher, radius);
692 target = Object::ToUnit(worldObjectTarget);
693 }
694 else
695 {
698 Cell::VisitAllObjects(this, searcher, radius);
699 }
700 }
701 else
702 {
703 // Environmental trap: Any player
704 Player* player = nullptr;
705 Trinity::AnyPlayerInObjectRangeCheck checker(this, radius);
707 Cell::VisitWorldObjects(this, searcher, radius);
708 target = player;
709 }
710
711 if (target)
712 SetLootState(GO_ACTIVATED, target);
713
714 }
715 else if (uint32 max_charges = goInfo->GetCharges())
716 {
717 if (m_usetimes >= max_charges)
718 {
719 m_usetimes = 0;
720 SetLootState(GO_JUST_DEACTIVATED); // can be despawned or destroyed
721 }
722 }
723 }
724
725 break;
726 }
727 case GO_ACTIVATED:
728 {
729 switch (GetGoType())
730 {
735 break;
738 {
741 }
742 break;
745 {
746 if (m_groupLootTimer <= diff)
747 {
748 if (Group* group = sGroupMgr->GetGroupByGUID(lootingGroupLowGUID))
749 group->EndRoll(&loot, GetMap());
750
753 }
754 else
755 m_groupLootTimer -= diff;
756 }
757
758 // Non-consumable chest was partially looted and restock time passed, restock all loot now
760 {
761 m_restockTime = 0;
764 }
765 break;
767 {
768 GameObjectTemplate const* goInfo = GetGOInfo();
769 if (goInfo->trap.type == 2 && goInfo->trap.spellId)
770 {
772 CastSpell(nullptr, goInfo->trap.spellId);
774 }
775 else if (Unit* target = ObjectAccessor::GetUnit(*this, m_lootStateUnitGUID))
776 {
777 // Some traps do not have a spell but should be triggered
780 if (goInfo->trap.spellId)
781 CastSpell(target, goInfo->trap.spellId, args);
782
783 // Template value or 4 seconds
785
786 if (goInfo->trap.type == 1)
788 else if (!goInfo->trap.type)
790
791 // Battleground gameobjects have data2 == 0 && data5 == 3
792 if (!goInfo->trap.diameter && goInfo->trap.cooldown == 3)
793 if (Player* player = target->ToPlayer())
794 if (Battleground* bg = player->GetBattleground())
795 bg->HandleTriggerBuff(GetGUID());
796 }
797 break;
798 }
799 default:
800 break;
801 }
802 break;
803 }
805 {
806 // If nearby linked trap exists, despawn it
807 if (GameObject* linkedTrap = GetLinkedTrap())
808 linkedTrap->DespawnOrUnsummon();
809
810 //if Gameobject should cast spell, then this, but some GOs (type = 10) should be destroyed
812 {
813 uint32 spellId = GetGOInfo()->goober.spellId;
814
815 if (spellId)
816 {
817 for (GuidSet::const_iterator it = m_unique_users.begin(); it != m_unique_users.end(); ++it)
818 // m_unique_users can contain only player GUIDs
819 if (Player* owner = ObjectAccessor::GetPlayer(*this, *it))
820 owner->CastSpell(owner, spellId, false);
821
822 m_unique_users.clear();
823 m_usetimes = 0;
824 }
825
826 // Only goobers with a lock id or a reset time may reset their go state
829
830 //any return here in case battleground traps
831 if (GameObjectOverride const* goOverride = GetGameObjectOverride())
832 if (goOverride->Flags & GO_FLAG_NODESPAWN)
833 return;
834 }
835
836 loot.clear();
837
838 // Do not delete chests or goobers that are not consumed on loot, while still allowing them to despawn when they expire if summoned
839 bool isSummonedAndExpired = (GetOwner() || GetSpellId()) && m_respawnTime == 0;
840 if ((GetGoType() == GAMEOBJECT_TYPE_CHEST || GetGoType() == GAMEOBJECT_TYPE_GOOBER) && !GetGOInfo()->IsDespawnAtAction() && !isSummonedAndExpired)
841 {
843 {
844 // Start restock timer when the chest is fully looted
848 }
849 else
852 return;
853 }
854 else if (!GetOwnerGUID().IsEmpty() || GetSpellId())
855 {
857 Delete();
858 return;
859 }
860
862
863 //burning flags in some battlegrounds, if you find better condition, just add it
864 if (GetGOInfo()->IsDespawnAtAction() || GetGoAnimProgress() > 0)
865 {
867 //reset flags
868 if (GameObjectOverride const* goOverride = GetGameObjectOverride())
869 ReplaceAllFlags(GameObjectFlags(goOverride->Flags));
870 }
871
873 return;
874
876 {
877 m_respawnTime = 0;
878
879 if (m_spawnId)
881 else
882 Delete();
883
884 return;
885 }
886
887 uint32 respawnDelay = m_respawnDelayTime;
888 if (uint32 scalingMode = sWorld->getIntConfig(CONFIG_RESPAWN_DYNAMICMODE))
889 GetMap()->ApplyDynamicModeRespawnScaling(this, this->m_spawnId, respawnDelay, scalingMode);
890 m_respawnTime = GameTime::GetGameTime() + respawnDelay;
891
892 // if option not set then object will be saved at grid unload
893 // Otherwise just save respawn time to map object memory
895
898 else
900
901 break;
902 }
903 }
904}
905
907{
908 if (m_spawnId)
909 {
910 if (GameObjectOverride const* goOverride = sObjectMgr->GetGameObjectOverride(m_spawnId))
911 return goOverride;
912 }
913
914 return m_goTemplateAddon;
915}
916
918{
919 // Do not refresh despawned GO from spellcast (GO's from spellcast are destroyed after despawn)
921 return;
922
923 if (isSpawned())
924 GetMap()->AddToMap(this);
925}
926
928{
929 AddUse();
930 m_unique_users.insert(player->GetGUID());
931}
932
934{
935 if (delay > 0ms)
936 {
937 if (!m_despawnDelay || m_despawnDelay > delay.count())
938 {
939 m_despawnDelay = delay.count();
940 m_despawnRespawnTime = forceRespawnTime;
941 }
942 }
943 else
944 {
945 if (m_goData)
946 {
947 uint32 const respawnDelay = (forceRespawnTime > 0s) ? forceRespawnTime.count() : m_goData->spawntimesecs;
948 SaveRespawnTime(respawnDelay);
949 }
950 Delete();
951 }
952}
953
955{
958
960
962
963 if (GameObjectOverride const* goOverride = GetGameObjectOverride())
964 ReplaceAllFlags(GameObjectFlags(goOverride->Flags));
965
966 uint32 poolid = GetSpawnId() ? sPoolMgr->IsPartOfAPool<GameObject>(GetSpawnId()) : 0;
967 if (poolid)
968 sPoolMgr->UpdatePool<GameObject>(poolid, GetSpawnId());
969 else
971}
972
973void GameObject::getFishLoot(Loot* fishloot, Player* loot_owner)
974{
975 fishloot->clear();
976
977 uint32 zone, subzone;
978 uint32 defaultzone = 1;
979 GetZoneAndAreaId(zone, subzone);
980
981 // if subzone loot exist use it
982 fishloot->FillLoot(subzone, LootTemplates_Fishing, loot_owner, true, true);
983 if (fishloot->empty()) //use this becase if zone or subzone has set LOOT_MODE_JUNK_FISH,Even if no normal drop, fishloot->FillLoot return true. it wrong.
984 {
985 //subzone no result,use zone loot
986 fishloot->FillLoot(zone, LootTemplates_Fishing, loot_owner, true, true);
987 //use zone 1 as default, somewhere fishing got nothing,becase subzone and zone not set, like Off the coast of Storm Peaks.
988 if (fishloot->empty())
989 fishloot->FillLoot(defaultzone, LootTemplates_Fishing, loot_owner, true, true);
990 }
991}
992
993void GameObject::getFishLootJunk(Loot* fishloot, Player* loot_owner)
994{
995 fishloot->clear();
996
997 uint32 zone, subzone;
998 uint32 defaultzone = 1;
999 GetZoneAndAreaId(zone, subzone);
1000
1001 // if subzone loot exist use it
1002 fishloot->FillLoot(subzone, LootTemplates_Fishing, loot_owner, true, true, LOOT_MODE_JUNK_FISH);
1003 if (fishloot->empty()) //use this becase if zone or subzone has normal mask drop, then fishloot->FillLoot return true.
1004 {
1005 //use zone loot
1006 fishloot->FillLoot(zone, LootTemplates_Fishing, loot_owner, true, true, LOOT_MODE_JUNK_FISH);
1007 if (fishloot->empty())
1008 //use zone 1 as default
1009 fishloot->FillLoot(defaultzone, LootTemplates_Fishing, loot_owner, true, true, LOOT_MODE_JUNK_FISH);
1010 }
1011}
1012
1014{
1015 // this should only be used when the gameobject has already been loaded
1016 // preferably after adding to map, because mapid may not be valid otherwise
1017 GameObjectData const* data = sObjectMgr->GetGameObjectData(m_spawnId);
1018 if (!data)
1019 {
1020 TC_LOG_ERROR("misc", "GameObject::SaveToDB failed, cannot get gameobject data!");
1021 return;
1022 }
1023
1024 SaveToDB(GetMapId(), data->spawnMask, data->phaseMask);
1025}
1026
1027void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask)
1028{
1029 GameObjectTemplate const* goI = GetGOInfo();
1030 if (!goI)
1031 return;
1032
1033 if (!m_spawnId)
1034 m_spawnId = sObjectMgr->GenerateGameObjectSpawnId();
1035
1036 // update in loaded data (changing data only in this place)
1037 GameObjectData& data = sObjectMgr->NewOrExistGameObjectData(m_spawnId);
1038
1039 if (!data.spawnId)
1040 data.spawnId = m_spawnId;
1041 ASSERT(data.spawnId == m_spawnId);
1042 data.id = GetEntry();
1043 data.mapId = GetMapId();
1044 data.spawnPoint.Relocate(this);
1045 data.phaseMask = phaseMask;
1049 data.goState = GetGoState();
1050 data.spawnMask = spawnMask;
1051 data.artKit = GetGoArtKit();
1052 if (!data.spawnGroupData)
1053 data.spawnGroupData = sObjectMgr->GetDefaultSpawnGroup();
1054
1055 // Update in DB
1056 WorldDatabaseTransaction trans = WorldDatabase.BeginTransaction();
1057
1058 uint8 index = 0;
1059
1061 stmt->setUInt32(0, m_spawnId);
1062 trans->Append(stmt);
1063
1064 stmt = WorldDatabase.GetPreparedStatement(WORLD_INS_GAMEOBJECT);
1065 stmt->setUInt32(index++, m_spawnId);
1066 stmt->setUInt32(index++, GetEntry());
1067 stmt->setUInt16(index++, uint16(mapid));
1068 stmt->setUInt8(index++, spawnMask);
1069 stmt->setUInt32(index++, GetPhaseMask());
1070 stmt->setFloat(index++, GetPositionX());
1071 stmt->setFloat(index++, GetPositionY());
1072 stmt->setFloat(index++, GetPositionZ());
1073 stmt->setFloat(index++, GetOrientation());
1074 stmt->setFloat(index++, m_localRotation.x);
1075 stmt->setFloat(index++, m_localRotation.y);
1076 stmt->setFloat(index++, m_localRotation.z);
1077 stmt->setFloat(index++, m_localRotation.w);
1078 stmt->setInt32(index++, int32(m_respawnDelayTime));
1079 stmt->setUInt8(index++, GetGoAnimProgress());
1080 stmt->setUInt8(index++, uint8(GetGoState()));
1081 trans->Append(stmt);
1082
1083 WorldDatabase.CommitTransaction(trans);
1084}
1085
1086bool GameObject::LoadFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap, bool)
1087{
1088 GameObjectData const* data = sObjectMgr->GetGameObjectData(spawnId);
1089
1090 if (!data)
1091 {
1092 TC_LOG_ERROR("sql.sql", "Gameobject (GUID: {}) not found in table `gameobject`, can't load. ", spawnId);
1093 return false;
1094 }
1095
1096 uint32 entry = data->id;
1097 //uint32 map_id = data->mapid; // already used before call
1098 uint32 phaseMask = data->phaseMask;
1099
1100 uint32 animprogress = data->animprogress;
1101 GOState go_state = data->goState;
1102 uint32 artKit = data->artKit;
1103
1104 m_spawnId = spawnId;
1106 if (!Create(map->GenerateLowGuid<HighGuid::GameObject>(), entry, map, phaseMask, data->spawnPoint, data->rotation, animprogress, go_state, artKit, !m_respawnCompatibilityMode))
1107 return false;
1108
1109 if (data->spawntimesecs >= 0)
1110 {
1111 m_spawnedByDefault = true;
1112
1114 {
1117 m_respawnTime = 0;
1118 }
1119 else
1120 {
1123
1124 // ready to respawn
1126 {
1127 m_respawnTime = 0;
1129 }
1130 }
1131 }
1132 else
1133 {
1135 {
1136 TC_LOG_WARN("sql.sql", "GameObject {} (SpawnID {}) is not spawned by default, but tries to use a non-hack spawn system. This will not work. Defaulting to compatibility mode.", entry, spawnId);
1138 }
1139
1140 m_spawnedByDefault = false;
1142 m_respawnTime = 0;
1143 }
1144
1145 m_goData = data;
1146
1148
1149 if (addToMap && !GetMap()->AddToMap(this))
1150 return false;
1151
1152 return true;
1153}
1154
1156{
1157 GameObjectData const* data = sObjectMgr->GetGameObjectData(spawnId);
1158 if (!data)
1159 return false;
1160
1161 CharacterDatabaseTransaction charTrans = CharacterDatabase.BeginTransaction();
1162
1163 sMapMgr->DoForAllMapsWithMapId(data->mapId,
1164 [spawnId, charTrans](Map* map) -> void
1165 {
1166 // despawn all active objects, and remove their respawns
1167 std::vector<GameObject*> toUnload;
1168 for (auto const& pair : Trinity::Containers::MapEqualRange(map->GetGameObjectBySpawnIdStore(), spawnId))
1169 toUnload.push_back(pair.second);
1170 for (GameObject* obj : toUnload)
1171 map->AddObjectToRemoveList(obj);
1172 map->RemoveRespawnTime(SPAWN_TYPE_GAMEOBJECT, spawnId, charTrans);
1173 }
1174 );
1175
1176 // delete data from memory
1177 sObjectMgr->DeleteGameObjectData(spawnId);
1178
1179 CharacterDatabase.CommitTransaction(charTrans);
1180
1181 WorldDatabaseTransaction trans = WorldDatabase.BeginTransaction();
1182
1183 // ... and the database
1185 stmt->setUInt32(0, spawnId);
1186 trans->Append(stmt);
1187
1188 stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_SPAWNGROUP_MEMBER);
1190 stmt->setUInt32(1, spawnId);
1191 trans->Append(stmt);
1192
1193 stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_EVENT_GAMEOBJECT);
1194 stmt->setUInt32(0, spawnId);
1195 trans->Append(stmt);
1196
1197 stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_LINKED_RESPAWN);
1198 stmt->setUInt32(0, spawnId);
1200 trans->Append(stmt);
1201
1202 stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_LINKED_RESPAWN);
1203 stmt->setUInt32(0, spawnId);
1205 trans->Append(stmt);
1206
1207 stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_LINKED_RESPAWN_MASTER);
1208 stmt->setUInt32(0, spawnId);
1210 trans->Append(stmt);
1211
1212 stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_LINKED_RESPAWN_MASTER);
1213 stmt->setUInt32(0, spawnId);
1215 trans->Append(stmt);
1216
1217 stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_GAMEOBJECT_ADDON);
1218 stmt->setUInt32(0, spawnId);
1219 trans->Append(stmt);
1220
1221 WorldDatabase.CommitTransaction(trans);
1222
1223 return true;
1224}
1225
1226/*********************************************************/
1227/*** QUEST SYSTEM ***/
1228/*********************************************************/
1229bool GameObject::hasQuest(uint32 quest_id) const
1230{
1231 return sObjectMgr->GetGOQuestRelations(GetEntry()).HasQuest(quest_id);
1232}
1233
1235{
1236 return sObjectMgr->GetGOQuestInvolvedRelations(GetEntry()).HasQuest(quest_id);
1237}
1238
1240{
1241 // If something is marked as a transport, don't transmit an out of range packet for it.
1242 GameObjectTemplate const* gInfo = GetGOInfo();
1243 if (!gInfo)
1244 return false;
1245
1247}
1248
1249// is Dynamic transport = non-stop Transport
1251{
1252 // If something is marked as a transport, don't transmit an out of range packet for it.
1253 GameObjectTemplate const* gInfo = GetGOInfo();
1254 if (!gInfo)
1255 return false;
1256
1257 return gInfo->type == GAMEOBJECT_TYPE_MAP_OBJ_TRANSPORT || (gInfo->type == GAMEOBJECT_TYPE_TRANSPORT && !gInfo->transport.pause);
1258}
1259
1261{
1262 GameObjectTemplate const* gInfo = GetGOInfo();
1263 if (!gInfo)
1264 return false;
1265
1267}
1268
1270{
1271 if (m_goData && (forceDelay || m_respawnTime > GameTime::GetGameTime()) && m_spawnedByDefault)
1272 {
1274 {
1275 RespawnInfo ri;
1277 ri.spawnId = m_spawnId;
1280 return;
1281 }
1282
1283 uint32 thisRespawnTime = forceDelay ? GameTime::GetGameTime() + forceDelay : m_respawnTime;
1285 }
1286}
1287
1288bool GameObject::IsNeverVisible(bool allowServersideObjects) const
1289{
1290 if (WorldObject::IsNeverVisible(allowServersideObjects))
1291 return true;
1292
1293 if (GetGOInfo()->GetServerOnly() && !allowServersideObjects)
1294 return true;
1295
1296 return false;
1297}
1298
1300{
1302 return true;
1303
1305 return true;
1306
1307 if (!seer)
1308 return false;
1309
1310 // Always seen by owner and friendly units
1311 if (!GetOwnerGUID().IsEmpty())
1312 {
1313 if (seer->GetGUID() == GetOwnerGUID())
1314 return true;
1315
1316 Unit* owner = GetOwner();
1317 if (Unit const* unitSeer = seer->ToUnit())
1318 if (owner && owner->IsFriendlyTo(unitSeer))
1319 return true;
1320 }
1321
1322 return false;
1323}
1324
1326{
1328 return true;
1329
1330 // Despawned
1331 if (!isSpawned())
1332 return true;
1333
1334 return false;
1335}
1336
1338{
1339 if (Unit* owner = GetOwner())
1340 return owner->GetLevelForTarget(target);
1341
1343 {
1344 if (GetGOInfo()->trap.level != 0)
1345 return GetGOInfo()->trap.level;
1346 if (const Unit* targetUnit = target->ToUnit())
1347 return targetUnit->GetLevel();
1348 }
1349
1350 return 1;
1351}
1352
1354{
1355 time_t now = GameTime::GetGameTime();
1356 if (m_respawnTime > now)
1357 return m_respawnTime;
1358 else
1359 return now;
1360}
1361
1363{
1364 m_respawnTime = respawn > 0 ? GameTime::GetGameTime() + respawn : 0;
1365 m_respawnDelayTime = respawn > 0 ? respawn : 0;
1366 if (respawn && !m_spawnedByDefault)
1368
1371}
1372
1381
1382bool GameObject::ActivateToQuest(Player const* target) const
1383{
1384 if (target->HasQuestForGO(GetEntry()))
1385 return true;
1386
1387 if (!sObjectMgr->IsGameObjectForQuests(GetEntry()))
1388 return false;
1389
1390 switch (GetGoType())
1391 {
1393 {
1394 GameObject* go = const_cast<GameObject*>(this);
1395 QuestGiverStatus questStatus = const_cast<Player*>(target)->GetQuestDialogStatus(go);
1396 if (questStatus > DIALOG_STATUS_UNAVAILABLE)
1397 return true;
1398 break;
1399 }
1401 {
1402 // Chests become inactive while not ready to be looted
1403 if (getLootState() == GO_NOT_READY)
1404 return false;
1405
1406 // scan GO chest with loot including quest items
1408 {
1409 if (Battleground const* bg = target->GetBattleground())
1410 return bg->CanActivateGO(GetEntry(), target->GetTeam());
1411 return true;
1412 }
1413 break;
1414 }
1416 {
1418 return true;
1419 break;
1420 }
1422 {
1424 return true;
1425 break;
1426 }
1427 default:
1428 break;
1429 }
1430
1431 return false;
1432}
1433
1435{
1436 GameObjectTemplate const* trapInfo = sObjectMgr->GetGameObjectTemplate(trapEntry);
1437 if (!trapInfo || trapInfo->type != GAMEOBJECT_TYPE_TRAP)
1438 return;
1439
1440 SpellInfo const* trapSpell = sSpellMgr->GetSpellInfo(trapInfo->trap.spellId);
1441 if (!trapSpell) // checked at load already
1442 return;
1443
1444 if (GameObject* trapGO = GetLinkedTrap())
1445 trapGO->CastSpell(target, trapSpell->Id);
1446}
1447
1449{
1450 GameObject* ok = nullptr;
1451 Trinity::NearestGameObjectFishingHole u_check(*this, range);
1453 Cell::VisitGridObjects(this, checker, range);
1454 return ok;
1455}
1456
1468
1469void GameObject::UseDoorOrButton(uint32 time_to_restore, bool alternative /* = false */, Unit* user /*=nullptr*/)
1470{
1471 if (m_lootState != GO_READY)
1472 return;
1473
1474 if (!time_to_restore)
1475 time_to_restore = GetGOInfo()->GetAutoCloseTime();
1476
1477 SwitchDoorOrButton(true, alternative);
1479
1480 m_cooldownTime = time_to_restore ? (GameTime::GetGameTimeMS() + time_to_restore) : 0;
1481}
1482
1483void GameObject::ActivateObject(GameObjectActions action, WorldObject* spellCaster, uint32 spellId, int32 effectIndex)
1484{
1485 Unit* unitCaster = spellCaster ? spellCaster->ToUnit() : nullptr;
1486
1487 switch (action)
1488 {
1490 TC_LOG_FATAL("spell", "Spell {} has action type NONE in effect {}", spellId, effectIndex);
1491 break;
1497 break;
1498 case GameObjectActions::Disturb: // What's the difference with Open?
1499 if (unitCaster)
1500 Use(unitCaster);
1501 break;
1504 break;
1507 break;
1509 if (unitCaster)
1510 Use(unitCaster);
1511 break;
1513 if (unitCaster)
1514 {
1515 UseDoorOrButton(0, false, unitCaster);
1517 }
1518 break;
1521 break;
1523 // No use cases, implementation unknown
1524 break;
1526 if (unitCaster)
1527 UseDoorOrButton(0, true, unitCaster);
1528 break;
1531 break;
1533 // No use cases, implementation unknown
1534 break;
1537 break;
1540 break;
1543 break;
1547 break;
1552 {
1553 GameObjectTemplateAddon const* templateAddon = GetTemplateAddon();
1554
1555 uint32 artKitIndex = uint32(action) - uint32(GameObjectActions::UseArtKit0);
1556
1557 uint32 artKitValue = 0;
1558 if (templateAddon != nullptr)
1559 artKitValue = templateAddon->artKits[artKitIndex];
1560
1561 if (artKitValue == 0)
1562 TC_LOG_ERROR("sql.sql", "GameObject {} hit by spell {} needs `artkit{}` in `gameobject_template_addon`", GetEntry(), spellId, artKitIndex);
1563 else
1564 SetGoArtKit(artKitValue);
1565
1566 break;
1567 }
1569 // No use cases, implementation unknown
1570 break;
1571 default:
1572 TC_LOG_ERROR("spell", "Spell {} has unhandled action {} in effect {}", spellId, int32(action), effectIndex);
1573 break;
1574 }
1575}
1576
1578{
1580 GameObjectData* data = const_cast<GameObjectData*>(sObjectMgr->GetGameObjectData(m_spawnId));
1581 if (data)
1582 data->artKit = kit;
1583}
1584
1586{
1587 GameObjectData const* data = nullptr;
1588 if (go)
1589 {
1590 go->SetGoArtKit(artkit);
1591 data = go->GetGameObjectData();
1592 }
1593 else if (lowguid)
1594 data = sObjectMgr->GetGameObjectData(lowguid);
1595
1596 if (data)
1597 const_cast<GameObjectData*>(data)->artKit = artkit;
1598}
1599
1600void GameObject::SwitchDoorOrButton(bool activate, bool alternative /* = false */)
1601{
1602 if (activate)
1604 else
1606
1607 if (GetGoState() == GO_STATE_READY) //if closed -> open
1609 else //if open -> close
1611}
1612
1614{
1615 // by default spell caster is user
1616 Unit* spellCaster = user;
1617 uint32 spellId = 0;
1618 bool triggered = false;
1619 bool addUse = false;
1620
1621 if (Player* playerUser = user->ToPlayer())
1622 {
1623 if (m_goInfo->CannotBeUsedUnderImmunity() && playerUser->HasUnitFlag(UNIT_FLAG_IMMUNE))
1624 return;
1625
1626 if (!m_goInfo->IsUsableMounted())
1628
1629 playerUser->PlayerTalkClass->ClearMenus();
1630 if (AI()->OnGossipHello(playerUser))
1631 return;
1632 }
1633
1634 // If cooldown data present in template
1635 if (uint32 cooldown = GetGOInfo()->GetCooldown())
1636 {
1638 return;
1639
1641 }
1642
1643 switch (GetGoType())
1644 {
1645 case GAMEOBJECT_TYPE_DOOR: //0
1646 case GAMEOBJECT_TYPE_BUTTON: //1
1647 //doors/buttons never really despawn, only reset to default state/flags
1648 UseDoorOrButton(0, false, user);
1649 return;
1651 {
1652 if (user->GetTypeId() != TYPEID_PLAYER)
1653 return;
1654
1655 Player* player = user->ToPlayer();
1656
1657 player->PrepareGossipMenu(this, GetGOInfo()->questgiver.gossipID, true);
1658 player->SendPreparedGossip(this);
1659 return;
1660 }
1661 case GAMEOBJECT_TYPE_TRAP: //6
1662 {
1663 GameObjectTemplate const* goInfo = GetGOInfo();
1664 if (goInfo->trap.spellId)
1665 CastSpell(user, goInfo->trap.spellId);
1666
1667 m_cooldownTime = GameTime::GetGameTimeMS() + (goInfo->trap.cooldown ? goInfo->trap.cooldown : uint32(4)) * IN_MILLISECONDS; // template or 4 seconds
1668
1669 if (goInfo->trap.type == 1) // Deactivate after trigger
1671
1672 return;
1673 }
1674 //Sitting: Wooden bench, chairs enzz
1675 case GAMEOBJECT_TYPE_CHAIR: //7
1676 {
1677 GameObjectTemplate const* info = GetGOInfo();
1678 if (!info)
1679 return;
1680
1681 if (user->GetTypeId() != TYPEID_PLAYER)
1682 return;
1683
1684 if (ChairListSlots.empty()) // this is called once at first chair use to make list of available slots
1685 {
1686 if (info->chair.slots > 0) // sometimes chairs in DB have error in fields and we dont know number of slots
1687 for (uint32 i = 0; i < info->chair.slots; ++i)
1688 ChairListSlots[i].Clear(); // Last user of current slot set to 0 (none sit here yet)
1689 else
1690 ChairListSlots[0].Clear(); // error in DB, make one default slot
1691 }
1692
1693 Player* player = user->ToPlayer();
1694
1695 // a chair may have n slots. we have to calculate their positions and teleport the player to the nearest one
1696
1697 float lowestDist = DEFAULT_VISIBILITY_DISTANCE;
1698
1699 uint32 nearest_slot = 0;
1700 float x_lowest = GetPositionX();
1701 float y_lowest = GetPositionY();
1702
1703 // the object orientation + 1/2 pi
1704 // every slot will be on that straight line
1705 float orthogonalOrientation = GetOrientation() + float(M_PI) * 0.5f;
1706 // find nearest slot
1707 bool found_free_slot = false;
1708 for (ChairSlotAndUser::iterator itr = ChairListSlots.begin(); itr != ChairListSlots.end(); ++itr)
1709 {
1710 // the distance between this slot and the center of the go - imagine a 1D space
1711 float relativeDistance = (info->size*itr->first)-(info->size*(info->chair.slots-1)/2.0f);
1712
1713 float x_i = GetPositionX() + relativeDistance * std::cos(orthogonalOrientation);
1714 float y_i = GetPositionY() + relativeDistance * std::sin(orthogonalOrientation);
1715
1716 if (!itr->second.IsEmpty())
1717 {
1718 if (Player* ChairUser = ObjectAccessor::GetPlayer(*this, itr->second))
1719 {
1720 if (ChairUser->IsSitState() && ChairUser->GetStandState() != UNIT_STAND_STATE_SIT && ChairUser->GetExactDist2d(x_i, y_i) < 0.1f)
1721 continue; // This seat is already occupied by ChairUser. NOTE: Not sure if the ChairUser->GetStandState() != UNIT_STAND_STATE_SIT check is required.
1722 else
1723 itr->second.Clear(); // This seat is unoccupied.
1724 }
1725 else
1726 itr->second.Clear(); // The seat may of had an occupant, but they're offline.
1727 }
1728
1729 found_free_slot = true;
1730
1731 // calculate the distance between the player and this slot
1732 float thisDistance = player->GetDistance2d(x_i, y_i);
1733
1734 if (thisDistance <= lowestDist)
1735 {
1736 nearest_slot = itr->first;
1737 lowestDist = thisDistance;
1738 x_lowest = x_i;
1739 y_lowest = y_i;
1740 }
1741 }
1742
1743 if (found_free_slot)
1744 {
1745 ChairSlotAndUser::iterator itr = ChairListSlots.find(nearest_slot);
1746 if (itr != ChairListSlots.end())
1747 {
1748 itr->second = player->GetGUID(); //this slot in now used by player
1751 return;
1752 }
1753 }
1754
1755 return;
1756 }
1757 //big gun, its a spell/aura
1758 case GAMEOBJECT_TYPE_GOOBER: //10
1759 {
1760 GameObjectTemplate const* info = GetGOInfo();
1761
1762 if (Player* player = user->ToPlayer())
1763 {
1764 if (info->goober.pageId) // show page...
1765 {
1767 data << GetGUID();
1768 player->SendDirectMessage(&data);
1769 }
1770 else if (info->goober.gossipID)
1771 {
1772 player->PrepareGossipMenu(this, info->goober.gossipID);
1773 player->SendPreparedGossip(this);
1774 }
1775
1776 if (info->goober.eventId)
1777 {
1778 TC_LOG_DEBUG("maps.script", "Goober ScriptStart id {} for GO entry {} (GUID {}).", info->goober.eventId, GetEntry(), GetSpawnId());
1779 GetMap()->ScriptsStart(sEventScripts, info->goober.eventId, player, this);
1780 EventInform(info->goober.eventId, user);
1781 }
1782
1783 // possible quest objective for active quests
1784 if (info->goober.questId && sObjectMgr->GetQuestTemplate(info->goober.questId))
1785 {
1786 //Quest require to be active for GO using
1787 if (player->GetQuestStatus(info->goober.questId) != QUEST_STATUS_INCOMPLETE)
1788 break;
1789 }
1790
1791 if (Group* group = player->GetGroup())
1792 {
1793 for (GroupReference const* itr = group->GetFirstMember(); itr != nullptr; itr = itr->next())
1794 if (Player* member = itr->GetSource())
1795 if (member->IsAtGroupRewardDistance(this))
1796 member->KillCreditGO(info->entry, GetGUID());
1797 }
1798 else
1799 player->KillCreditGO(info->entry, GetGUID());
1800 }
1801
1802 if (uint32 trapEntry = info->goober.linkedTrapId)
1803 TriggeringLinkedGameObject(trapEntry, user);
1804
1807
1808 // this appear to be ok, however others exist in addition to this that should have custom (ex: 190510, 188692, 187389)
1809 if (info->goober.customAnim)
1811 else
1813
1815
1816 // cast this spell later if provided
1817 spellId = info->goober.spellId;
1818 spellCaster = nullptr;
1819
1820 break;
1821 }
1822 case GAMEOBJECT_TYPE_CAMERA: //13
1823 {
1824 GameObjectTemplate const* info = GetGOInfo();
1825 if (!info)
1826 return;
1827
1828 if (user->GetTypeId() != TYPEID_PLAYER)
1829 return;
1830
1831 Player* player = user->ToPlayer();
1832
1833 if (info->camera.cinematicId)
1834 player->SendCinematicStart(info->camera.cinematicId);
1835
1836 if (info->camera.eventID)
1837 {
1838 GetMap()->ScriptsStart(sEventScripts, info->camera.eventID, player, this);
1839 EventInform(info->camera.eventID, user);
1840 }
1841
1842 return;
1843 }
1844 //fishing bobber
1846 {
1847 Player* player = user->ToPlayer();
1848 if (!player)
1849 return;
1850
1851 if (player->GetGUID() != GetOwnerGUID())
1852 return;
1853
1854 switch (getLootState())
1855 {
1856 case GO_READY: // ready for loot
1857 {
1858 uint32 zone, subzone;
1859 GetZoneAndAreaId(zone, subzone);
1860
1861 int32 zone_skill = sObjectMgr->GetFishingBaseSkillLevel(subzone);
1862 if (!zone_skill)
1863 zone_skill = sObjectMgr->GetFishingBaseSkillLevel(zone);
1864
1865 //provide error, no fishable zone or area should be 0
1866 if (!zone_skill)
1867 TC_LOG_ERROR("sql.sql", "Fishable areaId {} are not properly defined in `skill_fishing_base_level`.", subzone);
1868
1869 int32 skill = player->GetSkillValue(SKILL_FISHING);
1870
1871 int32 chance;
1872 if (skill < zone_skill)
1873 {
1874 chance = int32(pow((double)skill/zone_skill, 2) * 100);
1875 if (chance < 1)
1876 chance = 1;
1877 }
1878 else
1879 chance = 100;
1880
1881 int32 roll = irand(1, 100);
1882
1883 TC_LOG_DEBUG("misc", "Fishing check (skill: {} zone min skill: {} chance {} roll: {}", skill, zone_skill, chance, roll);
1884
1885 player->UpdateFishingSkill();
1886
1888 GameObject* fishingPool = LookupFishingHoleAround(20.0f + CONTACT_DISTANCE);
1889
1890 // If fishing skill is high enough, or if fishing on a pool, send correct loot.
1891 // Fishing pools have no skill requirement as of patch 3.3.0 (undocumented change).
1892 if (chance >= roll || fishingPool)
1893 {
1895 // prevent removing GO at spell cancel
1897 SetOwnerGUID(player->GetGUID());
1898 SetSpellId(0); // prevent removing unintended auras at Unit::RemoveGameObject
1899
1900 if (fishingPool)
1901 {
1902 fishingPool->Use(player);
1904 }
1905 else
1906 player->SendLoot(GetGUID(), LOOT_FISHING);
1907 }
1908 else // If fishing skill is too low, send junk loot.
1910 break;
1911 }
1912 case GO_JUST_DEACTIVATED: // nothing to do, will be deleted at next update
1913 break;
1914 default:
1915 {
1917
1919 player->SendDirectMessage(&data);
1920 break;
1921 }
1922 }
1923
1925 return;
1926 }
1927
1928 case GAMEOBJECT_TYPE_RITUAL: //18
1929 {
1930 if (user->GetTypeId() != TYPEID_PLAYER)
1931 return;
1932
1933 Player* player = user->ToPlayer();
1934
1935 Unit* owner = GetOwner();
1936
1937 GameObjectTemplate const* info = GetGOInfo();
1938
1939 Player* m_ritualOwner = nullptr;
1942
1943 // ritual owner is set for GO's without owner (not summoned)
1944 if (!m_ritualOwner && !owner)
1945 {
1946 m_ritualOwnerGUID = player->GetGUID();
1947 m_ritualOwner = player;
1948 }
1949
1950 if (owner)
1951 {
1952 if (owner->GetTypeId() != TYPEID_PLAYER)
1953 return;
1954
1955 // accept only use by player from same group as owner, excluding owner itself (unique use already added in spell effect)
1956 if (player == owner->ToPlayer() || (info->summoningRitual.castersGrouped && !player->IsInSameRaidWith(owner->ToPlayer())))
1957 return;
1958
1959 // expect owner to already be channeling, so if not...
1961 return;
1962
1963 // in case summoning ritual caster is GO creator
1964 spellCaster = owner;
1965 }
1966 else
1967 {
1968 if (player != m_ritualOwner && (info->summoningRitual.castersGrouped && !player->IsInSameRaidWith(m_ritualOwner)))
1969 return;
1970
1971 spellCaster = player;
1972 }
1973
1974 AddUniqueUse(player);
1975
1976 if (info->summoningRitual.animSpell)
1977 {
1978 player->CastSpell(player, info->summoningRitual.animSpell, true);
1979
1980 // for this case, summoningRitual.spellId is always triggered
1981 triggered = true;
1982 }
1983
1984 // full amount unique participants including original summoner
1986 {
1987 if (m_ritualOwner)
1988 spellCaster = m_ritualOwner;
1989
1990 spellId = info->summoningRitual.spellId;
1991
1992 if (spellId == 62330) // GO store nonexistent spell, replace by expected
1993 {
1994 // spell have reagent and mana cost but it not expected use its
1995 // it triggered spell in fact cast at currently channeled GO
1996 spellId = 61993;
1997 triggered = true;
1998 }
1999
2000 // Cast casterTargetSpell at a random GO user
2001 // on the current DB there is only one gameobject that uses this (Ritual of Doom)
2002 // and its required target number is 1 (outter for loop will run once)
2003 if (info->summoningRitual.casterTargetSpell && info->summoningRitual.casterTargetSpell != 1) // No idea why this field is a bool in some cases
2004 for (uint32 i = 0; i < info->summoningRitual.casterTargetSpellTargets; i++)
2005 // m_unique_users can contain only player GUIDs
2007 spellCaster->CastSpell(target, info->summoningRitual.casterTargetSpell, true);
2008
2009 // finish owners spell
2010 if (owner)
2012
2013 // can be deleted now, if
2016 else
2017 {
2018 // reset ritual for this GO
2020 m_unique_users.clear();
2021 m_usetimes = 0;
2022 }
2023 }
2024 else
2025 return;
2026
2027 // go to end function to spell casting
2028 break;
2029 }
2031 {
2032 GameObjectTemplate const* info = GetGOInfo();
2033 if (!info)
2034 return;
2035
2036 if (info->spellcaster.partyOnly)
2037 {
2038 ObjectGuid ownerGuid = GetOwnerGUID();
2039 if (ownerGuid.IsEmpty())
2040 return;
2041
2042 if (ownerGuid != user->GetGUID())
2043 {
2044 if (Unit* owner = ObjectAccessor::GetUnit(*this, ownerGuid))
2045 ownerGuid = owner->GetCharmerOrOwnerOrOwnGUID();
2046
2047 Player const* playerUser = user->GetCharmerOrOwnerPlayerOrPlayerItself();
2048 if (!playerUser)
2049 return;
2050
2051 Group const* group = playerUser->GetGroup();
2052 if (!group || !group->IsMember(ownerGuid))
2053 return;
2054 }
2055 }
2056
2058 spellId = info->spellcaster.spellId;
2059
2060 addUse = true;
2061 break;
2062 }
2064 {
2065 GameObjectTemplate const* info = GetGOInfo();
2066
2067 if (user->GetTypeId() != TYPEID_PLAYER)
2068 return;
2069
2070 Player* player = user->ToPlayer();
2071
2072 Player* targetPlayer = ObjectAccessor::FindPlayer(player->GetTarget());
2073
2074 // accept only use by player from same raid as caster, except caster itself
2075 if (!targetPlayer || targetPlayer == player || !targetPlayer->IsInSameRaidWith(player))
2076 return;
2077
2078 //required lvl checks!
2079 uint8 level = player->GetLevel();
2080 if (level < info->meetingstone.minLevel)
2081 return;
2082 level = targetPlayer->GetLevel();
2083 if (level < info->meetingstone.minLevel)
2084 return;
2085
2086 if (info->entry == 194097)
2087 spellId = 61994; // Ritual of Summoning
2088 else
2089 spellId = 59782; // Summoning Stone Effect
2090
2091 break;
2092 }
2093
2094 case GAMEOBJECT_TYPE_FLAGSTAND: // 24
2095 {
2096 if (user->GetTypeId() != TYPEID_PLAYER)
2097 return;
2098
2099 Player* player = user->ToPlayer();
2100
2101 if (player->CanUseBattlegroundObject(this))
2102 {
2103 // in battleground check
2104 Battleground* bg = player->GetBattleground();
2105 if (!bg)
2106 return;
2107
2108 if (player->GetVehicle())
2109 return;
2110
2113 // BG flag click
2114 // AB:
2115 // 15001
2116 // 15002
2117 // 15003
2118 // 15004
2119 // 15005
2120 bg->EventPlayerClickedOnFlag(player, this);
2121 return; //we don;t need to delete flag ... it is despawned!
2122 }
2123 break;
2124 }
2125
2126 case GAMEOBJECT_TYPE_FISHINGHOLE: // 25
2127 {
2128 if (user->GetTypeId() != TYPEID_PLAYER)
2129 return;
2130
2131 Player* player = user->ToPlayer();
2132
2133 player->SendLoot(GetGUID(), LOOT_FISHINGHOLE);
2135 return;
2136 }
2137
2138 case GAMEOBJECT_TYPE_FLAGDROP: // 26
2139 {
2140 if (user->GetTypeId() != TYPEID_PLAYER)
2141 return;
2142
2143 Player* player = user->ToPlayer();
2144
2145 if (player->CanUseBattlegroundObject(this))
2146 {
2147 // in battleground check
2148 Battleground* bg = player->GetBattleground();
2149 if (!bg)
2150 return;
2151
2152 if (player->GetVehicle())
2153 return;
2154
2157 // BG flag dropped
2158 // WS:
2159 // 179785 - Silverwing Flag
2160 // 179786 - Warsong Flag
2161 // EotS:
2162 // 184142 - Netherstorm Flag
2163 GameObjectTemplate const* info = GetGOInfo();
2164 if (info)
2165 {
2166 switch (info->entry)
2167 {
2168 case 179785: // Silverwing Flag
2169 case 179786: // Warsong Flag
2170 if (bg->GetTypeID(true) == BATTLEGROUND_WS)
2171 bg->EventPlayerClickedOnFlag(player, this);
2172 break;
2173 case 184142: // Netherstorm Flag
2174 if (bg->GetTypeID(true) == BATTLEGROUND_EY)
2175 bg->EventPlayerClickedOnFlag(player, this);
2176 break;
2177 }
2178 }
2179 //this cause to call return, all flags must be deleted here!!
2180 spellId = 0;
2181 Delete();
2182 }
2183 break;
2184 }
2186 {
2187 GameObjectTemplate const* info = GetGOInfo();
2188 if (!info)
2189 return;
2190
2191 if (user->GetTypeId() != TYPEID_PLAYER)
2192 return;
2193
2194 Player* player = user->ToPlayer();
2195
2196 // fallback, will always work
2198
2200 player->SendDirectMessage(&data);
2201
2203 return;
2204 }
2205 default:
2207 TC_LOG_ERROR("misc", "GameObject::Use(): unit ({}, name: {}) tries to use object ({}, name: {}) of unknown type ({})",
2208 user->GetGUID().ToString(), user->GetName(), GetGUID().ToString(), GetGOInfo()->name, GetGoType());
2209 break;
2210 }
2211
2212 if (!spellId)
2213 return;
2214
2215 if (!sSpellMgr->GetSpellInfo(spellId))
2216 {
2217 if (user->GetTypeId() != TYPEID_PLAYER || !sOutdoorPvPMgr->HandleCustomSpell(user->ToPlayer(), spellId, this))
2218 TC_LOG_ERROR("misc", "WORLD: unknown spell id {} at use action for gameobject (Entry: {} GoType: {})", spellId, GetEntry(), GetGoType());
2219 else
2220 TC_LOG_DEBUG("outdoorpvp", "WORLD: {} non-dbc spell was handled by OutdoorPvP", spellId);
2221 return;
2222 }
2223
2224 if (Player* player = user->ToPlayer())
2225 sOutdoorPvPMgr->HandleCustomSpell(player, spellId, this);
2226
2227 SpellCastResult castResult;
2228 if (spellCaster)
2229 castResult = spellCaster->CastSpell(user, spellId, triggered);
2230 else
2231 castResult = CastSpell(user, spellId);
2232
2233 if (addUse && castResult == SPELL_CAST_OK)
2234 AddUse();
2235}
2236
2238{
2240 data << GetGUID();
2241 data << uint32(anim);
2242 SendMessageToSet(&data, true);
2243}
2244
2245bool GameObject::IsInRange(float x, float y, float z, float radius) const
2246{
2248 if (!info)
2249 return IsWithinDist3d(x, y, z, radius);
2250
2251 float sinA = std::sin(GetOrientation());
2252 float cosA = std::cos(GetOrientation());
2253 float dx = x - GetPositionX();
2254 float dy = y - GetPositionY();
2255 float dz = z - GetPositionZ();
2256 float dist = std::sqrt(dx*dx + dy*dy);
2259 if (G3D::fuzzyEq(dist, 0.0f))
2260 return true;
2261
2262 float sinB = dx / dist;
2263 float cosB = dy / dist;
2264 dx = dist * (cosA * cosB + sinA * sinB);
2265 dy = dist * (cosA * sinB - sinA * cosB);
2266 return dx < info->GeoBoxMax.X + radius && dx > info->GeoBoxMin.X - radius
2267 && dy < info->GeoBoxMax.Y + radius && dy > info->GeoBoxMin.Y - radius
2268 && dz < info->GeoBoxMax.Z + radius && dz > info->GeoBoxMin.Z - radius;
2269}
2270
2271void GameObject::EventInform(uint32 eventId, WorldObject* invoker /*= nullptr*/)
2272{
2273 if (!eventId)
2274 return;
2275
2276 if (AI())
2277 AI()->EventInform(eventId);
2278
2279 if (GetZoneScript())
2280 GetZoneScript()->ProcessEvent(this, eventId);
2281
2282 if (BattlegroundMap* bgMap = GetMap()->ToBattlegroundMap())
2283 if (bgMap->GetBG())
2284 bgMap->GetBG()->ProcessEvent(this, eventId, invoker);
2285}
2286
2288{
2290 if (uint32 scriptId = gameObjectData->scriptId)
2291 return scriptId;
2292
2293 return GetGOInfo()->ScriptId;
2294}
2295
2297{
2298 // copy references to stringIds from template and spawn
2299 m_stringIds = parent->m_stringIds;
2300
2301 // then copy script stringId, not just its reference
2302 SetScriptStringId(std::string(parent->GetStringId(StringIdType::Script)));
2303}
2304
2305bool GameObject::HasStringId(std::string_view id) const
2306{
2307 return std::ranges::any_of(m_stringIds, [id](std::string const* stringId) { return stringId && *stringId == id; });
2308}
2309
2311{
2312 if (!id.empty())
2313 {
2314 m_scriptStringId.emplace(std::move(id));
2316 }
2317 else
2318 {
2319 m_scriptStringId.reset();
2321 }
2322}
2323
2324// overwrite WorldObject function for proper name localization
2325std::string const & GameObject::GetNameForLocaleIdx(LocaleConstant loc_idx) const
2326{
2327 if (loc_idx != DEFAULT_LOCALE)
2328 {
2329 uint8 uloc_idx = uint8(loc_idx);
2330 if (GameObjectLocale const* cl = sObjectMgr->GetGameObjectLocale(GetEntry()))
2331 if (cl->Name.size() > uloc_idx && !cl->Name[uloc_idx].empty())
2332 return cl->Name[uloc_idx];
2333 }
2334
2335 return GetName();
2336}
2337
2339{
2340 static const int32 PACK_YZ = 1 << 20;
2341 static const int32 PACK_X = PACK_YZ << 1;
2342
2343 static const int32 PACK_YZ_MASK = (PACK_YZ << 1) - 1;
2344 static const int32 PACK_X_MASK = (PACK_X << 1) - 1;
2345
2346 int8 w_sign = (m_localRotation.w >= 0.f ? 1 : -1);
2347 int64 x = int32(m_localRotation.x * PACK_X) * w_sign & PACK_X_MASK;
2348 int64 y = int32(m_localRotation.y * PACK_YZ) * w_sign & PACK_YZ_MASK;
2349 int64 z = int32(m_localRotation.z * PACK_YZ) * w_sign & PACK_YZ_MASK;
2350 m_packedRotation = z | (y << 21) | (x << 42);
2351}
2352
2353void GameObject::SetLocalRotation(float qx, float qy, float qz, float qw)
2354{
2355 G3D::Quat rotation(qx, qy, qz, qw);
2356 rotation.unitize();
2357 m_localRotation.x = rotation.x;
2358 m_localRotation.y = rotation.y;
2359 m_localRotation.z = rotation.z;
2360 m_localRotation.w = rotation.w;
2362}
2363
2371
2372void GameObject::SetLocalRotationAngles(float z_rot, float y_rot, float x_rot)
2373{
2374 G3D::Quat quat(G3D::Matrix3::fromEulerAnglesZYX(z_rot, y_rot, x_rot));
2375 SetLocalRotation(quat.x, quat.y, quat.z, quat.w);
2376}
2377
2379{
2380 QuaternionData localRotation = GetLocalRotation();
2381 if (Transport* transport = GetTransport())
2382 {
2383 QuaternionData worldRotation = transport->GetWorldRotation();
2384
2385 G3D::Quat worldRotationQuat(worldRotation.x, worldRotation.y, worldRotation.z, worldRotation.w);
2386 G3D::Quat localRotationQuat(localRotation.x, localRotation.y, localRotation.z, localRotation.w);
2387
2388 G3D::Quat resultRotation = localRotationQuat * worldRotationQuat;
2389
2390 return QuaternionData(resultRotation.x, resultRotation.y, resultRotation.z, resultRotation.w);
2391 }
2392 return localRotation;
2393}
2394
2395void GameObject::ModifyHealth(int32 change, WorldObject* attackerOrHealer /*= nullptr*/, uint32 spellId /*= 0*/)
2396{
2397 if (!m_goValue.Building.MaxHealth || !change)
2398 return;
2399
2400 // prevent double destructions of the same object
2401 if (change < 0 && !m_goValue.Building.Health)
2402 return;
2403
2404 if (int32(m_goValue.Building.Health) + change <= 0)
2408 else
2409 m_goValue.Building.Health += change;
2410
2411 // Set the health bar, value = 255 * healthPct;
2413
2414 // dealing damage, send packet
2415 if (Player* player = attackerOrHealer ? attackerOrHealer->GetCharmerOrOwnerPlayerOrPlayerItself() : nullptr)
2416 {
2417 WorldPacket data(SMSG_DESTRUCTIBLE_BUILDING_DAMAGE, 8 + 8 + 8 + 4 + 4);
2418 data << GetPackGUID();
2419 data << attackerOrHealer->GetPackGUID();
2420 data << player->GetPackGUID();
2421 data << uint32(-change); // change < 0 triggers SPELL_BUILDING_HEAL combat log event
2422 // change >= 0 triggers SPELL_BUILDING_DAMAGE event
2423 data << uint32(spellId);
2424 player->SendDirectMessage(&data);
2425 }
2426
2428
2430 newState = GO_DESTRUCTIBLE_DESTROYED;
2431 else if (m_goValue.Building.Health <= GetGOInfo()->building.damagedNumHits)
2432 newState = GO_DESTRUCTIBLE_DAMAGED;
2434 newState = GO_DESTRUCTIBLE_INTACT;
2435
2436 if (newState == GetDestructibleState())
2437 return;
2438
2439 SetDestructibleState(newState, attackerOrHealer, false);
2440}
2441
2442void GameObject::SetDestructibleState(GameObjectDestructibleState state, WorldObject* attackerOrHealer /*= nullptr*/, bool setHealth /*= false*/)
2443{
2444 // the user calling this must know he is already operating on destructible gameobject
2446
2447 switch (state)
2448 {
2452 if (setHealth)
2453 {
2455 SetGoAnimProgress(255);
2456 }
2457 EnableCollision(true);
2458 break;
2460 {
2461 EventInform(m_goInfo->building.damagedEvent, attackerOrHealer);
2462 AI()->Damaged(attackerOrHealer, m_goInfo->building.damagedEvent);
2463
2466
2467 uint32 modelId = m_goInfo->displayId;
2469 if (modelData->State1Wmo)
2470 modelId = modelData->State1Wmo;
2471 SetDisplayId(modelId);
2472
2473 if (setHealth)
2474 {
2476 uint32 maxHealth = m_goValue.Building.MaxHealth;
2477 // in this case current health is 0 anyway so just prevent crashing here
2478 if (!maxHealth)
2479 maxHealth = 1;
2480 SetGoAnimProgress(m_goValue.Building.Health * 255 / maxHealth);
2481 }
2482 break;
2483 }
2485 {
2486 EventInform(m_goInfo->building.destroyedEvent, attackerOrHealer);
2487 AI()->Destroyed(attackerOrHealer, m_goInfo->building.destroyedEvent);
2488
2489 if (Player* player = attackerOrHealer ? attackerOrHealer->GetCharmerOrOwnerPlayerOrPlayerItself() : nullptr)
2490 if (Battleground* bg = player->GetBattleground())
2491 bg->DestroyGate(player, this);
2492
2495
2496 uint32 modelId = m_goInfo->displayId;
2498 if (modelData->State2Wmo)
2499 modelId = modelData->State2Wmo;
2500 SetDisplayId(modelId);
2501
2502 if (setHealth)
2503 {
2506 }
2507 EnableCollision(false);
2508 break;
2509 }
2511 {
2512 EventInform(m_goInfo->building.rebuildingEvent, attackerOrHealer);
2514
2515 uint32 modelId = m_goInfo->displayId;
2517 if (modelData->State3Wmo)
2518 modelId = modelData->State3Wmo;
2519 SetDisplayId(modelId);
2520
2521 // restores to full health
2522 if (setHealth)
2523 {
2525 SetGoAnimProgress(255);
2526 }
2527 EnableCollision(true);
2528 break;
2529 }
2530 }
2531}
2532
2534{
2535 m_lootState = state;
2536 if (unit)
2537 m_lootStateUnitGUID = unit->GetGUID();
2538 else
2540
2541 AI()->OnLootStateChanged(state, unit);
2542
2543 // Start restock timer if the chest is partially looted or not looted at all
2544 if (GetGoType() == GAMEOBJECT_TYPE_CHEST && state == GO_ACTIVATED)
2545 {
2546 GameObjectTemplate const* goInfo = GetGOInfo();
2547 if (goInfo->chest.chestRestockTime > 0 && m_restockTime == 0)
2549
2550 // If world chests were opened, despawn them after 5 minutes
2551 if (goInfo->chest.chestRestockTime == 0 && GetMap()->IsWorldMap())
2552 DespawnOrUnsummon(5min);
2553 }
2554
2555 if (GetGoType() == GAMEOBJECT_TYPE_DOOR) // only set collision for doors on SetGoState
2556 return;
2557
2558 if (m_model)
2559 {
2560 bool collision = false;
2561 // Use the current go state
2562 if ((GetGoState() != GO_STATE_READY && (state == GO_ACTIVATED || state == GO_JUST_DEACTIVATED)) || state == GO_READY)
2563 collision = !collision;
2564
2565 EnableCollision(collision);
2566 }
2567}
2568
2573
2575{
2577 if (AI())
2578 AI()->OnStateChanged(state);
2579 if (m_model && !IsTransport())
2580 {
2581 if (!IsInWorld())
2582 return;
2583
2584 // startOpen determines whether we are going to add or remove the LoS on activation
2585 bool collision = false;
2586 if (state == GO_STATE_READY)
2587 collision = !collision;
2588
2589 EnableCollision(collision);
2590 }
2591}
2592
2601
2603{
2605 UpdateModel();
2606}
2607
2608void GameObject::SetPhaseMask(uint32 newPhaseMask, bool update)
2609{
2610 WorldObject::SetPhaseMask(newPhaseMask, update);
2611 if (m_model && m_model->isEnabled())
2612 EnableCollision(true);
2613}
2614
2616{
2617 if (!m_model)
2618 return;
2619
2620 /*if (enable && !GetMap()->ContainsGameObjectModel(*m_model))
2621 GetMap()->InsertGameObjectModel(*m_model);*/
2622
2623 m_model->enable(enable ? GetPhaseMask() : 0);
2624}
2625
2627{
2628 if (!IsInWorld())
2629 return;
2630 if (m_model)
2631 if (GetMap()->ContainsGameObjectModel(*m_model))
2633 delete m_model;
2634 CreateModel();
2635 if (m_model)
2637}
2638
2640{
2641 if (!m_lootRecipient)
2642 return nullptr;
2644}
2645
2647{
2649 return nullptr;
2650 return sGroupMgr->GetGroupByGUID(m_lootRecipientGroup);
2651}
2652
2654{
2655 // set the player whose group should receive the right
2656 // to loot the creature after it dies
2657 // should be set to nullptr after the loot disappears
2658
2659 if (!unit)
2660 {
2662 m_lootRecipientGroup = group ? group->GetGUID() : ObjectGuid::Empty;
2663 return;
2664 }
2665
2666 if (unit->GetTypeId() != TYPEID_PLAYER && !unit->IsVehicle())
2667 return;
2668
2670 if (!player) // normal creature, no player involved
2671 return;
2672
2673 m_lootRecipient = player->GetGUID();
2674
2675 // either get the group from the passed parameter or from unit's one
2676 if (group)
2677 m_lootRecipientGroup = group->GetGUID();
2678 else if (Group* unitGroup = player->GetGroup())
2679 m_lootRecipientGroup = unitGroup->GetGUID();
2680}
2681
2682bool GameObject::IsLootAllowedFor(Player const* player) const
2683{
2685 return true;
2686
2687 if (player->GetGUID() == m_lootRecipient)
2688 return true;
2689
2690 Group const* playerGroup = player->GetGroup();
2691 if (!playerGroup || playerGroup != GetLootRecipientGroup()) // if we dont have a group we arent the recipient
2692 return false; // if go doesnt have group bound it means it was solo killed by someone else
2693
2694 return true;
2695}
2696
2701
2702void GameObject::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player const* target) const
2703{
2704 if (!target)
2705 return;
2706
2708 bool targetIsGM = target->IsGameMaster();
2709
2710 ByteBuffer fieldBuffer;
2711
2713
2715 uint32 visibleFlag = UF_FLAG_PUBLIC;
2716 if (GetOwnerGUID() == target->GetGUID())
2717 visibleFlag |= UF_FLAG_OWNER;
2718
2719 for (uint16 index = 0; index < m_valuesCount; ++index)
2720 {
2721 if (_fieldNotifyFlags & flags[index] ||
2722 ((updateType == UPDATETYPE_VALUES ? _changesMask.GetBit(index) : m_uint32Values[index]) && (flags[index] & visibleFlag)) ||
2723 (index == GAMEOBJECT_FLAGS && forcedFlags))
2724 {
2725 updateMask.SetBit(index);
2726
2727 if (index == GAMEOBJECT_DYNAMIC)
2728 {
2729 uint16 dynFlags = 0;
2730 int16 pathProgress = -1;
2731 switch (GetGoType())
2732 {
2734 if (ActivateToQuest(target))
2735 dynFlags |= GO_DYNFLAG_LO_ACTIVATE;
2736 break;
2739 if (ActivateToQuest(target))
2741 else if (targetIsGM)
2742 dynFlags |= GO_DYNFLAG_LO_ACTIVATE;
2743 break;
2745 if (ActivateToQuest(target))
2746 dynFlags |= GO_DYNFLAG_LO_SPARKLE;
2747 break;
2750 {
2751 if (uint32 transportPeriod = GetTransportPeriod())
2752 {
2753 float timer = float(m_goValue.Transport.PathProgress % transportPeriod);
2754 pathProgress = int16(timer / float(transportPeriod) * 65535.0f);
2755 }
2756 break;
2757 }
2758 default:
2759 break;
2760 }
2761
2762 fieldBuffer << uint16(dynFlags);
2763 fieldBuffer << int16(pathProgress);
2764 }
2765 else if (index == GAMEOBJECT_FLAGS)
2766 {
2769 if (GetGOInfo()->chest.groupLootRules && !IsLootAllowedFor(target))
2771
2772 fieldBuffer << goFlags;
2773 }
2774 else
2775 fieldBuffer << m_uint32Values[index]; // other cases
2776 }
2777 }
2778
2779 updateMask.AppendToPacket(data);
2780 data->append(fieldBuffer);
2781}
2782
2783void GameObject::GetRespawnPosition(float &x, float &y, float &z, float* ori /* = nullptr*/) const
2784{
2785 if (m_goData)
2786 {
2787 if (ori)
2788 m_goData->spawnPoint.GetPosition(x, y, z, *ori);
2789 else
2791 }
2792 else
2793 {
2794 if (ori)
2795 GetPosition(x, y, z, *ori);
2796 else
2797 GetPosition(x, y, z);
2798 }
2799}
2800
2802{
2803 switch (GetGoType())
2804 {
2806 return 0.0f;
2812 return 5.5555553f;
2814 return 10.0f;
2817 return 3.0f;
2819 return 100.0f;
2821 return 20.0f + CONTACT_DISTANCE; // max spell range
2827 return 5.0f;
2828 // Following values are not blizzlike
2831 // Successful mailbox interaction is rather critical to the client, failing it will start a minute-long cooldown until the next mail query may be executed.
2832 // And since movement info update is not sent with mailbox interaction query, server may find the player outside of interaction range. Thus we increase it.
2833 return 10.0f; // 5.0f is blizzlike
2834 default:
2835 return INTERACTION_DISTANCE;
2836 }
2837}
2838
2840{
2841 if (!m_model)
2842 return;
2843
2844 if (GetMap()->ContainsGameObjectModel(*m_model))
2845 {
2849 }
2850}
2851
2853{
2854public:
2855 explicit GameObjectModelOwnerImpl(GameObject* owner) : _owner(owner) { }
2856
2857 bool IsSpawned() const override { return _owner->isSpawned(); }
2858 uint32 GetDisplayId() const override { return _owner->GetDisplayId(); }
2859 uint32 GetPhaseMask() const override { return _owner->GetPhaseMask(); }
2860 G3D::Vector3 GetPosition() const override { return G3D::Vector3(_owner->GetPositionX(), _owner->GetPositionY(), _owner->GetPositionZ()); }
2861 float GetOrientation() const override { return _owner->GetOrientation(); }
2862 float GetScale() const override { return _owner->GetObjectScale(); }
2863 void DebugVisualizeCorner(G3D::Vector3 const& corner) const override { const_cast<GameObject*>(_owner)->SummonCreature(1, corner.x, corner.y, corner.z, 0, TEMPSUMMON_MANUAL_DESPAWN); }
2864
2865private:
2867};
2868
2870{
2871 m_model = GameObjectModel::Create(std::make_unique<GameObjectModelOwnerImpl>(this), sWorld->GetDataPath());
2872}
2873
2874std::string GameObject::GetDebugInfo() const
2875{
2876 std::stringstream sstr;
2877 sstr << WorldObject::GetDebugInfo() << "\n"
2878 << "SpawnId: " << GetSpawnId() << " GoState: " << std::to_string(GetGoState()) << " ScriptId: " << GetScriptId() << " AIName: " << GetAIName();
2879 return sstr.str();
2880}
2881
2882bool GameObject::IsAtInteractDistance(Player const* player, SpellInfo const* spell) const
2883{
2884 if (spell || (spell = GetSpellForLock(player)))
2885 {
2886 float maxRange = spell->GetMaxRange(spell->IsPositive());
2887
2889 return maxRange * maxRange >= GetExactDistSq(player);
2890
2891 if (sGameObjectDisplayInfoStore.LookupEntry(GetGOInfo()->displayId))
2892 return IsAtInteractDistance(*player, maxRange);
2893 }
2894
2896}
2897
2898bool GameObject::IsAtInteractDistance(Position const& pos, float radius) const
2899{
2900 if (GameObjectDisplayInfoEntry const* displayInfo = sGameObjectDisplayInfoStore.LookupEntry(GetGOInfo()->displayId))
2901 {
2902 float scale = GetObjectScale();
2903
2904 float minX = displayInfo->GeoBoxMin.X * scale - radius;
2905 float minY = displayInfo->GeoBoxMin.Y * scale - radius;
2906 float minZ = displayInfo->GeoBoxMin.Z * scale - radius;
2907 float maxX = displayInfo->GeoBoxMax.X * scale + radius;
2908 float maxY = displayInfo->GeoBoxMax.Y * scale + radius;
2909 float maxZ = displayInfo->GeoBoxMax.Z * scale + radius;
2910
2911 QuaternionData worldRotation = GetWorldRotation();
2912 G3D::Quat worldRotationQuat(worldRotation.x, worldRotation.y, worldRotation.z, worldRotation.w);
2913
2914 return G3D::CoordinateFrame { { worldRotationQuat }, { GetPositionX(), GetPositionY(), GetPositionZ() } }
2915 .toWorldSpace(G3D::Box { { minX, minY, minZ }, { maxX, maxY, maxZ } })
2916 .contains({ pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ() });
2917 }
2918
2919 return GetExactDist(&pos) <= radius;
2920}
2921
2922bool GameObject::IsWithinDistInMap(Player const* player) const
2923{
2924 return IsInMap(player) && InSamePhase(player) && IsAtInteractDistance(player);
2925}
2926
2928{
2929 if (!player)
2930 return nullptr;
2931
2932 uint32 lockId = GetGOInfo()->GetLockId();
2933 if (!lockId)
2934 return nullptr;
2935
2936 LockEntry const* lock = sLockStore.LookupEntry(lockId);
2937 if (!lock)
2938 return nullptr;
2939
2940 for (uint8 i = 0; i < MAX_LOCK_CASE; ++i)
2941 {
2942 if (!lock->Type[i])
2943 continue;
2944
2945 if (lock->Type[i] == LOCK_KEY_SPELL)
2946 if (SpellInfo const* spell = sSpellMgr->GetSpellInfo(lock->Index[i]))
2947 return spell;
2948
2949 if (lock->Type[i] != LOCK_KEY_SKILL)
2950 break;
2951
2952 for (auto&& playerSpell : player->GetSpellMap())
2953 if (SpellInfo const* spell = sSpellMgr->GetSpellInfo(playerSpell.first))
2954 for (SpellEffectInfo const& spellEffectInfo : spell->GetEffects())
2955 if (spellEffectInfo.IsEffect(SPELL_EFFECT_OPEN_LOCK) && ((uint32) spellEffectInfo.MiscValue) == lock->Index[i])
2956 if (spellEffectInfo.CalcValue(player) >= int32(lock->Skill[i]))
2957 return spell;
2958 }
2959
2960 return nullptr;
2961}
LocaleConstant
Definition Common.h:48
@ TOTAL_LOCALES
Definition Common.h:59
@ LOCALE_enUS
Definition Common.h:49
#define DEFAULT_LOCALE
Definition Common.h:62
@ IN_MILLISECONDS
Definition Common.h:35
@ MINUTE
Definition Common.h:29
@ WEEK
Definition Common.h:32
#define M_PI
Definition Common.h:72
@ ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT
Definition DBCEnums.h:195
DBCStorage< DestructibleModelDataEntry > sDestructibleModelDataStore(DestructibleModelDatafmt)
DBCStorage< LockEntry > sLockStore(LockEntryfmt)
DBCStorage< GameObjectDisplayInfoEntry > sGameObjectDisplayInfoStore(GameObjectDisplayInfofmt)
#define MAX_LOCK_CASE
SQLTransaction< WorldDatabaseConnection > WorldDatabaseTransaction
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
DatabaseWorkerPool< WorldDatabaseConnection > WorldDatabase
Accessor to the world database.
uint8_t uint8
Definition Define.h:135
int64_t int64
Definition Define.h:128
int16_t int16
Definition Define.h:130
int8_t int8
Definition Define.h:131
int32_t int32
Definition Define.h:129
uint16_t uint16
Definition Define.h:134
uint32_t uint32
Definition Define.h:133
uint16 flags
std::chrono::seconds Seconds
Seconds shorthand typedef.
Definition Duration.h:27
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition Duration.h:24
#define ASSERT
Definition Errors.h:68
#define MAX_GAMEOBJECT_QUEST_ITEMS
GameObjectActions
LootState
Definition GameObject.h:75
@ GO_ACTIVATED
Definition GameObject.h:78
@ GO_READY
Definition GameObject.h:77
@ GO_NOT_READY
Definition GameObject.h:76
@ GO_JUST_DEACTIVATED
Definition GameObject.h:79
#define FISHING_BOBBER_READY_TIME
Definition GameObject.h:83
@ GRID_MAP_TYPE_MASK_PLAYER
Definition GridDefines.h:75
@ GRID_MAP_TYPE_MASK_CREATURE
Definition GridDefines.h:72
#define sGroupMgr
Definition GroupMgr.h:58
#define TC_LOG_WARN(filterType__,...)
Definition Log.h:162
#define TC_LOG_DEBUG(filterType__,...)
Definition Log.h:156
#define TC_LOG_ERROR(filterType__,...)
Definition Log.h:165
#define TC_LOG_FATAL(filterType__,...)
Definition Log.h:168
LootStore LootTemplates_Gameobject("gameobject_loot_template", "gameobject entry", true)
LootStore LootTemplates_Fishing("fishing_loot_template", "area id", true)
@ LOOT_FISHING_JUNK
Definition Loot.h:95
@ LOOT_FISHING
Definition Loot.h:86
@ LOOT_FISHINGHOLE
Definition Loot.h:93
#define sMapMgr
Definition MapManager.h:211
#define DEFAULT_VISIBILITY_DISTANCE
@ TEMPSUMMON_MANUAL_DESPAWN
#define INTERACTION_DISTANCE
#define CONTACT_DISTANCE
@ TYPEID_GAMEOBJECT
Definition ObjectGuid.h:40
@ TYPEID_PLAYER
Definition ObjectGuid.h:39
@ TYPEMASK_GAMEOBJECT
Definition ObjectGuid.h:54
ScriptMapMap sEventScripts
Definition ObjectMgr.cpp:60
#define sObjectMgr
Definition ObjectMgr.h:1721
#define sOutdoorPvPMgr
@ TELE_TO_NOT_LEAVE_COMBAT
Definition Player.h:681
@ TELE_TO_NOT_UNSUMMON_PET
Definition Player.h:682
@ TELE_TO_NOT_LEAVE_TRANSPORT
Definition Player.h:680
#define sPoolMgr
Definition PoolMgr.h:148
@ QUEST_STATUS_INCOMPLETE
Definition QuestDef.h:107
QuestGiverStatus
Definition QuestDef.h:115
@ DIALOG_STATUS_UNAVAILABLE
Definition QuestDef.h:117
int32 irand(int32 min, int32 max)
Definition Random.cpp:35
uint32 urand(uint32 min, uint32 max)
Definition Random.cpp:42
GameobjectTypes
@ GAMEOBJECT_TYPE_GUILD_BANK
@ GAMEOBJECT_TYPE_MINI_GAME
@ GAMEOBJECT_TYPE_CAMERA
@ GAMEOBJECT_TYPE_BUTTON
@ GAMEOBJECT_TYPE_MAP_OBJECT
@ GAMEOBJECT_TYPE_SPELL_FOCUS
@ GAMEOBJECT_TYPE_TRANSPORT
@ GAMEOBJECT_TYPE_MEETINGSTONE
@ GAMEOBJECT_TYPE_TRAP
@ GAMEOBJECT_TYPE_GENERIC
@ GAMEOBJECT_TYPE_CHEST
@ GAMEOBJECT_TYPE_FISHINGHOLE
@ GAMEOBJECT_TYPE_FLAGDROP
@ GAMEOBJECT_TYPE_QUESTGIVER
@ GAMEOBJECT_TYPE_MAILBOX
@ GAMEOBJECT_TYPE_SPELLCASTER
@ GAMEOBJECT_TYPE_FLAGSTAND
@ GAMEOBJECT_TYPE_CHAIR
@ GAMEOBJECT_TYPE_TEXT
@ GAMEOBJECT_TYPE_DUNGEON_DIFFICULTY
@ GAMEOBJECT_TYPE_AREADAMAGE
@ GAMEOBJECT_TYPE_GOOBER
@ GAMEOBJECT_TYPE_FISHINGNODE
@ GAMEOBJECT_TYPE_BARBER_CHAIR
@ GAMEOBJECT_TYPE_MAP_OBJ_TRANSPORT
@ GAMEOBJECT_TYPE_DOOR
@ GAMEOBJECT_TYPE_RITUAL
@ GAMEOBJECT_TYPE_BINDER
@ GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING
@ GO_DYNFLAG_LO_ACTIVATE
@ GO_DYNFLAG_LO_SPARKLE
@ STEALTH_TRAP
@ SPELL_EFFECT_OPEN_LOCK
@ INVISIBILITY_TRAP
#define MAX_GAMEOBJECT_TYPE
@ LOCK_KEY_SKILL
@ LOCK_KEY_SPELL
#define MAX_GAMEOBJECT_DATA
GameObjectDestructibleState
@ GO_DESTRUCTIBLE_DESTROYED
@ GO_DESTRUCTIBLE_REBUILDING
@ GO_DESTRUCTIBLE_INTACT
@ GO_DESTRUCTIBLE_DAMAGED
@ LOOT_MODE_JUNK_FISH
@ BATTLEGROUND_WS
@ BATTLEGROUND_EY
GameObjectFlags
@ GO_FLAG_NODESPAWN
@ GO_FLAG_NOT_SELECTABLE
@ GO_FLAG_IN_USE
@ GO_FLAG_DESTROYED
@ GO_FLAG_LOCKED
@ GO_FLAG_DAMAGED
SpellCastResult
@ SPELL_CAST_OK
GOState
@ GO_STATE_READY
@ GO_STATE_DESTROYED
@ GO_STATE_ACTIVE
@ SKILL_FISHING
@ SPAWNGROUP_FLAG_COMPATIBILITY_MODE
Definition SpawnData.h:50
@ LINKED_RESPAWN_CREATURE_TO_GO
Definition SpawnData.h:111
@ LINKED_RESPAWN_GO_TO_GO
Definition SpawnData.h:112
@ LINKED_RESPAWN_GO_TO_CREATURE
Definition SpawnData.h:113
@ SPAWN_TYPE_GAMEOBJECT
Definition SpawnData.h:32
@ SPELL_AURA_MOD_INVISIBILITY
@ SPELL_AURA_MOUNTED
@ SPELL_AURA_MOD_STEALTH
@ TARGET_CHECK_ENEMY
Definition SpellInfo.h:81
@ TARGET_CHECK_DEFAULT
Definition SpellInfo.h:79
@ TARGET_CHECK_ALLY
Definition SpellInfo.h:82
@ TARGET_OBJECT_TYPE_UNIT
Definition SpellInfo.h:66
#define sSpellMgr
Definition SpellMgr.h:738
#define sTransportMgr
UnitStandStateType
Definition UnitDefines.h:33
@ UNIT_STAND_STATE_SIT_LOW_CHAIR
Definition UnitDefines.h:38
@ UNIT_STAND_STATE_SIT
Definition UnitDefines.h:35
@ UNIT_FLAG_IMMUNE
@ CURRENT_CHANNELED_SPELL
Definition Unit.h:608
@ UPDATETYPE_VALUES
Definition UpdateData.h:30
@ UPDATEFLAG_ROTATION
Definition UpdateData.h:50
@ UPDATEFLAG_POSITION
Definition UpdateData.h:49
@ UPDATEFLAG_LOWGUID
Definition UpdateData.h:45
@ UPDATEFLAG_TRANSPORT
Definition UpdateData.h:42
@ UPDATEFLAG_STATIONARY_POSITION
Definition UpdateData.h:47
uint32 GameObjectUpdateFieldFlags[GAMEOBJECT_END]
@ UF_FLAG_PUBLIC
@ UF_FLAG_OWNER
@ GAMEOBJECT_DYNAMIC
@ GAMEOBJECT_END
@ GAMEOBJECT_PARENTROTATION
@ GAMEOBJECT_FLAGS
@ GAMEOBJECT_BYTES_1
@ GAMEOBJECT_DISPLAYID
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
Definition Util.h:554
@ WORLD_DEL_EVENT_GAMEOBJECT
@ WORLD_DEL_SPAWNGROUP_MEMBER
@ WORLD_DEL_GAMEOBJECT
@ WORLD_DEL_LINKED_RESPAWN
@ WORLD_INS_GAMEOBJECT
@ WORLD_DEL_GAMEOBJECT_ADDON
@ WORLD_DEL_LINKED_RESPAWN_MASTER
BattlegroundTypeId GetTypeID(bool GetRandom=false) const
virtual void EventPlayerClickedOnFlag(Player *, GameObject *)
void append(T value)
Definition ByteBuffer.h:129
void AddFlag(FLAG_TYPE flag)
Definition Object.h:287
void AddValue(FLAG_TYPE flag, T_VALUES value)
Definition Object.h:292
virtual void Damaged(WorldObject *, uint32)
virtual void OnStateChanged(uint32)
virtual void InitializeAI()
virtual void UpdateAI(uint32)
virtual void Destroyed(WorldObject *, uint32)
virtual void Reset()
virtual void EventInform(uint32)
virtual void OnLootStateChanged(uint32, Unit *)
float GetScale() const override
uint32 GetDisplayId() const override
G3D::Vector3 GetPosition() const override
float GetOrientation() const override
uint32 GetPhaseMask() const override
GameObjectModelOwnerImpl(GameObject *owner)
bool IsSpawned() const override
void DebugVisualizeCorner(G3D::Vector3 const &corner) const override
bool isEnabled() const
static GameObjectModel * Create(std::unique_ptr< GameObjectModelOwnerBase > modelOwner, std::string const &dataPath)
void enable(uint32 ph_mask)
void getFishLootJunk(Loot *loot, Player *loot_owner)
void SetLocalRotationAngles(float z_rot, float y_rot, float x_rot)
bool HasStringId(std::string_view id) const
void GetRespawnPosition(float &x, float &y, float &z, float *ori=nullptr) const
void SetGoState(GOState state)
ObjectGuid GetOwnerGUID() const override
Definition GameObject.h:141
bool IsWithinDistInMap(Player const *player) const
void UseDoorOrButton(uint32 time_to_restore=0, bool alternative=false, Unit *user=nullptr)
GameObjectValue m_goValue
Definition GameObject.h:346
GameObjectTemplate const * GetGOInfo() const
Definition GameObject.h:102
void CreateModel()
GOState GetGoState() const
Definition GameObject.h:178
time_t m_respawnTime
Definition GameObject.h:321
std::string GetDebugInfo() const override
time_t m_cooldownTime
Definition GameObject.h:329
bool LoadFromDB(ObjectGuid::LowType spawnId, Map *map, bool addToMap, bool=true)
void AddUse()
Definition GameObject.h:214
void RemoveFlag(GameObjectFlags flags)
Definition GameObject.h:172
bool hasInvolvedQuest(uint32 quest_id) const override
void SetGoArtKit(uint8 artkit)
GameObjectData const * m_goData
Definition GameObject.h:345
LootState getLootState() const
Definition GameObject.h:193
uint32 GetSpellId() const
Definition GameObject.h:148
uint8 GetGoAnimProgress() const
Definition GameObject.h:183
int64 m_packedRotation
Definition GameObject.h:350
Position m_stationaryPosition
Definition GameObject.h:352
void InheritStringIds(GameObject const *parent)
void SetLootRecipient(Unit *unit, Group *group=nullptr)
void Delete()
void SetPhaseMask(uint32 newPhaseMask, bool update) override
ObjectGuid m_lootRecipientGroup
Definition GameObject.h:355
QuaternionData const & GetLocalRotation() const
Definition GameObject.h:118
time_t m_restockTime
Definition GameObject.h:328
Group * GetLootRecipientGroup() const
uint32 GetUniqueUseCount() const
Definition GameObject.h:217
void ReplaceAllFlags(GameObjectFlags flags)
Definition GameObject.h:173
void RemoveFromWorld() override
void EnableCollision(bool enable)
uint8 GetGoArtKit() const
Definition GameObject.h:181
void SetGoAnimProgress(uint8 animprogress)
Definition GameObject.h:184
ObjectGuid m_lootStateUnitGUID
Definition GameObject.h:326
uint8 GetLevelForTarget(WorldObject const *target) const override
bool IsAtInteractDistance(Position const &pos, float radius) const
bool isSpawned() const
Definition GameObject.h:155
void SetOwnerGUID(ObjectGuid owner)
Definition GameObject.h:131
void DespawnOrUnsummon(Milliseconds delay=0ms, Seconds forceRespawnTime=0s)
void SetDestructibleState(GameObjectDestructibleState state, WorldObject *attackerOrHealer=nullptr, bool setHealth=false)
ChairSlotAndUser ChairListSlots
Definition GameObject.h:340
virtual uint32 GetTransportPeriod() const
void SetScriptStringId(std::string id)
bool ActivateToQuest(Player const *target) const
void SetFlag(GameObjectFlags flags)
Definition GameObject.h:171
Player * GetLootRecipient() const
uint32 m_spellId
Definition GameObject.h:320
bool IsAlwaysVisibleFor(WorldObject const *seer) const override
std::array< std::string const *, 3 > m_stringIds
Definition GameObject.h:347
bool HasLootRecipient() const
Definition GameObject.h:227
void SetLootState(LootState s, Unit *unit=nullptr)
uint32 m_respawnDelayTime
Definition GameObject.h:322
SpellInfo const * GetSpellForLock(Player const *player) const
GameObjectAI * AI() const
Definition GameObject.h:275
void ResetLootMode()
Definition GameObject.h:202
GuidSet m_unique_users
Definition GameObject.h:336
GameObject * GetLinkedTrap()
bool IsInRange(float x, float y, float z, float radius) const
void SetRespawnTime(int32 respawn)
void TriggeringLinkedGameObject(uint32 trapEntry, Unit *target)
void SetRespawnCompatibilityMode(bool mode=true)
Definition GameObject.h:270
GameobjectTypes GetGoType() const
Definition GameObject.h:176
void SetGoType(GameobjectTypes type)
Definition GameObject.h:177
uint32 m_despawnDelay
Definition GameObject.h:323
Seconds m_despawnRespawnTime
Definition GameObject.h:324
QuaternionData m_localRotation
Definition GameObject.h:351
void SetLinkedTrap(GameObject *linkedTrap)
Definition GameObject.h:232
void SetLocalRotation(float qx, float qy, float qz, float qw)
GameObjectData const * GetGameObjectData() const
Definition GameObject.h:105
bool m_respawnCompatibilityMode
Definition GameObject.h:374
GameObjectTemplateAddon const * m_goTemplateAddon
Definition GameObject.h:344
ObjectGuid::LowType GetSpawnId() const
Definition GameObject.h:112
bool AIM_Initialize()
void SaveRespawnTime(uint32 forceDelay=0)
float GetInteractionDistance() const
void RemoveFromOwner()
void ActivateObject(GameObjectActions action, WorldObject *spellCaster=nullptr, uint32 spellId=0, int32 effectIndex=-1)
void SendCustomAnim(uint32 anim)
void Refresh()
time_t GetRespawnTimeEx() const
bool hasQuest(uint32 quest_id) const override
GameObjectAI * m_AI
Definition GameObject.h:373
uint32 GetDisplayId() const
Definition GameObject.h:283
GameObjectModel * m_model
Definition GameObject.h:288
void ResetDoorOrButton()
void SetLevel(uint32 level)
Definition GameObject.h:175
uint32 GetScriptId() const
Optional< std::string > m_scriptStringId
Definition GameObject.h:348
void UpdateModelPosition()
void AIM_Destroy()
GameObjectTemplateAddon const * GetTemplateAddon() const
Definition GameObject.h:103
void ModifyHealth(int32 change, WorldObject *attackerOrHealer=nullptr, uint32 spellId=0)
GameObject * LookupFishingHoleAround(float range)
void SetDisplayId(uint32 displayid)
GameObjectTemplate const * m_goInfo
Definition GameObject.h:343
void SetLootGenerationTime()
ObjectGuid::LowType m_spawnId
For new or temporary gameobjects is 0 for saved it is lowguid.
Definition GameObject.h:342
uint32 m_groupLootTimer
Definition GameObject.h:228
std::string_view GetStringId(StringIdType type) const
Definition GameObject.h:280
void UpdateModel()
void Use(Unit *user)
ObjectGuid m_linkedTrap
Definition GameObject.h:359
bool IsDynTransport() const
void SwitchDoorOrButton(bool activate, bool alternative=false)
void CleanupsBeforeDelete(bool finalCleanup=true) override
bool IsDestructibleBuilding() const
void SaveToDB()
bool IsNeverVisible(bool allowServersideObjects) const override
bool IsInvisibleDueToDespawn() const override
QuaternionData GetWorldRotation() const
static bool DeleteFromDB(ObjectGuid::LowType spawnId)
void getFishLoot(Loot *loot, Player *loot_owner)
void UpdatePackedRotation()
Transport * ToTransport()
Definition GameObject.h:291
bool m_spawnedByDefault
Definition GameObject.h:327
void AddToWorld() override
GameObjectDestructibleState GetDestructibleState() const
Definition GameObject.h:258
void Update(uint32 p_time) override
bool IsLootAllowedFor(Player const *player) const
LootState m_lootState
Definition GameObject.h:325
void AddUniqueUse(Player *player)
std::string const & GetAIName() const
GameObjectOverride const * GetGameObjectOverride() const
void SetParentRotation(QuaternionData const &rotation)
ObjectGuid lootingGroupLowGUID
Definition GameObject.h:229
ObjectGuid m_ritualOwnerGUID
Definition GameObject.h:335
bool Create(ObjectGuid::LowType guidlow, uint32 name_id, Map *map, uint32 phaseMask, Position const &pos, QuaternionData const &rotation, uint32 animprogress, GOState go_state, uint32 artKit=0, bool dynamic=false, ObjectGuid::LowType spawnid=0)
std::string const & GetNameForLocaleIdx(LocaleConstant locale) const override
uint32 m_usetimes
Definition GameObject.h:337
void EventInform(uint32 eventId, WorldObject *invoker=nullptr)
void SetSpellId(uint32 id)
Definition GameObject.h:143
GOState m_prevGoState
Definition GameObject.h:331
void BuildValuesUpdate(uint8 updatetype, ByteBuffer *data, Player const *target) const override
bool IsTransport() const
ObjectGuid m_lootRecipient
Definition GameObject.h:354
void SetFaction(uint32 faction) override
Definition GameObject.h:286
uint32 m_lootGenerationTime
Definition GameObject.h:357
GuidSet m_SkillupList
Definition GameObject.h:333
Definition Group.h:165
ObjectGuid GetGUID() const
Definition Group.cpp:2473
bool IsMember(ObjectGuid guid) const
Definition Group.cpp:2505
bool HaveQuestLootForPlayer(uint32 loot_id, Player const *player) const
Definition LootMgr.cpp:208
Definition Map.h:281
void ScriptsStart(std::map< uint32, std::multimap< uint32, ScriptInfo > > const &scripts, uint32 id, Object *source, Object *target)
Put scripts in the execution queue.
MapStoredObjectTypesContainer & GetObjectsStore()
Definition Map.h:489
void RemoveGameObjectModel(GameObjectModel const &model)
Definition Map.h:535
bool AddToMap(T *)
Definition Map.cpp:630
time_t GetLinkedRespawnTime(ObjectGuid guid) const
Definition Map.cpp:4542
void RemoveRespawnTime(SpawnObjectType type, ObjectGuid::LowType spawnId, CharacterDatabaseTransaction dbTrans=nullptr, bool alwaysDeleteFromDB=false)
Definition Map.h:753
bool Is25ManRaid() const
Definition Map.cpp:4261
void ApplyDynamicModeRespawnScaling(WorldObject const *obj, ObjectGuid::LowType spawnId, uint32 &respawnDelay, uint32 mode) const
Definition Map.cpp:3312
ObjectGuid::LowType GenerateLowGuid()
Definition Map.h:587
time_t GetGORespawnTime(ObjectGuid::LowType spawnId) const
Definition Map.h:555
void SaveRespawnInfoDB(RespawnInfo const &info, CharacterDatabaseTransaction dbTrans=nullptr)
Definition Map.cpp:4493
void SaveRespawnTime(SpawnObjectType type, ObjectGuid::LowType spawnId, uint32 entry, time_t respawnTime, uint32 gridId, CharacterDatabaseTransaction dbTrans=nullptr, bool startup=false)
Definition Map.cpp:4460
GameObjectBySpawnIdContainer & GetGameObjectBySpawnIdStore()
Definition Map.h:496
void InsertGameObjectModel(GameObjectModel const &model)
Definition Map.h:536
uint32 GetId() const
Definition Map.cpp:4216
void Respawn(RespawnInfo *info, CharacterDatabaseTransaction dbTrans=nullptr)
Definition Map.cpp:3105
static ObjectGuid const Empty
Definition ObjectGuid.h:140
bool IsEmpty() const
Definition ObjectGuid.h:172
std::string ToString() const
uint32 LowType
Definition ObjectGuid.h:142
void Clear()
Definition ObjectGuid.h:150
static std::string_view GetLocaleString(std::vector< std::string > const &data, size_t locale)
Definition ObjectMgr.h:1525
void SetByteValue(uint16 index, uint8 offset, uint8 value)
Definition Object.cpp:668
void BuildValuesUpdateBlockForPlayer(UpdateData *data, Player const *target) const
Definition Object.cpp:214
uint16 m_objectType
Definition Object.h:232
float GetObjectScale() const
Definition Object.h:84
PackedGuid const & GetPackGUID() const
Definition Object.h:80
static Unit * ToUnit(Object *o)
Definition Object.h:192
bool IsInWorld() const
Definition Object.h:73
uint16 _fieldNotifyFlags
Definition Object.h:248
void AddToObjectUpdateIfNeeded()
Definition Object.cpp:473
UpdateMask _changesMask
Definition Object.h:244
TypeID GetTypeId() const
Definition Object.h:93
uint32 * m_uint32Values
Definition Object.h:240
uint16 m_valuesCount
Definition Object.h:246
uint32 GetEntry() const
Definition Object.h:81
void _Create(ObjectGuid const &guid)
Definition Object.cpp:109
void SetFloatValue(uint16 index, float value)
Definition Object.cpp:655
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:78
void SetEntry(uint32 entry)
Definition Object.h:82
virtual void SetObjectScale(float scale)
Definition Object.h:85
void SetUInt32Value(uint16 index, uint32 value)
Definition Object.cpp:585
uint16 m_updateFlag
Definition Object.h:235
ObjectGuid GetGUID() const
Definition Object.h:79
TypeID m_objectTypeId
Definition Object.h:234
static Player * ToPlayer(Object *o)
Definition Object.h:180
Unit * ToUnit()
Definition Object.h:194
uint32 GetTeam() const
Definition Player.h:1832
bool IsInSameRaidWith(Player const *p) const
Definition Player.cpp:2297
bool UpdateFishingSkill()
Definition Player.cpp:5523
void SendDirectMessage(WorldPacket const *data) const
Definition Player.cpp:6161
uint16 GetSkillValue(uint32 skill) const
Definition Player.cpp:5892
void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1=0, uint32 miscValue2=0, WorldObject *ref=nullptr)
Definition Player.cpp:24940
bool CanUseBattlegroundObject(GameObject *gameobject) const
Definition Player.cpp:24193
void SendPreparedGossip(WorldObject *source)
Definition Player.cpp:14052
PlayerSpellMap const & GetSpellMap() const
Definition Player.h:1534
bool HasQuestForGO(int32 goId) const
Definition Player.cpp:23226
void SendLoot(ObjectGuid guid, LootType loot_type)
Definition Player.cpp:8079
Battleground * GetBattleground() const
Definition Player.cpp:23049
Group * GetGroup()
Definition Player.h:2171
bool IsGameMaster() const
Definition Player.h:998
void SendCinematicStart(uint32 CinematicSequenceId) const
Definition Player.cpp:6166
bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options=0)
Definition Player.cpp:1524
QuestStatus GetQuestStatus(uint32 quest_id) const
Definition Player.cpp:15642
void PrepareGossipMenu(WorldObject *source, uint32 menuId=0, bool showQuests=false)
Definition Player.cpp:13886
void setUInt16(uint8 index, uint16 value)
void setUInt32(uint8 index, uint32 value)
void setFloat(uint8 index, float value)
void setInt32(uint8 index, int32 value)
void setUInt8(uint8 index, uint8 value)
float GetMaxRange(bool positive=false, WorldObject *caster=nullptr, Spell *spell=nullptr) const
uint32 Id
Definition SpellInfo.h:289
bool IsPositive() const
bool Remove(KEY_TYPE const &handle)
bool Insert(KEY_TYPE const &handle, SPECIFIC_TYPE *obj)
Definition Unit.h:769
bool IsVehicle() const
Definition Unit.h:887
Vehicle * GetVehicle() const
Definition Unit.h:1737
void RemoveAurasByType(AuraType auraType, std::function< bool(AuraApplication const *)> const &check, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Definition Unit.cpp:3765
void RemoveGameObject(GameObject *gameObj, bool del)
Definition Unit.cpp:5111
void FinishSpell(CurrentSpellTypes spellType, bool ok=true)
Definition Unit.cpp:3051
void SetStandState(UnitStandStateType state)
Definition Unit.cpp:10363
ObjectGuid GetTarget() const
Definition Unit.h:1797
uint8 GetLevel() const
Definition Unit.h:889
Spell * GetCurrentSpell(CurrentSpellTypes spellType) const
Definition Unit.h:1476
bool BuildPacket(WorldPacket *packet)
void SetBit(uint32 bit)
Definition UpdateMask.h:81
void AppendToPacket(ByteBuffer *data)
Definition UpdateMask.h:87
bool GetBit(uint32 index) const
Definition UpdateMask.h:40
uint32 GetMapId() const
Definition Position.h:193
virtual void SetPhaseMask(uint32 newPhaseMask, bool update)
Definition Object.cpp:3417
uint32 GetPhaseMask() const
Definition Object.h:368
bool IsWithinDist3d(float x, float y, float z, float dist) const
Definition Object.cpp:1167
virtual void SendMessageToSet(WorldPacket const *data, bool self) const
Definition Object.cpp:1783
Map * GetMap() const
Definition Object.h:449
void AddToWorld() override
Definition Object.cpp:1060
void RemoveFromWorld() override
Definition Object.cpp:1066
virtual bool IsInvisibleDueToDespawn() const
Definition Object.h:625
FlaggedValuesArray32< int32, uint32, InvisibilityType, TOTAL_INVISIBILITY_TYPES > m_invisibility
Definition Object.h:441
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2832
std::string GetDebugInfo() const override
Definition Object.cpp:3614
uint32 LastUsedScriptID
Definition Object.h:561
Unit * GetOwner() const
Definition Object.cpp:2180
ZoneScript * GetZoneScript() const
Definition Object.h:455
void SetZoneScript()
Definition Object.cpp:1971
float GetDistance2d(WorldObject const *obj) const
Definition Object.cpp:1141
ZoneScript * m_zoneScript
Definition Object.h:605
bool InSamePhase(uint32 phasemask) const
Definition Object.h:369
std::string const & GetName() const
Definition Object.h:382
virtual void SetMap(Map *map)
Definition Object.cpp:1808
virtual bool IsAlwaysVisibleFor(WorldObject const *) const
Definition Object.h:624
void AddObjectToRemoveList()
Definition Object.cpp:1838
virtual bool IsNeverVisible(bool allowServersideObjects) const
Definition Object.h:623
void DestroyForNearbyPlayers()
Definition Object.cpp:3449
Transport * GetTransport() const
Definition Object.h:564
void UpdatePositionData()
Definition Object.cpp:1042
Player * GetCharmerOrOwnerPlayerOrPlayerItself() const
Definition Object.cpp:2203
void SetName(std::string newname)
Definition Object.h:383
void SendObjectDeSpawnAnim(ObjectGuid guid)
Definition Object.cpp:1801
FlaggedValuesArray32< int32, uint32, StealthType, TOTAL_STEALTH_TYPES > m_stealth
Definition Object.h:438
void SetVisibilityDistanceOverride(VisibilityDistanceType type)
Definition Object.cpp:1022
void GetZoneAndAreaId(uint32 &zoneid, uint32 &areaid) const
Definition Object.h:375
bool IsFriendlyTo(WorldObject const *target) const
Definition Object.cpp:2801
bool IsInMap(WorldObject const *obj) const
Definition Object.cpp:1160
virtual void Update(uint32 diff)
Definition Object.cpp:960
virtual void UpdateObjectVisibility(bool forced=true)
Definition Object.cpp:3482
virtual void CleanupsBeforeDelete(bool finalCleanup=true)
Definition Object.cpp:1031
WorldPacket const * Write() override
WorldPacket && Move()
Definition Packet.h:53
virtual uint32 GetGameObjectEntry(ObjectGuid::LowType, uint32 entry)
Definition ZoneScript.h:37
virtual void OnGameObjectRemove(GameObject *)
Definition ZoneScript.h:43
virtual void ProcessEvent(WorldObject *, uint32)
Definition ZoneScript.h:58
virtual void OnGameObjectCreate(GameObject *)
Definition ZoneScript.h:42
@ SMSG_GAMEOBJECT_PAGETEXT
Definition Opcodes.h:508
@ SMSG_GAMEOBJECT_CUSTOM_ANIM
Definition Opcodes.h:208
@ SMSG_FISH_ESCAPED
Definition Opcodes.h:486
@ SMSG_ENABLE_BARBER_SHOP
Definition Opcodes.h:1092
@ SMSG_DESTRUCTIBLE_BUILDING_DAMAGE
Definition Opcodes.h:79
@ SMSG_FISH_NOT_HOOKED
Definition Opcodes.h:485
#define sWorld
Definition World.h:900
@ CONFIG_RESPAWN_DYNAMICMODE
Definition World.h:395
ObjectData const gameObjectData[]
GameObjectAI * SelectGameObjectAI(GameObject *go)
time_t GetGameTime()
Definition GameTime.cpp:42
uint32 GetGameTimeMS()
Definition GameTime.cpp:47
TC_GAME_API Unit * GetUnit(WorldObject const &, ObjectGuid const &guid)
TC_GAME_API GameObject * GetGameObject(WorldObject const &u, ObjectGuid const &guid)
TC_GAME_API Player * FindPlayer(ObjectGuid const &)
TC_GAME_API Player * GetPlayer(Map const *, ObjectGuid const &guid)
TC_GAME_API Player * FindConnectedPlayer(ObjectGuid const &)
auto SelectRandomContainerElement(C const &container) -> typename std::add_const< decltype(*std::begin(container))>::type &
Definition Containers.h:108
void MultimapErasePair(M< K, V, Rest... > &multimap, K const &key, V const &value)
Definition MapUtils.h:39
GridCoord ComputeGridCoord(float x, float y)
CastSpellExtraArgs & SetOriginalCaster(ObjectGuid const &guid)
static void VisitAllObjects(WorldObject const *obj, T &visitor, float radius, bool dont_load=true)
Definition CellImpl.h:192
static void VisitGridObjects(WorldObject const *obj, T &visitor, float radius, bool dont_load=true)
Definition CellImpl.h:168
static void VisitWorldObjects(WorldObject const *obj, T &visitor, float radius, bool dont_load=true)
Definition CellImpl.h:180
QuaternionData ParentRotation
InvisibilityType invisibilityType
QuaternionData rotation
std::array< uint32, 4 > artKits
struct GameObjectTemplate::@191::@210 spellcaster
struct GameObjectTemplate::@191::@199 chair
bool CannotBeUsedUnderImmunity() const
uint32 GetAutoCloseTime() const
WorldPacket QueryData[TOTAL_LOCALES]
bool IsLargeGameObject() const
bool IsUsableMounted() const
WorldPacket BuildQueryData(LocaleConstant loc) const
bool IsInfiniteGameObject() const
bool IsDespawnAtAction() const
struct GameObjectTemplate::@191::@223 raw
uint32 GetCharges() const
struct GameObjectTemplate::@191::@203 transport
struct GameObjectTemplate::@191::@219 barberChair
struct GameObjectTemplate::@191::@202 goober
bool GetDespawnPossibility() const
struct GameObjectTemplate::@191::@205 camera
struct GameObjectTemplate::@191::@207 summoningRitual
struct GameObjectTemplate::@191::@196 chest
struct GameObjectTemplate::@191::@220 building
std::string castBarCaption
struct GameObjectTemplate::@191::@198 trap
uint32 GetLockId() const
struct GameObjectTemplate::@191::@197 _generic
uint32 GetLootId() const
uint32 Type[MAX_LOCK_CASE]
uint32 Index[MAX_LOCK_CASE]
uint32 Skill[MAX_LOCK_CASE]
Definition Loot.h:207
bool empty() const
Definition Loot.h:238
void clear()
Definition Loot.cpp:148
bool FillLoot(uint32 lootId, LootStore const &store, Player *lootOwner, bool personal, bool noEmptyError=false, uint16 lootMode=LOOT_MODE_DEFAULT)
Definition Loot.cpp:220
uint8 maxDuplicates
Definition Loot.h:221
std::string ToString() const
Definition Position.cpp:149
float GetExactDist(float x, float y, float z) const
Definition Position.h:121
float GetPositionZ() const
Definition Position.h:81
float GetOrientation() const
Definition Position.h:82
bool IsPositionValid() const
Definition Position.cpp:44
Position GetPosition() const
Definition Position.h:87
float GetPositionX() const
Definition Position.h:79
void GetPosition(float &x, float &y) const
Definition Position.h:84
float GetPositionY() const
Definition Position.h:80
float GetExactDistSq(float x, float y, float z) const
Definition Position.h:113
void Relocate(float x, float y)
Definition Position.h:66
void toEulerAnglesZYX(float &Z, float &Y, float &X) const
bool isUnit() const
static QuaternionData fromEulerAnglesZYX(float Z, float Y, float X)
ObjectGuid::LowType spawnId
Definition Map.h:260
time_t respawnTime
Definition Map.h:262
SpawnObjectType type
Definition Map.h:259
uint32 phaseMask
Definition SpawnData.h:98
uint8 spawnMask
Definition SpawnData.h:100
uint32 id
Definition SpawnData.h:96
Position spawnPoint
Definition SpawnData.h:97
int32 spawntimesecs
Definition SpawnData.h:99
std::string StringId
Definition SpawnData.h:102
SpawnGroupFlags flags
Definition SpawnData.h:63
uint32 spawnId
Definition SpawnData.h:85
SpawnGroupTemplateData const * spawnGroupData
Definition SpawnData.h:88
uint32 mapId
Definition SpawnData.h:86
uint32 QuestItems[MAX_GAMEOBJECT_QUEST_ITEMS]
uint32 Data[MAX_GAMEOBJECT_DATA]
struct GameObjectValue::@190 Building
struct GameObjectValue::@187 Transport
struct GameObjectValue::@188 FishingHole
uint32 CurrentSeg
Definition GameObject.h:50
SpellTargetCheckTypes TargetSearcherCheckType
Definition GameObject.h:43
uint32 PathProgress
Definition GameObject.h:48
TransportAnimation const * AnimationInfo
Definition GameObject.h:49
struct GameObjectValue::@186 Trap