TrinityCore
Loading...
Searching...
No Matches
Object.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 "Object.h"
19#include "BattlefieldMgr.h"
20#include "CellImpl.h"
21#include "CinematicMgr.h"
22#include "CombatLogPackets.h"
23#include "Corpse.h"
24#include "CreatureGroups.h"
25#include "DB2Stores.h"
26#include "DynamicObject.h"
27#include "GameObject.h"
28#include "GridNotifiersImpl.h"
29#include "InstanceScenario.h"
30#include "Log.h"
31#include "Map.h"
32#include "MiscPackets.h"
33#include "ObjectAccessor.h"
34#include "ObjectMgr.h"
35#include "OutdoorPvPMgr.h"
36#include "PathGenerator.h"
37#include "PhasingHandler.h"
38#include "Player.h"
39#include "ReputationMgr.h"
40#include "SmoothPhasing.h"
41#include "Spell.h"
42#include "SpellAuraEffects.h"
43#include "SpellMgr.h"
44#include "SpellPackets.h"
45#include "TemporarySummon.h"
46#include "Totem.h"
47#include "UpdateData.h"
48#include "VMapFactory.h"
49#include "VMapManager.h"
50#include "World.h"
51#include <G3D/Vector3.h>
52#include <sstream>
53
63
73
80
81Object::~Object() = default;
82
84{
86
87 // Set new ref when adding to world (except if we already have one - also set in constructor to allow scripts to work in initialization phase)
88 // Changing the ref when adding/removing from world prevents accessing players on different maps (possibly from another thread)
89 if (!m_scriptRef)
91}
92
99
101{
103
104 std::size_t sizePos = buf.wpos();
105 buf << uint32(0);
107 BuildValuesUpdateWithFlag(flags, buf, target);
108 buf.put<uint32>(sizePos, buf.wpos() - sizePos - 4);
109
110 data->AddUpdateBlock();
111}
112
114{
115 uint8 contentsChangedMask = 0;
116 for (std::size_t i = 0; i < m_entityFragments.UpdateableCount; ++i)
117 {
119 contentsChangedMask |= m_entityFragments.Updateable.Masks[i] >> 1; // set the "fragment exists" bit
120
122 contentsChangedMask |= m_entityFragments.Updateable.Masks[i];
123 }
124
125 data << uint8(flags.HasFlag(UF::UpdateFieldFlag::Owner));
126 data << uint8(false); // m_entityFragments.IdsChanged
127 data << uint8(contentsChangedMask);
128}
129
134
135void Object::BuildValuesUpdateWithFlag(UF::UpdateFieldFlag /*flags*/, ByteBuffer& data, Player const* /*target*/) const
136{
137 data << uint32(0);
138}
139
140void Object::BuildObjectFragmentCreate(void const* rawFragmentData, UF::UpdateFieldFlag flags, ByteBuffer& data, Player const* target, BaseEntity const* /*entity*/)
141{
142 static_cast<Object const*>(rawFragmentData)->BuildValuesCreate(flags, data, target);
143}
144
145void Object::BuildObjectFragmentUpdate(void const* rawFragmentData, UF::UpdateFieldFlag flags, ByteBuffer& data, Player const* target, BaseEntity const* /*entity*/)
146{
147 static_cast<Object const*>(rawFragmentData)->BuildValuesUpdate(flags, data, target);
148}
149
150bool Object::IsObjectFragmentChanged(void const* rawFragmentData)
151{
152 return static_cast<Object const*>(rawFragmentData)->m_values.GetChangedObjectTypeMask() != 0;
153}
154
155void Object::ClearObjectFragmentChanged(void const* rawFragmentData)
156{
157 const_cast<Object*>(static_cast<Object const*>(rawFragmentData))->ClearValuesChangesMask();
158}
159
160std::string Object::GetDebugInfo() const
161{
162 std::stringstream sstr;
163 sstr << BaseEntity::GetDebugInfo() << " Entry " << GetEntry();
164 return std::move(sstr).str();
165}
166
168{
169 TC_LOG_DEBUG("misc", "MOVEMENT INFO");
170 TC_LOG_DEBUG("misc", "{}", guid.ToString());
171 TC_LOG_DEBUG("misc", "flags {} ({})", Movement::MovementFlags_ToString(flags), flags);
172 TC_LOG_DEBUG("misc", "time {} current time {}", time, getMSTime());
173 TC_LOG_DEBUG("misc", "position: `{}`", pos);
174 if (!transport.guid.IsEmpty())
175 {
176 TC_LOG_DEBUG("misc", "TRANSPORT:");
177 TC_LOG_DEBUG("misc", "{}", transport.guid.ToString());
178 TC_LOG_DEBUG("misc", "position: `{}`", transport.pos);
179 TC_LOG_DEBUG("misc", "seat: {}", transport.seat);
180 TC_LOG_DEBUG("misc", "time: {}", transport.time);
182 TC_LOG_DEBUG("misc", "prevTime: {}", transport.prevTime);
184 TC_LOG_DEBUG("misc", "vehicleId: {}", transport.vehicleId);
185 }
186
188 TC_LOG_DEBUG("misc", "pitch: {}", pitch);
189
191 {
192 TC_LOG_DEBUG("misc", "fallTime: {} j_zspeed: {}", jump.fallTime, jump.zspeed);
194 TC_LOG_DEBUG("misc", "j_sinAngle: {} j_cosAngle: {} j_xyspeed: {}", jump.sinAngle, jump.cosAngle, jump.xyspeed);
195 }
196
198 TC_LOG_DEBUG("misc", "stepUpStartElevation: {}", stepUpStartElevation);
199
200 if (inertia)
201 {
202 TC_LOG_DEBUG("misc", "inertia->id: {}", inertia->id);
203 TC_LOG_DEBUG("misc", "inertia->force: {}", inertia->force);
204 TC_LOG_DEBUG("misc", "inertia->lifetime: {}", inertia->lifetime);
205 }
206
207 if (advFlying)
208 {
209 TC_LOG_DEBUG("misc", "advFlying->forwardVelocity: {}", advFlying->forwardVelocity);
210 TC_LOG_DEBUG("misc", "advFlying->upVelocity: {}", advFlying->upVelocity);
211 }
212
214 TC_LOG_DEBUG("misc", "standingOnGameObjectGUID: {}", standingOnGameObjectGUID->ToString());
215}
216
217WorldObject::WorldObject(bool isWorldObject) : Object(), WorldLocation(), LastUsedScriptID(0),
218m_movementInfo(), m_name(), m_isActive(false), m_isFarVisible(false), m_isStoredInWorldObjectGridContainer(isWorldObject), m_zoneScript(nullptr),
219m_transport(nullptr), m_zoneId(0), m_areaId(0), m_staticFloorZ(VMAP_INVALID_HEIGHT), m_outdoors(false), m_liquidStatus(LIQUID_MAP_NO_WATER),
220m_currMap(nullptr), m_InstanceId(0), _dbPhase(0), m_notifyflags(0), _heartbeatTimer(HEARTBEAT_INTERVAL)
221{
223
226}
227
229{
230 // this may happen because there are many !create/delete
232 {
233 if (GetTypeId() == TYPEID_CORPSE)
234 {
235 TC_LOG_FATAL("misc", "WorldObject::~WorldObject Corpse Type: {} ({}) deleted but still in map!!",
236 ToCorpse()->GetType(), GetGUID().ToString());
237 ABORT();
238 }
239 ResetMap();
240 }
241}
242
244{
245 m_Events.Update(diff);
246
248 while (_heartbeatTimer <= 0ms)
249 {
251 Heartbeat();
252 }
253}
254
256{
257 if (!IsInWorld())
258 return;
259
260 GetMap()->AddObjectToSwitchList(this, on);
261}
262
264{
266 return true;
267
268 if (ToCreature() && ToCreature()->m_isTempWorldObject)
269 return true;
270
271 return false;
272}
273
275{
276 if (m_isActive == on)
277 return;
278
279 if (GetTypeId() == TYPEID_PLAYER)
280 return;
281
282 m_isActive = on;
283
284 if (on && !IsInWorld())
285 return;
286
287 Map* map = FindMap();
288 if (!map)
289 return;
290
291 if (on)
292 map->AddToActive(this);
293 else
294 map->RemoveFromActive(this);
295}
296
298{
300 if (GetTypeId() == TYPEID_PLAYER)
301 return;
302
303 if (Creature* creature = ToCreature())
304 {
306 switch (type)
307 {
309 creature->SetUnitFlag2(UNIT_FLAG2_LARGE_AOI);
310 break;
312 creature->SetUnitFlag2(UNIT_FLAG2_GIGANTIC_AOI);
313 break;
315 creature->SetUnitFlag2(UNIT_FLAG2_INFINITE_AOI);
316 break;
317 default:
318 break;
319 }
320 }
321
323}
324
326{
327 if (GetTypeId() == TYPEID_PLAYER)
328 return;
329
330 m_isFarVisible = on;
331}
332
333void WorldObject::CleanupsBeforeDelete(bool /*finalCleanup*/)
334{
335 if (IsInWorld())
337
338 if (TransportBase* transport = GetTransport())
339 transport->RemovePassenger(this);
340
341 m_Events.KillAllEvents(false); // non-delatable (currently cast spells) will not deleted now but it will deleted at call in Map::RemoveAllObjectsInRemoveList
342}
343
350
352{
353 m_zoneId = m_areaId = data.areaId;
354 if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(m_areaId))
355 if (area->ParentAreaID && area->GetFlags().HasFlag(AreaFlags::IsSubzone))
356 m_zoneId = area->ParentAreaID;
357 m_outdoors = data.outdoors;
358 m_staticFloorZ = data.floorZ;
361}
368
370{
371 if (!IsInWorld())
372 return;
373
375
377}
378
380{
381 switch (GetZoneId())
382 {
383 case 4197: // Wintergrasp
384 case 5095: // Tol Barad
385 case 6941: // Ashran
386 return true;
387 break;
388 default:
389 return false;
390 break;
391 }
392}
393
395{
396 Map* map = GetMap();
397 return map->IsDungeon() ? ((InstanceMap*)map)->GetInstanceScript() : nullptr;
398}
399
401{
402 float dz = std::fabs(GetPositionZ() - obj->GetPositionZ());
403 float sizefactor = GetCombatReach() + obj->GetCombatReach();
404 float dist = dz - sizefactor;
405 return (dist > 0 ? dist : 0);
406}
407
408bool WorldObject::_IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D, bool incOwnRadius, bool incTargetRadius) const
409{
410 float sizefactor = 0;
411 sizefactor += incOwnRadius ? GetCombatReach() : 0.0f;
412 sizefactor += incTargetRadius ? obj->GetCombatReach() : 0.0f;
413 float maxdist = dist2compare + sizefactor;
414
415 Position const* thisOrTransport = this;
416 Position const* objOrObjTransport = obj;
417
418 if (GetTransport() && GetTransport() == obj->GetTransport())
419 {
420 thisOrTransport = &m_movementInfo.transport.pos;
421 objOrObjTransport = &obj->m_movementInfo.transport.pos;
422 }
423
424 if (is3D)
425 return thisOrTransport->IsInDist(objOrObjTransport, maxdist);
426 else
427 return thisOrTransport->IsInDist2d(objOrObjTransport, maxdist);
428}
429
431{
432 float d = GetExactDist(obj) - GetCombatReach() - obj->GetCombatReach();
433 return d > 0.0f ? d : 0.0f;
434}
435
436float WorldObject::GetDistance(Position const& pos) const
437{
438 float d = GetExactDist(&pos) - GetCombatReach();
439 return d > 0.0f ? d : 0.0f;
440}
441
442float WorldObject::GetDistance(float x, float y, float z) const
443{
444 float d = GetExactDist(x, y, z) - GetCombatReach();
445 return d > 0.0f ? d : 0.0f;
446}
447
449{
450 float d = GetExactDist2d(obj) - GetCombatReach() - obj->GetCombatReach();
451 return d > 0.0f ? d : 0.0f;
452}
453
454float WorldObject::GetDistance2d(float x, float y) const
455{
456 float d = GetExactDist2d(x, y) - GetCombatReach();
457 return d > 0.0f ? d : 0.0f;
458}
459
461{
462 if (this == obj)
463 return true;
464 return IsInMap(obj);
465}
466
467bool WorldObject::IsInMap(WorldObject const* obj) const
468{
469 if (obj)
470 return IsInWorld() && obj->IsInWorld() && (GetMap() == obj->GetMap());
471 return false;
472}
473
474bool WorldObject::IsWithinDist3d(float x, float y, float z, float dist) const
475{
476 return IsInDist(x, y, z, dist + GetCombatReach());
477}
478
479bool WorldObject::IsWithinDist3d(Position const* pos, float dist) const
480{
481 return IsInDist(pos, dist + GetCombatReach());
482}
483
484bool WorldObject::IsWithinDist2d(float x, float y, float dist) const
485{
486 return IsInDist2d(x, y, dist + GetCombatReach());
487}
488
489bool WorldObject::IsWithinDist2d(Position const* pos, float dist) const
490{
491 return IsInDist2d(pos, dist + GetCombatReach());
492}
493
494bool WorldObject::IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D /*= true*/, bool incOwnRadius /*= true*/, bool incTargetRadius /*= true*/) const
495{
496 return obj && _IsWithinDist(obj, dist2compare, is3D, incOwnRadius, incTargetRadius);
497}
498
499bool WorldObject::IsWithinDistInMap(WorldObject const* obj, float dist2compare, bool is3D /*= true*/, bool incOwnRadius /*= true*/, bool incTargetRadius /*= true*/) const
500{
501 return obj && IsInMap(obj) && InSamePhase(obj) && _IsWithinDist(obj, dist2compare, is3D, incOwnRadius, incTargetRadius);
502}
503
505{
506 G3D::Vector3 vThis(GetPositionX(), GetPositionY(), GetPositionZ() + GetCollisionHeight());
507 G3D::Vector3 vObj(dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ());
508 G3D::Vector3 contactPoint = vThis + (vObj - vThis).directionOrZero() * std::min(dest.GetExactDist(GetPosition()), GetCombatReach());
509
510 return Position(contactPoint.x, contactPoint.y, contactPoint.z, GetAbsoluteAngle(contactPoint.x, contactPoint.y));
511}
512
513bool WorldObject::IsWithinLOS(float ox, float oy, float oz, LineOfSightChecks checks, VMAP::ModelIgnoreFlags ignoreFlags) const
514{
515 if (IsInWorld())
516 {
517 oz += GetCollisionHeight();
518 float x, y, z;
519 if (GetTypeId() == TYPEID_PLAYER)
520 {
521 GetPosition(x, y, z);
522 z += GetCollisionHeight();
523 }
524 else
525 GetHitSpherePointFor({ ox, oy, oz }, x, y, z);
526
527 return GetMap()->isInLineOfSight(GetPhaseShift(), x, y, z, ox, oy, oz, checks, ignoreFlags);
528 }
529
530 return true;
531}
532
534{
535 if (!IsInMap(obj))
536 return false;
537
538 float ox, oy, oz;
539 if (obj->GetTypeId() == TYPEID_PLAYER)
540 {
541 obj->GetPosition(ox, oy, oz);
542 oz += GetCollisionHeight();
543 }
544 else
546
547 float x, y, z;
548 if (GetTypeId() == TYPEID_PLAYER)
549 {
550 GetPosition(x, y, z);
551 z += GetCollisionHeight();
552 }
553 else
554 GetHitSpherePointFor({ obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ() + obj->GetCollisionHeight() }, x, y, z);
555
556 return GetMap()->isInLineOfSight(GetPhaseShift(), x, y, z, ox, oy, oz, checks, ignoreFlags);
557}
558
559void WorldObject::GetHitSpherePointFor(Position const& dest, float& x, float& y, float& z) const
560{
561 Position pos = GetHitSpherePointFor(dest);
562 x = pos.GetPositionX();
563 y = pos.GetPositionY();
564 z = pos.GetPositionZ();
565}
566
567bool WorldObject::GetDistanceOrder(WorldObject const* obj1, WorldObject const* obj2, bool is3D /* = true */) const
568{
569 float dx1 = GetPositionX() - obj1->GetPositionX();
570 float dy1 = GetPositionY() - obj1->GetPositionY();
571 float distsq1 = dx1*dx1 + dy1*dy1;
572 if (is3D)
573 {
574 float dz1 = GetPositionZ() - obj1->GetPositionZ();
575 distsq1 += dz1*dz1;
576 }
577
578 float dx2 = GetPositionX() - obj2->GetPositionX();
579 float dy2 = GetPositionY() - obj2->GetPositionY();
580 float distsq2 = dx2*dx2 + dy2*dy2;
581 if (is3D)
582 {
583 float dz2 = GetPositionZ() - obj2->GetPositionZ();
584 distsq2 += dz2*dz2;
585 }
586
587 return distsq1 < distsq2;
588}
589
590bool WorldObject::IsInRange(WorldObject const* obj, float minRange, float maxRange, bool is3D /* = true */) const
591{
592 float dx = GetPositionX() - obj->GetPositionX();
593 float dy = GetPositionY() - obj->GetPositionY();
594 float distsq = dx*dx + dy*dy;
595 if (is3D)
596 {
597 float dz = GetPositionZ() - obj->GetPositionZ();
598 distsq += dz*dz;
599 }
600
601 float sizefactor = GetCombatReach() + obj->GetCombatReach();
602
603 // check only for real range
604 if (minRange > 0.0f)
605 {
606 float mindist = minRange + sizefactor;
607 if (distsq < mindist * mindist)
608 return false;
609 }
610
611 float maxdist = maxRange + sizefactor;
612 return distsq < maxdist * maxdist;
613}
614
615bool WorldObject::IsInRange2d(Position const* pos, float minRange, float maxRange) const
616{
617 float distsq = GetExactDist2dSq(pos);
618
619 float sizefactor = GetCombatReach();
620
621 // check only for real range
622 if (minRange > 0.0f)
623 {
624 float mindist = minRange + sizefactor;
625 if (distsq < mindist * mindist)
626 return false;
627 }
628
629 float maxdist = maxRange + sizefactor;
630 return distsq < maxdist * maxdist;
631}
632
633bool WorldObject::IsInRange3d(Position const* pos, float minRange, float maxRange) const
634{
635 float distsq = GetExactDistSq(pos);
636
637 float sizefactor = GetCombatReach();
638
639 // check only for real range
640 if (minRange > 0.0f)
641 {
642 float mindist = minRange + sizefactor;
643 if (distsq < mindist * mindist)
644 return false;
645 }
646
647 float maxdist = maxRange + sizefactor;
648 return distsq < maxdist * maxdist;
649}
650
651bool WorldObject::IsInBetween(Position const& pos1, Position const& pos2, float size) const
652{
653 float dist = GetExactDist2d(pos1);
654
655 // not using sqrt() for performance
656 if ((dist * dist) >= pos1.GetExactDist2dSq(pos2))
657 return false;
658
659 if (!size)
660 size = GetCombatReach() / 2;
661
662 float angle = pos1.GetAbsoluteAngle(pos2);
663
664 // not using sqrt() for performance
665 return (size * size) >= GetExactDist2dSq(pos1.GetPositionX() + std::cos(angle) * dist, pos1.GetPositionY() + std::sin(angle) * dist);
666}
667
668bool WorldObject::isInFront(WorldObject const* target, float arc) const
669{
670 return HasInArc(arc, target);
671}
672
673bool WorldObject::isInBack(WorldObject const* target, float arc) const
674{
675 return !HasInArc(2 * float(M_PI) - arc, target);
676}
677
678Position WorldObject::GetRandomPoint(Position const& srcPos, float distance, float minDistance /*= 0.0f*/) const
679{
680 float x, y, z;
681 srcPos.GetPosition(x, y, z);
682 if (distance)
683 {
684 // angle to face `obj` to `this`
685 float angle = rand_norm() * static_cast<float>(2 * M_PI);
686 float new_dist = minDistance + (distance - minDistance) * std::sqrt(rand_norm());
687
688 x += new_dist * std::cos(angle);
689 y += new_dist * std::sin(angle);
690
693 UpdateGroundPositionZ(x, y, z); // update to LOS height if available
694 }
695 return Position(x, y, z, GetOrientation());
696}
697
698void WorldObject::UpdateGroundPositionZ(float x, float y, float &z) const
699{
700 float new_z = GetMapHeight(x, y, z);
701 if (new_z > INVALID_HEIGHT)
702 {
703 z = new_z;
704 if (Unit const* unit = ToUnit())
705 z += unit->GetHoverOffset();
706 }
707}
708
709void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z, float* groundZ) const
710{
711 // TODO: Allow transports to be part of dynamic vmap tree
712 if (GetTransport())
713 {
714 if (groundZ)
715 *groundZ = z;
716
717 return;
718 }
719
720 if (Unit const* unit = ToUnit())
721 {
722 if (!unit->CanFly())
723 {
724 bool canSwim = unit->CanSwim();
725 float ground_z = z;
726 float max_z;
727 if (canSwim)
728 max_z = GetMapWaterOrGroundLevel(x, y, z, &ground_z);
729 else
730 max_z = ground_z = GetMapHeight(x, y, z);
731
732 if (max_z > INVALID_HEIGHT)
733 {
734 // hovering units cannot go below their hover height
735 float hoverOffset = unit->GetHoverOffset();
736 max_z += hoverOffset;
737 ground_z += hoverOffset;
738
739 if (z > max_z)
740 z = max_z;
741 else if (z < ground_z)
742 z = ground_z;
743 }
744
745 if (groundZ)
746 *groundZ = ground_z;
747 }
748 else
749 {
750 float ground_z = GetMapHeight(x, y, z) + unit->GetHoverOffset();
751 if (z < ground_z)
752 z = ground_z;
753
754 if (groundZ)
755 *groundZ = ground_z;
756 }
757 }
758 else
759 {
760 float ground_z = GetMapHeight(x, y, z);
761 if (ground_z > INVALID_HEIGHT)
762 z = ground_z;
763
764 if (groundZ)
765 *groundZ = ground_z;
766 }
767}
768
770{
771 if (isActiveObject())
772 {
773 if (GetTypeId() == TYPEID_PLAYER && ToPlayer()->GetCinematicMgr()->IsOnCinematic())
775
776 return GetMap()->GetVisibilityRange();
777 }
778
779 if (Creature const* thisCreature = ToCreature())
780 return thisCreature->m_SightDistance;
781
782 return 0.0f;
783}
784
786{
789 else if (IsFarVisible() && !ToPlayer())
791 else
792 return GetMap()->GetVisibilityRange();
793}
794
795float WorldObject::GetSightRange(WorldObject const* target) const
796{
797 if (IsUnit())
798 {
799 if (Player const* player = ToPlayer())
800 {
801 if (target && !target->IsPlayer())
802 {
803 if (target->IsVisibilityOverridden())
804 return *target->m_visibilityDistanceOverride;
805 if (target->IsFarVisible())
807 }
808
809 if (player->GetCinematicMgr()->IsOnCinematic())
811
812 return GetMap()->GetVisibilityRange();
813 }
814
815 if (Creature const* creature = ToCreature())
816 return creature->m_SightDistance;
817
818 return SIGHT_RANGE_UNIT;
819 }
820
821 if (IsDynObject() && isActiveObject())
822 return GetMap()->GetVisibilityRange();
823
824 return 0.0f;
825}
826
828{
829 if (!IsPrivateObject())
830 return true;
831
832 // Owner of this private object
833 if (_privateObjectOwner == seer->GetGUID())
834 return true;
835
836 // Another private object of the same owner
838 return true;
839
840 if (Player const* playerSeer = seer->ToPlayer())
841 if (playerSeer->IsInGroup(_privateObjectOwner))
842 return true;
843
844 return false;
845}
846
848{
849 if (!_smoothPhasing)
850 _smoothPhasing = std::make_unique<SmoothPhasing>();
851
852 return _smoothPhasing.get();
853}
854
855bool WorldObject::CanSeeOrDetect(WorldObject const* obj, CanSeeOrDetectExtraArgs const& args /*= { }*/) const
856{
857 if (this == obj)
858 return true;
859
860 if (obj->IsNeverVisibleFor(this, args.ImplicitDetection) || CanNeverSee(obj, args.IgnorePhaseShift))
861 return false;
862
863 if (obj->IsAlwaysVisibleFor(this) || CanAlwaysSee(obj))
864 return true;
865
867 return false;
868
869 if (SmoothPhasing const* smoothPhasing = obj->GetSmoothPhasing())
870 if (smoothPhasing->IsBeingReplacedForSeer(GetGUID()))
871 return false;
872
873 if (!obj->IsPrivateObject() && !sConditionMgr->IsObjectMeetingVisibilityByObjectIdConditions(obj, this))
874 return false;
875
876 // Spawn tracking
878 if (Player const* player = ToPlayer())
879 if (SpawnTrackingStateData const* spawnTrackingStateData = obj->GetSpawnTrackingStateDataForPlayer(player))
880 if (!spawnTrackingStateData->Visible)
881 return false;
882
883 bool corpseVisibility = false;
884 if (args.DistanceCheck)
885 {
886 bool corpseCheck = false;
887 if (Player const* thisPlayer = ToPlayer())
888 {
889 if (thisPlayer->isDead() && thisPlayer->GetHealth() > 0 && // Cheap way to check for ghost state
891 {
892 if (Corpse* corpse = thisPlayer->GetCorpse())
893 {
894 corpseCheck = true;
895 if (corpse->IsWithinDist(thisPlayer, GetSightRange(obj), false))
896 if (corpse->IsWithinDist(obj, GetSightRange(obj), false))
897 corpseVisibility = true;
898 }
899 }
900
901 if (Unit const* target = obj->ToUnit())
902 {
903 // Don't allow to detect vehicle accessories if you can't see vehicle
904 if (Unit const* vehicle = target->GetVehicleBase())
905 if (!thisPlayer->HaveAtClient(vehicle))
906 return false;
907 }
908 }
909
910 WorldObject const* viewpoint = this;
911 if (Player const* player = ToPlayer())
912 viewpoint = player->GetViewpoint();
913
914 if (!viewpoint)
915 viewpoint = this;
916
917 if (!corpseCheck && !viewpoint->IsWithinDist(obj, GetSightRange(obj), false))
918 return false;
919 }
920
921 // GM visibility off or hidden NPC
923 {
924 // Stop checking other things for GMs
926 return true;
927 }
928 else
930
931 // Ghost players, Spirit Healers, and some other NPCs
933 {
934 // Alive players can see dead players in some cases, but other objects can't do that
935 if (Player const* thisPlayer = ToPlayer())
936 {
937 if (Player const* objPlayer = obj->ToPlayer())
938 {
939 if (!thisPlayer->IsGroupVisibleFor(objPlayer))
940 return false;
941 }
942 else
943 return false;
944 }
945 else
946 return false;
947 }
948
949 if (obj->IsInvisibleDueToDespawn(this))
950 return false;
951
952 if (!CanDetect(obj, args.ImplicitDetection, args.AlertCheck))
953 return false;
954
955 return true;
956}
957
958bool WorldObject::CanNeverSee(WorldObject const* obj, bool ignorePhaseShift /*= false*/) const
959{
960 return GetMap() != obj->GetMap() || (!ignorePhaseShift && !InSamePhase(obj));
961}
962
963bool WorldObject::CanDetect(WorldObject const* obj, bool implicitDetect, bool checkAlert) const
964{
965 WorldObject const* seer = this;
966
967 // If a unit is possessing another one, it uses the detection of the latter
968 // Pets don't have detection, they use the detection of their masters
969 if (Unit const* thisUnit = ToUnit())
970 {
971 if (thisUnit->isPossessing())
972 {
973 if (Unit* charmed = thisUnit->GetCharmed())
974 seer = charmed;
975 }
976 else if (Unit* controller = thisUnit->GetCharmerOrOwner())
977 seer = controller;
978 }
979
980 if (obj->IsAlwaysDetectableFor(seer))
981 return true;
982
983 if (!implicitDetect && !seer->CanDetectInvisibilityOf(obj))
984 return false;
985
986 if (!implicitDetect && !seer->CanDetectStealthOf(obj, checkAlert))
987 return false;
988
989 return true;
990}
991
993{
995
996 // Check for not detected types
997 if (mask != obj->m_invisibility.GetFlags())
998 return false;
999
1000 // It isn't possible in invisibility to detect something that can't detect the invisible object
1001 // (it's at least true for spell: 66)
1002 // It seems like that only Units are affected by this check (couldn't see arena doors with preparation invisibility)
1003 if (obj->IsUnit() && (!IsUnit() || !ToUnit()->HasAuraType(SPELL_AURA_DETECT_VISIBLE_WHILE_INVISIBLE)))
1005 return false;
1006
1007 for (uint32 i = 0; i < TOTAL_INVISIBILITY_TYPES; ++i)
1008 {
1009 if (!(mask & (uint64(1) << i)))
1010 continue;
1011
1012 int32 objInvisibilityValue = obj->m_invisibility.GetValue(InvisibilityType(i));
1013 int32 ownInvisibilityDetectValue = m_invisibilityDetect.GetValue(InvisibilityType(i));
1014
1015 // Too low value to detect
1016 if (ownInvisibilityDetectValue < objInvisibilityValue)
1017 return false;
1018 }
1019
1020 return true;
1021}
1022
1023bool WorldObject::CanDetectStealthOf(WorldObject const* obj, bool checkAlert) const
1024{
1025 // Combat reach is the minimal distance (both in front and behind),
1026 // and it is also used in the range calculation.
1027 // One stealth point increases the visibility range by 0.3 yard.
1028
1029 if (!obj->m_stealth.GetFlags())
1030 return true;
1031
1032 float distance = GetExactDist(obj);
1033 float combatReach = 0.0f;
1034
1035 Unit const* unit = ToUnit();
1036 if (unit)
1037 combatReach = unit->GetCombatReach();
1038
1039 if (distance < combatReach)
1040 return true;
1041
1042 // Only check back for units, it does not make sense for gameobjects
1043 if (unit && !HasInArc(float(M_PI), obj))
1044 return false;
1045
1046 // Traps should detect stealth always
1047 if (GameObject const* go = ToGameObject())
1048 if (go->GetGoType() == GAMEOBJECT_TYPE_TRAP)
1049 return true;
1050
1051 GameObject const* go = obj->ToGameObject();
1052 for (uint32 i = 0; i < TOTAL_STEALTH_TYPES; ++i)
1053 {
1054 if (!(obj->m_stealth.GetFlags() & (1 << i)))
1055 continue;
1056
1058 return true;
1059
1060 // Starting points
1061 int32 detectionValue = 30;
1062
1063 // Level difference: 5 point / level, starting from level 1.
1064 // There may be spells for this and the starting points too, but
1065 // not in the DBCs of the client.
1066 detectionValue += int32(GetLevelForTarget(obj) - 1) * 5;
1067
1068 // Apply modifiers
1069 detectionValue += m_stealthDetect.GetValue(StealthType(i));
1070 if (go)
1071 if (Unit* owner = go->GetOwner())
1072 detectionValue -= int32(owner->GetLevelForTarget(this) - 1) * 5;
1073
1074 detectionValue -= obj->m_stealth.GetValue(StealthType(i));
1075
1076 // Calculate max distance
1077 float visibilityRange = float(detectionValue) * 0.3f + combatReach;
1078
1079 // If this unit is an NPC then player detect range doesn't apply
1080 if (unit && unit->GetTypeId() == TYPEID_PLAYER && visibilityRange > MAX_PLAYER_STEALTH_DETECT_RANGE)
1081 visibilityRange = MAX_PLAYER_STEALTH_DETECT_RANGE;
1082
1083 // When checking for alert state, look 8% further, and then 1.5 yards more than that.
1084 if (checkAlert)
1085 visibilityRange += (visibilityRange * 0.08f) + 1.5f;
1086
1087 // If checking for alert, and creature's visibility range is greater than aggro distance, No alert
1088 Unit const* tunit = obj->ToUnit();
1089 if (checkAlert && unit && unit->ToCreature() && visibilityRange >= unit->ToCreature()->GetAttackDistance(tunit) + unit->ToCreature()->m_CombatDistance)
1090 return false;
1091
1092 if (distance > visibilityRange)
1093 return false;
1094 }
1095
1096 return true;
1097}
1098
1099void WorldObject::SendMessageToSet(WorldPacket const* data, bool self) const
1100{
1101 if (IsInWorld())
1103}
1104
1105void WorldObject::SendMessageToSetInRange(WorldPacket const* data, float dist, bool /*self*/) const
1106{
1107 Trinity::PacketSenderRef sender(data);
1109 Cell::VisitWorldObjects(this, notifier, dist);
1110}
1111
1112void WorldObject::SendMessageToSet(WorldPacket const* data, Player const* skipped_rcvr) const
1113{
1114 Trinity::PacketSenderRef sender(data);
1115 Trinity::MessageDistDeliverer<Trinity::PacketSenderRef> notifier(this, sender, GetVisibilityRange(), false, skipped_rcvr);
1117}
1118
1120{
1122
1124 : i_message(msg)
1125 {
1126 msg->Write();
1127 }
1128
1129 void operator()(Player const* player) const
1130 {
1131 if (player->IsAdvancedCombatLoggingEnabled())
1133 else
1135 }
1136};
1137
1139{
1140 CombatLogSender combatLogSender(combatLog);
1141
1142 if (Player const* self = ToPlayer())
1143 combatLogSender(self);
1144
1145 Trinity::MessageDistDeliverer<CombatLogSender> notifier(this, combatLogSender, GetVisibilityRange());
1147}
1148
1150{
1151 ASSERT(map);
1152 ASSERT(!IsInWorld());
1153 if (m_currMap == map) // command add npc: first create, than loadfromdb
1154 return;
1155 if (m_currMap)
1156 {
1157 TC_LOG_FATAL("misc", "WorldObject::SetMap: obj {} new map {} {}, old map {} {}", (uint32)GetTypeId(), map->GetId(), map->GetInstanceId(), m_currMap->GetId(), m_currMap->GetInstanceId());
1158 ABORT();
1159 }
1160 m_currMap = map;
1161 m_mapId = map->GetId();
1162 m_InstanceId = map->GetInstanceId();
1165}
1166
1168{
1170 ASSERT(!IsInWorld());
1173 m_currMap = nullptr;
1174 //maybe not for corpse
1175 //m_mapId = 0;
1176 //m_InstanceId = 0;
1177}
1178
1180{
1181 Map* map = FindMap();
1182 if (!map)
1183 {
1184 TC_LOG_ERROR("misc", "Object {} at attempt add to move list not have valid map (Id: {}).", GetGUID().ToString(), GetMapId());
1185 return;
1186 }
1187
1188 map->AddObjectToRemoveList(this);
1189}
1190
1191TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropertiesEntry const* properties /*= nullptr*/, Milliseconds duration /*= 0ms*/, WorldObject* summoner /*= nullptr*/, uint32 spellId /*= 0*/, uint32 vehId /*= 0*/, ObjectGuid privateObjectOwner /*= ObjectGuid::Empty*/, SmoothPhasingInfo const* smoothPhasingInfo /* = nullptr*/)
1192{
1193 uint32 mask = UNIT_MASK_SUMMON;
1194 if (properties)
1195 {
1196 switch (properties->Control)
1197 {
1199 mask = UNIT_MASK_GUARDIAN;
1200 break;
1202 mask = UNIT_MASK_PUPPET;
1203 break;
1206 mask = UNIT_MASK_MINION;
1207 break;
1210 {
1211 switch (SummonTitle(properties->Title))
1212 {
1216 mask = UNIT_MASK_GUARDIAN;
1217 break;
1218 case SummonTitle::Totem:
1220 mask = UNIT_MASK_TOTEM;
1221 break;
1223 case SummonTitle::Mount:
1224 mask = UNIT_MASK_SUMMON;
1225 break;
1227 mask = UNIT_MASK_MINION;
1228 break;
1229 default:
1231 mask = UNIT_MASK_GUARDIAN;
1232 break;
1233 }
1234 break;
1235 }
1236 default:
1237 return nullptr;
1238 }
1239 }
1240
1241 Unit* summonerUnit = summoner ? summoner->ToUnit() : nullptr;
1242
1243 TempSummon* summon = nullptr;
1244 switch (mask)
1245 {
1246 case UNIT_MASK_SUMMON:
1247 summon = new TempSummon(properties, summoner, false);
1248 break;
1249 case UNIT_MASK_GUARDIAN:
1250 summon = new Guardian(properties, summonerUnit, false);
1251 break;
1252 case UNIT_MASK_PUPPET:
1253 summon = new Puppet(properties, summonerUnit);
1254 break;
1255 case UNIT_MASK_TOTEM:
1256 summon = new Totem(properties, summonerUnit);
1257 break;
1258 case UNIT_MASK_MINION:
1259 summon = new Minion(properties, summonerUnit, false);
1260 break;
1261 }
1262
1263 if (!summon->Create(GenerateLowGuid<HighGuid::Creature>(), this, entry, pos, nullptr, vehId, true))
1264 {
1265 delete summon;
1266 return nullptr;
1267 }
1268
1269 TransportBase* transport = summoner ? summoner->GetTransport() : nullptr;
1270 if (transport)
1271 {
1272 // This object must be added to transport before adding to map for the client to properly display it
1273 transport->AddPassenger(summon, transport->GetPositionOffsetTo(pos));
1274 }
1275
1276 if (summoner && !(properties && properties->GetFlags().HasFlag(SummonPropertiesFlags::IgnoreSummonerPhase)))
1277 PhasingHandler::InheritPhaseShift(summon, summoner);
1278
1279 summon->SetCreatedBySpell(spellId);
1280
1281 summon->SetHomePosition(pos);
1282
1283 summon->InitStats(summoner, duration);
1284
1285 summon->SetPrivateObjectOwner(privateObjectOwner);
1286
1287 if (smoothPhasingInfo)
1288 {
1289 if (summoner && smoothPhasingInfo->ReplaceObject)
1290 {
1291 if (WorldObject* replacedObject = ObjectAccessor::GetWorldObject(*summoner, *smoothPhasingInfo->ReplaceObject))
1292 {
1293 SmoothPhasingInfo originalSmoothPhasingInfo = *smoothPhasingInfo;
1294 originalSmoothPhasingInfo.ReplaceObject = summon->GetGUID();
1295 replacedObject->GetOrCreateSmoothPhasing()->SetViewerDependentInfo(privateObjectOwner, originalSmoothPhasingInfo);
1296
1297 summon->SetDemonCreatorGUID(privateObjectOwner);
1298 }
1299 }
1300
1301 summon->GetOrCreateSmoothPhasing()->SetSingleInfo(*smoothPhasingInfo);
1302 }
1303
1304 if (!AddToMap(summon->ToCreature()))
1305 {
1306 // Returning false will cause the object to be deleted - remove from transport
1307 if (transport)
1308 transport->RemovePassenger(summon);
1309
1310 delete summon;
1311 return nullptr;
1312 }
1313
1314 summon->InitSummon(summoner);
1315
1316 // call MoveInLineOfSight for nearby creatures
1317 Trinity::AIRelocationNotifier notifier(*summon);
1318 Cell::VisitAllObjects(summon, notifier, GetVisibilityRange());
1319
1320 return summon;
1321}
1322
1323template <std::invocable<TempSummonData const&> SummonCreature>
1324static void SummonCreatureGroup(uint32 summonerId, SummonerType summonerType, uint8 group, std::list<TempSummon*>* summoned, SummonCreature summonCreature)
1325{
1326 std::vector<TempSummonData> const* data = sObjectMgr->GetSummonGroup(summonerId, summonerType, group);
1327 if (!data)
1328 {
1329 TC_LOG_WARN("scripts", "Summoner {} type {} tried to summon non-existing summon group {}.", summonerId, summonerType, group);
1330 return;
1331 }
1332
1333 std::vector<TempSummon*> summons;
1334 summons.reserve(data->size());
1335
1336 for (TempSummonData const& tempSummonData : *data)
1337 if (TempSummon* summon = summonCreature(tempSummonData))
1338 summons.push_back(summon);
1339
1340 CreatureGroup* creatureGroup = new CreatureGroup(0);
1341 for (TempSummon* summon : summons)
1342 {
1343 if (!summon->IsInWorld()) // evil script might despawn a summon
1344 continue;
1345
1346 creatureGroup->AddMember(summon);
1347 if (summoned)
1348 summoned->push_back(summon);
1349 }
1350
1351 if (creatureGroup->IsEmpty())
1352 delete creatureGroup;
1353}
1354
1362void Map::SummonCreatureGroup(uint8 group, std::list<TempSummon*>* list /*= nullptr*/)
1363{
1364 ::SummonCreatureGroup(GetId(), SUMMONER_TYPE_MAP, group, list, [&](TempSummonData const& tempSummonData)
1365 {
1366 return SummonCreature(tempSummonData.entry, tempSummonData.pos, nullptr, tempSummonData.time);
1367 });
1368}
1369
1371{
1372 if (Map* map = FindMap())
1373 {
1374 if (InstanceMap* instanceMap = map->ToInstanceMap())
1375 return reinterpret_cast<ZoneScript*>(instanceMap->GetInstanceScript());
1376 if (BattlegroundMap* bgMap = map->ToBattlegroundMap())
1377 return reinterpret_cast<ZoneScript*>(bgMap->GetBattlegroundScript());
1378 if (!map->IsBattlegroundOrArena())
1379 {
1380 if (Battlefield* bf = sBattlefieldMgr->GetBattlefieldToZoneId(map, GetZoneId()))
1381 return bf;
1382
1383 return sOutdoorPvPMgr->GetOutdoorPvPToZoneId(map, GetZoneId());
1384 }
1385 }
1386 return nullptr;
1387}
1388
1393
1395{
1396 if (IsInWorld())
1397 if (InstanceMap* instanceMap = GetMap()->ToInstanceMap())
1398 return instanceMap->GetInstanceScenario();
1399
1400 return nullptr;
1401}
1402
1403TempSummon* WorldObject::SummonCreature(uint32 entry, Position const& pos, TempSummonType despawnType /*= TEMPSUMMON_MANUAL_DESPAWN*/, Milliseconds despawnTime /*= 0s*/, uint32 vehId /*= 0*/, uint32 spellId /*= 0*/, ObjectGuid privateObjectOwner /* = ObjectGuid::Empty */)
1404{
1405 if (Map* map = FindMap())
1406 {
1407 if (TempSummon* summon = map->SummonCreature(entry, pos, nullptr, despawnTime, this, spellId, vehId, privateObjectOwner))
1408 {
1409 summon->SetTempSummonType(despawnType);
1410 return summon;
1411 }
1412 }
1413
1414 return nullptr;
1415}
1416
1417TempSummon* WorldObject::SummonCreature(uint32 id, float x, float y, float z, float o /*= 0*/, TempSummonType despawnType /*= TEMPSUMMON_MANUAL_DESPAWN*/, Milliseconds despawnTime /*= 0s*/, ObjectGuid privateObjectOwner /* = ObjectGuid::Empty */)
1418{
1419 if (!x && !y && !z)
1420 GetClosePoint(x, y, z, GetCombatReach());
1421 if (!o)
1422 o = GetOrientation();
1423 return SummonCreature(id, { x,y,z,o }, despawnType, despawnTime, 0, 0, privateObjectOwner);
1424}
1425
1426TempSummon* WorldObject::SummonPersonalClone(Position const& pos, TempSummonType despawnType /*= TEMPSUMMON_MANUAL_DESPAWN*/, Milliseconds despawnTime /*= 0s*/, uint32 vehId /*= 0*/, uint32 spellId /*= 0*/, Player* privateObjectOwner /*= nullptr*/)
1427{
1428 ASSERT(privateObjectOwner);
1429
1430 if (Map* map = FindMap())
1431 {
1432 SmoothPhasingInfo smoothPhasingInfo{GetGUID(), true, true};
1433 if (TempSummon* summon = map->SummonCreature(GetEntry(), pos, nullptr, despawnTime, privateObjectOwner, spellId, vehId, privateObjectOwner->GetGUID(), &smoothPhasingInfo))
1434 {
1435 summon->SetTempSummonType(despawnType);
1436
1437 if (Creature* thisCreature = ToCreature())
1438 summon->InheritStringIds(thisCreature);
1439 return summon;
1440 }
1441 }
1442
1443 return nullptr;
1444}
1445
1446GameObject* WorldObject::SummonGameObject(uint32 entry, Position const& pos, QuaternionData const& rot, Seconds respawnTime, GOSummonType summonType)
1447{
1448 if (!IsInWorld())
1449 return nullptr;
1450
1451 GameObjectTemplate const* goinfo = sObjectMgr->GetGameObjectTemplate(entry);
1452 if (!goinfo)
1453 {
1454 TC_LOG_ERROR("sql.sql", "Gameobject template {} not found in database!", entry);
1455 return nullptr;
1456 }
1457
1458 Map* map = GetMap();
1459 GameObject* go = GameObject::CreateGameObject(entry, map, pos, rot, 255, GO_STATE_READY);
1460 if (!go)
1461 return nullptr;
1462
1464
1465 go->SetRespawnTime(respawnTime.count());
1466 if (GetTypeId() == TYPEID_PLAYER || (GetTypeId() == TYPEID_UNIT && summonType == GO_SUMMON_TIMED_OR_CORPSE_DESPAWN)) //not sure how to handle this
1467 ToUnit()->AddGameObject(go);
1468 else
1469 go->SetSpawnedByDefault(false);
1470
1471 map->AddToMap(go);
1472 return go;
1473}
1474
1475GameObject* WorldObject::SummonGameObject(uint32 entry, float x, float y, float z, float ang, QuaternionData const& rot, Seconds respawnTime, GOSummonType summonType)
1476{
1477 if (!x && !y && !z)
1478 {
1479 GetClosePoint(x, y, z, GetCombatReach());
1480 ang = GetOrientation();
1481 }
1482
1483 Position pos(x, y, z, ang);
1484 return SummonGameObject(entry, pos, rot, respawnTime, summonType);
1485}
1486
1487Creature* WorldObject::SummonTrigger(float x, float y, float z, float ang, Milliseconds despawnTime, CreatureAI* (*GetAI)(Creature*))
1488{
1489 TempSummonType summonType = (despawnTime == 0s) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN;
1490 Creature* summon = SummonCreature(WORLD_TRIGGER, x, y, z, ang, summonType, despawnTime);
1491 if (!summon)
1492 return nullptr;
1493
1494 //summon->SetName(GetName());
1496 {
1497 summon->SetFaction(((Unit*)this)->GetFaction());
1498 summon->SetLevel(((Unit*)this)->GetLevel());
1499 }
1500
1501 if (GetAI)
1502 summon->AIM_Initialize(GetAI(summon));
1503 return summon;
1504}
1505
1512void WorldObject::SummonCreatureGroup(uint8 group, std::list<TempSummon*>* list /*= nullptr*/)
1513{
1514 ASSERT((GetTypeId() == TYPEID_GAMEOBJECT || GetTypeId() == TYPEID_UNIT) && "Only GOs and creatures can summon npc groups!");
1515
1517 {
1518 return SummonCreature(tempSummonData.entry, tempSummonData.pos, tempSummonData.type, tempSummonData.time);
1519 });
1520}
1521
1522Creature* WorldObject::FindNearestCreature(uint32 entry, float range, bool alive) const
1523{
1524 Creature* creature = nullptr;
1525 Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck checker(*this, entry, alive, range);
1527 Cell::VisitAllObjects(this, searcher, range);
1528 return creature;
1529}
1530
1532{
1533 Creature* creature = nullptr;
1534 Trinity::NearestCheckCustomizer checkCustomizer(*this, range);
1535 Trinity::CreatureWithOptionsInObjectRangeCheck checker(*this, checkCustomizer, options);
1536 Trinity::CreatureLastSearcher searcher(this, creature, checker);
1537 if (options.IgnorePhases)
1539
1540 Cell::VisitAllObjects(this, searcher, range);
1541 return creature;
1542}
1543
1544GameObject* WorldObject::FindNearestGameObject(uint32 entry, float range, bool spawnedOnly) const
1545{
1546 GameObject* go = nullptr;
1547 Trinity::NearestGameObjectEntryInObjectRangeCheck checker(*this, entry, range, spawnedOnly);
1549 Cell::VisitGridObjects(this, searcher, range);
1550 return go;
1551}
1552
1554{
1555 GameObject* go = nullptr;
1556 Trinity::NearestCheckCustomizer checkCustomizer(*this, range);
1557 Trinity::GameObjectWithOptionsInObjectRangeCheck checker(*this, checkCustomizer, options);
1558 Trinity::GameObjectLastSearcher searcher(this, go, checker);
1559 if (options.IgnorePhases)
1561
1562 Cell::VisitGridObjects(this, searcher, range);
1563 return go;
1564}
1565
1567{
1568 GameObject* go = nullptr;
1571 Cell::VisitGridObjects(this, searcher, range);
1572 return go;
1573}
1574
1576{
1577 GameObject* go = nullptr;
1578 Trinity::NearestGameObjectTypeInObjectRangeCheck checker(*this, type, range);
1580 Cell::VisitGridObjects(this, searcher, range);
1581 return go;
1582}
1583
1585{
1586 Player* target = nullptr;
1587
1588 Trinity::NearestPlayerInObjectRangeCheck checker(this, range);
1590 Cell::VisitWorldObjects(this, searcher, range);
1591
1592 return target;
1593}
1594
1596{
1598 if (!guid.IsEmpty())
1599 guid = GetGUID();
1600 return guid;
1601}
1602
1604{
1605 return ObjectAccessor::GetUnit(*this, GetOwnerGUID());
1606}
1607
1609{
1610 if (Unit const* unit = ToUnit())
1611 return unit->GetCharmerOrOwner();
1612 else if (GameObject const* go = ToGameObject())
1613 return go->GetOwner();
1614
1615 return nullptr;
1616}
1617
1619{
1620 if (Unit* u = GetCharmerOrOwner())
1621 return u;
1622
1623 return const_cast<WorldObject*>(this)->ToUnit();
1624}
1625
1627{
1629 if (guid.IsPlayer())
1630 return ObjectAccessor::GetPlayer(*this, guid);
1631
1632 return const_cast<WorldObject*>(this)->ToPlayer();
1633}
1634
1636{
1637 if (!GetCharmerOrOwnerGUID())
1638 return const_cast<WorldObject*>(this)->ToPlayer();
1639
1640 if (Unit* owner = GetCharmerOrOwner())
1642
1643 return nullptr;
1644}
1645
1647{
1648 if (Player* player = const_cast<WorldObject*>(this)->ToPlayer())
1649 return player;
1650
1651 if (GetTypeId() == TYPEID_UNIT)
1652 {
1653 Creature const* creature = ToCreature();
1654 if (creature->IsPet() || creature->IsTotem())
1655 {
1656 if (Unit* owner = creature->GetOwner())
1657 return owner->ToPlayer();
1658 }
1659 }
1660 else if (GetTypeId() == TYPEID_GAMEOBJECT)
1661 {
1662 GameObject const* go = ToGameObject();
1663 if (Unit* owner = go->GetOwner())
1664 return owner->ToPlayer();
1665 }
1666
1667 return nullptr;
1668}
1669
1671{
1672 bool positive = target ? !IsHostileTo(target) : true;
1673 return spellInfo->GetMinMaxRange(positive);
1674}
1675
1677{
1678 if (Player* modOwner = GetSpellModOwner())
1679 {
1680 modOwner->ApplySpellMod(spellInfo, SpellModOp::Points, value);
1681 switch (effIndex)
1682 {
1683 case EFFECT_0:
1684 modOwner->ApplySpellMod(spellInfo, SpellModOp::PointsIndex0, value);
1685 break;
1686 case EFFECT_1:
1687 modOwner->ApplySpellMod(spellInfo, SpellModOp::PointsIndex1, value);
1688 break;
1689 case EFFECT_2:
1690 modOwner->ApplySpellMod(spellInfo, SpellModOp::PointsIndex2, value);
1691 break;
1692 case EFFECT_3:
1693 modOwner->ApplySpellMod(spellInfo, SpellModOp::PointsIndex3, value);
1694 break;
1695 case EFFECT_4:
1696 modOwner->ApplySpellMod(spellInfo, SpellModOp::PointsIndex4, value);
1697 break;
1698 default:
1699 break;
1700 }
1701 }
1702 return value;
1703}
1704
1705int32 WorldObject::CalcSpellDuration(SpellInfo const* spellInfo, std::vector<SpellPowerCost> const* powerCosts) const
1706{
1707 int32 minduration = spellInfo->GetDuration();
1708 if (minduration <= 0)
1709 return minduration;
1710
1711 int32 maxduration = spellInfo->GetMaxDuration();
1712 if (minduration == maxduration)
1713 return minduration;
1714
1715 if (!powerCosts)
1716 return minduration;
1717
1718 auto consumedItr = std::ranges::find(*powerCosts, POWER_COMBO_POINTS, &SpellPowerCost::Power);
1719 if (consumedItr == powerCosts->end())
1720 return minduration;
1721
1722 return std::min(minduration + spellInfo->DurationEntry->DurationPerResource * consumedItr->Amount, maxduration);
1723}
1724
1725int32 WorldObject::ModSpellDuration(SpellInfo const* spellInfo, WorldObject const* target, int32 duration, bool positive, uint32 effectMask) const
1726{
1727 // don't mod permanent auras duration
1728 if (duration < 0)
1729 return duration;
1730
1731 // some auras are not affected by duration modifiers
1733 return duration;
1734
1735 // cut duration only of negative effects
1736 Unit const* unitTarget = target->ToUnit();
1737 if (!unitTarget)
1738 return duration;
1739
1740 if (!positive)
1741 {
1742 uint64 mechanicMask = spellInfo->GetSpellMechanicMaskByEffectMask(effectMask);
1743 auto mechanicCheck = [mechanicMask](AuraEffect const* aurEff) -> bool
1744 {
1745 if (mechanicMask & (UI64LIT(1) << aurEff->GetMiscValue()))
1746 return true;
1747 return false;
1748 };
1749
1750 // Find total mod value (negative bonus)
1751 int32 durationMod_always = unitTarget->GetTotalAuraModifier(SPELL_AURA_MECHANIC_DURATION_MOD, mechanicCheck);
1752 // Find max mod (negative bonus)
1753 int32 durationMod_not_stack = unitTarget->GetMaxNegativeAuraModifier(SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK, mechanicCheck);
1754
1755 // Select strongest negative mod
1756 int32 durationMod = std::min(durationMod_always, durationMod_not_stack);
1757 if (durationMod != 0)
1758 AddPct(duration, durationMod);
1759
1760 // there are only negative mods currently
1761 durationMod_always = unitTarget->GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL, spellInfo->Dispel);
1763
1764 durationMod = std::min(durationMod_always, durationMod_not_stack);
1765 if (durationMod != 0)
1766 AddPct(duration, durationMod);
1767 }
1768 else
1769 {
1770 // else positive mods here, there are no currently
1771 // when there will be, change GetTotalAuraModifierByMiscValue to GetMaxPositiveAuraModifierByMiscValue
1772
1773 // Mixology - duration boost
1774 if (unitTarget->GetTypeId() == TYPEID_PLAYER)
1775 {
1776 if (spellInfo->SpellFamilyName == SPELLFAMILY_POTION && (
1777 sSpellMgr->IsSpellMemberOfSpellGroup(spellInfo->Id, SPELL_GROUP_ELIXIR_BATTLE) ||
1778 sSpellMgr->IsSpellMemberOfSpellGroup(spellInfo->Id, SPELL_GROUP_ELIXIR_GUARDIAN)))
1779 {
1780 SpellEffectInfo const& effect = spellInfo->GetEffect(EFFECT_0);
1781 if (unitTarget->HasAura(53042) && unitTarget->HasSpell(effect.TriggerSpell))
1782 duration *= 2;
1783 }
1784 }
1785 }
1786
1787 return std::max(duration, 0);
1788}
1789
1790void WorldObject::ModSpellCastTime(SpellInfo const* spellInfo, int32& castTime, Spell* spell /*= nullptr*/) const
1791{
1792 if (!spellInfo || castTime < 0)
1793 return;
1794
1795 // called from caster
1796 if (Player* modOwner = GetSpellModOwner())
1797 modOwner->ApplySpellMod(spellInfo, SpellModOp::ChangeCastTime, castTime, spell);
1798
1799 Unit const* unitCaster = ToUnit();
1800 if (!unitCaster)
1801 return;
1802
1803 if (unitCaster->IsPlayer() && unitCaster->ToPlayer()->GetCommandStatus(CHEAT_CASTTIME))
1804 castTime = 0;
1806 ((GetTypeId() == TYPEID_PLAYER && spellInfo->SpellFamilyName) || GetTypeId() == TYPEID_UNIT))
1807 castTime = unitCaster->CanInstantCast() ? 0 : int32(float(castTime) * unitCaster->m_unitData->ModCastingSpeed);
1809 castTime = int32(float(castTime) * unitCaster->m_modAttackSpeedPct[BASE_ATTACK]);
1811 castTime = int32(float(castTime) * unitCaster->m_modAttackSpeedPct[RANGED_ATTACK]);
1812 else if (IsPartOfSkillLine(SKILL_COOKING, spellInfo->Id) && unitCaster->HasAura(67556)) // cooking with Chef Hat.
1813 castTime = 500;
1814}
1815
1816void WorldObject::ModSpellDurationTime(SpellInfo const* spellInfo, int32& duration, Spell* spell /*= nullptr*/) const
1817{
1818 if (!spellInfo || duration < 0)
1819 return;
1820
1821 if (spellInfo->IsChanneled()
1824 return;
1825
1826 // called from caster
1827 if (Player* modOwner = GetSpellModOwner())
1828 modOwner->ApplySpellMod(spellInfo, SpellModOp::ChangeCastTime, duration, spell);
1829
1830 Unit const* unitCaster = ToUnit();
1831 if (!unitCaster)
1832 return;
1833
1835 ((GetTypeId() == TYPEID_PLAYER && spellInfo->SpellFamilyName) || GetTypeId() == TYPEID_UNIT))
1836 duration = int32(float(duration) * unitCaster->m_unitData->ModCastingSpeed);
1838 duration = int32(float(duration) * unitCaster->m_modAttackSpeedPct[RANGED_ATTACK]);
1839}
1840
1841float WorldObject::MeleeSpellMissChance(Unit const* /*victim*/, WeaponAttackType /*attType*/, SpellInfo const* /*spellInfo*/) const
1842{
1843 return 0.0f;
1844}
1845
1846SpellMissInfo WorldObject::MeleeSpellHitResult(Unit* /*victim*/, SpellInfo const* /*spellInfo*/) const
1847{
1848 return SPELL_MISS_NONE;
1849}
1850
1852{
1853 // Can`t miss on dead target (on skinning for example)
1854 if (!victim->IsAlive() && victim->GetTypeId() != TYPEID_PLAYER)
1855 return SPELL_MISS_NONE;
1856
1857 if (spellInfo->HasAttribute(SPELL_ATTR3_NO_AVOIDANCE))
1858 return SPELL_MISS_NONE;
1859
1860 float missChance = [&]()
1861 {
1863 return 0.0f;
1864
1865 SpellSchoolMask schoolMask = spellInfo->GetSchoolMask();
1866 // PvP - PvE spell misschances per leveldif > 2
1867 int32 lchance = victim->GetTypeId() == TYPEID_PLAYER ? 7 : 11;
1868 int32 thisLevel = GetLevelForTarget(victim);
1869 if (GetTypeId() == TYPEID_UNIT && ToCreature()->IsTrigger())
1870 thisLevel = std::max<int32>(thisLevel, spellInfo->SpellLevel);
1871 int32 leveldif = int32(victim->GetLevelForTarget(this)) - thisLevel;
1872 int32 levelBasedHitDiff = leveldif;
1873
1874 // Base hit chance from attacker and victim levels
1875 float modHitChance = 100;
1876 if (levelBasedHitDiff >= 0)
1877 {
1878 if (victim->GetTypeId() != TYPEID_PLAYER)
1879 {
1880 modHitChance = 94 - 3 * std::min(levelBasedHitDiff, 3);
1881 levelBasedHitDiff -= 3;
1882 }
1883 else
1884 {
1885 modHitChance = 96 - std::min(levelBasedHitDiff, 2);
1886 levelBasedHitDiff -= 2;
1887 }
1888 if (levelBasedHitDiff > 0)
1889 modHitChance -= lchance * std::min(levelBasedHitDiff, 7);
1890 }
1891 else
1892 modHitChance = 97 - levelBasedHitDiff;
1893
1894 // Spellmod from SpellModOp::HitChance
1895 if (Player* modOwner = GetSpellModOwner())
1896 modOwner->ApplySpellMod(spellInfo, SpellModOp::HitChance, modHitChance);
1897
1898 // Spells with SPELL_ATTR3_IGNORE_HIT_RESULT will ignore target's avoidance effects
1899 if (!spellInfo->HasAttribute(SPELL_ATTR3_ALWAYS_HIT))
1900 {
1901 // Chance hit from victim SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE auras
1903 }
1904
1905 float HitChance = modHitChance;
1906 // Increase hit chance from attacker SPELL_AURA_MOD_SPELL_HIT_CHANCE and attacker ratings
1907 if (Unit const* unit = ToUnit())
1908 HitChance += unit->m_modSpellHitChance;
1909
1910 RoundToInterval(HitChance, 0.0f, 100.0f);
1911
1912 return 100.0f - HitChance;
1913 }();
1914
1915 int32 tmp = int32(missChance * 100.0f);
1916
1917 int32 rand = irand(0, 9999);
1918 if (tmp > 0 && rand < tmp)
1919 return SPELL_MISS_MISS;
1920
1921 // Chance resist mechanic (select max value from every mechanic spell effect)
1922 int32 resist_chance = victim->GetMechanicResistChance(spellInfo) * 100.0f;
1923
1924 // Roll chance
1925 if (resist_chance > 0 && rand < (tmp += resist_chance))
1926 return SPELL_MISS_RESIST;
1927
1928 // cast by caster in front of victim
1929 if (!victim->HasUnitState(UNIT_STATE_CONTROLLED) && (victim->HasInArc(float(M_PI), this) || victim->HasAuraType(SPELL_AURA_IGNORE_HIT_DIRECTION)))
1930 {
1931 int32 deflect_chance = victim->GetTotalAuraModifier(SPELL_AURA_DEFLECT_SPELLS) * 100.0f;
1932 if (deflect_chance > 0 && rand < (tmp += deflect_chance))
1933 return SPELL_MISS_DEFLECT;
1934 }
1935
1936 return SPELL_MISS_NONE;
1937}
1938
1939// Calculate spell hit result can be:
1940// Every spell can: Evade/Immune/Reflect/Sucesful hit
1941// For melee based spells:
1942// Miss
1943// Dodge
1944// Parry
1945// For spells
1946// Resist
1947SpellMissInfo WorldObject::SpellHitResult(Unit* victim, SpellInfo const* spellInfo, bool canReflect, bool canImmune) const
1948{
1949 // Check for immune
1950 if (canImmune && victim->IsImmunedToSpell(spellInfo, MAX_EFFECT_MASK, this))
1951 return SPELL_MISS_IMMUNE;
1952
1953 // Damage immunity is only checked if the spell has damage effects, this immunity must not prevent aura apply
1954 // returns SPELL_MISS_IMMUNE in that case, for other spells, the SMSG_SPELL_GO must show hit
1955 if (spellInfo->HasOnlyDamageEffects() && victim->IsImmunedToDamage(this, spellInfo))
1956 return SPELL_MISS_IMMUNE;
1957
1958 // All positive spells can`t miss
1960 if (spellInfo->IsPositive() && !IsHostileTo(victim)) // prevent from affecting enemy by "positive" spell
1961 return SPELL_MISS_NONE;
1962
1963 if (this == victim)
1964 return SPELL_MISS_NONE;
1965
1966 // Return evade for units in evade mode
1967 if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks())
1968 return SPELL_MISS_EVADE;
1969
1970 // Try victim reflect spell
1971 if (canReflect)
1972 {
1973 float reflectchance = victim->GetTotalAuraModifier(SPELL_AURA_REFLECT_SPELLS);
1975
1976 if (reflectchance > 0 && roll_chance(reflectchance))
1978 }
1979
1980 if (spellInfo->HasAttribute(SPELL_ATTR3_ALWAYS_HIT))
1981 return SPELL_MISS_NONE;
1982
1983 switch (spellInfo->DmgClass)
1984 {
1987 return MeleeSpellHitResult(victim, spellInfo);
1989 return SPELL_MISS_NONE;
1991 return MagicSpellHitResult(victim, spellInfo);
1992 }
1993 return SPELL_MISS_NONE;
1994}
1995
1996void WorldObject::SendSpellMiss(Unit* target, uint32 spellID, SpellMissInfo missInfo)
1997{
1999 spellMissLog.SpellID = spellID;
2000 spellMissLog.Caster = GetGUID();
2001 spellMissLog.Entries.emplace_back(target->GetGUID(), missInfo);
2002 SendMessageToSet(spellMissLog.Write(), true);
2003}
2004
2006{
2007 uint32 factionId = GetFaction();
2008 FactionTemplateEntry const* entry = sFactionTemplateStore.LookupEntry(factionId);
2009 if (!entry)
2010 {
2011 switch (GetTypeId())
2012 {
2013 case TYPEID_PLAYER:
2014 TC_LOG_ERROR("entities.unit", "Player {} has invalid faction (faction template id) #{}", ToPlayer()->GetName(), factionId);
2015 break;
2016 case TYPEID_UNIT:
2017 TC_LOG_ERROR("entities.unit", "Creature (template id: {}) has invalid faction (faction template Id) #{}", ToCreature()->GetCreatureTemplate()->Entry, factionId);
2018 break;
2019 case TYPEID_GAMEOBJECT:
2020 if (factionId) // Gameobjects may have faction template id = 0
2021 TC_LOG_ERROR("entities.faction", "GameObject (template id: {}) has invalid faction (faction template Id) #{}", ToGameObject()->GetGOInfo()->entry, factionId);
2022 break;
2023 default:
2024 TC_LOG_ERROR("entities.unit", "Object (name={}, type={}) has invalid faction (faction template Id) #{}", GetName(), uint32(GetTypeId()), factionId);
2025 break;
2026 }
2027 }
2028
2029 return entry;
2030}
2031
2032// function based on function Unit::UnitReaction from 13850 client
2034{
2035 // always friendly to self
2036 if (this == target)
2037 return REP_FRIENDLY;
2038
2039 auto isAttackableBySummoner = [&](Unit const* me, ObjectGuid const& targetGuid)
2040 {
2041 if (!me)
2042 return false;
2043
2044 TempSummon const* tempSummon = me->ToTempSummon();
2045 if (!tempSummon || !tempSummon->m_Properties)
2046 return false;
2047
2049 && targetGuid == tempSummon->GetSummonerGUID())
2050 return true;
2051
2052 return false;
2053 };
2054
2055 if (isAttackableBySummoner(ToUnit(), target->GetGUID()) || isAttackableBySummoner(target->ToUnit(), GetGUID()))
2056 return REP_NEUTRAL;
2057
2058 // always friendly to charmer or owner
2060 return REP_FRIENDLY;
2061
2062 Player const* selfPlayerOwner = GetAffectingPlayer();
2063 Player const* targetPlayerOwner = target->GetAffectingPlayer();
2064
2065 // check forced reputation to support SPELL_AURA_FORCE_REACTION
2066 if (selfPlayerOwner)
2067 {
2068 if (FactionTemplateEntry const* targetFactionTemplateEntry = target->GetFactionTemplateEntry())
2069 if (ReputationRank const* repRank = selfPlayerOwner->GetReputationMgr().GetForcedRankIfAny(targetFactionTemplateEntry))
2070 return *repRank;
2071 }
2072 else if (targetPlayerOwner)
2073 {
2074 if (FactionTemplateEntry const* selfFactionTemplateEntry = GetFactionTemplateEntry())
2075 if (ReputationRank const* repRank = targetPlayerOwner->GetReputationMgr().GetForcedRankIfAny(selfFactionTemplateEntry))
2076 return *repRank;
2077 }
2078
2079 Unit const* unit = Coalesce<const Unit>(ToUnit(), selfPlayerOwner);
2080 Unit const* targetUnit = Coalesce<const Unit>(target->ToUnit(), targetPlayerOwner);
2081 if (unit && unit->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED))
2082 {
2083 if (targetUnit && targetUnit->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED))
2084 {
2085 if (selfPlayerOwner && targetPlayerOwner)
2086 {
2087 // always friendly to other unit controlled by player, or to the player himself
2088 if (selfPlayerOwner == targetPlayerOwner)
2089 return REP_FRIENDLY;
2090
2091 // duel - always hostile to opponent
2092 if (selfPlayerOwner->duel && selfPlayerOwner->duel->Opponent == targetPlayerOwner && selfPlayerOwner->duel->State == DUEL_STATE_IN_PROGRESS)
2093 return REP_HOSTILE;
2094
2095 // same group - checks dependant only on our faction - skip FFA_PVP for example
2096 if (selfPlayerOwner->IsInRaidWith(targetPlayerOwner))
2097 return REP_FRIENDLY; // return true to allow config option AllowTwoSide.Interaction.Group to work
2098 // however client seems to allow mixed group parties, because in 13850 client it works like:
2099 // return GetFactionReactionTo(GetFactionTemplateEntry(), target);
2100 }
2101
2102 // check FFA_PVP
2103 if (unit->IsFFAPvP() && targetUnit->IsFFAPvP())
2104 return REP_HOSTILE;
2105
2106 if (selfPlayerOwner)
2107 {
2108 if (FactionTemplateEntry const* targetFactionTemplateEntry = targetUnit->GetFactionTemplateEntry())
2109 {
2110 if (ReputationRank const* repRank = selfPlayerOwner->GetReputationMgr().GetForcedRankIfAny(targetFactionTemplateEntry))
2111 return *repRank;
2112 if (!selfPlayerOwner->HasUnitFlag2(UNIT_FLAG2_IGNORE_REPUTATION))
2113 {
2114 if (FactionEntry const* targetFactionEntry = sFactionStore.LookupEntry(targetFactionTemplateEntry->Faction))
2115 {
2116 if (targetFactionEntry->CanHaveReputation())
2117 {
2118 // check contested flags
2119 if ((targetFactionTemplateEntry->Flags & FACTION_TEMPLATE_FLAG_CONTESTED_GUARD) &&
2120 selfPlayerOwner->HasPlayerFlag(PLAYER_FLAGS_CONTESTED_PVP))
2121 return REP_HOSTILE;
2122
2123 // if faction has reputation, hostile state depends only from AtWar state
2124 if (selfPlayerOwner->GetReputationMgr().IsAtWar(targetFactionEntry))
2125 return REP_HOSTILE;
2126 return REP_FRIENDLY;
2127 }
2128 }
2129 }
2130 }
2131 }
2132 }
2133 }
2134
2135 // do checks dependant only on our faction
2137}
2138
2139/*static*/ ReputationRank WorldObject::GetFactionReactionTo(FactionTemplateEntry const* factionTemplateEntry, WorldObject const* target)
2140{
2141 // always neutral when no template entry found
2142 if (!factionTemplateEntry)
2143 return REP_NEUTRAL;
2144
2145 FactionTemplateEntry const* targetFactionTemplateEntry = target->GetFactionTemplateEntry();
2146 if (!targetFactionTemplateEntry)
2147 return REP_NEUTRAL;
2148
2149 if (Player const* targetPlayerOwner = target->GetAffectingPlayer())
2150 {
2151 // check contested flags
2152 if ((factionTemplateEntry->Flags & FACTION_TEMPLATE_FLAG_CONTESTED_GUARD) &&
2153 targetPlayerOwner->HasPlayerFlag(PLAYER_FLAGS_CONTESTED_PVP))
2154 return REP_HOSTILE;
2155 if (ReputationRank const* repRank = targetPlayerOwner->GetReputationMgr().GetForcedRankIfAny(factionTemplateEntry))
2156 return *repRank;
2157 if (target->IsUnit() && !target->ToUnit()->HasUnitFlag2(UNIT_FLAG2_IGNORE_REPUTATION))
2158 {
2159 if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionTemplateEntry->Faction))
2160 {
2161 if (factionEntry->CanHaveReputation())
2162 {
2163 // CvP case - check reputation, don't allow state higher than neutral when at war
2164 ReputationRank repRank = targetPlayerOwner->GetReputationMgr().GetRank(factionEntry);
2165 if (targetPlayerOwner->GetReputationMgr().IsAtWar(factionEntry))
2166 repRank = std::min(REP_NEUTRAL, repRank);
2167 return repRank;
2168 }
2169 }
2170 }
2171 }
2172
2173 // common faction based check
2174 if (factionTemplateEntry->IsHostileTo(targetFactionTemplateEntry))
2175 return REP_HOSTILE;
2176 if (factionTemplateEntry->IsFriendlyTo(targetFactionTemplateEntry))
2177 return REP_FRIENDLY;
2178 if (targetFactionTemplateEntry->IsFriendlyTo(factionTemplateEntry))
2179 return REP_FRIENDLY;
2180 if (factionTemplateEntry->Flags & FACTION_TEMPLATE_FLAG_HOSTILE_BY_DEFAULT)
2181 return REP_HOSTILE;
2182 // neutral by default
2183 return REP_NEUTRAL;
2184}
2185
2186bool WorldObject::IsHostileTo(WorldObject const* target) const
2187{
2188 return GetReactionTo(target) <= REP_HOSTILE;
2189}
2190
2192{
2193 return GetReactionTo(target) >= REP_FRIENDLY;
2194}
2195
2197{
2198 FactionTemplateEntry const* my_faction = GetFactionTemplateEntry();
2199 if (!my_faction->Faction)
2200 return false;
2201
2202 FactionEntry const* raw_faction = sFactionStore.LookupEntry(my_faction->Faction);
2203 if (raw_faction && raw_faction->ReputationIndex >= 0)
2204 return false;
2205
2206 return my_faction->IsHostileToPlayers();
2207}
2208
2210{
2211 FactionTemplateEntry const* my_faction = GetFactionTemplateEntry();
2212 if (!my_faction->Faction)
2213 return true;
2214
2215 FactionEntry const* raw_faction = sFactionStore.LookupEntry(my_faction->Faction);
2216 if (raw_faction && raw_faction->ReputationIndex >= 0)
2217 return false;
2218
2219 return my_faction->IsNeutralToAll();
2220}
2221
2223{
2224 SpellInfo const* info = sSpellMgr->GetSpellInfo(spellId, args.CastDifficulty != DIFFICULTY_NONE ? args.CastDifficulty : GetMap()->GetDifficultyID());
2225 if (!info)
2226 {
2227 TC_LOG_ERROR("entities.unit", "CastSpell: unknown spell {} by caster {}", spellId, GetGUID());
2229 }
2230
2231 if (!targets.Targets)
2232 {
2233 TC_LOG_ERROR("entities.unit", "CastSpell: Invalid target passed to spell cast {} by {}", spellId, GetGUID());
2235 }
2236
2237 Spell* spell = new Spell(this, info, args.TriggerFlags, args.OriginalCaster, args.OriginalCastId);
2239 spell->SetSpellValue(value);
2240
2241 spell->m_CastItem = args.CastItem;
2242 if (args.OriginalCastItemLevel)
2244
2246 {
2247 if (args.TriggeringSpell)
2248 spell->m_CastItem = args.TriggeringSpell->m_CastItem;
2249 else if (args.TriggeringAura && !args.TriggeringAura->GetBase()->GetCastItemGUID().IsEmpty())
2250 if (Player const* triggeringAuraCaster = Object::ToPlayer(args.TriggeringAura->GetCaster()))
2251 spell->m_CastItem = triggeringAuraCaster->GetItemByGuid(args.TriggeringAura->GetBase()->GetCastItemGUID());
2252 }
2253
2254 spell->m_customArg = args.CustomArg;
2255 spell->m_scriptResult = args.ScriptResult;
2257
2258 return spell->prepare(*targets.Targets, args.TriggeringAura);
2259}
2260
2261void WorldObject::SendPlayOrphanSpellVisual(Position const& sourceLocation, ObjectGuid const& target, uint32 spellVisualId, float travelSpeed, bool speedAsTime /*= false*/, bool withSourceOrientation /*= false*/)
2262{
2263 WorldPackets::Spells::PlayOrphanSpellVisual playOrphanSpellVisual;
2264 playOrphanSpellVisual.SourceLocation = sourceLocation;
2265 if (withSourceOrientation)
2266 {
2267 if (IsGameObject())
2268 {
2270 rotation.toEulerAnglesZYX(playOrphanSpellVisual.SourceRotation.Pos.m_positionZ,
2271 playOrphanSpellVisual.SourceRotation.Pos.m_positionY,
2272 playOrphanSpellVisual.SourceRotation.Pos.m_positionX);
2273 }
2274 else
2275 playOrphanSpellVisual.SourceRotation = Position(0.0f, 0.0f, GetOrientation());
2276 }
2277
2278 playOrphanSpellVisual.Target = target; // exclusive with TargetLocation
2279 playOrphanSpellVisual.SpellVisualID = spellVisualId;
2280 playOrphanSpellVisual.TravelSpeed = travelSpeed;
2281 playOrphanSpellVisual.SpeedAsTime = speedAsTime;
2282 playOrphanSpellVisual.LaunchDelay = 0.0f;
2283 SendMessageToSet(playOrphanSpellVisual.Write(), true);
2284}
2285
2286void WorldObject::SendPlayOrphanSpellVisual(Position const& sourceLocation, Position const& targetLocation, uint32 spellVisualId, float travelSpeed, bool speedAsTime /*= false*/, bool withSourceOrientation /*= false*/)
2287{
2288 WorldPackets::Spells::PlayOrphanSpellVisual playOrphanSpellVisual;
2289 playOrphanSpellVisual.SourceLocation = sourceLocation;
2290 if (withSourceOrientation)
2291 {
2292 if (IsGameObject())
2293 {
2295 rotation.toEulerAnglesZYX(playOrphanSpellVisual.SourceRotation.Pos.m_positionZ,
2296 playOrphanSpellVisual.SourceRotation.Pos.m_positionY,
2297 playOrphanSpellVisual.SourceRotation.Pos.m_positionX);
2298 }
2299 else
2300 playOrphanSpellVisual.SourceRotation = Position(0.0f, 0.0f, GetOrientation());
2301 }
2302
2303 playOrphanSpellVisual.TargetLocation = targetLocation; // exclusive with Target
2304 playOrphanSpellVisual.SpellVisualID = spellVisualId;
2305 playOrphanSpellVisual.TravelSpeed = travelSpeed;
2306 playOrphanSpellVisual.SpeedAsTime = speedAsTime;
2307 playOrphanSpellVisual.LaunchDelay = 0.0f;
2308 SendMessageToSet(playOrphanSpellVisual.Write(), true);
2309}
2310
2311void WorldObject::SendPlayOrphanSpellVisual(ObjectGuid const& target, uint32 spellVisualId, float travelSpeed, bool speedAsTime /*= false*/, bool withSourceOrientation /*= false*/)
2312{
2313 SendPlayOrphanSpellVisual(GetPosition(), target, spellVisualId, travelSpeed, speedAsTime, withSourceOrientation);
2314}
2315
2316void WorldObject::SendPlayOrphanSpellVisual(Position const& targetLocation, uint32 spellVisualId, float travelSpeed, bool speedAsTime /*= false*/, bool withSourceOrientation /*= false*/)
2317{
2318 SendPlayOrphanSpellVisual(GetPosition(), targetLocation, spellVisualId, travelSpeed, speedAsTime, withSourceOrientation);
2319}
2320
2322{
2323 WorldPackets::Spells::CancelOrphanSpellVisual cancelOrphanSpellVisual;
2324 cancelOrphanSpellVisual.SpellVisualID = id;
2325 SendMessageToSet(cancelOrphanSpellVisual.Write(), true);
2326}
2327
2328// function based on function Unit::CanAttack from 13850 client
2329bool WorldObject::IsValidAttackTarget(WorldObject const* target, SpellInfo const* bySpell /*= nullptr*/) const
2330{
2331 ASSERT(target);
2332
2333 // some positive spells can be casted at hostile target
2334 bool isPositiveSpell = bySpell && bySpell->IsPositive();
2335
2336 // can't attack self (spells can, attribute check)
2337 if (!bySpell && this == target)
2338 return false;
2339
2340 // can't attack unattackable units
2341 Unit const* unitTarget = target->ToUnit();
2342 if (unitTarget && unitTarget->HasUnitState(UNIT_STATE_UNATTACKABLE))
2343 return false;
2344
2345 // can't attack GMs
2346 if (target->GetTypeId() == TYPEID_PLAYER && target->ToPlayer()->IsGameMaster())
2347 return false;
2348
2349 Unit const* unit = ToUnit();
2350 // visibility checks (only units)
2351 if (unit)
2352 {
2353 // can't attack invisible
2354 CanSeeOrDetectExtraArgs canSeeOrDetectExtraArgs;
2355 if (bySpell)
2356 {
2357 canSeeOrDetectExtraArgs.ImplicitDetection = bySpell->IsAffectingArea();
2358 canSeeOrDetectExtraArgs.IgnorePhaseShift = bySpell->HasAttribute(SPELL_ATTR6_IGNORE_PHASE_SHIFT);
2361 }
2362 if (!unit->CanSeeOrDetect(target, canSeeOrDetectExtraArgs))
2363 return false;
2364 }
2365
2366 // can't attack dead
2367 if ((!bySpell || !bySpell->IsAllowingDeadTarget()) && unitTarget && !unitTarget->IsAlive())
2368 return false;
2369
2370 // can't attack untargetable
2371 if ((!bySpell || !bySpell->HasAttribute(SPELL_ATTR6_CAN_TARGET_UNTARGETABLE)) && unitTarget && unitTarget->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE_2))
2372 return false;
2373
2374 if (unitTarget && unitTarget->IsUninteractible())
2375 return false;
2376
2377 if (Player const* playerAttacker = ToPlayer())
2378 {
2379 if (playerAttacker->HasPlayerFlag(PLAYER_FLAGS_UBER))
2380 return false;
2381 }
2382
2383 // check flags
2385 return false;
2386
2387 Unit const* unitOrOwner = unit;
2388 GameObject const* go = ToGameObject();
2389 if (go && go->GetGoType() == GAMEOBJECT_TYPE_TRAP)
2390 unitOrOwner = go->GetOwner();
2391
2392 // ignore immunity flags when assisting
2393 if (unitOrOwner && unitTarget && !(isPositiveSpell && bySpell->HasAttribute(SPELL_ATTR6_CAN_ASSIST_IMMUNE_PC)))
2394 {
2395 if (!unitOrOwner->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) && unitTarget->IsImmuneToNPC())
2396 return false;
2397
2398 if (!unitTarget->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) && unitOrOwner->IsImmuneToNPC())
2399 return false;
2400
2401 if (!bySpell || !bySpell->HasAttribute(SPELL_ATTR8_CAN_ATTACK_IMMUNE_PC))
2402 {
2403 if (unitOrOwner->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) && unitTarget->IsImmuneToPC())
2404 return false;
2405
2406 if (unitTarget->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) && unitOrOwner->IsImmuneToPC())
2407 return false;
2408 }
2409 }
2410
2411 // CvC case - can attack each other only when one of them is hostile
2412 if (unit && !unit->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) && unitTarget && !unitTarget->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED))
2413 return IsHostileTo(unitTarget) || unitTarget->IsHostileTo(this);
2414
2415 // Traps without owner or with NPC owner versus Creature case - can attack to creature only when one of them is hostile
2416 if (go && go->GetGoType() == GAMEOBJECT_TYPE_TRAP)
2417 {
2418 Unit const* goOwner = go->GetOwner();
2419 if (!goOwner || !goOwner->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED))
2420 if (unitTarget && !unitTarget->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED))
2421 return IsHostileTo(unitTarget) || unitTarget->IsHostileTo(this);
2422 }
2423
2424 // PvP, PvC, CvP case
2425 // can't attack friendly targets
2426 if (IsFriendlyTo(target) || target->IsFriendlyTo(this))
2427 return false;
2428
2429 Player const* playerAffectingAttacker = (unit && unit->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED)) || go ? GetAffectingPlayer() : nullptr;
2430 Player const* playerAffectingTarget = unitTarget && unitTarget->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) ? unitTarget->GetAffectingPlayer() : nullptr;
2431
2432 // Pets of mounted players are immune to NPCs
2433 if (!playerAffectingAttacker && unitTarget && unitTarget->IsPet() && playerAffectingTarget && playerAffectingTarget->IsMounted())
2434 return false;
2435
2436 // Not all neutral creatures can be attacked (even some unfriendly faction does not react aggresive to you, like Sporaggar)
2437 if ((playerAffectingAttacker && !playerAffectingTarget) || (!playerAffectingAttacker && playerAffectingTarget))
2438 {
2439 Player const* player = playerAffectingAttacker ? playerAffectingAttacker : playerAffectingTarget;
2440
2441 if (Unit const* creature = playerAffectingAttacker ? unitTarget : unit)
2442 {
2443 if (creature->IsContestedGuard() && player->HasPlayerFlag(PLAYER_FLAGS_CONTESTED_PVP))
2444 return true;
2445
2446 if (FactionTemplateEntry const* factionTemplate = creature->GetFactionTemplateEntry())
2447 {
2448 if (!(player->GetReputationMgr().GetForcedRankIfAny(factionTemplate)))
2449 if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionTemplate->Faction))
2450 if (FactionState const* repState = player->GetReputationMgr().GetState(factionEntry))
2451 if (!repState->Flags.HasFlag(ReputationFlags::AtWar))
2452 return false;
2453
2454 }
2455 }
2456 }
2457
2458 if (playerAffectingAttacker && playerAffectingTarget)
2459 if (playerAffectingAttacker->duel && playerAffectingAttacker->duel->Opponent == playerAffectingTarget && playerAffectingAttacker->duel->State == DUEL_STATE_IN_PROGRESS)
2460 return true;
2461
2462 // PvP case - can't attack when attacker or target are in sanctuary
2463 // however, 13850 client doesn't allow to attack when one of the unit's has sanctuary flag and is pvp
2464 if (unitTarget && unitTarget->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED)
2465 && unitOrOwner && unitOrOwner->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED)
2466 && (unitTarget->IsInSanctuary() || unitOrOwner->IsInSanctuary())
2467 && (!bySpell || bySpell->HasAttribute(SPELL_ATTR8_IGNORE_SANCTUARY)))
2468 return false;
2469
2470 // additional checks - only PvP case
2471 if (playerAffectingAttacker && playerAffectingTarget)
2472 {
2473 if (playerAffectingTarget->IsPvP() || (bySpell && bySpell->HasAttribute(SPELL_ATTR5_IGNORE_AREA_EFFECT_PVP_CHECK)))
2474 return true;
2475
2476 if (playerAffectingAttacker->IsFFAPvP() && playerAffectingTarget->IsFFAPvP())
2477 return true;
2478
2479 return playerAffectingAttacker->HasPvpFlag(UNIT_BYTE2_FLAG_UNK1) ||
2480 playerAffectingTarget->HasPvpFlag(UNIT_BYTE2_FLAG_UNK1);
2481 }
2482
2483 return true;
2484}
2485
2486// function based on function Unit::CanAssist from 13850 client
2487bool WorldObject::IsValidAssistTarget(WorldObject const* target, SpellInfo const* bySpell /*= nullptr*/) const
2488{
2489 ASSERT(target);
2490
2491 // some negative spells can be casted at friendly target
2492 bool isNegativeSpell = bySpell && !bySpell->IsPositive();
2493
2494 // can assist to self
2495 if (this == target)
2496 return true;
2497
2498 // can't assist unattackable units
2499 Unit const* unitTarget = target->ToUnit();
2500 if (unitTarget && unitTarget->HasUnitState(UNIT_STATE_UNATTACKABLE))
2501 return false;
2502
2503 // can't assist GMs
2504 if (target->GetTypeId() == TYPEID_PLAYER && target->ToPlayer()->IsGameMaster())
2505 return false;
2506
2507 // can't assist own vehicle or passenger
2508 Unit const* unit = ToUnit();
2509 if (unit && unitTarget && unit->GetVehicle())
2510 {
2511 if (unit->IsOnVehicle(unitTarget))
2512 return false;
2513
2514 if (unit->GetVehicleBase()->IsOnVehicle(unitTarget))
2515 return false;
2516 }
2517
2518 // can't assist invisible
2519 CanSeeOrDetectExtraArgs canSeeOrDetectExtraArgs;
2520 if (bySpell)
2521 {
2522 canSeeOrDetectExtraArgs.ImplicitDetection = bySpell->IsAffectingArea();
2523 canSeeOrDetectExtraArgs.IgnorePhaseShift = bySpell->HasAttribute(SPELL_ATTR6_IGNORE_PHASE_SHIFT);
2526 }
2527 if (!CanSeeOrDetect(target, canSeeOrDetectExtraArgs))
2528 return false;
2529
2530 // can't assist dead
2531 if ((!bySpell || !bySpell->IsAllowingDeadTarget()) && unitTarget && !unitTarget->IsAlive())
2532 return false;
2533
2534 // can't assist untargetable
2535 if ((!bySpell || !bySpell->HasAttribute(SPELL_ATTR6_CAN_TARGET_UNTARGETABLE)) && unitTarget && unitTarget->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE_2))
2536 return false;
2537
2538 if ((!bySpell || !bySpell->HasAttribute(SPELL_ATTR11_CAN_ASSIST_UNINTERACTIBLE)) && unitTarget && unitTarget->IsUninteractible())
2539 return false;
2540
2541 // check flags for negative spells
2542 if (isNegativeSpell && unitTarget && unitTarget->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_ON_TAXI | UNIT_FLAG_NOT_ATTACKABLE_1))
2543 return false;
2544
2545 if (isNegativeSpell || !bySpell || !bySpell->HasAttribute(SPELL_ATTR6_CAN_ASSIST_IMMUNE_PC))
2546 {
2547 if (unit && unit->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED))
2548 {
2549 if (!bySpell || !bySpell->HasAttribute(SPELL_ATTR8_CAN_ATTACK_IMMUNE_PC))
2550 if (unitTarget && unitTarget->IsImmuneToPC())
2551 return false;
2552 }
2553 else
2554 {
2555 if (unitTarget && unitTarget->IsImmuneToNPC())
2556 return false;
2557 }
2558 }
2559
2560 // can't assist non-friendly targets
2561 if (GetReactionTo(target) < REP_NEUTRAL && target->GetReactionTo(this) < REP_NEUTRAL && (!ToCreature() || !ToCreature()->IsTreatedAsRaidUnit()))
2562 return false;
2563
2564 // PvP case
2565 if (unitTarget && unitTarget->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED))
2566 {
2567 if (unit && unit->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED))
2568 {
2569 Player const* selfPlayerOwner = GetAffectingPlayer();
2570 Player const* targetPlayerOwner = unitTarget->GetAffectingPlayer();
2571 if (selfPlayerOwner && targetPlayerOwner)
2572 {
2573 // can't assist player which is dueling someone
2574 if (selfPlayerOwner != targetPlayerOwner && targetPlayerOwner->duel)
2575 return false;
2576 }
2577 // can't assist player in ffa_pvp zone from outside
2578 if (unitTarget->IsFFAPvP() && !unit->IsFFAPvP())
2579 return false;
2580
2581 // can't assist player out of sanctuary from sanctuary if has pvp enabled
2582 if (unitTarget->IsPvP() && (!bySpell || bySpell->HasAttribute(SPELL_ATTR8_IGNORE_SANCTUARY)))
2583 if (unit->IsInSanctuary() && !unitTarget->IsInSanctuary())
2584 return false;
2585 }
2586 }
2587 // PvC case - player can assist creature only if has specific type flags
2588 // !target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) &&
2589 else if (unit && unit->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED))
2590 {
2591 if (!bySpell || !bySpell->HasAttribute(SPELL_ATTR6_CAN_ASSIST_IMMUNE_PC))
2592 if (unitTarget && !unitTarget->IsPvP())
2593 if (Creature const* creatureTarget = target->ToCreature())
2594 return creatureTarget->IsTreatedAsRaidUnit() || (creatureTarget->GetCreatureDifficulty()->TypeFlags & CREATURE_TYPE_FLAG_CAN_ASSIST);
2595 }
2596
2597 return true;
2598}
2599
2601{
2602 // Patch 1.2 notes: Spell Reflection no longer reflects abilities
2604 return victim;
2605
2607 for (AuraEffect const* aurEff : magnetAuras)
2608 {
2609 if (Unit* magnet = aurEff->GetBase()->GetCaster())
2610 {
2611 if (spellInfo->CheckExplicitTarget(this, magnet) == SPELL_CAST_OK && IsValidAttackTarget(magnet, spellInfo))
2612 {
2614 if (spellInfo->HasHitDelay())
2615 {
2616 // Set up missile speed based delay
2617 float hitDelay = spellInfo->LaunchDelay;
2619 hitDelay += std::max(spellInfo->Speed, spellInfo->MinDuration);
2620 else if (spellInfo->Speed > 0.0f)
2621 hitDelay += std::max(std::max(victim->GetDistance(this), 5.0f) / spellInfo->Speed, spellInfo->MinDuration);
2622
2623 uint32 delay = uint32(std::floor(hitDelay * 1000.0f));
2624 // Schedule charge drop
2625 aurEff->GetBase()->DropChargeDelayed(delay, AURA_REMOVE_BY_EXPIRE);
2626 }
2627 else
2628 aurEff->GetBase()->DropCharge(AURA_REMOVE_BY_EXPIRE);
2629
2630 return magnet;
2631 }
2632 }
2633 }
2634 return victim;
2635}
2636
2638{
2639 return spellInfo->GetSpellXSpellVisualId(this);
2640}
2641
2642template <typename Container>
2643void WorldObject::GetGameObjectListWithEntryInGrid(Container& gameObjectContainer, uint32 entry, float maxSearchRange /*= 250.0f*/) const
2644{
2645 Trinity::AllGameObjectsWithEntryInRange check(this, entry, maxSearchRange);
2646 Trinity::GameObjectListSearcher<Trinity::AllGameObjectsWithEntryInRange> searcher(this, gameObjectContainer, check);
2647 Cell::VisitGridObjects(this, searcher, maxSearchRange);
2648}
2649
2650template <typename Container>
2651void WorldObject::GetGameObjectListWithOptionsInGrid(Container& gameObjectContainer, float maxSearchRange, FindGameObjectOptions const& options) const
2652{
2653 Trinity::InRangeCheckCustomizer checkCustomizer(*this, maxSearchRange);
2654 Trinity::GameObjectWithOptionsInObjectRangeCheck check(*this, checkCustomizer, options);
2655 Trinity::GameObjectListSearcher searcher(this, gameObjectContainer, check);
2656 if (options.IgnorePhases)
2658
2659 Cell::VisitGridObjects(this, searcher, maxSearchRange);
2660}
2661
2662template <typename Container>
2663void WorldObject::GetCreatureListWithEntryInGrid(Container& creatureContainer, uint32 entry, float maxSearchRange /*= 250.0f*/) const
2664{
2665 Trinity::AllCreaturesOfEntryInRange check(this, entry, maxSearchRange);
2666 Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange> searcher(this, creatureContainer, check);
2667 Cell::VisitGridObjects(this, searcher, maxSearchRange);
2668}
2669
2670template <typename Container>
2671void WorldObject::GetCreatureListWithOptionsInGrid(Container& creatureContainer, float maxSearchRange, FindCreatureOptions const& options) const
2672{
2673 Trinity::InRangeCheckCustomizer checkCustomizer(*this, maxSearchRange);
2674 Trinity::CreatureWithOptionsInObjectRangeCheck check(*this, checkCustomizer, options);
2675 Trinity::CreatureListSearcher searcher(this, creatureContainer, check);
2676 if (options.IgnorePhases)
2678
2679 Cell::VisitGridObjects(this, searcher, maxSearchRange);
2680}
2681
2682template <typename Container>
2683void WorldObject::GetPlayerListInGrid(Container& playerContainer, float maxSearchRange, bool alive /*= true*/) const
2684{
2685 Trinity::AnyUnitInObjectRangeCheck checker(this, maxSearchRange, true, alive);
2686 Trinity::PlayerListSearcher searcher(this, playerContainer, checker);
2687 Cell::VisitWorldObjects(this, searcher, maxSearchRange);
2688}
2689
2690void WorldObject::GetNearPoint2D(WorldObject const* searcher, float& x, float& y, float distance2d, float absAngle) const
2691{
2692 float effectiveReach = GetCombatReach();
2693
2694 if (searcher)
2695 {
2696 effectiveReach += searcher->GetCombatReach();
2697
2698 if (this != searcher)
2699 {
2700 float myHover = 0.0f, searcherHover = 0.0f;
2701 if (Unit const* unit = ToUnit())
2702 myHover = unit->GetHoverOffset();
2703 if (Unit const* searchUnit = searcher->ToUnit())
2704 searcherHover = searchUnit->GetHoverOffset();
2705
2706 float hoverDelta = myHover - searcherHover;
2707 if (hoverDelta != 0.0f)
2708 effectiveReach = std::sqrt(std::max(effectiveReach * effectiveReach - hoverDelta * hoverDelta, 0.0f));
2709 }
2710 }
2711
2712 x = GetPositionX() + (effectiveReach + distance2d) * std::cos(absAngle);
2713 y = GetPositionY() + (effectiveReach + distance2d) * std::sin(absAngle);
2714
2717}
2718
2719void WorldObject::GetNearPoint(WorldObject const* searcher, float& x, float& y, float& z, float distance2d, float absAngle) const
2720{
2721 GetNearPoint2D(searcher, x, y, distance2d, absAngle);
2722 z = GetPositionZ();
2723 (searcher ? searcher : this)->UpdateAllowedPositionZ(x, y, z);
2724
2725 // if detection disabled, return first point
2726 if (!sWorld->getBoolConfig(CONFIG_DETECT_POS_COLLISION))
2727 return;
2728
2729 // return if the point is already in LoS
2730 if (IsWithinLOS(x, y, z))
2731 return;
2732
2733 // remember first point
2734 float first_x = x;
2735 float first_y = y;
2736 float first_z = z;
2737
2738 // loop in a circle to look for a point in LoS using small steps
2739 for (float angle = float(M_PI) / 8; angle < float(M_PI) * 2; angle += float(M_PI) / 8)
2740 {
2741 GetNearPoint2D(searcher, x, y, distance2d, absAngle + angle);
2742 z = GetPositionZ();
2743 (searcher ? searcher : this)->UpdateAllowedPositionZ(x, y, z);
2744 if (IsWithinLOS(x, y, z))
2745 return;
2746 }
2747
2748 // still not in LoS, give up and return first position found
2749 x = first_x;
2750 y = first_y;
2751 z = first_z;
2752}
2753
2754void WorldObject::GetClosePoint(float& x, float& y, float& z, float size, float distance2d /*= 0*/, float relAngle /*= 0*/) const
2755{
2756 // angle calculated from current orientation
2757 GetNearPoint(nullptr, x, y, z, distance2d + size, GetOrientation() + relAngle);
2758}
2759
2761{
2762 Position pos = GetPosition();
2763 MovePosition(pos, dist, angle);
2764 return pos;
2765}
2766
2768{
2769 Position pos = GetPosition();
2770 MovePositionToFirstCollision(pos, dist, angle);
2771 return pos;
2772}
2773
2775{
2776 Position pos = GetPosition();
2777 MovePosition(pos, radius * std::sqrt(rand_norm()), rand_norm() * static_cast<float>(2 * M_PI));
2778 return pos;
2779}
2780
2781void WorldObject::GetContactPoint(WorldObject const* obj, float& x, float& y, float& z, float distance2d /*= CONTACT_DISTANCE*/) const
2782{
2783 // angle to face `obj` to `this` using distance includes size of `obj`
2784 GetNearPoint(obj, x, y, z, distance2d, GetAbsoluteAngle(obj));
2785}
2786
2787void WorldObject::MovePosition(Position &pos, float dist, float angle, float maxHeightChange /*= 6.0f*/) const
2788{
2789 angle += GetOrientation();
2790 float destx, desty, destz, ground, floor;
2791 destx = pos.m_positionX + dist * std::cos(angle);
2792 desty = pos.m_positionY + dist * std::sin(angle);
2793
2794 // Prevent invalid coordinates here, position is unchanged
2795 if (!Trinity::IsValidMapCoord(destx, desty, pos.m_positionZ))
2796 {
2797 TC_LOG_FATAL("misc", "WorldObject::MovePosition: Object {} has invalid coordinates X: {} and Y: {} were passed!",
2798 GetGUID().ToString(), destx, desty);
2799 return;
2800 }
2801
2802 ground = GetMapHeight(destx, desty, MAX_HEIGHT);
2803 floor = GetMapHeight(destx, desty, pos.m_positionZ);
2804 destz = std::fabs(ground - pos.m_positionZ) <= std::fabs(floor - pos.m_positionZ) ? ground : floor;
2805
2806 float step = dist/10.0f;
2807
2808 for (uint8 j = 0; j < 10; ++j)
2809 {
2810 // do not allow too big z changes
2811 if (std::fabs(pos.m_positionZ - destz) > maxHeightChange)
2812 {
2813 destx -= step * std::cos(angle);
2814 desty -= step * std::sin(angle);
2815 ground = GetMap()->GetHeight(GetPhaseShift(), destx, desty, MAX_HEIGHT, true);
2816 floor = GetMap()->GetHeight(GetPhaseShift(), destx, desty, pos.m_positionZ, true);
2817 destz = std::fabs(ground - pos.m_positionZ) <= std::fabs(floor - pos.m_positionZ) ? ground : floor;
2818 }
2819 // we have correct destz now
2820 else
2821 {
2822 pos.Relocate(destx, desty, destz);
2823 break;
2824 }
2825 }
2826
2831}
2832
2833void WorldObject::MovePositionToFirstCollision(Position &pos, float dist, float angle) const
2834{
2835 angle += GetOrientation();
2836 float cosAngle = std::cos(angle);
2837 float sinAngle = std::sin(angle);
2838 float destx, desty, destz;
2839 destx = pos.m_positionX + dist * cosAngle;
2840 desty = pos.m_positionY + dist * sinAngle;
2841 destz = pos.m_positionZ;
2842
2843 // Prevent invalid coordinates here, position is unchanged
2844 if (!Trinity::IsValidMapCoord(destx, desty))
2845 {
2846 TC_LOG_FATAL("misc", "WorldObject::MovePositionToFirstCollision invalid coordinates Src: {}, dist {}, angle {}, destX: {} destY: {} were passed!",
2847 pos.ToString(), dist, angle, destx, desty);
2848 return;
2849 }
2850
2851 float halfHeight = GetCollisionHeight() * 0.5f;
2852 bool col = false;
2853
2854 // Use a detour raycast to get our first collision point
2855 PathGenerator path(this);
2856 path.SetUseRaycast(true);
2857 path.CalculatePath(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), destx, desty, destz, false);
2858
2859 // Check for valid path types before we proceed
2861 {
2862 G3D::Vector3 const& result = path.GetPath().back();
2863 destx = result.x;
2864 desty = result.y;
2865 destz = result.z;
2866 }
2867 else
2868 {
2869 // check static LOS
2870 // Unit is flying, check for potential collision via vmaps
2872 pos.m_positionX, pos.m_positionY, pos.m_positionZ + halfHeight,
2873 destx, desty, destz + halfHeight,
2874 destx, desty, destz, -0.5f);
2875
2876 destz -= halfHeight;
2877
2878 // Collided with static LOS object, move back to collision point
2879 if (col)
2880 {
2881 destx -= CONTACT_DISTANCE * cosAngle;
2882 desty -= CONTACT_DISTANCE * sinAngle;
2883 }
2884 }
2885
2886 // check dynamic collision
2888 pos.m_positionX, pos.m_positionY, pos.m_positionZ + halfHeight,
2889 destx, desty, destz + halfHeight,
2890 destx, desty, destz, -0.5f);
2891
2892 destz -= halfHeight;
2893
2894 // Collided with a gameobject, move back to collision point
2895 if (col)
2896 {
2897 destx -= CONTACT_DISTANCE * cosAngle;
2898 desty -= CONTACT_DISTANCE * sinAngle;
2899 }
2900
2901 float groundZ = VMAP_INVALID_HEIGHT_VALUE;
2904 UpdateAllowedPositionZ(destx, desty, destz, &groundZ);
2905
2906 pos.Relocate(destx, desty, destz, GetOrientation());
2907
2908 // position has no ground under it (or is too far away)
2909 if (groundZ <= INVALID_HEIGHT)
2910 {
2911 if (Unit const* unit = ToUnit())
2912 {
2913 // unit can fly, ignore.
2914 if (unit->CanFly())
2915 return;
2916
2917 // fall back to gridHeight if any
2918 float gridHeight = GetMap()->GetGridHeight(GetPhaseShift(), pos.m_positionX, pos.m_positionY);
2919 if (gridHeight > INVALID_HEIGHT)
2920 pos.m_positionZ = gridHeight + unit->GetHoverOffset();
2921 }
2922 }
2923}
2924
2925void WorldObject::PlayDistanceSound(uint32 soundId, Player const* target /*= nullptr*/) const
2926{
2927 if (target)
2929 else
2931}
2932
2933void WorldObject::StopDistanceSound(Player const* target /*= nullptr*/) const
2934{
2935 if (target)
2937 else
2939}
2940
2941void WorldObject::PlayDirectSound(uint32 soundId, Player const* target /*= nullptr*/, uint32 broadcastTextId /*= 0*/) const
2942{
2943 if (target)
2944 target->SendDirectMessage(WorldPackets::Misc::PlaySound(GetGUID(), soundId, broadcastTextId).Write());
2945 else
2946 SendMessageToSet(WorldPackets::Misc::PlaySound(GetGUID(), soundId, broadcastTextId).Write(), true);
2947}
2948
2949void WorldObject::PlayDirectMusic(uint32 musicId, Player const* target /*= nullptr*/) const
2950{
2951 if (target)
2952 target->SendDirectMessage(WorldPackets::Misc::PlayMusic(musicId).Write());
2953 else
2954 SendMessageToSet(WorldPackets::Misc::PlayMusic(musicId).Write(), true);
2955}
2956
2957void WorldObject::PlayObjectSound(int32 soundKitId, ObjectGuid targetObjectGUID, Player const* target /*= nullptr*/, int32 broadcastTextId /*= 0*/) const
2958{
2960 pkt.TargetObjectGUID = targetObjectGUID;
2961 pkt.SourceObjectGUID = GetGUID();
2962 pkt.SoundKitID = soundKitId;
2963 pkt.Position = GetPosition();
2964 pkt.BroadcastTextID = broadcastTextId;
2965
2966 if (target)
2967 target->SendDirectMessage(pkt.Write());
2968 else
2969 SendMessageToSet(pkt.Write(), true);
2970}
2971
2972template <std::invocable<Player*> Work>
2974{
2975 Work& work;
2976
2977 explicit WorldObjectVisibleChangeVisitor(Work& work_) : work(work_) { }
2978
2979 void Visit(PlayerMapType& m) const
2980 {
2981 for (GridReference<Player>& ref : m)
2982 {
2983 Player* source = ref.GetSource();
2984
2985 work(source);
2986
2987 for (Player* viewer : source->GetSharedVisionList())
2988 work(viewer);
2989 }
2990 }
2991
2992 void Visit(CreatureMapType& m) const
2993 {
2994 for (GridReference<Creature>& ref : m)
2995 for (Player* viewer : ref.GetSource()->GetSharedVisionList())
2996 work(viewer);
2997 }
2998
3000 {
3001 for (GridReference<DynamicObject>& ref : m)
3002 {
3003 DynamicObject* source = ref.GetSource();
3004 ObjectGuid guid = source->GetCasterGUID();
3005
3006 if (guid.IsPlayer())
3007 {
3008 //GetCaster() will be nullptr if DynObj is in removelist
3009 if (Player* caster = ObjectAccessor::GetPlayer(*source, guid))
3010 if (*caster->m_activePlayerData->FarsightObject == source->GetGUID())
3011 work(caster);
3012 }
3013 }
3014 }
3015
3016 template <class SKIP>
3017 static void Visit(GridRefManager<SKIP> const&) { }
3018};
3019
3021{
3023
3024 void operator()(Player* player) const
3025 {
3026 if (player == object)
3027 return;
3028
3029 if (!player->HaveAtClient(object))
3030 return;
3031
3032 if (Unit const* unit = object->ToUnit(); unit && unit->GetCharmerGUID() == player->GetGUID())
3033 return;
3034
3035 object->DestroyForPlayer(player);
3036 player->m_clientGUIDs.erase(object->GetGUID());
3037 }
3038};
3039
3041{
3042 if (!IsInWorld())
3043 return;
3044
3045 WorldObjectClientDestroyWork destroyer{ .object = this };
3046 WorldObjectVisibleChangeVisitor visitor(destroyer);
3048}
3049
3051{
3052 //updates object's visibility for nearby players
3053 WorldObject* objects[] = { this };
3054 Trinity::VisibleChangesNotifier notifier({ std::begin(objects), std::end(objects) });
3056}
3057
3059{
3064
3065 void operator()(Player* player)
3066 {
3067 // Only send update once to a player
3068 if (player->HaveAtClient(&i_object) && plr_list.insert(player->GetGUID()).second)
3070 }
3071};
3072
3074{
3076
3077 WorldObjectChangeAccumulator notifier(*this, data_map);
3078 WorldObjectVisibleChangeVisitor visitor(notifier);
3079 //we must build packets for all visible players
3081
3082 ClearUpdateMask(false);
3083}
3084
3086{
3087 GetMap()->AddUpdateObject(this);
3088 return true;
3089}
3090
3095
3097{
3098 if (GetTransport())
3099 return GetTransport()->GetTransportGUID();
3100 return ObjectGuid::Empty;
3101}
3102
3108
3110{
3111 if (!IsInWorld())
3112 return m_staticFloorZ;
3113 return std::max<float>(m_staticFloorZ, GetMap()->GetGameObjectFloor(GetPhaseShift(), GetPositionX(), GetPositionY(), GetPositionZ() + Z_OFFSET_FIND_HEIGHT));
3114}
3115
3116float WorldObject::GetMapWaterOrGroundLevel(float x, float y, float z, float* ground/* = nullptr*/) const
3117{
3118 bool swimming = [&]()
3119 {
3120 if (Creature const* creature = ToCreature())
3121 return (!creature->CannotPenetrateWater() && !creature->HasAuraType(SPELL_AURA_WATER_WALK));
3122 else if (Unit const* unit = ToUnit())
3123 return !unit->HasAuraType(SPELL_AURA_WATER_WALK);
3124
3125 return true;
3126 }();
3127
3128 return GetMap()->GetWaterOrGroundLevel(GetPhaseShift(), x, y, z, ground, swimming, GetCollisionHeight());
3129}
3130
3131float WorldObject::GetMapHeight(float x, float y, float z, bool vmap/* = true*/, float distanceToSearch/* = DEFAULT_HEIGHT_SEARCH*/) const
3132{
3133 if (z != MAX_HEIGHT)
3135
3136 return GetMap()->GetHeight(GetPhaseShift(), x, y, z, vmap, distanceToSearch);
3137}
3138
3139std::string WorldObject::GetDebugInfo() const
3140{
3141 std::stringstream sstr;
3142 sstr << WorldLocation::GetDebugInfo() << "\n"
3143 << Object::GetDebugInfo() << "\n"
3144 << "Name: " << GetName();
3145 return sstr.str();
3146}
3147
3148template TC_GAME_API void WorldObject::GetGameObjectListWithEntryInGrid(std::list<GameObject*>&, uint32, float) const;
3149template TC_GAME_API void WorldObject::GetGameObjectListWithEntryInGrid(std::deque<GameObject*>&, uint32, float) const;
3150template TC_GAME_API void WorldObject::GetGameObjectListWithEntryInGrid(std::vector<GameObject*>&, uint32, float) const;
3151
3152template TC_GAME_API void WorldObject::GetGameObjectListWithOptionsInGrid(std::list<GameObject*>&, float, FindGameObjectOptions const&) const;
3153template TC_GAME_API void WorldObject::GetGameObjectListWithOptionsInGrid(std::deque<GameObject*>&, float, FindGameObjectOptions const&) const;
3154template TC_GAME_API void WorldObject::GetGameObjectListWithOptionsInGrid(std::vector<GameObject*>&, float, FindGameObjectOptions const&) const;
3155
3156template TC_GAME_API void WorldObject::GetCreatureListWithEntryInGrid(std::list<Creature*>&, uint32, float) const;
3157template TC_GAME_API void WorldObject::GetCreatureListWithEntryInGrid(std::deque<Creature*>&, uint32, float) const;
3158template TC_GAME_API void WorldObject::GetCreatureListWithEntryInGrid(std::vector<Creature*>&, uint32, float) const;
3159
3160template TC_GAME_API void WorldObject::GetCreatureListWithOptionsInGrid(std::list<Creature*>&, float, FindCreatureOptions const&) const;
3161template TC_GAME_API void WorldObject::GetCreatureListWithOptionsInGrid(std::deque<Creature*>&,float, FindCreatureOptions const&) const;
3162template TC_GAME_API void WorldObject::GetCreatureListWithOptionsInGrid(std::vector<Creature*>&, float, FindCreatureOptions const&) const;
3163
3164template TC_GAME_API void WorldObject::GetPlayerListInGrid(std::list<Player*>&, float, bool) const;
3165template TC_GAME_API void WorldObject::GetPlayerListInGrid(std::deque<Player*>&, float, bool) const;
3166template TC_GAME_API void WorldObject::GetPlayerListInGrid(std::vector<Player*>&, float, bool) const;
std::unordered_map< Player *, UpdateData > UpdateDataMapType
Definition BaseEntity.h:32
#define sBattlefieldMgr
#define M_PI
Definition Common.h:118
#define sConditionMgr
DB2Storage< FactionTemplateEntry > sFactionTemplateStore("FactionTemplate.db2", &FactionTemplateLoadInfo::Instance)
DB2Storage< AreaTableEntry > sAreaTableStore("AreaTable.db2", &AreaTableLoadInfo::Instance)
DB2Storage< FactionEntry > sFactionStore("Faction.db2", &FactionLoadInfo::Instance)
#define MAX_EFFECT_MASK
Definition DBCEnums.h:2451
@ DIFFICULTY_NONE
Definition DBCEnums.h:936
@ FACTION_TEMPLATE_FLAG_HOSTILE_BY_DEFAULT
Definition DBCEnums.h:1006
@ FACTION_TEMPLATE_FLAG_CONTESTED_GUARD
Definition DBCEnums.h:1005
#define TC_GAME_API
Definition Define.h:129
uint8_t uint8
Definition Define.h:156
int32_t int32
Definition Define.h:150
uint64_t uint64
Definition Define.h:153
#define UI64LIT(N)
Definition Define.h:139
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 ABORT
Definition Errors.h:79
#define ASSERT
Definition Errors.h:72
#define MAX_HEIGHT
Definition GridDefines.h:60
#define INVALID_HEIGHT
Definition GridDefines.h:61
#define TC_LOG_DEBUG(filterType__, message__,...)
Definition Log.h:173
#define TC_LOG_ERROR(filterType__, message__,...)
Definition Log.h:182
#define TC_LOG_FATAL(filterType__, message__,...)
Definition Log.h:185
#define TC_LOG_WARN(filterType__, message__,...)
Definition Log.h:179
@ LIQUID_MAP_NO_WATER
Definition MapDefines.h:134
@ MOVEMENTFLAG_FLYING
@ MOVEMENTFLAG_FALLING
@ MOVEMENTFLAG_SWIMMING
@ MOVEMENTFLAG_SPLINE_ELEVATION
@ MOVEMENTFLAG_ALWAYS_ALLOW_PITCHING
#define MAX_VISIBILITY_DISTANCE
#define DEFAULT_VISIBILITY_DISTANCE
TempSummonType
@ TEMPSUMMON_DEAD_DESPAWN
@ TEMPSUMMON_TIMED_DESPAWN
#define VISIBILITY_DISTANCE_LARGE
#define VISIBILITY_DISTANCE_TINY
GOSummonType
@ GO_SUMMON_TIMED_OR_CORPSE_DESPAWN
#define SIGHT_RANGE_UNIT
#define CONTACT_DISTANCE
#define DEFAULT_VISIBILITY_INSTANCE
#define VISIBILITY_DISTANCE_GIGANTIC
#define VISIBILITY_DISTANCE_SMALL
VisibilityDistanceType
std::unordered_set< ObjectGuid > GuidUnorderedSet
Definition ObjectGuid.h:435
@ TYPEID_OBJECT
Definition ObjectGuid.h:38
@ TYPEID_GAMEOBJECT
Definition ObjectGuid.h:46
@ TYPEID_UNIT
Definition ObjectGuid.h:43
@ TYPEID_CORPSE
Definition ObjectGuid.h:48
@ TYPEID_PLAYER
Definition ObjectGuid.h:44
#define sObjectMgr
Definition ObjectMgr.h:1873
SummonerType
Definition ObjectMgr.h:72
@ SUMMONER_TYPE_MAP
Definition ObjectMgr.h:75
@ SUMMONER_TYPE_CREATURE
Definition ObjectMgr.h:73
@ SUMMONER_TYPE_GAMEOBJECT
Definition ObjectMgr.h:74
constexpr float VisibilityDistances[AsUnderlyingType(VisibilityDistanceType::Max)]
Definition Object.cpp:54
struct Object::ObjectFragmentInfoInitializer InitObjectFragment
static void SummonCreatureGroup(uint32 summonerId, SummonerType summonerType, uint8 group, std::list< TempSummon * > *summoned, SummonCreature summonCreature)
Definition Object.cpp:1324
static constexpr Milliseconds const HEARTBEAT_INTERVAL
Definition Object.h:79
#define sOutdoorPvPMgr
@ PATHFIND_NOT_USING_PATH
@ PATHFIND_NOPATH
@ PATHFIND_FARFROMPOLY_START
@ DUEL_STATE_IN_PROGRESS
Definition Player.h:449
@ PLAYER_FLAGS_CONTESTED_PVP
Definition Player.h:520
@ PLAYER_FLAGS_UBER
Definition Player.h:531
@ CHEAT_CASTTIME
Definition Player.h:1061
int32 irand(int32 min, int32 max)
Definition Random.cpp:36
float rand_norm()
Definition Random.cpp:76
bool roll_chance(float chance, PseudoRandomDistributionState &state)
Definition Random.cpp:131
@ SERVERSIDE_VISIBILITY_GM
@ SERVERSIDE_VISIBILITY_GHOST
@ SPELL_ATTR11_CAN_ASSIST_UNINTERACTIBLE
@ EFFECT_3
@ EFFECT_1
@ EFFECT_0
@ EFFECT_4
@ EFFECT_2
@ SPELL_ATTR9_HASTE_AFFECTS_MELEE_ABILITY_CASTTIME
@ SPELL_ATTR9_MISSILE_SPEED_IS_DELAY_IN_SEC
@ SPELL_ATTR7_REFLECTION_ONLY_DEFENDS
@ SPELL_ATTR7_NO_ATTACK_MISS
@ SPELL_ATTR7_NO_TARGET_DURATION_MOD
StealthType
@ TOTAL_STEALTH_TYPES
GameobjectTypes
@ GAMEOBJECT_TYPE_TRAP
@ SPELL_ATTR5_IGNORE_AREA_EFFECT_PVP_CHECK
@ SPELL_ATTR5_SPELL_HASTE_AFFECTS_PERIODIC
SpellMissInfo
@ SPELL_MISS_IMMUNE
@ SPELL_MISS_NONE
@ SPELL_MISS_RESIST
@ SPELL_MISS_MISS
@ SPELL_MISS_EVADE
@ SPELL_MISS_REFLECT
@ SPELL_MISS_DEFLECT
SpellSchoolMask
@ SPELL_ATTR2_AUTO_REPEAT
@ SPELL_ATTR2_RETAIN_ITEM_CAST
SummonTitle
InvisibilityType
@ TOTAL_INVISIBILITY_TYPES
@ SPELL_ATTR1_NO_REDIRECTION
@ SPELL_ATTR3_ALWAYS_HIT
@ SPELL_ATTR3_NO_AVOIDANCE
@ SPELL_ATTR3_IGNORE_CASTER_MODIFIERS
@ SPELL_DAMAGE_CLASS_RANGED
@ SPELL_DAMAGE_CLASS_MAGIC
@ SPELL_DAMAGE_CLASS_NONE
@ SPELL_DAMAGE_CLASS_MELEE
WeaponAttackType
@ BASE_ATTACK
@ RANGED_ATTACK
@ POWER_COMBO_POINTS
@ SPELL_ATTR0_IS_TRADESKILL
@ SPELL_ATTR0_IS_ABILITY
@ SPELL_ATTR0_NO_IMMUNITIES
@ SPELL_ATTR0_USES_RANGED_SLOT
ReputationRank
@ REP_FRIENDLY
@ REP_NEUTRAL
@ REP_HOSTILE
LineOfSightChecks
SpellCastResult
@ SPELL_FAILED_BAD_TARGETS
@ SPELL_CAST_OK
@ SPELL_FAILED_SPELL_UNAVAILABLE
@ GHOST_VISIBILITY_ALIVE
@ GHOST_VISIBILITY_GHOST
@ SPELLFAMILY_POTION
constexpr float Z_OFFSET_FIND_HEIGHT
@ GO_STATE_READY
@ SUMMON_CATEGORY_POSSESSED_VEHICLE
@ SUMMON_CATEGORY_PET
@ SUMMON_CATEGORY_VEHICLE
@ SUMMON_CATEGORY_ALLY
@ SUMMON_CATEGORY_PUPPET
@ SUMMON_CATEGORY_WILD
@ CREATURE_TYPE_FLAG_CAN_ASSIST
@ SPELL_ATTR8_IGNORE_SANCTUARY
@ SPELL_ATTR8_MELEE_HASTE_AFFECTS_PERIODIC
@ SPELL_ATTR8_ALLOW_TARGETS_HIDDEN_BY_SPAWN_TRACKING
@ SPELL_ATTR8_CAN_ATTACK_IMMUNE_PC
@ SKILL_COOKING
@ SPELL_ATTR6_CAN_TARGET_UNTARGETABLE
@ SPELL_ATTR6_IGNORE_PHASE_SHIFT
@ SPELL_ATTR6_CAN_ASSIST_IMMUNE_PC
@ AURA_REMOVE_BY_EXPIRE
@ SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL_NOT_STACK
@ SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK
@ SPELL_AURA_REFLECT_SPELLS
@ SPELL_AURA_IGNORE_HIT_DIRECTION
@ SPELL_AURA_DEFLECT_SPELLS
@ SPELL_AURA_DETECT_VISIBLE_WHILE_INVISIBLE
@ SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL
@ SPELL_AURA_WATER_WALK
@ SPELL_AURA_MECHANIC_DURATION_MOD
@ SPELL_AURA_DETECT_STEALTH
@ SPELL_AURA_SPELL_MAGNET
@ SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE
@ SPELL_AURA_REFLECT_SPELLS_SCHOOL
double SpellEffectValue
This is a double instead of float to be able to store full range of int32.
@ SPELL_ATTR0_CU_CAN_TARGET_ANY_PRIVATE_OBJECT
Definition SpellInfo.h:169
bool IsPartOfSkillLine(uint32 skillId, uint32 spellId)
Definition SpellMgr.cpp:119
@ SPELL_GROUP_ELIXIR_BATTLE
Definition SpellMgr.h:314
@ SPELL_GROUP_ELIXIR_GUARDIAN
Definition SpellMgr.h:315
#define sSpellMgr
Definition SpellMgr.h:812
uint32 getMSTime()
Definition Timer.h:33
@ UNIT_FLAG2_IGNORE_REPUTATION
@ UNIT_FLAG2_GIGANTIC_AOI
@ UNIT_FLAG2_INFINITE_AOI
@ UNIT_FLAG2_LARGE_AOI
@ UNIT_BYTE2_FLAG_UNK1
Definition UnitDefines.h:94
@ UNIT_FLAG_NON_ATTACKABLE
@ UNIT_FLAG_NON_ATTACKABLE_2
@ UNIT_FLAG_ON_TAXI
@ UNIT_FLAG_NOT_ATTACKABLE_1
@ UNIT_FLAG_PLAYER_CONTROLLED
@ UNIT_MASK_PUPPET
Definition Unit.h:376
@ UNIT_MASK_TOTEM
Definition Unit.h:373
@ UNIT_MASK_SUMMON
Definition Unit.h:370
@ UNIT_MASK_GUARDIAN
Definition Unit.h:372
@ UNIT_MASK_MINION
Definition Unit.h:371
#define WORLD_TRIGGER
Definition Unit.h:36
#define MAX_PLAYER_STEALTH_DETECT_RANGE
Definition Unit.h:644
@ UNIT_STATE_UNATTACKABLE
Definition Unit.h:313
@ UNIT_STATE_CONTROLLED
Definition Unit.h:315
T AddPct(T &base, U pct)
Definition Util.h:85
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
#define VMAP_INVALID_HEIGHT_VALUE
Definition VMapManager.h:71
#define VMAP_INVALID_HEIGHT
Definition VMapManager.h:70
Unit * GetCaster() const
Aura * GetBase() const
ObjectGuid GetCastItemGUID() const
Definition SpellAuras.h:188
bool IsUnit() const
Definition BaseEntity.h:171
ObjectGuid const & GetGUID() const
Definition BaseEntity.h:163
void BuildUpdateChangesMask()
virtual std::string GetDebugInfo() const
WowCS::EntityFragmentsHolder m_entityFragments
Definition BaseEntity.h:353
UF::UpdateFieldHolder m_values
Definition BaseEntity.h:205
bool IsInWorld() const
Definition BaseEntity.h:158
virtual void RemoveFromWorld()
CreateObjectBits m_updateFlag
Definition BaseEntity.h:352
bool IsDynObject() const
Definition BaseEntity.h:175
virtual void AddToWorld()
void ClearUpdateMask(bool remove)
bool IsGameObject() const
Definition BaseEntity.h:174
bool IsPlayer() const
Definition BaseEntity.h:173
ByteBuffer & PrepareValuesUpdateBuffer(UpdateData *data) const
TypeID m_objectTypeId
Definition BaseEntity.h:351
TypeID GetTypeId() const
Definition BaseEntity.h:166
void BuildFieldsUpdate(Player *player, UpdateDataMapType &data_map) const
size_t wpos() const
Definition ByteBuffer.h:462
void put(std::size_t pos, T value)
Definition ByteBuffer.h:261
bool IsEmpty() const
void AddMember(Creature *member)
void SetHomePosition(float x, float y, float z, float o)
Definition Creature.h:394
float GetAttackDistance(Unit const *player) const
bool IsEvadingAttacks() const
Definition Creature.h:225
bool AIM_Initialize(CreatureAI *ai=nullptr)
bool Create(ObjectGuid::LowType guidlow, Map *map, uint32 entry, Position const &pos, CreatureData const *data, uint32 vehId, bool dynamic=false)
float m_CombatDistance
Definition Creature.h:435
ObjectGuid GetCasterGUID() const
void KillAllEvents(bool force)
void Update(uint32 p_time)
T_FLAGS GetFlags() const
Definition Object.h:207
T_VALUES GetValue(FLAG_TYPE flag) const
Definition Object.h:212
void SetValue(FLAG_TYPE flag, T_VALUES value)
Definition Object.h:213
static GameObject * CreateGameObject(uint32 entry, Map *map, Position const &pos, QuaternionData const &rotation, uint32 animProgress, GOState goState, uint32 artKit=0)
void SetRespawnTime(int32 respawn)
void SetSpawnedByDefault(bool b)
Definition GameObject.h:272
GameobjectTypes GetGoType() const
Definition GameObject.h:288
QuaternionData GetWorldRotation() const
Definition Map.h:227
bool IsDungeon() const
Definition Map.cpp:3303
void AddObjectToRemoveList(WorldObject *obj)
Definition Map.cpp:2588
void RemoveFromActive(WorldObject *obj)
Definition Map.cpp:2805
bool AddToMap(T *)
Definition Map.cpp:527
void RemoveUpdateObject(BaseEntity *obj)
Definition Map.h:582
bool isInLineOfSight(PhaseShift const &phaseShift, float x1, float y1, float z1, float x2, float y2, float z2, LineOfSightChecks checks, VMAP::ModelIgnoreFlags ignoreFlags) const
Definition Map.cpp:1760
TempSummon * SummonCreature(uint32 entry, Position const &pos, SummonPropertiesEntry const *properties=nullptr, Milliseconds duration=0ms, WorldObject *summoner=nullptr, uint32 spellId=0, uint32 vehId=0, ObjectGuid privateObjectOwner=ObjectGuid::Empty, SmoothPhasingInfo const *smoothPhasingInfo=nullptr)
Definition Object.cpp:1191
void GetZoneAndAreaId(PhaseShift const &phaseShift, uint32 &zoneid, uint32 &areaid, float x, float y, float z)
Definition Map.cpp:1720
bool getObjectHitPos(PhaseShift const &phaseShift, float x1, float y1, float z1, float x2, float y2, float z2, float &rx, float &ry, float &rz, float modifyDist)
Definition Map.cpp:1771
void AddWorldObject(WorldObject *obj)
Definition Map.cpp:2762
void GetFullTerrainStatusForPosition(PhaseShift const &phaseShift, float x, float y, float z, PositionFullTerrainStatus &data, Optional< map_liquidHeaderTypeFlags > reqLiquidType={}, float collisionHeight=2.03128f)
Definition Map.cpp:1698
float GetWaterOrGroundLevel(PhaseShift const &phaseShift, float x, float y, float z, float *ground=nullptr, bool swim=false, float collisionHeight=2.03128f)
Definition Map.cpp:1755
BattlegroundMap * ToBattlegroundMap()
Definition Map.h:498
void SummonCreatureGroup(uint8 group, std::list< TempSummon * > *list=nullptr)
Definition Object.cpp:1362
void AddUpdateObject(BaseEntity *obj)
Definition Map.h:577
void RemoveWorldObject(WorldObject *obj)
Definition Map.cpp:2767
Difficulty GetDifficultyID() const
Definition Map.h:363
uint32 GetId() const
Definition Map.cpp:3288
float GetVisibilityRange() const
Definition Map.h:257
float GetHeight(PhaseShift const &phaseShift, float x, float y, float z, bool vmap=true, float maxSearchDist=DEFAULT_HEIGHT_SEARCH)
Definition Map.h:329
InstanceMap * ToInstanceMap()
Definition Map.h:495
float GetGridHeight(PhaseShift const &phaseShift, float x, float y)
Definition Map.cpp:1730
uint32 GetInstanceId() const
Definition Map.h:353
void AddToActive(WorldObject *obj)
Definition Map.cpp:2772
void AddObjectToSwitchList(WorldObject *obj, bool on)
Definition Map.cpp:2598
static ObjectGuid const Empty
Definition ObjectGuid.h:314
bool IsEmpty() const
Definition ObjectGuid.h:362
bool IsPlayer() const
Definition ObjectGuid.h:369
std::string ToString() const
Corpse * ToCorpse()
Definition Object.h:136
virtual void BuildValuesUpdateWithFlag(UF::UpdateFieldFlag flags, ByteBuffer &data, Player const *target) const
Definition Object.cpp:135
void AddToWorld() override
Definition Object.cpp:83
Trinity::unique_trackable_ptr< Object > m_scriptRef
Definition Object.h:191
std::string GetDebugInfo() const override
Definition Object.cpp:160
Player * ToPlayer()
Definition Object.h:126
Object()
Definition Object.cpp:74
static void BuildObjectFragmentUpdate(void const *rawFragmentData, UF::UpdateFieldFlag flags, ByteBuffer &data, Player const *target, BaseEntity const *entity)
Definition Object.cpp:145
void BuildValuesUpdateBlockForPlayerWithFlag(UpdateData *data, UF::UpdateFieldFlag flags, Player const *target) const
Definition Object.cpp:100
virtual void BuildValuesCreate(UF::UpdateFieldFlag flags, ByteBuffer &data, Player const *target) const =0
virtual void BuildValuesUpdate(UF::UpdateFieldFlag flags, ByteBuffer &data, Player const *target) const =0
static void BuildObjectFragmentCreate(void const *rawFragmentData, UF::UpdateFieldFlag flags, ByteBuffer &data, Player const *target, BaseEntity const *entity)
Definition Object.cpp:140
GameObject * ToGameObject()
Definition Object.h:131
static bool IsObjectFragmentChanged(void const *rawFragmentData)
Definition Object.cpp:150
uint32 GetEntry() const
Definition Object.h:89
Creature * ToCreature()
Definition Object.h:121
void BuildEntityFragmentsForValuesUpdateForPlayerWithMask(ByteBuffer &data, EnumFlag< UF::UpdateFieldFlag > flags) const
Definition Object.cpp:113
virtual void ClearValuesChangesMask()
Definition Object.cpp:130
void RemoveFromWorld() override
Definition Object.cpp:93
UF::UpdateField< UF::ObjectData, int32(WowCS::EntityFragment::CGObject), TYPEID_OBJECT > m_objectData
Definition Object.h:161
virtual ~Object()
virtual SpawnTrackingStateData const * GetSpawnTrackingStateDataForPlayer(Player const *player) const
Definition Object.h:169
static void ClearObjectFragmentChanged(void const *rawFragmentData)
Definition Object.cpp:155
Unit * ToUnit()
Definition Object.h:116
void SetUseRaycast(bool useRaycast)
Movement::PointsArray const & GetPath() const
PathType GetPathType() const
bool CalculatePath(float srcX, float srcY, float srcZ, float destX, float destY, float destZ, bool forceDest=false)
static uint32 GetTerrainMapId(PhaseShift const &phaseShift, uint32 mapId, TerrainInfo const *terrain, float x, float y)
static void InheritPhaseShift(WorldObject *target, WorldObject const *source)
static PhaseShift const & GetAlwaysVisiblePhaseShift()
void SendDirectMessage(WorldPacket const *data) const
Definition Player.cpp:6193
GuidUnorderedSet m_clientGUIDs
Definition Player.h:2686
bool HaveAtClient(BaseEntity const *u) const
Definition Player.cpp:24425
bool GetCommandStatus(uint32 command) const
Definition Player.h:1323
bool IsGameMaster() const
Definition Player.h:1293
bool IsAdvancedCombatLoggingEnabled() const
Definition Player.h:2870
bool HasPlayerFlag(PlayerFlags flags) const
Definition Player.h:2895
std::unique_ptr< DuelInfo > duel
Definition Player.h:2126
ReputationMgr & GetReputationMgr()
Definition Player.h:2422
FactionState const * GetState(FactionEntry const *factionEntry) const
bool IsAtWar(uint32 faction_id) const
ReputationRank const * GetForcedRankIfAny(FactionTemplateEntry const *factionTemplateEntry) const
void SetSingleInfo(SmoothPhasingInfo const &info)
uint32 TriggerSpell
Definition SpellInfo.h:234
uint32 SpellLevel
Definition SpellInfo.h:389
uint32 GetSpellXSpellVisualId(WorldObject const *caster=nullptr, WorldObject const *viewer=nullptr) const
SpellRange GetMinMaxRange(bool positive=false, WorldObject const *caster=nullptr, Spell *spell=nullptr) const
uint32 const Id
Definition SpellInfo.h:328
float MinDuration
Definition SpellInfo.h:395
bool HasOnlyDamageEffects() const
uint32 Dispel
Definition SpellInfo.h:331
bool HasHitDelay() const
float Speed
Definition SpellInfo.h:393
int32 GetMaxDuration() const
bool IsAllowingDeadTarget() const
float LaunchDelay
Definition SpellInfo.h:394
SpellSchoolMask GetSchoolMask() const
bool IsChanneled() const
bool HasAttribute(SpellAttr0 attribute) const
Definition SpellInfo.h:456
SpellDurationEntry const * DurationEntry
Definition SpellInfo.h:390
uint64 GetSpellMechanicMaskByEffectMask(uint32 effectMask) const
int32 GetDuration() const
SpellEffectInfo const & GetEffect(SpellEffIndex index) const
Definition SpellInfo.h:590
SpellCastResult CheckExplicitTarget(WorldObject const *caster, WorldObject const *target, Item const *itemTarget=nullptr) const
bool IsAffectingArea() const
bool IsPositive() const
uint32 DmgClass
Definition SpellInfo.h:416
uint32 SpellFamilyName
Definition SpellInfo.h:414
Definition Spell.h:277
std::any m_customArg
Definition Spell.h:649
void SetSpellValue(CastSpellExtraArgsInit::SpellValueOverride const &value)
Definition Spell.cpp:8729
int32 m_castItemLevel
Definition Spell.h:603
SpellCastResult prepare(SpellCastTargets const &targets, AuraEffect const *triggeredByAura=nullptr)
Definition Spell.cpp:3432
bool m_scriptWaitsForSpellHit
Definition Spell.h:657
Item * m_CastItem
Definition Spell.h:600
Scripting::v2::ActionResultSetter< SpellCastResult > m_scriptResult
Definition Spell.h:656
virtual void InitStats(WorldObject *summoner, Milliseconds duration)
ObjectGuid GetSummonerGUID() const
void SetTempSummonType(TempSummonType type)
virtual void InitSummon(WorldObject *summoner)
SummonPropertiesEntry const *const m_Properties
Definition Totem.h:31
virtual ObjectGuid GetTransportGUID() const =0
virtual Position GetPositionOffsetTo(Position const &endPos) const =0
This method transforms supplied global coordinates into local offsets.
virtual void AddPassenger(WorldObject *passenger, Position const &offset)=0
virtual TransportBase * RemovePassenger(WorldObject *passenger)=0
void ClearChangesMask(UpdateField< T, BlockBit, Bit >(Derived::*field))
uint32 GetChangedObjectTypeMask() const
Definition BaseEntity.h:81
Definition Unit.h:647
Unit * GetCharmed() const
Definition Unit.h:1232
Vehicle * GetVehicle() const
Definition Unit.h:1800
AuraEffectList const & GetAuraEffectsByType(AuraType type) const
Definition Unit.h:1362
bool HasPvpFlag(UnitPVPStateFlags flags) const
Definition Unit.h:895
float GetTotalAuraModifierByMiscMask(AuraType auraType, uint32 misc_mask) const
Definition Unit.cpp:5107
bool HasAuraTypeWithMiscvalue(AuraType auraType, int32 miscValue) const
Definition Unit.cpp:4845
void SetFaction(uint32 faction) override
Definition Unit.h:887
std::forward_list< AuraEffect * > AuraEffectList
Definition Unit.h:664
float GetMaxNegativeAuraModifierByMiscValue(AuraType auraType, int32 misc_value) const
Definition Unit.cpp:5177
bool IsPvP() const
Definition Unit.h:901
Unit * GetVehicleBase() const
Definition Unit.cpp:12206
bool IsPet() const
Definition Unit.h:763
bool HasUnitFlag(UnitFlags flags) const
Definition Unit.h:860
void SetCreatedBySpell(int32 spellId)
Definition Unit.h:875
bool CanInstantCast() const
Definition Unit.h:1851
bool HasUnitFlag2(UnitFlags2 flags) const
Definition Unit.h:865
bool IsInSanctuary() const
Definition Unit.h:900
void SetDemonCreatorGUID(ObjectGuid guid)
Definition Unit.h:1224
bool IsAlive() const
Definition Unit.h:1205
float GetCombatReach() const override
Definition Unit.h:717
TempSummon * ToTempSummon()
Definition Unit.h:1844
virtual bool HasSpell(uint32) const
Definition Unit.h:1099
bool IsOnVehicle(Unit const *vehicle) const
Definition Unit.cpp:12201
bool IsImmuneToNPC() const
Definition Unit.h:1063
Unit * GetCharmerOrOwner() const
Definition Unit.h:1241
void AddGameObject(GameObject *gameObj)
Definition Unit.cpp:5385
SharedVisionList const & GetSharedVisionList()
Definition Unit.h:1275
float GetMechanicResistChance(SpellInfo const *spellInfo) const
Definition Unit.cpp:2571
float GetTotalAuraModifier(AuraType auraType) const
Definition Unit.cpp:5087
bool HasAuraType(AuraType auraType) const
Definition Unit.cpp:4832
bool IsImmunedToSpell(SpellInfo const *spellInfo, uint32 effectMask, WorldObject const *caster, bool requireImmunityPurgesEffectAttribute=false) const
Definition Unit.cpp:7742
uint8 GetLevelForTarget(WorldObject const *) const override
Definition Unit.h:771
bool IsFFAPvP() const
Definition Unit.h:902
bool IsMounted() const
Definition Unit.h:927
float GetMaxNegativeAuraModifier(AuraType auraType) const
Definition Unit.cpp:5102
float GetTotalAuraModifierByMiscValue(AuraType auraType, int32 misc_value) const
Definition Unit.cpp:5147
UF::UpdateField< UF::UnitData, int32(WowCS::EntityFragment::CGObject), TYPEID_UNIT > m_unitData
Definition Unit.h:1897
bool IsImmunedToDamage(SpellSchoolMask meleeSchoolMask) const
Definition Unit.cpp:7874
bool HasUnitState(const uint32 f) const
Definition Unit.h:755
bool IsInRaidWith(Unit const *unit) const
Definition Unit.cpp:12272
void SetLevel(uint8 lvl, bool sendUpdate=true)
Definition Unit.cpp:10019
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition Unit.cpp:4822
std::array< float, MAX_ATTACK > m_modAttackSpeedPct
Definition Unit.h:1543
bool IsUninteractible() const
Definition Unit.h:1067
bool IsTotem() const
Definition Unit.h:765
bool IsImmuneToPC() const
Definition Unit.h:1060
void AddUpdateBlock()
Definition UpdateData.h:46
static VMapManager * createOrGetVMapManager()
bool getObjectHitPos(uint32 mapId, float x1, float y1, float z1, float x2, float y2, float z2, float &rx, float &ry, float &rz, float modifyDist)
std::string GetDebugInfo() const
Definition Position.cpp:316
constexpr uint32 GetMapId() const
Definition Position.h:216
uint32 m_mapId
Definition Position.h:218
Unit * GetMagicHitRedirectTarget(Unit *victim, SpellInfo const *spellInfo)
Definition Object.cpp:2600
bool InSamePhase(PhaseShift const &phaseShift) const
Definition Object.h:314
float m_staticFloorZ
Definition Object.h:592
TempSummon * SummonPersonalClone(Position const &pos, TempSummonType despawnType=TEMPSUMMON_MANUAL_DESPAWN, Milliseconds despawnTime=0s, uint32 vehId=0, uint32 spellId=0, Player *privateObjectOwner=nullptr)
Definition Object.cpp:1426
ZLiquidStatus m_liquidStatus
Definition Object.h:594
void GetPlayerListInGrid(Container &playerContainer, float maxSearchRange, bool alive=true) const
Definition Object.cpp:2683
virtual bool IsInvisibleDueToDespawn(WorldObject const *seer) const
Definition Object.h:607
Player * SelectNearestPlayer(float range) const
Definition Object.cpp:1584
void PlayDirectSound(uint32 soundId, Player const *target=nullptr, uint32 broadcastTextId=0) const
Definition Object.cpp:2941
void MovePosition(Position &pos, float dist, float angle, float maxHeightChange=6.0f) const
Definition Object.cpp:2787
bool IsWithinDist2d(float x, float y, float dist) const
Definition Object.cpp:484
bool IsWithinDist3d(float x, float y, float z, float dist) const
Definition Object.cpp:474
GameObject * FindNearestGameObject(uint32 entry, float range, bool spawnedOnly=true) const
Definition Object.cpp:1544
virtual void SendMessageToSet(WorldPacket const *data, bool self) const
Definition Object.cpp:1099
bool CanDetect(WorldObject const *obj, bool ignoreStealth, bool checkAlert=false) const
Definition Object.cpp:963
Map * GetMap() const
Definition Object.h:411
virtual void ResetMap()
Definition Object.cpp:1167
Scenario * GetScenario() const
Definition Object.cpp:1394
ZoneScript * FindZoneScript() const
Definition Object.cpp:1370
void GetGameObjectListWithOptionsInGrid(Container &gameObjectContainer, float maxSearchRange, FindGameObjectOptions const &options) const
Definition Object.cpp:2651
Creature * FindNearestCreatureWithOptions(float range, FindCreatureOptions const &options) const
Definition Object.cpp:1531
void UpdateAllowedPositionZ(float x, float y, float &z, float *groundZ=nullptr) const
Definition Object.cpp:709
Position GetRandomPoint(Position const &srcPos, float distance, float minDistance=0.0f) const
Definition Object.cpp:678
void AddToWorld() override
Definition Object.cpp:363
virtual float GetCollisionHeight() const
Definition Object.h:553
virtual bool IsAlwaysVisibleFor(WorldObject const *seer) const
Definition Object.h:606
Map * FindMap() const
Definition Object.h:412
Unit * GetCharmerOrOwner() const
Definition Object.cpp:1608
void RemoveFromWorld() override
Definition Object.cpp:369
virtual ~WorldObject()
Definition Object.cpp:228
InstanceScript * GetInstanceScript() const
Definition Object.cpp:394
virtual uint8 GetLevelForTarget(WorldObject const *) const
Definition Object.h:385
virtual void UpdateObjectVisibilityOnDestroy()
Definition Object.h:511
void SendSpellMiss(Unit *target, uint32 spellID, SpellMissInfo missInfo)
Definition Object.cpp:1996
Unit * GetCharmerOrOwnerOrSelf() const
Definition Object.cpp:1618
bool CheckPrivateObjectOwnerVisibility(WorldObject const *seer) const
Definition Object.cpp:827
bool IsWithinLOS(float x, float y, float z, LineOfSightChecks checks=LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags ignoreFlags=VMAP::ModelIgnoreFlags::Nothing) const
Definition Object.cpp:513
void BuildUpdate(UpdateDataMapType &) override
Definition Object.cpp:3073
void SendCombatLogMessage(WorldPackets::CombatLog::CombatLogServerPacket *combatLog) const
Definition Object.cpp:1138
virtual SpellMissInfo MeleeSpellHitResult(Unit *victim, SpellInfo const *spellInfo) const
Definition Object.cpp:1846
uint32 m_InstanceId
Definition Object.h:615
Position GetHitSpherePointFor(Position const &dest) const
Definition Object.cpp:504
void GetCreatureListWithEntryInGrid(Container &creatureContainer, uint32 entry, float maxSearchRange=250.0f) const
Definition Object.cpp:2663
void GetNearPoint(WorldObject const *searcher, float &x, float &y, float &z, float distance2d, float absAngle) const
Definition Object.cpp:2719
ObjectGuid GetPrivateObjectOwner() const
Definition Object.h:569
bool IsInRange2d(Position const *pos, float minRange, float maxRange) const
Definition Object.cpp:615
uint32 m_areaId
Definition Object.h:591
float GetGridActivationRange() const
Definition Object.cpp:769
void GetClosePoint(float &x, float &y, float &z, float size, float distance2d=0, float relAngle=0) const
Definition Object.cpp:2754
void GetGameObjectListWithEntryInGrid(Container &gameObjectContainer, uint32 entry, float maxSearchRange=250.0f) const
Definition Object.cpp:2643
GameObject * FindNearestGameObjectOfType(GameobjectTypes type, float range) const
Definition Object.cpp:1575
float GetMapHeight(float x, float y, float z, bool vmap=true, float distanceToSearch=50.0f) const
Definition Object.cpp:3131
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2222
void PlayDirectMusic(uint32 musicId, Player const *target=nullptr) const
Definition Object.cpp:2949
float GetMapWaterOrGroundLevel(float x, float y, float z, float *ground=nullptr) const
Definition Object.cpp:3116
std::string GetDebugInfo() const override
Definition Object.cpp:3139
bool IsValidAttackTarget(WorldObject const *target, SpellInfo const *bySpell=nullptr) const
Definition Object.cpp:2329
bool IsHostileToPlayers() const
Definition Object.cpp:2196
virtual bool IsAlwaysDetectableFor(WorldObject const *seer) const
Definition Object.h:609
bool IsHostileTo(WorldObject const *target) const
Definition Object.cpp:2186
bool IsVisibilityOverridden() const
Definition Object.h:528
virtual ObjectGuid GetCharmerOrOwnerGUID() const
Definition Object.h:439
SmoothPhasing * GetOrCreateSmoothPhasing()
Definition Object.cpp:847
virtual bool CanNeverSee(WorldObject const *obj, bool ignorePhaseShift=false) const
Definition Object.cpp:958
TempSummon * SummonCreature(uint32 entry, Position const &pos, TempSummonType despawnType=TEMPSUMMON_MANUAL_DESPAWN, Milliseconds despawnTime=0s, uint32 vehId=0, uint32 spellId=0, ObjectGuid privateObjectOwner=ObjectGuid::Empty)
Definition Object.cpp:1403
PhaseShift & GetPhaseShift()
Definition Object.h:310
Unit * GetOwner() const
Definition Object.cpp:1603
FlaggedValuesArray32< int32, uint64, InvisibilityType, TOTAL_INVISIBILITY_TYPES > m_invisibility
Definition Object.h:403
int32 CalcSpellDuration(SpellInfo const *spellInfo, std::vector< SpellPowerCost > const *powerCosts) const
Definition Object.cpp:1705
bool isActiveObject() const
Definition Object.h:524
PhaseShift _phaseShift
Definition Object.h:616
bool IsSelfOrInSameMap(WorldObject const *obj) const
Definition Object.cpp:460
void SetZoneScript()
Definition Object.cpp:1389
TransportBase * GetTransport() const
Definition Object.h:537
bool GetDistanceOrder(WorldObject const *obj1, WorldObject const *obj2, bool is3D=true) const
Definition Object.cpp:567
bool IsPrivateObject() const
Definition Object.h:568
FlaggedValuesArray32< int32, uint64, InvisibilityType, TOTAL_INVISIBILITY_TYPES > m_invisibilityDetect
Definition Object.h:404
bool isInFront(WorldObject const *target, float arc=float(M_PI)) const
Definition Object.cpp:668
SpellMissInfo SpellHitResult(Unit *victim, SpellInfo const *spellInfo, bool canReflect, bool canImmune) const
Definition Object.cpp:1947
void setActive(bool isActiveObject)
Definition Object.cpp:274
void SetPrivateObjectOwner(ObjectGuid const &owner)
Definition Object.h:570
Position GetNearPosition(float dist, float angle)
Definition Object.cpp:2760
float GetDistance2d(WorldObject const *obj) const
Definition Object.cpp:448
Creature * SummonTrigger(float x, float y, float z, float ang, Milliseconds despawnTime, CreatureAI *(*GetAI)(Creature *)=nullptr)
Definition Object.cpp:1487
ZoneScript * m_zoneScript
Definition Object.h:584
GameObject * SummonGameObject(uint32 entry, Position const &pos, QuaternionData const &rot, Seconds respawnTime, GOSummonType summonType=GO_SUMMON_TIMED_OR_CORPSE_DESPAWN)
Definition Object.cpp:1446
ObjectGuid GetCharmerOrOwnerOrOwnGUID() const
Definition Object.cpp:1595
Position GetRandomNearPosition(float radius)
Definition Object.cpp:2774
int32 ModSpellDuration(SpellInfo const *spellInfo, WorldObject const *target, int32 duration, bool positive, uint32 effectMask) const
Definition Object.cpp:1725
SmoothPhasing * GetSmoothPhasing()
Definition Object.h:575
float GetSightRange(WorldObject const *target=nullptr) const
Definition Object.cpp:795
static ReputationRank GetFactionReactionTo(FactionTemplateEntry const *factionTemplateEntry, WorldObject const *target)
Definition Object.cpp:2139
void PlayDistanceSound(uint32 soundId, Player const *target=nullptr) const
Definition Object.cpp:2925
virtual bool IsNeverVisibleFor(WorldObject const *seer, bool allowServersideObjects) const
Definition Object.h:605
float GetFloorZ() const
Definition Object.cpp:3109
std::string const & GetName() const
Definition Object.h:342
virtual void SetMap(Map *map)
Definition Object.cpp:1149
bool IsFarVisible() const
Definition Object.h:526
virtual void Heartbeat()
Definition Object.h:611
void SetFarVisible(bool on)
Definition Object.cpp:325
bool IsInBetween(Position const &pos1, Position const &pos2, float size=0) const
Definition Object.cpp:651
void AddObjectToRemoveList()
Definition Object.cpp:1179
void GetNearPoint2D(WorldObject const *searcher, float &x, float &y, float distance, float absAngle) const
Definition Object.cpp:2690
SpellRange GetSpellMinMaxRangeForTarget(Unit const *target, SpellInfo const *spellInfo) const
Definition Object.cpp:1670
bool IsWithinLOSInMap(WorldObject const *obj, LineOfSightChecks checks=LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags ignoreFlags=VMAP::ModelIgnoreFlags::Nothing) const
Definition Object.cpp:533
WorldObject(bool isWorldObject)
Definition Object.cpp:217
bool CanDetectStealthOf(WorldObject const *obj, bool checkAlert=false) const
Definition Object.cpp:1023
virtual void ProcessPositionDataChanged(PositionFullTerrainStatus const &data)
Definition Object.cpp:351
SpellMissInfo MagicSpellHitResult(Unit *victim, SpellInfo const *spellInfo) const
Definition Object.cpp:1851
bool CanSeeOrDetect(WorldObject const *obj, CanSeeOrDetectExtraArgs const &args={ }) const
Definition Object.cpp:855
void GetContactPoint(WorldObject const *obj, float &x, float &y, float &z, float distance2d=CONTACT_DISTANCE) const
Definition Object.cpp:2781
bool CanDetectInvisibilityOf(WorldObject const *obj) const
Definition Object.cpp:992
virtual ObjectGuid GetTransGUID() const
Definition Object.cpp:3096
GameObject * FindNearestGameObjectWithOptions(float range, FindGameObjectOptions const &options) const
Definition Object.cpp:1553
bool const m_isStoredInWorldObjectGridContainer
Definition Object.h:583
void DestroyForNearbyPlayers()
Definition Object.cpp:3040
GameObject * FindNearestUnspawnedGameObject(uint32 entry, float range) const
Definition Object.cpp:1566
bool isInBack(WorldObject const *target, float arc=float(M_PI)) const
Definition Object.cpp:673
FlaggedValuesArray32< int32, uint32, StealthType, TOTAL_STEALTH_TYPES > m_stealthDetect
Definition Object.h:401
void SendPlayOrphanSpellVisual(Position const &sourceLocation, ObjectGuid const &target, uint32 spellVisualId, float travelSpeed, bool speedAsTime=false, bool withSourceOrientation=false)
Definition Object.cpp:2261
Creature * FindNearestCreature(uint32 entry, float range, bool alive=true) const
Definition Object.cpp:1522
bool IsNeutralToAll() const
Definition Object.cpp:2209
void UpdatePositionData()
Definition Object.cpp:344
bool m_isActive
Definition Object.h:580
void UpdateGroundPositionZ(float x, float y, float &z) const
Definition Object.cpp:698
bool IsStoredInWorldObjectGridContainer() const
Definition Object.cpp:263
Player * GetSpellModOwner() const
Definition Object.cpp:1646
Player * GetCharmerOrOwnerPlayerOrPlayerItself() const
Definition Object.cpp:1626
bool IsWithinDistInMap(WorldObject const *obj, float dist2compare, bool is3D=true, bool incOwnRadius=true, bool incTargetRadius=true) const
Definition Object.cpp:499
ReputationRank GetReactionTo(WorldObject const *target) const
Definition Object.cpp:2033
void SetIsStoredInWorldObjectGridContainer(bool apply)
Definition Object.cpp:255
bool m_outdoors
Definition Object.h:593
bool IsInWorldPvpZone() const
Definition Object.cpp:379
bool IsValidAssistTarget(WorldObject const *target, SpellInfo const *bySpell=nullptr) const
Definition Object.cpp:2487
bool IsInRange(WorldObject const *obj, float minRange, float maxRange, bool is3D=true) const
Definition Object.cpp:590
std::unique_ptr< SmoothPhasing > _smoothPhasing
Definition Object.h:624
EventProcessor m_Events
Definition Object.h:561
virtual bool _IsWithinDist(WorldObject const *obj, float dist2compare, bool is3D, bool incOwnRadius=true, bool incTargetRadius=true) const
Definition Object.cpp:408
void MovePositionToFirstCollision(Position &pos, float dist, float angle) const
Definition Object.cpp:2833
float GetVisibilityRange() const
Definition Object.cpp:785
SpellEffectValue ApplyEffectModifiers(SpellInfo const *spellInfo, uint8 effIndex, SpellEffectValue value) const
Definition Object.cpp:1676
bool IsInRange3d(Position const *pos, float minRange, float maxRange) const
Definition Object.cpp:633
TransportBase * m_transport
Definition Object.h:587
FlaggedValuesArray32< int32, uint32, StealthType, TOTAL_STEALTH_TYPES > m_stealth
Definition Object.h:400
virtual uint32 GetCastSpellXSpellVisualId(SpellInfo const *spellInfo) const
Definition Object.cpp:2637
FlaggedValuesArray32< int32, uint32, ServerSideVisibilityType, TOTAL_SERVERSIDE_VISIBILITY_TYPES > m_serverSideVisibilityDetect
Definition Object.h:407
void SendCancelOrphanSpellVisual(uint32 id)
Definition Object.cpp:2321
virtual uint32 GetFaction() const =0
float GetDistance(WorldObject const *obj) const
Definition Object.cpp:430
Optional< float > m_visibilityDistanceOverride
Definition Object.h:582
ObjectGuid _privateObjectOwner
Definition Object.h:622
virtual ObjectGuid GetOwnerGUID() const =0
void SetVisibilityDistanceOverride(VisibilityDistanceType type)
Definition Object.cpp:297
void StopDistanceSound(Player const *target=nullptr) const
Definition Object.cpp:2933
virtual void SendMessageToSetInRange(WorldPacket const *data, float dist, bool self) const
Definition Object.cpp:1105
Position GetFirstCollisionPosition(float dist, float angle)
Definition Object.cpp:2767
uint32 GetZoneId() const
Definition Object.h:332
Milliseconds _heartbeatTimer
Definition Object.h:626
MovementInfo m_movementInfo
Definition Object.h:548
Optional< WmoLocation > m_currentWmo
Definition Object.h:595
uint32 m_zoneId
Definition Object.h:590
FlaggedValuesArray32< int32, uint32, ServerSideVisibilityType, TOTAL_SERVERSIDE_VISIBILITY_TYPES > m_serverSideVisibility
Definition Object.h:406
float GetDistanceZ(WorldObject const *obj) const
Definition Object.cpp:400
void PlayObjectSound(int32 soundKitId, ObjectGuid targetObject, Player const *target=nullptr, int32 broadcastTextId=0) const
Definition Object.cpp:2957
bool m_isFarVisible
Definition Object.h:581
void GetCreatureListWithOptionsInGrid(Container &creatureContainer, float maxSearchRange, FindCreatureOptions const &options) const
Definition Object.cpp:2671
bool IsWithinDist(WorldObject const *obj, float dist2compare, bool is3D=true, bool incOwnRadius=true, bool incTargetRadius=true) const
Definition Object.cpp:494
void SummonCreatureGroup(uint8 group, std::list< TempSummon * > *list=nullptr)
Definition Object.cpp:1512
void ModSpellCastTime(SpellInfo const *spellInfo, int32 &castTime, Spell *spell=nullptr) const
Definition Object.cpp:1790
bool IsFriendlyTo(WorldObject const *target) const
Definition Object.cpp:2191
virtual float GetCombatReach() const
Definition Object.h:302
Map * m_currMap
Definition Object.h:613
Player * GetAffectingPlayer() const
Definition Object.cpp:1635
virtual bool CanAlwaysSee(WorldObject const *) const
Definition Object.h:604
bool IsInMap(WorldObject const *obj) const
Definition Object.cpp:467
virtual void Update(uint32 diff)
Definition Object.cpp:243
FactionTemplateEntry const * GetFactionTemplateEntry() const
Definition Object.cpp:2005
bool AddToObjectUpdate() override
Definition Object.cpp:3085
virtual void UpdateObjectVisibility(bool forced=true)
Definition Object.cpp:3050
virtual void CleanupsBeforeDelete(bool finalCleanup=true)
Definition Object.cpp:333
void RemoveFromObjectUpdate() override
Definition Object.cpp:3091
virtual float MeleeSpellMissChance(Unit const *victim, WeaponAttackType attType, SpellInfo const *spellInfo) const
Definition Object.cpp:1841
void ModSpellDurationTime(SpellInfo const *spellInfo, int32 &durationTime, Spell *spell=nullptr) const
Definition Object.cpp:1816
void SetTransport(TransportBase *t)
Definition Object.cpp:3103
std::vector< SpellLogMissEntry > Entries
WorldPacket const * Write() override
WorldPacket const * Write() override
TaggedPosition<::Position::XYZ > Position
virtual WorldPacket const * Write()=0
TaggedPosition< Position::XYZ > SourceRotation
TaggedPosition< Position::XYZ > TargetLocation
TaggedPosition< Position::XYZ > SourceLocation
WorldPacket const * Write() override
#define sWorld
Definition World.h:919
@ CONFIG_DETECT_POS_COLLISION
Definition World.h:128
static constexpr uint32 Entry[5]
TC_GAME_API std::string MovementFlags_ToString(MovementFlags flags)
TC_GAME_API WorldObject * GetWorldObject(WorldObject const &, ObjectGuid const &)
TC_GAME_API Unit * GetUnit(WorldObject const &, ObjectGuid const &guid)
TC_GAME_API Player * GetPlayer(Map const *, ObjectGuid const &guid)
bool IsValidMapCoord(float c)
constexpr void NormalizeMapCoord(float &c)
UpdateFieldFlag
Definition UpdateField.h:37
constexpr bool IsIndirectFragment(EntityFragment frag)
bool IncludeHiddenBySpawnTracking
Definition Object.h:273
std::vector< SpellValueOverride > SpellValueOverrides
TriggerCastFlags TriggerFlags
Scripting::v2::ActionResultSetter< SpellCastResult > ScriptResult
Spell const * TriggeringSpell
Optional< int32 > OriginalCastItemLevel
AuraEffect const * TriggeringAura
Optional< SpellCastTargets > Targets
static void VisitWorldObjects(WorldObject const *obj, T &visitor, float radius)
Definition CellImpl.h:150
static void VisitAllObjects(WorldObject const *obj, T &visitor, float radius)
Definition CellImpl.h:160
static void VisitGridObjects(WorldObject const *obj, T &visitor, float radius)
Definition CellImpl.h:140
CombatLogSender(WorldPackets::CombatLog::CombatLogServerPacket *msg)
Definition Object.cpp:1123
WorldPackets::CombatLog::CombatLogServerPacket const * i_message
Definition Object.cpp:1121
void operator()(Player const *player) const
Definition Object.cpp:1129
int16 ReputationIndex
bool IsHostileToPlayers() const
bool IsNeutralToAll() const
bool IsFriendlyTo(FactionTemplateEntry const *entry) const
bool IsHostileTo(FactionTemplateEntry const *entry) const
ObjectGuid guid
Optional< Inertia > inertia
Optional< ObjectGuid > standingOnGameObjectGUID
struct MovementInfo::JumpInfo jump
float stepUpStartElevation
struct MovementInfo::TransportInfo transport
MovementFlags flags
void OutDebug()
Definition Object.cpp:167
Optional< AdvFlying > advFlying
Optional< WmoLocation > wmoLocation
Definition MapDefines.h:172
ZLiquidStatus liquidStatus
Definition MapDefines.h:171
constexpr void SetOrientation(float orientation)
Definition Position.h:82
constexpr float GetPositionX() const
Definition Position.h:87
constexpr Position()
Definition Position.h:31
float m_positionZ
Definition Position.h:66
constexpr float GetPositionY() const
Definition Position.h:88
float GetExactDist2d(const float x, const float y) const
Definition Position.h:117
constexpr bool IsInDist2d(float x, float y, float dist) const
Definition Position.h:151
std::string ToString() const
Definition Position.cpp:202
float GetExactDist(float x, float y, float z) const
Definition Position.h:129
float m_positionX
Definition Position.h:64
float m_positionY
Definition Position.h:65
bool HasInArc(float arcangle, Position const *pos, float border=2.0f) const
Definition Position.cpp:173
float GetAbsoluteAngle(float x, float y) const
Definition Position.h:136
constexpr float GetExactDist2dSq(const float x, const float y) const
Definition Position.h:108
constexpr void GetPosition(float &x, float &y) const
Definition Position.h:92
constexpr void Relocate(float x, float y)
Definition Position.h:74
constexpr float GetExactDistSq(float x, float y, float z) const
Definition Position.h:121
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
void toEulerAnglesZYX(float &Z, float &Y, float &X) const
Optional< ObjectGuid > ReplaceObject
EnumFlag< SummonPropertiesFlags > GetFlags() const
Position Pos
Definition Position.h:254
Stores data for temp summons.
Definition ObjectMgr.h:90
Milliseconds time
Despawn time, usable only with certain temp summon types.
Definition ObjectMgr.h:94
uint32 entry
Entry of summoned creature.
Definition ObjectMgr.h:91
Position pos
Position, where should be creature spawned.
Definition ObjectMgr.h:92
UpdateDataMapType & i_updateDatas
Definition Object.cpp:3060
WorldObjectChangeAccumulator(WorldObject &obj, UpdateDataMapType &d)
Definition Object.cpp:3063
void operator()(Player *player)
Definition Object.cpp:3065
GuidUnorderedSet plr_list
Definition Object.cpp:3062
void operator()(Player *player) const
Definition Object.cpp:3024
WorldObjectVisibleChangeVisitor(Work &work_)
Definition Object.cpp:2977
void Visit(PlayerMapType &m) const
Definition Object.cpp:2979
static void Visit(GridRefManager< SKIP > const &)
Definition Object.cpp:3017
void Visit(CreatureMapType &m) const
Definition Object.cpp:2992
void Visit(DynamicObjectMapType &m) const
Definition Object.cpp:2999
static void Register(EntityFragment fragment, EntityFragmentSerializeFn serializeCreate, EntityFragmentSerializeFn serializeUpdate, EntityFragmentIsChangedFn isChanged, EntityFragmentClearChangedFn clearChanged)
void Add(EntityFragment fragment, bool update, void const *data=nullptr)