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 "InstanceScript.h"
25#include "Log.h"
26#include "LootMgr.h"
27#include "Map.h"
28#include "ObjectMgr.h"
29#include "Player.h"
30#include "Pet.h"
31#include "ReputationMgr.h"
32#include "ScriptMgr.h"
33#include "SpellAuras.h"
34#include "SpellMgr.h"
35#include "World.h"
36
38{
39 "None",
40 "Creature Loot",
41 "Disenchant Loot",
42 "Fishing Loot",
43 "GameObject Loot",
44 "Item Loot",
45 "Mail Loot",
46 "Milling Loot",
47 "Pickpocketing Loot",
48 "Prospecting Loot",
49 "Reference Loot",
50 "Skinning Loot",
51 "Spell Loot",
52 "Spell Impl. Target",
53 "Gossip Menu",
54 "Gossip Menu Option",
55 "Creature Vehicle",
56 "Spell Expl. Target",
57 "Spell Click Event",
58 "Quest Accept",
59 "Quest Show Mark",
60 "Vehicle Spell",
61 "SmartScript",
62 "Npc Vendor",
63 "Spell Proc",
64 "Terrain Swap",
65 "Phase"
66};
67
69{
70 { "None", false, false, false, false },
71 { "Aura", true, true, true, false },
72 { "Item Stored", true, true, true, false },
73 { "Item Equipped", true, false, false, false },
74 { "Zone", true, false, false, false },
75 { "Reputation", true, true, false, false },
76 { "Team", true, false, false, false },
77 { "Skill", true, true, false, false },
78 { "Quest Rewarded", true, false, false, false },
79 { "Quest Taken", true, false, false, false },
80 { "Drunken", true, false, false, false },
81 { "WorldState", true, true, false, false },
82 { "Active Event", true, false, false, false },
83 { "Instance Info", true, true, true, false },
84 { "Quest None", true, false, false, false },
85 { "Class", true, false, false, false },
86 { "Race", true, false, false, false },
87 { "Achievement", true, false, false, false },
88 { "Title", true, false, false, false },
89 { "SpawnMask", true, false, false, false },
90 { "Gender", true, false, false, false },
91 { "Unit State", true, false, false, false },
92 { "Map", true, false, false, false },
93 { "Area", true, false, false, false },
94 { "CreatureType", true, false, false, false },
95 { "Spell Known", true, false, false, false },
96 { "PhaseMask", true, false, false, false },
97 { "Level", true, true, false, false },
98 { "Quest Completed", true, false, false, false },
99 { "Near Creature", true, true, true, false },
100 { "Near GameObject", true, true, false, false },
101 { "Object Entry or Guid", true, true, true, false },
102 { "Object TypeMask", true, false, false, false },
103 { "Relation", true, true, false, false },
104 { "Reaction", true, true, false, false },
105 { "Distance", true, true, true, false },
106 { "Alive", false, false, false, false },
107 { "Health Value", true, true, false, false },
108 { "Health Pct", true, true, false, false },
109 { "Realm Achievement", true, false, false, false },
110 { "In Water", false, false, false, false },
111 { "Terrain Swap", false, false, false, false },
112 { "Sit/stand state", true, true, false, false },
113 { "Daily Quest Completed", true, false, false, false },
114 { "Charmed", false, false, false, false },
115 { "Pet type", true, false, false, false },
116 { "On Taxi", false, false, false, false },
117 { "Quest state mask", true, true, false, false },
118 { "Quest objective progress", true, true, true, false },
119 { "Map Difficulty", true, false, false, false },
120 { "Is Gamemaster", true, false, false, false },
121 { "Object Entry or Guid", true, true, true, false },
122 { "Object TypeMask", true, false, false, false },
123 { "BattlePet Species Learned", true, true, true, false },
124 { "On Scenario Step", true, false, false, false },
125 { "Scene In Progress", true, false, false, false },
126 { "Player Condition", true, false, false, false },
127 { "Private Object", false, false, false, false },
128 { "String ID", false, false, false, true },
129 { "Label", false, false, false, false },
130};
131
132// Checks if object meets the condition
133// Can have CONDITION_SOURCE_TYPE_NONE && !mReferenceId if called from a special event (ie: SmartAI)
135{
137 WorldObject* object = sourceInfo.mConditionTargets[ConditionTarget];
138 // object not present, return false
139 if (!object)
140 {
141 TC_LOG_DEBUG("condition", "Condition object not found for {}", ToString());
142 return false;
143 }
144 bool condMeets = false;
145 switch (ConditionType)
146 {
147 case CONDITION_NONE:
148 condMeets = true; // empty condition, always met
149 break;
150 case CONDITION_AURA:
151 {
152 if (Unit* unit = object->ToUnit())
153 condMeets = unit->HasAuraEffect(ConditionValue1, ConditionValue2);
154 break;
155 }
156 case CONDITION_ITEM:
157 {
158 if (Player* player = object->ToPlayer())
159 {
160 // don't allow 0 items (it's checked during table load)
162 bool checkBank = ConditionValue3 ? true : false;
163 condMeets = player->HasItemCount(ConditionValue1, ConditionValue2, checkBank);
164 }
165 break;
166 }
168 {
169 if (Player* player = object->ToPlayer())
170 condMeets = player->HasItemOrGemWithIdEquipped(ConditionValue1, 1);
171 break;
172 }
173 case CONDITION_ZONEID:
174 condMeets = object->GetZoneId() == ConditionValue1;
175 break;
177 {
178 if (Player* player = object->ToPlayer())
179 {
180 if (FactionEntry const* faction = sFactionStore.LookupEntry(ConditionValue1))
181 condMeets = (ConditionValue2 & (1 << player->GetReputationMgr().GetRank(faction))) != 0;
182 }
183 break;
184 }
186 {
187 if (Player* player = object->ToPlayer())
188 condMeets = player->HasAchieved(ConditionValue1);
189 break;
190 }
191 case CONDITION_TEAM:
192 {
193 if (Player* player = object->ToPlayer())
194 condMeets = player->GetTeam() == ConditionValue1;
195 break;
196 }
197 case CONDITION_CLASS:
198 {
199 if (Unit* unit = object->ToUnit())
200 condMeets = (unit->GetClassMask() & ConditionValue1) != 0;
201 break;
202 }
203 case CONDITION_RACE:
204 {
205 if (Unit* unit = object->ToUnit())
206 condMeets = (unit->GetRaceMask() & ConditionValue1) != 0;
207 break;
208 }
209 case CONDITION_GENDER:
210 {
211 if (Player* player = object->ToPlayer())
212 condMeets = player->GetNativeGender() == Gender(ConditionValue1);
213 break;
214 }
215 case CONDITION_SKILL:
216 {
217 if (Player* player = object->ToPlayer())
218 condMeets = player->HasSkill(ConditionValue1) && player->GetBaseSkillValue(ConditionValue1) >= ConditionValue2;
219 break;
220 }
222 {
223 if (Player* player = object->ToPlayer())
224 condMeets = player->GetQuestRewardStatus(ConditionValue1);
225 break;
226 }
228 {
229 if (Player* player = object->ToPlayer())
230 {
231 QuestStatus status = player->GetQuestStatus(ConditionValue1);
232 condMeets = (status == QUEST_STATUS_INCOMPLETE);
233 }
234 break;
235 }
237 {
238 if (Player* player = object->ToPlayer())
239 {
240 QuestStatus status = player->GetQuestStatus(ConditionValue1);
241 condMeets = (status == QUEST_STATUS_COMPLETE && !player->GetQuestRewardStatus(ConditionValue1));
242 }
243 break;
244 }
246 {
247 if (Player* player = object->ToPlayer())
248 {
249 QuestStatus status = player->GetQuestStatus(ConditionValue1);
250 condMeets = (status == QUEST_STATUS_NONE);
251 }
252 break;
253 }
255 condMeets = sGameEventMgr->IsActiveEvent(ConditionValue1);
256 break;
258 {
259 Map* map = object->GetMap();
260 if (map->IsDungeon())
261 {
262 if (InstanceScript const* instance = ((InstanceMap*)map)->GetInstanceScript())
263 {
264 switch (ConditionValue3)
265 {
267 condMeets = instance->GetData(ConditionValue1) == ConditionValue2;
268 break;
270 condMeets = instance->GetGuidData(ConditionValue1).GetRawValue() == uint64(ConditionValue2);
271 break;
273 condMeets = instance->GetBossState(ConditionValue1) == EncounterState(ConditionValue2);
274 break;
276 condMeets = instance->GetData64(ConditionValue1) == ConditionValue2;
277 break;
278 }
279 }
280 }
281 break;
282 }
283 case CONDITION_MAPID:
284 condMeets = object->GetMapId() == ConditionValue1;
285 break;
286 case CONDITION_AREAID:
287 condMeets = object->GetAreaId() == ConditionValue1;
288 break;
289 case CONDITION_SPELL:
290 {
291 if (Player* player = object->ToPlayer())
292 condMeets = player->HasSpell(ConditionValue1);
293 break;
294 }
295 case CONDITION_LEVEL:
296 {
297 if (Unit* unit = object->ToUnit())
298 condMeets = CompareValues(static_cast<ComparisionType>(ConditionValue2), static_cast<uint32>(unit->GetLevel()), ConditionValue1);
299 break;
300 }
302 {
303 if (Player* player = object->ToPlayer())
304 condMeets = (uint32)Player::GetDrunkenstateByValue(player->GetDrunkValue()) >= ConditionValue1;
305 break;
306 }
308 {
309 condMeets = object->FindNearestCreature(ConditionValue1, (float)ConditionValue2, bool(!ConditionValue3)) != nullptr;
310 break;
311 }
313 {
314 condMeets = object->FindNearestGameObject(ConditionValue1, (float)ConditionValue2) != nullptr;
315 break;
316 }
318 {
319 if (uint32(object->GetTypeId()) == ConditionValue1)
320 {
321 condMeets = !ConditionValue2 || (object->GetEntry() == ConditionValue2);
322
323 if (ConditionValue3)
324 {
325 switch (object->GetTypeId())
326 {
327 case TYPEID_UNIT:
328 condMeets &= object->ToCreature()->GetSpawnId() == ConditionValue3;
329 break;
331 condMeets &= object->ToGameObject()->GetSpawnId() == ConditionValue3;
332 break;
333 default:
334 break;
335 }
336 }
337 }
338 break;
339 }
341 {
342 condMeets = object->isType(ConditionValue1);
343 break;
344 }
346 {
347 if (WorldObject* toObject = sourceInfo.mConditionTargets[ConditionValue1])
348 {
349 Unit* toUnit = toObject->ToUnit();
350 Unit* unit = object->ToUnit();
351 if (toUnit && unit)
352 {
353 switch (static_cast<RelationType>(ConditionValue2))
354 {
355 case RELATION_SELF:
356 condMeets = unit == toUnit;
357 break;
359 condMeets = unit->IsInPartyWith(toUnit);
360 break;
362 condMeets = unit->IsInRaidWith(toUnit);
363 break;
365 condMeets = unit->GetOwnerGUID() == toUnit->GetGUID();
366 break;
368 condMeets = unit->IsOnVehicle(toUnit);
369 break;
371 condMeets = unit->GetCreatorGUID() == toUnit->GetGUID();
372 break;
373 default:
374 break;
375 }
376 }
377 }
378 break;
379 }
381 {
382 if (WorldObject* toObject = sourceInfo.mConditionTargets[ConditionValue1])
383 {
384 Unit* toUnit = toObject->ToUnit();
385 Unit* unit = object->ToUnit();
386 if (toUnit && unit)
387 condMeets = ((1 << unit->GetReactionTo(toUnit)) & ConditionValue2) != 0;
388 }
389 break;
390 }
392 {
393 if (WorldObject* toObject = sourceInfo.mConditionTargets[ConditionValue1])
394 condMeets = CompareValues(static_cast<ComparisionType>(ConditionValue3), object->GetDistance(toObject), static_cast<float>(ConditionValue2));
395 break;
396 }
397 case CONDITION_ALIVE:
398 {
399 if (Unit* unit = object->ToUnit())
400 condMeets = unit->IsAlive();
401 break;
402 }
403 case CONDITION_HP_VAL:
404 {
405 if (Unit* unit = object->ToUnit())
406 condMeets = CompareValues(static_cast<ComparisionType>(ConditionValue2), unit->GetHealth(), static_cast<uint32>(ConditionValue1));
407 break;
408 }
409 case CONDITION_HP_PCT:
410 {
411 if (Unit* unit = object->ToUnit())
412 condMeets = CompareValues(static_cast<ComparisionType>(ConditionValue2), unit->GetHealthPct(), static_cast<float>(ConditionValue1));
413 break;
414 }
416 {
417 condMeets = ConditionValue2 == sWorld->getWorldState(ConditionValue1);
418 break;
419 }
421 {
422 condMeets = (object->GetPhaseMask() & ConditionValue1) != 0;
423 break;
424 }
425 case CONDITION_TITLE:
426 {
427 if (Player* player = object->ToPlayer())
428 condMeets = player->HasTitle(ConditionValue1);
429 break;
430 }
432 {
433 condMeets = ((1 << object->GetMap()->GetSpawnMode()) & ConditionValue1) != 0;
434 break;
435 }
437 {
438 if (Unit* unit = object->ToUnit())
439 condMeets = unit->HasUnitState(ConditionValue1);
440 break;
441 }
443 {
444 if (Creature* creature = object->ToCreature())
445 condMeets = creature->GetCreatureTemplate()->type == ConditionValue1;
446 break;
447 }
449 {
450 AchievementEntry const* achievement = sAchievementStore.LookupEntry(ConditionValue1);
451 if (achievement && sAchievementMgr->IsRealmCompleted(achievement))
452 condMeets = true;
453 break;
454 }
456 {
457 if (Unit* unit = object->ToUnit())
458 condMeets = unit->IsInWater();
459 break;
460 }
462 {
463 if (Unit* unit = object->ToUnit())
464 {
465 if (ConditionValue1 == 0)
466 condMeets = (unit->GetStandState() == ConditionValue2);
467 else if (ConditionValue2 == 0)
468 condMeets = unit->IsStandState();
469 else if (ConditionValue2 == 1)
470 condMeets = unit->IsSitState();
471 }
472 break;
473 }
475 {
476 if (Player* player = object->ToPlayer())
477 condMeets = player->IsDailyQuestDone(ConditionValue1);
478 break;
479 }
481 {
482 if (Unit* unit = object->ToUnit())
483 condMeets = unit->IsCharmed();
484 break;
485 }
487 {
488 if (Player* player = object->ToPlayer())
489 if (Pet* pet = player->GetPet())
490 condMeets = (((1 << pet->getPetType()) & ConditionValue1) != 0);
491 break;
492 }
493 case CONDITION_TAXI:
494 {
495 if (Player* player = object->ToPlayer())
496 condMeets = player->IsInFlight();
497 break;
498 }
500 {
501 if (Player* player = object->ToPlayer())
502 {
503 if (
504 ((ConditionValue2 & (1 << QUEST_STATUS_NONE)) && (player->GetQuestStatus(ConditionValue1) == QUEST_STATUS_NONE)) ||
505 ((ConditionValue2 & (1 << QUEST_STATUS_COMPLETE)) && (player->GetQuestStatus(ConditionValue1) == QUEST_STATUS_COMPLETE)) ||
506 ((ConditionValue2 & (1 << QUEST_STATUS_INCOMPLETE)) && (player->GetQuestStatus(ConditionValue1) == QUEST_STATUS_INCOMPLETE)) ||
507 ((ConditionValue2 & (1 << QUEST_STATUS_FAILED)) && (player->GetQuestStatus(ConditionValue1) == QUEST_STATUS_FAILED)) ||
508 ((ConditionValue2 & (1 << QUEST_STATUS_REWARDED)) && player->GetQuestRewardStatus(ConditionValue1))
509 )
510 condMeets = true;
511 }
512 break;
513 }
515 {
516 if (Player* player = object->ToPlayer())
517 {
518 const Quest* quest = ASSERT_NOTNULL(sObjectMgr->GetQuestTemplate(ConditionValue1));
519 uint16 log_slot = player->FindQuestSlot(quest->GetQuestId());
520 if (log_slot >= MAX_QUEST_LOG_SIZE)
521 break;
522 if (player->GetQuestSlotCounter(log_slot, ConditionValue2) == ConditionValue3)
523 condMeets = true;
524 }
525 break;
526 }
528 {
529 condMeets = object->GetMap()->GetDifficulty() == ConditionValue1;
530 break;
531 }
533 {
534 if (Player* player = object->ToPlayer())
535 {
536 if (ConditionValue1 == 1)
537 condMeets = player->CanBeGameMaster();
538 else
539 condMeets = player->IsGameMaster();
540 }
541 break;
542 }
544 {
545 if (Creature const* creature = object->ToCreature())
546 condMeets = creature->HasStringId(ConditionStringValue1);
547 else if (GameObject const* go = object->ToGameObject())
548 condMeets = go->HasStringId(ConditionStringValue1);
549 break;
550 }
551 default:
552 condMeets = false;
553 break;
554 }
555
557 condMeets = !condMeets;
558
559 if (!condMeets)
560 sourceInfo.mLastFailedCondition = this;
561
562 return condMeets && sScriptMgr->OnConditionCheck(this, sourceInfo); // Returns true by default.;
563}
564
566{
567 // build mask of types for which condition can return true
568 // this is used for speeding up gridsearches
570 return (GRID_MAP_TYPE_MASK_ALL);
571 uint32 mask = 0;
572 switch (ConditionType)
573 {
574 case CONDITION_NONE:
576 break;
577 case CONDITION_AURA:
579 break;
580 case CONDITION_ITEM:
582 break;
585 break;
586 case CONDITION_ZONEID:
588 break;
591 break;
594 break;
595 case CONDITION_TEAM:
597 break;
598 case CONDITION_CLASS:
600 break;
601 case CONDITION_RACE:
603 break;
604 case CONDITION_SKILL:
606 break;
609 break;
612 break;
615 break;
618 break;
621 break;
624 break;
625 case CONDITION_MAPID:
627 break;
628 case CONDITION_AREAID:
630 break;
631 case CONDITION_SPELL:
633 break;
634 case CONDITION_LEVEL:
636 break;
639 break;
642 break;
645 break;
647 switch (ConditionValue1)
648 {
649 case TYPEID_UNIT:
651 break;
652 case TYPEID_PLAYER:
654 break;
657 break;
658 case TYPEID_CORPSE:
660 break;
661 default:
662 break;
663 }
664 break;
674 break;
677 break;
680 break;
683 break;
684 case CONDITION_ALIVE:
686 break;
687 case CONDITION_HP_VAL:
689 break;
690 case CONDITION_HP_PCT:
692 break;
695 break;
698 break;
699 case CONDITION_TITLE:
701 break;
704 break;
705 case CONDITION_GENDER:
707 break;
710 break;
713 break;
716 break;
719 break;
722 break;
725 break;
728 break;
731 break;
732 case CONDITION_TAXI:
734 break;
737 break;
740 break;
743 break;
746 break;
748 mask |= GRID_MAP_TYPE_MASK_ALL & ~GRID_MAP_TYPE_MASK_PLAYER;
749 break;
752 break;
753 default:
754 ABORT_MSG("Condition::GetSearcherTypeMaskForCondition - missing condition handling!");
755 break;
756 }
757 return mask;
758}
759
780
781std::string Condition::ToString(bool ext /*= false*/) const
782{
783 std::ostringstream ss;
784 ss << "[Condition ";
785 ss << "SourceType: " << SourceType;
788 else
789 ss << " (Unknown)";
791 ss << ", SourceGroup: " << SourceGroup;
792 ss << ", SourceEntry: " << SourceEntry;
794 ss << ", SourceId: " << SourceId;
795
796 if (ext)
797 {
798 ss << ", ConditionType: " << ConditionType;
801 else
802 ss << " (Unknown)";
803 }
804
805 ss << "]";
806 return ss.str();
807}
808
810
815
817{
818 if (conditions.empty())
820 // groupId, typeMask
821 std::map<uint32, uint32> elseGroupSearcherTypeMasks;
822 for (ConditionContainer::const_iterator i = conditions.begin(); i != conditions.end(); ++i)
823 {
824 // no point of having not loaded conditions in list
825 ASSERT((*i)->isLoaded() && "ConditionMgr::GetSearcherTypeMaskForConditionList - not yet loaded condition found in list");
826 std::map<uint32, uint32>::const_iterator itr = elseGroupSearcherTypeMasks.find((*i)->ElseGroup);
827 // group not filled yet, fill with widest mask possible
828 if (itr == elseGroupSearcherTypeMasks.end())
829 elseGroupSearcherTypeMasks[(*i)->ElseGroup] = GRID_MAP_TYPE_MASK_ALL;
830 // no point of checking anymore, empty mask
831 else if (!itr->second)
832 continue;
833
834 if ((*i)->ReferenceId) // handle reference
835 {
836 ConditionReferenceContainer::const_iterator ref = ConditionReferenceStore.find((*i)->ReferenceId);
837 ASSERT(ref != ConditionReferenceStore.end() && "ConditionMgr::GetSearcherTypeMaskForConditionList - incorrect reference");
838 elseGroupSearcherTypeMasks[(*i)->ElseGroup] &= GetSearcherTypeMaskForConditionList((*ref).second);
839 }
840 else // handle normal condition
841 {
842 // object will match conditions in one ElseGroupStore only when it matches all of them
843 // so, let's find a smallest possible mask which satisfies all conditions
844 elseGroupSearcherTypeMasks[(*i)->ElseGroup] &= (*i)->GetSearcherTypeMaskForCondition();
845 }
846 }
847 // object will match condition when one of the checks in ElseGroupStore is matching
848 // so, let's include all possible masks
849 uint32 mask = 0;
850 for (std::map<uint32, uint32>::const_iterator i = elseGroupSearcherTypeMasks.begin(); i != elseGroupSearcherTypeMasks.end(); ++i)
851 mask |= i->second;
852
853 return mask;
854}
855
857{
858 // groupId, groupCheckPassed
859 std::map<uint32, bool> elseGroupStore;
860 for (Condition const* condition : conditions)
861 {
862 TC_LOG_DEBUG("condition", "ConditionMgr::IsPlayerMeetToConditionList {} val1: {}", condition->ToString(), condition->ConditionValue1);
863 if (condition->isLoaded())
864 {
866 std::map<uint32, bool>::const_iterator itr = elseGroupStore.find(condition->ElseGroup);
868 if (itr == elseGroupStore.end())
869 elseGroupStore[condition->ElseGroup] = true;
870 else if (!(*itr).second)
871 continue;
872
873 if (condition->ReferenceId)//handle reference
874 {
875 ConditionReferenceContainer::const_iterator ref = ConditionReferenceStore.find(condition->ReferenceId);
876 if (ref != ConditionReferenceStore.end())
877 {
878 if (!IsObjectMeetToConditionList(sourceInfo, ref->second))
879 elseGroupStore[condition->ElseGroup] = false;
880 }
881 else
882 {
883 TC_LOG_DEBUG("condition", "ConditionMgr::IsPlayerMeetToConditionList {} Reference template -{} not found",
884 condition->ToString(), condition->ReferenceId); // checked at loading, should never happen
885 }
886
887 }
888 else //handle normal condition
889 {
890 if (!condition->Meets(sourceInfo))
891 elseGroupStore[condition->ElseGroup] = false;
892 }
893 }
894 }
895 for (std::map<uint32, bool>::const_iterator i = elseGroupStore.begin(); i != elseGroupStore.end(); ++i)
896 if (i->second)
897 return true;
898
899 return false;
900}
901
903{
905 return IsObjectMeetToConditions(srcInfo, conditions);
906}
907
909{
910 ConditionSourceInfo srcInfo = ConditionSourceInfo(object1, object2);
911 return IsObjectMeetToConditions(srcInfo, conditions);
912}
913
915{
916 if (conditions.empty())
917 return true;
918
919 TC_LOG_DEBUG("condition", "ConditionMgr::IsObjectMeetToConditions");
920 return IsObjectMeetToConditionList(sourceInfo, conditions);
921}
922
945
950
952{
953 if (sourceType > CONDITION_SOURCE_TYPE_NONE && sourceType < CONDITION_SOURCE_TYPE_MAX)
954 {
955 ConditionsByEntryMap::const_iterator i = ConditionStore[sourceType].find(entry);
956 if (i != ConditionStore[sourceType].end())
957 {
958 TC_LOG_DEBUG("condition", "GetConditionsForNotGroupedEntry: found conditions for type {} and entry {}", uint32(sourceType), entry);
959 return IsObjectMeetToConditions(sourceInfo, i->second);
960 }
961 }
962
963 return true;
964}
965
966bool ConditionMgr::IsObjectMeetingNotGroupedConditions(ConditionSourceType sourceType, uint32 entry, WorldObject* target0, WorldObject* target1 /*= nullptr*/, WorldObject* target2 /*= nullptr*/) const
967{
968 ConditionSourceInfo conditionSource(target0, target1, target2);
969 return IsObjectMeetingNotGroupedConditions(sourceType, entry, conditionSource);
970}
971
973{
974 if (sourceType > CONDITION_SOURCE_TYPE_NONE && sourceType < CONDITION_SOURCE_TYPE_MAX)
975 if (ConditionStore[sourceType].find(entry) != ConditionStore[sourceType].end())
976 return true;
977
978 return false;
979}
980
982{
983 ConditionEntriesByCreatureIdMap::const_iterator itr = SpellClickEventConditionStore.find(creatureId);
984 if (itr != SpellClickEventConditionStore.end())
985 {
986 ConditionsByEntryMap::const_iterator i = itr->second.find(spellId);
987 if (i != itr->second.end())
988 {
989 TC_LOG_DEBUG("condition", "GetConditionsForSpellClickEvent: found conditions for SpellClickEvent entry {} spell {}", creatureId, spellId);
990 ConditionSourceInfo sourceInfo(clicker, target);
991 return IsObjectMeetToConditions(sourceInfo, i->second);
992 }
993 }
994 return true;
995}
996
998{
999 ConditionEntriesByCreatureIdMap::const_iterator itr = SpellClickEventConditionStore.find(creatureId);
1000 if (itr != SpellClickEventConditionStore.end())
1001 {
1002 ConditionsByEntryMap::const_iterator i = itr->second.find(spellId);
1003 if (i != itr->second.end())
1004 {
1005 TC_LOG_DEBUG("condition", "GetConditionsForSpellClickEvent: found conditions for SpellClickEvent entry {} spell {}", creatureId, spellId);
1006 return &i->second;
1007 }
1008 }
1009 return nullptr;
1010}
1011
1012bool ConditionMgr::IsObjectMeetingVehicleSpellConditions(uint32 creatureId, uint32 spellId, Player* player, Unit* vehicle) const
1013{
1014 ConditionEntriesByCreatureIdMap::const_iterator itr = VehicleSpellConditionStore.find(creatureId);
1015 if (itr != VehicleSpellConditionStore.end())
1016 {
1017 ConditionsByEntryMap::const_iterator i = itr->second.find(spellId);
1018 if (i != itr->second.end())
1019 {
1020 TC_LOG_DEBUG("condition", "GetConditionsForVehicleSpell: found conditions for Vehicle entry {} spell {}", creatureId, spellId);
1021 ConditionSourceInfo sourceInfo(player, vehicle);
1022 return IsObjectMeetToConditions(sourceInfo, i->second);
1023 }
1024 }
1025 return true;
1026}
1027
1028bool ConditionMgr::IsObjectMeetingSmartEventConditions(int32 entryOrGuid, uint32 eventId, uint32 sourceType, Unit* unit, WorldObject* baseObject) const
1029{
1030 SmartEventConditionContainer::const_iterator itr = SmartEventConditionStore.find(std::make_pair(entryOrGuid, sourceType));
1031 if (itr != SmartEventConditionStore.end())
1032 {
1033 ConditionsByEntryMap::const_iterator i = itr->second.find(eventId + 1);
1034 if (i != itr->second.end())
1035 {
1036 TC_LOG_DEBUG("condition", "GetConditionsForSmartEvent: found conditions for Smart Event entry or guid {} eventId {}", entryOrGuid, eventId);
1037 ConditionSourceInfo sourceInfo(unit, baseObject);
1038 return IsObjectMeetToConditions(sourceInfo, i->second);
1039 }
1040 }
1041 return true;
1042}
1043
1045{
1046 ConditionEntriesByCreatureIdMap::const_iterator itr = NpcVendorConditionContainerStore.find(creatureId);
1047 if (itr != NpcVendorConditionContainerStore.end())
1048 {
1049 ConditionsByEntryMap::const_iterator i = (*itr).second.find(itemId);
1050 if (i != (*itr).second.end())
1051 {
1052 TC_LOG_DEBUG("condition", "GetConditionsForNpcVendorEvent: found conditions for creature entry {} item {}", creatureId, itemId);
1053 ConditionSourceInfo sourceInfo(player, vendor);
1054 return IsObjectMeetToConditions(sourceInfo, i->second);
1055 }
1056 }
1057 return true;
1058}
1059
1064
1066{
1067 static ConditionMgr instance;
1068 return &instance;
1069}
1070
1072{
1073 uint32 oldMSTime = getMSTime();
1074
1075 Clean();
1076
1077 //must clear all custom handled cases (groupped types) before reload
1078 if (isReload)
1079 {
1080 TC_LOG_INFO("misc", "Reseting Loot Conditions...");
1093
1094 TC_LOG_INFO("misc", "Re-Loading `gossip_menu` Table for Conditions!");
1095 sObjectMgr->LoadGossipMenu();
1096
1097 TC_LOG_INFO("misc", "Re-Loading `gossip_menu_option` Table for Conditions!");
1098 sObjectMgr->LoadGossipMenuItems();
1099 sSpellMgr->UnloadSpellInfoImplicitTargetConditionLists();
1100 }
1101
1102 QueryResult result = WorldDatabase.Query("SELECT SourceTypeOrReferenceId, SourceGroup, SourceEntry, SourceId, ElseGroup, ConditionTypeOrReference, ConditionTarget, "
1103 "ConditionValue1, ConditionValue2, ConditionValue3, ConditionStringValue1, "
1104 "NegativeCondition, ErrorType, ErrorTextId, ScriptName FROM conditions");
1105
1106 if (!result)
1107 {
1108 TC_LOG_INFO("server.loading", ">> Loaded 0 conditions. DB table `conditions` is empty!");
1109 return;
1110 }
1111
1112 uint32 count = 0;
1113
1114 do
1115 {
1116 Field* fields = result->Fetch();
1117
1118 Condition* cond = new Condition();
1119 int32 iSourceTypeOrReferenceId = fields[0].GetInt32();
1120 cond->SourceGroup = fields[1].GetUInt32();
1121 cond->SourceEntry = fields[2].GetInt32();
1122 cond->SourceId = fields[3].GetInt32();
1123 cond->ElseGroup = fields[4].GetUInt32();
1124 int32 iConditionTypeOrReference = fields[5].GetInt32();
1125 cond->ConditionTarget = fields[6].GetUInt8();
1126 cond->ConditionValue1 = fields[7].GetUInt32();
1127 cond->ConditionValue2 = fields[8].GetUInt32();
1128 cond->ConditionValue3 = fields[9].GetUInt32();
1129 cond->ConditionStringValue1 = fields[10].GetString();
1130 cond->NegativeCondition = fields[11].GetBool();
1131 cond->ErrorType = fields[12].GetUInt32();
1132 cond->ErrorTextId = fields[13].GetUInt32();
1133 cond->ScriptId = sObjectMgr->GetScriptId(fields[14].GetString());
1134
1135 if (iConditionTypeOrReference >= 0)
1136 cond->ConditionType = ConditionTypes(iConditionTypeOrReference);
1137
1138 if (iSourceTypeOrReferenceId >= 0)
1139 cond->SourceType = ConditionSourceType(iSourceTypeOrReferenceId);
1140
1141 if (iConditionTypeOrReference < 0)//it has a reference
1142 {
1143 if (iConditionTypeOrReference == iSourceTypeOrReferenceId)//self referencing, skip
1144 {
1145 TC_LOG_ERROR("sql.sql", "Condition reference {} is referencing self, skipped", iSourceTypeOrReferenceId);
1146 delete cond;
1147 continue;
1148 }
1149 cond->ReferenceId = uint32(abs(iConditionTypeOrReference));
1150
1151 char const* rowType = "reference template";
1152 if (iSourceTypeOrReferenceId >= 0)
1153 rowType = "reference";
1154 //check for useless data
1155 if (cond->ConditionTarget)
1156 TC_LOG_ERROR("sql.sql", "Condition {} {} has useless data in ConditionTarget ({})!", rowType, iSourceTypeOrReferenceId, cond->ConditionTarget);
1157 if (cond->ConditionValue1)
1158 TC_LOG_ERROR("sql.sql", "Condition {} {} has useless data in value1 ({})!", rowType, iSourceTypeOrReferenceId, cond->ConditionValue1);
1159 if (cond->ConditionValue2)
1160 TC_LOG_ERROR("sql.sql", "Condition {} {} has useless data in value2 ({})!", rowType, iSourceTypeOrReferenceId, cond->ConditionValue2);
1161 if (cond->ConditionValue3)
1162 TC_LOG_ERROR("sql.sql", "Condition {} {} has useless data in value3 ({})!", rowType, iSourceTypeOrReferenceId, cond->ConditionValue3);
1163 if (cond->NegativeCondition)
1164 TC_LOG_ERROR("sql.sql", "Condition {} {} has useless data in NegativeCondition ({})!", rowType, iSourceTypeOrReferenceId, cond->NegativeCondition);
1165 if (cond->SourceGroup && iSourceTypeOrReferenceId < 0)
1166 TC_LOG_ERROR("sql.sql", "Condition {} {} has useless data in SourceGroup ({})!", rowType, iSourceTypeOrReferenceId, cond->SourceGroup);
1167 if (cond->SourceEntry && iSourceTypeOrReferenceId < 0)
1168 TC_LOG_ERROR("sql.sql", "Condition {} {} has useless data in SourceEntry ({})!", rowType, iSourceTypeOrReferenceId, cond->SourceEntry);
1169 }
1170 else if (!isConditionTypeValid(cond))//doesn't have reference, validate ConditionType
1171 {
1172 delete cond;
1173 continue;
1174 }
1175
1176 if (iSourceTypeOrReferenceId < 0)//it is a reference template
1177 {
1178 ConditionReferenceStore[std::abs(iSourceTypeOrReferenceId)].push_back(cond);//add to reference storage
1179 ++count;
1180 continue;
1181 }//end of reference templates
1182
1183 //if not a reference and SourceType is invalid, skip
1184 if (iConditionTypeOrReference >= 0 && !isSourceTypeValid(cond))
1185 {
1186 delete cond;
1187 continue;
1188 }
1189
1190 //Grouping is only allowed for some types (loot templates, gossip menus, gossip items)
1191 if (cond->SourceGroup && !CanHaveSourceGroupSet(cond->SourceType))
1192 {
1193 TC_LOG_ERROR("sql.sql", "{} has not allowed value of SourceGroup = {}!", cond->ToString(), cond->SourceGroup);
1194 delete cond;
1195 continue;
1196 }
1197 if (cond->SourceId && !CanHaveSourceIdSet(cond->SourceType))
1198 {
1199 TC_LOG_ERROR("sql.sql", "{} has not allowed value of SourceId = {}!", cond->ToString(), cond->SourceId);
1200 delete cond;
1201 continue;
1202 }
1203
1204 if (cond->ErrorType && cond->SourceType != CONDITION_SOURCE_TYPE_SPELL)
1205 {
1206 TC_LOG_ERROR("sql.sql", "{} can't have ErrorType ({}), set to 0!", cond->ToString(), cond->ErrorType);
1207 cond->ErrorType = 0;
1208 }
1209
1210 if (cond->ErrorTextId && !cond->ErrorType)
1211 {
1212 TC_LOG_ERROR("sql.sql", "{} has any ErrorType, ErrorTextId ({}) is set, set to 0!", cond->ToString(), cond->ErrorTextId);
1213 cond->ErrorTextId = 0;
1214 }
1215
1216 if (cond->SourceGroup)
1217 {
1218 bool valid = false;
1219 // handle grouped conditions
1220 switch (cond->SourceType)
1221 {
1224 break;
1227 break;
1230 break;
1233 break;
1236 break;
1239 break;
1242 break;
1245 break;
1248 break;
1251 break;
1254 break;
1257 break;
1259 valid = addToGossipMenus(cond);
1260 break;
1262 valid = addToGossipMenuItems(cond);
1263 break;
1265 {
1266 SpellClickEventConditionStore[cond->SourceGroup][cond->SourceEntry].push_back(cond);
1267 if (cond->ConditionType == CONDITION_AURA)
1269 valid = true;
1270 ++count;
1271 continue; // do not add to m_AllocatedMemory to avoid double deleting
1272 }
1275 break;
1277 {
1278 VehicleSpellConditionStore[cond->SourceGroup][cond->SourceEntry].push_back(cond);
1279 valid = true;
1280 ++count;
1281 continue; // do not add to m_AllocatedMemory to avoid double deleting
1282 }
1284 {
1286 std::pair<int32, uint32> key = std::make_pair(cond->SourceEntry, cond->SourceId);
1287 SmartEventConditionStore[key][cond->SourceGroup].push_back(cond);
1288 valid = true;
1289 ++count;
1290 continue;
1291 }
1293 {
1294 NpcVendorConditionContainerStore[cond->SourceGroup][cond->SourceEntry].push_back(cond);
1295 valid = true;
1296 ++count;
1297 continue;
1298 }
1299 default:
1300 break;
1301 }
1302
1303 if (!valid)
1304 {
1305 TC_LOG_ERROR("sql.sql", "{} Not handled grouped condition.", cond->ToString());
1306 delete cond;
1307 }
1308 else
1309 {
1310 AllocatedMemoryStore.push_back(cond);
1311 ++count;
1312 }
1313 continue;
1314 }
1315
1316 //handle not grouped conditions
1317 //add new Condition to storage based on Type/Entry
1320 ConditionStore[cond->SourceType][cond->SourceEntry].push_back(cond);
1321 ++count;
1322 }
1323 while (result->NextRow());
1324
1325 TC_LOG_INFO("server.loading", ">> Loaded {} conditions in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
1326}
1327
1329{
1330 if (!loot)
1331 {
1332 TC_LOG_ERROR("sql.sql", "{} LootTemplate {} not found.", cond->ToString(), cond->SourceGroup);
1333 return false;
1334 }
1335
1336 if (loot->addConditionItem(cond))
1337 return true;
1338
1339 TC_LOG_ERROR("sql.sql", "{} Item {} not found in LootTemplate {}.", cond->ToString(), cond->SourceEntry, cond->SourceGroup);
1340 return false;
1341}
1342
1344{
1345 GossipMenusMapBoundsNonConst pMenuBounds = sObjectMgr->GetGossipMenusMapBoundsNonConst(cond->SourceGroup);
1346
1347 if (pMenuBounds.first != pMenuBounds.second)
1348 {
1349 for (GossipMenusContainer::iterator itr = pMenuBounds.first; itr != pMenuBounds.second; ++itr)
1350 {
1351 if ((*itr).second.MenuID == cond->SourceGroup && (*itr).second.TextID == uint32(cond->SourceEntry))
1352 {
1353 (*itr).second.Conditions.push_back(cond);
1354 return true;
1355 }
1356 }
1357 }
1358
1359 TC_LOG_ERROR("sql.sql", "{} GossipMenu {} not found.", cond->ToString(), cond->SourceGroup);
1360 return false;
1361}
1362
1364{
1365 GossipMenuItemsMapBoundsNonConst pMenuItemBounds = sObjectMgr->GetGossipMenuItemsMapBoundsNonConst(cond->SourceGroup);
1366 if (pMenuItemBounds.first != pMenuItemBounds.second)
1367 {
1368 for (GossipMenuItemsContainer::iterator itr = pMenuItemBounds.first; itr != pMenuItemBounds.second; ++itr)
1369 {
1370 if ((*itr).second.MenuID == cond->SourceGroup && (*itr).second.OptionID == uint32(cond->SourceEntry))
1371 {
1372 (*itr).second.Conditions.push_back(cond);
1373 return true;
1374 }
1375 }
1376 }
1377
1378 TC_LOG_ERROR("sql.sql", "{} GossipMenuId {} Item {} not found.", cond->ToString(), cond->SourceGroup, cond->SourceEntry);
1379 return false;
1380}
1381
1383{
1384 uint32 conditionEffMask = cond->SourceGroup;
1385 SpellInfo* spellInfo = const_cast<SpellInfo*>(sSpellMgr->AssertSpellInfo(cond->SourceEntry));
1386 std::list<uint32> sharedMasks;
1387 for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects())
1388 {
1389 // additional checks by condition type
1390 if (conditionEffMask & (1 << spellEffectInfo.EffectIndex))
1391 {
1392 switch (cond->ConditionType)
1393 {
1395 {
1396 uint32 implicitTargetMask = GetTargetFlagMask(spellEffectInfo.TargetA.GetObjectType()) | GetTargetFlagMask(spellEffectInfo.TargetB.GetObjectType());
1397 if ((implicitTargetMask & TARGET_FLAG_UNIT_MASK) && cond->ConditionValue1 != TYPEID_UNIT && cond->ConditionValue1 != TYPEID_PLAYER)
1398 {
1399 TC_LOG_ERROR("sql.sql", "{} in `condition` table - spell {} EFFECT_{} - "
1400 "target requires ConditionValue1 to be either TYPEID_UNIT ({}) or TYPEID_PLAYER ({})", cond->ToString(), spellInfo->Id, uint32(spellEffectInfo.EffectIndex), uint32(TYPEID_UNIT), uint32(TYPEID_PLAYER));
1401 return false;
1402 }
1403
1404 if ((implicitTargetMask & TARGET_FLAG_GAMEOBJECT_MASK) && cond->ConditionValue1 != TYPEID_GAMEOBJECT)
1405 {
1406 TC_LOG_ERROR("sql.sql", "{} in `condition` table - spell {} EFFECT_{} - "
1407 "target requires ConditionValue1 to be TYPEID_GAMEOBJECT ({})", cond->ToString(), spellInfo->Id, uint32(spellEffectInfo.EffectIndex), uint32(TYPEID_GAMEOBJECT));
1408 return false;
1409 }
1410
1411 if ((implicitTargetMask & TARGET_FLAG_CORPSE_MASK) && cond->ConditionValue1 != TYPEID_CORPSE)
1412 {
1413 TC_LOG_ERROR("sql.sql", "{} in `condition` table - spell {} EFFECT_{} - "
1414 "target requires ConditionValue1 to be TYPEID_CORPSE ({})", cond->ToString(), spellInfo->Id, uint32(spellEffectInfo.EffectIndex), uint32(TYPEID_CORPSE));
1415 return false;
1416 }
1417 break;
1418 }
1419 default:
1420 break;
1421 }
1422 }
1423
1424 // check if effect is already a part of some shared mask
1425 auto itr = std::find_if(sharedMasks.begin(), sharedMasks.end(), [&](uint32 mask) { return !!(mask & (1 << spellEffectInfo.EffectIndex)); });
1426 if (itr != sharedMasks.end())
1427 continue;
1428
1429 // build new shared mask with found effect
1430 uint32 sharedMask = 1 << spellEffectInfo.EffectIndex;
1431 ConditionContainer* cmp = spellEffectInfo.ImplicitTargetConditions;
1432 for (size_t effIndex = spellEffectInfo.EffectIndex + 1; effIndex < spellInfo->GetEffects().size(); ++effIndex)
1433 if (spellInfo->GetEffect(SpellEffIndex(effIndex)).ImplicitTargetConditions == cmp)
1434 sharedMask |= 1 << effIndex;
1435
1436 sharedMasks.push_back(sharedMask);
1437 }
1438
1439 for (uint32 effectMask : sharedMasks)
1440 {
1441 // some effect indexes should have same data
1442 if (uint32 commonMask = effectMask & conditionEffMask)
1443 {
1444 size_t firstEffIndex = 0;
1445 for (; firstEffIndex < spellInfo->GetEffects().size(); ++firstEffIndex)
1446 if ((1 << firstEffIndex) & effectMask)
1447 break;
1448
1449 if (firstEffIndex >= spellInfo->GetEffects().size())
1450 return false;
1451
1452 // get shared data
1453 ConditionContainer* sharedList = spellInfo->GetEffect(SpellEffIndex(firstEffIndex)).ImplicitTargetConditions;
1454
1455 // there's already data entry for that sharedMask
1456 if (sharedList)
1457 {
1458 // we have overlapping masks in db
1459 if (conditionEffMask != effectMask)
1460 {
1461 TC_LOG_ERROR("sql.sql", "{} in `condition` table, has incorrect SourceGroup {} (spell effectMask) set - "
1462 "effect masks are overlapping (all SourceGroup values having given bit set must be equal) - ignoring.", cond->ToString(), cond->SourceGroup);
1463 return false;
1464 }
1465 }
1466 // no data for shared mask, we can create new submask
1467 else
1468 {
1469 // add new list, create new shared mask
1470 sharedList = new ConditionContainer();
1471 bool assigned = false;
1472 for (size_t i = firstEffIndex; i < spellInfo->GetEffects().size(); ++i)
1473 {
1474 if ((1 << i) & commonMask)
1475 {
1476 const_cast<SpellEffectInfo&>(spellInfo->GetEffect(SpellEffIndex(i))).ImplicitTargetConditions = sharedList;
1477 assigned = true;
1478 }
1479 }
1480
1481 if (!assigned)
1482 {
1483 delete sharedList;
1484 return false;
1485 }
1486 }
1487 sharedList->push_back(cond);
1488 break;
1489 }
1490 }
1491 return true;
1492}
1493
1495{
1497 {
1498 TC_LOG_ERROR("sql.sql", "{} Invalid ConditionSourceType in `condition` table, ignoring.", cond->ToString());
1499 return false;
1500 }
1501
1502 switch (cond->SourceType)
1503 {
1505 {
1507 {
1508 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `creature_loot_template`, ignoring.", cond->ToString());
1509 return false;
1510 }
1511
1513 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1514 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1515 {
1516 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString());
1517 return false;
1518 }
1519 break;
1520 }
1522 {
1524 {
1525 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `disenchant_loot_template`, ignoring.", cond->ToString());
1526 return false;
1527 }
1528
1530 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1531 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1532 {
1533 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString());
1534 return false;
1535 }
1536 break;
1537 }
1539 {
1541 {
1542 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `fishing_loot_template`, ignoring.", cond->ToString());
1543 return false;
1544 }
1545
1547 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1548 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1549 {
1550 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString());
1551 return false;
1552 }
1553 break;
1554 }
1556 {
1558 {
1559 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `gameobject_loot_template`, ignoring.", cond->ToString());
1560 return false;
1561 }
1562
1564 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1565 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1566 {
1567 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString());
1568 return false;
1569 }
1570 break;
1571 }
1573 {
1575 {
1576 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `item_loot_template`, ignoring.", cond->ToString());
1577 return false;
1578 }
1579
1581 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1582 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1583 {
1584 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString());
1585 return false;
1586 }
1587 break;
1588 }
1590 {
1592 {
1593 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `mail_loot_template`, ignoring.", cond->ToString());
1594 return false;
1595 }
1596
1598 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1599 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1600 {
1601 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString());
1602 return false;
1603 }
1604 break;
1605 }
1607 {
1609 {
1610 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `milling_loot_template`, ignoring.", cond->ToString());
1611 return false;
1612 }
1613
1615 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1616 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1617 {
1618 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString());
1619 return false;
1620 }
1621 break;
1622 }
1624 {
1626 {
1627 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `pickpocketing_loot_template`, ignoring.", cond->ToString());
1628 return false;
1629 }
1630
1632 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1633 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1634 {
1635 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString());
1636 return false;
1637 }
1638 break;
1639 }
1641 {
1643 {
1644 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `prospecting_loot_template`, ignoring.", cond->ToString());
1645 return false;
1646 }
1647
1649 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1650 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1651 {
1652 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString());
1653 return false;
1654 }
1655 break;
1656 }
1658 {
1660 {
1661 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `reference_loot_template`, ignoring.", cond->ToString());
1662 return false;
1663 }
1664
1666 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1667 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1668 {
1669 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString());
1670 return false;
1671 }
1672 break;
1673 }
1675 {
1677 {
1678 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `skinning_loot_template`, ignoring.", cond->ToString());
1679 return false;
1680 }
1681
1683 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1684 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1685 {
1686 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString());
1687 return false;
1688 }
1689 break;
1690 }
1692 {
1694 {
1695 TC_LOG_ERROR("sql.sql", "{} SourceGroup in `condition` table, does not exist in `spell_loot_template`, ignoring.", cond->ToString());
1696 return false;
1697 }
1698
1700 ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1701 if (!pItemProto && !loot->isReference(cond->SourceEntry))
1702 {
1703 TC_LOG_ERROR("sql.sql", "{} SourceType, SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString());
1704 return false;
1705 }
1706 break;
1707 }
1709 {
1710 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(cond->SourceEntry);
1711 if (!spellInfo)
1712 {
1713 TC_LOG_ERROR("sql.sql", "{} SourceEntry in `condition` table does not exist in `spell.dbc`, ignoring.", cond->ToString());
1714 return false;
1715 }
1716
1717 if ((cond->SourceGroup > MAX_EFFECT_MASK) || !cond->SourceGroup)
1718 {
1719 TC_LOG_ERROR("sql.sql", "{} in `condition` table, has incorrect SourceGroup (spell effectMask) set, ignoring.", cond->ToString());
1720 return false;
1721 }
1722
1723 uint32 origGroup = cond->SourceGroup;
1724
1725 for (SpellEffectInfo const& spellEffectInfo : spellInfo->GetEffects())
1726 {
1727 if (!((1 << spellEffectInfo.EffectIndex) & cond->SourceGroup))
1728 continue;
1729
1730 if (spellEffectInfo.ChainTargets > 0)
1731 continue;
1732
1733 switch (spellEffectInfo.TargetA.GetSelectionCategory())
1734 {
1739 continue;
1740 default:
1741 break;
1742 }
1743
1744 switch (spellEffectInfo.TargetB.GetSelectionCategory())
1745 {
1750 continue;
1751 default:
1752 break;
1753 }
1754
1755 switch (spellEffectInfo.Effect)
1756 {
1764 continue;
1765 default:
1766 break;
1767 }
1768
1769 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));
1770 cond->SourceGroup &= ~(1 << spellEffectInfo.EffectIndex);
1771 }
1772 // all effects were removed, no need to add the condition at all
1773 if (!cond->SourceGroup)
1774 return false;
1775 break;
1776 }
1778 {
1779 if (!sObjectMgr->GetCreatureTemplate(cond->SourceEntry))
1780 {
1781 TC_LOG_ERROR("sql.sql", "{} SourceEntry in `condition` table, does not exist in `creature_template`, ignoring.", cond->ToString());
1782 return false;
1783 }
1784 break;
1785 }
1788 {
1789 SpellInfo const* spellProto = sSpellMgr->GetSpellInfo(cond->SourceEntry);
1790 if (!spellProto)
1791 {
1792 TC_LOG_ERROR("sql.sql", "{} SourceEntry in `condition` table does not exist in `spell.dbc`, ignoring.", cond->ToString());
1793 return false;
1794 }
1795 break;
1796 }
1798 if (!sObjectMgr->GetQuestTemplate(cond->SourceEntry))
1799 {
1800 TC_LOG_ERROR("sql.sql", "{} SourceEntry specifies non-existing quest, skipped.", cond->ToString());
1801 return false;
1802 }
1803 break;
1805 if (!sObjectMgr->GetCreatureTemplate(cond->SourceGroup))
1806 {
1807 TC_LOG_ERROR("sql.sql", "{} SourceEntry in `condition` table, does not exist in `creature_template`, ignoring.", cond->ToString());
1808 return false;
1809 }
1810
1811 if (!sSpellMgr->GetSpellInfo(cond->SourceEntry))
1812 {
1813 TC_LOG_ERROR("sql.sql", "{} SourceEntry in `condition` table does not exist in `spell.dbc`, ignoring.", cond->ToString());
1814 return false;
1815 }
1816 break;
1818 if (!sObjectMgr->GetCreatureTemplate(cond->SourceGroup))
1819 {
1820 TC_LOG_ERROR("sql.sql", "{} SourceEntry in `condition` table, does not exist in `creature_template`, ignoring.", cond->ToString());
1821 return false;
1822 }
1823
1824 if (!sSpellMgr->GetSpellInfo(cond->SourceEntry))
1825 {
1826 TC_LOG_ERROR("sql.sql", "{} SourceEntry in `condition` table does not exist in `spell.dbc`, ignoring.", cond->ToString());
1827 return false;
1828 }
1829 break;
1831 {
1832 if (!sObjectMgr->GetCreatureTemplate(cond->SourceGroup))
1833 {
1834 TC_LOG_ERROR("sql.sql", "{} SourceEntry in `condition` table, does not exist in `creature_template`, ignoring.", cond->ToString());
1835 return false;
1836 }
1837 ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(cond->SourceEntry);
1838 if (!itemTemplate)
1839 {
1840 TC_LOG_ERROR("sql.sql", "{} SourceEntry in `condition` table, does not exist in `item_template`, ignoring.", cond->ToString());
1841 return false;
1842 }
1843 break;
1844 }
1846 {
1847 if (!sAreaTriggerStore.LookupEntry(cond->SourceEntry))
1848 {
1849 TC_LOG_ERROR("sql.sql", "%s SourceEntry in `condition` table, does not exists in AreaTrigger.dbc, ignoring.", cond->ToString().c_str());
1850 return false;
1851 }
1852 break;
1853 }
1855 {
1856 TC_LOG_ERROR("sql.sql", "CONDITION_SOURCE_TYPE_TERRAIN_SWAP: is only for master branch, skipped");
1857 return false;
1858 }
1860 {
1861 TC_LOG_ERROR("sql.sql", "CONDITION_SOURCE_TYPE_PHASE: is only for master branch, skipped");
1862 return false;
1863 }
1865 {
1866 TC_LOG_ERROR("sql.sql", "CONDITION_SOURCE_TYPE_GRAVEYARD: is only for master branch, skipped");
1867 return false;
1868 }
1870 {
1871 TC_LOG_ERROR("sql.sql", "CONDITION_SOURCE_TYPE_AREATRIGGER: is only for master branch, skipped");
1872 return false;
1873 }
1875 {
1876 TC_LOG_ERROR("sql.sql", "CONDITION_SOURCE_TYPE_CONVERSATION_LINE: is only for master branch, skipped");
1877 return false;
1878 }
1883 default:
1884 break;
1885 }
1886
1887 return true;
1888}
1889
1891{
1893 {
1894 TC_LOG_ERROR("sql.sql", "{} Invalid ConditionType in `condition` table, ignoring.", cond->ToString(true));
1895 return false;
1896 }
1897
1899 {
1900 TC_LOG_ERROR("sql.sql", "{} in `condition` table, has incorrect ConditionTarget set, ignoring.", cond->ToString(true));
1901 return false;
1902 }
1903
1904 switch (cond->ConditionType)
1905 {
1906 case CONDITION_AURA:
1907 {
1908 if (!sSpellMgr->GetSpellInfo(cond->ConditionValue1))
1909 {
1910 TC_LOG_ERROR("sql.sql", "{} has non existing spell (Id: {}), skipped.", cond->ToString(true), cond->ConditionValue1);
1911 return false;
1912 }
1913
1914 if (cond->ConditionValue2 > EFFECT_2)
1915 {
1916 TC_LOG_ERROR("sql.sql", "{} has non existing effect index ({}) (must be 0..2), skipped.", cond->ToString(true), cond->ConditionValue2);
1917 return false;
1918 }
1919 break;
1920 }
1921 case CONDITION_ITEM:
1922 {
1923 ItemTemplate const* proto = sObjectMgr->GetItemTemplate(cond->ConditionValue1);
1924 if (!proto)
1925 {
1926 TC_LOG_ERROR("sql.sql", "{} Item ({}) does not exist, skipped.", cond->ToString(true), cond->ConditionValue1);
1927 return false;
1928 }
1929
1930 if (!cond->ConditionValue2)
1931 {
1932 TC_LOG_ERROR("sql.sql", "{} Zero item count in ConditionValue2, skipped.", cond->ToString(true));
1933 return false;
1934 }
1935 break;
1936 }
1938 {
1939 ItemTemplate const* proto = sObjectMgr->GetItemTemplate(cond->ConditionValue1);
1940 if (!proto)
1941 {
1942 TC_LOG_ERROR("sql.sql", "{} Item ({}) does not exist, skipped.", cond->ToString(true), cond->ConditionValue1);
1943 return false;
1944 }
1945 break;
1946 }
1947 case CONDITION_ZONEID:
1948 {
1949 AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(cond->ConditionValue1);
1950 if (!areaEntry)
1951 {
1952 TC_LOG_ERROR("sql.sql", "{} Area ({}) does not exist, skipped.", cond->ToString(true), cond->ConditionValue1);
1953 return false;
1954 }
1955
1956 if (areaEntry->ParentAreaID != 0)
1957 {
1958 TC_LOG_ERROR("sql.sql", "{} requires to be in area ({}) which is a subzone but zone expected, skipped.", cond->ToString(true), cond->ConditionValue1);
1959 return false;
1960 }
1961 break;
1962 }
1964 {
1965 FactionEntry const* factionEntry = sFactionStore.LookupEntry(cond->ConditionValue1);
1966 if (!factionEntry)
1967 {
1968 TC_LOG_ERROR("sql.sql", "{} has non existing faction ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
1969 return false;
1970 }
1971 break;
1972 }
1973 case CONDITION_TEAM:
1974 {
1975 if (cond->ConditionValue1 != ALLIANCE && cond->ConditionValue1 != HORDE)
1976 {
1977 TC_LOG_ERROR("sql.sql", "{} specifies unknown team ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
1978 return false;
1979 }
1980 break;
1981 }
1982 case CONDITION_SKILL:
1983 {
1984 SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(cond->ConditionValue1);
1985 if (!pSkill)
1986 {
1987 TC_LOG_ERROR("sql.sql", "{} specifies non-existing skill ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
1988 return false;
1989 }
1990
1991 if (cond->ConditionValue2 < 1 || cond->ConditionValue2 > sWorld->GetConfigMaxSkillValue())
1992 {
1993 TC_LOG_ERROR("sql.sql", "{} specifies skill ({}) with invalid value ({}), skipped.", cond->ToString(true), cond->ConditionValue1, cond->ConditionValue2);
1994 return false;
1995 }
1996 break;
1997 }
1999 if (cond->ConditionValue2 >= (1 << MAX_QUEST_STATUS))
2000 {
2001 TC_LOG_ERROR("sql.sql", "{} has invalid state mask ({}), skipped.", cond->ToString(true), cond->ConditionValue2);
2002 return false;
2003 }
2004 [[fallthrough]];
2010 {
2011 if (!sObjectMgr->GetQuestTemplate(cond->ConditionValue1))
2012 {
2013 TC_LOG_ERROR("sql.sql", "{} points to non-existing quest ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2014 return false;
2015 }
2016 break;
2017 }
2019 {
2020 GameEventMgr::GameEventDataMap const& events = sGameEventMgr->GetEventMap();
2021 if (cond->ConditionValue1 >= events.size() || !events[cond->ConditionValue1].isValid())
2022 {
2023 TC_LOG_ERROR("sql.sql", "{} has non existing event id ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2024 return false;
2025 }
2026 break;
2027 }
2029 {
2030 AchievementEntry const* achievement = sAchievementStore.LookupEntry(cond->ConditionValue1);
2031 if (!achievement)
2032 {
2033 TC_LOG_ERROR("sql.sql", "{} has non existing achivement id ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2034 return false;
2035 }
2036 break;
2037 }
2038 case CONDITION_CLASS:
2039 {
2041 {
2042 TC_LOG_ERROR("sql.sql", "{} has non existing classmask ({}), skipped.", cond->ToString(true), cond->ConditionValue1 & ~CLASSMASK_ALL_PLAYABLE);
2043 return false;
2044 }
2045 break;
2046 }
2047 case CONDITION_RACE:
2048 {
2050 {
2051 TC_LOG_ERROR("sql.sql", "{} has non existing racemask ({}), skipped.", cond->ToString(true), cond->ConditionValue1 & ~RACEMASK_ALL_PLAYABLE);
2052 return false;
2053 }
2054 break;
2055 }
2056 case CONDITION_GENDER:
2057 {
2059 {
2060 TC_LOG_ERROR("sql.sql", "{} has invalid gender ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2061 return false;
2062 }
2063 break;
2064 }
2065 case CONDITION_MAPID:
2066 {
2067 MapEntry const* me = sMapStore.LookupEntry(cond->ConditionValue1);
2068 if (!me)
2069 {
2070 TC_LOG_ERROR("sql.sql", "{} has non existing map ({}), skipped", cond->ToString(true), cond->ConditionValue1);
2071 return false;
2072 }
2073 break;
2074 }
2075 case CONDITION_SPELL:
2076 {
2077 if (!sSpellMgr->GetSpellInfo(cond->ConditionValue1))
2078 {
2079 TC_LOG_ERROR("sql.sql", "{} has non existing spell (Id: {}), skipped", cond->ToString(true), cond->ConditionValue1);
2080 return false;
2081 }
2082 break;
2083 }
2084 case CONDITION_LEVEL:
2085 {
2086 if (cond->ConditionValue2 >= COMP_TYPE_MAX)
2087 {
2088 TC_LOG_ERROR("sql.sql", "{} has invalid ComparisionType ({}), skipped.", cond->ToString(true), cond->ConditionValue2);
2089 return false;
2090 }
2091 break;
2092 }
2094 {
2095 if (cond->ConditionValue1 > DRUNKEN_SMASHED)
2096 {
2097 TC_LOG_ERROR("sql.sql", "{} has invalid state ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2098 return false;
2099 }
2100 break;
2101 }
2103 {
2104 if (!sObjectMgr->GetCreatureTemplate(cond->ConditionValue1))
2105 {
2106 TC_LOG_ERROR("sql.sql", "{} has non existing creature template entry ({}), skipped", cond->ToString(true), cond->ConditionValue1);
2107 return false;
2108 }
2109 break;
2110 }
2112 {
2113 if (!sObjectMgr->GetGameObjectTemplate(cond->ConditionValue1))
2114 {
2115 TC_LOG_ERROR("sql.sql", "{} has non existing gameobject template entry ({}), skipped.", cond->ToString(), cond->ConditionValue1);
2116 return false;
2117 }
2118 break;
2119 }
2121 {
2122 switch (cond->ConditionValue1)
2123 {
2124 case TYPEID_UNIT:
2125 if (cond->ConditionValue2 && !sObjectMgr->GetCreatureTemplate(cond->ConditionValue2))
2126 {
2127 TC_LOG_ERROR("sql.sql", "{} has non existing creature template entry ({}), skipped.", cond->ToString(true), cond->ConditionValue2);
2128 return false;
2129 }
2130 if (cond->ConditionValue3)
2131 {
2132 if (CreatureData const* creatureData = sObjectMgr->GetCreatureData(cond->ConditionValue3))
2133 {
2134 if (cond->ConditionValue2 && creatureData->id != cond->ConditionValue2)
2135 {
2136 TC_LOG_ERROR("sql.sql", "{} has guid {} set but does not match creature entry ({}), skipped.", cond->ToString(true), cond->ConditionValue3, cond->ConditionValue2);
2137 return false;
2138 }
2139 }
2140 else
2141 {
2142 TC_LOG_ERROR("sql.sql", "{} has non existing creature guid ({}), skipped.", cond->ToString(true), cond->ConditionValue3);
2143 return false;
2144 }
2145 }
2146 break;
2147 case TYPEID_GAMEOBJECT:
2148 if (cond->ConditionValue2 && !sObjectMgr->GetGameObjectTemplate(cond->ConditionValue2))
2149 {
2150 TC_LOG_ERROR("sql.sql", "{} has non existing gameobject template entry ({}), skipped.", cond->ToString(true), cond->ConditionValue2);
2151 return false;
2152 }
2153 if (cond->ConditionValue3)
2154 {
2155 if (GameObjectData const* goData = sObjectMgr->GetGameObjectData(cond->ConditionValue3))
2156 {
2157 if (cond->ConditionValue2 && goData->id != cond->ConditionValue2)
2158 {
2159 TC_LOG_ERROR("sql.sql", "{} has guid {} set but does not match gameobject entry ({}), skipped.", cond->ToString(true), cond->ConditionValue3, cond->ConditionValue2);
2160 return false;
2161 }
2162 }
2163 else
2164 {
2165 TC_LOG_ERROR("sql.sql", "{} has non existing gameobject guid ({}), skipped.", cond->ToString(true), cond->ConditionValue3);
2166 return false;
2167 }
2168 }
2169 break;
2170 case TYPEID_PLAYER:
2171 case TYPEID_CORPSE:
2172 if (cond->ConditionValue2)
2174 if (cond->ConditionValue3)
2176 break;
2177 default:
2178 TC_LOG_ERROR("sql.sql", "{} has wrong typeid set ({}), skipped", cond->ToString(true), cond->ConditionValue1);
2179 return false;
2180 }
2181 break;
2182 }
2184 {
2186 {
2187 TC_LOG_ERROR("sql.sql", "{} has invalid typemask set ({}), skipped.", cond->ToString(true), cond->ConditionValue2);
2188 return false;
2189 }
2190 break;
2191 }
2193 {
2195 {
2196 TC_LOG_ERROR("sql.sql", "{} has invalid ConditionValue1(ConditionTarget selection) ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2197 return false;
2198 }
2199 if (cond->ConditionValue1 == cond->ConditionTarget)
2200 {
2201 TC_LOG_ERROR("sql.sql", "{} has ConditionValue1(ConditionTarget selection) set to self ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2202 return false;
2203 }
2204 if (cond->ConditionValue2 >= RELATION_MAX)
2205 {
2206 TC_LOG_ERROR("sql.sql", "{} has invalid ConditionValue2(RelationType) ({}), skipped.", cond->ToString(true), cond->ConditionValue2);
2207 return false;
2208 }
2209 break;
2210 }
2212 {
2214 {
2215 TC_LOG_ERROR("sql.sql", "{} has invalid ConditionValue1(ConditionTarget selection) ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2216 return false;
2217 }
2218 if (cond->ConditionValue1 == cond->ConditionTarget)
2219 {
2220 TC_LOG_ERROR("sql.sql", "{} has ConditionValue1(ConditionTarget selection) set to self ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2221 return false;
2222 }
2223 if (!cond->ConditionValue2)
2224 {
2225 TC_LOG_ERROR("sql.sql", "{} has invalid ConditionValue2(rankMask) ({}), skipped.", cond->ToString(true), cond->ConditionValue2);
2226 return false;
2227 }
2228 break;
2229 }
2231 {
2233 {
2234 TC_LOG_ERROR("sql.sql", "{} has invalid ConditionValue1(ConditionTarget selection) ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2235 return false;
2236 }
2237 if (cond->ConditionValue1 == cond->ConditionTarget)
2238 {
2239 TC_LOG_ERROR("sql.sql", "{} has ConditionValue1(ConditionTarget selection) set to self ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2240 return false;
2241 }
2242 if (cond->ConditionValue3 >= COMP_TYPE_MAX)
2243 {
2244 TC_LOG_ERROR("sql.sql", "{} has invalid ComparisionType ({}), skipped.", cond->ToString(true), cond->ConditionValue3);
2245 return false;
2246 }
2247 break;
2248 }
2249 case CONDITION_HP_VAL:
2250 {
2251 if (cond->ConditionValue2 >= COMP_TYPE_MAX)
2252 {
2253 TC_LOG_ERROR("sql.sql", "{} has invalid ComparisionType ({}), skipped.", cond->ToString(true), cond->ConditionValue2);
2254 return false;
2255 }
2256 if (cond->ConditionValue3)
2257 TC_LOG_ERROR("sql.sql", "{} has useless data in value3 ({})!", cond->ToString(true), cond->ConditionValue3);
2258 break;
2259 }
2260 case CONDITION_HP_PCT:
2261 {
2262 if (cond->ConditionValue1 > 100)
2263 {
2264 TC_LOG_ERROR("sql.sql", "{} has too big percent value ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2265 return false;
2266 }
2267 if (cond->ConditionValue2 >= COMP_TYPE_MAX)
2268 {
2269 TC_LOG_ERROR("sql.sql", "{} has invalid ComparisionType ({}), skipped.", cond->ToString(true), cond->ConditionValue2);
2270 return false;
2271 }
2272 if (cond->ConditionValue3)
2273 TC_LOG_ERROR("sql.sql", "{} has useless data in value3 ({})!", cond->ToString(), cond->ConditionValue3);
2274 break;
2275 }
2277 {
2278 if (!sWorld->getWorldState(cond->ConditionValue1))
2279 {
2280 TC_LOG_ERROR("sql.sql", "{} has non existing world state in value1 ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2281 return false;
2282 }
2283 break;
2284 }
2285 case CONDITION_TITLE:
2286 {
2287 CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(cond->ConditionValue1);
2288 if (!titleEntry)
2289 {
2290 TC_LOG_ERROR("sql.sql", "{} has non existing title in value1 ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2291 return false;
2292 }
2293 break;
2294 }
2296 {
2298 {
2299 TC_LOG_ERROR("sql.sql", "{} has non existing SpawnMask in value1 ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2300 return false;
2301 }
2302 break;
2303 }
2305 {
2307 {
2308 TC_LOG_ERROR("sql.sql", "{} has non existing UnitState in value1 ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2309 return false;
2310 }
2311 break;
2312 }
2314 {
2316 {
2317 TC_LOG_ERROR("sql.sql", "{} has non existing CreatureType in value1 ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2318 return false;
2319 }
2320 break;
2321 }
2323 case CONDITION_AREAID:
2325 case CONDITION_ALIVE:
2326 break;
2328 {
2329 AchievementEntry const* achievement = sAchievementStore.LookupEntry(cond->ConditionValue1);
2330 if (!achievement)
2331 {
2332 TC_LOG_ERROR("sql.sql", "{} has non existing realm first achivement id ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2333 return false;
2334 }
2335 break;
2336 }
2338 TC_LOG_ERROR("sql.sql", "{} is not valid for this branch, skipped.", cond->ToString(true));
2339 return false;
2341 {
2342 bool valid = false;
2343 switch (cond->ConditionValue1)
2344 {
2345 case 0:
2347 break;
2348 case 1:
2349 valid = cond->ConditionValue2 <= 1;
2350 break;
2351 default:
2352 valid = false;
2353 break;
2354 }
2355 if (!valid)
2356 {
2357 TC_LOG_ERROR("sql.sql", "{} has non-existing stand state ({},{}), skipped.", cond->ToString(true), cond->ConditionValue1, cond->ConditionValue2);
2358 return false;
2359 }
2360 break;
2361 }
2362 case CONDITION_PET_TYPE:
2363 if (cond->ConditionValue1 >= (1 << MAX_PET_TYPE))
2364 {
2365 TC_LOG_ERROR("sql.sql", "{} has non-existing pet type {}, skipped.", cond->ToString(true), cond->ConditionValue1);
2366 return false;
2367 }
2368 break;
2370 {
2371 const Quest* quest = sObjectMgr->GetQuestTemplate(cond->ConditionValue1);
2372 if (!quest)
2373 {
2374 TC_LOG_ERROR("sql.sql", "{} points to non-existing quest ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2375 return false;
2376 }
2377
2378 if (cond->ConditionValue2 > 3)
2379 {
2380 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);
2381 return false;
2382 }
2383
2384 if (quest->RequiredNpcOrGo[cond->ConditionValue2] == 0)
2385 {
2386 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);
2387 return false;
2388 }
2389
2390 if (cond->ConditionValue3 > quest->RequiredNpcOrGoCount[cond->ConditionValue2])
2391 {
2392 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);
2393 return false;
2394 }
2395 break;
2396 }
2398 if (cond->ConditionValue1 >= MAX_DIFFICULTY)
2399 {
2400 TC_LOG_ERROR("sql.sql", "{} has non existing difficulty in value1 ({}), skipped.", cond->ToString(true), cond->ConditionValue1);
2401 return false;
2402 }
2403 break;
2404 case CONDITION_IN_WATER:
2405 case CONDITION_CHARMED:
2406 case CONDITION_TAXI:
2409 default:
2410 break;
2416 case CONDITION_LABEL:
2417 TC_LOG_ERROR("sql.sql", "{} uses condition type not supported in this game version, skipped.", cond->ToString(true));
2418 return false;
2419 }
2420
2429
2430 return true;
2431}
2432
2434{
2435 TC_LOG_ERROR("sql.sql", "{} has useless data in ConditionValue{} ({})!", cond->ToString(true), index, value);
2436}
2437
2438void ConditionMgr::LogUselessConditionValue(Condition const* cond, uint8 index, std::string_view value)
2439{
2440 TC_LOG_ERROR("sql.sql", "{} has useless data in ConditionStringValue{} ({})!", cond->ToString(true), index, value);
2441}
2442
2444{
2445 for (ConditionReferenceContainer::iterator itr = ConditionReferenceStore.begin(); itr != ConditionReferenceStore.end(); ++itr)
2446 for (ConditionContainer::const_iterator it = itr->second.begin(); it != itr->second.end(); ++it)
2447 delete *it;
2448
2450
2451 for (uint32 i = 0; i < CONDITION_SOURCE_TYPE_MAX; ++i)
2452 {
2453 for (ConditionsByEntryMap::iterator it = ConditionStore[i].begin(); it != ConditionStore[i].end(); ++it)
2454 for (ConditionContainer::const_iterator itr = it->second.begin(); itr != it->second.end(); ++itr)
2455 delete *itr;
2456
2457 ConditionStore[i].clear();
2458 }
2459
2460 for (ConditionEntriesByCreatureIdMap::iterator itr = VehicleSpellConditionStore.begin(); itr != VehicleSpellConditionStore.end(); ++itr)
2461 for (ConditionsByEntryMap::iterator it = itr->second.begin(); it != itr->second.end(); ++it)
2462 for (ConditionContainer::const_iterator i = it->second.begin(); i != it->second.end(); ++i)
2463 delete *i;
2464
2466
2467 for (SmartEventConditionContainer::iterator itr = SmartEventConditionStore.begin(); itr != SmartEventConditionStore.end(); ++itr)
2468 for (ConditionsByEntryMap::iterator it = itr->second.begin(); it != itr->second.end(); ++it)
2469 for (ConditionContainer::const_iterator i = it->second.begin(); i != it->second.end(); ++i)
2470 delete *i;
2471
2473
2474 for (ConditionEntriesByCreatureIdMap::iterator itr = SpellClickEventConditionStore.begin(); itr != SpellClickEventConditionStore.end(); ++itr)
2475 for (ConditionsByEntryMap::iterator it = itr->second.begin(); it != itr->second.end(); ++it)
2476 for (ConditionContainer::const_iterator i = it->second.begin(); i != it->second.end(); ++i)
2477 delete *i;
2478
2481
2482 for (ConditionEntriesByCreatureIdMap::iterator itr = NpcVendorConditionContainerStore.begin(); itr != NpcVendorConditionContainerStore.end(); ++itr)
2483 for (ConditionsByEntryMap::iterator it = itr->second.begin(); it != itr->second.end(); ++it)
2484 for (ConditionContainer::const_iterator i = it->second.begin(); i != it->second.end(); ++i)
2485 delete *i;
2486
2488
2489 // this is a BIG hack, feel free to fix it if you can figure out the ConditionMgr ;)
2490 for (std::vector<Condition*>::const_iterator itr = AllocatedMemoryStore.begin(); itr != AllocatedMemoryStore.end(); ++itr)
2491 delete *itr;
2492
2493 AllocatedMemoryStore.clear();
2494}
#define sAchievementMgr
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
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_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:389
#define MAX_DIFFICULTY
Definition DBCEnums.h:296
@ SPAWNMASK_RAID_ALL
Definition DBCEnums.h:314
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:801
std::pair< GossipMenusContainer::iterator, GossipMenusContainer::iterator > GossipMenusMapBoundsNonConst
Definition ObjectMgr.h:798
@ MAX_PET_TYPE
Definition PetDefines.h:33
@ DRUNKEN_SMASHED
Definition Player.h:337
#define MAX_QUEST_LOG_SIZE
Definition QuestDef.h:36
QuestStatus
Definition QuestDef.h:103
@ QUEST_STATUS_REWARDED
Definition QuestDef.h:110
@ QUEST_STATUS_FAILED
Definition QuestDef.h:109
@ QUEST_STATUS_INCOMPLETE
Definition QuestDef.h:107
@ QUEST_STATUS_NONE
Definition QuestDef.h:104
@ MAX_QUEST_STATUS
Definition QuestDef.h:111
@ QUEST_STATUS_COMPLETE
Definition QuestDef.h:105
#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:251
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
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:281
bool IsDungeon() const
Definition Map.cpp:4236
static Creature * ToCreature(Object *o)
Definition Object.h:186
static Unit * ToUnit(Object *o)
Definition Object.h:192
static GameObject * ToGameObject(Object *o)
Definition Object.h:198
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:180
Definition Pet.h:40
static bool IsValidGender(uint8 Gender)
Definition Player.h:1379
static DrunkenState GetDrunkenstateByValue(uint8 value)
Definition Player.cpp:861
int32 RequiredNpcOrGo[QUEST_OBJECTIVES_COUNT]
Definition QuestDef.h:308
uint32 RequiredNpcOrGoCount[QUEST_OBJECTIVES_COUNT]
Definition QuestDef.h:309
uint32 GetQuestId() const
Definition QuestDef.h:229
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:769
ObjectGuid GetCreatorGUID() const
Definition Unit.h:1243
ObjectGuid GetOwnerGUID() const override
Definition Unit.h:1241
bool IsOnVehicle(Unit const *vehicle) const
Definition Unit.cpp:11821
bool IsInRaidWith(Unit const *unit) const
Definition Unit.cpp:11892
bool IsInPartyWith(Unit const *unit) const
Definition Unit.cpp:11873
ReputationRank GetReactionTo(WorldObject const *target) const
Definition Object.cpp:2662
float GetDistance(WorldObject const *obj) const
Definition Object.cpp:1123
#define sWorld
Definition World.h:900
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