OregonCore  revision 3611e8a-git
Your Favourite TBC server
ConditionMgr.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the OregonCore 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 "Player.h"
19 #include "SpellAuras.h"
20 #include "SpellMgr.h"
21 #include "GameEventMgr.h"
22 #include "ObjectMgr.h"
23 #include "InstanceData.h"
24 #include "ConditionMgr.h"
25 #include "ScriptMgr.h"
26 #include "ScriptedCreature.h"
27 #include "ReputationMgr.h"
28 
30 
32 {
33  "None",
34  "Creature Loot",
35  "Disenchant Loot",
36  "Fishing Loot",
37  "GameObject Loot",
38  "Item Loot",
39  "Mail Loot",
40  "Milling Loot",
41  "Pickpocketing Loot",
42  "Prospecting Loot",
43  "Reference Loot",
44  "Skinning Loot",
45  "Spell Loot",
46  "Spell Impl. Target",
47  "Gossip Menu",
48  "Gossip Menu Option",
49  "Creature Vehicle",
50  "Spell Expl. Target",
51  "Spell Click Event",
52  "Quest Accept",
53  "Quest Show Mark",
54  "SmartScript"
55 };
56 
58 {
59  { "None", false, false, false },
60  { "Aura", true, true, true },
61  { "Item Stored", true, true, true },
62  { "Item Equipped", true, false, false },
63  { "Zone", true, false, false },
64  { "Reputation", true, true, false },
65  { "Team", true, false, false },
66  { "Skill", true, true, false },
67  { "Quest Rewarded", true, false, false },
68  { "Quest Taken", true, false, false },
69  { "Drunken", true, false, false },
70  { "WorldState", true, true, false },
71  { "Active Event", true, false, false },
72  { "Instance Info", true, true, true },
73  { "Quest None", true, false, false },
74  { "Class", true, false, false },
75  { "Race", true, false, false },
76  { "Achievement", true, false, false },
77  { "Title", true, false, false },
78  { "SpawnMask", true, false, false },
79  { "Gender", true, false, false },
80  { "Unit State", true, false, false },
81  { "Map", true, false, false },
82  { "Area", true, false, false },
83  { "CreatureType", true, false, false },
84  { "Spell Known", true, false, false },
85  { "PhaseMask", true, false, false },
86  { "Level", true, true, false },
87  { "Quest Completed", true, false, false },
88  { "Near Creature", true, true, true },
89  { "Near GameObject", true, true, false },
90  { "Object Entry or Guid", true, true, true },
91  { "Object TypeMask", true, false, false },
92  { "Relation", true, true, false },
93  { "Reaction", true, true, false },
94  { "Distance", true, true, true },
95  { "Alive", false, false, false },
96  { "Health Value", true, true, false },
97  { "Health Pct", true, true, false }
98 };
99 
100 // Checks if object meets the condition
101 // Can have CONDITION_SOURCE_TYPE_NONE && !ReferenceId if called from a special event (ie: eventAI)
103 {
105  WorldObject* object = sourceInfo.mConditionTargets[ConditionTarget];
106  // object not present, return false
107  if (!object)
108  {
109  sLog.outDebug("Condition object not found for condition (Entry: %u Type: %u Group: %u)", SourceEntry, SourceType, SourceGroup);
110  return false; // player not present, return false
111  }
112  bool condMeets = false;
113  bool sendErrorMsg = false;
114  switch (Type)
115  {
116  case CONDITION_NONE:
117  condMeets = true; // empty condition, always met
118  break;
119  case CONDITION_AURA:
120  {
121  if (Unit* unit = object->ToUnit())
122  condMeets = unit->HasAura(ConditionValue1, ConditionValue2);
123  break;
124  }
125  case CONDITION_ITEM:
126  {
127  if (Player* player = object->ToPlayer())
128  {
129  // don't allow 0 items (it's checked during table load)
131  bool checkBank = ConditionValue3 ? true : false;
132  condMeets = player->HasItemCount(ConditionValue1, ConditionValue2, checkBank);
133  }
134  break;
135  }
137  {
138  if (Player* player = object->ToPlayer())
139  condMeets = player->GetItemOrItemWithGemEquipped(ConditionValue1);
140  break;
141  }
142  case CONDITION_ZONEID:
143  condMeets = object->GetZoneId() == ConditionValue1;
144  break;
146  {
147  if (Player* player = object->ToPlayer())
148  {
149  if (FactionEntry const* faction = sFactionStore.LookupEntry(ConditionValue1))
150  condMeets = (ConditionValue2 & (1 << player->GetReputationMgr().GetRank(faction))) != 0;
151  }
152  break;
153  }
154  case CONDITION_TEAM:
155  {
156  if (Player* player = object->ToPlayer())
157  condMeets = player->GetTeam() == ConditionValue1;
158  break;
159  }
160  case CONDITION_CLASS:
161  {
162  if (Unit* unit = object->ToUnit())
163  condMeets = unit->getClassMask() & ConditionValue1;
164  break;
165  }
166  case CONDITION_RACE:
167  {
168  if (Unit* unit = object->ToUnit())
169  condMeets = unit->getRaceMask() & ConditionValue1;
170  break;
171  }
172  case CONDITION_GENDER:
173  {
174  if (Player* player = object->ToPlayer())
175  condMeets = player->getGender() == ConditionValue1;
176  break;
177  }
178  case CONDITION_SKILL:
179  {
180  if (Player* player = object->ToPlayer())
181  condMeets = player->HasSkill(ConditionValue1) && player->GetBaseSkillValue(ConditionValue1) >= ConditionValue2;
182  break;
183  }
185  {
186  if (Player* player = object->ToPlayer())
187  condMeets = player->GetQuestRewardStatus(ConditionValue1);
188  break;
189  }
191  {
192  if (Player* player = object->ToPlayer())
193  {
194  QuestStatus status = player->GetQuestStatus(ConditionValue1);
195  condMeets = (status == QUEST_STATUS_INCOMPLETE);
196  }
197  break;
198  }
200  {
201  if (Player* player = object->ToPlayer())
202  {
203  QuestStatus status = player->GetQuestStatus(ConditionValue1);
204  condMeets = (status == QUEST_STATUS_COMPLETE && !player->GetQuestRewardStatus(ConditionValue1));
205  }
206  break;
207  }
209  {
210  if (Player* player = object->ToPlayer())
211  {
212  QuestStatus status = player->GetQuestStatus(ConditionValue1);
213  condMeets = (status == QUEST_STATUS_NONE);
214  }
215  break;
216  }
218  condMeets = sGameEventMgr.IsActiveEvent(ConditionValue1);
219  break;
221  {
222  Map* map = object->GetMap();
223  if (map && map->IsDungeon())
224  {
225  if (InstanceData* instance = ((InstanceMap*)map)->GetInstanceData())
226  {
227  switch (ConditionValue3)
228  {
229  case INSTANCE_INFO_DATA:
230  condMeets = instance->GetData(ConditionValue1) == ConditionValue2;
231  break;
233  condMeets = instance->GetData64(ConditionValue1) == ConditionValue2;
234  break;
235  /* @todo Implement this feature
236  case INSTANCE_INFO_BOSS_STATE:
237  condMeets = instance->GetBossState(ConditionValue1) == ConditionValue2;
238  break;*/
239  }
240  }
241  }
242  break;
243  }
245  condMeets = true; //spell target condition is handled in spellsystem, here it is always true
246  break;
247  case CONDITION_MAPID:
248  condMeets = object->GetMapId() == ConditionValue1;
249  break;
250  case CONDITION_AREAID:
251  condMeets = object->GetAreaId() == ConditionValue1;
252  break;
253  case CONDITION_SPELL:
254  {
255  if (Player* player = object->ToPlayer())
256  condMeets = player->HasSpell(ConditionValue1);
257  break;
258  }
259  case CONDITION_LEVEL:
260  {
261  if (Unit* unit = object->ToUnit())
262  condMeets = CompareValues(static_cast<ComparisionType>(ConditionValue2), static_cast<uint32>(unit->getLevel()), ConditionValue1);
263  break;
264  }
266  {
267  if (Player* player = object->ToPlayer())
268  condMeets = (uint32)Player::GetDrunkenstateByValue(player->GetDrunkValue()) >= ConditionValue1;
269  break;
270  }
272  {
273  condMeets = GetClosestCreatureWithEntry(object, ConditionValue1, (float)ConditionValue2, bool(!ConditionValue3)) ? true : false;
274  break;
275  }
277  {
278  condMeets = GetClosestGameObjectWithEntry(object, ConditionValue1, (float)ConditionValue2) ? true : false;
279  break;
280  }
282  {
283  if (object->GetTypeId() == ConditionValue1)
284  {
285  condMeets = !ConditionValue2 || (object->GetEntry() == ConditionValue2);
286 
287  if (ConditionValue3)
288  {
289  switch (object->GetTypeId())
290  {
291  case TYPEID_UNIT:
292  condMeets &= object->ToCreature()->GetDBTableGUIDLow() == ConditionValue3;
293  break;
294  case TYPEID_GAMEOBJECT:
295  condMeets &= object->ToGameObject()->GetDBTableGUIDLow() == ConditionValue3;
296  break;
297  }
298  }
299  }
300  break;
301  }
302  case CONDITION_TYPE_MASK:
303  {
304  condMeets = object->isType(ConditionValue1);
305  break;
306  }
308  {
309  if (WorldObject* toObject = sourceInfo.mConditionTargets[ConditionValue1])
310  {
311  Unit* toUnit = toObject->ToUnit();
312  Unit* unit = object->ToUnit();
313  if (toUnit && unit)
314  {
315  switch (ConditionValue2)
316  {
317  case RELATION_SELF:
318  condMeets = unit == toUnit;
319  break;
320  case RELATION_IN_PARTY:
321  condMeets = unit->IsInPartyWith(toUnit);
322  break;
324  condMeets = unit->IsInRaidWith(toUnit);
325  break;
326  case RELATION_OWNED_BY:
327  condMeets = unit->GetOwnerGUID() == toUnit->GetGUID();
328  break;
329  case RELATION_CREATED_BY:
330  condMeets = unit->GetCreatorGUID() == toUnit->GetGUID();
331  break;
332  }
333  }
334  }
335  break;
336  }
338  {
339  if (WorldObject* toObject = sourceInfo.mConditionTargets[ConditionValue1])
340  {
341  Unit* toUnit = toObject->ToUnit();
342  Unit* unit = object->ToUnit();
343  if (toUnit && unit)
344  condMeets = (1 << unit->GetReactionTo(toUnit)) & ConditionValue2;
345  }
346  break;
347  }
349  {
350  if (WorldObject* toObject = sourceInfo.mConditionTargets[ConditionValue1])
351  condMeets = CompareValues(static_cast<ComparisionType>(ConditionValue3), object->GetDistance(toObject), static_cast<float>(ConditionValue2));
352  break;
353  }
354  case CONDITION_ALIVE:
355  {
356  if (Unit* unit = object->ToUnit())
357  condMeets = unit->IsAlive();
358  break;
359  }
360  case CONDITION_HP_VAL:
361  {
362  if (Unit* unit = object->ToUnit())
363  condMeets = CompareValues(static_cast<ComparisionType>(ConditionValue2), unit->GetHealth(), static_cast<uint32>(ConditionValue1));
364  break;
365  }
366  case CONDITION_HP_PCT:
367  {
368  if (Unit* unit = object->ToUnit())
369  condMeets = CompareValues(static_cast<ComparisionType>(ConditionValue2), unit->GetHealthPct(), static_cast<float>(ConditionValue1));
370  break;
371  }
373  {
374  /* @todo Implement this feature
375  condMeets = ConditionValue2 == sWorld.getWorldState(ConditionValue1);*/
376  condMeets = false;
377  break;
378  }
379  case CONDITION_TITLE:
380  {
381  if (Player* player = object->ToPlayer())
382  condMeets = player->HasTitle(ConditionValue1);
383  break;
384  }
385  case CONDITION_SPAWNMASK:
386  {
387  condMeets = ((1 << object->GetMap()->GetSpawnMode()) & ConditionValue1);
388  break;
389  }
391  {
392  if (Unit* unit = object->ToUnit())
393  condMeets = unit->HasUnitState(ConditionValue1);
394  break;
395  }
397  {
398  if (Creature* creature = object->ToCreature())
399  condMeets = creature->GetCreatureTemplate()->type == ConditionValue1;
400  break;
401  }
402  default:
403  condMeets = false;
404  break;
405  }
406 
407  if (NegativeCondition)
408  condMeets = !condMeets;
409 
410  if (!condMeets)
411  sourceInfo.mLastFailedCondition = this;
412 
413  /* @ConditionTodo
414  bool script = sScriptMgr->OnConditionCheck(this, sourceInfo); // Returns true by default.
415  return condMeets && script;
416  */
417 
418  return condMeets;
419 }
420 
422 {
423  // returns number of targets which are available for given source type
424  switch(SourceType)
425  {
430  return 2;
431  default:
432  return 1;
433  }
434 }
435 
436 std::string Condition::ToString(bool ext /*= false*/) const
437 {
438  std::ostringstream ss;
439  ss << "[Condition ";
440  ss << "SourceType: " << SourceType;
441  if (SourceType < CONDITION_SOURCE_TYPE_MAX)
442  ss << " (" << ConditionMgr::StaticSourceTypeData[SourceType] << ")";
443  else
444  ss << " (Unknown)";
445  if (ConditionMgr::isGroupable(SourceType))
446  ss << ", SourceGroup: " << SourceGroup;
447  ss << ", SourceEntry: " << SourceEntry;
448  if (ConditionMgr::CanHaveSourceIdSet(SourceType))
449  ss << ", SourceId: " << SourceId;
450 
451  if (ext)
452  {
453  ss << ", ConditionType: " << Type;
454  if (Type < CONDITION_MAX)
455  ss << " (" << ConditionMgr::StaticConditionTypeData[Type].Name << ")";
456  else
457  ss << " (Unknown)";
458  }
459 
460  ss << "]";
461  return ss.str();
462 }
463 
465 {
466 }
467 
469 {
470  Clean();
471 }
472 
474 {
475  ConditionList conditions;
476  ConditionReferenceContainer::const_iterator ref = ConditionReferenceStore.find(refId);
477  if (ref != ConditionReferenceStore.end())
478  conditions = (*ref).second;
479  return conditions;
480 }
481 
483 {
484  // groupId, groupCheckPassed
485  std::map<uint32, bool> ElseGroupStore;
486  for (ConditionList::const_iterator i = conditions.begin(); i != conditions.end(); ++i)
487  {
488  sLog.outDebug("ConditionMgr::IsPlayerMeetToConditionList condType: %u val1: %u",(*i)->Type,(*i)->ConditionValue1);
489  if ((*i)->isLoaded())
490  {
492  std::map<uint32, bool>::const_iterator itr = ElseGroupStore.find((*i)->ElseGroup);
494  if (itr == ElseGroupStore.end())
495  ElseGroupStore[(*i)->ElseGroup] = true;
496  else if (!(*itr).second)
497  continue;
498 
499  if ((*i)->ReferenceId)//handle reference
500  {
501  ConditionReferenceContainer::const_iterator ref = ConditionReferenceStore.find((*i)->ReferenceId);
502  if (ref != ConditionReferenceStore.end())
503  {
504  if (!IsObjectMeetToConditionList(sourceInfo, (*ref).second))
505  ElseGroupStore[(*i)->ElseGroup] = false;
506  }
507  else
508  {
509  sLog.outDebug("IsPlayerMeetToConditionList: Reference template -%u not found",
510  (*i)->ReferenceId);//checked at loading, should never happen
511  }
512  }
513  else //handle normal condition
514  {
515  if (!(*i)->Meets(sourceInfo))
516  ElseGroupStore[(*i)->ElseGroup] = false;
517  }
518  }
519  }
520  for (std::map<uint32, bool>::const_iterator i = ElseGroupStore.begin(); i != ElseGroupStore.end(); ++i)
521  if (i->second)
522  return true;
523 
524  return false;
525 }
526 
528 {
529  ConditionSourceInfo info(object);
530  return IsObjectMeetToConditions(info, conditions);
531 }
532 
534 {
535  ConditionSourceInfo srcInfo = ConditionSourceInfo(object1, object2);
536  return IsObjectMeetToConditions(srcInfo, conditions);
537 }
538 
540 {
541  if (conditions.empty())
542  return true;
543 
544  sLog.outDebug("ConditionMgr::IsObjectMeetToConditions");
545  return IsObjectMeetToConditionList(sourceInfo, conditions);
546 }
547 
549 {
550  ConditionList spellCond;
551  if (sourceType > CONDITION_SOURCE_TYPE_NONE && sourceType < CONDITION_SOURCE_TYPE_MAX)
552  {
553  ConditionContainer::const_iterator itr = ConditionStore.find(sourceType);
554  if (itr != ConditionStore.end())
555  {
556  ConditionTypeContainer::const_iterator i = (*itr).second.find(entry);
557  if (i != (*itr).second.end())
558  {
559  spellCond = (*i).second;
560  sLog.outDebug("GetConditionsForNotGroupedEntry: found conditions for type %u and entry %u", uint32(sourceType), entry);
561  }
562  }
563  }
564  return spellCond;
565 }
566 
568 {
569  return (sourceType == CONDITION_SOURCE_TYPE_SMART_EVENT);
570 }
571 
573 {
574  ConditionList cond;
575  SmartEventConditionContainer::const_iterator itr = SmartEventConditionStore.find(std::make_pair(entryOrGuid, sourceType));
576  if (itr != SmartEventConditionStore.end())
577  {
578  ConditionTypeContainer::const_iterator i = (*itr).second.find(eventId + 1);
579  if (i != (*itr).second.end())
580  {
581  cond = (*i).second;
582  sLog.outDebug("GetConditionsForSmartEvent: found conditions for Smart Event entry or guid %d eventId %u", entryOrGuid, eventId);
583  }
584  }
585  return cond;
586 }
587 
588 void ConditionMgr::LoadConditions(bool isReload)
589 {
590  Clean();
591 
592  //must clear all custom handled cases (groupped types) before reload
593  if (isReload)
594  {
595  sLog.outString("Reseting Loot Conditions...");
606 
607  sLog.outString("Re-Loading `gossip_menu` Table for Conditions!");
608  sObjectMgr.LoadGossipMenu();
609 
610  sLog.outString("Re-Loading `gossip_menu_option` Table for Conditions!");
611  sObjectMgr.LoadGossipMenuItems();
612  }
613 
614  uint32 count = 0;
615  QueryResult_AutoPtr result = WorldDatabase.Query("SELECT SourceTypeOrReferenceId, SourceGroup, SourceEntry, SourceId, ElseGroup, ConditionTypeOrReference, ConditionTarget, ConditionValue1, ConditionValue2, ConditionValue3, NegativeCondition, ErrorType, ErrorTextId, ScriptName FROM conditions");
616 
617  if (!result)
618  {
619  sLog.outString();
620  sLog.outErrorDb(">> Loaded `conditions`, table is empty!");
621  return;
622  }
623 
624  do
625  {
626  Field *fields = result->Fetch();
627 
628  Condition* cond = new Condition();
629  int32 iSourceTypeOrReferenceId = fields[0].GetInt32();
630  cond->SourceGroup = fields[1].GetUInt32();
631  cond->SourceEntry = fields[2].GetInt32();
632  cond->SourceId = fields[3].GetInt32();
633  cond->ElseGroup = fields[4].GetUInt32();
634  int32 iConditionTypeOrReference = fields[5].GetInt32();
635  cond->ConditionTarget = fields[6].GetUInt8();
636  cond->ConditionValue1 = fields[7].GetUInt32();
637  cond->ConditionValue2 = fields[8].GetUInt32();
638  cond->ConditionValue3 = fields[9].GetUInt32();
639  cond->NegativeCondition = fields[10].GetUInt8();
640  cond->ErrorType = fields[11].GetUInt32();
641  cond->ErrorTextId = fields[12].GetUInt32();
642  cond->ScriptId = sObjectMgr.GetScriptId(fields[13].GetString());
643 
644  if (iConditionTypeOrReference >= 0)
645  cond->Type = ConditionType(iConditionTypeOrReference);
646 
647  if (iSourceTypeOrReferenceId >= 0)
648  cond->SourceType = ConditionSourceType(iSourceTypeOrReferenceId);
649 
650  if (iConditionTypeOrReference < 0)//it has a reference
651  {
652  if (iConditionTypeOrReference == iSourceTypeOrReferenceId)//self referencing, skipp
653  {
654  sLog.outErrorDb("Condition reference %i is referencing self, skipped", iSourceTypeOrReferenceId);
655  delete cond;
656  continue;
657  }
658  cond->ReferenceId = uint32(abs(iConditionTypeOrReference));
659 
660  const char* rowType = "reference template";
661  if (iSourceTypeOrReferenceId >= 0)
662  rowType = "reference";
663  //check for useless data
664  if (cond->ConditionTarget)
665  sLog.outErrorDb("Condition %s %i has useless data in ConditionTarget (%u)!", rowType, iSourceTypeOrReferenceId, cond->ConditionTarget);
666  if (cond->ConditionValue1)
667  sLog.outErrorDb("Condition %s %i has useless data in value1 (%u)!", rowType, iSourceTypeOrReferenceId, cond->ConditionValue1);
668  if (cond->ConditionValue2)
669  sLog.outErrorDb("Condition %s %i has useless data in value2 (%u)!", rowType, iSourceTypeOrReferenceId, cond->ConditionValue2);
670  if (cond->ConditionValue3)
671  sLog.outErrorDb("Condition %s %i has useless data in value3 (%u)!", rowType, iSourceTypeOrReferenceId, cond->ConditionValue3);
672  if (cond->NegativeCondition)
673  sLog.outErrorDb("Condition %s %i has useless data in NegativeCondition (%u)!", rowType, iSourceTypeOrReferenceId, cond->NegativeCondition);
674  if (cond->SourceGroup && iSourceTypeOrReferenceId < 0)
675  sLog.outErrorDb("Condition %s %i has useless data in SourceGroup (%u)!", rowType, iSourceTypeOrReferenceId, cond->SourceGroup);
676  if (cond->SourceEntry && iSourceTypeOrReferenceId < 0)
677  sLog.outErrorDb("Condition %s %i has useless data in SourceEntry (%u)!", rowType, iSourceTypeOrReferenceId, cond->SourceEntry);
678  }
679  else if (!isConditionTypeValid(cond))//doesn't have reference, validate ConditionType
680  {
681  delete cond;
682  continue;
683  }
684 
685  if (iSourceTypeOrReferenceId < 0)//it is a reference template
686  {
687  uint32 uRefId = abs(iSourceTypeOrReferenceId);
688  if (ConditionReferenceStore.find(uRefId) == ConditionReferenceStore.end())//make sure we have a list for our conditions, based on reference id
689  {
690  ConditionList mCondList;
691  ConditionReferenceStore[uRefId] = mCondList;
692  }
693  ConditionReferenceStore[uRefId].push_back(cond);//add to reference storage
694  count++;
695  continue;
696  }//end of reference templates
697 
698  //if not a reference and SourceType is invalid, skip
699  if (iConditionTypeOrReference >= 0 && !isSourceTypeValid(cond))
700  {
701  delete cond;
702  continue;
703  }
704 
705  if (cond->SourceId && !CanHaveSourceIdSet(cond->SourceType))
706  {
707  sLog.outError("%s has not allowed value of SourceId = %u!", cond->ToString().c_str(), cond->SourceId);
708  delete cond;
709  continue;
710  }
711 
712  if (cond->ErrorType && cond->SourceType != CONDITION_SOURCE_TYPE_SPELL)
713  {
714  sLog.outError("Condition type %u entry %i can't have ErrorType (%u), set to 0!", uint32(cond->SourceType), cond->SourceEntry, cond->ErrorType);
715  cond->ErrorType = 0;
716  }
717 
718  if (cond->ErrorTextId && !cond->ErrorType)
719  {
720  sLog.outError("Condition type %u entry %i has any ErrorType, ErrorTextId (%u) is set, set to 0!", uint32(cond->SourceType), cond->SourceEntry, cond->ErrorTextId);
721  cond->ErrorTextId = 0;
722  }
723 
724  //Grouping is only allowed for some types (loot templates, gossip menus, gossip items)
725  if (cond->SourceGroup && !isGroupable(cond->SourceType))
726  {
727  sLog.outErrorDb("Condition type %u has not allowed grouping %u!", uint32(cond->SourceType), cond->SourceGroup);
728  delete cond;
729  continue;
730  }
731  else if (cond->SourceGroup)
732  {
733  bool valid = false;
734  // handle grouped conditions
735  switch (cond->SourceType)
736  {
738  valid = addToLootTemplate(cond, LootTemplates_Creature.GetLootForConditionFill(cond->SourceGroup));
739  break;
741  valid = addToLootTemplate(cond, LootTemplates_Disenchant.GetLootForConditionFill(cond->SourceGroup));
742  break;
744  valid = addToLootTemplate(cond, LootTemplates_Fishing.GetLootForConditionFill(cond->SourceGroup));
745  break;
747  valid = addToLootTemplate(cond, LootTemplates_Gameobject.GetLootForConditionFill(cond->SourceGroup));
748  break;
750  valid = addToLootTemplate(cond, LootTemplates_Item.GetLootForConditionFill(cond->SourceGroup));
751  break;
753  valid = addToLootTemplate(cond, LootTemplates_Mail.GetLootForConditionFill(cond->SourceGroup));
754  break;
756  valid = addToLootTemplate(cond, LootTemplates_Pickpocketing.GetLootForConditionFill(cond->SourceGroup));
757  break;
759  valid = addToLootTemplate(cond, LootTemplates_Prospecting.GetLootForConditionFill(cond->SourceGroup));
760  break;
762  valid = addToLootTemplate(cond, LootTemplates_Reference.GetLootForConditionFill(cond->SourceGroup));
763  break;
765  valid = addToLootTemplate(cond, LootTemplates_Skinning.GetLootForConditionFill(cond->SourceGroup));
766  break;
768  valid = addToGossipMenus(cond);
769  break;
771  valid = addToGossipMenuItems(cond);
772  break;
774  {
776  std::pair<int32, uint32> key = std::make_pair(cond->SourceEntry, cond->SourceId);
777  SmartEventConditionStore[key][cond->SourceGroup].push_back(cond);
778  valid = true;
779  ++count;
780  continue;
781  }
782  }
783 
784  if (!valid)
785  {
786  sLog.outErrorDb("Not handled grouped condition, SourceGroup %u", cond->SourceGroup);
787  delete cond;
788  }
789  else
790  {
791  AllocatedMemoryStore.push_back(cond);
792  ++count;
793  }
794  continue;
795  }
796 
797  //handle not grouped conditions
798  //make sure we have a storage list for our SourceType
799  if (ConditionStore.find(cond->SourceType) == ConditionStore.end())
800  {
801  ConditionTypeContainer mTypeMap;
802  ConditionStore[cond->SourceType] = mTypeMap;//add new empty list for SourceType
803  }
804 
805  //make sure we have a condition list for our SourceType's entry
806  if (ConditionStore[cond->SourceType].find(cond->SourceEntry) == ConditionStore[cond->SourceType].end())
807  {
808  ConditionList mCondList;
809  ConditionStore[cond->SourceType][cond->SourceEntry] = mCondList;
810  }
811 
812  //add new Condition to storage based on Type/Entry
813  ConditionStore[cond->SourceType][cond->SourceEntry].push_back(cond);
814  ++count;
815  }
816  while (result->NextRow());
817 
818  sLog.outString();
819  sLog.outString(">> Loaded %u conditions", count);
820 }
821 
823 {
824  if (!loot)
825  {
826  sLog.outErrorDb("ConditionMgr: LootTemplate %u not found", cond->SourceGroup);
827  return false;
828  }
829 
830  if (loot->addConditionItem(cond))
831  return true;
832 
833  sLog.outErrorDb("ConditionMgr: Item %u not found in LootTemplate %u", cond->SourceEntry, cond->SourceGroup);
834  return false;
835 }
836 
838 {
839  GossipMenusMapBoundsNonConst pMenuBounds = sObjectMgr.GetGossipMenusMapBoundsNonConst(cond->SourceGroup);
840 
841  if (pMenuBounds.first != pMenuBounds.second)
842  {
843  for (GossipMenusMap::iterator itr = pMenuBounds.first; itr != pMenuBounds.second; ++itr)
844  {
845  if ((*itr).second.entry == cond->SourceGroup && (*itr).second.text_id == cond->SourceEntry)
846  {
847  (*itr).second.conditions.push_back(cond);
848  return true;
849  }
850  }
851  }
852 
853  sLog.outErrorDb("addToGossipMenus: GossipMenu %u not found", cond->SourceGroup);
854  return false;
855 }
856 
858 {
859  GossipMenuItemsMapBoundsNonConst pMenuItemBounds = sObjectMgr.GetGossipMenuItemsMapBoundsNonConst(cond->SourceGroup);
860  if (pMenuItemBounds.first != pMenuItemBounds.second)
861  {
862  for (GossipMenuItemsMap::iterator itr = pMenuItemBounds.first; itr != pMenuItemBounds.second; ++itr)
863  {
864  if ((*itr).second.menu_id == cond->SourceGroup && (*itr).second.id == cond->SourceEntry)
865  {
866  (*itr).second.conditions.push_back(cond);
867  return true;
868  }
869  }
870  }
871 
872  sLog.outErrorDb("addToGossipMenuItems: GossipMenuIt %u Item %u not found", cond->SourceGroup, cond->SourceEntry);
873  return false;
874 }
875 
877 {
879  {
880  sLog.outErrorDb("Invalid ConditionSourceType %u in `conditions` table, ignoring.", uint32(cond->SourceType));
881  return false;
882  }
883 
884  switch (cond->SourceType)
885  {
887  {
889  {
890  sLog.outErrorDb("SourceGroup %u in `conditions` table, does not exist in `creature_loot_template`, ignoring.", cond->SourceGroup);
891  return false;
892  }
894  ItemTemplate const* pItemProto = sItemStorage.LookupEntry<ItemTemplate>(cond->SourceEntry);
895  if (!pItemProto && !loot->isReference(cond->SourceEntry))
896  {
897  sLog.outErrorDb("SourceType %u, SourceEntry %u in `conditions` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry);
898  return false;
899  }
900  break;
901  }
903  {
905  {
906  sLog.outErrorDb("SourceGroup %u in `conditions` table, does not exist in `disenchant_loot_template`, ignoring.", cond->SourceGroup);
907  return false;
908  }
909 
911  ItemTemplate const* pItemProto = sItemStorage.LookupEntry<ItemTemplate>(cond->SourceEntry);
912  if (!pItemProto && !loot->isReference(cond->SourceEntry))
913  {
914  sLog.outErrorDb("SourceType %u, SourceEntry %u in `conditions` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry);
915  return false;
916  }
917  break;
918  }
920  {
922  {
923  sLog.outErrorDb("SourceGroup %u in `conditions` table, does not exist in `fishing_loot_template`, ignoring.", cond->SourceGroup);
924  return false;
925  }
926 
928  ItemTemplate const* pItemProto = sItemStorage.LookupEntry<ItemTemplate>(cond->SourceEntry);
929  if (!pItemProto && !loot->isReference(cond->SourceEntry))
930  {
931  sLog.outErrorDb("SourceType %u, SourceEntry %u in `conditions` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry);
932  return false;
933  }
934  break;
935  }
937  {
939  {
940  sLog.outErrorDb("SourceGroup %u in `conditions` table, does not exist in `gameobject_loot_template`, ignoring.", cond->SourceGroup);
941  return false;
942  }
943 
945  ItemTemplate const* pItemProto = sItemStorage.LookupEntry<ItemTemplate>(cond->SourceEntry);
946  if (!pItemProto && !loot->isReference(cond->SourceEntry))
947  {
948  sLog.outErrorDb("SourceType %u, SourceEntry %u in `conditions` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry);
949  return false;
950  }
951  break;
952  }
954  {
956  {
957  sLog.outErrorDb("SourceGroup %u in `conditions` table, does not exist in `item_loot_template`, ignoring.", cond->SourceGroup);
958  return false;
959  }
960 
962  ItemTemplate const* pItemProto = sItemStorage.LookupEntry<ItemTemplate>(cond->SourceEntry);
963  if (!pItemProto && !loot->isReference(cond->SourceEntry))
964  {
965  sLog.outErrorDb("SourceType %u, SourceEntry %u in `conditions` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry);
966  return false;
967  }
968  break;
969  }
971  {
973  {
974  sLog.outErrorDb("SourceGroup %u in `conditions` table, does not exist in `mail_loot_template`, ignoring.", cond->SourceGroup);
975  return false;
976  }
977 
979  ItemTemplate const* pItemProto = sItemStorage.LookupEntry<ItemTemplate>(cond->SourceEntry);
980  if (!pItemProto && !loot->isReference(cond->SourceEntry))
981  {
982  sLog.outErrorDb("SourceType %u, SourceEntry %u in `conditions` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry);
983  return false;
984  }
985  break;
986  }
988  {
990  {
991  sLog.outErrorDb("SourceGroup %u in `conditions` table, does not exist in `pickpocketing_loot_template`, ignoring.", cond->SourceGroup);
992  return false;
993  }
994 
996  ItemTemplate const* pItemProto = sItemStorage.LookupEntry<ItemTemplate>(cond->SourceEntry);
997  if (!pItemProto && !loot->isReference(cond->SourceEntry))
998  {
999  sLog.outErrorDb("SourceType %u, SourceEntry %u in `conditions` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry);
1000  return false;
1001  }
1002  break;
1003  }
1005  {
1007  {
1008  sLog.outErrorDb("SourceGroup %u in `conditions` table, does not exist in `prospecting_loot_template`, ignoring.", cond->SourceGroup);
1009  return false;
1010  }
1011 
1013  ItemTemplate const* pItemProto = sItemStorage.LookupEntry<ItemTemplate>(cond->SourceEntry);
1014  if (!pItemProto && !loot->isReference(cond->SourceEntry))
1015  {
1016  sLog.outErrorDb("SourceType %u, SourceEntry %u in `conditions` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry);
1017  return false;
1018  }
1019  break;
1020  }
1022  {
1024  {
1025  sLog.outErrorDb("SourceGroup %u in `conditions` table, does not exist in `reference_loot_template`, ignoring.", cond->SourceGroup);
1026  return false;
1027  }
1028 
1030  ItemTemplate const* pItemProto = sItemStorage.LookupEntry<ItemTemplate>(cond->SourceEntry);
1031  if (!pItemProto && !loot->isReference(cond->SourceEntry))
1032  {
1033  sLog.outErrorDb("SourceType %u, SourceEntry %u in `conditions` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry);
1034  return false;
1035  }
1036  break;
1037  }
1039  {
1041  {
1042  sLog.outErrorDb("SourceGroup %u in `conditions` table, does not exist in `skinning_loot_template`, ignoring.", cond->SourceGroup);
1043  return false;
1044  }
1045 
1047  ItemTemplate const* pItemProto = sItemStorage.LookupEntry<ItemTemplate>(cond->SourceEntry);
1048  if (!pItemProto && !loot->isReference(cond->SourceEntry))
1049  {
1050  sLog.outErrorDb("SourceType %u, SourceEntry %u in `conditions` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry);
1051  return false;
1052  }
1053  break;
1054  }
1056  {
1057  if (cond->Type != CONDITION_SPELL_SCRIPT_TARGET)
1058  {
1059  sLog.outErrorDb("SourceEntry %u in `conditions` table, has ConditionType %u. Only CONDITION_SPELL_SCRIPT_TARGET(17) is valid for CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET(14), ignoring.", cond->SourceEntry, uint32(cond->Type));
1060  return false;
1061  }
1062 
1063  SpellEntry const* spellProto = sSpellStore.LookupEntry(cond->SourceEntry);
1064  if (!spellProto)
1065  {
1066  sLog.outErrorDb("SourceEntry %u in `conditions` table, does not exist in `spell.dbc`, ignoring.", cond->SourceEntry);
1067  return false;
1068  }
1069 
1070  bool targetfound = false;
1071  for (uint8 i = 0; i < 3; ++i)
1072  {
1073  if (spellProto->EffectImplicitTargetA[i] == TARGET_UNIT_AREA_ENTRY_SRC ||
1077  spellProto->EffectImplicitTargetA[i] == TARGET_UNIT_NEARBY_ENTRY ||
1078  spellProto->EffectImplicitTargetB[i] == TARGET_UNIT_NEARBY_ENTRY ||
1081  spellProto->EffectImplicitTargetA[i] == TARGET_DST_NEARBY_ENTRY ||
1082  spellProto->EffectImplicitTargetB[i] == TARGET_DST_NEARBY_ENTRY ||
1083  spellProto->EffectImplicitTargetA[i] == TARGET_UNIT_CONE_ENTRY ||
1085  {
1086  targetfound = true;
1087  break;
1088  }
1089  }
1090  if (!targetfound)
1091  {
1092  sLog.outErrorDb("SourceEntry %u in `conditions` table does not have any implicit target TARGET_UNIT_NEARBY_ENTRY(38) or TARGET_DST_NEARBY_ENTRY (46)\
1093  ,TARGET_UNIT_AREA_ENTRY_SRC(7), TARGET_UNIT_AREA_ENTRY_DST(8), TARGET_UNIT_CONE_ENTRY(60), TARGET_GAMEOBJECT_NEARBY_ENTRY(40)",cond->SourceEntry);
1094  return false;
1095  }
1096  break;
1097  }
1099  {
1101  {
1102  sLog.outErrorDb("SourceEntry %u in `conditions` table, does not exist in `creature_template`, ignoring.", cond->SourceEntry);
1103  return false;
1104  }
1105  break;
1106  }
1108  {
1109  SpellEntry const* spellProto = sSpellStore.LookupEntry(cond->SourceEntry);
1110  if (!spellProto)
1111  {
1112  sLog.outErrorDb("SourceEntry %u in `conditions` table, does not exist in `spell.dbc`, ignoring.", cond->SourceEntry);
1113  return false;
1114  }
1115  break;
1116  }
1118  {
1119  Quest const *Quest = sObjectMgr.GetQuestTemplate(cond->SourceEntry);
1120  if (!Quest)
1121  {
1122  sLog.outErrorDb("CONDITION_SOURCE_TYPE_QUEST_ACCEPT specifies non-existing quest (%u), skipped", cond->SourceEntry);
1123  return false;
1124  }
1125  }
1126  break;
1128  {
1129  Quest const *Quest = sObjectMgr.GetQuestTemplate(cond->SourceEntry);
1130  if (!Quest)
1131  {
1132  sLog.outErrorDb("CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK specifies non-existing quest (%u), skipped", cond->SourceEntry);
1133  return false;
1134  }
1135  }
1136  break;
1138  sLog.outErrorDb("Found SourceTypeOrReferenceId = CONDITION_SOURCE_TYPE_UNUSED_18 in `conditions` table - ignoring");
1139  return false;
1144  default:
1145  break;
1146  }
1147 
1148  return true;
1149 }
1151 {
1152  if (cond->Type == CONDITION_NONE || cond->Type >= CONDITION_MAX)
1153  {
1154  sLog.outErrorDb("Invalid ConditionType %u at SourceEntry %u in `conditions` table, ignoring.", uint32(cond->Type),cond->SourceEntry);
1155  return false;
1156  }
1157 
1158  if (cond->ConditionTarget >= cond->GetMaxAvailableConditionTargets())
1159  {
1160  sLog.outErrorDb("SourceType %u, SourceEntry %u in `conditions` table, has incorrect ConditionTarget set, ignoring.", cond->SourceType, cond->SourceEntry);
1161  return false;
1162  }
1163 
1164  switch (cond->Type)
1165  {
1166  case CONDITION_AURA:
1167  {
1168  if (!sSpellStore.LookupEntry(cond->ConditionValue1))
1169  {
1170  sLog.outErrorDb("Aura condition has non existing spell (Id: %d), skipped", cond->ConditionValue1);
1171  return false;
1172  }
1173 
1174  if (cond->ConditionValue2 > 2)
1175  {
1176  sLog.outErrorDb("Aura condition has non existing effect index (%u) (must be 0..2), skipped", cond->ConditionValue2);
1177  return false;
1178  }
1179  if (cond->ConditionValue3)
1180  sLog.outErrorDb("Aura condition has useless data in value3 (%u)!", cond->ConditionValue3);
1181  break;
1182  }
1183  case CONDITION_ITEM:
1184  {
1185  ItemTemplate const *proto = sObjectMgr.GetItemTemplate(cond->ConditionValue1);
1186  if (!proto)
1187  {
1188  sLog.outErrorDb("Item condition has non existing item (%u), skipped", cond->ConditionValue1);
1189  return false;
1190  }
1191 
1192  if (!cond->ConditionValue2)
1193  {
1194  sLog.outErrorDb("Item condition has 0 set for item count in value2 (%u), skipped", cond->ConditionValue2);
1195  return false;
1196  }
1197  break;
1198  }
1200  {
1201  ItemTemplate const *proto = sObjectMgr.GetItemTemplate(cond->ConditionValue1);
1202  if (!proto)
1203  {
1204  sLog.outErrorDb("ItemEquipped condition has non existing item (%u), skipped", cond->ConditionValue1);
1205  return false;
1206  }
1207 
1208  if (cond->ConditionValue2)
1209  sLog.outErrorDb("ItemEquipped condition has useless data in value2 (%u)!", cond->ConditionValue2);
1210  break;
1211  }
1212  case CONDITION_ZONEID:
1213  {
1214  AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(cond->ConditionValue1);
1215  if (!areaEntry)
1216  {
1217  sLog.outErrorDb("Zone condition has non existing area (%u), skipped", cond->ConditionValue1);
1218  return false;
1219  }
1220 
1221  if (areaEntry->zone != 0)
1222  {
1223  sLog.outErrorDb("Zone condition requires to be in area (%u) which is a subzone but zone expected, skipped", cond->ConditionValue1);
1224  return false;
1225  }
1226 
1227  if (cond->ConditionValue2)
1228  sLog.outErrorDb("Zone condition has useless data in value2 (%u)!", cond->ConditionValue2);
1229  break;
1230  }
1232  {
1233  FactionEntry const* factionEntry = sFactionStore.LookupEntry(cond->ConditionValue1);
1234  if (!factionEntry)
1235  {
1236  sLog.outErrorDb("Reputation condition has non existing faction (%u), skipped", cond->ConditionValue1);
1237  return false;
1238  }
1239  break;
1240  }
1241  case CONDITION_TEAM:
1242  {
1243  if (cond->ConditionValue1 != ALLIANCE && cond->ConditionValue1 != HORDE)
1244  {
1245  sLog.outErrorDb("Team condition specifies unknown team (%u), skipped", cond->ConditionValue1);
1246  return false;
1247  }
1248 
1249  if (cond->ConditionValue2)
1250  sLog.outErrorDb("Team condition has useless data in value2 (%u)!", cond->ConditionValue2);
1251  break;
1252  }
1253  case CONDITION_SKILL:
1254  {
1255  SkillLineEntry const *pSkill = sSkillLineStore.LookupEntry(cond->ConditionValue1);
1256  if (!pSkill)
1257  {
1258  sLog.outErrorDb("Skill condition specifies non-existing skill (%u), skipped", cond->ConditionValue1);
1259  return false;
1260  }
1261 
1262  if (cond->ConditionValue2 < 1 || cond->ConditionValue2 > sWorld.GetConfigMaxSkillValue())
1263  {
1264  sLog.outErrorDb("Skill condition specifies invalid skill value (%u), skipped", cond->ConditionValue2);
1265  return false;
1266  }
1267  break;
1268  }
1270  case CONDITION_QUESTTAKEN:
1271  case CONDITION_QUEST_NONE:
1273  {
1274  Quest const *Quest = sObjectMgr.GetQuestTemplate(cond->ConditionValue1);
1275  if (!Quest)
1276  {
1277  sLog.outErrorDb("Quest condition specifies non-existing quest (%u), skipped", cond->ConditionValue1);
1278  return false;
1279  }
1280 
1281  if (cond->ConditionValue2 > 1)
1282  sLog.outErrorDb("Quest condition has useless data in value2 (%u)!", cond->ConditionValue2);
1283  break;
1284  }
1286  {
1287  GameEventMgr::GameEventDataMap const& events = sGameEventMgr.GetEventMap();
1288  if (cond->ConditionValue1 >=events.size() || !events[cond->ConditionValue1].isValid())
1289  {
1290  sLog.outErrorDb("Active event condition has non existing event id (%u), skipped", cond->ConditionValue1);
1291  return false;
1292  }
1293 
1294  if (cond->ConditionValue2)
1295  sLog.outErrorDb("Active event condition has useless data in value2 (%u)!", cond->ConditionValue2);
1296  break;
1297  }
1298  case CONDITION_CLASS:
1299  {
1300  if (!(cond->ConditionValue1 & CLASSMASK_ALL_PLAYABLE))
1301  {
1302  sLog.outErrorDb("Class condition has non existing classmask (%u), skipped", cond->ConditionValue1 & ~CLASSMASK_ALL_PLAYABLE);
1303  return false;
1304  }
1305 
1306  if (cond->ConditionValue2)
1307  sLog.outErrorDb("Class condition has useless data in value2 (%u)!", cond->ConditionValue2);
1308  break;
1309  }
1310  case CONDITION_RACE:
1311  {
1312  if (!(cond->ConditionValue1 & RACEMASK_ALL_PLAYABLE))
1313  {
1314  sLog.outErrorDb("Race condition has non existing racemask (%u), skipped", cond->ConditionValue1 & ~RACEMASK_ALL_PLAYABLE);
1315  return false;
1316  }
1317 
1318  if (cond->ConditionValue2)
1319  sLog.outErrorDb("Race condition has useless data in value2 (%u)!", cond->ConditionValue2);
1320  break;
1321  }
1323  {
1325  {
1326  sLog.outErrorDb("SpellTarget condition has non existing spell target type (%u), skipped", cond->ConditionValue1);
1327  return false;
1328  }
1329 
1330  switch(cond->ConditionValue1)
1331  {
1333  {
1335  {
1336  sLog.outErrorDb("SpellTarget condition has non existing gameobject (%u) as target, skipped", cond->ConditionValue2);
1337  return false;
1338  }
1339  break;
1340  }
1343  {
1345  {
1346  sLog.outErrorDb("SpellTarget condition has non existing creature template entry (%u) as target, skipped", cond->ConditionValue2);
1347  return false;
1348  }
1349 
1351  if (cond->SourceEntry == 30427 && !cInfo->SkinLootId)
1352  {
1353  sLog.outErrorDb("SpellTarget condition has creature entry %u as a target of spellid 30427, but this creature has no skinlootid. Gas extraction will not work!, skipped", cond->ConditionValue2);
1354  return false;
1355  }
1356  break;
1357  }
1358  }
1359 
1360  if (cond->ConditionValue3)
1361  sLog.outErrorDb("SpellTarget condition has useless data in value3 (%u)!", cond->ConditionValue3);
1362  break;
1363  }
1364  case CONDITION_TITLE:
1365  {
1366  CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(cond->ConditionValue1);
1367  if (!titleEntry)
1368  {
1369  sLog.outErrorDb("Title condition has non existing title in value1 (%u), skipped", cond->ConditionValue1);
1370  return false;
1371  }
1372  break;
1373  }
1374  case CONDITION_SPAWNMASK:
1375  {
1376  if (cond->ConditionValue1 >= 2)
1377  {
1378  sLog.outError("Map Difficulty condition has non existing map difficulty in value1 (%u), skipped", cond->ConditionValue1);
1379  return false;
1380  }
1381  break;
1382  }
1383  case CONDITION_GENDER:
1384  {
1385  /* ConditionTodo
1386  if (!Player::IsValidGender(uint8(cond->ConditionValue1)))
1387  {
1388  sLog.outError("Gender condition has invalid gender (%u), skipped", cond->ConditionValue1);
1389  return false;
1390  }*/
1391 
1392  if (cond->ConditionValue2)
1393  sLog.outError("Gender condition has useless data in value2 (%u)!", cond->ConditionValue2);
1394  if (cond->ConditionValue3)
1395  sLog.outError("Gender condition has useless data in value3 (%u)!", cond->ConditionValue3);
1396  break;
1397  }
1398  case CONDITION_UNIT_STATE:
1399  {
1401  {
1402  sLog.outError("UnitState condition has non existing UnitState in value1 (%u), skipped", cond->ConditionValue1);
1403  return false;
1404  }
1405  break;
1406  }
1407  case CONDITION_MAPID:
1408  {
1409  MapEntry const * me = sMapStore.LookupEntry(cond->ConditionValue1);
1410  if (!me)
1411  {
1412  sLog.outErrorDb("Map condition has non existing map (%u), skipped", cond->ConditionValue1);
1413  return false;
1414  }
1415 
1416  if (cond->ConditionValue2)
1417  sLog.outErrorDb("Map condition has useless data in value2 (%u)!", cond->ConditionValue2);
1418  break;
1419  }
1421  {
1423  {
1424  sLog.outErrorDb("CreatureType condition has non existing CreatureType in value1 (%u), skipped", cond->ConditionValue1);
1425  return false;
1426  }
1427  break;
1428  }
1429  case CONDITION_SPELL:
1430  {
1431  if (!sSpellStore.LookupEntry(cond->ConditionValue1))
1432  {
1433  sLog.outErrorDb("Spell condition has non existing spell (Id: %d), skipped", cond->ConditionValue1);
1434  return false;
1435  }
1436 
1437  if (cond->ConditionValue2)
1438  sLog.outErrorDb("Spell condition has useless data in value2 (%u)!", cond->ConditionValue2);
1439  break;
1440  }
1441  case CONDITION_LEVEL:
1442  {
1443  if (cond->ConditionValue2 >= COMP_TYPE_MAX)
1444  {
1445  sLog.outErrorDb("Level condition has invalid option (%u), skipped", cond->ConditionValue2);
1446  return false;
1447  }
1448  break;
1449  }
1451  {
1452  if (cond->ConditionValue1 > DRUNKEN_SMASHED)
1453  {
1454  sLog.outErrorDb("DrunkState condition has invalid state (%u), skipped", cond->ConditionValue1);
1455  return false;
1456  }
1457  break;
1458  }
1460  {
1462  {
1463  sLog.outErrorDb("NearCreature condition has non existing creature template entry (%u), skipped", cond->ConditionValue1);
1464  return false;
1465  }
1466  break;
1467  }
1469  {
1471  {
1472  sLog.outErrorDb("NearGameObject condition has non existing gameobject template entry (%u), skipped", cond->ConditionValue1);
1473  return false;
1474  }
1475  break;
1476  }
1478  {
1479  switch (cond->ConditionValue1)
1480  {
1481  case TYPEID_UNIT:
1482  if (cond->ConditionValue2 && !sObjectMgr.GetCreatureTemplate(cond->ConditionValue2))
1483  {
1484  sLog.outErrorDb("ObjectEntryGuid condition has non existing creature template entry (%u), skipped", cond->ConditionValue2);
1485  return false;
1486  }
1487  if (cond->ConditionValue3)
1488  {
1489  if (CreatureData const* creatureData = sObjectMgr.GetCreatureData(cond->ConditionValue3))
1490  {
1491  if (cond->ConditionValue2 && creatureData->id != cond->ConditionValue2)
1492  {
1493  sLog.outErrorDb("ObjectEntryGuid condition has guid %u set but does not match creature entry (%u), skipped", cond->ConditionValue3, cond->ConditionValue2);
1494  return false;
1495  }
1496  }
1497  else
1498  {
1499  sLog.outErrorDb("ObjectEntryGuid condition has non existing creature guid (%u), skipped", cond->ConditionValue3);
1500  return false;
1501  }
1502  }
1503  break;
1504  case TYPEID_GAMEOBJECT:
1505  if (cond->ConditionValue2 && !sObjectMgr.GetGameObjectInfo(cond->ConditionValue2))
1506  {
1507  sLog.outErrorDb("ObjectEntryGuid condition has non existing game object template entry (%u), skipped", cond->ConditionValue2);
1508  return false;
1509  }
1510  if (cond->ConditionValue3)
1511  {
1512  if (GameObjectData const* goData = sObjectMgr.GetGOData(cond->ConditionValue3))
1513  {
1514  if (cond->ConditionValue2 && goData->id != cond->ConditionValue2)
1515  {
1516  sLog.outErrorDb("ObjectEntryGuid condition has guid %u set but does not match gameobject entry (%u), skipped", cond->ConditionValue3, cond->ConditionValue2);
1517  return false;
1518  }
1519  }
1520  else
1521  {
1522  sLog.outErrorDb("ObjectEntryGuid condition has non existing gameobject guid (%u), skipped", cond->ConditionValue3);
1523  return false;
1524  }
1525  }
1526  break;
1527  case TYPEID_PLAYER:
1528  case TYPEID_CORPSE:
1529  if (cond->ConditionValue2)
1530  sLog.outErrorDb("ObjectEntryGuid condition has useless data in value2 (%u)!", cond->ConditionValue2);
1531  if (cond->ConditionValue3)
1532  sLog.outErrorDb("ObjectEntryGuid condition has useless data in value3 (%u)!", cond->ConditionValue3);
1533  break;
1534  default:
1535  sLog.outErrorDb("ObjectEntryGuid condition has wrong typeid set (%u), skipped", cond->ConditionValue1);
1536  return false;
1537  }
1538  break;
1539  }
1540  case CONDITION_TYPE_MASK:
1541  {
1543  {
1544  sLog.outErrorDb("TypeMask condition has invalid typemask set (%u), skipped", cond->ConditionValue2);
1545  return false;
1546  }
1547  if (cond->ConditionValue2)
1548  sLog.outErrorDb("TypeMask condition has useless data in value2 (%u)!", cond->ConditionValue2);
1549  if (cond->ConditionValue3)
1550  sLog.outErrorDb("TypeMask condition has useless data in value3 (%u)!", cond->ConditionValue3);
1551  break;
1552  }
1553  case CONDITION_RELATION_TO:
1554  {
1555  if (cond->ConditionValue1 >= cond->GetMaxAvailableConditionTargets())
1556  {
1557  sLog.outErrorDb("RelationTo condition has invalid ConditionValue1(ConditionTarget selection) (%u), skipped", cond->ConditionValue1);
1558  return false;
1559  }
1560  if (cond->ConditionValue1 == cond->ConditionTarget)
1561  {
1562  sLog.outErrorDb("RelationTo condition has ConditionValue1(ConditionTarget selection) set to self (%u), skipped", cond->ConditionValue1);
1563  return false;
1564  }
1565  if (cond->ConditionValue2 >= RELATION_MAX)
1566  {
1567  sLog.outErrorDb("RelationTo condition has invalid ConditionValue2(RelationType) (%u), skipped", cond->ConditionValue2);
1568  return false;
1569  }
1570  if (cond->ConditionValue3)
1571  sLog.outErrorDb("RelationTo condition has useless data in value3 (%u)!", cond->ConditionValue3);
1572  break;
1573  }
1574  case CONDITION_REACTION_TO:
1575  {
1576  if (cond->ConditionValue1 >= cond->GetMaxAvailableConditionTargets())
1577  {
1578  sLog.outErrorDb("ReactionTo condition has invalid ConditionValue1(ConditionTarget selection) (%u), skipped", cond->ConditionValue1);
1579  return false;
1580  }
1581  if (cond->ConditionValue1 == cond->ConditionTarget)
1582  {
1583  sLog.outErrorDb("ReactionTo condition has ConditionValue1(ConditionTarget selection) set to self (%u), skipped", cond->ConditionValue1);
1584  return false;
1585  }
1586  if (!cond->ConditionValue2)
1587  {
1588  sLog.outErrorDb("ConditionValue2 condition has invalid ConditionValue2(rankMask) (%u), skipped", cond->ConditionValue2);
1589  return false;
1590  }
1591  break;
1592  }
1593  case CONDITION_DISTANCE_TO:
1594  {
1595  if (cond->ConditionValue1 >= cond->GetMaxAvailableConditionTargets())
1596  {
1597  sLog.outErrorDb("DistanceTo condition has invalid ConditionValue1(ConditionTarget selection) (%u), skipped", cond->ConditionValue1);
1598  return false;
1599  }
1600  if (cond->ConditionValue1 == cond->ConditionTarget)
1601  {
1602  sLog.outErrorDb("DistanceTo condition has ConditionValue1(ConditionTarget selection) set to self (%u), skipped", cond->ConditionValue1);
1603  return false;
1604  }
1605  if (cond->ConditionValue3 >= COMP_TYPE_MAX)
1606  {
1607  sLog.outErrorDb("DistanceTo condition has invalid ComparisionType (%u), skipped", cond->ConditionValue3);
1608  return false;
1609  }
1610  break;
1611  }
1612  case CONDITION_ALIVE:
1613  {
1614  if (cond->ConditionValue1)
1615  sLog.outErrorDb("Alive condition has useless data in value1 (%u)!", cond->ConditionValue1);
1616  if (cond->ConditionValue2)
1617  sLog.outErrorDb("Alive condition has useless data in value2 (%u)!", cond->ConditionValue2);
1618  if (cond->ConditionValue3)
1619  sLog.outErrorDb("Alive condition has useless data in value3 (%u)!", cond->ConditionValue3);
1620  break;
1621  }
1622  case CONDITION_HP_VAL:
1623  {
1624  if (cond->ConditionValue2 >= COMP_TYPE_MAX)
1625  {
1626  sLog.outErrorDb("HpVal condition has invalid ComparisionType (%u), skipped", cond->ConditionValue2);
1627  return false;
1628  }
1629  if (cond->ConditionValue3)
1630  sLog.outErrorDb("HpVal condition has useless data in value3 (%u)!", cond->ConditionValue3);
1631  break;
1632  }
1633  case CONDITION_HP_PCT:
1634  {
1635  if (cond->ConditionValue1 > 100)
1636  {
1637  sLog.outErrorDb("HpPct condition has too big percent value (%u), skipped", cond->ConditionValue1);
1638  return false;
1639  }
1640  if (cond->ConditionValue2 >= COMP_TYPE_MAX)
1641  {
1642  sLog.outErrorDb("HpPct condition has invalid ComparisionType (%u), skipped", cond->ConditionValue2);
1643  return false;
1644  }
1645  if (cond->ConditionValue3)
1646  sLog.outErrorDb("HpPct condition has useless data in value3 (%u)!", cond->ConditionValue3);
1647  break;
1648  }
1649  case CONDITION_AREAID:
1651  break;
1652  case CONDITION_WORLD_STATE:
1653  {
1654  /* @todo Implement this feature
1655  if (!sWorld->getWorldState(cond->ConditionValue1))
1656  {
1657  sLog.outErrorDb("World state condition has non existing world state in value1 (%u), skipped", cond->ConditionValue1);
1658  return false;
1659  }*/
1660  if (cond->ConditionValue2)
1661  sLog.outErrorDb("World state condition has useless data in value2 (%u)!", cond->ConditionValue2);
1662  if (cond->ConditionValue3)
1663  sLog.outErrorDb("World state condition has useless data in value3 (%u)!", cond->ConditionValue3);
1664  break;
1665  }
1666  }
1667  return true;
1668 }
1669 
1671 {
1672  for (ConditionReferenceContainer::iterator itr = ConditionReferenceStore.begin(); itr != ConditionReferenceStore.end(); ++itr)
1673  {
1674  for (ConditionList::const_iterator it = itr->second.begin(); it != itr->second.end(); ++it)
1675  delete *it;
1676  itr->second.clear();
1677  }
1678 
1679  ConditionReferenceStore.clear();
1680 
1681  for (ConditionContainer::iterator itr = ConditionStore.begin(); itr != ConditionStore.end(); ++itr)
1682  {
1683  for (ConditionTypeContainer::iterator it = itr->second.begin(); it != itr->second.end(); ++it)
1684  {
1685  for (ConditionList::const_iterator i = it->second.begin(); i != it->second.end(); ++i)
1686  delete *i;
1687  it->second.clear();
1688  }
1689  itr->second.clear();
1690  }
1691 
1692  ConditionStore.clear();
1693 
1694  for (SmartEventConditionContainer::iterator itr = SmartEventConditionStore.begin(); itr != SmartEventConditionStore.end(); ++itr)
1695  {
1696  for (ConditionTypeContainer::iterator it = itr->second.begin(); it != itr->second.end(); ++it)
1697  {
1698  for (ConditionList::const_iterator i = it->second.begin(); i != it->second.end(); ++i)
1699  delete *i;
1700  it->second.clear();
1701  }
1702  itr->second.clear();
1703  }
1704 
1705  SmartEventConditionStore.clear();
1706 
1707  // this is a BIG hack, feel free to fix it if you can figure out the ConditionMgr ;)
1708  for (std::list<Condition*>::const_iterator itr = AllocatedMemoryStore.begin(); itr != AllocatedMemoryStore.end(); ++itr)
1709  delete *itr;
1710 
1711  AllocatedMemoryStore.clear();
1712 }
AreaTableEntry const * GetAreaEntryByAreaID(uint32 area_id)
Definition: DBCStores.cpp:623
static bool isGroupable(ConditionSourceType sourceType)
Definition: ConditionMgr.h:246
void ResetConditions()
Definition: LootMgr.cpp:170
uint32 ElseGroup
Definition: ConditionMgr.h:185
SQLStorage sCreatureStorage
static DrunkenState GetDrunkenstateByValue(uint16 value)
Definition: Player.cpp:1003
ConditionType Type
Definition: ConditionMgr.h:186
DBCStorage< SkillLineEntry > sSkillLineStore(SkillLinefmt)
ConditionSourceType
Definition: ConditionMgr.h:101
ReputationRank GetReactionTo(Unit const *target) const
Definition: Unit.cpp:7147
bool isReference(uint32 id)
Definition: LootMgr.cpp:1279
DatabaseType WorldDatabase
Accessor to the world database.
Definition: Main.cpp:53
bool CompareValues(ComparisionType type, T val1, T val2)
Definition: ConditionMgr.h:292
static ConditionTypeInfo const StaticConditionTypeData[CONDITION_MAX]
Definition: ConditionMgr.h:274
std::list< Condition * > ConditionList
Definition: ConditionMgr.h:223
Definition: Field.h:24
bool addToLootTemplate(Condition *cond, LootTemplate *loot)
bool IsInPartyWith(Unit const *unit) const
Definition: Unit.cpp:13257
LootStore LootTemplates_Gameobject("gameobject_loot_template","gameobject entry")
bool isSourceTypeValid(Condition *cond)
QuestStatus
Definition: QuestDef.h:89
#define sLog
Log class singleton.
Definition: Log.h:187
LootTemplate * GetLootForConditionFill(uint32 loot_id)
Definition: LootMgr.cpp:189
ACE_INT32 int32
Definition: Define.h:67
QueryResult_AutoPtr Query(const char *sql)
Definition: Database.cpp:383
bool IsDungeon() const
Definition: Map.h:427
int32 SourceEntry
Definition: ConditionMgr.h:183
ConditionList GetConditionsForSmartEvent(int32 entryOrGuid, uint32 eventId, uint32 sourceType)
LootStore LootTemplates_Creature("creature_loot_template","creature entry")
uint32 SourceId
Definition: ConditionMgr.h:184
#define sObjectMgr
Definition: ObjectMgr.h:1285
uint32 ErrorTextId
Definition: ConditionMgr.h:191
ConditionType
Definition: ConditionMgr.h:29
DBCStorage< MapEntry > sMapStore(MapEntryfmt)
DBCStorage< SpellEntry > sSpellStore(SpellEntryfmt)
Player * ToPlayer()
Definition: Object.h:386
uint32 SkinLootId
Definition: Creature.h:177
DBCStorage< CharTitlesEntry > sCharTitlesStore(CharTitlesEntryfmt)
ConditionList GetConditionsForNotGroupedEntry(ConditionSourceType sourceType, uint32 entry)
uint8 GetTypeId() const
Definition: Object.h:204
uint32 ErrorType
Definition: ConditionMgr.h:190
ACE_UINT8 uint8
Definition: Define.h:73
INSTANTIATE_SINGLETON_1(ConditionMgr)
ConditionList GetConditionReferences(uint32 refId)
float GetDistance(const WorldObject *obj) const
Definition: Object.h:706
uint32 SourceGroup
Definition: ConditionMgr.h:182
std::string ToString(bool ext=false) const
LootStore LootTemplates_Prospecting("prospecting_loot_template","item entry (ore)")
GameObject * GetClosestGameObjectWithEntry(WorldObject *pSource, uint32 uiEntry, float fMaxSearchRange)
uint32 EffectImplicitTargetB[MAX_SPELL_EFFECTS]
Definition: DBCStructure.h:732
uint64 GetCreatorGUID() const
Definition: Unit.h:1455
bool addToGossipMenus(Condition *cond)
uint8 ConditionTarget
Definition: ConditionMgr.h:194
LootStore LootTemplates_Mail("mail_loot_template","mail template id")
#define CLASSMASK_ALL_PLAYABLE
Definition: SharedDefines.h:93
uint32 EffectImplicitTargetA[MAX_SPELL_EFFECTS]
Definition: DBCStructure.h:731
Creature * GetClosestCreatureWithEntry(WorldObject *pSource, uint32 uiEntry, float fMaxSearchRange, bool bAlive)
uint32 ConditionValue3
Definition: ConditionMgr.h:189
LootStore LootTemplates_Item("item_loot_template","item entry")
Definition: Map.h:266
SQLStorage sItemStorage
bool NegativeCondition
Definition: ConditionMgr.h:195
bool HaveLootFor(uint32 loot_id) const
Definition: LootMgr.h:184
Condition * mLastFailedCondition
Definition: ConditionMgr.h:169
uint64 GetOwnerGUID() const
Definition: Unit.h:1451
LootStore LootTemplates_Pickpocketing("pickpocketing_loot_template","creature pickpocket lootid")
uint32 ConditionValue2
Definition: ConditionMgr.h:188
LootStore LootTemplates_Reference("reference_loot_template","reference id")
bool IsObjectMeetToConditionList(ConditionSourceInfo &sourceInfo, ConditionList const &conditions)
T const * LookupEntry(uint32 id) const
Definition: SQLStorage.h:52
static bool CanHaveSourceIdSet(ConditionSourceType sourceType)
LootStore LootTemplates_Fishing("fishing_loot_template","area id")
#define sGameEventMgr
Definition: GameEventMgr.h:179
uint32 ScriptId
Definition: ConditionMgr.h:193
bool Meets(ConditionSourceInfo &sourceInfo)
bool addToGossipMenuItems(Condition *cond)
ACE_Refcounted_Auto_Ptr< QueryResult, ACE_Null_Mutex > QueryResult_AutoPtr
Definition: QueryResult.h:113
uint32 ConditionValue1
Definition: ConditionMgr.h:187
#define MAX_SPELL_TARGET_TYPE
Definition: SpellMgr.h:706
std::pair< GossipMenusMap::iterator, GossipMenusMap::iterator > GossipMenusMapBoundsNonConst
Definition: ObjectMgr.h:448
static char const * StaticSourceTypeData[CONDITION_SOURCE_TYPE_MAX]
Definition: ConditionMgr.h:273
Creature * ToCreature()
Definition: Object.h:389
DBCStorage< FactionEntry > sFactionStore(FactionEntryfmt)
#define RACEMASK_ALL_PLAYABLE
Definition: SharedDefines.h:68
std::vector< GameEventData > GameEventDataMap
Definition: GameEventMgr.h:94
void LoadConditions(bool isReload=false)
#define ASSERT
Definition: Errors.h:33
bool isConditionTypeValid(Condition *cond)
uint32 GetMaxAvailableConditionTargets()
#define sWorld
Definition: World.h:860
WorldObject * mConditionTargets[MAX_CONDITION_TARGETS]
Definition: ConditionMgr.h:168
SQLStorage sGOStorage
#define CONDITION_MAX
Definition: ConditionMgr.h:72
bool IsInRaidWith(Unit const *unit) const
Definition: Unit.cpp:13273
ACE_UINT32 uint32
Definition: Define.h:71
uint32 ReferenceId
Definition: ConditionMgr.h:192
LootStore LootTemplates_Skinning("skinning_loot_template","creature skinning id")
LootStore LootTemplates_Disenchant("disenchant_loot_template","item disenchant id")
Definition: Unit.h:884
bool IsObjectMeetToConditions(WorldObject *object, ConditionList const &conditions)
Definition: Player.h:922
bool addConditionItem(Condition *cond)
Definition: LootMgr.cpp:1226
Unit * ToUnit()
Definition: Object.h:392
std::map< uint32, ConditionList > ConditionTypeContainer
Definition: ConditionMgr.h:224
ConditionSourceType SourceType
Definition: ConditionMgr.h:181
#define COMP_TYPE_MAX
Definition: ConditionMgr.h:139
std::pair< GossipMenuItemsMap::iterator, GossipMenuItemsMap::iterator > GossipMenuItemsMapBoundsNonConst
Definition: ObjectMgr.h:451
const uint64 & GetGUID() const
Definition: Object.h:156