diff options
| -rw-r--r-- | sql/updates/world/2012_02_10_02_world_conditions.sql | 9 | ||||
| -rw-r--r-- | sql/updates/world/2012_02_10_03_world_conditions.sql | 2 | ||||
| -rw-r--r-- | sql/updates/world/2012_02_10_04_world_conditions.sql | 1 | ||||
| -rwxr-xr-x | src/server/game/AI/EventAI/CreatureEventAI.cpp | 3 | ||||
| -rw-r--r-- | src/server/game/AI/SmartScripts/SmartScript.cpp | 13 | ||||
| -rw-r--r-- | src/server/game/AI/SmartScripts/SmartScript.h | 12 | ||||
| -rwxr-xr-x | src/server/game/Conditions/ConditionMgr.cpp | 224 | ||||
| -rwxr-xr-x | src/server/game/Conditions/ConditionMgr.h | 83 | ||||
| -rwxr-xr-x | src/server/game/Entities/Player/Player.cpp | 13 | ||||
| -rwxr-xr-x | src/server/game/Entities/Player/Player.h | 2 | ||||
| -rwxr-xr-x | src/server/game/Scripting/ScriptMgr.cpp | 6 | ||||
| -rwxr-xr-x | src/server/game/Scripting/ScriptMgr.h | 5 | ||||
| -rwxr-xr-x | src/server/game/Spells/Spell.cpp | 17 |
13 files changed, 247 insertions, 143 deletions
diff --git a/sql/updates/world/2012_02_10_02_world_conditions.sql b/sql/updates/world/2012_02_10_02_world_conditions.sql new file mode 100644 index 00000000000..66d72e1be3a --- /dev/null +++ b/sql/updates/world/2012_02_10_02_world_conditions.sql @@ -0,0 +1,9 @@ +-- CONDITION_NO_AURA -> CONDITION_AURA + NegativeCondition +DELETE FROM `conditions` WHERE `NegativeCondition`=1 AND `ConditionTypeOrReference`=1; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) SELECT `SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`, 1 ,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`, 1 ,`ErrorTextId`,`ScriptName`,`Comment` FROM `conditions` WHERE `ConditionTypeOrReference`=11; +DELETE FROM `conditions` WHERE `ConditionTypeOrReference`=11; + +-- CONDITION_NOITEM -> CONDITION_ITEM + NegativeCondition +DELETE FROM `conditions` WHERE `NegativeCondition`=1 AND `ConditionTypeOrReference`=2; -- not a typo +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorTextId`,`ScriptName`,`Comment`) SELECT `SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`, 2 ,`ConditionValue1`, 1 ,`ConditionValue2`, 1 ,`ErrorTextId`,`ScriptName`,`Comment` FROM `conditions` WHERE `ConditionTypeOrReference`=26; +DELETE FROM `conditions` WHERE `ConditionTypeOrReference`=26; diff --git a/sql/updates/world/2012_02_10_03_world_conditions.sql b/sql/updates/world/2012_02_10_03_world_conditions.sql new file mode 100644 index 00000000000..b46684df7d5 --- /dev/null +++ b/sql/updates/world/2012_02_10_03_world_conditions.sql @@ -0,0 +1,2 @@ +-- CONDITION_SPELL with ConditionValue2 = 1 -> CONDITION_SPELL + NegativeCondition +UPDATE `conditions` SET `NegativeCondition` = 1, `ConditionValue2` = 0 WHERE `ConditionTypeOrReference` = 25 AND `ConditionValue2` = 1; diff --git a/sql/updates/world/2012_02_10_04_world_conditions.sql b/sql/updates/world/2012_02_10_04_world_conditions.sql new file mode 100644 index 00000000000..4703ec29044 --- /dev/null +++ b/sql/updates/world/2012_02_10_04_world_conditions.sql @@ -0,0 +1 @@ +ALTER TABLE `conditions` ADD COLUMN `ConditionTarget` tinyint(3) UNSIGNED NOT NULL default '0' AFTER `ConditionTypeOrReference`; diff --git a/src/server/game/AI/EventAI/CreatureEventAI.cpp b/src/server/game/AI/EventAI/CreatureEventAI.cpp index 5db9d0b1cdb..9036448d9b4 100755 --- a/src/server/game/AI/EventAI/CreatureEventAI.cpp +++ b/src/server/game/AI/EventAI/CreatureEventAI.cpp @@ -1338,7 +1338,8 @@ void CreatureEventAI::ReceiveEmote(Player* player, uint32 textEmote) cond.mConditionValue1 = (*itr).Event.receive_emote.conditionValue1; cond.mConditionValue2 = (*itr).Event.receive_emote.conditionValue2; - if (cond.Meets(player)) + ConditionSourceInfo srcInfo = ConditionSourceInfo(player); + if (cond.Meets(srcInfo)) { sLog->outDebug(LOG_FILTER_DATABASE_AI, "CreatureEventAI: ReceiveEmote CreatureEventAI: Condition ok, processing"); ProcessEvent(*itr, player); diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 42a23236182..4b15805c2c9 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -2783,6 +2783,19 @@ void SmartScript::InstallEvents() } } +bool SmartScript::ConditionValid(Unit* u, int32 c, int32 v1, int32 v2, int32 v3) +{ + if (c == 0) return true; + if (!u || !u->ToPlayer()) return false; + Condition cond; + cond.mConditionType = ConditionType(uint32(c)); + cond.mConditionValue1 = uint32(v1); + cond.mConditionValue1 = uint32(v2); + cond.mConditionValue1 = uint32(v3); + ConditionSourceInfo srcInfo = ConditionSourceInfo(u->ToPlayer()); + return cond.Meets(srcInfo); +} + void SmartScript::OnUpdate(uint32 const diff) { if ((mScriptType == SMART_SCRIPT_TYPE_CREATURE || mScriptType == SMART_SCRIPT_TYPE_GAMEOBJECT) && !GetBaseObject()) diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h index fec38a690ed..f7524582ab7 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.h +++ b/src/server/game/AI/SmartScripts/SmartScript.h @@ -84,17 +84,7 @@ class SmartScript return obj && obj->GetTypeId() == TYPEID_GAMEOBJECT; } - bool ConditionValid(Unit* u, int32 c, int32 v1, int32 v2, int32 v3) - { - if (c == 0) return true; - if (!u || !u->ToPlayer()) return false; - Condition cond; - cond.mConditionType = ConditionType(uint32(c)); - cond.mConditionValue1 = uint32(v1); - cond.mConditionValue1 = uint32(v2); - cond.mConditionValue1 = uint32(v3); - return cond.Meets(u->ToPlayer()); - } + bool ConditionValid(Unit* u, int32 c, int32 v1, int32 v2, int32 v3); void OnUpdate(const uint32 diff); void OnMoveInLineOfSight(Unit* who); diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp index 9391636c619..8b785ebaa26 100755 --- a/src/server/game/Conditions/ConditionMgr.cpp +++ b/src/server/game/Conditions/ConditionMgr.cpp @@ -29,8 +29,10 @@ // Checks if object meets the condition // Can have CONDITION_SOURCE_TYPE_NONE && !mReferenceId if called from a special event (ie: eventAI) -bool Condition::Meets(WorldObject* object, WorldObject* invoker) +bool Condition::Meets(ConditionSourceInfo& sourceInfo) { + ASSERT(mConditionTarget < MAX_CONDITION_TARGETS); + WorldObject* object = sourceInfo.mConditionTargets[mConditionTarget]; // object not present, return false if (!object) { @@ -150,12 +152,6 @@ bool Condition::Meets(WorldObject* object, WorldObject* invoker) } break; } - case CONDITION_NO_AURA: - { - if (Unit* unit = object->ToUnit()) - condMeets = !unit->HasAuraEffect(mConditionValue1, mConditionValue2); - break; - } case CONDITION_ACTIVE_EVENT: condMeets = sGameEventMgr->IsActiveEvent(mConditionValue1); break; @@ -215,18 +211,7 @@ bool Condition::Meets(WorldObject* object, WorldObject* invoker) case CONDITION_SPELL: { if (Player* player = object->ToPlayer()) - { - if (mConditionValue2 == 1) - condMeets = player->HasSpell(mConditionValue1); - else - condMeets = !player->HasSpell(mConditionValue1); - } - break; - } - case CONDITION_NOITEM: - { - if (Player* player = object->ToPlayer()) - condMeets = !player->HasItemCount(mConditionValue1, 1, mConditionValue2 ? true : false); + condMeets = player->HasSpell(mConditionValue1); break; } case CONDITION_LEVEL: @@ -274,24 +259,14 @@ bool Condition::Meets(WorldObject* object, WorldObject* invoker) condMeets = false; break; } - switch (mSourceType) - { - case CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET: - case CONDITION_SOURCE_TYPE_SPELL: - sendErrorMsg = true; - break; - default: - break; - } if (mNegativeCondition) condMeets = !condMeets; - if (Player* player = object->ToPlayer()) - if (sendErrorMsg && ErrorTextd && (!condMeets))//send special error from DB - player->m_ConditionErrorMsgId = ErrorTextd; + if (!condMeets) + sourceInfo.mLastFailedCondition = this; - bool script = sScriptMgr->OnConditionCheck(this, object, invoker); // Returns true by default. + bool script = sScriptMgr->OnConditionCheck(this, sourceInfo); // Returns true by default. return condMeets && script; } @@ -313,7 +288,7 @@ ConditionList ConditionMgr::GetConditionReferences(uint32 refId) return conditions; } -bool ConditionMgr::IsObjectMeetToConditionList(WorldObject* object, ConditionList const& conditions, WorldObject* invoker /*= NULL*/) +bool ConditionMgr::IsObjectMeetToConditionList(ConditionSourceInfo& sourceInfo, ConditionList const& conditions) { std::map<uint32, bool> ElseGroupStore; for (ConditionList::const_iterator i = conditions.begin(); i != conditions.end(); ++i) @@ -332,7 +307,7 @@ bool ConditionMgr::IsObjectMeetToConditionList(WorldObject* object, ConditionLis ConditionReferenceContainer::const_iterator ref = ConditionReferenceStore.find((*i)->mReferenceId); if (ref != ConditionReferenceStore.end()) { - if (!IsObjectMeetToConditionList(object, (*ref).second, invoker)) + if (!IsObjectMeetToConditionList(sourceInfo, (*ref).second)) ElseGroupStore[(*i)->mElseGroup] = false; } else @@ -344,7 +319,7 @@ bool ConditionMgr::IsObjectMeetToConditionList(WorldObject* object, ConditionLis } else //handle normal condition { - if (!(*i)->Meets(object, invoker)) + if (!(*i)->Meets(sourceInfo)) ElseGroupStore[(*i)->mElseGroup] = false; } } @@ -356,23 +331,19 @@ bool ConditionMgr::IsObjectMeetToConditionList(WorldObject* object, ConditionLis return false; } -bool ConditionMgr::IsObjectMeetToConditions(WorldObject* object, ConditionList const& conditions, WorldObject* invoker /*= NULL*/) +bool ConditionMgr::IsObjectMeetToConditions(WorldObject* object, ConditionList const& conditions) +{ + ConditionSourceInfo srcInfo = ConditionSourceInfo(object); + return IsObjectMeetToConditions(srcInfo, conditions); +} + +bool ConditionMgr::IsObjectMeetToConditions(ConditionSourceInfo& sourceInfo, ConditionList const& conditions) { if (conditions.empty()) return true; - Player* player = object ? object->ToPlayer() : NULL; - - if (player) - player->m_ConditionErrorMsgId = 0; - - sLog->outDebug(LOG_FILTER_CONDITIONSYS, "ConditionMgr::IsPlayerMeetToConditions"); - bool result = IsObjectMeetToConditionList(player, conditions, invoker); - - 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 - - return result; + sLog->outDebug(LOG_FILTER_CONDITIONSYS, "ConditionMgr::IsObjectMeetToConditions"); + return IsObjectMeetToConditionList(sourceInfo, conditions); } ConditionList ConditionMgr::GetConditionsForNotGroupedEntry(ConditionSourceType sourceType, uint32 entry) @@ -456,7 +427,7 @@ void ConditionMgr::LoadConditions(bool isReload) sObjectMgr->LoadGossipMenuItems(); } - QueryResult result = WorldDatabase.Query("SELECT SourceTypeOrReferenceId, SourceGroup, SourceEntry, SourceId, ElseGroup, ConditionTypeOrReference, " + QueryResult result = WorldDatabase.Query("SELECT SourceTypeOrReferenceId, SourceGroup, SourceEntry, SourceId, ElseGroup, ConditionTypeOrReference, ConditionTarget, " " ConditionValue1, ConditionValue2, ConditionValue3, NegativeCondition, ErrorTextId, ScriptName FROM conditions"); if (!result) @@ -480,12 +451,13 @@ void ConditionMgr::LoadConditions(bool isReload) cond->mSourceId = fields[3].GetUInt32(); cond->mElseGroup = fields[4].GetUInt32(); int32 iConditionTypeOrReference = fields[5].GetInt32(); - cond->mConditionValue1 = fields[6].GetUInt32(); - cond->mConditionValue2 = fields[7].GetUInt32(); - cond->mConditionValue3 = fields[8].GetUInt32(); - cond->mNegativeCondition = fields[9].GetUInt8(); - cond->ErrorTextd = fields[10].GetUInt32(); - cond->mScriptId = sObjectMgr->GetScriptId(fields[11].GetCString()); + cond->mConditionTarget = fields[6].GetUInt8(); + cond->mConditionValue1 = fields[7].GetUInt32(); + cond->mConditionValue2 = fields[8].GetUInt32(); + cond->mConditionValue3 = fields[9].GetUInt32(); + cond->mNegativeCondition = fields[10].GetUInt8(); + cond->ErrorTextd = fields[11].GetUInt32(); + cond->mScriptId = sObjectMgr->GetScriptId(fields[12].GetCString()); if (iConditionTypeOrReference >= 0) cond->mConditionType = ConditionType(iConditionTypeOrReference); @@ -504,6 +476,8 @@ void ConditionMgr::LoadConditions(bool isReload) if (iSourceTypeOrReferenceId >= 0) rowType = "reference"; //check for useless data + if (cond->mConditionTarget) + sLog->outErrorDb("Condition %s %i has useless data in ConditionTarget (%u)!", rowType, iSourceTypeOrReferenceId, cond->mConditionTarget); if (cond->mConditionValue1) sLog->outErrorDb("Condition %s %i has useless data in value1 (%u)!", rowType, iSourceTypeOrReferenceId, cond->mConditionValue1); if (cond->mConditionValue2) @@ -759,6 +733,12 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); return false; } + + if (cond->mConditionTarget) + { + sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, has incorrect ConditionTarget set, ignoring.", cond->mSourceType, cond->mSourceEntry); + return false; + } break; } case CONDITION_SOURCE_TYPE_DISENCHANT_LOOT_TEMPLATE: @@ -776,6 +756,12 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); return false; } + + if (cond->mConditionTarget) + { + sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, has incorrect ConditionTarget set, ignoring.", cond->mSourceType, cond->mSourceEntry); + return false; + } break; } case CONDITION_SOURCE_TYPE_FISHING_LOOT_TEMPLATE: @@ -793,6 +779,12 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); return false; } + + if (cond->mConditionTarget) + { + sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, has incorrect ConditionTarget set, ignoring.", cond->mSourceType, cond->mSourceEntry); + return false; + } break; } case CONDITION_SOURCE_TYPE_GAMEOBJECT_LOOT_TEMPLATE: @@ -810,6 +802,12 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); return false; } + + if (cond->mConditionTarget) + { + sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, has incorrect ConditionTarget set, ignoring.", cond->mSourceType, cond->mSourceEntry); + return false; + } break; } case CONDITION_SOURCE_TYPE_ITEM_LOOT_TEMPLATE: @@ -827,6 +825,12 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); return false; } + + if (cond->mConditionTarget) + { + sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, has incorrect ConditionTarget set, ignoring.", cond->mSourceType, cond->mSourceEntry); + return false; + } break; } case CONDITION_SOURCE_TYPE_MAIL_LOOT_TEMPLATE: @@ -844,6 +848,12 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); return false; } + + if (cond->mConditionTarget) + { + sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, has incorrect ConditionTarget set, ignoring.", cond->mSourceType, cond->mSourceEntry); + return false; + } break; } case CONDITION_SOURCE_TYPE_MILLING_LOOT_TEMPLATE: @@ -861,6 +871,12 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); return false; } + + if (cond->mConditionTarget) + { + sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, has incorrect ConditionTarget set, ignoring.", cond->mSourceType, cond->mSourceEntry); + return false; + } break; } case CONDITION_SOURCE_TYPE_PICKPOCKETING_LOOT_TEMPLATE: @@ -878,6 +894,12 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); return false; } + + if (cond->mConditionTarget) + { + sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, has incorrect ConditionTarget set, ignoring.", cond->mSourceType, cond->mSourceEntry); + return false; + } break; } case CONDITION_SOURCE_TYPE_PROSPECTING_LOOT_TEMPLATE: @@ -895,6 +917,12 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); return false; } + + if (cond->mConditionTarget) + { + sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, has incorrect ConditionTarget set, ignoring.", cond->mSourceType, cond->mSourceEntry); + return false; + } break; } case CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE: @@ -912,6 +940,12 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); return false; } + + if (cond->mConditionTarget) + { + sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, has incorrect ConditionTarget set, ignoring.", cond->mSourceType, cond->mSourceEntry); + return false; + } break; } case CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE: @@ -929,6 +963,12 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); return false; } + + if (cond->mConditionTarget) + { + sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, has incorrect ConditionTarget set, ignoring.", cond->mSourceType, cond->mSourceEntry); + return false; + } break; } case CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE: @@ -946,6 +986,12 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, does not exist in `item_template`, ignoring.", cond->mSourceType, cond->mSourceEntry); return false; } + + if (cond->mConditionTarget) + { + sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, has incorrect ConditionTarget set, ignoring.", cond->mSourceType, cond->mSourceEntry); + return false; + } break; } case CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET: @@ -1015,6 +1061,12 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `creature_template`, ignoring.", cond->mSourceEntry); return false; } + + if (cond->mConditionTarget) + { + sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, has incorrect ConditionTarget set, ignoring.", cond->mSourceType, cond->mSourceEntry); + return false; + } break; } case CONDITION_SOURCE_TYPE_SPELL: @@ -1025,6 +1077,12 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `spell.dbc`, ignoring.", cond->mSourceEntry); return false; } + + if (cond->mConditionTarget > 2) + { + sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, has incorrect ConditionTarget set, ignoring.", cond->mSourceType, cond->mSourceEntry); + return false; + } break; } case CONDITION_SOURCE_TYPE_ITEM_REQUIRED_TARGET: @@ -1069,6 +1127,12 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) ", or the spells are already listed in CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET conditions.", cond->mSourceEntry); break; } + + if (cond->mConditionTarget > 2) + { + sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, has incorrect ConditionTarget set, ignoring.", cond->mSourceType, cond->mSourceEntry); + return false; + } break; } case CONDITION_SOURCE_TYPE_QUEST_ACCEPT: @@ -1077,6 +1141,11 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) sLog->outErrorDb("CONDITION_SOURCE_TYPE_QUEST_ACCEPT specifies non-existing quest (%u), skipped", cond->mSourceEntry); return false; } + if (cond->mConditionTarget) + { + sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, has incorrect ConditionTarget set, ignoring.", cond->mSourceType, cond->mSourceEntry); + return false; + } break; case CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK: if (!sObjectMgr->GetQuestTemplate(cond->mSourceEntry)) @@ -1084,6 +1153,11 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) sLog->outErrorDb("CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK specifies non-existing quest (%u), skipped", cond->mSourceEntry); return false; } + if (cond->mConditionTarget) + { + sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, has incorrect ConditionTarget set, ignoring.", cond->mSourceType, cond->mSourceEntry); + return false; + } break; case CONDITION_SOURCE_TYPE_VEHICLE_SPELL: if (!sObjectMgr->GetCreatureTemplate(cond->mSourceGroup)) @@ -1097,10 +1171,21 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) sLog->outErrorDb("SourceEntry %u in `condition` table, does not exist in `spell.dbc`, ignoring.", cond->mSourceEntry); return false; } + if (cond->mConditionTarget) + { + sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, has incorrect ConditionTarget set, ignoring.", cond->mSourceType, cond->mSourceEntry); + return false; + } break; case CONDITION_SOURCE_TYPE_GOSSIP_MENU: case CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION: case CONDITION_SOURCE_TYPE_SMART_EVENT: + if (cond->mConditionTarget) + { + sLog->outErrorDb("SourceType %u, SourceEntry %u in `condition` table, has incorrect ConditionTarget set, ignoring.", cond->mSourceType, cond->mSourceEntry); + return false; + } + break; case CONDITION_SOURCE_TYPE_NONE: default: break; @@ -1246,23 +1331,6 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) sLog->outErrorDb("Quest condition has useless data in value3 (%u)!", cond->mConditionValue3); break; } - case CONDITION_NO_AURA: - { - if (!sSpellMgr->GetSpellInfo(cond->mConditionValue1)) - { - sLog->outErrorDb("NoAura condition has non existing spell (Id: %d), skipped", cond->mConditionValue1); - return false; - } - - if (cond->mConditionValue2 > 2) - { - sLog->outErrorDb("NoAura condition has non existing effect index (%u) in value2 (must be 0..2), skipped", cond->mConditionValue2); - return false; - } - if (cond->mConditionValue3) - sLog->outErrorDb("NoAura condition has useless data in value3 (%u)!", cond->mConditionValue3); - break; - } case CONDITION_ACTIVE_EVENT: { GameEventMgr::GameEventDataMap const& events = sGameEventMgr->GetEventMap(); @@ -1447,18 +1515,6 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) sLog->outErrorDb("Spell condition has useless data in value3 (%u)!", cond->mConditionValue3); break; } - case CONDITION_NOITEM: - { - ItemTemplate const* proto = sObjectMgr->GetItemTemplate(cond->mConditionValue1); - if (!proto) - { - sLog->outErrorDb("NoItem condition has non existing item (%u), skipped", cond->mConditionValue1); - return false; - } - if (cond->mConditionValue3) - sLog->outErrorDb("NoItem condition has useless data in value3 (%u)!", cond->mConditionValue3); - break; - } case CONDITION_LEVEL: { if (cond->mConditionValue2 >= LVL_COND_MAX) diff --git a/src/server/game/Conditions/ConditionMgr.h b/src/server/game/Conditions/ConditionMgr.h index 1a666abbf2b..aca666c55de 100755 --- a/src/server/game/Conditions/ConditionMgr.h +++ b/src/server/game/Conditions/ConditionMgr.h @@ -24,7 +24,9 @@ class Player; class Unit; +class WorldObject; class LootTemplate; +struct Condition; enum ConditionType { // value1 value2 value3 @@ -39,7 +41,7 @@ enum ConditionType CONDITION_QUESTREWARDED = 8, // quest_id 0 0 true if quest_id was rewarded before CONDITION_QUESTTAKEN = 9, // quest_id 0, 0 true while quest active CONDITION_DRUNKENSTATE = 10, // DrunkenState 0, 0 true if player is drunk enough - CONDITION_NO_AURA = 11, // spell_id effindex 0 true if does not have aura of spell_id with effect effindex + CONDITION_UNUSED_11 = 11, CONDITION_ACTIVE_EVENT = 12, // event_id 0 0 true if event is active CONDITION_INSTANCE_DATA = 13, // entry data 0 true if data is set in current instance CONDITION_QUEST_NONE = 14, // quest_id 0 0 true if doesn't have quest saved @@ -53,9 +55,9 @@ enum ConditionType CONDITION_MAPID = 22, // map_id 0 0 true if in map_id CONDITION_AREAID = 23, // area_id 0 0 true if in area_id CONDITION_ITEM_TARGET = 24, // ItemRequiredTargetType, TargetEntry, 0 - CONDITION_SPELL = 25, // spell_id bool 0 bool 1 for true 0 for false - CONDITION_NOITEM = 26, // item_id bank 0 true if player does not have any of the item (if 'bank' is set it searches in bank slots too) - CONDITION_LEVEL = 27, // level opt 0 true if player's level is equal to param1 (param2 can modify the statement) + CONDITION_SPELL = 25, // spell_id 0 0 true if player has learned spell + CONDITION_UNUSED_26 = 26, + CONDITION_LEVEL = 27, // level opt 0 true if unit's level is equal to param1 (param2 can modify the statement) CONDITION_QUEST_COMPLETE = 28, // quest_id 0 0 true if player has quest_id with all objectives complete, but not yet rewarded CONDITION_NEAR_CREATURE = 29, // creature entry distance 0 true if there is a creature of entry in range CONDITION_NEAR_GAMEOBJECT = 30, // gameobject entry distance 0 true if there is a gameobject of entry in range @@ -74,32 +76,50 @@ enum LevelConditionType enum ConditionSourceType { - CONDITION_SOURCE_TYPE_NONE = 0, //DONE - CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE = 1, //DONE - CONDITION_SOURCE_TYPE_DISENCHANT_LOOT_TEMPLATE = 2, //DONE - CONDITION_SOURCE_TYPE_FISHING_LOOT_TEMPLATE = 3, //DONE - CONDITION_SOURCE_TYPE_GAMEOBJECT_LOOT_TEMPLATE = 4, //DONE - CONDITION_SOURCE_TYPE_ITEM_LOOT_TEMPLATE = 5, //DONE - CONDITION_SOURCE_TYPE_MAIL_LOOT_TEMPLATE = 6, //DONE - CONDITION_SOURCE_TYPE_MILLING_LOOT_TEMPLATE = 7, //DONE - CONDITION_SOURCE_TYPE_PICKPOCKETING_LOOT_TEMPLATE = 8, //DONE - CONDITION_SOURCE_TYPE_PROSPECTING_LOOT_TEMPLATE = 9, //DONE - CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE = 10, //DONE - CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE = 11, //DONE - CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE = 12, //DONE - CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET = 13, //DONE - CONDITION_SOURCE_TYPE_GOSSIP_MENU = 14, //DONE - CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION = 15, //DONE - CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE = 16, //DONE - CONDITION_SOURCE_TYPE_SPELL = 17, //DONE - CONDITION_SOURCE_TYPE_ITEM_REQUIRED_TARGET = 18, //DONE - CONDITION_SOURCE_TYPE_QUEST_ACCEPT = 19, //DONE - CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK = 20, //DONE - CONDITION_SOURCE_TYPE_VEHICLE_SPELL = 21, //DONE - CONDITION_SOURCE_TYPE_SMART_EVENT = 22, //DONE + CONDITION_SOURCE_TYPE_NONE = 0, + CONDITION_SOURCE_TYPE_CREATURE_LOOT_TEMPLATE = 1, + CONDITION_SOURCE_TYPE_DISENCHANT_LOOT_TEMPLATE = 2, + CONDITION_SOURCE_TYPE_FISHING_LOOT_TEMPLATE = 3, + CONDITION_SOURCE_TYPE_GAMEOBJECT_LOOT_TEMPLATE = 4, + CONDITION_SOURCE_TYPE_ITEM_LOOT_TEMPLATE = 5, + CONDITION_SOURCE_TYPE_MAIL_LOOT_TEMPLATE = 6, + CONDITION_SOURCE_TYPE_MILLING_LOOT_TEMPLATE = 7, + CONDITION_SOURCE_TYPE_PICKPOCKETING_LOOT_TEMPLATE = 8, + CONDITION_SOURCE_TYPE_PROSPECTING_LOOT_TEMPLATE = 9, + CONDITION_SOURCE_TYPE_REFERENCE_LOOT_TEMPLATE = 10, + CONDITION_SOURCE_TYPE_SKINNING_LOOT_TEMPLATE = 11, + CONDITION_SOURCE_TYPE_SPELL_LOOT_TEMPLATE = 12, + CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET = 13, + CONDITION_SOURCE_TYPE_GOSSIP_MENU = 14, + CONDITION_SOURCE_TYPE_GOSSIP_MENU_OPTION = 15, + CONDITION_SOURCE_TYPE_CREATURE_TEMPLATE_VEHICLE = 16, + CONDITION_SOURCE_TYPE_SPELL = 17, + CONDITION_SOURCE_TYPE_ITEM_REQUIRED_TARGET = 18, + CONDITION_SOURCE_TYPE_QUEST_ACCEPT = 19, + CONDITION_SOURCE_TYPE_QUEST_SHOW_MARK = 20, + CONDITION_SOURCE_TYPE_VEHICLE_SPELL = 21, + CONDITION_SOURCE_TYPE_SMART_EVENT = 22, CONDITION_SOURCE_TYPE_MAX = 23 //MAX }; +enum +{ + MAX_CONDITION_TARGETS = 3, +}; + +struct ConditionSourceInfo +{ + WorldObject* mConditionTargets[MAX_CONDITION_TARGETS]; + Condition* mLastFailedCondition; + ConditionSourceInfo(WorldObject* target0, WorldObject* target1 = NULL, WorldObject* target2 = NULL) + { + mConditionTargets[0] = target0; + mConditionTargets[1] = target1; + mConditionTargets[2] = target2; + mLastFailedCondition = NULL; + } +}; + struct Condition { ConditionSourceType mSourceType; //SourceTypeOrReferenceId @@ -108,6 +128,7 @@ struct Condition uint32 mSourceId; // So far, only used in CONDITION_SOURCE_TYPE_SMART_EVENT uint32 mElseGroup; ConditionType mConditionType; //ConditionTypeOrReference + uint8 mConditionTarget; uint32 mConditionValue1; uint32 mConditionValue2; uint32 mConditionValue3; @@ -123,6 +144,7 @@ struct Condition mSourceEntry = 0; mElseGroup = 0; mConditionType = CONDITION_NONE; + mConditionTarget = 0; mConditionValue1 = 0; mConditionValue2 = 0; mConditionValue3 = 0; @@ -132,7 +154,7 @@ struct Condition mNegativeCondition = false; } - bool Meets(WorldObject* player, WorldObject* invoker = NULL); + bool Meets(ConditionSourceInfo& sourceInfo); bool isLoaded() const { return mConditionType > CONDITION_NONE || mReferenceId; } }; @@ -157,7 +179,8 @@ class ConditionMgr bool isConditionTypeValid(Condition* cond); ConditionList GetConditionReferences(uint32 refId); - bool IsObjectMeetToConditions(WorldObject* object, ConditionList const& conditions, WorldObject* invoker = NULL); + bool IsObjectMeetToConditions(WorldObject* object, ConditionList const& conditions); + bool IsObjectMeetToConditions(ConditionSourceInfo& sourceInfo, ConditionList const& conditions); ConditionList GetConditionsForNotGroupedEntry(ConditionSourceType sourceType, uint32 entry); ConditionList GetConditionsForSmartEvent(int32 entryOrGuid, uint32 eventId, uint32 sourceType); ConditionList GetConditionsForVehicleSpell(uint32 creatureID, uint32 spellID); @@ -167,7 +190,7 @@ class ConditionMgr bool addToLootTemplate(Condition* cond, LootTemplate* loot); bool addToGossipMenus(Condition* cond); bool addToGossipMenuItems(Condition* cond); - bool IsObjectMeetToConditionList(WorldObject* player, ConditionList const& conditions, WorldObject* invoker = NULL); + bool IsObjectMeetToConditionList(ConditionSourceInfo& sourceInfo, ConditionList const& conditions); bool isGroupable(ConditionSourceType sourceType) const { diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index c6ea26a2dfd..630551cfc2a 100755 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -856,8 +856,6 @@ Player::Player(WorldSession* session): Unit(true), m_achievementMgr(this), m_rep for (uint8 i = 0; i < MAX_POWERS; ++i) m_powerFraction[i] = 0; - m_ConditionErrorMsgId = 0; - isDebugAreaTriggers = false; SetPendingBind(0, 0); @@ -4425,11 +4423,14 @@ bool Player::resetTalents(bool no_cost) // skip non-existant talent ranks if (talentInfo->RankID[rank] == 0) continue; + const SpellInfo* _spellEntry = sSpellMgr->GetSpellInfo(talentInfo->RankID[rank]); + if (!_spellEntry) + continue; removeSpell(talentInfo->RankID[rank], true); - if (const SpellInfo* _spellEntry = sSpellMgr->GetSpellInfo(talentInfo->RankID[rank])) - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) // search through the SpellInfo for valid trigger spells - if (_spellEntry->Effects[i].TriggerSpell > 0 && _spellEntry->Effects[i].Effect == SPELL_EFFECT_LEARN_SPELL) - removeSpell(_spellEntry->Effects[i].TriggerSpell, true); // and remove any spells that the talent teaches + // search for spells that the talent teaches and unlearn them + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + if (_spellEntry->Effects[i].TriggerSpell > 0 && _spellEntry->Effects[i].Effect == SPELL_EFFECT_LEARN_SPELL) + removeSpell(_spellEntry->Effects[i].TriggerSpell, true); // if this talent rank can be found in the PlayerTalentMap, mark the talent as removed so it gets deleted PlayerTalentMap::iterator plrTalent = m_talents[m_activeSpec]->find(talentInfo->RankID[rank]); if (plrTalent != m_talents[m_activeSpec]->end()) diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 489b4eacec5..345df411165 100755 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -2325,8 +2325,6 @@ class Player : public Unit, public GridObject<Player> void SetHomebind(WorldLocation const& loc, uint32 area_id); - uint32 m_ConditionErrorMsgId; - // Homebind coordinates uint32 m_homebindMapId; uint16 m_homebindAreaId; diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp index eccf12aa7e1..b40319358b6 100755 --- a/src/server/game/Scripting/ScriptMgr.cpp +++ b/src/server/game/Scripting/ScriptMgr.cpp @@ -1036,14 +1036,12 @@ void ScriptMgr::OnAuctionExpire(AuctionHouseObject* ah, AuctionEntry* entry) FOREACH_SCRIPT(AuctionHouseScript)->OnAuctionExpire(ah, entry); } -bool ScriptMgr::OnConditionCheck(Condition* condition, WorldObject* object, WorldObject* invoker) +bool ScriptMgr::OnConditionCheck(Condition* condition, ConditionSourceInfo& sourceInfo) { ASSERT(condition); - ASSERT(object); - // invoker can be NULL. GET_SCRIPT_RET(ConditionScript, condition->mScriptId, tmpscript, true); - return tmpscript->OnConditionCheck(condition, object, invoker); + return tmpscript->OnConditionCheck(condition, sourceInfo); } void ScriptMgr::OnInstall(Vehicle* veh) diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index 853db564a6d..048a7581215 100755 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -62,6 +62,7 @@ class WorldObject; struct AchievementCriteriaData; struct AuctionEntry; +struct ConditionSourceInfo; struct Condition; struct ItemTemplate; struct OutdoorPvPData; @@ -572,7 +573,7 @@ class ConditionScript : public ScriptObject bool IsDatabaseBound() const { return true; } // Called when a single condition is checked for a player. - virtual bool OnConditionCheck(Condition* /*condition*/, WorldObject* /*object*/, WorldObject* /*invoker*/) { return true; } + virtual bool OnConditionCheck(Condition* /*condition*/, ConditionSourceInfo& /*sourceInfo*/) { return true; } }; class VehicleScript : public ScriptObject @@ -938,7 +939,7 @@ class ScriptMgr public: /* ConditionScript */ - bool OnConditionCheck(Condition* condition, WorldObject* object, WorldObject* invoker); + bool OnConditionCheck(Condition* condition, ConditionSourceInfo& sourceInfo); public: /* VehicleScript */ diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 9dccb0ff341..7c578a39355 100755 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -4716,12 +4716,23 @@ SpellCastResult Spell::CheckCast(bool strict) return SPELL_FAILED_DONT_REPORT; } - // check spell caster's conditions from database - if (Player* plrCaster = m_caster->GetCharmerOrOwnerPlayerOrPlayerItself()) + // check spell cast conditions from database { + ConditionSourceInfo condInfo = ConditionSourceInfo(m_caster); + condInfo.mConditionTargets[1] = m_targets.GetObjectTarget(); ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL, m_spellInfo->Id); - if (!conditions.empty() && !sConditionMgr->IsObjectMeetToConditions(plrCaster, conditions)) + if (!conditions.empty() && !sConditionMgr->IsObjectMeetToConditions(condInfo, conditions)) + { + // send error msg to player if condition failed and text message available + // TODO: using WorldSession::SendNotification is not blizzlike + if (Player* playerCaster = m_caster->ToPlayer()) + { + if (playerCaster->GetSession() && condInfo.mLastFailedCondition + && condInfo.mLastFailedCondition->ErrorTextd) + playerCaster->GetSession()->SendNotification(condInfo.mLastFailedCondition->ErrorTextd); + } return SPELL_FAILED_DONT_REPORT; + } } // Don't check explicit target for passive spells (workaround) (check should be skipped only for learn case) |
