TrinityCore
ConditionMgr.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 "ConditionMgr.h"
19#include "AchievementMgr.h"
20#include "AreaTrigger.h"
22#include "BattlePetMgr.h"
23#include "Battleground.h"
24#include "Containers.h"
26#include "DB2Stores.h"
27#include "DatabaseEnv.h"
28#include "GameEventMgr.h"
29#include "GameObject.h"
30#include "GameTime.h"
31#include "Group.h"
32#include "InstanceScenario.h"
33#include "InstanceScript.h"
34#include "Item.h"
35#include "LFGMgr.h"
36#include "LanguageMgr.h"
37#include "Log.h"
38#include "LootMgr.h"
39#include "Map.h"
40#include "ObjectAccessor.h"
41#include "ObjectMgr.h"
42#include "Pet.h"
43#include "PhasingHandler.h"
44#include "Player.h"
45#include "RaceMask.h"
46#include "Realm.h"
47#include "ReputationMgr.h"
48#include "ScriptMgr.h"
49#include "Spell.h"
50#include "SpellAuraEffects.h"
51#include "SpellAuras.h"
52#include "SpellMgr.h"
53#include "World.h"
54#include "WorldSession.h"
55#include "WorldStateMgr.h"
56#include "WowTime.h"
57#include <random>
58#include <sstream>
59
61{
62 "None",
63 "Creature Loot",
64 "Disenchant Loot",
65 "Fishing Loot",
66 "GameObject Loot",
67 "Item Loot",
68 "Mail Loot",
69 "Milling Loot",
70 "Pickpocketing Loot",
71 "Prospecting Loot",
72 "Reference Loot",
73 "Skinning Loot",
74 "Spell Loot",
75 "Spell Impl. Target",
76 "Gossip Menu",
77 "Gossip Menu Option",
78 "Creature Vehicle",
79 "Spell Expl. Target",
80 "Spell Click Event",
81 "Quest Available",
82 "Unused",
83 "Vehicle Spell",
84 "SmartScript",
85 "Npc Vendor",
86 "Spell Proc",
87 "Terrain Swap",
88 "Phase",
89 "Graveyard",
90 "AreaTrigger",
91 "ConversationLine",
92 "AreaTrigger Client Triggered",
93 "Trainer Spell",
94 "Object Visibility (by ID)",
95 "Spawn Group"
96};
97
99{
100 { "None", false, false, false, false },
101 { "Aura", true, true, true, false },
102 { "Item Stored", true, true, true, false },
103 { "Item Equipped", true, false, false, false },
104 { "Zone", true, false, false, false },
105 { "Reputation", true, true, false, false },
106 { "Team", true, false, false, false },
107 { "Skill", true, true, false, false },
108 { "Quest Rewarded", true, false, false, false },
109 { "Quest Taken", true, false, false, false },
110 { "Drunken", true, false, false, false },
111 { "WorldState", true, true, false, false },
112 { "Active Event", true, false, false, false },
113 { "Instance Info", true, true, true, false },
114 { "Quest None", true, false, false, false },
115 { "Class", true, false, false, false },
116 { "Race", true, false, false, false },
117 { "Achievement", true, false, false, false },
118 { "Title", true, false, false, false },
119 { "SpawnMask", true, false, false, false },
120 { "Gender", true, false, false, false },
121 { "Unit State", true, false, false, false },
122 { "Map", true, false, false, false },
123 { "Area", true, false, false, false },
124 { "CreatureType", true, false, false, false },
125 { "Spell Known", true, false, false, false },
126 { "Phase", true, false, false, false },
127 { "Level", true, true, false, false },
128 { "Quest Completed", true, false, false, false },
129 { "Near Creature", true, true, true, false },
130 { "Near GameObject", true, true, false, false },
131 { "Object Entry or Guid", true, true, true, false },
132 { "Object TypeMask", true, false, false, false },
133 { "Relation", true, true, false, false },
134 { "Reaction", true, true, false, false },
135 { "Distance", true, true, true, false },
136 { "Alive", false, false, false, false },
137 { "Health Value", true, true, false, false },
138 { "Health Pct", true, true, false, false },
139 { "Realm Achievement", true, false, false, false },
140 { "In Water", false, false, false, false },
141 { "Terrain Swap", true, false, false, false },
142 { "Sit/stand state", true, true, false, false },
143 { "Daily Quest Completed", true, false, false, false },
144 { "Charmed", false, false, false, false },
145 { "Pet type", true, false, false, false },
146 { "On Taxi", false, false, false, false },
147 { "Quest state mask", true, true, false, false },
148 { "Quest objective progress", true, false, true, false },
149 { "Map Difficulty", true, false, false, false },
150 { "Is Gamemaster", true, false, false, false },
151 { "Object Entry or Guid", true, true, true, false },
152 { "Object TypeMask", true, false, false, false },
153 { "BattlePet Species Learned", true, true, true, false },
154 { "On Scenario Step", true, false, false, false },
155 { "Scene In Progress", true, false, false, false },
156 { "Player Condition", true, false, false, false },
157 { "String ID", false, false, false, true }
158};
159
161{
162 mConditionTargets[0] = target0;
163 mConditionTargets[1] = target1;
164 mConditionTargets[2] = target2;
165 if (target0)
166 mConditionMap = target0->GetMap();
167 else if (target1)
168 mConditionMap = target1->GetMap();
169 else if (target2)
170 mConditionMap = target2->GetMap();
171 else
172 mConditionMap = nullptr;
173 mLastFailedCondition = nullptr;
174}
175
177{
178 std::fill(std::begin(mConditionTargets), std::end(mConditionTargets), nullptr);
179 mConditionMap = map;
180 mLastFailedCondition = nullptr;
181}
182
183std::size_t ConditionId::GetHash() const
184{
185 std::size_t hashVal = 0;
189 return hashVal;
190}
191
192// Checks if object meets the condition
193// Can have CONDITION_SOURCE_TYPE_NONE && !mReferenceId if called from a special event (ie: SmartAI)
195{
197
198 Map const* map = sourceInfo.mConditionMap;
199 bool condMeets = false;
200 bool needsObject = false;
201 switch (ConditionType)
202 {
203 case CONDITION_NONE:
204 condMeets = true; // empty condition, always met
205 break;
207 condMeets = sGameEventMgr->IsActiveEvent(ConditionValue1);
208 break;
210 {
211 if (InstanceMap const* instanceMap = map->ToInstanceMap())
212 {
213 if (InstanceScript const* instance = instanceMap->GetInstanceScript())
214 {
215 switch (ConditionValue3)
216 {
218 condMeets = instance->GetData(ConditionValue1) == ConditionValue2;
219 break;
221 condMeets = instance->GetBossState(ConditionValue1) == EncounterState(ConditionValue2);
222 break;
224 condMeets = instance->GetData64(ConditionValue1) == ConditionValue2;
225 break;
226 default:
227 condMeets = false;
228 break;
229 }
230 }
231 }
232 else if (BattlegroundMap const* bgMap = map->ToBattlegroundMap())
233 {
234 ZoneScript const* zoneScript = bgMap->GetBG();
235 switch (ConditionValue3)
236 {
238 condMeets = zoneScript->GetData(ConditionValue1) == ConditionValue2;
239 break;
241 condMeets = zoneScript->GetData64(ConditionValue1) == ConditionValue2;
242 break;
243 default:
244 condMeets = false;
245 break;
246 }
247 }
248 break;
249 }
250 case CONDITION_MAPID:
251 condMeets = map->GetId() == ConditionValue1;
252 break;
254 {
255 condMeets = sWorldStateMgr->GetValue(ConditionValue1, map) == int32(ConditionValue2);
256 break;
257 }
259 {
260 AchievementEntry const* achievement = sAchievementStore.LookupEntry(ConditionValue1);
261 if (achievement && sAchievementMgr->IsRealmCompleted(achievement))
262 condMeets = true;
263 break;
264 }
266 {
267 condMeets = map->GetDifficultyID() == ConditionValue1;
268 break;
269 }
271 {
272 if (InstanceMap const* instanceMap = map->ToInstanceMap())
273 if (Scenario const* scenario = instanceMap->GetInstanceScenario())
274 if (ScenarioStepEntry const* step = scenario->GetStep())
275 condMeets = step->ID == ConditionValue1;
276 break;
277 }
278 default:
279 needsObject = true;
280 break;
281 }
282
283 WorldObject const* object = sourceInfo.mConditionTargets[ConditionTarget];
284 // object not present, return false
285 if (needsObject && !object)
286 {
287 TC_LOG_DEBUG("condition", "Condition object not found for {}", ToString());
288 return false;
289 }
290 switch (ConditionType)
291 {
292 case CONDITION_AURA:
293 {
294 if (Unit const* unit = object->ToUnit())
295 condMeets = unit->HasAuraEffect(ConditionValue1, ConditionValue2);
296 break;
297 }
298 case CONDITION_ITEM:
299 {
300 if (Player const* player = object->ToPlayer())
301 {
302 // don't allow 0 items (it's checked during table load)
304 bool checkBank = ConditionValue3 ? true : false;
305 condMeets = player->HasItemCount(ConditionValue1, ConditionValue2, checkBank);
306 }
307 break;
308 }
310 {
311 if (Player const* player = object->ToPlayer())
312 condMeets = player->HasItemOrGemWithIdEquipped(ConditionValue1, 1);
313 break;
314 }
315 case CONDITION_ZONEID:
316 condMeets = object->GetZoneId() == ConditionValue1;
317 break;
319 {
320 if (Player const* player = object->ToPlayer())
321 {
322 if (FactionEntry const* faction = sFactionStore.LookupEntry(ConditionValue1))
323 condMeets = (ConditionValue2 & (1 << player->GetReputationMgr().GetRank(faction))) != 0;
324 }
325 break;
326 }
328 {
329 if (Player const* player = object->ToPlayer())
330 condMeets = player->HasAchieved(ConditionValue1);
331 break;
332 }
333 case CONDITION_TEAM:
334 {
335 if (Player const* player = object->ToPlayer())
336 condMeets = player->GetTeam() == Team(ConditionValue1);
337 break;
338 }
339 case CONDITION_CLASS:
340 {
341 if (Unit const* unit = object->ToUnit())
342 condMeets = (unit->GetClassMask() & ConditionValue1) != 0;
343 break;
344 }
345 case CONDITION_RACE:
346 {
347 if (Unit const* unit = object->ToUnit())
348 condMeets = Trinity::RaceMask<uint32>{ ConditionValue1 }.HasRace(unit->GetRace());
349 break;
350 }
351 case CONDITION_GENDER:
352 {
353 if (Player const* player = object->ToPlayer())
354 condMeets = player->GetNativeGender() == Gender(ConditionValue1);
355 break;
356 }
357 case CONDITION_SKILL:
358 {
359 if (Player const* player = object->ToPlayer())
360 condMeets = player->HasSkill(ConditionValue1) && player->GetBaseSkillValue(ConditionValue1) >= ConditionValue2;
361 break;
362 }
364 {
365 if (Player const* player = object->ToPlayer())
366 condMeets = player->GetQuestRewardStatus(ConditionValue1);
367 break;
368 }
370 {
371 if (Player const* player = object->ToPlayer())
372 {
373 QuestStatus status = player->GetQuestStatus(ConditionValue1);
374 condMeets = (status == QUEST_STATUS_INCOMPLETE);
375 }
376 break;
377 }
379 {
380 if (Player const* player = object->ToPlayer())
381 {
382 QuestStatus status = player->GetQuestStatus(ConditionValue1);
383 condMeets = (status == QUEST_STATUS_COMPLETE && !player->GetQuestRewardStatus(ConditionValue1));
384 }
385 break;
386 }
388 {
389 if (Player const* player = object->ToPlayer())
390 {
391 QuestStatus status = player->GetQuestStatus(ConditionValue1);
392 condMeets = (status == QUEST_STATUS_NONE);
393 }
394 break;
395 }
396 case CONDITION_AREAID:
397 condMeets = DB2Manager::IsInArea(object->GetAreaId(), ConditionValue1);
398 break;
399 case CONDITION_SPELL:
400 {
401 if (Player const* player = object->ToPlayer())
402 condMeets = player->HasSpell(ConditionValue1);
403 break;
404 }
405 case CONDITION_LEVEL:
406 {
407 if (Unit const* unit = object->ToUnit())
408 condMeets = CompareValues(static_cast<ComparisionType>(ConditionValue2), static_cast<uint32>(unit->GetLevel()), ConditionValue1);
409 break;
410 }
412 {
413 if (Player const* player = object->ToPlayer())
414 condMeets = (uint32)Player::GetDrunkenstateByValue(player->GetDrunkValue()) >= ConditionValue1;
415 break;
416 }
418 {
419 condMeets = object->FindNearestCreature(ConditionValue1, (float)ConditionValue2, bool(!ConditionValue3)) != nullptr;
420 break;
421 }
423 {
424 condMeets = object->FindNearestGameObject(ConditionValue1, (float)ConditionValue2) != nullptr;
425 break;
426 }
428 {
429 if (uint32(object->GetTypeId()) == ConditionValue1)
430 {
431 condMeets = !ConditionValue2 || (object->GetEntry() == ConditionValue2);
432
433 if (ConditionValue3)
434 {
435 switch (object->GetTypeId())
436 {
437 case TYPEID_UNIT:
438 condMeets &= object->ToCreature()->GetSpawnId() == ConditionValue3;
439 break;
441 condMeets &= object->ToGameObject()->GetSpawnId() == ConditionValue3;
442 break;
443 default:
444 break;
445 }
446 }
447 }
448 break;
449 }
451 {
452 condMeets = object->isType(ConditionValue1);
453 break;
454 }
456 {
457 if (WorldObject const* toObject = sourceInfo.mConditionTargets[ConditionValue1])
458 {
459 Unit const* toUnit = toObject->ToUnit();
460 Unit const* unit = object->ToUnit();
461 if (toUnit && unit)
462 {
463 switch (static_cast<RelationType>(ConditionValue2))
464 {
465 case RELATION_SELF:
466 condMeets = unit == toUnit;
467 break;
469 condMeets = unit->IsInPartyWith(toUnit);
470 break;
472 condMeets = unit->IsInRaidWith(toUnit);
473 break;
475 condMeets = unit->GetOwnerGUID() == toUnit->GetGUID();
476 break;
478 condMeets = unit->IsOnVehicle(toUnit);
479 break;
481 condMeets = unit->GetCreatorGUID() == toUnit->GetGUID();
482 break;
483 default:
484 break;
485 }
486 }
487 }
488 break;
489 }
491 {
492 if (WorldObject const* toObject = sourceInfo.mConditionTargets[ConditionValue1])
493 {
494 Unit const* toUnit = toObject->ToUnit();
495 Unit const* unit = object->ToUnit();
496 if (toUnit && unit)
497 condMeets = ((1 << unit->GetReactionTo(toUnit)) & ConditionValue2) != 0;
498 }
499 break;
500 }
502 {
503 if (WorldObject const* toObject = sourceInfo.mConditionTargets[ConditionValue1])
504 condMeets = CompareValues(static_cast<ComparisionType>(ConditionValue3), object->GetDistance(toObject), static_cast<float>(ConditionValue2));
505 break;
506 }
507 case CONDITION_ALIVE:
508 {
509 if (Unit const* unit = object->ToUnit())
510 condMeets = unit->IsAlive();
511 break;
512 }
513 case CONDITION_HP_VAL:
514 {
515 if (Unit const* unit = object->ToUnit())
516 condMeets = CompareValues(static_cast<ComparisionType>(ConditionValue2), unit->GetHealth(), static_cast<uint64>(ConditionValue1));
517 break;
518 }
519 case CONDITION_HP_PCT:
520 {
521 if (Unit const* unit = object->ToUnit())
522 condMeets = CompareValues(static_cast<ComparisionType>(ConditionValue2), unit->GetHealthPct(), static_cast<float>(ConditionValue1));
523 break;
524 }
526 {
527 condMeets = object->GetPhaseShift().HasPhase(ConditionValue1);
528 break;
529 }
530 case CONDITION_TITLE:
531 {
532 if (Player const* player = object->ToPlayer())
533 condMeets = player->HasTitle(ConditionValue1);
534 break;
535 }
537 {
538 if (Unit const* unit = object->ToUnit())
539 condMeets = unit->HasUnitState(ConditionValue1);
540 break;
541 }
543 {
544 if (Creature const* creature = object->ToCreature())
545 condMeets = creature->GetCreatureTemplate()->type == ConditionValue1;
546 break;
547 }
549 {
550 if (Unit const* unit = object->ToUnit())
551 condMeets = unit->IsInWater();
552 break;
553 }
555 {
556 condMeets = object->GetPhaseShift().HasVisibleMapId(ConditionValue1);
557 break;
558 }
560 {
561 if (Unit const* unit = object->ToUnit())
562 {
563 if (ConditionValue1 == 0)
564 condMeets = (unit->GetStandState() == UnitStandStateType(ConditionValue2));
565 else if (ConditionValue2 == 0)
566 condMeets = unit->IsStandState();
567 else if (ConditionValue2 == 1)
568 condMeets = unit->IsSitState();
569 }
570 break;
571 }
573 {
574 if (Player const* player = object->ToPlayer())
575 condMeets = player->IsDailyQuestDone(ConditionValue1);
576 break;
577 }
579 {
580 if (Unit const* unit = object->ToUnit())
581 condMeets = unit->IsCharmed();
582 break;
583 }
585 {
586 if (Player const* player = object->ToPlayer())
587 if (Pet const* pet = player->GetPet())
588 condMeets = (((1 << pet->getPetType()) & ConditionValue1) != 0);
589 break;
590 }
591 case CONDITION_TAXI:
592 {
593 if (Player const* player = object->ToPlayer())
594 condMeets = player->IsInFlight();
595 break;
596 }
598 {
599 if (Player const* player = object->ToPlayer())
600 {
601 if (
602 ((ConditionValue2 & (1 << QUEST_STATUS_NONE)) && (player->GetQuestStatus(ConditionValue1) == QUEST_STATUS_NONE)) ||
603 ((ConditionValue2 & (1 << QUEST_STATUS_COMPLETE)) && (player->GetQuestStatus(ConditionValue1) == QUEST_STATUS_COMPLETE)) ||
604 ((ConditionValue2 & (1 << QUEST_STATUS_INCOMPLETE)) && (player->GetQuestStatus(ConditionValue1) == QUEST_STATUS_INCOMPLETE)) ||
605 ((ConditionValue2 & (1 << QUEST_STATUS_FAILED)) && (player->GetQuestStatus(ConditionValue1) == QUEST_STATUS_FAILED)) ||
606 ((ConditionValue2 & (1 << QUEST_STATUS_REWARDED)) && player->GetQuestRewardStatus(ConditionValue1))
607 )
608 condMeets = true;
609 }
610 break;
611 }
613 {
614 if (Player const* player = object->ToPlayer())
615 {
616 QuestObjective const* obj = sObjectMgr->GetQuestObjective(ConditionValue1);
617 if (!obj)
618 break;
619
620 Quest const* quest = sObjectMgr->GetQuestTemplate(obj->QuestID);
621 if (!quest)
622 break;
623
624 uint16 slot = player->FindQuestSlot(obj->QuestID);
625 if (slot >= MAX_QUEST_LOG_SIZE)
626 break;
627
628 condMeets = player->GetQuestSlotObjectiveData(slot, *obj) == int32(ConditionValue3);
629 }
630 break;
631 }
633 {
634 if (Player const* player = object->ToPlayer())
635 {
636 if (ConditionValue1 == 1)
637 condMeets = player->CanBeGameMaster();
638 else
639 condMeets = player->IsGameMaster();
640 }
641 break;
642 }
644 {
645 if (Player const* player = object->ToPlayer())
646 condMeets = CompareValues(static_cast<ComparisionType>(ConditionValue3),
647 player->GetSession()->GetBattlePetMgr()->GetPetCount(sBattlePetSpeciesStore.AssertEntry(ConditionValue1), player->GetGUID()),
648 static_cast<uint8>(ConditionValue2));
649 break;
650 }
652 {
653 if (Player const* player = object->ToPlayer())
654 condMeets = player->GetSceneMgr().GetActiveSceneCount(ConditionValue1) > 0;
655 break;
656 }
658 {
659 if (Player const* player = object->ToPlayer())
660 if (PlayerConditionEntry const* playerCondition = sPlayerConditionStore.LookupEntry(ConditionValue1))
661 condMeets = ConditionMgr::IsPlayerMeetingCondition(player, playerCondition);
662 break;
663 }
665 {
666 condMeets = !object->GetPrivateObjectOwner().IsEmpty();
667 break;
668 }
670 {
671 if (Creature const* creature = object->ToCreature())
672 condMeets = creature->HasStringId(ConditionStringValue1);
673 else if (GameObject const* go = object->ToGameObject())
674 condMeets = go->HasStringId(ConditionStringValue1);
675 break;
676 }
677 default:
678 break;
679 }
680
682 condMeets = !condMeets;
683
684 if (!condMeets)
685 sourceInfo.mLastFailedCondition = this;
686
687 return condMeets && sScriptMgr->OnConditionCheck(this, sourceInfo); // Returns true by default.;
688}
689
691{
692 // build mask of types for which condition can return true
693 // this is used for speeding up gridsearches
695 return (GRID_MAP_TYPE_MASK_ALL);
696 uint32 mask = 0;
697 switch (ConditionType)
698 {
699 case CONDITION_NONE:
701 break;
702 case CONDITION_AURA:
704 break;
705 case CONDITION_ITEM:
707 break;
710 break;
711 case CONDITION_ZONEID:
713 break;
716 break;
719 break;
720 case CONDITION_TEAM:
722 break;
723 case CONDITION_CLASS:
725 break;
726 case CONDITION_RACE:
728 break;
729 case CONDITION_SKILL:
731 break;
734 break;
737 break;
740 break;
743 break;
746 break;
749 break;
750 case CONDITION_MAPID:
752 break;
753 case CONDITION_AREAID:
755 break;
756 case CONDITION_SPELL:
758 break;
759 case CONDITION_LEVEL:
761 break;
764 break;
767 break;
770 break;
772 switch (ConditionValue1)
773 {
774 case TYPEID_UNIT:
776 break;
777 case TYPEID_PLAYER:
779 break;
782 break;
783 case TYPEID_CORPSE:
785 break;
788 break;
789 default:
790 break;
791 }
792 break;
804 break;
807 break;
810 break;
813 break;
814 case CONDITION_ALIVE:
816 break;
817 case CONDITION_HP_VAL:
819 break;
820 case CONDITION_HP_PCT:
822 break;
825 break;
828 break;
829 case CONDITION_TITLE:
831 break;
832 case CONDITION_GENDER:
834 break;
837 break;
840 break;
843 break;
846 break;
849 break;
852 break;
855 break;
858 break;
861 break;
862 case CONDITION_TAXI:
864 break;
867 break;
870 break;
873 break;
876 break;
879 break;
882 break;
885 break;
888 break;
890 mask |= GRID_MAP_TYPE_MASK_ALL & ~GRID_MAP_TYPE_MASK_PLAYER;
891 break;
892 default:
893 ABORT_MSG("Condition::GetSearcherTypeMaskForCondition - missing condition handling!");
894 break;
895 }
896 return mask;
897}
898
900{
901 // returns number of targets which are available for given source type
902 switch (SourceType)
903 {
914 return 2;
915 default:
916 return 1;
917 }
918}
919
920std::string Condition::ToString(bool ext /*= false*/) const
921{
922 std::ostringstream ss;
923 ss << "[Condition ";
924 ss << "SourceType: " << SourceType;
928 ss << " (Reference)";
929 else
930 ss << " (Unknown)";
932 ss << ", SourceGroup: " << SourceGroup;
933 ss << ", SourceEntry: " << SourceEntry;
935 ss << ", SourceId: " << SourceId;
936
937 if (ext)
938 {
939 ss << ", ConditionType: " << ConditionType;
942 else
943 ss << " (Unknown)";
944 }
945
946 ss << "]";
947 return ss.str();
948}
949
951
953{
954 Clean();
955}
956
958{
959 if (conditions.empty())
961 // groupId, typeMask
962 std::map<uint32, uint32> elseGroupSearcherTypeMasks;
963 for (ConditionContainer::const_iterator i = conditions.begin(); i != conditions.end(); ++i)
964 {
965 // no point of having not loaded conditions in list
966 ASSERT(i->isLoaded() && "ConditionMgr::GetSearcherTypeMaskForConditionList - not yet loaded condition found in list");
967 std::map<uint32, uint32>::const_iterator itr = elseGroupSearcherTypeMasks.find(i->ElseGroup);
968 // group not filled yet, fill with widest mask possible
969 if (itr == elseGroupSearcherTypeMasks.end())
970 elseGroupSearcherTypeMasks[i->ElseGroup] = GRID_MAP_TYPE_MASK_ALL;
971 // no point of checking anymore, empty mask
972 else if (!itr->second)
973 continue;
974
975 if (i->ReferenceId) // handle reference
976 {
977 auto ref = ConditionStore[CONDITION_SOURCE_TYPE_REFERENCE_CONDITION].find({ i->ReferenceId, 0, 0 });
978 ASSERT(ref != ConditionStore[CONDITION_SOURCE_TYPE_REFERENCE_CONDITION].end() && "ConditionMgr::GetSearcherTypeMaskForConditionList - incorrect reference");
979 elseGroupSearcherTypeMasks[i->ElseGroup] &= GetSearcherTypeMaskForConditionList(*(ref->second));
980 }
981 else // handle normal condition
982 {
983 // object will match conditions in one ElseGroupStore only when it matches all of them
984 // so, let's find a smallest possible mask which satisfies all conditions
985 elseGroupSearcherTypeMasks[i->ElseGroup] &= i->GetSearcherTypeMaskForCondition();
986 }
987 }
988 // object will match condition when one of the checks in ElseGroupStore is matching
989 // so, let's include all possible masks
990 uint32 mask = 0;
991 for (std::map<uint32, uint32>::const_iterator i = elseGroupSearcherTypeMasks.begin(); i != elseGroupSearcherTypeMasks.end(); ++i)
992 mask |= i->second;
993
994 return mask;
995}
996
998{
999 // groupId, groupCheckPassed
1000 std::map<uint32, bool> elseGroupStore;
1001 for (Condition const& condition : conditions)
1002 {
1003 TC_LOG_DEBUG("condition", "ConditionMgr::IsPlayerMeetToConditionList {} val1: {}", condition.ToString(), condition.ConditionValue1);
1004 if (condition.isLoaded())
1005 {
1007 std::map<uint32, bool>::iterator itr = elseGroupStore.try_emplace(condition.ElseGroup, true).first;
1008 if (!itr->second)
1009 continue;
1010
1011 if (condition.ReferenceId)//handle reference
1012 {
1013 auto ref = ConditionStore[CONDITION_SOURCE_TYPE_REFERENCE_CONDITION].find({ condition.ReferenceId, 0, 0 });
1015 {
1016 if (!IsObjectMeetToConditionList(sourceInfo, *ref->second))
1017 itr->second = false;
1018 }
1019 else
1020 {
1021 TC_LOG_DEBUG("condition", "ConditionMgr::IsPlayerMeetToConditionList {} Reference template -{} not found",
1022 condition.ToString(), condition.ReferenceId); // checked at loading, should never happen
1023 }
1024
1025 }
1026 else //handle normal condition
1027 {
1028 if (!condition.Meets(sourceInfo))
1029 itr->second = false;
1030 }
1031 }
1032 }
1033 for (std::map<uint32, bool>::const_iterator i = elseGroupStore.begin(); i != elseGroupStore.end(); ++i)
1034 if (i->second)
1035 return true;
1036
1037 return false;
1038}
1039
1041{
1042 ConditionSourceInfo srcInfo = ConditionSourceInfo(object);
1043 return IsObjectMeetToConditions(srcInfo, conditions);
1044}
1045
1046bool ConditionMgr::IsObjectMeetToConditions(WorldObject const* object1, WorldObject const* object2, ConditionContainer const& conditions) const
1047{
1048 ConditionSourceInfo srcInfo = ConditionSourceInfo(object1, object2);
1049 return IsObjectMeetToConditions(srcInfo, conditions);
1050}
1051
1053{
1054 if (conditions.empty())
1055 return true;
1056
1057 TC_LOG_DEBUG("condition", "ConditionMgr::IsObjectMeetToConditions");
1058 return IsObjectMeetToConditionList(sourceInfo, conditions);
1059}
1060
1062{
1063 return (sourceType == CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE ||
1075 sourceType == CONDITION_SOURCE_TYPE_GOSSIP_MENU ||
1080 sourceType == CONDITION_SOURCE_TYPE_SMART_EVENT ||
1081 sourceType == CONDITION_SOURCE_TYPE_NPC_VENDOR ||
1082 sourceType == CONDITION_SOURCE_TYPE_PHASE ||
1083 sourceType == CONDITION_SOURCE_TYPE_GRAVEYARD ||
1084 sourceType == CONDITION_SOURCE_TYPE_AREATRIGGER ||
1088}
1089
1091{
1092 return (sourceType == CONDITION_SOURCE_TYPE_SMART_EVENT);
1093}
1094
1096{
1097 switch (sourceType)
1098 {
1100 switch (conditionType)
1101 {
1102 case CONDITION_NONE:
1105 case CONDITION_MAPID:
1110 return true;
1111 default:
1112 return false;
1113 }
1114 break;
1115 default:
1116 break;
1117 }
1118 return true;
1119}
1120
1122{
1123 if (sourceType > CONDITION_SOURCE_TYPE_NONE && sourceType < CONDITION_SOURCE_TYPE_MAX)
1124 {
1125 auto i = ConditionStore[sourceType].find({ 0, int32(entry), 0 });
1126 if (i != ConditionStore[sourceType].end())
1127 {
1128 TC_LOG_DEBUG("condition", "GetConditionsForNotGroupedEntry: found conditions for type {} and entry {}", uint32(sourceType), entry);
1129 return IsObjectMeetToConditions(sourceInfo, *i->second);
1130 }
1131 }
1132
1133 return true;
1134}
1135
1136bool ConditionMgr::IsObjectMeetingNotGroupedConditions(ConditionSourceType sourceType, uint32 entry, WorldObject const* target0, WorldObject const* target1 /*= nullptr*/, WorldObject const* target2 /*= nullptr*/) const
1137{
1138 ConditionSourceInfo conditionSource(target0, target1, target2);
1139 return IsObjectMeetingNotGroupedConditions(sourceType, entry, conditionSource);
1140}
1141
1143{
1144 ConditionSourceInfo conditionSource(map);
1145 return IsObjectMeetingNotGroupedConditions(sourceType, entry, conditionSource);
1146}
1147
1149{
1150 if (sourceType > CONDITION_SOURCE_TYPE_NONE && sourceType < CONDITION_SOURCE_TYPE_MAX)
1151 return ConditionStore[sourceType].contains({ 0, int32(entry), 0 });
1152
1153 return false;
1154}
1155
1156bool ConditionMgr::IsObjectMeetingSpellClickConditions(uint32 creatureId, uint32 spellId, WorldObject const* clicker, WorldObject const* target) const
1157{
1158 auto itr = ConditionStore[CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT].find({ creatureId, int32(spellId), 0 });
1160 {
1161 TC_LOG_DEBUG("condition", "IsObjectMeetingSpellClickConditions: found conditions for SpellClickEvent entry {} spell {}", creatureId, spellId);
1162 ConditionSourceInfo sourceInfo(clicker, target);
1163 return IsObjectMeetToConditions(sourceInfo, *itr->second);
1164 }
1165 return true;
1166}
1167
1169{
1170 auto itr = ConditionStore[CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT].find({ creatureId, int32(spellId), 0 });
1172 {
1173 TC_LOG_DEBUG("condition", "HasConditionsForSpellClickEvent: found conditions for SpellClickEvent entry {} spell {}", creatureId, spellId);
1174 return true;
1175 }
1176 return false;
1177}
1178
1179bool ConditionMgr::IsObjectMeetingVehicleSpellConditions(uint32 creatureId, uint32 spellId, Player const* player, Unit const* vehicle) const
1180{
1181 auto itr = ConditionStore[CONDITION_SOURCE_TYPE_VEHICLE_SPELL].find({ creatureId, int32(spellId), 0 });
1183 {
1184 TC_LOG_DEBUG("condition", "GetConditionsForVehicleSpell: found conditions for Vehicle entry {} spell {}", creatureId, spellId);
1185 ConditionSourceInfo sourceInfo(player, vehicle);
1186 return IsObjectMeetToConditions(sourceInfo, *itr->second);
1187 }
1188 return true;
1189}
1190
1191bool ConditionMgr::IsObjectMeetingSmartEventConditions(int64 entryOrGuid, uint32 eventId, uint32 sourceType, Unit const* unit, WorldObject const* baseObject) const
1192{
1193 auto itr = ConditionStore[CONDITION_SOURCE_TYPE_SMART_EVENT].find({ eventId + 1, int32(entryOrGuid), sourceType });
1195 {
1196 TC_LOG_DEBUG("condition", "GetConditionsForSmartEvent: found conditions for Smart Event entry or guid {} eventId {}", entryOrGuid, eventId);
1197 ConditionSourceInfo sourceInfo(unit, baseObject);
1198 return IsObjectMeetToConditions(sourceInfo, *itr->second);
1199 }
1200 return true;
1201}
1202
1203bool ConditionMgr::IsObjectMeetingVendorItemConditions(uint32 creatureId, uint32 itemId, Player const* player, Creature const* vendor) const
1204{
1205 auto itr = ConditionStore[CONDITION_SOURCE_TYPE_NPC_VENDOR].find({ creatureId, int32(itemId), 0 });
1207 {
1208 TC_LOG_DEBUG("condition", "GetConditionsForNpcVendor: found conditions for creature entry {} item {}", creatureId, itemId);
1209 ConditionSourceInfo sourceInfo(player, vendor);
1210 return IsObjectMeetToConditions(sourceInfo, *itr->second);
1211 }
1212 return true;
1213}
1214
1216{
1218}
1219
1220ConditionContainer const* ConditionMgr::GetConditionsForAreaTrigger(uint32 areaTriggerId, bool isServerSide) const
1221{
1222 auto itr = ConditionStore[CONDITION_SOURCE_TYPE_AREATRIGGER].find({ areaTriggerId, isServerSide ? 1 : 0, 0 });
1224 return itr->second.get();
1225 return nullptr;
1226}
1227
1229{
1230 auto itr = ConditionStore[CONDITION_SOURCE_TYPE_NPC_VENDOR].find({ trainerId, int32(spellId), 0 });
1232 {
1233 TC_LOG_DEBUG("condition", "IsObjectMeetingTrainerSpellConditions: found conditions for trainer id {} spell {}", trainerId, spellId);
1234 return IsObjectMeetToConditions(player, *itr->second);
1235 }
1236 return true;
1237}
1238
1240{
1241 auto itr = ConditionStore[CONDITION_SOURCE_TYPE_OBJECT_ID_VISIBILITY].find({ objectType, int32(entry), 0 });
1243 {
1244 TC_LOG_DEBUG("condition", "IsObjectMeetingVisibilityByObjectIdConditions: found conditions for objectType {} entry {}", objectType, entry);
1245 return IsObjectMeetToConditions(seer, *itr->second);
1246 }
1247 return true;
1248}
1249
1251{
1252 static ConditionMgr instance;
1253 return &instance;
1254}
1255
1257{
1258 uint32 oldMSTime = getMSTime();
1259
1260 Clean();
1261
1262 //must clear all custom handled cases (groupped types) before reload
1263 if (isReload)
1264 {
1265 sSpellMgr->UnloadSpellInfoImplicitTargetConditionLists();
1266
1267 sObjectMgr->UnloadPhaseConditions();
1268 }
1269
1270 QueryResult result = WorldDatabase.Query("SELECT SourceTypeOrReferenceId, SourceGroup, SourceEntry, SourceId, ElseGroup, ConditionTypeOrReference, ConditionTarget, "
1271 "ConditionValue1, ConditionValue2, ConditionValue3, ConditionStringValue1, "
1272 "NegativeCondition, ErrorType, ErrorTextId, ScriptName FROM conditions");
1273
1274 if (!result)
1275 {
1276 TC_LOG_INFO("server.loading", ">> Loaded 0 conditions. DB table `conditions` is empty!");
1277 return;
1278 }
1279
1280 uint32 count = 0;
1281
1282 auto getOrInitConditions = [this](ConditionSourceType sourceType, ConditionId const& id)
1283 {
1284 auto [itr, inserted] = ConditionStore[sourceType].try_emplace(id, nullptr);
1285 if (inserted)
1286 itr->second = std::make_shared<std::vector<Condition>>();
1287 return itr->second;
1288 };
1289
1290 do
1291 {
1292 Field* fields = result->Fetch();
1293
1294 Condition cond;
1295 int32 iSourceTypeOrReferenceId = fields[0].GetInt32();
1296 cond.SourceGroup = fields[1].GetUInt32();
1297 cond.SourceEntry = fields[2].GetInt32();
1298 cond.SourceId = fields[3].GetInt32();
1299 cond.ElseGroup = fields[4].GetUInt32();
1300 int32 iConditionTypeOrReference = fields[5].GetInt32();
1301 cond.ConditionTarget = fields[6].GetUInt8();
1302 cond.ConditionValue1 = fields[7].GetUInt32();
1303 cond.ConditionValue2 = fields[8].GetUInt32();
1304 cond.ConditionValue3 = fields[9].GetUInt32();
1305 cond.ConditionStringValue1 = fields[10].GetString();
1306 cond.NegativeCondition = fields[11].GetBool();
1307 cond.ErrorType = fields[12].GetUInt32();
1308 cond.ErrorTextId = fields[13].GetUInt32();
1309 cond.ScriptId = sObjectMgr->GetScriptId(fields[14].GetString());
1310
1311 if (iConditionTypeOrReference >= 0)
1312 cond.ConditionType = ConditionTypes(iConditionTypeOrReference);
1313
1314 if (iSourceTypeOrReferenceId >= 0)
1315 cond.SourceType = ConditionSourceType(iSourceTypeOrReferenceId);
1316
1317 if (iConditionTypeOrReference < 0)//it has a reference
1318 {
1319 if (iConditionTypeOrReference == iSourceTypeOrReferenceId)//self referencing, skip
1320 {
1321 TC_LOG_ERROR("sql.sql", "Condition reference {} is referencing self, skipped", iSourceTypeOrReferenceId);
1322 continue;
1323 }
1324
1325 cond.ReferenceId = uint32(-iConditionTypeOrReference);
1326
1327 char const* rowType = "reference template";
1328 if (iSourceTypeOrReferenceId >= 0)
1329 rowType = "reference";
1330 //check for useless data
1331 if (cond.ConditionTarget)
1332 TC_LOG_ERROR("sql.sql", "Condition {} {} has useless data in ConditionTarget ({})!", rowType, iSourceTypeOrReferenceId, cond.ConditionTarget);
1333 if (cond.ConditionValue1)
1334 TC_LOG_ERROR("sql.sql", "Condition {} {} has useless data in value1 ({})!", rowType, iSourceTypeOrReferenceId, cond.ConditionValue1);
1335 if (cond.ConditionValue2)
1336 TC_LOG_ERROR("sql.sql", "Condition {} {} has useless data in value2 ({})!", rowType, iSourceTypeOrReferenceId, cond.ConditionValue2);
1337 if (cond.ConditionValue3)
1338 TC_LOG_ERROR("sql.sql", "Condition {} {} has useless data in value3 ({})!", rowType, iSourceTypeOrReferenceId, cond.ConditionValue3);
1339 if (cond.NegativeCondition)
1340 TC_LOG_ERROR("sql.sql", "Condition {} {} has useless data in NegativeCondition ({})!", rowType, iSourceTypeOrReferenceId, cond.NegativeCondition);
1341 }
1342 else if (!isConditionTypeValid(&cond))//doesn't have reference, validate ConditionType
1343 continue;
1344
1345 if (iSourceTypeOrReferenceId < 0)//it is a reference template
1346 {
1347 if (cond.SourceGroup)
1348 TC_LOG_ERROR("sql.sql", "Condition reference template {} has useless data in SourceGroup ({})!", iSourceTypeOrReferenceId, cond.SourceGroup);
1349 if (cond.SourceEntry)
1350 TC_LOG_ERROR("sql.sql", "Condition reference template {} has useless data in SourceEntry ({})!", iSourceTypeOrReferenceId, cond.SourceEntry);
1351 if (cond.SourceId)
1352 TC_LOG_ERROR("sql.sql", "Condition reference template {} has useless data in SourceId ({})!", iSourceTypeOrReferenceId, cond.SourceId);
1353
1355 cond.SourceGroup = -iSourceTypeOrReferenceId;
1356 }
1357 else if (!isSourceTypeValid(&cond)) //if not a reference and SourceType is invalid, skip
1358 continue;
1359
1360 //Grouping is only allowed for some types (loot templates, gossip menus, gossip items)
1361 if (cond.SourceGroup && !CanHaveSourceGroupSet(cond.SourceType))
1362 {
1363 TC_LOG_ERROR("sql.sql", "{} has not allowed value of SourceGroup = {}!", cond.ToString(), cond.SourceGroup);
1364 continue;
1365 }
1366 if (cond.SourceId && !CanHaveSourceIdSet(cond.SourceType))
1367 {
1368 TC_LOG_ERROR("sql.sql", "{} has not allowed value of SourceId = {}!", cond.ToString(), cond.SourceId);
1369 continue;
1370 }
1371
1373 {
1374 TC_LOG_ERROR("sql.sql", "{} can't have ErrorType ({}), set to 0!", cond.ToString(), cond.ErrorType);
1375 cond.ErrorType = 0;
1376 }
1377
1378 if (cond.ErrorTextId && !cond.ErrorType)
1379 {
1380 TC_LOG_ERROR("sql.sql", "{} has any ErrorType, ErrorTextId ({}) is set, set to 0!", cond.ToString(), cond.ErrorTextId);
1381 cond.ErrorTextId = 0;
1382 }
1383
1384 getOrInitConditions(cond.SourceType, { cond.SourceGroup, cond.SourceEntry, cond.SourceId })->emplace_back(std::move(cond));
1385 ++count;
1386 }
1387 while (result->NextRow());
1388
1389 for (auto&& [id, conditions] : ConditionStore[CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE])
1390 addToLootTemplate(id, conditions, LootTemplates_Creature.GetLootForConditionFill(id.SourceGroup));
1391
1392 for (auto&& [id, conditions] : ConditionStore[CONDITION_SOURCE_TYPE_DISENCHANT_LOOT_TEMPLATE])
1394
1395 for (auto&& [id, conditions] : ConditionStore[CONDITION_SOURCE_TYPE_FISHING_LOOT_TEMPLATE])
1396 addToLootTemplate(id, conditions, LootTemplates_Fishing.GetLootForConditionFill(id.SourceGroup));
1397
1398 for (auto&& [id, conditions] : ConditionStore[CONDITION_SOURCE_TYPE_GAMEOBJECT_LOOT_TEMPLATE])
1400
1401 for (auto&& [id, conditions] : ConditionStore[CONDITION_SOURCE_TYPE_ITEM_LOOT_TEMPLATE])
1402 addToLootTemplate(id, conditions, LootTemplates_Item.GetLootForConditionFill(id.SourceGroup));
1403
1404 for (auto&& [id, conditions] : ConditionStore[CONDITION_SOURCE_TYPE_MAIL_LOOT_TEMPLATE])
1405 addToLootTemplate(id, conditions, LootTemplates_Mail.GetLootForConditionFill(id.SourceGroup));
1406
1407 for (auto&& [id, conditions] : ConditionStore[CONDITION_SOURCE_TYPE_MILLING_LOOT_TEMPLATE])
1408 addToLootTemplate(id, conditions, LootTemplates_Milling.GetLootForConditionFill(id.SourceGroup));
1409
1412
1415
1416 for (auto&& [id, conditions] : ConditionStore[CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE])
1417 addToLootTemplate(id, conditions, LootTemplates_Reference.GetLootForConditionFill(id.SourceGroup));
1418
1419 for (auto&& [id, conditions] : ConditionStore[CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE])
1420 addToLootTemplate(id, conditions, LootTemplates_Skinning.GetLootForConditionFill(id.SourceGroup));
1421
1422 for (auto&& [id, conditions] : ConditionStore[CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE])
1423 addToLootTemplate(id, conditions, LootTemplates_Spell.GetLootForConditionFill(id.SourceGroup));
1424
1425 for (auto&& [id, conditions] : ConditionStore[CONDITION_SOURCE_TYPE_GOSSIP_MENU])
1426 addToGossipMenus(id, conditions);
1427
1428 for (auto&& [id, conditions] : ConditionStore[CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION])
1429 addToGossipMenuItems(id, conditions);
1430
1432 for (auto&& [id, conditions] : ConditionStore[CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT])
1433 for (Condition const& condition : *conditions)
1434 if (condition.ConditionType == CONDITION_AURA)
1435 SpellsUsedInSpellClickConditions.insert(condition.ConditionValue1);
1436
1437 for (auto&& [id, conditions] : ConditionStore[CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET])
1438 for (Condition const& condition : *conditions)
1440
1441 for (auto&& [id, conditions] : ConditionStore[CONDITION_SOURCE_TYPE_PHASE])
1442 addToPhases(id, conditions);
1443
1444 for (auto&& [id, conditions] : ConditionStore[CONDITION_SOURCE_TYPE_GRAVEYARD])
1445 addToGraveyardData(id, conditions);
1446
1447 TC_LOG_INFO("server.loading", ">> Loaded {} conditions in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
1448}
1449
1450void ConditionMgr::addToLootTemplate(ConditionId const& id, std::shared_ptr<std::vector<Condition>> conditions, LootTemplate* loot) const
1451{
1452 if (!loot)
1453 {
1454 for (Condition const& condition : *conditions)
1455 TC_LOG_ERROR("sql.sql", "{} LootTemplate {} not found.", condition.ToString(), id.SourceGroup);
1456 return;
1457 }
1458
1459 if (loot->LinkConditions(id, ConditionsReference{ conditions }))
1460 return;
1461
1462 for (Condition const& condition : *conditions)
1463 TC_LOG_ERROR("sql.sql", "{} Item {} not found in LootTemplate {}.", condition.ToString(), id.SourceEntry, id.SourceGroup);
1464}
1465
1466void ConditionMgr::addToGossipMenus(ConditionId const& id, std::shared_ptr<std::vector<Condition>> conditions) const
1467{
1468 GossipMenusMapBoundsNonConst pMenuBounds = sObjectMgr->GetGossipMenusMapBoundsNonConst(id.SourceGroup);
1469
1470 if (pMenuBounds.first != pMenuBounds.second)
1471 {
1472 for (GossipMenusContainer::iterator itr = pMenuBounds.first; itr != pMenuBounds.second; ++itr)
1473 if (itr->second.MenuID == id.SourceGroup && (itr->second.TextID == uint32(id.SourceEntry) || id.SourceEntry == 0))
1474 itr->second.Conditions = { conditions };
1475
1476 return;
1477 }
1478
1479 for (Condition const& condition : *conditions)
1480 TC_LOG_ERROR("sql.sql", "{} GossipMenu {} not found.", condition.ToString(), id.SourceGroup);
1481}
1482
1483void ConditionMgr::addToGossipMenuItems(ConditionId const& id, std::shared_ptr<std::vector<Condition>> conditions) const
1484{
1485 Trinity::IteratorPair pMenuItemBounds = sObjectMgr->GetGossipMenuItemsMapBoundsNonConst(id.SourceGroup);
1486 for (auto& [_, gossipMenuItem] : pMenuItemBounds)
1487 {
1488 if (gossipMenuItem.MenuID == id.SourceGroup && gossipMenuItem.OrderIndex == uint32(id.SourceEntry))
1489 {
1490 gossipMenuItem.Conditions = { conditions };
1491 return;
1492 }
1493 }
1494
1495 for (Condition const& condition : *conditions)
1496 TC_LOG_ERROR("sql.sql", "{} GossipMenuId {} Item {} not found.", condition.ToString(), id.SourceGroup, id.SourceEntry);
1497}
1498
1500{
1501 sSpellMgr->ForEachSpellInfoDifficulty(cond.SourceEntry, [&](SpellInfo const* spellInfo)
1502 {
1503 uint32 conditionEffMask = cond.SourceGroup;
1504 std::list<uint32> sharedMasks;
1505 for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects())
1506 {
1507 // additional checks by condition type
1508 if (conditionEffMask & (1 << spellEffectInfo.EffectIndex))
1509 {
1510 switch (cond.ConditionType)
1511 {
1512 case CONDITION_OBJECT_ENTRY_GUID:
1513 {
1514 uint32 implicitTargetMask = GetTargetFlagMask(spellEffectInfo.TargetA.GetObjectType()) | GetTargetFlagMask(spellEffectInfo.TargetB.GetObjectType());
1515 if ((implicitTargetMask & TARGET_FLAG_UNIT_MASK) && cond.ConditionValue1 != TYPEID_UNIT && cond.ConditionValue1 != TYPEID_PLAYER)
1516 {
1517 TC_LOG_ERROR("sql.sql", "{} in `condition` table - spell {} EFFECT_{} - "
1518 "target requires ConditionValue1 to be either TYPEID_UNIT ({}) or TYPEID_PLAYER ({})", cond.ToString(), spellInfo->Id, uint32(spellEffectInfo.EffectIndex), uint32(TYPEID_UNIT), uint32(TYPEID_PLAYER));
1519 return;
1520 }
1521
1522 if ((implicitTargetMask & TARGET_FLAG_GAMEOBJECT_MASK) && cond.ConditionValue1 != TYPEID_GAMEOBJECT)
1523 {
1524 TC_LOG_ERROR("sql.sql", "{} in `condition` table - spell {} EFFECT_{} - "
1525 "target requires ConditionValue1 to be TYPEID_GAMEOBJECT ({})", cond.ToString(), spellInfo->Id, uint32(spellEffectInfo.EffectIndex), uint32(TYPEID_GAMEOBJECT));
1526 return;
1527 }
1528
1529 if ((implicitTargetMask & TARGET_FLAG_CORPSE_MASK) && cond.ConditionValue1 != TYPEID_CORPSE)
1530 {
1531 TC_LOG_ERROR("sql.sql", "{} in `condition` table - spell {} EFFECT_{} - "
1532 "target requires ConditionValue1 to be TYPEID_CORPSE ({})", cond.ToString(), spellInfo->Id, uint32(spellEffectInfo.EffectIndex), uint32(TYPEID_CORPSE));
1533 return;
1534 }
1535 break;
1536 }
1537 default:
1538 break;
1539 }
1540 }
1541
1542 // check if effect is already a part of some shared mask
1543 auto itr = std::find_if(sharedMasks.begin(), sharedMasks.end(), [&](uint32 mask) { return !!(mask & (1 << spellEffectInfo.EffectIndex)); });
1544 if (itr != sharedMasks.end())
1545 continue;
1546
1547 // build new shared mask with found effect
1548 uint32 sharedMask = 1 << spellEffectInfo.EffectIndex;
1549 for (size_t effIndex = spellEffectInfo.EffectIndex + 1; effIndex < spellInfo->GetEffects().size(); ++effIndex)
1550 if (spellInfo->GetEffect(SpellEffIndex(effIndex)).ImplicitTargetConditions == spellEffectInfo.ImplicitTargetConditions)
1551 sharedMask |= 1 << effIndex;
1552
1553 sharedMasks.push_back(sharedMask);
1554 }
1555
1556 for (uint32 effectMask : sharedMasks)
1557 {
1558 // some effect indexes should have same data
1559 if (uint32 commonMask = effectMask & conditionEffMask)
1560 {
1561 size_t firstEffIndex = 0;
1562 for (; firstEffIndex < spellInfo->GetEffects().size(); ++firstEffIndex)
1563 if ((1 << firstEffIndex) & effectMask)
1564 break;
1565
1566 if (firstEffIndex >= spellInfo->GetEffects().size())
1567 return;
1568
1569 // get shared data
1570 std::shared_ptr<ConditionContainer> sharedList = spellInfo->GetEffect(SpellEffIndex(firstEffIndex)).ImplicitTargetConditions;
1571
1572 // there's already data entry for that sharedMask
1573 if (sharedList)
1574 {
1575 // we have overlapping masks in db
1576 if (conditionEffMask != effectMask)
1577 {
1578 TC_LOG_ERROR("sql.sql", "{} in `condition` table, has incorrect SourceGroup {} (spell effectMask) set - "
1579 "effect masks are overlapping (all SourceGroup values having given bit set must be equal) - ignoring (Difficulty {}).",
1580 cond.ToString(), cond.SourceGroup, uint32(spellInfo->Difficulty));
1581 return;
1582 }
1583 }
1584 // no data for shared mask, we can create new submask
1585 else
1586 {
1587 // add new list, create new shared mask
1588 sharedList = std::make_shared<ConditionContainer>();
1589 bool assigned = false;
1590 for (size_t i = firstEffIndex; i < spellInfo->GetEffects().size(); ++i)
1591 {
1592 if ((1 << i) & commonMask)
1593 {
1594 const_cast<SpellEffectInfo&>(spellInfo->GetEffect(SpellEffIndex(i))).ImplicitTargetConditions = sharedList;
1595 assigned = true;
1596 }
1597 }
1598
1599 if (!assigned)
1600 break;
1601 }
1602 sharedList->push_back(cond);
1603 break;
1604 }
1605 }
1606 });
1607}
1608
1609void ConditionMgr::addToPhases(ConditionId const& id, std::shared_ptr<std::vector<Condition>> conditions) const
1610{
1611 if (!id.SourceEntry)
1612 {
1613 if (PhaseInfoStruct const* phaseInfo = sObjectMgr->GetPhaseInfo(id.SourceGroup))
1614 {
1615 bool found = false;
1616 for (uint32 areaId : phaseInfo->Areas)
1617 {
1618 if (std::vector<PhaseAreaInfo>* phases = const_cast<std::vector<PhaseAreaInfo>*>(sObjectMgr->GetPhasesForArea(areaId)))
1619 {
1620 for (PhaseAreaInfo& phase : *phases)
1621 {
1622 if (phase.PhaseInfo->Id == id.SourceGroup)
1623 {
1624 phase.Conditions.insert(phase.Conditions.end(), conditions->begin(), conditions->end());
1625 found = true;
1626 }
1627 }
1628 }
1629 }
1630
1631 if (found)
1632 return;
1633 }
1634 }
1635 else if (std::vector<PhaseAreaInfo>* phases = const_cast<std::vector<PhaseAreaInfo>*>(sObjectMgr->GetPhasesForArea(id.SourceEntry)))
1636 {
1637 for (PhaseAreaInfo& phase : *phases)
1638 {
1639 if (phase.PhaseInfo->Id == id.SourceGroup)
1640 {
1641 phase.Conditions.insert(phase.Conditions.end(), conditions->begin(), conditions->end());
1642 return;
1643 }
1644 }
1645 }
1646
1647 for (Condition const& condition : *conditions)
1648 TC_LOG_ERROR("sql.sql", "{} Area {} does not have phase {}.", condition.ToString(), id.SourceEntry, id.SourceGroup);
1649}
1650
1651void ConditionMgr::addToGraveyardData(ConditionId const& id, std::shared_ptr<std::vector<Condition>> conditions) const
1652{
1653 if (GraveyardData* graveyard = const_cast<GraveyardData*>(sObjectMgr->FindGraveyardData(id.SourceEntry, id.SourceGroup)))
1654 {
1655 graveyard->Conditions = { conditions };
1656 return;
1657 }
1658
1659 for (Condition const& condition : *conditions)
1660 TC_LOG_ERROR("sql.sql", "{}, Graveyard {} does not have ghostzone {}.", condition.ToString(), id.SourceEntry, id.SourceGroup);
1661}
1662
1664{
1665 switch (cond->SourceType)
1666 {
1668 {
1670 {
1671 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `creature_loot_template`, ignoring.", cond->ToString());
1672 return false;
1673 }
1674
1676 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1677 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1678 {
1679 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, item does not exist, ignoring.", cond->ToString());
1680 return false;
1681 }
1682 break;
1683 }
1685 {
1687 {
1688 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `disenchant_loot_template`, ignoring.", cond->ToString());
1689 return false;
1690 }
1691
1693 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1694 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1695 {
1696 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, item does not exist, ignoring.", cond->ToString());
1697 return false;
1698 }
1699 break;
1700 }
1702 {
1704 {
1705 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `fishing_loot_template`, ignoring.", cond->ToString());
1706 return false;
1707 }
1708
1710 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1711 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1712 {
1713 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, item does not exist, ignoring.", cond->ToString());
1714 return false;
1715 }
1716 break;
1717 }
1719 {
1721 {
1722 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `gameobject_loot_template`, ignoring.", cond->ToString());
1723 return false;
1724 }
1725
1727 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1728 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1729 {
1730 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, item does not exist, ignoring.", cond->ToString());
1731 return false;
1732 }
1733 break;
1734 }
1736 {
1738 {
1739 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `item_loot_template`, ignoring.", cond->ToString());
1740 return false;
1741 }
1742
1744 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1745 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1746 {
1747 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, item does not exist, ignoring.", cond->ToString());
1748 return false;
1749 }
1750 break;
1751 }
1753 {
1755 {
1756 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `mail_loot_template`, ignoring.", cond->ToString());
1757 return false;
1758 }
1759
1761 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1762 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1763 {
1764 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, item does not exist, ignoring.", cond->ToString());
1765 return false;
1766 }
1767 break;
1768 }
1770 {
1772 {
1773 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `milling_loot_template`, ignoring.", cond->ToString());
1774 return false;
1775 }
1776
1778 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1779 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1780 {
1781 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, item does not exist, ignoring.", cond->ToString());
1782 return false;
1783 }
1784 break;
1785 }
1787 {
1789 {
1790 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `pickpocketing_loot_template`, ignoring.", cond->ToString());
1791 return false;
1792 }
1793
1795 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1796 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1797 {
1798 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, item does not exist, ignoring.", cond->ToString());
1799 return false;
1800 }
1801 break;
1802 }
1804 {
1806 {
1807 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `prospecting_loot_template`, ignoring.", cond->ToString());
1808 return false;
1809 }
1810
1812 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1813 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1814 {
1815 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, item does not exist, ignoring.", cond->ToString());
1816 return false;
1817 }
1818 break;
1819 }
1821 {
1823 {
1824 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `reference_loot_template`, ignoring.", cond->ToString());
1825 return false;
1826 }
1827
1829 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1830 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1831 {
1832 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, item does not exist, ignoring.", cond->ToString());
1833 return false;
1834 }
1835 break;
1836 }
1838 {
1840 {
1841 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `skinning_loot_template`, ignoring.", cond->ToString());
1842 return false;
1843 }
1844
1846 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1847 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1848 {
1849 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, item does not exist, ignoring.", cond->ToString());
1850 return false;
1851 }
1852 break;
1853 }
1855 {
1857 {
1858 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `spell_loot_template`, ignoring.", cond->ToString());
1859 return false;
1860 }
1861
1863 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1864 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1865 {
1866 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, item does not exist, ignoring.", cond->ToString());
1867 return false;
1868 }
1869 break;
1870 }
1872 {
1873 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(cond->SourceEntry, DIFFICULTY_NONE);
1874 if (!spellInfo)
1875 {
1876 TC_LOG_ERROR("sql.sql", "{} SourceEntry in `condition` table does not exist in `Spell.db2`, ignoring.", cond->ToString());
1877 return false;
1878 }
1879
1880 if ((cond->SourceGroup > MAX_EFFECT_MASK) || !cond->SourceGroup)
1881 {
1882 TC_LOG_ERROR("sql.sql", "{} in `condition` table, has incorrect SourceGroup (spell effectMask) set, ignoring.", cond->ToString());
1883 return false;
1884 }
1885
1886 uint32 origGroup = cond->SourceGroup;
1887
1888 for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects())
1889 {
1890 if (!((1 << spellEffectInfo.EffectIndex) & cond->SourceGroup))
1891 continue;
1892
1893 if (spellEffectInfo.ChainTargets > 0)
1894 continue;
1895
1896 switch (spellEffectInfo.TargetA.GetSelectionCategory())
1897 {
1903 continue;
1904 default:
1905 break;
1906 }
1907
1908 switch (spellEffectInfo.TargetB.GetSelectionCategory())
1909 {
1915 continue;
1916 default:
1917 break;
1918 }
1919
1920 switch (spellEffectInfo.Effect)
1921 {
1932 continue;
1933 default:
1934 break;
1935 }
1936
1937 TC_LOG_ERROR("sql.sql", "SourceEntry {} SourceGroup {} in `condition` table - spell {} does not have implicit targets of types: _AREA_, _CONE_, _NEARBY_, __CHAIN__ or is not SPELL_EFFECT_PERSISTENT_AREA_AURA or SPELL_EFFECT_APPLY_AREA_AURA_* for effect {}, SourceGroup needs correction, ignoring.", cond->SourceEntry, origGroup, cond->SourceEntry, uint32(spellEffectInfo.EffectIndex));
1938 cond->SourceGroup &= ~(1 << spellEffectInfo.EffectIndex);
1939 }
1940 // all effects were removed, no need to add the condition at all
1941 if (!cond->SourceGroup)
1942 return false;
1943 break;
1944 }
1946 {
1947 if (!sObjectMgr->GetCreatureTemplate(cond->SourceEntry))
1948 {
1949 TC_LOG_ERROR("sql.sql", "{} SourceEntry in `condition` table, does not exist in `creature_template`, ignoring.", cond->ToString());
1950 return false;
1951 }
1952 break;
1953 }
1956 {
1957 SpellInfo const* spellProto = sSpellMgr->GetSpellInfo(cond->SourceEntry, DIFFICULTY_NONE);
1958 if (!spellProto)
1959 {
1960 TC_LOG_ERROR("sql.sql", "{} SourceEntry in `condition` table does not exist in `Spell.db2`, ignoring.", cond->ToString());
1961 return false;
1962 }
1963 break;
1964 }
1966 if (!sObjectMgr->GetQuestTemplate(cond->SourceEntry))
1967 {
1968 TC_LOG_ERROR("sql.sql", "{} SourceEntry specifies non-existing quest, skipped.", cond->ToString());
1969 return false;
1970 }
1971 break;
1973 if (!sObjectMgr->GetCreatureTemplate(cond->SourceGroup))
1974 {
1975 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `creature_template`, ignoring.", cond->ToString());
1976 return false;
1977 }
1978
1979 if (!sSpellMgr->GetSpellInfo(cond->SourceEntry, DIFFICULTY_NONE))
1980 {
1981 TC_LOG_ERROR("sql.sql", "{} SourceEntry in `condition` table does not exist in `Spell.db2`, ignoring.", cond->ToString());
1982 return false;
1983 }
1984 break;
1986 if (!sObjectMgr->GetCreatureTemplate(cond->SourceGroup))
1987 {
1988 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `creature_template`, ignoring.", cond->ToString());
1989 return false;
1990 }
1991
1992 if (!sSpellMgr->GetSpellInfo(cond->SourceEntry, DIFFICULTY_NONE))
1993 {
1994 TC_LOG_ERROR("sql.sql", "{} SourceEntry in `condition` table does not exist in `Spell.db2`, ignoring.", cond->ToString());
1995 return false;
1996 }
1997 break;
1999 {
2000 if (!sObjectMgr->GetCreatureTemplate(cond->SourceGroup))
2001 {
2002 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `creature_template`, ignoring.", cond->ToString());
2003 return false;
2004 }
2005 ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(cond->SourceEntry);
2006 if (!itemTemplate)
2007 {
2008 TC_LOG_ERROR("sql.sql", "{} SourceEntry in `condition` table, item does not exist, ignoring.", cond->ToString());
2009 return false;
2010 }
2011 break;
2012 }
2014 {
2015 if (!sMapStore.LookupEntry(cond->SourceEntry))
2016 {
2017 TC_LOG_ERROR("sql.sql", "{} SourceEntry in `condition` table, does not exist in Map.db2, ignoring.", cond->ToString());
2018 return false;
2019 }
2020 break;
2021 }
2023 {
2024 if (cond->SourceEntry && !sAreaTableStore.LookupEntry(cond->SourceEntry))
2025 {
2026 TC_LOG_ERROR("sql.sql", "{} SourceEntry in `condition` table, does not exist in AreaTable.db2, ignoring.", cond->ToString());
2027 return false;
2028 }
2029 break;
2030 }
2034 break;
2036 if (!sObjectMgr->FindGraveyardData(cond->SourceEntry, cond->SourceGroup))
2037 {
2038 TC_LOG_ERROR("sql.sql", "{} SourceEntry in `condition` table, does not exist in `graveyard_zone`, ignoring.", cond->ToString());
2039 return false;
2040 }
2041 break;
2043 if (cond->SourceEntry != 0 && cond->SourceEntry != 1)
2044 {
2045 TC_LOG_ERROR("sql.sql", "{} in `condition` table, unexpected SourceEntry value (expected 0 or 1), ignoring.", cond->ToString());
2046 return false;
2047 }
2048 if (!sAreaTriggerDataStore->GetAreaTriggerTemplate({ uint32(cond->SourceGroup), cond->SourceEntry == 1 }))
2049 {
2050 TC_LOG_ERROR("sql.sql", "{} in `condition` table, does not exist in `areatrigger_template`, ignoring.", cond->ToString());
2051 return false;
2052 }
2053 break;
2055 if (!sConversationDataStore->GetConversationLineTemplate(cond->SourceEntry))
2056 {
2057 TC_LOG_ERROR("sql.sql", "{} does not exist in `conversation_line_template`, ignoring.", cond->ToString());
2058 return false;
2059 }
2060 break;
2062 if (!sAreaTriggerStore.LookupEntry(cond->SourceEntry))
2063 {
2064 TC_LOG_ERROR("sql.sql", "{} SourceEntry in `condition` table, does not exists in AreaTrigger.db2, ignoring.", cond->ToString());
2065 return false;
2066 }
2067 break;
2069 {
2070 if (!sObjectMgr->GetTrainer(cond->SourceGroup))
2071 {
2072 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `trainer`, ignoring.", cond->ToString());
2073 return false;
2074 }
2075 if (!sSpellMgr->GetSpellInfo(cond->SourceEntry, DIFFICULTY_NONE))
2076 {
2077 TC_LOG_ERROR("sql.sql", "{} SourceEntry in `condition` table does not exist in `Spell.db2`, ignoring.", cond->ToString());
2078 return false;
2079 }
2080 break;
2081 }
2083 {
2084 if (cond->SourceGroup <= 0 || cond->SourceGroup >= NUM_CLIENT_OBJECT_TYPES)
2085 {
2086 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, is no valid object type, ignoring.", cond->ToString());
2087 return false;
2088 }
2089
2090 if (cond->SourceGroup == TYPEID_UNIT)
2091 {
2092 if (!sObjectMgr->GetCreatureTemplate(cond->SourceEntry))
2093 {
2094 TC_LOG_ERROR("sql.sql", "{} SourceEntry in `condition` table, does not exist in `creature_template`, ignoring.", cond->ToString());
2095 return false;
2096 }
2097 }
2098 else if (cond->SourceGroup == TYPEID_GAMEOBJECT)
2099 {
2100 if (!sObjectMgr->GetGameObjectTemplate(cond->SourceEntry))
2101 {
2102 TC_LOG_ERROR("sql.sql", "{} SourceEntry in `condition` table, does not exist in `gameobject_template`, ignoring.", cond->ToString());
2103 return false;
2104 }
2105 }
2106 else
2107 {
2108 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, uses unchecked type id, ignoring.", cond->ToString());
2109 return false;
2110 }
2111 break;
2112 }
2114 {
2115 SpawnGroupTemplateData const* spawnGroup = sObjectMgr->GetSpawnGroupData(cond->SourceEntry);
2116 if (!spawnGroup)
2117 {
2118 TC_LOG_ERROR("sql.sql", "{} SourceEntry in `condition` table, does not exist in `spawn_group_template`, ignoring.", cond->ToString());
2119 return false;
2120 }
2121 if (spawnGroup->flags & (SPAWNGROUP_FLAG_SYSTEM))
2122 {
2123 TC_LOG_ERROR("sql.sql", "{} in `spawn_group_template` table cannot have SPAWNGROUP_FLAG_SYSTEM flags, ignoring.", cond->ToString());
2124 return false;
2125 }
2126 break;
2127 }
2128 default:
2129 TC_LOG_ERROR("sql.sql", "{} Invalid ConditionSourceType in `condition` table, ignoring.", cond->ToString());
2130 return false;
2131 }
2132
2133 return true;
2134}
2135
2137{
2138 switch (cond->ConditionType)
2139 {
2140 case CONDITION_AURA:
2141 {
2142 if (!sSpellMgr->GetSpellInfo(cond->ConditionValue1, DIFFICULTY_NONE))
2143 {
2144 TC_LOG_ERROR("sql.sql", "{} has non existing spell (Id: {}), skipped.", cond->ToString(true), cond->ConditionValue1);
2145 return false;
2146 }
2147
2149 {
2150 TC_LOG_ERROR("sql.sql", "{} has non existing effect index ({}) (must be 0..{}), skipped.", cond->ToString(true), cond->ConditionValue2, MAX_SPELL_EFFECTS - 1);
2151 return false;
2152 }
2153 break;
2154 }
2155 case CONDITION_ITEM:
2156 {
2157 ItemTemplate const* proto = sObjectMgr->GetItemTemplate(cond->ConditionValue1);
2158 if (!proto)
2159 {
2160 TC_LOG_ERROR("sql.sql", "{} Item ({}) does not exist, skipped.", cond->ToString(true), cond->ConditionValue1);
2161 return false;
2162 }
2163
2164 if (!cond->ConditionValue2)
2165 {
2166 TC_LOG_ERROR("sql.sql", "{} Zero item count in ConditionValue2, skipped.", cond->ToString(true));
2167 return false;
2168 }
2169 break;
2170 }
2172 {
2173 ItemTemplate const* proto = sObjectMgr->GetItemTemplate(cond->ConditionValue1);
2174 if (!proto)
2175 {
2176 TC_LOG_ERROR("sql.sql", "{} Item ({}) does not exist, skipped.", cond->ToString(true), cond->ConditionValue1);
2177 return false;
2178 }
2179 break;
2180 }
2181 case CONDITION_ZONEID:
2182 {
2183 AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(cond->ConditionValue1);
2184 if (!areaEntry)
2185 {
2186 TC_LOG_ERROR("sql.sql", "{} Area ({}) does not exist, skipped.", cond->ToString(true), cond->ConditionValue1);
2187 return false;
2188 }
2189
2190 if (areaEntry->ParentAreaID != 0 && areaEntry->GetFlags().HasFlag(AreaFlags::IsSubzone))
2191 {
2192 TC_LOG_ERROR("sql.sql", "{} requires to be in area ({}) which is a subzone but zone expected, skipped.", cond->ToString(true), cond->ConditionValue1);
2193 return false;
2194 }
2195 break;
2196 }
2198 {
2199 FactionEntry const* factionEntry = sFactionStore.LookupEntry(cond->ConditionValue1);
2200 if (!factionEntry)
2201 {
2202 TC_LOG_ERROR("sql.sql", "{} has non existing faction ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2203 return false;
2204 }
2205 break;
2206 }
2207 case CONDITION_TEAM:
2208 {
2209 if (cond->ConditionValue1 != ALLIANCE && cond->ConditionValue1 != HORDE)
2210 {
2211 TC_LOG_ERROR("sql.sql", "{} specifies unknown team ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2212 return false;
2213 }
2214 break;
2215 }
2216 case CONDITION_SKILL:
2217 {
2218 SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(cond->ConditionValue1);
2219 if (!pSkill)
2220 {
2221 TC_LOG_ERROR("sql.sql", "{} specifies non-existing skill ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2222 return false;
2223 }
2224
2225 if (cond->ConditionValue2 < 1 || cond->ConditionValue2 > sWorld->GetConfigMaxSkillValue())
2226 {
2227 TC_LOG_ERROR("sql.sql", "{} specifies skill ({}) with invalid value ({}), skipped.", cond->ToString(true), cond->ConditionValue1, cond->ConditionValue2);
2228 return false;
2229 }
2230 break;
2231 }
2233 if (cond->ConditionValue2 >= (1 << MAX_QUEST_STATUS))
2234 {
2235 TC_LOG_ERROR("sql.sql", "{} has invalid state mask ({}), skipped.", cond->ToString(true), cond->ConditionValue2);
2236 return false;
2237 }
2238 [[fallthrough]];
2244 {
2245 if (!sObjectMgr->GetQuestTemplate(cond->ConditionValue1))
2246 {
2247 TC_LOG_ERROR("sql.sql", "{} points to non-existing quest ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2248 return false;
2249 }
2250 break;
2251 }
2253 {
2254 GameEventMgr::GameEventDataMap const& events = sGameEventMgr->GetEventMap();
2255 if (cond->ConditionValue1 >= events.size() || !events[cond->ConditionValue1].isValid())
2256 {
2257 TC_LOG_ERROR("sql.sql", "{} has non existing event id ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2258 return false;
2259 }
2260 break;
2261 }
2263 {
2264 AchievementEntry const* achievement = sAchievementStore.LookupEntry(cond->ConditionValue1);
2265 if (!achievement)
2266 {
2267 TC_LOG_ERROR("sql.sql", "{} has non existing achivement id ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2268 return false;
2269 }
2270 break;
2271 }
2272 case CONDITION_CLASS:
2273 {
2275 {
2276 TC_LOG_ERROR("sql.sql", "{} has non existing classmask ({}), skipped.", cond->ToString(true), cond->ConditionValue1 & ~CLASSMASK_ALL_PLAYABLE);
2277 return false;
2278 }
2279 break;
2280 }
2281 case CONDITION_RACE:
2282 {
2283 Trinity::RaceMask<uint64> invalidRaceMask = Trinity::RaceMask<uint64>{ cond->ConditionValue1 } & ~RACEMASK_ALL_PLAYABLE;
2284 if (!invalidRaceMask.IsEmpty()) // uint32 works thanks to weird index remapping in racemask
2285 {
2286 TC_LOG_ERROR("sql.sql", "{} has non existing racemask ({}), skipped.", cond->ToString(true), invalidRaceMask.RawValue);
2287 return false;
2288 }
2289 break;
2290 }
2291 case CONDITION_GENDER:
2292 {
2294 {
2295 TC_LOG_ERROR("sql.sql", "{} has invalid gender ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2296 return false;
2297 }
2298 break;
2299 }
2300 case CONDITION_MAPID:
2301 {
2302 MapEntry const* me = sMapStore.LookupEntry(cond->ConditionValue1);
2303 if (!me)
2304 {
2305 TC_LOG_ERROR("sql.sql", "{} has non existing map ({}), skipped", cond->ToString(true), cond->ConditionValue1);
2306 return false;
2307 }
2308 break;
2309 }
2310 case CONDITION_SPELL:
2311 {
2312 if (!sSpellMgr->GetSpellInfo(cond->ConditionValue1, DIFFICULTY_NONE))
2313 {
2314 TC_LOG_ERROR("sql.sql", "{} has non existing spell (Id: {}), skipped", cond->ToString(true), cond->ConditionValue1);
2315 return false;
2316 }
2317 break;
2318 }
2319 case CONDITION_LEVEL:
2320 {
2321 if (cond->ConditionValue2 >= COMP_TYPE_MAX)
2322 {
2323 TC_LOG_ERROR("sql.sql", "{} has invalid ComparisionType ({}), skipped.", cond->ToString(true), cond->ConditionValue2);
2324 return false;
2325 }
2326 break;
2327 }
2329 {
2330 if (cond->ConditionValue1 > DRUNKEN_SMASHED)
2331 {
2332 TC_LOG_ERROR("sql.sql", "{} has invalid state ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2333 return false;
2334 }
2335 break;
2336 }
2338 {
2339 if (!sObjectMgr->GetCreatureTemplate(cond->ConditionValue1))
2340 {
2341 TC_LOG_ERROR("sql.sql", "{} has non existing creature template entry ({}), skipped", cond->ToString(true), cond->ConditionValue1);
2342 return false;
2343 }
2344 break;
2345 }
2347 {
2348 if (!sObjectMgr->GetGameObjectTemplate(cond->ConditionValue1))
2349 {
2350 TC_LOG_ERROR("sql.sql", "{} has non existing gameobject template entry ({}), skipped.", cond->ToString(), cond->ConditionValue1);
2351 return false;
2352 }
2353 break;
2354 }
2358 [[fallthrough]];
2360 {
2361 switch (cond->ConditionValue1)
2362 {
2363 case TYPEID_UNIT:
2364 if (cond->ConditionValue2 && !sObjectMgr->GetCreatureTemplate(cond->ConditionValue2))
2365 {
2366 TC_LOG_ERROR("sql.sql", "{} has non existing creature template entry ({}), skipped.", cond->ToString(true), cond->ConditionValue2);
2367 return false;
2368 }
2369 if (cond->ConditionValue3)
2370 {
2371 if (CreatureData const* creatureData = sObjectMgr->GetCreatureData(cond->ConditionValue3))
2372 {
2373 if (cond->ConditionValue2 && creatureData->id != cond->ConditionValue2)
2374 {
2375 TC_LOG_ERROR("sql.sql", "{} has guid {} set but does not match creature entry ({}), skipped.", cond->ToString(true), cond->ConditionValue3, cond->ConditionValue2);
2376 return false;
2377 }
2378 }
2379 else
2380 {
2381 TC_LOG_ERROR("sql.sql", "{} has non existing creature guid ({}), skipped.", cond->ToString(true), cond->ConditionValue3);
2382 return false;
2383 }
2384 }
2385 break;
2386 case TYPEID_GAMEOBJECT:
2387 if (cond->ConditionValue2 && !sObjectMgr->GetGameObjectTemplate(cond->ConditionValue2))
2388 {
2389 TC_LOG_ERROR("sql.sql", "{} has non existing gameobject template entry ({}), skipped.", cond->ToString(true), cond->ConditionValue2);
2390 return false;
2391 }
2392 if (cond->ConditionValue3)
2393 {
2394 if (GameObjectData const* goData = sObjectMgr->GetGameObjectData(cond->ConditionValue3))
2395 {
2396 if (cond->ConditionValue2 && goData->id != cond->ConditionValue2)
2397 {
2398 TC_LOG_ERROR("sql.sql", "{} has guid {} set but does not match gameobject entry ({}), skipped.", cond->ToString(true), cond->ConditionValue3, cond->ConditionValue2);
2399 return false;
2400 }
2401 }
2402 else
2403 {
2404 TC_LOG_ERROR("sql.sql", "{} has non existing gameobject guid ({}), skipped.", cond->ToString(true), cond->ConditionValue3);
2405 return false;
2406 }
2407 }
2408 break;
2409 case TYPEID_PLAYER:
2410 case TYPEID_CORPSE:
2411 if (cond->ConditionValue2)
2413 if (cond->ConditionValue3)
2415 break;
2416 default:
2417 TC_LOG_ERROR("sql.sql", "{} has wrong typeid set ({}), skipped", cond->ToString(true), cond->ConditionValue1);
2418 return false;
2419 }
2420 break;
2421 }
2425 [[fallthrough]];
2427 {
2429 {
2430 TC_LOG_ERROR("sql.sql", "{} has invalid typemask set ({}), skipped.", cond->ToString(true), cond->ConditionValue2);
2431 return false;
2432 }
2433 break;
2434 }
2436 {
2438 {
2439 TC_LOG_ERROR("sql.sql", "{} has invalid ConditionValue1(ConditionTarget selection) ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2440 return false;
2441 }
2442 if (cond->ConditionValue1 == cond->ConditionTarget)
2443 {
2444 TC_LOG_ERROR("sql.sql", "{} has ConditionValue1(ConditionTarget selection) set to self ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2445 return false;
2446 }
2447 if (cond->ConditionValue2 >= RELATION_MAX)
2448 {
2449 TC_LOG_ERROR("sql.sql", "{} has invalid ConditionValue2(RelationType) ({}), skipped.", cond->ToString(true), cond->ConditionValue2);
2450 return false;
2451 }
2452 break;
2453 }
2455 {
2457 {
2458 TC_LOG_ERROR("sql.sql", "{} has invalid ConditionValue1(ConditionTarget selection) ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2459 return false;
2460 }
2461 if (cond->ConditionValue1 == cond->ConditionTarget)
2462 {
2463 TC_LOG_ERROR("sql.sql", "{} has ConditionValue1(ConditionTarget selection) set to self ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2464 return false;
2465 }
2466 if (!cond->ConditionValue2)
2467 {
2468 TC_LOG_ERROR("sql.sql", "{} has invalid ConditionValue2(rankMask) ({}), skipped.", cond->ToString(true), cond->ConditionValue2);
2469 return false;
2470 }
2471 break;
2472 }
2474 {
2476 {
2477 TC_LOG_ERROR("sql.sql", "{} has invalid ConditionValue1(ConditionTarget selection) ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2478 return false;
2479 }
2480 if (cond->ConditionValue1 == cond->ConditionTarget)
2481 {
2482 TC_LOG_ERROR("sql.sql", "{} has ConditionValue1(ConditionTarget selection) set to self ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2483 return false;
2484 }
2485 if (cond->ConditionValue3 >= COMP_TYPE_MAX)
2486 {
2487 TC_LOG_ERROR("sql.sql", "{} has invalid ComparisionType ({}), skipped.", cond->ToString(true), cond->ConditionValue3);
2488 return false;
2489 }
2490 break;
2491 }
2492 case CONDITION_HP_VAL:
2493 {
2494 if (cond->ConditionValue2 >= COMP_TYPE_MAX)
2495 {
2496 TC_LOG_ERROR("sql.sql", "{} has invalid ComparisionType ({}), skipped.", cond->ToString(true), cond->ConditionValue2);
2497 return false;
2498 }
2499 break;
2500 }
2501 case CONDITION_HP_PCT:
2502 {
2503 if (cond->ConditionValue1 > 100)
2504 {
2505 TC_LOG_ERROR("sql.sql", "{} has too big percent value ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2506 return false;
2507 }
2508 if (cond->ConditionValue2 >= COMP_TYPE_MAX)
2509 {
2510 TC_LOG_ERROR("sql.sql", "{} has invalid ComparisionType ({}), skipped.", cond->ToString(true), cond->ConditionValue2);
2511 return false;
2512 }
2513 break;
2514 }
2516 {
2517 if (!sWorldStateMgr->GetWorldStateTemplate(cond->ConditionValue1))
2518 {
2519 TC_LOG_ERROR("sql.sql", "{} has non existing world state in value1 ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2520 return false;
2521 }
2522 break;
2523 }
2524 case CONDITION_PHASEID:
2525 {
2526 if (!sPhaseStore.LookupEntry(cond->ConditionValue1))
2527 {
2528 TC_LOG_ERROR("sql.sql", "{} has nonexistent phaseid in value1 ({}), skipped", cond->ToString(true), cond->ConditionValue1);
2529 return false;
2530 }
2531 break;
2532 }
2533 case CONDITION_TITLE:
2534 {
2535 CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(cond->ConditionValue1);
2536 if (!titleEntry)
2537 {
2538 TC_LOG_ERROR("sql.sql", "{} has non existing title in value1 ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2539 return false;
2540 }
2541 break;
2542 }
2544 {
2545 TC_LOG_ERROR("sql.sql", "{} using deprecated condition type CONDITION_SPAWNMASK.", cond->ToString(true));
2546 return false;
2547 }
2549 {
2551 {
2552 TC_LOG_ERROR("sql.sql", "{} has non existing UnitState in value1 ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2553 return false;
2554 }
2555 break;
2556 }
2558 {
2560 {
2561 TC_LOG_ERROR("sql.sql", "{} has non existing CreatureType in value1 ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2562 return false;
2563 }
2564 break;
2565 }
2567 {
2568 AchievementEntry const* achievement = sAchievementStore.LookupEntry(cond->ConditionValue1);
2569 if (!achievement)
2570 {
2571 TC_LOG_ERROR("sql.sql", "{} has non existing realm first achivement id ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2572 return false;
2573 }
2574 break;
2575 }
2577 {
2578 bool valid = false;
2579 switch (cond->ConditionValue1)
2580 {
2581 case 0:
2583 break;
2584 case 1:
2585 valid = cond->ConditionValue2 <= 1;
2586 break;
2587 default:
2588 valid = false;
2589 break;
2590 }
2591 if (!valid)
2592 {
2593 TC_LOG_ERROR("sql.sql", "{} has non-existing stand state ({},{}), skipped.", cond->ToString(true), cond->ConditionValue1, cond->ConditionValue2);
2594 return false;
2595 }
2596 break;
2597 }
2599 {
2600 QuestObjective const* obj = sObjectMgr->GetQuestObjective(cond->ConditionValue1);
2601 if (!obj)
2602 {
2603 TC_LOG_ERROR("sql.sql", "{} points to non-existing quest objective ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2604 return false;
2605 }
2606 int32 limit = obj->IsStoringFlag() ? 1 : obj->Amount;
2607 if (int32(cond->ConditionValue3) > limit)
2608 {
2609 TC_LOG_ERROR("sql.sql", "{} has quest objective count {} in value3, but quest objective {} has a maximum objective count of {}, skipped.", cond->ToString(true), cond->ConditionValue3, cond->ConditionValue1, limit);
2610 return false;
2611 }
2612 break;
2613 }
2614 case CONDITION_PET_TYPE:
2615 if (cond->ConditionValue1 >= (1 << MAX_PET_TYPE))
2616 {
2617 TC_LOG_ERROR("sql.sql", "{} has non-existing pet type {}, skipped.", cond->ToString(true), cond->ConditionValue1);
2618 return false;
2619 }
2620 break;
2623 {
2624 TC_LOG_ERROR("sql.sql", "{} has unsupported ConditionValue3 {} (INSTANCE_INFO_GUID_DATA), skipped.", cond->ToString(true), cond->ConditionValue3);
2625 return false;
2626 }
2627 break;
2628 case CONDITION_AREAID:
2629 case CONDITION_ALIVE:
2630 case CONDITION_IN_WATER:
2632 case CONDITION_CHARMED:
2633 case CONDITION_TAXI:
2636 break;
2638 if (!sDifficultyStore.LookupEntry(cond->ConditionValue1))
2639 {
2640 TC_LOG_ERROR("sql.sql", "{} has non existing difficulty in value1 ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2641 return false;
2642 }
2643 break;
2645 if (!sBattlePetSpeciesStore.LookupEntry(cond->ConditionValue1))
2646 {
2647 TC_LOG_ERROR("sql.sql", "{} has non existing BattlePet SpeciesId in value1 ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2648 return false;
2649 }
2651 {
2652 TC_LOG_ERROR("sql.sql", "{} has invalid (greater than {}) value2 ({}), skipped.", cond->ToString(true),
2654 return false;
2655 }
2656 if (cond->ConditionValue3 >= COMP_TYPE_MAX)
2657 {
2658 TC_LOG_ERROR("sql.sql", "{} has invalid ComparisionType ({}), skipped.", cond->ToString(true), cond->ConditionValue3);
2659 return false;
2660 }
2661 break;
2663 {
2664 if (!sScenarioStepStore.LookupEntry(cond->ConditionValue1))
2665 {
2666 TC_LOG_ERROR("sql.sql", "{} has non existing ScenarioStep in value1 ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2667 return false;
2668 }
2669 break;
2670 }
2672 {
2673 if (!sSceneScriptPackageStore.LookupEntry(cond->ConditionValue1))
2674 {
2675 TC_LOG_ERROR("sql.sql", "{} has non existing SceneScriptPackageId in value1 ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2676 return false;
2677 }
2678 break;
2679 }
2681 {
2682 if (!sPlayerConditionStore.LookupEntry(cond->ConditionValue1))
2683 {
2684 TC_LOG_ERROR("sql.sql", "{} has non existing PlayerConditionId in value1 ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2685 return false;
2686 }
2687 break;
2688 }
2689 default:
2690 TC_LOG_ERROR("sql.sql", "{} Invalid ConditionType in `condition` table, ignoring.", cond->ToString());
2691 return false;
2692 }
2693
2695 {
2696 TC_LOG_ERROR("sql.sql", "{} in `condition` table, has incorrect ConditionTarget set, ignoring.", cond->ToString(true));
2697 return false;
2698 }
2699
2708
2709 return true;
2710}
2711
2713{
2714 TC_LOG_ERROR("sql.sql", "{} has useless data in ConditionValue{} ({})!", cond->ToString(true), index, value);
2715}
2716
2717void ConditionMgr::LogUselessConditionValue(Condition const* cond, uint8 index, std::string_view value)
2718{
2719 TC_LOG_ERROR("sql.sql", "{} has useless data in ConditionStringValue{} ({})!", cond->ToString(true), index, value);
2720}
2721
2723{
2724 for (std::unordered_map<ConditionId, std::shared_ptr<std::vector<Condition>>>& conditionsMap : ConditionStore)
2725 conditionsMap.clear();
2726
2728}
2729
2730inline bool PlayerConditionCompare(int32 comparisonType, int32 value1, int32 value2)
2731{
2732 switch (comparisonType)
2733 {
2734 case 1:
2735 return value1 == value2;
2736 case 2:
2737 return value1 != value2;
2738 case 3:
2739 return value1 > value2;
2740 case 4:
2741 return value1 >= value2;
2742 case 5:
2743 return value1 < value2;
2744 case 6:
2745 return value1 <= value2;
2746 default:
2747 break;
2748 }
2749 return false;
2750}
2751
2752template<std::size_t N>
2753inline bool PlayerConditionLogic(uint32 logic, std::array<bool, N>& results)
2754{
2755 static_assert(N < 16, "Logic array size must be equal to or less than 16");
2756
2757 for (std::size_t i = 0; i < results.size(); ++i)
2758 if ((logic >> (16 + i)) & 1)
2759 results[i] ^= true;
2760
2761 bool result = results[0];
2762 for (std::size_t i = 1; i < results.size(); ++i)
2763 {
2764 switch ((logic >> (2 * (i - 1))) & 3)
2765 {
2766 case 1:
2767 result = result && results[i];
2768 break;
2769 case 2:
2770 result = result || results[i];
2771 break;
2772 default:
2773 break;
2774 }
2775 }
2776
2777 return result;
2778}
2779
2781{
2782 Group const* group = player->GetGroup();
2783 if (!group)
2784 return 0;
2785
2786 switch (status)
2787 {
2789 return sLFGMgr->inLfgDungeonMap(player->GetGUID(), player->GetMapId(), player->GetMap()->GetDifficultyID()) ? 1 : 0;
2791 return sLFGMgr->inLfgDungeonMap(player->GetGUID(), player->GetMapId(), player->GetMap()->GetDifficultyID()) &&
2792 sLFGMgr->selectedRandomLfgDungeon(player->GetGUID()) ? 1 : 0;
2794 {
2795 if (!sLFGMgr->inLfgDungeonMap(player->GetGUID(), player->GetMapId(), player->GetMap()->GetDifficultyID()))
2796 return 0;
2797
2798 uint32 selectedRandomDungeon = sLFGMgr->GetSelectedRandomDungeon(player->GetGUID());
2799 if (!selectedRandomDungeon)
2800 return 0;
2801
2802 if (lfg::LfgReward const* reward = sLFGMgr->GetRandomDungeonReward(selectedRandomDungeon, player->GetLevel()))
2803 if (Quest const* quest = sObjectMgr->GetQuestTemplate(reward->firstQuest))
2804 if (player->CanRewardQuest(quest, false))
2805 return 1;
2806 return 0;
2807 }
2809 break;
2811 break;
2813 break;
2815 break;
2817 break;
2818 default:
2819 break;
2820 }
2821
2822 return 0;
2823}
2824
2826{
2827 if (Optional<ContentTuningLevels> levels = sDB2Manager.GetContentTuningData(condition->ContentTuningID, player->m_playerData->CtrOptions->ContentTuningConditionMask))
2828 {
2829 uint8 minLevel = condition->Flags & 0x800 ? levels->MinLevelWithDelta : levels->MinLevel;
2830 uint8 maxLevel = 0;
2831 if (!(condition->Flags & 0x20))
2832 maxLevel = condition->Flags & 0x800 ? levels->MaxLevelWithDelta : levels->MaxLevel;
2833
2834 if (condition->Flags & 0x80)
2835 {
2836 if (minLevel && player->GetLevel() >= minLevel && (!maxLevel || player->GetLevel() <= maxLevel))
2837 return false;
2838
2839 if (maxLevel && player->GetLevel() <= maxLevel && (!minLevel || player->GetLevel() >= minLevel))
2840 return false;
2841 }
2842 else
2843 {
2844 if (minLevel && player->GetLevel() < minLevel)
2845 return false;
2846
2847 if (maxLevel && player->GetLevel() > maxLevel)
2848 return false;
2849 }
2850 }
2851
2852 if (!condition->RaceMask.IsEmpty() && !condition->RaceMask.HasRace(player->GetRace()))
2853 return false;
2854
2855 if (condition->ClassMask && !(player->GetClassMask() & condition->ClassMask))
2856 return false;
2857
2858 if (condition->Gender >= 0 && player->GetGender() != condition->Gender)
2859 return false;
2860
2861 if (condition->NativeGender >= 0 && player->GetNativeGender() != condition->NativeGender)
2862 return false;
2863
2864 if (condition->PowerType != -1 && condition->PowerTypeComp)
2865 {
2866 int32 requiredPowerValue = condition->Flags & 4 ? player->GetMaxPower(Powers(condition->PowerType)) : condition->PowerTypeValue;
2867 if (!PlayerConditionCompare(condition->PowerTypeComp, player->GetPower(Powers(condition->PowerType)), requiredPowerValue))
2868 return false;
2869 }
2870
2871 if (condition->ChrSpecializationIndex >= 0 || condition->ChrSpecializationRole >= 0)
2872 {
2874 {
2875 if (condition->ChrSpecializationIndex >= 0 && spec->OrderIndex != condition->ChrSpecializationIndex)
2876 return false;
2877
2878 if (condition->ChrSpecializationRole >= 0 && spec->Role != condition->ChrSpecializationRole)
2879 return false;
2880 }
2881 }
2882
2883 if (condition->SkillID[0] || condition->SkillID[1] || condition->SkillID[2] || condition->SkillID[3])
2884 {
2885 std::array<bool, std::tuple_size_v<decltype(condition->SkillID)>> results;
2886 results.fill(true);
2887 for (std::size_t i = 0; i < condition->SkillID.size(); ++i)
2888 {
2889 if (condition->SkillID[i])
2890 {
2891 uint16 skillValue = player->GetSkillValue(condition->SkillID[i]);
2892 results[i] = skillValue != 0 && skillValue > condition->MinSkill[i] && skillValue < condition->MaxSkill[i];
2893 }
2894 }
2895
2896 if (!PlayerConditionLogic(condition->SkillLogic, results))
2897 return false;
2898 }
2899
2900 if (condition->LanguageID)
2901 {
2902 int32 languageSkill = 0;
2904 languageSkill = 300;
2905 else
2906 {
2907 for (std::pair<uint32 const, LanguageDesc> const& languageDesc : sLanguageMgr->GetLanguageDescById(Language(condition->LanguageID)))
2908 languageSkill = std::max<int32>(languageSkill, player->GetSkillValue(languageDesc.second.SkillId));
2909 }
2910
2911 if (condition->MinLanguage && languageSkill < condition->MinLanguage)
2912 return false;
2913
2914 if (condition->MaxLanguage && languageSkill > condition->MaxLanguage)
2915 return false;
2916 }
2917
2918 if (condition->MinFactionID[0] || condition->MinFactionID[1] || condition->MinFactionID[2] || condition->MaxFactionID)
2919 {
2920 if (!condition->MinFactionID[0] && !condition->MinFactionID[1] && !condition->MinFactionID[2])
2921 {
2922 if (ReputationRank const* forcedRank = player->GetReputationMgr().GetForcedRankIfAny(condition->MaxFactionID))
2923 {
2924 if (*forcedRank > ReputationRank(condition->MaxReputation))
2925 return false;
2926 }
2927 else if (sFactionStore.HasRecord(condition->MaxReputation) && player->GetReputationRank(condition->MaxFactionID) > ReputationRank(condition->MaxReputation))
2928 return false;
2929 }
2930 else
2931 {
2932 std::array<bool, std::tuple_size_v<decltype(condition->MinFactionID)> + 1> results;
2933 results.fill(true);
2934 for (std::size_t i = 0; i < condition->MinFactionID.size(); ++i)
2935 {
2936 if (sFactionStore.HasRecord(condition->MinFactionID[i]))
2937 {
2938 if (ReputationRank const* forcedRank = player->GetReputationMgr().GetForcedRankIfAny(condition->MinFactionID[i]))
2939 results[i] = *forcedRank >= ReputationRank(condition->MinReputation[i]);
2940 else
2941 results[i] = player->GetReputationRank(condition->MinFactionID[i]) >= ReputationRank(condition->MinReputation[i]);
2942 }
2943 }
2944
2945 if (ReputationRank const* forcedRank = player->GetReputationMgr().GetForcedRankIfAny(condition->MaxFactionID))
2946 results[3] = *forcedRank <= ReputationRank(condition->MaxReputation);
2947 else if (sFactionStore.HasRecord(condition->MaxReputation))
2948 results[3] = player->GetReputationRank(condition->MaxFactionID) <= ReputationRank(condition->MaxReputation);
2949
2950 if (!PlayerConditionLogic(condition->ReputationLogic, results))
2951 return false;
2952 }
2953 }
2954
2955 if (condition->CurrentPvpFaction)
2956 {
2957 int8 team;
2958 if (player->GetMap()->IsBattlegroundOrArena())
2959 team = player->m_playerData->ArenaFaction;
2960 else
2961 team = player->GetTeamId();
2962
2963 if (condition->CurrentPvpFaction - 1 != team)
2964 return false;
2965 }
2966
2967 if (condition->PvpMedal && !((1 << (condition->PvpMedal - 1)) & *player->m_activePlayerData->PvpMedals))
2968 return false;
2969
2970 if (condition->LifetimeMaxPVPRank && player->m_activePlayerData->LifetimeMaxRank != condition->LifetimeMaxPVPRank)
2971 return false;
2972
2973 if (condition->MovementFlags[0] && !(player->GetUnitMovementFlags() & condition->MovementFlags[0]))
2974 return false;
2975
2976 if (condition->MovementFlags[1] && !(player->GetExtraUnitMovementFlags() & condition->MovementFlags[1]))
2977 return false;
2978
2979 if (condition->WeaponSubclassMask)
2980 {
2982 if (!mainHand || !((1 << mainHand->GetTemplate()->GetSubClass()) & condition->WeaponSubclassMask))
2983 return false;
2984 }
2985
2986 if (condition->PartyStatus)
2987 {
2988 Group const* group = player->GetGroup();
2989 switch (condition->PartyStatus)
2990 {
2991 case 1:
2992 if (group)
2993 return false;
2994 break;
2995 case 2:
2996 if (!group)
2997 return false;
2998 break;
2999 case 3:
3000 if (!group || group->isRaidGroup())
3001 return false;
3002 break;
3003 case 4:
3004 if (!group || !group->isRaidGroup())
3005 return false;
3006 break;
3007 case 5:
3008 if (group && group->isRaidGroup())
3009 return false;
3010 break;
3011 default:
3012 break;
3013 }
3014 }
3015
3016 if (condition->PrevQuestID[0])
3017 {
3018 std::array<bool, std::tuple_size_v<decltype(condition->PrevQuestID)>> results;
3019 results.fill(true);
3020 for (std::size_t i = 0; i < condition->PrevQuestID.size(); ++i)
3021 if (uint32 questBit = sDB2Manager.GetQuestUniqueBitFlag(condition->PrevQuestID[i]))
3022 results[i] = (player->m_activePlayerData->QuestCompleted[((questBit - 1) >> 6)] & (UI64LIT(1) << ((questBit - 1) & 63))) != 0;
3023
3024 if (!PlayerConditionLogic(condition->PrevQuestLogic, results))
3025 return false;
3026 }
3027
3028 if (condition->CurrQuestID[0])
3029 {
3030 std::array<bool, std::tuple_size_v<decltype(condition->CurrQuestID)>> results;
3031 results.fill(true);
3032 for (std::size_t i = 0; i < condition->CurrQuestID.size(); ++i)
3033 if (condition->CurrQuestID[i])
3034 results[i] = player->FindQuestSlot(condition->CurrQuestID[i]) != MAX_QUEST_LOG_SIZE;
3035
3036 if (!PlayerConditionLogic(condition->CurrQuestLogic, results))
3037 return false;
3038 }
3039
3040 if (condition->CurrentCompletedQuestID[0])
3041 {
3042 std::array<bool, std::tuple_size_v<decltype(condition->CurrentCompletedQuestID)>> results;
3043 results.fill(true);
3044 for (std::size_t i = 0; i < condition->CurrentCompletedQuestID.size(); ++i)
3045 if (condition->CurrentCompletedQuestID[i])
3046 results[i] = player->GetQuestStatus(condition->CurrentCompletedQuestID[i]) == QUEST_STATUS_COMPLETE;
3047
3048 if (!PlayerConditionLogic(condition->CurrentCompletedQuestLogic, results))
3049 return false;
3050 }
3051
3052 if (condition->SpellID[0])
3053 {
3054 std::array<bool, std::tuple_size_v<decltype(condition->SpellID)>> results;
3055 results.fill(true);
3056 for (std::size_t i = 0; i < condition->SpellID.size(); ++i)
3057 if (condition->SpellID[i])
3058 results[i] = player->HasSpell(condition->SpellID[i]);
3059
3060 if (!PlayerConditionLogic(condition->SpellLogic, results))
3061 return false;
3062 }
3063
3064 if (condition->ItemID[0])
3065 {
3066 std::array<bool, std::tuple_size_v<decltype(condition->ItemID)>> results;
3067 results.fill(true);
3068 for (std::size_t i = 0; i < condition->ItemID.size(); ++i)
3069 if (condition->ItemID[i])
3070 results[i] = player->GetItemCount(condition->ItemID[i], condition->ItemFlags != 0) >= condition->ItemCount[i];
3071
3072 if (!PlayerConditionLogic(condition->ItemLogic, results))
3073 return false;
3074 }
3075
3076 if (condition->CurrencyID[0])
3077 {
3078 std::array<bool, std::tuple_size_v<decltype(condition->CurrencyID)>> results;
3079 results.fill(true);
3080 for (std::size_t i = 0; i < condition->CurrencyID.size(); ++i)
3081 if (condition->CurrencyID[i])
3082 results[i] = player->GetCurrencyQuantity(condition->CurrencyID[i]) >= condition->CurrencyCount[i];
3083
3084 if (!PlayerConditionLogic(condition->CurrencyLogic, results))
3085 return false;
3086 }
3087
3088 if (condition->Explored[0] || condition->Explored[1])
3089 {
3090 for (std::size_t i = 0; i < condition->Explored.size(); ++i)
3091 if (AreaTableEntry const* area = sAreaTableStore.LookupEntry(condition->Explored[i]))
3092 if (!player->HasExploredZone(area->ID))
3093 return false;
3094 }
3095
3096 if (condition->AuraSpellID[0])
3097 {
3098 std::array<bool, std::tuple_size_v<decltype(condition->AuraSpellID)>> results;
3099 results.fill(true);
3100 for (std::size_t i = 0; i < condition->AuraSpellID.size(); ++i)
3101 {
3102 if (condition->AuraSpellID[i])
3103 {
3104 if (condition->AuraStacks[i])
3105 results[i] = player->GetAuraCount(condition->AuraSpellID[i]) >= condition->AuraStacks[i];
3106 else
3107 results[i] = player->HasAura(condition->AuraSpellID[i]);
3108 }
3109 }
3110
3111 if (!PlayerConditionLogic(condition->AuraSpellLogic, results))
3112 return false;
3113 }
3114
3115 if (condition->Time[0])
3116 {
3117 WowTime time0;
3118 time0.SetPackedTime(condition->Time[0]);
3119
3120 if (condition->Time[1])
3121 {
3122 WowTime time1;
3123 time1.SetPackedTime(condition->Time[1]);
3124
3125 if (!GameTime::GetWowTime()->IsInRange(time0, time1))
3126 return false;
3127 }
3128 else if (*GameTime::GetWowTime() != time0)
3129 return false;
3130 }
3131
3132 if (condition->WorldStateExpressionID)
3133 {
3134 WorldStateExpressionEntry const* worldStateExpression = sWorldStateExpressionStore.LookupEntry(condition->WorldStateExpressionID);
3135 if (!worldStateExpression)
3136 return false;
3137
3138 if (!IsMeetingWorldStateExpression(player->GetMap(), worldStateExpression))
3139 return false;
3140 }
3141
3142 if (condition->WeatherID)
3143 if (player->GetMap()->GetZoneWeather(player->GetZoneId()) != WeatherState(condition->WeatherID))
3144 return false;
3145
3146 if (condition->Achievement[0])
3147 {
3148 std::array<bool, std::tuple_size_v<decltype(condition->Achievement)>> results;
3149 results.fill(true);
3150 for (std::size_t i = 0; i < condition->Achievement.size(); ++i)
3151 {
3152 if (condition->Achievement[i])
3153 {
3154 // if (condition->Flags & 2) { any character on account completed it } else { current character only }
3155 // TODO: part of accountwide achievements
3156 results[i] = player->HasAchieved(condition->Achievement[i]);
3157 }
3158 }
3159
3160 if (!PlayerConditionLogic(condition->AchievementLogic, results))
3161 return false;
3162 }
3163
3164 if (condition->LfgStatus[0])
3165 {
3166 std::array<bool, std::tuple_size_v<decltype(condition->LfgStatus)>> results;
3167 results.fill(true);
3168 for (std::size_t i = 0; i < condition->LfgStatus.size(); ++i)
3169 if (condition->LfgStatus[i])
3170 results[i] = PlayerConditionCompare(condition->LfgCompare[i],
3172 condition->LfgValue[i]);
3173
3174 if (!PlayerConditionLogic(condition->LfgLogic, results))
3175 return false;
3176 }
3177
3178 if (condition->AreaID[0])
3179 {
3180 std::array<bool, std::tuple_size_v<decltype(condition->AreaID)>> results;
3181 results.fill(true);
3182 for (std::size_t i = 0; i < condition->AreaID.size(); ++i)
3183 if (condition->AreaID[i])
3184 results[i] = DB2Manager::IsInArea(player->GetAreaId(), condition->AreaID[i]);
3185
3186 if (!PlayerConditionLogic(condition->AreaLogic, results))
3187 return false;
3188 }
3189
3190 if (condition->MinExpansionLevel != -1 && player->GetSession()->GetExpansion() < condition->MinExpansionLevel)
3191 return false;
3192
3193 if (condition->MaxExpansionLevel != -1 && player->GetSession()->GetExpansion() > condition->MaxExpansionLevel)
3194 return false;
3195
3196 if (condition->MinExpansionLevel != -1 && condition->MinExpansionTier != -1 && !player->IsGameMaster()
3197 && ((condition->MinExpansionLevel == int32(sWorld->getIntConfig(CONFIG_EXPANSION)) && condition->MinExpansionTier > 0) /*TODO: implement tier*/
3198 || condition->MinExpansionLevel > int32(sWorld->getIntConfig(CONFIG_EXPANSION))))
3199 return false;
3200
3201 if (condition->PhaseID || condition->PhaseGroupID || condition->PhaseUseFlags)
3202 if (!PhasingHandler::InDbPhaseShift(player, condition->PhaseUseFlags, condition->PhaseID, condition->PhaseGroupID))
3203 return false;
3204
3205 if (condition->QuestKillID)
3206 {
3207 Quest const* quest = sObjectMgr->GetQuestTemplate(condition->QuestKillID);
3208 uint16 questSlot = player->FindQuestSlot(condition->QuestKillID);
3209 if (quest && player->GetQuestStatus(condition->QuestKillID) != QUEST_STATUS_COMPLETE && questSlot < MAX_QUEST_LOG_SIZE)
3210 {
3211 std::array<bool, std::tuple_size_v<decltype(condition->QuestKillMonster)>> results;
3212 results.fill(true);
3213 for (std::size_t i = 0; i < condition->QuestKillMonster.size(); ++i)
3214 {
3215 if (condition->QuestKillMonster[i])
3216 {
3217 auto objectiveItr = std::find_if(quest->GetObjectives().begin(), quest->GetObjectives().end(), [condition, i](QuestObjective const& objective) -> bool
3218 {
3219 return objective.Type == QUEST_OBJECTIVE_MONSTER && uint32(objective.ObjectID) == condition->QuestKillMonster[i];
3220 });
3221 if (objectiveItr != quest->GetObjectives().end())
3222 results[i] = player->GetQuestSlotObjectiveData(questSlot, *objectiveItr) >= objectiveItr->Amount;
3223 }
3224 }
3225
3226 if (!PlayerConditionLogic(condition->QuestKillLogic, results))
3227 return false;
3228 }
3229 }
3230
3231 if (condition->MinAvgItemLevel && int32(std::floor(player->m_playerData->AvgItemLevel[0])) < condition->MinAvgItemLevel)
3232 return false;
3233
3234 if (condition->MaxAvgItemLevel && int32(std::floor(player->m_playerData->AvgItemLevel[0])) > condition->MaxAvgItemLevel)
3235 return false;
3236
3237 if (condition->MinAvgEquippedItemLevel && uint32(std::floor(player->m_playerData->AvgItemLevel[1])) < condition->MinAvgEquippedItemLevel)
3238 return false;
3239
3240 if (condition->MaxAvgEquippedItemLevel && uint32(std::floor(player->m_playerData->AvgItemLevel[1])) > condition->MaxAvgEquippedItemLevel)
3241 return false;
3242
3243 if (condition->ModifierTreeID && !player->ModifierTreeSatisfied(condition->ModifierTreeID))
3244 return false;
3245
3246 if (condition->CovenantID && player->m_playerData->CovenantID != condition->CovenantID)
3247 return false;
3248
3249 if (std::any_of(condition->TraitNodeEntryID.begin(), condition->TraitNodeEntryID.end(), [](int32 traitNodeEntryId) { return traitNodeEntryId != 0; }))
3250 {
3251 auto getTraitNodeEntryRank = [player](int32 traitNodeEntryId) -> Optional<uint16>
3252 {
3253 for (UF::TraitConfig const& traitConfig : player->m_activePlayerData->TraitConfigs)
3254 {
3255 if (TraitConfigType(*traitConfig.Type) == TraitConfigType::Combat)
3256 {
3257 if (int32(*player->m_activePlayerData->ActiveCombatTraitConfigID) != traitConfig.ID
3259 continue;
3260 }
3261
3262 for (UF::TraitEntry const& traitEntry : traitConfig.Entries)
3263 if (traitEntry.TraitNodeEntryID == traitNodeEntryId)
3264 return traitEntry.Rank;
3265 }
3266 return {};
3267 };
3268
3269 std::array<bool, std::tuple_size_v<decltype(condition->TraitNodeEntryID)>> results;
3270 results.fill(true);
3271 for (std::size_t i = 0; i < condition->TraitNodeEntryID.size(); ++i)
3272 {
3273 if (!condition->TraitNodeEntryID[i])
3274 continue;
3275
3276 Optional<int32> rank = getTraitNodeEntryRank(condition->TraitNodeEntryID[i]);
3277 if (!rank)
3278 results[i] = false;
3279 else if (condition->TraitNodeEntryMinRank[i] && rank < condition->TraitNodeEntryMinRank[i])
3280 results[i] = false;
3281 else if (condition->TraitNodeEntryMaxRank[i] && rank > condition->TraitNodeEntryMaxRank[i])
3282 results[i] = false;
3283 }
3284
3285 if (!PlayerConditionLogic(condition->TraitNodeEntryLogic, results))
3286 return false;
3287 }
3288
3289 return true;
3290}
3291
3292ByteBuffer HexToBytes(const std::string& hex)
3293{
3294 ByteBuffer buffer(hex.length() / 2, ByteBuffer::Resize{});
3295 Trinity::Impl::HexStrToByteArray(hex, buffer.contents(), buffer.size());
3296 return buffer;
3297}
3298
3300{
3301 // WSE_FUNCTION_NONE
3302 [](Map const* /*map*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3303 {
3304 return 0;
3305 },
3306
3307 // WSE_FUNCTION_RANDOM
3308 [](Map const* /*map*/, uint32 arg1, uint32 arg2) -> int32
3309 {
3310 return irand(std::min(arg1, arg2), std::max(arg1, arg2));
3311 },
3312
3313 // WSE_FUNCTION_MONTH
3314 [](Map const* /*map*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3315 {
3316 return GameTime::GetDateAndTime()->tm_mon + 1;
3317 },
3318
3319 // WSE_FUNCTION_DAY
3320 [](Map const* /*map*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3321 {
3322 return GameTime::GetDateAndTime()->tm_mday + 1;
3323 },
3324
3325 // WSE_FUNCTION_TIME_OF_DAY
3326 [](Map const* /*map*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3327 {
3328 tm const* localTime = GameTime::GetDateAndTime();
3329 return localTime->tm_hour * MINUTE + localTime->tm_min;
3330 },
3331
3332 // WSE_FUNCTION_REGION
3333 [](Map const* /*map*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3334 {
3335 return realm.Id.Region;
3336 },
3337
3338 // WSE_FUNCTION_CLOCK_HOUR
3339 [](Map const* /*map*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3340 {
3341 uint32 currentHour = GameTime::GetDateAndTime()->tm_hour + 1;
3342 return currentHour <= 12 ? (currentHour ? currentHour : 12) : currentHour - 12;
3343 },
3344
3345 // WSE_FUNCTION_OLD_DIFFICULTY_ID
3346 [](Map const* map, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3347 {
3348 if (DifficultyEntry const* difficulty = sDifficultyStore.LookupEntry(map->GetDifficultyID()))
3349 return difficulty->OldEnumValue;
3350
3351 return -1;
3352 },
3353
3354 // WSE_FUNCTION_HOLIDAY_START
3355 [](Map const* /*map*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3356 {
3357 return 0;
3358 },
3359
3360 // WSE_FUNCTION_HOLIDAY_LEFT
3361 [](Map const* /*map*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3362 {
3363 return 0;
3364 },
3365
3366 // WSE_FUNCTION_HOLIDAY_ACTIVE
3367 [](Map const* /*map*/, uint32 arg1, uint32 /*arg2*/) -> int32
3368 {
3369 return int32(IsHolidayActive(HolidayIds(arg1)));
3370 },
3371
3372 // WSE_FUNCTION_TIMER_CURRENT_TIME
3373 [](Map const* /*map*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3374 {
3375 return GameTime::GetGameTime();
3376 },
3377
3378 // WSE_FUNCTION_WEEK_NUMBER
3379 [](Map const* /*map*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3380 {
3381 time_t now = GameTime::GetGameTime();
3382 uint32 raidOrigin = 1135695600;
3383 if (Cfg_RegionsEntry const* region = sCfgRegionsStore.LookupEntry(realm.Id.Region))
3384 raidOrigin = region->Raidorigin;
3385
3386 return (now - raidOrigin) / WEEK;
3387 },
3388
3389 // WSE_FUNCTION_UNK13
3390 [](Map const* /*map*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3391 {
3392 return 0;
3393 },
3394
3395 // WSE_FUNCTION_UNK14
3396 [](Map const* /*map*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3397 {
3398 return 0;
3399 },
3400
3401 // WSE_FUNCTION_DIFFICULTY_ID
3402 [](Map const* map, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3403 {
3404 return map->GetDifficultyID();
3405 },
3406
3407 // WSE_FUNCTION_WAR_MODE_ACTIVE
3408 [](Map const* /*map*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3409 {
3410 // check if current zone/map is bound to war mode
3411 return 0;
3412 },
3413
3414 // WSE_FUNCTION_UNK17
3415 [](Map const* /*map*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3416 {
3417 return 0;
3418 },
3419
3420 // WSE_FUNCTION_UNK18
3421 [](Map const* /*map*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3422 {
3423 return 0;
3424 },
3425
3426 // WSE_FUNCTION_UNK19
3427 [](Map const* /*map*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3428 {
3429 return 0;
3430 },
3431
3432 // WSE_FUNCTION_UNK20
3433 [](Map const* /*map*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3434 {
3435 return 0;
3436 },
3437
3438 // WSE_FUNCTION_UNK21
3439 [](Map const* /*map*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3440 {
3441 return 0;
3442 },
3443
3444 // WSE_FUNCTION_WORLD_STATE_EXPRESSION
3445 [](Map const* map, uint32 arg1, uint32 /*arg2*/) -> int32
3446 {
3447 if (WorldStateExpressionEntry const* worldStateExpression = sWorldStateExpressionStore.LookupEntry(arg1))
3448 return ConditionMgr::IsMeetingWorldStateExpression(map, worldStateExpression);
3449
3450 return 0;
3451 },
3452
3453 // WSE_FUNCTION_KEYSTONE_AFFIX
3454 [](Map const* /*map*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3455 {
3456 return 0;
3457 },
3458
3459 // WSE_FUNCTION_UNK24
3460 [](Map const* /*map*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3461 {
3462 return 0;
3463 },
3464
3465 // WSE_FUNCTION_UNK25
3466 [](Map const* /*map*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3467 {
3468 return 0;
3469 },
3470
3471 // WSE_FUNCTION_UNK26
3472 [](Map const* /*map*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3473 {
3474 return 0;
3475 },
3476
3477 // WSE_FUNCTION_UNK27
3478 [](Map const* /*map*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3479 {
3480 return 0;
3481 },
3482
3483 // WSE_FUNCTION_KEYSTONE_LEVEL
3484 [](Map const* /*map*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3485 {
3486 return 0;
3487 },
3488
3489 // WSE_FUNCTION_UNK29
3490 [](Map const* /*map*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3491 {
3492 return 0;
3493 },
3494
3495 // WSE_FUNCTION_UNK30
3496 [](Map const* /*map*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3497 {
3498 return 0;
3499 },
3500
3501 // WSE_FUNCTION_UNK31
3502 [](Map const* /*map*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3503 {
3504 return 0;
3505 },
3506
3507 // WSE_FUNCTION_UNK32
3508 [](Map const* /*map*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3509 {
3510 return 0;
3511 },
3512
3513 // WSE_FUNCTION_MERSENNE_RANDOM
3514 [](Map const* /*map*/, uint32 arg1, uint32 arg2) -> int32
3515 {
3516 if (arg1 == 1)
3517 return 1;
3518
3519 // init with predetermined seed
3520 std::mt19937 mt(arg2 ? arg2 : 1);
3521 return mt() % arg1 + 1;
3522 },
3523
3524 // WSE_FUNCTION_UNK34
3525 [](Map const* /*map*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3526 {
3527 return 0;
3528 },
3529
3530 // WSE_FUNCTION_UNK35
3531 [](Map const* /*map*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3532 {
3533 return 0;
3534 },
3535
3536 // WSE_FUNCTION_UNK36
3537 [](Map const* /*map*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3538 {
3539 return 0;
3540 },
3541
3542 // WSE_FUNCTION_UI_WIDGET_DATA
3543 [](Map const* /*map*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3544 {
3545 return 0;
3546 },
3547
3548 // WSE_FUNCTION_TIME_EVENT_PASSED
3549 [](Map const* /*map*/, uint32 /*arg1*/, uint32 /*arg2*/) -> int32
3550 {
3551 return 0;
3552 },
3553};
3554
3556{
3558 int32 value = 0;
3559
3560 switch (valueType)
3561 {
3563 {
3564 value = buffer.read<int32>();
3565 break;
3566 }
3568 {
3569 uint32 worldStateId = buffer.read<uint32>();
3570 value = sWorldStateMgr->GetValue(worldStateId, map);
3571 break;
3572 }
3574 {
3575 uint32 functionType = buffer.read<uint32>();
3576 int32 arg1 = EvalSingleValue(buffer, map);
3577 int32 arg2 = EvalSingleValue(buffer, map);
3578
3579 if (functionType >= WSE_FUNCTION_MAX)
3580 return 0;
3581
3582 value = WorldStateExpressionFunctions[functionType](map, arg1, arg2);
3583 break;
3584 }
3585 default:
3586 break;
3587 }
3588
3589 return value;
3590}
3591
3592int32 EvalValue(ByteBuffer& buffer, Map const* map)
3593{
3594 int32 leftValue = EvalSingleValue(buffer, map);
3595
3597 if (operatorType == WorldStateExpressionOperatorType::None)
3598 return leftValue;
3599
3600 int32 rightValue = EvalSingleValue(buffer, map);
3601
3602 switch (operatorType)
3603 {
3604 case WorldStateExpressionOperatorType::Sum: return leftValue + rightValue;
3605 case WorldStateExpressionOperatorType::Substraction: return leftValue - rightValue;
3606 case WorldStateExpressionOperatorType::Multiplication: return leftValue * rightValue;
3607 case WorldStateExpressionOperatorType::Division: return !rightValue ? 0 : leftValue / rightValue;
3608 case WorldStateExpressionOperatorType::Remainder: return !rightValue ? 0 : leftValue % rightValue;
3609 default:
3610 break;
3611 }
3612
3613 return leftValue;
3614}
3615
3616bool EvalRelOp(ByteBuffer& buffer, Map const* map)
3617{
3618 int32 leftValue = EvalValue(buffer, map);
3619
3621 if (compareLogic == WorldStateExpressionComparisonType::None)
3622 return leftValue != 0;
3623
3624 int32 rightValue = EvalValue(buffer, map);
3625
3626 switch (compareLogic)
3627 {
3628 case WorldStateExpressionComparisonType::Equal: return leftValue == rightValue;
3629 case WorldStateExpressionComparisonType::NotEqual: return leftValue != rightValue;
3630 case WorldStateExpressionComparisonType::Less: return leftValue < rightValue;
3631 case WorldStateExpressionComparisonType::LessOrEqual: return leftValue <= rightValue;
3632 case WorldStateExpressionComparisonType::Greater: return leftValue > rightValue;
3633 case WorldStateExpressionComparisonType::GreaterOrEqual: return leftValue >= rightValue;
3634 default:
3635 break;
3636 }
3637
3638 return false;
3639}
3640
3642{
3643 ByteBuffer buffer = HexToBytes(expression->Expression);
3644 if (buffer.empty())
3645 return false;
3646
3647 bool enabled = buffer.read<bool>();
3648 if (!enabled)
3649 return false;
3650
3651 bool finalResult = EvalRelOp(buffer, map);
3653
3654 while (resultLogic != WorldStateExpressionLogic::None)
3655 {
3656 bool secondResult = EvalRelOp(buffer, map);
3657
3658 switch (resultLogic)
3659 {
3660 case WorldStateExpressionLogic::And: finalResult = finalResult && secondResult; break;
3661 case WorldStateExpressionLogic::Or: finalResult = finalResult || secondResult; break;
3662 case WorldStateExpressionLogic::Xor: finalResult = finalResult != secondResult; break;
3663 default:
3664 break;
3665 }
3666
3667 if (buffer.rpos() >= buffer.size())
3668 break;
3669
3670 resultLogic = buffer.read<WorldStateExpressionLogic>();
3671 }
3672
3673 return finalResult;
3674}
3675
3676int32 GetUnitConditionVariable(Unit const* unit, Unit const* otherUnit, UnitConditionVariable variable, int32 value)
3677{
3678 switch (variable)
3679 {
3681 return unit->GetRace();
3683 return unit->GetClass();
3685 return unit->GetLevel();
3687 return unit == otherUnit;
3689 return otherUnit && unit->GetCharmerOrOwnerGUID() == otherUnit->GetGUID();
3691 return otherUnit && otherUnit->GetCharmerOrOwnerGUID() == unit->GetGUID();
3693 return otherUnit && otherUnit->GetTarget() == unit->GetGUID();
3695 return otherUnit && unit->IsValidAssistTarget(otherUnit);
3697 return otherUnit && unit->IsValidAttackTarget(otherUnit);
3699 return !unit->GetCharmedGUID().IsEmpty() || !unit->GetMinionGUID().IsEmpty();
3701 if (Player const* player = unit->ToPlayer())
3702 return player->GetWeaponForAttack(BASE_ATTACK) || player->GetWeaponForAttack(OFF_ATTACK);
3703 return unit->GetVirtualItemId(0) || unit->GetVirtualItemId(1);
3705 return unit->GetHealthPct();
3707 return unit->GetPowerPct(POWER_MANA);
3709 return unit->GetPowerPct(POWER_RAGE);
3711 return unit->GetPowerPct(POWER_ENERGY);
3713 return unit->GetPower(POWER_COMBO_POINTS);
3715 return unit->GetAuraApplication(value, [](AuraApplication const* aurApp)
3716 {
3717 return (aurApp->GetFlags() & AFLAG_NEGATIVE) == 0;
3718 }) != nullptr ? value : 0;
3720 return unit->GetAuraApplication([value](AuraApplication const* aurApp)
3721 {
3722 return (aurApp->GetFlags() & AFLAG_NEGATIVE) == 0 && int32(aurApp->GetBase()->GetSpellInfo()->Dispel) == value;
3723 }) != nullptr ? value : 0;
3725 return unit->GetAuraApplication([value](AuraApplication const* aurApp)
3726 {
3727 return (aurApp->GetFlags() & AFLAG_NEGATIVE) == 0 && (aurApp->GetBase()->GetSpellInfo()->GetSpellMechanicMaskByEffectMask(aurApp->GetEffectMask()) & (UI64LIT(1) << value)) != 0;
3728 }) != nullptr ? value : 0;
3730 return unit->GetAuraApplication(value, [](AuraApplication const* aurApp)
3731 {
3732 return (aurApp->GetFlags() & AFLAG_NEGATIVE) != 0;
3733 }) != nullptr ? value : 0;
3735 return unit->GetAuraApplication([value](AuraApplication const* aurApp)
3736 {
3737 return (aurApp->GetFlags() & AFLAG_NEGATIVE) != 0 && int32(aurApp->GetBase()->GetSpellInfo()->Dispel) == value;
3738 }) != nullptr ? value : 0;
3740 return unit->GetAuraApplication([value](AuraApplication const* aurApp)
3741 {
3742 return (aurApp->GetFlags() & AFLAG_NEGATIVE) != 0 && (aurApp->GetBase()->GetSpellInfo()->GetSpellMechanicMaskByEffectMask(aurApp->GetEffectMask()) & (UI64LIT(1) << value)) != 0;
3743 }) != nullptr ? value : 0;
3745 return unit->GetAuraApplication([value](AuraApplication const* aurApp)
3746 {
3747 return (aurApp->GetFlags() & AFLAG_NEGATIVE) != 0 && (aurApp->GetBase()->GetSpellInfo()->GetSchoolMask() & (1 << value)) != 0;
3748 }) != nullptr ? value : 0;
3750 break;
3752 break;
3754 break;
3756 break;
3758 break;
3760 break;
3762 break;
3764 return unit->IsInCombat();
3768 case UnitConditionVariable::IsCastingSpell: // this is supposed to return spell id by client code but data always has 0 or 1
3769 return unit->GetCurrentSpell(CURRENT_GENERIC_SPELL) != nullptr;
3771 case UnitConditionVariable::IsChannelingSpell: // this is supposed to return spell id by client code but data always has 0 or 1
3772 return unit->GetChannelSpellId() != 0;
3774 return std::count_if(unit->getAttackers().begin(), unit->getAttackers().end(), [unit](Unit* attacker)
3775 {
3776 float distance = std::max(unit->GetCombatReach() + attacker->GetCombatReach() + 1.3333334f, 5.0f);
3777 if (unit->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) || attacker->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED))
3778 distance += 1.0f;
3779 return unit->GetExactDistSq(attacker) < distance * distance;
3780 });
3782 return otherUnit && unit->GetTarget() == otherUnit->GetGUID();
3784 return otherUnit ? int32(unit->GetExactDist(otherUnit)) : 0;
3786 if (otherUnit)
3787 {
3788 float distance = std::max(unit->GetCombatReach() + otherUnit->GetCombatReach() + 1.3333334f, 5.0f);
3790 distance += 1.0f;
3791 return unit->GetExactDistSq(otherUnit) < distance * distance;
3792 }
3793 return 0;
3795 break;
3801 return unit->GetThreatManager().GetThreatListSize();
3803 break;
3805 break;
3807 break;
3809 break;
3811 break;
3813 break;
3815 break;
3817 break;
3819 break;
3821 return unit->getAttackers().size();
3823 return std::count_if(unit->getAttackers().begin(), unit->getAttackers().end(), [unit](Unit* attacker)
3824 {
3825 float distance = std::max(unit->GetCombatReach() + attacker->GetCombatReach() + 1.3333334f, 5.0f);
3826 if (unit->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) || attacker->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED))
3827 distance += 1.0f;
3828 return unit->GetExactDistSq(attacker) >= distance * distance;
3829 });
3831 return unit->GetCreatureType();
3833 if (Unit const* target = ObjectAccessor::GetUnit(*unit, unit->GetTarget()))
3834 {
3835 float distance = std::max(unit->GetCombatReach() + target->GetCombatReach() + 1.3333334f, 5.0f);
3836 if (unit->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) || target->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED))
3837 distance += 1.0f;
3838 return unit->GetExactDistSq(target) < distance * distance;
3839 }
3840 return 0;
3842 if (Unit const* target = ObjectAccessor::GetUnit(*unit, unit->GetTarget()))
3843 {
3844 float distance = std::max(unit->GetCombatReach() + target->GetCombatReach() + 1.3333334f, 5.0f);
3845 if (unit->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED) || target->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED))
3846 distance += 1.0f;
3847 return unit->GetExactDistSq(target) >= distance * distance;
3848 }
3849 return 0;
3851 return unit->GetHealth();
3853 return unit->HasSpell(value) ? value : 0;
3855 return value >= 0 && value < int32(TOTAL_AURAS) && std::find_if(unit->GetAuraEffectsByType(AuraType(value)).begin(), unit->GetAuraEffectsByType(AuraType(value)).end(), [unit](AuraEffect const* aurEff)
3856 {
3857 return (aurEff->GetBase()->GetApplicationOfTarget(unit->GetGUID())->GetFlags() & AFLAG_NEGATIVE) != 0;
3858 }) != unit->GetAuraEffectsByType(AuraType(value)).end();
3860 break;
3862 return unit->IsPlayer();
3864 break;
3866 break;
3868 break;
3870 break;
3872 return !unit->GetCritterGUID().IsEmpty();
3874 return !unit->m_SummonSlot[SUMMON_SLOT_TOTEM].IsEmpty();
3876 return !unit->m_SummonSlot[SUMMON_SLOT_TOTEM_2].IsEmpty();
3878 return !unit->m_SummonSlot[SUMMON_SLOT_TOTEM_3].IsEmpty();
3880 return !unit->m_SummonSlot[SUMMON_SLOT_TOTEM_4].IsEmpty();
3882 break;
3884 return unit->GetEntry();
3886 break;
3888 return unit->HasAura(value) ? value : 0;
3890 return otherUnit && unit->GetReactionTo(otherUnit) <= REP_HOSTILE;
3892 return unit->IsPlayer() && unit->ToPlayer()->GetPrimarySpecializationEntry()
3895 return unit->IsPlayer() && unit->ToPlayer()->GetPrimarySpecializationEntry()
3898 return unit->IsPlayer() && unit->ToPlayer()->GetPrimarySpecializationEntry()
3901 return unit->IsPlayer() && unit->ToPlayer()->GetPrimarySpecializationEntry()
3904 return unit->IsCreature() && unit->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED);
3906 return unit->GetHealth() == 0;
3908 break;
3910 return unit->GetMountDisplayId() != 0;
3912 break;
3914 return otherUnit && (otherUnit->GetCharmerGUID() == unit->GetGUID() || otherUnit->GetCreatorGUID() == unit->GetGUID());
3916 return otherUnit && (unit->GetCharmerGUID() == otherUnit->GetGUID() || unit->GetCreatorGUID() == otherUnit->GetGUID());
3918 return otherUnit && unit->GetTarget() == otherUnit->GetGUID();
3920 return unit->GetGender();
3922 if (Optional<ContentTuningLevels> levelRange = sDB2Manager.GetContentTuningData(value, 0))
3923 return unit->GetLevel() >= levelRange->MinLevel && unit->GetLevel() <= levelRange->MaxLevel ? value : 0;
3924 return 0;
3926 return unit->IsFlying();
3928 return unit->IsHovering();
3930 return value >= 0 && value < int32(TOTAL_AURAS) && std::find_if(unit->GetAuraEffectsByType(AuraType(value)).begin(), unit->GetAuraEffectsByType(AuraType(value)).end(), [unit](AuraEffect const* aurEff)
3931 {
3932 return (aurEff->GetBase()->GetApplicationOfTarget(unit->GetGUID())->GetFlags() & AFLAG_NEGATIVE) == 0;
3933 }) != unit->GetAuraEffectsByType(AuraType(value)).end();
3935 return unit->GetAuraApplication([value](AuraApplication const* aurApp)
3936 {
3937 return (aurApp->GetFlags() & AFLAG_NEGATIVE) == 0 && (aurApp->GetBase()->GetSpellInfo()->GetSchoolMask() & (1 << value)) != 0;
3938 }) != nullptr ? value : 0;
3939 default:
3940 break;
3941 }
3942
3943 return 0;
3944}
3945
3946bool ConditionMgr::IsUnitMeetingCondition(Unit const* unit, Unit const* otherUnit, UnitConditionEntry const* condition)
3947{
3948 for (size_t i = 0; i < MAX_UNIT_CONDITION_VALUES; ++i)
3949 {
3950 if (!condition->Variable[i])
3951 break;
3952
3953 int32 unitValue = GetUnitConditionVariable(unit, otherUnit, UnitConditionVariable(condition->Variable[i]), condition->Value[i]);
3954 bool meets = false;
3955 switch (UnitConditionOp(condition->Op[i]))
3956 {
3958 meets = unitValue == condition->Value[i];
3959 break;
3961 meets = unitValue != condition->Value[i];
3962 break;
3964 meets = unitValue < condition->Value[i];
3965 break;
3967 meets = unitValue <= condition->Value[i];
3968 break;
3970 meets = unitValue > condition->Value[i];
3971 break;
3973 meets = unitValue >= condition->Value[i];
3974 break;
3975 default:
3976 break;
3977 }
3978
3979 if (condition->GetFlags().HasFlag(UnitConditionFlags::LogicOr))
3980 {
3981 if (meets)
3982 return true;
3983 }
3984 else if (!meets)
3985 return false;
3986 }
3987
3988 return !condition->GetFlags().HasFlag(UnitConditionFlags::LogicOr);
3989}
#define sAchievementMgr
#define sAreaTriggerDataStore
@ MINUTE
Definition: Common.h:29
@ WEEK
Definition: Common.h:32
bool PlayerConditionLogic(uint32 logic, std::array< bool, N > &results)
bool PlayerConditionCompare(int32 comparisonType, int32 value1, int32 value2)
int32 GetUnitConditionVariable(Unit const *unit, Unit const *otherUnit, UnitConditionVariable variable, int32 value)
bool EvalRelOp(ByteBuffer &buffer, Map const *map)
int32 EvalSingleValue(ByteBuffer &buffer, Map const *map)
ByteBuffer HexToBytes(const std::string &hex)
int32 EvalValue(ByteBuffer &buffer, Map const *map)
std::vector< Condition > ConditionContainer
Definition: ConditionMgr.h:290
ConditionSourceType
Definition: ConditionMgr.h:153
@ CONDITION_SOURCE_TYPE_MAX
Definition: ConditionMgr.h:191
@ CONDITION_SOURCE_TYPE_CONVERSATION_LINE
Definition: ConditionMgr.h:183
@ CONDITION_SOURCE_TYPE_VEHICLE_SPELL
Definition: ConditionMgr.h:175
@ CONDITION_SOURCE_TYPE_DISENCHANT_LOOT_TEMPLATE
Definition: ConditionMgr.h:156
@ CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE
Definition: ConditionMgr.h:164
@ CONDITION_SOURCE_TYPE_TERRAIN_SWAP
Definition: ConditionMgr.h:179
@ CONDITION_SOURCE_TYPE_NPC_VENDOR
Definition: ConditionMgr.h:177
@ CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION
Definition: ConditionMgr.h:169
@ CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT
Definition: ConditionMgr.h:172
@ CONDITION_SOURCE_TYPE_REFERENCE_CONDITION
Definition: ConditionMgr.h:190
@ CONDITION_SOURCE_TYPE_MAIL_LOOT_TEMPLATE
Definition: ConditionMgr.h:160
@ CONDITION_SOURCE_TYPE_PHASE
Definition: ConditionMgr.h:180
@ CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE
Definition: ConditionMgr.h:166
@ CONDITION_SOURCE_TYPE_SMART_EVENT
Definition: ConditionMgr.h:176
@ CONDITION_SOURCE_TYPE_PICKPOCKETING_LOOT_TEMPLATE
Definition: ConditionMgr.h:162
@ CONDITION_SOURCE_TYPE_PROSPECTING_LOOT_TEMPLATE
Definition: ConditionMgr.h:163
@ CONDITION_SOURCE_TYPE_AREATRIGGER_CLIENT_TRIGGERED
Definition: ConditionMgr.h:184
@ CONDITION_SOURCE_TYPE_AREATRIGGER
Definition: ConditionMgr.h:182
@ CONDITION_SOURCE_TYPE_SPAWN_GROUP
Definition: ConditionMgr.h:187
@ CONDITION_SOURCE_TYPE_SPELL
Definition: ConditionMgr.h:171
@ CONDITION_SOURCE_TYPE_FISHING_LOOT_TEMPLATE
Definition: ConditionMgr.h:157
@ CONDITION_SOURCE_TYPE_OBJECT_ID_VISIBILITY
Definition: ConditionMgr.h:186
@ CONDITION_SOURCE_TYPE_GOSSIP_MENU
Definition: ConditionMgr.h:168
@ CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE
Definition: ConditionMgr.h:170
@ CONDITION_SOURCE_TYPE_ITEM_LOOT_TEMPLATE
Definition: ConditionMgr.h:159
@ CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET
Definition: ConditionMgr.h:167
@ CONDITION_SOURCE_TYPE_GRAVEYARD
Definition: ConditionMgr.h:181
@ CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE
Definition: ConditionMgr.h:165
@ CONDITION_SOURCE_TYPE_TRAINER_SPELL
Definition: ConditionMgr.h:185
@ CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE
Definition: ConditionMgr.h:155
@ CONDITION_SOURCE_TYPE_GAMEOBJECT_LOOT_TEMPLATE
Definition: ConditionMgr.h:158
@ CONDITION_SOURCE_TYPE_MILLING_LOOT_TEMPLATE
Definition: ConditionMgr.h:161
@ CONDITION_SOURCE_TYPE_SPELL_PROC
Definition: ConditionMgr.h:178
@ CONDITION_SOURCE_TYPE_QUEST_AVAILABLE
Definition: ConditionMgr.h:173
@ CONDITION_SOURCE_TYPE_NONE
Definition: ConditionMgr.h:154
@ CONDITION_SOURCE_TYPE_MAX_DB_ALLOWED
Definition: ConditionMgr.h:189
@ INSTANCE_INFO_DATA64
Definition: ConditionMgr.h:210
@ INSTANCE_INFO_DATA
Definition: ConditionMgr.h:207
@ INSTANCE_INFO_BOSS_STATE
Definition: ConditionMgr.h:209
@ INSTANCE_INFO_GUID_DATA
Definition: ConditionMgr.h:208
@ MAX_CONDITION_TARGETS
Definition: ConditionMgr.h:215
ConditionTypes
Definition: ConditionMgr.h:60
@ CONDITION_TAXI
Definition: ConditionMgr.h:107
@ CONDITION_MAPID
Definition: ConditionMgr.h:83
@ CONDITION_SKILL
Definition: ConditionMgr.h:68
@ CONDITION_RACE
Definition: ConditionMgr.h:77
@ CONDITION_STRING_ID
Definition: ConditionMgr.h:119
@ CONDITION_PHASEID
Definition: ConditionMgr.h:87
@ CONDITION_REACTION_TO
Definition: ConditionMgr.h:95
@ CONDITION_NEAR_GAMEOBJECT
Definition: ConditionMgr.h:91
@ CONDITION_QUESTREWARDED
Definition: ConditionMgr.h:69
@ CONDITION_REALM_ACHIEVEMENT
Definition: ConditionMgr.h:100
@ CONDITION_QUEST_OBJECTIVE_PROGRESS
Definition: ConditionMgr.h:109
@ CONDITION_DAILY_QUEST_DONE
Definition: ConditionMgr.h:104
@ CONDITION_ACTIVE_EVENT
Definition: ConditionMgr.h:73
@ CONDITION_SPAWNMASK_DEPRECATED
Definition: ConditionMgr.h:80
@ CONDITION_INSTANCE_INFO
Definition: ConditionMgr.h:74
@ CONDITION_RELATION_TO
Definition: ConditionMgr.h:94
@ CONDITION_PRIVATE_OBJECT
Definition: ConditionMgr.h:118
@ CONDITION_STAND_STATE
Definition: ConditionMgr.h:103
@ CONDITION_DRUNKENSTATE
Definition: ConditionMgr.h:71
@ CONDITION_AURA
Definition: ConditionMgr.h:62
@ CONDITION_ACHIEVEMENT
Definition: ConditionMgr.h:78
@ CONDITION_OBJECT_ENTRY_GUID
Definition: ConditionMgr.h:112
@ CONDITION_PET_TYPE
Definition: ConditionMgr.h:106
@ CONDITION_DIFFICULTY_ID
Definition: ConditionMgr.h:110
@ CONDITION_DISTANCE_TO
Definition: ConditionMgr.h:96
@ CONDITION_SCENARIO_STEP
Definition: ConditionMgr.h:115
@ CONDITION_HP_VAL
Definition: ConditionMgr.h:98
@ CONDITION_BATTLE_PET_COUNT
Definition: ConditionMgr.h:114
@ CONDITION_GENDER
Definition: ConditionMgr.h:81
@ CONDITION_GAMEMASTER
Definition: ConditionMgr.h:111
@ CONDITION_TERRAIN_SWAP
Definition: ConditionMgr.h:102
@ CONDITION_REPUTATION_RANK
Definition: ConditionMgr.h:66
@ CONDITION_HP_PCT
Definition: ConditionMgr.h:99
@ CONDITION_QUEST_COMPLETE
Definition: ConditionMgr.h:89
@ CONDITION_MAX
Definition: ConditionMgr.h:120
@ CONDITION_SPELL
Definition: ConditionMgr.h:86
@ CONDITION_ZONEID
Definition: ConditionMgr.h:65
@ CONDITION_OBJECT_ENTRY_GUID_LEGACY
Definition: ConditionMgr.h:92
@ CONDITION_CHARMED
Definition: ConditionMgr.h:105
@ CONDITION_TYPE_MASK
Definition: ConditionMgr.h:113
@ CONDITION_AREAID
Definition: ConditionMgr.h:84
@ CONDITION_IN_WATER
Definition: ConditionMgr.h:101
@ CONDITION_ITEM
Definition: ConditionMgr.h:63
@ CONDITION_WORLD_STATE
Definition: ConditionMgr.h:72
@ CONDITION_CLASS
Definition: ConditionMgr.h:76
@ CONDITION_TEAM
Definition: ConditionMgr.h:67
@ CONDITION_NONE
Definition: ConditionMgr.h:61
@ CONDITION_QUEST_NONE
Definition: ConditionMgr.h:75
@ CONDITION_QUESTSTATE
Definition: ConditionMgr.h:108
@ CONDITION_ITEM_EQUIPPED
Definition: ConditionMgr.h:64
@ CONDITION_SCENE_IN_PROGRESS
Definition: ConditionMgr.h:116
@ CONDITION_LEVEL
Definition: ConditionMgr.h:88
@ CONDITION_QUESTTAKEN
Definition: ConditionMgr.h:70
@ CONDITION_PLAYER_CONDITION
Definition: ConditionMgr.h:117
@ CONDITION_NEAR_CREATURE
Definition: ConditionMgr.h:90
@ CONDITION_TITLE
Definition: ConditionMgr.h:79
@ CONDITION_ALIVE
Definition: ConditionMgr.h:97
@ CONDITION_CREATURE_TYPE
Definition: ConditionMgr.h:85
@ CONDITION_TYPE_MASK_LEGACY
Definition: ConditionMgr.h:93
@ CONDITION_UNIT_STATE
Definition: ConditionMgr.h:82
RelationType
Definition: ConditionMgr.h:195
@ RELATION_IN_PARTY
Definition: ConditionMgr.h:197
@ RELATION_IN_RAID_OR_PARTY
Definition: ConditionMgr.h:198
@ RELATION_CREATED_BY
Definition: ConditionMgr.h:201
@ RELATION_MAX
Definition: ConditionMgr.h:202
@ RELATION_SELF
Definition: ConditionMgr.h:196
@ RELATION_PASSENGER_OF
Definition: ConditionMgr.h:200
@ RELATION_OWNED_BY
Definition: ConditionMgr.h:199
#define sConversationDataStore
DB2Storage< PhaseEntry > sPhaseStore("Phase.db2", &PhaseLoadInfo::Instance)
DB2Storage< DifficultyEntry > sDifficultyStore("Difficulty.db2", &DifficultyLoadInfo::Instance)
DB2Storage< SkillLineEntry > sSkillLineStore("SkillLine.db2", &SkillLineLoadInfo::Instance)
DB2Storage< AchievementEntry > sAchievementStore("Achievement.db2", &AchievementLoadInfo::Instance)
DB2Storage< MapEntry > sMapStore("Map.db2", &MapLoadInfo::Instance)
DB2Storage< WorldStateExpressionEntry > sWorldStateExpressionStore("WorldStateExpression.db2", &WorldStateExpressionLoadInfo::Instance)
DB2Storage< CharTitlesEntry > sCharTitlesStore("CharTitles.db2", &CharTitlesLoadInfo::Instance)
DB2Storage< ChrSpecializationEntry > sChrSpecializationStore("ChrSpecialization.db2", &ChrSpecializationLoadInfo::Instance)
DB2Storage< SceneScriptPackageEntry > sSceneScriptPackageStore("SceneScriptPackage.db2", &SceneScriptPackageLoadInfo::Instance)
DB2Storage< ScenarioStepEntry > sScenarioStepStore("ScenarioStep.db2", &ScenarioStepLoadInfo::Instance)
DB2Storage< BattlePetSpeciesEntry > sBattlePetSpeciesStore("BattlePetSpecies.db2", &BattlePetSpeciesLoadInfo::Instance)
DB2Storage< AreaTriggerEntry > sAreaTriggerStore("AreaTrigger.db2", &AreaTriggerLoadInfo::Instance)
DB2Storage< Cfg_RegionsEntry > sCfgRegionsStore("Cfg_Regions.db2", &CfgRegionsLoadInfo::Instance)
DB2Storage< PlayerConditionEntry > sPlayerConditionStore("PlayerCondition.db2", &PlayerConditionLoadInfo::Instance)
DB2Storage< AreaTableEntry > sAreaTableStore("AreaTable.db2", &AreaTableLoadInfo::Instance)
DB2Storage< FactionEntry > sFactionStore("Faction.db2", &FactionLoadInfo::Instance)
#define sDB2Manager
Definition: DB2Stores.h:538
#define MAX_UNIT_CONDITION_VALUES
TraitConfigType
Definition: DBCEnums.h:2185
PlayerConditionLfgStatus
Definition: DBCEnums.h:1753
@ DIFFICULTY_NONE
Definition: DBCEnums.h:874
#define MAX_EFFECT_MASK
Definition: DBCEnums.h:1954
TraitCombatConfigFlags
Definition: DBCEnums.h:2157
UnitConditionVariable
Definition: DBCEnums.h:2315
WorldStateExpressionFunctions
Definition: DBCEnums.h:2529
@ WSE_FUNCTION_MAX
Definition: DBCEnums.h:2570
WorldStateExpressionValueType
Definition: DBCEnums.h:2493
UnitConditionOp
Definition: DBCEnums.h:2305
WorldStateExpressionComparisonType
Definition: DBCEnums.h:2508
#define MAX_SPELL_EFFECTS
Definition: DBCEnums.h:1953
WorldStateExpressionLogic
Definition: DBCEnums.h:2500
WorldStateExpressionOperatorType
Definition: DBCEnums.h:2519
std::shared_ptr< ResultSet > QueryResult
DatabaseWorkerPool< WorldDatabaseConnection > WorldDatabase
Accessor to the world database.
Definition: DatabaseEnv.cpp:20
uint8_t uint8
Definition: Define.h:144
int64_t int64
Definition: Define.h:137
int8_t int8
Definition: Define.h:140
int32_t int32
Definition: Define.h:138
uint64_t uint64
Definition: Define.h:141
#define UI64LIT(N)
Definition: Define.h:127
uint16_t uint16
Definition: Define.h:143
uint32_t uint32
Definition: Define.h:142
#define ABORT_MSG
Definition: Errors.h:75
#define ASSERT
Definition: Errors.h:68
bool IsHolidayActive(HolidayIds id)
#define sGameEventMgr
Definition: GameEventMgr.h:177
@ GRID_MAP_TYPE_MASK_PLAYER
Definition: GridDefines.h:85
@ GRID_MAP_TYPE_MASK_CREATURE
Definition: GridDefines.h:82
@ GRID_MAP_TYPE_MASK_ALL
Definition: GridDefines.h:89
@ GRID_MAP_TYPE_MASK_GAMEOBJECT
Definition: GridDefines.h:84
@ GRID_MAP_TYPE_MASK_CORPSE
Definition: GridDefines.h:81
@ GRID_MAP_TYPE_MASK_AREATRIGGER
Definition: GridDefines.h:86
EncounterState
#define sLFGMgr
Definition: LFGMgr.h:507
#define sLanguageMgr
Definition: LanguageMgr.h:97
#define TC_LOG_DEBUG(filterType__,...)
Definition: Log.h:156
#define TC_LOG_ERROR(filterType__,...)
Definition: Log.h:165
#define TC_LOG_INFO(filterType__,...)
Definition: Log.h:159
LootStore LootTemplates_Spell("spell_loot_template", "spell id (random item creating)", false)
LootStore LootTemplates_Skinning("skinning_loot_template", "creature skinning id", true)
LootStore LootTemplates_Gameobject("gameobject_loot_template", "gameobject entry", true)
LootStore LootTemplates_Item("item_loot_template", "item entry", true)
LootStore LootTemplates_Milling("milling_loot_template", "item entry (herb)", true)
LootStore LootTemplates_Reference("reference_loot_template", "reference id", false)
LootStore LootTemplates_Disenchant("disenchant_loot_template", "item disenchant id", true)
LootStore LootTemplates_Prospecting("prospecting_loot_template", "item entry (ore)", true)
LootStore LootTemplates_Creature("creature_loot_template", "creature entry", true)
LootStore LootTemplates_Pickpocketing("pickpocketing_loot_template", "creature pickpocket lootid", true)
LootStore LootTemplates_Mail("mail_loot_template", "mail template id", false)
LootStore LootTemplates_Fishing("fishing_loot_template", "area id", true)
@ TYPEID_AREATRIGGER
Definition: ObjectGuid.h:46
@ TYPEID_GAMEOBJECT
Definition: ObjectGuid.h:43
@ TYPEID_UNIT
Definition: ObjectGuid.h:40
@ TYPEID_CORPSE
Definition: ObjectGuid.h:45
@ TYPEID_PLAYER
Definition: ObjectGuid.h:41
@ TYPEMASK_UNIT
Definition: ObjectGuid.h:60
@ TYPEMASK_CORPSE
Definition: ObjectGuid.h:65
@ TYPEMASK_GAMEOBJECT
Definition: ObjectGuid.h:63
@ TYPEMASK_PLAYER
Definition: ObjectGuid.h:61
@ TYPEMASK_AREATRIGGER
Definition: ObjectGuid.h:66
#define NUM_CLIENT_OBJECT_TYPES
Definition: ObjectGuid.h:51
#define sObjectMgr
Definition: ObjectMgr.h:1946
std::pair< GossipMenusContainer::iterator, GossipMenusContainer::iterator > GossipMenusMapBoundsNonConst
Definition: ObjectMgr.h:777
std::optional< T > Optional
Optional helper class to wrap optional values within.
Definition: Optional.h:25
@ MAX_PET_TYPE
Definition: PetDefines.h:33
@ EQUIPMENT_SLOT_MAINHAND
Definition: Player.h:646
#define INVENTORY_SLOT_BAG_0
Definition: Player.h:625
@ DRUNKEN_SMASHED
Definition: Player.h:421
#define MAX_QUEST_LOG_SIZE
Definition: QuestDef.h:44
QuestStatus
Definition: QuestDef.h:141
@ QUEST_STATUS_REWARDED
Definition: QuestDef.h:148
@ QUEST_STATUS_FAILED
Definition: QuestDef.h:147
@ QUEST_STATUS_INCOMPLETE
Definition: QuestDef.h:145
@ QUEST_STATUS_NONE
Definition: QuestDef.h:142
@ MAX_QUEST_STATUS
Definition: QuestDef.h:149
@ QUEST_STATUS_COMPLETE
Definition: QuestDef.h:143
int32 irand(int32 min, int32 max)
Definition: Random.cpp:35
#define sScriptMgr
Definition: ScriptMgr.h:1418
SpellEffIndex
Definition: SharedDefines.h:29
Language
Gender
@ CREATURE_TYPE_GAS_CLOUD
@ SPELL_EFFECT_APPLY_AREA_AURA_PARTY
@ SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
@ SPELL_EFFECT_APPLY_AREA_AURA_PARTY_NONRANDOM
@ SPELL_EFFECT_APPLY_AURA_ON_PET
@ SPELL_EFFECT_APPLY_AREA_AURA_PET
@ SPELL_EFFECT_APPLY_AREA_AURA_RAID
@ SPELL_EFFECT_PERSISTENT_AREA_AURA
@ SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
@ SPELL_EFFECT_APPLY_AREA_AURA_SUMMONS
@ SPELL_EFFECT_APPLY_AREA_AURA_OWNER
@ SUMMON_SLOT_TOTEM
@ SUMMON_SLOT_TOTEM_4
@ SUMMON_SLOT_TOTEM_3
@ SUMMON_SLOT_TOTEM_2
@ OFF_ATTACK
@ BASE_ATTACK
Team
@ ALLIANCE
@ HORDE
Powers
@ POWER_RAGE
@ POWER_ENERGY
@ POWER_COMBO_POINTS
@ POWER_MANA
ReputationRank
@ REP_HOSTILE
#define CLASSMASK_ALL_PLAYABLE
HolidayIds
@ SPAWNGROUP_FLAG_SYSTEM
Definition: SpawnData.h:54
AuraType
@ SPELL_AURA_PERIODIC_DAMAGE
@ SPELL_AURA_COMPREHEND_LANGUAGE
@ TOTAL_AURAS
@ AFLAG_NEGATIVE
@ TARGET_SELECT_CATEGORY_CONE
Definition: SpellInfo.h:48
@ TARGET_SELECT_CATEGORY_AREA
Definition: SpellInfo.h:49
@ TARGET_SELECT_CATEGORY_NEARBY
Definition: SpellInfo.h:47
@ TARGET_SELECT_CATEGORY_LINE
Definition: SpellInfo.h:51
@ TARGET_SELECT_CATEGORY_TRAJ
Definition: SpellInfo.h:50
#define sSpellMgr
Definition: SpellMgr.h:849
uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
Definition: Timer.h:57
uint32 getMSTime()
Definition: Timer.h:33
UnitStandStateType
Definition: UnitDefines.h:41
@ UNIT_STAND_STATE_SUBMERGED
Definition: UnitDefines.h:51
@ MOVEMENTFLAG_FORWARD
Definition: UnitDefines.h:358
@ MOVEMENTFLAG_STRAFE_LEFT
Definition: UnitDefines.h:360
@ MOVEMENTFLAG_BACKWARD
Definition: UnitDefines.h:359
@ MOVEMENTFLAG_STRAFE_RIGHT
Definition: UnitDefines.h:361
@ UNIT_FLAG_PLAYER_CONTROLLED
Definition: UnitDefines.h:147
@ CURRENT_GENERIC_SPELL
Definition: Unit.h:590
@ UNIT_STATE_ALL_STATE_SUPPORTED
Definition: Unit.h:286
bool CompareValues(ComparisionType type, T val1, T val2)
Definition: Util.h:469
constexpr std::underlying_type< E >::type AsUnderlyingType(E enumValue)
Definition: Util.h:491
ComparisionType
Definition: Util.h:459
@ COMP_TYPE_MAX
Definition: Util.h:465
#define sWorldStateMgr
Definition: WorldStateMgr.h:50
uint16 GetFlags() const
Definition: SpellAuras.h:81
Aura * GetBase() const
Definition: SpellAuras.h:78
uint32 GetEffectMask() const
Definition: SpellAuras.h:82
Aura * GetBase() const
AuraApplication const * GetApplicationOfTarget(ObjectGuid guid) const
SpellInfo const * GetSpellInfo() const
Definition: SpellAuras.h:134
size_t rpos() const
Definition: ByteBuffer.h:399
size_t size() const
Definition: ByteBuffer.h:536
bool empty() const
Definition: ByteBuffer.h:537
uint8 * contents()
Definition: ByteBuffer.h:522
bool isConditionTypeValid(Condition *cond) const
bool IsSpellUsedInSpellClickConditions(uint32 spellId) const
std::unordered_set< uint32 > SpellsUsedInSpellClickConditions
Definition: ConditionMgr.h:362
void addToLootTemplate(ConditionId const &id, std::shared_ptr< std::vector< Condition > > conditions, LootTemplate *loot) const
bool IsObjectMeetingVendorItemConditions(uint32 creatureId, uint32 itemId, Player const *player, Creature const *vendor) const
bool IsObjectMeetToConditions(WorldObject const *object, ConditionContainer const &conditions) const
bool isSourceTypeValid(Condition *cond) const
static bool IsPlayerMeetingCondition(Player const *player, PlayerConditionEntry const *condition)
uint32 GetSearcherTypeMaskForConditionList(ConditionContainer const &conditions) const
bool IsObjectMeetingNotGroupedConditions(ConditionSourceType sourceType, uint32 entry, ConditionSourceInfo &sourceInfo) const
static ConditionMgr * instance()
static bool IsMeetingWorldStateExpression(Map const *map, WorldStateExpressionEntry const *expression)
void addToGraveyardData(ConditionId const &id, std::shared_ptr< std::vector< Condition > > conditions) const
bool HasConditionsForNotGroupedEntry(ConditionSourceType sourceType, uint32 entry) const
bool IsObjectMeetToConditionList(ConditionSourceInfo &sourceInfo, ConditionContainer const &conditions) const
bool IsObjectMeetingSpellClickConditions(uint32 creatureId, uint32 spellId, WorldObject const *clicker, WorldObject const *target) const
static bool IsUnitMeetingCondition(Unit const *unit, Unit const *otherUnit, UnitConditionEntry const *condition)
bool HasConditionsForSpellClickEvent(uint32 creatureId, uint32 spellId) const
static void LogUselessConditionValue(Condition const *cond, uint8 index, uint32 value)
bool IsMapMeetingNotGroupedConditions(ConditionSourceType sourceType, uint32 entry, Map const *map) const
bool IsObjectMeetingTrainerSpellConditions(uint32 trainerId, uint32 spellId, Player *player) const
ConditionEntriesByTypeArray ConditionStore
Definition: ConditionMgr.h:360
ConditionContainer const * GetConditionsForAreaTrigger(uint32 areaTriggerId, bool isServerSide) const
void addToSpellImplicitTargetConditions(Condition const &cond) const
void addToPhases(ConditionId const &id, std::shared_ptr< std::vector< Condition > > conditions) const
bool IsObjectMeetingSmartEventConditions(int64 entryOrGuid, uint32 eventId, uint32 sourceType, Unit const *unit, WorldObject const *baseObject) const
static bool CanHaveSourceGroupSet(ConditionSourceType sourceType)
void addToGossipMenuItems(ConditionId const &id, std::shared_ptr< std::vector< Condition > > conditions) const
void addToGossipMenus(ConditionId const &id, std::shared_ptr< std::vector< Condition > > conditions) const
static char const *const StaticSourceTypeData[CONDITION_SOURCE_TYPE_MAX_DB_ALLOWED]
Definition: ConditionMgr.h:342
bool IsObjectMeetingVisibilityByObjectIdConditions(uint32 objectType, uint32 entry, WorldObject const *seer) const
static uint32 GetPlayerConditionLfgValue(Player const *player, PlayerConditionLfgStatus status)
static bool CanHaveConditionType(ConditionSourceType sourceType, ConditionTypes conditionType)
static bool CanHaveSourceIdSet(ConditionSourceType sourceType)
static ConditionTypeInfo const StaticConditionTypeData[CONDITION_MAX]
Definition: ConditionMgr.h:343
bool IsObjectMeetingVehicleSpellConditions(uint32 creatureId, uint32 spellId, Player const *player, Unit const *vehicle) const
void LoadConditions(bool isReload=false)
static bool IsInArea(uint32 objectAreaId, uint32 areaId)
Definition: DB2Stores.cpp:1907
constexpr bool HasFlag(T flag) const
Definition: EnumFlag.h:106
Class used to access individual fields of database query result.
Definition: Field.h:90
uint8 GetUInt8() const
Definition: Field.cpp:30
std::string GetString() const
Definition: Field.cpp:118
bool GetBool() const
Definition: Field.h:98
uint32 GetUInt32() const
Definition: Field.cpp:62
int32 GetInt32() const
Definition: Field.cpp:70
std::vector< GameEventData > GameEventDataMap
Definition: GameEventMgr.h:103
Definition: Group.h:197
bool isRaidGroup() const
Definition: Group.cpp:1638
Definition: Item.h:170
ItemTemplate const * GetTemplate() const
Definition: Item.cpp:1141
LootTemplate * GetLootForConditionFill(uint32 loot_id)
Definition: LootMgr.cpp:229
bool HaveLootFor(uint32 loot_id) const
Definition: LootMgr.h:83
bool isReference(uint32 id)
Definition: LootMgr.cpp:905
bool LinkConditions(ConditionId const &id, ConditionsReference reference)
Definition: LootMgr.cpp:854
Definition: Map.h:189
bool IsBattlegroundOrArena() const
Definition: Map.cpp:3340
BattlegroundMap * ToBattlegroundMap()
Definition: Map.h:457
Difficulty GetDifficultyID() const
Definition: Map.h:324
uint32 GetId() const
Definition: Map.cpp:3228
InstanceMap * ToInstanceMap()
Definition: Map.h:454
WeatherState GetZoneWeather(uint32 zoneId) const
Definition: Map.cpp:3947
bool IsEmpty() const
Definition: ObjectGuid.h:319
static Creature * ToCreature(Object *o)
Definition: Object.h:219
bool IsPlayer() const
Definition: Object.h:212
static Unit * ToUnit(Object *o)
Definition: Object.h:225
static GameObject * ToGameObject(Object *o)
Definition: Object.h:231
TypeID GetTypeId() const
Definition: Object.h:173
uint32 GetEntry() const
Definition: Object.h:161
bool IsCreature() const
Definition: Object.h:218
static ObjectGuid GetGUID(Object const *o)
Definition: Object.h:159
static Player * ToPlayer(Object *o)
Definition: Object.h:213
Definition: Pet.h:40
static bool InDbPhaseShift(WorldObject const *object, uint8 phaseUseFlags, uint16 phaseId, uint32 phaseGroupId)
ChrSpecialization GetPrimarySpecialization() const
Definition: Player.h:1841
UF::UpdateField< UF::PlayerData, 0, TYPEID_PLAYER > m_playerData
Definition: Player.h:2863
Gender GetNativeGender() const override
Definition: Player.h:1217
uint16 GetSkillValue(uint32 skill) const
Definition: Player.cpp:6052
uint16 FindQuestSlot(uint32 quest_id) const
Definition: Player.cpp:16432
bool CanRewardQuest(Quest const *quest, bool msg) const
Definition: Player.cpp:14717
uint32 GetItemCount(uint32 item, bool inBankAlso=false, Item *skipItem=nullptr) const
Definition: Player.cpp:9511
bool HasAchieved(uint32 achievementId) const
Definition: Player.cpp:26751
WorldSession * GetSession() const
Definition: Player.h:2101
Item * GetItemByPos(uint16 pos) const
Definition: Player.cpp:9582
bool ModifierTreeSatisfied(uint32 modifierTreeId) const
Definition: Player.cpp:26789
TeamId GetTeamId() const
Definition: Player.h:2236
bool HasExploredZone(uint32 areaId) const
Definition: Player.cpp:6437
bool IsGameMaster() const
Definition: Player.h:1178
QuestStatus GetQuestStatus(uint32 quest_id) const
Definition: Player.cpp:16050
UF::UpdateField< UF::ActivePlayerData, 0, TYPEID_ACTIVE_PLAYER > m_activePlayerData
Definition: Player.h:2864
static bool IsValidGender(uint8 Gender)
Definition: Player.h:1707
ReputationRank GetReputationRank(uint32 faction_id) const
Definition: Player.cpp:6497
bool HasSpell(uint32 spell) const override
Definition: Player.cpp:3792
Group * GetGroup(Optional< uint8 > partyIndex)
Definition: Player.h:2606
int32 GetQuestSlotObjectiveData(uint16 slot, QuestObjective const &objective) const
Definition: Player.cpp:16470
ChrSpecializationEntry const * GetPrimarySpecializationEntry() const
Definition: Player.cpp:29827
ReputationMgr & GetReputationMgr()
Definition: Player.h:2251
static DrunkenState GetDrunkenstateByValue(uint8 value)
Definition: Player.cpp:876
uint32 GetCurrencyQuantity(uint32 id) const
Definition: Player.cpp:7346
QuestObjectives const & GetObjectives() const
Definition: QuestDef.h:631
ReputationRank const * GetForcedRankIfAny(FactionTemplateEntry const *factionTemplateEntry) const
::Difficulty const Difficulty
Definition: SpellInfo.h:326
uint32 Dispel
Definition: SpellInfo.h:328
SpellSchoolMask GetSchoolMask() const
Definition: SpellInfo.cpp:2465
uint64 GetSpellMechanicMaskByEffectMask(uint32 effectMask) const
Definition: SpellInfo.cpp:2495
SpellEffectInfo const & GetEffect(SpellEffIndex index) const
Definition: SpellInfo.h:577
std::vector< SpellEffectInfo > const & GetEffects() const
Definition: SpellInfo.h:576
size_t GetThreatListSize() const
Utility class to enable range for loop syntax for multimap.equal_range uses.
Definition: IteratorPair.h:32
Definition: Unit.h:627
uint32 GetChannelSpellId() const
Definition: Unit.h:1402
AuraEffectList const & GetAuraEffectsByType(AuraType type) const
Definition: Unit.h:1321
float GetHealthPct() const
Definition: Unit.h:784
uint32 GetUnitMovementFlags() const
Definition: Unit.h:1664
ThreatManager & GetThreatManager()
Definition: Unit.h:1063
bool HasAuraTypeWithMiscvalue(AuraType auraType, int32 miscValue) const
Definition: Unit.cpp:4687
uint8 GetClass() const
Definition: Unit.h:752
std::array< ObjectGuid, MAX_SUMMON_SLOT > m_SummonSlot
Definition: Unit.h:1460
uint32 GetClassMask() const
Definition: Unit.h:754
uint32 GetMountDisplayId() const
Definition: Unit.h:899
ObjectGuid GetOwnerGUID() const override
Definition: Unit.h:1170
bool HasUnitFlag(UnitFlags flags) const
Definition: Unit.h:832
ObjectGuid GetCharmedGUID() const
Definition: Unit.h:1190
float GetCombatReach() const override
Definition: Unit.h:694
int32 GetMaxPower(Powers power) const
Definition: Unit.cpp:9410
ObjectGuid GetCharmerOrOwnerGUID() const override
Definition: Unit.h:1195
virtual bool HasSpell(uint32) const
Definition: Unit.h:1069
ObjectGuid GetCreatorGUID() const override
Definition: Unit.h:1172
bool IsOnVehicle(Unit const *vehicle) const
Definition: Unit.cpp:11475
Gender GetGender() const
Definition: Unit.h:755
uint32 GetCreatureType() const
Definition: Unit.cpp:8880
bool HasNegativeAuraWithInterruptFlag(InterruptFlags flag, ObjectGuid guid=ObjectGuid::Empty) const
Definition: Unit.cpp:4723
uint32 GetVirtualItemId(uint32 slot) const
Definition: Unit.cpp:13588
uint32 GetAuraCount(uint32 spellId) const
Definition: Unit.cpp:4648
bool IsHovering() const
Definition: Unit.h:1137
ObjectGuid GetMinionGUID() const
Definition: Unit.h:1174
bool HasUnitMovementFlag(uint32 f) const
Definition: Unit.h:1663
uint64 GetHealth() const
Definition: Unit.h:776
AttackerSet const & getAttackers() const
Definition: Unit.h:713
bool HasAuraType(AuraType auraType) const
Definition: Unit.cpp:4674
ObjectGuid GetCritterGUID() const
Definition: Unit.h:1178
uint32 GetExtraUnitMovementFlags() const
Definition: Unit.h:1670
int32 GetPower(Powers power) const
Definition: Unit.cpp:9401
bool IsInRaidWith(Unit const *unit) const
Definition: Unit.cpp:11546
float GetPowerPct(Powers power) const
Definition: Unit.h:807
bool HasAura(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0) const
Definition: Unit.cpp:4664
ObjectGuid GetCharmerGUID() const
Definition: Unit.h:1187
bool IsFlying() const
Definition: Unit.h:1735
AuraApplication * GetAuraApplication(uint32 spellId, ObjectGuid casterGUID=ObjectGuid::Empty, ObjectGuid itemCasterGUID=ObjectGuid::Empty, uint32 reqEffMask=0, AuraApplication *except=nullptr) const
Definition: Unit.cpp:4506
bool IsInPartyWith(Unit const *unit) const
Definition: Unit.cpp:11527
ObjectGuid GetTarget() const
Definition: Unit.h:1759
uint8 GetLevel() const
Definition: Unit.h:746
uint8 GetRace() const
Definition: Unit.h:749
bool IsInCombat() const
Definition: Unit.h:1043
Spell * GetCurrentSpell(CurrentSpellTypes spellType) const
Definition: Unit.h:1442
constexpr uint32 GetMapId() const
Definition: Position.h:201
Map * GetMap() const
Definition: Object.h:624
bool IsValidAttackTarget(WorldObject const *target, SpellInfo const *bySpell=nullptr) const
Definition: Object.cpp:2991
ReputationRank GetReactionTo(WorldObject const *target) const
Definition: Object.cpp:2707
bool IsValidAssistTarget(WorldObject const *target, SpellInfo const *bySpell=nullptr) const
Definition: Object.cpp:3144
float GetDistance(WorldObject const *obj) const
Definition: Object.cpp:1078
uint32 GetAreaId() const
Definition: Object.h:546
uint32 GetZoneId() const
Definition: Object.h:545
uint8 GetExpansion() const
void SetPackedTime(uint32 packedTime)
Definition: WowTime.cpp:34
bool IsInRange(WowTime const &from, WowTime const &to) const
Definition: WowTime.cpp:173
virtual uint32 GetData(uint32) const
Definition: ZoneScript.h:91
virtual uint64 GetData64(uint32) const
Definition: ZoneScript.h:87
#define sWorld
Definition: World.h:931
WeatherState
Definition: Weather.h:46
Realm realm
Definition: World.cpp:3966
@ CONFIG_EXPANSION
Definition: World.h:308
ObjectData const creatureData[]
@ DEFAULT_MAX_BATTLE_PETS_PER_SPECIES
Definition: BattlePetMgr.h:32
WowTime const * GetWowTime()
Definition: GameTime.cpp:97
tm const * GetDateAndTime()
Definition: GameTime.cpp:87
time_t GetGameTime()
Definition: GameTime.cpp:44
TC_GAME_API Unit * GetUnit(WorldObject const &, ObjectGuid const &guid)
TC_COMMON_API void HexStrToByteArray(std::string_view str, uint8 *out, size_t outlen, bool reverse=false)
Definition: Util.cpp:871
constexpr TypeMask ConvertLegacyTypeMask(uint32 legacyTypeMask)
Definition: ObjectGuid.h:482
constexpr ::TypeID ConvertLegacyTypeID(TypeID legacyTypeID)
Definition: ObjectGuid.h:451
void hash_combine(std::size_t &seed, T const &val)
Definition: Hash.h:28
constexpr std::size_t size()
Definition: UpdateField.h:796
TC_PROTO_API ::google::protobuf::internal::ExtensionIdentifier< ::google::protobuf::FieldOptions, ::google::protobuf::internal::MessageTypeTraits< ::bgs::protocol::FieldRestriction >, 11, false > valid
uint16 ParentAreaID
Definition: DB2Structure.h:131
EnumFlag< AreaFlags > GetFlags() const
Definition: DB2Structure.h:153
EnumFlag< ChrSpecializationFlag > GetFlags() const
Definition: DB2Structure.h:872
ChrSpecializationRole GetRole() const
Definition: DB2Structure.h:873
std::size_t GetHash() const
uint32 SourceGroup
Definition: ConditionMgr.h:229
uint32 SourceId
Definition: ConditionMgr.h:231
int32 SourceEntry
Definition: ConditionMgr.h:230
ConditionSourceInfo(WorldObject const *target0, WorldObject const *target1=nullptr, WorldObject const *target2=nullptr)
Condition const * mLastFailedCondition
Definition: ConditionMgr.h:222
WorldObject const * mConditionTargets[MAX_CONDITION_TARGETS]
Definition: ConditionMgr.h:220
Map const * mConditionMap
Definition: ConditionMgr.h:221
uint32 SourceGroup
Definition: ConditionMgr.h:247
ConditionTypes ConditionType
Definition: ConditionMgr.h:251
std::string ToString(bool ext=false) const
std::string ConditionStringValue1
Definition: ConditionMgr.h:255
uint32 GetSearcherTypeMaskForCondition() const
uint32 ErrorType
Definition: ConditionMgr.h:256
uint32 SourceId
Definition: ConditionMgr.h:249
int32 SourceEntry
Definition: ConditionMgr.h:248
uint32 ElseGroup
Definition: ConditionMgr.h:250
uint32 ScriptId
Definition: ConditionMgr.h:259
bool NegativeCondition
Definition: ConditionMgr.h:261
ConditionSourceType SourceType
Definition: ConditionMgr.h:246
uint32 ConditionValue2
Definition: ConditionMgr.h:253
uint8 ConditionTarget
Definition: ConditionMgr.h:260
uint32 ReferenceId
Definition: ConditionMgr.h:258
uint32 ErrorTextId
Definition: ConditionMgr.h:257
uint32 ConditionValue3
Definition: ConditionMgr.h:254
uint32 GetMaxAvailableConditionTargets() const
uint32 ConditionValue1
Definition: ConditionMgr.h:252
bool Meets(ConditionSourceInfo &sourceInfo) const
uint32 GetSubClass() const
Definition: ItemTemplate.h:778
std::array< int32, 4 > AuraSpellID
std::array< int32, 4 > TraitNodeEntryID
std::array< uint32, 4 > ItemCount
std::array< uint32, 2 > Time
std::array< uint32, 4 > LfgValue
std::array< uint8, 4 > LfgCompare
std::array< uint16, 4 > MaxSkill
std::array< uint16, 4 > TraitNodeEntryMaxRank
std::array< uint16, 4 > Achievement
uint32 CurrentCompletedQuestLogic
std::array< int32, 4 > CurrentCompletedQuestID
std::array< uint8, 4 > LfgStatus
std::array< int32, 4 > PrevQuestID
std::array< int32, 4 > CurrQuestID
std::array< uint16, 4 > SkillID
std::array< int32, 2 > MovementFlags
std::array< uint16, 2 > Explored
std::array< uint32, 3 > MinFactionID
std::array< uint32, 4 > CurrencyCount
std::array< uint8, 4 > AuraStacks
std::array< uint16, 4 > AreaID
std::array< uint32, 6 > QuestKillMonster
std::array< uint16, 4 > MinSkill
std::array< uint8, 3 > MinReputation
std::array< uint16, 4 > TraitNodeEntryMinRank
std::array< int32, 4 > ItemID
Trinity::RaceMask< int64 > RaceMask
std::array< int32, 4 > SpellID
std::array< uint32, 4 > CurrencyID
float GetExactDist(float x, float y, float z) const
Definition: Position.h:118
constexpr float GetExactDistSq(float x, float y, float z) const
Definition: Position.h:110
bool IsStoringFlag() const
Definition: QuestDef.h:479
uint32 QuestID
Definition: QuestDef.h:446
int32 Amount
Definition: QuestDef.h:450
Battlenet::RealmHandle Id
Definition: Realm.h:82
SpawnGroupFlags flags
Definition: SpawnData.h:70
constexpr bool HasRace(uint8 raceId) const
Definition: RaceMask.h:88
constexpr bool IsEmpty() const
Definition: RaceMask.h:143
UpdateField< int32, 4, 5 > Type
Definition: UpdateFields.h:736
UpdateField< int32, 8, 9 > CombatConfigFlags
Definition: UpdateFields.h:739
DynamicUpdateField< UF::TraitEntry, 0, 1 > Entries
Definition: UpdateFields.h:733
UpdateField< int32, 0, 2 > ID
Definition: UpdateFields.h:734
int32 TraitNodeEntryID
Definition: UpdateFields.h:721
EnumFlag< UnitConditionFlags > GetFlags() const
std::array< int32, MAX_UNIT_CONDITION_VALUES > Value
std::array< int8, MAX_UNIT_CONDITION_VALUES > Op
std::array< uint8, MAX_UNIT_CONDITION_VALUES > Variable
Reward info.
Definition: LFGMgr.h:234