aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Conditions/ConditionMgr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game/Conditions/ConditionMgr.cpp')
-rwxr-xr-xsrc/server/game/Conditions/ConditionMgr.cpp1531
1 files changed, 1000 insertions, 531 deletions
diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp
index a745c5a2f13..7d21f94f372 100755
--- a/src/server/game/Conditions/ConditionMgr.cpp
+++ b/src/server/game/Conditions/ConditionMgr.cpp
@@ -26,209 +26,426 @@
#include "ConditionMgr.h"
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
+#include "Spell.h"
-// Checks if player meets the condition
+// Checks if object meets the condition
// Can have CONDITION_SOURCE_TYPE_NONE && !mReferenceId if called from a special event (ie: eventAI)
-bool Condition::Meets(Player* player, Unit* invoker)
+bool Condition::Meets(ConditionSourceInfo& sourceInfo)
{
- if (!player)
+ ASSERT(ConditionTarget < MAX_CONDITION_TARGETS);
+ WorldObject* object = sourceInfo.mConditionTargets[ConditionTarget];
+ // object not present, return false
+ if (!object)
{
- sLog->outDebug(LOG_FILTER_CONDITIONSYS, "Condition player not found");
- return false; // player not present, return false
+ sLog->outDebug(LOG_FILTER_CONDITIONSYS, "Condition object not found for condition (Entry: %u Type: %u Group: %u)", SourceEntry, SourceType, SourceGroup);
+ return false;
}
- uint32 refId = mConditionValue3;//value 3 can be a 'quick' reference
bool condMeets = false;
- bool sendErrorMsg = false;
- switch (mConditionType)
+ switch (ConditionType)
{
case CONDITION_NONE:
condMeets = true; // empty condition, always met
break;
case CONDITION_AURA:
- refId = 0;
- if (!mConditionValue3)
- condMeets = player->HasAuraEffect(mConditionValue1, mConditionValue2);
- else if (Unit* target = player->GetSelectedUnit())
- condMeets = target->HasAuraEffect(mConditionValue1, mConditionValue2);
+ {
+ if (Unit* unit = object->ToUnit())
+ condMeets = unit->HasAuraEffect(ConditionValue1, ConditionValue2);
break;
+ }
case CONDITION_ITEM:
- condMeets = (mConditionValue2 && player->HasItemCount(mConditionValue1, mConditionValue2)) || (!mConditionValue2 && !player->HasItemCount(mConditionValue1, mConditionValue2));//HasItemCount returns false if 0 count is used
+ {
+ if (Player* player = object->ToPlayer())
+ {
+ // don't allow 0 items (it's checked during table load)
+ ASSERT(ConditionValue2);
+ bool checkBank = ConditionValue3 ? true : false;
+ condMeets = player->HasItemCount(ConditionValue1, ConditionValue2, checkBank);
+ }
break;
+ }
case CONDITION_ITEM_EQUIPPED:
- condMeets = player->HasItemOrGemWithIdEquipped(mConditionValue1, 1);
+ {
+ if (Player* player = object->ToPlayer())
+ condMeets = player->HasItemOrGemWithIdEquipped(ConditionValue1, 1);
break;
+ }
case CONDITION_ZONEID:
- condMeets = player->GetZoneId() == mConditionValue1;
+ condMeets = object->GetZoneId() == ConditionValue1;
break;
case CONDITION_REPUTATION_RANK:
{
- if (FactionEntry const* faction = sFactionStore.LookupEntry(mConditionValue1))
- condMeets = (mConditionValue2 & (1 << player->GetReputationMgr().GetRank(faction)));
+ if (Player* player = object->ToPlayer())
+ {
+ if (FactionEntry const* faction = sFactionStore.LookupEntry(ConditionValue1))
+ condMeets = (ConditionValue2 & (1 << player->GetReputationMgr().GetRank(faction)));
+ }
break;
}
case CONDITION_ACHIEVEMENT:
- condMeets = player->GetAchievementMgr().HasAchieved(mConditionValue1);
+ {
+ if (Player* player = object->ToPlayer())
+ condMeets = player->GetAchievementMgr().HasAchieved(ConditionValue1);
break;
+ }
case CONDITION_TEAM:
- condMeets = player->GetTeam() == mConditionValue1;
+ {
+ if (Player* player = object->ToPlayer())
+ condMeets = player->GetTeam() == ConditionValue1;
break;
+ }
case CONDITION_CLASS:
- condMeets = player->getClassMask() & mConditionValue1;
+ {
+ if (Unit* unit = object->ToUnit())
+ condMeets = unit->getClassMask() & ConditionValue1;
break;
+ }
case CONDITION_RACE:
- condMeets = player->getRaceMask() & mConditionValue1;
+ {
+ if (Unit* unit = object->ToUnit())
+ condMeets = unit->getRaceMask() & ConditionValue1;
break;
+ }
case CONDITION_SKILL:
- condMeets = player->HasSkill(mConditionValue1) && player->GetBaseSkillValue(mConditionValue1) >= mConditionValue2;
+ {
+ if (Player* player = object->ToPlayer())
+ condMeets = player->HasSkill(ConditionValue1) && player->GetBaseSkillValue(ConditionValue1) >= ConditionValue2;
break;
+ }
case CONDITION_QUESTREWARDED:
- condMeets = (player->GetQuestRewardStatus(mConditionValue1) == !mConditionValue2);
+ {
+ if (Player* player = object->ToPlayer())
+ condMeets = (player->GetQuestRewardStatus(ConditionValue1) == !ConditionValue2);
break;
+ }
case CONDITION_QUESTTAKEN:
{
- QuestStatus status = player->GetQuestStatus(mConditionValue1);
- condMeets = ((status == QUEST_STATUS_INCOMPLETE) == !mConditionValue2);
+ if (Player* player = object->ToPlayer())
+ {
+ QuestStatus status = player->GetQuestStatus(ConditionValue1);
+ condMeets = ((status == QUEST_STATUS_INCOMPLETE) == !ConditionValue2);
+ }
break;
}
case CONDITION_QUEST_COMPLETE:
{
- QuestStatus status = player->GetQuestStatus(mConditionValue1);
- condMeets = ((status == QUEST_STATUS_COMPLETE && !player->GetQuestRewardStatus(mConditionValue1)) == !mConditionValue2);
+ if (Player* player = object->ToPlayer())
+ {
+ QuestStatus status = player->GetQuestStatus(ConditionValue1);
+ condMeets = ((status == QUEST_STATUS_COMPLETE && !player->GetQuestRewardStatus(ConditionValue1)) == !ConditionValue2);
+ }
break;
}
case CONDITION_QUEST_NONE:
{
- QuestStatus status = player->GetQuestStatus(mConditionValue1);
- condMeets = ((status == QUEST_STATUS_NONE) == !mConditionValue2);
+ if (Player* player = object->ToPlayer())
+ {
+ QuestStatus status = player->GetQuestStatus(ConditionValue1);
+ condMeets = ((status == QUEST_STATUS_NONE) == !ConditionValue2);
+ }
break;
}
- case CONDITION_NO_AURA:
- condMeets = !player->HasAuraEffect(mConditionValue1, mConditionValue2);
- break;
case CONDITION_ACTIVE_EVENT:
- condMeets = sGameEventMgr->IsActiveEvent(mConditionValue1);
+ condMeets = sGameEventMgr->IsActiveEvent(ConditionValue1);
break;
case CONDITION_INSTANCE_DATA:
{
- Map* map = player->GetMap();
+ Map* map = object->GetMap();
if (map && map->IsDungeon() && ((InstanceMap*)map)->GetInstanceScript())
- condMeets = ((InstanceMap*)map)->GetInstanceScript()->GetData(mConditionValue1) == mConditionValue2;
+ condMeets = ((InstanceMap*)map)->GetInstanceScript()->GetData(ConditionValue1) == ConditionValue2;
break;
}
- case CONDITION_SPELL_SCRIPT_TARGET:
- condMeets = true;//spell target condition is handled in spellsystem, here it is always true
- refId = 0;//cant have references! use CONDITION_SOURCE_TYPE_SPELL for it
+ case CONDITION_MAPID:
+ condMeets = object->GetMapId() == ConditionValue1;
break;
- case CONDITION_CREATURE_TARGET:
+ case CONDITION_AREAID:
+ condMeets = object->GetAreaId() == ConditionValue1;
+ break;
+ case CONDITION_SPELL:
{
- Unit* target = player->GetSelectedUnit();
- if (target)
- if (Creature* cTarget = target->ToCreature())
- if (cTarget->GetEntry() == mConditionValue1)
- condMeets = true;
+ if (Player* player = object->ToPlayer())
+ condMeets = player->HasSpell(ConditionValue1);
break;
}
- case CONDITION_TARGET_HEALTH_BELOW_PCT:
+ case CONDITION_LEVEL:
{
- Unit* target = player->GetSelectedUnit();
- if (target)
- condMeets = !target->HealthAbovePct(mConditionValue1);
+ if (Unit* unit = object->ToUnit())
+ condMeets = CompareValues(static_cast<ComparisionType>(ConditionValue2), static_cast<uint32>(unit->getLevel()), ConditionValue1);
break;
}
- case CONDITION_TARGET_RANGE:
+ case CONDITION_DRUNKENSTATE:
{
- if (Unit* target = player->GetSelectedUnit())
- if (player->GetDistance(target) >= mConditionValue1 && (!mConditionValue2 || player->GetDistance(target) <= mConditionValue2))
- condMeets = true;
+ if (Player* player = object->ToPlayer())
+ condMeets = (uint32)Player::GetDrunkenstateByValue(player->GetDrunkValue()) >= ConditionValue1;
break;
}
- case CONDITION_MAPID:
- condMeets = player->GetMapId() == mConditionValue1;
+ case CONDITION_NEAR_CREATURE:
+ {
+ condMeets = GetClosestCreatureWithEntry(object, ConditionValue1, (float)ConditionValue2) ? true : false;
break;
- case CONDITION_AREAID:
- condMeets = player->GetAreaId() == mConditionValue1;
+ }
+ case CONDITION_NEAR_GAMEOBJECT:
+ {
+ condMeets = GetClosestGameObjectWithEntry(object, ConditionValue1, (float)ConditionValue2) ? true : false;
break;
- case CONDITION_ITEM_TARGET:
+ }
+ case CONDITION_OBJECT_ENTRY:
{
- condMeets = true;//handled in Item::IsTargetValidForItemUse
- refId = 0;//cant have references for now
+ if (object->GetTypeId() == ConditionValue1)
+ condMeets = (!ConditionValue2) || (object->GetEntry() == ConditionValue2);
break;
}
- case CONDITION_SPELL:
- if (mConditionValue2 == 1)
- condMeets = player->HasSpell(mConditionValue1);
- else
- condMeets = !player->HasSpell(mConditionValue1);
+ case CONDITION_TYPE_MASK:
+ {
+ condMeets = object->isType(ConditionValue1);
break;
- case CONDITION_NOITEM:
- condMeets = !player->HasItemCount(mConditionValue1, 1, mConditionValue2 ? true : false);
+ }
+ case CONDITION_RELATION_TO:
+ {
+ if (WorldObject* toObject = sourceInfo.mConditionTargets[ConditionValue1])
+ {
+ Unit* toUnit = toObject->ToUnit();
+ Unit* unit = object->ToUnit();
+ if (toUnit && unit)
+ {
+ switch (ConditionValue2)
+ {
+ case RELATION_SELF:
+ condMeets = unit == toUnit;
+ break;
+ case RELATION_IN_PARTY:
+ condMeets = unit->IsInPartyWith(toUnit);
+ break;
+ case RELATION_IN_RAID_OR_PARTY:
+ condMeets = unit->IsInRaidWith(toUnit);
+ break;
+ case RELATION_OWNED_BY:
+ condMeets = unit->GetOwnerGUID() == toUnit->GetGUID();
+ break;
+ case RELATION_PASSENGER_OF:
+ condMeets = unit->IsOnVehicle(toUnit);
+ break;
+ }
+ }
+ }
break;
- case CONDITION_LEVEL:
+ }
+ case CONDITION_REACTION_TO:
{
- switch (mConditionValue2)
+ if (WorldObject* toObject = sourceInfo.mConditionTargets[ConditionValue1])
{
- case LVL_COND_EQ:
- condMeets = player->getLevel() == mConditionValue1;
- break;
- case LVL_COND_HIGH:
- condMeets = player->getLevel() > mConditionValue1;
- break;
- case LVL_COND_LOW:
- condMeets = player->getLevel() < mConditionValue1;
- break;
- case LVL_COND_HIGH_EQ:
- condMeets = player->getLevel() >= mConditionValue1;
- break;
- case LVL_COND_LOW_EQ:
- condMeets = player->getLevel() <= mConditionValue1;
- break;
+ Unit* toUnit = toObject->ToUnit();
+ Unit* unit = object->ToUnit();
+ if (toUnit && unit)
+ condMeets = (1 << unit->GetReactionTo(toUnit)) & ConditionValue2;
}
break;
}
- case CONDITION_DRUNKENSTATE:
+ case CONDITION_DISTANCE_TO:
{
- condMeets = (uint32)Player::GetDrunkenstateByValue(player->GetDrunkValue()) >= mConditionValue1;
+ if (WorldObject* toObject = sourceInfo.mConditionTargets[ConditionValue1])
+ condMeets = CompareValues(static_cast<ComparisionType>(ConditionValue3), object->GetDistance(toObject), static_cast<float>(ConditionValue2));
break;
}
- case CONDITION_NEAR_CREATURE:
+ case CONDITION_ALIVE:
{
- condMeets = GetClosestCreatureWithEntry(player, mConditionValue1, (float)mConditionValue2) ? true : false;
+ if (Unit* unit = object->ToUnit())
+ condMeets = unit->isAlive();
break;
}
- case CONDITION_NEAR_GAMEOBJECT:
+ case CONDITION_HP_VAL:
+ {
+ if (Unit* unit = object->ToUnit())
+ condMeets = CompareValues(static_cast<ComparisionType>(ConditionValue2), unit->GetHealth(), static_cast<uint32>(ConditionValue1));
+ break;
+ }
+ case CONDITION_HP_PCT:
{
- condMeets = GetClosestGameObjectWithEntry(player, mConditionValue1, (float)mConditionValue2) ? true : false;
+ if (Unit* unit = object->ToUnit())
+ condMeets = CompareValues(static_cast<ComparisionType>(ConditionValue2), unit->GetHealthPct(), static_cast<float>(ConditionValue1));
+ break;
+ }
+ case CONDITION_WORLD_STATE:
+ {
+ condMeets = ConditionValue2 == sWorld->getWorldState(ConditionValue1);
+ break;
+ }
+ case CONDITION_PHASEMASK:
+ {
+ condMeets = object->GetPhaseMask() & ConditionValue1;
break;
}
default:
condMeets = false;
- refId = 0;
break;
}
- switch (mSourceType)
+
+ if (NegativeCondition)
+ condMeets = !condMeets;
+
+ if (!condMeets)
+ sourceInfo.mLastFailedCondition = this;
+
+ bool script = sScriptMgr->OnConditionCheck(this, sourceInfo); // Returns true by default.
+ return condMeets && script;
+}
+
+uint32 Condition::GetSearcherTypeMaskForCondition()
+{
+ // build mask of types for which condition can return true
+ // this is used for speeding up gridsearches
+ if (NegativeCondition)
+ return (GRID_MAP_TYPE_MASK_ALL);
+ uint32 mask = 0;
+ switch (ConditionType)
{
- case CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET:
- case CONDITION_SOURCE_TYPE_SPELL:
- sendErrorMsg = true;
+ case CONDITION_NONE:
+ mask |= GRID_MAP_TYPE_MASK_ALL;
+ break;
+ case CONDITION_AURA:
+ mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_ITEM:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_ITEM_EQUIPPED:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_ZONEID:
+ mask |= GRID_MAP_TYPE_MASK_ALL;
+ break;
+ case CONDITION_REPUTATION_RANK:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_ACHIEVEMENT:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_TEAM:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_CLASS:
+ mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_RACE:
+ mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_SKILL:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_QUESTREWARDED:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_QUESTTAKEN:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_QUEST_COMPLETE:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_QUEST_NONE:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_ACTIVE_EVENT:
+ mask |= GRID_MAP_TYPE_MASK_ALL;
+ break;
+ case CONDITION_INSTANCE_DATA:
+ mask |= GRID_MAP_TYPE_MASK_ALL;
+ break;
+ case CONDITION_MAPID:
+ mask |= GRID_MAP_TYPE_MASK_ALL;
+ break;
+ case CONDITION_AREAID:
+ mask |= GRID_MAP_TYPE_MASK_ALL;
+ break;
+ case CONDITION_SPELL:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_LEVEL:
+ mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_DRUNKENSTATE:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_NEAR_CREATURE:
+ mask |= GRID_MAP_TYPE_MASK_ALL;
+ break;
+ case CONDITION_NEAR_GAMEOBJECT:
+ mask |= GRID_MAP_TYPE_MASK_ALL;
+ break;
+ case CONDITION_OBJECT_ENTRY:
+ switch (ConditionValue1)
+ {
+ case TYPEID_UNIT:
+ mask |= GRID_MAP_TYPE_MASK_CREATURE;
+ break;
+ case TYPEID_PLAYER:
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case TYPEID_GAMEOBJECT:
+ mask |= GRID_MAP_TYPE_MASK_GAMEOBJECT;
+ break;
+ case TYPEID_CORPSE:
+ mask |= GRID_MAP_TYPE_MASK_CORPSE;
+ break;
+ default:
+ break;
+ }
+ case CONDITION_TYPE_MASK:
+ if (ConditionValue1 & TYPEMASK_UNIT)
+ mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
+ if (ConditionValue1 & TYPEMASK_PLAYER)
+ mask |= GRID_MAP_TYPE_MASK_PLAYER;
+ if (ConditionValue1 & TYPEMASK_GAMEOBJECT)
+ mask |= GRID_MAP_TYPE_MASK_GAMEOBJECT;
+ if (ConditionValue1 & TYPEMASK_CORPSE)
+ mask |= GRID_MAP_TYPE_MASK_CORPSE;
+ break;
+ case CONDITION_RELATION_TO:
+ mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_REACTION_TO:
+ mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_DISTANCE_TO:
+ mask |= GRID_MAP_TYPE_MASK_ALL;
+ break;
+ case CONDITION_ALIVE:
+ mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_HP_VAL:
+ mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_HP_PCT:
+ mask |= GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER;
+ break;
+ case CONDITION_WORLD_STATE:
+ mask |= GRID_MAP_TYPE_MASK_ALL;
+ break;
+ case CONDITION_PHASEMASK:
+ mask |= GRID_MAP_TYPE_MASK_ALL;
break;
default:
+ ASSERT(false && "Condition::GetSearcherTypeMaskForCondition - missing condition handling!");
break;
}
+ return mask;
+}
- bool refMeets = false;
- if (condMeets && refId)//only have to check references if 'this' is met
+uint32 Condition::GetMaxAvailableConditionTargets()
+{
+ // returns number of targets which are available for given source type
+ switch(SourceType)
{
- ConditionList ref = sConditionMgr->GetConditionReferences(refId);
- refMeets = sConditionMgr->IsPlayerMeetToConditions(player, ref);
+ case CONDITION_SOURCE_TYPE_SPELL:
+ case CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET:
+ case CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE:
+ case CONDITION_SOURCE_TYPE_VEHICLE_SPELL:
+ case CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT:
+ case CONDITION_SOURCE_TYPE_GOSSIP_MENU:
+ case CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION:
+ case CONDITION_SOURCE_TYPE_SMART_EVENT:
+ return 2;
+ default:
+ return 1;
}
- else
- refMeets = true;
-
- if (sendErrorMsg && ErrorTextd && (!condMeets || !refMeets))//send special error from DB
- player->m_ConditionErrorMsgId = ErrorTextd;
-
- bool script = sScriptMgr->OnConditionCheck(this, player, invoker); // Returns true by default.
- return condMeets && refMeets && script;
}
ConditionMgr::ConditionMgr()
@@ -249,39 +466,80 @@ ConditionList ConditionMgr::GetConditionReferences(uint32 refId)
return conditions;
}
-bool ConditionMgr::IsPlayerMeetToConditionList(Player* player, ConditionList const& conditions, Unit* invoker /*= NULL*/)
+uint32 ConditionMgr::GetSearcherTypeMaskForConditionList(ConditionList const& conditions)
+{
+ if (conditions.empty())
+ return GRID_MAP_TYPE_MASK_ALL;
+ // groupId, typeMask
+ std::map<uint32, uint32> ElseGroupStore;
+ for (ConditionList::const_iterator i = conditions.begin(); i != conditions.end(); ++i)
+ {
+ // no point of having not loaded conditions in list
+ ASSERT((*i)->isLoaded() && "ConditionMgr::GetSearcherTypeMaskForConditionList - not yet loaded condition found in list");
+ std::map<uint32, uint32>::const_iterator itr = ElseGroupStore.find((*i)->ElseGroup);
+ // group not filled yet, fill with widest mask possible
+ if (itr == ElseGroupStore.end())
+ ElseGroupStore[(*i)->ElseGroup] = GRID_MAP_TYPE_MASK_ALL;
+ // no point of checking anymore, empty mask
+ else if (!(*itr).second)
+ continue;
+
+ if ((*i)->ReferenceId) // handle reference
+ {
+ ConditionReferenceContainer::const_iterator ref = ConditionReferenceStore.find((*i)->ReferenceId);
+ ASSERT(ref != ConditionReferenceStore.end() && "ConditionMgr::GetSearcherTypeMaskForConditionList - incorrect reference");
+ ElseGroupStore[(*i)->ElseGroup] &= GetSearcherTypeMaskForConditionList((*ref).second);
+ }
+ else // handle normal condition
+ {
+ // object will match conditions in one ElseGroupStore only when it matches all of them
+ // so, let's find a smallest possible mask which satisfies all conditions
+ ElseGroupStore[(*i)->ElseGroup] &= (*i)->GetSearcherTypeMaskForCondition();
+ }
+ }
+ // object will match condition when one of the checks in ElseGroupStore is matching
+ // so, let's include all possible masks
+ uint32 mask = 0;
+ for (std::map<uint32, uint32>::const_iterator i = ElseGroupStore.begin(); i != ElseGroupStore.end(); ++i)
+ mask |= i->second;
+
+ return mask;
+}
+
+bool ConditionMgr::IsObjectMeetToConditionList(ConditionSourceInfo& sourceInfo, ConditionList const& conditions)
{
+ // groupId, groupCheckPassed
std::map<uint32, bool> ElseGroupStore;
for (ConditionList::const_iterator i = conditions.begin(); i != conditions.end(); ++i)
{
- sLog->outDebug(LOG_FILTER_CONDITIONSYS, "ConditionMgr::IsPlayerMeetToConditionList condType: %u val1: %u", (*i)->mConditionType, (*i)->mConditionValue1);
+ sLog->outDebug(LOG_FILTER_CONDITIONSYS, "ConditionMgr::IsPlayerMeetToConditionList condType: %u val1: %u", (*i)->ConditionType, (*i)->ConditionValue1);
if ((*i)->isLoaded())
{
- std::map<uint32, bool>::const_iterator itr = ElseGroupStore.find((*i)->mElseGroup);
+ std::map<uint32, bool>::const_iterator itr = ElseGroupStore.find((*i)->ElseGroup);
if (itr == ElseGroupStore.end())
- ElseGroupStore[(*i)->mElseGroup] = true;
+ ElseGroupStore[(*i)->ElseGroup] = true;
else if (!(*itr).second)
continue;
- if ((*i)->mReferenceId)//handle reference
+ if ((*i)->ReferenceId)//handle reference
{
- ConditionReferenceContainer::const_iterator ref = ConditionReferenceStore.find((*i)->mReferenceId);
+ ConditionReferenceContainer::const_iterator ref = ConditionReferenceStore.find((*i)->ReferenceId);
if (ref != ConditionReferenceStore.end())
{
- if (!IsPlayerMeetToConditionList(player, (*ref).second, invoker))
- ElseGroupStore[(*i)->mElseGroup] = false;
+ if (!IsObjectMeetToConditionList(sourceInfo, (*ref).second))
+ ElseGroupStore[(*i)->ElseGroup] = false;
}
else
{
sLog->outDebug(LOG_FILTER_CONDITIONSYS, "IsPlayerMeetToConditionList: Reference template -%u not found",
- (*i)->mReferenceId);//checked at loading, should never happen
+ (*i)->ReferenceId);//checked at loading, should never happen
}
}
else //handle normal condition
{
- if (!(*i)->Meets(player, invoker))
- ElseGroupStore[(*i)->mElseGroup] = false;
+ if (!(*i)->Meets(sourceInfo))
+ ElseGroupStore[(*i)->ElseGroup] = false;
}
}
}
@@ -292,21 +550,52 @@ bool ConditionMgr::IsPlayerMeetToConditionList(Player* player, ConditionList con
return false;
}
-bool ConditionMgr::IsPlayerMeetToConditions(Player* player, ConditionList const& conditions, Unit* invoker /*= NULL*/)
+bool ConditionMgr::IsObjectMeetToConditions(WorldObject* object, ConditionList const& conditions)
+{
+ ConditionSourceInfo srcInfo = ConditionSourceInfo(object);
+ return IsObjectMeetToConditions(srcInfo, conditions);
+}
+
+bool ConditionMgr::IsObjectMeetToConditions(WorldObject* object1, WorldObject* object2, ConditionList const& conditions)
+{
+ ConditionSourceInfo srcInfo = ConditionSourceInfo(object1, object2);
+ return IsObjectMeetToConditions(srcInfo, conditions);
+}
+
+bool ConditionMgr::IsObjectMeetToConditions(ConditionSourceInfo& sourceInfo, ConditionList const& conditions)
{
if (conditions.empty())
return true;
- if (player)
- player->m_ConditionErrorMsgId = 0;
-
- sLog->outDebug(LOG_FILTER_CONDITIONSYS, "ConditionMgr::IsPlayerMeetToConditions");
- bool result = IsPlayerMeetToConditionList(player, conditions, invoker);
+ sLog->outDebug(LOG_FILTER_CONDITIONSYS, "ConditionMgr::IsObjectMeetToConditions");
+ return IsObjectMeetToConditionList(sourceInfo, conditions);
+}
- if (player && player->m_ConditionErrorMsgId && player->GetSession() && !result)
- player->GetSession()->SendNotification(player->m_ConditionErrorMsgId); //m_ConditionErrorMsgId is set only if a condition was not met
+bool ConditionMgr::CanHaveSourceGroupSet(ConditionSourceType sourceType) const
+{
+ return (sourceType == CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_DISENCHANT_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_FISHING_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_GAMEOBJECT_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_ITEM_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_MAIL_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_MILLING_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_PICKPOCKETING_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_PROSPECTING_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE ||
+ sourceType == CONDITION_SOURCE_TYPE_GOSSIP_MENU ||
+ sourceType == CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION ||
+ sourceType == CONDITION_SOURCE_TYPE_VEHICLE_SPELL ||
+ sourceType == CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET ||
+ sourceType == CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT ||
+ sourceType == CONDITION_SOURCE_TYPE_SMART_EVENT);
+}
- return result;
+bool ConditionMgr::CanHaveSourceIdSet(ConditionSourceType sourceType) const
+{
+ return (sourceType == CONDITION_SOURCE_TYPE_SMART_EVENT);
}
ConditionList ConditionMgr::GetConditionsForNotGroupedEntry(ConditionSourceType sourceType, uint32 entry)
@@ -328,33 +617,50 @@ ConditionList ConditionMgr::GetConditionsForNotGroupedEntry(ConditionSourceType
return spellCond;
}
-ConditionList ConditionMgr::GetConditionsForVehicleSpell(uint32 creatureID, uint32 spellID)
+
+ConditionList ConditionMgr::GetConditionsForSpellClickEvent(uint32 creatureId, uint32 spellId)
{
ConditionList cond;
- VehicleSpellConditionContainer::const_iterator itr = VehicleSpellConditionStore.find(creatureID);
+ CreatureSpellConditionContainer::const_iterator itr = SpellClickEventConditionStore.find(creatureId);
+ if (itr != SpellClickEventConditionStore.end())
+ {
+ ConditionTypeContainer::const_iterator i = (*itr).second.find(spellId);
+ if (i != (*itr).second.end())
+ {
+ cond = (*i).second;
+ sLog->outDebug(LOG_FILTER_CONDITIONSYS, "GetConditionsForSpellClickEvent: found conditions for Vehicle entry %u spell %u", creatureId, spellId);
+ }
+ }
+ return cond;
+}
+
+ConditionList ConditionMgr::GetConditionsForVehicleSpell(uint32 creatureId, uint32 spellId)
+{
+ ConditionList cond;
+ CreatureSpellConditionContainer::const_iterator itr = VehicleSpellConditionStore.find(creatureId);
if (itr != VehicleSpellConditionStore.end())
{
- ConditionTypeContainer::const_iterator i = (*itr).second.find(spellID);
+ ConditionTypeContainer::const_iterator i = (*itr).second.find(spellId);
if (i != (*itr).second.end())
{
cond = (*i).second;
- sLog->outDebug(LOG_FILTER_CONDITIONSYS, "GetConditionsForVehicleSpell: found conditions for Vehicle entry %u spell %u", creatureID, spellID);
+ sLog->outDebug(LOG_FILTER_CONDITIONSYS, "GetConditionsForVehicleSpell: found conditions for Vehicle entry %u spell %u", creatureId, spellId);
}
}
return cond;
}
-ConditionList ConditionMgr::GetConditionsForSmartEvent(uint32 entry, uint32 eventId, uint32 sourceType)
+ConditionList ConditionMgr::GetConditionsForSmartEvent(int32 entryOrGuid, uint32 eventId, uint32 sourceType)
{
ConditionList cond;
- SmartEventConditionContainer::const_iterator itr = SmartEventConditionStore.find(std::make_pair(entry, sourceType));
+ SmartEventConditionContainer::const_iterator itr = SmartEventConditionStore.find(std::make_pair(entryOrGuid, sourceType));
if (itr != SmartEventConditionStore.end())
{
ConditionTypeContainer::const_iterator i = (*itr).second.find(eventId + 1);
if (i != (*itr).second.end())
{
cond = (*i).second;
- sLog->outDebug(LOG_FILTER_CONDITIONSYS, "GetConditionsForSmartEvent: found conditions for Smart Event entry %u event_id %u", entry, eventId);
+ sLog->outDebug(LOG_FILTER_CONDITIONSYS, "GetConditionsForSmartEvent: found conditions for Smart Event entry or guid %d event_id %u", entryOrGuid, eventId);
}
}
return cond;
@@ -388,10 +694,11 @@ void ConditionMgr::LoadConditions(bool isReload)
sLog->outString("Re-Loading `gossip_menu_option` Table for Conditions!");
sObjectMgr->LoadGossipMenuItems();
+ sSpellMgr->UnloadSpellInfoImplicitTargetConditionLists();
}
- QueryResult result = WorldDatabase.Query("SELECT SourceTypeOrReferenceId, SourceGroup, SourceEntry, SourceId, ElseGroup, ConditionTypeOrReference, "
- " ConditionValue1, ConditionValue2, ConditionValue3, ErrorTextId, ScriptName FROM conditions");
+ QueryResult result = WorldDatabase.Query("SELECT SourceTypeOrReferenceId, SourceGroup, SourceEntry, SourceId, ElseGroup, ConditionTypeOrReference, ConditionTarget, "
+ " ConditionValue1, ConditionValue2, ConditionValue3, NegativeCondition, ErrorTextId, ScriptName FROM conditions");
if (!result)
{
@@ -409,19 +716,24 @@ void ConditionMgr::LoadConditions(bool isReload)
Condition* cond = new Condition();
int32 iSourceTypeOrReferenceId = fields[0].GetInt32();
- cond->mSourceGroup = fields[1].GetUInt32();
- cond->mSourceEntry = fields[2].GetUInt32();
- cond->mSourceId = fields[3].GetUInt32();
- cond->mElseGroup = fields[4].GetUInt32();
+ cond->SourceGroup = fields[1].GetUInt32();
+ cond->SourceEntry = fields[2].GetInt32();
+ cond->SourceId = fields[3].GetUInt32();
+ cond->ElseGroup = fields[4].GetUInt32();
int32 iConditionTypeOrReference = fields[5].GetInt32();
- cond->mConditionValue1 = fields[6].GetUInt32();
- cond->mConditionValue2 = fields[7].GetUInt32();
- cond->mConditionValue3 = fields[8].GetUInt32();
- cond->ErrorTextd = fields[9].GetUInt32();
- cond->mScriptId = sObjectMgr->GetScriptId(fields[10].GetCString());
+ cond->ConditionTarget = fields[6].GetUInt8();
+ cond->ConditionValue1 = fields[7].GetUInt32();
+ cond->ConditionValue2 = fields[8].GetUInt32();
+ cond->ConditionValue3 = fields[9].GetUInt32();
+ cond->NegativeCondition = fields[10].GetUInt8();
+ cond->ErrorTextId = fields[11].GetUInt32();
+ cond->ScriptId = sObjectMgr->GetScriptId(fields[12].GetCString());
if (iConditionTypeOrReference >= 0)
- cond->mConditionType = ConditionType(iConditionTypeOrReference);
+ cond->ConditionType = ConditionTypes(iConditionTypeOrReference);
+
+ if (iSourceTypeOrReferenceId >= 0)
+ cond->SourceType = ConditionSourceType(iSourceTypeOrReferenceId);
if (iConditionTypeOrReference < 0)//it has a reference
{
@@ -431,22 +743,26 @@ void ConditionMgr::LoadConditions(bool isReload)
delete cond;
continue;
}
- cond->mReferenceId = uint32(abs(iConditionTypeOrReference));
+ cond->ReferenceId = uint32(abs(iConditionTypeOrReference));
const char* rowType = "reference template";
if (iSourceTypeOrReferenceId >= 0)
rowType = "reference";
//check for useless data
- if (cond->mConditionValue1)
- sLog->outErrorDb("Condition %s %i has useless data in value1 (%u)!", rowType, iSourceTypeOrReferenceId, cond->mConditionValue1);
- if (cond->mConditionValue2)
- sLog->outErrorDb("Condition %s %i has useless data in value2 (%u)!", rowType, iSourceTypeOrReferenceId, cond->mConditionValue2);
- if (cond->mConditionValue3)
- sLog->outErrorDb("Condition %s %i has useless data in value3 (%u)!", rowType, iSourceTypeOrReferenceId, cond->mConditionValue3);
- if (cond->mSourceGroup && iSourceTypeOrReferenceId < 0)
- sLog->outErrorDb("Condition %s %i has useless data in SourceGroup (%u)!", rowType, iSourceTypeOrReferenceId, cond->mSourceGroup);
- if (cond->mSourceEntry && iSourceTypeOrReferenceId < 0)
- sLog->outErrorDb("Condition %s %i has useless data in SourceEntry (%u)!", rowType, iSourceTypeOrReferenceId, cond->mSourceEntry);
+ if (cond->ConditionTarget)
+ sLog->outErrorDb("Condition %s %i has useless data in ConditionTarget (%u)!", rowType, iSourceTypeOrReferenceId, cond->ConditionTarget);
+ if (cond->ConditionValue1)
+ sLog->outErrorDb("Condition %s %i has useless data in value1 (%u)!", rowType, iSourceTypeOrReferenceId, cond->ConditionValue1);
+ if (cond->ConditionValue2)
+ sLog->outErrorDb("Condition %s %i has useless data in value2 (%u)!", rowType, iSourceTypeOrReferenceId, cond->ConditionValue2);
+ if (cond->ConditionValue3)
+ sLog->outErrorDb("Condition %s %i has useless data in value3 (%u)!", rowType, iSourceTypeOrReferenceId, cond->ConditionValue3);
+ if (cond->NegativeCondition)
+ sLog->outErrorDb("Condition %s %i has useless data in NegativeCondition (%u)!", rowType, iSourceTypeOrReferenceId, cond->NegativeCondition);
+ if (cond->SourceGroup && iSourceTypeOrReferenceId < 0)
+ sLog->outErrorDb("Condition %s %i has useless data in SourceGroup (%u)!", rowType, iSourceTypeOrReferenceId, cond->SourceGroup);
+ if (cond->SourceEntry && iSourceTypeOrReferenceId < 0)
+ sLog->outErrorDb("Condition %s %i has useless data in SourceEntry (%u)!", rowType, iSourceTypeOrReferenceId, cond->SourceEntry);
}
else if (!isConditionTypeValid(cond))//doesn't have reference, validate ConditionType
{
@@ -467,8 +783,6 @@ void ConditionMgr::LoadConditions(bool isReload)
continue;
}//end of reference templates
- cond->mSourceType = ConditionSourceType(iSourceTypeOrReferenceId);
-
//if not a reference and SourceType is invalid, skip
if (iConditionTypeOrReference >= 0 && !isSourceTypeValid(cond))
{
@@ -477,53 +791,60 @@ void ConditionMgr::LoadConditions(bool isReload)
}
//Grouping is only allowed for some types (loot templates, gossip menus, gossip items)
- if (cond->mSourceGroup && !isGroupable(cond->mSourceType))
+ if (cond->SourceGroup && !CanHaveSourceGroupSet(cond->SourceType))
{
- sLog->outErrorDb("Condition type %u has not allowed grouping %u!", uint32(cond->mSourceType), cond->mSourceGroup);
+ sLog->outErrorDb("Condition type %u has not allowed value of SourceGroup = %u!", uint32(cond->SourceType), cond->SourceGroup);
delete cond;
continue;
}
- else if (cond->mSourceGroup)
+ if (cond->SourceId && !CanHaveSourceIdSet(cond->SourceType))
+ {
+ sLog->outErrorDb("Condition type %u has not allowed value of SourceId = %u!", uint32(cond->SourceType), cond->SourceId);
+ delete cond;
+ continue;
+ }
+
+ if (cond->SourceGroup)
{
bool valid = false;
- //handle grouped conditions
- switch (cond->mSourceType)
+ // handle grouped conditions
+ switch (cond->SourceType)
{
case CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE:
- valid = addToLootTemplate(cond, LootTemplates_Creature.GetLootForConditionFill(cond->mSourceGroup));
+ valid = addToLootTemplate(cond, LootTemplates_Creature.GetLootForConditionFill(cond->SourceGroup));
break;
case CONDITION_SOURCE_TYPE_DISENCHANT_LOOT_TEMPLATE:
- valid = addToLootTemplate(cond, LootTemplates_Disenchant.GetLootForConditionFill(cond->mSourceGroup));
+ valid = addToLootTemplate(cond, LootTemplates_Disenchant.GetLootForConditionFill(cond->SourceGroup));
break;
case CONDITION_SOURCE_TYPE_FISHING_LOOT_TEMPLATE:
- valid = addToLootTemplate(cond, LootTemplates_Fishing.GetLootForConditionFill(cond->mSourceGroup));
+ valid = addToLootTemplate(cond, LootTemplates_Fishing.GetLootForConditionFill(cond->SourceGroup));
break;
case CONDITION_SOURCE_TYPE_GAMEOBJECT_LOOT_TEMPLATE:
- valid = addToLootTemplate(cond, LootTemplates_Gameobject.GetLootForConditionFill(cond->mSourceGroup));
+ valid = addToLootTemplate(cond, LootTemplates_Gameobject.GetLootForConditionFill(cond->SourceGroup));
break;
case CONDITION_SOURCE_TYPE_ITEM_LOOT_TEMPLATE:
- valid = addToLootTemplate(cond, LootTemplates_Item.GetLootForConditionFill(cond->mSourceGroup));
+ valid = addToLootTemplate(cond, LootTemplates_Item.GetLootForConditionFill(cond->SourceGroup));
break;
case CONDITION_SOURCE_TYPE_MAIL_LOOT_TEMPLATE:
- valid = addToLootTemplate(cond, LootTemplates_Mail.GetLootForConditionFill(cond->mSourceGroup));
+ valid = addToLootTemplate(cond, LootTemplates_Mail.GetLootForConditionFill(cond->SourceGroup));
break;
case CONDITION_SOURCE_TYPE_MILLING_LOOT_TEMPLATE:
- valid = addToLootTemplate(cond, LootTemplates_Milling.GetLootForConditionFill(cond->mSourceGroup));
+ valid = addToLootTemplate(cond, LootTemplates_Milling.GetLootForConditionFill(cond->SourceGroup));
break;
case CONDITION_SOURCE_TYPE_PICKPOCKETING_LOOT_TEMPLATE:
- valid = addToLootTemplate(cond, LootTemplates_Pickpocketing.GetLootForConditionFill(cond->mSourceGroup));
+ valid = addToLootTemplate(cond, LootTemplates_Pickpocketing.GetLootForConditionFill(cond->SourceGroup));
break;
case CONDITION_SOURCE_TYPE_PROSPECTING_LOOT_TEMPLATE:
- valid = addToLootTemplate(cond, LootTemplates_Prospecting.GetLootForConditionFill(cond->mSourceGroup));
+ valid = addToLootTemplate(cond, LootTemplates_Prospecting.GetLootForConditionFill(cond->SourceGroup));
break;
case CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE:
- valid = addToLootTemplate(cond, LootTemplates_Reference.GetLootForConditionFill(cond->mSourceGroup));
+ valid = addToLootTemplate(cond, LootTemplates_Reference.GetLootForConditionFill(cond->SourceGroup));
break;
case CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE:
- valid = addToLootTemplate(cond, LootTemplates_Skinning.GetLootForConditionFill(cond->mSourceGroup));
+ valid = addToLootTemplate(cond, LootTemplates_Skinning.GetLootForConditionFill(cond->SourceGroup));
break;
case CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE:
- valid = addToLootTemplate(cond, LootTemplates_Spell.GetLootForConditionFill(cond->mSourceGroup));
+ valid = addToLootTemplate(cond, LootTemplates_Spell.GetLootForConditionFill(cond->SourceGroup));
break;
case CONDITION_SOURCE_TYPE_GOSSIP_MENU:
valid = addToGossipMenus(cond);
@@ -531,21 +852,44 @@ void ConditionMgr::LoadConditions(bool isReload)
case CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION:
valid = addToGossipMenuItems(cond);
break;
+ case CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT:
+ {
+ //if no list for npc create one
+ if (SpellClickEventConditionStore.find(cond->SourceGroup) == SpellClickEventConditionStore.end())
+ {
+ ConditionTypeContainer cmap;
+ SpellClickEventConditionStore[cond->SourceGroup] = cmap;
+ }
+ //if no list for spellclick spell create one
+ if (SpellClickEventConditionStore[cond->SourceGroup].find(cond->SourceEntry) == SpellClickEventConditionStore[cond->SourceGroup].end())
+ {
+ ConditionList clist;
+ SpellClickEventConditionStore[cond->SourceGroup][cond->SourceEntry] = clist;
+ }
+ SpellClickEventConditionStore[cond->SourceGroup][cond->SourceEntry].push_back(cond);
+ valid = true;
+ ++count;
+ continue; // do not add to m_AllocatedMemory to avoid double deleting
+ break;
+ }
+ case CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET:
+ valid = addToSpellImplicitTargetConditions(cond);
+ break;
case CONDITION_SOURCE_TYPE_VEHICLE_SPELL:
{
//if no list for vehicle create one
- if (VehicleSpellConditionStore.find(cond->mSourceGroup) == VehicleSpellConditionStore.end())
+ if (VehicleSpellConditionStore.find(cond->SourceGroup) == VehicleSpellConditionStore.end())
{
ConditionTypeContainer cmap;
- VehicleSpellConditionStore[cond->mSourceGroup] = cmap;
+ VehicleSpellConditionStore[cond->SourceGroup] = cmap;
}
//if no list for vehicle's spell create one
- if (VehicleSpellConditionStore[cond->mSourceGroup].find(cond->mSourceEntry) == VehicleSpellConditionStore[cond->mSourceGroup].end())
+ if (VehicleSpellConditionStore[cond->SourceGroup].find(cond->SourceEntry) == VehicleSpellConditionStore[cond->SourceGroup].end())
{
ConditionList clist;
- VehicleSpellConditionStore[cond->mSourceGroup][cond->mSourceEntry] = clist;
+ VehicleSpellConditionStore[cond->SourceGroup][cond->SourceEntry] = clist;
}
- VehicleSpellConditionStore[cond->mSourceGroup][cond->mSourceEntry].push_back(cond);
+ VehicleSpellConditionStore[cond->SourceGroup][cond->SourceEntry].push_back(cond);
valid = true;
++count;
continue; // do not add to m_AllocatedMemory to avoid double deleting
@@ -553,18 +897,18 @@ void ConditionMgr::LoadConditions(bool isReload)
case CONDITION_SOURCE_TYPE_SMART_EVENT:
{
// If the entry does not exist, create a new list
- std::pair<uint32, uint32> key = std::make_pair(cond->mSourceEntry, cond->mSourceId);
+ std::pair<int32, uint32> key = std::make_pair(cond->SourceEntry, cond->SourceId);
if (SmartEventConditionStore.find(key) == SmartEventConditionStore.end())
{
ConditionTypeContainer cmap;
SmartEventConditionStore[key] = cmap;
}
- if (SmartEventConditionStore[key].find(cond->mSourceGroup) == SmartEventConditionStore[key].end())
+ if (SmartEventConditionStore[key].find(cond->SourceGroup) == SmartEventConditionStore[key].end())
{
ConditionList clist;
- SmartEventConditionStore[key][cond->mSourceGroup] = clist;
+ SmartEventConditionStore[key][cond->SourceGroup] = clist;
}
- SmartEventConditionStore[key][cond->mSourceGroup].push_back(cond);
+ SmartEventConditionStore[key][cond->SourceGroup].push_back(cond);
valid = true;
++count;
continue;
@@ -575,7 +919,7 @@ void ConditionMgr::LoadConditions(bool isReload)
if (!valid)
{
- sLog->outErrorDb("Not handled grouped condition, SourceGroup %u", cond->mSourceGroup);
+ sLog->outErrorDb("Not handled grouped condition, SourceGroup %u", cond->SourceGroup);
delete cond;
}
else
@@ -588,21 +932,21 @@ void ConditionMgr::LoadConditions(bool isReload)
//handle not grouped conditions
//make sure we have a storage list for our SourceType
- if (ConditionStore.find(cond->mSourceType) == ConditionStore.end())
+ if (ConditionStore.find(cond->SourceType) == ConditionStore.end())
{
ConditionTypeContainer mTypeMap;
- ConditionStore[cond->mSourceType] = mTypeMap;//add new empty list for SourceType
+ ConditionStore[cond->SourceType] = mTypeMap;//add new empty list for SourceType
}
//make sure we have a condition list for our SourceType's entry
- if (ConditionStore[cond->mSourceType].find(cond->mSourceEntry) == ConditionStore[cond->mSourceType].end())
+ if (ConditionStore[cond->SourceType].find(cond->SourceEntry) == ConditionStore[cond->SourceType].end())
{
ConditionList mCondList;
- ConditionStore[cond->mSourceType][cond->mSourceEntry] = mCondList;
+ ConditionStore[cond->SourceType][cond->SourceEntry] = mCondList;
}
//add new Condition to storage based on Type/Entry
- ConditionStore[cond->mSourceType][cond->mSourceEntry].push_back(cond);
+ ConditionStore[cond->SourceType][cond->SourceEntry].push_back(cond);
++count;
}
while (result->NextRow());
@@ -615,26 +959,26 @@ bool ConditionMgr::addToLootTemplate(Condition* cond, LootTemplate* loot)
{
if (!loot)
{
- sLog->outErrorDb("ConditionMgr: LootTemplate %u not found", cond->mSourceGroup);
+ sLog->outErrorDb("ConditionMgr: LootTemplate %u not found", cond->SourceGroup);
return false;
}
if (loot->addConditionItem(cond))
return true;
- sLog->outErrorDb("ConditionMgr: Item %u not found in LootTemplate %u", cond->mSourceEntry, cond->mSourceGroup);
+ sLog->outErrorDb("ConditionMgr: Item %u not found in LootTemplate %u", cond->SourceEntry, cond->SourceGroup);
return false;
}
bool ConditionMgr::addToGossipMenus(Condition* cond)
{
- GossipMenusMapBoundsNonConst pMenuBounds = sObjectMgr->GetGossipMenusMapBoundsNonConst(cond->mSourceGroup);
+ GossipMenusMapBoundsNonConst pMenuBounds = sObjectMgr->GetGossipMenusMapBoundsNonConst(cond->SourceGroup);
if (pMenuBounds.first != pMenuBounds.second)
{
- for (GossipMenusMap::iterator itr = pMenuBounds.first; itr != pMenuBounds.second; ++itr)
+ for (GossipMenusContainer::iterator itr = pMenuBounds.first; itr != pMenuBounds.second; ++itr)
{
- if ((*itr).second.entry == cond->mSourceGroup && (*itr).second.text_id == cond->mSourceEntry)
+ if ((*itr).second.entry == cond->SourceGroup && (*itr).second.text_id == uint32(cond->SourceEntry))
{
(*itr).second.conditions.push_back(cond);
return true;
@@ -642,18 +986,18 @@ bool ConditionMgr::addToGossipMenus(Condition* cond)
}
}
- sLog->outErrorDb("addToGossipMenus: GossipMenu %u not found", cond->mSourceGroup);
+ sLog->outErrorDb("addToGossipMenus: GossipMenu %u not found", cond->SourceGroup);
return false;
}
bool ConditionMgr::addToGossipMenuItems(Condition* cond)
{
- GossipMenuItemsMapBoundsNonConst pMenuItemBounds = sObjectMgr->GetGossipMenuItemsMapBoundsNonConst(cond->mSourceGroup);
+ GossipMenuItemsMapBoundsNonConst pMenuItemBounds = sObjectMgr->GetGossipMenuItemsMapBoundsNonConst(cond->SourceGroup);
if (pMenuItemBounds.first != pMenuItemBounds.second)
{
- for (GossipMenuItemsMap::iterator itr = pMenuItemBounds.first; itr != pMenuItemBounds.second; ++itr)
+ for (GossipMenuItemsContainer::iterator itr = pMenuItemBounds.first; itr != pMenuItemBounds.second; ++itr)
{
- if ((*itr).second.MenuId == cond->mSourceGroup && (*itr).second.OptionIndex == cond->mSourceEntry)
+ if ((*itr).second.MenuId == cond->SourceGroup && (*itr).second.OptionIndex == uint32(cond->SourceEntry))
{
(*itr).second.Conditions.push_back(cond);
return true;
@@ -661,380 +1005,402 @@ bool ConditionMgr::addToGossipMenuItems(Condition* cond)
}
}
- sLog->outErrorDb("addToGossipMenuItems: GossipMenuId %u Item %u not found", cond->mSourceGroup, cond->mSourceEntry);
+ sLog->outErrorDb("addToGossipMenuItems: GossipMenuId %u Item %u not found", cond->SourceGroup, cond->SourceEntry);
return false;
}
+bool ConditionMgr::addToSpellImplicitTargetConditions(Condition* cond)
+{
+ uint32 conditionEffMask = cond->SourceGroup;
+ SpellInfo* spellInfo = const_cast<SpellInfo*>(sSpellMgr->GetSpellInfo(cond->SourceEntry));
+ ASSERT(spellInfo);
+ std::list<uint32> sharedMasks;
+ for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ {
+ // check if effect is already a part of some shared mask
+ bool found = false;
+ for (std::list<uint32>::iterator itr = sharedMasks.begin(); itr != sharedMasks.end(); ++itr)
+ {
+ if ((1<<i) & *itr)
+ {
+ found = true;
+ break;
+ }
+ }
+ if (found)
+ continue;
+
+ // build new shared mask with found effect
+ uint32 sharedMask = (1<<i);
+ ConditionList* cmp = spellInfo->Effects[i].ImplicitTargetConditions;
+ for (uint8 effIndex = i+1; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
+ {
+ if (spellInfo->Effects[effIndex].ImplicitTargetConditions == cmp)
+ sharedMask |= 1<<effIndex;
+ }
+ sharedMasks.push_back(sharedMask);
+ }
+
+ for (std::list<uint32>::iterator itr = sharedMasks.begin(); itr != sharedMasks.end(); ++itr)
+ {
+ // some effect indexes should have same data
+ if (uint32 commonMask = *itr & conditionEffMask)
+ {
+ uint8 firstEffIndex = 0;
+ for (; firstEffIndex < MAX_SPELL_EFFECTS; ++firstEffIndex)
+ if ((1<<firstEffIndex) & *itr)
+ break;
+
+ // get shared data
+ ConditionList* sharedList = spellInfo->Effects[firstEffIndex].ImplicitTargetConditions;
+
+ // there's already data entry for that sharedMask
+ if (sharedList)
+ {
+ // we have overlapping masks in db
+ if (conditionEffMask != *itr)
+ {
+ sLog->outErrorDb("SourceEntry %u in `condition` table, has incorrect SourceGroup %u (spell effectMask) set - "
+ "effect masks are overlapping (all SourceGroup values having given bit set must be equal) - ignoring.", cond->SourceEntry, cond->SourceGroup);
+ return false;
+ }
+ }
+ // no data for shared mask, we can create new submask
+ else
+ {
+ // add new list, create new shared mask
+ sharedList = new ConditionList();
+ for (uint8 i = firstEffIndex; i < MAX_SPELL_EFFECTS; ++i)
+ if ((1<<i) & commonMask)
+ spellInfo->Effects[i].ImplicitTargetConditions = sharedList;
+ }
+ sharedList->push_back(cond);
+ break;
+ }
+ }
+ return true;
+}
+
bool ConditionMgr::isSourceTypeValid(Condition* cond)
{
- if (cond->mSourceType == CONDITION_SOURCE_TYPE_NONE || cond->mSourceType >= CONDITION_SOURCE_TYPE_MAX)
+ if (cond->SourceType == CONDITION_SOURCE_TYPE_NONE || cond->SourceType >= CONDITION_SOURCE_TYPE_MAX)
{
- sLog->outErrorDb("Invalid ConditionSourceType %u in `condition` table, ignoring.", uint32(cond->mSourceType));
+ sLog->outErrorDb("Invalid ConditionSourceType %u in `condition` table, ignoring.", uint32(cond->SourceType));
return false;
}
- switch (cond->mSourceType)
+ switch (cond->SourceType)
{
case CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE:
{
- if (!LootTemplates_Creature.HaveLootFor(cond->mSourceGroup))
+ if (!LootTemplates_Creature.HaveLootFor(cond->SourceGroup))
{
- sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `creature_loot_template`, ignoring.", cond->mSourceGroup);
+ sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `creature_loot_template`, ignoring.", cond->SourceGroup);
return false;
}
- LootTemplate* loot = LootTemplates_Creature.GetLootForConditionFill(cond->mSourceGroup);
- ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->mSourceEntry);
- if (!pItemProto && !loot->isReference(cond->mSourceEntry))
+ LootTemplate* loot = LootTemplates_Creature.GetLootForConditionFill(cond->SourceGroup);
+ ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
+ if (!pItemProto && !loot->isReference(cond->SourceEntry))
{
- sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry);
+ sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry);
return false;
}
break;
}
case CONDITION_SOURCE_TYPE_DISENCHANT_LOOT_TEMPLATE:
{
- if (!LootTemplates_Disenchant.HaveLootFor(cond->mSourceGroup))
+ if (!LootTemplates_Disenchant.HaveLootFor(cond->SourceGroup))
{
- sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `disenchant_loot_template`, ignoring.", cond->mSourceGroup);
+ sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `disenchant_loot_template`, ignoring.", cond->SourceGroup);
return false;
}
- LootTemplate* loot = LootTemplates_Disenchant.GetLootForConditionFill(cond->mSourceGroup);
- ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->mSourceEntry);
- if (!pItemProto && !loot->isReference(cond->mSourceEntry))
+ LootTemplate* loot = LootTemplates_Disenchant.GetLootForConditionFill(cond->SourceGroup);
+ ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
+ if (!pItemProto && !loot->isReference(cond->SourceEntry))
{
- sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry);
+ sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry);
return false;
}
break;
}
case CONDITION_SOURCE_TYPE_FISHING_LOOT_TEMPLATE:
{
- if (!LootTemplates_Fishing.HaveLootFor(cond->mSourceGroup))
+ if (!LootTemplates_Fishing.HaveLootFor(cond->SourceGroup))
{
- sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `fishing_loot_template`, ignoring.", cond->mSourceGroup);
+ sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `fishing_loot_template`, ignoring.", cond->SourceGroup);
return false;
}
- LootTemplate* loot = LootTemplates_Fishing.GetLootForConditionFill(cond->mSourceGroup);
- ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->mSourceEntry);
- if (!pItemProto && !loot->isReference(cond->mSourceEntry))
+ LootTemplate* loot = LootTemplates_Fishing.GetLootForConditionFill(cond->SourceGroup);
+ ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
+ if (!pItemProto && !loot->isReference(cond->SourceEntry))
{
- sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry);
+ sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry);
return false;
}
break;
}
case CONDITION_SOURCE_TYPE_GAMEOBJECT_LOOT_TEMPLATE:
{
- if (!LootTemplates_Gameobject.HaveLootFor(cond->mSourceGroup))
+ if (!LootTemplates_Gameobject.HaveLootFor(cond->SourceGroup))
{
- sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `gameobject_loot_template`, ignoring.", cond->mSourceGroup);
+ sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `gameobject_loot_template`, ignoring.", cond->SourceGroup);
return false;
}
- LootTemplate* loot = LootTemplates_Gameobject.GetLootForConditionFill(cond->mSourceGroup);
- ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->mSourceEntry);
- if (!pItemProto && !loot->isReference(cond->mSourceEntry))
+ LootTemplate* loot = LootTemplates_Gameobject.GetLootForConditionFill(cond->SourceGroup);
+ ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
+ if (!pItemProto && !loot->isReference(cond->SourceEntry))
{
- sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry);
+ sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry);
return false;
}
break;
}
case CONDITION_SOURCE_TYPE_ITEM_LOOT_TEMPLATE:
{
- if (!LootTemplates_Item.HaveLootFor(cond->mSourceGroup))
+ if (!LootTemplates_Item.HaveLootFor(cond->SourceGroup))
{
- sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `item_loot_template`, ignoring.", cond->mSourceGroup);
+ sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `item_loot_template`, ignoring.", cond->SourceGroup);
return false;
}
- LootTemplate* loot = LootTemplates_Item.GetLootForConditionFill(cond->mSourceGroup);
- ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->mSourceEntry);
- if (!pItemProto && !loot->isReference(cond->mSourceEntry))
+ LootTemplate* loot = LootTemplates_Item.GetLootForConditionFill(cond->SourceGroup);
+ ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
+ if (!pItemProto && !loot->isReference(cond->SourceEntry))
{
- sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry);
+ sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry);
return false;
}
break;
}
case CONDITION_SOURCE_TYPE_MAIL_LOOT_TEMPLATE:
{
- if (!LootTemplates_Mail.HaveLootFor(cond->mSourceGroup))
+ if (!LootTemplates_Mail.HaveLootFor(cond->SourceGroup))
{
- sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `mail_loot_template`, ignoring.", cond->mSourceGroup);
+ sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `mail_loot_template`, ignoring.", cond->SourceGroup);
return false;
}
- LootTemplate* loot = LootTemplates_Mail.GetLootForConditionFill(cond->mSourceGroup);
- ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->mSourceEntry);
- if (!pItemProto && !loot->isReference(cond->mSourceEntry))
+ LootTemplate* loot = LootTemplates_Mail.GetLootForConditionFill(cond->SourceGroup);
+ ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
+ if (!pItemProto && !loot->isReference(cond->SourceEntry))
{
- sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry);
+ sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry);
return false;
}
break;
}
case CONDITION_SOURCE_TYPE_MILLING_LOOT_TEMPLATE:
{
- if (!LootTemplates_Milling.HaveLootFor(cond->mSourceGroup))
+ if (!LootTemplates_Milling.HaveLootFor(cond->SourceGroup))
{
- sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `milling_loot_template`, ignoring.", cond->mSourceGroup);
+ sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `milling_loot_template`, ignoring.", cond->SourceGroup);
return false;
}
- LootTemplate* loot = LootTemplates_Milling.GetLootForConditionFill(cond->mSourceGroup);
- ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->mSourceEntry);
- if (!pItemProto && !loot->isReference(cond->mSourceEntry))
+ LootTemplate* loot = LootTemplates_Milling.GetLootForConditionFill(cond->SourceGroup);
+ ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
+ if (!pItemProto && !loot->isReference(cond->SourceEntry))
{
- sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry);
+ sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry);
return false;
}
break;
}
case CONDITION_SOURCE_TYPE_PICKPOCKETING_LOOT_TEMPLATE:
{
- if (!LootTemplates_Pickpocketing.HaveLootFor(cond->mSourceGroup))
+ if (!LootTemplates_Pickpocketing.HaveLootFor(cond->SourceGroup))
{
- sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `pickpocketing_loot_template`, ignoring.", cond->mSourceGroup);
+ sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `pickpocketing_loot_template`, ignoring.", cond->SourceGroup);
return false;
}
- LootTemplate* loot = LootTemplates_Pickpocketing.GetLootForConditionFill(cond->mSourceGroup);
- ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->mSourceEntry);
- if (!pItemProto && !loot->isReference(cond->mSourceEntry))
+ LootTemplate* loot = LootTemplates_Pickpocketing.GetLootForConditionFill(cond->SourceGroup);
+ ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
+ if (!pItemProto && !loot->isReference(cond->SourceEntry))
{
- sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry);
+ sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry);
return false;
}
break;
}
case CONDITION_SOURCE_TYPE_PROSPECTING_LOOT_TEMPLATE:
{
- if (!LootTemplates_Prospecting.HaveLootFor(cond->mSourceGroup))
+ if (!LootTemplates_Prospecting.HaveLootFor(cond->SourceGroup))
{
- sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `prospecting_loot_template`, ignoring.", cond->mSourceGroup);
+ sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `prospecting_loot_template`, ignoring.", cond->SourceGroup);
return false;
}
- LootTemplate* loot = LootTemplates_Prospecting.GetLootForConditionFill(cond->mSourceGroup);
- ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->mSourceEntry);
- if (!pItemProto && !loot->isReference(cond->mSourceEntry))
+ LootTemplate* loot = LootTemplates_Prospecting.GetLootForConditionFill(cond->SourceGroup);
+ ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
+ if (!pItemProto && !loot->isReference(cond->SourceEntry))
{
- sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry);
+ sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry);
return false;
}
break;
}
case CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE:
{
- if (!LootTemplates_Reference.HaveLootFor(cond->mSourceGroup))
+ if (!LootTemplates_Reference.HaveLootFor(cond->SourceGroup))
{
- sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `reference_loot_template`, ignoring.", cond->mSourceGroup);
+ sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `reference_loot_template`, ignoring.", cond->SourceGroup);
return false;
}
- LootTemplate* loot = LootTemplates_Reference.GetLootForConditionFill(cond->mSourceGroup);
- ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->mSourceEntry);
- if (!pItemProto && !loot->isReference(cond->mSourceEntry))
+ LootTemplate* loot = LootTemplates_Reference.GetLootForConditionFill(cond->SourceGroup);
+ ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
+ if (!pItemProto && !loot->isReference(cond->SourceEntry))
{
- sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry);
+ sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry);
return false;
}
break;
}
case CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE:
{
- if (!LootTemplates_Skinning.HaveLootFor(cond->mSourceGroup))
+ if (!LootTemplates_Skinning.HaveLootFor(cond->SourceGroup))
{
- sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `skinning_loot_template`, ignoring.", cond->mSourceGroup);
+ sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `skinning_loot_template`, ignoring.", cond->SourceGroup);
return false;
}
- LootTemplate* loot = LootTemplates_Skinning.GetLootForConditionFill(cond->mSourceGroup);
- ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->mSourceEntry);
- if (!pItemProto && !loot->isReference(cond->mSourceEntry))
+ LootTemplate* loot = LootTemplates_Skinning.GetLootForConditionFill(cond->SourceGroup);
+ ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
+ if (!pItemProto && !loot->isReference(cond->SourceEntry))
{
- sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry);
+ sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry);
return false;
}
break;
}
case CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE:
{
- if (!LootTemplates_Spell.HaveLootFor(cond->mSourceGroup))
+ if (!LootTemplates_Spell.HaveLootFor(cond->SourceGroup))
{
- sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `spell_loot_template`, ignoring.", cond->mSourceGroup);
+ sLog->outErrorDb("SourceGroup %u in `condition` table, does not exist in `spell_loot_template`, ignoring.", cond->SourceGroup);
return false;
}
- LootTemplate* loot = LootTemplates_Spell.GetLootForConditionFill(cond->mSourceGroup);
- ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->mSourceEntry);
- if (!pItemProto && !loot->isReference(cond->mSourceEntry))
+ LootTemplate* loot = LootTemplates_Spell.GetLootForConditionFill(cond->SourceGroup);
+ ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->SourceEntry);
+ if (!pItemProto && !loot->isReference(cond->SourceEntry))
{
- sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry);
+ sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->SourceType, cond->SourceEntry);
return false;
}
break;
}
- case CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET:
+ case CONDITION_SOURCE_TYPE_SPELL_IMPLICIT_TARGET:
{
- if (cond->mConditionType != CONDITION_SPELL_SCRIPT_TARGET)
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(cond->SourceEntry);
+ if (!spellInfo)
{
- sLog->outErrorDb("SourceEntry %u in `condition` table, has ConditionType %u. Only CONDITION_SPELL_SCRIPT_TARGET(18) is valid for CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET(14), ignoring.", cond->mSourceEntry, uint32(cond->mConditionType));
+ sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `spell.dbc`, ignoring.", cond->SourceEntry);
return false;
}
- SpellInfo const* spellProto = sSpellMgr->GetSpellInfo(cond->mSourceEntry);
- if (!spellProto)
+ if ((cond->SourceGroup > MAX_EFFECT_MASK) || !cond->SourceGroup)
{
- sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `spell.dbc`, ignoring.", cond->mSourceEntry);
+ sLog->outErrorDb("SourceEntry %u in `condition` table, has incorrect SourceGroup %u (spell effectMask) set , ignoring.", cond->SourceEntry, cond->SourceGroup);
return false;
}
- bool targetfound = false;
+ uint32 origGroup = cond->SourceGroup;
+
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
{
- if (spellProto->Effects[i].TargetA.GetTarget() == TARGET_UNIT_SRC_AREA_ENTRY ||
- spellProto->Effects[i].TargetB.GetTarget() == TARGET_UNIT_SRC_AREA_ENTRY ||
- spellProto->Effects[i].TargetA.GetTarget() == TARGET_UNIT_DEST_AREA_ENTRY ||
- spellProto->Effects[i].TargetB.GetTarget() == TARGET_UNIT_DEST_AREA_ENTRY ||
- spellProto->Effects[i].TargetA.GetTarget() == TARGET_UNIT_NEARBY_ENTRY ||
- spellProto->Effects[i].TargetB.GetTarget() == TARGET_UNIT_NEARBY_ENTRY ||
- spellProto->Effects[i].TargetA.GetTarget() == TARGET_GAMEOBJECT_NEARBY_ENTRY ||
- spellProto->Effects[i].TargetB.GetTarget() == TARGET_GAMEOBJECT_NEARBY_ENTRY ||
- spellProto->Effects[i].TargetA.GetTarget() == TARGET_GAMEOBJECT_SRC_AREA ||
- spellProto->Effects[i].TargetB.GetTarget() == TARGET_GAMEOBJECT_SRC_AREA ||
- spellProto->Effects[i].TargetA.GetTarget() == TARGET_GAMEOBJECT_DEST_AREA ||
- spellProto->Effects[i].TargetB.GetTarget() == TARGET_GAMEOBJECT_DEST_AREA ||
- spellProto->Effects[i].TargetA.GetTarget() == TARGET_DEST_NEARBY_ENTRY ||
- spellProto->Effects[i].TargetB.GetTarget() == TARGET_DEST_NEARBY_ENTRY ||
- spellProto->Effects[i].TargetA.GetTarget() == TARGET_UNIT_CONE_ENTRY ||
- spellProto->Effects[i].TargetB.GetTarget() == TARGET_UNIT_CONE_ENTRY)
+ if (!((1<<i) & cond->SourceGroup))
+ continue;
+
+ switch (spellInfo->Effects[i].TargetA.GetSelectionCategory())
{
- targetfound = true;
- //break;
+ case TARGET_SELECT_CATEGORY_NEARBY:
+ case TARGET_SELECT_CATEGORY_CONE:
+ case TARGET_SELECT_CATEGORY_AREA:
+ continue;
+ default:
+ break;
}
- else if (cond->mConditionValue3 & (1 << i))
+
+ switch (spellInfo->Effects[i].TargetB.GetSelectionCategory())
{
- cond->mConditionValue3 &= ~(1 << i);
- sLog->outErrorDb("SourceEntry %u in `condition` table does not have any implicit target TARGET_UNIT_NEARBY_ENTRY(38) or TARGET_DEST_NEARBY_ENTRY (46)"
- ", TARGET_UNIT_SRC_AREA_ENTRY(7), TARGET_UNIT_DEST_AREA_ENTRY(8), TARGET_UNIT_CONE_ENTRY(60), TARGET_GAMEOBJECT_NEARBY_ENTRY(40)"
- "TARGET_GAMEOBJECT_SRC_AREA(51), TARGET_GAMEOBJECT_DEST_AREA(52) in effect %u", cond->mSourceEntry, uint32(i));
+ case TARGET_SELECT_CATEGORY_NEARBY:
+ case TARGET_SELECT_CATEGORY_CONE:
+ case TARGET_SELECT_CATEGORY_AREA:
+ continue;
+ default:
+ break;
}
+
+ sLog->outErrorDb("SourceEntry %u SourceGroup %u in `condition` table - spell %u does not have implicit targets of types: _AREA_, _CONE_, _NEARBY_ for effect %u, SourceGroup needs correction, ignoring.", cond->SourceEntry, origGroup, cond->SourceEntry, uint32(i));
+ cond->SourceGroup &= ~(1<<i);
}
- if (!targetfound && !cond->mConditionValue3) // cond->mConditionValue3 already errored up there
- {
- sLog->outErrorDb("SourceEntry %u in `condition` table does not have any implicit target TARGET_UNIT_NEARBY_ENTRY(38) or TARGET_DEST_NEARBY_ENTRY (46)"
- ", TARGET_UNIT_SRC_AREA_ENTRY(7), TARGET_UNIT_DEST_AREA_ENTRY(8), TARGET_UNIT_CONE_ENTRY(60), TARGET_GAMEOBJECT_NEARBY_ENTRY(40)"
- "TARGET_GAMEOBJECT_SRC_AREA(51), TARGET_GAMEOBJECT_DEST_AREA(52)", cond->mSourceEntry);
- return false;
- }
- if ((cond->mConditionValue1 == SPELL_TARGET_TYPE_DEAD) && !spellProto->IsAllowingDeadTarget())
- {
- sLog->outErrorDb("SourceEntry %u in `condition` table does have SPELL_TARGET_TYPE_DEAD specified but spell does not have SPELL_ATTR2_CAN_TARGET_DEAD", cond->mSourceEntry);
+ // all effects were removed, no need to add the condition at all
+ if (!cond->SourceGroup)
return false;
- }
break;
}
case CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE:
{
- if (!sObjectMgr->GetCreatureTemplate(cond->mSourceEntry))
+ if (!sObjectMgr->GetCreatureTemplate(cond->SourceEntry))
{
- sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `creature_template`, ignoring.", cond->mSourceEntry);
+ sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `creature_template`, ignoring.", cond->SourceEntry);
return false;
}
break;
}
case CONDITION_SOURCE_TYPE_SPELL:
{
- SpellInfo const* spellProto = sSpellMgr->GetSpellInfo(cond->mSourceEntry);
+ SpellInfo const* spellProto = sSpellMgr->GetSpellInfo(cond->SourceEntry);
if (!spellProto)
{
- sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `spell.dbc`, ignoring.", cond->mSourceEntry);
+ sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `spell.dbc`, ignoring.", cond->SourceEntry);
return false;
}
break;
}
- case CONDITION_SOURCE_TYPE_ITEM_REQUIRED_TARGET:
- {
- if (cond->mConditionType != CONDITION_ITEM_TARGET)
+ case CONDITION_SOURCE_TYPE_QUEST_ACCEPT:
+ if (!sObjectMgr->GetQuestTemplate(cond->SourceEntry))
{
- sLog->outErrorDb("SourceEntry %u in `condition` table, has ConditionType %u. Only CONDITION_ITEM_TARGET(24) is valid for CONDITION_SOURCE_TYPE_ITEM_REQUIRED_TARGET(18), ignoring.", cond->mSourceEntry, uint32(cond->mConditionType));
+ sLog->outErrorDb("CONDITION_SOURCE_TYPE_QUEST_ACCEPT specifies non-existing quest (%u), skipped", cond->SourceEntry);
return false;
}
-
- ItemTemplate const* pItemProto = sObjectMgr->GetItemTemplate(cond->mSourceEntry);
- if (!pItemProto)
+ break;
+ case CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK:
+ if (!sObjectMgr->GetQuestTemplate(cond->SourceEntry))
{
- sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `item_tamplate`, ignoring.", cond->mSourceEntry);
+ sLog->outErrorDb("CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK specifies non-existing quest (%u), skipped", cond->SourceEntry);
return false;
}
-
- bool bIsItemSpellValid = false;
- for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
- {
- if (SpellInfo const* pSpellInfo = sSpellMgr->GetSpellInfo(pItemProto->Spells[i].SpellId))
- {
- if (pItemProto->Spells[i].SpellTrigger == ITEM_SPELLTRIGGER_ON_USE ||
- pItemProto->Spells[i].SpellTrigger == ITEM_SPELLTRIGGER_ON_NO_DELAY_USE)
- {
- ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET, pSpellInfo->Id);//script loading is done before item target loading
- if (!conditions.empty())
- break;
-
- for (int j = 0; j < MAX_SPELL_EFFECTS; ++j)
- {
- if (pSpellInfo->Effects[j].TargetA.GetTarget() == TARGET_UNIT_TARGET_ENEMY ||
- pSpellInfo->Effects[j].TargetB.GetTarget() == TARGET_UNIT_TARGET_ENEMY ||
- pSpellInfo->Effects[j].TargetA.GetTarget() == TARGET_UNIT_TARGET_ANY ||
- pSpellInfo->Effects[j].TargetB.GetTarget() == TARGET_UNIT_TARGET_ANY)
- {
- bIsItemSpellValid = true;
- break;
- }
- }
-
- if (bIsItemSpellValid)
- break;
- }
- }
- }
-
- if (!bIsItemSpellValid)
- {
- sLog->outErrorDb("Conditions: CONDITION_SOURCE_TYPE_ITEM_REQUIRED_TARGET for item %u, which either doesn't have item spelltrigger or its spells don't have implicit target "
- "TARGET_UNIT_TARGET_ENEMY(6), TARGET_UNIT_TARGET_ANY(25), or the spells are already listed in CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET conditions.", cond->mSourceEntry);
- break;
- }
break;
- }
- case CONDITION_SOURCE_TYPE_QUEST_ACCEPT:
- if (!sObjectMgr->GetQuestTemplate(cond->mSourceEntry))
+ case CONDITION_SOURCE_TYPE_VEHICLE_SPELL:
+ if (!sObjectMgr->GetCreatureTemplate(cond->SourceGroup))
{
- sLog->outErrorDb("CONDITION_SOURCE_TYPE_QUEST_ACCEPT specifies non-existing quest (%u), skipped", cond->mSourceEntry);
+ sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `creature_template`, ignoring.", cond->SourceGroup);
return false;
}
- break;
- case CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK:
- if (!sObjectMgr->GetQuestTemplate(cond->mSourceEntry))
+
+ if (!sSpellMgr->GetSpellInfo(cond->SourceEntry))
{
- sLog->outErrorDb("CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK specifies non-existing quest (%u), skipped", cond->mSourceEntry);
+ sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `spell.dbc`, ignoring.", cond->SourceEntry);
return false;
}
break;
- case CONDITION_SOURCE_TYPE_VEHICLE_SPELL:
- if (!sObjectMgr->GetCreatureTemplate(cond->mSourceGroup))
+ case CONDITION_SOURCE_TYPE_SPELL_CLICK_EVENT:
+ if (!sObjectMgr->GetCreatureTemplate(cond->SourceGroup))
{
- sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `creature_template`, ignoring.", cond->mSourceGroup);
+ sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `creature_template`, ignoring.", cond->SourceGroup);
return false;
}
- if (!sSpellMgr->GetSpellInfo(cond->mSourceEntry))
+ if (!sSpellMgr->GetSpellInfo(cond->SourceEntry))
{
- sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `spell.dbc`, ignoring.", cond->mSourceEntry);
+ sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `spell.dbc`, ignoring.", cond->SourceEntry);
return false;
}
break;
@@ -1050,113 +1416,131 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond)
}
bool ConditionMgr::isConditionTypeValid(Condition* cond)
{
- if (cond->mConditionType == CONDITION_NONE || cond->mConditionType >= CONDITION_MAX)
+ if (cond->ConditionType == CONDITION_NONE || cond->ConditionType >= CONDITION_MAX)
{
- sLog->outErrorDb("Invalid ConditionType %u at SourceEntry %u in `condition` table, ignoring.", uint32(cond->mConditionType), cond->mSourceEntry);
+ sLog->outErrorDb("Invalid ConditionType %u at SourceEntry %u in `condition` table, ignoring.", uint32(cond->ConditionType), cond->SourceEntry);
return false;
}
- switch (cond->mConditionType)
+ if (cond->ConditionTarget >= cond->GetMaxAvailableConditionTargets())
+ {
+ sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, has incorrect ConditionTarget set, ignoring.", cond->SourceType, cond->SourceEntry);
+ return false;
+ }
+
+ switch (cond->ConditionType)
{
case CONDITION_AURA:
{
- if (!sSpellMgr->GetSpellInfo(cond->mConditionValue1))
+ if (!sSpellMgr->GetSpellInfo(cond->ConditionValue1))
{
- sLog->outErrorDb("Aura condition has non existing spell (Id: %d), skipped", cond->mConditionValue1);
+ sLog->outErrorDb("Aura condition has non existing spell (Id: %d), skipped", cond->ConditionValue1);
return false;
}
- if (cond->mConditionValue2 > 2)
+ if (cond->ConditionValue2 > EFFECT_2)
{
- sLog->outErrorDb("Aura condition has non existing effect index (%u) (must be 0..2), skipped", cond->mConditionValue2);
+ sLog->outErrorDb("Aura condition has non existing effect index (%u) (must be 0..2), skipped", cond->ConditionValue2);
return false;
}
+ if (cond->ConditionValue3)
+ sLog->outErrorDb("Aura condition has useless data in value3 (%u)!", cond->ConditionValue3);
break;
}
case CONDITION_ITEM:
{
- ItemTemplate const* proto = sObjectMgr->GetItemTemplate(cond->mConditionValue1);
+ ItemTemplate const* proto = sObjectMgr->GetItemTemplate(cond->ConditionValue1);
if (!proto)
{
- sLog->outErrorDb("Item condition has non existing item (%u), skipped", cond->mConditionValue1);
+ sLog->outErrorDb("Item condition has non existing item (%u), skipped", cond->ConditionValue1);
return false;
}
- if (!cond->mConditionValue2)
+ if (!cond->ConditionValue2)
{
- sLog->outErrorDb("Item condition has 0 set for item count in value2 (%u), skipped", cond->mConditionValue2);
+ sLog->outErrorDb("Item condition has 0 set for item count in value2 (%u), skipped", cond->ConditionValue2);
return false;
}
break;
}
case CONDITION_ITEM_EQUIPPED:
{
- ItemTemplate const* proto = sObjectMgr->GetItemTemplate(cond->mConditionValue1);
+ ItemTemplate const* proto = sObjectMgr->GetItemTemplate(cond->ConditionValue1);
if (!proto)
{
- sLog->outErrorDb("ItemEquipped condition has non existing item (%u), skipped", cond->mConditionValue1);
+ sLog->outErrorDb("ItemEquipped condition has non existing item (%u), skipped", cond->ConditionValue1);
return false;
}
- if (cond->mConditionValue2)
- sLog->outErrorDb("ItemEquipped condition has useless data in value2 (%u)!", cond->mConditionValue2);
+ if (cond->ConditionValue2)
+ sLog->outErrorDb("ItemEquipped condition has useless data in value2 (%u)!", cond->ConditionValue2);
+ if (cond->ConditionValue3)
+ sLog->outErrorDb("ItemEquipped condition has useless data in value3 (%u)!", cond->ConditionValue3);
break;
}
case CONDITION_ZONEID:
{
- AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(cond->mConditionValue1);
+ AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(cond->ConditionValue1);
if (!areaEntry)
{
- sLog->outErrorDb("Zone condition has non existing area (%u), skipped", cond->mConditionValue1);
+ sLog->outErrorDb("ZoneID condition has non existing area (%u), skipped", cond->ConditionValue1);
return false;
}
if (areaEntry->zone != 0)
{
- sLog->outErrorDb("Zone condition requires to be in area (%u) which is a subzone but zone expected, skipped", cond->mConditionValue1);
+ sLog->outErrorDb("ZoneID condition requires to be in area (%u) which is a subzone but zone expected, skipped", cond->ConditionValue1);
return false;
}
- if (cond->mConditionValue2)
- sLog->outErrorDb("Zone condition has useless data in value2 (%u)!", cond->mConditionValue2);
+ if (cond->ConditionValue2)
+ sLog->outErrorDb("ZoneID condition has useless data in value2 (%u)!", cond->ConditionValue2);
+ if (cond->ConditionValue3)
+ sLog->outErrorDb("ZoneID condition has useless data in value3 (%u)!", cond->ConditionValue3);
break;
}
case CONDITION_REPUTATION_RANK:
{
- FactionEntry const* factionEntry = sFactionStore.LookupEntry(cond->mConditionValue1);
+ FactionEntry const* factionEntry = sFactionStore.LookupEntry(cond->ConditionValue1);
if (!factionEntry)
{
- sLog->outErrorDb("Reputation condition has non existing faction (%u), skipped", cond->mConditionValue1);
+ sLog->outErrorDb("Reputation condition has non existing faction (%u), skipped", cond->ConditionValue1);
return false;
}
+ if (cond->ConditionValue3)
+ sLog->outErrorDb("Reputation condition has useless data in value3 (%u)!", cond->ConditionValue3);
break;
}
case CONDITION_TEAM:
{
- if (cond->mConditionValue1 != ALLIANCE && cond->mConditionValue1 != HORDE)
+ if (cond->ConditionValue1 != ALLIANCE && cond->ConditionValue1 != HORDE)
{
- sLog->outErrorDb("Team condition specifies unknown team (%u), skipped", cond->mConditionValue1);
+ sLog->outErrorDb("Team condition specifies unknown team (%u), skipped", cond->ConditionValue1);
return false;
}
- if (cond->mConditionValue2)
- sLog->outErrorDb("Team condition has useless data in value2 (%u)!", cond->mConditionValue2);
+ if (cond->ConditionValue2)
+ sLog->outErrorDb("Team condition has useless data in value2 (%u)!", cond->ConditionValue2);
+ if (cond->ConditionValue3)
+ sLog->outErrorDb("Team condition has useless data in value3 (%u)!", cond->ConditionValue3);
break;
}
case CONDITION_SKILL:
{
- SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(cond->mConditionValue1);
+ SkillLineEntry const* pSkill = sSkillLineStore.LookupEntry(cond->ConditionValue1);
if (!pSkill)
{
- sLog->outErrorDb("Skill condition specifies non-existing skill (%u), skipped", cond->mConditionValue1);
+ sLog->outErrorDb("Skill condition specifies non-existing skill (%u), skipped", cond->ConditionValue1);
return false;
}
- if (cond->mConditionValue2 < 1 || cond->mConditionValue2 > sWorld->GetConfigMaxSkillValue())
+ if (cond->ConditionValue2 < 1 || cond->ConditionValue2 > sWorld->GetConfigMaxSkillValue())
{
- sLog->outErrorDb("Skill condition specifies invalid skill value (%u), skipped", cond->mConditionValue2);
+ sLog->outErrorDb("Skill condition specifies invalid skill value (%u), skipped", cond->ConditionValue2);
return false;
}
+ if (cond->ConditionValue3)
+ sLog->outErrorDb("Skill condition has useless data in value3 (%u)!", cond->ConditionValue3);
break;
}
case CONDITION_QUESTREWARDED:
@@ -1164,246 +1548,331 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond)
case CONDITION_QUEST_NONE:
case CONDITION_QUEST_COMPLETE:
{
- if (!sObjectMgr->GetQuestTemplate(cond->mConditionValue1))
+ if (!sObjectMgr->GetQuestTemplate(cond->ConditionValue1))
{
- sLog->outErrorDb("Quest condition specifies non-existing quest (%u), skipped", cond->mConditionValue1);
+ sLog->outErrorDb("Quest condition specifies non-existing quest (%u), skipped", cond->ConditionValue1);
return false;
}
- if (cond->mConditionValue2 > 1)
- sLog->outErrorDb("Quest condition has useless data in value2 (%u)!", cond->mConditionValue2);
- break;
- }
- case CONDITION_NO_AURA:
- {
- if (!sSpellMgr->GetSpellInfo(cond->mConditionValue1))
- {
- sLog->outErrorDb("Aura condition has non existing spell (Id: %d), skipped", cond->mConditionValue1);
- return false;
- }
-
- if (cond->mConditionValue2 > 2)
- {
- sLog->outErrorDb("Aura condition has non existing effect index (%u) in value2 (must be 0..2), skipped", cond->mConditionValue2);
- return false;
- }
+ if (cond->ConditionValue2 > 1)
+ sLog->outErrorDb("Quest condition has useless data in value2 (%u)!", cond->ConditionValue2);
+ if (cond->ConditionValue3)
+ sLog->outErrorDb("Quest condition has useless data in value3 (%u)!", cond->ConditionValue3);
break;
}
case CONDITION_ACTIVE_EVENT:
{
GameEventMgr::GameEventDataMap const& events = sGameEventMgr->GetEventMap();
- if (cond->mConditionValue1 >=events.size() || !events[cond->mConditionValue1].isValid())
+ if (cond->ConditionValue1 >=events.size() || !events[cond->ConditionValue1].isValid())
{
- sLog->outErrorDb("Active event condition has non existing event id (%u), skipped", cond->mConditionValue1);
+ sLog->outErrorDb("ActiveEvent condition has non existing event id (%u), skipped", cond->ConditionValue1);
return false;
}
- if (cond->mConditionValue2)
- sLog->outErrorDb("Active event condition has useless data in value2 (%u)!", cond->mConditionValue2);
+ if (cond->ConditionValue2)
+ sLog->outErrorDb("ActiveEvent condition has useless data in value2 (%u)!", cond->ConditionValue2);
+ if (cond->ConditionValue3)
+ sLog->outErrorDb("ActiveEvent condition has useless data in value3 (%u)!", cond->ConditionValue3);
break;
}
case CONDITION_ACHIEVEMENT:
{
- AchievementEntry const* achievement = GetAchievementStore()->LookupEntry(cond->mConditionValue1);
+ AchievementEntry const* achievement = GetAchievementStore()->LookupEntry(cond->ConditionValue1);
if (!achievement)
{
- sLog->outErrorDb("Achivemen condition has non existing achivement id (%u), skipped", cond->mConditionValue1);
+ sLog->outErrorDb("Achivement condition has non existing achivement id (%u), skipped", cond->ConditionValue1);
return false;
}
- if (cond->mConditionValue2)
- sLog->outErrorDb("Achivemen condition has useless data in value2 (%u)!", cond->mConditionValue2);
+ if (cond->ConditionValue2)
+ sLog->outErrorDb("Achivement condition has useless data in value2 (%u)!", cond->ConditionValue2);
+ if (cond->ConditionValue3)
+ sLog->outErrorDb("Achivement condition has useless data in value3 (%u)!", cond->ConditionValue3);
break;
}
case CONDITION_CLASS:
{
- if (!(cond->mConditionValue1 & CLASSMASK_ALL_PLAYABLE))
+ if (!(cond->ConditionValue1 & CLASSMASK_ALL_PLAYABLE))
{
- sLog->outErrorDb("Class condition has non existing classmask (%u), skipped", cond->mConditionValue1 & ~CLASSMASK_ALL_PLAYABLE);
+ sLog->outErrorDb("Class condition has non existing classmask (%u), skipped", cond->ConditionValue1 & ~CLASSMASK_ALL_PLAYABLE);
return false;
}
- if (cond->mConditionValue2)
- sLog->outErrorDb("Class condition has useless data in value2 (%u)!", cond->mConditionValue2);
+ if (cond->ConditionValue2)
+ sLog->outErrorDb("Class condition has useless data in value2 (%u)!", cond->ConditionValue2);
+ if (cond->ConditionValue3)
+ sLog->outErrorDb("Class condition has useless data in value3 (%u)!", cond->ConditionValue3);
break;
}
case CONDITION_RACE:
{
- if (!(cond->mConditionValue1 & RACEMASK_ALL_PLAYABLE))
+ if (!(cond->ConditionValue1 & RACEMASK_ALL_PLAYABLE))
{
- sLog->outErrorDb("Race condition has non existing racemask (%u), skipped", cond->mConditionValue1 & ~RACEMASK_ALL_PLAYABLE);
+ sLog->outErrorDb("Race condition has non existing racemask (%u), skipped", cond->ConditionValue1 & ~RACEMASK_ALL_PLAYABLE);
return false;
}
- if (cond->mConditionValue2)
- sLog->outErrorDb("Race condition has useless data in value2 (%u)!", cond->mConditionValue2);
+ if (cond->ConditionValue2)
+ sLog->outErrorDb("Race condition has useless data in value2 (%u)!", cond->ConditionValue2);
+ if (cond->ConditionValue3)
+ sLog->outErrorDb("Race condition has useless data in value3 (%u)!", cond->ConditionValue3);
break;
}
- case CONDITION_SPELL_SCRIPT_TARGET:
+ case CONDITION_MAPID:
{
- if (cond->mConditionValue1 >= MAX_SPELL_TARGET_TYPE)
+ MapEntry const* me = sMapStore.LookupEntry(cond->ConditionValue1);
+ if (!me)
{
- sLog->outErrorDb("SpellTarget condition has non existing spell target type (%u), skipped", cond->mConditionValue1);
+ sLog->outErrorDb("Map condition has non existing map (%u), skipped", cond->ConditionValue1);
return false;
}
- switch (cond->mConditionValue1)
- {
- case SPELL_TARGET_TYPE_GAMEOBJECT:
- {
- if (cond->mConditionValue2 && !sObjectMgr->GetGameObjectTemplate(cond->mConditionValue2))
- {
- sLog->outErrorDb("SpellTarget condition has non existing gameobject (%u) as target, skipped", cond->mConditionValue2);
- return false;
- }
- break;
- }
- case SPELL_TARGET_TYPE_CONTROLLED:
- case SPELL_TARGET_TYPE_CREATURE:
- case SPELL_TARGET_TYPE_DEAD:
- {
- if (cond->mConditionValue2 && !sObjectMgr->GetCreatureTemplate(cond->mConditionValue2))
- {
- sLog->outErrorDb("SpellTarget condition has non existing creature template entry (%u) as target, skipped", cond->mConditionValue2);
- return false;
- }
-
- const CreatureTemplate* cInfo = sObjectMgr->GetCreatureTemplate(cond->mConditionValue2);
- if (cond->mSourceEntry == 30427 && !cInfo->SkinLootId)
- {
- 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->mConditionValue2);
- return false;
- }
- break;
- }
- }
+ if (cond->ConditionValue2)
+ sLog->outErrorDb("Map condition has useless data in value2 (%u)!", cond->ConditionValue2);
+ if (cond->ConditionValue3)
+ sLog->outErrorDb("Map condition has useless data in value3 (%u)!", cond->ConditionValue3);
break;
}
- case CONDITION_CREATURE_TARGET:
+ case CONDITION_SPELL:
{
- if (!cond->mConditionValue1 && !sObjectMgr->GetCreatureTemplate(cond->mConditionValue1))
+ if (!sSpellMgr->GetSpellInfo(cond->ConditionValue1))
{
- sLog->outErrorDb("CreatureTarget condition has non existing creature template entry (%u) as target, skipped", cond->mConditionValue1);
+ sLog->outErrorDb("Spell condition has non existing spell (Id: %d), skipped", cond->ConditionValue1);
return false;
}
- if (cond->mConditionValue2)
- sLog->outErrorDb("CreatureTarget condition has useless data in value2 (%u)!", cond->mConditionValue2);
+ if (cond->ConditionValue2)
+ sLog->outErrorDb("Spell condition has useless data in value2 (%u)!", cond->ConditionValue2);
+ if (cond->ConditionValue3)
+ sLog->outErrorDb("Spell condition has useless data in value3 (%u)!", cond->ConditionValue3);
break;
}
- case CONDITION_TARGET_HEALTH_BELOW_PCT:
+ case CONDITION_LEVEL:
{
- if (cond->mConditionValue1 > 100)
+ if (cond->ConditionValue2 >= COMP_TYPE_MAX)
{
- sLog->outErrorDb("TargetHealthBelowPct condition has invalid data in value1 (%u), skipped", cond->mConditionValue1);
+ sLog->outErrorDb("Level condition has invalid option (%u), skipped", cond->ConditionValue2);
return false;
}
-
- if (cond->mConditionValue2)
- sLog->outErrorDb("TargetHealthBelowPct condition has useless data in value2 (%u)!", cond->mConditionValue2);
+ if (cond->ConditionValue3)
+ sLog->outErrorDb("Level condition has useless data in value3 (%u)!", cond->ConditionValue3);
break;
}
- case CONDITION_TARGET_RANGE:
+ case CONDITION_DRUNKENSTATE:
{
- if (cond->mConditionValue2 && cond->mConditionValue2 < cond->mConditionValue1)//maxDist can be 0 for infinit max range
+ if (cond->ConditionValue1 > DRUNKEN_SMASHED)
+ {
+ sLog->outErrorDb("DrunkState condition has invalid state (%u), skipped", cond->ConditionValue1);
+ return false;
+ }
+ if (cond->ConditionValue2)
{
- sLog->outErrorDb("TargetRange condition has max distance closer then min distance, skipped");
+ sLog->outErrorDb("DrunkState condition has useless data in value2 (%u)!", cond->ConditionValue2);
return false;
}
+ if (cond->ConditionValue3)
+ sLog->outErrorDb("DrunkState condition has useless data in value3 (%u)!", cond->ConditionValue3);
break;
}
- case CONDITION_MAPID:
+ case CONDITION_NEAR_CREATURE:
{
- MapEntry const* me = sMapStore.LookupEntry(cond->mConditionValue1);
- if (!me)
+ if (!sObjectMgr->GetCreatureTemplate(cond->ConditionValue1))
{
- sLog->outErrorDb("Map condition has non existing map (%u), skipped", cond->mConditionValue1);
+ sLog->outErrorDb("NearCreature condition has non existing creature template entry (%u), skipped", cond->ConditionValue1);
return false;
}
-
- if (cond->mConditionValue2)
- sLog->outErrorDb("Map condition has useless data in value2 (%u)!", cond->mConditionValue2);
+ if (cond->ConditionValue3)
+ sLog->outErrorDb("NearCreature condition has useless data in value3 (%u)!", cond->ConditionValue3);
break;
}
- case CONDITION_ITEM_TARGET:
+ case CONDITION_NEAR_GAMEOBJECT:
{
- if (!cond->mConditionValue1 || cond->mConditionValue1 > MAX_ITEM_REQ_TARGET_TYPE)
+ if (!sObjectMgr->GetGameObjectTemplate(cond->ConditionValue1))
{
- sLog->outErrorDb("ItemTarget condition has incorrect target type (%u), skipped", cond->mConditionValue1);
+ sLog->outErrorDb("NearGameObject condition has non existing gameobject template entry (%u), skipped", cond->ConditionValue1);
return false;
}
-
- if (!cond->mConditionValue2 && !sObjectMgr->GetCreatureTemplate(cond->mConditionValue2))
+ if (cond->ConditionValue3)
+ sLog->outErrorDb("NearGameObject condition has useless data in value3 (%u)!", cond->ConditionValue3);
+ break;
+ }
+ case CONDITION_OBJECT_ENTRY:
+ {
+ switch (cond->ConditionValue1)
{
- sLog->outErrorDb("ItemTarget condition has non existing creature template entry (%u) as target, skipped", cond->mConditionValue2);
- return false;
+ case TYPEID_UNIT:
+ if (cond->ConditionValue2 && !sObjectMgr->GetCreatureTemplate(cond->ConditionValue2))
+ {
+ sLog->outErrorDb("ObjectEntry condition has non existing creature template entry (%u), skipped", cond->ConditionValue2);
+ return false;
+ }
+ break;
+ case TYPEID_GAMEOBJECT:
+ if (cond->ConditionValue2 && !sObjectMgr->GetGameObjectTemplate(cond->ConditionValue2))
+ {
+ sLog->outErrorDb("ObjectEntry condition has non existing game object template entry (%u), skipped", cond->ConditionValue2);
+ return false;
+ }
+ break;
+ case TYPEID_PLAYER:
+ case TYPEID_CORPSE:
+ if (cond->ConditionValue2)
+ sLog->outErrorDb("ObjectEntry condition has useless data in value2 (%u)!", cond->ConditionValue2);
+ break;
+ default:
+ sLog->outErrorDb("ObjectEntry condition has wrong typeid set (%u), skipped", cond->ConditionValue1);
+ return false;
}
-
- if (cond->mConditionValue3)
- sLog->outErrorDb("ItemTarget condition has useless data in value3 (%u)!", cond->mConditionValue3);
+ if (cond->ConditionValue3)
+ sLog->outErrorDb("ObjectEntry condition has useless data in value3 (%u)!", cond->ConditionValue3);
break;
}
- case CONDITION_SPELL:
+ case CONDITION_TYPE_MASK:
{
- if (!sSpellMgr->GetSpellInfo(cond->mConditionValue1))
+ if (!cond->ConditionValue1 || (cond->ConditionValue1 & ~(TYPEMASK_UNIT | TYPEMASK_PLAYER | TYPEMASK_GAMEOBJECT | TYPEMASK_CORPSE)))
{
- sLog->outErrorDb("Spell condition has non existing spell (Id: %d), skipped", cond->mConditionValue1);
+ sLog->outErrorDb("TypeMask condition has invalid typemask set (%u), skipped", cond->ConditionValue2);
return false;
}
-
- if (cond->mConditionValue2)
- sLog->outErrorDb("Spell condition has useless data in value2 (%u)!", cond->mConditionValue2);
+ if (cond->ConditionValue2)
+ sLog->outErrorDb("TypeMask condition has useless data in value2 (%u)!", cond->ConditionValue2);
+ if (cond->ConditionValue3)
+ sLog->outErrorDb("TypeMask condition has useless data in value3 (%u)!", cond->ConditionValue3);
break;
}
- case CONDITION_NOITEM:
+ case CONDITION_RELATION_TO:
{
- ItemTemplate const* proto = sObjectMgr->GetItemTemplate(cond->mConditionValue1);
- if (!proto)
+ if (cond->ConditionValue1 >= cond->GetMaxAvailableConditionTargets())
+ {
+ sLog->outErrorDb("RelationTo condition has invalid ConditionValue1(ConditionTarget selection) (%u), skipped", cond->ConditionValue1);
+ return false;
+ }
+ if (cond->ConditionValue1 == cond->ConditionTarget)
+ {
+ sLog->outErrorDb("RelationTo condition has ConditionValue1(ConditionTarget selection) set to self (%u), skipped", cond->ConditionValue1);
+ return false;
+ }
+ if (cond->ConditionValue2 >= RELATION_MAX)
{
- sLog->outErrorDb("NoItem condition has non existing item (%u), skipped", cond->mConditionValue1);
+ sLog->outErrorDb("RelationTo condition has invalid ConditionValue2(RelationType) (%u), skipped", cond->ConditionValue2);
return false;
}
+ if (cond->ConditionValue3)
+ sLog->outErrorDb("RelationTo condition has useless data in value3 (%u)!", cond->ConditionValue3);
break;
}
- case CONDITION_LEVEL:
+ case CONDITION_REACTION_TO:
{
- if (cond->mConditionValue2 >= LVL_COND_MAX)
+ if (cond->ConditionValue1 >= cond->GetMaxAvailableConditionTargets())
+ {
+ sLog->outErrorDb("ReactionTo condition has invalid ConditionValue1(ConditionTarget selection) (%u), skipped", cond->ConditionValue1);
+ return false;
+ }
+ if (cond->ConditionValue1 == cond->ConditionTarget)
+ {
+ sLog->outErrorDb("ReactionTo condition has ConditionValue1(ConditionTarget selection) set to self (%u), skipped", cond->ConditionValue1);
+ return false;
+ }
+ if (!cond->ConditionValue2)
{
- sLog->outErrorDb("Level condition has invalid option (%u), skipped", cond->mConditionValue2);
+ sLog->outErrorDb("mConditionValue2 condition has invalid ConditionValue2(rankMask) (%u), skipped", cond->ConditionValue2);
return false;
}
break;
}
- case CONDITION_DRUNKENSTATE:
+ case CONDITION_DISTANCE_TO:
{
- if (cond->mConditionValue1 > DRUNKEN_SMASHED)
+ if (cond->ConditionValue1 >= cond->GetMaxAvailableConditionTargets())
+ {
+ sLog->outErrorDb("DistanceTo condition has invalid ConditionValue1(ConditionTarget selection) (%u), skipped", cond->ConditionValue1);
+ return false;
+ }
+ if (cond->ConditionValue1 == cond->ConditionTarget)
+ {
+ sLog->outErrorDb("DistanceTo condition has ConditionValue1(ConditionTarget selection) set to self (%u), skipped", cond->ConditionValue1);
+ return false;
+ }
+ if (cond->ConditionValue3 >= COMP_TYPE_MAX)
{
- sLog->outErrorDb("DrunkState condition has invalid state (%u), skipped", cond->mConditionValue1);
+ sLog->outErrorDb("DistanceTo condition has invalid ComparisionType (%u), skipped", cond->ConditionValue3);
return false;
}
break;
}
- case CONDITION_NEAR_CREATURE:
+ case CONDITION_ALIVE:
+ {
+ if (cond->ConditionValue1)
+ sLog->outErrorDb("Alive condition has useless data in value1 (%u)!", cond->ConditionValue1);
+ if (cond->ConditionValue2)
+ sLog->outErrorDb("Alive condition has useless data in value2 (%u)!", cond->ConditionValue2);
+ if (cond->ConditionValue3)
+ sLog->outErrorDb("Alive condition has useless data in value3 (%u)!", cond->ConditionValue3);
+ break;
+ }
+ case CONDITION_HP_VAL:
{
- if (!sObjectMgr->GetCreatureTemplate(cond->mConditionValue1))
+ if (cond->ConditionValue2 >= COMP_TYPE_MAX)
{
- sLog->outErrorDb("NearCreature condition has non existing creature template entry (%u), skipped", cond->mConditionValue1);
+ sLog->outErrorDb("HpVal condition has invalid ComparisionType (%u), skipped", cond->ConditionValue2);
return false;
}
+ if (cond->ConditionValue3)
+ sLog->outErrorDb("HpVal condition has useless data in value3 (%u)!", cond->ConditionValue3);
break;
}
- case CONDITION_NEAR_GAMEOBJECT:
+ case CONDITION_HP_PCT:
{
- if (!sObjectMgr->GetGameObjectTemplate(cond->mConditionValue1))
+ if (cond->ConditionValue1 > 100)
{
- sLog->outErrorDb("NearGameObject condition has non existing gameobject template entry (%u), skipped", cond->mConditionValue1);
+ sLog->outErrorDb("HpPct condition has too big percent value (%u), skipped", cond->ConditionValue1);
return false;
}
+ if (cond->ConditionValue2 >= COMP_TYPE_MAX)
+ {
+ sLog->outErrorDb("HpPct condition has invalid ComparisionType (%u), skipped", cond->ConditionValue2);
+ return false;
+ }
+ if (cond->ConditionValue3)
+ sLog->outErrorDb("HpPct condition has useless data in value3 (%u)!", cond->ConditionValue3);
break;
}
case CONDITION_AREAID:
case CONDITION_INSTANCE_DATA:
break;
+ case CONDITION_WORLD_STATE:
+ {
+ if (!sWorld->getWorldState(cond->ConditionValue1))
+ {
+ sLog->outErrorDb("World state condition has non existing world state in value1 (%u), skipped", cond->ConditionValue1);
+ return false;
+ }
+ if (cond->ConditionValue3)
+ sLog->outErrorDb("World state condition has useless data in value3 (%u)!", cond->ConditionValue3);
+ break;
+ }
+ case CONDITION_PHASEMASK:
+ {
+ if (cond->ConditionValue2)
+ sLog->outErrorDb("Phasemask condition has useless data in value2 (%u)!", cond->ConditionValue2);
+ if (cond->ConditionValue3)
+ sLog->outErrorDb("Phasemask condition has useless data in value3 (%u)!", cond->ConditionValue3);
+ break;
+ }
+ case CONDITION_UNUSED_18:
+ sLog->outErrorDb("Found ConditionTypeOrReference = CONDITION_UNUSED_18 in `conditions` table - ignoring");
+ return false;
+ case CONDITION_UNUSED_19:
+ sLog->outErrorDb("Found ConditionTypeOrReference = CONDITION_UNUSED_19 in `conditions` table - ignoring");
+ return false;
+ case CONDITION_UNUSED_20:
+ sLog->outErrorDb("Found ConditionTypeOrReference = CONDITION_UNUSED_20 in `conditions` table - ignoring");
+ return false;
+ case CONDITION_UNUSED_21:
+ sLog->outErrorDb("Found ConditionTypeOrReference = CONDITION_UNUSED_21 in `conditions` table - ignoring");
+ return false;
+ case CONDITION_UNUSED_24:
+ sLog->outErrorDb("Found ConditionTypeOrReference = CONDITION_UNUSED_24 in `conditions` table - ignoring");
+ return false;
default:
break;
}
@@ -1434,7 +1903,7 @@ void ConditionMgr::Clean()
ConditionStore.clear();
- for (VehicleSpellConditionContainer::iterator itr = VehicleSpellConditionStore.begin(); itr != VehicleSpellConditionStore.end(); ++itr)
+ for (CreatureSpellConditionContainer::iterator itr = VehicleSpellConditionStore.begin(); itr != VehicleSpellConditionStore.end(); ++itr)
{
for (ConditionTypeContainer::iterator it = itr->second.begin(); it != itr->second.end(); ++it)
{