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