TrinityCore
Loading...
Searching...
No Matches
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 "DBCStores.h"
21#include "DatabaseEnv.h"
22#include "GameEventMgr.h"
23#include "GameObject.h"
24#include "Group.h"
25#include "InstanceScript.h"
26#include "Log.h"
27#include "LootMgr.h"
28#include "Map.h"
29#include "ObjectMgr.h"
30#include "Player.h"
31#include "Pet.h"
32#include "ReputationMgr.h"
33#include "ScriptMgr.h"
34#include "SpellAuras.h"
35#include "SpellMgr.h"
36#include "World.h"
37
39{
40 "None",
41 "Creature Loot",
42 "Disenchant Loot",
43 "Fishing Loot",
44 "GameObject Loot",
45 "Item Loot",
46 "Mail Loot",
47 "Milling Loot",
48 "Pickpocketing Loot",
49 "Prospecting Loot",
50 "Reference Loot",
51 "Skinning Loot",
52 "Spell Loot",
53 "Spell Impl. Target",
54 "Gossip Menu",
55 "Gossip Menu Option",
56 "Creature Vehicle",
57 "Spell Expl. Target",
58 "Spell Click Event",
59 "Quest Accept",
60 "Quest Show Mark",
61 "Vehicle Spell",
62 "SmartScript",
63 "Npc Vendor",
64 "Spell Proc",
65 "Terrain Swap",
66 "Phase"
67};
68
70{
71 { "None", false, false, false, false },
72 { "Aura", true, true, true, false },
73 { "Item Stored", true, true, true, false },
74 { "Item Equipped", true, false, false, false },
75 { "Zone", true, false, false, false },
76 { "Reputation", true, true, false, false },
77 { "Team", true, false, false, false },
78 { "Skill", true, true, false, false },
79 { "Quest Rewarded", true, false, false, false },
80 { "Quest Taken", true, false, false, false },
81 { "Drunken", true, false, false, false },
82 { "WorldState", true, true, false, false },
83 { "Active Event", true, false, false, false },
84 { "Instance Info", true, true, true, false },
85 { "Quest None", true, false, false, false },
86 { "Class", true, false, false, false },
87 { "Race", true, false, false, false },
88 { "Achievement", true, false, false, false },
89 { "Title", true, false, false, false },
90 { "SpawnMask", true, false, false, false },
91 { "Gender", true, false, false, false },
92 { "Unit State", true, false, false, false },
93 { "Map", true, false, false, false },
94 { "Area", true, false, false, false },
95 { "CreatureType", true, false, false, false },
96 { "Spell Known", true, false, false, false },
97 { "PhaseMask", true, false, false, false },
98 { "Level", true, true, false, false },
99 { "Quest Completed", true, false, false, false },
100 { "Near Creature", true, true, true, false },
101 { "Near GameObject", true, true, false, false },
102 { "Object Entry or Guid", true, true, true, false },
103 { "Object TypeMask", true, false, false, false },
104 { "Relation", true, true, false, false },
105 { "Reaction", true, true, false, false },
106 { "Distance", true, true, true, false },
107 { "Alive", false, false, false, false },
108 { "Health Value", true, true, false, false },
109 { "Health Pct", true, true, false, false },
110 { "Realm Achievement", true, false, false, false },
111 { "In Water", false, false, false, false },
112 { "Terrain Swap", false, false, false, false },
113 { "Sit/stand state", true, true, false, false },
114 { "Daily Quest Completed", true, false, false, false },
115 { "Charmed", false, false, false, false },
116 { "Pet type", true, false, false, false },
117 { "On Taxi", false, false, false, false },
118 { "Quest state mask", true, true, false, false },
119 { "Quest objective progress", true, true, true, false },
120 { "Map Difficulty", true, false, false, false },
121 { "Is Gamemaster", true, false, false, false },
122 { "Object Entry or Guid", true, true, true, false },
123 { "Object TypeMask", true, false, false, false },
124 { "BattlePet Species Learned", true, true, true, false },
125 { "On Scenario Step", true, false, false, false },
126 { "Scene In Progress", true, false, false, false },
127 { "Player Condition", true, false, false, false },
128 { "Private Object", false, false, false, false },
129 { "String ID", false, false, false, true },
130 { "Label", false, false, false, false },
131 { "Group status", true, false, false, false }
132};
133
134static bool MeetsGroupStatusCondition(Player const* player, GroupStatusCondition status)
135{
136 Group const* group = player->GetGroup();
137 switch (status)
138 {
140 return group == nullptr;
142 return group != nullptr;
144 return group && !group->isRaidGroup();
146 return group && group->isRaidGroup();
148 return !group || !group->isRaidGroup();
149 }
150 return false;
151}
152
153// Checks if object meets the condition
154// Can have CONDITION_SOURCE_TYPE_NONE && !mReferenceId if called from a special event (ie: SmartAI)
156{
158 WorldObject* object = sourceInfo.mConditionTargets[ConditionTarget];
159 // object not present, return false
160 if (!object)
161 {
162 TC_LOG_DEBUG("condition", "Condition object not found for {}", ToString());
163 return false;
164 }
165 bool condMeets = false;
166 switch (ConditionType)
167 {
168 case CONDITION_NONE:
169 condMeets = true; // empty condition, always met
170 break;
171 case CONDITION_AURA:
172 {
173 if (Unit* unit = object->ToUnit())
174 condMeets = unit->HasAuraEffect(ConditionValue1, ConditionValue2);
175 break;
176 }
177 case CONDITION_ITEM:
178 {
179 if (Player* player = object->ToPlayer())
180 {
181 // don't allow 0 items (it's checked during table load)
183 bool checkBank = ConditionValue3 ? true : false;
184 condMeets = player->HasItemCount(ConditionValue1, ConditionValue2, checkBank);
185 }
186 break;
187 }
189 {
190 if (Player* player = object->ToPlayer())
191 condMeets = player->HasItemOrGemWithIdEquipped(ConditionValue1, 1);
192 break;
193 }
194 case CONDITION_ZONEID:
195 condMeets = object->GetZoneId() == ConditionValue1;
196 break;
198 {
199 if (Player* player = object->ToPlayer())
200 {
201 if (FactionEntry const* faction = sFactionStore.LookupEntry(ConditionValue1))
202 condMeets = (ConditionValue2 & (1 << player->GetReputationMgr().GetRank(faction))) != 0;
203 }
204 break;
205 }
207 {
208 if (Player* player = object->ToPlayer())
209 condMeets = player->HasAchieved(ConditionValue1);
210 break;
211 }
212 case CONDITION_TEAM:
213 {
214 if (Player* player = object->ToPlayer())
215 condMeets = player->GetTeam() == ConditionValue1;
216 break;
217 }
218 case CONDITION_CLASS:
219 {
220 if (Unit* unit = object->ToUnit())
221 condMeets = (unit->GetClassMask() & ConditionValue1) != 0;
222 break;
223 }
224 case CONDITION_RACE:
225 {
226 if (Unit* unit = object->ToUnit())
227 condMeets = (unit->GetRaceMask() & ConditionValue1) != 0;
228 break;
229 }
230 case CONDITION_GENDER:
231 {
232 if (Player* player = object->ToPlayer())
233 condMeets = player->GetNativeGender() == Gender(ConditionValue1);
234 break;
235 }
236 case CONDITION_SKILL:
237 {
238 if (Player* player = object->ToPlayer())
239 condMeets = player->HasSkill(ConditionValue1) && player->GetBaseSkillValue(ConditionValue1) >= ConditionValue2;
240 break;
241 }
243 {
244 if (Player* player = object->ToPlayer())
245 condMeets = player->GetQuestRewardStatus(ConditionValue1);
246 break;
247 }
249 {
250 if (Player* player = object->ToPlayer())
251 {
252 QuestStatus status = player->GetQuestStatus(ConditionValue1);
253 condMeets = (status == QUEST_STATUS_INCOMPLETE);
254 }
255 break;
256 }
258 {
259 if (Player* player = object->ToPlayer())
260 {
261 QuestStatus status = player->GetQuestStatus(ConditionValue1);
262 condMeets = (status == QUEST_STATUS_COMPLETE && !player->GetQuestRewardStatus(ConditionValue1));
263 }
264 break;
265 }
267 {
268 if (Player* player = object->ToPlayer())
269 {
270 QuestStatus status = player->GetQuestStatus(ConditionValue1);
271 condMeets = (status == QUEST_STATUS_NONE);
272 }
273 break;
274 }
276 condMeets = sGameEventMgr->IsActiveEvent(ConditionValue1);
277 break;
279 {
280 Map* map = object->GetMap();
281 if (map->IsDungeon())
282 {
283 if (InstanceScript const* instance = ((InstanceMap*)map)->GetInstanceScript())
284 {
285 switch (ConditionValue3)
286 {
288 condMeets = instance->GetData(ConditionValue1) == ConditionValue2;
289 break;
291 condMeets = instance->GetGuidData(ConditionValue1).GetRawValue() == uint64(ConditionValue2);
292 break;
294 condMeets = instance->GetBossState(ConditionValue1) == EncounterState(ConditionValue2);
295 break;
297 condMeets = instance->GetData64(ConditionValue1) == ConditionValue2;
298 break;
299 }
300 }
301 }
302 break;
303 }
304 case CONDITION_MAPID:
305 condMeets = object->GetMapId() == ConditionValue1;
306 break;
307 case CONDITION_AREAID:
308 condMeets = object->GetAreaId() == ConditionValue1;
309 break;
310 case CONDITION_SPELL:
311 {
312 if (Player* player = object->ToPlayer())
313 condMeets = player->HasSpell(ConditionValue1);
314 break;
315 }
316 case CONDITION_LEVEL:
317 {
318 if (Unit* unit = object->ToUnit())
319 condMeets = CompareValues(static_cast<ComparisionType>(ConditionValue2), static_cast<uint32>(unit->GetLevel()), ConditionValue1);
320 break;
321 }
323 {
324 if (Player* player = object->ToPlayer())
325 condMeets = (uint32)Player::GetDrunkenstateByValue(player->GetDrunkValue()) >= ConditionValue1;
326 break;
327 }
329 {
330 condMeets = object->FindNearestCreature(ConditionValue1, (float)ConditionValue2, bool(!ConditionValue3)) != nullptr;
331 break;
332 }
334 {
335 condMeets = object->FindNearestGameObject(ConditionValue1, (float)ConditionValue2) != nullptr;
336 break;
337 }
339 {
340 if (uint32(object->GetTypeId()) == ConditionValue1)
341 {
342 condMeets = !ConditionValue2 || (object->GetEntry() == ConditionValue2);
343
344 if (ConditionValue3)
345 {
346 switch (object->GetTypeId())
347 {
348 case TYPEID_UNIT:
349 condMeets &= object->ToCreature()->GetSpawnId() == ConditionValue3;
350 break;
352 condMeets &= object->ToGameObject()->GetSpawnId() == ConditionValue3;
353 break;
354 default:
355 break;
356 }
357 }
358 }
359 break;
360 }
362 {
363 condMeets = object->isType(ConditionValue1);
364 break;
365 }
367 {
368 if (WorldObject* toObject = sourceInfo.mConditionTargets[ConditionValue1])
369 {
370 Unit* toUnit = toObject->ToUnit();
371 Unit* unit = object->ToUnit();
372 if (toUnit && unit)
373 {
374 switch (static_cast<RelationType>(ConditionValue2))
375 {
376 case RELATION_SELF:
377 condMeets = unit == toUnit;
378 break;
380 condMeets = unit->IsInPartyWith(toUnit);
381 break;
383 condMeets = unit->IsInRaidWith(toUnit);
384 break;
386 condMeets = unit->GetOwnerGUID() == toUnit->GetGUID();
387 break;
389 condMeets = unit->IsOnVehicle(toUnit);
390 break;
392 condMeets = unit->GetCreatorGUID() == toUnit->GetGUID();
393 break;
394 default:
395 break;
396 }
397 }
398 }
399 break;
400 }
402 {
403 if (WorldObject* toObject = sourceInfo.mConditionTargets[ConditionValue1])
404 {
405 Unit* toUnit = toObject->ToUnit();
406 Unit* unit = object->ToUnit();
407 if (toUnit && unit)
408 condMeets = ((1 << unit->GetReactionTo(toUnit)) & ConditionValue2) != 0;
409 }
410 break;
411 }
413 {
414 if (WorldObject* toObject = sourceInfo.mConditionTargets[ConditionValue1])
415 condMeets = CompareValues(static_cast<ComparisionType>(ConditionValue3), object->GetDistance(toObject), static_cast<float>(ConditionValue2));
416 break;
417 }
418 case CONDITION_ALIVE:
419 {
420 if (Unit* unit = object->ToUnit())
421 condMeets = unit->IsAlive();
422 break;
423 }
424 case CONDITION_HP_VAL:
425 {
426 if (Unit* unit = object->ToUnit())
427 condMeets = CompareValues(static_cast<ComparisionType>(ConditionValue2), unit->GetHealth(), static_cast<uint32>(ConditionValue1));
428 break;
429 }
430 case CONDITION_HP_PCT:
431 {
432 if (Unit* unit = object->ToUnit())
433 condMeets = CompareValues(static_cast<ComparisionType>(ConditionValue2), unit->GetHealthPct(), static_cast<float>(ConditionValue1));
434 break;
435 }
437 {
438 condMeets = ConditionValue2 == sWorld->getWorldState(ConditionValue1);
439 break;
440 }
442 {
443 condMeets = (object->GetPhaseMask() & ConditionValue1) != 0;
444 break;
445 }
446 case CONDITION_TITLE:
447 {
448 if (Player* player = object->ToPlayer())
449 condMeets = player->HasTitle(ConditionValue1);
450 break;
451 }
453 {
454 condMeets = ((1 << object->GetMap()->GetSpawnMode()) & ConditionValue1) != 0;
455 break;
456 }
458 {
459 if (Unit* unit = object->ToUnit())
460 condMeets = unit->HasUnitState(ConditionValue1);
461 break;
462 }
464 {
465 if (Creature* creature = object->ToCreature())
466 condMeets = creature->GetCreatureTemplate()->type == ConditionValue1;
467 break;
468 }
470 {
471 AchievementEntry const* achievement = sAchievementStore.LookupEntry(ConditionValue1);
472 if (achievement && sAchievementMgr->IsRealmCompleted(achievement))
473 condMeets = true;
474 break;
475 }
477 {
478 if (Unit* unit = object->ToUnit())
479 condMeets = unit->IsInWater();
480 break;
481 }
483 {
484 if (Unit* unit = object->ToUnit())
485 {
486 if (ConditionValue1 == 0)
487 condMeets = (unit->GetStandState() == ConditionValue2);
488 else if (ConditionValue2 == 0)
489 condMeets = unit->IsStandState();
490 else if (ConditionValue2 == 1)
491 condMeets = unit->IsSitState();
492 }
493 break;
494 }
496 {
497 if (Player* player = object->ToPlayer())
498 condMeets = player->IsDailyQuestDone(ConditionValue1);
499 break;
500 }
502 {
503 if (Unit* unit = object->ToUnit())
504 condMeets = unit->IsCharmed();
505 break;
506 }
508 {
509 if (Player* player = object->ToPlayer())
510 if (Pet* pet = player->GetPet())
511 condMeets = (((1 << pet->getPetType()) & ConditionValue1) != 0);
512 break;
513 }
514 case CONDITION_TAXI:
515 {
516 if (Player* player = object->ToPlayer())
517 condMeets = player->IsInFlight();
518 break;
519 }
521 {
522 if (Player* player = object->ToPlayer())
523 {
524 if (
525 ((ConditionValue2 & (1 << QUEST_STATUS_NONE)) && (player->GetQuestStatus(ConditionValue1) == QUEST_STATUS_NONE)) ||
526 ((ConditionValue2 & (1 << QUEST_STATUS_COMPLETE)) && (player->GetQuestStatus(ConditionValue1) == QUEST_STATUS_COMPLETE)) ||
527 ((ConditionValue2 & (1 << QUEST_STATUS_INCOMPLETE)) && (player->GetQuestStatus(ConditionValue1) == QUEST_STATUS_INCOMPLETE)) ||
528 ((ConditionValue2 & (1 << QUEST_STATUS_FAILED)) && (player->GetQuestStatus(ConditionValue1) == QUEST_STATUS_FAILED)) ||
529 ((ConditionValue2 & (1 << QUEST_STATUS_REWARDED)) && player->GetQuestRewardStatus(ConditionValue1))
530 )
531 condMeets = true;
532 }
533 break;
534 }
536 {
537 if (Player* player = object->ToPlayer())
538 {
539 const Quest* quest = ASSERT_NOTNULL(sObjectMgr->GetQuestTemplate(ConditionValue1));
540 uint16 log_slot = player->FindQuestSlot(quest->GetQuestId());
541 if (log_slot >= MAX_QUEST_LOG_SIZE)
542 break;
543 if (player->GetQuestSlotCounter(log_slot, ConditionValue2) == ConditionValue3)
544 condMeets = true;
545 }
546 break;
547 }
549 {
550 condMeets = object->GetMap()->GetDifficultyID() == ConditionValue1;
551 break;
552 }
554 {
555 if (Player* player = object->ToPlayer())
556 {
557 if (ConditionValue1 == 1)
558 condMeets = player->CanBeGameMaster();
559 else
560 condMeets = player->IsGameMaster();
561 }
562 break;
563 }
565 {
566 if (Creature const* creature = object->ToCreature())
567 condMeets = creature->HasStringId(ConditionStringValue1);
568 else if (GameObject const* go = object->ToGameObject())
569 condMeets = go->HasStringId(ConditionStringValue1);
570 break;
571 }
573 {
574 if (Player const* player = object->ToPlayer())
576 break;
577 }
578 default:
579 condMeets = false;
580 break;
581 }
582
584 condMeets = !condMeets;
585
586 if (!condMeets)
587 sourceInfo.mLastFailedCondition = this;
588
589 return condMeets && sScriptMgr->OnConditionCheck(this, sourceInfo); // Returns true by default.;
590}
591
593{
594 // build mask of types for which condition can return true
595 // this is used for speeding up gridsearches
597 return (GRID_MAP_TYPE_MASK_ALL);
598 uint32 mask = 0;
599 switch (ConditionType)
600 {
601 case CONDITION_NONE:
603 break;
604 case CONDITION_AURA:
606 break;
607 case CONDITION_ITEM:
609 break;
612 break;
613 case CONDITION_ZONEID:
615 break;
618 break;
621 break;
622 case CONDITION_TEAM:
624 break;
625 case CONDITION_CLASS:
627 break;
628 case CONDITION_RACE:
630 break;
631 case CONDITION_SKILL:
633 break;
636 break;
639 break;
642 break;
645 break;
648 break;
651 break;
652 case CONDITION_MAPID:
654 break;
655 case CONDITION_AREAID:
657 break;
658 case CONDITION_SPELL:
660 break;
661 case CONDITION_LEVEL:
663 break;
666 break;
669 break;
672 break;
674 switch (ConditionValue1)
675 {
676 case TYPEID_UNIT:
678 break;
679 case TYPEID_PLAYER:
681 break;
684 break;
685 case TYPEID_CORPSE:
687 break;
688 default:
689 break;
690 }
691 break;
701 break;
704 break;
707 break;
710 break;
711 case CONDITION_ALIVE:
713 break;
714 case CONDITION_HP_VAL:
716 break;
717 case CONDITION_HP_PCT:
719 break;
722 break;
725 break;
726 case CONDITION_TITLE:
728 break;
731 break;
732 case CONDITION_GENDER:
734 break;
737 break;
740 break;
743 break;
746 break;
749 break;
752 break;
755 break;
758 break;
759 case CONDITION_TAXI:
761 break;
764 break;
767 break;
770 break;
773 break;
775 mask |= GRID_MAP_TYPE_MASK_ALL & ~GRID_MAP_TYPE_MASK_PLAYER;
776 break;
779 break;
782 break;
783 default:
784 ABORT_MSG("Condition::GetSearcherTypeMaskForCondition - missing condition handling!");
785 break;
786 }
787 return mask;
788}
789
810
811std::string Condition::ToString(bool ext /*= false*/) const
812{
813 std::ostringstream ss;
814 ss << "[Condition ";
815 ss << "SourceType: " << SourceType;
818 else
819 ss << " (Unknown)";
821 ss << ", SourceGroup: " << SourceGroup;
822 ss << ", SourceEntry: " << SourceEntry;
824 ss << ", SourceId: " << SourceId;
825
826 if (ext)
827 {
828 ss << ", ConditionType: " << ConditionType;
831 else
832 ss << " (Unknown)";
833 }
834
835 ss << "]";
836 return ss.str();
837}
838
840
845
847{
848 if (conditions.empty())
850 // groupId, typeMask
851 std::map<uint32, uint32> elseGroupSearcherTypeMasks;
852 for (ConditionContainer::const_iterator i = conditions.begin(); i != conditions.end(); ++i)
853 {
854 // no point of having not loaded conditions in list
855 ASSERT((*i)->isLoaded() && "ConditionMgr::GetSearcherTypeMaskForConditionList - not yet loaded condition found in list");
856 std::map<uint32, uint32>::const_iterator itr = elseGroupSearcherTypeMasks.find((*i)->ElseGroup);
857 // group not filled yet, fill with widest mask possible
858 if (itr == elseGroupSearcherTypeMasks.end())
859 elseGroupSearcherTypeMasks[(*i)->ElseGroup] = GRID_MAP_TYPE_MASK_ALL;
860 // no point of checking anymore, empty mask
861 else if (!itr->second)
862 continue;
863
864 if ((*i)->ReferenceId) // handle reference
865 {
866 ConditionReferenceContainer::const_iterator ref = ConditionReferenceStore.find((*i)->ReferenceId);
867 ASSERT(ref != ConditionReferenceStore.end() && "ConditionMgr::GetSearcherTypeMaskForConditionList - incorrect reference");
868 elseGroupSearcherTypeMasks[(*i)->ElseGroup] &= GetSearcherTypeMaskForConditionList((*ref).second);
869 }
870 else // handle normal condition
871 {
872 // object will match conditions in one ElseGroupStore only when it matches all of them
873 // so, let's find a smallest possible mask which satisfies all conditions
874 elseGroupSearcherTypeMasks[(*i)->ElseGroup] &= (*i)->GetSearcherTypeMaskForCondition();
875 }
876 }
877 // object will match condition when one of the checks in ElseGroupStore is matching
878 // so, let's include all possible masks
879 uint32 mask = 0;
880 for (std::map<uint32, uint32>::const_iterator i = elseGroupSearcherTypeMasks.begin(); i != elseGroupSearcherTypeMasks.end(); ++i)
881 mask |= i->second;
882
883 return mask;
884}
885
887{
888 // groupId, groupCheckPassed
889 std::map<uint32, bool> elseGroupStore;
890 for (Condition const* condition : conditions)
891 {
892 TC_LOG_DEBUG("condition", "ConditionMgr::IsPlayerMeetToConditionList {} val1: {}", condition->ToString(), condition->ConditionValue1);
893 if (condition->isLoaded())
894 {
896 std::map<uint32, bool>::const_iterator itr = elseGroupStore.find(condition->ElseGroup);
898 if (itr == elseGroupStore.end())
899 elseGroupStore[condition->ElseGroup] = true;
900 else if (!(*itr).second)
901 continue;
902
903 if (condition->ReferenceId)//handle reference
904 {
905 ConditionReferenceContainer::const_iterator ref = ConditionReferenceStore.find(condition->ReferenceId);
906 if (ref != ConditionReferenceStore.end())
907 {
908 if (!IsObjectMeetToConditionList(sourceInfo, ref->second))
909 elseGroupStore[condition->ElseGroup] = false;
910 }
911 else
912 {
913 TC_LOG_DEBUG("condition", "ConditionMgr::IsPlayerMeetToConditionList {} Reference template -{} not found",
914 condition->ToString(), condition->ReferenceId); // checked at loading, should never happen
915 }
916
917 }
918 else //handle normal condition
919 {
920 if (!condition->Meets(sourceInfo))
921 elseGroupStore[condition->ElseGroup] = false;
922 }
923 }
924 }
925 for (std::map<uint32, bool>::const_iterator i = elseGroupStore.begin(); i != elseGroupStore.end(); ++i)
926 if (i->second)
927 return true;
928
929 return false;
930}
931
933{
935 return IsObjectMeetToConditions(srcInfo, conditions);
936}
937
939{
940 ConditionSourceInfo srcInfo = ConditionSourceInfo(object1, object2);
941 return IsObjectMeetToConditions(srcInfo, conditions);
942}
943
945{
946 if (conditions.empty())
947 return true;
948
949 TC_LOG_DEBUG("condition", "ConditionMgr::IsObjectMeetToConditions");
950 return IsObjectMeetToConditionList(sourceInfo, conditions);
951}
952
975
980
982{
983 if (sourceType > CONDITION_SOURCE_TYPE_NONE && sourceType < CONDITION_SOURCE_TYPE_MAX)
984 {
985 ConditionsByEntryMap::const_iterator i = ConditionStore[sourceType].find(entry);
986 if (i != ConditionStore[sourceType].end())
987 {
988 TC_LOG_DEBUG("condition", "GetConditionsForNotGroupedEntry: found conditions for type {} and entry {}", uint32(sourceType), entry);
989 return IsObjectMeetToConditions(sourceInfo, i->second);
990 }
991 }
992
993 return true;
994}
995
996bool ConditionMgr::IsObjectMeetingNotGroupedConditions(ConditionSourceType sourceType, uint32 entry, WorldObject* target0, WorldObject* target1 /*= nullptr*/, WorldObject* target2 /*= nullptr*/) const
997{
998 ConditionSourceInfo conditionSource(target0, target1, target2);
999 return IsObjectMeetingNotGroupedConditions(sourceType, entry, conditionSource);
1000}
1001
1003{
1004 if (sourceType > CONDITION_SOURCE_TYPE_NONE && sourceType < CONDITION_SOURCE_TYPE_MAX)
1005 if (ConditionStore[sourceType].find(entry) != ConditionStore[sourceType].end())
1006 return true;
1007
1008 return false;
1009}
1010
1012{
1013 ConditionEntriesByCreatureIdMap::const_iterator itr = SpellClickEventConditionStore.find(creatureId);
1014 if (itr != SpellClickEventConditionStore.end())
1015 {
1016 ConditionsByEntryMap::const_iterator i = itr->second.find(spellId);
1017 if (i != itr->second.end())
1018 {
1019 TC_LOG_DEBUG("condition", "GetConditionsForSpellClickEvent: found conditions for SpellClickEvent entry {} spell {}", creatureId, spellId);
1020 ConditionSourceInfo sourceInfo(clicker, target);
1021 return IsObjectMeetToConditions(sourceInfo, i->second);
1022 }
1023 }
1024 return true;
1025}
1026
1028{
1029 ConditionEntriesByCreatureIdMap::const_iterator itr = SpellClickEventConditionStore.find(creatureId);
1030 if (itr != SpellClickEventConditionStore.end())
1031 {
1032 ConditionsByEntryMap::const_iterator i = itr->second.find(spellId);
1033 if (i != itr->second.end())
1034 {
1035 TC_LOG_DEBUG("condition", "GetConditionsForSpellClickEvent: found conditions for SpellClickEvent entry {} spell {}", creatureId, spellId);
1036 return &i->second;
1037 }
1038 }
1039 return nullptr;
1040}
1041
1042bool ConditionMgr::IsObjectMeetingVehicleSpellConditions(uint32 creatureId, uint32 spellId, Player* player, Unit* vehicle) const
1043{
1044 ConditionEntriesByCreatureIdMap::const_iterator itr = VehicleSpellConditionStore.find(creatureId);
1045 if (itr != VehicleSpellConditionStore.end())
1046 {
1047 ConditionsByEntryMap::const_iterator i = itr->second.find(spellId);
1048 if (i != itr->second.end())
1049 {
1050 TC_LOG_DEBUG("condition", "GetConditionsForVehicleSpell: found conditions for Vehicle entry {} spell {}", creatureId, spellId);
1051 ConditionSourceInfo sourceInfo(player, vehicle);
1052 return IsObjectMeetToConditions(sourceInfo, i->second);
1053 }
1054 }
1055 return true;
1056}
1057
1058bool ConditionMgr::IsObjectMeetingSmartEventConditions(int32 entryOrGuid, uint32 eventId, uint32 sourceType, Unit* unit, WorldObject* baseObject) const
1059{
1060 SmartEventConditionContainer::const_iterator itr = SmartEventConditionStore.find(std::make_pair(entryOrGuid, sourceType));
1061 if (itr != SmartEventConditionStore.end())
1062 {
1063 ConditionsByEntryMap::const_iterator i = itr->second.find(eventId + 1);
1064 if (i != itr->second.end())
1065 {
1066 TC_LOG_DEBUG("condition", "GetConditionsForSmartEvent: found conditions for Smart Event entry or guid {} eventId {}", entryOrGuid, eventId);
1067 ConditionSourceInfo sourceInfo(unit, baseObject);
1068 return IsObjectMeetToConditions(sourceInfo, i->second);
1069 }
1070 }
1071 return true;
1072}
1073
1075{
1076 ConditionEntriesByCreatureIdMap::const_iterator itr = NpcVendorConditionContainerStore.find(creatureId);
1077 if (itr != NpcVendorConditionContainerStore.end())
1078 {
1079 ConditionsByEntryMap::const_iterator i = (*itr).second.find(itemId);
1080 if (i != (*itr).second.end())
1081 {
1082 TC_LOG_DEBUG("condition", "GetConditionsForNpcVendorEvent: found conditions for creature entry {} item {}", creatureId, itemId);
1083 ConditionSourceInfo sourceInfo(player, vendor);
1084 return IsObjectMeetToConditions(sourceInfo, i->second);
1085 }
1086 }
1087 return true;
1088}
1089
1094
1096{
1097 static ConditionMgr instance;
1098 return &instance;
1099}
1100
1102{
1103 uint32 oldMSTime = getMSTime();
1104
1105 Clean();
1106
1107 //must clear all custom handled cases (groupped types) before reload
1108 if (isReload)
1109 {
1110 TC_LOG_INFO("misc", "Reseting Loot Conditions...");
1123
1124 TC_LOG_INFO("misc", "Re-Loading `gossip_menu` Table for Conditions!");
1125 sObjectMgr->LoadGossipMenu();
1126
1127 TC_LOG_INFO("misc", "Re-Loading `gossip_menu_option` Table for Conditions!");
1128 sObjectMgr->LoadGossipMenuItems();
1129 sSpellMgr->UnloadSpellInfoImplicitTargetConditionLists();
1130 }
1131
1132 QueryResult result = WorldDatabase.Query("SELECT SourceTypeOrReferenceId, SourceGroup, SourceEntry, SourceId, ElseGroup, ConditionTypeOrReference, ConditionTarget, "
1133 "ConditionValue1, ConditionValue2, ConditionValue3, ConditionStringValue1, "
1134 "NegativeCondition, ErrorType, ErrorTextId, ScriptName FROM conditions");
1135
1136 if (!result)
1137 {
1138 TC_LOG_INFO("server.loading", ">> Loaded 0 conditions. DB table `conditions` is empty!");
1139 return;
1140 }
1141
1142 uint32 count = 0;
1143
1144 do
1145 {
1146 Field* fields = result->Fetch();
1147
1148 Condition* cond = new Condition();
1149 int32 iSourceTypeOrReferenceId = fields[0].GetInt32();
1150 cond->SourceGroup = fields[1].GetUInt32();
1151 cond->SourceEntry = fields[2].GetInt32();
1152 cond->SourceId = fields[3].GetInt32();
1153 cond->ElseGroup = fields[4].GetUInt32();
1154 int32 iConditionTypeOrReference = fields[5].GetInt32();
1155 cond->ConditionTarget = fields[6].GetUInt8();
1156 cond->ConditionValue1 = fields[7].GetUInt32();
1157 cond->ConditionValue2 = fields[8].GetUInt32();
1158 cond->ConditionValue3 = fields[9].GetUInt32();
1159 cond->ConditionStringValue1 = fields[10].GetString();
1160 cond->NegativeCondition = fields[11].GetBool();
1161 cond->ErrorType = fields[12].GetUInt32();
1162 cond->ErrorTextId = fields[13].GetUInt32();
1163 cond->ScriptId = sObjectMgr->GetScriptId(fields[14].GetString());
1164
1165 if (iConditionTypeOrReference >= 0)
1166 cond->ConditionType = ConditionTypes(iConditionTypeOrReference);
1167
1168 if (iSourceTypeOrReferenceId >= 0)
1169 cond->SourceType = ConditionSourceType(iSourceTypeOrReferenceId);
1170
1171 if (iConditionTypeOrReference < 0)//it has a reference
1172 {
1173 if (iConditionTypeOrReference == iSourceTypeOrReferenceId)//self referencing, skip
1174 {
1175 TC_LOG_ERROR("sql.sql", "Condition reference {} is referencing self, skipped", iSourceTypeOrReferenceId);
1176 delete cond;
1177 continue;
1178 }
1179 cond->ReferenceId = uint32(abs(iConditionTypeOrReference));
1180
1181 char const* rowType = "reference template";
1182 if (iSourceTypeOrReferenceId >= 0)
1183 rowType = "reference";
1184 //check for useless data
1185 if (cond->ConditionTarget)
1186 TC_LOG_ERROR("sql.sql", "Condition {} {} has useless data in ConditionTarget ({})!", rowType, iSourceTypeOrReferenceId, cond->ConditionTarget);
1187 if (cond->ConditionValue1)
1188 TC_LOG_ERROR("sql.sql", "Condition {} {} has useless data in value1 ({})!", rowType, iSourceTypeOrReferenceId, cond->ConditionValue1);
1189 if (cond->ConditionValue2)
1190 TC_LOG_ERROR("sql.sql", "Condition {} {} has useless data in value2 ({})!", rowType, iSourceTypeOrReferenceId, cond->ConditionValue2);
1191 if (cond->ConditionValue3)
1192 TC_LOG_ERROR("sql.sql", "Condition {} {} has useless data in value3 ({})!", rowType, iSourceTypeOrReferenceId, cond->ConditionValue3);
1193 if (cond->NegativeCondition)
1194 TC_LOG_ERROR("sql.sql", "Condition {} {} has useless data in NegativeCondition ({})!", rowType, iSourceTypeOrReferenceId, cond->NegativeCondition);
1195 if (cond->SourceGroup && iSourceTypeOrReferenceId < 0)
1196 TC_LOG_ERROR("sql.sql", "Condition {} {} has useless data in SourceGroup ({})!", rowType, iSourceTypeOrReferenceId, cond->SourceGroup);
1197 if (cond->SourceEntry && iSourceTypeOrReferenceId < 0)
1198 TC_LOG_ERROR("sql.sql", "Condition {} {} has useless data in SourceEntry ({})!", rowType, iSourceTypeOrReferenceId, cond->SourceEntry);
1199 }
1200 else if (!isConditionTypeValid(cond))//doesn't have reference, validate ConditionType
1201 {
1202 delete cond;
1203 continue;
1204 }
1205
1206 if (iSourceTypeOrReferenceId < 0)//it is a reference template
1207 {
1208 ConditionReferenceStore[std::abs(iSourceTypeOrReferenceId)].push_back(cond);//add to reference storage
1209 ++count;
1210 continue;
1211 }//end of reference templates
1212
1213 //if not a reference and SourceType is invalid, skip
1214 if (iConditionTypeOrReference >= 0 && !isSourceTypeValid(cond))
1215 {
1216 delete cond;
1217 continue;
1218 }
1219
1220 //Grouping is only allowed for some types (loot templates, gossip menus, gossip items)
1221 if (cond->SourceGroup && !CanHaveSourceGroupSet(cond->SourceType))
1222 {
1223 TC_LOG_ERROR("sql.sql", "{} has not allowed value of SourceGroup = {}!", cond->ToString(), cond->SourceGroup);
1224 delete cond;
1225 continue;
1226 }
1227 if (cond->SourceId && !CanHaveSourceIdSet(cond->SourceType))
1228 {
1229 TC_LOG_ERROR("sql.sql", "{} has not allowed value of SourceId = {}!", cond->ToString(), cond->SourceId);
1230 delete cond;
1231 continue;
1232 }
1233
1234 if (cond->ErrorType && cond->SourceType != CONDITION_SOURCE_TYPE_SPELL)
1235 {
1236 TC_LOG_ERROR("sql.sql", "{} can't have ErrorType ({}), set to 0!", cond->ToString(), cond->ErrorType);
1237 cond->ErrorType = 0;
1238 }
1239
1240 if (cond->ErrorTextId && !cond->ErrorType)
1241 {
1242 TC_LOG_ERROR("sql.sql", "{} has any ErrorType, ErrorTextId ({}) is set, set to 0!", cond->ToString(), cond->ErrorTextId);
1243 cond->ErrorTextId = 0;
1244 }
1245
1246 if (cond->SourceGroup)
1247 {
1248 bool valid = false;
1249 // handle grouped conditions
1250 switch (cond->SourceType)
1251 {
1254 break;
1257 break;
1260 break;
1263 break;
1266 break;
1269 break;
1272 break;
1275 break;
1278 break;
1281 break;
1284 break;
1287 break;
1289 valid = addToGossipMenus(cond);
1290 break;
1292 valid = addToGossipMenuItems(cond);
1293 break;
1295 {
1296 SpellClickEventConditionStore[cond->SourceGroup][cond->SourceEntry].push_back(cond);
1297 if (cond->ConditionType == CONDITION_AURA)
1299 valid = true;
1300 ++count;
1301 continue; // do not add to m_AllocatedMemory to avoid double deleting
1302 }
1305 break;
1307 {
1308 VehicleSpellConditionStore[cond->SourceGroup][cond->SourceEntry].push_back(cond);
1309 valid = true;
1310 ++count;
1311 continue; // do not add to m_AllocatedMemory to avoid double deleting
1312 }
1314 {
1316 std::pair<int32, uint32> key = std::make_pair(cond->SourceEntry, cond->SourceId);
1317 SmartEventConditionStore[key][cond->SourceGroup].push_back(cond);
1318 valid = true;
1319 ++count;
1320 continue;
1321 }
1323 {
1324 NpcVendorConditionContainerStore[cond->SourceGroup][cond->SourceEntry].push_back(cond);
1325 valid = true;
1326 ++count;
1327 continue;
1328 }
1329 default:
1330 break;
1331 }
1332
1333 if (!valid)
1334 {
1335 TC_LOG_ERROR("sql.sql", "{} Not handled grouped condition.", cond->ToString());
1336 delete cond;
1337 }
1338 else
1339 {
1340 AllocatedMemoryStore.push_back(cond);
1341 ++count;
1342 }
1343 continue;
1344 }
1345
1346 //handle not grouped conditions
1347 //add new Condition to storage based on Type/Entry
1350 ConditionStore[cond->SourceType][cond->SourceEntry].push_back(cond);
1351 ++count;
1352 }
1353 while (result->NextRow());
1354
1355 TC_LOG_INFO("server.loading", ">> Loaded {} conditions in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
1356}
1357
1359{
1360 if (!loot)
1361 {
1362 TC_LOG_ERROR("sql.sql", "{} LootTemplate {} not found.", cond->ToString(), cond->SourceGroup);
1363 return false;
1364 }
1365
1366 if (loot->addConditionItem(cond))
1367 return true;
1368
1369 TC_LOG_ERROR("sql.sql", "{} Item {} not found in LootTemplate {}.", cond->ToString(), cond->SourceEntry, cond->SourceGroup);
1370 return false;
1371}
1372
1374{
1375 GossipMenusMapBoundsNonConst pMenuBounds = sObjectMgr->GetGossipMenusMapBoundsNonConst(cond->SourceGroup);
1376
1377 if (pMenuBounds.first != pMenuBounds.second)
1378 {
1379 for (GossipMenusContainer::iterator itr = pMenuBounds.first; itr != pMenuBounds.second; ++itr)
1380 {
1381 if ((*itr).second.MenuID == cond->SourceGroup && (*itr).second.TextID == uint32(cond->SourceEntry))
1382 {
1383 (*itr).second.Conditions.push_back(cond);
1384 return true;
1385 }
1386 }
1387 }
1388
1389 TC_LOG_ERROR("sql.sql", "{} GossipMenu {} not found.", cond->ToString(), cond->SourceGroup);
1390 return false;
1391}
1392
1394{
1395 GossipMenuItemsMapBoundsNonConst pMenuItemBounds = sObjectMgr->GetGossipMenuItemsMapBoundsNonConst(cond->SourceGroup);
1396 if (pMenuItemBounds.first != pMenuItemBounds.second)
1397 {
1398 for (GossipMenuItemsContainer::iterator itr = pMenuItemBounds.first; itr != pMenuItemBounds.second; ++itr)
1399 {
1400 if ((*itr).second.MenuID == cond->SourceGroup && (*itr).second.OptionID == uint32(cond->SourceEntry))
1401 {
1402 (*itr).second.Conditions.push_back(cond);
1403 return true;
1404 }
1405 }
1406 }
1407
1408 TC_LOG_ERROR("sql.sql", "{} GossipMenuId {} Item {} not found.", cond->ToString(), cond->SourceGroup, cond->SourceEntry);
1409 return false;
1410}
1411
1413{
1414 uint32 conditionEffMask = cond->SourceGroup;
1415 SpellInfo* spellInfo = const_cast<SpellInfo*>(sSpellMgr->AssertSpellInfo(cond->SourceEntry));
1416 std::list<uint32> sharedMasks;
1417 for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects())
1418 {
1419 // additional checks by condition type
1420 if (conditionEffMask & (1 << spellEffectInfo.EffectIndex))
1421 {
1422 switch (cond->ConditionType)
1423 {
1425 {
1426 uint32 implicitTargetMask = GetTargetFlagMask(spellEffectInfo.TargetA.GetObjectType()) | GetTargetFlagMask(spellEffectInfo.TargetB.GetObjectType());
1427 if ((implicitTargetMask & TARGET_FLAG_UNIT_MASK) && cond->ConditionValue1 != TYPEID_UNIT && cond->ConditionValue1 != TYPEID_PLAYER)
1428 {
1429 TC_LOG_ERROR("sql.sql", "{} in `condition` table - spell {} EFFECT_{} - "
1430 "target requires ConditionValue1 to be either TYPEID_UNIT ({}) or TYPEID_PLAYER ({})", cond->ToString(), spellInfo->Id, uint32(spellEffectInfo.EffectIndex), uint32(TYPEID_UNIT), uint32(TYPEID_PLAYER));
1431 return false;
1432 }
1433
1434 if ((implicitTargetMask & TARGET_FLAG_GAMEOBJECT_MASK) && cond->ConditionValue1 != TYPEID_GAMEOBJECT)
1435 {
1436 TC_LOG_ERROR("sql.sql", "{} in `condition` table - spell {} EFFECT_{} - "
1437 "target requires ConditionValue1 to be TYPEID_GAMEOBJECT ({})", cond->ToString(), spellInfo->Id, uint32(spellEffectInfo.EffectIndex), uint32(TYPEID_GAMEOBJECT));
1438 return false;
1439 }
1440
1441 if ((implicitTargetMask & TARGET_FLAG_CORPSE_MASK) && cond->ConditionValue1 != TYPEID_CORPSE)
1442 {
1443 TC_LOG_ERROR("sql.sql", "{} in `condition` table - spell {} EFFECT_{} - "
1444 "target requires ConditionValue1 to be TYPEID_CORPSE ({})", cond->ToString(), spellInfo->Id, uint32(spellEffectInfo.EffectIndex), uint32(TYPEID_CORPSE));
1445 return false;
1446 }
1447 break;
1448 }
1449 default:
1450 break;
1451 }
1452 }
1453
1454 // check if effect is already a part of some shared mask
1455 auto itr = std::find_if(sharedMasks.begin(), sharedMasks.end(), [&](uint32 mask) { return !!(mask & (1 << spellEffectInfo.EffectIndex)); });
1456 if (itr != sharedMasks.end())
1457 continue;
1458
1459 // build new shared mask with found effect
1460 uint32 sharedMask = 1 << spellEffectInfo.EffectIndex;
1461 ConditionContainer* cmp = spellEffectInfo.ImplicitTargetConditions;
1462 for (size_t effIndex = spellEffectInfo.EffectIndex + 1; effIndex < spellInfo->GetEffects().size(); ++effIndex)
1463 if (spellInfo->GetEffect(SpellEffIndex(effIndex)).ImplicitTargetConditions == cmp)
1464 sharedMask |= 1 << effIndex;
1465
1466 sharedMasks.push_back(sharedMask);
1467 }
1468
1469 for (uint32 effectMask : sharedMasks)
1470 {
1471 // some effect indexes should have same data
1472 if (uint32 commonMask = effectMask & conditionEffMask)
1473 {
1474 size_t firstEffIndex = 0;
1475 for (; firstEffIndex < spellInfo->GetEffects().size(); ++firstEffIndex)
1476 if ((1 << firstEffIndex) & effectMask)
1477 break;
1478
1479 if (firstEffIndex >= spellInfo->GetEffects().size())
1480 return false;
1481
1482 // get shared data
1483 ConditionContainer* sharedList = spellInfo->GetEffect(SpellEffIndex(firstEffIndex)).ImplicitTargetConditions;
1484
1485 // there's already data entry for that sharedMask
1486 if (sharedList)
1487 {
1488 // we have overlapping masks in db
1489 if (conditionEffMask != effectMask)
1490 {
1491 TC_LOG_ERROR("sql.sql", "{} in `condition` table, has incorrect SourceGroup {} (spell effectMask) set - "
1492 "effect masks are overlapping (all SourceGroup values having given bit set must be equal) - ignoring.", cond->ToString(), cond->SourceGroup);
1493 return false;
1494 }
1495 }
1496 // no data for shared mask, we can create new submask
1497 else
1498 {
1499 // add new list, create new shared mask
1500 sharedList = new ConditionContainer();
1501 bool assigned = false;
1502 for (size_t i = firstEffIndex; i < spellInfo->GetEffects().size(); ++i)
1503 {
1504 if ((1 << i) & commonMask)
1505 {
1506 const_cast<SpellEffectInfo&>(spellInfo->GetEffect(SpellEffIndex(i))).ImplicitTargetConditions = sharedList;
1507 assigned = true;
1508 }
1509 }
1510
1511 if (!assigned)
1512 {
1513 delete sharedList;
1514 return false;
1515 }
1516 }
1517 sharedList->push_back(cond);
1518 break;
1519 }
1520 }
1521 return true;
1522}
1523
1525{
1527 {
1528 TC_LOG_ERROR("sql.sql", "{} Invalid ConditionSourceType in `condition` table, ignoring.", cond->ToString());
1529 return false;
1530 }
1531
1532 switch (cond->SourceType)
1533 {
1535 {
1537 {
1538 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `creature_loot_template`, ignoring.", cond->ToString());
1539 return false;
1540 }
1541
1543 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1544 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1545 {
1546 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString());
1547 return false;
1548 }
1549 break;
1550 }
1552 {
1554 {
1555 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `disenchant_loot_template`, ignoring.", cond->ToString());
1556 return false;
1557 }
1558
1560 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1561 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1562 {
1563 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString());
1564 return false;
1565 }
1566 break;
1567 }
1569 {
1571 {
1572 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `fishing_loot_template`, ignoring.", cond->ToString());
1573 return false;
1574 }
1575
1577 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1578 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1579 {
1580 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString());
1581 return false;
1582 }
1583 break;
1584 }
1586 {
1588 {
1589 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `gameobject_loot_template`, ignoring.", cond->ToString());
1590 return false;
1591 }
1592
1594 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1595 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1596 {
1597 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString());
1598 return false;
1599 }
1600 break;
1601 }
1603 {
1605 {
1606 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `item_loot_template`, ignoring.", cond->ToString());
1607 return false;
1608 }
1609
1611 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1612 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1613 {
1614 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString());
1615 return false;
1616 }
1617 break;
1618 }
1620 {
1622 {
1623 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `mail_loot_template`, ignoring.", cond->ToString());
1624 return false;
1625 }
1626
1628 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1629 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1630 {
1631 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString());
1632 return false;
1633 }
1634 break;
1635 }
1637 {
1639 {
1640 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `milling_loot_template`, ignoring.", cond->ToString());
1641 return false;
1642 }
1643
1645 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1646 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1647 {
1648 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString());
1649 return false;
1650 }
1651 break;
1652 }
1654 {
1656 {
1657 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `pickpocketing_loot_template`, ignoring.", cond->ToString());
1658 return false;
1659 }
1660
1662 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1663 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1664 {
1665 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString());
1666 return false;
1667 }
1668 break;
1669 }
1671 {
1673 {
1674 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `prospecting_loot_template`, ignoring.", cond->ToString());
1675 return false;
1676 }
1677
1679 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1680 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1681 {
1682 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString());
1683 return false;
1684 }
1685 break;
1686 }
1688 {
1690 {
1691 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `reference_loot_template`, ignoring.", cond->ToString());
1692 return false;
1693 }
1694
1696 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1697 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1698 {
1699 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString());
1700 return false;
1701 }
1702 break;
1703 }
1705 {
1707 {
1708 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `skinning_loot_template`, ignoring.", cond->ToString());
1709 return false;
1710 }
1711
1713 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1714 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1715 {
1716 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString());
1717 return false;
1718 }
1719 break;
1720 }
1722 {
1724 {
1725 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `spell_loot_template`, ignoring.", cond->ToString());
1726 return false;
1727 }
1728
1730 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1731 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1732 {
1733 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString());
1734 return false;
1735 }
1736 break;
1737 }
1739 {
1740 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(cond->SourceEntry);
1741 if (!spellInfo)
1742 {
1743 TC_LOG_ERROR("sql.sql", "{} SourceEntry in `condition` table does not exist in `spell.dbc`, ignoring.", cond->ToString());
1744 return false;
1745 }
1746
1747 if ((cond->SourceGroup > MAX_EFFECT_MASK) || !cond->SourceGroup)
1748 {
1749 TC_LOG_ERROR("sql.sql", "{} in `condition` table, has incorrect SourceGroup (spell effectMask) set, ignoring.", cond->ToString());
1750 return false;
1751 }
1752
1753 uint32 origGroup = cond->SourceGroup;
1754
1755 for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects())
1756 {
1757 if (!((1 << spellEffectInfo.EffectIndex) & cond->SourceGroup))
1758 continue;
1759
1760 if (spellEffectInfo.ChainTargets > 0)
1761 continue;
1762
1763 switch (spellEffectInfo.TargetA.GetSelectionCategory())
1764 {
1769 continue;
1770 default:
1771 break;
1772 }
1773
1774 switch (spellEffectInfo.TargetB.GetSelectionCategory())
1775 {
1780 continue;
1781 default:
1782 break;
1783 }
1784
1785 switch (spellEffectInfo.Effect)
1786 {
1794 continue;
1795 default:
1796 break;
1797 }
1798
1799 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));
1800 cond->SourceGroup &= ~(1 << spellEffectInfo.EffectIndex);
1801 }
1802 // all effects were removed, no need to add the condition at all
1803 if (!cond->SourceGroup)
1804 return false;
1805 break;
1806 }
1808 {
1809 if (!sObjectMgr->GetCreatureTemplate(cond->SourceEntry))
1810 {
1811 TC_LOG_ERROR("sql.sql", "{} SourceEntry in `condition` table, does not exist in `creature_template`, ignoring.", cond->ToString());
1812 return false;
1813 }
1814 break;
1815 }
1818 {
1819 SpellInfo const* spellProto = sSpellMgr->GetSpellInfo(cond->SourceEntry);
1820 if (!spellProto)
1821 {
1822 TC_LOG_ERROR("sql.sql", "{} SourceEntry in `condition` table does not exist in `spell.dbc`, ignoring.", cond->ToString());
1823 return false;
1824 }
1825 break;
1826 }
1828 if (!sObjectMgr->GetQuestTemplate(cond->SourceEntry))
1829 {
1830 TC_LOG_ERROR("sql.sql", "{} SourceEntry specifies non-existing quest, skipped.", cond->ToString());
1831 return false;
1832 }
1833 break;
1835 if (!sObjectMgr->GetCreatureTemplate(cond->SourceGroup))
1836 {
1837 TC_LOG_ERROR("sql.sql", "{} SourceEntry in `condition` table, does not exist in `creature_template`, ignoring.", cond->ToString());
1838 return false;
1839 }
1840
1841 if (!sSpellMgr->GetSpellInfo(cond->SourceEntry))
1842 {
1843 TC_LOG_ERROR("sql.sql", "{} SourceEntry in `condition` table does not exist in `spell.dbc`, ignoring.", cond->ToString());
1844 return false;
1845 }
1846 break;
1848 if (!sObjectMgr->GetCreatureTemplate(cond->SourceGroup))
1849 {
1850 TC_LOG_ERROR("sql.sql", "{} SourceEntry in `condition` table, does not exist in `creature_template`, ignoring.", cond->ToString());
1851 return false;
1852 }
1853
1854 if (!sSpellMgr->GetSpellInfo(cond->SourceEntry))
1855 {
1856 TC_LOG_ERROR("sql.sql", "{} SourceEntry in `condition` table does not exist in `spell.dbc`, ignoring.", cond->ToString());
1857 return false;
1858 }
1859 break;
1861 {
1862 if (!sObjectMgr->GetCreatureTemplate(cond->SourceGroup))
1863 {
1864 TC_LOG_ERROR("sql.sql", "{} SourceEntry in `condition` table, does not exist in `creature_template`, ignoring.", cond->ToString());
1865 return false;
1866 }
1867 ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1868 if (!itemTemplate)
1869 {
1870 TC_LOG_ERROR("sql.sql", "{} SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString());
1871 return false;
1872 }
1873 break;
1874 }
1876 {
1877 if (!sAreaTriggerStore.LookupEntry(cond->SourceEntry))
1878 {
1879 TC_LOG_ERROR("sql.sql", "%s SourceEntry in `condition` table, does not exists in AreaTrigger.dbc, ignoring.", cond->ToString().c_str());
1880 return false;
1881 }
1882 break;
1883 }
1885 {
1886 TC_LOG_ERROR("sql.sql", "CONDITION_SOURCE_TYPE_TERRAIN_SWAP: is only for master branch, skipped");
1887 return false;
1888 }
1890 {
1891 TC_LOG_ERROR("sql.sql", "CONDITION_SOURCE_TYPE_PHASE: is only for master branch, skipped");
1892 return false;
1893 }
1895 {
1896 TC_LOG_ERROR("sql.sql", "CONDITION_SOURCE_TYPE_GRAVEYARD: is only for master branch, skipped");
1897 return false;
1898 }
1900 {
1901 TC_LOG_ERROR("sql.sql", "CONDITION_SOURCE_TYPE_AREATRIGGER: is only for master branch, skipped");
1902 return false;
1903 }
1905 {
1906 TC_LOG_ERROR("sql.sql", "CONDITION_SOURCE_TYPE_CONVERSATION_LINE: is only for master branch, skipped");
1907 return false;
1908 }
1913 default:
1914 break;
1915 }
1916
1917 return true;
1918}
1919
1921{
1923 {
1924 TC_LOG_ERROR("sql.sql", "{} Invalid ConditionType in `condition` table, ignoring.", cond->ToString(true));
1925 return false;
1926 }
1927
1929 {
1930 TC_LOG_ERROR("sql.sql", "{} in `condition` table, has incorrect ConditionTarget set, ignoring.", cond->ToString(true));
1931 return false;
1932 }
1933
1934 switch (cond->ConditionType)
1935 {
1936 case CONDITION_AURA:
1937 {
1938 if (!sSpellMgr->GetSpellInfo(cond->ConditionValue1))
1939 {
1940 TC_LOG_ERROR("sql.sql", "{} has non existing spell (Id: {}), skipped.", cond->ToString(true), cond->ConditionValue1);
1941 return false;
1942 }
1943
1944 if (cond->ConditionValue2 > EFFECT_2)
1945 {
1946 TC_LOG_ERROR("sql.sql", "{} has non existing effect index ({}) (must be 0..2), skipped.", cond->ToString(true), cond->ConditionValue2);
1947 return false;
1948 }
1949 break;
1950 }
1951 case CONDITION_ITEM:
1952 {
1953 ItemTemplate const* proto = sObjectMgr->GetItemTemplate(cond->ConditionValue1);
1954 if (!proto)
1955 {
1956 TC_LOG_ERROR("sql.sql", "{} Item ({}) does not exist, skipped.", cond->ToString(true), cond->ConditionValue1);
1957 return false;
1958 }
1959
1960 if (!cond->ConditionValue2)
1961 {
1962 TC_LOG_ERROR("sql.sql", "{} Zero item count in ConditionValue2, skipped.", cond->ToString(true));
1963 return false;
1964 }
1965 break;
1966 }
1968 {
1969 ItemTemplate const* proto = sObjectMgr->GetItemTemplate(cond->ConditionValue1);
1970 if (!proto)
1971 {
1972 TC_LOG_ERROR("sql.sql", "{} Item ({}) does not exist, skipped.", cond->ToString(true), cond->ConditionValue1);
1973 return false;
1974 }
1975 break;
1976 }
1977 case CONDITION_ZONEID:
1978 {
1979 AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(cond->ConditionValue1);
1980 if (!areaEntry)
1981 {
1982 TC_LOG_ERROR("sql.sql", "{} Area ({}) does not exist, skipped.", cond->ToString(true), cond->ConditionValue1);
1983 return false;
1984 }
1985
1986 if (areaEntry->ParentAreaID != 0)
1987 {
1988 TC_LOG_ERROR("sql.sql", "{} requires to be in area ({}) which is a subzone but zone expected, skipped.", cond->ToString(true), cond->ConditionValue1);
1989 return false;
1990 }
1991 break;
1992 }
1994 {
1995 FactionEntry const* factionEntry = sFactionStore.LookupEntry(cond->ConditionValue1);
1996 if (!factionEntry)
1997 {
1998 TC_LOG_ERROR("sql.sql", "{} has non existing faction ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
1999 return false;
2000 }
2001 break;
2002 }
2003 case CONDITION_TEAM:
2004 {
2005 if (cond->ConditionValue1 != ALLIANCE && cond->ConditionValue1 != HORDE)
2006 {
2007 TC_LOG_ERROR("sql.sql", "{} specifies unknown team ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2008 return false;
2009 }
2010 break;
2011 }
2012 case CONDITION_SKILL:
2013 {
2014 SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(cond->ConditionValue1);
2015 if (!pSkill)
2016 {
2017 TC_LOG_ERROR("sql.sql", "{} specifies non-existing skill ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2018 return false;
2019 }
2020
2021 if (cond->ConditionValue2 < 1 || cond->ConditionValue2 > sWorld->GetConfigMaxSkillValue())
2022 {
2023 TC_LOG_ERROR("sql.sql", "{} specifies skill ({}) with invalid value ({}), skipped.", cond->ToString(true), cond->ConditionValue1, cond->ConditionValue2);
2024 return false;
2025 }
2026 break;
2027 }
2029 if (cond->ConditionValue2 >= (1 << MAX_QUEST_STATUS))
2030 {
2031 TC_LOG_ERROR("sql.sql", "{} has invalid state mask ({}), skipped.", cond->ToString(true), cond->ConditionValue2);
2032 return false;
2033 }
2034 [[fallthrough]];
2040 {
2041 if (!sObjectMgr->GetQuestTemplate(cond->ConditionValue1))
2042 {
2043 TC_LOG_ERROR("sql.sql", "{} points to non-existing quest ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2044 return false;
2045 }
2046 break;
2047 }
2049 {
2050 GameEventMgr::GameEventDataMap const& events = sGameEventMgr->GetEventMap();
2051 if (cond->ConditionValue1 >= events.size() || !events[cond->ConditionValue1].isValid())
2052 {
2053 TC_LOG_ERROR("sql.sql", "{} has non existing event id ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2054 return false;
2055 }
2056 break;
2057 }
2059 {
2060 AchievementEntry const* achievement = sAchievementStore.LookupEntry(cond->ConditionValue1);
2061 if (!achievement)
2062 {
2063 TC_LOG_ERROR("sql.sql", "{} has non existing achivement id ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2064 return false;
2065 }
2066 break;
2067 }
2068 case CONDITION_CLASS:
2069 {
2071 {
2072 TC_LOG_ERROR("sql.sql", "{} has non existing classmask ({}), skipped.", cond->ToString(true), cond->ConditionValue1 & ~CLASSMASK_ALL_PLAYABLE);
2073 return false;
2074 }
2075 break;
2076 }
2077 case CONDITION_RACE:
2078 {
2080 {
2081 TC_LOG_ERROR("sql.sql", "{} has non existing racemask ({}), skipped.", cond->ToString(true), cond->ConditionValue1 & ~RACEMASK_ALL_PLAYABLE);
2082 return false;
2083 }
2084 break;
2085 }
2086 case CONDITION_GENDER:
2087 {
2089 {
2090 TC_LOG_ERROR("sql.sql", "{} has invalid gender ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2091 return false;
2092 }
2093 break;
2094 }
2095 case CONDITION_MAPID:
2096 {
2097 MapEntry const* me = sMapStore.LookupEntry(cond->ConditionValue1);
2098 if (!me)
2099 {
2100 TC_LOG_ERROR("sql.sql", "{} has non existing map ({}), skipped", cond->ToString(true), cond->ConditionValue1);
2101 return false;
2102 }
2103 break;
2104 }
2105 case CONDITION_SPELL:
2106 {
2107 if (!sSpellMgr->GetSpellInfo(cond->ConditionValue1))
2108 {
2109 TC_LOG_ERROR("sql.sql", "{} has non existing spell (Id: {}), skipped", cond->ToString(true), cond->ConditionValue1);
2110 return false;
2111 }
2112 break;
2113 }
2114 case CONDITION_LEVEL:
2115 {
2116 if (cond->ConditionValue2 >= COMP_TYPE_MAX)
2117 {
2118 TC_LOG_ERROR("sql.sql", "{} has invalid ComparisionType ({}), skipped.", cond->ToString(true), cond->ConditionValue2);
2119 return false;
2120 }
2121 break;
2122 }
2124 {
2125 if (cond->ConditionValue1 > DRUNKEN_SMASHED)
2126 {
2127 TC_LOG_ERROR("sql.sql", "{} has invalid state ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2128 return false;
2129 }
2130 break;
2131 }
2133 {
2134 if (!sObjectMgr->GetCreatureTemplate(cond->ConditionValue1))
2135 {
2136 TC_LOG_ERROR("sql.sql", "{} has non existing creature template entry ({}), skipped", cond->ToString(true), cond->ConditionValue1);
2137 return false;
2138 }
2139 break;
2140 }
2142 {
2143 if (!sObjectMgr->GetGameObjectTemplate(cond->ConditionValue1))
2144 {
2145 TC_LOG_ERROR("sql.sql", "{} has non existing gameobject template entry ({}), skipped.", cond->ToString(), cond->ConditionValue1);
2146 return false;
2147 }
2148 break;
2149 }
2151 {
2152 switch (cond->ConditionValue1)
2153 {
2154 case TYPEID_UNIT:
2155 if (cond->ConditionValue2 && !sObjectMgr->GetCreatureTemplate(cond->ConditionValue2))
2156 {
2157 TC_LOG_ERROR("sql.sql", "{} has non existing creature template entry ({}), skipped.", cond->ToString(true), cond->ConditionValue2);
2158 return false;
2159 }
2160 if (cond->ConditionValue3)
2161 {
2162 if (CreatureData const* creatureData = sObjectMgr->GetCreatureData(cond->ConditionValue3))
2163 {
2164 if (cond->ConditionValue2 && creatureData->id != cond->ConditionValue2)
2165 {
2166 TC_LOG_ERROR("sql.sql", "{} has guid {} set but does not match creature entry ({}), skipped.", cond->ToString(true), cond->ConditionValue3, cond->ConditionValue2);
2167 return false;
2168 }
2169 }
2170 else
2171 {
2172 TC_LOG_ERROR("sql.sql", "{} has non existing creature guid ({}), skipped.", cond->ToString(true), cond->ConditionValue3);
2173 return false;
2174 }
2175 }
2176 break;
2177 case TYPEID_GAMEOBJECT:
2178 if (cond->ConditionValue2 && !sObjectMgr->GetGameObjectTemplate(cond->ConditionValue2))
2179 {
2180 TC_LOG_ERROR("sql.sql", "{} has non existing gameobject template entry ({}), skipped.", cond->ToString(true), cond->ConditionValue2);
2181 return false;
2182 }
2183 if (cond->ConditionValue3)
2184 {
2185 if (GameObjectData const* goData = sObjectMgr->GetGameObjectData(cond->ConditionValue3))
2186 {
2187 if (cond->ConditionValue2 && goData->id != cond->ConditionValue2)
2188 {
2189 TC_LOG_ERROR("sql.sql", "{} has guid {} set but does not match gameobject entry ({}), skipped.", cond->ToString(true), cond->ConditionValue3, cond->ConditionValue2);
2190 return false;
2191 }
2192 }
2193 else
2194 {
2195 TC_LOG_ERROR("sql.sql", "{} has non existing gameobject guid ({}), skipped.", cond->ToString(true), cond->ConditionValue3);
2196 return false;
2197 }
2198 }
2199 break;
2200 case TYPEID_PLAYER:
2201 case TYPEID_CORPSE:
2202 if (cond->ConditionValue2)
2204 if (cond->ConditionValue3)
2206 break;
2207 default:
2208 TC_LOG_ERROR("sql.sql", "{} has wrong typeid set ({}), skipped", cond->ToString(true), cond->ConditionValue1);
2209 return false;
2210 }
2211 break;
2212 }
2214 {
2216 {
2217 TC_LOG_ERROR("sql.sql", "{} has invalid typemask set ({}), skipped.", cond->ToString(true), cond->ConditionValue2);
2218 return false;
2219 }
2220 break;
2221 }
2223 {
2225 {
2226 TC_LOG_ERROR("sql.sql", "{} has invalid ConditionValue1(ConditionTarget selection) ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2227 return false;
2228 }
2229 if (cond->ConditionValue1 == cond->ConditionTarget)
2230 {
2231 TC_LOG_ERROR("sql.sql", "{} has ConditionValue1(ConditionTarget selection) set to self ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2232 return false;
2233 }
2234 if (cond->ConditionValue2 >= RELATION_MAX)
2235 {
2236 TC_LOG_ERROR("sql.sql", "{} has invalid ConditionValue2(RelationType) ({}), skipped.", cond->ToString(true), cond->ConditionValue2);
2237 return false;
2238 }
2239 break;
2240 }
2242 {
2244 {
2245 TC_LOG_ERROR("sql.sql", "{} has invalid ConditionValue1(ConditionTarget selection) ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2246 return false;
2247 }
2248 if (cond->ConditionValue1 == cond->ConditionTarget)
2249 {
2250 TC_LOG_ERROR("sql.sql", "{} has ConditionValue1(ConditionTarget selection) set to self ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2251 return false;
2252 }
2253 if (!cond->ConditionValue2)
2254 {
2255 TC_LOG_ERROR("sql.sql", "{} has invalid ConditionValue2(rankMask) ({}), skipped.", cond->ToString(true), cond->ConditionValue2);
2256 return false;
2257 }
2258 break;
2259 }
2261 {
2263 {
2264 TC_LOG_ERROR("sql.sql", "{} has invalid ConditionValue1(ConditionTarget selection) ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2265 return false;
2266 }
2267 if (cond->ConditionValue1 == cond->ConditionTarget)
2268 {
2269 TC_LOG_ERROR("sql.sql", "{} has ConditionValue1(ConditionTarget selection) set to self ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2270 return false;
2271 }
2272 if (cond->ConditionValue3 >= COMP_TYPE_MAX)
2273 {
2274 TC_LOG_ERROR("sql.sql", "{} has invalid ComparisionType ({}), skipped.", cond->ToString(true), cond->ConditionValue3);
2275 return false;
2276 }
2277 break;
2278 }
2279 case CONDITION_HP_VAL:
2280 {
2281 if (cond->ConditionValue2 >= COMP_TYPE_MAX)
2282 {
2283 TC_LOG_ERROR("sql.sql", "{} has invalid ComparisionType ({}), skipped.", cond->ToString(true), cond->ConditionValue2);
2284 return false;
2285 }
2286 if (cond->ConditionValue3)
2287 TC_LOG_ERROR("sql.sql", "{} has useless data in value3 ({})!", cond->ToString(true), cond->ConditionValue3);
2288 break;
2289 }
2290 case CONDITION_HP_PCT:
2291 {
2292 if (cond->ConditionValue1 > 100)
2293 {
2294 TC_LOG_ERROR("sql.sql", "{} has too big percent value ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2295 return false;
2296 }
2297 if (cond->ConditionValue2 >= COMP_TYPE_MAX)
2298 {
2299 TC_LOG_ERROR("sql.sql", "{} has invalid ComparisionType ({}), skipped.", cond->ToString(true), cond->ConditionValue2);
2300 return false;
2301 }
2302 if (cond->ConditionValue3)
2303 TC_LOG_ERROR("sql.sql", "{} has useless data in value3 ({})!", cond->ToString(), cond->ConditionValue3);
2304 break;
2305 }
2307 {
2308 if (!sWorld->getWorldState(cond->ConditionValue1))
2309 {
2310 TC_LOG_ERROR("sql.sql", "{} has non existing world state in value1 ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2311 return false;
2312 }
2313 break;
2314 }
2315 case CONDITION_TITLE:
2316 {
2317 CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(cond->ConditionValue1);
2318 if (!titleEntry)
2319 {
2320 TC_LOG_ERROR("sql.sql", "{} has non existing title in value1 ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2321 return false;
2322 }
2323 break;
2324 }
2326 {
2328 {
2329 TC_LOG_ERROR("sql.sql", "{} has non existing SpawnMask in value1 ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2330 return false;
2331 }
2332 break;
2333 }
2335 {
2337 {
2338 TC_LOG_ERROR("sql.sql", "{} has non existing UnitState in value1 ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2339 return false;
2340 }
2341 break;
2342 }
2344 {
2346 {
2347 TC_LOG_ERROR("sql.sql", "{} has non existing CreatureType in value1 ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2348 return false;
2349 }
2350 break;
2351 }
2353 case CONDITION_AREAID:
2355 case CONDITION_ALIVE:
2356 break;
2358 {
2359 AchievementEntry const* achievement = sAchievementStore.LookupEntry(cond->ConditionValue1);
2360 if (!achievement)
2361 {
2362 TC_LOG_ERROR("sql.sql", "{} has non existing realm first achivement id ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2363 return false;
2364 }
2365 break;
2366 }
2368 TC_LOG_ERROR("sql.sql", "{} is not valid for this branch, skipped.", cond->ToString(true));
2369 return false;
2371 {
2372 bool valid = false;
2373 switch (cond->ConditionValue1)
2374 {
2375 case 0:
2377 break;
2378 case 1:
2379 valid = cond->ConditionValue2 <= 1;
2380 break;
2381 default:
2382 valid = false;
2383 break;
2384 }
2385 if (!valid)
2386 {
2387 TC_LOG_ERROR("sql.sql", "{} has non-existing stand state ({},{}), skipped.", cond->ToString(true), cond->ConditionValue1, cond->ConditionValue2);
2388 return false;
2389 }
2390 break;
2391 }
2392 case CONDITION_PET_TYPE:
2393 if (cond->ConditionValue1 >= (1 << MAX_PET_TYPE))
2394 {
2395 TC_LOG_ERROR("sql.sql", "{} has non-existing pet type {}, skipped.", cond->ToString(true), cond->ConditionValue1);
2396 return false;
2397 }
2398 break;
2400 {
2401 const Quest* quest = sObjectMgr->GetQuestTemplate(cond->ConditionValue1);
2402 if (!quest)
2403 {
2404 TC_LOG_ERROR("sql.sql", "{} points to non-existing quest ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2405 return false;
2406 }
2407
2408 if (cond->ConditionValue2 > 3)
2409 {
2410 TC_LOG_ERROR("sql.sql", "{} has out-of-range quest objective index specified ({}), it must be a number between 0 and 3. skipped.", cond->ToString(true), cond->ConditionValue2);
2411 return false;
2412 }
2413
2414 if (quest->RequiredNpcOrGo[cond->ConditionValue2] == 0)
2415 {
2416 TC_LOG_ERROR("sql.sql", "{} has quest objective {} for quest {}, but the field RequiredNPCOrGo{} is 0, skipped.", cond->ToString(true), cond->ConditionValue2, cond->ConditionValue1, cond->ConditionValue2);
2417 return false;
2418 }
2419
2420 if (cond->ConditionValue3 > quest->RequiredNpcOrGoCount[cond->ConditionValue2])
2421 {
2422 TC_LOG_ERROR("sql.sql", "{} has quest objective count {} in value3, but quest {} has a maximum objective count of {} in RequiredNPCOrGOCount{}, skipped.", cond->ToString(true), cond->ConditionValue3, cond->ConditionValue2, quest->RequiredNpcOrGoCount[cond->ConditionValue2], cond->ConditionValue2);
2423 return false;
2424 }
2425 break;
2426 }
2428 if (cond->ConditionValue1 >= MAX_DIFFICULTY)
2429 {
2430 TC_LOG_ERROR("sql.sql", "{} has non existing difficulty in value1 ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2431 return false;
2432 }
2433 break;
2436 {
2437 TC_LOG_ERROR("sql.sql", "{} has non invalid group status condition value1 ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2438 return false;
2439 }
2440 break;
2441 case CONDITION_IN_WATER:
2442 case CONDITION_CHARMED:
2443 case CONDITION_TAXI:
2446 default:
2447 break;
2453 case CONDITION_LABEL:
2454 TC_LOG_ERROR("sql.sql", "{} uses condition type not supported in this game version, skipped.", cond->ToString(true));
2455 return false;
2456 }
2457
2466
2467 return true;
2468}
2469
2471{
2472 TC_LOG_ERROR("sql.sql", "{} has useless data in ConditionValue{} ({})!", cond->ToString(true), index, value);
2473}
2474
2475void ConditionMgr::LogUselessConditionValue(Condition const* cond, uint8 index, std::string_view value)
2476{
2477 TC_LOG_ERROR("sql.sql", "{} has useless data in ConditionStringValue{} ({})!", cond->ToString(true), index, value);
2478}
2479
2481{
2482 for (ConditionReferenceContainer::iterator itr = ConditionReferenceStore.begin(); itr != ConditionReferenceStore.end(); ++itr)
2483 for (ConditionContainer::const_iterator it = itr->second.begin(); it != itr->second.end(); ++it)
2484 delete *it;
2485
2487
2488 for (uint32 i = 0; i < CONDITION_SOURCE_TYPE_MAX; ++i)
2489 {
2490 for (ConditionsByEntryMap::iterator it = ConditionStore[i].begin(); it != ConditionStore[i].end(); ++it)
2491 for (ConditionContainer::const_iterator itr = it->second.begin(); itr != it->second.end(); ++itr)
2492 delete *itr;
2493
2494 ConditionStore[i].clear();
2495 }
2496
2497 for (ConditionEntriesByCreatureIdMap::iterator itr = VehicleSpellConditionStore.begin(); itr != VehicleSpellConditionStore.end(); ++itr)
2498 for (ConditionsByEntryMap::iterator it = itr->second.begin(); it != itr->second.end(); ++it)
2499 for (ConditionContainer::const_iterator i = it->second.begin(); i != it->second.end(); ++i)
2500 delete *i;
2501
2503
2504 for (SmartEventConditionContainer::iterator itr = SmartEventConditionStore.begin(); itr != SmartEventConditionStore.end(); ++itr)
2505 for (ConditionsByEntryMap::iterator it = itr->second.begin(); it != itr->second.end(); ++it)
2506 for (ConditionContainer::const_iterator i = it->second.begin(); i != it->second.end(); ++i)
2507 delete *i;
2508
2510
2511 for (ConditionEntriesByCreatureIdMap::iterator itr = SpellClickEventConditionStore.begin(); itr != SpellClickEventConditionStore.end(); ++itr)
2512 for (ConditionsByEntryMap::iterator it = itr->second.begin(); it != itr->second.end(); ++it)
2513 for (ConditionContainer::const_iterator i = it->second.begin(); i != it->second.end(); ++i)
2514 delete *i;
2515
2518
2519 for (ConditionEntriesByCreatureIdMap::iterator itr = NpcVendorConditionContainerStore.begin(); itr != NpcVendorConditionContainerStore.end(); ++itr)
2520 for (ConditionsByEntryMap::iterator it = itr->second.begin(); it != itr->second.end(); ++it)
2521 for (ConditionContainer::const_iterator i = it->second.begin(); i != it->second.end(); ++i)
2522 delete *i;
2523
2525
2526 // this is a BIG hack, feel free to fix it if you can figure out the ConditionMgr ;)
2527 for (std::vector<Condition*>::const_iterator itr = AllocatedMemoryStore.begin(); itr != AllocatedMemoryStore.end(); ++itr)
2528 delete *itr;
2529
2530 AllocatedMemoryStore.clear();
2531}
#define sAchievementMgr
static bool MeetsGroupStatusCondition(Player const *player, GroupStatusCondition status)
ConditionSourceType
@ CONDITION_SOURCE_TYPE_MAX
@ CONDITION_SOURCE_TYPE_CONVERSATION_LINE
@ CONDITION_SOURCE_TYPE_VEHICLE_SPELL
@ CONDITION_SOURCE_TYPE_DISENCHANT_LOOT_TEMPLATE
@ CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE
@ CONDITION_SOURCE_TYPE_TERRAIN_SWAP
@ CONDITION_SOURCE_TYPE_NPC_VENDOR
@ CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION
@ CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT
@ CONDITION_SOURCE_TYPE_MAIL_LOOT_TEMPLATE
@ CONDITION_SOURCE_TYPE_PHASE
@ CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE
@ CONDITION_SOURCE_TYPE_SMART_EVENT
@ CONDITION_SOURCE_TYPE_PICKPOCKETING_LOOT_TEMPLATE
@ CONDITION_SOURCE_TYPE_PROSPECTING_LOOT_TEMPLATE
@ CONDITION_SOURCE_TYPE_AREATRIGGER_CLIENT_TRIGGERED
@ CONDITION_SOURCE_TYPE_AREATRIGGER
@ CONDITION_SOURCE_TYPE_SPELL
@ CONDITION_SOURCE_TYPE_FISHING_LOOT_TEMPLATE
@ CONDITION_SOURCE_TYPE_GOSSIP_MENU
@ CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE
@ CONDITION_SOURCE_TYPE_ITEM_LOOT_TEMPLATE
@ CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET
@ CONDITION_SOURCE_TYPE_GRAVEYARD
@ CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE
@ CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE
@ CONDITION_SOURCE_TYPE_GAMEOBJECT_LOOT_TEMPLATE
@ CONDITION_SOURCE_TYPE_MILLING_LOOT_TEMPLATE
@ CONDITION_SOURCE_TYPE_SPELL_PROC
@ CONDITION_SOURCE_TYPE_QUEST_AVAILABLE
@ CONDITION_SOURCE_TYPE_NONE
@ INSTANCE_INFO_DATA64
@ INSTANCE_INFO_DATA
@ INSTANCE_INFO_BOSS_STATE
@ INSTANCE_INFO_GUID_DATA
@ MAX_CONDITION_TARGETS
GroupStatusCondition
ConditionTypes
@ CONDITION_TAXI
@ CONDITION_MAPID
@ CONDITION_SKILL
@ CONDITION_RACE
@ CONDITION_STRING_ID
@ CONDITION_REACTION_TO
@ CONDITION_NEAR_GAMEOBJECT
@ CONDITION_QUESTREWARDED
@ CONDITION_REALM_ACHIEVEMENT
@ CONDITION_PHASEMASK
@ CONDITION_GROUP_STATUS
@ CONDITION_QUEST_OBJECTIVE_PROGRESS
@ CONDITION_DAILY_QUEST_DONE
@ CONDITION_ACTIVE_EVENT
@ CONDITION_INSTANCE_INFO
@ CONDITION_RELATION_TO
@ CONDITION_PRIVATE_OBJECT
@ CONDITION_STAND_STATE
@ CONDITION_LABEL
@ CONDITION_DRUNKENSTATE
@ CONDITION_AURA
@ CONDITION_ACHIEVEMENT
@ CONDITION_OBJECT_ENTRY_GUID
@ CONDITION_PET_TYPE
@ CONDITION_DIFFICULTY_ID
@ CONDITION_DISTANCE_TO
@ CONDITION_SCENARIO_STEP
@ CONDITION_HP_VAL
@ CONDITION_BATTLE_PET_COUNT
@ CONDITION_GENDER
@ CONDITION_GAMEMASTER
@ CONDITION_TERRAIN_SWAP
@ CONDITION_REPUTATION_RANK
@ CONDITION_HP_PCT
@ CONDITION_QUEST_COMPLETE
@ CONDITION_MAX
@ CONDITION_SPELL
@ CONDITION_ZONEID
@ CONDITION_CHARMED
@ CONDITION_TYPE_MASK
@ CONDITION_AREAID
@ CONDITION_IN_WATER
@ CONDITION_ITEM
@ CONDITION_WORLD_STATE
@ CONDITION_SPAWNMASK
@ CONDITION_CLASS
@ CONDITION_TEAM
@ CONDITION_NONE
@ CONDITION_QUEST_NONE
@ CONDITION_QUESTSTATE
@ CONDITION_ITEM_EQUIPPED
@ CONDITION_SCENE_IN_PROGRESS
@ CONDITION_LEVEL
@ CONDITION_QUESTTAKEN
@ CONDITION_PLAYER_CONDITION
@ CONDITION_NEAR_CREATURE
@ CONDITION_TITLE
@ CONDITION_ALIVE
@ CONDITION_CREATURE_TYPE
@ CONDITION_UNIT_STATE
std::vector< Condition * > ConditionContainer
RelationType
@ RELATION_IN_PARTY
@ RELATION_IN_RAID_OR_PARTY
@ RELATION_CREATED_BY
@ RELATION_MAX
@ RELATION_SELF
@ RELATION_PASSENGER_OF
@ RELATION_OWNED_BY
#define MAX_EFFECT_MASK
Definition DBCEnums.h:387
#define MAX_DIFFICULTY
Definition DBCEnums.h:294
@ SPAWNMASK_RAID_ALL
Definition DBCEnums.h:312
DBCStorage< CharTitlesEntry > sCharTitlesStore(CharTitlesEntryfmt)
DBCStorage< FactionEntry > sFactionStore(FactionEntryfmt)
DBCStorage< AreaTriggerEntry > sAreaTriggerStore(AreaTriggerEntryfmt)
DBCStorage< AchievementEntry > sAchievementStore(Achievementfmt)
DBCStorage< SkillLineEntry > sSkillLineStore(SkillLinefmt)
DBCStorage< MapEntry > sMapStore(MapEntryfmt)
DBCStorage< AreaTableEntry > sAreaTableStore(AreaTableEntryfmt)
std::shared_ptr< ResultSet > QueryResult
DatabaseWorkerPool< WorldDatabaseConnection > WorldDatabase
Accessor to the world database.
uint8_t uint8
Definition Define.h:135
int32_t int32
Definition Define.h:129
uint64_t uint64
Definition Define.h:132
uint16_t uint16
Definition Define.h:134
uint32_t uint32
Definition Define.h:133
#define ABORT_MSG
Definition Errors.h:75
#define ASSERT_NOTNULL(pointer)
Definition Errors.h:84
#define ASSERT
Definition Errors.h:68
#define sGameEventMgr
@ GRID_MAP_TYPE_MASK_PLAYER
Definition GridDefines.h:75
@ GRID_MAP_TYPE_MASK_CREATURE
Definition GridDefines.h:72
@ GRID_MAP_TYPE_MASK_ALL
Definition GridDefines.h:76
@ GRID_MAP_TYPE_MASK_GAMEOBJECT
Definition GridDefines.h:74
@ GRID_MAP_TYPE_MASK_CORPSE
Definition GridDefines.h:71
EncounterState
#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_GAMEOBJECT
Definition ObjectGuid.h:40
@ TYPEID_UNIT
Definition ObjectGuid.h:38
@ TYPEID_CORPSE
Definition ObjectGuid.h:42
@ TYPEID_PLAYER
Definition ObjectGuid.h:39
@ TYPEMASK_UNIT
Definition ObjectGuid.h:52
@ TYPEMASK_CORPSE
Definition ObjectGuid.h:56
@ TYPEMASK_GAMEOBJECT
Definition ObjectGuid.h:54
@ TYPEMASK_PLAYER
Definition ObjectGuid.h:53
#define sObjectMgr
Definition ObjectMgr.h:1721
std::pair< GossipMenuItemsContainer::iterator, GossipMenuItemsContainer::iterator > GossipMenuItemsMapBoundsNonConst
Definition ObjectMgr.h:795
std::pair< GossipMenusContainer::iterator, GossipMenusContainer::iterator > GossipMenusMapBoundsNonConst
Definition ObjectMgr.h:792
@ MAX_PET_TYPE
Definition PetDefines.h:33
@ DRUNKEN_SMASHED
Definition Player.h:339
#define MAX_QUEST_LOG_SIZE
Definition QuestDef.h:36
QuestStatus
Definition QuestDef.h:102
@ QUEST_STATUS_REWARDED
Definition QuestDef.h:109
@ QUEST_STATUS_FAILED
Definition QuestDef.h:108
@ QUEST_STATUS_INCOMPLETE
Definition QuestDef.h:106
@ QUEST_STATUS_NONE
Definition QuestDef.h:103
@ MAX_QUEST_STATUS
Definition QuestDef.h:110
@ QUEST_STATUS_COMPLETE
Definition QuestDef.h:104
#define sScriptMgr
Definition ScriptMgr.h:1168
SpellEffIndex
@ EFFECT_2
@ SPELL_EFFECT_APPLY_AREA_AURA_PARTY
@ SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
@ 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_OWNER
Gender
@ CREATURE_TYPE_GAS_CLOUD
@ ALLIANCE
@ HORDE
#define CLASSMASK_ALL_PLAYABLE
#define RACEMASK_ALL_PLAYABLE
@ TARGET_FLAG_UNIT_MASK
@ TARGET_FLAG_CORPSE_MASK
@ TARGET_FLAG_GAMEOBJECT_MASK
uint32 GetTargetFlagMask(SpellTargetObjectTypes objType)
Definition SpellInfo.cpp:35
@ TARGET_SELECT_CATEGORY_CONE
Definition SpellInfo.h:46
@ TARGET_SELECT_CATEGORY_AREA
Definition SpellInfo.h:47
@ TARGET_SELECT_CATEGORY_NEARBY
Definition SpellInfo.h:45
@ TARGET_SELECT_CATEGORY_TRAJ
Definition SpellInfo.h:48
#define sSpellMgr
Definition SpellMgr.h:738
uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
Definition Timer.h:57
uint32 getMSTime()
Definition Timer.h:33
@ UNIT_STAND_STATE_SUBMERGED
Definition UnitDefines.h:43
@ UNIT_STATE_ALL_STATE_SUPPORTED
Definition Unit.h:265
bool CompareValues(ComparisionType type, T val1, T val2)
Definition Util.h:532
ComparisionType
Definition Util.h:522
@ COMP_TYPE_MAX
Definition Util.h:528
bool isConditionTypeValid(Condition *cond) const
bool IsSpellUsedInSpellClickConditions(uint32 spellId) const
ConditionEntriesByCreatureIdMap NpcVendorConditionContainerStore
std::unordered_set< uint32 > SpellsUsedInSpellClickConditions
bool addToSpellImplicitTargetConditions(Condition *cond) const
ConditionEntriesByCreatureIdMap VehicleSpellConditionStore
bool IsObjectMeetingVehicleSpellConditions(uint32 creatureId, uint32 spellId, Player *player, Unit *vehicle) const
std::vector< Condition * > AllocatedMemoryStore
ConditionContainer const * GetConditionsForSpellClickEvent(uint32 creatureId, uint32 spellId) const
bool isSourceTypeValid(Condition *cond) const
bool addToGossipMenus(Condition *cond) const
uint32 GetSearcherTypeMaskForConditionList(ConditionContainer const &conditions) const
bool IsObjectMeetingNotGroupedConditions(ConditionSourceType sourceType, uint32 entry, ConditionSourceInfo &sourceInfo) const
static ConditionMgr * instance()
SmartEventConditionContainer SmartEventConditionStore
bool HasConditionsForNotGroupedEntry(ConditionSourceType sourceType, uint32 entry) const
bool IsObjectMeetingSmartEventConditions(int32 entryOrGuid, uint32 eventId, uint32 sourceType, Unit *unit, WorldObject *baseObject) const
bool IsObjectMeetToConditionList(ConditionSourceInfo &sourceInfo, ConditionContainer const &conditions) const
bool IsObjectMeetingSpellClickConditions(uint32 creatureId, uint32 spellId, WorldObject *clicker, WorldObject *target) const
static void LogUselessConditionValue(Condition const *cond, uint8 index, uint32 value)
bool addToLootTemplate(Condition *cond, LootTemplate *loot) const
bool addToGossipMenuItems(Condition *cond) const
ConditionEntriesByTypeArray ConditionStore
static bool CanHaveSourceGroupSet(ConditionSourceType sourceType)
ConditionEntriesByCreatureIdMap SpellClickEventConditionStore
ConditionReferenceContainer ConditionReferenceStore
static bool CanHaveSourceIdSet(ConditionSourceType sourceType)
bool IsObjectMeetToConditions(WorldObject *object, ConditionContainer const &conditions) const
static ConditionTypeInfo const StaticConditionTypeData[CONDITION_MAX]
bool IsObjectMeetingVendorItemConditions(uint32 creatureId, uint32 itemId, Player *player, Creature *vendor) const
static char const *const StaticSourceTypeData[CONDITION_SOURCE_TYPE_MAX]
void LoadConditions(bool isReload=false)
Class used to access individual fields of database query result.
Definition Field.h:92
uint8 GetUInt8() const
Definition Field.cpp:29
std::string GetString() const
Definition Field.cpp:125
bool GetBool() const
Definition Field.h:100
uint32 GetUInt32() const
Definition Field.cpp:61
int32 GetInt32() const
Definition Field.cpp:69
std::vector< GameEventData > GameEventDataMap
Definition Group.h:165
bool isRaidGroup() const
Definition Group.cpp:2402
void ResetConditions()
Definition LootMgr.cpp:218
LootTemplate * GetLootForConditionFill(uint32 loot_id)
Definition LootMgr.cpp:237
bool HaveLootFor(uint32 loot_id) const
Definition LootMgr.h:78
bool isReference(uint32 id)
Definition LootMgr.cpp:771
bool addConditionItem(Condition *cond)
Definition LootMgr.cpp:713
Definition Map.h:302
bool IsDungeon() const
Definition Map.cpp:4231
static Creature * ToCreature(Object *o)
Definition Object.h:189
static Unit * ToUnit(Object *o)
Definition Object.h:195
static GameObject * ToGameObject(Object *o)
Definition Object.h:201
TypeID GetTypeId() const
Definition Object.h:93
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:78
static Player * ToPlayer(Object *o)
Definition Object.h:183
Definition Pet.h:40
Group * GetGroup()
Definition Player.h:2159
static bool IsValidGender(uint8 Gender)
Definition Player.h:1363
static DrunkenState GetDrunkenstateByValue(uint8 value)
Definition Player.cpp:865
std::array< uint32, QUEST_OBJECTIVES_COUNT > RequiredNpcOrGoCount
Definition QuestDef.h:309
uint32 GetQuestId() const
Definition QuestDef.h:228
std::array< int32, QUEST_OBJECTIVES_COUNT > RequiredNpcOrGo
Definition QuestDef.h:308
std::vector< Condition * > * ImplicitTargetConditions
Definition SpellInfo.h:230
uint32 Id
Definition SpellInfo.h:289
SpellEffectInfo const & GetEffect(SpellEffIndex index) const
Definition SpellInfo.h:483
std::array< SpellEffectInfo, MAX_SPELL_EFFECTS > const & GetEffects() const
Definition SpellInfo.h:482
Definition Unit.h:783
ObjectGuid GetCreatorGUID() const
Definition Unit.h:1256
ObjectGuid GetOwnerGUID() const override
Definition Unit.h:1254
bool IsOnVehicle(Unit const *vehicle) const
Definition Unit.cpp:11792
bool IsInRaidWith(Unit const *unit) const
Definition Unit.cpp:11863
bool IsInPartyWith(Unit const *unit) const
Definition Unit.cpp:11844
ReputationRank GetReactionTo(WorldObject const *target) const
Definition Object.cpp:2663
float GetDistance(WorldObject const *obj) const
Definition Object.cpp:1124
#define sWorld
Definition World.h:901
ObjectData const creatureData[]
Condition const * mLastFailedCondition
WorldObject * mConditionTargets[MAX_CONDITION_TARGETS]
uint32 SourceGroup
ConditionTypes ConditionType
std::string ToString(bool ext=false) const
std::string ConditionStringValue1
uint32 GetSearcherTypeMaskForCondition() const
uint32 ErrorType
uint32 SourceId
int32 SourceEntry
uint32 ElseGroup
uint32 ScriptId
bool NegativeCondition
ConditionSourceType SourceType
uint32 ConditionValue2
uint8 ConditionTarget
uint32 ReferenceId
uint32 ErrorTextId
uint32 ConditionValue3
uint32 GetMaxAvailableConditionTargets() const
uint32 ConditionValue1
bool Meets(ConditionSourceInfo &sourceInfo) const