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 "Battleground.h"
21#include "CellImpl.h"
22#include "CinematicMgr.h"
23#include "Common.h"
24#include "Creature.h"
25#include "GameTime.h"
26#include "GridNotifiersImpl.h"
27#include "G3DPosition.hpp"
28#include "Item.h"
29#include "Log.h"
30#include "Map.h"
31#include "MiscPackets.h"
32#include "MovementInfo.h"
33#include "MovementPackets.h"
34#include "ObjectAccessor.h"
35#include "ObjectMgr.h"
36#include "OutdoorPvPMgr.h"
37#include "PathGenerator.h"
38#include "Player.h"
39#include "ReputationMgr.h"
40#include "SpellAuraEffects.h"
41#include "SpellMgr.h"
42#include "StringConvert.h"
43#include "TemporarySummon.h"
44#include "Totem.h"
45#include "Transport.h"
46#include "Unit.h"
47#include "UpdateFieldFlags.h"
48#include "Vehicle.h"
49#include "VMapFactory.h"
50#include "VMapManager2.h"
51#include "World.h"
52#include <G3D/Vector3.h>
53
63
78
80{
81 if (IsInWorld())
82 {
83 TC_LOG_FATAL("misc", "Object::~Object {} deleted but still in world!!", GetGUID().ToString());
84 if (Item* item = ToItem())
85 TC_LOG_FATAL("misc", "Item slot {}", item->GetSlot());
86 ABORT();
87 }
88
90 {
91 TC_LOG_FATAL("misc", "Object::~Object {} deleted but still in update list!!", GetGUID().ToString());
92 ABORT();
93 }
94
95 delete [] m_uint32Values;
96 m_uint32Values = nullptr;
97}
98
100{
102 memset(m_uint32Values, 0, m_valuesCount*sizeof(uint32));
103
105
106 m_objectUpdated = false;
107}
108
117
119{
120 if (m_inWorld)
121 return;
122
124
125 m_inWorld = true;
126
127 // synchronize values mirror with values array (changes will send in updatecreate opcode any way
129 ClearUpdateMask(false);
130
131 // 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)
132 // Changing the ref when adding/removing from world prevents accessing players on different maps (possibly from another thread)
133 if (!m_scriptRef)
135}
136
138{
139 if (!m_inWorld)
140 return;
141
142 m_inWorld = false;
143
144 // if we remove from world then sending changes not required
145 ClearUpdateMask(true);
146
147 m_scriptRef = nullptr;
148}
149
151{
152 ByteBuffer& buf = data->GetBuffer();
153
155 buf << GetPackGUID();
156
158
159 data->AddUpdateBlock();
160}
161
163{
164 if (!target)
165 return;
166
169
171 if (target == this) // building packet for yourself
173
174 if (Unit const* unit = ToUnit())
175 {
176 if (unit->GetVictim())
178 }
179
180 //TC_LOG_DEBUG("BuildCreateUpdate: update-type: {}, object-type: {} got flags: {:X}, flags2: {:X}", updateType, m_objectTypeId, flags, flags2);
181
182 ByteBuffer& buf = data->GetBuffer();
183 buf << uint8(updateType);
184 buf << GetPackGUID();
185 buf << uint8(m_objectTypeId);
186
188 BuildValuesUpdate(updateType, &buf, target);
189 data->AddUpdateBlock();
190}
191
193{
194 // send create update to player
195 UpdateData upd;
196 WorldPacket packet;
197
198 if (player->HaveAtClient(this))
200 else
202 upd.BuildPacket(&packet);
203 player->SendDirectMessage(&packet);
204}
205
207{
208 ByteBuffer& buf = data->GetBuffer();
209
210 buf << uint8(UPDATETYPE_VALUES);
211 buf << GetPackGUID();
212
214
215 data->AddUpdateBlock();
216}
217
222
223void Object::DestroyForPlayer(Player* target, bool onDeath) const
224{
225 ASSERT(target);
226
227 WorldPacket data(SMSG_DESTROY_OBJECT, 8 + 1);
228 data << GetGUID();
231 data << uint8(onDeath ? 1 : 0);
232 target->SendDirectMessage(&data);
233}
234
236{
237 ASSERT(index < m_valuesCount || PrintIndexError(index, false));
238 return m_int32Values[index];
239}
240
242{
243 ASSERT(index < m_valuesCount || PrintIndexError(index, false));
244 return m_uint32Values[index];
245}
246
248{
249 ASSERT(index + 1 < m_valuesCount || PrintIndexError(index, false));
250 return *((uint64*)&(m_uint32Values[index]));
251}
252
254{
255 ASSERT(index < m_valuesCount || PrintIndexError(index, false));
256 return m_floatValues[index];
257}
258
260{
261 ASSERT(index < m_valuesCount || PrintIndexError(index, false));
262 ASSERT(offset < 4);
263 return *(((uint8*)&m_uint32Values[index])+offset);
264}
265
267{
268 ASSERT(index < m_valuesCount || PrintIndexError(index, false));
269 ASSERT(offset < 2);
270 return *(((uint16*)&m_uint32Values[index])+offset);
271}
272
274{
275 ASSERT(index + 1 < m_valuesCount || PrintIndexError(index, false));
276 return *((ObjectGuid*)&(m_uint32Values[index]));
277}
278
280{
281 Unit const* unit = nullptr;
282 WorldObject const* object = nullptr;
283
284 unit = ToUnit();
285 if (!unit)
286 object = ToWorldObject();
287
288 *data << uint16(flags); // update flags
289
290 // 0x20
292 {
293 ASSERT(unit);
294 unit->BuildMovementPacket(data);
295
296 *data << float(unit->GetSpeed(MOVE_WALK));
297 *data << float(unit->GetSpeed(MOVE_RUN));
298 *data << float(unit->GetSpeed(MOVE_RUN_BACK));
299 *data << float(unit->GetSpeed(MOVE_SWIM));
300 *data << float(unit->GetSpeed(MOVE_SWIM_BACK));
301 *data << float(unit->GetSpeed(MOVE_FLIGHT));
302 *data << float(unit->GetSpeed(MOVE_FLIGHT_BACK));
303 *data << float(unit->GetSpeed(MOVE_TURN_RATE));
304 *data << float(unit->GetSpeed(MOVE_PITCH_RATE));
305
306 // 0x08000000
309 }
310 else
311 {
313 {
314 ASSERT(object);
315 Transport* transport = object->GetTransport();
316
317 if (transport)
318 *data << transport->GetPackGUID();
319 else
320 *data << uint8(0);
321
322 *data << float(object->GetPositionX());
323 *data << float(object->GetPositionY());
324 *data << float(object->GetPositionZ());
325
326 if (transport)
327 {
328 *data << float(object->GetTransOffsetX());
329 *data << float(object->GetTransOffsetY());
330 *data << float(object->GetTransOffsetZ());
331 }
332 else
333 {
334 *data << float(object->GetPositionX());
335 *data << float(object->GetPositionY());
336 *data << float(object->GetPositionZ());
337 }
338
339 *data << object->GetOrientation();
340
341 if (transport)
342 *data << float(object->GetTransOffsetO());
343 else
344 *data << float(object->GetOrientation());
345 }
346 else
347 {
348 // 0x40
350 {
351 ASSERT(object);
352 *data << float(object->GetStationaryX());
353 *data << float(object->GetStationaryY());
354 *data << float(object->GetStationaryZ());
355 *data << float(object->GetStationaryO());
356 }
357 }
358 }
359
360 // 0x8
362 {
363 *data << uint32(0);
364 }
365
366 // 0x10
368 {
369 switch (GetTypeId())
370 {
371 case TYPEID_OBJECT:
372 case TYPEID_ITEM:
373 case TYPEID_CONTAINER:
376 case TYPEID_CORPSE:
377 *data << uint32(GetGUID().GetCounter()); // GetGUID().GetCounter()
378 break;
381 case TYPEID_UNIT:
382 *data << uint32(0x0000000B); // unk
383 break;
384 case TYPEID_PLAYER:
386 *data << uint32(0x0000002F); // unk
387 else
388 *data << uint32(0x00000008); // unk
389 break;
390 default:
391 *data << uint32(0x00000000); // unk
392 break;
393 }
394 }
395
396 // 0x4
398 {
399 ASSERT(unit);
400 if (Unit* victim = unit->GetVictim())
401 *data << victim->GetPackGUID();
402 else
403 *data << uint8(0);
405
406 // 0x2
408 {
409 GameObject const* go = ToGameObject();
415 if (go && go->ToTransport())
416 *data << uint32(go->GetGOValue()->Transport.PathProgress);
417 else
419 }
420
421 // 0x80
423 {
424 ASSERT(unit);
425 ASSERT(unit->GetVehicleKit());
427 *data << uint32(unit->GetVehicleKit()->GetVehicleInfo()->ID);
429 *data << float(unit->GetTransOffsetO());
430 else
431 *data << float(unit->GetOrientation());
432 }
433
434 // 0x200
436 *data << int64(ToGameObject()->GetPackedLocalRotation());
437}
438
439void Object::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player const* target) const
440{
441 if (!target)
442 return;
443
444 ByteBuffer fieldBuffer;
446
447 uint32* flags = nullptr;
448 uint32 visibleFlag = GetUpdateFieldData(target, flags);
449 ASSERT(flags);
450
451 for (uint16 index = 0; index < m_valuesCount; ++index)
452 {
453 if (_fieldNotifyFlags & flags[index] ||
454 ((updateType == UPDATETYPE_VALUES ? _changesMask.GetBit(index) : m_uint32Values[index]) && (flags[index] & visibleFlag)))
455 {
456 updateMask.SetBit(index);
457 fieldBuffer << m_uint32Values[index];
458 }
459 }
460
461 updateMask.AppendToPacket(data);
462 data->append(fieldBuffer);
463}
464
470
471void Object::ClearUpdateMask(bool remove)
472{
474
475 if (m_objectUpdated)
476 {
477 if (remove)
479
480 m_objectUpdated = false;
481 }
482}
483
485{
486 UpdateDataMapType::iterator iter = data_map.try_emplace(player).first;
487 BuildValuesUpdateBlockForPlayer(&iter->second, iter->first);
488}
489
491{
492 uint32 visibleFlag = UF_FLAG_PUBLIC;
493
494 if (target == this)
495 visibleFlag |= UF_FLAG_PRIVATE;
496
497 switch (GetTypeId())
498 {
499 case TYPEID_ITEM:
500 case TYPEID_CONTAINER:
502 if (((Item const*)this)->GetOwnerGUID() == target->GetGUID())
503 visibleFlag |= UF_FLAG_OWNER | UF_FLAG_ITEM_OWNER;
504 break;
505 case TYPEID_UNIT:
506 case TYPEID_PLAYER:
507 {
510 if (ToUnit()->GetOwnerGUID() == target->GetGUID())
511 visibleFlag |= UF_FLAG_OWNER;
512
514 if (ToUnit()->HasAuraTypeWithCaster(SPELL_AURA_EMPATHY, target->GetGUID()))
515 visibleFlag |= UF_FLAG_SPECIAL_INFO;
516
517 if (plr && plr->IsInSameRaidWith(target))
518 visibleFlag |= UF_FLAG_PARTY_MEMBER;
519 break;
520 }
523 if (ToGameObject()->GetOwnerGUID() == target->GetGUID())
524 visibleFlag |= UF_FLAG_OWNER;
525 break;
528 if (ToDynObject()->GetCasterGUID() == target->GetGUID())
529 visibleFlag |= UF_FLAG_OWNER;
530 break;
531 case TYPEID_CORPSE:
533 if (ToCorpse()->GetOwnerGUID() == target->GetGUID())
534 visibleFlag |= UF_FLAG_OWNER;
535 break;
536 case TYPEID_OBJECT:
537 break;
538 }
539
540 return visibleFlag;
541}
542
543bool Object::_LoadIntoDataField(std::string const& data, uint32 startOffset, uint32 count)
544{
545 if (data.empty())
546 return false;
547
548 std::vector<std::string_view> tokens = Trinity::Tokenize(data, ' ', false);
549
550 if (tokens.size() != count)
551 return false;
552
553 for (uint32 index = 0; index < count; ++index)
554 {
555 Optional<uint32> val = Trinity::StringTo<uint32>(tokens[index]);
556 if (!val)
557 return false;
558 m_uint32Values[startOffset + index] = *val;
559 _changesMask.SetBit(startOffset + index);
560 }
561 return true;
562}
563
565{
566 ASSERT(index < m_valuesCount || PrintIndexError(index, true));
567
568 if (m_int32Values[index] != value)
569 {
570 m_int32Values[index] = value;
571 _changesMask.SetBit(index);
572
574 }
575}
576
578{
579 ASSERT(index < m_valuesCount || PrintIndexError(index, true));
580
581 if (m_uint32Values[index] != value)
582 {
583 m_uint32Values[index] = value;
584 _changesMask.SetBit(index);
585
587 }
588}
589
591{
592 ASSERT(index < m_valuesCount || PrintIndexError(index, true));
593
594 m_uint32Values[index] = value;
595 _changesMask.SetBit(index);
596}
597
599{
600 ASSERT(index + 1 < m_valuesCount || PrintIndexError(index, true));
601 if (*((uint64*)&(m_uint32Values[index])) != value)
602 {
603 m_uint32Values[index] = PAIR64_LOPART(value);
604 m_uint32Values[index + 1] = PAIR64_HIPART(value);
605 _changesMask.SetBit(index);
606 _changesMask.SetBit(index + 1);
607
609 }
610}
611
613{
614 ASSERT(index + 1 < m_valuesCount || PrintIndexError(index, true));
615 if (!value.IsEmpty() && ((ObjectGuid*)&(m_uint32Values[index]))->IsEmpty())
616 {
617 *((ObjectGuid*)&(m_uint32Values[index])) = value;
618 _changesMask.SetBit(index);
619 _changesMask.SetBit(index + 1);
620
622
623 return true;
624 }
625
626 return false;
627}
628
630{
631 ASSERT(index + 1 < m_valuesCount || PrintIndexError(index, true));
632 if (!value.IsEmpty() && *((ObjectGuid*)&(m_uint32Values[index])) == value)
633 {
634 m_uint32Values[index] = 0;
635 m_uint32Values[index + 1] = 0;
636 _changesMask.SetBit(index);
637 _changesMask.SetBit(index + 1);
638
640
641 return true;
642 }
643
644 return false;
645}
646
647void Object::SetFloatValue(uint16 index, float value)
648{
649 ASSERT(index < m_valuesCount || PrintIndexError(index, true));
650
651 if (m_floatValues[index] != value)
652 {
653 m_floatValues[index] = value;
654 _changesMask.SetBit(index);
655
657 }
658}
659
660void Object::SetByteValue(uint16 index, uint8 offset, uint8 value)
661{
662 ASSERT(index < m_valuesCount || PrintIndexError(index, true));
663 ASSERT(offset < 4);
664
665 if (uint8(m_uint32Values[index] >> (offset * 8)) != value)
666 {
667 m_uint32Values[index] &= ~uint32(uint32(0xFF) << (offset * 8));
668 m_uint32Values[index] |= uint32(uint32(value) << (offset * 8));
669 _changesMask.SetBit(index);
670
672
673 }
674}
675
676void Object::SetUInt16Value(uint16 index, uint8 offset, uint16 value)
677{
678 ASSERT(index < m_valuesCount || PrintIndexError(index, true));
679 ASSERT(offset < 2);
680
681 if (uint16(m_uint32Values[index] >> (offset * 16)) != value)
682 {
683 m_uint32Values[index] &= ~uint32(uint32(0xFFFF) << (offset * 16));
684 m_uint32Values[index] |= uint32(uint32(value) << (offset * 16));
685 _changesMask.SetBit(index);
686
688 }
689}
690
692{
693 ASSERT(index + 1 < m_valuesCount || PrintIndexError(index, true));
694 if (*((ObjectGuid*)&(m_uint32Values[index])) != value)
695 {
696 *((ObjectGuid*)&(m_uint32Values[index])) = value;
697 _changesMask.SetBit(index);
698 _changesMask.SetBit(index + 1);
699
701 }
702}
703
704void Object::SetStatFloatValue(uint16 index, float value)
705{
706 if (value < 0)
707 value = 0.0f;
708
709 SetFloatValue(index, value);
710}
711
713{
714 if (value < 0)
715 value = 0;
716
717 SetUInt32Value(index, uint32(value));
718}
719
720void Object::ApplyModUInt32Value(uint16 index, int32 val, bool apply)
721{
722 int32 cur = GetUInt32Value(index);
723 cur += (apply ? val : -val);
724 if (cur < 0)
725 cur = 0;
726 SetUInt32Value(index, cur);
727}
728
729void Object::ApplyModInt32Value(uint16 index, int32 val, bool apply)
730{
731 int32 cur = GetInt32Value(index);
732 cur += (apply ? val : -val);
733 SetInt32Value(index, cur);
734}
735
736void Object::ApplyModUInt16Value(uint16 index, uint8 offset, int16 val, bool apply)
737{
738 int16 cur = GetUInt16Value(index, offset);
739 cur += (apply ? val : -val);
740 if (cur < 0)
741 cur = 0;
742 SetUInt16Value(index, offset, cur);
743}
744
745void Object::ApplyModSignedFloatValue(uint16 index, float val, bool apply)
746{
747 float cur = GetFloatValue(index);
748 cur += (apply ? val : -val);
749 SetFloatValue(index, cur);
750}
751
752void Object::ApplyModPositiveFloatValue(uint16 index, float val, bool apply)
753{
754 float cur = GetFloatValue(index);
755 cur += (apply ? val : -val);
756 if (cur < 0)
757 cur = 0;
758 SetFloatValue(index, cur);
759}
760
761void Object::SetFlag(uint16 index, uint32 newFlag)
762{
763 ASSERT(index < m_valuesCount || PrintIndexError(index, true));
764 uint32 oldval = m_uint32Values[index];
765 uint32 newval = oldval | newFlag;
766
767 if (oldval != newval)
768 {
769 m_uint32Values[index] = newval;
770 _changesMask.SetBit(index);
771
773 }
774}
775
776void Object::RemoveFlag(uint16 index, uint32 oldFlag)
777{
778 ASSERT(index < m_valuesCount || PrintIndexError(index, true));
779
780 uint32 oldval = m_uint32Values[index];
781 uint32 newval = oldval & ~oldFlag;
782
783 if (oldval != newval)
784 {
785 m_uint32Values[index] = newval;
786 _changesMask.SetBit(index);
787
789 }
790}
791
793{
794 if (HasFlag(index, flag))
795 RemoveFlag(index, flag);
796 else
797 SetFlag(index, flag);
798}
799
800bool Object::HasFlag(uint16 index, uint32 flag) const
801{
802 ASSERT(index < m_valuesCount || PrintIndexError(index, true));
803 return (m_uint32Values[index] & flag) != 0;
804}
805
806void Object::ApplyModFlag(uint16 index, uint32 flag, bool apply)
807{
808 if (apply) SetFlag(index, flag); else RemoveFlag(index, flag);
809}
810
811void Object::SetByteFlag(uint16 index, uint8 offset, uint8 newFlag)
812{
813 ASSERT(index < m_valuesCount || PrintIndexError(index, true));
814 ASSERT(offset < 4);
815
816 if (!(uint8(m_uint32Values[index] >> (offset * 8)) & newFlag))
817 {
818 m_uint32Values[index] |= uint32(uint32(newFlag) << (offset * 8));
819 _changesMask.SetBit(index);
820
822 }
823}
824
825void Object::RemoveByteFlag(uint16 index, uint8 offset, uint8 oldFlag)
826{
827 ASSERT(index < m_valuesCount || PrintIndexError(index, true));
828 ASSERT(offset < 4);
829
830 if (uint8(m_uint32Values[index] >> (offset * 8)) & oldFlag)
831 {
832 m_uint32Values[index] &= ~uint32(uint32(oldFlag) << (offset * 8));
833 _changesMask.SetBit(index);
834
836 }
837}
838
839void Object::ToggleByteFlag(uint16 index, uint8 offset, uint8 flag)
840{
841 if (HasByteFlag(index, offset, flag))
842 RemoveByteFlag(index, offset, flag);
843 else
844 SetByteFlag(index, offset, flag);
845}
846
847bool Object::HasByteFlag(uint16 index, uint8 offset, uint8 flag) const
848{
849 ASSERT(index < m_valuesCount || PrintIndexError(index, false));
850 ASSERT(offset < 4);
851 return (((uint8*)&m_uint32Values[index])[offset] & flag) != 0;
852}
853
854void Object::ApplyModByteFlag(uint16 index, uint8 offset, uint8 flag, bool apply)
855{
856 if (apply) SetByteFlag(index, offset, flag); else RemoveByteFlag(index, offset, flag);
857}
858
859void Object::SetFlag64(uint16 index, uint64 newFlag)
860{
861 uint64 oldval = GetUInt64Value(index);
862 uint64 newval = oldval | newFlag;
863 SetUInt64Value(index, newval);
864}
865
867{
868 uint64 oldval = GetUInt64Value(index);
869 uint64 newval = oldval & ~oldFlag;
870 SetUInt64Value(index, newval);
871}
872
874{
875 if (HasFlag64(index, flag))
876 RemoveFlag64(index, flag);
877 else
878 SetFlag64(index, flag);
879}
880
881bool Object::HasFlag64(uint16 index, uint64 flag) const
882{
883 ASSERT(index < m_valuesCount || PrintIndexError(index, false));
884 return (GetUInt64Value(index) & flag) != 0;
885}
886
887void Object::ApplyModFlag64(uint16 index, uint64 flag, bool apply)
888{
889 if (apply) SetFlag64(index, flag); else RemoveFlag64(index, flag);
890}
891
892bool Object::PrintIndexError(uint32 index, bool set) const
893{
894 TC_LOG_ERROR("misc", "Attempt to {} non-existing value field: {} (count: {}) for object typeid: {} type mask: {}", (set ? "set value to" : "get value from"), index, m_valuesCount, GetTypeId(), m_objectType);
895
896 // ASSERT must fail after function call
897 return false;
898}
899
900std::string Object::GetDebugInfo() const
901{
902 std::stringstream sstr;
903 sstr << GetGUID().ToString() + " Entry " << GetEntry();
904 return sstr.str();
905}
906
908{
909 TC_LOG_DEBUG("misc", "MOVEMENT INFO");
910 TC_LOG_DEBUG("misc", "{}", guid.ToString());
911 TC_LOG_DEBUG("misc", "flags {}", flags);
912 TC_LOG_DEBUG("misc", "flags2 {}", flags2);
913 TC_LOG_DEBUG("misc", "time {} current time {}", flags2, uint64(::time(nullptr)));
914 TC_LOG_DEBUG("misc", "position: `{}`", pos.ToString());
916 {
917 TC_LOG_DEBUG("misc", "TRANSPORT:");
918 TC_LOG_DEBUG("misc", "{}", transport.guid.ToString());
919 TC_LOG_DEBUG("misc", "position: `{}`", transport.pos.ToString());
920 TC_LOG_DEBUG("misc", "seat: {}", transport.seat);
921 TC_LOG_DEBUG("misc", "time: {}", transport.time);
923 TC_LOG_DEBUG("misc", "time2: {}", transport.time2);
924 }
925
927 TC_LOG_DEBUG("misc", "pitch: {}", pitch);
928
929 TC_LOG_DEBUG("misc", "fallTime: {}", fallTime);
931 TC_LOG_DEBUG("misc", "j_zspeed: {} j_sinAngle: {} j_cosAngle: {} j_xyspeed: {}", jump.zspeed, jump.sinAngle, jump.cosAngle, jump.xyspeed);
932
934 TC_LOG_DEBUG("misc", "splineElevation: {}", splineElevation);
935}
936
937WorldObject::WorldObject(bool isWorldObject) : Object(), WorldLocation(), LastUsedScriptID(0),
938m_movementInfo(), m_name(), m_isActive(false), m_isFarVisible(false), m_isStoredInWorldObjectGridContainer(isWorldObject), m_zoneScript(nullptr),
939m_transport(nullptr), m_zoneId(0), m_areaId(0), m_staticFloorZ(VMAP_INVALID_HEIGHT), m_outdoors(false), m_liquidStatus(LIQUID_MAP_NO_WATER),
940m_currMap(nullptr), m_InstanceId(0), m_phaseMask(PHASEMASK_NORMAL), m_notifyflags(0), _heartbeatTimer(HEARTBEAT_INTERVAL)
941{
944}
945
947{
948 // this may happen because there are many !create/delete
950 {
951 if (GetTypeId() == TYPEID_CORPSE)
952 {
953 TC_LOG_FATAL("misc", "WorldObject::~WorldObject Corpse Type: {} ({}) deleted but still in map!!",
954 ToCorpse()->GetType(), GetGUID().ToString());
955 ABORT();
956 }
957 ResetMap();
958 }
959}
960
962{
963 m_Events.Update(diff);
964
966 while (_heartbeatTimer <= 0ms)
967 {
969 Heartbeat();
970 }
971}
972
974{
975 if (!IsInWorld())
976 return;
977
978 GetMap()->AddObjectToSwitchList(this, on);
979}
980
982{
984 return true;
985
986 if (ToCreature() && ToCreature()->m_isTempWorldObject)
987 return true;
988
989 return false;
990}
991
993{
994 if (m_isActive == on)
995 return;
996
997 if (GetTypeId() == TYPEID_PLAYER)
998 return;
999
1000 m_isActive = on;
1001
1002 if (on && !IsInWorld())
1003 return;
1004
1005 Map* map = FindMap();
1006 if (!map)
1007 return;
1008
1009 if (on)
1010 map->AddToActive(this);
1011 else
1012 map->RemoveFromActive(this);
1013}
1014
1016{
1017 if (GetTypeId() == TYPEID_PLAYER)
1018 return;
1019
1020 m_isFarVisible = on;
1021}
1022
1031
1032void WorldObject::CleanupsBeforeDelete(bool /*finalCleanup*/)
1033{
1034 if (IsInWorld())
1036
1037 if (Transport* transport = GetTransport())
1038 transport->RemovePassenger(this);
1039
1040 m_Events.KillAllEvents(false); // non-delatable (currently cast spells) will not deleted now but it will deleted at call in Map::RemoveAllObjectsInRemoveList
1041}
1042
1049
1051{
1052 m_zoneId = m_areaId = data.areaId;
1053 if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(m_areaId))
1054 if (area->ParentAreaID)
1055 m_zoneId = area->ParentAreaID;
1056 m_outdoors = data.outdoors;
1057 m_staticFloorZ = data.floorZ;
1059}
1060
1066
1068{
1069 if (!IsInWorld())
1070 return;
1071
1073
1075}
1076
1078{
1079 switch (GetZoneId())
1080 {
1081 case AREA_WINTERGRASP: // Wintergrasp
1082 return true;
1083 default:
1084 return false;
1085 }
1086}
1087
1089{
1090 Map* map = GetMap();
1091 return map->IsDungeon() ? ((InstanceMap*)map)->GetInstanceScript() : nullptr;
1092}
1093
1095{
1096 float dz = std::fabs(GetPositionZ() - obj->GetPositionZ());
1097 float sizefactor = GetCombatReach() + obj->GetCombatReach();
1098 float dist = dz - sizefactor;
1099 return (dist > 0 ? dist : 0);
1100}
1101
1102bool WorldObject::_IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D, bool incOwnRadius, bool incTargetRadius) const
1103{
1104 float sizefactor = 0;
1105 sizefactor += incOwnRadius ? GetCombatReach() : 0.0f;
1106 sizefactor += incTargetRadius ? obj->GetCombatReach() : 0.0f;
1107 float maxdist = dist2compare + sizefactor;
1108
1109 Position const* thisOrTransport = this;
1110 Position const* objOrObjTransport = obj;
1111
1112 if (GetTransport() && obj->GetTransport() && obj->GetTransport()->GetGUID() == GetTransport()->GetGUID())
1113 {
1114 thisOrTransport = &m_movementInfo.transport.pos;
1115 objOrObjTransport = &obj->m_movementInfo.transport.pos;
1116 }
1117
1118 if (is3D)
1119 return thisOrTransport->IsInDist(objOrObjTransport, maxdist);
1120 else
1121 return thisOrTransport->IsInDist2d(objOrObjTransport, maxdist);
1122}
1123
1125{
1126 float d = GetExactDist(obj) - GetCombatReach() - obj->GetCombatReach();
1127 return d > 0.0f ? d : 0.0f;
1128}
1129
1130float WorldObject::GetDistance(Position const& pos) const
1131{
1132 float d = GetExactDist(&pos) - GetCombatReach();
1133 return d > 0.0f ? d : 0.0f;
1134}
1135
1136float WorldObject::GetDistance(float x, float y, float z) const
1137{
1138 float d = GetExactDist(x, y, z) - GetCombatReach();
1139 return d > 0.0f ? d : 0.0f;
1140}
1141
1143{
1144 float d = GetExactDist2d(obj) - GetCombatReach() - obj->GetCombatReach();
1145 return d > 0.0f ? d : 0.0f;
1146}
1147
1148float WorldObject::GetDistance2d(float x, float y) const
1149{
1150 float d = GetExactDist2d(x, y) - GetCombatReach();
1151 return d > 0.0f ? d : 0.0f;
1152}
1153
1155{
1156 if (this == obj)
1157 return true;
1158 return IsInMap(obj);
1159}
1160
1161bool WorldObject::IsInMap(WorldObject const* obj) const
1162{
1163 if (obj)
1164 return IsInWorld() && obj->IsInWorld() && (GetMap() == obj->GetMap());
1165 return false;
1166}
1167
1168bool WorldObject::IsWithinDist3d(float x, float y, float z, float dist) const
1169{
1170 return IsInDist(x, y, z, dist + GetCombatReach());
1171}
1172
1173bool WorldObject::IsWithinDist3d(Position const* pos, float dist) const
1174{
1175 return IsInDist(pos, dist + GetCombatReach());
1176}
1177
1178bool WorldObject::IsWithinDist2d(float x, float y, float dist) const
1179{
1180 return IsInDist2d(x, y, dist + GetCombatReach());
1181}
1182
1183bool WorldObject::IsWithinDist2d(Position const* pos, float dist) const
1184{
1185 return IsInDist2d(pos, dist + GetCombatReach());
1186}
1187
1188bool WorldObject::IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D /*= true*/) const
1189{
1190 return obj && _IsWithinDist(obj, dist2compare, is3D);
1191}
1192
1193bool WorldObject::IsWithinDistInMap(WorldObject const* obj, float dist2compare, bool is3D /*= true*/, bool incOwnRadius /*= true*/, bool incTargetRadius /*= true*/) const
1194{
1195 return obj && IsInMap(obj) && InSamePhase(obj) && _IsWithinDist(obj, dist2compare, is3D, incOwnRadius, incTargetRadius);
1196}
1197
1199{
1200 G3D::Vector3 vThis(GetPositionX(), GetPositionY(), GetPositionZ() + GetCollisionHeight());
1201 G3D::Vector3 vObj(dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ());
1202 G3D::Vector3 contactPoint = vThis + (vObj - vThis).directionOrZero() * std::min(dest.GetExactDist(GetPosition()), GetCombatReach());
1203
1204 return Position(contactPoint.x, contactPoint.y, contactPoint.z, GetAbsoluteAngle(contactPoint.x, contactPoint.y));
1205}
1206
1207bool WorldObject::IsWithinLOS(float ox, float oy, float oz, LineOfSightChecks checks, VMAP::ModelIgnoreFlags ignoreFlags) const
1208{
1209 if (IsInWorld())
1210 {
1211 oz += GetCollisionHeight();
1212 float x, y, z;
1213 if (GetTypeId() == TYPEID_PLAYER)
1214 {
1215 GetPosition(x, y, z);
1216 z += GetCollisionHeight();
1217 }
1218 else
1219 GetHitSpherePointFor({ ox, oy, oz }, x, y, z);
1220
1221 return GetMap()->isInLineOfSight(x, y, z, ox, oy, oz, GetPhaseMask(), checks, ignoreFlags);
1222 }
1223
1224 return true;
1225}
1226
1228{
1229 if (!IsInMap(obj))
1230 return false;
1231
1232 float ox, oy, oz;
1233 if (obj->GetTypeId() == TYPEID_PLAYER)
1234 {
1235 obj->GetPosition(ox, oy, oz);
1236 oz += GetCollisionHeight();
1237 }
1238 else
1240
1241 float x, y, z;
1242 if (GetTypeId() == TYPEID_PLAYER)
1243 {
1244 GetPosition(x, y, z);
1245 z += GetCollisionHeight();
1246 }
1247 else
1248 GetHitSpherePointFor({ obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ() + obj->GetCollisionHeight() }, x, y, z);
1249
1250 return GetMap()->isInLineOfSight(x, y, z, ox, oy, oz, GetPhaseMask(), checks, ignoreFlags);
1251}
1252
1253void WorldObject::GetHitSpherePointFor(Position const& dest, float& x, float& y, float& z) const
1254{
1255 Position pos = GetHitSpherePointFor(dest);
1256 x = pos.GetPositionX();
1257 y = pos.GetPositionY();
1258 z = pos.GetPositionZ();
1259}
1260
1261bool WorldObject::GetDistanceOrder(WorldObject const* obj1, WorldObject const* obj2, bool is3D /* = true */) const
1262{
1263 float dx1 = GetPositionX() - obj1->GetPositionX();
1264 float dy1 = GetPositionY() - obj1->GetPositionY();
1265 float distsq1 = dx1*dx1 + dy1*dy1;
1266 if (is3D)
1267 {
1268 float dz1 = GetPositionZ() - obj1->GetPositionZ();
1269 distsq1 += dz1*dz1;
1270 }
1271
1272 float dx2 = GetPositionX() - obj2->GetPositionX();
1273 float dy2 = GetPositionY() - obj2->GetPositionY();
1274 float distsq2 = dx2*dx2 + dy2*dy2;
1275 if (is3D)
1276 {
1277 float dz2 = GetPositionZ() - obj2->GetPositionZ();
1278 distsq2 += dz2*dz2;
1279 }
1280
1281 return distsq1 < distsq2;
1282}
1283
1284bool WorldObject::IsInRange(WorldObject const* obj, float minRange, float maxRange, bool is3D /* = true */) const
1285{
1286 float dx = GetPositionX() - obj->GetPositionX();
1287 float dy = GetPositionY() - obj->GetPositionY();
1288 float distsq = dx*dx + dy*dy;
1289 if (is3D)
1290 {
1291 float dz = GetPositionZ() - obj->GetPositionZ();
1292 distsq += dz*dz;
1293 }
1294
1295 float sizefactor = GetCombatReach() + obj->GetCombatReach();
1296
1297 // check only for real range
1298 if (minRange > 0.0f)
1299 {
1300 float mindist = minRange + sizefactor;
1301 if (distsq < mindist * mindist)
1302 return false;
1303 }
1304
1305 float maxdist = maxRange + sizefactor;
1306 return distsq < maxdist * maxdist;
1307}
1308
1309bool WorldObject::IsInRange2d(float x, float y, float minRange, float maxRange) const
1310{
1311 float dx = GetPositionX() - x;
1312 float dy = GetPositionY() - y;
1313 float distsq = dx*dx + dy*dy;
1314
1315 float sizefactor = GetCombatReach();
1316
1317 // check only for real range
1318 if (minRange > 0.0f)
1319 {
1320 float mindist = minRange + sizefactor;
1321 if (distsq < mindist * mindist)
1322 return false;
1323 }
1324
1325 float maxdist = maxRange + sizefactor;
1326 return distsq < maxdist * maxdist;
1327}
1328
1329bool WorldObject::IsInRange3d(float x, float y, float z, float minRange, float maxRange) const
1330{
1331 float dx = GetPositionX() - x;
1332 float dy = GetPositionY() - y;
1333 float dz = GetPositionZ() - z;
1334 float distsq = dx*dx + dy*dy + dz*dz;
1335
1336 float sizefactor = GetCombatReach();
1337
1338 // check only for real range
1339 if (minRange > 0.0f)
1340 {
1341 float mindist = minRange + sizefactor;
1342 if (distsq < mindist * mindist)
1343 return false;
1344 }
1345
1346 float maxdist = maxRange + sizefactor;
1347 return distsq < maxdist * maxdist;
1348}
1349
1350bool WorldObject::IsInBetween(Position const& pos1, Position const& pos2, float size) const
1351{
1352 float dist = GetExactDist2d(pos1);
1353
1354 // not using sqrt() for performance
1355 if ((dist * dist) >= pos1.GetExactDist2dSq(pos2))
1356 return false;
1357
1358 if (!size)
1359 size = GetCombatReach() / 2;
1360
1361 float angle = pos1.GetAbsoluteAngle(pos2);
1362
1363 // not using sqrt() for performance
1364 return (size * size) >= GetExactDist2dSq(pos1.GetPositionX() + std::cos(angle) * dist, pos1.GetPositionY() + std::sin(angle) * dist);
1365}
1366
1367bool WorldObject::isInFront(WorldObject const* target, float arc) const
1368{
1369 return HasInArc(arc, target);
1370}
1371
1372bool WorldObject::isInBack(WorldObject const* target, float arc) const
1373{
1374 return !HasInArc(2 * float(M_PI) - arc, target);
1375}
1376
1377void WorldObject::GetRandomPoint(Position const& pos, float distance, float& rand_x, float& rand_y, float& rand_z) const
1378{
1379 if (!distance)
1380 {
1381 pos.GetPosition(rand_x, rand_y, rand_z);
1382 return;
1383 }
1384
1385 // angle to face `obj` to `this`
1386 float angle = (float)rand_norm()*static_cast<float>(2*M_PI);
1387 float new_dist = (float)rand_norm() + (float)rand_norm();
1388 new_dist = distance * (new_dist > 1 ? new_dist - 2 : new_dist);
1389
1390 rand_x = pos.m_positionX + new_dist * std::cos(angle);
1391 rand_y = pos.m_positionY + new_dist * std::sin(angle);
1392 rand_z = pos.m_positionZ;
1393
1396 UpdateGroundPositionZ(rand_x, rand_y, rand_z); // update to LOS height if available
1397}
1398
1399Position WorldObject::GetRandomPoint(Position const& srcPos, float distance) const
1400{
1401 float x, y, z;
1402 GetRandomPoint(srcPos, distance, x, y, z);
1403 return Position(x, y, z, GetOrientation());
1404}
1405
1406void WorldObject::UpdateGroundPositionZ(float x, float y, float &z) const
1407{
1408 float new_z = GetMapHeight(x, y, z);
1409 if (new_z > INVALID_HEIGHT)
1410 {
1411 z = new_z;
1412 if (Unit const* unit = ToUnit())
1413 z += unit->GetHoverOffset();
1414 }
1415}
1416
1417void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z, float* groundZ) const
1418{
1419 // TODO: Allow transports to be part of dynamic vmap tree
1420 if (GetTransport())
1421 {
1422 if (groundZ)
1423 *groundZ = z;
1424
1425 return;
1426 }
1427
1428 if (Unit const* unit = ToUnit())
1429 {
1430 if (!unit->CanFly())
1431 {
1432 bool canSwim = unit->CanSwim();
1433 float ground_z = z;
1434 float max_z;
1435 if (canSwim)
1436 max_z = GetMapWaterOrGroundLevel(x, y, z, &ground_z);
1437 else
1438 max_z = ground_z = GetMapHeight(x, y, z);
1439
1440 if (max_z > INVALID_HEIGHT)
1441 {
1442 // hovering units cannot go below their hover height
1443 float hoverOffset = unit->GetHoverOffset();
1444 max_z += hoverOffset;
1445 ground_z += hoverOffset;
1446
1447 if (z > max_z)
1448 z = max_z;
1449 else if (z < ground_z)
1450 z = ground_z;
1451 }
1452
1453 if (groundZ)
1454 *groundZ = ground_z;
1455 }
1456 else
1457 {
1458 float ground_z = GetMapHeight(x, y, z) + unit->GetHoverOffset();
1459 if (z < ground_z)
1460 z = ground_z;
1461
1462 if (groundZ)
1463 *groundZ = ground_z;
1464 }
1465 }
1466 else
1467 {
1468 float ground_z = GetMapHeight(x, y, z);
1469 if (ground_z > INVALID_HEIGHT)
1470 z = ground_z;
1471
1472 if (groundZ)
1473 *groundZ = ground_z;
1474 }
1475}
1476
1478{
1479 if (isActiveObject())
1480 {
1481 if (GetTypeId() == TYPEID_PLAYER && ToPlayer()->GetCinematicMgr()->IsOnCinematic())
1483
1484 return GetMap()->GetVisibilityRange();
1485 }
1486
1487 if (Creature const* thisCreature = ToCreature())
1488 return thisCreature->m_SightDistance;
1489
1490 return 0.0f;
1491}
1492
1494{
1495 if (IsVisibilityOverridden() && !ToPlayer())
1497 else if (IsFarVisible() && !ToPlayer())
1499 else
1500 return GetMap()->GetVisibilityRange();
1501}
1502
1503float WorldObject::GetSightRange(WorldObject const* target) const
1504{
1505 if (ToUnit())
1506 {
1507 if (ToPlayer())
1508 {
1509 if (target && target->IsVisibilityOverridden() && !target->ToPlayer())
1510 return *target->m_visibilityDistanceOverride;
1511 else if (target && target->IsFarVisible() && !target->ToPlayer())
1513 else if (ToPlayer()->GetCinematicMgr()->IsOnCinematic())
1515 else
1516 return GetMap()->GetVisibilityRange();
1517 }
1518 else if (ToCreature())
1519 return ToCreature()->m_SightDistance;
1520 else
1521 return SIGHT_RANGE_UNIT;
1522 }
1523
1524 if (ToDynObject() && isActiveObject())
1525 {
1526 return GetMap()->GetVisibilityRange();
1527 }
1528
1529 return 0.0f;
1530}
1531
1533{
1534 if (!IsPrivateObject())
1535 return true;
1536
1537 // Owner of this private object
1538 if (_privateObjectOwner == seer->GetGUID())
1539 return true;
1540
1541 // Another private object of the same owner
1543 return true;
1544
1545 return false;
1546}
1547
1548bool WorldObject::CanSeeOrDetect(WorldObject const* obj, bool implicitDetect, bool distanceCheck, bool checkAlert) const
1549{
1550 if (this == obj)
1551 return true;
1552
1553 if (obj->IsNeverVisible(implicitDetect) || CanNeverSee(obj))
1554 return false;
1555
1556 if (obj->IsAlwaysVisibleFor(this) || CanAlwaysSee(obj))
1557 return true;
1558
1559 if (!obj->CheckPrivateObjectOwnerVisibility(this))
1560 return false;
1561
1562 bool corpseVisibility = false;
1563 if (distanceCheck)
1564 {
1565 bool corpseCheck = false;
1566 if (Player const* thisPlayer = ToPlayer())
1567 {
1568 if (thisPlayer->isDead() && thisPlayer->GetHealth() > 0 && // Cheap way to check for ghost state
1570 {
1571 if (Corpse* corpse = thisPlayer->GetCorpse())
1572 {
1573 corpseCheck = true;
1574 if (corpse->IsWithinDist(thisPlayer, GetSightRange(obj), false))
1575 if (corpse->IsWithinDist(obj, GetSightRange(obj), false))
1576 corpseVisibility = true;
1577 }
1578 }
1579
1580 if (Unit const* target = obj->ToUnit())
1581 {
1582 // Don't allow to detect vehicle accessories if you can't see vehicle
1583 if (Unit const* vehicle = target->GetVehicleBase())
1584 if (!thisPlayer->HaveAtClient(vehicle))
1585 return false;
1586 }
1587 }
1588
1589 WorldObject const* viewpoint = this;
1590 if (Player const* player = ToPlayer())
1591 viewpoint = player->GetViewpoint();
1592
1593 if (!viewpoint)
1594 viewpoint = this;
1595
1596 if (!corpseCheck && !viewpoint->IsWithinDist(obj, GetSightRange(obj), false))
1597 return false;
1598 }
1599
1600 // GM visibility off or hidden NPC
1602 {
1603 // Stop checking other things for GMs
1605 return true;
1606 }
1607 else
1609
1610 // Ghost players, Spirit Healers, and some other NPCs
1612 {
1613 // Alive players can see dead players in some cases, but other objects can't do that
1614 if (Player const* thisPlayer = ToPlayer())
1615 {
1616 if (Player const* objPlayer = obj->ToPlayer())
1617 {
1618 if (thisPlayer->GetTeam() != objPlayer->GetTeam() || !thisPlayer->IsGroupVisibleFor(objPlayer))
1619 return false;
1620 }
1621 else
1622 return false;
1623 }
1624 else
1625 return false;
1626 }
1627
1628 if (obj->IsInvisibleDueToDespawn())
1629 return false;
1630
1631 if (!CanDetect(obj, implicitDetect, checkAlert))
1632 return false;
1633
1634 return true;
1635}
1636
1638{
1639 return GetMap() != obj->GetMap() || !InSamePhase(obj);
1640}
1641
1642bool WorldObject::CanDetect(WorldObject const* obj, bool implicitDetect, bool checkAlert) const
1643{
1644 WorldObject const* seer = this;
1645
1646 // If a unit is possessing another one, it uses the detection of the latter
1647 // Pets don't have detection, they use the detection of their masters
1648 if (Unit const* thisUnit = ToUnit())
1649 {
1650 if (thisUnit->isPossessing())
1651 {
1652 if (Unit* charmed = thisUnit->GetCharmed())
1653 seer = charmed;
1654 }
1655 else if (Unit* controller = thisUnit->GetCharmerOrOwner())
1656 seer = controller;
1657 }
1658
1659 if (obj->IsAlwaysDetectableFor(seer))
1660 return true;
1661
1662 if (!implicitDetect && !seer->CanDetectInvisibilityOf(obj))
1663 return false;
1664
1665 if (!implicitDetect && !seer->CanDetectStealthOf(obj, checkAlert))
1666 return false;
1667
1668 return true;
1669}
1670
1672{
1674
1675 // Check for not detected types
1676 if (mask != obj->m_invisibility.GetFlags())
1677 return false;
1678
1679 // It isn't possible in invisibility to detect something that can't detect the invisible object
1680 // (it's at least true for spell: 66)
1681 // It seems like that only Units are affected by this check (couldn't see arena doors with preparation invisibility)
1682 if (obj->ToUnit())
1684 return false;
1685
1686 for (uint32 i = 0; i < TOTAL_INVISIBILITY_TYPES; ++i)
1687 {
1688 if (!(mask & (1 << i)))
1689 continue;
1690
1691 int32 objInvisibilityValue = obj->m_invisibility.GetValue(InvisibilityType(i));
1692 int32 ownInvisibilityDetectValue = m_invisibilityDetect.GetValue(InvisibilityType(i));
1693
1694 // Too low value to detect
1695 if (ownInvisibilityDetectValue < objInvisibilityValue)
1696 return false;
1697 }
1698
1699 return true;
1700}
1701
1702bool WorldObject::CanDetectStealthOf(WorldObject const* obj, bool checkAlert) const
1703{
1704 // Combat reach is the minimal distance (both in front and behind),
1705 // and it is also used in the range calculation.
1706 // One stealth point increases the visibility range by 0.3 yard.
1707
1708 if (!obj->m_stealth.GetFlags())
1709 return true;
1710
1711 float distance = GetExactDist(obj);
1712 float combatReach = 0.0f;
1713
1714 Unit const* unit = ToUnit();
1715 if (unit)
1716 combatReach = unit->GetCombatReach();
1717
1718 if (distance < combatReach)
1719 return true;
1720
1721 // Only check back for units, it does not make sense for gameobjects
1722 if (unit && !HasInArc(float(M_PI), obj))
1723 return false;
1724
1725 // Traps should detect stealth always
1726 if (GameObject const* go = ToGameObject())
1727 if (go->GetGoType() == GAMEOBJECT_TYPE_TRAP)
1728 return true;
1729
1730 GameObject const* go = obj->ToGameObject();
1731 for (uint32 i = 0; i < TOTAL_STEALTH_TYPES; ++i)
1732 {
1733 if (!(obj->m_stealth.GetFlags() & (1 << i)))
1734 continue;
1735
1737 return true;
1738
1739 // Starting points
1740 int32 detectionValue = 30;
1741
1742 // Level difference: 5 point / level, starting from level 1.
1743 // There may be spells for this and the starting points too, but
1744 // not in the DBCs of the client.
1745 detectionValue += int32(GetLevelForTarget(obj) - 1) * 5;
1746
1747 // Apply modifiers
1748 detectionValue += m_stealthDetect.GetValue(StealthType(i));
1749 if (go)
1750 if (Unit* owner = go->GetOwner())
1751 detectionValue -= int32(owner->GetLevelForTarget(this) - 1) * 5;
1752
1753 detectionValue -= obj->m_stealth.GetValue(StealthType(i));
1754
1755 // Calculate max distance
1756 float visibilityRange = float(detectionValue) * 0.3f + combatReach;
1757
1758 // If this unit is an NPC then player detect range doesn't apply
1759 if (unit && unit->GetTypeId() == TYPEID_PLAYER && visibilityRange > MAX_PLAYER_STEALTH_DETECT_RANGE)
1760 visibilityRange = MAX_PLAYER_STEALTH_DETECT_RANGE;
1761
1762 // When checking for alert state, look 8% further, and then 1.5 yards more than that.
1763 if (checkAlert)
1764 visibilityRange += (visibilityRange * 0.08f) + 1.5f;
1765
1766 // If checking for alert, and creature's visibility range is greater than aggro distance, No alert
1767 Unit const* tunit = obj->ToUnit();
1768 if (checkAlert && unit && unit->ToCreature() && visibilityRange >= unit->ToCreature()->GetAttackDistance(tunit) + unit->ToCreature()->m_CombatDistance)
1769 return false;
1770
1771 if (distance > visibilityRange)
1772 return false;
1773 }
1774
1775 return true;
1776}
1777
1783
1784void WorldObject::SendMessageToSet(WorldPacket const* data, bool self) const
1785{
1786 if (IsInWorld())
1788}
1789
1790void WorldObject::SendMessageToSetInRange(WorldPacket const* data, float dist, bool /*self*/) const
1791{
1792 Trinity::MessageDistDeliverer notifier(this, data, dist);
1793 Cell::VisitWorldObjects(this, notifier, dist);
1794}
1795
1796void WorldObject::SendMessageToSet(WorldPacket const* data, Player const* skipped_rcvr) const
1797{
1798 Trinity::MessageDistDeliverer notifier(this, data, GetVisibilityRange(), false, skipped_rcvr);
1800}
1801
1803{
1805 data << guid;
1806 SendMessageToSet(&data, true);
1807}
1808
1810{
1811 ASSERT(map);
1812 ASSERT(!IsInWorld());
1813 if (m_currMap == map) // command add npc: first create, than loadfromdb
1814 return;
1815 if (m_currMap)
1816 {
1817 TC_LOG_FATAL("misc", "WorldObject::SetMap: obj {} new map {} {}, old map {} {}", (uint32)GetTypeId(), map->GetId(), map->GetInstanceId(), m_currMap->GetId(), m_currMap->GetInstanceId());
1818 ABORT();
1819 }
1820 m_currMap = map;
1821 m_mapId = map->GetId();
1822 m_InstanceId = map->GetInstanceId();
1825}
1826
1828{
1830 ASSERT(!IsInWorld());
1833 m_currMap = nullptr;
1834 //maybe not for corpse
1835 //m_mapId = 0;
1836 //m_InstanceId = 0;
1837}
1838
1840{
1842
1843 Map* map = FindMap();
1844 if (!map)
1845 {
1846 TC_LOG_ERROR("misc", "Object {} at attempt add to move list not have valid map (Id: {}).", GetGUID().ToString(), GetMapId());
1847 return;
1848 }
1849
1850 map->AddObjectToRemoveList(this);
1851}
1852
1853TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropertiesEntry const* properties /*= nullptr*/, uint32 duration /*= 0*/, WorldObject* summoner /*= nullptr*/, uint32 spellId /*= 0*/, uint32 vehId /*= 0*/, ObjectGuid privateObjectOwner /*= ObjectGuid::Empty*/)
1854{
1855 uint32 mask = UNIT_MASK_SUMMON;
1856 if (properties)
1857 {
1858 switch (properties->Control)
1859 {
1861 mask = UNIT_MASK_GUARDIAN;
1862 break;
1864 mask = UNIT_MASK_PUPPET;
1865 break;
1867 mask = UNIT_MASK_MINION;
1868 break;
1872 {
1873 switch (properties->Title)
1874 {
1875 case SUMMON_TYPE_MINION:
1878 mask = UNIT_MASK_GUARDIAN;
1879 break;
1880 case SUMMON_TYPE_TOTEM:
1882 mask = UNIT_MASK_TOTEM;
1883 break;
1886 mask = UNIT_MASK_SUMMON;
1887 break;
1889 mask = UNIT_MASK_MINION;
1890 break;
1891 default:
1892 if (properties->Flags & 512) // Mirror Image, Summon Gargoyle
1893 mask = UNIT_MASK_GUARDIAN;
1894 break;
1895 }
1896 break;
1897 }
1898 default:
1899 return nullptr;
1900 }
1901 }
1902
1903 uint32 phase = PHASEMASK_NORMAL;
1904 if (summoner)
1905 phase = summoner->GetPhaseMask();
1906
1907 Unit* summonerUnit = summoner ? summoner->ToUnit() : nullptr;
1908
1909 TempSummon* summon = nullptr;
1910 switch (mask)
1911 {
1912 case UNIT_MASK_SUMMON:
1913 summon = new TempSummon(properties, summoner, false);
1914 break;
1915 case UNIT_MASK_GUARDIAN:
1916 summon = new Guardian(properties, summonerUnit, false);
1917 break;
1918 case UNIT_MASK_PUPPET:
1919 summon = new Puppet(properties, summonerUnit);
1920 break;
1921 case UNIT_MASK_TOTEM:
1922 summon = new Totem(properties, summonerUnit);
1923 break;
1924 case UNIT_MASK_MINION:
1925 summon = new Minion(properties, summonerUnit, false);
1926 break;
1927 }
1928
1929 if (!summon->Create(GenerateLowGuid<HighGuid::Unit>(), this, phase, entry, pos, nullptr, vehId, true))
1930 {
1931 delete summon;
1932 return nullptr;
1933 }
1934
1935 summon->SetCreatedBySpell(spellId);
1936
1937 summon->SetHomePosition(pos);
1938
1939 summon->InitStats(duration);
1940
1941 summon->SetPrivateObjectOwner(privateObjectOwner);
1942
1943 AddToMap(summon->ToCreature());
1944 summon->InitSummon();
1945
1946 // call MoveInLineOfSight for nearby creatures
1947 Trinity::AIRelocationNotifier notifier(*summon);
1948 Cell::VisitAllObjects(summon, notifier, GetVisibilityRange());
1949
1950 return summon;
1951}
1952
1960void Map::SummonCreatureGroup(uint8 group, std::list<TempSummon*>* list /*= nullptr*/)
1961{
1962 std::vector<TempSummonData> const* data = sObjectMgr->GetSummonGroup(GetId(), SUMMONER_TYPE_MAP, group);
1963 if (!data)
1964 return;
1965
1966 for (std::vector<TempSummonData>::const_iterator itr = data->begin(); itr != data->end(); ++itr)
1967 if (TempSummon* summon = SummonCreature(itr->entry, itr->pos, nullptr, itr->time))
1968 if (list)
1969 list->push_back(summon);
1970}
1971
1973{
1974 if (Map* map = FindMap())
1975 {
1976 if (InstanceMap* instanceMap = map->ToInstanceMap())
1977 m_zoneScript = reinterpret_cast<ZoneScript*>(instanceMap->GetInstanceScript());
1978 else if (!map->IsBattlegroundOrArena())
1979 {
1980 if (Battlefield* bf = sBattlefieldMgr->GetBattlefieldToZoneId(GetZoneId()))
1981 m_zoneScript = bf;
1982 else
1983 m_zoneScript = sOutdoorPvPMgr->GetZoneScript(GetZoneId());
1984 }
1985 }
1986}
1987
1989{
1990 m_zoneScript = nullptr;
1991}
1992
1993TempSummon* 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*/)
1994{
1995 if (Map* map = FindMap())
1996 {
1997 if (TempSummon* summon = map->SummonCreature(entry, pos, nullptr, despawnTime.count(), this, spellId, vehId, privateObjectOwner))
1998 {
1999 summon->SetTempSummonType(despawnType);
2000 return summon;
2001 }
2002 }
2003
2004 return nullptr;
2005}
2006
2007TempSummon* 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*/)
2008{
2009 if (!x && !y && !z)
2010 GetClosePoint(x, y, z, GetCombatReach());
2011 if (!o)
2012 o = GetOrientation();
2013 return SummonCreature(id, { x,y,z,o }, despawnType, despawnTime, 0, 0, privateObjectOwner);
2014}
2015
2016GameObject* WorldObject::SummonGameObject(uint32 entry, Position const& pos, QuaternionData const& rot, Seconds respawnTime, GOSummonType summonType)
2017{
2018 if (!IsInWorld())
2019 return nullptr;
2020
2021 GameObjectTemplate const* goinfo = sObjectMgr->GetGameObjectTemplate(entry);
2022 if (!goinfo)
2023 {
2024 TC_LOG_ERROR("sql.sql", "Gameobject template {} not found in database!", entry);
2025 return nullptr;
2026 }
2027
2028 Map* map = GetMap();
2029 GameObject* go = new GameObject();
2030 if (!go->Create(map->GenerateLowGuid<HighGuid::GameObject>(), entry, map, GetPhaseMask(), pos, rot, 255, GO_STATE_READY))
2031 {
2032 delete go;
2033 return nullptr;
2034 }
2035
2036 go->SetRespawnTime(respawnTime.count());
2037 if (GetTypeId() == TYPEID_PLAYER || (GetTypeId() == TYPEID_UNIT && summonType == GO_SUMMON_TIMED_OR_CORPSE_DESPAWN)) //not sure how to handle this
2038 ToUnit()->AddGameObject(go);
2039 else
2040 go->SetSpawnedByDefault(false);
2041
2042 map->AddToMap(go);
2043 return go;
2044}
2045
2046GameObject* WorldObject::SummonGameObject(uint32 entry, float x, float y, float z, float ang, QuaternionData const& rot, Seconds respawnTime, GOSummonType summonType)
2047{
2048 if (!x && !y && !z)
2049 {
2050 GetClosePoint(x, y, z, GetCombatReach());
2051 ang = GetOrientation();
2052 }
2053
2054 Position pos(x, y, z, ang);
2055 return SummonGameObject(entry, pos, rot, respawnTime, summonType);
2056}
2057
2058Creature* WorldObject::SummonTrigger(float x, float y, float z, float ang, Milliseconds despawnTime, CreatureAI* (*GetAI)(Creature*))
2059{
2060 TempSummonType summonType = (despawnTime == 0s) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN;
2061 Creature* summon = SummonCreature(WORLD_TRIGGER, x, y, z, ang, summonType, despawnTime);
2062 if (!summon)
2063 return nullptr;
2064
2065 //summon->SetName(GetName());
2067 {
2068 summon->SetFaction(((Unit*)this)->GetFaction());
2069 summon->SetLevel(((Unit*)this)->GetLevel());
2070 }
2071
2072 if (GetAI)
2073 summon->AIM_Initialize(GetAI(summon));
2074 return summon;
2075}
2076
2083void WorldObject::SummonCreatureGroup(uint8 group, std::list<TempSummon*>* list /*= nullptr*/)
2084{
2085 ASSERT((GetTypeId() == TYPEID_GAMEOBJECT || GetTypeId() == TYPEID_UNIT) && "Only GOs and creatures can summon npc groups!");
2086
2087 std::vector<TempSummonData> const* data = sObjectMgr->GetSummonGroup(GetEntry(), GetTypeId() == TYPEID_GAMEOBJECT ? SUMMONER_TYPE_GAMEOBJECT : SUMMONER_TYPE_CREATURE, group);
2088 if (!data)
2089 {
2090 TC_LOG_WARN("scripts", "{} ({}) tried to summon non-existing summon group {}.", GetName(), GetGUID().ToString(), group);
2091 return;
2092 }
2093
2094 for (std::vector<TempSummonData>::const_iterator itr = data->begin(); itr != data->end(); ++itr)
2095 if (TempSummon* summon = SummonCreature(itr->entry, itr->pos, itr->type, Milliseconds(itr->time)))
2096 if (list)
2097 list->push_back(summon);
2098}
2099
2100Creature* WorldObject::FindNearestCreature(uint32 entry, float range, bool alive) const
2101{
2102 Creature* creature = nullptr;
2103 Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck checker(*this, entry, alive, range);
2105 Cell::VisitAllObjects(this, searcher, range);
2106 return creature;
2107}
2108
2110{
2111 Creature* creature = nullptr;
2112 Trinity::NearestCheckCustomizer checkCustomizer(*this, range);
2113 Trinity::CreatureWithOptionsInObjectRangeCheck checker(*this, checkCustomizer, options);
2114 Trinity::CreatureLastSearcher searcher(this, creature, checker);
2115 if (options.IgnorePhases)
2117
2118 Cell::VisitAllObjects(this, searcher, range);
2119 return creature;
2120}
2121
2122GameObject* WorldObject::FindNearestGameObject(uint32 entry, float range, bool spawnedOnly) const
2123{
2124 GameObject* go = nullptr;
2125 Trinity::NearestGameObjectEntryInObjectRangeCheck checker(*this, entry, range, spawnedOnly);
2127 Cell::VisitGridObjects(this, searcher, range);
2128 return go;
2129}
2130
2132{
2133 GameObject* go = nullptr;
2134 Trinity::NearestCheckCustomizer checkCustomizer(*this, range);
2135 Trinity::GameObjectWithOptionsInObjectRangeCheck checker(*this, checkCustomizer, options);
2136 Trinity::GameObjectLastSearcher searcher(this, go, checker);
2137 if (options.IgnorePhases)
2139
2140 Cell::VisitGridObjects(this, searcher, range);
2141 return go;
2142}
2143
2145{
2146 GameObject* go = nullptr;
2149 Cell::VisitGridObjects(this, searcher, range);
2150 return go;
2151}
2152
2154{
2155 GameObject* go = nullptr;
2156 Trinity::NearestGameObjectTypeInObjectRangeCheck checker(*this, type, range);
2158 Cell::VisitGridObjects(this, searcher, range);
2159 return go;
2160}
2161
2163{
2164 Player* target = nullptr;
2165
2166 Trinity::NearestPlayerInObjectRangeCheck checker(this, distance);
2168 Cell::VisitWorldObjects(this, searcher, distance);
2169
2170 return target;
2171}
2172
2174{
2176 if (!guid.IsEmpty())
2177 return guid;
2178 return GetGUID();
2179}
2180
2182{
2183 return ObjectAccessor::GetUnit(*this, GetOwnerGUID());
2184}
2185
2187{
2188 if (Unit const* unit = ToUnit())
2189 return unit->GetCharmerOrOwner();
2190 else if (GameObject const* go = ToGameObject())
2191 return go->GetOwner();
2192
2193 return nullptr;
2194}
2195
2197{
2198 if (Unit* u = GetCharmerOrOwner())
2199 return u;
2200
2201 return const_cast<WorldObject*>(this)->ToUnit();
2202}
2203
2205{
2207 if (guid.IsPlayer())
2208 return ObjectAccessor::GetPlayer(*this, guid);
2209
2210 return const_cast<WorldObject*>(this)->ToPlayer();
2211}
2212
2214{
2215 if (!GetCharmerOrOwnerGUID())
2216 return const_cast<WorldObject*>(this)->ToPlayer();
2217
2218 if (Unit* owner = GetCharmerOrOwner())
2220
2221 return nullptr;
2222}
2223
2225{
2226 if (Player* player = const_cast<WorldObject*>(this)->ToPlayer())
2227 return player;
2228
2229 if (GetTypeId() == TYPEID_UNIT)
2230 {
2231 Creature const* creature = ToCreature();
2232 if (creature->IsPet() || creature->IsTotem())
2233 {
2234 if (Unit* owner = creature->GetOwner())
2235 return owner->ToPlayer();
2236 }
2237 }
2238 else if (GetTypeId() == TYPEID_GAMEOBJECT)
2239 {
2240 GameObject const* go = ToGameObject();
2241 if (Unit* owner = go->GetOwner())
2242 return owner->ToPlayer();
2243 }
2244
2245 return nullptr;
2246}
2247
2248// function uses real base points (typically value - 1)
2249int32 WorldObject::CalculateSpellDamage(SpellEffectInfo const& spellEffectInfo, int32 const* basePoints /*= nullptr*/) const
2250{
2251 return spellEffectInfo.CalcValue(this, basePoints);
2252}
2253
2254float WorldObject::GetSpellMaxRangeForTarget(Unit const* target, SpellInfo const* spellInfo) const
2255{
2256 if (!spellInfo->RangeEntry)
2257 return 0.f;
2258
2259 if (spellInfo->RangeEntry->RangeMax[0] == spellInfo->RangeEntry->RangeMax[1])
2260 return spellInfo->GetMaxRange();
2261
2262 if (!target)
2263 return spellInfo->GetMaxRange(true);
2264
2265 return spellInfo->GetMaxRange(!IsHostileTo(target));
2266}
2267
2268float WorldObject::GetSpellMinRangeForTarget(Unit const* target, SpellInfo const* spellInfo) const
2269{
2270 if (!spellInfo->RangeEntry)
2271 return 0.f;
2272
2273 if (spellInfo->RangeEntry->RangeMin[0] == spellInfo->RangeEntry->RangeMin[1])
2274 return spellInfo->GetMinRange();
2275
2276 if (!target)
2277 return spellInfo->GetMinRange(true);
2278
2279 return spellInfo->GetMinRange(!IsHostileTo(target));
2280}
2281
2282float WorldObject::ApplyEffectModifiers(SpellInfo const* spellInfo, uint8 effIndex, float value) const
2283{
2284 if (Player* modOwner = GetSpellModOwner())
2285 {
2286 modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_ALL_EFFECTS, value);
2287 switch (effIndex)
2288 {
2289 case EFFECT_0:
2290 modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_EFFECT1, value);
2291 break;
2292 case EFFECT_1:
2293 modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_EFFECT2, value);
2294 break;
2295 case EFFECT_2:
2296 modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_EFFECT3, value);
2297 break;
2298 }
2299 }
2300 return value;
2301}
2302
2304{
2305 uint8 comboPoints = 0;
2306 if (Unit const* unit = ToUnit())
2307 comboPoints = unit->GetComboPoints();
2308
2309 int32 minduration = spellInfo->GetDuration();
2310 int32 maxduration = spellInfo->GetMaxDuration();
2311
2312 int32 duration;
2313 if (comboPoints && minduration != -1 && minduration != maxduration)
2314 duration = minduration + int32((maxduration - minduration) * comboPoints / 5);
2315 else
2316 duration = minduration;
2317
2318 return duration;
2319}
2320
2321int32 WorldObject::ModSpellDuration(SpellInfo const* spellInfo, WorldObject const* target, int32 duration, bool positive, uint32 effectMask) const
2322{
2323 // don't mod permanent auras duration
2324 if (duration < 0)
2325 return duration;
2326
2327 // some auras are not affected by duration modifiers
2329 return duration;
2330
2331 // cut duration only of negative effects
2332 Unit const* unitTarget = target->ToUnit();
2333 if (!unitTarget)
2334 return duration;
2335
2336 if (!positive)
2337 {
2338 int32 mechanicMask = spellInfo->GetSpellMechanicMaskByEffectMask(effectMask);
2339 auto mechanicCheck = [mechanicMask](AuraEffect const* aurEff) -> bool
2340 {
2341 if (mechanicMask & (1 << aurEff->GetMiscValue()))
2342 return true;
2343 return false;
2344 };
2345
2346 // Find total mod value (negative bonus)
2347 int32 durationMod_always = unitTarget->GetTotalAuraModifier(SPELL_AURA_MECHANIC_DURATION_MOD, mechanicCheck);
2348 // Find max mod (negative bonus)
2349 int32 durationMod_not_stack = unitTarget->GetMaxNegativeAuraModifier(SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK, mechanicCheck);
2350
2351 // Select strongest negative mod
2352 int32 durationMod = std::min(durationMod_always, durationMod_not_stack);
2353 if (durationMod != 0)
2354 AddPct(duration, durationMod);
2355
2356 // there are only negative mods currently
2357 durationMod_always = unitTarget->GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL, spellInfo->Dispel);
2359
2360 durationMod = std::min(durationMod_always, durationMod_not_stack);
2361 if (durationMod != 0)
2362 AddPct(duration, durationMod);
2363 }
2364 else
2365 {
2366 // else positive mods here, there are no currently
2367 // when there will be, change GetTotalAuraModifierByMiscValue to GetMaxPositiveAuraModifierByMiscValue
2368
2369 // Mixology - duration boost
2370 if (unitTarget->GetTypeId() == TYPEID_PLAYER)
2371 {
2372 if (spellInfo->SpellFamilyName == SPELLFAMILY_POTION && (
2373 sSpellMgr->IsSpellMemberOfSpellGroup(spellInfo->Id, SPELL_GROUP_ELIXIR_BATTLE) ||
2374 sSpellMgr->IsSpellMemberOfSpellGroup(spellInfo->Id, SPELL_GROUP_ELIXIR_GUARDIAN)))
2375 {
2376 if (unitTarget->HasAura(53042) && unitTarget->HasSpell(spellInfo->GetEffect(EFFECT_0).TriggerSpell))
2377 duration *= 2;
2378 }
2379 }
2380 }
2381
2382 // Glyphs which increase duration of selfcast buffs
2383 if (unitTarget == this)
2384 {
2385 switch (spellInfo->SpellFamilyName)
2386 {
2387 case SPELLFAMILY_DRUID:
2388 if (spellInfo->SpellFamilyFlags[0] & 0x100)
2389 {
2390 // Glyph of Thorns
2391 if (AuraEffect* aurEff = unitTarget->GetAuraEffect(57862, EFFECT_0))
2392 duration += aurEff->GetAmount() * MINUTE * IN_MILLISECONDS;
2393 }
2394 break;
2396 if ((spellInfo->SpellFamilyFlags[0] & 0x00000002) && spellInfo->SpellIconID == 298)
2397 {
2398 // Glyph of Blessing of Might
2399 if (AuraEffect* aurEff = unitTarget->GetAuraEffect(57958, EFFECT_0))
2400 duration += aurEff->GetAmount() * MINUTE * IN_MILLISECONDS;
2401 }
2402 else if ((spellInfo->SpellFamilyFlags[0] & 0x00010000) && spellInfo->SpellIconID == 306)
2403 {
2404 // Glyph of Blessing of Wisdom
2405 if (AuraEffect* aurEff = unitTarget->GetAuraEffect(57979, EFFECT_0))
2406 duration += aurEff->GetAmount() * MINUTE * IN_MILLISECONDS;
2407 }
2408 break;
2409 }
2410 }
2411
2412 return std::max(duration, 0);
2413}
2414
2415void WorldObject::ModSpellCastTime(SpellInfo const* spellInfo, int32& castTime, Spell* spell /*= nullptr*/) const
2416{
2417 if (!spellInfo || castTime < 0)
2418 return;
2419
2420 // called from caster
2421 if (Player* modOwner = GetSpellModOwner())
2422 modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CASTING_TIME, castTime, spell);
2423
2424 Unit const* unitCaster = ToUnit();
2425 if (!unitCaster)
2426 return;
2427
2429 ((GetTypeId() == TYPEID_PLAYER && spellInfo->SpellFamilyName) || GetTypeId() == TYPEID_UNIT))
2430 castTime = unitCaster->CanInstantCast() ? 0 : int32(float(castTime) * unitCaster->GetFloatValue(UNIT_MOD_CAST_SPEED));
2432 castTime = int32(float(castTime) * unitCaster->m_modAttackSpeedPct[RANGED_ATTACK]);
2433 else if (spellInfo->SpellVisual[0] == 3881 && unitCaster->HasAura(67556)) // cooking with Chef Hat.
2434 castTime = 500;
2435}
2436
2437void WorldObject::ModSpellDurationTime(SpellInfo const* spellInfo, int32& duration, Spell* spell /*= nullptr*/) const
2438{
2439 if (!spellInfo || duration < 0)
2440 return;
2441
2442 if (spellInfo->IsChanneled() && !spellInfo->HasAttribute(SPELL_ATTR5_HASTE_AFFECT_DURATION))
2443 return;
2444
2445 // called from caster
2446 if (Player* modOwner = GetSpellModOwner())
2447 modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CASTING_TIME, duration, spell);
2448
2449 Unit const* unitCaster = ToUnit();
2450 if (!unitCaster)
2451 return;
2452
2454 ((GetTypeId() == TYPEID_PLAYER && spellInfo->SpellFamilyName) || GetTypeId() == TYPEID_UNIT))
2455 duration = int32(float(duration) * unitCaster->GetFloatValue(UNIT_MOD_CAST_SPEED));
2457 duration = int32(float(duration) * unitCaster->m_modAttackSpeedPct[RANGED_ATTACK]);
2458}
2459
2460float WorldObject::MeleeSpellMissChance(Unit const* /*victim*/, WeaponAttackType /*attType*/, int32 /*skillDiff*/, uint32 /*spellId*/) const
2461{
2462 return 0.0f;
2463}
2464
2465SpellMissInfo WorldObject::MeleeSpellHitResult(Unit* /*victim*/, SpellInfo const* /*spellInfo*/) const
2466{
2467 return SPELL_MISS_NONE;
2468}
2469
2471{
2472 // Can`t miss on dead target (on skinning for example)
2473 if (!victim->IsAlive() && victim->GetTypeId() != TYPEID_PLAYER)
2474 return SPELL_MISS_NONE;
2475
2476 if (spellInfo->HasAttribute(SPELL_ATTR7_CANT_MISS))
2477 return SPELL_MISS_NONE;
2478
2479 SpellSchoolMask schoolMask = spellInfo->GetSchoolMask();
2480 // PvP - PvE spell misschances per leveldif > 2
2481 int32 lchance = victim->GetTypeId() == TYPEID_PLAYER ? 7 : 11;
2482 int32 thisLevel = GetLevelForTarget(victim);
2483 if (GetTypeId() == TYPEID_UNIT && ToCreature()->IsTrigger())
2484 thisLevel = std::max<int32>(thisLevel, spellInfo->SpellLevel);
2485 int32 leveldif = int32(victim->GetLevelForTarget(this)) - thisLevel;
2486
2487 // Base hit chance from attacker and victim levels
2488 int32 modHitChance;
2489 if (leveldif < 3)
2490 modHitChance = 96 - leveldif;
2491 else
2492 modHitChance = 94 - (leveldif - 2) * lchance;
2493
2494 // Spellmod from SPELLMOD_RESIST_MISS_CHANCE
2495 if (Player* modOwner = GetSpellModOwner())
2496 modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_RESIST_MISS_CHANCE, modHitChance);
2497
2498 // Increase from attacker SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT auras
2499 if (Unit const* unit = ToUnit())
2501
2502 // Chance hit from victim SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE auras
2504 // Reduce spell hit chance for Area of effect spells from victim SPELL_AURA_MOD_AOE_AVOIDANCE aura
2505 if (spellInfo->IsAffectingArea())
2506 modHitChance -= victim->GetTotalAuraModifier(SPELL_AURA_MOD_AOE_AVOIDANCE);
2507
2508 // Decrease hit chance from victim rating bonus
2509 if (victim->GetTypeId() == TYPEID_PLAYER)
2510 modHitChance -= int32(victim->ToPlayer()->GetRatingBonusValue(CR_HIT_TAKEN_SPELL));
2511
2512 int32 HitChance = modHitChance * 100;
2513 // Increase hit chance from attacker SPELL_AURA_MOD_SPELL_HIT_CHANCE and attacker ratings
2514 if (Unit const* unit = ToUnit())
2515 HitChance += int32(unit->m_modSpellHitChance * 100.0f);
2516
2517 RoundToInterval(HitChance, 0, 10000);
2518
2519 int32 tmp = 10000 - HitChance;
2520
2521 int32 rand = irand(0, 9999);
2522 if (tmp > 0 && rand < tmp)
2523 return SPELL_MISS_MISS;
2524
2525 // Chance resist mechanic (select max value from every mechanic spell effect)
2526 int32 resist_chance = victim->GetMechanicResistChance(spellInfo) * 100;
2527
2528 // Chance resist debuff
2529 if (!spellInfo->IsPositive() && !spellInfo->HasAttribute(SPELL_ATTR4_IGNORE_RESISTANCES))
2530 {
2531 bool hasAura = false;
2532 for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects())
2533 {
2534 if (spellEffectInfo.IsAura())
2535 {
2536 hasAura = true;
2537 break;
2538 }
2539 }
2540
2541 if (hasAura)
2542 resist_chance += victim->GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_DEBUFF_RESISTANCE, static_cast<int32>(spellInfo->Dispel)) * 100;
2543
2544 // resistance chance for binary spells, equals to average damage reduction of non-binary spell
2546 resist_chance += int32(Unit::CalculateAverageResistReduction(this, spellInfo->GetSchoolMask(), victim, spellInfo) * 10000.f); // 100 for spell calculations, and 100 for return value percentage
2547 }
2548
2549 // Roll chance
2550 if (resist_chance > 0 && rand < (tmp += resist_chance))
2551 return SPELL_MISS_RESIST;
2552
2553 // cast by caster in front of victim
2554 if (!victim->HasUnitState(UNIT_STATE_CONTROLLED) && (victim->HasInArc(float(M_PI), this) || victim->HasAuraType(SPELL_AURA_IGNORE_HIT_DIRECTION)))
2555 {
2556 int32 deflect_chance = victim->GetTotalAuraModifier(SPELL_AURA_DEFLECT_SPELLS) * 100;
2557 if (deflect_chance > 0 && rand < (tmp += deflect_chance))
2558 return SPELL_MISS_DEFLECT;
2559 }
2560
2561 return SPELL_MISS_NONE;
2562}
2563
2564// Calculate spell hit result can be:
2565// Every spell can: Evade/Immune/Reflect/Sucesful hit
2566// For melee based spells:
2567// Miss
2568// Dodge
2569// Parry
2570// For spells
2571// Resist
2572SpellMissInfo WorldObject::SpellHitResult(Unit* victim, SpellInfo const* spellInfo, bool canReflect /*= false*/) const
2573{
2574 // Check for immune
2575 if (victim->IsImmunedToSpell(spellInfo, this))
2576 return SPELL_MISS_IMMUNE;
2577
2578 // Damage immunity is only checked if the spell has damage effects, this immunity must not prevent aura apply
2579 // returns SPELL_MISS_IMMUNE in that case, for other spells, the SMSG_SPELL_GO must show hit
2580 if (spellInfo->HasOnlyDamageEffects() && victim->IsImmunedToDamage(spellInfo))
2581 return SPELL_MISS_IMMUNE;
2582
2583 // All positive spells can`t miss
2585 if (spellInfo->IsPositive() && !IsHostileTo(victim)) // prevent from affecting enemy by "positive" spell
2586 return SPELL_MISS_NONE;
2587
2588 if (this == victim)
2589 return SPELL_MISS_NONE;
2590
2591 // Return evade for units in evade mode
2592 if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks())
2593 return SPELL_MISS_EVADE;
2594
2595 // Try victim reflect spell
2596 if (canReflect)
2597 {
2598 int32 reflectchance = victim->GetTotalAuraModifier(SPELL_AURA_REFLECT_SPELLS);
2600
2601 if (reflectchance > 0 && roll_chance_i(reflectchance))
2602 return SPELL_MISS_REFLECT;
2603 }
2604
2606 return SPELL_MISS_NONE;
2607
2608 switch (spellInfo->DmgClass)
2609 {
2612 return MeleeSpellHitResult(victim, spellInfo);
2614 return SPELL_MISS_NONE;
2616 return MagicSpellHitResult(victim, spellInfo);
2617 }
2618 return SPELL_MISS_NONE;
2619}
2620
2621void WorldObject::SendSpellMiss(Unit* target, uint32 spellID, SpellMissInfo missInfo)
2622{
2623 WorldPacket data(SMSG_SPELLLOGMISS, (4 + 8 + 1 + 4 + 8 + 1));
2624 data << uint32(spellID);
2625 data << GetGUID();
2626 data << uint8(0); // can be 0 or 1
2627 data << uint32(1); // target count
2628 // for (i = 0; i < target count; ++i)
2629 data << target->GetGUID(); // target GUID
2630 data << uint8(missInfo);
2631 // end loop
2632 SendMessageToSet(&data, true);
2633}
2634
2636{
2637 uint32 factionId = GetFaction();
2638 FactionTemplateEntry const* entry = sFactionTemplateStore.LookupEntry(factionId);
2639 if (!entry)
2640 {
2641 switch (GetTypeId())
2642 {
2643 case TYPEID_PLAYER:
2644 TC_LOG_ERROR("entities.unit", "Player {} has invalid faction (faction template id) #{}", ToPlayer()->GetName(), factionId);
2645 break;
2646 case TYPEID_UNIT:
2647 TC_LOG_ERROR("entities.unit", "Creature (template id: {}) has invalid faction (faction template Id) #{}", ToCreature()->GetCreatureTemplate()->Entry, factionId);
2648 break;
2649 case TYPEID_GAMEOBJECT:
2650 if (factionId) // Gameobjects may have faction template id = 0
2651 TC_LOG_ERROR("entities.faction", "GameObject (template id: {}) has invalid faction (faction template Id) #{}", ToGameObject()->GetGOInfo()->entry, factionId);
2652 break;
2653 default:
2654 TC_LOG_ERROR("entities.unit", "Object (name={}, type={}) has invalid faction (faction template Id) #{}", GetName(), uint32(GetTypeId()), factionId);
2655 break;
2656 }
2657 }
2658
2659 return entry;
2660}
2661
2662// function based on function Unit::UnitReaction from 13850 client
2664{
2665 // always friendly to self
2666 if (this == target)
2667 return REP_FRIENDLY;
2668
2669 // always friendly to charmer or owner
2671 return REP_FRIENDLY;
2672
2673 Player const* selfPlayerOwner = GetAffectingPlayer();
2674 Player const* targetPlayerOwner = target->GetAffectingPlayer();
2675
2676 // check forced reputation to support SPELL_AURA_FORCE_REACTION
2677 if (selfPlayerOwner)
2678 {
2679 if (FactionTemplateEntry const* targetFactionTemplateEntry = target->GetFactionTemplateEntry())
2680 if (ReputationRank const* repRank = selfPlayerOwner->GetReputationMgr().GetForcedRankIfAny(targetFactionTemplateEntry))
2681 return *repRank;
2682 }
2683 else if (targetPlayerOwner)
2684 {
2685 if (FactionTemplateEntry const* selfFactionTemplateEntry = GetFactionTemplateEntry())
2686 if (ReputationRank const* repRank = targetPlayerOwner->GetReputationMgr().GetForcedRankIfAny(selfFactionTemplateEntry))
2687 return *repRank;
2688 }
2689
2690 Unit const* unit = Coalesce<const Unit>(ToUnit(), selfPlayerOwner);
2691 Unit const* targetUnit = Coalesce<const Unit>(target->ToUnit(), targetPlayerOwner);
2692 if (unit && unit->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED))
2693 {
2694 if (targetUnit && targetUnit->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED))
2695 {
2696 if (selfPlayerOwner && targetPlayerOwner)
2697 {
2698 // always friendly to other unit controlled by player, or to the player himself
2699 if (selfPlayerOwner == targetPlayerOwner)
2700 return REP_FRIENDLY;
2701
2702 // duel - always hostile to opponent
2703 if (selfPlayerOwner->duel && selfPlayerOwner->duel->Opponent == targetPlayerOwner && selfPlayerOwner->duel->State == DUEL_STATE_IN_PROGRESS)
2704 return REP_HOSTILE;
2705
2706 // same group - checks dependant only on our faction - skip FFA_PVP for example
2707 if (selfPlayerOwner->IsInRaidWith(targetPlayerOwner))
2708 return REP_FRIENDLY; // return true to allow config option AllowTwoSide.Interaction.Group to work
2709 // however client seems to allow mixed group parties, because in 13850 client it works like:
2710 // return GetFactionReactionTo(GetFactionTemplateEntry(), target);
2711 }
2712
2713 // check FFA_PVP
2714 if (unit->IsFFAPvP() && targetUnit->IsFFAPvP())
2715 return REP_HOSTILE;
2716
2717 if (selfPlayerOwner)
2718 {
2719 if (FactionTemplateEntry const* targetFactionTemplateEntry = targetUnit->GetFactionTemplateEntry())
2720 {
2721 if (ReputationRank const* repRank = selfPlayerOwner->GetReputationMgr().GetForcedRankIfAny(targetFactionTemplateEntry))
2722 return *repRank;
2723 if (!selfPlayerOwner->HasUnitFlag2(UNIT_FLAG2_IGNORE_REPUTATION))
2724 {
2725 if (FactionEntry const* targetFactionEntry = sFactionStore.LookupEntry(targetFactionTemplateEntry->Faction))
2726 {
2727 if (targetFactionEntry->CanHaveReputation())
2728 {
2729 // check contested flags
2730 if ((targetFactionTemplateEntry->Flags & FACTION_TEMPLATE_FLAG_CONTESTED_GUARD) &&
2732 return REP_HOSTILE;
2733
2734 // if faction has reputation, hostile state depends only from AtWar state
2735 if (selfPlayerOwner->GetReputationMgr().IsAtWar(targetFactionEntry))
2736 return REP_HOSTILE;
2737 return REP_FRIENDLY;
2738 }
2739 }
2740 }
2741 }
2742 }
2743 }
2744 }
2745
2746 // do checks dependant only on our faction
2748}
2749
2750/*static*/ ReputationRank WorldObject::GetFactionReactionTo(FactionTemplateEntry const* factionTemplateEntry, WorldObject const* target)
2751{
2752 // always neutral when no template entry found
2753 if (!factionTemplateEntry)
2754 return REP_NEUTRAL;
2755
2756 FactionTemplateEntry const* targetFactionTemplateEntry = target->GetFactionTemplateEntry();
2757 if (!targetFactionTemplateEntry)
2758 return REP_NEUTRAL;
2759
2760 if (Player const* targetPlayerOwner = target->GetAffectingPlayer())
2761 {
2762 // check contested flags
2763 if ((factionTemplateEntry->Flags & FACTION_TEMPLATE_FLAG_CONTESTED_GUARD) &&
2764 targetPlayerOwner->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_CONTESTED_PVP))
2765 return REP_HOSTILE;
2766 if (ReputationRank const* repRank = targetPlayerOwner->GetReputationMgr().GetForcedRankIfAny(factionTemplateEntry))
2767 return *repRank;
2768 if (target->IsUnit() && !target->ToUnit()->HasUnitFlag2(UNIT_FLAG2_IGNORE_REPUTATION))
2769 {
2770 if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionTemplateEntry->Faction))
2771 {
2772 if (factionEntry->CanHaveReputation())
2773 {
2774 // CvP case - check reputation, don't allow state higher than neutral when at war
2775 ReputationRank repRank = targetPlayerOwner->GetReputationMgr().GetRank(factionEntry);
2776 if (targetPlayerOwner->GetReputationMgr().IsAtWar(factionEntry))
2777 repRank = std::min(REP_NEUTRAL, repRank);
2778 return repRank;
2779 }
2780 }
2781 }
2782 }
2783
2784 // common faction based check
2785 if (factionTemplateEntry->IsHostileTo(*targetFactionTemplateEntry))
2786 return REP_HOSTILE;
2787 if (factionTemplateEntry->IsFriendlyTo(*targetFactionTemplateEntry))
2788 return REP_FRIENDLY;
2789 if (targetFactionTemplateEntry->IsFriendlyTo(*factionTemplateEntry))
2790 return REP_FRIENDLY;
2791 if (factionTemplateEntry->Flags & FACTION_TEMPLATE_FLAG_HOSTILE_BY_DEFAULT)
2792 return REP_HOSTILE;
2793 // neutral by default
2794 return REP_NEUTRAL;
2795}
2796
2797bool WorldObject::IsHostileTo(WorldObject const* target) const
2798{
2799 return GetReactionTo(target) <= REP_HOSTILE;
2800}
2801
2803{
2804 return GetReactionTo(target) >= REP_FRIENDLY;
2805}
2806
2808{
2809 FactionTemplateEntry const* my_faction = GetFactionTemplateEntry();
2810 if (!my_faction->Faction)
2811 return false;
2812
2813 FactionEntry const* raw_faction = sFactionStore.LookupEntry(my_faction->Faction);
2814 if (raw_faction && raw_faction->ReputationIndex >= 0)
2815 return false;
2816
2817 return my_faction->IsHostileToPlayers();
2818}
2819
2821{
2822 FactionTemplateEntry const* my_faction = GetFactionTemplateEntry();
2823 if (!my_faction->Faction)
2824 return true;
2825
2826 FactionEntry const* raw_faction = sFactionStore.LookupEntry(my_faction->Faction);
2827 if (raw_faction && raw_faction->ReputationIndex >= 0)
2828 return false;
2829
2830 return my_faction->IsNeutralToAll();
2831}
2832
2834{
2835 SpellInfo const* info = sSpellMgr->GetSpellInfo(spellId);
2836 if (!info)
2837 {
2838 TC_LOG_ERROR("entities.unit", "CastSpell: unknown spell {} by caster {}", spellId, GetGUID().ToString());
2840 }
2841
2842 if (!targets.Targets)
2843 {
2844 TC_LOG_ERROR("entities.unit", "CastSpell: Invalid target passed to spell cast {} by {}", spellId, GetGUID().ToString());
2846 }
2847
2848 Spell* spell = new Spell(this, info, args.TriggerFlags, args.OriginalCaster);
2849 for (auto const& pair : args.SpellValueOverrides)
2850 spell->SetSpellValue(pair.first, pair.second);
2851
2852 spell->m_CastItem = args.CastItem;
2853 return spell->prepare(*targets.Targets, args.TriggeringAura);
2854}
2855
2856// function based on function Unit::CanAttack from 13850 client
2857bool WorldObject::IsValidAttackTarget(WorldObject const* target, SpellInfo const* bySpell /*= nullptr*/) const
2858{
2859 ASSERT(target);
2860
2861 // some positive spells can be casted at hostile target
2862 bool isPositiveSpell = bySpell && bySpell->IsPositive();
2863
2864 // can't attack self (spells can, attribute check)
2865 if (!bySpell && this == target)
2866 return false;
2867
2868 // can't attack unattackable units
2869 Unit const* unitTarget = target->ToUnit();
2870 if (unitTarget && unitTarget->HasUnitState(UNIT_STATE_UNATTACKABLE))
2871 return false;
2872
2873 // can't attack GMs
2874 if (target->GetTypeId() == TYPEID_PLAYER && target->ToPlayer()->IsGameMaster())
2875 return false;
2876
2877 Unit const* unit = ToUnit();
2878 // visibility checks (only units)
2879 if (unit)
2880 {
2881 // can't attack invisible
2882 if (!bySpell || !bySpell->HasAttribute(SPELL_ATTR6_CAN_TARGET_INVISIBLE))
2883 {
2884 if (!unit->CanSeeOrDetect(target, bySpell && bySpell->IsAffectingArea()))
2885 return false;
2886 }
2887 }
2888
2889 // can't attack dead
2890 if ((!bySpell || !bySpell->IsAllowingDeadTarget()) && unitTarget && !unitTarget->IsAlive())
2891 return false;
2892
2893 // can't attack untargetable
2894 if ((!bySpell || !bySpell->HasAttribute(SPELL_ATTR6_CAN_TARGET_UNTARGETABLE)) && unitTarget && unitTarget->HasUnitFlag(UNIT_FLAG_UNINTERACTIBLE))
2895 return false;
2896
2897 if (Player const* playerAttacker = ToPlayer())
2898 {
2899 if (playerAttacker->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_UBER))
2900 return false;
2901 }
2902
2903 // check flags
2905 return false;
2906
2907 Unit const* unitOrOwner = unit;
2908 GameObject const* go = ToGameObject();
2909 if (go && go->GetGoType() == GAMEOBJECT_TYPE_TRAP)
2910 unitOrOwner = go->GetOwner();
2911
2912 // ignore immunity flags when assisting
2913 if (unitOrOwner && unitTarget && !(isPositiveSpell && bySpell->HasAttribute(SPELL_ATTR6_ASSIST_IGNORE_IMMUNE_FLAG)))
2914 {
2915 if (!unitOrOwner->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) && unitTarget->IsImmuneToNPC())
2916 return false;
2917
2918 if (!unitTarget->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) && unitOrOwner->IsImmuneToNPC())
2919 return false;
2920
2921 if (unitOrOwner->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) && unitTarget->IsImmuneToPC())
2922 return false;
2923
2924 if (unitTarget->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) && unitOrOwner->IsImmuneToPC())
2925 return false;
2926 }
2927
2928 // CvC case - can attack each other only when one of them is hostile
2929 if (unit && !unit->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) && unitTarget && !unitTarget->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED))
2930 return IsHostileTo(unitTarget) || unitTarget->IsHostileTo(this);
2931
2932 // Traps without owner or with NPC owner versus Creature case - can attack to creature only when one of them is hostile
2933 if (go && go->GetGoType() == GAMEOBJECT_TYPE_TRAP)
2934 {
2935 Unit const* goOwner = go->GetOwner();
2936 if (!goOwner || !goOwner->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED))
2937 if (unitTarget && !unitTarget->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED))
2938 return IsHostileTo(unitTarget) || unitTarget->IsHostileTo(this);
2939 }
2940
2941 // PvP, PvC, CvP case
2942 // can't attack friendly targets
2943 if (IsFriendlyTo(target) || target->IsFriendlyTo(this))
2944 return false;
2945
2946 Player const* playerAffectingAttacker = unit && unit->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) ? GetAffectingPlayer() : go ? GetAffectingPlayer() : nullptr;
2947 Player const* playerAffectingTarget = unitTarget && unitTarget->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) ? unitTarget->GetAffectingPlayer() : nullptr;
2948
2949 // Not all neutral creatures can be attacked (even some unfriendly faction does not react aggresive to you, like Sporaggar)
2950 if ((playerAffectingAttacker && !playerAffectingTarget) || (!playerAffectingAttacker && playerAffectingTarget))
2951 {
2952 Player const* player = playerAffectingAttacker ? playerAffectingAttacker : playerAffectingTarget;
2953
2954 if (Unit const* creature = playerAffectingAttacker ? unitTarget : unit)
2955 {
2956 if (creature->IsContestedGuard() && player->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_CONTESTED_PVP))
2957 return true;
2958
2959 if (FactionTemplateEntry const* factionTemplate = creature->GetFactionTemplateEntry())
2960 {
2961 if (!(player->GetReputationMgr().GetForcedRankIfAny(factionTemplate)))
2962 if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionTemplate->Faction))
2963 if (FactionState const* repState = player->GetReputationMgr().GetState(factionEntry))
2964 if (!repState->Flags.HasFlag(ReputationFlags::AtWar))
2965 return false;
2966
2967 }
2968 }
2969 }
2970
2971 Creature const* creatureAttacker = ToCreature();
2972 if (creatureAttacker && (creatureAttacker->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_TREAT_AS_RAID_UNIT))
2973 return false;
2974
2975 if (playerAffectingAttacker && playerAffectingTarget)
2976 if (playerAffectingAttacker->duel && playerAffectingAttacker->duel->Opponent == playerAffectingTarget && playerAffectingAttacker->duel->State == DUEL_STATE_IN_PROGRESS)
2977 return true;
2978
2979 // PvP case - can't attack when attacker or target are in sanctuary
2980 // however, 13850 client doesn't allow to attack when one of the unit's has sanctuary flag and is pvp
2981 if (unitTarget && unitTarget->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) && unitOrOwner && unitOrOwner->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) && (unitTarget->IsInSanctuary() || unitOrOwner->IsInSanctuary()))
2982 return false;
2983
2984 // additional checks - only PvP case
2985 if (playerAffectingAttacker && playerAffectingTarget)
2986 {
2987 if (playerAffectingTarget->IsPvP())
2988 return true;
2989
2990 if (playerAffectingAttacker->IsFFAPvP() && playerAffectingTarget->IsFFAPvP())
2991 return true;
2992
2993 return playerAffectingAttacker->HasPvpFlag(UNIT_BYTE2_FLAG_UNK1) ||
2994 playerAffectingTarget->HasPvpFlag(UNIT_BYTE2_FLAG_UNK1);
2995 }
2996
2997 return true;
2998}
2999
3000// function based on function Unit::CanAssist from 13850 client
3001bool WorldObject::IsValidAssistTarget(WorldObject const* target, SpellInfo const* bySpell /*= nullptr*/) const
3002{
3003 ASSERT(target);
3004
3005 // some negative spells can be casted at friendly target
3006 bool isNegativeSpell = bySpell && !bySpell->IsPositive();
3007
3008 // can assist to self
3009 if (this == target)
3010 return true;
3011
3012 // can't assist unattackable units
3013 Unit const* unitTarget = target->ToUnit();
3014 if (unitTarget && unitTarget->HasUnitState(UNIT_STATE_UNATTACKABLE))
3015 return false;
3016
3017 // can't assist GMs
3018 if (target->GetTypeId() == TYPEID_PLAYER && target->ToPlayer()->IsGameMaster())
3019 return false;
3020
3021 // can't assist own vehicle or passenger
3022 Unit const* unit = ToUnit();
3023 if (unit && unitTarget && unit->GetVehicle())
3024 {
3025 if (unit->IsOnVehicle(unitTarget))
3026 return false;
3027
3028 if (unit->GetVehicleBase()->IsOnVehicle(unitTarget))
3029 return false;
3030 }
3031
3032 // can't assist invisible
3033 if ((!bySpell || !bySpell->HasAttribute(SPELL_ATTR6_CAN_TARGET_INVISIBLE)) && !CanSeeOrDetect(target, bySpell && bySpell->IsAffectingArea()))
3034 return false;
3035
3036 // can't assist dead
3037 if ((!bySpell || !bySpell->IsAllowingDeadTarget()) && unitTarget && !unitTarget->IsAlive())
3038 return false;
3039
3040 // can't assist untargetable
3041 if ((!bySpell || !bySpell->HasAttribute(SPELL_ATTR6_CAN_TARGET_UNTARGETABLE)) && unitTarget && unitTarget->HasUnitFlag(UNIT_FLAG_UNINTERACTIBLE))
3042 return false;
3043
3044 // check flags for negative spells
3046 return false;
3047
3048 if (isNegativeSpell || !bySpell || !bySpell->HasAttribute(SPELL_ATTR6_ASSIST_IGNORE_IMMUNE_FLAG))
3049 {
3050 if (unit && unit->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED))
3051 {
3052 if (unitTarget && unitTarget->IsImmuneToPC())
3053 return false;
3054 }
3055 else
3056 {
3057 if (unitTarget && unitTarget->IsImmuneToNPC())
3058 return false;
3059 }
3060 }
3061
3062 // can't assist non-friendly targets
3063 if (GetReactionTo(target) < REP_NEUTRAL && target->GetReactionTo(this) < REP_NEUTRAL && (!ToCreature() || !(ToCreature()->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_TREAT_AS_RAID_UNIT)))
3064 return false;
3065
3066 // PvP case
3067 if (unitTarget && unitTarget->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED))
3068 {
3069 if (unit && unit->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED))
3070 {
3071 Player const* selfPlayerOwner = GetAffectingPlayer();
3072 Player const* targetPlayerOwner = unitTarget->GetAffectingPlayer();
3073 if (selfPlayerOwner && targetPlayerOwner)
3074 {
3075 // can't assist player which is dueling someone
3076 if (selfPlayerOwner != targetPlayerOwner && targetPlayerOwner->duel)
3077 return false;
3078 }
3079 // can't assist player in ffa_pvp zone from outside
3080 if (unitTarget->IsFFAPvP() && !unit->IsFFAPvP())
3081 return false;
3082
3083 // can't assist player out of sanctuary from sanctuary if has pvp enabled
3084 if (unitTarget->IsPvP())
3085 if (unit->IsInSanctuary() && !unitTarget->IsInSanctuary())
3086 return false;
3087 }
3088 }
3089 // PvC case - player can assist creature only if has specific type flags
3090 // !target->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) &&
3091 else if (unit && unit->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED))
3092 {
3093 if (!bySpell || !bySpell->HasAttribute(SPELL_ATTR6_ASSIST_IGNORE_IMMUNE_FLAG))
3094 if (unitTarget && !unitTarget->IsPvP())
3095 if (Creature const* creatureTarget = target->ToCreature())
3096 return ((creatureTarget->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_TREAT_AS_RAID_UNIT) || (creatureTarget->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_CAN_ASSIST));
3097 }
3098
3099 return true;
3100}
3101
3103{
3104 // Patch 1.2 notes: Spell Reflection no longer reflects abilities
3106 return victim;
3107
3109 for (AuraEffect const* aurEff : magnetAuras)
3110 {
3111 if (Unit* magnet = aurEff->GetBase()->GetCaster())
3112 {
3113 if (spellInfo->CheckExplicitTarget(this, magnet) == SPELL_CAST_OK && IsValidAttackTarget(magnet, spellInfo))
3114 {
3116 if (spellInfo->Speed > 0.0f)
3117 {
3118 // Set up missile speed based delay
3119 uint32 delay = uint32(std::floor(std::max<float>(victim->GetDistance(this), 5.0f) / spellInfo->Speed * 1000.0f));
3120 // Schedule charge drop
3121 aurEff->GetBase()->DropChargeDelayed(delay, AURA_REMOVE_BY_EXPIRE);
3122 }
3123 else
3124 aurEff->GetBase()->DropCharge(AURA_REMOVE_BY_EXPIRE);
3125
3126 return magnet;
3127 }
3128 }
3129 }
3130 return victim;
3131}
3132
3133template <typename Container>
3134void WorldObject::GetGameObjectListWithEntryInGrid(Container& gameObjectContainer, uint32 entry, float maxSearchRange /*= 250.0f*/) const
3135{
3136 Trinity::AllGameObjectsWithEntryInRange check(this, entry, maxSearchRange);
3137 Trinity::GameObjectListSearcher<Trinity::AllGameObjectsWithEntryInRange> searcher(this, gameObjectContainer, check);
3138 Cell::VisitGridObjects(this, searcher, maxSearchRange);
3139}
3140
3141template <typename Container>
3142void WorldObject::GetGameObjectListWithOptionsInGrid(Container& gameObjectContainer, float maxSearchRange, FindGameObjectOptions const& options) const
3143{
3144 Trinity::InRangeCheckCustomizer checkCustomizer(*this, maxSearchRange);
3145 Trinity::GameObjectWithOptionsInObjectRangeCheck check(*this, checkCustomizer, options);
3146 Trinity::GameObjectListSearcher searcher(this, gameObjectContainer, check);
3147 if (options.IgnorePhases)
3149
3150 Cell::VisitGridObjects(this, searcher, maxSearchRange);
3151}
3152
3153template <typename Container>
3154void WorldObject::GetCreatureListWithEntryInGrid(Container& creatureContainer, uint32 entry, float maxSearchRange /*= 250.0f*/) const
3155{
3156 Trinity::AllCreaturesOfEntryInRange check(this, entry, maxSearchRange);
3157 Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange> searcher(this, creatureContainer, check);
3158 Cell::VisitGridObjects(this, searcher, maxSearchRange);
3159}
3160
3161template <typename Container>
3162void WorldObject::GetCreatureListWithOptionsInGrid(Container& creatureContainer, float maxSearchRange, FindCreatureOptions const& options) const
3163{
3164 Trinity::InRangeCheckCustomizer checkCustomizer(*this, maxSearchRange);
3165 Trinity::CreatureWithOptionsInObjectRangeCheck check(*this, checkCustomizer, options);
3166 Trinity::CreatureListSearcher searcher(this, creatureContainer, check);
3167 if (options.IgnorePhases)
3169
3170 Cell::VisitGridObjects(this, searcher, maxSearchRange);
3171}
3172
3173template <typename Container>
3174void WorldObject::GetPlayerListInGrid(Container& playerContainer, float maxSearchRange, bool alive /*= true*/) const
3175{
3176 Trinity::AnyPlayerInObjectRangeCheck checker(this, maxSearchRange, alive);
3177 Trinity::PlayerListSearcher<Trinity::AnyPlayerInObjectRangeCheck> searcher(this, playerContainer, checker);
3178 Cell::VisitWorldObjects(this, searcher, maxSearchRange);
3179}
3180
3181void WorldObject::GetNearPoint2D(WorldObject const* searcher, float& x, float& y, float distance2d, float absAngle) const
3182{
3183 float effectiveReach = GetCombatReach();
3184
3185 if (searcher)
3186 {
3187 effectiveReach += searcher->GetCombatReach();
3188
3189 if (this != searcher)
3190 {
3191 float myHover = 0.0f, searcherHover = 0.0f;
3192 if (Unit const* unit = ToUnit())
3193 myHover = unit->GetHoverOffset();
3194 if (Unit const* searchUnit = searcher->ToUnit())
3195 searcherHover = searchUnit->GetHoverOffset();
3196
3197 float hoverDelta = myHover - searcherHover;
3198 if (hoverDelta != 0.0f)
3199 effectiveReach = std::sqrt(std::max(effectiveReach * effectiveReach - hoverDelta * hoverDelta, 0.0f));
3200 }
3201 }
3202
3203 x = GetPositionX() + (effectiveReach + distance2d) * std::cos(absAngle);
3204 y = GetPositionY() + (effectiveReach + distance2d) * std::sin(absAngle);
3205
3208}
3209
3210void WorldObject::GetNearPoint(WorldObject const* searcher, float& x, float& y, float& z, float distance2d, float absAngle) const
3211{
3212 GetNearPoint2D(searcher, x, y, distance2d, absAngle);
3213 z = GetPositionZ();
3214 (searcher ? searcher : this)->UpdateAllowedPositionZ(x, y, z);
3215
3216 // if detection disabled, return first point
3217 if (!sWorld->getBoolConfig(CONFIG_DETECT_POS_COLLISION))
3218 return;
3219
3220 // return if the point is already in LoS
3221 if (IsWithinLOS(x, y, z))
3222 return;
3223
3224 // remember first point
3225 float first_x = x;
3226 float first_y = y;
3227 float first_z = z;
3228
3229 // loop in a circle to look for a point in LoS using small steps
3230 for (float angle = float(M_PI) / 8; angle < float(M_PI) * 2; angle += float(M_PI) / 8)
3231 {
3232 GetNearPoint2D(searcher, x, y, distance2d, absAngle + angle);
3233 z = GetPositionZ();
3234 (searcher ? searcher : this)->UpdateAllowedPositionZ(x, y, z);
3235 if (IsWithinLOS(x, y, z))
3236 return;
3237 }
3238
3239 // still not in LoS, give up and return first position found
3240 x = first_x;
3241 y = first_y;
3242 z = first_z;
3243}
3244
3245void WorldObject::GetClosePoint(float& x, float& y, float& z, float size, float distance2d /*= 0*/, float relAngle /*= 0*/) const
3246{
3247 // angle calculated from current orientation
3248 GetNearPoint(nullptr, x, y, z, distance2d + size, GetOrientation() + relAngle);
3249}
3250
3252{
3253 Position pos = GetPosition();
3254 MovePosition(pos, dist, angle);
3255 return pos;
3256}
3257
3259{
3260 Position pos = GetPosition();
3261 MovePositionToFirstCollision(pos, dist, angle);
3262 return pos;
3263}
3264
3266{
3267 Position pos = GetPosition();
3268 MovePosition(pos, radius * (float)rand_norm(), (float)rand_norm() * static_cast<float>(2 * M_PI));
3269 return pos;
3270}
3271
3272void WorldObject::GetContactPoint(WorldObject const* obj, float& x, float& y, float& z, float distance2d /*= CONTACT_DISTANCE*/) const
3273{
3274 // angle to face `obj` to `this` using distance includes size of `obj`
3275 GetNearPoint(obj, x, y, z, distance2d, GetAbsoluteAngle(obj));
3276}
3277
3278void WorldObject::MovePosition(Position &pos, float dist, float angle)
3279{
3280 angle += GetOrientation();
3281 float destx, desty, destz, ground, floor;
3282 destx = pos.m_positionX + dist * std::cos(angle);
3283 desty = pos.m_positionY + dist * std::sin(angle);
3284
3285 // Prevent invalid coordinates here, position is unchanged
3286 if (!Trinity::IsValidMapCoord(destx, desty, pos.m_positionZ))
3287 {
3288 TC_LOG_FATAL("misc", "WorldObject::MovePosition: Object {} has invalid coordinates X: {} and Y: {} were passed!",
3289 GetGUID().ToString(), destx, desty);
3290 return;
3291 }
3292
3293 ground = GetMapHeight(destx, desty, MAX_HEIGHT);
3294 floor = GetMapHeight(destx, desty, pos.m_positionZ);
3295 destz = std::fabs(ground - pos.m_positionZ) <= std::fabs(floor - pos.m_positionZ) ? ground : floor;
3296
3297 float step = dist/10.0f;
3298
3299 for (uint8 j = 0; j < 10; ++j)
3300 {
3301 // do not allow too big z changes
3302 if (std::fabs(pos.m_positionZ - destz) > 6)
3303 {
3304 destx -= step * std::cos(angle);
3305 desty -= step * std::sin(angle);
3306 ground = GetMapHeight(destx, desty, MAX_HEIGHT);
3307 floor = GetMapHeight(destx, desty, pos.m_positionZ);
3308 destz = std::fabs(ground - pos.m_positionZ) <= std::fabs(floor - pos.m_positionZ) ? ground : floor;
3309 }
3310 // we have correct destz now
3311 else
3312 {
3313 pos.Relocate(destx, desty, destz);
3314 break;
3315 }
3316 }
3317
3322}
3323
3324void WorldObject::MovePositionToFirstCollision(Position &pos, float dist, float angle)
3325{
3326 angle += GetOrientation();
3327 float cosAngle = std::cos(angle);
3328 float sinAngle = std::sin(angle);
3329 float destx, desty, destz;
3330 destx = pos.m_positionX + dist * cosAngle;
3331 desty = pos.m_positionY + dist * sinAngle;
3332 destz = pos.m_positionZ;
3333
3334 // Prevent invalid coordinates here, position is unchanged
3335 if (!Trinity::IsValidMapCoord(destx, desty))
3336 {
3337 TC_LOG_FATAL("misc", "WorldObject::MovePositionToFirstCollision invalid coordinates Src: {}, dist {}, angle {}, destX: {} destY: {} were passed!",
3338 pos.ToString(), dist, angle, destx, desty);
3339 return;
3340 }
3341
3342 float halfHeight = GetCollisionHeight() * 0.5f;
3343 bool col = false;
3344
3345 // Use a detour raycast to get our first collision point
3346 PathGenerator path(this);
3347 path.SetUseRaycast(true);
3348 path.CalculatePath(destx, desty, destz, false);
3349
3350 // Check for valid path types before we proceed
3352 {
3353 G3D::Vector3 const& result = path.GetPath().back();
3354 destx = result.x;
3355 desty = result.y;
3356 destz = result.z;
3357 }
3358 else
3359 {
3360 // check static LOS
3361 // Unit is flying, check for potential collision via vmaps
3363 pos.m_positionX, pos.m_positionY, pos.m_positionZ + halfHeight,
3364 destx, desty, destz + halfHeight,
3365 destx, desty, destz, -0.5f);
3366
3367 destz -= halfHeight;
3368
3369 // Collided with static LOS object, move back to collision point
3370 if (col)
3371 {
3372 destx -= CONTACT_DISTANCE * cosAngle;
3373 desty -= CONTACT_DISTANCE * sinAngle;
3374 }
3375 }
3376
3377 // check dynamic collision
3379 pos.m_positionX, pos.m_positionY, pos.m_positionZ + halfHeight,
3380 destx, desty, destz + halfHeight,
3381 destx, desty, destz, -0.5f);
3382
3383 destz -= halfHeight;
3384
3385 // Collided with a gameobject, move back to collision point
3386 if (col)
3387 {
3388 destx -= CONTACT_DISTANCE * cosAngle;
3389 desty -= CONTACT_DISTANCE * sinAngle;
3390 }
3391
3392 float groundZ = VMAP_INVALID_HEIGHT_VALUE;
3395 UpdateAllowedPositionZ(destx, desty, destz, &groundZ);
3396
3397 pos.Relocate(destx, desty, destz, GetOrientation());
3398
3399 // position has no ground under it (or is too far away)
3400 if (groundZ <= INVALID_HEIGHT)
3401 {
3402 if (Unit const* unit = ToUnit())
3403 {
3404 // unit can fly, ignore.
3405 if (unit->CanFly())
3406 return;
3407
3408 // fall back to gridHeight if any
3409 float gridHeight = GetMap()->GetGridHeight(pos.m_positionX, pos.m_positionY);
3410 if (gridHeight > INVALID_HEIGHT)
3411 pos.m_positionZ = gridHeight + unit->GetHoverOffset();
3412 }
3413 }
3414}
3415
3416void WorldObject::SetPhaseMask(uint32 newPhaseMask, bool update)
3417{
3418 m_phaseMask = newPhaseMask;
3419
3420 if (update && IsInWorld())
3422}
3423
3424void WorldObject::PlayDistanceSound(uint32 soundId, Player* target /*= nullptr*/)
3425{
3426 if (target)
3428 else
3430}
3431
3432void WorldObject::PlayDirectSound(uint32 soundId, Player* target /*= nullptr*/)
3433{
3434 if (target)
3435 target->SendDirectMessage(WorldPackets::Misc::PlaySound(soundId).Write());
3436 else
3437 SendMessageToSet(WorldPackets::Misc::PlaySound(soundId).Write(), true);
3438}
3439
3440void WorldObject::PlayDirectMusic(uint32 musicId, Player* target /*= nullptr*/)
3441{
3442 if (target)
3443 target->SendDirectMessage(WorldPackets::Misc::PlayMusic(musicId).Write());
3444 else
3445 SendMessageToSet(WorldPackets::Misc::PlayMusic(musicId).Write(), true);
3446}
3447
3449{
3450 if (!IsInWorld())
3451 return;
3452
3453 std::list<Player*> targets;
3457 for (std::list<Player*>::const_iterator iter = targets.begin(); iter != targets.end(); ++iter)
3458 {
3459 Player* player = (*iter);
3460
3461 if (player == this)
3462 continue;
3463
3464 if (!player->HaveAtClient(this))
3465 continue;
3466
3467 if (Unit const* unit = ToUnit())
3468 {
3469 if (unit->GetCharmerGUID() == player->GetGUID())
3470 continue;
3471
3472 DestroyForPlayer(player, unit->IsDuringRemoveFromWorld() && unit->isDead()); // at remove from world (destroy) show kill animation
3473 }
3474 else
3475 DestroyForPlayer(player);
3476
3477 player->m_clientGUIDs.erase(GetGUID());
3478 }
3479}
3480
3482{
3483 //updates object's visibility for nearby players
3484 Trinity::VisibleChangesNotifier notifier(*this);
3486}
3487
3489{
3495 {
3496 Player* source = nullptr;
3497 for (PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
3498 {
3499 source = iter->GetSource();
3500
3501 BuildPacket(source);
3502
3503 if (!source->GetSharedVisionList().empty())
3504 {
3505 SharedVisionList::const_iterator it = source->GetSharedVisionList().begin();
3506 for (; it != source->GetSharedVisionList().end(); ++it)
3507 BuildPacket(*it);
3508 }
3509 }
3510 }
3511
3513 {
3514 Creature* source = nullptr;
3515 for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
3516 {
3517 source = iter->GetSource();
3518 if (!source->GetSharedVisionList().empty())
3519 {
3520 SharedVisionList::const_iterator it = source->GetSharedVisionList().begin();
3521 for (; it != source->GetSharedVisionList().end(); ++it)
3522 BuildPacket(*it);
3523 }
3524 }
3525 }
3526
3528 {
3529 DynamicObject* source = nullptr;
3530 for (DynamicObjectMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
3531 {
3532 source = iter->GetSource();
3533 ObjectGuid guid = source->GetCasterGUID();
3534
3535 if (guid.IsPlayer())
3536 {
3537 //Caster may be nullptr if DynObj is in removelist
3538 if (Player* caster = ObjectAccessor::FindPlayer(guid))
3539 if (caster->GetGuidValue(PLAYER_FARSIGHT) == source->GetGUID())
3540 BuildPacket(caster);
3541 }
3542 }
3543 }
3544
3545 void BuildPacket(Player* player)
3546 {
3547 // Only send update once to a player
3548 if (plr_list.find(player->GetGUID()) == plr_list.end() && player->HaveAtClient(&i_object))
3549 {
3551 plr_list.insert(player->GetGUID());
3552 }
3553 }
3554
3555 template<class SKIP> void Visit(GridRefManager<SKIP> &) { }
3556};
3557
3559{
3560 WorldObjectChangeAccumulator notifier(*this, data_map);
3561 //we must build packets for all visible players
3563
3564 ClearUpdateMask(false);
3565}
3566
3568{
3569 GetMap()->AddUpdateObject(this);
3570 return true;
3571}
3572
3577
3579{
3580 if (GetTransport())
3581 return GetTransport()->GetGUID();
3582 return ObjectGuid::Empty;
3583}
3584
3586{
3587 if (!IsInWorld())
3588 return m_staticFloorZ;
3589 return std::max<float>(m_staticFloorZ, GetMap()->GetGameObjectFloor(GetPhaseMask(), GetPositionX(), GetPositionY(), GetPositionZ() + Z_OFFSET_FIND_HEIGHT));
3590}
3591
3592float WorldObject::GetMapWaterOrGroundLevel(float x, float y, float z, float* ground/* = nullptr*/) const
3593{
3594 bool swimming = [&]()
3595 {
3596 if (Unit const* unit = ToUnit())
3597 return !unit->HasAuraType(SPELL_AURA_WATER_WALK);
3598
3599 return false;
3600 }();
3601
3602 return GetMap()->GetWaterOrGroundLevel(GetPhaseMask(), x, y, z, ground, swimming, GetCollisionHeight());
3603}
3604
3605float WorldObject::GetMapHeight(float x, float y, float z, bool vmap/* = true*/, float distanceToSearch/* = DEFAULT_HEIGHT_SEARCH*/) const
3606{
3607 if (z != MAX_HEIGHT)
3609
3610 return GetMap()->GetHeight(GetPhaseMask(), x, y, z, vmap, distanceToSearch);
3611}
3612
3613std::string WorldObject::GetDebugInfo() const
3614{
3615 std::stringstream sstr;
3616 sstr << WorldLocation::GetDebugInfo() << "\n"
3617 << Object::GetDebugInfo() << "\n"
3618 << "Name: " << GetName();
3619 return sstr.str();
3620}
3621
3622template TC_GAME_API void WorldObject::GetGameObjectListWithEntryInGrid(std::list<GameObject*>&, uint32, float) const;
3623template TC_GAME_API void WorldObject::GetGameObjectListWithEntryInGrid(std::deque<GameObject*>&, uint32, float) const;
3624template TC_GAME_API void WorldObject::GetGameObjectListWithEntryInGrid(std::vector<GameObject*>&, uint32, float) const;
3625
3626template TC_GAME_API void WorldObject::GetGameObjectListWithOptionsInGrid(std::list<GameObject*>&, float, FindGameObjectOptions const&) const;
3627template TC_GAME_API void WorldObject::GetGameObjectListWithOptionsInGrid(std::deque<GameObject*>&, float, FindGameObjectOptions const&) const;
3628template TC_GAME_API void WorldObject::GetGameObjectListWithOptionsInGrid(std::vector<GameObject*>&, float, FindGameObjectOptions const&) const;
3629
3630template TC_GAME_API void WorldObject::GetCreatureListWithEntryInGrid(std::list<Creature*>&, uint32, float) const;
3631template TC_GAME_API void WorldObject::GetCreatureListWithEntryInGrid(std::deque<Creature*>&, uint32, float) const;
3632template TC_GAME_API void WorldObject::GetCreatureListWithEntryInGrid(std::vector<Creature*>&, uint32, float) const;
3633
3634template TC_GAME_API void WorldObject::GetCreatureListWithOptionsInGrid(std::list<Creature*>&, float, FindCreatureOptions const&) const;
3635template TC_GAME_API void WorldObject::GetCreatureListWithOptionsInGrid(std::deque<Creature*>&,float, FindCreatureOptions const&) const;
3636template TC_GAME_API void WorldObject::GetCreatureListWithOptionsInGrid(std::vector<Creature*>&, float, FindCreatureOptions const&) const;
3637
3638template TC_GAME_API void WorldObject::GetPlayerListInGrid(std::list<Player*>&, float, bool) const;
3639template TC_GAME_API void WorldObject::GetPlayerListInGrid(std::deque<Player*>&, float, bool) const;
3640template TC_GAME_API void WorldObject::GetPlayerListInGrid(std::vector<Player*>&, float, bool) const;
#define sBattlefieldMgr
@ IN_MILLISECONDS
Definition Common.h:35
@ MINUTE
Definition Common.h:29
#define M_PI
Definition Common.h:71
@ FACTION_TEMPLATE_FLAG_HOSTILE_BY_DEFAULT
Definition DBCEnums.h:319
@ FACTION_TEMPLATE_FLAG_CONTESTED_GUARD
Definition DBCEnums.h:318
DBCStorage< FactionEntry > sFactionStore(FactionEntryfmt)
DBCStorage< FactionTemplateEntry > sFactionTemplateStore(FactionTemplateEntryfmt)
DBCStorage< AreaTableEntry > sAreaTableStore(AreaTableEntryfmt)
#define TC_GAME_API
Definition Define.h:114
uint8_t uint8
Definition Define.h:135
int64_t int64
Definition Define.h:128
int16_t int16
Definition Define.h:130
int32_t int32
Definition Define.h:129
uint64_t uint64
Definition Define.h:132
uint16_t uint16
Definition Define.h:134
uint32_t uint32
Definition Define.h:133
uint16 flags
std::chrono::seconds Seconds
Seconds shorthand typedef.
Definition Duration.h:27
std::chrono::milliseconds Milliseconds
Milliseconds shorthand typedef.
Definition Duration.h:24
#define ABORT
Definition Errors.h:74
#define ASSERT
Definition Errors.h:68
#define VMAP_INVALID_HEIGHT_VALUE
#define VMAP_INVALID_HEIGHT
#define TC_LOG_WARN(filterType__,...)
Definition Log.h:162
#define TC_LOG_DEBUG(filterType__,...)
Definition Log.h:156
#define TC_LOG_ERROR(filterType__,...)
Definition Log.h:165
#define TC_LOG_FATAL(filterType__,...)
Definition Log.h:168
@ LIQUID_MAP_NO_WATER
Definition MapDefines.h:75
#define MAX_HEIGHT
Definition Map.h:261
#define INVALID_HEIGHT
Definition Map.h:262
uint32 PAIR64_LOPART(uint64 x)
@ PHASEMASK_ANYWHERE
@ PHASEMASK_NORMAL
#define MAX_VISIBILITY_DISTANCE
#define DEFAULT_VISIBILITY_DISTANCE
#define VISIBILITY_DISTANCE_LARGE
TempSummonType
@ TEMPSUMMON_DEAD_DESPAWN
@ TEMPSUMMON_TIMED_DESPAWN
#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
uint32 PAIR64_HIPART(uint64 x)
#define VISIBILITY_DISTANCE_SMALL
VisibilityDistanceType
@ TYPEID_OBJECT
Definition ObjectGuid.h:35
@ TYPEID_DYNAMICOBJECT
Definition ObjectGuid.h:41
@ TYPEID_GAMEOBJECT
Definition ObjectGuid.h:40
@ TYPEID_UNIT
Definition ObjectGuid.h:38
@ TYPEID_CORPSE
Definition ObjectGuid.h:42
@ TYPEID_ITEM
Definition ObjectGuid.h:36
@ TYPEID_PLAYER
Definition ObjectGuid.h:39
@ TYPEID_CONTAINER
Definition ObjectGuid.h:37
std::set< ObjectGuid > GuidSet
Definition ObjectGuid.h:260
@ TYPEMASK_OBJECT
Definition ObjectGuid.h:49
#define sObjectMgr
Definition ObjectMgr.h:1721
@ SUMMONER_TYPE_MAP
Definition ObjectMgr.h:68
@ SUMMONER_TYPE_CREATURE
Definition ObjectMgr.h:66
@ SUMMONER_TYPE_GAMEOBJECT
Definition ObjectMgr.h:67
constexpr float VisibilityDistances[AsUnderlyingType(VisibilityDistanceType::Max)]
Definition Object.cpp:54
static constexpr Milliseconds const HEARTBEAT_INTERVAL
Definition Object.h:66
std::unordered_map< Player *, UpdateData > UpdateDataMapType
Definition Object.h:63
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition Optional.h:25
#define sOutdoorPvPMgr
@ PATHFIND_NOT_USING_PATH
@ PATHFIND_NOPATH
@ PATHFIND_FARFROMPOLY_START
@ DUEL_STATE_IN_PROGRESS
Definition Player.h:257
@ PLAYER_FLAGS_CONTESTED_PVP
Definition Player.h:354
@ PLAYER_FLAGS_UBER
Definition Player.h:365
int32 irand(int32 min, int32 max)
Definition Random.cpp:35
double rand_norm()
Definition Random.cpp:75
bool roll_chance_i(int chance)
Definition Random.h:59
@ SERVERSIDE_VISIBILITY_GM
@ SERVERSIDE_VISIBILITY_GHOST
GameobjectTypes
@ GAMEOBJECT_TYPE_TRAP
@ EFFECT_1
@ EFFECT_0
@ EFFECT_2
@ SPELL_ATTR7_CANT_MISS
@ SPELL_ATTR7_IGNORE_DURATION_MODS
StealthType
@ TOTAL_STEALTH_TYPES
@ SPELL_ATTR5_HASTE_AFFECT_DURATION
SpellSchoolMask
@ SPELL_SCHOOL_MASK_MAGIC
@ SPELL_ATTR2_AUTOREPEAT_FLAG
InvisibilityType
@ TOTAL_INVISIBILITY_TYPES
@ SPELL_ATTR1_CANT_BE_REDIRECTED
@ UNIT_DYNFLAG_SPECIALINFO
@ SPELL_ATTR3_NO_DONE_BONUS
@ SPELL_ATTR3_IGNORE_HIT_RESULT
@ SPELL_DAMAGE_CLASS_RANGED
@ SPELL_DAMAGE_CLASS_MAGIC
@ SPELL_DAMAGE_CLASS_NONE
@ SPELL_DAMAGE_CLASS_MELEE
@ SUMMON_TYPE_VEHICLE2
@ SUMMON_TYPE_LIGHTWELL
@ SUMMON_TYPE_MINION
@ SUMMON_TYPE_GUARDIAN
@ SUMMON_TYPE_TOTEM
@ SUMMON_TYPE_VEHICLE
@ SUMMON_TYPE_MINIPET
@ SUMMON_TYPE_GUARDIAN2
WeaponAttackType
@ RANGED_ATTACK
@ SPELLFAMILY_PALADIN
@ SPELLFAMILY_POTION
@ SPELLFAMILY_DRUID
@ SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY
@ SPELL_ATTR0_TRADESPELL
@ SPELL_ATTR0_ABILITY
@ SPELL_ATTR0_REQ_AMMO
ReputationRank
@ REP_FRIENDLY
@ REP_NEUTRAL
@ REP_HOSTILE
@ GHOST_VISIBILITY_ALIVE
@ GHOST_VISIBILITY_GHOST
LineOfSightChecks
SpellMissInfo
@ SPELL_MISS_IMMUNE
@ SPELL_MISS_NONE
@ SPELL_MISS_RESIST
@ SPELL_MISS_MISS
@ SPELL_MISS_EVADE
@ SPELL_MISS_REFLECT
@ SPELL_MISS_DEFLECT
constexpr float Z_OFFSET_FIND_HEIGHT
@ AREA_WINTERGRASP
SpellCastResult
@ SPELL_FAILED_BAD_TARGETS
@ SPELL_CAST_OK
@ SPELL_FAILED_SPELL_UNAVAILABLE
@ GO_STATE_READY
@ SPELL_ATTR4_IGNORE_RESISTANCES
@ SUMMON_CATEGORY_PET
@ SUMMON_CATEGORY_VEHICLE
@ SUMMON_CATEGORY_ALLY
@ SUMMON_CATEGORY_PUPPET
@ SUMMON_CATEGORY_WILD
@ SUMMON_CATEGORY_UNK
@ CREATURE_TYPE_FLAG_TREAT_AS_RAID_UNIT
@ CREATURE_TYPE_FLAG_CAN_ASSIST
@ SPELL_ATTR6_CAN_TARGET_INVISIBLE
@ SPELL_ATTR6_ASSIST_IGNORE_IMMUNE_FLAG
@ SPELL_ATTR6_CAN_TARGET_UNTARGETABLE
@ AURA_REMOVE_BY_EXPIRE
@ SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL_NOT_STACK
@ SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK
@ SPELL_AURA_MOD_DEBUFF_RESISTANCE
@ SPELL_AURA_REFLECT_SPELLS
@ SPELL_AURA_IGNORE_HIT_DIRECTION
@ SPELL_AURA_EMPATHY
@ 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_MOD_INCREASES_SPELL_PCT_TO_HIT
@ SPELL_AURA_SPELL_MAGNET
@ SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE
@ SPELL_AURA_MOD_AOE_AVOIDANCE
@ SPELL_AURA_REFLECT_SPELLS_SCHOOL
@ SPELLMOD_EFFECT2
@ SPELLMOD_ALL_EFFECTS
@ SPELLMOD_EFFECT3
@ SPELLMOD_EFFECT1
@ SPELLMOD_CASTING_TIME
@ SPELLMOD_RESIST_MISS_CHANCE
@ SPELL_ATTR0_CU_BINARY_SPELL
Definition SpellInfo.h:161
@ SPELL_GROUP_ELIXIR_BATTLE
Definition SpellMgr.h:295
@ SPELL_GROUP_ELIXIR_GUARDIAN
Definition SpellMgr.h:296
#define sSpellMgr
Definition SpellMgr.h:738
@ UNIT_FLAG2_IGNORE_REPUTATION
@ MOVEMENTFLAG_SPLINE_ENABLED
@ MOVEMENTFLAG_ONTRANSPORT
@ MOVEMENTFLAG_FLYING
@ MOVEMENTFLAG_FALLING
@ MOVEMENTFLAG_SWIMMING
@ MOVEMENTFLAG_SPLINE_ELEVATION
@ MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING
@ MOVEMENTFLAG2_INTERPOLATED_MOVEMENT
@ UNIT_BYTE2_FLAG_UNK1
@ MOVE_FLIGHT
@ MOVE_SWIM
@ MOVE_TURN_RATE
@ MOVE_FLIGHT_BACK
@ MOVE_SWIM_BACK
@ MOVE_RUN
@ MOVE_PITCH_RATE
@ MOVE_RUN_BACK
@ MOVE_WALK
@ UNIT_FLAG_NON_ATTACKABLE
@ UNIT_FLAG_NON_ATTACKABLE_2
@ UNIT_FLAG_ON_TAXI
@ UNIT_FLAG_UNINTERACTIBLE
@ UNIT_FLAG_NOT_ATTACKABLE_1
@ UNIT_FLAG_PLAYER_CONTROLLED
@ UNIT_MASK_PUPPET
Definition Unit.h:384
@ UNIT_MASK_TOTEM
Definition Unit.h:381
@ UNIT_MASK_SUMMON
Definition Unit.h:378
@ UNIT_MASK_GUARDIAN
Definition Unit.h:380
@ UNIT_MASK_MINION
Definition Unit.h:379
#define WORLD_TRIGGER
Definition Unit.h:34
#define MAX_PLAYER_STEALTH_DETECT_RANGE
Definition Unit.h:780
@ UNIT_STATE_UNATTACKABLE
Definition Unit.h:272
@ UNIT_STATE_CONTROLLED
Definition Unit.h:274
@ CR_HIT_TAKEN_SPELL
Definition Unit.h:349
@ UPDATETYPE_VALUES
Definition UpdateData.h:30
@ UPDATETYPE_CREATE_OBJECT
Definition UpdateData.h:32
@ UPDATETYPE_MOVEMENT
Definition UpdateData.h:31
@ UPDATETYPE_CREATE_OBJECT2
Definition UpdateData.h:33
@ UPDATEFLAG_LIVING
Definition UpdateData.h:46
@ UPDATEFLAG_ROTATION
Definition UpdateData.h:50
@ UPDATEFLAG_POSITION
Definition UpdateData.h:49
@ UPDATEFLAG_LOWGUID
Definition UpdateData.h:45
@ UPDATEFLAG_VEHICLE
Definition UpdateData.h:48
@ UPDATEFLAG_TRANSPORT
Definition UpdateData.h:42
@ UPDATEFLAG_UNKNOWN
Definition UpdateData.h:44
@ UPDATEFLAG_NONE
Definition UpdateData.h:40
@ UPDATEFLAG_SELF
Definition UpdateData.h:41
@ UPDATEFLAG_STATIONARY_POSITION
Definition UpdateData.h:47
@ UPDATEFLAG_HAS_TARGET
Definition UpdateData.h:43
uint32 UnitUpdateFieldFlags[PLAYER_END]
uint32 CorpseUpdateFieldFlags[CORPSE_END]
uint32 ItemUpdateFieldFlags[CONTAINER_END]
uint32 GameObjectUpdateFieldFlags[GAMEOBJECT_END]
uint32 DynamicObjectUpdateFieldFlags[DYNAMICOBJECT_END]
@ UF_FLAG_DYNAMIC
@ UF_FLAG_SPECIAL_INFO
@ UF_FLAG_ITEM_OWNER
@ UF_FLAG_PUBLIC
@ UF_FLAG_OWNER
@ UF_FLAG_PRIVATE
@ UF_FLAG_PARTY_MEMBER
@ UNIT_MOD_CAST_SPEED
@ PLAYER_FLAGS
@ PLAYER_FARSIGHT
@ OBJECT_FIELD_GUID
@ OBJECT_FIELD_TYPE
T AddPct(T &base, U pct)
Definition Util.h:77
T RoundToInterval(T &num, T floor, T ceil)
Definition Util.h:89
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
Definition Util.h:554
void append(T value)
Definition ByteBuffer.h:133
void SetHomePosition(float x, float y, float z, float o)
Definition Creature.h:302
float GetAttackDistance(Unit const *player) const
bool IsEvadingAttacks() const
Definition Creature.h:156
bool AIM_Initialize(CreatureAI *ai=nullptr)
float m_SightDistance
Definition Creature.h:344
float m_CombatDistance
Definition Creature.h:344
CreatureTemplate const * GetCreatureTemplate() const
Definition Creature.h:195
bool Create(ObjectGuid::LowType guidlow, Map *map, uint32 phaseMask, uint32 entry, Position const &pos, CreatureData const *data=nullptr, uint32 vehId=0, bool dynamic=false)
ObjectGuid GetCasterGUID() const
void KillAllEvents(bool force)
void Update(uint32 p_time)
T_FLAGS GetFlags() const
Definition Object.h:287
T_VALUES GetValue(FLAG_TYPE flag) const
Definition Object.h:292
void SetValue(FLAG_TYPE flag, T_VALUES value)
Definition Object.h:293
GameObjectValue const * GetGOValue() const
Definition GameObject.h:106
void SetRespawnTime(int32 respawn)
void SetSpawnedByDefault(bool b)
Definition GameObject.h:162
GameobjectTypes GetGoType() const
Definition GameObject.h:176
Transport * ToTransport()
Definition GameObject.h:291
bool Create(ObjectGuid::LowType guidlow, uint32 name_id, Map *map, uint32 phaseMask, Position const &pos, QuaternionData const &rotation, uint32 animprogress, GOState go_state, uint32 artKit=0, bool dynamic=false, ObjectGuid::LowType spawnid=0)
iterator begin()
Definition Item.h:62
Definition Map.h:302
bool IsDungeon() const
Definition Map.cpp:4231
void AddObjectToRemoveList(WorldObject *obj)
Definition Map.cpp:3562
void RemoveFromActive(WorldObject *obj)
Definition Map.cpp:3771
bool AddToMap(T *)
Definition Map.cpp:630
float GetHeight(float x, float y, float z, bool checkVMap=true, float maxSearchDist=DEFAULT_HEIGHT_SEARCH) const
Definition Map.cpp:2484
bool getObjectHitPos(uint32 phasemask, float x1, float y1, float z1, float x2, float y2, float z2, float &rx, float &ry, float &rz, float modifyDist)
Definition Map.cpp:2881
void RemoveUpdateObject(Object *obj)
Definition Map.h:625
void AddWorldObject(WorldObject *obj)
Definition Map.h:461
ObjectGuid::LowType GenerateLowGuid()
Definition Map.h:607
float GetGridHeight(float x, float y) const
Definition Map.cpp:2522
bool isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask, LineOfSightChecks checks, VMAP::ModelIgnoreFlags ignoreFlags) const
Definition Map.cpp:2870
void SummonCreatureGroup(uint8 group, std::list< TempSummon * > *list=nullptr)
Definition Object.cpp:1960
void GetFullTerrainStatusForPosition(uint32 phaseMask, float x, float y, float z, PositionFullTerrainStatus &data, Optional< uint8 > reqLiquidType={}, float collisionHeight=2.03128f) const
Definition Map.cpp:2723
void RemoveWorldObject(WorldObject *obj)
Definition Map.h:462
uint32 GetId() const
Definition Map.cpp:4216
float GetVisibilityRange() const
Definition Map.h:332
void GetZoneAndAreaId(uint32 phaseMask, uint32 &zoneid, uint32 &areaid, float x, float y, float z) const
Definition Map.cpp:2627
float GetWaterOrGroundLevel(uint32 phasemask, float x, float y, float z, float *ground=nullptr, bool swim=false, float collisionHeight=2.03128f) const
Definition Map.cpp:2458
InstanceMap * ToInstanceMap()
Definition Map.h:540
TempSummon * SummonCreature(uint32 entry, Position const &pos, SummonPropertiesEntry const *properties=nullptr, uint32 duration=0, WorldObject *summoner=nullptr, uint32 spellId=0, uint32 vehId=0, ObjectGuid privateObjectOwner=ObjectGuid::Empty)
Definition Object.cpp:1853
uint32 GetInstanceId() const
Definition Map.h:408
void AddToActive(WorldObject *obj)
Definition Map.cpp:3732
void AddUpdateObject(Object *obj)
Definition Map.h:620
void AddObjectToSwitchList(WorldObject *obj, bool on)
Definition Map.cpp:3571
static ObjectGuid const Empty
Definition ObjectGuid.h:140
bool IsEmpty() const
Definition ObjectGuid.h:172
bool IsPlayer() const
Definition ObjectGuid.h:179
std::string ToString() const
void ApplyModSignedFloatValue(uint16 index, float val, bool apply)
Definition Object.cpp:745
void UpdateUInt32Value(uint16 index, uint32 value)
Definition Object.cpp:590
void ToggleFlag64(uint16 index, uint64 flag)
Definition Object.cpp:873
Corpse * ToCorpse()
Definition Object.h:209
uint8 GetByteValue(uint16 index, uint8 offset) const
Definition Object.cpp:259
void SetByteValue(uint16 index, uint8 offset, uint8 value)
Definition Object.cpp:660
int32 * m_int32Values
Definition Object.h:241
void BuildFieldsUpdate(Player *, UpdateDataMapType &) const
Definition Object.cpp:484
void BuildValuesUpdateBlockForPlayer(UpdateData *data, Player const *target) const
Definition Object.cpp:206
uint16 m_objectType
Definition Object.h:234
static Creature * ToCreature(Object *o)
Definition Object.h:189
void BuildMovementUpdateBlock(UpdateData *data, uint32 flags=0) const
Definition Object.cpp:150
int32 GetInt32Value(uint16 index) const
Definition Object.cpp:235
void ApplyModFlag64(uint16 index, uint64 flag, bool apply)
Definition Object.cpp:887
void SetInt32Value(uint16 index, int32 value)
Definition Object.cpp:564
bool m_isNewObject
Definition Object.h:260
Trinity::unique_trackable_ptr< Object > m_scriptRef
Definition Object.h:265
PackedGuid const & GetPackGUID() const
Definition Object.h:80
DynamicObject * ToDynObject()
Definition Object.h:215
void SetUInt16Value(uint16 index, uint8 offset, uint16 value)
Definition Object.cpp:676
static Unit * ToUnit(Object *o)
Definition Object.h:195
uint32 GetUInt32Value(uint16 index) const
Definition Object.cpp:241
Player * ToPlayer()
Definition Object.h:185
static GameObject * ToGameObject(Object *o)
Definition Object.h:201
bool IsInWorld() const
Definition Object.h:73
Object()
Definition Object.cpp:64
uint16 GetUInt16Value(uint16 index, uint8 offset) const
Definition Object.cpp:266
virtual void DestroyForPlayer(Player *target, bool onDeath=false) const
Definition Object.cpp:223
virtual void BuildValuesUpdate(uint8 updatetype, ByteBuffer *data, Player const *target) const
Definition Object.cpp:439
void ApplyModInt32Value(uint16 index, int32 val, bool apply)
Definition Object.cpp:729
uint16 _fieldNotifyFlags
Definition Object.h:250
uint32 GetUpdateFieldData(Player const *target, uint32 *&flags) const
Definition Object.cpp:490
void AddToObjectUpdateIfNeeded()
Definition Object.cpp:465
bool HasDynamicFlag(uint32 flag) const
Definition Object.h:88
void ApplyModPositiveFloatValue(uint16 index, float val, bool apply)
Definition Object.cpp:752
bool AddGuidValue(uint16 index, ObjectGuid value)
Definition Object.cpp:612
UpdateMask _changesMask
Definition Object.h:246
bool IsUnit() const
Definition Object.h:194
TypeID GetTypeId() const
Definition Object.h:93
uint32 * m_uint32Values
Definition Object.h:242
virtual void BuildCreateUpdateBlockForPlayer(UpdateData *data, Player *target) const
Definition Object.cpp:162
WorldObject * ToWorldObject()
Definition Object.h:173
virtual bool AddToObjectUpdate()=0
void ApplyModByteFlag(uint16 index, uint8 offset, uint8 flag, bool apply)
Definition Object.cpp:854
uint16 m_valuesCount
Definition Object.h:248
void _InitValues()
Definition Object.cpp:99
void BuildMovementUpdate(ByteBuffer *data, uint16 flags) const
Definition Object.cpp:279
void SetFlag(uint16 index, uint32 newFlag)
Definition Object.cpp:761
void ApplyModUInt16Value(uint16 index, uint8 offset, int16 val, bool apply)
Definition Object.cpp:736
void RemoveFlag(uint16 index, uint32 oldFlag)
Definition Object.cpp:776
void ApplyModUInt32Value(uint16 index, int32 val, bool apply)
Definition Object.cpp:720
float GetFloatValue(uint16 index) const
Definition Object.cpp:253
void ApplyModFlag(uint16 index, uint32 flag, bool apply)
Definition Object.cpp:806
void ClearUpdateMask(bool remove)
Definition Object.cpp:471
void SetGuidValue(uint16 index, ObjectGuid value)
Definition Object.cpp:691
GameObject * ToGameObject()
Definition Object.h:203
void SetFlag64(uint16 index, uint64 newFlag)
Definition Object.cpp:859
bool _LoadIntoDataField(std::string const &data, uint32 startOffset, uint32 count)
Definition Object.cpp:543
uint32 GetEntry() const
Definition Object.h:81
uint64 GetUInt64Value(uint16 index) const
Definition Object.cpp:247
bool PrintIndexError(uint32 index, bool set) const
Definition Object.cpp:892
Creature * ToCreature()
Definition Object.h:191
PackedGuid m_PackGUID
Definition Object.h:262
Item * ToItem()
Definition Object.h:179
virtual std::string GetDebugInfo() const
Definition Object.cpp:900
void _Create(ObjectGuid const &guid)
Definition Object.cpp:109
void RemoveFlag64(uint16 index, uint64 oldFlag)
Definition Object.cpp:866
void SetFloatValue(uint16 index, float value)
Definition Object.cpp:647
bool RemoveGuidValue(uint16 index, ObjectGuid value)
Definition Object.cpp:629
void SetStatFloatValue(uint16 index, float value)
Definition Object.cpp:704
virtual void RemoveFromObjectUpdate()=0
virtual void AddToWorld()
Definition Object.cpp:118
void RemoveByteFlag(uint16 index, uint8 offset, uint8 newFlag)
Definition Object.cpp:825
bool HasFlag(uint16 index, uint32 flag) const
Definition Object.cpp:800
virtual void RemoveFromWorld()
Definition Object.cpp:137
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:78
bool m_inWorld
Definition Object.h:259
float * m_floatValues
Definition Object.h:243
void BuildOutOfRangeUpdateBlock(UpdateData *data) const
Definition Object.cpp:218
bool HasByteFlag(uint16 index, uint8 offset, uint8 flag) const
Definition Object.cpp:847
void SendUpdateToPlayer(Player *player)
Definition Object.cpp:192
void SetUInt32Value(uint16 index, uint32 value)
Definition Object.cpp:577
uint16 m_updateFlag
Definition Object.h:237
ObjectGuid GetGUID() const
Definition Object.h:79
void ToggleFlag(uint16 index, uint32 flag)
Definition Object.cpp:792
virtual ~Object()
Definition Object.cpp:79
bool HasFlag64(uint16 index, uint64 flag) const
Definition Object.cpp:881
TypeID m_objectTypeId
Definition Object.h:236
void SetStatInt32Value(uint16 index, int32 value)
Definition Object.cpp:712
bool m_objectUpdated
Definition Object.h:256
void SetUInt64Value(uint16 index, uint64 value)
Definition Object.cpp:598
static Player * ToPlayer(Object *o)
Definition Object.h:183
ObjectGuid GetGuidValue(uint16 index) const
Definition Object.cpp:273
void ToggleByteFlag(uint16 index, uint8 offset, uint8 flag)
Definition Object.cpp:839
Unit * ToUnit()
Definition Object.h:197
void ForceValuesUpdateAtIndex(uint32)
Definition Object.cpp:1778
void SetByteFlag(uint16 index, uint8 offset, uint8 newFlag)
Definition Object.cpp:811
void Set(ObjectGuid const &guid)
void SetUseRaycast(bool useRaycast)
Movement::PointsArray const & GetPath() const
PathType GetPathType() const
bool CalculatePath(float destX, float destY, float destZ, bool forceDest=false)
bool HaveAtClient(Object const *u) const
Definition Player.cpp:22065
bool IsInSameRaidWith(Player const *p) const
Definition Player.cpp:2329
void SendDirectMessage(WorldPacket const *data) const
Definition Player.cpp:6163
float GetRatingBonusValue(CombatRating cr) const
Definition Player.cpp:5218
GuidUnorderedSet m_clientGUIDs
Definition Player.h:2083
bool IsGameMaster() const
Definition Player.h:976
std::unique_ptr< DuelInfo > duel
Definition Player.h:1587
ReputationMgr & GetReputationMgr()
Definition Player.h:1834
FactionState const * GetState(FactionEntry const *factionEntry) const
bool IsAtWar(uint32 faction_id) const
ReputationRank const * GetForcedRankIfAny(FactionTemplateEntry const *factionTemplateEntry) const
uint32 TriggerSpell
Definition SpellInfo.h:228
int32 CalcValue(WorldObject const *caster=nullptr, int32 const *basePoints=nullptr) const
uint32 SpellLevel
Definition SpellInfo.h:329
float GetMaxRange(bool positive=false, WorldObject *caster=nullptr, Spell *spell=nullptr) const
flag96 SpellFamilyFlags
Definition SpellInfo.h:357
uint32 Id
Definition SpellInfo.h:289
SpellRangeEntry const * RangeEntry
Definition SpellInfo.h:338
bool HasOnlyDamageEffects() const
uint32 Dispel
Definition SpellInfo.h:291
float Speed
Definition SpellInfo.h:339
float GetMinRange(bool positive=false) const
int32 GetMaxDuration() const
std::array< uint32, 2 > SpellVisual
Definition SpellInfo.h:348
uint32 GetSpellMechanicMaskByEffectMask(uint32 effectMask) const
bool IsAllowingDeadTarget() const
SpellSchoolMask GetSchoolMask() const
bool IsChanneled() const
bool HasAttribute(SpellAttr0 attribute) const
Definition SpellInfo.h:375
int32 GetDuration() const
SpellEffectInfo const & GetEffect(SpellEffIndex index) const
Definition SpellInfo.h:483
SpellCastResult CheckExplicitTarget(WorldObject const *caster, WorldObject const *target, Item const *itemTarget=nullptr) const
uint32 SpellIconID
Definition SpellInfo.h:349
bool IsAffectingArea() const
bool IsPositive() const
uint32 DmgClass
Definition SpellInfo.h:358
std::array< SpellEffectInfo, MAX_SPELL_EFFECTS > const & GetEffects() const
Definition SpellInfo.h:482
uint32 SpellFamilyName
Definition SpellInfo.h:356
Definition Spell.h:152
void SetSpellValue(SpellValueMod mod, int32 value)
Definition Spell.cpp:7878
SpellCastResult prepare(SpellCastTargets const &targets, AuraEffect const *triggeredByAura=nullptr)
Definition Spell.cpp:3091
Item * m_CastItem
Definition Spell.h:397
virtual void InitSummon()
void SetTempSummonType(TempSummonType type)
virtual void InitStats(uint32 lifetime)
Definition Totem.h:39
Definition Unit.h:783
Unit * GetCharmed() const
Definition Unit.h:1269
Vehicle * GetVehicle() const
Definition Unit.h:1753
AuraEffectList const & GetAuraEffectsByType(AuraType type) const
Definition Unit.h:1397
bool HasPvpFlag(UnitPVPStateFlags flags) const
Definition Unit.h:996
Movement::MoveSpline * movespline
Definition Unit.h:1820
float GetSpeed(UnitMoveType mtype) const
Definition Unit.cpp:8608
bool HasAuraTypeWithMiscvalue(AuraType auraType, int32 miscValue) const
Definition Unit.cpp:4578
void SetFaction(uint32 faction) override
Definition Unit.h:988
virtual bool IsImmunedToSpell(SpellInfo const *spellInfo, WorldObject const *caster, bool requireImmunityPurgesEffectAttribute=false) const
Definition Unit.cpp:7631
bool IsPvP() const
Definition Unit.h:1002
virtual bool CanFly() const =0
Unit * GetVehicleBase() const
Definition Unit.cpp:11797
bool IsPet() const
Definition Unit.h:898
bool HasUnitFlag(UnitFlags flags) const
Definition Unit.h:967
void SetCreatedBySpell(int32 spellId)
Definition Unit.h:978
bool CanInstantCast() const
Definition Unit.h:1817
AuraEffect * GetAuraEffect(uint32 spellId, uint8 effIndex, ObjectGuid casterGUID=ObjectGuid::Empty) const
Definition Unit.cpp:4382
int32 GetMaxNegativeAuraModifier(AuraType auraType) const
Definition Unit.cpp:4830
bool HasUnitFlag2(UnitFlags2 flags) const
Definition Unit.h:973
bool IsInSanctuary() const
Definition Unit.h:1001
bool IsAlive() const
Definition Unit.h:1247
float GetCombatReach() const override
Definition Unit.h:853
int32 GetMechanicResistChance(SpellInfo const *spellInfo) const
Definition Unit.cpp:2382
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint8 reqEffMask=0) const
Definition Unit.cpp:4558
virtual bool HasSpell(uint32) const
Definition Unit.h:1175
int32 GetTotalAuraModifierByMiscMask(AuraType auraType, uint32 misc_mask) const
Definition Unit.cpp:4835
bool IsOnVehicle(Unit const *vehicle) const
Definition Unit.cpp:11792
bool IsImmuneToNPC() const
Definition Unit.h:1154
int32 GetMaxNegativeAuraModifierByMiscValue(AuraType auraType, int32 misc_value) const
Definition Unit.cpp:4905
bool IsDuringRemoveFromWorld() const
Definition Unit.h:1802
Unit * GetCharmerOrOwner() const
Definition Unit.h:1278
void AddGameObject(GameObject *gameObj)
Definition Unit.cpp:5116
static float CalculateAverageResistReduction(WorldObject const *caster, SpellSchoolMask schoolMask, Unit const *victim, SpellInfo const *spellInfo=nullptr)
Definition Unit.cpp:1737
float GetHoverOffset() const
Definition Unit.h:1783
SharedVisionList const & GetSharedVisionList()
Definition Unit.h:1318
bool HasUnitMovementFlag(uint32 f) const
Definition Unit.h:1694
bool HasAuraType(AuraType auraType) const
Definition Unit.cpp:4565
uint8 GetLevelForTarget(WorldObject const *) const override
Definition Unit.h:904
int32 GetTotalAuraModifier(AuraType auraType) const
Definition Unit.cpp:4815
bool IsFFAPvP() const
Definition Unit.h:1003
void BuildMovementPacket(ByteBuffer *data) const
Definition Unit.cpp:12740
Unit * GetVictim() const
Definition Unit.h:873
bool IsImmunedToDamage(SpellSchoolMask meleeSchoolMask) const
Definition Unit.cpp:7579
bool HasUnitState(const uint32 f) const
Definition Unit.h:890
bool IsInRaidWith(Unit const *unit) const
Definition Unit.cpp:11863
void SetLevel(uint8 lvl, bool sendUpdate=true)
Definition Unit.cpp:9321
virtual bool CanSwim() const
Definition Unit.cpp:12789
uint8 GetComboPoints(Unit const *who=nullptr) const
--------—Combo point system----------------—
Definition Unit.h:1711
int32 GetTotalAuraModifierByMiscValue(AuraType auraType, int32 misc_value) const
Definition Unit.cpp:4875
float m_modAttackSpeedPct[MAX_ATTACK]
Definition Unit.h:1515
ObjectGuid GetCharmerGUID() const
Definition Unit.h:1265
std::list< AuraEffect * > AuraEffectList
Definition Unit.h:801
bool IsTotem() const
Definition Unit.h:900
Vehicle * GetVehicleKit() const
Definition Unit.h:1751
float m_modSpellHitChance
Definition Unit.h:1512
bool IsImmuneToPC() const
Definition Unit.h:1151
bool isDead() const
Definition Unit.h:1249
void AddOutOfRangeGUID(GuidSet &guids)
ByteBuffer & GetBuffer()
Definition UpdateData.h:67
bool BuildPacket(WorldPacket *packet)
void AddUpdateBlock()
Definition UpdateData.h:66
void SetBit(uint32 bit)
Definition UpdateMask.h:81
void AppendToPacket(ByteBuffer *data)
Definition UpdateMask.h:87
void Clear()
Definition UpdateMask.h:52
bool GetBit(uint32 index) const
Definition UpdateMask.h:40
void SetCount(uint32 valuesCount)
Definition UpdateMask.h:45
void SetBit(uint32 index)
Definition UpdateMask.h:30
static VMapManager2 * createOrGetVMapManager()
bool getObjectHitPos(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2, float &rx, float &ry, float &rz, float modifyDist) override
VehicleEntry const * GetVehicleInfo() const
Definition Vehicle.h:46
std::string GetDebugInfo() const
Definition Position.cpp:224
uint32 GetMapId() const
Definition Position.h:193
uint32 m_mapId
Definition Position.h:195
Unit * GetMagicHitRedirectTarget(Unit *victim, SpellInfo const *spellInfo)
Definition Object.cpp:3102
float m_staticFloorZ
Definition Object.h:615
ZLiquidStatus m_liquidStatus
Definition Object.h:617
void GetPlayerListInGrid(Container &playerContainer, float maxSearchRange, bool alive=true) const
Definition Object.cpp:3174
virtual void SetPhaseMask(uint32 newPhaseMask, bool update)
Definition Object.cpp:3416
uint32 GetPhaseMask() const
Definition Object.h:370
bool IsInRange3d(float x, float y, float z, float minRange, float maxRange) const
Definition Object.cpp:1329
bool IsWithinDist2d(float x, float y, float dist) const
Definition Object.cpp:1178
bool IsWithinDist3d(float x, float y, float z, float dist) const
Definition Object.cpp:1168
GameObject * FindNearestGameObject(uint32 entry, float range, bool spawnedOnly=true) const
Definition Object.cpp:2122
virtual void SendMessageToSet(WorldPacket const *data, bool self) const
Definition Object.cpp:1784
bool CanDetect(WorldObject const *obj, bool ignoreStealth, bool checkAlert=false) const
Definition Object.cpp:1642
Map * GetMap() const
Definition Object.h:451
virtual void ResetMap()
Definition Object.cpp:1827
void GetGameObjectListWithOptionsInGrid(Container &gameObjectContainer, float maxSearchRange, FindGameObjectOptions const &options) const
Definition Object.cpp:3142
Creature * FindNearestCreatureWithOptions(float range, FindCreatureOptions const &options) const
Definition Object.cpp:2109
void UpdateAllowedPositionZ(float x, float y, float &z, float *groundZ=nullptr) const
Definition Object.cpp:1417
void AddToWorld() override
Definition Object.cpp:1061
virtual float GetCollisionHeight() const
Definition Object.h:585
Map * FindMap() const
Definition Object.h:452
Unit * GetCharmerOrOwner() const
Definition Object.cpp:2186
void RemoveFromWorld() override
Definition Object.cpp:1067
virtual float GetStationaryO() const
Definition Object.h:582
Player * SelectNearestPlayer(float distance) const
Definition Object.cpp:2162
virtual ~WorldObject()
Definition Object.cpp:946
InstanceScript * GetInstanceScript() const
Definition Object.cpp:1088
virtual uint8 GetLevelForTarget(WorldObject const *) const
Definition Object.h:425
void SendSpellMiss(Unit *target, uint32 spellID, SpellMissInfo missInfo)
Definition Object.cpp:2621
Unit * GetCharmerOrOwnerOrSelf() const
Definition Object.cpp:2196
bool CheckPrivateObjectOwnerVisibility(WorldObject const *seer) const
Definition Object.cpp:1532
bool IsWithinLOS(float x, float y, float z, LineOfSightChecks checks=LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags ignoreFlags=VMAP::ModelIgnoreFlags::Nothing) const
Definition Object.cpp:1207
bool IsInRange2d(float x, float y, float minRange, float maxRange) const
Definition Object.cpp:1309
void BuildUpdate(UpdateDataMapType &) override
Definition Object.cpp:3558
virtual SpellMissInfo MeleeSpellHitResult(Unit *victim, SpellInfo const *spellInfo) const
Definition Object.cpp:2465
uint32 m_InstanceId
Definition Object.h:635
Position GetHitSpherePointFor(Position const &dest) const
Definition Object.cpp:1198
void GetCreatureListWithEntryInGrid(Container &creatureContainer, uint32 entry, float maxSearchRange=250.0f) const
Definition Object.cpp:3154
void GetNearPoint(WorldObject const *searcher, float &x, float &y, float &z, float distance2d, float absAngle) const
Definition Object.cpp:3210
ObjectGuid GetPrivateObjectOwner() const
Definition Object.h:597
virtual bool IsInvisibleDueToDespawn() const
Definition Object.h:627
uint32 m_areaId
Definition Object.h:614
virtual bool IsAlwaysDetectableFor(WorldObject const *) const
Definition Object.h:629
float GetGridActivationRange() const
Definition Object.cpp:1477
void ClearZoneScript()
Definition Object.cpp:1988
void GetClosePoint(float &x, float &y, float &z, float size, float distance2d=0, float relAngle=0) const
Definition Object.cpp:3245
void GetGameObjectListWithEntryInGrid(Container &gameObjectContainer, uint32 entry, float maxSearchRange=250.0f) const
Definition Object.cpp:3134
GameObject * FindNearestGameObjectOfType(GameobjectTypes type, float range) const
Definition Object.cpp:2153
float GetMapHeight(float x, float y, float z, bool vmap=true, float distanceToSearch=50.0f) const
Definition Object.cpp:3605
FlaggedValuesArray32< int32, uint32, InvisibilityType, TOTAL_INVISIBILITY_TYPES > m_invisibility
Definition Object.h:443
SpellCastResult CastSpell(CastSpellTargetArg const &targets, uint32 spellId, CastSpellExtraArgs const &args={ })
Definition Object.cpp:2833
float GetMapWaterOrGroundLevel(float x, float y, float z, float *ground=nullptr) const
Definition Object.cpp:3592
std::string GetDebugInfo() const override
Definition Object.cpp:3613
bool IsValidAttackTarget(WorldObject const *target, SpellInfo const *bySpell=nullptr) const
Definition Object.cpp:2857
bool IsHostileToPlayers() const
Definition Object.cpp:2807
bool IsHostileTo(WorldObject const *target) const
Definition Object.cpp:2797
bool IsVisibilityOverridden() const
Definition Object.h:557
virtual ObjectGuid GetCharmerOrOwnerGUID() const
Definition Object.h:475
float GetTransOffsetX() const
Definition Object.h:567
void MovePositionToFirstCollision(Position &pos, float dist, float angle)
Definition Object.cpp:3324
FlaggedValuesArray32< int32, uint32, InvisibilityType, TOTAL_INVISIBILITY_TYPES > m_invisibilityDetect
Definition Object.h:444
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:1993
Unit * GetOwner() const
Definition Object.cpp:2181
bool isActiveObject() const
Definition Object.h:553
bool IsSelfOrInSameMap(WorldObject const *obj) const
Definition Object.cpp:1154
void SetZoneScript()
Definition Object.cpp:1972
bool GetDistanceOrder(WorldObject const *obj1, WorldObject const *obj2, bool is3D=true) const
Definition Object.cpp:1261
bool IsPrivateObject() const
Definition Object.h:596
bool isInFront(WorldObject const *target, float arc=float(M_PI)) const
Definition Object.cpp:1367
void setActive(bool isActiveObject)
Definition Object.cpp:992
void SetPrivateObjectOwner(ObjectGuid const &owner)
Definition Object.h:598
bool CanSeeOrDetect(WorldObject const *obj, bool implicitDetect=false, bool distanceCheck=false, bool checkAlert=false) const
Definition Object.cpp:1548
Position GetNearPosition(float dist, float angle)
Definition Object.cpp:3251
float GetDistance2d(WorldObject const *obj) const
Definition Object.cpp:1142
Creature * SummonTrigger(float x, float y, float z, float ang, Milliseconds despawnTime, CreatureAI *(*GetAI)(Creature *)=nullptr)
Definition Object.cpp:2058
ZoneScript * m_zoneScript
Definition Object.h:607
GameObject * SummonGameObject(uint32 entry, Position const &pos, QuaternionData const &rot, Seconds respawnTime, GOSummonType summonType=GO_SUMMON_TIMED_OR_CORPSE_DESPAWN)
Definition Object.cpp:2016
ObjectGuid GetCharmerOrOwnerOrOwnGUID() const
Definition Object.cpp:2173
Position GetRandomNearPosition(float radius)
Definition Object.cpp:3265
int32 ModSpellDuration(SpellInfo const *spellInfo, WorldObject const *target, int32 duration, bool positive, uint32 effectMask) const
Definition Object.cpp:2321
float GetTransOffsetY() const
Definition Object.h:568
bool InSamePhase(uint32 phasemask) const
Definition Object.h:371
float GetSightRange(WorldObject const *target=nullptr) const
Definition Object.cpp:1503
static ReputationRank GetFactionReactionTo(FactionTemplateEntry const *factionTemplateEntry, WorldObject const *target)
Definition Object.cpp:2750
float GetFloorZ() const
Definition Object.cpp:3585
std::string const & GetName() const
Definition Object.h:384
virtual void SetMap(Map *map)
Definition Object.cpp:1809
bool IsFarVisible() const
Definition Object.h:555
virtual void Heartbeat()
Definition Object.h:631
void SetFarVisible(bool on)
Definition Object.cpp:1015
virtual float GetStationaryX() const
Definition Object.h:579
float GetTransOffsetZ() const
Definition Object.h:569
virtual bool IsAlwaysVisibleFor(WorldObject const *) const
Definition Object.h:626
bool IsInBetween(Position const &pos1, Position const &pos2, float size=0) const
Definition Object.cpp:1350
void AddObjectToRemoveList()
Definition Object.cpp:1839
void GetNearPoint2D(WorldObject const *searcher, float &x, float &y, float distance, float absAngle) const
Definition Object.cpp:3181
void PlayDirectMusic(uint32 musicId, Player *target=nullptr)
Definition Object.cpp:3440
int32 CalcSpellDuration(SpellInfo const *spellInfo) const
Definition Object.cpp:2303
virtual bool IsNeverVisible(bool allowServersideObjects) const
Definition Object.h:625
bool IsWithinLOSInMap(WorldObject const *obj, LineOfSightChecks checks=LINEOFSIGHT_ALL_CHECKS, VMAP::ModelIgnoreFlags ignoreFlags=VMAP::ModelIgnoreFlags::Nothing) const
Definition Object.cpp:1227
WorldObject(bool isWorldObject)
Definition Object.cpp:937
bool CanDetectStealthOf(WorldObject const *obj, bool checkAlert=false) const
Definition Object.cpp:1702
virtual void ProcessPositionDataChanged(PositionFullTerrainStatus const &data)
Definition Object.cpp:1050
SpellMissInfo MagicSpellHitResult(Unit *victim, SpellInfo const *spellInfo) const
Definition Object.cpp:2470
void GetContactPoint(WorldObject const *obj, float &x, float &y, float &z, float distance2d=CONTACT_DISTANCE) const
Definition Object.cpp:3272
bool CanDetectInvisibilityOf(WorldObject const *obj) const
Definition Object.cpp:1671
virtual ObjectGuid GetTransGUID() const
Definition Object.cpp:3578
GameObject * FindNearestGameObjectWithOptions(float range, FindGameObjectOptions const &options) const
Definition Object.cpp:2131
bool const m_isStoredInWorldObjectGridContainer
Definition Object.h:606
uint32 m_phaseMask
Definition Object.h:636
void DestroyForNearbyPlayers()
Definition Object.cpp:3448
Transport * GetTransport() const
Definition Object.h:566
float ApplyEffectModifiers(SpellInfo const *spellInfo, uint8 effIndex, float value) const
Definition Object.cpp:2282
GameObject * FindNearestUnspawnedGameObject(uint32 entry, float range) const
Definition Object.cpp:2144
bool isInBack(WorldObject const *target, float arc=float(M_PI)) const
Definition Object.cpp:1372
FlaggedValuesArray32< int32, uint32, StealthType, TOTAL_STEALTH_TYPES > m_stealthDetect
Definition Object.h:441
Creature * FindNearestCreature(uint32 entry, float range, bool alive=true) const
Definition Object.cpp:2100
bool IsNeutralToAll() const
Definition Object.cpp:2820
void UpdatePositionData()
Definition Object.cpp:1043
bool m_isActive
Definition Object.h:603
void UpdateGroundPositionZ(float x, float y, float &z) const
Definition Object.cpp:1406
bool IsStoredInWorldObjectGridContainer() const
Definition Object.cpp:981
Player * GetSpellModOwner() const
Definition Object.cpp:2224
Player * GetCharmerOrOwnerPlayerOrPlayerItself() const
Definition Object.cpp:2204
bool IsWithinDistInMap(WorldObject const *obj, float dist2compare, bool is3D=true, bool incOwnRadius=true, bool incTargetRadius=true) const
Definition Object.cpp:1193
ReputationRank GetReactionTo(WorldObject const *target) const
Definition Object.cpp:2663
void SetIsStoredInWorldObjectGridContainer(bool apply)
Definition Object.cpp:973
bool m_outdoors
Definition Object.h:616
bool IsInWorldPvpZone() const
Definition Object.cpp:1077
void SendObjectDeSpawnAnim(ObjectGuid guid)
Definition Object.cpp:1802
bool IsValidAssistTarget(WorldObject const *target, SpellInfo const *bySpell=nullptr) const
Definition Object.cpp:3001
bool IsInRange(WorldObject const *obj, float minRange, float maxRange, bool is3D=true) const
Definition Object.cpp:1284
EventProcessor m_Events
Definition Object.h:593
virtual bool _IsWithinDist(WorldObject const *obj, float dist2compare, bool is3D, bool incOwnRadius=true, bool incTargetRadius=true) const
Definition Object.cpp:1102
float GetVisibilityRange() const
Definition Object.cpp:1493
virtual float MeleeSpellMissChance(Unit const *victim, WeaponAttackType attType, int32 skillDiff, uint32 spellId) const
Definition Object.cpp:2460
FlaggedValuesArray32< int32, uint32, StealthType, TOTAL_STEALTH_TYPES > m_stealth
Definition Object.h:440
FlaggedValuesArray32< int32, uint32, ServerSideVisibilityType, TOTAL_SERVERSIDE_VISIBILITY_TYPES > m_serverSideVisibilityDetect
Definition Object.h:447
float GetSpellMinRangeForTarget(Unit const *target, SpellInfo const *spellInfo) const
Definition Object.cpp:2268
void PlayDirectSound(uint32 soundId, Player *target=nullptr)
Definition Object.cpp:3432
virtual uint32 GetFaction() const =0
SpellMissInfo SpellHitResult(Unit *victim, SpellInfo const *spellInfo, bool canReflect=false) const
Definition Object.cpp:2572
float GetDistance(WorldObject const *obj) const
Definition Object.cpp:1124
Optional< float > m_visibilityDistanceOverride
Definition Object.h:605
ObjectGuid _privateObjectOwner
Definition Object.h:640
void PlayDistanceSound(uint32 soundId, Player *target=nullptr)
Definition Object.cpp:3424
float GetTransOffsetO() const
Definition Object.h:570
virtual ObjectGuid GetOwnerGUID() const =0
void SetVisibilityDistanceOverride(VisibilityDistanceType type)
Definition Object.cpp:1023
bool CanNeverSee(WorldObject const *obj) const
Definition Object.cpp:1637
bool IsWithinDist(WorldObject const *obj, float dist2compare, bool is3D=true) const
Definition Object.cpp:1188
virtual void SendMessageToSetInRange(WorldPacket const *data, float dist, bool self) const
Definition Object.cpp:1790
Position GetFirstCollisionPosition(float dist, float angle)
Definition Object.cpp:3258
uint32 GetZoneId() const
Definition Object.h:375
Milliseconds _heartbeatTimer
Definition Object.h:642
MovementInfo m_movementInfo
Definition Object.h:577
uint32 m_zoneId
Definition Object.h:613
FlaggedValuesArray32< int32, uint32, ServerSideVisibilityType, TOTAL_SERVERSIDE_VISIBILITY_TYPES > m_serverSideVisibility
Definition Object.h:446
float GetDistanceZ(WorldObject const *obj) const
Definition Object.cpp:1094
bool m_isFarVisible
Definition Object.h:604
void GetCreatureListWithOptionsInGrid(Container &creatureContainer, float maxSearchRange, FindCreatureOptions const &options) const
Definition Object.cpp:3162
float GetSpellMaxRangeForTarget(Unit const *target, SpellInfo const *spellInfo) const
Definition Object.cpp:2254
virtual float GetStationaryY() const
Definition Object.h:580
void SummonCreatureGroup(uint8 group, std::list< TempSummon * > *list=nullptr)
Definition Object.cpp:2083
void ModSpellCastTime(SpellInfo const *spellInfo, int32 &castTime, Spell *spell=nullptr) const
Definition Object.cpp:2415
bool IsFriendlyTo(WorldObject const *target) const
Definition Object.cpp:2802
virtual float GetCombatReach() const
Definition Object.h:360
virtual float GetStationaryZ() const
Definition Object.h:581
Map * m_currMap
Definition Object.h:633
Player * GetAffectingPlayer() const
Definition Object.cpp:2213
virtual bool CanAlwaysSee(WorldObject const *) const
Definition Object.h:647
bool IsInMap(WorldObject const *obj) const
Definition Object.cpp:1161
virtual void Update(uint32 diff)
Definition Object.cpp:961
void MovePosition(Position &pos, float dist, float angle)
Definition Object.cpp:3278
void GetRandomPoint(Position const &srcPos, float distance, float &rand_x, float &rand_y, float &rand_z) const
Definition Object.cpp:1377
FactionTemplateEntry const * GetFactionTemplateEntry() const
Definition Object.cpp:2635
bool AddToObjectUpdate() override
Definition Object.cpp:3567
int32 CalculateSpellDamage(SpellEffectInfo const &spellEffectInfo, int32 const *basePoints=nullptr) const
Definition Object.cpp:2249
virtual void UpdateObjectVisibility(bool forced=true)
Definition Object.cpp:3481
virtual void CleanupsBeforeDelete(bool finalCleanup=true)
Definition Object.cpp:1032
void RemoveFromObjectUpdate() override
Definition Object.cpp:3573
void ModSpellDurationTime(SpellInfo const *spellInfo, int32 &durationTime, Spell *spell=nullptr) const
Definition Object.cpp:2437
static void WriteCreateObjectSplineDataBlock(::Movement::MoveSpline const &moveSpline, ByteBuffer &data)
@ SMSG_SPELLLOGMISS
Definition Opcodes.h:616
@ SMSG_GAMEOBJECT_DESPAWN_ANIM
Definition Opcodes.h:562
@ SMSG_DESTROY_OBJECT
Definition Opcodes.h:199
#define sWorld
Definition World.h:901
@ CONFIG_DETECT_POS_COLLISION
Definition World.h:115
uint32 const Entry[5]
uint32 GetGameTimeMS()
Definition GameTime.cpp:47
TC_GAME_API Unit * GetUnit(WorldObject const &, ObjectGuid const &guid)
TC_GAME_API Player * FindPlayer(ObjectGuid const &)
TC_GAME_API Player * GetPlayer(Map const *, ObjectGuid const &guid)
TC_COMMON_API std::vector< std::string_view > Tokenize(std::string_view str, char sep, bool keepEmpty)
Definition Util.cpp:56
bool IsValidMapCoord(float c)
void NormalizeMapCoord(float &c)
TriggerCastFlags TriggerFlags
struct CastSpellExtraArgs::@267 SpellValueOverrides
ObjectGuid OriginalCaster
AuraEffect const * TriggeringAura
Optional< SpellCastTargets > Targets
static void VisitAllObjects(WorldObject const *obj, T &visitor, float radius, bool dont_load=true)
Definition CellImpl.h:192
static void VisitGridObjects(WorldObject const *obj, T &visitor, float radius, bool dont_load=true)
Definition CellImpl.h:168
static void VisitWorldObjects(WorldObject const *obj, T &visitor, float radius, bool dont_load=true)
Definition CellImpl.h:180
int32 ReputationIndex
bool IsHostileTo(FactionTemplateEntry const &entry) const
bool IsHostileToPlayers() const
bool IsNeutralToAll() const
bool IsFriendlyTo(FactionTemplateEntry const &entry) const
ObjectGuid guid
struct MovementInfo::JumpInfo jump
uint32 fallTime
struct MovementInfo::TransportInfo transport
float splineElevation
uint32 GetMovementFlags() const
void OutDebug()
Definition Object.cpp:907
Position pos
ZLiquidStatus liquidStatus
Definition MapDefines.h:111
float m_positionZ
Definition Position.h:58
float GetExactDist2dSq(const float x, const float y) const
Definition Position.h:100
float GetExactDist2d(const float x, const float y) const
Definition Position.h:109
Position()
Definition Position.h:29
std::string ToString() const
Definition Position.cpp:149
float GetExactDist(float x, float y, float z) const
Definition Position.h:121
float m_positionX
Definition Position.h:56
float GetPositionZ() const
Definition Position.h:81
float m_positionY
Definition Position.h:57
bool IsInDist2d(float x, float y, float dist) const
Definition Position.h:145
float GetOrientation() const
Definition Position.h:82
bool IsInDist(float x, float y, float z, float dist) const
Definition Position.h:148
bool HasInArc(float arcangle, Position const *pos, float border=2.0f) const
Definition Position.cpp:120
float GetAbsoluteAngle(float x, float y) const
Definition Position.h:128
void SetOrientation(float orientation)
Definition Position.h:74
Position GetPosition() const
Definition Position.h:87
float GetPositionX() const
Definition Position.h:79
void GetPosition(float &x, float &y) const
Definition Position.h:84
float GetPositionY() const
Definition Position.h:80
void Relocate(float x, float y)
Definition Position.h:66
UpdateDataMapType & i_updateDatas
Definition Object.cpp:3490
WorldObjectChangeAccumulator(WorldObject &obj, UpdateDataMapType &d)
Definition Object.cpp:3493
void Visit(GridRefManager< SKIP > &)
Definition Object.cpp:3555
void Visit(PlayerMapType &m)
Definition Object.cpp:3494
void Visit(DynamicObjectMapType &m)
Definition Object.cpp:3527
void BuildPacket(Player *player)
Definition Object.cpp:3545
void Visit(CreatureMapType &m)
Definition Object.cpp:3512
struct GameObjectValue::@187 Transport
uint32 PathProgress
Definition GameObject.h:48