TrinityCore
Loading...
Searching...
No Matches
Creature.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 "Creature.h"
19#include "BattlegroundMgr.h"
20#include "CellImpl.h"
21#include "CharmInfo.h"
22#include "CombatPackets.h"
23#include "Containers.h"
24#include "CreatureAI.h"
25#include "CreatureAISelector.h"
26#include "CreatureGroups.h"
27#include "DB2Stores.h"
28#include "DatabaseEnv.h"
29#include "Formulas.h"
30#include "GameEventMgr.h"
31#include "GameTime.h"
32#include "GridNotifiersImpl.h"
33#include "Group.h"
34#include "ItemTemplate.h"
35#include "Log.h"
36#include "Loot.h"
37#include "LootMgr.h"
38#include "MapManager.h"
39#include "MapUtils.h"
40#include "MiscPackets.h"
41#include "MotionMaster.h"
42#include "ObjectAccessor.h"
43#include "ObjectMgr.h"
44#include "PhasingHandler.h"
45#include "Player.h"
46#include "PoolMgr.h"
47#include "QueryPackets.h"
48#include "ScriptedGossip.h"
49#include "Spell.h"
50#include "SpellAuraEffects.h"
51#include "SpellMgr.h"
52#include "TemporarySummon.h"
53#include "Vehicle.h"
54#include "World.h"
55#include "ZoneScript.h"
56#include <G3D/g3dmath.h>
57#include <sstream>
58
60Random(CreatureRandomMovementType::Walk), InteractionPauseTimer(sWorld->getIntConfig(CONFIG_CREATURE_STOP_FOR_PLAYER)) { }
61
63{
64 char const* const ChaseStates[] = { "Run", "CanWalk", "AlwaysWalk" };
65 char const* const RandomStates[] = { "Walk", "CanRun", "AlwaysRun" };
66
67 std::ostringstream str;
68 str << std::boolalpha
69 << ", HoverInitiallyEnabled: " << HoverInitiallyEnabled
70 << ", Chase: " << ChaseStates[AsUnderlyingType(Chase)]
71 << ", Random: " << RandomStates[AsUnderlyingType(Random)];
72 str << ", InteractionPauseTimer: " << InteractionPauseTimer;
73
74 return str.str();
75}
76
78 : itemId(_item), count(_count), lastIncrementTime(GameTime::GetGameTime()) { }
79
81{
82 auto newEnd = std::remove_if(m_items.begin(), m_items.end(), [=](VendorItem const& vendorItem)
83 {
84 return vendorItem.item == item_id && vendorItem.Type == type;
85 });
86
87 bool found = newEnd != m_items.end();
88 m_items.erase(newEnd, m_items.end());
89 return found;
90}
91
92VendorItem const* VendorItemData::FindItemCostPair(uint32 item_id, uint32 extendedCost, uint8 type) const
93{
94 for (VendorItem const& vendorItem : m_items)
95 if (vendorItem.item == item_id && vendorItem.ExtendedCost == extendedCost && vendorItem.Type == type)
96 return &vendorItem;
97 return nullptr;
98}
99
102
104CreatureTemplate::CreatureTemplate(CreatureTemplate&& other) noexcept = default;
107
109{
110 return idx < Models.size() ? &Models[idx] : nullptr;
111}
112
114{
115 if (!Models.size())
116 return nullptr;
117
118 // If only one element, ignore the Probability (even if 0)
119 if (Models.size() == 1)
120 return &Models[0];
121
123 {
124 return model.Probability;
125 });
126
127 return &(*selectedItr);
128}
129
131{
132 for (CreatureModel const& model : Models)
133 if (model.CreatureDisplayID)
134 return &model;
135
136 return nullptr;
137}
138
140{
141 for (CreatureModel const& model : Models)
142 if (displayId == model.CreatureDisplayID)
143 return &model;
144
145 return nullptr;
146}
147
149{
150 for (CreatureModel const& model : Models)
151 if (CreatureModelInfo const* modelInfo = sObjectMgr->GetCreatureModelInfo(model.CreatureDisplayID))
152 if (modelInfo && modelInfo->is_trigger)
153 return &model;
154
156}
157
159{
160 for (CreatureModel const& model : Models)
161 if (CreatureModelInfo const* modelInfo = sObjectMgr->GetCreatureModelInfo(model.CreatureDisplayID))
162 if (modelInfo && !modelInfo->is_trigger)
163 return &model;
164
166}
167
169{
170 QueryData = std::make_unique<WorldPacket[]>(TOTAL_LOCALES);
171
172 for (uint8 loc = LOCALE_enUS; loc < TOTAL_LOCALES; ++loc)
173 {
174 if (!sWorld->getBoolConfig(CONFIG_LOAD_LOCALES) && loc != DEFAULT_LOCALE)
175 continue;
176
177 QueryData[loc] = BuildQueryData(static_cast<LocaleConstant>(loc), DIFFICULTY_NONE);
178 }
179}
180
182{
183 CreatureDifficulty const* creatureDifficulty = GetDifficulty(difficulty);
184
186
187 queryTemp.CreatureID = Entry;
188
189 queryTemp.Allow = true;
190
191 WorldPackets::Query::CreatureStats& stats = queryTemp.Stats;
192
193 stats.Leader = RacialLeader;
194
195 stats.Name[0] = Name;
196 stats.NameAlt[0] = FemaleName;
197
198 stats.Flags[0] = creatureDifficulty->TypeFlags;
199 stats.Flags[1] = creatureDifficulty->TypeFlags2;
200 stats.Flags[2] = creatureDifficulty->TypeFlags3;
201
202 stats.CreatureType = type;
203 stats.CreatureFamily = family;
205
206 for (uint32 i = 0; i < MAX_KILL_CREDIT; ++i)
207 stats.ProxyCreatureID[i] = KillCredit[i];
208
209 std::transform(Models.begin(), Models.end(), std::back_inserter(stats.Display.CreatureDisplay),
211 {
212 stats.Display.TotalProbability += model.Probability;
213 return { model.CreatureDisplayID, model.DisplayScale, model.Probability };
214 });
215
216 stats.HpMulti = creatureDifficulty->HealthModifier;
217 stats.EnergyMulti = creatureDifficulty->ManaModifier;
218
219 stats.CreatureMovementInfoID = movementId;
220 stats.RequiredExpansion = RequiredExpansion;
221 stats.HealthScalingExpansion = creatureDifficulty->HealthScalingExpansion;
222 stats.VignetteID = VignetteID;
223 stats.Class = unit_class;
224 stats.CreatureDifficultyID = creatureDifficulty->CreatureDifficultyID;
225 stats.WidgetSetID = WidgetSetID;
226 stats.WidgetSetUnitConditionID = WidgetSetUnitConditionID;
227
228 stats.Title = SubName;
229 stats.TitleAlt = TitleAlt;
230 stats.CursorName = IconName;
231
232 if (std::vector<uint32> const* items = sObjectMgr->GetCreatureQuestItemList(Entry, difficulty))
233 stats.QuestItems.assign(items->begin(), items->end());
234
235 if (std::vector<int32> const* currencies = sObjectMgr->GetCreatureQuestCurrencyList(Entry))
236 stats.QuestCurrencies.assign(currencies->begin(), currencies->end());
237
238 if (loc != LOCALE_enUS)
239 if (CreatureLocale const* creatureLocale = sObjectMgr->GetCreatureLocale(Entry))
240 {
241 ObjectMgr::GetLocaleString(creatureLocale->Name, loc, stats.Name[0]);
242 ObjectMgr::GetLocaleString(creatureLocale->NameAlt, loc, stats.NameAlt[0]);
243 ObjectMgr::GetLocaleString(creatureLocale->Title, loc, stats.Title);
244 ObjectMgr::GetLocaleString(creatureLocale->TitleAlt, loc, stats.TitleAlt);
245 }
246
247 queryTemp.Write();
248 queryTemp.ShrinkToFit();
249 return queryTemp.Move();
250}
251
253{
254 auto it = difficultyStore.find(difficulty);
255 if (it != difficultyStore.end())
256 return &it->second;
257
258 // If there is no data for the difficulty, try to get data for the fallback difficulty
259 DifficultyEntry const* difficultyEntry = sDifficultyStore.LookupEntry(difficulty);
260 if (difficultyEntry)
261 return GetDifficulty(Difficulty(difficultyEntry->FallbackDifficultyID));
262
263 // No data for DIFFICULTY_NONE (0)
264 static CreatureDifficulty constexpr DefDifficulty =
265 {
266 .DeltaLevelMin = 0,
267 .DeltaLevelMax = 0,
268 .ContentTuningID = 0,
269 .HealthScalingExpansion = 0,
270 .HealthModifier = 1.f,
271 .ManaModifier = 1.f,
272 .ArmorModifier = 1.f,
273 .DamageModifier = 1.f,
274 .CreatureDifficultyID = 0,
275 .TypeFlags = 0,
276 .TypeFlags2 = 0,
277 .TypeFlags3 = 0,
278 .LootID = 0,
279 .PickPocketLootID = 0,
280 .SkinLootID = 0,
281 .GoldMin = 0,
282 .GoldMax = 0,
283 .StaticFlags = CreatureStaticFlagsHolder()
284 };
285 return &DefDifficulty;
286}
287
288bool AssistDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
289{
291 {
292 while (!m_assistants.empty())
293 {
295 m_assistants.pop_front();
296
297 if (assistant && assistant->CanAssistTo(&m_owner, victim))
298 {
299 assistant->SetNoCallAssistance(true);
300 assistant->EngageWithTarget(victim);
301 }
302 }
303 }
304 return true;
305}
306
308{
309 return sObjectMgr->GetCreatureBaseStats(level, unitClass);
310}
311
313{
314 m_owner.DespawnOrUnsummon(0s, m_respawnTimer); // since we are here, we are not TempSummon as object type cannot change during runtime
315 return true;
316}
317
318Creature::Creature(bool isWorldObject) : Unit(isWorldObject), MapObject(), m_PlayerDamageReq(0), m_dontClearTapListOnEvade(false), _pickpocketLootRestore(0),
319 m_corpseRemoveTime(0), m_respawnTime(0), m_respawnDelay(300), m_corpseDelay(60), m_ignoreCorpseDecayRatio(false), m_wanderDistance(0.0f),
320 m_boundaryCheckTime(2500), m_reactState(REACT_AGGRESSIVE),
321 m_defaultMovementType(IDLE_MOTION_TYPE), m_spawnId(UI64LIT(0)), m_equipmentId(0), m_originalEquipmentId(0),
322 m_AlreadyCallAssistance(false), m_AlreadySearchedAssistance(false), m_cannotReachTarget(false), m_cannotReachTimer(0),
323 m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_baseAttackPower(0), m_baseRangedAttackPower(0), m_originalEntry(0),
324 m_homePosition(), m_transportHomePosition(), m_creatureInfo(nullptr), m_creatureData(nullptr), m_creatureDifficulty(nullptr), m_stringIds(),
325 _waypointPathId(0), _currentWaypointNodeInfo(0, 0), m_formation(nullptr), m_triggerJustAppeared(true), m_respawnCompatibilityMode(false),
326 _aggroGracePeriodExpired(false), _lastDamagedTime(0), _regenerateHealth(true), _creatureImmunitiesId(0), _gossipMenuId(0), _sparringHealthPct(0)
327{
329
330 for (uint8 i = 0; i < MAX_CREATURE_SPELLS; ++i)
331 m_spells[i] = 0;
332
333 DisableReputationGain = false;
334
336 m_CombatDistance = 0;//MELEE_RANGE;
337
338 ResetLootMode(); // restore default loot mode
339 m_isTempWorldObject = false;
340}
341
342Creature::~Creature() = default;
343
345{
347 if (!IsInWorld())
348 {
350 if (m_spawnId)
351 GetMap()->GetCreatureBySpawnIdStore().insert(std::make_pair(m_spawnId, this));
352
356 if (IsVehicle())
358
359 if (GetZoneScript())
361 }
362}
363
365{
366 if (IsInWorld())
367 {
368 if (GetZoneScript())
370
371 if (m_formation)
373
375
376 if (m_spawnId)
377 Trinity::Containers::MultimapErasePair(GetMap()->GetCreatureBySpawnIdStore(), m_spawnId, this);
379 }
380}
381
383{
384 if (GetMotionMaster()->GetCurrentMovementGeneratorType() == HOME_MOTION_TYPE)
385 return true;
386
387 return false;
388}
389
391{
392 if (IsSummon())
393 return;
394
396 if (!lowguid)
397 return;
398
399 if (FormationInfo const* formationInfo = sFormationMgr->GetFormationInfo(lowguid))
400 FormationMgr::AddCreatureToGroup(formationInfo->LeaderSpawnId, this);
401}
402
404{
405 if (!m_formation)
406 return false;
407
408 return m_formation->IsLeader(this);
409}
410
412{
413 if (!m_formation)
414 return;
415
416 if (!m_formation->IsLeader(this))
417 return;
418
420}
421
423{
424 if (!m_formation)
425 return false;
426
428}
429
430void Creature::RemoveCorpse(bool setSpawnTime, bool destroyForNearbyPlayers)
431{
432 if (getDeathState() != CORPSE)
433 return;
434
436 {
440 m_loot = nullptr;
441 uint32 respawnDelay = m_respawnDelay;
442 if (CreatureAI* ai = AI())
443 ai->CorpseRemoved(respawnDelay);
444
445 if (destroyForNearbyPlayers)
447
448 // Should get removed later, just keep "compatibility" with scripts
449 if (setSpawnTime)
450 m_respawnTime = std::max<time_t>(GameTime::GetGameTime() + respawnDelay, m_respawnTime);
451
452 // if corpse was removed during falling, the falling will continue and override relocation to respawn position
453 if (IsFalling())
454 StopMoving();
455
456 Position respawnPosition = GetRespawnPosition();
457
458 // We were spawned on transport, calculate real position
460 {
461 m_movementInfo.transport.pos = respawnPosition;
462
463 if (TransportBase* transport = GetDirectTransport())
464 respawnPosition = transport->GetPositionWithOffset(respawnPosition);
465 }
466
467 UpdateAllowedPositionZ(respawnPosition.GetPositionX(), respawnPosition.GetPositionY(), respawnPosition.m_positionZ);
468 SetHomePosition(respawnPosition);
469 GetMap()->CreatureRelocation(this, respawnPosition.GetPositionX(), respawnPosition.GetPositionY(), respawnPosition.GetPositionZ(), respawnPosition.GetOrientation());
470 }
471 else
472 {
473 if (CreatureAI* ai = AI())
474 ai->CorpseRemoved(m_respawnDelay);
475
476 // In case this is called directly and normal respawn timer not set
477 // Since this timer will be longer than the already present time it
478 // will be ignored if the correct place added a respawn timer
479 if (setSpawnTime)
480 {
481 uint32 respawnDelay = m_respawnDelay;
482 m_respawnTime = std::max<time_t>(GameTime::GetGameTime() + respawnDelay, m_respawnTime);
483
485 }
486
487 if (TempSummon* summon = ToTempSummon())
488 summon->UnSummon();
489 else
491 }
492}
493
497bool Creature::InitEntry(uint32 entry, CreatureData const* data /*= nullptr*/)
498{
499 CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(entry);
500 if (!creatureInfo)
501 {
502 TC_LOG_ERROR("sql.sql", "Creature::InitEntry creature entry {} does not exist.", entry);
503 return false;
504 }
505
506 m_creatureInfo = creatureInfo;
507 SetEntry(entry);
508 m_creatureDifficulty = creatureInfo->GetDifficulty(!IsPet() ? GetMap()->GetDifficultyID() : DIFFICULTY_NONE);
509
510 // equal to player Race field, but creature does not have race
512
513 // known valid are: CLASS_WARRIOR, CLASS_PALADIN, CLASS_ROGUE, CLASS_MAGE
514 SetClass(uint8(creatureInfo->unit_class));
515
516 // Cancel load if no model defined
517 if (!(creatureInfo->GetFirstValidModel()))
518 {
519 TC_LOG_ERROR("sql.sql", "Creature (Entry: {}) has no model defined in table `creature_template`, can't load. ", entry);
520 return false;
521 }
522
523 CreatureModel model = *ObjectMgr::ChooseDisplayId(creatureInfo, data);
524 CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelRandomGender(&model, creatureInfo);
525 if (!minfo) // Cancel load if no model defined
526 {
527 TC_LOG_ERROR("sql.sql", "Creature (Entry: {}) has invalid model {} defined in table `creature_template_model`, can't load.", entry, model.CreatureDisplayID);
528 return false;
529 }
530
531 SetDisplayId(model.CreatureDisplayID, true);
532
533 // Load creature equipment
534 if (!data)
535 LoadEquipment(); // use default equipment (if available) for summons
536 else if (data->equipmentId == 0)
537 LoadEquipment(0); // 0 means no equipment for creature table
538 else
539 {
542 }
543
544 SetName(creatureInfo->Name); // at normal entry always
545
546 SetModCastingSpeed(1.0f);
548 SetModSpellHaste(1.0f);
549 SetModHaste(1.0f);
550 SetModRangedHaste(1.0f);
551 SetModHasteRegen(1.0f);
552 SetModTimeRate(1.0f);
554
555 SetSpeedRate(MOVE_WALK, creatureInfo->speed_walk);
556 SetSpeedRate(MOVE_RUN, creatureInfo->speed_run);
557 SetSpeedRate(MOVE_SWIM, 1.0f); // using 1.0 rate
558 SetSpeedRate(MOVE_FLIGHT, 1.0f); // using 1.0 rate
559
560 // Will set UNIT_FIELD_BOUNDINGRADIUS, UNIT_FIELD_COMBATREACH and UNIT_FIELD_DISPLAYSCALE
562
564
566
567 // checked at loading
571
572 for (uint8 i = 0; i < MAX_CREATURE_SPELLS; ++i)
574
576 ApplyAllStaticFlags(staticFlags);
577
579 || IsPet()
580 || IsTotem()
581 || creatureInfo->flags_extra & CREATURE_FLAG_EXTRA_NO_XP);
582
583 // TODO: migrate these in DB
587
588 return true;
589}
590
591bool Creature::UpdateEntry(uint32 entry, CreatureData const* data /*= nullptr*/, bool updateLevel /* = true */)
592{
593 if (!InitEntry(entry, data))
594 return false;
595
596 CreatureTemplate const* cInfo = GetCreatureTemplate();
597
599
600 // creatures always have melee weapon ready if any unless specified otherwise
601 if (!GetCreatureAddon())
603
604 SetFaction(cInfo->faction);
605
606 uint64 npcFlags;
607 uint32 unitFlags, unitFlags2, unitFlags3;
608 ObjectMgr::ChooseCreatureFlags(cInfo, &npcFlags, &unitFlags, &unitFlags2, &unitFlags3, _staticFlags, data);
609
611 npcFlags |= sGameEventMgr->GetNPCFlag(this);
612
613 if (IsVendor() && !(npcFlags & UNIT_NPC_FLAG_VENDOR_MASK))
615
616 ReplaceAllNpcFlags(NPCFlags(npcFlags & 0xFFFFFFFF));
617 ReplaceAllNpcFlags2(NPCFlags2(npcFlags >> 32));
618
619 if (npcFlags & UNIT_NPC_FLAG_VENDOR_MASK)
621
622 SetPetitioner((npcFlags & UNIT_NPC_FLAG_PETITIONER) != 0);
623
624 // if unit is in combat, keep this flag
625 unitFlags &= ~UNIT_FLAG_IN_COMBAT;
626 if (IsInCombat())
627 unitFlags |= UNIT_FLAG_IN_COMBAT;
628
629 ReplaceAllUnitFlags(UnitFlags(unitFlags));
630 ReplaceAllUnitFlags2(UnitFlags2(unitFlags2));
631 ReplaceAllUnitFlags3(UnitFlags3(unitFlags3));
632
634
635 // Set StateWorldEffectsQuestObjectiveID if there is only one linked objective for this creature
636 if (data && data->spawnTrackingQuestObjectives.size() == 1)
638
640
644
645 if (updateLevel)
646 SelectLevel();
647 else if (!IsGuardian())
648 {
649 uint32 previousHealth = GetHealth();
650 UpdateLevelDependantStats(); // We still re-initialize level dependant stats on entry update
651 if (previousHealth > 0)
652 SetHealth(previousHealth);
653 }
654
655 // Do not update guardian stats here - they are handled in Guardian::InitStatsForLevel()
656 if (!IsGuardian())
657 {
665
666 SetCanModifyStats(true);
668 }
669
670 // checked and error show at loading templates
671 if (FactionTemplateEntry const* factionTemplate = sFactionTemplateStore.LookupEntry(cInfo->faction))
672 {
673 SetPvP((factionTemplate->Flags & FACTION_TEMPLATE_FLAG_PVP) != 0);
674 if (IsTaxi())
675 {
676 uint32 taxiNodesId = sObjectMgr->GetNearestTaxiNode(GetPositionX(), GetPositionY(), GetPositionZ(), GetMapId(),
677 factionTemplate->FactionGroup & FACTION_MASK_ALLIANCE ? ALLIANCE : HORDE);
679 }
680 }
681
682 // updates spell bars for vehicles and set player's faction - should be called here, to overwrite faction that is set from the new template
683 if (IsVehicle())
684 {
685 if (Player* owner = Creature::GetCharmerOrOwnerPlayerOrPlayerItself()) // this check comes in case we don't have a player
686 {
687 SetFaction(owner->GetFaction()); // vehicles should have same as owner faction
688 owner->VehicleSpellInitialize();
689 }
690 }
691
692 // trigger creature is always uninteractible and can not be attacked
693 if (IsTrigger())
694 SetUninteractible(true);
695
698
700
702 {
705 }
706
708
710
714
716
717 //We must update last scriptId or it looks like we reloaded a script, breaking some things such as gossip temporarily
719
721
722 return true;
723}
724
726{
727 CreatureStaticFlagsOverride const* staticFlagsOverride = sObjectMgr->GetCreatureStaticFlagsOverride(spawnId, difficultyId);
728 if (!staticFlagsOverride)
729 return creatureDifficulty->StaticFlags;
730
732 staticFlagsOverride->StaticFlags1.value_or(creatureDifficulty->StaticFlags.GetFlags()),
733 staticFlagsOverride->StaticFlags2.value_or(creatureDifficulty->StaticFlags.GetFlags2()),
734 staticFlagsOverride->StaticFlags3.value_or(creatureDifficulty->StaticFlags.GetFlags3()),
735 staticFlagsOverride->StaticFlags4.value_or(creatureDifficulty->StaticFlags.GetFlags4()),
736 staticFlagsOverride->StaticFlags5.value_or(creatureDifficulty->StaticFlags.GetFlags5()),
737 staticFlagsOverride->StaticFlags6.value_or(creatureDifficulty->StaticFlags.GetFlags6()),
738 staticFlagsOverride->StaticFlags7.value_or(creatureDifficulty->StaticFlags.GetFlags7()),
739 staticFlagsOverride->StaticFlags8.value_or(creatureDifficulty->StaticFlags.GetFlags8()));
740}
741
743{
745
746 // Apply all other side effects of flag changes
748}
749
751{
753 {
756
759 m_triggerJustAppeared = false;
760 AI()->JustAppeared();
761 }
762
764
765 GetThreatManager().Update(diff);
766
767 switch (m_deathState)
768 {
769 case JUST_RESPAWNED:
770 // Must not be called, see Creature::setDeathState JUST_RESPAWNED -> ALIVE promoting.
771 TC_LOG_ERROR("entities.unit", "Creature {} in wrong state: JUST_RESPAWNED (4)", GetGUID().ToString());
772 break;
773 case JUST_DIED:
774 // Must not be called, see Creature::setDeathState JUST_DIED -> CORPSE promoting.
775 TC_LOG_ERROR("entities.unit", "Creature {} in wrong state: JUST_DIED (1)", GetGUID().ToString());
776 break;
777 case DEAD:
778 {
780 {
781 TC_LOG_ERROR("entities.unit", "Creature {} in wrong state: DEAD (3)", GetGUID().ToString());
782 break;
783 }
784 time_t now = GameTime::GetGameTime();
785 if (m_respawnTime <= now)
786 {
787 // Delay respawn if spawn group is not active
788 if (m_creatureData && !GetMap()->IsSpawnGroupActive(m_creatureData->spawnGroupData->groupId))
789 {
790 m_respawnTime = now + urand(4,7);
791 break; // Will be rechecked on next Update call after delay expires
792 }
793
794 ObjectGuid dbtableHighGuid = ObjectGuid::Create<HighGuid::Creature>(GetMapId(), GetEntry(), m_spawnId);
795 time_t linkedRespawnTime = GetMap()->GetLinkedRespawnTime(dbtableHighGuid);
796 if (!linkedRespawnTime) // Can respawn
797 Respawn();
798 else // the master is dead
799 {
800 ObjectGuid targetGuid = sObjectMgr->GetLinkedRespawnGuid(dbtableHighGuid);
801 if (targetGuid == dbtableHighGuid) // if linking self, never respawn
803 else
804 {
805 // else copy time from master and add a little
806 time_t baseRespawnTime = std::max(linkedRespawnTime, now);
807 time_t const offset = urand(5, MINUTE);
808
809 // linked guid can be a boss, uses std::numeric_limits<time_t>::max to never respawn in that instance
810 // we shall inherit it instead of adding and causing an overflow
811 if (baseRespawnTime <= std::numeric_limits<time_t>::max() - offset)
812 m_respawnTime = baseRespawnTime + offset;
813 else
814 m_respawnTime = std::numeric_limits<time_t>::max();
815 }
816 SaveRespawnTime(); // also save to DB immediately
817 }
818 }
819 break;
820 }
821 case CORPSE:
822 {
823 Unit::Update(diff);
824 // deathstate changed on spells update, prevent problems
825 if (m_deathState != CORPSE)
826 break;
827
828 if (IsEngaged())
829 Unit::AIUpdateTick(diff);
830
831 if (m_loot)
832 m_loot->Update();
833
834 for (auto&& [playerOwner, loot] : m_personalLoot)
835 loot->Update();
836
838 {
839 RemoveCorpse(false);
840 TC_LOG_DEBUG("entities.unit", "Removing corpse... {} ", GetEntry());
841 }
842 break;
843 }
844 case ALIVE:
845 {
846 Unit::Update(diff);
847
848 // creature can be dead after Unit::Update call
849 // CORPSE/DEAD state will processed at next tick (in other case death timer will be updated unexpectedly)
850 if (!IsAlive())
851 break;
852
853 if (_spellFocusInfo.Delay)
854 {
855 if (_spellFocusInfo.Delay <= diff)
857 else
858 _spellFocusInfo.Delay -= diff;
859 }
860
861 // periodic check to see if the creature has passed an evade boundary
862 if (IsAIEnabled() && !IsInEvadeMode() && IsEngaged())
863 {
864 if (diff >= m_boundaryCheckTime)
865 {
866 AI()->CheckInRoom();
867 m_boundaryCheckTime = 2500;
868 } else
869 m_boundaryCheckTime -= diff;
870 }
871
872 Unit::AIUpdateTick(diff);
873
875
876 // creature can be dead after UpdateAI call
877 // CORPSE/DEAD state will processed at next tick (in other case death timer will be updated unexpectedly)
878 if (!IsAlive())
879 break;
880
881 if (m_regenTimer > 0)
882 {
883 if (diff >= m_regenTimer)
884 m_regenTimer = 0;
885 else
886 m_regenTimer -= diff;
887 }
888
889 if (m_regenTimer == 0)
890 {
891 if (!IsInEvadeMode())
892 {
893 // regenerate health if not in combat or if polymorphed)
894 if (!IsEngaged() || IsPolymorphed())
896 else if (CanNotReachTarget())
897 {
898 // regenerate health if cannot reach the target and the setting is set to do so.
899 // this allows to disable the health regen of raid bosses if pathfinding has issues for whatever reason
900 if (sWorld->getBoolConfig(CONFIG_REGEN_HP_CANNOT_REACH_TARGET_IN_RAID) || !GetMap()->IsRaid())
901 {
903 TC_LOG_DEBUG("entities.unit.chase", "RegenerateHealth() enabled because Creature cannot reach the target. Detail: {}", GetDebugInfo());
904 }
905 else
906 TC_LOG_DEBUG("entities.unit.chase", "RegenerateHealth() disabled even if the Creature cannot reach the target. Detail: {}", GetDebugInfo());
907 }
908 }
909
910 if (GetPowerType() == POWER_ENERGY)
912 else
914
916 }
917
918 if (CanNotReachTarget() && !IsInEvadeMode() && !GetMap()->IsRaid())
919 {
920 m_cannotReachTimer += diff;
922 if (CreatureAI* ai = AI())
923 ai->EnterEvadeMode(EvadeReason::NoPath);
924 }
925 break;
926 }
927 default:
928 break;
929 }
930}
931
933{
935
936 // Creatures with CREATURE_STATIC_FLAG_2_FORCE_PARTY_MEMBERS_INTO_COMBAT periodically force party members into combat
938
939 // creatures should only attack surroundings initially after heartbeat has passed or until attacked
941 {
943
944 // trigger MoveInLineOfSight
946 Cell::VisitAllObjects(this, notifier, GetVisibilityRange());
947 }
948}
949
951{
952 uint32 curValue = GetPower(power);
953 uint32 maxValue = GetMaxPower(power);
954
956 return;
957
958 if (curValue >= maxValue)
959 return;
960
961 float addvalue = 0.0f;
962
963 switch (power)
964 {
965 case POWER_FOCUS:
966 {
967 // For hunter pets.
968 addvalue = 24 * sWorld->getRate(RATE_POWER_FOCUS);
969 break;
970 }
971 case POWER_ENERGY:
972 {
973 // For deathknight's ghoul.
974 addvalue = 20;
975 break;
976 }
977 case POWER_MANA:
978 {
979 // Combat and any controlled creature
980 if (IsInCombat() || GetCharmerOrOwnerGUID().IsEmpty())
981 {
982 float ManaIncreaseRate = sWorld->getRate(RATE_POWER_MANA);
983
984 addvalue = uint32((27.0f / 5.0f + 17.0f) * ManaIncreaseRate);
985 }
986 else
987 addvalue = maxValue / 3;
988
989 break;
990 }
991 default:
992 return;
993 }
994
995 // Apply modifiers (if any).
997
999
1000 ModifyPower(power, int32(addvalue));
1001}
1002
1004{
1005 if (!CanRegenerateHealth())
1006 return;
1007
1008 uint32 curValue = GetHealth();
1009 uint32 maxValue = GetMaxHealth();
1010
1011 if (curValue >= maxValue)
1012 return;
1013
1014 uint32 addvalue = 0;
1015
1016 // Not only pet, but any controlled creature (and not polymorphed)
1017 if (!GetCharmerOrOwnerGUID().IsEmpty() && !IsPolymorphed())
1018 {
1019 float HealthIncreaseRate = sWorld->getRate(RATE_HEALTH);
1020
1021 addvalue = 0.015f * ((float)GetMaxHealth()) * HealthIncreaseRate;
1022 }
1023 else
1024 addvalue = maxValue/3;
1025
1026 // Apply modifiers (if any).
1028
1030
1031 ModifyHealth(addvalue);
1032}
1033
1035{
1036 if (!GetVictim())
1037 return;
1038
1040 return;
1041
1042 float radius = sWorld->getFloatConfig(CONFIG_CREATURE_FAMILY_FLEE_ASSISTANCE_RADIUS);
1043 if (radius >0)
1044 {
1045 Creature* creature = nullptr;
1048 Cell::VisitGridObjects(this, searcher, radius);
1049
1051
1052 if (!creature)
1055 else
1056 GetMotionMaster()->MoveSeekAssistance(creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ());
1057 }
1058}
1059
1061{
1062 PopAI();
1063 RefreshAI();
1064 return true;
1065}
1066
1067bool Creature::AIM_Create(CreatureAI* ai /*= nullptr*/)
1068{
1070
1071 SetAI(ai ? ai : FactorySelector::SelectAI(this));
1072
1073 return true;
1074}
1075
1077{
1078 if (!AIM_Create(ai))
1079 return false;
1080
1081 AI()->InitializeAI();
1082 if (GetVehicleKit())
1083 GetVehicleKit()->Reset();
1084 return true;
1085}
1086
1088{
1089 if (m_formation)
1090 {
1091 if (m_formation->GetLeader() == this)
1093 else if (m_formation->IsFormed())
1094 {
1095 GetMotionMaster()->MoveIdle(); // wait the order of leader
1096 return;
1097 }
1098 }
1099
1101}
1102
1103bool Creature::Create(ObjectGuid::LowType guidlow, Map* map, uint32 entry, Position const& pos, CreatureData const* data /*= nullptr*/, uint32 vehId /*= 0*/, bool dynamic)
1104{
1105 ASSERT(map);
1106 SetMap(map);
1107
1108 if (data)
1109 {
1112 }
1113
1114 // Set if this creature can handle dynamic spawns
1115 if (!dynamic)
1117
1118 CreatureTemplate const* cinfo = sObjectMgr->GetCreatureTemplate(entry);
1119 if (!cinfo)
1120 {
1121 TC_LOG_ERROR("sql.sql", "Creature::Create(): creature template (guidlow: {}, entry: {}) does not exist.", guidlow, entry);
1122 return false;
1123 }
1124
1125 CreatureDifficulty const* creatureDifficulty = cinfo->GetDifficulty(GetMap()->GetDifficultyID());
1126
1129 Relocate(pos);
1130
1131 // Check if the position is valid before calling CreateFromProto(), otherwise we might add Auras to Creatures at
1132 // invalid position, triggering a crash about Auras not removed in the destructor
1133 if (!IsPositionValid())
1134 {
1135 TC_LOG_ERROR("entities.unit", "Creature::Create(): given coordinates for creature (guidlow {}, entry {}) are not valid (X: {}, Y: {}, Z: {}, O: {})", guidlow, entry, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation());
1136 return false;
1137 }
1138 {
1139 // area/zone id is needed immediately for ZoneScript::GetCreatureEntry hook before it is known which creature template to load (no model/scale available yet)
1140 PositionFullTerrainStatus terrainStatus;
1142 ProcessPositionDataChanged(terrainStatus);
1143 }
1144
1145 // Allow players to see those units while dead, do it here (mayby altered by addon auras)
1146 if (creatureDifficulty->TypeFlags & CREATURE_TYPE_FLAG_VISIBLE_TO_GHOSTS)
1148
1149 if (!CreateFromProto(guidlow, entry, data, vehId))
1150 return false;
1151
1152 cinfo = GetCreatureTemplate(); // might be different than initially requested
1154 m_respawnDelay = 0; // special value, prevents respawn for dungeon bosses unless overridden
1155
1156 switch (GetCreatureClassification())
1157 {
1160 break;
1163 break;
1166 break;
1169 break;
1172 break;
1175 break;
1176 default:
1178 break;
1179 }
1180
1183
1185
1187 {
1190 }
1191
1194
1196 {
1199 }
1200
1202
1203 return true;
1204}
1205
1206Creature* Creature::CreateCreature(uint32 entry, Map* map, Position const& pos, uint32 vehId /*= 0*/)
1207{
1208 CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(entry);
1209 if (!cInfo)
1210 return nullptr;
1211
1212 ObjectGuid::LowType lowGuid;
1213 if (vehId || cInfo->VehicleId)
1214 lowGuid = map->GenerateLowGuid<HighGuid::Vehicle>();
1215 else
1216 lowGuid = map->GenerateLowGuid<HighGuid::Creature>();
1217
1218 Creature* creature = new Creature();
1219 if (!creature->Create(lowGuid, map, entry, pos, nullptr, vehId))
1220 {
1221 delete creature;
1222 return nullptr;
1223 }
1224
1225 return creature;
1226}
1227
1228Creature* Creature::CreateCreatureFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap /*= true*/, bool allowDuplicate /*= false*/)
1229{
1230 Creature* creature = new Creature();
1231 if (!creature->LoadFromDB(spawnId, map, addToMap, allowDuplicate))
1232 {
1233 delete creature;
1234 return nullptr;
1235 }
1236
1237 return creature;
1238}
1239
1241{
1242 Unit* target = nullptr;
1243
1244 if (CanHaveThreatList())
1246 else if (!HasReactState(REACT_PASSIVE))
1247 {
1248 // We're a player pet, probably
1249 target = getAttackerForHelper();
1250 if (!target && IsSummon())
1251 {
1252 if (Unit* owner = ToTempSummon()->GetOwner())
1253 {
1254 if (owner->IsInCombat())
1255 target = owner->getAttackerForHelper();
1256 if (!target)
1257 {
1258 for (ControlList::const_iterator itr = owner->m_Controlled.begin(); itr != owner->m_Controlled.end(); ++itr)
1259 {
1260 if ((*itr)->IsInCombat())
1261 {
1262 target = (*itr)->getAttackerForHelper();
1263 if (target)
1264 break;
1265 }
1266 }
1267 }
1268 }
1269 }
1270 }
1271 else
1272 return nullptr;
1273
1274 if (target && _IsTargetAcceptable(target) && CanCreatureAttack(target))
1275 {
1276 if (!HasSpellFocus())
1277 SetInFront(target);
1278 return target;
1279 }
1280
1282 if (GetVehicle())
1283 return nullptr;
1284
1286 if (!iAuras.empty())
1287 {
1288 for (Unit::AuraEffectList::const_iterator itr = iAuras.begin(); itr != iAuras.end(); ++itr)
1289 {
1290 if ((*itr)->GetBase()->IsPermanent())
1291 {
1293 break;
1294 }
1295 }
1296 return nullptr;
1297 }
1298
1299 // enter in evade mode in other case
1301
1302 return nullptr;
1303}
1304
1306{
1309 /*
1310 else if (IsCivilian())
1311 SetReactState(REACT_DEFENSIVE);
1312 */
1313 else
1315}
1316
1318{
1319 if (!IsBattleMaster())
1320 return false;
1321
1322 BattlegroundTypeId bgTypeId = sBattlegroundMgr->GetBattleMasterBG(GetEntry());
1323 if (!msg)
1324 return player->GetBGAccessByLevel(bgTypeId);
1325
1326 if (!player->GetBGAccessByLevel(bgTypeId))
1327 {
1328 ClearGossipMenuFor(player);
1329 switch (bgTypeId)
1330 {
1331 case BATTLEGROUND_AV: SendGossipMenuFor(player, 7616, this); break;
1332 case BATTLEGROUND_WS: SendGossipMenuFor(player, 7599, this); break;
1333 case BATTLEGROUND_AB: SendGossipMenuFor(player, 7642, this); break;
1334 case BATTLEGROUND_EY:
1335 case BATTLEGROUND_NA:
1336 case BATTLEGROUND_BE:
1337 case BATTLEGROUND_AA:
1338 case BATTLEGROUND_RL:
1339 case BATTLEGROUND_SA:
1340 case BATTLEGROUND_DS:
1341 case BATTLEGROUND_RV: SendGossipMenuFor(player, 10024, this); break;
1342 default: break;
1343 }
1344 return false;
1345 }
1346 return true;
1347}
1348
1350{
1351 return player->GetLevel() >= 15
1352 && player->GetClass() == GetCreatureTemplate()->trainer_class;
1353}
1354
1356{
1357 if (m_lootId)
1358 return *m_lootId;
1359
1360 return GetCreatureDifficulty()->LootID;
1361}
1362
1364{
1365 m_lootId = lootId;
1366}
1367
1368void Creature::SetTappedBy(Unit const* unit, bool withGroup)
1369{
1370 // set the player whose group should receive the right
1371 // to loot the creature after it dies
1372 // should be set to nullptr after the loot disappears
1373
1374 if (!unit)
1375 {
1376 m_tapList.clear();
1378 return;
1379 }
1380
1382 return;
1383
1384 if (unit->GetTypeId() != TYPEID_PLAYER && !unit->IsVehicle())
1385 return;
1386
1388 if (!player) // normal creature, no player involved
1389 return;
1390
1391 m_tapList.insert(player->GetGUID());
1392 if (withGroup)
1393 if (Group const* group = player->GetGroup())
1394 for (GroupReference const& itr : group->GetMembers())
1395 if (GetMap()->IsRaid() || group->SameSubGroup(player, itr.GetSource()))
1396 m_tapList.insert(itr.GetSource()->GetGUID());
1397
1400}
1401
1403{
1404 // only temporary summons are allowed to not clear their tap list
1405 if (!m_spawnId)
1406 m_dontClearTapListOnEvade = dontClear;
1407}
1408
1409// return true if this creature is tapped by the player or by a member of his group.
1410bool Creature::isTappedBy(Player const* player) const
1411{
1412 return m_tapList.find(player->GetGUID()) != m_tapList.end();
1413}
1414
1416{
1417 if (m_personalLoot.empty())
1418 return m_loot.get();
1419
1421 return loot;
1422
1423 return nullptr;
1424}
1425
1427{
1428 if (m_loot && !m_loot->isLooted())
1429 return false;
1430
1431 for (auto const& [_, loot] : m_personalLoot)
1432 if (!loot->isLooted())
1433 return false;
1434
1435 return true;
1436}
1437
1438bool Creature::IsSkinnedBy(Player const* player) const
1439{
1440 if (Loot* loot = GetLootForPlayer(player))
1441 return loot->loot_type == LOOT_SKINNING;
1442
1443 return false;
1444}
1445
1447{
1448 // this should only be used when the creature has already been loaded
1449 // preferably after adding to map, because mapid may not be valid otherwise
1450 CreatureData const* data = sObjectMgr->GetCreatureData(m_spawnId);
1451 if (!data)
1452 {
1453 TC_LOG_ERROR("entities.unit", "Creature::SaveToDB failed, cannot get creature data!");
1454 return;
1455 }
1456
1457 uint32 mapId = GetMapId();
1458 if (TransportBase* transport = GetTransport())
1459 if (transport->GetMapIdForSpawning() >= 0)
1460 mapId = transport->GetMapIdForSpawning();
1461
1462 SaveToDB(mapId, data->spawnDifficulties);
1463}
1464
1465void Creature::SaveToDB(uint32 mapid, std::vector<Difficulty> const& spawnDifficulties)
1466{
1467 // update in loaded data
1468 if (!m_spawnId)
1469 m_spawnId = sObjectMgr->GenerateCreatureSpawnId();
1470
1471 CreatureData& data = sObjectMgr->NewOrExistCreatureData(m_spawnId);
1472
1473 uint32 displayId = GetNativeDisplayId();
1474 uint64 spawnNpcFlags = (uint64(GetNpcFlags2()) << 32) | GetNpcFlags();
1475 Optional<uint64> npcflag;
1476 Optional<uint32> unitFlags;
1477 Optional<uint32> unitFlags2;
1478 Optional<uint32> unitFlags3;
1479
1480 // check if it's a custom model and if not, use 0 for displayId
1481 CreatureTemplate const* cinfo = GetCreatureTemplate();
1482 for (CreatureModel const& model : cinfo->Models)
1483 if (displayId && displayId == model.CreatureDisplayID)
1484 displayId = 0;
1485
1486 if (spawnNpcFlags != cinfo->npcflag)
1487 npcflag = spawnNpcFlags;
1488
1489 if (m_unitData->Flags != cinfo->unit_flags)
1490 unitFlags = m_unitData->Flags;
1491
1492 if (m_unitData->Flags2 != cinfo->unit_flags2)
1493 unitFlags2 = m_unitData->Flags2;
1494
1495 if (m_unitData->Flags3 != cinfo->unit_flags3)
1496 unitFlags3 = m_unitData->Flags3;
1497
1498 if (!data.spawnId)
1499 data.spawnId = m_spawnId;
1500 ASSERT(data.spawnId == m_spawnId);
1501 data.id = GetEntry();
1502 if (displayId)
1503 data.display.emplace(displayId, DEFAULT_PLAYER_DISPLAY_SCALE, 1.0f);
1504 else
1505 data.display.reset();
1507 if (!GetTransport())
1508 {
1509 data.mapId = GetMapId();
1510 data.spawnPoint.Relocate(this);
1511 }
1512 else
1513 {
1514 data.mapId = mapid;
1516 }
1518 // prevent add data integrity problems
1520 data.currentwaypoint = 0;
1521 if (!cinfo->RegenHealth)
1523
1524 // prevent add data integrity problems
1527 data.spawnDifficulties = spawnDifficulties;
1528 data.npcflag = npcflag;
1529 data.unit_flags = unitFlags;
1530 data.unit_flags2 = unitFlags2;
1531 data.unit_flags3 = unitFlags3;
1532 if (!data.spawnGroupData)
1533 data.spawnGroupData = sObjectMgr->GetDefaultSpawnGroup();
1534
1535 data.phaseId = GetDBPhase() > 0 ? GetDBPhase() : data.phaseId;
1536 data.phaseGroup = GetDBPhase() < 0 ? -GetDBPhase() : data.phaseGroup;
1537
1538 // update in DB
1539 WorldDatabaseTransaction trans = WorldDatabase.BeginTransaction();
1540
1542 stmt->setUInt64(0, m_spawnId);
1543 trans->Append(stmt);
1544
1545 uint8 index = 0;
1546
1547 stmt = WorldDatabase.GetPreparedStatement(WORLD_INS_CREATURE);
1548 stmt->setUInt64(index++, m_spawnId);
1549 stmt->setUInt32(index++, GetEntry());
1550 stmt->setUInt16(index++, uint16(mapid));
1551 stmt->setString(index++, [&data]() -> std::string
1552 {
1553 std::ostringstream os;
1554 if (!data.spawnDifficulties.empty())
1555 {
1556 auto itr = data.spawnDifficulties.begin();
1557 os << int32(*itr++);
1558
1559 for (; itr != data.spawnDifficulties.end(); ++itr)
1560 os << ',' << int32(*itr);
1561 }
1562
1563 return std::move(os).str();
1564 }());
1565 stmt->setUInt8(index++, data.phaseUseFlags);
1566 stmt->setUInt32(index++, data.phaseId);
1567 stmt->setUInt32(index++, data.phaseGroup);
1568 stmt->setInt32(index++, data.terrainSwapMap);
1569 stmt->setUInt32(index++, displayId);
1570 stmt->setUInt8(index++, GetCurrentEquipmentId());
1571 stmt->setFloat(index++, GetPositionX());
1572 stmt->setFloat(index++, GetPositionY());
1573 stmt->setFloat(index++, GetPositionZ());
1574 stmt->setFloat(index++, GetOrientation());
1575 stmt->setUInt32(index++, m_respawnDelay);
1576 stmt->setFloat(index++, m_wanderDistance);
1577 stmt->setUInt32(index++, 0);
1578 stmt->setUInt32(index++, uint32(GetHealthPct()));
1579 stmt->setUInt8(index++, uint8(GetDefaultMovementType()));
1580 if (npcflag.has_value())
1581 stmt->setUInt64(index++, *npcflag);
1582 else
1583 stmt->setNull(index++);
1584
1585 if (unitFlags.has_value())
1586 stmt->setUInt32(index++, *unitFlags);
1587 else
1588 stmt->setNull(index++);
1589
1590 if (unitFlags2.has_value())
1591 stmt->setUInt32(index++, *unitFlags2);
1592 else
1593 stmt->setNull(index++);
1594
1595 if (unitFlags3.has_value())
1596 stmt->setUInt32(index++, *unitFlags3);
1597 else
1598 stmt->setNull(index++);
1599
1600 stmt->setString(index++, sObjectMgr->GetScriptName(data.scriptId));
1601 if (std::string_view stringId = GetStringId(StringIdType::Spawn); !stringId.empty())
1602 stmt->setString(index++, stringId);
1603 else
1604 stmt->setNull(index++);
1605
1606 trans->Append(stmt);
1607
1608 WorldDatabase.CommitTransaction(trans);
1609}
1610
1612{
1613 // Level
1615 int32 levelWithDelta = m_unitData->ScalingLevelMax + m_unitData->ScalingLevelDelta;
1616 uint8 level = RoundToInterval<int32>(levelWithDelta, 1, STRONG_MAX_LEVEL);
1617 SetLevel(level);
1618
1620}
1621
1623{
1624 CreatureTemplate const* cInfo = GetCreatureTemplate();
1626 uint8 level = GetLevel();
1627 CreatureBaseStats const* stats = sObjectMgr->GetCreatureBaseStats(level, cInfo->unit_class);
1628
1629 // health
1630 float healthmod = GetHealthMod(classification);
1631
1632 uint32 basehp = GetMaxHealthByLevel(level);
1633 uint32 health = uint32(basehp * healthmod);
1634
1635 SetCreateHealth(health);
1636 SetMaxHealth(health);
1637 SetHealth(health);
1639
1641
1642 // mana
1643 Powers powerType = CalculateDisplayPowerType();
1644 SetCreateMana(stats->BaseMana);
1646 SetPowerType(powerType, true, true);
1647
1648 // damage
1649 float basedamage = GetBaseDamageForLevel(level);
1650
1651 float weaponBaseMinDamage = basedamage;
1652 float weaponBaseMaxDamage = basedamage * 1.5f;
1653
1654 SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, weaponBaseMinDamage);
1655 SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, weaponBaseMaxDamage);
1656
1657 SetBaseWeaponDamage(OFF_ATTACK, MINDAMAGE, weaponBaseMinDamage);
1658 SetBaseWeaponDamage(OFF_ATTACK, MAXDAMAGE, weaponBaseMaxDamage);
1659
1660 SetBaseWeaponDamage(RANGED_ATTACK, MINDAMAGE, weaponBaseMinDamage);
1661 SetBaseWeaponDamage(RANGED_ATTACK, MAXDAMAGE, weaponBaseMaxDamage);
1662
1665
1666 float armor = GetBaseArmorForLevel(level);
1668}
1669
1671{
1672 if (IsWildBattlePet())
1673 {
1674 uint8 wildBattlePetLevel = WILD_BATTLE_PET_DEFAULT_LEVEL;
1675
1676 if (AreaTableEntry const* areaTable = sAreaTableStore.LookupEntry(GetZoneId()))
1677 if (areaTable->WildBattlePetLevelMin > 0)
1678 wildBattlePetLevel = urand(areaTable->WildBattlePetLevelMin, areaTable->WildBattlePetLevelMax);
1679
1680 SetWildBattlePetLevel(wildBattlePetLevel);
1681 }
1682}
1683
1685{
1686 switch (classification)
1687 {
1689 return sWorld->getRate(RATE_CREATURE_HP_NORMAL);
1691 return sWorld->getRate(RATE_CREATURE_HP_ELITE);
1693 return sWorld->getRate(RATE_CREATURE_HP_RAREELITE);
1695 return sWorld->getRate(RATE_CREATURE_HP_OBSOLETE);
1697 return sWorld->getRate(RATE_CREATURE_HP_RARE);
1699 return sWorld->getRate(RATE_CREATURE_HP_TRIVIAL);
1701 return sWorld->getRate(RATE_CREATURE_HP_MINUSMOB);
1702 default:
1703 return sWorld->getRate(RATE_CREATURE_HP_ELITE);
1704 }
1705}
1706
1708{
1710 m_PlayerDamageReq > unDamage ? m_PlayerDamageReq -= unDamage : m_PlayerDamageReq = 0;
1711}
1712
1714{
1715 switch (classification)
1716 {
1718 return sWorld->getRate(RATE_CREATURE_DAMAGE_NORMAL);
1720 return sWorld->getRate(RATE_CREATURE_DAMAGE_ELITE);
1722 return sWorld->getRate(RATE_CREATURE_DAMAGE_RAREELITE);
1724 return sWorld->getRate(RATE_CREATURE_DAMAGE_OBSOLETE);
1726 return sWorld->getRate(RATE_CREATURE_DAMAGE_RARE);
1728 return sWorld->getRate(RATE_CREATURE_DAMAGE_TRIVIAL);
1730 return sWorld->getRate(RATE_CREATURE_DAMAGE_MINUSMOB);
1731 default:
1732 return sWorld->getRate(RATE_CREATURE_DAMAGE_ELITE);
1733 }
1734}
1735
1758
1759void Creature::OverrideSparringHealthPct(std::vector<float> const& healthPct)
1760{
1762}
1763
1765{
1766 if (GetSparringHealthPct() == 0)
1767 return damage;
1768
1769 if (!attacker)
1770 return damage;
1771
1773 return damage;
1774
1776 return 0;
1777
1778 uint32 sparringHealth = GetMaxHealth() * GetSparringHealthPct() / 100;
1779 if (GetHealth() - damage <= sparringHealth)
1780 return GetHealth() - sparringHealth;
1781
1782 if (damage >= GetHealth())
1783 return GetHealth() - 1;
1784
1785 return damage;
1786}
1787
1789{
1790 if (!GetSparringHealthPct())
1791 return false;
1792
1793 if (!attacker)
1794 return false;
1795
1796 if (!attacker->IsCreature())
1797 return false;
1798
1800 return false;
1801
1803 return false;
1804
1805 return true;
1806}
1807
1808bool Creature::CreateFromProto(ObjectGuid::LowType guidlow, uint32 entry, CreatureData const* data /*= nullptr*/, uint32 vehId /*= 0*/)
1809{
1810 SetZoneScript();
1811 if (GetZoneScript() && data)
1812 {
1813 entry = GetZoneScript()->GetCreatureEntry(guidlow, data);
1814 if (!entry)
1815 return false;
1816 }
1817
1818 CreatureTemplate const* cinfo = sObjectMgr->GetCreatureTemplate(entry);
1819 if (!cinfo)
1820 {
1821 TC_LOG_ERROR("sql.sql", "Creature::CreateFromProto(): creature template (guidlow: {}, entry: {}) does not exist.", guidlow, entry);
1822 return false;
1823 }
1824
1825 SetOriginalEntry(entry);
1826
1827 if (vehId || cinfo->VehicleId)
1828 _Create(ObjectGuid::Create<HighGuid::Vehicle>(GetMapId(), entry, guidlow));
1829 else
1830 _Create(ObjectGuid::Create<HighGuid::Creature>(GetMapId(), entry, guidlow));
1831
1832 if (!UpdateEntry(entry, data))
1833 return false;
1834
1835 if (!vehId)
1836 {
1837 if (GetCreatureTemplate()->VehicleId)
1838 {
1839 vehId = GetCreatureTemplate()->VehicleId;
1840 entry = GetCreatureTemplate()->Entry;
1841 }
1842 else
1843 vehId = cinfo->VehicleId;
1844 }
1845
1846 if (vehId)
1847 if (CreateVehicleKit(vehId, entry, true))
1849
1850 if (!IsPet())
1851 if (uint32 vignetteId = GetCreatureTemplate()->VignetteID)
1852 SetVignette(vignetteId);
1853
1854 return true;
1855}
1856
1857bool Creature::LoadFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap, bool allowDuplicate)
1858{
1859 if (!allowDuplicate)
1860 {
1861 // If an alive instance of this spawnId is already found, skip creation
1862 // If only dead instance(s) exist, despawn them and spawn a new (maybe also dead) version
1863 const auto creatureBounds = map->GetCreatureBySpawnIdStore().equal_range(spawnId);
1864 std::vector <Creature*> despawnList;
1865
1866 if (creatureBounds.first != creatureBounds.second)
1867 {
1868 for (auto itr = creatureBounds.first; itr != creatureBounds.second; ++itr)
1869 {
1870 if (itr->second->IsAlive())
1871 {
1872 TC_LOG_DEBUG("maps", "Would have spawned {} but {} already exists", spawnId, creatureBounds.first->second->GetGUID().ToString());
1873 return false;
1874 }
1875 else
1876 {
1877 despawnList.push_back(itr->second);
1878 TC_LOG_DEBUG("maps", "Despawned dead instance of spawn {} ({})", spawnId, itr->second->GetGUID().ToString());
1879 }
1880 }
1881
1882 for (Creature* despawnCreature : despawnList)
1883 {
1884 despawnCreature->AddObjectToRemoveList();
1885 }
1886 }
1887 }
1888
1889 CreatureData const* data = sObjectMgr->GetCreatureData(spawnId);
1890 if (!data)
1891 {
1892 TC_LOG_ERROR("sql.sql", "Creature (SpawnID {}) not found in table `creature`, can't load. ", spawnId);
1893 return false;
1894 }
1895
1896 m_spawnId = spawnId;
1897
1899 m_creatureData = data;
1902
1903 if (!Create(map->GenerateLowGuid<HighGuid::Creature>(), map, data->id, data->spawnPoint, data, 0U , !m_respawnCompatibilityMode))
1904 return false;
1905
1906 //We should set first home position, because then AI calls home movement
1907 SetHomePosition(*this);
1908
1910
1912
1914 {
1916 {
1917 // @todo pools need fixing! this is just a temporary thing, but they violate dynspawn principles
1918 if (!data->poolId)
1919 {
1920 TC_LOG_ERROR("entities.unit", "Creature (SpawnID {}) trying to load in inactive spawn group '{}':\n{}", spawnId, data->spawnGroupData->name, GetDebugInfo());
1921 return false;
1922 }
1923 }
1924
1926 }
1927
1928 if (m_respawnTime)
1929 {
1931 {
1932 // @todo same as above
1933 if (!data->poolId)
1934 {
1935 TC_LOG_ERROR("entities.unit", "Creature (SpawnID {}) trying to load despite a respawn timer in progress:\n{}", spawnId, GetDebugInfo());
1936 return false;
1937 }
1938 }
1939 else
1940 {
1941 // compatibility mode creatures will be respawned in ::Update()
1943 }
1944
1945 if (CanFly())
1946 {
1947 float tz = map->GetHeight(GetPhaseShift(), data->spawnPoint, true, MAX_FALL_DISTANCE);
1948 if (data->spawnPoint.GetPositionZ() - tz > 0.1f && Trinity::IsValidMapCoord(tz))
1950 }
1951 }
1952
1954
1956
1957 // checked at creature_template loading
1959
1961
1962 if (addToMap && !GetMap()->AddToMap(this))
1963 return false;
1964 return true;
1965}
1966
1972
1973void Creature::LoadEquipment(int8 id, bool force /*= true*/)
1974{
1975 if (id == 0)
1976 {
1977 if (force)
1978 {
1979 for (uint8 i = 0; i < MAX_EQUIPMENT_ITEMS; ++i)
1980 SetVirtualItem(i, 0);
1981 m_equipmentId = 0;
1982 }
1983
1984 return;
1985 }
1986
1987 EquipmentInfo const* einfo = sObjectMgr->GetEquipmentInfo(GetEntry(), id);
1988 if (!einfo)
1989 return;
1990
1991 m_equipmentId = id;
1992 for (uint8 i = 0; i < MAX_EQUIPMENT_ITEMS; ++i)
1993 SetVirtualItem(i, einfo->Items[i].ItemId, einfo->Items[i].AppearanceModId, einfo->Items[i].ItemVisual);
1994}
1995
1997{
1998 // set health only if regenerating is not enabled (otherwise it would immediately go back to full health anyway)
2001 // or when creature respawns in legacy compatibility mode
2002 else if (getDeathState() == JUST_RESPAWNED)
2003 SetFullHealth();
2004
2006}
2007
2008bool Creature::hasQuest(uint32 quest_id) const
2009{
2010 return sObjectMgr->GetCreatureQuestRelations(GetEntry()).HasQuest(quest_id);
2011}
2012
2014{
2015 return sObjectMgr->GetCreatureQuestInvolvedRelations(GetEntry()).HasQuest(quest_id);
2016}
2017
2019{
2020 CreatureData const* data = sObjectMgr->GetCreatureData(spawnId);
2021 if (!data)
2022 return false;
2023
2024 CharacterDatabaseTransaction charTrans = CharacterDatabase.BeginTransaction();
2025
2026 sMapMgr->DoForAllMapsWithMapId(data->mapId,
2027 [spawnId, charTrans](Map* map) -> void
2028 {
2029 // despawn all active creatures, and remove their respawns
2030 std::vector<Creature*> toUnload;
2031 for (auto const& pair : Trinity::Containers::MapEqualRange(map->GetCreatureBySpawnIdStore(), spawnId))
2032 toUnload.push_back(pair.second);
2033 for (Creature* creature : toUnload)
2034 map->AddObjectToRemoveList(creature);
2035 map->RemoveRespawnTime(SPAWN_TYPE_CREATURE, spawnId, charTrans);
2036 }
2037 );
2038
2039 // delete data from memory ...
2040 sObjectMgr->DeleteCreatureData(spawnId);
2041
2042 CharacterDatabase.CommitTransaction(charTrans);
2043
2044 WorldDatabaseTransaction trans = WorldDatabase.BeginTransaction();
2045
2046 // ... and the database
2048 stmt->setUInt64(0, spawnId);
2049 trans->Append(stmt);
2050
2051 stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_SPAWNGROUP_MEMBER);
2053 stmt->setUInt64(1, spawnId);
2054 trans->Append(stmt);
2055
2056 stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_CREATURE_ADDON);
2057 stmt->setUInt64(0, spawnId);
2058 trans->Append(stmt);
2059
2060 stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_GAME_EVENT_CREATURE);
2061 stmt->setUInt64(0, spawnId);
2062 trans->Append(stmt);
2063
2064 stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_GAME_EVENT_MODEL_EQUIP);
2065 stmt->setUInt64(0, spawnId);
2066 trans->Append(stmt);
2067
2068 stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_LINKED_RESPAWN);
2069 stmt->setUInt64(0, spawnId);
2071 trans->Append(stmt);
2072
2073 stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_LINKED_RESPAWN);
2074 stmt->setUInt64(0, spawnId);
2076 trans->Append(stmt);
2077
2078 stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_LINKED_RESPAWN_MASTER);
2079 stmt->setUInt64(0, spawnId);
2081 trans->Append(stmt);
2082
2083 stmt = WorldDatabase.GetPreparedStatement(WORLD_DEL_LINKED_RESPAWN_MASTER);
2084 stmt->setUInt64(0, spawnId);
2086 trans->Append(stmt);
2087
2088 WorldDatabase.CommitTransaction(trans);
2089
2090 return true;
2091}
2092
2094{
2096 return true;
2097
2099 return false;
2100
2101 return true;
2102}
2103
2105{
2106 if (IsAIEnabled() && AI()->CanSeeAlways(obj))
2107 return true;
2108
2109 return false;
2110}
2111
2112bool Creature::CanStartAttack(Unit const* who, bool force) const
2113{
2114 if (IsCivilian())
2115 return false;
2116
2117 // This set of checks is should be done only for creatures
2120 return false;
2121
2122 // Do not attack non-combat pets
2124 return false;
2125
2127 //|| who->IsControlledByPlayer() && who->IsFlying()))
2128 // we cannot check flying for other creatures, too much map/vmap calculation
2130 return false;
2131
2132 if (!force)
2133 {
2134 if (!_IsTargetAcceptable(who))
2135 return false;
2136
2138 return false;
2139 }
2140
2141 if (!CanCreatureAttack(who, force))
2142 return false;
2143
2144 // No aggro from gray creatures
2146 return false;
2147
2148 return IsWithinLOSInMap(who);
2149}
2150
2151bool Creature::CheckNoGrayAggroConfig(uint32 playerLevel, uint32 creatureLevel) const
2152{
2153 if (Trinity::XP::GetColorCode(playerLevel, creatureLevel) != XP_GRAY)
2154 return false;
2155
2156 uint32 notAbove = sWorld->getIntConfig(CONFIG_NO_GRAY_AGGRO_ABOVE);
2157 uint32 notBelow = sWorld->getIntConfig(CONFIG_NO_GRAY_AGGRO_BELOW);
2158 if (notAbove == 0 && notBelow == 0)
2159 return false;
2160
2161 if (playerLevel <= notBelow || (playerLevel >= notAbove && notAbove > 0))
2162 return true;
2163 return false;
2164}
2165
2166float Creature::GetAttackDistance(Unit const* player) const
2167{
2168 float aggroRate = sWorld->getRate(RATE_CREATURE_AGGRO);
2169 if (aggroRate == 0)
2170 return 0.0f;
2171
2172 // WoW Wiki: the minimum radius seems to be 5 yards, while the maximum range is 45 yards
2173 float maxRadius = 45.0f * aggroRate;
2174 float minRadius = 5.0f * aggroRate;
2175
2176 int32 expansionMaxLevel = int32(GetMaxLevelForExpansion(GetCreatureDifficulty()->GetHealthScalingExpansion()));
2177 int32 playerLevel = player->GetLevelForTarget(this);
2178 int32 creatureLevel = GetLevelForTarget(player);
2179
2180 // The aggro radius for creatures with equal level as the player is 15 yards.
2181 // The combatreach should not get taken into account for the distance so we drop it from the range (see Supremus as expample)
2182 float baseAggroDistance = 15.0f - GetCombatReach();
2183 float aggroRadius = baseAggroDistance;
2184
2185 // detect range auras
2186 if (uint32(creatureLevel + 5) <= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
2187 {
2190 }
2191
2192 // The aggro range of creatures with higher levels than the total player level for the expansion should get the maxlevel treatment
2193 // This makes sure that creatures such as bosses wont have a bigger aggro range than the rest of the npc's
2194 // The following code is used for blizzlike behaviour such as skippable bosses
2195 if (creatureLevel > expansionMaxLevel)
2196 aggroRadius = baseAggroDistance + float(expansionMaxLevel - playerLevel);
2197 else // + - 1 yard for each level difference between player and creature
2198 aggroRadius += float(creatureLevel - playerLevel);
2199
2200 // Make sure that we wont go over the total range limits
2201 if (aggroRadius > maxRadius)
2202 aggroRadius = maxRadius;
2203 else if (aggroRadius < minRadius)
2204 aggroRadius = minRadius;
2205
2206 return (aggroRadius * aggroRate);
2207}
2208
2210{
2212
2213 if (s == JUST_DIED)
2214 {
2216
2217 uint32 respawnDelay = m_respawnDelay;
2218 if (uint32 scalingMode = sWorld->getIntConfig(CONFIG_RESPAWN_DYNAMICMODE))
2219 GetMap()->ApplyDynamicModeRespawnScaling(this, m_spawnId, respawnDelay, scalingMode);
2220
2221 // @todo remove the boss respawn time hack in a dynspawn follow-up once we have creature groups in instances
2223 {
2224 if (IsDungeonBoss() && !m_respawnDelay)
2225 m_respawnTime = std::numeric_limits<time_t>::max(); // never respawn in this instance
2226 else
2228 }
2229 else
2230 {
2231 if (IsDungeonBoss() && !m_respawnDelay)
2232 m_respawnTime = std::numeric_limits<time_t>::max(); // never respawn in this instance
2233 else
2234 m_respawnTime = GameTime::GetGameTime() + respawnDelay;
2235 }
2236
2238
2239 ReleaseSpellFocus(nullptr, false); // remove spellcast focus
2240 DoNotReacquireSpellFocusTarget(); // cancel delayed re-target
2241 SetTarget(ObjectGuid::Empty); // drop target - dead mobs shouldn't ever target things
2242
2245
2246 SetMountDisplayId(0); // if creature is mounted on a virtual mount, remove it at death
2247
2248 setActive(false);
2249
2250 SetNoSearchAssistance(false);
2251
2252 //Dismiss group if is leader
2253 if (m_formation)
2254 {
2255 if (m_formation->GetLeader() == this)
2257
2258 if (ZoneScript* script = GetZoneScript())
2260 script->OnCreatureGroupDepleted(m_formation);
2261 }
2262
2263 bool needsFalling = (IsFlying() || IsHovering()) && !IsUnderWater() && !HasUnitState(UNIT_STATE_ROOT);
2264 SetHover(false, false);
2265 SetDisableGravity(false, false);
2266
2267 if (needsFalling)
2269
2271 }
2272 else if (s == JUST_RESPAWNED)
2273 {
2274 if (IsPet())
2275 SetFullHealth();
2276 else
2278
2279 SetTappedBy(nullptr);
2281
2282 SetCannotReachTarget(false);
2284
2286
2287 if (!IsPet())
2288 {
2290 CreatureTemplate const* cInfo = GetCreatureTemplate();
2291
2292 uint64 npcFlags;
2293 uint32 unitFlags, unitFlags2, unitFlags3;
2294 ObjectMgr::ChooseCreatureFlags(cInfo, &npcFlags, &unitFlags, &unitFlags2, &unitFlags3, _staticFlags, creatureData);
2295
2297 npcFlags |= sGameEventMgr->GetNPCFlag(this);
2298
2299 ReplaceAllNpcFlags(NPCFlags(npcFlags & 0xFFFFFFFF));
2300 ReplaceAllNpcFlags2(NPCFlags2(npcFlags >> 32));
2301
2302 ReplaceAllUnitFlags(UnitFlags(unitFlags));
2303 ReplaceAllUnitFlags2(UnitFlags2(unitFlags2));
2304 ReplaceAllUnitFlags3(UnitFlags3(unitFlags3));
2306
2308
2310
2311 if (uint32 vignetteId = cInfo->VignetteID)
2312 SetVignette(vignetteId);
2313 }
2314
2317
2318 if (!IsPet())
2320
2322 }
2323}
2324
2325void Creature::Respawn(bool force)
2326{
2327 if (force)
2328 {
2329 if (IsAlive())
2331 else if (getDeathState() != CORPSE)
2333 }
2334
2336 {
2338 RemoveCorpse(false, false);
2339
2340 if (getDeathState() == DEAD)
2341 {
2342 TC_LOG_DEBUG("entities.unit", "Respawning creature {} ({})", GetName(), GetGUID().ToString());
2343 m_respawnTime = 0;
2345 m_loot = nullptr;
2346
2347 if (m_originalEntry != GetEntry())
2349
2350 SelectLevel();
2351
2353
2355 if (sObjectMgr->GetCreatureModelRandomGender(&display, GetCreatureTemplate()))
2356 SetDisplayId(display.CreatureDisplayID, true);
2357
2359
2360 // Re-initialize reactstate that could be altered by movementgenerators
2362
2363 if (UnitAI* ai = AI()) // reset the AI to be sure no dirty or uninitialized values will be used till next tick
2364 ai->Reset();
2365
2366 m_triggerJustAppeared = true;
2368
2369 uint32 poolid = GetCreatureData() ? GetCreatureData()->poolId : 0;
2370 if (poolid)
2371 sPoolMgr->UpdatePool<Creature>(GetMap()->GetPoolData(), poolid, GetSpawnId());
2372 }
2374 }
2375 else
2376 {
2377 if (m_spawnId)
2379 }
2380
2381 TC_LOG_DEBUG("entities.unit", "Respawning creature {} ({})",
2382 GetName(), GetGUID().ToString());
2383
2384}
2385
2386void Creature::ForcedDespawn(uint32 timeMSToDespawn, Seconds forceRespawnTimer)
2387{
2388 if (timeMSToDespawn)
2389 {
2390 m_Events.AddEvent(new ForcedDespawnDelayEvent(*this, forceRespawnTimer), m_Events.CalculateTime(Milliseconds(timeMSToDespawn)));
2391 return;
2392 }
2393
2395 {
2396 uint32 corpseDelay = GetCorpseDelay();
2397 uint32 respawnDelay = GetRespawnDelay();
2398
2399 // do it before killing creature
2401
2402 bool overrideRespawnTime = false;
2403 if (IsAlive())
2404 {
2405 if (forceRespawnTimer > Seconds::zero())
2406 {
2407 SetCorpseDelay(0);
2408 SetRespawnDelay(forceRespawnTimer.count());
2409 overrideRespawnTime = true;
2410 }
2411
2413 }
2414
2415 // Skip corpse decay time
2416 RemoveCorpse(!overrideRespawnTime, false);
2417
2418 SetCorpseDelay(corpseDelay);
2419 SetRespawnDelay(respawnDelay);
2420 }
2421 else
2422 {
2423 if (forceRespawnTimer > Seconds::zero())
2424 SaveRespawnTime(forceRespawnTimer.count());
2425 else
2426 {
2427 uint32 respawnDelay = m_respawnDelay;
2428 if (uint32 scalingMode = sWorld->getIntConfig(CONFIG_RESPAWN_DYNAMICMODE))
2429 GetMap()->ApplyDynamicModeRespawnScaling(this, m_spawnId, respawnDelay, scalingMode);
2430 m_respawnTime = GameTime::GetGameTime() + respawnDelay;
2432 }
2433
2435 }
2436}
2437
2438void Creature::DespawnOrUnsummon(Milliseconds timeToDespawn /*= 0s*/, Seconds forceRespawnTimer /*= 0s*/)
2439{
2440 if (TempSummon* summon = ToTempSummon())
2441 summon->UnSummon(timeToDespawn.count());
2442 else
2443 ForcedDespawn(timeToDespawn.count(), forceRespawnTimer);
2444}
2445
2446void Creature::LoadTemplateImmunities(int32 creatureImmunitiesId)
2447{
2448 // uint32 max used for "spell id", the immunity system will not perform SpellInfo checks against invalid spells
2449 // used so we know which immunities were loaded from template
2450 static uint32 constexpr placeholderSpellId = std::numeric_limits<uint32>::max();
2451
2452 auto applyCreatureImmunities = [this](CreatureImmunities const* immunities, bool apply)
2453 {
2454 for (std::size_t i = 0; i < immunities->School.size(); ++i)
2455 if (immunities->School[i])
2456 ApplySpellImmune(placeholderSpellId, IMMUNITY_SCHOOL, 1 << i, apply);
2457
2458 for (std::size_t i = 0; i < immunities->DispelType.size(); ++i)
2459 if (immunities->DispelType[i])
2460 ApplySpellImmune(placeholderSpellId, IMMUNITY_DISPEL, i, apply);
2461
2462 for (std::size_t i = 0; i < immunities->Mechanic.size(); ++i)
2463 if (immunities->Mechanic[i])
2464 ApplySpellImmune(placeholderSpellId, IMMUNITY_MECHANIC, i, apply);
2465
2466 for (SpellEffects effect : immunities->Effect)
2467 ApplySpellImmune(placeholderSpellId, IMMUNITY_EFFECT, effect, apply);
2468
2469 for (AuraType aura : immunities->Aura)
2470 ApplySpellImmune(placeholderSpellId, IMMUNITY_STATE, aura, apply);
2471
2472 if (immunities->Other != SpellOtherImmunity::None)
2473 ApplySpellImmune(placeholderSpellId, IMMUNITY_OTHER, immunities->Other.AsUnderlyingType(), apply);
2474 };
2475
2476 // unapply template immunities (in case we're updating entry)
2478 applyCreatureImmunities(immunities, false);
2479
2480 // apply new immunities
2481 if (CreatureImmunities const* immunities = SpellMgr::GetCreatureImmunities(creatureImmunitiesId))
2482 {
2483 _creatureImmunitiesId = creatureImmunitiesId;
2484 applyCreatureImmunities(immunities, true);
2485 }
2486 else
2488}
2489
2490bool Creature::IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo const& spellEffectInfo, WorldObject const* caster,
2491 bool requireImmunityPurgesEffectAttribute /*= false*/) const
2492{
2494 return true;
2495
2496 return Unit::IsImmunedToSpellEffect(spellInfo, spellEffectInfo, caster, requireImmunityPurgesEffectAttribute);
2497}
2498
2500{
2501 if (IsPet())
2502 return false;
2503
2505}
2506
2508{
2509 if (IsPet())
2510 return false;
2511
2512 return (GetCreatureDifficulty()->TypeFlags & CREATURE_TYPE_FLAG_BOSS_MOB) != 0;
2513}
2514
2515// select nearest hostile unit within the given distance (regardless of threat list).
2516Unit* Creature::SelectNearestTarget(float dist, bool playerOnly /* = false */) const
2517{
2518 if (dist == 0.0f)
2520
2521 Unit* target = nullptr;
2522 Trinity::NearestHostileUnitCheck u_check(this, dist, playerOnly);
2524 Cell::VisitAllObjects(this, searcher, dist);
2525 return target;
2526}
2527
2528// select nearest hostile unit within the given attack distance (i.e. distance is ignored if > than ATTACK_DISTANCE), regardless of threat list.
2530{
2531 if (dist > MAX_VISIBILITY_DISTANCE)
2532 {
2533 TC_LOG_ERROR("entities.unit", "Creature {} SelectNearestTargetInAttackDistance called with dist > MAX_VISIBILITY_DISTANCE. Distance set to ATTACK_DISTANCE.", GetGUID().ToString());
2534 dist = ATTACK_DISTANCE;
2535 }
2536
2537 Unit* target = nullptr;
2540 Cell::VisitAllObjects(this, searcher, std::max(dist, ATTACK_DISTANCE));
2541 return target;
2542}
2543
2545{
2547
2548 packet.UnitGUID = GetGUID();
2549 packet.Reaction = reactionType;
2550
2551 SendMessageToSet(packet.Write(), true);
2552
2553 TC_LOG_DEBUG("network", "WORLD: Sent SMSG_AI_REACTION, type {}.", reactionType);
2554}
2555
2557{
2558 if (!m_AlreadyCallAssistance && GetVictim() && !IsPet() && !IsCharmed())
2559 {
2560 SetNoCallAssistance(true);
2561
2562 float radius = sWorld->getFloatConfig(CONFIG_CREATURE_FAMILY_ASSISTANCE_RADIUS);
2563
2564 if (radius > 0)
2565 {
2566 std::list<Creature*> assistList;
2567 Trinity::AnyAssistCreatureInRangeCheck u_check(this, GetVictim(), radius);
2569 Cell::VisitGridObjects(this, searcher, radius);
2570
2571 if (!assistList.empty())
2572 {
2574 while (!assistList.empty())
2575 {
2576 // Pushing guids because in delay can happen some creature gets despawned => invalid pointer
2577 e->AddAssistant((*assistList.begin())->GetGUID());
2578 assistList.pop_front();
2579 }
2581 }
2582 }
2583 }
2584}
2585
2586void Creature::CallForHelp(float radius)
2587{
2588 if (radius <= 0.0f || !IsEngaged() || !IsAlive() || IsPet() || IsCharmed())
2589 return;
2590
2592 if (!target)
2593 target = GetThreatManager().GetAnyTarget();
2594 if (!target)
2595 target = GetCombatManager().GetAnyTarget();
2596
2597 if (!target)
2598 {
2599 TC_LOG_ERROR("entities.unit", "Creature {} ({}) trying to call for help without being in combat.", GetEntry(), GetName());
2600 return;
2601 }
2602
2603 Trinity::CallOfHelpCreatureInRangeDo u_do(this, target, radius);
2605 Cell::VisitGridObjects(this, worker, radius);
2606}
2607
2608bool Creature::CanAssistTo(Unit const* u, Unit const* enemy, bool checkfaction /*= true*/) const
2609{
2610 // is it true?
2612 return false;
2613
2614 // we don't need help from zombies :)
2615 if (!IsAlive())
2616 return false;
2617
2618 // we cannot assist in evade mode
2619 if (IsInEvadeMode())
2620 return false;
2621
2622 // or if enemy is in evade mode
2623 if (enemy->GetTypeId() == TYPEID_UNIT && enemy->ToCreature()->IsInEvadeMode())
2624 return false;
2625
2626 // we don't need help from non-combatant ;)
2627 if (IsCivilian())
2628 return false;
2629
2631 return false;
2632
2633 // skip fighting creature
2634 if (IsEngaged())
2635 return false;
2636
2637 // only free creature
2638 if (!GetCharmerOrOwnerGUID().IsEmpty())
2639 return false;
2640
2641 // only from same creature faction
2642 if (checkfaction)
2643 {
2644 if (GetFaction() != u->GetFaction())
2645 return false;
2646 }
2647 else
2648 {
2649 if (!IsFriendlyTo(u))
2650 return false;
2651 }
2652
2653 // skip non hostile to caster enemy creatures
2654 if (!IsHostileTo(enemy))
2655 return false;
2656
2657 return true;
2658}
2659
2660// use this function to avoid having hostile creatures attack
2661// friendlies and other mobs they shouldn't attack
2662bool Creature::_IsTargetAcceptable(Unit const* target) const
2663{
2664 ASSERT(target);
2665
2666 // if the target cannot be attacked, the target is not acceptable
2667 if (IsFriendlyTo(target)
2668 || !target->isTargetableForAttack(false)
2669 || (m_vehicle && (IsOnVehicle(target) || m_vehicle->GetBase()->IsOnVehicle(target))))
2670 return false;
2671
2672 if (target->HasUnitState(UNIT_STATE_DIED))
2673 {
2674 // some creatures can detect fake death
2676 return true;
2677 else
2678 return false;
2679 }
2680
2681 // if I'm already fighting target, or I'm hostile towards the target, the target is acceptable
2682 if (IsEngagedBy(target) || IsHostileTo(target))
2683 return true;
2684
2685 // if the target's victim is not friendly, or the target is friendly, the target is not acceptable
2686 return false;
2687}
2688
2690{
2692 return;
2693
2695 {
2696 RespawnInfo ri;
2698 ri.spawnId = m_spawnId;
2701 return;
2702 }
2703
2704 time_t thisRespawnTime = forceDelay ? GameTime::GetGameTime() + forceDelay : m_respawnTime;
2706}
2707
2708// this should not be called by petAI or
2709bool Creature::CanCreatureAttack(Unit const* victim, bool /*force*/) const
2710{
2711 if (!victim->IsInMap(this))
2712 return false;
2713
2714 if (!IsValidAttackTarget(victim))
2715 return false;
2716
2717 if (!victim->isInAccessiblePlaceFor(this))
2718 return false;
2719
2720 if (CreatureAI* ai = AI())
2721 if (!ai->CanAIAttack(victim))
2722 return false;
2723
2724 // we cannot attack in evade mode
2725 if (IsInEvadeMode())
2726 return false;
2727
2728 // or if enemy is in evade mode
2729 if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsInEvadeMode())
2730 return false;
2731
2733 {
2734 if (GetMap()->IsDungeon())
2735 return true;
2736
2737 // don't check distance to home position if recently damaged, this should include taunt auras
2739 return true;
2740 }
2741
2742 // Map visibility range, but no more than 2*cell size
2743 float dist = std::min<float>(GetMap()->GetVisibilityRange(), SIZE_OF_GRID_CELL * 2);
2744
2745 if (Unit* unit = GetCharmerOrOwner())
2746 return victim->IsWithinDist(unit, dist);
2747 else
2748 {
2749 // include sizes for huge npcs
2750 dist += GetCombatReach() + victim->GetCombatReach();
2751
2752 // to prevent creatures in air ignore attacks because distance is already too high...
2753 if (CanFly())
2754 return victim->IsInDist2d(&m_homePosition, dist);
2755 else
2756 return victim->IsInDist(&m_homePosition, dist);
2757 }
2758}
2759
2761{
2762 if (m_spawnId)
2763 {
2764 if (CreatureAddon const* addon = sObjectMgr->GetCreatureAddon(m_spawnId))
2765 return addon;
2766 }
2767
2768 return sObjectMgr->GetCreatureTemplateAddon(GetEntry());
2769}
2770
2771//creature_addon table
2773{
2774 CreatureAddon const* creatureAddon = GetCreatureAddon();
2775 if (!creatureAddon)
2776 return false;
2777
2778 if (uint32 mountDisplayId = _defaultMountDisplayIdOverride.value_or(creatureAddon->mount); mountDisplayId != 0)
2779 Mount(mountDisplayId);
2780
2782 ReplaceAllVisFlags(UnitVisFlags(creatureAddon->visFlags));
2783 SetAnimTier(AnimTier(creatureAddon->animTier), false);
2784
2785 SetSheath(SheathState(creatureAddon->sheathState));
2787
2788 // These fields must only be handled by core internals and must not be modified via scripts/DB dat
2791
2792 if (creatureAddon->emote != 0)
2793 SetEmoteState(Emote(creatureAddon->emote));
2794
2795 SetAIAnimKitId(creatureAddon->aiAnimKit);
2796 SetMovementAnimKitId(creatureAddon->movementAnimKit);
2797 SetMeleeAnimKitId(creatureAddon->meleeAnimKit);
2798
2799 // Check if visibility distance different
2802
2803 // Load Path
2804 if (creatureAddon->PathId != 0)
2805 _waypointPathId = creatureAddon->PathId;
2806
2807 if (!creatureAddon->auras.empty())
2808 {
2809 for (std::vector<uint32>::const_iterator itr = creatureAddon->auras.begin(); itr != creatureAddon->auras.end(); ++itr)
2810 {
2811 SpellInfo const* AdditionalSpellInfo = sSpellMgr->GetSpellInfo(*itr, GetMap()->GetDifficultyID());
2812 if (!AdditionalSpellInfo)
2813 {
2814 TC_LOG_ERROR("sql.sql", "Creature {} has wrong spell {} defined in `auras` field.", GetGUID().ToString(), *itr);
2815 continue;
2816 }
2817
2818 // skip already applied aura
2819 if (HasAura(*itr))
2820 continue;
2821
2822 AddAura(*itr, this);
2823 TC_LOG_DEBUG("entities.unit", "Spell: {} added to creature {}", *itr, GetGUID().ToString());
2824 }
2825 }
2826 return true;
2827}
2828
2829void Creature::LoadCreaturesSparringHealth(bool force /*= false*/)
2830{
2831 if (std::vector<float> const* templateValues = sObjectMgr->GetCreatureTemplateSparringValues(GetCreatureTemplate()->Entry))
2832 if (force || std::find(templateValues->begin(), templateValues->end(), _sparringHealthPct) != templateValues->end()) // only re-randomize sparring value if it was loaded from template (not when set to custom value from script)
2834}
2835
2838{
2840 packet.AreaID = GetAreaId();
2841 packet.Write();
2842
2843 Team enemyTeam = attacker->GetTeam();
2844 if (enemyTeam != ALLIANCE)
2845 sWorld->SendGlobalMessage(packet.GetRawPacket(), nullptr, ALLIANCE);
2846 if (enemyTeam != HORDE)
2847 sWorld->SendGlobalMessage(packet.GetRawPacket(), nullptr, HORDE);
2848}
2849
2850void Creature::SetCanMelee(bool canMelee, bool fleeFromMelee /*= false*/)
2851{
2852 bool wasFleeingFromMelee = HasFlag(CREATURE_STATIC_FLAG_NO_MELEE_FLEE);
2853
2854 _staticFlags.ApplyFlag(CREATURE_STATIC_FLAG_NO_MELEE_FLEE, !canMelee && fleeFromMelee);
2856
2857 if (wasFleeingFromMelee == HasFlag(CREATURE_STATIC_FLAG_NO_MELEE_FLEE))
2858 return;
2859
2860 Unit* victim = GetVictim();
2861 if (!victim)
2862 return;
2863
2865 if (!currentMovement)
2866 return;
2867
2868 bool canChangeMovement = [&]
2869 {
2870 if (wasFleeingFromMelee)
2872
2873 return currentMovement->GetMovementGeneratorType() == CHASE_MOTION_TYPE;
2874 }();
2875
2876 if (!canChangeMovement)
2877 return;
2878
2879 GetMotionMaster()->Remove(currentMovement);
2881}
2882
2884{
2886 GetMotionMaster()->MoveChase(victim, range, angle);
2887 else
2888 GetMotionMaster()->MoveFleeing(victim);
2889}
2890
2891bool Creature::HasSpell(uint32 spellID) const
2892{
2893 return std::find(std::begin(m_spells), std::end(m_spells), spellID) != std::end(m_spells);
2894}
2895
2897{
2898 time_t now = GameTime::GetGameTime();
2899 if (m_respawnTime > now)
2900 return m_respawnTime;
2901 else
2902 return now;
2903}
2904
2906{
2907 m_respawnTime = respawn ? GameTime::GetGameTime() + respawn : 0;
2908}
2909
2911{
2912 if (m_creatureData)
2913 {
2914 if (dist)
2916
2917 return m_creatureData->spawnPoint;
2918 }
2919 else
2920 {
2921 if (dist)
2922 *dist = 0;
2923
2924 return GetHomePosition();
2925 }
2926}
2927
2929{
2930 SetHover(GetMovementTemplate().IsHoverInitiallyEnabled());
2931
2932 // CREATURE_STATIC_FLAG_FLOATING disables gravity and plays hover anim
2934
2935 // CREATURE_STATIC_FLAG_SESSILE disables gravity and applies root
2937
2939 {
2941 SetSwim(false);
2942 }
2943 else
2945
2947}
2948
2950{
2951 // Do not update movement flags if creature is controlled by a player (charm/vehicle)
2952 if (m_playerMovingMe)
2953 return;
2954
2955 // Set the movement flags if the creature is in that mode. (Only fly if actually in air, only swim if in water, etc)
2956 float ground = GetFloorZ();
2957 bool isInAir = (G3D::fuzzyGt(GetPositionZ(), ground + GetHoverOffset() + GROUND_HEIGHT_TOLERANCE) || G3D::fuzzyLt(GetPositionZ(), ground - GROUND_HEIGHT_TOLERANCE)); // Can be underground too, prevent the falling
2958 if (!isInAir)
2960
2962 if (GetVictim() && GetVictim()->IsInWater() && !GetVictim()->IsOnOceanFloor())
2964
2965 if (IsInWater() && CanSwim())
2966 SetSwim(true);
2967 else if (!IsInWater()) // We do not want to disable swimming again when a creature is in water - may to lead some nasty bugs
2968 SetSwim(false);
2969}
2970
2976
2978{
2979 if (IsFloating())
2980 SetDisableGravity(true, false);
2981 else
2982 {
2983 if (IsSessile() ||
2987 return;
2988
2989 SetDisableGravity(false, false);
2990 }
2991}
2992
2998
3000{
3001 if (IsSessile())
3002 {
3004 SetDisableGravity(true, false, false);
3005 }
3006 else
3007 {
3009 return;
3010
3013
3014 if (IsFloating() ||
3017 return;
3018
3019 SetDisableGravity(false, false, false);
3020 }
3021}
3022
3024{
3025 if (CreatureMovementData const* movementOverride = sObjectMgr->GetCreatureMovementOverride(m_spawnId))
3026 return *movementOverride;
3027
3028 return GetCreatureTemplate()->Movement;
3029}
3030
3032{
3033 if (Unit::CanSwim())
3034 return true;
3035
3036 if (IsPet())
3037 return true;
3038
3039 return false;
3040}
3041
3049
3051{
3052 time_t now = GameTime::GetGameTime();
3053 // Do not reset corpse remove time if corpse is already removed
3054 if (m_corpseRemoveTime <= now)
3055 return;
3056
3057 // Scripts can choose to ignore RATE_CORPSE_DECAY_LOOTED by calling SetCorpseDelay(timer, true)
3058 float decayRate = m_ignoreCorpseDecayRatio ? 1.f : sWorld->getRate(RATE_CORPSE_DECAY_LOOTED);
3059
3060 // corpse skinnable, but without skinning flag, and then skinned, corpse will despawn next update
3061 bool isFullySkinned = [&]() -> bool
3062 {
3063 if (m_loot && m_loot->loot_type == LOOT_SKINNING && m_loot->isLooted())
3064 return true;
3065
3066 bool hasSkinningLoot = false;
3067 for (auto const& [_, loot] : m_personalLoot)
3068 {
3069 if (loot->loot_type == LOOT_SKINNING)
3070 {
3071 if (!loot->isLooted())
3072 return false;
3073
3074 hasSkinningLoot = true;
3075 }
3076 }
3077
3078 return hasSkinningLoot;
3079 }();
3080
3081 if (isFullySkinned)
3082 m_corpseRemoveTime = now;
3083 else
3084 m_corpseRemoveTime = now + uint32(m_corpseDelay * decayRate);
3085
3087}
3088
3094
3100
3102{
3104
3105 // If as a result of npcflag updates we stop seeing UNIT_NPC_FLAG_QUESTGIVER then
3106 // we must also send SMSG_QUEST_GIVER_STATUS_MULTIPLE because client will not request it automatically
3107 if (IsQuestGiver())
3108 {
3109 auto sender = [&](Player const* receiver)
3110 {
3111 receiver->PlayerTalkClass->SendQuestGiverStatus(receiver->GetQuestDialogStatus(this), GetGUID());
3112 };
3113 Trinity::MessageDistDeliverer notifier(this, sender, GetVisibilityRange());
3115 }
3116}
3117
3119{
3120 return m_unitData->ContentTuningID != 0;
3121}
3122
3124{
3125 CreatureDifficulty const* creatureDifficulty = GetCreatureDifficulty();
3126
3127 int32 contentTuningId = creatureDifficulty->ContentTuningID;
3128
3129 if (!contentTuningId && !IsCritter())
3130 {
3131 if (MapDifficultyEntry const* mapDifficulty = GetMap()->GetMapDifficulty())
3132 if (mapDifficulty->ContentTuningID)
3133 contentTuningId = mapDifficulty->ContentTuningID;
3134
3135 if (!contentTuningId)
3136 {
3137 AreaTableEntry const* area = sAreaTableStore.LookupEntry(GetAreaId());
3138 while (area)
3139 {
3140 if (area->ContentTuningID)
3141 {
3142 contentTuningId = area->ContentTuningID;
3143 break;
3144 }
3145
3146 area = sAreaTableStore.LookupEntry(area->ParentAreaID);
3147 }
3148 }
3149 }
3150
3151 int32 scalingLevelDelta = 0;
3152 if (contentTuningId)
3153 {
3154 int32 mindelta = std::min(creatureDifficulty->DeltaLevelMax, creatureDifficulty->DeltaLevelMin);
3155 int32 maxdelta = std::max(creatureDifficulty->DeltaLevelMax, creatureDifficulty->DeltaLevelMin);
3156 scalingLevelDelta = mindelta == maxdelta ? mindelta : irand(mindelta, maxdelta);
3157 }
3158
3159 ApplyLevelScaling(contentTuningId, scalingLevelDelta);
3160}
3161
3162void Creature::ApplyLevelScaling(int32 contentTuningId, int32 scalingLevelDelta)
3163{
3164 if (Optional<ContentTuningLevels> levels = sDB2Manager.GetContentTuningData(contentTuningId, {}))
3165 {
3168 }
3169
3172}
3173
3175{
3176 CreatureTemplate const* cInfo = GetCreatureTemplate();
3177 CreatureDifficulty const* creatureDifficulty = GetCreatureDifficulty();
3178 double baseHealth = sDB2Manager.EvaluateExpectedStat(ExpectedStatType::CreatureHealth, level, creatureDifficulty->GetHealthScalingExpansion(), m_unitData->ContentTuningID, Classes(cInfo->unit_class), 0);
3179 return std::ceil(baseHealth * creatureDifficulty->HealthModifier);
3180}
3181
3183{
3184 if (!HasScalableLevels())
3185 return 1.0f;
3186
3187 uint8 levelForTarget = GetLevelForTarget(target);
3188
3189 return double(GetMaxHealthByLevel(levelForTarget)) / double(GetCreateHealth());
3190}
3191
3193{
3194 CreatureTemplate const* cInfo = GetCreatureTemplate();
3195 CreatureDifficulty const* creatureDifficulty = GetCreatureDifficulty();
3196 return sDB2Manager.EvaluateExpectedStat(ExpectedStatType::CreatureAutoAttackDps, level, creatureDifficulty->GetHealthScalingExpansion(), m_unitData->ContentTuningID, Classes(cInfo->unit_class), 0);
3197}
3198
3200{
3201 if (!HasScalableLevels())
3202 return 1.0f;
3203
3204 uint8 levelForTarget = GetLevelForTarget(target);
3205
3206 return GetBaseDamageForLevel(levelForTarget) / GetBaseDamageForLevel(GetLevel());
3207}
3208
3210{
3211 CreatureTemplate const* cInfo = GetCreatureTemplate();
3212 CreatureDifficulty const* creatureDifficulty = GetCreatureDifficulty();
3213 float baseArmor = sDB2Manager.EvaluateExpectedStat(ExpectedStatType::CreatureArmor, level, creatureDifficulty->GetHealthScalingExpansion(), m_unitData->ContentTuningID, Classes(cInfo->unit_class), 0);
3214 return baseArmor * creatureDifficulty->ArmorModifier;
3215}
3216
3218{
3219 if (!HasScalableLevels())
3220 return 1.0f;
3221
3222 uint8 levelForTarget = GetLevelForTarget(target);
3223
3224 return GetBaseArmorForLevel(levelForTarget) / GetBaseArmorForLevel(GetLevel());
3225}
3226
3228{
3229 if (Unit const* unitTarget = target->ToUnit())
3230 {
3231 // If this creature should scale level, adapt level depending of target level
3232 // between UNIT_FIELD_SCALING_LEVEL_MIN and UNIT_FIELD_SCALING_LEVEL_MAX
3233 if (HasScalableLevels())
3234 {
3235 int32 scalingLevelMin = m_unitData->ScalingLevelMin;
3236 int32 scalingLevelMax = m_unitData->ScalingLevelMax;
3237 int32 scalingLevelDelta = m_unitData->ScalingLevelDelta;
3238 uint8 scalingFactionGroup = m_unitData->ScalingFactionGroup;
3239 int32 targetLevel = unitTarget->GetEffectiveLevel();
3240
3241 int32 targetLevelDelta = 0;
3242
3243 if (Player const* playerTarget = target->ToPlayer())
3244 {
3245 if (scalingFactionGroup && sFactionTemplateStore.AssertEntry(sChrRacesStore.AssertEntry(playerTarget->GetRace())->FactionID)->FactionGroup != scalingFactionGroup)
3246 scalingLevelMin = scalingLevelMax;
3247
3248 int32 maxCreatureScalingLevel = playerTarget->m_activePlayerData->MaxCreatureScalingLevel;
3249 targetLevelDelta = std::min(maxCreatureScalingLevel > 0 ? maxCreatureScalingLevel - targetLevel : 0, *playerTarget->m_activePlayerData->ScalingPlayerLevelDelta);
3250 }
3251
3252 int32 levelWithDelta = targetLevel + targetLevelDelta;
3253 int32 level = RoundToInterval(levelWithDelta, scalingLevelMin, scalingLevelMax) + scalingLevelDelta;
3254 return RoundToInterval(level, 1, MAX_LEVEL + 3);
3255 }
3256 }
3257
3258 return Unit::GetLevelForTarget(target);
3259}
3260
3261std::string const& Creature::GetAIName() const
3262{
3263 return sObjectMgr->GetCreatureTemplate(GetEntry())->AIName;
3264}
3265
3266std::string Creature::GetScriptName() const
3267{
3268 return sObjectMgr->GetScriptName(GetScriptId());
3269}
3270
3272{
3274 if (uint32 scriptId = creatureData->scriptId)
3275 return scriptId;
3276
3277 return ASSERT_NOTNULL(sObjectMgr->GetCreatureTemplate(GetEntry()))->ScriptID;
3278}
3279
3281{
3282 // copy references to stringIds from template and spawn
3283 m_stringIds = parent->m_stringIds;
3284
3285 // then copy script stringId, not just its reference
3286 SetScriptStringId(std::string(parent->GetStringId(StringIdType::Script)));
3287}
3288
3289bool Creature::HasStringId(std::string_view id) const
3290{
3291 return std::ranges::any_of(m_stringIds, [id](std::string const* stringId) { return stringId && *stringId == id; });
3292}
3293
3295{
3296 if (!id.empty())
3297 {
3298 m_scriptStringId.emplace(std::move(id));
3300 }
3301 else
3302 {
3303 m_scriptStringId.reset();
3305 }
3306}
3307
3309{
3310 if (!player)
3311 return nullptr;
3312
3313 if (CreatureData const* data = GetCreatureData())
3314 {
3315 if (data->spawnTrackingData && !data->spawnTrackingQuestObjectives.empty())
3316 {
3317 SpawnTrackingState state = player->GetSpawnTrackingStateByObjectives(data->spawnTrackingData->SpawnTrackingId, data->spawnTrackingQuestObjectives);
3318 return &data->spawnTrackingStates[AsUnderlyingType(state)];
3319 }
3320 }
3321
3322 return nullptr;
3323}
3324
3326{
3327 return sObjectMgr->GetNpcVendorItemList(GetEntry());
3328}
3329
3331{
3332 if (!vItem->maxcount)
3333 return vItem->maxcount;
3334
3335 VendorItemCounts::iterator itr = m_vendorItemCounts.begin();
3336 for (; itr != m_vendorItemCounts.end(); ++itr)
3337 if (itr->itemId == vItem->item)
3338 break;
3339
3340 if (itr == m_vendorItemCounts.end())
3341 return vItem->maxcount;
3342
3343 VendorItemCount* vCount = &*itr;
3344
3345 time_t ptime = GameTime::GetGameTime();
3346
3347 if (time_t(vCount->lastIncrementTime + vItem->incrtime) <= ptime)
3348 if (ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(vItem->item))
3349 {
3350 uint32 diff = uint32((ptime - vCount->lastIncrementTime)/vItem->incrtime);
3351 if ((vCount->count + diff * pProto->GetBuyCount()) >= vItem->maxcount)
3352 {
3353 m_vendorItemCounts.erase(itr);
3354 return vItem->maxcount;
3355 }
3356
3357 vCount->count += diff * pProto->GetBuyCount();
3358 vCount->lastIncrementTime = ptime;
3359 }
3360
3361 return vCount->count;
3362}
3363
3365{
3366 if (!vItem->maxcount)
3367 return 0;
3368
3369 VendorItemCounts::iterator itr = m_vendorItemCounts.begin();
3370 for (; itr != m_vendorItemCounts.end(); ++itr)
3371 if (itr->itemId == vItem->item)
3372 break;
3373
3374 if (itr == m_vendorItemCounts.end())
3375 {
3376 uint32 new_count = vItem->maxcount > used_count ? vItem->maxcount-used_count : 0;
3377 m_vendorItemCounts.push_back(VendorItemCount(vItem->item, new_count));
3378 return new_count;
3379 }
3380
3381 VendorItemCount* vCount = &*itr;
3382
3383 time_t ptime = GameTime::GetGameTime();
3384
3385 if (time_t(vCount->lastIncrementTime + vItem->incrtime) <= ptime)
3386 if (ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(vItem->item))
3387 {
3388 uint32 diff = uint32((ptime - vCount->lastIncrementTime)/vItem->incrtime);
3389 if ((vCount->count + diff * pProto->GetBuyCount()) < vItem->maxcount)
3390 vCount->count += diff * pProto->GetBuyCount();
3391 else
3392 vCount->count = vItem->maxcount;
3393 }
3394
3395 vCount->count = vCount->count > used_count ? vCount->count-used_count : 0;
3396 vCount->lastIncrementTime = ptime;
3397 return vCount->count;
3398}
3399
3425
3449
3450// overwrite WorldObject function for proper name localization
3452{
3453 if (locale != DEFAULT_LOCALE)
3454 if (CreatureLocale const* cl = sObjectMgr->GetCreatureLocale(GetEntry()))
3455 if (cl->Name.size() > locale && !cl->Name[locale].empty())
3456 return cl->Name[locale];
3457
3458 return GetName();
3459}
3460
3461bool Creature::HasLabel(int32 cretureLabel) const
3462{
3463 return advstd::ranges::contains(GetLabels(), cretureLabel);
3464}
3465
3466std::span<int32 const> Creature::GetLabels() const
3467{
3468 return sDB2Manager.GetCreatureLabels(GetCreatureDifficulty()->CreatureDifficultyID);
3469}
3470
3472{
3473 return MAX_SPELL_CHARM;
3474}
3475
3477{
3478 if (pos >= MAX_SPELL_CHARM || !m_charmInfo || m_charmInfo->GetCharmSpell(pos)->GetType() != ACT_ENABLED)
3479 return 0;
3480 else
3481 return m_charmInfo->GetCharmSpell(pos)->GetAction();
3482}
3483
3485{
3486 float range = 0.f;
3487
3488 for (uint8 i = 0; i < GetPetAutoSpellSize(); ++i)
3489 {
3490 uint32 spellID = GetPetAutoSpellOnPos(i);
3491 if (!spellID)
3492 continue;
3493
3494 if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID, GetMap()->GetDifficultyID()))
3495 {
3496 if (spellInfo->GetRecoveryTime() == 0 && spellInfo->RangeEntry && spellInfo->RangeEntry->ID != 1 /*Self*/ && spellInfo->RangeEntry->ID != 2 /*Combat Range*/ && spellInfo->GetMaxRange() > range)
3497 range = spellInfo->GetMaxRange();
3498 }
3499 }
3500
3501 return range;
3502}
3503
3505{
3506 if (cannotReach == m_cannotReachTarget)
3507 return;
3508 m_cannotReachTarget = cannotReach;
3510
3511 if (cannotReach)
3512 TC_LOG_DEBUG("entities.unit.chase", "Creature::SetCannotReachTarget() called with true. Details: {}", GetDebugInfo());
3513}
3514
3516{
3517 if (mountCreatureDisplayId && !sCreatureDisplayInfoStore.HasRecord(*mountCreatureDisplayId))
3518 mountCreatureDisplayId.reset();
3519
3520 _defaultMountDisplayIdOverride = mountCreatureDisplayId;
3521}
3522
3523float Creature::GetAggroRange(Unit const* target) const
3524{
3525 // Determines the aggro range for creatures (usually pets), used mainly for aggressive pet target selection.
3526 // Based on data from wowwiki due to lack of 3.3.5a data
3527
3528 if (target && IsPet())
3529 {
3530 uint32 targetLevel = 0;
3531
3532 if (target->GetTypeId() == TYPEID_PLAYER)
3533 targetLevel = target->GetLevelForTarget(this);
3534 else if (target->GetTypeId() == TYPEID_UNIT)
3535 targetLevel = target->ToCreature()->GetLevelForTarget(this);
3536
3537 uint32 myLevel = GetLevelForTarget(target);
3538 int32 levelDiff = int32(targetLevel) - int32(myLevel);
3539
3540 // The maximum Aggro Radius is capped at 45 yards (25 level difference)
3541 if (levelDiff < -25)
3542 levelDiff = -25;
3543
3544 // The base aggro radius for mob of same level
3545 float aggroRadius = 20;
3546
3547 // Aggro Radius varies with level difference at a rate of roughly 1 yard/level
3548 aggroRadius -= (float)levelDiff;
3549
3550 // detect range auras
3552
3553 // detected range auras
3555
3556 // Just in case, we don't want pets running all over the map
3557 if (aggroRadius > MAX_AGGRO_RADIUS)
3558 aggroRadius = MAX_AGGRO_RADIUS;
3559
3560 // Minimum Aggro Radius for a mob seems to be combat range (5 yards)
3561 // hunter pets seem to ignore minimum aggro radius so we'll default it a little higher
3562 if (aggroRadius < 10)
3563 aggroRadius = 10;
3564
3565 return (aggroRadius);
3566 }
3567
3568 // Default
3569 return 0.0f;
3570}
3571
3572Unit* Creature::SelectNearestHostileUnitInAggroRange(bool useLOS, bool ignoreCivilians) const
3573{
3574 // Selects nearest hostile target within creature's aggro range. Used primarily by
3575 // pets set to aggressive. Will not return neutral or friendly targets.
3576
3577 Unit* target = nullptr;
3578
3579 Trinity::NearestHostileUnitInAggroRangeCheck u_check(this, useLOS, ignoreCivilians);
3581
3583
3584 return target;
3585}
3586
3588{
3589 return GetCreatureTemplate()->scale;
3590}
3591
3593{
3594 Unit::SetObjectScale(scale);
3595
3596 if (CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelInfo(GetDisplayId()))
3597 {
3598 SetBoundingRadius((IsPet() ? 1.0f : minfo->bounding_radius) * scale * GetDisplayScale());
3599 SetCombatReach((IsPet() ? DEFAULT_PLAYER_COMBAT_REACH : minfo->combat_reach) * scale * GetDisplayScale());
3600 }
3601}
3602
3603void Creature::SetDisplayId(uint32 displayId, bool setNative /*= false*/)
3604{
3605 Unit::SetDisplayId(displayId, setNative);
3606
3607 if (CreatureModelInfo const* modelInfo = sObjectMgr->GetCreatureModelInfo(displayId))
3608 {
3609 SetBoundingRadius((IsPet() ? 1.0f : modelInfo->bounding_radius) * GetObjectScale() * GetDisplayScale());
3610 SetCombatReach((IsPet() ? DEFAULT_PLAYER_COMBAT_REACH : modelInfo->combat_reach) * GetObjectScale() * GetDisplayScale());
3611 }
3612}
3613
3615{
3616 if (CreatureModel const* model = GetCreatureTemplate()->GetModelByIdx(modelIdx))
3617 SetDisplayId(model->CreatureDisplayID);
3618}
3619
3621{
3622 if (HasSpellFocus())
3623 _spellFocusInfo.Target = guid;
3624 else
3626}
3627
3628void Creature::SetSpellFocus(Spell const* focusSpell, WorldObject const* target)
3629{
3630 // Pointer validation and checking for a already existing focus
3631 if (_spellFocusInfo.Spell || !focusSpell)
3632 return;
3633
3634 // Prevent dead / feign death creatures from setting a focus target
3636 return;
3637
3638 // Don't allow stunned creatures to set a focus target
3640 return;
3641
3642 // some spells shouldn't track targets
3643 if (focusSpell->IsFocusDisabled())
3644 return;
3645
3646 SpellInfo const* spellInfo = focusSpell->GetSpellInfo();
3647
3648 // don't use spell focus for vehicle spells
3649 if (spellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE))
3650 return;
3651
3652 // instant non-channeled casts and non-target spells don't need facing updates
3653 if (!target && (!focusSpell->GetCastTime() && !spellInfo->IsChanneled()))
3654 return;
3655
3656 // store pre-cast values for target and orientation (used to later restore)
3657 if (!_spellFocusInfo.Delay)
3658 { // only overwrite these fields if we aren't transitioning from one spell focus to another
3659 _spellFocusInfo.Target = GetTarget();
3660 _spellFocusInfo.Orientation = GetOrientation();
3661 }
3662 else // don't automatically reacquire target for the previous spellcast
3663 _spellFocusInfo.Delay = 0;
3664
3665 _spellFocusInfo.Spell = focusSpell;
3666
3667 bool const noTurnDuringCast = spellInfo->HasAttribute(SPELL_ATTR5_AI_DOESNT_FACE_TARGET);
3668 bool const turnDisabled = CannotTurn();
3669 // set target, then force send update packet to players if it changed to provide appropriate facing
3670 ObjectGuid newTarget = (target && !noTurnDuringCast && !turnDisabled) ? target->GetGUID() : ObjectGuid::Empty;
3671 if (GetTarget() != newTarget)
3673
3674 // If we are not allowed to turn during cast but have a focus target, face the target
3675 if (!turnDisabled && noTurnDuringCast && target)
3676 SetFacingToObject(target, false);
3677
3678 if (noTurnDuringCast)
3680}
3681
3682bool Creature::HasSpellFocus(Spell const* focusSpell) const
3683{
3684 if (isDead()) // dead creatures cannot focus
3685 {
3686 if (_spellFocusInfo.Spell || _spellFocusInfo.Delay)
3687 {
3688 TC_LOG_WARN("entities.unit", "Creature '{}' (entry {}) has spell focus (spell id {}, delay {}ms) despite being dead.",
3689 GetName(), GetEntry(), _spellFocusInfo.Spell ? _spellFocusInfo.Spell->GetSpellInfo()->Id : 0, _spellFocusInfo.Delay);
3690 }
3691 return false;
3692 }
3693
3694 if (focusSpell)
3695 return (focusSpell == _spellFocusInfo.Spell);
3696 else
3697 return (_spellFocusInfo.Spell || _spellFocusInfo.Delay);
3698}
3699
3700void Creature::ReleaseSpellFocus(Spell const* focusSpell, bool withDelay)
3701{
3702 if (!_spellFocusInfo.Spell)
3703 return;
3704
3705 // focused to something else
3706 if (focusSpell && focusSpell != _spellFocusInfo.Spell)
3707 return;
3708
3709 if (_spellFocusInfo.Spell->GetSpellInfo()->HasAttribute(SPELL_ATTR5_AI_DOESNT_FACE_TARGET))
3711
3712 if (IsPet()) // player pets do not use delay system
3713 {
3714 if (!CannotTurn())
3716 }
3717 else // don't allow re-target right away to prevent visual bugs
3718 _spellFocusInfo.Delay = withDelay ? 1000 : 1;
3719
3720 _spellFocusInfo.Spell = nullptr;
3721}
3722
3724{
3725 if (!HasSpellFocus())
3726 {
3727 TC_LOG_ERROR("entities.unit", "Creature::ReacquireSpellFocusTarget() being called with HasSpellFocus() returning false. {}", GetDebugInfo());
3728 return;
3729 }
3730
3732
3733 if (!CannotTurn())
3734 {
3735 if (!_spellFocusInfo.Target.IsEmpty())
3736 {
3737 if (WorldObject const* objTarget = ObjectAccessor::GetWorldObject(*this, _spellFocusInfo.Target))
3738 SetFacingToObject(objTarget, false);
3739 }
3740 else
3741 SetFacingTo(_spellFocusInfo.Orientation, false);
3742 }
3743 _spellFocusInfo.Delay = 0;
3744}
3745
3747{
3748 _spellFocusInfo.Delay = 0;
3749 _spellFocusInfo.Spell = nullptr;
3750}
3751
3753{
3755 return false;
3756
3757 return true;
3758}
3759
3764
3769
3771{
3772 CreatureTextRepeatIds& repeats = m_textRepeat[textGroup];
3773 if (std::find(repeats.begin(), repeats.end(), id) == repeats.end())
3774 repeats.push_back(id);
3775 else
3776 TC_LOG_ERROR("sql.sql", "CreatureTextMgr: TextGroup {} for Creature({}) {}, id {} already added", uint32(textGroup), GetName(), GetGUID().ToString(), uint32(id));
3777}
3778
3780{
3782
3783 CreatureTextRepeatGroup::const_iterator groupItr = m_textRepeat.find(textGroup);
3784 if (groupItr != m_textRepeat.end())
3785 ids = groupItr->second;
3786
3787 return ids;
3788}
3789
3791{
3792 CreatureTextRepeatGroup::iterator groupItr = m_textRepeat.find(textGroup);
3793 if (groupItr != m_textRepeat.end())
3794 groupItr->second.clear();
3795}
3796
3801
3803{
3804 if (CreatureAI const* ai = AI())
3805 return ai->IsEngaged();
3806 return false;
3807}
3808
3810{
3811 Unit::AtEngage(target);
3812
3814
3816
3818 Dismount();
3819
3820 if (IsPet() || IsGuardian()) // update pets' speed for catchup OOC speed
3821 {
3825 }
3826
3828 if (movetype == WAYPOINT_MOTION_TYPE || movetype == POINT_MOTION_TYPE || (IsAIEnabled() && AI()->IsEscorted()))
3829 {
3831
3832 // if its a vehicle, set the home positon of every creature passenger at engage
3833 // so that they are in combat range if hostile
3834 if (Vehicle* vehicle = GetVehicleKit())
3835 {
3836 for (auto seat = vehicle->Seats.begin(); seat != vehicle->Seats.end(); ++seat)
3837 if (Unit* passenger = ObjectAccessor::GetUnit(*this, seat->second.Passenger.Guid))
3838 if (Creature* creature = passenger->ToCreature())
3839 creature->SetHomePosition(GetPosition());
3840 }
3841 }
3842
3843 if (CreatureAI* ai = AI())
3844 ai->JustEngagedWith(target);
3845 if (CreatureGroup* formation = GetFormation())
3846 formation->MemberEngagingTarget(this, target);
3847
3848 // Creatures with CREATURE_STATIC_FLAG_2_FORCE_PARTY_MEMBERS_INTO_COMBAT periodically force party members into combat
3850}
3851
3853{
3855
3859
3860 if (IsPet() || IsGuardian()) // update pets' speed for catchup OOC speed
3861 {
3865 }
3866}
3867
3869{
3871 return;
3872
3873 Trinity::Containers::FlatSet<Group const*> partiesToForceIntoCombat;
3874 for (auto const& [_, combatReference] : GetCombatManager().GetPvECombatRefs())
3875 {
3876 if (combatReference->IsSuppressedFor(this))
3877 continue;
3878
3879 Player* player = Object::ToPlayer(combatReference->GetOther(this));
3880 if (!player || player->IsGameMaster())
3881 continue;
3882
3883 if (Group const* group = player->GetGroup())
3884 partiesToForceIntoCombat.insert(group);
3885 }
3886
3887 for (Group const* partyToForceIntoCombat : partiesToForceIntoCombat)
3888 {
3889 for (GroupReference const& ref : partyToForceIntoCombat->GetMembers())
3890 {
3891 Player* player = ref.GetSource();
3892 if (!player->IsInMap(this) || player->IsGameMaster())
3893 continue;
3894
3895 EngageWithTarget(player);
3896 }
3897 }
3898}
3899
3901{
3902 if (CreatureAI const* ai = AI())
3903 return ai->IsEscorted();
3904 return false;
3905}
3906
3907std::string Creature::GetDebugInfo() const
3908{
3909 std::stringstream sstr;
3910 sstr << Unit::GetDebugInfo() << "\n"
3911 << "AIName: " << GetAIName() << " ScriptName: " << GetScriptName()
3912 << " WaypointPath: " << GetWaypointPathId() << " SpawnId: " << GetSpawnId();
3913 return sstr.str();
3914}
3915
3916void Creature::ExitVehicle(Position const* /*exitPosition*/)
3917{
3918 bool const isInVehicle = GetVehicle();
3920
3921 // if alive creature exits a vehicle, set it's home position to the
3922 // exited position so it won't run away (home) and evade if it's hostile
3923 if (isInVehicle && IsAlive())
3925}
3926
3928{
3929 return _gossipMenuId;
3930}
3931
3933{
3934 _gossipMenuId = gossipMenuId;
3935}
3936
3938{
3939 if (_trainerId)
3940 return *_trainerId;
3941
3942 return sObjectMgr->GetCreatureDefaultTrainer(GetEntry());
3943}
3944
3946{
3947 _trainerId = trainerId;
3948}
3949
3955
3957{
3958 if (!IsAreaSpiritHealer())
3959 return;
3960
3962
3963 // maybe NPC is summoned with these spells:
3964 // ID - 24237 Summon Alliance Graveyard Teleporter (SERVERSIDE)
3965 // ID - 46894 Summon Horde Graveyard Teleporter (SERVERSIDE)
3966 SummonCreature(npcEntry, GetPosition(), TEMPSUMMON_TIMED_DESPAWN, 1s, 0, 0);
3967}
3968
3970{
3971 auto clickBounds = sObjectMgr->GetSpellClickInfoMapBounds(GetEntry());
3972 auto itr = clickBounds.begin();
3973 // Set InteractSpellID if there is only one row in npc_spellclick_spells in db for this creature
3974 if (itr != clickBounds.end() && ++itr == clickBounds.end())
3975 SetInteractSpellId(clickBounds.begin()->second.spellId);
3976 else
3978}
3979
3981{
3982 m_objectData->WriteCreate(flags, data, target, this);
3983 m_unitData->WriteCreate(flags, data, target, this);
3984}
3985
3987{
3989
3991 m_objectData->WriteUpdate(flags, data, target, this);
3992
3994 m_unitData->WriteUpdate(flags, data, target, this);
3995}
3996
3998{
4000 valuesMask.Set(TYPEID_UNIT);
4001
4002 data << uint32(valuesMask.GetBlock(0));
4003
4004 UF::UnitData::Mask mask;
4006 m_unitData->WriteUpdate(mask, data, target, this, true);
4007}
4008
4010 UF::UnitData::Mask const& requestedUnitMask, Player const* target, bool ignoreNestedChangesMask) const
4011{
4014 if (requestedObjectMask.IsAnySet())
4015 valuesMask.Set(TYPEID_OBJECT);
4016
4017 UF::UnitData::Mask unitMask = requestedUnitMask;
4019 if (unitMask.IsAnySet())
4020 valuesMask.Set(TYPEID_UNIT);
4021
4022 ByteBuffer& buffer = PrepareValuesUpdateBuffer(data);
4023 std::size_t sizePos = buffer.wpos();
4024 buffer << uint32(0);
4026 buffer << uint32(valuesMask.GetBlock(0));
4027
4028 if (valuesMask[TYPEID_OBJECT])
4029 m_objectData->WriteUpdate(requestedObjectMask, buffer, target, this, ignoreNestedChangesMask);
4030
4031 if (valuesMask[TYPEID_UNIT])
4032 m_unitData->WriteUpdate(unitMask, buffer, target, this, ignoreNestedChangesMask);
4033
4034 buffer.put<uint32>(sizePos, buffer.wpos() - sizePos - 4);
4035
4036 data->AddUpdateBlock();
4037}
4038
4040{
4041 UpdateData udata(Owner->GetMapId());
4042 WorldPacket packet;
4043
4045
4046 udata.BuildPacket(&packet);
4047 player->SendDirectMessage(&packet);
4048}
#define sBattlegroundMgr
@ SPELL_SPIRIT_HEAL_CHANNEL_AOE
constexpr uint8 MAX_SPELL_CHARM
Definition CharmInfo.h:27
LocaleConstant
Definition Common.h:51
@ TOTAL_LOCALES
Definition Common.h:65
@ LOCALE_enUS
Definition Common.h:52
#define DEFAULT_LOCALE
Definition Common.h:69
@ IN_MILLISECONDS
Definition Common.h:38
@ MINUTE
Definition Common.h:32
@ WEEK
Definition Common.h:35
const uint32 CREATURE_REGEN_INTERVAL
@ CREATURE_FLAG_EXTRA_DUNGEON_BOSS
@ CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING
@ CREATURE_FLAG_EXTRA_CANNOT_ENTER_COMBAT
@ CREATURE_FLAG_EXTRA_NO_XP
@ CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK
@ CREATURE_FLAG_EXTRA_IGNORE_FEIGN_DEATH
@ CREATURE_FLAG_EXTRA_NO_TAUNT
@ CREATURE_FLAG_EXTRA_GHOST_VISIBILITY
@ CREATURE_FLAG_EXTRA_USE_OFFHAND_ATTACK
@ CREATURE_FLAG_EXTRA_WORLDEVENT
CreatureChaseMovementType
const uint8 MAX_KILL_CREDIT
@ CREATURE_STATIC_FLAG_5_INTERACT_WHILE_HOSTILE
@ CREATURE_STATIC_FLAG_IGNORE_COMBAT
@ CREATURE_STATIC_FLAG_NO_XP
@ CREATURE_STATIC_FLAG_NO_MELEE_FLEE
@ CREATURE_STATIC_FLAG_SESSILE
@ CREATURE_STATIC_FLAG_FLOATING
@ CREATURE_STATIC_FLAG_3_ALLOW_INTERACTION_WHILE_IN_COMBAT
@ CREATURE_STATIC_FLAG_4_NO_BIRTH_ANIM
@ CREATURE_STATIC_FLAG_4_NO_MELEE_APPROACH
@ CREATURE_STATIC_FLAG_2_ALLOW_MOUNTED_COMBAT
@ CREATURE_STATIC_FLAG_2_FORCE_RAID_COMBAT
CreatureRandomMovementType
const uint32 CREATURE_NOPATH_EVADE_TIME
const uint32 MAX_CREATURE_SPELLS
const uint32 PET_FOCUS_REGEN_INTERVAL
#define sFormationMgr
AreaSpiritHealerData
@ NPC_ALLIANCE_GRAVEYARD_TELEPORT
@ NPC_HORDE_GRAVEYARD_TELEPORT
VendorDataTypeFlags
Definition Creature.h:63
std::vector< uint8 > CreatureTextRepeatIds
Definition Creature.h:78
#define CREATURE_Z_ATTACK_RANGE
Definition Creature.h:52
static constexpr uint8 WILD_BATTLE_PET_DEFAULT_LEVEL
Definition Creature.h:74
static constexpr size_t CREATURE_TAPPERS_SOFT_CAP
Definition Creature.h:75
DB2Storage< DifficultyEntry > sDifficultyStore("Difficulty.db2", &DifficultyLoadInfo::Instance)
DB2Storage< ChrRacesEntry > sChrRacesStore("ChrRaces.db2", &ChrRacesLoadInfo::Instance)
DB2Storage< CreatureDisplayInfoEntry > sCreatureDisplayInfoStore("CreatureDisplayInfo.db2", &CreatureDisplayInfoLoadInfo::Instance)
DB2Storage< FactionTemplateEntry > sFactionTemplateStore("FactionTemplate.db2", &FactionTemplateLoadInfo::Instance)
DB2Storage< AreaTableEntry > sAreaTableStore("AreaTable.db2", &AreaTableLoadInfo::Instance)
#define sDB2Manager
Definition DB2Stores.h:579
@ MAX_LEVEL
Definition DBCEnums.h:45
@ STRONG_MAX_LEVEL
Definition DBCEnums.h:49
@ FACTION_MASK_ALLIANCE
Definition DBCEnums.h:1012
Difficulty
Definition DBCEnums.h:935
@ DIFFICULTY_NONE
Definition DBCEnums.h:936
@ FACTION_TEMPLATE_FLAG_PVP
Definition DBCEnums.h:1004
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:156
int8_t int8
Definition Define.h:152
int32_t int32
Definition Define.h:150
uint64_t uint64
Definition Define.h:153
#define UI64LIT(N)
Definition Define.h:139
uint16_t uint16
Definition Define.h:155
uint32_t uint32
Definition Define.h:154
uint16 flags
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition Duration.h:24
std::chrono::seconds Seconds
Seconds shorthand typedef.
Definition Duration.h:28
#define ASSERT_NOTNULL(pointer)
Definition Errors.h:74
#define ASSERT
Definition Errors.h:72
#define sGameEventMgr
#define MAX_FALL_DISTANCE
Definition GridDefines.h:62
#define SIZE_OF_GRID_CELL
Definition GridDefines.h:48
#define TC_LOG_DEBUG(filterType__, message__,...)
Definition Log.h:173
#define TC_LOG_ERROR(filterType__, message__,...)
Definition Log.h:182
#define TC_LOG_WARN(filterType__, message__,...)
Definition Log.h:179
@ LOOT_SKINNING
Definition Loot.h:107
#define sMapMgr
Definition MapManager.h:186
MovementGeneratorType
@ IDLE_MOTION_TYPE
@ CHASE_MOTION_TYPE
@ WAYPOINT_MOTION_TYPE
@ FLEEING_MOTION_TYPE
@ HOME_MOTION_TYPE
@ POINT_MOTION_TYPE
@ RANDOM_MOTION_TYPE
@ MOVEMENTFLAG_FALLING
#define ATTACK_DISTANCE
#define MAX_VISIBILITY_DISTANCE
#define DEFAULT_PLAYER_COMBAT_REACH
@ TEMPSUMMON_TIMED_DESPAWN
#define DEFAULT_PLAYER_DISPLAY_SCALE
@ TYPEID_OBJECT
Definition ObjectGuid.h:38
@ TYPEID_UNIT
Definition ObjectGuid.h:43
@ TYPEID_PLAYER
Definition ObjectGuid.h:44
#define sObjectMgr
Definition ObjectMgr.h:1873
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition Optional.h:25
#define sPoolMgr
Definition PoolMgr.h:179
@ RACE_NONE
Definition RaceMask.h:29
int32 irand(int32 min, int32 max)
Definition Random.cpp:36
uint32 urand(uint32 min, uint32 max)
Definition Random.cpp:43
void SendGossipMenuFor(Player *player, uint32 npcTextID, ObjectGuid const &guid)
void ClearGossipMenuFor(Player *player)
@ SERVERSIDE_VISIBILITY_GHOST
SpellEffects
@ SPELL_EFFECT_HEAL
@ SPELL_EFFECT_ATTACK_ME
@ SPELL_EFFECT_KNOCK_BACK_DEST
@ SPELL_EFFECT_KNOCK_BACK
Classes
constexpr uint32 GetMaxLevelForExpansion(uint32 expansion)
@ SPELL_ATTR5_AI_DOESNT_FACE_TARGET
@ XP_GRAY
@ SPELL_SCHOOL_MASK_NORMAL
@ CREATURE_TYPE_CRITTER
@ CREATURE_TYPE_NON_COMBAT_PET
@ CREATURE_TYPE_MECHANICAL
@ UNIT_DYNFLAG_TAPPED
@ UNIT_DYNFLAG_LOOTABLE
@ UNIT_DYNFLAG_NONE
AiReaction
@ OFF_ATTACK
@ BASE_ATTACK
@ RANGED_ATTACK
float const GROUND_HEIGHT_TOLERANCE
@ IMMUNITY_STATE
@ IMMUNITY_EFFECT
@ IMMUNITY_MECHANIC
@ IMMUNITY_SCHOOL
@ IMMUNITY_OTHER
@ IMMUNITY_DISPEL
@ ALLIANCE
@ HORDE
Powers
@ POWER_ENERGY
@ POWER_MANA
@ POWER_FOCUS
BattlegroundTypeId
@ BATTLEGROUND_AA
@ BATTLEGROUND_WS
@ BATTLEGROUND_EY
@ BATTLEGROUND_AV
@ BATTLEGROUND_BE
@ BATTLEGROUND_RV
@ BATTLEGROUND_NA
@ BATTLEGROUND_DS
@ BATTLEGROUND_SA
@ BATTLEGROUND_AB
@ BATTLEGROUND_RL
@ GHOST_VISIBILITY_ALIVE
@ GHOST_VISIBILITY_GHOST
CreatureClassifications
@ FACTION_ALLIANCE_GENERIC
SpellSchools
@ SPELL_SCHOOL_SHADOW
@ SPELL_SCHOOL_NATURE
@ SPELL_SCHOOL_FROST
@ SPELL_SCHOOL_ARCANE
@ SPELL_SCHOOL_FIRE
@ SPELL_SCHOOL_HOLY
@ CREATURE_TYPE_FLAG_VISIBLE_TO_GHOSTS
@ CREATURE_TYPE_FLAG_BOSS_MOB
@ CREATURE_TYPE_FLAG_TREAT_AS_RAID_UNIT
Creature can be targeted by spells that require target to be in caster's party/raid.
@ CREATURE_TYPE_FLAG_ALLOW_MOUNTED_COMBAT
@ SPAWNGROUP_FLAG_COMPATIBILITY_MODE
Definition SpawnData.h:57
@ LINKED_RESPAWN_CREATURE_TO_GO
Definition SpawnData.h:154
@ LINKED_RESPAWN_CREATURE_TO_CREATURE
Definition SpawnData.h:153
@ LINKED_RESPAWN_GO_TO_CREATURE
Definition SpawnData.h:156
@ SPAWN_TYPE_CREATURE
Definition SpawnData.h:36
SpawnTrackingState
Definition SpawnData.h:94
@ SPELL_AURA_MOD_POWER_REGEN
@ SPELL_AURA_PREVENTS_FLEEING
@ SPELL_AURA_CONTROL_VEHICLE
@ SPELL_AURA_MOD_INVISIBILITY
@ SPELL_AURA_MOD_HEALTH_REGEN_PERCENT
@ SPELL_AURA_DISABLE_GRAVITY
@ SPELL_AURA_MOD_STUN_DISABLE_GRAVITY
@ SPELL_AURA_MOD_DETECTED_RANGE
@ SPELL_AURA_MOD_ROOT
@ SPELL_AURA_MOD_TAUNT
@ SPELL_AURA_FEIGN_DEATH
@ SPELL_AURA_MOD_ROOT_DISABLE_GRAVITY
@ SPELL_AURA_MOD_POWER_REGEN_PERCENT
@ SPELL_AURA_MOD_DETECT_RANGE
@ SPELL_AURA_MOD_REGEN
@ FORM_NONE
#define sSpellMgr
Definition SpellMgr.h:812
@ MOVE_FLIGHT
@ MOVE_SWIM
@ MOVE_RUN
@ MOVE_WALK
UnitFlags2
@ UNIT_FLAG2_AI_WILL_ONLY_SWIM_IF_TARGET_SWIMS
@ UNIT_FLAG2_FEIGN_DEATH
@ UNIT_FLAG2_REGENERATE_POWER
@ UNIT_PET_FLAG_NONE
@ REACT_PASSIVE
@ REACT_AGGRESSIVE
UnitStandStateType
Definition UnitDefines.h:41
constexpr NPCFlags UNIT_NPC_FLAG_VENDOR_MASK
@ ACT_ENABLED
NPCFlags
Non Player Character flags.
@ UNIT_NPC_FLAG_NONE
@ UNIT_NPC_FLAG_SPELLCLICK
@ UNIT_NPC_FLAG_PETITIONER
UnitFlags3
SheathState
Definition UnitDefines.h:81
@ SHEATH_STATE_MELEE
Definition UnitDefines.h:83
#define MAX_EQUIPMENT_ITEMS
Definition UnitDefines.h:37
NPCFlags2
@ UNIT_NPC_FLAG_2_NONE
UnitPVPStateFlags
Definition UnitDefines.h:91
AnimTier
Definition UnitDefines.h:69
UnitVisFlags
Definition UnitDefines.h:58
UnitFlags
@ UNIT_FLAG_STUNNED
@ UNIT_FLAG_NON_ATTACKABLE
@ UNIT_FLAG_IN_COMBAT
@ UNIT_FLAG_FLEEING
@ UNIT_FLAG_PLAYER_CONTROLLED
@ BASE_VALUE
Definition Unit.h:158
@ MINDAMAGE
Definition Unit.h:172
@ MAXDAMAGE
Definition Unit.h:173
UnitMods
Definition Unit.h:177
@ UNIT_MOD_ARMOR
Definition Unit.h:210
@ UNIT_MOD_RESISTANCE_SHADOW
Definition Unit.h:215
@ UNIT_MOD_RESISTANCE_FROST
Definition Unit.h:214
@ UNIT_MOD_RESISTANCE_HOLY
Definition Unit.h:211
@ UNIT_MOD_RESISTANCE_ARCANE
Definition Unit.h:216
@ UNIT_MOD_HEALTH
Definition Unit.h:183
@ UNIT_MOD_POWER_START
Definition Unit.h:226
@ UNIT_MOD_RESISTANCE_FIRE
Definition Unit.h:212
@ UNIT_MOD_RESISTANCE_NATURE
Definition Unit.h:213
#define MAX_AGGRO_RADIUS
Definition Unit.h:45
DeathState
Definition Unit.h:265
@ CORPSE
Definition Unit.h:268
@ DEAD
Definition Unit.h:269
@ ALIVE
Definition Unit.h:266
@ JUST_RESPAWNED
Definition Unit.h:270
@ JUST_DIED
Definition Unit.h:267
@ UNIT_STATE_DIED
Definition Unit.h:275
@ UNIT_STATE_ATTACK_PLAYER
Definition Unit.h:289
@ UNIT_STATE_ROOT
Definition Unit.h:285
@ UNIT_STATE_IGNORE_PATHFINDING
Definition Unit.h:303
@ UNIT_STATE_FLEEING
Definition Unit.h:282
@ UNIT_STATE_FOCUSING
Definition Unit.h:281
@ UNIT_STATE_ALL_ERASABLE
Definition Unit.h:322
@ BASE_PCT
Definition Unit.h:165
T RoundToInterval(T &num, T floor, T ceil)
Definition Util.h:97
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
Definition Util.h:565
@ WORLD_DEL_SPAWNGROUP_MEMBER
@ WORLD_DEL_GAME_EVENT_MODEL_EQUIP
@ WORLD_DEL_CREATURE_ADDON
@ WORLD_DEL_LINKED_RESPAWN
@ WORLD_DEL_GAME_EVENT_CREATURE
@ WORLD_DEL_CREATURE
@ WORLD_DEL_LINKED_RESPAWN_MASTER
@ WORLD_INS_CREATURE
ObjectGuid m_victim
Definition Creature.h:634
bool Execute(uint64 e_time, uint32 p_time) override
Definition Creature.cpp:288
void AddAssistant(ObjectGuid guid)
Definition Creature.h:630
GuidList m_assistants
Definition Creature.h:635
ObjectGuid const & GetGUID() const
Definition BaseEntity.h:163
void SetUpdateFieldValue(UF::UpdateFieldPrivateSetter< T > setter, typename UF::UpdateFieldPrivateSetter< T >::value_type value)
Definition BaseEntity.h:221
WowCS::EntityFragmentsHolder m_entityFragments
Definition BaseEntity.h:353
void RemoveOptionalUpdateFieldValue(UF::OptionalUpdateFieldSetter< T > setter)
Definition BaseEntity.h:291
UF::UpdateFieldHolder m_values
Definition BaseEntity.h:205
bool IsInWorld() const
Definition BaseEntity.h:158
void _Create(ObjectGuid const &guid)
Definition BaseEntity.h:218
CreateObjectBits m_updateFlag
Definition BaseEntity.h:352
void SetUpdateFieldFlagValue(UF::UpdateFieldPrivateSetter< T > setter, typename UF::UpdateFieldPrivateSetter< T >::value_type flag)
Definition BaseEntity.h:228
void RemoveUpdateFieldFlagValue(UF::UpdateFieldPrivateSetter< T > setter, typename UF::UpdateFieldPrivateSetter< T >::value_type flag)
Definition BaseEntity.h:235
bool IsCreature() const
Definition BaseEntity.h:172
bool IsPlayer() const
Definition BaseEntity.h:173
ByteBuffer & PrepareValuesUpdateBuffer(UpdateData *data) const
TypeID GetTypeId() const
Definition BaseEntity.h:166
size_t wpos() const
Definition ByteBuffer.h:462
void put(std::size_t pos, T value)
Definition ByteBuffer.h:261
Unit * GetAnyTarget() const
std::unordered_map< ObjectGuid, CombatReference * > const & GetPvECombatRefs() const
virtual void EnterEvadeMode(EvadeReason why=EvadeReason::Other)
virtual void JustAppeared()
virtual bool CheckInRoom()
Creature * GetLeader() const
void FormationReset(bool dismiss)
bool HasAliveMembers() const
bool IsFormed() const
bool IsLeader(Creature const *creature) const
bool CanLeaderStartMoving() const
bool HasFlag(CreatureStaticFlags flag) const
EnumFlag< CreatureStaticFlags8 > GetFlags8() const
void ApplyFlag(CreatureStaticFlags flag, bool apply)
EnumFlag< CreatureStaticFlags2 > GetFlags2() const
EnumFlag< CreatureStaticFlags > GetFlags() const
EnumFlag< CreatureStaticFlags7 > GetFlags7() const
EnumFlag< CreatureStaticFlags5 > GetFlags5() const
EnumFlag< CreatureStaticFlags6 > GetFlags6() const
EnumFlag< CreatureStaticFlags4 > GetFlags4() const
EnumFlag< CreatureStaticFlags3 > GetFlags3() const
bool HasClassification(CreatureClassifications classification) const
Definition Creature.h:173
bool LoadCreaturesAddon()
time_t _pickpocketLootRestore
Timers.
Definition Creature.h:536
bool HasSpell(uint32 spellID) const override
uint32 CalculateDamageForSparring(Unit *attacker, uint32 damage)
bool AIM_Destroy()
VendorItemCounts m_vendorItemCounts
Definition Creature.h:528
void SetHomePosition(float x, float y, float z, float o)
Definition Creature.h:394
float m_wanderDistance
Definition Creature.h:542
void SetNoSearchAssistance(bool val)
Definition Creature.h:348
void ReleaseSpellFocus(Spell const *focusSpell=nullptr, bool withDelay=true)
CreatureDifficulty const * m_creatureDifficulty
Definition Creature.h:570
void SetCanMelee(bool canMelee, bool fleeFromMelee=false)
bool IsTrigger() const
Definition Creature.h:127
void Respawn(bool force=false)
std::array< std::string const *, 3 > m_stringIds
Definition Creature.h:571
void SetInteractionAllowedInCombat(bool interactionAllowed) override
void ResetLootMode()
Definition Creature.h:330
bool CanSwim() const override
void RegenerateHealth()
CreatureTextRepeatGroup m_textRepeat
Definition Creature.h:608
VendorItemData const * GetVendorItems() const
void StartDefaultCombatMovement(Unit *victim, Optional< float > range={}, Optional< float > angle={})
float _sparringHealthPct
Definition Creature.h:621
bool CreateFromProto(ObjectGuid::LowType guidlow, uint32 entry, CreatureData const *data=nullptr, uint32 vehId=0)
bool _regenerateHealth
Definition Creature.h:615
CreatureStaticFlagsHolder _staticFlags
Definition Creature.h:577
bool IsDungeonBoss() const
Definition Creature.h:175
bool LoadFromDB(ObjectGuid::LowType spawnId, Map *map, bool addToMap, bool allowDuplicate)
float GetHealthMultiplierForTarget(WorldObject const *target) const override
bool isWorldBoss() const
bool IsReturningHome() const
Definition Creature.cpp:382
Optional< uint32 > m_lootId
Definition Creature.h:574
void UpdateLevelDependantStats()
int8 m_originalEquipmentId
Definition Creature.h:551
void setDeathState(DeathState s) override
static Creature * CreateCreatureFromDB(ObjectGuid::LowType spawnId, Map *map, bool addToMap=true, bool allowDuplicate=false)
bool UpdateAllStats() override
void CallForHelp(float fRadius)
float GetAttackDistance(Unit const *player) const
ObjectGuid::LowType m_spawnId
For new or temporary creatures is 0 for saved it is lowguid.
Definition Creature.h:549
std::unique_ptr< Loot > m_loot
Definition Creature.h:307
void Update(uint32 time) override
Definition Creature.cpp:750
CreatureDifficulty const * GetCreatureDifficulty() const
Definition Creature.h:276
bool _IsTargetAcceptable(Unit const *target) const
CreatureClassifications GetCreatureClassification() const
Definition Creature.h:172
Optional< uint32 > _defaultMountDisplayIdOverride
Definition Creature.h:617
bool IsSessile() const
Definition Creature.h:149
bool IsIgnoringFeignDeath() const
Definition Creature.h:352
bool IsCivilian() const
Definition Creature.h:126
float GetSparringHealthPct() const
Definition Creature.h:472
void SetRespawnTime(uint32 respawn)
std::span< int32 const > GetLabels() const
bool HasLabel(int32 cretureLabel) const
void SetObjectScale(float scale) override
Optional< std::string > m_scriptStringId
Definition Creature.h:572
uint32 m_spells[MAX_CREATURE_SPELLS]
Definition Creature.h:332
void ApplyAllStaticFlags(CreatureStaticFlagsHolder const &flags)
Definition Creature.cpp:742
static float GetDamageMod(CreatureClassifications classification)
bool m_cannotReachTarget
Definition Creature.h:555
bool m_respawnCompatibilityMode
Definition Creature.h:593
void SelectWildBattlePetLevel()
std::string GetNameForLocaleIdx(LocaleConstant locale) const override
bool IsFloating() const
Definition Creature.h:142
std::unordered_map< ObjectGuid, std::unique_ptr< Loot > > m_personalLoot
Definition Creature.h:308
CreatureTemplate const * m_creatureInfo
Definition Creature.h:568
void BuildValuesUpdate(UF::UpdateFieldFlag flags, ByteBuffer &data, Player const *target) const override
bool IsSpawnedOnTransport() const
Definition Creature.h:116
void UpdateNearbyPlayersInteractions() override
bool CanFly() const override
Definition Creature.h:167
Position const & GetHomePosition() const
Definition Creature.h:397
bool CanGiveExperience() const
CreatureTextRepeatIds GetTextRepeatGroup(uint8 textGroup)
void LoadEquipment(int8 id=1, bool force=false)
uint8 GetLevelForTarget(WorldObject const *target) const override
void SetTrainerId(Optional< uint32 > trainerId)
bool HasReactState(ReactStates state) const
Definition Creature.h:182
bool AIM_Initialize(CreatureAI *ai=nullptr)
void DoNotReacquireSpellFocusTarget()
void RemoveCorpse(bool setSpawnTime=true, bool destroyForNearbyPlayers=true)
Definition Creature.cpp:430
void SendZoneUnderAttackMessage(Player *attacker)
Send a message to LocalDefense channel for players opposition team in the zone.
bool m_triggerJustAppeared
Definition Creature.h:592
bool _aggroGracePeriodExpired
Definition Creature.h:595
void StartPickPocketRefillTimer()
void AllLootRemovedFromCorpse()
static Creature * CreateCreature(uint32 entry, Map *map, Position const &pos, uint32 vehId=0)
float GetAggroRange(Unit const *target) const
void LoadTemplateImmunities(int32 creatureImmunitiesId)
void SetVendor(NPCFlags flags, bool apply)
void BuildValuesCreate(UF::UpdateFieldFlag flags, ByteBuffer &data, Player const *target) const override
uint32 m_baseAttackPower
Definition Creature.h:559
void SignalFormationMovement()
Definition Creature.cpp:411
void SetDisplayFromModel(uint32 modelIdx)
bool IsEngaged() const override
void Heartbeat() override
Definition Creature.cpp:932
MovementGeneratorType m_defaultMovementType
Definition Creature.h:548
void BuildValuesUpdateForPlayerWithMask(UpdateData *data, UF::ObjectData::Mask const &requestedObjectMask, UF::UnitData::Mask const &requestedUnitMask, Player const *target, bool ignoreNestedChangesMask) const
Unit * SelectNearestHostileUnitInAggroRange(bool useLOS=false, bool ignoreCivilians=false) const
bool Create(ObjectGuid::LowType guidlow, Map *map, uint32 entry, Position const &pos, CreatureData const *data, uint32 vehId, bool dynamic=false)
void SetReactState(ReactStates st)
Definition Creature.h:180
uint32 GetTrainerId() const
UF::OptionalUpdateField< UF::VendorData, int32(WowCS::EntityFragment::FVendor_C), 0 > m_vendorData
Definition Creature.h:500
void RemoveFromWorld() override
Definition Creature.cpp:364
void SetTextRepeatId(uint8 textGroup, uint8 id)
uint32 _waypointPathId
Definition Creature.h:587
void ResetPlayerDamageReq()
Definition Creature.h:423
float m_SightDistance
Definition Creature.h:435
int32 _creatureImmunitiesId
Definition Creature.h:618
void SetRespawnCompatibilityMode(bool mode=true)
Definition Creature.h:430
void SetCannotReachTarget(bool cannotReach)
bool ShouldFakeDamageFrom(Unit *attacker)
void ApplyLevelScaling()
void ClearTextRepeatGroup(uint8 textGroup)
void SetRespawnDelay(uint32 delay)
Definition Creature.h:368
void AddToWorld() override
Definition Creature.cpp:344
uint32 m_cannotReachTimer
Definition Creature.h:556
uint32 m_respawnDelay
Definition Creature.h:539
void SetScriptStringId(std::string id)
void SetTappedBy(Unit const *unit, bool withGroup=true)
void InitializeMovementCapabilities()
void InitializeInteractSpellId()
bool IsSkinnedBy(Player const *player) const
time_t m_corpseRemoveTime
Definition Creature.h:537
void ForcedDespawn(uint32 timeMSToDespawn=0, Seconds forceRespawnTimer=0s)
float GetPetChaseDistance() const
bool IsFormationLeaderMoveAllowed() const
Definition Creature.cpp:422
void SummonGraveyardTeleporter()
bool IsImmuneToNPC() const
Definition Unit.h:1063
void DespawnOrUnsummon(Milliseconds timeToDespawn=0s, Seconds forceRespawnTime=0s)
bool UpdateEntry(uint32 entry, CreatureData const *data=nullptr, bool updateLevel=true)
Definition Creature.cpp:591
float GetArmorMultiplierForTarget(WorldObject const *target) const override
bool HasStringId(std::string_view id) const
CreatureStaticFlagsHolder GenerateStaticFlags(CreatureDifficulty const *creatureDifficulty, ObjectGuid::LowType spawnId, Difficulty difficultyId) const
Definition Creature.cpp:725
float GetSpellDamageMod(CreatureClassifications classification) const
time_t m_respawnTime
Definition Creature.h:538
void UpdateFloatingMovementFlags()
void DoFleeToGetAssistance()
float GetDamageMultiplierForTarget(WorldObject const *target) const override
uint32 _gossipMenuId
Definition Creature.h:619
bool CanResetTalents(Player *player) const
bool IsEscorted() const
void AtEngage(Unit *target) override
uint32 GetScriptId() const
CreatureData const * m_creatureData
Definition Creature.h:569
float m_CombatDistance
Definition Creature.h:435
void AtDisengage() override
bool hasInvolvedQuest(uint32 quest_id) const override
uint32 m_boundaryCheckTime
Definition Creature.h:543
bool isCanInteractWithBattleMaster(Player *player, bool msg) const
Position m_homePosition
Definition Creature.h:563
uint32 GetWaypointPathId() const
Definition Creature.h:404
Loot * GetLootForPlayer(Player const *player) const override
CreatureData const * GetCreatureData() const
Definition Creature.h:275
bool CanGeneratePickPocketLoot() const
void UpdateSessileMovementFlags()
struct Creature::@193 _spellFocusInfo
void SetFloating(bool floating)
ObjectGuid::LowType GetSpawnId() const
Definition Creature.h:110
Position GetRespawnPosition(float *dist=nullptr) const
void SetInteractionAllowedWhileHostile(bool interactionAllowed) override
bool CanNotReachTarget() const
Definition Creature.h:390
bool m_AlreadyCallAssistance
Definition Creature.h:553
CreatureTemplate const * GetCreatureTemplate() const
Definition Creature.h:274
uint32 GetRespawnDelay() const
Definition Creature.h:367
void SetDontClearTapListOnEvade(bool dontClear)
bool IsFormationLeader() const
Definition Creature.cpp:403
bool CanCreatureAttack(Unit const *victim, bool force=true) const
void SetSessile(bool sessile)
bool CanRegenerateHealth() const
Definition Creature.h:380
bool DisableReputationGain
Definition Creature.h:566
void SetTarget(ObjectGuid const &guid) override
float GetBaseDamageForLevel(uint8 level) const
uint32 GetLootId() const
CreatureGroup * m_formation
Definition Creature.h:591
static bool DeleteFromDB(ObjectGuid::LowType spawnId)
void SetInteractSpellId(int32 interactSpellId)
Definition Creature.h:498
void InitializeReactState()
bool AIM_Create(CreatureAI *ai=nullptr)
uint32 m_corpseDelay
Definition Creature.h:540
void Motion_Initialize()
bool IsImmunedToSpellEffect(SpellInfo const *spellInfo, SpellEffectInfo const &spellEffectInfo, WorldObject const *caster, bool requireImmunityPurgesEffectAttribute=false) const override
void LoadCreaturesSparringHealth(bool force=false)
uint32 UpdateVendorItemCurrentCount(VendorItem const *vItem, uint32 used_count)
void SetSpawnHealth()
bool CheckNoGrayAggroConfig(uint32 playerLevel, uint32 creatureLevel) const
uint8 m_equipmentId
Definition Creature.h:550
bool IsElite() const
bool isTappedBy(Player const *player) const
Creature(bool isWorldObject=false)
Definition Creature.cpp:318
CreatureGroup * GetFormation()
Definition Creature.h:414
uint32 GetCorpseDelay() const
Definition Creature.h:124
GuidUnorderedSet m_tapList
Definition Creature.h:532
bool m_dontClearTapListOnEvade
Definition Creature.h:533
uint64 GetMaxHealthByLevel(uint8 level) const
SpawnTrackingStateData const * GetSpawnTrackingStateDataForPlayer(Player const *player) const override
void OverrideSparringHealthPct(float healthPct)
Definition Creature.h:470
bool CanAssistTo(Unit const *u, Unit const *enemy, bool checkfaction=true) const
std::string_view GetStringId(StringIdType type) const
Definition Creature.h:285
uint32 m_originalEntry
Definition Creature.h:561
float GetNativeObjectScale() const override
bool HasScalableLevels() const
void SetDefaultMount(Optional< uint32 > mountCreatureDisplayId)
void ExitVehicle(Position const *exitPosition=nullptr) override
Unit * SelectVictim()
void SearchFormation()
Definition Creature.cpp:390
uint32 GetVendorItemCurrentCount(VendorItem const *vItem)
float GetBaseArmorForLevel(uint8 level) const
bool m_isTempWorldObject
Definition Creature.h:437
void SetDisplayId(uint32 displayId, bool setNative=false) override
void SetPetitioner(bool apply)
std::string GetScriptName() const
void LowerPlayerDamageReq(uint64 unDamage)
time_t GetLastDamagedTime() const
Definition Creature.h:449
MovementGeneratorType GetDefaultMovementType() const override
void SetSpellFocus(Spell const *focusSpell, WorldObject const *target)
Optional< uint32 > _trainerId
Definition Creature.h:620
bool HasFlag(CreatureStaticFlags flag) const
Definition Creature.h:480
bool IsInvisibleDueToDespawn(WorldObject const *seer) const override
bool IsFullyLooted() const
void SaveRespawnTime(uint32 forceDelay=0)
uint8 GetCurrentEquipmentId() const
Definition Creature.h:263
bool InitEntry(uint32 entry, CreatureData const *data=nullptr)
Definition Creature.cpp:497
Unit * SelectNearestTarget(float dist=0, bool playerOnly=false) const
void SetCorpseDelay(uint32 delay, bool ignoreCorpseDecayRatio=false)
Definition Creature.h:118
void SetMeleeDamageSchool(SpellSchools school)
Definition Creature.h:238
void ForcePartyMembersIntoCombat()
static float GetHealthMod(CreatureClassifications classification)
void SaveToDB()
Unit * SelectNearestTargetInAttackDistance(float dist=0) const
void SelectLevel()
CreatureMovementData const & GetMovementTemplate() const
void SendAIReaction(AiReaction reactionType)
void SetGossipMenuId(uint32 gossipMenuId)
void ResetPickPocketRefillTimer()
Definition Creature.h:310
void SetNoCallAssistance(bool val)
Definition Creature.h:347
void SetTreatAsRaidUnit(bool treatAsRaidUnit)
Definition Creature.h:243
void UpdateMovementCapabilities()
bool m_ignoreCorpseDecayRatio
Definition Creature.h:541
bool CanOnlySwimIfTargetSwims() const
Definition Creature.h:163
bool CanAlwaysSee(WorldObject const *obj) const override
bool hasQuest(uint32 quest_id) const override
void Regenerate(Powers power)
Definition Creature.cpp:950
time_t GetRespawnTimeEx() const
CreatureAddon const * GetCreatureAddon() const
std::string const & GetAIName() const
void CallAssistance()
void InheritStringIds(Creature const *parent)
void SetLootId(Optional< uint32 > lootId)
bool IsImmuneToPC() const
Definition Unit.h:1060
void SetCanDualWield(bool value) override
bool IsInEvadeMode() const
Definition Creature.h:224
void ReacquireSpellFocusTarget()
CreatureAI * AI() const
Definition Creature.h:235
uint32 m_baseRangedAttackPower
Definition Creature.h:560
virtual uint32 GetPetAutoSpellOnPos(uint8 pos) const
void BuildValuesUpdateWithFlag(UF::UpdateFieldFlag flags, ByteBuffer &data, Player const *target) const override
std::string GetDebugInfo() const override
bool CanStartAttack(Unit const *u, bool force) const
bool IsMovementPreventedByCasting() const override
void SetOriginalEntry(uint32 entry)
Definition Creature.h:427
bool HasSpellFocus(Spell const *focusSpell=nullptr) const override
uint32 GetGossipMenuId() const
void SetIgnoreFeignDeath(bool ignoreFeignDeath)
Definition Creature.h:353
uint64 m_PlayerDamageReq
Definition Creature.h:424
virtual uint8 GetPetAutoSpellSize() const
constexpr std::underlying_type_t< T > AsUnderlyingType() const
Definition EnumFlag.h:122
void AddEvent(BasicEvent *event, Milliseconds e_time, bool set_addtime=true)
Milliseconds CalculateTime(Milliseconds t_offset) const
void SetValue(FLAG_TYPE flag, T_VALUES value)
Definition Object.h:213
Seconds const m_respawnTimer
Definition Creature.h:647
bool Execute(uint64 e_time, uint32 p_time) override
Definition Creature.cpp:312
static void RemoveCreatureFromGroup(CreatureGroup *group, Creature *member)
static void AddCreatureToGroup(ObjectGuid::LowType leaderSpawnId, Creature *creature)
Definition Group.h:209
Definition Map.h:227
bool IsDungeon() const
Definition Map.cpp:3303
void CreatureRelocation(Creature *creature, float x, float y, float z, float ang, bool respawnRelocationOnFail=true)
Definition Map.cpp:1058
MapStoredObjectTypesContainer & GetObjectsStore()
Definition Map.h:463
time_t GetLinkedRespawnTime(ObjectGuid guid) const
Definition Map.cpp:3741
bool IsRaid() const
Definition Map.cpp:3313
void GetFullTerrainStatusForPosition(PhaseShift const &phaseShift, float x, float y, float z, PositionFullTerrainStatus &data, Optional< map_liquidHeaderTypeFlags > reqLiquidType={}, float collisionHeight=2.03128f)
Definition Map.cpp:1698
void ApplyDynamicModeRespawnScaling(WorldObject const *obj, ObjectGuid::LowType spawnId, uint32 &respawnDelay, uint32 mode) const
Definition Map.cpp:2287
ObjectGuid::LowType GenerateLowGuid()
Definition Map.h:564
time_t GetCreatureRespawnTime(ObjectGuid::LowType spawnId) const
Definition Map.h:529
void SaveRespawnInfoDB(RespawnInfo const &info, CharacterDatabaseTransaction dbTrans=nullptr)
Definition Map.cpp:3683
bool IsSpawnGroupActive(uint32 groupId) const
Definition Map.cpp:2486
Difficulty GetDifficultyID() const
Definition Map.h:363
void SaveRespawnTime(SpawnObjectType type, ObjectGuid::LowType spawnId, uint32 entry, time_t respawnTime, uint32 gridId, CharacterDatabaseTransaction dbTrans=nullptr, bool startup=false)
Definition Map.cpp:3650
float GetHeight(PhaseShift const &phaseShift, float x, float y, float z, bool vmap=true, float maxSearchDist=DEFAULT_HEIGHT_SEARCH)
Definition Map.h:329
CreatureBySpawnIdContainer & GetCreatureBySpawnIdStore()
Definition Map.h:466
SpawnedPoolData & GetPoolData()
Definition Map.h:758
void Respawn(RespawnInfo *info, CharacterDatabaseTransaction dbTrans=nullptr)
Definition Map.cpp:2070
void MoveFall(uint32 id=0, Scripting::v2::ActionResultSetter< MovementStopReason > &&scriptResult={})
MovementGeneratorType GetCurrentMovementGeneratorType() const
void MoveChase(Unit *target, Optional< ChaseRange > dist={}, Optional< ChaseAngle > angle={})
void MoveSeekAssistance(float x, float y, float z)
void MoveFleeing(Unit *enemy, Milliseconds time=0ms, Scripting::v2::ActionResultSetter< MovementStopReason > &&scriptResult={})
MovementGenerator * GetCurrentMovementGenerator() const
void Remove(MovementGenerator *movement, MovementSlot slot=MOTION_SLOT_ACTIVE)
void InitializeDefault()
virtual MovementGeneratorType GetMovementGeneratorType() const =0
static ObjectGuid const Empty
Definition ObjectGuid.h:314
uint64 LowType
Definition ObjectGuid.h:321
static void ChooseCreatureFlags(CreatureTemplate const *cInfo, uint64 *npcFlags, uint32 *unitFlags, uint32 *unitFlags2, uint32 *unitFlags3, CreatureStaticFlagsHolder const &staticFlags, CreatureData const *data=nullptr)
static std::string_view GetLocaleString(std::vector< std::string > const &data, LocaleConstant locale)
Definition ObjectMgr.h:1608
static CreatureModel const * ChooseDisplayId(CreatureTemplate const *cinfo, CreatureData const *data=nullptr)
void SetDynamicFlag(uint32 flag)
Definition Object.h:97
float GetObjectScale() const
Definition Object.h:92
Player * ToPlayer()
Definition Object.h:126
bool HasDynamicFlag(uint32 flag) const
Definition Object.h:96
void ReplaceAllDynamicFlags(uint32 flag)
Definition Object.h:99
uint32 GetEntry() const
Definition Object.h:89
Creature * ToCreature()
Definition Object.h:121
void RemoveDynamicFlag(uint32 flag)
Definition Object.h:98
void BuildEntityFragmentsForValuesUpdateForPlayerWithMask(ByteBuffer &data, EnumFlag< UF::UpdateFieldFlag > flags) const
Definition Object.cpp:113
void SetEntry(uint32 entry)
Definition Object.h:90
virtual void SetObjectScale(float scale)
Definition Object.h:93
UF::UpdateField< UF::ObjectData, int32(WowCS::EntityFragment::CGObject), TYPEID_OBJECT > m_objectData
Definition Object.h:161
Unit * ToUnit()
Definition Object.h:116
static void InitDbVisibleMapId(PhaseShift &phaseShift, int32 visibleMapId)
static void InitDbPhaseShift(PhaseShift &phaseShift, uint8 phaseUseFlags, uint16 phaseId, uint32 phaseGroupId)
void SendDirectMessage(WorldPacket const *data) const
Definition Player.cpp:6193
bool IsGameMaster() const
Definition Player.h:1293
Group * GetGroup(Optional< uint8 > partyIndex)
Definition Player.h:2781
SpawnTrackingState GetSpawnTrackingStateByObjectives(uint32 spawnTrackingId, std::vector< uint32 > const &questObjectives) const
Definition Player.cpp:17526
Team GetTeam() const
Definition Player.h:2406
bool GetBGAccessByLevel(BattlegroundTypeId bgTypeId) const
Definition Player.cpp:25789
void setUInt16(uint8 index, uint16 value)
void setString(uint8 index, std::string &&value)
void setUInt32(uint8 index, uint32 value)
void setFloat(uint8 index, float value)
void setUInt64(uint8 index, uint64 value)
void setInt32(uint8 index, int32 value)
void setUInt8(uint8 index, uint8 value)
bool IsEffect() const
bool IsChanneled() const
bool HasAttribute(SpellAttr0 attribute) const
Definition SpellInfo.h:456
bool HasAura(AuraType aura) const
static CreatureImmunities const * GetCreatureImmunities(int32 creatureImmunitiesId)
Definition SpellMgr.cpp:687
Definition Spell.h:277
SpellInfo const * GetSpellInfo() const
Definition Spell.h:702
bool IsFocusDisabled() const
Definition Spell.cpp:8298
int32 GetCastTime() const
Definition Spell.h:659
Spell(WorldObject *caster, SpellInfo const *info, TriggerCastFlags triggerFlags, ObjectGuid originalCasterGUID=ObjectGuid::Empty, ObjectGuid originalCastId=ObjectGuid::Empty)
Definition Spell.cpp:473
void EvaluateSuppressed(bool canExpire=false)
Unit * GetCurrentVictim()
Unit * GetAnyTarget() const
void Update(uint32 tdiff)
std::pair< iterator, bool > insert(Key const &key)
Definition FlatSet.h:82
Mask const & GetChangesMask() const
MutableFieldReference< T, false > ModifyValue(UpdateField< T, BlockBit, Bit >(Derived::*field))
bool HasChanged(uint32 index) const
Definition BaseEntity.h:83
uint32 GetChangedObjectTypeMask() const
Definition BaseEntity.h:81
virtual void InitializeAI()
Definition UnitAI.cpp:35
Definition Unit.h:647
void ClearUnitState(uint32 f)
Definition Unit.h:756
bool IsVehicle() const
Definition Unit.h:766
void ApplySpellImmune(uint32 spellId, SpellImmunity op, uint32 type, bool apply)
Definition Unit.cpp:8261
int32 ModifyPower(Powers power, int32 val, bool withPowerUpdate=true)
Definition Unit.cpp:8716
bool IsCharmed() const
Definition Unit.h:1256
Vehicle * GetVehicle() const
Definition Unit.h:1800
virtual bool IsMovementPreventedByCasting() const
Definition Unit.cpp:3283
bool IsBattleMaster() const
Definition Unit.h:1028
bool isTargetableForAttack(bool checkFakeDeath=true) const
Definition Unit.cpp:8604
bool IsHunterPet() const
Definition Unit.h:764
AuraEffectList const & GetAuraEffectsByType(AuraType type) const
Definition Unit.h:1362
float GetHealthPct() const
Definition Unit.h:808
void AIUpdateTick(uint32 diff)
Definition Unit.cpp:10223
void SetHealth(uint64 val)
Definition Unit.cpp:10041
void RemoveUnitMovementFlag(MovementFlags f)
Definition Unit.h:1760
void SetVirtualItem(uint32 slot, uint32 itemId, uint16 appearanceModId=0, uint16 itemVisual=0)
Definition Unit.cpp:14521
uint64 CountPctFromMaxHealth(float pct) const
Definition Unit.h:809
void Heartbeat() override
Definition Unit.cpp:507
bool CanHaveThreatList() const
====================== THREAT & COMBAT ====================
Definition Unit.h:1045
void UpdateObjectVisibility(bool forced=true) override
Definition Unit.cpp:12563
bool CannotTurn() const
Definition Unit.h:1070
int64 ModifyHealth(int64 val)
Definition Unit.cpp:8618
void SetFullHealth()
Definition Unit.h:814
void SetStandState(UnitStandStateType state, uint32 animKitID=0)
Definition Unit.cpp:10804
void SetInitialPowerValue(Powers powerType)
Definition Unit.cpp:5769
void ReplaceAllNpcFlags2(NPCFlags2 flags)
Definition Unit.h:1020
float GetDisplayScale() const
Definition Unit.h:1638
ThreatManager & GetThreatManager()
Definition Unit.h:1093
void ReplaceAllPvpFlags(UnitPVPStateFlags flags)
Definition Unit.h:898
void AddToWorld() override
Definition Unit.cpp:10301
void SetModRangedHaste(float rangedHaste)
Definition Unit.h:856
void ReplaceAllUnitFlags3(UnitFlags3 flags)
Definition Unit.h:873
virtual void SetCanDualWield(bool value)
Definition Unit.h:716
void SetControlled(bool apply, UnitState state)
Definition Unit.cpp:11631
uint8 GetClass() const
Definition Unit.h:776
uint32 m_regenTimer
Definition Unit.h:1975
void SetCreateHealth(uint32 val)
Definition Unit.h:1434
Vehicle * m_vehicle
Definition Unit.h:1977
std::unique_ptr< CharmInfo > m_charmInfo
Definition Unit.h:1969
void UpdateDisplayPower()
Definition Unit.cpp:5827
void SetRace(uint8 race)
Definition Unit.h:774
NPCFlags GetNpcFlags() const
Definition Unit.h:1010
void UpdateSpeed(UnitMoveType mtype)
Definition Unit.cpp:8797
bool IsPolymorphed() const
Definition Unit.cpp:10831
bool IsAreaSpiritHealer() const
Definition Unit.h:1032
void SetFaction(uint32 faction) override
Definition Unit.h:887
virtual void SetPvP(bool state)
Definition Unit.cpp:12336
void SetBaseWeaponDamage(WeaponAttackType attType, WeaponDamageRange damageRange, float value)
Definition Unit.h:1600
void StopMoving(bool force=false)
Definition Unit.cpp:10753
void SetStatPctModifier(UnitMods unitMod, UnitModifierPctType modifierType, float val)
Definition Unit.cpp:9675
Unit * getAttackerForHelper() const
Definition Unit.cpp:5849
std::forward_list< AuraEffect * > AuraEffectList
Definition Unit.h:664
Trinity::unique_trackable_ptr< Vehicle > m_vehicleKit
Definition Unit.h:1978
bool IsAreaSpiritHealerIndividual() const
Definition Unit.h:1039
void SetAnimTier(AnimTier animTier, bool notifyClient=true)
Definition Unit.cpp:10818
void ReplaceAllUnitFlags(UnitFlags flags)
Definition Unit.h:863
MotionMaster * GetMotionMaster()
Definition Unit.h:1750
bool IsPet() const
Definition Unit.h:763
Powers GetPowerType() const
Definition Unit.h:823
bool HasUnitFlag(UnitFlags flags) const
Definition Unit.h:860
void Dismount()
Definition Unit.cpp:8336
bool SetHover(bool enable, bool updateAnimTier=true)
Definition Unit.cpp:13656
NPCFlags2 GetNpcFlags2() const
Definition Unit.h:1016
Aura * AddAura(uint32 spellId, Unit *target)
Definition Unit.cpp:12344
void SetModHaste(float haste)
Definition Unit.h:855
virtual void AtDisengage()
Definition Unit.h:1998
void SetUnitFlag2(UnitFlags2 flags)
Definition Unit.h:866
bool HasUnitFlag2(UnitFlags2 flags) const
Definition Unit.h:865
std::string GetDebugInfo() const override
Definition Unit.cpp:14738
void ReplaceAllPetFlags(UnitPetFlag flags)
Definition Unit.h:909
bool IsAlive() const
Definition Unit.h:1205
float GetCombatReach() const override
Definition Unit.h:717
void ReplaceAllVisFlags(UnitVisFlags flags)
Definition Unit.h:922
DeathState m_deathState
Definition Unit.h:1920
void SetModCastingSpeedNeg(float castingSpeedNeg)
Definition Unit.h:853
int32 GetMaxPower(Powers power) const
Definition Unit.cpp:10105
void RemoveNpcFlag(NPCFlags flags)
Definition Unit.h:1013
TempSummon * ToTempSummon()
Definition Unit.h:1844
bool IsQuestGiver() const
Definition Unit.h:1024
ObjectGuid GetCharmerOrOwnerGUID() const override
Definition Unit.h:1236
void SetModHasteRegen(float hasteRegen)
Definition Unit.h:857
virtual void SetInteractionAllowedWhileHostile(bool interactionAllowed)
Definition Unit.cpp:9319
float GetNativeDisplayScale() const
Definition Unit.h:1641
Player * GetPlayerMovingMe() const
Definition Unit.h:1273
void SetUninteractible(bool apply)
Definition Unit.cpp:8583
void SetBaseAttackTime(WeaponAttackType att, uint32 val)
Definition Unit.cpp:11012
void AddUnitState(uint32 f)
Definition Unit.h:754
float GetTotalAuraMultiplier(AuraType auraType) const
Definition Unit.cpp:5092
bool IsTaxi() const
Definition Unit.h:1026
void SetSheath(SheathState sheathed)
Definition Unit.cpp:5832
bool IsOnVehicle(Unit const *vehicle) const
Definition Unit.cpp:12201
void SetBoundingRadius(float boundingRadius)
Definition Unit.h:720
void SetCreateMana(uint32 val)
Definition Unit.h:1436
bool isInAccessiblePlaceFor(Creature const *c) const
Definition Unit.cpp:3328
bool IsCharmedOwnedByPlayerOrPlayer() const
Definition Unit.h:1237
virtual void SetInteractionAllowedInCombat(bool interactionAllowed)
Definition Unit.cpp:9329
Unit * EnsureVictim() const
Definition Unit.h:740
void SetModSpellHaste(float spellHaste)
Definition Unit.h:854
void RefreshAI()
Definition Unit.cpp:10255
Unit * GetCharmerOrOwner() const
Definition Unit.h:1241
virtual void UpdateDamagePhysical(WeaponAttackType attType)
void SetFacingToObject(WorldObject const *object, bool force=true, uint32 movementId=EVENT_FACE)
Definition Unit.cpp:13394
uint32 GetCreatureType() const
Definition Unit.cpp:9478
virtual bool IsImmunedToSpellEffect(SpellInfo const *spellInfo, SpellEffectInfo const &spellEffectInfo, WorldObject const *caster, bool requireImmunityPurgesEffectAttribute=false) const
Definition Unit.cpp:7936
bool SetSwim(bool enable)
Definition Unit.cpp:13519
void SetCombatReach(float combatReach)
Definition Unit.h:718
void SetEmoteState(Emote emote)
Definition Unit.h:880
virtual void UpdateNearbyPlayersInteractions()
Definition Unit.cpp:9340
float GetTotalAuraMultiplierByMiscValue(AuraType auraType, int32 misc_value) const
Definition Unit.cpp:5157
uint32 GetDisplayId() const
Definition Unit.h:1637
bool IsAIEnabled() const
Definition Unit.h:678
uint32 GetNativeDisplayId() const
Definition Unit.h:1640
uint64 GetMaxHealth() const
Definition Unit.h:801
bool IsHovering() const
Definition Unit.h:1166
bool PopAI()
Definition Unit.cpp:10244
float GetHoverOffset() const
Definition Unit.h:1828
uint64 GetHealth() const
Definition Unit.h:800
bool IsSummon() const
Definition Unit.h:761
bool IsInWater() const
Definition Unit.cpp:3349
TransportBase * GetDirectTransport() const
Returns the transport this unit is on directly (if on vehicle and transport, return vehicle)
Definition Unit.cpp:12246
uint32 GetFaction() const override
Definition Unit.h:886
uint32 GetCreateHealth() const
Definition Unit.h:1435
void RemoveUnitFlag2(UnitFlags2 flags)
Definition Unit.h:867
void SetAI(UnitAI *newAI)
Definition Unit.cpp:10238
void SetSpellEmpowerStage(int8 stage)
Definition Unit.h:1471
float GetTotalAuraModifier(AuraType auraType) const
Definition Unit.cpp:5087
void SetNpcFlag(NPCFlags flags)
Definition Unit.h:1012
bool HasAuraType(AuraType auraType) const
Definition Unit.cpp:4832
void EngageWithTarget(Unit *who)
Definition Unit.cpp:8513
void UpdateCreatureType()
Definition Unit.cpp:9502
bool HasNpcFlag(NPCFlags flags) const
Definition Unit.h:1011
uint8 GetLevelForTarget(WorldObject const *) const override
Definition Unit.h:771
void SetMovementAnimKitId(uint16 animKitId)
Definition Unit.cpp:11277
void SetMaxHealth(uint64 val)
Definition Unit.cpp:10072
float GetTotalAuraModifierByMiscValue(AuraType auraType, int32 misc_value) const
Definition Unit.cpp:5147
bool IsGuardian() const
Definition Unit.h:762
Unit * GetVictim() const
Definition Unit.h:738
UF::UpdateField< UF::UnitData, int32(WowCS::EntityFragment::CGObject), TYPEID_UNIT > m_unitData
Definition Unit.h:1897
int32 GetPower(Powers power) const
Definition Unit.cpp:10096
void SetModTimeRate(float timeRate)
Definition Unit.h:858
bool IsUnderWater() const
Definition Unit.cpp:3354
void SetSpeedRate(UnitMoveType mtype, float rate)
Definition Unit.cpp:8961
DeathState getDeathState() const
Definition Unit.h:1208
bool IsEngagedBy(Unit const *who) const
Definition Unit.h:1050
bool IsCritter() const
Definition Unit.h:1040
bool CreateVehicleKit(uint32 id, uint32 creatureEntry, bool loading=false)
Definition Unit.cpp:12169
bool HasUnitState(const uint32 f) const
Definition Unit.h:755
virtual void Update(uint32 time) override
Definition Unit.cpp:428
void ProcessPositionDataChanged(PositionFullTerrainStatus const &data) override
Definition Unit.cpp:3364
void SetLevel(uint8 lvl, bool sendUpdate=true)
Definition Unit.cpp:10019
void SetCanModifyStats(bool modifyStats)
Definition Unit.h:1575
void SetClass(uint8 classId)
Definition Unit.h:777
void SetFacingTo(float ori, bool force=true, uint32 movementId=EVENT_FACE)
Definition Unit.cpp:13385
virtual bool CanSwim() const
Definition Unit.cpp:13040
void RemoveFromWorld() override
Definition Unit.cpp:10309
bool IsOnOceanFloor() const
Definition Unit.cpp:3359
Powers CalculateDisplayPowerType() const
Definition Unit.cpp:5781
bool isDying() const
Definition Unit.h:1206
void DoMeleeAttackIfReady()
Definition Unit.cpp:2166
void RemoveAllAuras()
Definition Unit.cpp:4400
void ReplaceAllUnitFlags2(UnitFlags2 flags)
Definition Unit.h:868
bool IsWildBattlePet() const
Definition Unit.h:1036
virtual void setDeathState(DeathState s)
Definition Unit.cpp:9180
virtual void AtEngage(Unit *target)
Definition Unit.cpp:9277
UF::UpdateFieldFlag GetUpdateFieldFlagsFor(Player const *target) const override
Definition Unit.cpp:14363
CombatManager & GetCombatManager()
Definition Unit.h:1053
bool IsVendor() const
Definition Unit.h:1022
bool IsFlying() const
Definition Unit.h:1823
void SetVignette(uint32 vignetteId)
Definition Unit.cpp:14723
bool IsUninteractible() const
Definition Unit.h:1067
bool IsSpiritHealer() const
Definition Unit.h:1031
bool IsTotem() const
Definition Unit.h:765
void SetInFront(WorldObject const *target)
Definition Unit.cpp:13379
void SetModCastingSpeed(float castingSpeed)
Definition Unit.h:852
Vehicle * GetVehicleKit() const
Definition Unit.h:1798
bool SetDisableGravity(bool disable, bool updateAnimTier=true, bool updatePlayHoverAnim=true)
Definition Unit.cpp:13440
void ReplaceAllNpcFlags(NPCFlags flags)
Definition Unit.h:1014
bool IsSpiritService() const
Definition Unit.h:1038
bool IsFalling() const
Definition Unit.cpp:13035
void SetStatFlatModifier(UnitMods unitMod, UnitModifierFlatType modifierType, float val)
Definition Unit.cpp:9666
void SetShapeshiftForm(ShapeshiftForm form)
Definition Unit.cpp:9521
void SetMeleeAnimKitId(uint16 animKitId)
Definition Unit.cpp:11294
ObjectGuid GetTarget() const
Definition Unit.h:1847
void SetPowerType(Powers power, bool sendUpdate=true, bool onInit=false)
Definition Unit.cpp:5716
uint8 GetLevel() const
Definition Unit.h:769
void SetMountDisplayId(uint32 mountDisplayId)
Definition Unit.h:929
virtual void SetDisplayId(uint32 displayId, bool setNative=false)
Definition Unit.cpp:10852
bool IsInCombat() const
Definition Unit.h:1073
void SetWildBattlePetLevel(uint32 wildBattlePetLevel)
Definition Unit.h:1291
void SetIsCombatDisallowed(bool apply)
Definition Unit.h:1886
void RemoveUnitFlag(UnitFlags flags)
Definition Unit.h:862
void SetAIAnimKitId(uint16 animKitId)
Definition Unit.cpp:11260
Player * m_playerMovingMe
Definition Unit.h:1966
bool isDead() const
Definition Unit.h:1207
virtual void ExitVehicle(Position const *exitPosition=nullptr)
Definition Unit.cpp:12931
bool BuildPacket(WorldPacket *packet)
void AddUpdateBlock()
Definition UpdateData.h:46
constexpr uint32 GetBlock(uint32 index) const
Definition UpdateMask.h:59
constexpr void Set(uint32 index)
Definition UpdateMask.h:91
Unit * GetBase() const
Definition Vehicle.h:49
void Reset(bool evading=false)
Reapplies immunities and reinstalls accessories. Only has effect for creatures.
Definition Vehicle.cpp:150
void Install()
Initializes power type for vehicle. Nothing more.
Definition Vehicle.cpp:90
constexpr uint32 GetMapId() const
Definition Position.h:216
virtual bool IsInvisibleDueToDespawn(WorldObject const *seer) const
Definition Object.h:607
virtual void SendMessageToSet(WorldPacket const *data, bool self) const
Definition Object.cpp:1099
Map * GetMap() const
Definition Object.h:411
void UpdateAllowedPositionZ(float x, float y, float &z, float *groundZ=nullptr) const
Definition Object.cpp:709
virtual void UpdateObjectVisibilityOnDestroy()
Definition Object.h:511
bool IsValidAttackTarget(WorldObject const *target, SpellInfo const *bySpell=nullptr) const
Definition Object.cpp:2329
bool IsHostileTo(WorldObject const *target) const
Definition Object.cpp:2186
float GetTransOffsetX() const
Definition Object.h:538
uint32 LastUsedScriptID
Definition Object.h:534
TempSummon * SummonCreature(uint32 entry, Position const &pos, TempSummonType despawnType=TEMPSUMMON_MANUAL_DESPAWN, Milliseconds despawnTime=0s, uint32 vehId=0, uint32 spellId=0, ObjectGuid privateObjectOwner=ObjectGuid::Empty)
Definition Object.cpp:1403
PhaseShift & GetPhaseShift()
Definition Object.h:310
Unit * GetOwner() const
Definition Object.cpp:1603
ZoneScript * GetZoneScript() const
Definition Object.h:417
void SetZoneScript()
Definition Object.cpp:1389
TransportBase * GetTransport() const
Definition Object.h:537
void setActive(bool isActiveObject)
Definition Object.cpp:274
float GetTransOffsetY() const
Definition Object.h:539
float GetFloorZ() const
Definition Object.cpp:3109
std::string const & GetName() const
Definition Object.h:342
virtual void SetMap(Map *map)
Definition Object.cpp:1149
float GetTransOffsetZ() const
Definition Object.h:540
void AddObjectToRemoveList()
Definition Object.cpp:1179
bool IsWithinLOSInMap(WorldObject const *obj, LineOfSightChecks checks=LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags ignoreFlags=VMAP::ModelIgnoreFlags::Nothing) const
Definition Object.cpp:533
bool IsNeutralToAll() const
Definition Object.cpp:2209
Player * GetCharmerOrOwnerPlayerOrPlayerItself() const
Definition Object.cpp:1626
bool IsWithinDistInMap(WorldObject const *obj, float dist2compare, bool is3D=true, bool incOwnRadius=true, bool incTargetRadius=true) const
Definition Object.cpp:499
void SetName(std::string newname)
Definition Object.h:343
EventProcessor m_Events
Definition Object.h:561
float GetVisibilityRange() const
Definition Object.cpp:785
FlaggedValuesArray32< int32, uint32, ServerSideVisibilityType, TOTAL_SERVERSIDE_VISIBILITY_TYPES > m_serverSideVisibilityDetect
Definition Object.h:407
uint32 GetAreaId() const
Definition Object.h:333
float GetTransOffsetO() const
Definition Object.h:541
void SetVisibilityDistanceOverride(VisibilityDistanceType type)
Definition Object.cpp:297
uint32 GetZoneId() const
Definition Object.h:332
MovementInfo m_movementInfo
Definition Object.h:548
FlaggedValuesArray32< int32, uint32, ServerSideVisibilityType, TOTAL_SERVERSIDE_VISIBILITY_TYPES > m_serverSideVisibility
Definition Object.h:406
float GetDistanceZ(WorldObject const *obj) const
Definition Object.cpp:400
bool IsWithinDist(WorldObject const *obj, float dist2compare, bool is3D=true, bool incOwnRadius=true, bool incTargetRadius=true) const
Definition Object.cpp:494
bool IsFriendlyTo(WorldObject const *target) const
Definition Object.cpp:2191
bool IsInMap(WorldObject const *obj) const
Definition Object.cpp:467
int32 GetDBPhase() const
Definition Object.h:327
WorldPacket const * Write() override
WorldPacket const * Write() override
WorldPacket const * GetRawPacket() const
Definition Packet.h:38
virtual uint32 GetCreatureEntry(ObjectGuid::LowType, CreatureData const *data)
virtual void OnCreatureRemove(Creature *)
Definition ZoneScript.h:77
virtual void OnCreatureCreate(Creature *)
Definition ZoneScript.h:76
#define sWorld
Definition World.h:919
@ CONFIG_CORPSE_DECAY_ELITE
Definition World.h:329
@ CONFIG_NO_GRAY_AGGRO_BELOW
Definition World.h:414
@ CONFIG_CORPSE_DECAY_OBSOLETE
Definition World.h:331
@ CONFIG_CREATURE_PICKPOCKET_REFILL
Definition World.h:405
@ CONFIG_RESPAWN_DYNAMICMODE
Definition World.h:420
@ CONFIG_MAX_PLAYER_LEVEL
Definition World.h:263
@ CONFIG_CORPSE_DECAY_MINUSMOB
Definition World.h:334
@ CONFIG_CORPSE_DECAY_NORMAL
Definition World.h:328
@ CONFIG_CORPSE_DECAY_TRIVIAL
Definition World.h:333
@ CONFIG_NO_GRAY_AGGRO_ABOVE
Definition World.h:413
@ CONFIG_CREATURE_STOP_FOR_PLAYER
Definition World.h:406
@ CONFIG_CORPSE_DECAY_RARE
Definition World.h:332
@ CONFIG_CORPSE_DECAY_RAREELITE
Definition World.h:330
@ CONFIG_CREATURE_FAMILY_ASSISTANCE_DELAY
Definition World.h:312
@ RATE_CREATURE_DAMAGE_NORMAL
Definition World.h:498
@ RATE_CREATURE_DAMAGE_RAREELITE
Definition World.h:500
@ RATE_CREATURE_AGGRO
Definition World.h:512
@ RATE_CREATURE_HP_ELITE
Definition World.h:492
@ RATE_CREATURE_HP_RARE
Definition World.h:495
@ RATE_CREATURE_DAMAGE_ELITE
Definition World.h:499
@ RATE_CREATURE_SPELLDAMAGE_TRIVIAL
Definition World.h:510
@ RATE_CREATURE_SPELLDAMAGE_NORMAL
Definition World.h:505
@ RATE_POWER_MANA
Definition World.h:453
@ RATE_CREATURE_SPELLDAMAGE_RAREELITE
Definition World.h:507
@ RATE_HEALTH
Definition World.h:452
@ RATE_CREATURE_HP_OBSOLETE
Definition World.h:494
@ RATE_CREATURE_DAMAGE_OBSOLETE
Definition World.h:501
@ RATE_CREATURE_DAMAGE_MINUSMOB
Definition World.h:504
@ RATE_POWER_FOCUS
Definition World.h:456
@ RATE_CREATURE_HP_NORMAL
Definition World.h:491
@ RATE_CREATURE_HP_MINUSMOB
Definition World.h:497
@ RATE_CREATURE_HP_TRIVIAL
Definition World.h:496
@ RATE_CORPSE_DECAY_LOOTED
Definition World.h:521
@ RATE_CREATURE_DAMAGE_RARE
Definition World.h:502
@ RATE_CREATURE_DAMAGE_TRIVIAL
Definition World.h:503
@ RATE_CREATURE_SPELLDAMAGE_ELITE
Definition World.h:506
@ RATE_CREATURE_SPELLDAMAGE_MINUSMOB
Definition World.h:511
@ RATE_CREATURE_HP_RAREELITE
Definition World.h:493
@ RATE_CREATURE_SPELLDAMAGE_OBSOLETE
Definition World.h:508
@ RATE_CREATURE_SPELLDAMAGE_RARE
Definition World.h:509
@ CONFIG_SIGHT_MONSTER
Definition World.h:209
@ CONFIG_CREATURE_FAMILY_FLEE_ASSISTANCE_RADIUS
Definition World.h:213
@ CONFIG_CREATURE_FAMILY_ASSISTANCE_RADIUS
Definition World.h:214
@ CONFIG_REGEN_HP_CANNOT_REACH_TARGET_IN_RAID
Definition World.h:195
@ CONFIG_LOAD_LOCALES
Definition World.h:201
static constexpr ObjectData creatureData[]
static constexpr uint32 Entry[5]
CreatureAI * SelectAI(Creature *creature)
time_t GetGameTime()
Definition GameTime.cpp:52
TC_GAME_API WorldObject * GetWorldObject(WorldObject const &, ObjectGuid const &)
TC_GAME_API Unit * GetUnit(WorldObject const &, ObjectGuid const &guid)
TC_GAME_API Creature * GetCreature(WorldObject const &u, ObjectGuid const &guid)
auto SelectRandomWeightedContainerElement(C const &container, std::span< double > const &weights) -> decltype(std::ranges::begin(container))
Definition Containers.h:127
auto SelectRandomContainerElement(C const &container) -> std::add_const_t< decltype(*std::ranges::begin(container))> &
Definition Containers.h:110
auto MapGetValuePtr(M &map, typename M::key_type const &key)
Definition MapUtils.h:37
void MultimapErasePair(M &multimap, typename M::key_type const &key, typename M::mapped_type const &value)
Definition MapUtils.h:57
XPColorChar GetColorCode(uint8 pl_level, uint8 mob_level)
Definition Formulas.h:91
bool IsValidMapCoord(float c)
constexpr GridCoord ComputeGridCoord(float x, float y)
UpdateFieldFlag
Definition UpdateField.h:37
void const * GetRawFragmentData(T const &fragmentData)
struct advstd::ranges::Contains contains
static void VisitWorldObjects(WorldObject const *obj, T &visitor, float radius)
Definition CellImpl.h:150
static void VisitAllObjects(WorldObject const *obj, T &visitor, float radius)
Definition CellImpl.h:160
static void VisitGridObjects(WorldObject const *obj, T &visitor, float radius)
Definition CellImpl.h:140
std::vector< uint32 > auras
uint16 meleeAnimKit
uint16 movementAnimKit
VisibilityDistanceType visibilityDistanceType
static CreatureBaseStats const * GetBaseStats(uint8 level, uint8 unitClass)
Definition Creature.cpp:307
float wander_distance
Optional< uint32 > curHealthPct
Optional< uint64 > npcflag
Optional< CreatureModel > display
Optional< uint32 > unit_flags2
uint32 currentwaypoint
Optional< uint32 > unit_flags3
Optional< uint32 > unit_flags
int32 GetHealthScalingExpansion() const
CreatureStaticFlagsHolder StaticFlags
std::bitset< MAX_MECHANIC > Mechanic
Definition SpellMgr.h:567
EnumFlag< SpellOtherImmunity > Other
Definition SpellMgr.h:570
std::bitset< MAX_SPELL_SCHOOL > School
Definition SpellMgr.h:565
std::vector< SpellEffects > Effect
Definition SpellMgr.h:568
std::bitset< DISPEL_MAX > DispelType
Definition SpellMgr.h:566
std::vector< AuraType > Aura
Definition SpellMgr.h:569
uint32 CreatureDisplayID
static CreatureModel const DefaultVisibleModel
static CreatureModel const DefaultInvisibleModel
CreatureRandomMovementType Random
std::string ToString() const
Definition Creature.cpp:62
CreatureChaseMovementType Chase
Optional< CreatureStaticFlags > StaticFlags1
Optional< CreatureStaticFlags5 > StaticFlags5
Optional< CreatureStaticFlags7 > StaticFlags7
Optional< CreatureStaticFlags3 > StaticFlags3
Optional< CreatureStaticFlags2 > StaticFlags2
Optional< CreatureStaticFlags6 > StaticFlags6
Optional< CreatureStaticFlags8 > StaticFlags8
Optional< CreatureStaticFlags4 > StaticFlags4
void InitializeQueryData()
Definition Creature.cpp:168
CreatureModel const * GetRandomValidModel() const
Definition Creature.cpp:113
CreatureModel const * GetModelByIdx(uint32 idx) const
Definition Creature.cpp:108
CreatureDifficulty const * GetDifficulty(Difficulty difficulty) const
Definition Creature.cpp:252
CreatureClassifications Classification
CreatureModel const * GetFirstInvisibleModel() const
Definition Creature.cpp:148
CreatureFamily family
std::string Name
uint32 spells[MAX_CREATURE_SPELLS]
int32 resistance[MAX_SPELL_SCHOOL]
CreatureModel const * GetFirstValidModel() const
Definition Creature.cpp:130
std::string StringId
CreatureTemplate & operator=(CreatureTemplate const &other)=delete
CreatureMovementData Movement
std::unique_ptr< WorldPacket[]> QueryData
uint32 KillCredit[MAX_KILL_CREDIT]
CreatureModel const * GetModelWithDisplayId(uint32 displayId) const
Definition Creature.cpp:139
CreatureModel const * GetFirstVisibleModel() const
Definition Creature.cpp:158
std::vector< CreatureModel > Models
std::unordered_map< Difficulty, CreatureDifficulty > difficultyStore
std::string FemaleName
WorldPacket BuildQueryData(LocaleConstant loc, Difficulty difficulty) const
Definition Creature.cpp:181
void operator()(Player const *player) const
EquipmentItem Items[MAX_EQUIPMENT_ITEMS]
uint16 AppearanceModId
Definition Loot.h:286
LootType loot_type
Definition Loot.h:293
struct MovementInfo::TransportInfo transport
constexpr float GetPositionX() const
Definition Position.h:87
float m_positionZ
Definition Position.h:66
constexpr float GetPositionY() const
Definition Position.h:88
constexpr bool IsInDist2d(float x, float y, float dist) const
Definition Position.h:151
std::string ToString() const
Definition Position.cpp:202
Position GetPositionWithOffset(Position const &offset) const
Definition Position.cpp:61
bool IsPositionValid() const
Definition Position.cpp:42
constexpr void Relocate(float x, float y)
Definition Position.h:74
constexpr Position GetPosition() const
Definition Position.h:95
constexpr bool IsInDist(float x, float y, float z, float dist) const
Definition Position.h:155
constexpr float GetOrientation() const
Definition Position.h:90
constexpr float GetPositionZ() const
Definition Position.h:89
ObjectGuid::LowType spawnId
Definition Map.h:174
time_t respawnTime
Definition Map.h:176
SpawnObjectType type
Definition Map.h:173
uint32 scriptId
Definition SpawnData.h:144
uint8 phaseUseFlags
Definition SpawnData.h:137
uint32 id
Definition SpawnData.h:135
uint32 phaseId
Definition SpawnData.h:138
Position spawnPoint
Definition SpawnData.h:136
int32 spawntimesecs
Definition SpawnData.h:142
int32 terrainSwapMap
Definition SpawnData.h:140
uint32 phaseGroup
Definition SpawnData.h:139
uint32 poolId
Definition SpawnData.h:141
std::string StringId
Definition SpawnData.h:145
std::vector< Difficulty > spawnDifficulties
Definition SpawnData.h:143
SpawnGroupFlags flags
Definition SpawnData.h:72
SpawnGroupTemplateData const * spawnGroupData
Definition SpawnData.h:124
uint64 spawnId
Definition SpawnData.h:121
std::vector< uint32 > spawnTrackingQuestObjectives
Definition SpawnData.h:126
bool Insert(ValueType< ObjectType > object)
bool Remove(ValueType< ObjectType > object)
static void AppendAllowedFieldsMaskForFlag(Mask &allowedMaskForTarget, EnumFlag< UpdateFieldFlag > fieldVisibilityFlags)
UpdateField< uint32, 0, 12 > StateWorldEffectsQuestObjectiveID
UpdateField< int32, 32, 44 > ScalingLevelMax
UpdateField< int32, 32, 42 > ContentTuningID
UpdateField< int32, 32, 45 > ScalingLevelDelta
UpdateField< int32, 96, 125 > TaxiNodesID
UpdateField< int32, 32, 43 > ScalingLevelMin
static void FilterDisallowedFieldsMaskForFlag(Mask &changesMask, EnumFlag< UpdateFieldFlag > fieldVisibilityFlags)
UpdateField< ObjectGuid, 0, 22 > Target
UpdateField< int32, 0, 1 > Flags
time_t lastIncrementTime
Definition Creature.h:46
VendorItemCount(uint32 _item, uint32 _count)
Definition Creature.cpp:77
std::vector< VendorItem > m_items
VendorItem const * FindItemCostPair(uint32 item_id, uint32 extendedCost, uint8 type) const
Definition Creature.cpp:92
bool RemoveItem(uint32 item_id, uint8 type)
Definition Creature.cpp:80
uint32 maxcount
uint32 incrtime
std::vector< CreatureXDisplay > CreatureDisplay
std::array< uint32, 3 > Flags
std::array< std::string, 4 > Name
std::array< std::string, 4 > NameAlt
std::array< uint32, 2 > ProxyCreatureID
void Remove(EntityFragment fragment)
void Add(EntityFragment fragment, bool update, void const *data=nullptr)