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 struct DefaultCreatureDifficulty : public CreatureDifficulty
265 {
266 DefaultCreatureDifficulty()
267 {
268 DeltaLevelMin = 0;
269 DeltaLevelMax = 0;
270 ContentTuningID = 0;
271 HealthScalingExpansion = 0;
272 HealthModifier = 1.f;
273 ManaModifier = 1.f;
274 ArmorModifier = 1.f;
275 DamageModifier = 1.f;
276 CreatureDifficultyID = 0;
277 TypeFlags = 0;
278 TypeFlags2 = 0;
279 TypeFlags3 = 0;
280 LootID = 0;
281 PickPocketLootID = 0;
282 SkinLootID = 0;
283 GoldMin = 0;
284 GoldMax = 0;
285 }
286 };
287 static const DefaultCreatureDifficulty defDifficulty;
288 return &defDifficulty;
289}
290
291bool AssistDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
292{
294 {
295 while (!m_assistants.empty())
296 {
298 m_assistants.pop_front();
299
300 if (assistant && assistant->CanAssistTo(&m_owner, victim))
301 {
302 assistant->SetNoCallAssistance(true);
303 assistant->EngageWithTarget(victim);
304 }
305 }
306 }
307 return true;
308}
309
311{
312 return sObjectMgr->GetCreatureBaseStats(level, unitClass);
313}
314
316{
317 m_owner.DespawnOrUnsummon(0s, m_respawnTimer); // since we are here, we are not TempSummon as object type cannot change during runtime
318 return true;
319}
320
321Creature::Creature(bool isWorldObject) : Unit(isWorldObject), MapObject(), m_PlayerDamageReq(0), m_dontClearTapListOnEvade(false), _pickpocketLootRestore(0),
322 m_corpseRemoveTime(0), m_respawnTime(0), m_respawnDelay(300), m_corpseDelay(60), m_ignoreCorpseDecayRatio(false), m_wanderDistance(0.0f),
323 m_boundaryCheckTime(2500), m_reactState(REACT_AGGRESSIVE),
324 m_defaultMovementType(IDLE_MOTION_TYPE), m_spawnId(UI64LIT(0)), m_equipmentId(0), m_originalEquipmentId(0),
325 m_AlreadyCallAssistance(false), m_AlreadySearchedAssistance(false), m_cannotReachTarget(false), m_cannotReachTimer(0),
326 m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_originalEntry(0), m_homePosition(), m_transportHomePosition(),
327 m_creatureInfo(nullptr), m_creatureData(nullptr), m_creatureDifficulty(nullptr), m_stringIds(), _waypointPathId(0), _currentWaypointNodeInfo(0, 0),
328 m_formation(nullptr), m_triggerJustAppeared(true), m_respawnCompatibilityMode(false), _aggroGracePeriodExpired(false), _lastDamagedTime(0),
329 _regenerateHealth(true), _creatureImmunitiesId(0), _gossipMenuId(0), _sparringHealthPct(0)
330{
332
333 for (uint8 i = 0; i < MAX_CREATURE_SPELLS; ++i)
334 m_spells[i] = 0;
335
336 DisableReputationGain = false;
337
339 m_CombatDistance = 0;//MELEE_RANGE;
340
341 ResetLootMode(); // restore default loot mode
342 m_isTempWorldObject = false;
343}
344
345Creature::~Creature() = default;
346
348{
350 if (!IsInWorld())
351 {
353 if (m_spawnId)
354 GetMap()->GetCreatureBySpawnIdStore().insert(std::make_pair(m_spawnId, this));
355
359 if (IsVehicle())
361
362 if (GetZoneScript())
364 }
365}
366
368{
369 if (IsInWorld())
370 {
371 if (GetZoneScript())
373
374 if (m_formation)
376
378
379 if (m_spawnId)
380 Trinity::Containers::MultimapErasePair(GetMap()->GetCreatureBySpawnIdStore(), m_spawnId, this);
382 }
383}
384
386{
387 if (GetMotionMaster()->GetCurrentMovementGeneratorType() == HOME_MOTION_TYPE)
388 return true;
389
390 return false;
391}
392
394{
395 if (IsSummon())
396 return;
397
399 if (!lowguid)
400 return;
401
402 if (FormationInfo const* formationInfo = sFormationMgr->GetFormationInfo(lowguid))
403 FormationMgr::AddCreatureToGroup(formationInfo->LeaderSpawnId, this);
404}
405
407{
408 if (!m_formation)
409 return false;
410
411 return m_formation->IsLeader(this);
412}
413
415{
416 if (!m_formation)
417 return;
418
419 if (!m_formation->IsLeader(this))
420 return;
421
423}
424
426{
427 if (!m_formation)
428 return false;
429
431}
432
433void Creature::RemoveCorpse(bool setSpawnTime, bool destroyForNearbyPlayers)
434{
435 if (getDeathState() != CORPSE)
436 return;
437
439 {
443 m_loot = nullptr;
444 uint32 respawnDelay = m_respawnDelay;
445 if (CreatureAI* ai = AI())
446 ai->CorpseRemoved(respawnDelay);
447
448 if (destroyForNearbyPlayers)
450
451 // Should get removed later, just keep "compatibility" with scripts
452 if (setSpawnTime)
453 m_respawnTime = std::max<time_t>(GameTime::GetGameTime() + respawnDelay, m_respawnTime);
454
455 // if corpse was removed during falling, the falling will continue and override relocation to respawn position
456 if (IsFalling())
457 StopMoving();
458
459 Position respawnPosition = GetRespawnPosition();
460
461 // We were spawned on transport, calculate real position
463 {
464 m_movementInfo.transport.pos = respawnPosition;
465
466 if (TransportBase* transport = GetDirectTransport())
467 respawnPosition = transport->GetPositionWithOffset(respawnPosition);
468 }
469
470 UpdateAllowedPositionZ(respawnPosition.GetPositionX(), respawnPosition.GetPositionY(), respawnPosition.m_positionZ);
471 SetHomePosition(respawnPosition);
472 GetMap()->CreatureRelocation(this, respawnPosition.GetPositionX(), respawnPosition.GetPositionY(), respawnPosition.GetPositionZ(), respawnPosition.GetOrientation());
473 }
474 else
475 {
476 if (CreatureAI* ai = AI())
477 ai->CorpseRemoved(m_respawnDelay);
478
479 // In case this is called directly and normal respawn timer not set
480 // Since this timer will be longer than the already present time it
481 // will be ignored if the correct place added a respawn timer
482 if (setSpawnTime)
483 {
484 uint32 respawnDelay = m_respawnDelay;
485 m_respawnTime = std::max<time_t>(GameTime::GetGameTime() + respawnDelay, m_respawnTime);
486
488 }
489
490 if (TempSummon* summon = ToTempSummon())
491 summon->UnSummon();
492 else
494 }
495}
496
500bool Creature::InitEntry(uint32 entry, CreatureData const* data /*= nullptr*/)
501{
502 CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(entry);
503 if (!creatureInfo)
504 {
505 TC_LOG_ERROR("sql.sql", "Creature::InitEntry creature entry {} does not exist.", entry);
506 return false;
507 }
508
509 m_creatureInfo = creatureInfo;
510 SetEntry(entry);
511 m_creatureDifficulty = creatureInfo->GetDifficulty(!IsPet() ? GetMap()->GetDifficultyID() : DIFFICULTY_NONE);
512
513 // equal to player Race field, but creature does not have race
515
516 // known valid are: CLASS_WARRIOR, CLASS_PALADIN, CLASS_ROGUE, CLASS_MAGE
517 SetClass(uint8(creatureInfo->unit_class));
518
519 // Cancel load if no model defined
520 if (!(creatureInfo->GetFirstValidModel()))
521 {
522 TC_LOG_ERROR("sql.sql", "Creature (Entry: {}) has no model defined in table `creature_template`, can't load. ", entry);
523 return false;
524 }
525
526 CreatureModel model = *ObjectMgr::ChooseDisplayId(creatureInfo, data);
527 CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelRandomGender(&model, creatureInfo);
528 if (!minfo) // Cancel load if no model defined
529 {
530 TC_LOG_ERROR("sql.sql", "Creature (Entry: {}) has invalid model {} defined in table `creature_template_model`, can't load.", entry, model.CreatureDisplayID);
531 return false;
532 }
533
534 SetDisplayId(model.CreatureDisplayID, true);
535
536 // Load creature equipment
537 if (!data)
538 LoadEquipment(); // use default equipment (if available) for summons
539 else if (data->equipmentId == 0)
540 LoadEquipment(0); // 0 means no equipment for creature table
541 else
542 {
545 }
546
547 SetName(creatureInfo->Name); // at normal entry always
548
549 SetModCastingSpeed(1.0f);
550 SetModSpellHaste(1.0f);
551 SetModHaste(1.0f);
552 SetModRangedHaste(1.0f);
553 SetModHasteRegen(1.0f);
554 SetModTimeRate(1.0f);
556
557 SetSpeedRate(MOVE_WALK, creatureInfo->speed_walk);
558 SetSpeedRate(MOVE_RUN, creatureInfo->speed_run);
559 SetSpeedRate(MOVE_SWIM, 1.0f); // using 1.0 rate
560 SetSpeedRate(MOVE_FLIGHT, 1.0f); // using 1.0 rate
561
562 // Will set UNIT_FIELD_BOUNDINGRADIUS, UNIT_FIELD_COMBATREACH and UNIT_FIELD_DISPLAYSCALE
564
566
568
569 // checked at loading
573
574 for (uint8 i = 0; i < MAX_CREATURE_SPELLS; ++i)
576
578 ApplyAllStaticFlags(staticFlags);
579
581 || IsPet()
582 || IsTotem()
583 || creatureInfo->flags_extra & CREATURE_FLAG_EXTRA_NO_XP);
584
585 // TODO: migrate these in DB
589
590 return true;
591}
592
593bool Creature::UpdateEntry(uint32 entry, CreatureData const* data /*= nullptr*/, bool updateLevel /* = true */)
594{
595 if (!InitEntry(entry, data))
596 return false;
597
598 CreatureTemplate const* cInfo = GetCreatureTemplate();
599
601
602 // creatures always have melee weapon ready if any unless specified otherwise
603 if (!GetCreatureAddon())
605
606 SetFaction(cInfo->faction);
607
608 uint64 npcFlags;
609 uint32 unitFlags, unitFlags2, unitFlags3;
610 ObjectMgr::ChooseCreatureFlags(cInfo, &npcFlags, &unitFlags, &unitFlags2, &unitFlags3, _staticFlags, data);
611
613 npcFlags |= sGameEventMgr->GetNPCFlag(this);
614
615 if (IsVendor() && !(npcFlags & UNIT_NPC_FLAG_VENDOR_MASK))
617
618 ReplaceAllNpcFlags(NPCFlags(npcFlags & 0xFFFFFFFF));
619 ReplaceAllNpcFlags2(NPCFlags2(npcFlags >> 32));
620
621 if (npcFlags & UNIT_NPC_FLAG_VENDOR_MASK)
623
624 SetPetitioner((npcFlags & UNIT_NPC_FLAG_PETITIONER) != 0);
625
626 // if unit is in combat, keep this flag
627 unitFlags &= ~UNIT_FLAG_IN_COMBAT;
628 if (IsInCombat())
629 unitFlags |= UNIT_FLAG_IN_COMBAT;
630
631 ReplaceAllUnitFlags(UnitFlags(unitFlags));
632 ReplaceAllUnitFlags2(UnitFlags2(unitFlags2));
633 ReplaceAllUnitFlags3(UnitFlags3(unitFlags3));
634
636
637 // Set StateWorldEffectsQuestObjectiveID if there is only one linked objective for this creature
638 if (data && data->spawnTrackingQuestObjectives.size() == 1)
640
642
646
647 if (updateLevel)
648 SelectLevel();
649 else if (!IsGuardian())
650 {
651 uint32 previousHealth = GetHealth();
652 UpdateLevelDependantStats(); // We still re-initialize level dependant stats on entry update
653 if (previousHealth > 0)
654 SetHealth(previousHealth);
655 }
656
657 // Do not update guardian stats here - they are handled in Guardian::InitStatsForLevel()
658 if (!IsGuardian())
659 {
667
668 SetCanModifyStats(true);
670 }
671
672 // checked and error show at loading templates
673 if (FactionTemplateEntry const* factionTemplate = sFactionTemplateStore.LookupEntry(cInfo->faction))
674 {
675 SetPvP((factionTemplate->Flags & FACTION_TEMPLATE_FLAG_PVP) != 0);
676 if (IsTaxi())
677 {
678 uint32 taxiNodesId = sObjectMgr->GetNearestTaxiNode(GetPositionX(), GetPositionY(), GetPositionZ(), GetMapId(),
679 factionTemplate->FactionGroup & FACTION_MASK_ALLIANCE ? ALLIANCE : HORDE);
681 }
682 }
683
684 // updates spell bars for vehicles and set player's faction - should be called here, to overwrite faction that is set from the new template
685 if (IsVehicle())
686 {
687 if (Player* owner = Creature::GetCharmerOrOwnerPlayerOrPlayerItself()) // this check comes in case we don't have a player
688 {
689 SetFaction(owner->GetFaction()); // vehicles should have same as owner faction
690 owner->VehicleSpellInitialize();
691 }
692 }
693
694 // trigger creature is always uninteractible and can not be attacked
695 if (IsTrigger())
696 SetUninteractible(true);
697
700
702
704 {
707 }
708
710
712
716
718
719 //We must update last scriptId or it looks like we reloaded a script, breaking some things such as gossip temporarily
721
723
724 return true;
725}
726
728{
729 CreatureStaticFlagsOverride const* staticFlagsOverride = sObjectMgr->GetCreatureStaticFlagsOverride(spawnId, difficultyId);
730 if (!staticFlagsOverride)
731 return creatureDifficulty->StaticFlags;
732
734 staticFlagsOverride->StaticFlags1.value_or(creatureDifficulty->StaticFlags.GetFlags()),
735 staticFlagsOverride->StaticFlags2.value_or(creatureDifficulty->StaticFlags.GetFlags2()),
736 staticFlagsOverride->StaticFlags3.value_or(creatureDifficulty->StaticFlags.GetFlags3()),
737 staticFlagsOverride->StaticFlags4.value_or(creatureDifficulty->StaticFlags.GetFlags4()),
738 staticFlagsOverride->StaticFlags5.value_or(creatureDifficulty->StaticFlags.GetFlags5()),
739 staticFlagsOverride->StaticFlags6.value_or(creatureDifficulty->StaticFlags.GetFlags6()),
740 staticFlagsOverride->StaticFlags7.value_or(creatureDifficulty->StaticFlags.GetFlags7()),
741 staticFlagsOverride->StaticFlags8.value_or(creatureDifficulty->StaticFlags.GetFlags8()));
742}
743
745{
747
748 // Apply all other side effects of flag changes
750}
751
753{
755 {
758
761 m_triggerJustAppeared = false;
762 AI()->JustAppeared();
763 }
764
766
767 GetThreatManager().Update(diff);
768
769 switch (m_deathState)
770 {
771 case JUST_RESPAWNED:
772 // Must not be called, see Creature::setDeathState JUST_RESPAWNED -> ALIVE promoting.
773 TC_LOG_ERROR("entities.unit", "Creature {} in wrong state: JUST_RESPAWNED (4)", GetGUID().ToString());
774 break;
775 case JUST_DIED:
776 // Must not be called, see Creature::setDeathState JUST_DIED -> CORPSE promoting.
777 TC_LOG_ERROR("entities.unit", "Creature {} in wrong state: JUST_DIED (1)", GetGUID().ToString());
778 break;
779 case DEAD:
780 {
782 {
783 TC_LOG_ERROR("entities.unit", "Creature {} in wrong state: DEAD (3)", GetGUID().ToString());
784 break;
785 }
786 time_t now = GameTime::GetGameTime();
787 if (m_respawnTime <= now)
788 {
789 // Delay respawn if spawn group is not active
790 if (m_creatureData && !GetMap()->IsSpawnGroupActive(m_creatureData->spawnGroupData->groupId))
791 {
792 m_respawnTime = now + urand(4,7);
793 break; // Will be rechecked on next Update call after delay expires
794 }
795
796 ObjectGuid dbtableHighGuid = ObjectGuid::Create<HighGuid::Creature>(GetMapId(), GetEntry(), m_spawnId);
797 time_t linkedRespawnTime = GetMap()->GetLinkedRespawnTime(dbtableHighGuid);
798 if (!linkedRespawnTime) // Can respawn
799 Respawn();
800 else // the master is dead
801 {
802 ObjectGuid targetGuid = sObjectMgr->GetLinkedRespawnGuid(dbtableHighGuid);
803 if (targetGuid == dbtableHighGuid) // if linking self, never respawn
805 else
806 {
807 // else copy time from master and add a little
808 time_t baseRespawnTime = std::max(linkedRespawnTime, now);
809 time_t const offset = urand(5, MINUTE);
810
811 // linked guid can be a boss, uses std::numeric_limits<time_t>::max to never respawn in that instance
812 // we shall inherit it instead of adding and causing an overflow
813 if (baseRespawnTime <= std::numeric_limits<time_t>::max() - offset)
814 m_respawnTime = baseRespawnTime + offset;
815 else
816 m_respawnTime = std::numeric_limits<time_t>::max();
817 }
818 SaveRespawnTime(); // also save to DB immediately
819 }
820 }
821 break;
822 }
823 case CORPSE:
824 {
825 Unit::Update(diff);
826 // deathstate changed on spells update, prevent problems
827 if (m_deathState != CORPSE)
828 break;
829
830 if (IsEngaged())
831 Unit::AIUpdateTick(diff);
832
833 if (m_loot)
834 m_loot->Update();
835
836 for (auto&& [playerOwner, loot] : m_personalLoot)
837 loot->Update();
838
840 {
841 RemoveCorpse(false);
842 TC_LOG_DEBUG("entities.unit", "Removing corpse... {} ", GetEntry());
843 }
844 break;
845 }
846 case ALIVE:
847 {
848 Unit::Update(diff);
849
850 // creature can be dead after Unit::Update call
851 // CORPSE/DEAD state will processed at next tick (in other case death timer will be updated unexpectedly)
852 if (!IsAlive())
853 break;
854
855 if (_spellFocusInfo.Delay)
856 {
857 if (_spellFocusInfo.Delay <= diff)
859 else
860 _spellFocusInfo.Delay -= diff;
861 }
862
863 // periodic check to see if the creature has passed an evade boundary
864 if (IsAIEnabled() && !IsInEvadeMode() && IsEngaged())
865 {
866 if (diff >= m_boundaryCheckTime)
867 {
868 AI()->CheckInRoom();
869 m_boundaryCheckTime = 2500;
870 } else
871 m_boundaryCheckTime -= diff;
872 }
873
874 Unit::AIUpdateTick(diff);
875
877
878 // creature can be dead after UpdateAI call
879 // CORPSE/DEAD state will processed at next tick (in other case death timer will be updated unexpectedly)
880 if (!IsAlive())
881 break;
882
883 if (m_regenTimer > 0)
884 {
885 if (diff >= m_regenTimer)
886 m_regenTimer = 0;
887 else
888 m_regenTimer -= diff;
889 }
890
891 if (m_regenTimer == 0)
892 {
893 if (!IsInEvadeMode())
894 {
895 // regenerate health if not in combat or if polymorphed)
896 if (!IsEngaged() || IsPolymorphed())
898 else if (CanNotReachTarget())
899 {
900 // regenerate health if cannot reach the target and the setting is set to do so.
901 // this allows to disable the health regen of raid bosses if pathfinding has issues for whatever reason
902 if (sWorld->getBoolConfig(CONFIG_REGEN_HP_CANNOT_REACH_TARGET_IN_RAID) || !GetMap()->IsRaid())
903 {
905 TC_LOG_DEBUG("entities.unit.chase", "RegenerateHealth() enabled because Creature cannot reach the target. Detail: {}", GetDebugInfo());
906 }
907 else
908 TC_LOG_DEBUG("entities.unit.chase", "RegenerateHealth() disabled even if the Creature cannot reach the target. Detail: {}", GetDebugInfo());
909 }
910 }
911
912 if (GetPowerType() == POWER_ENERGY)
914 else
916
918 }
919
920 if (CanNotReachTarget() && !IsInEvadeMode() && !GetMap()->IsRaid())
921 {
922 m_cannotReachTimer += diff;
924 if (CreatureAI* ai = AI())
925 ai->EnterEvadeMode(EvadeReason::NoPath);
926 }
927 break;
928 }
929 default:
930 break;
931 }
932}
933
935{
937
938 // Creatures with CREATURE_STATIC_FLAG_2_FORCE_PARTY_MEMBERS_INTO_COMBAT periodically force party members into combat
940
941 // creatures should only attack surroundings initially after heartbeat has passed or until attacked
943 {
945
946 // trigger MoveInLineOfSight
948 Cell::VisitAllObjects(this, notifier, GetVisibilityRange());
949 }
950}
951
953{
954 uint32 curValue = GetPower(power);
955 uint32 maxValue = GetMaxPower(power);
956
958 return;
959
960 if (curValue >= maxValue)
961 return;
962
963 float addvalue = 0.0f;
964
965 switch (power)
966 {
967 case POWER_FOCUS:
968 {
969 // For hunter pets.
970 addvalue = 24 * sWorld->getRate(RATE_POWER_FOCUS);
971 break;
972 }
973 case POWER_ENERGY:
974 {
975 // For deathknight's ghoul.
976 addvalue = 20;
977 break;
978 }
979 case POWER_MANA:
980 {
981 // Combat and any controlled creature
982 if (IsInCombat() || GetCharmerOrOwnerGUID().IsEmpty())
983 {
984 float ManaIncreaseRate = sWorld->getRate(RATE_POWER_MANA);
985
986 addvalue = uint32((27.0f / 5.0f + 17.0f) * ManaIncreaseRate);
987 }
988 else
989 addvalue = maxValue / 3;
990
991 break;
992 }
993 default:
994 return;
995 }
996
997 // Apply modifiers (if any).
999
1001
1002 ModifyPower(power, int32(addvalue));
1003}
1004
1006{
1007 if (!CanRegenerateHealth())
1008 return;
1009
1010 uint32 curValue = GetHealth();
1011 uint32 maxValue = GetMaxHealth();
1012
1013 if (curValue >= maxValue)
1014 return;
1015
1016 uint32 addvalue = 0;
1017
1018 // Not only pet, but any controlled creature (and not polymorphed)
1019 if (!GetCharmerOrOwnerGUID().IsEmpty() && !IsPolymorphed())
1020 {
1021 float HealthIncreaseRate = sWorld->getRate(RATE_HEALTH);
1022
1023 addvalue = 0.015f * ((float)GetMaxHealth()) * HealthIncreaseRate;
1024 }
1025 else
1026 addvalue = maxValue/3;
1027
1028 // Apply modifiers (if any).
1030
1032
1033 ModifyHealth(addvalue);
1034}
1035
1037{
1038 if (!GetVictim())
1039 return;
1040
1042 return;
1043
1044 float radius = sWorld->getFloatConfig(CONFIG_CREATURE_FAMILY_FLEE_ASSISTANCE_RADIUS);
1045 if (radius >0)
1046 {
1047 Creature* creature = nullptr;
1050 Cell::VisitGridObjects(this, searcher, radius);
1051
1053
1054 if (!creature)
1057 else
1058 GetMotionMaster()->MoveSeekAssistance(creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ());
1059 }
1060}
1061
1063{
1064 PopAI();
1065 RefreshAI();
1066 return true;
1067}
1068
1069bool Creature::AIM_Create(CreatureAI* ai /*= nullptr*/)
1070{
1072
1073 SetAI(ai ? ai : FactorySelector::SelectAI(this));
1074
1075 return true;
1076}
1077
1079{
1080 if (!AIM_Create(ai))
1081 return false;
1082
1083 AI()->InitializeAI();
1084 if (GetVehicleKit())
1085 GetVehicleKit()->Reset();
1086 return true;
1087}
1088
1090{
1091 if (m_formation)
1092 {
1093 if (m_formation->GetLeader() == this)
1095 else if (m_formation->IsFormed())
1096 {
1097 GetMotionMaster()->MoveIdle(); // wait the order of leader
1098 return;
1099 }
1100 }
1101
1103}
1104
1105bool Creature::Create(ObjectGuid::LowType guidlow, Map* map, uint32 entry, Position const& pos, CreatureData const* data /*= nullptr*/, uint32 vehId /*= 0*/, bool dynamic)
1106{
1107 ASSERT(map);
1108 SetMap(map);
1109
1110 if (data)
1111 {
1114 }
1115
1116 // Set if this creature can handle dynamic spawns
1117 if (!dynamic)
1119
1120 CreatureTemplate const* cinfo = sObjectMgr->GetCreatureTemplate(entry);
1121 if (!cinfo)
1122 {
1123 TC_LOG_ERROR("sql.sql", "Creature::Create(): creature template (guidlow: {}, entry: {}) does not exist.", guidlow, entry);
1124 return false;
1125 }
1126
1127 CreatureDifficulty const* creatureDifficulty = cinfo->GetDifficulty(GetMap()->GetDifficultyID());
1128
1131 Relocate(pos);
1132
1133 // Check if the position is valid before calling CreateFromProto(), otherwise we might add Auras to Creatures at
1134 // invalid position, triggering a crash about Auras not removed in the destructor
1135 if (!IsPositionValid())
1136 {
1137 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());
1138 return false;
1139 }
1140 {
1141 // area/zone id is needed immediately for ZoneScript::GetCreatureEntry hook before it is known which creature template to load (no model/scale available yet)
1142 PositionFullTerrainStatus terrainStatus;
1144 ProcessPositionDataChanged(terrainStatus);
1145 }
1146
1147 // Allow players to see those units while dead, do it here (mayby altered by addon auras)
1148 if (creatureDifficulty->TypeFlags & CREATURE_TYPE_FLAG_VISIBLE_TO_GHOSTS)
1150
1151 if (!CreateFromProto(guidlow, entry, data, vehId))
1152 return false;
1153
1154 cinfo = GetCreatureTemplate(); // might be different than initially requested
1156 m_respawnDelay = 0; // special value, prevents respawn for dungeon bosses unless overridden
1157
1158 switch (GetCreatureClassification())
1159 {
1162 break;
1165 break;
1168 break;
1171 break;
1174 break;
1177 break;
1178 default:
1180 break;
1181 }
1182
1185
1188
1190
1192 {
1195 }
1196
1199
1201 {
1204 }
1205
1207
1208 return true;
1209}
1210
1211Creature* Creature::CreateCreature(uint32 entry, Map* map, Position const& pos, uint32 vehId /*= 0*/)
1212{
1213 CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(entry);
1214 if (!cInfo)
1215 return nullptr;
1216
1217 ObjectGuid::LowType lowGuid;
1218 if (vehId || cInfo->VehicleId)
1219 lowGuid = map->GenerateLowGuid<HighGuid::Vehicle>();
1220 else
1221 lowGuid = map->GenerateLowGuid<HighGuid::Creature>();
1222
1223 Creature* creature = new Creature();
1224 if (!creature->Create(lowGuid, map, entry, pos, nullptr, vehId))
1225 {
1226 delete creature;
1227 return nullptr;
1228 }
1229
1230 return creature;
1231}
1232
1233Creature* Creature::CreateCreatureFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap /*= true*/, bool allowDuplicate /*= false*/)
1234{
1235 Creature* creature = new Creature();
1236 if (!creature->LoadFromDB(spawnId, map, addToMap, allowDuplicate))
1237 {
1238 delete creature;
1239 return nullptr;
1240 }
1241
1242 return creature;
1243}
1244
1246{
1247 Unit* target = nullptr;
1248
1249 if (CanHaveThreatList())
1251 else if (!HasReactState(REACT_PASSIVE))
1252 {
1253 // We're a player pet, probably
1254 target = getAttackerForHelper();
1255 if (!target && IsSummon())
1256 {
1257 if (Unit* owner = ToTempSummon()->GetOwner())
1258 {
1259 if (owner->IsInCombat())
1260 target = owner->getAttackerForHelper();
1261 if (!target)
1262 {
1263 for (ControlList::const_iterator itr = owner->m_Controlled.begin(); itr != owner->m_Controlled.end(); ++itr)
1264 {
1265 if ((*itr)->IsInCombat())
1266 {
1267 target = (*itr)->getAttackerForHelper();
1268 if (target)
1269 break;
1270 }
1271 }
1272 }
1273 }
1274 }
1275 }
1276 else
1277 return nullptr;
1278
1279 if (target && _IsTargetAcceptable(target) && CanCreatureAttack(target))
1280 {
1281 if (!HasSpellFocus())
1282 SetInFront(target);
1283 return target;
1284 }
1285
1287 if (GetVehicle())
1288 return nullptr;
1289
1291 if (!iAuras.empty())
1292 {
1293 for (Unit::AuraEffectList::const_iterator itr = iAuras.begin(); itr != iAuras.end(); ++itr)
1294 {
1295 if ((*itr)->GetBase()->IsPermanent())
1296 {
1298 break;
1299 }
1300 }
1301 return nullptr;
1302 }
1303
1304 // enter in evade mode in other case
1306
1307 return nullptr;
1308}
1309
1311{
1314 /*
1315 else if (IsCivilian())
1316 SetReactState(REACT_DEFENSIVE);
1317 */
1318 else
1320}
1321
1323{
1324 if (!IsBattleMaster())
1325 return false;
1326
1327 BattlegroundTypeId bgTypeId = sBattlegroundMgr->GetBattleMasterBG(GetEntry());
1328 if (!msg)
1329 return player->GetBGAccessByLevel(bgTypeId);
1330
1331 if (!player->GetBGAccessByLevel(bgTypeId))
1332 {
1333 ClearGossipMenuFor(player);
1334 switch (bgTypeId)
1335 {
1336 case BATTLEGROUND_AV: SendGossipMenuFor(player, 7616, this); break;
1337 case BATTLEGROUND_WS: SendGossipMenuFor(player, 7599, this); break;
1338 case BATTLEGROUND_AB: SendGossipMenuFor(player, 7642, this); break;
1339 case BATTLEGROUND_EY:
1340 case BATTLEGROUND_NA:
1341 case BATTLEGROUND_BE:
1342 case BATTLEGROUND_AA:
1343 case BATTLEGROUND_RL:
1344 case BATTLEGROUND_SA:
1345 case BATTLEGROUND_DS:
1346 case BATTLEGROUND_RV: SendGossipMenuFor(player, 10024, this); break;
1347 default: break;
1348 }
1349 return false;
1350 }
1351 return true;
1352}
1353
1355{
1356 return player->GetLevel() >= 15
1357 && player->GetClass() == GetCreatureTemplate()->trainer_class;
1358}
1359
1361{
1362 if (m_lootId)
1363 return *m_lootId;
1364
1365 return GetCreatureDifficulty()->LootID;
1366}
1367
1369{
1370 m_lootId = lootId;
1371}
1372
1373void Creature::SetTappedBy(Unit const* unit, bool withGroup)
1374{
1375 // set the player whose group should receive the right
1376 // to loot the creature after it dies
1377 // should be set to nullptr after the loot disappears
1378
1379 if (!unit)
1380 {
1381 m_tapList.clear();
1383 return;
1384 }
1385
1387 return;
1388
1389 if (unit->GetTypeId() != TYPEID_PLAYER && !unit->IsVehicle())
1390 return;
1391
1393 if (!player) // normal creature, no player involved
1394 return;
1395
1396 m_tapList.insert(player->GetGUID());
1397 if (withGroup)
1398 if (Group const* group = player->GetGroup())
1399 for (GroupReference const& itr : group->GetMembers())
1400 if (GetMap()->IsRaid() || group->SameSubGroup(player, itr.GetSource()))
1401 m_tapList.insert(itr.GetSource()->GetGUID());
1402
1405}
1406
1408{
1409 // only temporary summons are allowed to not clear their tap list
1410 if (!m_spawnId)
1411 m_dontClearTapListOnEvade = dontClear;
1412}
1413
1414// return true if this creature is tapped by the player or by a member of his group.
1415bool Creature::isTappedBy(Player const* player) const
1416{
1417 return m_tapList.find(player->GetGUID()) != m_tapList.end();
1418}
1419
1421{
1422 if (m_personalLoot.empty())
1423 return m_loot.get();
1424
1426 return loot;
1427
1428 return nullptr;
1429}
1430
1432{
1433 if (m_loot && !m_loot->isLooted())
1434 return false;
1435
1436 for (auto const& [_, loot] : m_personalLoot)
1437 if (!loot->isLooted())
1438 return false;
1439
1440 return true;
1441}
1442
1443bool Creature::IsSkinnedBy(Player const* player) const
1444{
1445 if (Loot* loot = GetLootForPlayer(player))
1446 return loot->loot_type == LOOT_SKINNING;
1447
1448 return false;
1449}
1450
1452{
1453 // this should only be used when the creature has already been loaded
1454 // preferably after adding to map, because mapid may not be valid otherwise
1455 CreatureData const* data = sObjectMgr->GetCreatureData(m_spawnId);
1456 if (!data)
1457 {
1458 TC_LOG_ERROR("entities.unit", "Creature::SaveToDB failed, cannot get creature data!");
1459 return;
1460 }
1461
1462 uint32 mapId = GetMapId();
1463 if (TransportBase* transport = GetTransport())
1464 if (transport->GetMapIdForSpawning() >= 0)
1465 mapId = transport->GetMapIdForSpawning();
1466
1467 SaveToDB(mapId, data->spawnDifficulties);
1468}
1469
1470void Creature::SaveToDB(uint32 mapid, std::vector<Difficulty> const& spawnDifficulties)
1471{
1472 // update in loaded data
1473 if (!m_spawnId)
1474 m_spawnId = sObjectMgr->GenerateCreatureSpawnId();
1475
1476 CreatureData& data = sObjectMgr->NewOrExistCreatureData(m_spawnId);
1477
1478 uint32 displayId = GetNativeDisplayId();
1479 uint64 spawnNpcFlags = (uint64(GetNpcFlags2()) << 32) | GetNpcFlags();
1480 Optional<uint64> npcflag;
1481 Optional<uint32> unitFlags;
1482 Optional<uint32> unitFlags2;
1483 Optional<uint32> unitFlags3;
1484
1485 // check if it's a custom model and if not, use 0 for displayId
1486 CreatureTemplate const* cinfo = GetCreatureTemplate();
1487 if (cinfo)
1488 {
1489 for (CreatureModel const& model : cinfo->Models)
1490 if (displayId && displayId == model.CreatureDisplayID)
1491 displayId = 0;
1492
1493 if (spawnNpcFlags != cinfo->npcflag)
1494 npcflag = spawnNpcFlags;
1495
1496 if (m_unitData->Flags != cinfo->unit_flags)
1497 unitFlags = m_unitData->Flags;
1498
1499 if (m_unitData->Flags2 != cinfo->unit_flags2)
1500 unitFlags2 = m_unitData->Flags2;
1501
1502 if (m_unitData->Flags3 != cinfo->unit_flags3)
1503 unitFlags3 = m_unitData->Flags3;
1504 }
1505
1506 if (!data.spawnId)
1507 data.spawnId = m_spawnId;
1508 ASSERT(data.spawnId == m_spawnId);
1509 data.id = GetEntry();
1510 if (displayId)
1511 data.display.emplace(displayId, DEFAULT_PLAYER_DISPLAY_SCALE, 1.0f);
1512 else
1513 data.display.reset();
1515 if (!GetTransport())
1516 {
1517 data.mapId = GetMapId();
1518 data.spawnPoint.Relocate(this);
1519 }
1520 else
1521 {
1522 data.mapId = mapid;
1524 }
1526 // prevent add data integrity problems
1528 data.currentwaypoint = 0;
1530 // prevent add data integrity problems
1533 data.spawnDifficulties = spawnDifficulties;
1534 data.npcflag = npcflag;
1535 data.unit_flags = unitFlags;
1536 data.unit_flags2 = unitFlags2;
1537 data.unit_flags3 = unitFlags3;
1538 if (!data.spawnGroupData)
1539 data.spawnGroupData = sObjectMgr->GetDefaultSpawnGroup();
1540
1541 data.phaseId = GetDBPhase() > 0 ? GetDBPhase() : data.phaseId;
1542 data.phaseGroup = GetDBPhase() < 0 ? -GetDBPhase() : data.phaseGroup;
1543
1544 // update in DB
1545 WorldDatabaseTransaction trans = WorldDatabase.BeginTransaction();
1546
1548 stmt->setUInt64(0, m_spawnId);
1549 trans->Append(stmt);
1550
1551 uint8 index = 0;
1552
1553 stmt = WorldDatabase.GetPreparedStatement(WORLD_INS_CREATURE);
1554 stmt->setUInt64(index++, m_spawnId);
1555 stmt->setUInt32(index++, GetEntry());
1556 stmt->setUInt16(index++, uint16(mapid));
1557 stmt->setString(index++, [&data]() -> std::string
1558 {
1559 std::ostringstream os;
1560 if (!data.spawnDifficulties.empty())
1561 {
1562 auto itr = data.spawnDifficulties.begin();
1563 os << int32(*itr++);
1564
1565 for (; itr != data.spawnDifficulties.end(); ++itr)
1566 os << ',' << int32(*itr);
1567 }
1568
1569 return std::move(os).str();
1570 }());
1571 stmt->setUInt8(index++, data.phaseUseFlags);
1572 stmt->setUInt32(index++, data.phaseId);
1573 stmt->setUInt32(index++, data.phaseGroup);
1574 stmt->setInt32(index++, data.terrainSwapMap);
1575 stmt->setUInt32(index++, displayId);
1576 stmt->setUInt8(index++, GetCurrentEquipmentId());
1577 stmt->setFloat(index++, GetPositionX());
1578 stmt->setFloat(index++, GetPositionY());
1579 stmt->setFloat(index++, GetPositionZ());
1580 stmt->setFloat(index++, GetOrientation());
1581 stmt->setUInt32(index++, m_respawnDelay);
1582 stmt->setFloat(index++, m_wanderDistance);
1583 stmt->setUInt32(index++, 0);
1584 stmt->setUInt32(index++, uint32(GetHealthPct()));
1585 stmt->setUInt8(index++, uint8(GetDefaultMovementType()));
1586 if (npcflag.has_value())
1587 stmt->setUInt64(index++, *npcflag);
1588 else
1589 stmt->setNull(index++);
1590
1591 if (unitFlags.has_value())
1592 stmt->setUInt32(index++, *unitFlags);
1593 else
1594 stmt->setNull(index++);
1595
1596 if (unitFlags2.has_value())
1597 stmt->setUInt32(index++, *unitFlags2);
1598 else
1599 stmt->setNull(index++);
1600
1601 if (unitFlags3.has_value())
1602 stmt->setUInt32(index++, *unitFlags3);
1603 else
1604 stmt->setNull(index++);
1605
1606 stmt->setString(index++, sObjectMgr->GetScriptName(data.scriptId));
1607 if (std::string_view stringId = GetStringId(StringIdType::Spawn); !stringId.empty())
1608 stmt->setString(index++, stringId);
1609 else
1610 stmt->setNull(index++);
1611
1612 trans->Append(stmt);
1613
1614 WorldDatabase.CommitTransaction(trans);
1615}
1616
1618{
1619 // Level
1621 int32 levelWithDelta = m_unitData->ScalingLevelMax + m_unitData->ScalingLevelDelta;
1622 uint8 level = RoundToInterval<int32>(levelWithDelta, 1, STRONG_MAX_LEVEL);
1623 SetLevel(level);
1624
1626}
1627
1629{
1630 CreatureTemplate const* cInfo = GetCreatureTemplate();
1632 uint8 level = GetLevel();
1633 CreatureBaseStats const* stats = sObjectMgr->GetCreatureBaseStats(level, cInfo->unit_class);
1634
1635 // health
1636 float healthmod = GetHealthMod(classification);
1637
1638 uint32 basehp = GetMaxHealthByLevel(level);
1639 uint32 health = uint32(basehp * healthmod);
1640
1641 SetCreateHealth(health);
1642 SetMaxHealth(health);
1643 SetHealth(health);
1645
1647
1648 // mana
1649 Powers powerType = CalculateDisplayPowerType();
1650 SetCreateMana(stats->BaseMana);
1652 SetPowerType(powerType, true, true);
1653
1654 // damage
1655 float basedamage = GetBaseDamageForLevel(level);
1656
1657 float weaponBaseMinDamage = basedamage;
1658 float weaponBaseMaxDamage = basedamage * 1.5f;
1659
1660 SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, weaponBaseMinDamage);
1661 SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, weaponBaseMaxDamage);
1662
1663 SetBaseWeaponDamage(OFF_ATTACK, MINDAMAGE, weaponBaseMinDamage);
1664 SetBaseWeaponDamage(OFF_ATTACK, MAXDAMAGE, weaponBaseMaxDamage);
1665
1666 SetBaseWeaponDamage(RANGED_ATTACK, MINDAMAGE, weaponBaseMinDamage);
1667 SetBaseWeaponDamage(RANGED_ATTACK, MAXDAMAGE, weaponBaseMaxDamage);
1668
1671
1672 float armor = GetBaseArmorForLevel(level);
1674}
1675
1677{
1678 if (IsWildBattlePet())
1679 {
1680 uint8 wildBattlePetLevel = WILD_BATTLE_PET_DEFAULT_LEVEL;
1681
1682 if (AreaTableEntry const* areaTable = sAreaTableStore.LookupEntry(GetZoneId()))
1683 if (areaTable->WildBattlePetLevelMin > 0)
1684 wildBattlePetLevel = urand(areaTable->WildBattlePetLevelMin, areaTable->WildBattlePetLevelMax);
1685
1686 SetWildBattlePetLevel(wildBattlePetLevel);
1687 }
1688}
1689
1691{
1692 switch (classification)
1693 {
1695 return sWorld->getRate(RATE_CREATURE_HP_NORMAL);
1697 return sWorld->getRate(RATE_CREATURE_HP_ELITE);
1699 return sWorld->getRate(RATE_CREATURE_HP_RAREELITE);
1701 return sWorld->getRate(RATE_CREATURE_HP_OBSOLETE);
1703 return sWorld->getRate(RATE_CREATURE_HP_RARE);
1705 return sWorld->getRate(RATE_CREATURE_HP_TRIVIAL);
1707 return sWorld->getRate(RATE_CREATURE_HP_MINUSMOB);
1708 default:
1709 return sWorld->getRate(RATE_CREATURE_HP_ELITE);
1710 }
1711}
1712
1714{
1716 m_PlayerDamageReq > unDamage ? m_PlayerDamageReq -= unDamage : m_PlayerDamageReq = 0;
1717}
1718
1720{
1721 switch (classification)
1722 {
1724 return sWorld->getRate(RATE_CREATURE_DAMAGE_NORMAL);
1726 return sWorld->getRate(RATE_CREATURE_DAMAGE_ELITE);
1728 return sWorld->getRate(RATE_CREATURE_DAMAGE_RAREELITE);
1730 return sWorld->getRate(RATE_CREATURE_DAMAGE_OBSOLETE);
1732 return sWorld->getRate(RATE_CREATURE_DAMAGE_RARE);
1734 return sWorld->getRate(RATE_CREATURE_DAMAGE_TRIVIAL);
1736 return sWorld->getRate(RATE_CREATURE_DAMAGE_MINUSMOB);
1737 default:
1738 return sWorld->getRate(RATE_CREATURE_DAMAGE_ELITE);
1739 }
1740}
1741
1764
1765void Creature::OverrideSparringHealthPct(std::vector<float> const& healthPct)
1766{
1768}
1769
1771{
1772 if (GetSparringHealthPct() == 0)
1773 return damage;
1774
1775 if (!attacker)
1776 return damage;
1777
1779 return damage;
1780
1782 return 0;
1783
1784 uint32 sparringHealth = GetMaxHealth() * GetSparringHealthPct() / 100;
1785 if (GetHealth() - damage <= sparringHealth)
1786 return GetHealth() - sparringHealth;
1787
1788 if (damage >= GetHealth())
1789 return GetHealth() - 1;
1790
1791 return damage;
1792}
1793
1795{
1796 if (!GetSparringHealthPct())
1797 return false;
1798
1799 if (!attacker)
1800 return false;
1801
1802 if (!attacker->IsCreature())
1803 return false;
1804
1806 return false;
1807
1809 return false;
1810
1811 return true;
1812}
1813
1814bool Creature::CreateFromProto(ObjectGuid::LowType guidlow, uint32 entry, CreatureData const* data /*= nullptr*/, uint32 vehId /*= 0*/)
1815{
1816 SetZoneScript();
1817 if (GetZoneScript() && data)
1818 {
1819 entry = GetZoneScript()->GetCreatureEntry(guidlow, data);
1820 if (!entry)
1821 return false;
1822 }
1823
1824 CreatureTemplate const* cinfo = sObjectMgr->GetCreatureTemplate(entry);
1825 if (!cinfo)
1826 {
1827 TC_LOG_ERROR("sql.sql", "Creature::CreateFromProto(): creature template (guidlow: {}, entry: {}) does not exist.", guidlow, entry);
1828 return false;
1829 }
1830
1831 SetOriginalEntry(entry);
1832
1833 if (vehId || cinfo->VehicleId)
1834 _Create(ObjectGuid::Create<HighGuid::Vehicle>(GetMapId(), entry, guidlow));
1835 else
1836 _Create(ObjectGuid::Create<HighGuid::Creature>(GetMapId(), entry, guidlow));
1837
1838 if (!UpdateEntry(entry, data))
1839 return false;
1840
1841 if (!vehId)
1842 {
1843 if (GetCreatureTemplate()->VehicleId)
1844 {
1845 vehId = GetCreatureTemplate()->VehicleId;
1846 entry = GetCreatureTemplate()->Entry;
1847 }
1848 else
1849 vehId = cinfo->VehicleId;
1850 }
1851
1852 if (vehId)
1853 if (CreateVehicleKit(vehId, entry, true))
1855
1856 if (!IsPet())
1857 if (uint32 vignetteId = GetCreatureTemplate()->VignetteID)
1858 SetVignette(vignetteId);
1859
1860 return true;
1861}
1862
1863bool Creature::LoadFromDB(ObjectGuid::LowType spawnId, Map* map, bool addToMap, bool allowDuplicate)
1864{
1865 if (!allowDuplicate)
1866 {
1867 // If an alive instance of this spawnId is already found, skip creation
1868 // If only dead instance(s) exist, despawn them and spawn a new (maybe also dead) version
1869 const auto creatureBounds = map->GetCreatureBySpawnIdStore().equal_range(spawnId);
1870 std::vector <Creature*> despawnList;
1871
1872 if (creatureBounds.first != creatureBounds.second)
1873 {
1874 for (auto itr = creatureBounds.first; itr != creatureBounds.second; ++itr)
1875 {
1876 if (itr->second->IsAlive())
1877 {
1878 TC_LOG_DEBUG("maps", "Would have spawned {} but {} already exists", spawnId, creatureBounds.first->second->GetGUID().ToString());
1879 return false;
1880 }
1881 else
1882 {
1883 despawnList.push_back(itr->second);
1884 TC_LOG_DEBUG("maps", "Despawned dead instance of spawn {} ({})", spawnId, itr->second->GetGUID().ToString());
1885 }
1886 }
1887
1888 for (Creature* despawnCreature : despawnList)
1889 {
1890 despawnCreature->AddObjectToRemoveList();
1891 }
1892 }
1893 }
1894
1895 CreatureData const* data = sObjectMgr->GetCreatureData(spawnId);
1896 if (!data)
1897 {
1898 TC_LOG_ERROR("sql.sql", "Creature (SpawnID {}) not found in table `creature`, can't load. ", spawnId);
1899 return false;
1900 }
1901
1902 m_spawnId = spawnId;
1903
1905 m_creatureData = data;
1908
1909 if (!Create(map->GenerateLowGuid<HighGuid::Creature>(), map, data->id, data->spawnPoint, data, 0U , !m_respawnCompatibilityMode))
1910 return false;
1911
1912 //We should set first home position, because then AI calls home movement
1913 SetHomePosition(*this);
1914
1916
1918
1920 {
1922 {
1923 // @todo pools need fixing! this is just a temporary thing, but they violate dynspawn principles
1924 if (!data->poolId)
1925 {
1926 TC_LOG_ERROR("entities.unit", "Creature (SpawnID {}) trying to load in inactive spawn group '{}':\n{}", spawnId, data->spawnGroupData->name, GetDebugInfo());
1927 return false;
1928 }
1929 }
1930
1932 }
1933
1934 if (m_respawnTime)
1935 {
1937 {
1938 // @todo same as above
1939 if (!data->poolId)
1940 {
1941 TC_LOG_ERROR("entities.unit", "Creature (SpawnID {}) trying to load despite a respawn timer in progress:\n{}", spawnId, GetDebugInfo());
1942 return false;
1943 }
1944 }
1945 else
1946 {
1947 // compatibility mode creatures will be respawned in ::Update()
1949 }
1950
1951 if (CanFly())
1952 {
1953 float tz = map->GetHeight(GetPhaseShift(), data->spawnPoint, true, MAX_FALL_DISTANCE);
1954 if (data->spawnPoint.GetPositionZ() - tz > 0.1f && Trinity::IsValidMapCoord(tz))
1956 }
1957 }
1958
1960
1962
1963 // checked at creature_template loading
1965
1967
1968 if (addToMap && !GetMap()->AddToMap(this))
1969 return false;
1970 return true;
1971}
1972
1978
1979void Creature::LoadEquipment(int8 id, bool force /*= true*/)
1980{
1981 if (id == 0)
1982 {
1983 if (force)
1984 {
1985 for (uint8 i = 0; i < MAX_EQUIPMENT_ITEMS; ++i)
1986 SetVirtualItem(i, 0);
1987 m_equipmentId = 0;
1988 }
1989
1990 return;
1991 }
1992
1993 EquipmentInfo const* einfo = sObjectMgr->GetEquipmentInfo(GetEntry(), id);
1994 if (!einfo)
1995 return;
1996
1997 m_equipmentId = id;
1998 for (uint8 i = 0; i < MAX_EQUIPMENT_ITEMS; ++i)
1999 SetVirtualItem(i, einfo->Items[i].ItemId, einfo->Items[i].AppearanceModId, einfo->Items[i].ItemVisual);
2000}
2001
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(GetCreatureTemplate()->RequiredExpansion));
2177 int32 playerLevel = player->GetLevelForTarget(this);
2178 int32 creatureLevel = GetLevelForTarget(player);
2179 int32 levelDifference = creatureLevel - playerLevel;
2180
2181 // The aggro radius for creatures with equal level as the player is 20 yards.
2182 // The combatreach should not get taken into account for the distance so we drop it from the range (see Supremus as expample)
2183 float baseAggroDistance = 20.0f - GetCombatReach();
2184
2185 // + - 1 yard for each level difference between player and creature
2186 float aggroRadius = baseAggroDistance + float(levelDifference);
2187
2188 // detect range auras
2189 if (uint32(creatureLevel + 5) <= sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
2190 {
2193 }
2194
2195 // The aggro range of creatures with higher levels than the total player level for the expansion should get the maxlevel treatment
2196 // This makes sure that creatures such as bosses wont have a bigger aggro range than the rest of the npc's
2197 // The following code is used for blizzlike behaviour such as skippable bosses
2198 if (creatureLevel > expansionMaxLevel)
2199 aggroRadius = baseAggroDistance + float(expansionMaxLevel - playerLevel);
2200
2201 // Make sure that we wont go over the total range limits
2202 if (aggroRadius > maxRadius)
2203 aggroRadius = maxRadius;
2204 else if (aggroRadius < minRadius)
2205 aggroRadius = minRadius;
2206
2207 return (aggroRadius * aggroRate);
2208}
2209
2211{
2213
2214 if (s == JUST_DIED)
2215 {
2217
2218 uint32 respawnDelay = m_respawnDelay;
2219 if (uint32 scalingMode = sWorld->getIntConfig(CONFIG_RESPAWN_DYNAMICMODE))
2220 GetMap()->ApplyDynamicModeRespawnScaling(this, m_spawnId, respawnDelay, scalingMode);
2221
2222 // @todo remove the boss respawn time hack in a dynspawn follow-up once we have creature groups in instances
2224 {
2225 if (IsDungeonBoss() && !m_respawnDelay)
2226 m_respawnTime = std::numeric_limits<time_t>::max(); // never respawn in this instance
2227 else
2229 }
2230 else
2231 {
2232 if (IsDungeonBoss() && !m_respawnDelay)
2233 m_respawnTime = std::numeric_limits<time_t>::max(); // never respawn in this instance
2234 else
2235 m_respawnTime = GameTime::GetGameTime() + respawnDelay;
2236 }
2237
2239
2240 ReleaseSpellFocus(nullptr, false); // remove spellcast focus
2241 DoNotReacquireSpellFocusTarget(); // cancel delayed re-target
2242 SetTarget(ObjectGuid::Empty); // drop target - dead mobs shouldn't ever target things
2243
2246
2247 SetMountDisplayId(0); // if creature is mounted on a virtual mount, remove it at death
2248
2249 setActive(false);
2250
2251 SetNoSearchAssistance(false);
2252
2253 //Dismiss group if is leader
2254 if (m_formation)
2255 {
2256 if (m_formation->GetLeader() == this)
2258
2259 if (ZoneScript* script = GetZoneScript())
2261 script->OnCreatureGroupDepleted(m_formation);
2262 }
2263
2264 bool needsFalling = (IsFlying() || IsHovering()) && !IsUnderWater() && !HasUnitState(UNIT_STATE_ROOT);
2265 SetHover(false, false);
2266 SetDisableGravity(false, false);
2267
2268 if (needsFalling)
2270
2272 }
2273 else if (s == JUST_RESPAWNED)
2274 {
2275 if (IsPet())
2276 SetFullHealth();
2277 else
2279
2280 SetTappedBy(nullptr);
2282
2283 SetCannotReachTarget(false);
2285
2287
2288 if (!IsPet())
2289 {
2291 CreatureTemplate const* cInfo = GetCreatureTemplate();
2292
2293 uint64 npcFlags;
2294 uint32 unitFlags, unitFlags2, unitFlags3;
2295 ObjectMgr::ChooseCreatureFlags(cInfo, &npcFlags, &unitFlags, &unitFlags2, &unitFlags3, _staticFlags, creatureData);
2296
2298 npcFlags |= sGameEventMgr->GetNPCFlag(this);
2299
2300 ReplaceAllNpcFlags(NPCFlags(npcFlags & 0xFFFFFFFF));
2301 ReplaceAllNpcFlags2(NPCFlags2(npcFlags >> 32));
2302
2303 ReplaceAllUnitFlags(UnitFlags(unitFlags));
2304 ReplaceAllUnitFlags2(UnitFlags2(unitFlags2));
2305 ReplaceAllUnitFlags3(UnitFlags3(unitFlags3));
2307
2309
2311
2312 if (uint32 vignetteId = cInfo->VignetteID)
2313 SetVignette(vignetteId);
2314 }
2315
2320 }
2321}
2322
2323void Creature::Respawn(bool force)
2324{
2325 if (force)
2326 {
2327 if (IsAlive())
2329 else if (getDeathState() != CORPSE)
2331 }
2332
2334 {
2336 RemoveCorpse(false, false);
2337
2338 if (getDeathState() == DEAD)
2339 {
2340 TC_LOG_DEBUG("entities.unit", "Respawning creature {} ({})", GetName(), GetGUID().ToString());
2341 m_respawnTime = 0;
2343 m_loot = nullptr;
2344
2345 if (m_originalEntry != GetEntry())
2347
2348 SelectLevel();
2349
2351
2353 if (sObjectMgr->GetCreatureModelRandomGender(&display, GetCreatureTemplate()))
2354 SetDisplayId(display.CreatureDisplayID, true);
2355
2357
2358 // Re-initialize reactstate that could be altered by movementgenerators
2360
2361 if (UnitAI* ai = AI()) // reset the AI to be sure no dirty or uninitialized values will be used till next tick
2362 ai->Reset();
2363
2364 m_triggerJustAppeared = true;
2366
2367 uint32 poolid = GetCreatureData() ? GetCreatureData()->poolId : 0;
2368 if (poolid)
2369 sPoolMgr->UpdatePool<Creature>(GetMap()->GetPoolData(), poolid, GetSpawnId());
2370 }
2372 }
2373 else
2374 {
2375 if (m_spawnId)
2377 }
2378
2379 TC_LOG_DEBUG("entities.unit", "Respawning creature {} ({})",
2380 GetName(), GetGUID().ToString());
2381
2382}
2383
2384void Creature::ForcedDespawn(uint32 timeMSToDespawn, Seconds forceRespawnTimer)
2385{
2386 if (timeMSToDespawn)
2387 {
2388 m_Events.AddEvent(new ForcedDespawnDelayEvent(*this, forceRespawnTimer), m_Events.CalculateTime(Milliseconds(timeMSToDespawn)));
2389 return;
2390 }
2391
2393 {
2394 uint32 corpseDelay = GetCorpseDelay();
2395 uint32 respawnDelay = GetRespawnDelay();
2396
2397 // do it before killing creature
2399
2400 bool overrideRespawnTime = false;
2401 if (IsAlive())
2402 {
2403 if (forceRespawnTimer > Seconds::zero())
2404 {
2405 SetCorpseDelay(0);
2406 SetRespawnDelay(forceRespawnTimer.count());
2407 overrideRespawnTime = true;
2408 }
2409
2411 }
2412
2413 // Skip corpse decay time
2414 RemoveCorpse(!overrideRespawnTime, false);
2415
2416 SetCorpseDelay(corpseDelay);
2417 SetRespawnDelay(respawnDelay);
2418 }
2419 else
2420 {
2421 if (forceRespawnTimer > Seconds::zero())
2422 SaveRespawnTime(forceRespawnTimer.count());
2423 else
2424 {
2425 uint32 respawnDelay = m_respawnDelay;
2426 if (uint32 scalingMode = sWorld->getIntConfig(CONFIG_RESPAWN_DYNAMICMODE))
2427 GetMap()->ApplyDynamicModeRespawnScaling(this, m_spawnId, respawnDelay, scalingMode);
2428 m_respawnTime = GameTime::GetGameTime() + respawnDelay;
2430 }
2431
2433 }
2434}
2435
2436void Creature::DespawnOrUnsummon(Milliseconds timeToDespawn /*= 0s*/, Seconds forceRespawnTimer /*= 0s*/)
2437{
2438 if (TempSummon* summon = ToTempSummon())
2439 summon->UnSummon(timeToDespawn.count());
2440 else
2441 ForcedDespawn(timeToDespawn.count(), forceRespawnTimer);
2442}
2443
2444void Creature::LoadTemplateImmunities(int32 creatureImmunitiesId)
2445{
2446 // uint32 max used for "spell id", the immunity system will not perform SpellInfo checks against invalid spells
2447 // used so we know which immunities were loaded from template
2448 static uint32 constexpr placeholderSpellId = std::numeric_limits<uint32>::max();
2449
2450 auto applyCreatureImmunities = [this](CreatureImmunities const* immunities, bool apply)
2451 {
2452 for (std::size_t i = 0; i < immunities->School.size(); ++i)
2453 if (immunities->School[i])
2454 ApplySpellImmune(placeholderSpellId, IMMUNITY_SCHOOL, 1 << i, apply);
2455
2456 for (std::size_t i = 0; i < immunities->DispelType.size(); ++i)
2457 if (immunities->DispelType[i])
2458 ApplySpellImmune(placeholderSpellId, IMMUNITY_DISPEL, i, apply);
2459
2460 for (std::size_t i = 0; i < immunities->Mechanic.size(); ++i)
2461 if (immunities->Mechanic[i])
2462 ApplySpellImmune(placeholderSpellId, IMMUNITY_MECHANIC, i, apply);
2463
2464 for (SpellEffectName effect : immunities->Effect)
2465 ApplySpellImmune(placeholderSpellId, IMMUNITY_EFFECT, effect, apply);
2466
2467 for (AuraType aura : immunities->Aura)
2468 ApplySpellImmune(placeholderSpellId, IMMUNITY_STATE, aura, apply);
2469
2470 if (immunities->Other != SpellOtherImmunity::None)
2471 ApplySpellImmune(placeholderSpellId, IMMUNITY_OTHER, immunities->Other.AsUnderlyingType(), apply);
2472 };
2473
2474 // unapply template immunities (in case we're updating entry)
2476 applyCreatureImmunities(immunities, false);
2477
2478 // apply new immunities
2479 if (CreatureImmunities const* immunities = SpellMgr::GetCreatureImmunities(creatureImmunitiesId))
2480 {
2481 _creatureImmunitiesId = creatureImmunitiesId;
2482 applyCreatureImmunities(immunities, true);
2483 }
2484 else
2486}
2487
2488bool Creature::IsImmunedToSpellEffect(SpellInfo const* spellInfo, SpellEffectInfo const& spellEffectInfo, WorldObject const* caster,
2489 bool requireImmunityPurgesEffectAttribute /*= false*/) const
2490{
2492 return true;
2493
2494 return Unit::IsImmunedToSpellEffect(spellInfo, spellEffectInfo, caster, requireImmunityPurgesEffectAttribute);
2495}
2496
2498{
2499 if (IsPet())
2500 return false;
2501
2503}
2504
2506{
2507 if (IsPet())
2508 return false;
2509
2510 return (GetCreatureDifficulty()->TypeFlags & CREATURE_TYPE_FLAG_BOSS_MOB) != 0;
2511}
2512
2513// select nearest hostile unit within the given distance (regardless of threat list).
2514Unit* Creature::SelectNearestTarget(float dist, bool playerOnly /* = false */) const
2515{
2516 if (dist == 0.0f)
2518
2519 Unit* target = nullptr;
2520 Trinity::NearestHostileUnitCheck u_check(this, dist, playerOnly);
2522 Cell::VisitAllObjects(this, searcher, dist);
2523 return target;
2524}
2525
2526// select nearest hostile unit within the given attack distance (i.e. distance is ignored if > than ATTACK_DISTANCE), regardless of threat list.
2528{
2529 if (dist > MAX_VISIBILITY_DISTANCE)
2530 {
2531 TC_LOG_ERROR("entities.unit", "Creature {} SelectNearestTargetInAttackDistance called with dist > MAX_VISIBILITY_DISTANCE. Distance set to ATTACK_DISTANCE.", GetGUID().ToString());
2532 dist = ATTACK_DISTANCE;
2533 }
2534
2535 Unit* target = nullptr;
2538 Cell::VisitAllObjects(this, searcher, std::max(dist, ATTACK_DISTANCE));
2539 return target;
2540}
2541
2543{
2545
2546 packet.UnitGUID = GetGUID();
2547 packet.Reaction = reactionType;
2548
2549 SendMessageToSet(packet.Write(), true);
2550
2551 TC_LOG_DEBUG("network", "WORLD: Sent SMSG_AI_REACTION, type {}.", reactionType);
2552}
2553
2555{
2556 if (!m_AlreadyCallAssistance && GetVictim() && !IsPet() && !IsCharmed())
2557 {
2558 SetNoCallAssistance(true);
2559
2560 float radius = sWorld->getFloatConfig(CONFIG_CREATURE_FAMILY_ASSISTANCE_RADIUS);
2561
2562 if (radius > 0)
2563 {
2564 std::list<Creature*> assistList;
2565 Trinity::AnyAssistCreatureInRangeCheck u_check(this, GetVictim(), radius);
2567 Cell::VisitGridObjects(this, searcher, radius);
2568
2569 if (!assistList.empty())
2570 {
2572 while (!assistList.empty())
2573 {
2574 // Pushing guids because in delay can happen some creature gets despawned => invalid pointer
2575 e->AddAssistant((*assistList.begin())->GetGUID());
2576 assistList.pop_front();
2577 }
2579 }
2580 }
2581 }
2582}
2583
2584void Creature::CallForHelp(float radius)
2585{
2586 if (radius <= 0.0f || !IsEngaged() || !IsAlive() || IsPet() || IsCharmed())
2587 return;
2588
2590 if (!target)
2591 target = GetThreatManager().GetAnyTarget();
2592 if (!target)
2593 target = GetCombatManager().GetAnyTarget();
2594
2595 if (!target)
2596 {
2597 TC_LOG_ERROR("entities.unit", "Creature {} ({}) trying to call for help without being in combat.", GetEntry(), GetName());
2598 return;
2599 }
2600
2601 Trinity::CallOfHelpCreatureInRangeDo u_do(this, target, radius);
2603 Cell::VisitGridObjects(this, worker, radius);
2604}
2605
2606bool Creature::CanAssistTo(Unit const* u, Unit const* enemy, bool checkfaction /*= true*/) const
2607{
2608 // is it true?
2610 return false;
2611
2612 // we don't need help from zombies :)
2613 if (!IsAlive())
2614 return false;
2615
2616 // we cannot assist in evade mode
2617 if (IsInEvadeMode())
2618 return false;
2619
2620 // or if enemy is in evade mode
2621 if (enemy->GetTypeId() == TYPEID_UNIT && enemy->ToCreature()->IsInEvadeMode())
2622 return false;
2623
2624 // we don't need help from non-combatant ;)
2625 if (IsCivilian())
2626 return false;
2627
2629 return false;
2630
2631 // skip fighting creature
2632 if (IsEngaged())
2633 return false;
2634
2635 // only free creature
2636 if (!GetCharmerOrOwnerGUID().IsEmpty())
2637 return false;
2638
2639 // only from same creature faction
2640 if (checkfaction)
2641 {
2642 if (GetFaction() != u->GetFaction())
2643 return false;
2644 }
2645 else
2646 {
2647 if (!IsFriendlyTo(u))
2648 return false;
2649 }
2650
2651 // skip non hostile to caster enemy creatures
2652 if (!IsHostileTo(enemy))
2653 return false;
2654
2655 return true;
2656}
2657
2658// use this function to avoid having hostile creatures attack
2659// friendlies and other mobs they shouldn't attack
2660bool Creature::_IsTargetAcceptable(Unit const* target) const
2661{
2662 ASSERT(target);
2663
2664 // if the target cannot be attacked, the target is not acceptable
2665 if (IsFriendlyTo(target)
2666 || !target->isTargetableForAttack(false)
2667 || (m_vehicle && (IsOnVehicle(target) || m_vehicle->GetBase()->IsOnVehicle(target))))
2668 return false;
2669
2670 if (target->HasUnitState(UNIT_STATE_DIED))
2671 {
2672 // some creatures can detect fake death
2674 return true;
2675 else
2676 return false;
2677 }
2678
2679 // if I'm already fighting target, or I'm hostile towards the target, the target is acceptable
2680 if (IsEngagedBy(target) || IsHostileTo(target))
2681 return true;
2682
2683 // if the target's victim is not friendly, or the target is friendly, the target is not acceptable
2684 return false;
2685}
2686
2688{
2690 return;
2691
2693 {
2694 RespawnInfo ri;
2696 ri.spawnId = m_spawnId;
2699 return;
2700 }
2701
2702 time_t thisRespawnTime = forceDelay ? GameTime::GetGameTime() + forceDelay : m_respawnTime;
2704}
2705
2706// this should not be called by petAI or
2707bool Creature::CanCreatureAttack(Unit const* victim, bool /*force*/) const
2708{
2709 if (!victim->IsInMap(this))
2710 return false;
2711
2712 if (!IsValidAttackTarget(victim))
2713 return false;
2714
2715 if (!victim->isInAccessiblePlaceFor(this))
2716 return false;
2717
2718 if (CreatureAI* ai = AI())
2719 if (!ai->CanAIAttack(victim))
2720 return false;
2721
2722 // we cannot attack in evade mode
2723 if (IsInEvadeMode())
2724 return false;
2725
2726 // or if enemy is in evade mode
2727 if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsInEvadeMode())
2728 return false;
2729
2731 {
2732 if (GetMap()->IsDungeon())
2733 return true;
2734
2735 // don't check distance to home position if recently damaged, this should include taunt auras
2737 return true;
2738 }
2739
2740 // Map visibility range, but no more than 2*cell size
2741 float dist = std::min<float>(GetMap()->GetVisibilityRange(), SIZE_OF_GRID_CELL * 2);
2742
2743 if (Unit* unit = GetCharmerOrOwner())
2744 return victim->IsWithinDist(unit, dist);
2745 else
2746 {
2747 // include sizes for huge npcs
2748 dist += GetCombatReach() + victim->GetCombatReach();
2749
2750 // to prevent creatures in air ignore attacks because distance is already too high...
2751 if (CanFly())
2752 return victim->IsInDist2d(&m_homePosition, dist);
2753 else
2754 return victim->IsInDist(&m_homePosition, dist);
2755 }
2756}
2757
2759{
2760 if (m_spawnId)
2761 {
2762 if (CreatureAddon const* addon = sObjectMgr->GetCreatureAddon(m_spawnId))
2763 return addon;
2764 }
2765
2766 return sObjectMgr->GetCreatureTemplateAddon(GetEntry());
2767}
2768
2769//creature_addon table
2771{
2772 CreatureAddon const* creatureAddon = GetCreatureAddon();
2773 if (!creatureAddon)
2774 return false;
2775
2776 if (uint32 mountDisplayId = _defaultMountDisplayIdOverride.value_or(creatureAddon->mount); mountDisplayId != 0)
2777 Mount(mountDisplayId);
2778
2780 ReplaceAllVisFlags(UnitVisFlags(creatureAddon->visFlags));
2781 SetAnimTier(AnimTier(creatureAddon->animTier), false);
2782
2783 SetSheath(SheathState(creatureAddon->sheathState));
2785
2786 // These fields must only be handled by core internals and must not be modified via scripts/DB dat
2789
2790 if (creatureAddon->emote != 0)
2791 SetEmoteState(Emote(creatureAddon->emote));
2792
2793 SetAIAnimKitId(creatureAddon->aiAnimKit);
2794 SetMovementAnimKitId(creatureAddon->movementAnimKit);
2795 SetMeleeAnimKitId(creatureAddon->meleeAnimKit);
2796
2797 // Check if visibility distance different
2800
2801 // Load Path
2802 if (creatureAddon->PathId != 0)
2803 _waypointPathId = creatureAddon->PathId;
2804
2805 if (!creatureAddon->auras.empty())
2806 {
2807 for (std::vector<uint32>::const_iterator itr = creatureAddon->auras.begin(); itr != creatureAddon->auras.end(); ++itr)
2808 {
2809 SpellInfo const* AdditionalSpellInfo = sSpellMgr->GetSpellInfo(*itr, GetMap()->GetDifficultyID());
2810 if (!AdditionalSpellInfo)
2811 {
2812 TC_LOG_ERROR("sql.sql", "Creature {} has wrong spell {} defined in `auras` field.", GetGUID().ToString(), *itr);
2813 continue;
2814 }
2815
2816 // skip already applied aura
2817 if (HasAura(*itr))
2818 continue;
2819
2820 AddAura(*itr, this);
2821 TC_LOG_DEBUG("entities.unit", "Spell: {} added to creature {}", *itr, GetGUID().ToString());
2822 }
2823 }
2824 return true;
2825}
2826
2827void Creature::LoadCreaturesSparringHealth(bool force /*= false*/)
2828{
2829 if (std::vector<float> const* templateValues = sObjectMgr->GetCreatureTemplateSparringValues(GetCreatureTemplate()->Entry))
2830 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)
2832}
2833
2836{
2838 packet.AreaID = GetAreaId();
2839 packet.Write();
2840
2841 Team enemyTeam = attacker->GetTeam();
2842 if (enemyTeam != ALLIANCE)
2843 sWorld->SendGlobalMessage(packet.GetRawPacket(), nullptr, ALLIANCE);
2844 if (enemyTeam != HORDE)
2845 sWorld->SendGlobalMessage(packet.GetRawPacket(), nullptr, HORDE);
2846}
2847
2848void Creature::SetCanMelee(bool canMelee, bool fleeFromMelee /*= false*/)
2849{
2850 bool wasFleeingFromMelee = HasFlag(CREATURE_STATIC_FLAG_NO_MELEE_FLEE);
2851
2852 _staticFlags.ApplyFlag(CREATURE_STATIC_FLAG_NO_MELEE_FLEE, !canMelee && fleeFromMelee);
2854
2855 if (wasFleeingFromMelee == HasFlag(CREATURE_STATIC_FLAG_NO_MELEE_FLEE))
2856 return;
2857
2858 Unit* victim = GetVictim();
2859 if (!victim)
2860 return;
2861
2863 if (!currentMovement)
2864 return;
2865
2866 bool canChangeMovement = [&]
2867 {
2868 if (wasFleeingFromMelee)
2870
2871 return currentMovement->GetMovementGeneratorType() == CHASE_MOTION_TYPE;
2872 }();
2873
2874 if (!canChangeMovement)
2875 return;
2876
2877 GetMotionMaster()->Remove(currentMovement);
2879}
2880
2882{
2884 GetMotionMaster()->MoveChase(victim, range, angle);
2885 else
2886 GetMotionMaster()->MoveFleeing(victim);
2887}
2888
2889bool Creature::HasSpell(uint32 spellID) const
2890{
2891 return std::find(std::begin(m_spells), std::end(m_spells), spellID) != std::end(m_spells);
2892}
2893
2895{
2896 time_t now = GameTime::GetGameTime();
2897 if (m_respawnTime > now)
2898 return m_respawnTime;
2899 else
2900 return now;
2901}
2902
2904{
2905 m_respawnTime = respawn ? GameTime::GetGameTime() + respawn : 0;
2906}
2907
2909{
2910 if (m_creatureData)
2911 {
2912 if (dist)
2914
2915 return m_creatureData->spawnPoint;
2916 }
2917 else
2918 {
2919 if (dist)
2920 *dist = 0;
2921
2922 return GetHomePosition();
2923 }
2924}
2925
2927{
2928 SetHover(GetMovementTemplate().IsHoverInitiallyEnabled());
2931
2932 // If an amphibious creatures was swimming while engaged, disable swimming again
2935
2937}
2938
2940{
2941 // Do not update movement flags if creature is controlled by a player (charm/vehicle)
2942 if (m_playerMovingMe)
2943 return;
2944
2945 // Set the movement flags if the creature is in that mode. (Only fly if actually in air, only swim if in water, etc)
2946 float ground = GetFloorZ();
2947 bool isInAir = (G3D::fuzzyGt(GetPositionZ(), ground + GetHoverOffset() + GROUND_HEIGHT_TOLERANCE) || G3D::fuzzyLt(GetPositionZ(), ground - GROUND_HEIGHT_TOLERANCE)); // Can be underground too, prevent the falling
2948 if (!isInAir)
2950
2951 // Some Amphibious creatures toggle swimming while engaged
2955
2956 SetSwim(IsInWater() && CanSwim());
2957}
2958
2960{
2961 if (CreatureMovementData const* movementOverride = sObjectMgr->GetCreatureMovementOverride(m_spawnId))
2962 return *movementOverride;
2963
2964 return GetCreatureTemplate()->Movement;
2965}
2966
2968{
2969 if (Unit::CanSwim())
2970 return true;
2971
2972 if (IsPet())
2973 return true;
2974
2975 return false;
2976}
2977
2985
2987{
2988 time_t now = GameTime::GetGameTime();
2989 // Do not reset corpse remove time if corpse is already removed
2990 if (m_corpseRemoveTime <= now)
2991 return;
2992
2993 // Scripts can choose to ignore RATE_CORPSE_DECAY_LOOTED by calling SetCorpseDelay(timer, true)
2994 float decayRate = m_ignoreCorpseDecayRatio ? 1.f : sWorld->getRate(RATE_CORPSE_DECAY_LOOTED);
2995
2996 // corpse skinnable, but without skinning flag, and then skinned, corpse will despawn next update
2997 bool isFullySkinned = [&]() -> bool
2998 {
2999 if (m_loot && m_loot->loot_type == LOOT_SKINNING && m_loot->isLooted())
3000 return true;
3001
3002 bool hasSkinningLoot = false;
3003 for (auto const& [_, loot] : m_personalLoot)
3004 {
3005 if (loot->loot_type == LOOT_SKINNING)
3006 {
3007 if (!loot->isLooted())
3008 return false;
3009
3010 hasSkinningLoot = true;
3011 }
3012 }
3013
3014 return hasSkinningLoot;
3015 }();
3016
3017 if (isFullySkinned)
3018 m_corpseRemoveTime = now;
3019 else
3020 m_corpseRemoveTime = now + uint32(m_corpseDelay * decayRate);
3021
3023}
3024
3030
3036
3038{
3040
3041 // If as a result of npcflag updates we stop seeing UNIT_NPC_FLAG_QUESTGIVER then
3042 // we must also send SMSG_QUEST_GIVER_STATUS_MULTIPLE because client will not request it automatically
3043 if (IsQuestGiver())
3044 {
3045 auto sender = [&](Player const* receiver)
3046 {
3047 receiver->PlayerTalkClass->SendQuestGiverStatus(receiver->GetQuestDialogStatus(this), GetGUID());
3048 };
3049 Trinity::MessageDistDeliverer notifier(this, sender, GetVisibilityRange());
3051 }
3052}
3053
3055{
3056 return m_unitData->ContentTuningID != 0;
3057}
3058
3060{
3061 CreatureDifficulty const* creatureDifficulty = GetCreatureDifficulty();
3062
3063 if (Optional<ContentTuningLevels> levels = sDB2Manager.GetContentTuningData(creatureDifficulty->ContentTuningID, {}))
3064 {
3067 }
3068
3069 int32 mindelta = std::min(creatureDifficulty->DeltaLevelMax, creatureDifficulty->DeltaLevelMin);
3070 int32 maxdelta = std::max(creatureDifficulty->DeltaLevelMax, creatureDifficulty->DeltaLevelMin);
3071 int32 delta = mindelta == maxdelta ? mindelta : irand(mindelta, maxdelta);
3072
3075}
3076
3078{
3079 CreatureTemplate const* cInfo = GetCreatureTemplate();
3080 CreatureDifficulty const* creatureDifficulty = GetCreatureDifficulty();
3081 double baseHealth = sDB2Manager.EvaluateExpectedStat(ExpectedStatType::CreatureHealth, level, creatureDifficulty->GetHealthScalingExpansion(), creatureDifficulty->ContentTuningID, Classes(cInfo->unit_class), 0);
3082 return std::max(baseHealth * creatureDifficulty->HealthModifier, 1.0);
3083}
3084
3086{
3087 if (!HasScalableLevels())
3088 return 1.0f;
3089
3090 uint8 levelForTarget = GetLevelForTarget(target);
3091
3092 return double(GetMaxHealthByLevel(levelForTarget)) / double(GetCreateHealth());
3093}
3094
3096{
3097 CreatureTemplate const* cInfo = GetCreatureTemplate();
3098 CreatureDifficulty const* creatureDifficulty = GetCreatureDifficulty();
3099 return sDB2Manager.EvaluateExpectedStat(ExpectedStatType::CreatureAutoAttackDps, level, creatureDifficulty->GetHealthScalingExpansion(), creatureDifficulty->ContentTuningID, Classes(cInfo->unit_class), 0);
3100}
3101
3103{
3104 if (!HasScalableLevels())
3105 return 1.0f;
3106
3107 uint8 levelForTarget = GetLevelForTarget(target);
3108
3109 return GetBaseDamageForLevel(levelForTarget) / GetBaseDamageForLevel(GetLevel());
3110}
3111
3113{
3114 CreatureTemplate const* cInfo = GetCreatureTemplate();
3115 CreatureDifficulty const* creatureDifficulty = GetCreatureDifficulty();
3116 float baseArmor = sDB2Manager.EvaluateExpectedStat(ExpectedStatType::CreatureArmor, level, creatureDifficulty->GetHealthScalingExpansion(), creatureDifficulty->ContentTuningID, Classes(cInfo->unit_class), 0);
3117 return baseArmor * creatureDifficulty->ArmorModifier;
3118}
3119
3121{
3122 if (!HasScalableLevels())
3123 return 1.0f;
3124
3125 uint8 levelForTarget = GetLevelForTarget(target);
3126
3127 return GetBaseArmorForLevel(levelForTarget) / GetBaseArmorForLevel(GetLevel());
3128}
3129
3131{
3132 if (Unit const* unitTarget = target->ToUnit())
3133 {
3134 // If this creature should scale level, adapt level depending of target level
3135 // between UNIT_FIELD_SCALING_LEVEL_MIN and UNIT_FIELD_SCALING_LEVEL_MAX
3136 if (HasScalableLevels())
3137 {
3138 int32 scalingLevelMin = m_unitData->ScalingLevelMin;
3139 int32 scalingLevelMax = m_unitData->ScalingLevelMax;
3140 int32 scalingLevelDelta = m_unitData->ScalingLevelDelta;
3141 uint8 scalingFactionGroup = m_unitData->ScalingFactionGroup;
3142 int32 targetLevel = unitTarget->GetEffectiveLevel();
3143
3144 int32 targetLevelDelta = 0;
3145
3146 if (Player const* playerTarget = target->ToPlayer())
3147 {
3148 if (scalingFactionGroup && sFactionTemplateStore.AssertEntry(sChrRacesStore.AssertEntry(playerTarget->GetRace())->FactionID)->FactionGroup != scalingFactionGroup)
3149 scalingLevelMin = scalingLevelMax;
3150
3151 int32 maxCreatureScalingLevel = playerTarget->m_activePlayerData->MaxCreatureScalingLevel;
3152 targetLevelDelta = std::min(maxCreatureScalingLevel > 0 ? maxCreatureScalingLevel - targetLevel : 0, *playerTarget->m_activePlayerData->ScalingPlayerLevelDelta);
3153 }
3154
3155 int32 levelWithDelta = targetLevel + targetLevelDelta;
3156 int32 level = RoundToInterval(levelWithDelta, scalingLevelMin, scalingLevelMax) + scalingLevelDelta;
3157 return RoundToInterval(level, 1, MAX_LEVEL + 3);
3158 }
3159 }
3160
3161 return Unit::GetLevelForTarget(target);
3162}
3163
3164std::string const& Creature::GetAIName() const
3165{
3166 return sObjectMgr->GetCreatureTemplate(GetEntry())->AIName;
3167}
3168
3169std::string Creature::GetScriptName() const
3170{
3171 return sObjectMgr->GetScriptName(GetScriptId());
3172}
3173
3175{
3177 if (uint32 scriptId = creatureData->scriptId)
3178 return scriptId;
3179
3180 return ASSERT_NOTNULL(sObjectMgr->GetCreatureTemplate(GetEntry()))->ScriptID;
3181}
3182
3184{
3185 // copy references to stringIds from template and spawn
3186 m_stringIds = parent->m_stringIds;
3187
3188 // then copy script stringId, not just its reference
3189 SetScriptStringId(std::string(parent->GetStringId(StringIdType::Script)));
3190}
3191
3192bool Creature::HasStringId(std::string_view id) const
3193{
3194 return std::ranges::any_of(m_stringIds, [id](std::string const* stringId) { return stringId && *stringId == id; });
3195}
3196
3198{
3199 if (!id.empty())
3200 {
3201 m_scriptStringId.emplace(std::move(id));
3203 }
3204 else
3205 {
3206 m_scriptStringId.reset();
3208 }
3209}
3210
3212{
3213 if (!player)
3214 return nullptr;
3215
3216 if (CreatureData const* data = GetCreatureData())
3217 {
3218 if (data->spawnTrackingData && !data->spawnTrackingQuestObjectives.empty())
3219 {
3220 SpawnTrackingState state = player->GetSpawnTrackingStateByObjectives(data->spawnTrackingData->SpawnTrackingId, data->spawnTrackingQuestObjectives);
3221 return &data->spawnTrackingStates[AsUnderlyingType(state)];
3222 }
3223 }
3224
3225 return nullptr;
3226}
3227
3229{
3230 return sObjectMgr->GetNpcVendorItemList(GetEntry());
3231}
3232
3234{
3235 if (!vItem->maxcount)
3236 return vItem->maxcount;
3237
3238 VendorItemCounts::iterator itr = m_vendorItemCounts.begin();
3239 for (; itr != m_vendorItemCounts.end(); ++itr)
3240 if (itr->itemId == vItem->item)
3241 break;
3242
3243 if (itr == m_vendorItemCounts.end())
3244 return vItem->maxcount;
3245
3246 VendorItemCount* vCount = &*itr;
3247
3248 time_t ptime = GameTime::GetGameTime();
3249
3250 if (time_t(vCount->lastIncrementTime + vItem->incrtime) <= ptime)
3251 if (ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(vItem->item))
3252 {
3253 uint32 diff = uint32((ptime - vCount->lastIncrementTime)/vItem->incrtime);
3254 if ((vCount->count + diff * pProto->GetBuyCount()) >= vItem->maxcount)
3255 {
3256 m_vendorItemCounts.erase(itr);
3257 return vItem->maxcount;
3258 }
3259
3260 vCount->count += diff * pProto->GetBuyCount();
3261 vCount->lastIncrementTime = ptime;
3262 }
3263
3264 return vCount->count;
3265}
3266
3268{
3269 if (!vItem->maxcount)
3270 return 0;
3271
3272 VendorItemCounts::iterator itr = m_vendorItemCounts.begin();
3273 for (; itr != m_vendorItemCounts.end(); ++itr)
3274 if (itr->itemId == vItem->item)
3275 break;
3276
3277 if (itr == m_vendorItemCounts.end())
3278 {
3279 uint32 new_count = vItem->maxcount > used_count ? vItem->maxcount-used_count : 0;
3280 m_vendorItemCounts.push_back(VendorItemCount(vItem->item, new_count));
3281 return new_count;
3282 }
3283
3284 VendorItemCount* vCount = &*itr;
3285
3286 time_t ptime = GameTime::GetGameTime();
3287
3288 if (time_t(vCount->lastIncrementTime + vItem->incrtime) <= ptime)
3289 if (ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(vItem->item))
3290 {
3291 uint32 diff = uint32((ptime - vCount->lastIncrementTime)/vItem->incrtime);
3292 if ((vCount->count + diff * pProto->GetBuyCount()) < vItem->maxcount)
3293 vCount->count += diff * pProto->GetBuyCount();
3294 else
3295 vCount->count = vItem->maxcount;
3296 }
3297
3298 vCount->count = vCount->count > used_count ? vCount->count-used_count : 0;
3299 vCount->lastIncrementTime = ptime;
3300 return vCount->count;
3301}
3302
3328
3352
3353// overwrite WorldObject function for proper name localization
3355{
3356 if (locale != DEFAULT_LOCALE)
3357 if (CreatureLocale const* cl = sObjectMgr->GetCreatureLocale(GetEntry()))
3358 if (cl->Name.size() > locale && !cl->Name[locale].empty())
3359 return cl->Name[locale];
3360
3361 return GetName();
3362}
3363
3364bool Creature::HasLabel(int32 cretureLabel) const
3365{
3366 return advstd::ranges::contains(GetLabels(), cretureLabel);
3367}
3368
3369std::span<int32 const> Creature::GetLabels() const
3370{
3371 return sDB2Manager.GetCreatureLabels(GetCreatureDifficulty()->CreatureDifficultyID);
3372}
3373
3375{
3376 return MAX_SPELL_CHARM;
3377}
3378
3380{
3381 if (pos >= MAX_SPELL_CHARM || !m_charmInfo || m_charmInfo->GetCharmSpell(pos)->GetType() != ACT_ENABLED)
3382 return 0;
3383 else
3384 return m_charmInfo->GetCharmSpell(pos)->GetAction();
3385}
3386
3388{
3389 float range = 0.f;
3390
3391 for (uint8 i = 0; i < GetPetAutoSpellSize(); ++i)
3392 {
3393 uint32 spellID = GetPetAutoSpellOnPos(i);
3394 if (!spellID)
3395 continue;
3396
3397 if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID, GetMap()->GetDifficultyID()))
3398 {
3399 if (spellInfo->GetRecoveryTime() == 0 && spellInfo->RangeEntry && spellInfo->RangeEntry->ID != 1 /*Self*/ && spellInfo->RangeEntry->ID != 2 /*Combat Range*/ && spellInfo->GetMaxRange() > range)
3400 range = spellInfo->GetMaxRange();
3401 }
3402 }
3403
3404 return range;
3405}
3406
3408{
3409 if (cannotReach == m_cannotReachTarget)
3410 return;
3411 m_cannotReachTarget = cannotReach;
3413
3414 if (cannotReach)
3415 TC_LOG_DEBUG("entities.unit.chase", "Creature::SetCannotReachTarget() called with true. Details: {}", GetDebugInfo());
3416}
3417
3419{
3420 if (mountCreatureDisplayId && !sCreatureDisplayInfoStore.HasRecord(*mountCreatureDisplayId))
3421 mountCreatureDisplayId.reset();
3422
3423 _defaultMountDisplayIdOverride = mountCreatureDisplayId;
3424}
3425
3426float Creature::GetAggroRange(Unit const* target) const
3427{
3428 // Determines the aggro range for creatures (usually pets), used mainly for aggressive pet target selection.
3429 // Based on data from wowwiki due to lack of 3.3.5a data
3430
3431 if (target && IsPet())
3432 {
3433 uint32 targetLevel = 0;
3434
3435 if (target->GetTypeId() == TYPEID_PLAYER)
3436 targetLevel = target->GetLevelForTarget(this);
3437 else if (target->GetTypeId() == TYPEID_UNIT)
3438 targetLevel = target->ToCreature()->GetLevelForTarget(this);
3439
3440 uint32 myLevel = GetLevelForTarget(target);
3441 int32 levelDiff = int32(targetLevel) - int32(myLevel);
3442
3443 // The maximum Aggro Radius is capped at 45 yards (25 level difference)
3444 if (levelDiff < -25)
3445 levelDiff = -25;
3446
3447 // The base aggro radius for mob of same level
3448 float aggroRadius = 20;
3449
3450 // Aggro Radius varies with level difference at a rate of roughly 1 yard/level
3451 aggroRadius -= (float)levelDiff;
3452
3453 // detect range auras
3455
3456 // detected range auras
3458
3459 // Just in case, we don't want pets running all over the map
3460 if (aggroRadius > MAX_AGGRO_RADIUS)
3461 aggroRadius = MAX_AGGRO_RADIUS;
3462
3463 // Minimum Aggro Radius for a mob seems to be combat range (5 yards)
3464 // hunter pets seem to ignore minimum aggro radius so we'll default it a little higher
3465 if (aggroRadius < 10)
3466 aggroRadius = 10;
3467
3468 return (aggroRadius);
3469 }
3470
3471 // Default
3472 return 0.0f;
3473}
3474
3475Unit* Creature::SelectNearestHostileUnitInAggroRange(bool useLOS, bool ignoreCivilians) const
3476{
3477 // Selects nearest hostile target within creature's aggro range. Used primarily by
3478 // pets set to aggressive. Will not return neutral or friendly targets.
3479
3480 Unit* target = nullptr;
3481
3482 Trinity::NearestHostileUnitInAggroRangeCheck u_check(this, useLOS, ignoreCivilians);
3484
3486
3487 return target;
3488}
3489
3491{
3492 return GetCreatureTemplate()->scale;
3493}
3494
3496{
3497 Unit::SetObjectScale(scale);
3498
3499 if (CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelInfo(GetDisplayId()))
3500 {
3501 SetBoundingRadius((IsPet() ? 1.0f : minfo->bounding_radius) * scale * GetDisplayScale());
3502 SetCombatReach((IsPet() ? DEFAULT_PLAYER_COMBAT_REACH : minfo->combat_reach) * scale * GetDisplayScale());
3503 }
3504}
3505
3506void Creature::SetDisplayId(uint32 displayId, bool setNative /*= false*/)
3507{
3508 Unit::SetDisplayId(displayId, setNative);
3509
3510 if (CreatureModelInfo const* modelInfo = sObjectMgr->GetCreatureModelInfo(displayId))
3511 {
3512 SetBoundingRadius((IsPet() ? 1.0f : modelInfo->bounding_radius) * GetObjectScale() * GetDisplayScale());
3513 SetCombatReach((IsPet() ? DEFAULT_PLAYER_COMBAT_REACH : modelInfo->combat_reach) * GetObjectScale() * GetDisplayScale());
3514 }
3515}
3516
3518{
3519 if (CreatureModel const* model = GetCreatureTemplate()->GetModelByIdx(modelIdx))
3520 SetDisplayId(model->CreatureDisplayID);
3521}
3522
3524{
3525 if (HasSpellFocus())
3526 _spellFocusInfo.Target = guid;
3527 else
3529}
3530
3531void Creature::SetSpellFocus(Spell const* focusSpell, WorldObject const* target)
3532{
3533 // Pointer validation and checking for a already existing focus
3534 if (_spellFocusInfo.Spell || !focusSpell)
3535 return;
3536
3537 // Prevent dead / feign death creatures from setting a focus target
3539 return;
3540
3541 // Don't allow stunned creatures to set a focus target
3543 return;
3544
3545 // some spells shouldn't track targets
3546 if (focusSpell->IsFocusDisabled())
3547 return;
3548
3549 SpellInfo const* spellInfo = focusSpell->GetSpellInfo();
3550
3551 // don't use spell focus for vehicle spells
3552 if (spellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE))
3553 return;
3554
3555 // instant non-channeled casts and non-target spells don't need facing updates
3556 if (!target && (!focusSpell->GetCastTime() && !spellInfo->IsChanneled()))
3557 return;
3558
3559 // store pre-cast values for target and orientation (used to later restore)
3560 if (!_spellFocusInfo.Delay)
3561 { // only overwrite these fields if we aren't transitioning from one spell focus to another
3562 _spellFocusInfo.Target = GetTarget();
3563 _spellFocusInfo.Orientation = GetOrientation();
3564 }
3565 else // don't automatically reacquire target for the previous spellcast
3566 _spellFocusInfo.Delay = 0;
3567
3568 _spellFocusInfo.Spell = focusSpell;
3569
3570 bool const noTurnDuringCast = spellInfo->HasAttribute(SPELL_ATTR5_AI_DOESNT_FACE_TARGET);
3571 bool const turnDisabled = CannotTurn();
3572 // set target, then force send update packet to players if it changed to provide appropriate facing
3573 ObjectGuid newTarget = (target && !noTurnDuringCast && !turnDisabled) ? target->GetGUID() : ObjectGuid::Empty;
3574 if (GetTarget() != newTarget)
3576
3577 // If we are not allowed to turn during cast but have a focus target, face the target
3578 if (!turnDisabled && noTurnDuringCast && target)
3579 SetFacingToObject(target, false);
3580
3581 if (noTurnDuringCast)
3583}
3584
3585bool Creature::HasSpellFocus(Spell const* focusSpell) const
3586{
3587 if (isDead()) // dead creatures cannot focus
3588 {
3589 if (_spellFocusInfo.Spell || _spellFocusInfo.Delay)
3590 {
3591 TC_LOG_WARN("entities.unit", "Creature '{}' (entry {}) has spell focus (spell id {}, delay {}ms) despite being dead.",
3592 GetName(), GetEntry(), _spellFocusInfo.Spell ? _spellFocusInfo.Spell->GetSpellInfo()->Id : 0, _spellFocusInfo.Delay);
3593 }
3594 return false;
3595 }
3596
3597 if (focusSpell)
3598 return (focusSpell == _spellFocusInfo.Spell);
3599 else
3600 return (_spellFocusInfo.Spell || _spellFocusInfo.Delay);
3601}
3602
3603void Creature::ReleaseSpellFocus(Spell const* focusSpell, bool withDelay)
3604{
3605 if (!_spellFocusInfo.Spell)
3606 return;
3607
3608 // focused to something else
3609 if (focusSpell && focusSpell != _spellFocusInfo.Spell)
3610 return;
3611
3612 if (_spellFocusInfo.Spell->GetSpellInfo()->HasAttribute(SPELL_ATTR5_AI_DOESNT_FACE_TARGET))
3614
3615 if (IsPet()) // player pets do not use delay system
3616 {
3617 if (!CannotTurn())
3619 }
3620 else // don't allow re-target right away to prevent visual bugs
3621 _spellFocusInfo.Delay = withDelay ? 1000 : 1;
3622
3623 _spellFocusInfo.Spell = nullptr;
3624}
3625
3627{
3628 if (!HasSpellFocus())
3629 {
3630 TC_LOG_ERROR("entities.unit", "Creature::ReacquireSpellFocusTarget() being called with HasSpellFocus() returning false. {}", GetDebugInfo());
3631 return;
3632 }
3633
3635
3636 if (!CannotTurn())
3637 {
3638 if (!_spellFocusInfo.Target.IsEmpty())
3639 {
3640 if (WorldObject const* objTarget = ObjectAccessor::GetWorldObject(*this, _spellFocusInfo.Target))
3641 SetFacingToObject(objTarget, false);
3642 }
3643 else
3644 SetFacingTo(_spellFocusInfo.Orientation, false);
3645 }
3646 _spellFocusInfo.Delay = 0;
3647}
3648
3650{
3651 _spellFocusInfo.Delay = 0;
3652 _spellFocusInfo.Spell = nullptr;
3653}
3654
3656{
3658 return false;
3659
3660 return true;
3661}
3662
3667
3672
3674{
3675 CreatureTextRepeatIds& repeats = m_textRepeat[textGroup];
3676 if (std::find(repeats.begin(), repeats.end(), id) == repeats.end())
3677 repeats.push_back(id);
3678 else
3679 TC_LOG_ERROR("sql.sql", "CreatureTextMgr: TextGroup {} for Creature({}) {}, id {} already added", uint32(textGroup), GetName(), GetGUID().ToString(), uint32(id));
3680}
3681
3683{
3685
3686 CreatureTextRepeatGroup::const_iterator groupItr = m_textRepeat.find(textGroup);
3687 if (groupItr != m_textRepeat.end())
3688 ids = groupItr->second;
3689
3690 return ids;
3691}
3692
3694{
3695 CreatureTextRepeatGroup::iterator groupItr = m_textRepeat.find(textGroup);
3696 if (groupItr != m_textRepeat.end())
3697 groupItr->second.clear();
3698}
3699
3704
3706{
3707 if (CreatureAI const* ai = AI())
3708 return ai->IsEngaged();
3709 return false;
3710}
3711
3713{
3714 Unit::AtEngage(target);
3715
3717
3719
3721 Dismount();
3722
3723 if (IsPet() || IsGuardian()) // update pets' speed for catchup OOC speed
3724 {
3728 }
3729
3731 if (movetype == WAYPOINT_MOTION_TYPE || movetype == POINT_MOTION_TYPE || (IsAIEnabled() && AI()->IsEscorted()))
3732 {
3734
3735 // if its a vehicle, set the home positon of every creature passenger at engage
3736 // so that they are in combat range if hostile
3737 if (Vehicle* vehicle = GetVehicleKit())
3738 {
3739 for (auto seat = vehicle->Seats.begin(); seat != vehicle->Seats.end(); ++seat)
3740 if (Unit* passenger = ObjectAccessor::GetUnit(*this, seat->second.Passenger.Guid))
3741 if (Creature* creature = passenger->ToCreature())
3742 creature->SetHomePosition(GetPosition());
3743 }
3744 }
3745
3746 if (CreatureAI* ai = AI())
3747 ai->JustEngagedWith(target);
3748 if (CreatureGroup* formation = GetFormation())
3749 formation->MemberEngagingTarget(this, target);
3750
3751 // Creatures with CREATURE_STATIC_FLAG_2_FORCE_PARTY_MEMBERS_INTO_COMBAT periodically force party members into combat
3753}
3754
3756{
3758
3762
3763 if (IsPet() || IsGuardian()) // update pets' speed for catchup OOC speed
3764 {
3768 }
3769}
3770
3772{
3774 return;
3775
3776 Trinity::Containers::FlatSet<Group const*> partiesToForceIntoCombat;
3777 for (auto const& [_, combatReference] : GetCombatManager().GetPvECombatRefs())
3778 {
3779 if (combatReference->IsSuppressedFor(this))
3780 continue;
3781
3782 Player* player = Object::ToPlayer(combatReference->GetOther(this));
3783 if (!player || player->IsGameMaster())
3784 continue;
3785
3786 if (Group const* group = player->GetGroup())
3787 partiesToForceIntoCombat.insert(group);
3788 }
3789
3790 for (Group const* partyToForceIntoCombat : partiesToForceIntoCombat)
3791 {
3792 for (GroupReference const& ref : partyToForceIntoCombat->GetMembers())
3793 {
3794 Player* player = ref.GetSource();
3795 if (!player->IsInMap(this) || player->IsGameMaster())
3796 continue;
3797
3798 EngageWithTarget(player);
3799 }
3800 }
3801}
3802
3804{
3805 if (CreatureAI const* ai = AI())
3806 return ai->IsEscorted();
3807 return false;
3808}
3809
3810std::string Creature::GetDebugInfo() const
3811{
3812 std::stringstream sstr;
3813 sstr << Unit::GetDebugInfo() << "\n"
3814 << "AIName: " << GetAIName() << " ScriptName: " << GetScriptName()
3815 << " WaypointPath: " << GetWaypointPathId() << " SpawnId: " << GetSpawnId();
3816 return sstr.str();
3817}
3818
3819void Creature::ExitVehicle(Position const* /*exitPosition*/)
3820{
3822
3823 // if the creature exits a vehicle, set it's home position to the
3824 // exited position so it won't run away (home) and evade if it's hostile
3826}
3827
3829{
3830 return _gossipMenuId;
3831}
3832
3834{
3835 _gossipMenuId = gossipMenuId;
3836}
3837
3839{
3840 if (_trainerId)
3841 return *_trainerId;
3842
3843 return sObjectMgr->GetCreatureDefaultTrainer(GetEntry());
3844}
3845
3847{
3848 _trainerId = trainerId;
3849}
3850
3856
3858{
3859 if (!IsAreaSpiritHealer())
3860 return;
3861
3863
3864 // maybe NPC is summoned with these spells:
3865 // ID - 24237 Summon Alliance Graveyard Teleporter (SERVERSIDE)
3866 // ID - 46894 Summon Horde Graveyard Teleporter (SERVERSIDE)
3867 SummonCreature(npcEntry, GetPosition(), TEMPSUMMON_TIMED_DESPAWN, 1s, 0, 0);
3868}
3869
3871{
3872 auto clickBounds = sObjectMgr->GetSpellClickInfoMapBounds(GetEntry());
3873 auto itr = clickBounds.begin();
3874 // Set InteractSpellID if there is only one row in npc_spellclick_spells in db for this creature
3875 if (itr != clickBounds.end() && ++itr == clickBounds.end())
3876 SetInteractSpellId(clickBounds.begin()->second.spellId);
3877 else
3879}
3880
3882{
3883 m_objectData->WriteCreate(flags, data, target, this);
3884 m_unitData->WriteCreate(flags, data, target, this);
3885}
3886
3888{
3890
3892 m_objectData->WriteUpdate(flags, data, target, this);
3893
3895 m_unitData->WriteUpdate(flags, data, target, this);
3896}
3897
3899{
3901 valuesMask.Set(TYPEID_UNIT);
3902
3903 data << uint32(valuesMask.GetBlock(0));
3904
3905 UF::UnitData::Mask mask;
3907 m_unitData->WriteUpdate(mask, data, target, this, true);
3908}
3909
3911 UF::UnitData::Mask const& requestedUnitMask, Player const* target, bool ignoreNestedChangesMask) const
3912{
3915 if (requestedObjectMask.IsAnySet())
3916 valuesMask.Set(TYPEID_OBJECT);
3917
3918 UF::UnitData::Mask unitMask = requestedUnitMask;
3920 if (unitMask.IsAnySet())
3921 valuesMask.Set(TYPEID_UNIT);
3922
3923 ByteBuffer& buffer = PrepareValuesUpdateBuffer(data);
3924 std::size_t sizePos = buffer.wpos();
3925 buffer << uint32(0);
3927 buffer << uint32(valuesMask.GetBlock(0));
3928
3929 if (valuesMask[TYPEID_OBJECT])
3930 m_objectData->WriteUpdate(requestedObjectMask, buffer, target, this, ignoreNestedChangesMask);
3931
3932 if (valuesMask[TYPEID_UNIT])
3933 m_unitData->WriteUpdate(unitMask, buffer, target, this, ignoreNestedChangesMask);
3934
3935 buffer.put<uint32>(sizePos, buffer.wpos() - sizePos - 4);
3936
3937 data->AddUpdateBlock();
3938}
3939
3941{
3942 UpdateData udata(Owner->GetMapId());
3943 WorldPacket packet;
3944
3946
3947 udata.BuildPacket(&packet);
3948 player->SendDirectMessage(&packet);
3949}
#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_CAN_SWIM
@ CREATURE_STATIC_FLAG_NO_XP
@ CREATURE_STATIC_FLAG_NO_MELEE_FLEE
@ 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:569
@ MAX_LEVEL
Definition DBCEnums.h:45
@ STRONG_MAX_LEVEL
Definition DBCEnums.h:49
@ FACTION_MASK_ALLIANCE
Definition DBCEnums.h:1009
Difficulty
Definition DBCEnums.h:932
@ DIFFICULTY_NONE
Definition DBCEnums.h:933
@ FACTION_TEMPLATE_FLAG_PVP
Definition DBCEnums.h:1001
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:82
#define ASSERT
Definition Errors.h:80
#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:181
#define TC_LOG_ERROR(filterType__, message__,...)
Definition Log.h:190
#define TC_LOG_WARN(filterType__, message__,...)
Definition Log.h:187
@ 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
#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:1885
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:28
int32 irand(int32 min, int32 max)
Definition Random.cpp:35
uint32 urand(uint32 min, uint32 max)
Definition Random.cpp:42
void SendGossipMenuFor(Player *player, uint32 npcTextID, ObjectGuid const &guid)
void ClearGossipMenuFor(Player *player)
@ SERVERSIDE_VISIBILITY_GHOST
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
SpellEffectName
@ SPELL_EFFECT_HEAL
@ SPELL_EFFECT_ATTACK_ME
@ SPELL_EFFECT_KNOCK_BACK_DEST
@ SPELL_EFFECT_KNOCK_BACK
@ 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_MOD_DETECTED_RANGE
@ SPELL_AURA_MOD_TAUNT
@ SPELL_AURA_FEIGN_DEATH
@ 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_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
@ MOVEMENTFLAG_FALLING
@ 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_CAN_SWIM
@ UNIT_FLAG_FLEEING
@ UNIT_FLAG_CANT_SWIM
@ UNIT_FLAG_PLAYER_CONTROLLED
@ BASE_VALUE
Definition Unit.h:156
@ MINDAMAGE
Definition Unit.h:171
@ MAXDAMAGE
Definition Unit.h:172
UnitMods
Definition Unit.h:176
@ UNIT_MOD_ARMOR
Definition Unit.h:209
@ UNIT_MOD_RESISTANCE_SHADOW
Definition Unit.h:214
@ UNIT_MOD_RESISTANCE_FROST
Definition Unit.h:213
@ UNIT_MOD_ATTACK_POWER
Definition Unit.h:216
@ UNIT_MOD_RESISTANCE_HOLY
Definition Unit.h:210
@ UNIT_MOD_RESISTANCE_ARCANE
Definition Unit.h:215
@ UNIT_MOD_HEALTH
Definition Unit.h:182
@ UNIT_MOD_POWER_START
Definition Unit.h:227
@ UNIT_MOD_RESISTANCE_FIRE
Definition Unit.h:211
@ UNIT_MOD_RESISTANCE_NATURE
Definition Unit.h:212
@ UNIT_MOD_ATTACK_POWER_RANGED
Definition Unit.h:217
#define MAX_AGGRO_RADIUS
Definition Unit.h:45
DeathState
Definition Unit.h:251
@ CORPSE
Definition Unit.h:254
@ DEAD
Definition Unit.h:255
@ ALIVE
Definition Unit.h:252
@ JUST_RESPAWNED
Definition Unit.h:256
@ JUST_DIED
Definition Unit.h:253
@ UNIT_STATE_DIED
Definition Unit.h:261
@ UNIT_STATE_ATTACK_PLAYER
Definition Unit.h:275
@ UNIT_STATE_ROOT
Definition Unit.h:271
@ UNIT_STATE_IGNORE_PATHFINDING
Definition Unit.h:289
@ UNIT_STATE_FLEEING
Definition Unit.h:268
@ UNIT_STATE_FOCUSING
Definition Unit.h:267
@ UNIT_STATE_ALL_ERASABLE
Definition Unit.h:308
@ BASE_PCT
Definition Unit.h:164
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
uint32 const Entry[5]
ObjectGuid m_victim
Definition Creature.h:624
bool Execute(uint64 e_time, uint32 p_time) override
Definition Creature.cpp:291
void AddAssistant(ObjectGuid guid)
Definition Creature.h:620
GuidList m_assistants
Definition Creature.h:625
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:461
void put(std::size_t pos, T value)
Definition ByteBuffer.h:260
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:167
bool LoadCreaturesAddon()
time_t _pickpocketLootRestore
Timers.
Definition Creature.h:528
bool HasSpell(uint32 spellID) const override
uint32 CalculateDamageForSparring(Unit *attacker, uint32 damage)
bool AIM_Destroy()
VendorItemCounts m_vendorItemCounts
Definition Creature.h:520
void SetHomePosition(float x, float y, float z, float o)
Definition Creature.h:386
float m_wanderDistance
Definition Creature.h:534
void SetNoSearchAssistance(bool val)
Definition Creature.h:340
void ReleaseSpellFocus(Spell const *focusSpell=nullptr, bool withDelay=true)
CreatureDifficulty const * m_creatureDifficulty
Definition Creature.h:560
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:561
void SetInteractionAllowedInCombat(bool interactionAllowed) override
void ResetLootMode()
Definition Creature.h:322
bool CanSwim() const override
void RegenerateHealth()
CreatureTextRepeatGroup m_textRepeat
Definition Creature.h:598
VendorItemData const * GetVendorItems() const
void StartDefaultCombatMovement(Unit *victim, Optional< float > range={}, Optional< float > angle={})
float _sparringHealthPct
Definition Creature.h:611
bool CreateFromProto(ObjectGuid::LowType guidlow, uint32 entry, CreatureData const *data=nullptr, uint32 vehId=0)
bool _regenerateHealth
Definition Creature.h:605
CreatureStaticFlagsHolder _staticFlags
Definition Creature.h:567
bool IsDungeonBoss() const
Definition Creature.h:169
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:385
Optional< uint32 > m_lootId
Definition Creature.h:564
void UpdateLevelDependantStats()
int8 m_originalEquipmentId
Definition Creature.h:543
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:541
std::unique_ptr< Loot > m_loot
Definition Creature.h:299
void Update(uint32 time) override
Definition Creature.cpp:752
CreatureDifficulty const * GetCreatureDifficulty() const
Definition Creature.h:268
bool _IsTargetAcceptable(Unit const *target) const
CreatureClassifications GetCreatureClassification() const
Definition Creature.h:166
Optional< uint32 > _defaultMountDisplayIdOverride
Definition Creature.h:607
bool IsSessile() const
Definition Creature.h:146
bool IsIgnoringFeignDeath() const
Definition Creature.h:344
bool IsCivilian() const
Definition Creature.h:126
float GetSparringHealthPct() const
Definition Creature.h:464
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:562
uint32 m_spells[MAX_CREATURE_SPELLS]
Definition Creature.h:324
void ApplyAllStaticFlags(CreatureStaticFlagsHolder const &flags)
Definition Creature.cpp:744
static float GetDamageMod(CreatureClassifications classification)
bool m_cannotReachTarget
Definition Creature.h:547
bool m_respawnCompatibilityMode
Definition Creature.h:583
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:300
CreatureTemplate const * m_creatureInfo
Definition Creature.h:558
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:161
Position const & GetHomePosition() const
Definition Creature.h:389
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:176
bool AIM_Initialize(CreatureAI *ai=nullptr)
void DoNotReacquireSpellFocusTarget()
void RemoveCorpse(bool setSpawnTime=true, bool destroyForNearbyPlayers=true)
Definition Creature.cpp:433
void SendZoneUnderAttackMessage(Player *attacker)
Send a message to LocalDefense channel for players opposition team in the zone.
bool m_triggerJustAppeared
Definition Creature.h:582
bool _aggroGracePeriodExpired
Definition Creature.h:585
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
void SignalFormationMovement()
Definition Creature.cpp:414
void SetDisplayFromModel(uint32 modelIdx)
bool IsEngaged() const override
void Heartbeat() override
Definition Creature.cpp:934
MovementGeneratorType m_defaultMovementType
Definition Creature.h:540
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)
struct Creature::@192 _spellFocusInfo
void SetReactState(ReactStates st)
Definition Creature.h:174
uint32 GetTrainerId() const
UF::OptionalUpdateField< UF::VendorData, int32(WowCS::EntityFragment::FVendor_C), 0 > m_vendorData
Definition Creature.h:492
void RemoveFromWorld() override
Definition Creature.cpp:367
void SetTextRepeatId(uint8 textGroup, uint8 id)
uint32 _waypointPathId
Definition Creature.h:577
void ResetPlayerDamageReq()
Definition Creature.h:415
float m_SightDistance
Definition Creature.h:427
int32 _creatureImmunitiesId
Definition Creature.h:608
void SetRespawnCompatibilityMode(bool mode=true)
Definition Creature.h:422
void SetCannotReachTarget(bool cannotReach)
bool ShouldFakeDamageFrom(Unit *attacker)
void ApplyLevelScaling()
void ClearTextRepeatGroup(uint8 textGroup)
void SetRespawnDelay(uint32 delay)
Definition Creature.h:360
void AddToWorld() override
Definition Creature.cpp:347
uint32 m_cannotReachTimer
Definition Creature.h:548
uint32 m_respawnDelay
Definition Creature.h:531
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:529
void ForcedDespawn(uint32 timeMSToDespawn=0, Seconds forceRespawnTimer=0s)
float GetPetChaseDistance() const
bool IsFormationLeaderMoveAllowed() const
Definition Creature.cpp:425
void SummonGraveyardTeleporter()
bool IsImmuneToNPC() const
Definition Unit.h:1048
void DespawnOrUnsummon(Milliseconds timeToDespawn=0s, Seconds forceRespawnTime=0s)
bool UpdateEntry(uint32 entry, CreatureData const *data=nullptr, bool updateLevel=true)
Definition Creature.cpp:593
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:727
float GetSpellDamageMod(CreatureClassifications classification) const
time_t m_respawnTime
Definition Creature.h:530
void DoFleeToGetAssistance()
float GetDamageMultiplierForTarget(WorldObject const *target) const override
uint32 _gossipMenuId
Definition Creature.h:609
bool CanResetTalents(Player *player) const
bool IsEscorted() const
void AtEngage(Unit *target) override
uint32 GetScriptId() const
CreatureData const * m_creatureData
Definition Creature.h:559
float m_CombatDistance
Definition Creature.h:427
void AtDisengage() override
bool hasInvolvedQuest(uint32 quest_id) const override
uint32 m_boundaryCheckTime
Definition Creature.h:535
bool isCanInteractWithBattleMaster(Player *player, bool msg) const
Position m_homePosition
Definition Creature.h:553
uint32 GetWaypointPathId() const
Definition Creature.h:396
Loot * GetLootForPlayer(Player const *player) const override
CreatureData const * GetCreatureData() const
Definition Creature.h:267
bool CanGeneratePickPocketLoot() const
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:382
bool m_AlreadyCallAssistance
Definition Creature.h:545
CreatureTemplate const * GetCreatureTemplate() const
Definition Creature.h:266
uint32 GetRespawnDelay() const
Definition Creature.h:359
void SetDontClearTapListOnEvade(bool dontClear)
bool IsFormationLeader() const
Definition Creature.cpp:406
bool CanCreatureAttack(Unit const *victim, bool force=true) const
bool CanRegenerateHealth() const
Definition Creature.h:372
bool DisableReputationGain
Definition Creature.h:556
void SetTarget(ObjectGuid const &guid) override
float GetBaseDamageForLevel(uint8 level) const
uint32 GetLootId() const
CreatureGroup * m_formation
Definition Creature.h:581
static bool DeleteFromDB(ObjectGuid::LowType spawnId)
void SetInteractSpellId(int32 interactSpellId)
Definition Creature.h:490
void InitializeReactState()
bool AIM_Create(CreatureAI *ai=nullptr)
uint32 m_corpseDelay
Definition Creature.h:532
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:542
bool IsElite() const
bool isTappedBy(Player const *player) const
Creature(bool isWorldObject=false)
Definition Creature.cpp:321
CreatureGroup * GetFormation()
Definition Creature.h:406
uint32 GetCorpseDelay() const
Definition Creature.h:124
GuidUnorderedSet m_tapList
Definition Creature.h:524
bool m_dontClearTapListOnEvade
Definition Creature.h:525
uint64 GetMaxHealthByLevel(uint8 level) const
SpawnTrackingStateData const * GetSpawnTrackingStateDataForPlayer(Player const *player) const override
void OverrideSparringHealthPct(float healthPct)
Definition Creature.h:462
bool CanAssistTo(Unit const *u, Unit const *enemy, bool checkfaction=true) const
std::string_view GetStringId(StringIdType type) const
Definition Creature.h:277
uint32 m_originalEntry
Definition Creature.h:551
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:393
uint32 GetVendorItemCurrentCount(VendorItem const *vItem)
float GetBaseArmorForLevel(uint8 level) const
bool m_isTempWorldObject
Definition Creature.h:429
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:441
MovementGeneratorType GetDefaultMovementType() const override
void SetSpellFocus(Spell const *focusSpell, WorldObject const *target)
Optional< uint32 > _trainerId
Definition Creature.h:610
bool HasFlag(CreatureStaticFlags flag) const
Definition Creature.h:472
bool IsInvisibleDueToDespawn(WorldObject const *seer) const override
bool IsFullyLooted() const
void SaveRespawnTime(uint32 forceDelay=0)
uint8 GetCurrentEquipmentId() const
Definition Creature.h:255
bool InitEntry(uint32 entry, CreatureData const *data=nullptr)
Definition Creature.cpp:500
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:231
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)
bool IsAmphibious() const
Definition Creature.h:139
void ResetPickPocketRefillTimer()
Definition Creature.h:302
void SetNoCallAssistance(bool val)
Definition Creature.h:339
void SetTreatAsRaidUnit(bool treatAsRaidUnit)
Definition Creature.h:236
void UpdateMovementCapabilities()
bool m_ignoreCorpseDecayRatio
Definition Creature.h:533
bool CanOnlySwimIfTargetSwims() const
Definition Creature.h:157
bool CanAlwaysSee(WorldObject const *obj) const override
bool hasQuest(uint32 quest_id) const override
void Regenerate(Powers power)
Definition Creature.cpp:952
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:1045
void SetCanDualWield(bool value) override
bool IsInEvadeMode() const
Definition Creature.h:217
void ReacquireSpellFocusTarget()
CreatureAI * AI() const
Definition Creature.h:228
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:419
bool HasSpellFocus(Spell const *focusSpell=nullptr) const override
uint32 GetGossipMenuId() const
void SetIgnoreFeignDeath(bool ignoreFeignDeath)
Definition Creature.h:345
uint64 m_PlayerDamageReq
Definition Creature.h:416
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:637
bool Execute(uint64 e_time, uint32 p_time) override
Definition Creature.cpp:315
static void RemoveCreatureFromGroup(CreatureGroup *group, Creature *member)
static void AddCreatureToGroup(ObjectGuid::LowType leaderSpawnId, Creature *creature)
Definition Group.h:205
Definition Map.h:225
bool IsDungeon() const
Definition Map.cpp:3267
void CreatureRelocation(Creature *creature, float x, float y, float z, float ang, bool respawnRelocationOnFail=true)
Definition Map.cpp:1050
MapStoredObjectTypesContainer & GetObjectsStore()
Definition Map.h:458
time_t GetLinkedRespawnTime(ObjectGuid guid) const
Definition Map.cpp:3705
bool IsRaid() const
Definition Map.cpp:3277
void GetFullTerrainStatusForPosition(PhaseShift const &phaseShift, float x, float y, float z, PositionFullTerrainStatus &data, Optional< map_liquidHeaderTypeFlags > reqLiquidType={}, float collisionHeight=2.03128f)
Definition Map.cpp:1688
void ApplyDynamicModeRespawnScaling(WorldObject const *obj, ObjectGuid::LowType spawnId, uint32 &respawnDelay, uint32 mode) const
Definition Map.cpp:2277
ObjectGuid::LowType GenerateLowGuid()
Definition Map.h:558
time_t GetCreatureRespawnTime(ObjectGuid::LowType spawnId) const
Definition Map.h:524
void SaveRespawnInfoDB(RespawnInfo const &info, CharacterDatabaseTransaction dbTrans=nullptr)
Definition Map.cpp:3647
bool IsSpawnGroupActive(uint32 groupId) const
Definition Map.cpp:2476
Difficulty GetDifficultyID() const
Definition Map.h:360
void SaveRespawnTime(SpawnObjectType type, ObjectGuid::LowType spawnId, uint32 entry, time_t respawnTime, uint32 gridId, CharacterDatabaseTransaction dbTrans=nullptr, bool startup=false)
Definition Map.cpp:3614
float GetHeight(PhaseShift const &phaseShift, float x, float y, float z, bool vmap=true, float maxSearchDist=DEFAULT_HEIGHT_SEARCH)
Definition Map.h:326
CreatureBySpawnIdContainer & GetCreatureBySpawnIdStore()
Definition Map.h:461
SpawnedPoolData & GetPoolData()
Definition Map.h:755
void Respawn(RespawnInfo *info, CharacterDatabaseTransaction dbTrans=nullptr)
Definition Map.cpp:2060
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:1611
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:6283
bool IsGameMaster() const
Definition Player.h:1309
Group * GetGroup(Optional< uint8 > partyIndex)
Definition Player.h:2796
SpawnTrackingState GetSpawnTrackingStateByObjectives(uint32 spawnTrackingId, std::vector< uint32 > const &questObjectives) const
Definition Player.cpp:17559
Team GetTeam() const
Definition Player.h:2423
bool GetBGAccessByLevel(BattlegroundTypeId bgTypeId) const
Definition Player.cpp:25858
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:8359
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:43
Definition Unit.h:635
void ClearUnitState(uint32 f)
Definition Unit.h:744
bool IsVehicle() const
Definition Unit.h:754
void ApplySpellImmune(uint32 spellId, SpellImmunity op, uint32 type, bool apply)
Definition Unit.cpp:8242
int32 ModifyPower(Powers power, int32 val, bool withPowerUpdate=true)
Definition Unit.cpp:8697
bool IsCharmed() const
Definition Unit.h:1236
Vehicle * GetVehicle() const
Definition Unit.h:1784
virtual bool IsMovementPreventedByCasting() const
Definition Unit.cpp:3261
bool IsBattleMaster() const
Definition Unit.h:1013
bool isTargetableForAttack(bool checkFakeDeath=true) const
Definition Unit.cpp:8585
bool IsHunterPet() const
Definition Unit.h:752
AuraEffectList const & GetAuraEffectsByType(AuraType type) const
Definition Unit.h:1342
float GetHealthPct() const
Definition Unit.h:796
void AIUpdateTick(uint32 diff)
Definition Unit.cpp:10155
void SetHealth(uint64 val)
Definition Unit.cpp:9973
void SetVirtualItem(uint32 slot, uint32 itemId, uint16 appearanceModId=0, uint16 itemVisual=0)
Definition Unit.cpp:14374
uint64 CountPctFromMaxHealth(float pct) const
Definition Unit.h:797
void Heartbeat() override
Definition Unit.cpp:502
bool CanHaveThreatList() const
====================== THREAT & COMBAT ====================
Definition Unit.h:1030
void UpdateObjectVisibility(bool forced=true) override
Definition Unit.cpp:12467
bool CannotTurn() const
Definition Unit.h:1055
int64 ModifyHealth(int64 val)
Definition Unit.cpp:8599
void SetFullHealth()
Definition Unit.h:802
void SetStandState(UnitStandStateType state, uint32 animKitID=0)
Definition Unit.cpp:10731
void SetInitialPowerValue(Powers powerType)
Definition Unit.cpp:5750
void ReplaceAllNpcFlags2(NPCFlags2 flags)
Definition Unit.h:1005
float GetDisplayScale() const
Definition Unit.h:1611
ThreatManager & GetThreatManager()
Definition Unit.h:1078
void ReplaceAllPvpFlags(UnitPVPStateFlags flags)
Definition Unit.h:883
void AddToWorld() override
Definition Unit.cpp:10233
void SetModRangedHaste(float rangedHaste)
Definition Unit.h:841
void ReplaceAllUnitFlags3(UnitFlags3 flags)
Definition Unit.h:858
virtual void SetCanDualWield(bool value)
Definition Unit.h:704
void SetControlled(bool apply, UnitState state)
Definition Unit.cpp:11545
uint8 GetClass() const
Definition Unit.h:764
uint32 m_regenTimer
Definition Unit.h:1958
void SetCreateHealth(uint32 val)
Definition Unit.h:1414
Vehicle * m_vehicle
Definition Unit.h:1960
std::unique_ptr< CharmInfo > m_charmInfo
Definition Unit.h:1952
void UpdateDisplayPower()
Definition Unit.cpp:5808
void SetRace(uint8 race)
Definition Unit.h:762
NPCFlags GetNpcFlags() const
Definition Unit.h:995
void UpdateSpeed(UnitMoveType mtype)
Definition Unit.cpp:8778
bool IsPolymorphed() const
Definition Unit.cpp:10758
bool IsAreaSpiritHealer() const
Definition Unit.h:1017
void SetFaction(uint32 faction) override
Definition Unit.h:872
virtual void SetPvP(bool state)
Definition Unit.cpp:12241
void SetBaseWeaponDamage(WeaponAttackType attType, WeaponDamageRange damageRange, float value)
Definition Unit.h:1573
virtual void AtEngage(Unit *)
Definition Unit.h:1980
void SetStatPctModifier(UnitMods unitMod, UnitModifierPctType modifierType, float val)
Definition Unit.cpp:9644
Unit * getAttackerForHelper() const
Definition Unit.cpp:5830
std::forward_list< AuraEffect * > AuraEffectList
Definition Unit.h:652
Trinity::unique_trackable_ptr< Vehicle > m_vehicleKit
Definition Unit.h:1961
bool IsAreaSpiritHealerIndividual() const
Definition Unit.h:1024
void SetAnimTier(AnimTier animTier, bool notifyClient=true)
Definition Unit.cpp:10745
void ReplaceAllUnitFlags(UnitFlags flags)
Definition Unit.h:848
MotionMaster * GetMotionMaster()
Definition Unit.h:1723
bool IsPet() const
Definition Unit.h:751
Powers GetPowerType() const
Definition Unit.h:811
bool HasUnitFlag(UnitFlags flags) const
Definition Unit.h:845
void Dismount()
Definition Unit.cpp:8317
bool SetHover(bool enable, bool updateAnimTier=true)
Definition Unit.cpp:13577
NPCFlags2 GetNpcFlags2() const
Definition Unit.h:1001
void SetFacingToObject(WorldObject const *object, bool force=true)
Definition Unit.cpp:13307
Aura * AddAura(uint32 spellId, Unit *target)
Definition Unit.cpp:12249
void SetModHaste(float haste)
Definition Unit.h:840
virtual void AtDisengage()
Definition Unit.h:1981
bool HasUnitFlag2(UnitFlags2 flags) const
Definition Unit.h:850
std::string GetDebugInfo() const override
Definition Unit.cpp:14591
void ReplaceAllPetFlags(UnitPetFlag flags)
Definition Unit.h:894
bool IsAlive() const
Definition Unit.h:1185
float GetCombatReach() const override
Definition Unit.h:705
void ReplaceAllVisFlags(UnitVisFlags flags)
Definition Unit.h:907
DeathState m_deathState
Definition Unit.h:1905
int32 GetMaxPower(Powers power) const
Definition Unit.cpp:10037
void StopMoving()
Definition Unit.cpp:10680
void RemoveNpcFlag(NPCFlags flags)
Definition Unit.h:998
TempSummon * ToTempSummon()
Definition Unit.h:1828
bool IsQuestGiver() const
Definition Unit.h:1009
ObjectGuid GetCharmerOrOwnerGUID() const override
Definition Unit.h:1216
bool SetDisableGravity(bool disable, bool updateAnimTier=true)
Definition Unit.cpp:13361
void SetModHasteRegen(float hasteRegen)
Definition Unit.h:842
virtual void SetInteractionAllowedWhileHostile(bool interactionAllowed)
Definition Unit.cpp:9292
float GetNativeDisplayScale() const
Definition Unit.h:1614
Player * GetPlayerMovingMe() const
Definition Unit.h:1253
void SetUninteractible(bool apply)
Definition Unit.cpp:8564
void SetBaseAttackTime(WeaponAttackType att, uint32 val)
Definition Unit.cpp:10939
void AddUnitState(uint32 f)
Definition Unit.h:742
float GetTotalAuraMultiplier(AuraType auraType) const
Definition Unit.cpp:5074
bool IsTaxi() const
Definition Unit.h:1011
void SetSheath(SheathState sheathed)
Definition Unit.cpp:5813
bool IsOnVehicle(Unit const *vehicle) const
Definition Unit.cpp:12106
void SetBoundingRadius(float boundingRadius)
Definition Unit.h:708
void SetCreateMana(uint32 val)
Definition Unit.h:1416
bool isInAccessiblePlaceFor(Creature const *c) const
Definition Unit.cpp:3310
bool IsCharmedOwnedByPlayerOrPlayer() const
Definition Unit.h:1217
virtual void SetInteractionAllowedInCombat(bool interactionAllowed)
Definition Unit.cpp:9302
Unit * EnsureVictim() const
Definition Unit.h:728
void SetModSpellHaste(float spellHaste)
Definition Unit.h:839
void RefreshAI()
Definition Unit.cpp:10187
Unit * GetCharmerOrOwner() const
Definition Unit.h:1221
virtual void UpdateDamagePhysical(WeaponAttackType attType)
uint32 GetCreatureType() const
Definition Unit.cpp:9451
virtual bool IsImmunedToSpellEffect(SpellInfo const *spellInfo, SpellEffectInfo const &spellEffectInfo, WorldObject const *caster, bool requireImmunityPurgesEffectAttribute=false) const
Definition Unit.cpp:7917
bool SetSwim(bool enable)
Definition Unit.cpp:13440
void SetCombatReach(float combatReach)
Definition Unit.h:706
void SetEmoteState(Emote emote)
Definition Unit.h:865
virtual void UpdateNearbyPlayersInteractions()
Definition Unit.cpp:9313
float GetTotalAuraMultiplierByMiscValue(AuraType auraType, int32 misc_value) const
Definition Unit.cpp:5139
uint32 GetDisplayId() const
Definition Unit.h:1610
bool IsAIEnabled() const
Definition Unit.h:666
uint32 GetNativeDisplayId() const
Definition Unit.h:1613
uint64 GetMaxHealth() const
Definition Unit.h:789
bool IsHovering() const
Definition Unit.h:1151
bool PopAI()
Definition Unit.cpp:10176
float GetHoverOffset() const
Definition Unit.h:1812
uint64 GetHealth() const
Definition Unit.h:788
bool IsSummon() const
Definition Unit.h:749
bool IsInWater() const
Definition Unit.cpp:3331
TransportBase * GetDirectTransport() const
Returns the transport this unit is on directly (if on vehicle and transport, return vehicle)
Definition Unit.cpp:12151
uint32 GetFaction() const override
Definition Unit.h:871
uint32 GetCreateHealth() const
Definition Unit.h:1415
void SetAI(UnitAI *newAI)
Definition Unit.cpp:10170
void SetSpellEmpowerStage(int8 stage)
Definition Unit.h:1451
float GetTotalAuraModifier(AuraType auraType) const
Definition Unit.cpp:5069
void SetNpcFlag(NPCFlags flags)
Definition Unit.h:997
bool HasAuraType(AuraType auraType) const
Definition Unit.cpp:4814
void EngageWithTarget(Unit *who)
Definition Unit.cpp:8494
void UpdateCreatureType()
Definition Unit.cpp:9475
bool HasNpcFlag(NPCFlags flags) const
Definition Unit.h:996
uint8 GetLevelForTarget(WorldObject const *) const override
Definition Unit.h:759
void SetMovementAnimKitId(uint16 animKitId)
Definition Unit.cpp:11191
void SetMaxHealth(uint64 val)
Definition Unit.cpp:10004
float GetTotalAuraModifierByMiscValue(AuraType auraType, int32 misc_value) const
Definition Unit.cpp:5129
bool IsGuardian() const
Definition Unit.h:750
Unit * GetVictim() const
Definition Unit.h:726
UF::UpdateField< UF::UnitData, int32(WowCS::EntityFragment::CGObject), TYPEID_UNIT > m_unitData
Definition Unit.h:1881
int32 GetPower(Powers power) const
Definition Unit.cpp:10028
void SetModTimeRate(float timeRate)
Definition Unit.h:843
bool IsUnderWater() const
Definition Unit.cpp:3336
void SetSpeedRate(UnitMoveType mtype, float rate)
Definition Unit.cpp:8942
DeathState getDeathState() const
Definition Unit.h:1188
void SetFacingTo(float const ori, bool force=true)
Definition Unit.cpp:13289
bool IsEngagedBy(Unit const *who) const
Definition Unit.h:1035
bool IsCritter() const
Definition Unit.h:1025
bool CreateVehicleKit(uint32 id, uint32 creatureEntry, bool loading=false)
Definition Unit.cpp:12074
bool HasUnitState(const uint32 f) const
Definition Unit.h:743
virtual void Update(uint32 time) override
Definition Unit.cpp:423
void ProcessPositionDataChanged(PositionFullTerrainStatus const &data) override
Definition Unit.cpp:3346
void SetLevel(uint8 lvl, bool sendUpdate=true)
Definition Unit.cpp:9956
void SetCanModifyStats(bool modifyStats)
Definition Unit.h:1549
void RemoveUnitMovementFlag(uint32 f)
Definition Unit.h:1733
void SetClass(uint8 classId)
Definition Unit.h:765
virtual bool CanSwim() const
Definition Unit.cpp:12944
void RemoveFromWorld() override
Definition Unit.cpp:10241
bool IsOnOceanFloor() const
Definition Unit.cpp:3341
Powers CalculateDisplayPowerType() const
Definition Unit.cpp:5762
bool isDying() const
Definition Unit.h:1186
void DoMeleeAttackIfReady()
Definition Unit.cpp:2174
void RemoveAllAuras()
Definition Unit.cpp:4382
void ReplaceAllUnitFlags2(UnitFlags2 flags)
Definition Unit.h:853
bool IsWildBattlePet() const
Definition Unit.h:1021
virtual void setDeathState(DeathState s)
Definition Unit.cpp:9161
UF::UpdateFieldFlag GetUpdateFieldFlagsFor(Player const *target) const override
Definition Unit.cpp:14216
CombatManager & GetCombatManager()
Definition Unit.h:1038
void SetUnitFlag(UnitFlags flags)
Definition Unit.h:846
bool IsVendor() const
Definition Unit.h:1007
bool IsFlying() const
Definition Unit.h:1807
void SetVignette(uint32 vignetteId)
Definition Unit.cpp:14576
bool IsUninteractible() const
Definition Unit.h:1052
bool IsSpiritHealer() const
Definition Unit.h:1016
bool IsTotem() const
Definition Unit.h:753
void SetInFront(WorldObject const *target)
Definition Unit.cpp:13283
void SetModCastingSpeed(float castingSpeed)
Definition Unit.h:838
Vehicle * GetVehicleKit() const
Definition Unit.h:1782
void ReplaceAllNpcFlags(NPCFlags flags)
Definition Unit.h:999
bool IsSpiritService() const
Definition Unit.h:1023
bool IsFalling() const
Definition Unit.cpp:12939
void SetStatFlatModifier(UnitMods unitMod, UnitModifierFlatType modifierType, float val)
Definition Unit.cpp:9635
void SetShapeshiftForm(ShapeshiftForm form)
Definition Unit.cpp:9494
void SetMeleeAnimKitId(uint16 animKitId)
Definition Unit.cpp:11208
ObjectGuid GetTarget() const
Definition Unit.h:1831
void SetPowerType(Powers power, bool sendUpdate=true, bool onInit=false)
Definition Unit.cpp:5697
uint8 GetLevel() const
Definition Unit.h:757
void SetMountDisplayId(uint32 mountDisplayId)
Definition Unit.h:914
virtual void SetDisplayId(uint32 displayId, bool setNative=false)
Definition Unit.cpp:10779
bool IsInCombat() const
Definition Unit.h:1058
void SetWildBattlePetLevel(uint32 wildBattlePetLevel)
Definition Unit.h:1271
void SetIsCombatDisallowed(bool apply)
Definition Unit.h:1870
void RemoveUnitFlag(UnitFlags flags)
Definition Unit.h:847
void SetAIAnimKitId(uint16 animKitId)
Definition Unit.cpp:11174
Player * m_playerMovingMe
Definition Unit.h:1949
bool isDead() const
Definition Unit.h:1187
virtual void ExitVehicle(Position const *exitPosition=nullptr)
Definition Unit.cpp:12835
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:1094
Map * GetMap() const
Definition Object.h:411
void UpdateAllowedPositionZ(float x, float y, float &z, float *groundZ=nullptr) const
Definition Object.cpp:711
virtual void UpdateObjectVisibilityOnDestroy()
Definition Object.h:511
bool IsValidAttackTarget(WorldObject const *target, SpellInfo const *bySpell=nullptr) const
Definition Object.cpp:2324
bool IsHostileTo(WorldObject const *target) const
Definition Object.cpp:2181
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:1398
PhaseShift & GetPhaseShift()
Definition Object.h:310
Unit * GetOwner() const
Definition Object.cpp:1598
ZoneScript * GetZoneScript() const
Definition Object.h:417
void SetZoneScript()
Definition Object.cpp:1384
TransportBase * GetTransport() const
Definition Object.h:537
void setActive(bool isActiveObject)
Definition Object.cpp:276
float GetTransOffsetY() const
Definition Object.h:539
float GetFloorZ() const
Definition Object.cpp:3106
std::string const & GetName() const
Definition Object.h:342
virtual void SetMap(Map *map)
Definition Object.cpp:1144
float GetTransOffsetZ() const
Definition Object.h:540
void AddObjectToRemoveList()
Definition Object.cpp:1174
bool IsWithinLOSInMap(WorldObject const *obj, LineOfSightChecks checks=LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags ignoreFlags=VMAP::ModelIgnoreFlags::Nothing) const
Definition Object.cpp:535
bool IsNeutralToAll() const
Definition Object.cpp:2204
Player * GetCharmerOrOwnerPlayerOrPlayerItself() const
Definition Object.cpp:1621
bool IsWithinDistInMap(WorldObject const *obj, float dist2compare, bool is3D=true, bool incOwnRadius=true, bool incTargetRadius=true) const
Definition Object.cpp:501
void SetName(std::string newname)
Definition Object.h:343
EventProcessor m_Events
Definition Object.h:561
float GetVisibilityRange() const
Definition Object.cpp:787
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:299
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:402
bool IsWithinDist(WorldObject const *obj, float dist2compare, bool is3D=true, bool incOwnRadius=true, bool incTargetRadius=true) const
Definition Object.cpp:496
bool IsFriendlyTo(WorldObject const *target) const
Definition Object.cpp:2186
bool IsInMap(WorldObject const *obj) const
Definition Object.cpp:469
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:916
@ CONFIG_CORPSE_DECAY_ELITE
Definition World.h:329
@ CONFIG_NO_GRAY_AGGRO_BELOW
Definition World.h:413
@ CONFIG_CORPSE_DECAY_OBSOLETE
Definition World.h:331
@ CONFIG_CREATURE_PICKPOCKET_REFILL
Definition World.h:404
@ CONFIG_RESPAWN_DYNAMICMODE
Definition World.h:419
@ CONFIG_MAX_PLAYER_LEVEL
Definition World.h:262
@ 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:412
@ CONFIG_CREATURE_STOP_FOR_PLAYER
Definition World.h:405
@ 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:493
@ RATE_CREATURE_DAMAGE_RAREELITE
Definition World.h:495
@ RATE_CREATURE_AGGRO
Definition World.h:507
@ RATE_CREATURE_HP_ELITE
Definition World.h:487
@ RATE_CREATURE_HP_RARE
Definition World.h:490
@ RATE_CREATURE_DAMAGE_ELITE
Definition World.h:494
@ RATE_CREATURE_SPELLDAMAGE_TRIVIAL
Definition World.h:505
@ RATE_CREATURE_SPELLDAMAGE_NORMAL
Definition World.h:500
@ RATE_POWER_MANA
Definition World.h:448
@ RATE_CREATURE_SPELLDAMAGE_RAREELITE
Definition World.h:502
@ RATE_HEALTH
Definition World.h:447
@ RATE_CREATURE_HP_OBSOLETE
Definition World.h:489
@ RATE_CREATURE_DAMAGE_OBSOLETE
Definition World.h:496
@ RATE_CREATURE_DAMAGE_MINUSMOB
Definition World.h:499
@ RATE_POWER_FOCUS
Definition World.h:451
@ RATE_CREATURE_HP_NORMAL
Definition World.h:486
@ RATE_CREATURE_HP_MINUSMOB
Definition World.h:492
@ RATE_CREATURE_HP_TRIVIAL
Definition World.h:491
@ RATE_CORPSE_DECAY_LOOTED
Definition World.h:516
@ RATE_CREATURE_DAMAGE_RARE
Definition World.h:497
@ RATE_CREATURE_DAMAGE_TRIVIAL
Definition World.h:498
@ RATE_CREATURE_SPELLDAMAGE_ELITE
Definition World.h:501
@ RATE_CREATURE_SPELLDAMAGE_MINUSMOB
Definition World.h:506
@ RATE_CREATURE_HP_RAREELITE
Definition World.h:488
@ RATE_CREATURE_SPELLDAMAGE_OBSOLETE
Definition World.h:503
@ RATE_CREATURE_SPELLDAMAGE_RARE
Definition World.h:504
@ CONFIG_SIGHT_MONSTER
Definition World.h:208
@ CONFIG_CREATURE_FAMILY_FLEE_ASSISTANCE_RADIUS
Definition World.h:212
@ CONFIG_CREATURE_FAMILY_ASSISTANCE_RADIUS
Definition World.h:213
@ CONFIG_REGEN_HP_CANNOT_REACH_TARGET_IN_RAID
Definition World.h:195
@ CONFIG_LOAD_LOCALES
Definition World.h:200
static constexpr ObjectData creatureData[]
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)
GridCoord ComputeGridCoord(float x, float y)
UpdateFieldFlag
Definition UpdateField.h:37
void const * GetRawFragmentData(T const &fragmentData)
struct advstd::ranges::Contains contains
static void VisitAllObjects(WorldObject const *obj, T &visitor, float radius, bool dont_load=true)
Definition CellImpl.h:203
static void VisitGridObjects(WorldObject const *obj, T &visitor, float radius, bool dont_load=true)
Definition CellImpl.h:179
static void VisitWorldObjects(WorldObject const *obj, T &visitor, float radius, bool dont_load=true)
Definition CellImpl.h:191
std::vector< uint32 > auras
uint16 meleeAnimKit
uint16 movementAnimKit
VisibilityDistanceType visibilityDistanceType
static CreatureBaseStats const * GetBaseStats(uint8 level, uint8 unitClass)
Definition Creature.cpp:310
float wander_distance
Optional< uint64 > npcflag
uint32 curHealthPct
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
std::vector< SpellEffectName > Effect
Definition SpellMgr.h:568
EnumFlag< SpellOtherImmunity > Other
Definition SpellMgr.h:570
std::bitset< MAX_SPELL_SCHOOL > School
Definition SpellMgr.h:565
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:172
time_t respawnTime
Definition Map.h:174
SpawnObjectType type
Definition Map.h:171
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, 43 > ScalingLevelDelta
UpdateField< int32, 32, 41 > ScalingLevelMin
UpdateField< int32, 32, 42 > ScalingLevelMax
UpdateField< int32, 32, 40 > ContentTuningID
static void FilterDisallowedFieldsMaskForFlag(Mask &changesMask, EnumFlag< UpdateFieldFlag > fieldVisibilityFlags)
UpdateField< ObjectGuid, 0, 22 > Target
UpdateField< int32, 96, 123 > TaxiNodesID
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)