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