mirror of
https://github.com/mangosfour/server.git
synced 2025-12-12 19:37:03 +00:00
[11964] Implement new conditions system
Tree-like design idea by Faramir118, thanks for that! * Add `conditions` table to store conditions. * REPLACE current handling of conditions for the *_loot_template tables Convert the old conditions in *_loot_template to the new system by SQL-Queries * ADD support for new conditions to gossip_menu and gossip_menu_option. If for these tables no condition_id (new system) is provided, the old conditions will still be used * Add a small helper python script to contrib/convertConditions, see README there for details * Add new command to reload the `conditions` table (.reload conditions) * Add two Meta-Condition types CONDITION_AND (-1) and CONDITION_OR (-2) which are used as: value1 (as condition_entry) AND / OR value2 (as condition_entry) With these meta-conditions it is possible to create tree like and very complicated combined conditions (like HasAura && (HasItem || HasQuest)) NOTE about conversion: For easier convertion all the old table data is still preserved, but will be removed eventually (within a circle of the moon approximately) The python script will not create an optimal initial fill of the `conditions` table. You might want to tweak it manually or suggest some optimized algorithm :) Signed-off-by: Schmoozerd <schmoozerd@scriptdev2.com>
This commit is contained in:
parent
f3b5e1e4bc
commit
8c29893310
18 changed files with 729 additions and 132 deletions
|
|
@ -2376,7 +2376,6 @@ void ObjectMgr::LoadItemPrototypes()
|
|||
sLog.outErrorDb("Item (Entry: %u) not exist in `item_template` but referenced in `CharStartOutfit.dbc`", *itr);
|
||||
}
|
||||
|
||||
|
||||
void ObjectMgr::LoadItemConverts()
|
||||
{
|
||||
m_ItemConvert.clear(); // needed for reload case
|
||||
|
|
@ -4703,7 +4702,7 @@ void ObjectMgr::LoadWorldTemplate()
|
|||
SQLWorldLoader loader;
|
||||
loader.Load(sWorldTemplate, false);
|
||||
|
||||
for(uint32 i = 0; i < sWorldTemplate.MaxEntry; i++)
|
||||
for (uint32 i = 0; i < sWorldTemplate.MaxEntry; ++i)
|
||||
{
|
||||
WorldTemplate const* temp = GetWorldTemplate(i);
|
||||
if (!temp)
|
||||
|
|
@ -4725,7 +4724,30 @@ void ObjectMgr::LoadWorldTemplate()
|
|||
}
|
||||
}
|
||||
|
||||
sLog.outString( ">> Loaded %u World Template definitions", sWorldTemplate.RecordCount );
|
||||
sLog.outString( ">> Loaded %u World Template definitions", sWorldTemplate.RecordCount);
|
||||
sLog.outString();
|
||||
}
|
||||
|
||||
void ObjectMgr::LoadConditions()
|
||||
{
|
||||
SQLWorldLoader loader;
|
||||
loader.Load(sConditionStorage, false);
|
||||
|
||||
for (uint32 i = 0; i < sConditionStorage.MaxEntry; ++i)
|
||||
{
|
||||
const PlayerCondition* condition = sConditionStorage.LookupEntry<PlayerCondition>(i);
|
||||
if (!condition)
|
||||
continue;
|
||||
|
||||
if (!condition->IsValid())
|
||||
{
|
||||
sLog.outErrorDb("ObjectMgr::LoadConditions: invalid condition_entry %u, skip", i);
|
||||
sConditionStorage.EraseEntry(i);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
sLog.outString( ">> Loaded %u Condition definitions", sConditionStorage.RecordCount);
|
||||
sLog.outString();
|
||||
}
|
||||
|
||||
|
|
@ -7425,7 +7447,7 @@ void ObjectMgr::LoadFishingBaseSkillLevel()
|
|||
// Returns Id if found, else adds it to Conditions and returns Id
|
||||
uint16 ObjectMgr::GetConditionId( ConditionType condition, uint32 value1, uint32 value2 )
|
||||
{
|
||||
PlayerCondition lc = PlayerCondition(condition, value1, value2);
|
||||
PlayerCondition lc = PlayerCondition(0, condition, value1, value2);
|
||||
for (uint16 i=0; i < mConditions.size(); ++i)
|
||||
{
|
||||
if (lc == mConditions[i])
|
||||
|
|
@ -7460,39 +7482,45 @@ bool ObjectMgr::CheckDeclinedNames( std::wstring mainpart, DeclinedName const& n
|
|||
// Checks if player meets the condition
|
||||
bool PlayerCondition::Meets(Player const * player) const
|
||||
{
|
||||
if( !player )
|
||||
if (!player)
|
||||
return false; // player not present, return false
|
||||
|
||||
switch (condition)
|
||||
switch (m_condition)
|
||||
{
|
||||
case CONDITION_OR:
|
||||
// Checked on load
|
||||
return sConditionStorage.LookupEntry<PlayerCondition>(m_value1)->Meets(player) || sConditionStorage.LookupEntry<PlayerCondition>(m_value2)->Meets(player);
|
||||
case CONDITION_AND:
|
||||
// Checked on load
|
||||
return sConditionStorage.LookupEntry<PlayerCondition>(m_value1)->Meets(player) && sConditionStorage.LookupEntry<PlayerCondition>(m_value2)->Meets(player);
|
||||
case CONDITION_NONE:
|
||||
return true; // empty condition, always met
|
||||
case CONDITION_AURA:
|
||||
return player->HasAura(value1, SpellEffectIndex(value2));
|
||||
return player->HasAura(m_value1, SpellEffectIndex(m_value2));
|
||||
case CONDITION_ITEM:
|
||||
return player->HasItemCount(value1, value2);
|
||||
return player->HasItemCount(m_value1, m_value2);
|
||||
case CONDITION_ITEM_EQUIPPED:
|
||||
return player->HasItemOrGemWithIdEquipped(value1,1);
|
||||
return player->HasItemOrGemWithIdEquipped(m_value1,1);
|
||||
case CONDITION_AREAID:
|
||||
{
|
||||
uint32 zone, area;
|
||||
player->GetZoneAndAreaId(zone,area);
|
||||
return (zone == value1 || area == value1) == (value2 == 0);
|
||||
return (zone == m_value1 || area == m_value1) == (m_value2 == 0);
|
||||
}
|
||||
case CONDITION_REPUTATION_RANK:
|
||||
{
|
||||
FactionEntry const* faction = sFactionStore.LookupEntry(value1);
|
||||
return faction && player->GetReputationMgr().GetRank(faction) >= ReputationRank(value2);
|
||||
FactionEntry const* faction = sFactionStore.LookupEntry(m_value1);
|
||||
return faction && player->GetReputationMgr().GetRank(faction) >= ReputationRank(m_value2);
|
||||
}
|
||||
case CONDITION_TEAM:
|
||||
return uint32(player->GetTeam()) == value1;
|
||||
return uint32(player->GetTeam()) == m_value1;
|
||||
case CONDITION_SKILL:
|
||||
return player->HasSkill(value1) && player->GetBaseSkillValue(value1) >= value2;
|
||||
return player->HasSkill(m_value1) && player->GetBaseSkillValue(m_value1) >= m_value2;
|
||||
case CONDITION_QUESTREWARDED:
|
||||
return player->GetQuestRewardStatus(value1);
|
||||
return player->GetQuestRewardStatus(m_value1);
|
||||
case CONDITION_QUESTTAKEN:
|
||||
{
|
||||
return player->IsCurrentQuest(value1, value2);
|
||||
return player->IsCurrentQuest(m_value1, m_value2);
|
||||
}
|
||||
case CONDITION_AD_COMMISSION_AURA:
|
||||
{
|
||||
|
|
@ -7503,72 +7531,72 @@ bool PlayerCondition::Meets(Player const * player) const
|
|||
return false;
|
||||
}
|
||||
case CONDITION_NO_AURA:
|
||||
return !player->HasAura(value1, SpellEffectIndex(value2));
|
||||
return !player->HasAura(m_value1, SpellEffectIndex(m_value2));
|
||||
case CONDITION_ACTIVE_GAME_EVENT:
|
||||
return sGameEventMgr.IsActiveEvent(value1);
|
||||
return sGameEventMgr.IsActiveEvent(m_value1);
|
||||
case CONDITION_AREA_FLAG:
|
||||
{
|
||||
if (AreaTableEntry const *pAreaEntry = GetAreaEntryByAreaID(player->GetAreaId()))
|
||||
{
|
||||
if ((!value1 || (pAreaEntry->flags & value1)) && (!value2 || !(pAreaEntry->flags & value2)))
|
||||
if ((!m_value1 || (pAreaEntry->flags & m_value1)) && (!m_value2 || !(pAreaEntry->flags & m_value2)))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case CONDITION_RACE_CLASS:
|
||||
if ((!value1 || (player->getRaceMask() & value1)) && (!value2 || (player->getClassMask() & value2)))
|
||||
if ((!m_value1 || (player->getRaceMask() & m_value1)) && (!m_value2 || (player->getClassMask() & m_value2)))
|
||||
return true;
|
||||
return false;
|
||||
case CONDITION_LEVEL:
|
||||
{
|
||||
switch(value2)
|
||||
switch(m_value2)
|
||||
{
|
||||
case 0: return player->getLevel() == value1;
|
||||
case 1: return player->getLevel() >= value1;
|
||||
case 2: return player->getLevel() <= value1;
|
||||
case 0: return player->getLevel() == m_value1;
|
||||
case 1: return player->getLevel() >= m_value1;
|
||||
case 2: return player->getLevel() <= m_value1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case CONDITION_NOITEM:
|
||||
return !player->HasItemCount(value1, value2);
|
||||
return !player->HasItemCount(m_value1, m_value2);
|
||||
case CONDITION_SPELL:
|
||||
{
|
||||
switch(value2)
|
||||
switch(m_value2)
|
||||
{
|
||||
case 0: return player->HasSpell(value1);
|
||||
case 1: return !player->HasSpell(value1);
|
||||
case 0: return player->HasSpell(m_value1);
|
||||
case 1: return !player->HasSpell(m_value1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case CONDITION_INSTANCE_SCRIPT:
|
||||
{
|
||||
// have meaning only for specific map instance script so ignore other maps
|
||||
if (player->GetMapId() != value1)
|
||||
if (player->GetMapId() != m_value1)
|
||||
return false;
|
||||
if (InstanceData* data = player->GetInstanceData())
|
||||
return data->CheckConditionCriteriaMeet(player, value1, value2);
|
||||
return data->CheckConditionCriteriaMeet(player, m_value1, m_value2);
|
||||
return false;
|
||||
}
|
||||
case CONDITION_QUESTAVAILABLE:
|
||||
{
|
||||
if (Quest const* quest = sObjectMgr.GetQuestTemplate(value1))
|
||||
if (Quest const* quest = sObjectMgr.GetQuestTemplate(m_value1))
|
||||
return player->CanTakeQuest(quest, false);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
case CONDITION_ACHIEVEMENT:
|
||||
{
|
||||
switch(value2)
|
||||
switch(m_value2)
|
||||
{
|
||||
case 0: return player->GetAchievementMgr().HasAchievement(value1);
|
||||
case 1: return !player->GetAchievementMgr().HasAchievement(value1);
|
||||
case 0: return player->GetAchievementMgr().HasAchievement(m_value1);
|
||||
case 1: return !player->GetAchievementMgr().HasAchievement(m_value1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
case CONDITION_ACHIEVEMENT_REALM:
|
||||
{
|
||||
AchievementEntry const* ach = sAchievementStore.LookupEntry(value1);
|
||||
switch(value2)
|
||||
AchievementEntry const* ach = sAchievementStore.LookupEntry(m_value1);
|
||||
switch(m_value2)
|
||||
{
|
||||
case 0: return sAchievementMgr.IsRealmCompleted(ach);
|
||||
case 1: return !sAchievementMgr.IsRealmCompleted(ach);
|
||||
|
|
@ -7577,39 +7605,39 @@ bool PlayerCondition::Meets(Player const * player) const
|
|||
}
|
||||
case CONDITION_QUEST_NONE:
|
||||
{
|
||||
if (!player->IsCurrentQuest(value1) && !player->GetQuestRewardStatus(value1))
|
||||
if (!player->IsCurrentQuest(m_value1) && !player->GetQuestRewardStatus(m_value1))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
case CONDITION_ITEM_WITH_BANK:
|
||||
return player->HasItemCount(value1, value2, true);
|
||||
return player->HasItemCount(m_value1, m_value2, true);
|
||||
case CONDITION_NOITEM_WITH_BANK:
|
||||
return !player->HasItemCount(value1, value2, true);
|
||||
return !player->HasItemCount(m_value1, m_value2, true);
|
||||
case CONDITION_NOT_ACTIVE_GAME_EVENT:
|
||||
return !sGameEventMgr.IsActiveEvent(value1);
|
||||
return !sGameEventMgr.IsActiveEvent(m_value1);
|
||||
case CONDITION_ACTIVE_HOLIDAY:
|
||||
return sGameEventMgr.IsActiveHoliday(HolidayIds(value1));
|
||||
return sGameEventMgr.IsActiveHoliday(HolidayIds(m_value1));
|
||||
case CONDITION_NOT_ACTIVE_HOLIDAY:
|
||||
return !sGameEventMgr.IsActiveHoliday(HolidayIds(value1));
|
||||
return !sGameEventMgr.IsActiveHoliday(HolidayIds(m_value1));
|
||||
case CONDITION_LEARNABLE_ABILITY:
|
||||
{
|
||||
// Already know the spell
|
||||
if (player->HasSpell(value1))
|
||||
if (player->HasSpell(m_value1))
|
||||
return false;
|
||||
|
||||
// If item defined, check if player has the item already.
|
||||
if (value2)
|
||||
if (m_value2)
|
||||
{
|
||||
// Hard coded item count. This should be ok, since the intention with this condition is to have
|
||||
// a all-in-one check regarding items that learn some ability (primary/secondary tradeskills).
|
||||
// Commonly, items like this is unique and/or are not expected to be obtained more than once.
|
||||
if (player->HasItemCount(value2, 1, true))
|
||||
if (player->HasItemCount(m_value2, 1, true))
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isSkillOk = false;
|
||||
|
||||
SkillLineAbilityMapBounds bounds = sSpellMgr.GetSkillLineAbilityMapBounds(value1);
|
||||
SkillLineAbilityMapBounds bounds = sSpellMgr.GetSkillLineAbilityMapBounds(m_value1);
|
||||
|
||||
for(SkillLineAbilityMap::const_iterator itr = bounds.first; itr != bounds.second; ++itr)
|
||||
{
|
||||
|
|
@ -7644,31 +7672,57 @@ bool PlayerCondition::Meets(Player const * player) const
|
|||
return false;
|
||||
}
|
||||
case CONDITION_SKILL_BELOW:
|
||||
if (value2 == 1)
|
||||
return !player->HasSkill(value1);
|
||||
if (m_value2 == 1)
|
||||
return !player->HasSkill(m_value1);
|
||||
else
|
||||
return player->HasSkill(value1) && player->GetBaseSkillValue(value1) < value2;
|
||||
return player->HasSkill(m_value1) && player->GetBaseSkillValue(m_value1) < m_value2;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Verification of condition values validity
|
||||
bool PlayerCondition::IsValid(ConditionType condition, uint32 value1, uint32 value2)
|
||||
bool PlayerCondition::IsValid(uint16 entry, ConditionType condition, uint32 value1, uint32 value2)
|
||||
{
|
||||
switch(condition)
|
||||
switch (condition)
|
||||
{
|
||||
case CONDITION_OR:
|
||||
case CONDITION_AND:
|
||||
{
|
||||
if (value1 >= entry)
|
||||
{
|
||||
sLog.outErrorDb("And or Or condition (entry %u, type %d) has invalid value1 %u, must be lower than entry, skipped", entry, condition, value1);
|
||||
return false;
|
||||
}
|
||||
if (value2 >= entry)
|
||||
{
|
||||
sLog.outErrorDb("And or Or condition (entry %u, type %d) has invalid value2 %u, must be lower than entry, skipped", entry, condition, value2);
|
||||
return false;
|
||||
}
|
||||
const PlayerCondition* condition1 = sConditionStorage.LookupEntry<PlayerCondition>(value1);
|
||||
if (!condition1)
|
||||
{
|
||||
sLog.outErrorDb("And or Or condition (entry %u, type %d) has value1 %u without proper condition, skipped", entry, condition, value1);
|
||||
return false;
|
||||
}
|
||||
const PlayerCondition* condition2 = sConditionStorage.LookupEntry<PlayerCondition>(value2);
|
||||
if (!condition2)
|
||||
{
|
||||
sLog.outErrorDb("And or Or condition (entry %u, type %d) has value2 %u without proper condition, skipped", entry, condition, value2);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CONDITION_AURA:
|
||||
{
|
||||
if (!sSpellStore.LookupEntry(value1))
|
||||
{
|
||||
sLog.outErrorDb("Aura condition (%u) requires to have non existing spell (Id: %d), skipped", condition, value1);
|
||||
sLog.outErrorDb("Aura condition (entry %u, type %u) requires to have non existing spell (Id: %d), skipped", entry, condition, value1);
|
||||
return false;
|
||||
}
|
||||
if (value2 >= MAX_EFFECT_INDEX)
|
||||
{
|
||||
sLog.outErrorDb("Aura condition (%u) requires to have non existing effect index (%u) (must be 0..%u), skipped",
|
||||
condition, value2, MAX_EFFECT_INDEX-1);
|
||||
sLog.outErrorDb("Aura condition (entry %u, type %u) requires to have non existing effect index (%u) (must be 0..%u), skipped", entry, condition, value2, MAX_EFFECT_INDEX-1);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
|
@ -7681,13 +7735,13 @@ bool PlayerCondition::IsValid(ConditionType condition, uint32 value1, uint32 val
|
|||
ItemPrototype const *proto = ObjectMgr::GetItemPrototype(value1);
|
||||
if (!proto)
|
||||
{
|
||||
sLog.outErrorDb("Item condition (%u) requires to have non existing item (%u), skipped", condition, value1);
|
||||
sLog.outErrorDb("Item condition (entry %u, type %u) requires to have non existing item (%u), skipped", entry, condition, value1);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (value2 < 1)
|
||||
{
|
||||
sLog.outErrorDb("Item condition (%u) useless with count < 1, skipped", condition);
|
||||
sLog.outErrorDb("Item condition (entry %u, type %u) useless with count < 1, skipped", entry, condition);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
|
@ -7697,7 +7751,7 @@ bool PlayerCondition::IsValid(ConditionType condition, uint32 value1, uint32 val
|
|||
ItemPrototype const *proto = ObjectMgr::GetItemPrototype(value1);
|
||||
if (!proto)
|
||||
{
|
||||
sLog.outErrorDb("ItemEquipped condition (%u) requires to have non existing item (%u) equipped, skipped", condition, value1);
|
||||
sLog.outErrorDb("ItemEquipped condition (entry %u, type %u) requires to have non existing item (%u) equipped, skipped", entry, condition, value1);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
|
@ -7707,13 +7761,13 @@ bool PlayerCondition::IsValid(ConditionType condition, uint32 value1, uint32 val
|
|||
AreaTableEntry const* areaEntry = GetAreaEntryByAreaID(value1);
|
||||
if (!areaEntry)
|
||||
{
|
||||
sLog.outErrorDb("Zone condition (%u) requires to be in non existing area (%u), skipped", condition, value1);
|
||||
sLog.outErrorDb("Zone condition (entry %u, type %u) requires to be in non existing area (%u), skipped", entry, condition, value1);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (value2 > 1)
|
||||
{
|
||||
sLog.outErrorDb("Zone condition (%u) has invalid argument %u (must be 0..1), skipped", condition, value2);
|
||||
sLog.outErrorDb("Zone condition (entry %u, type %u) has invalid argument %u (must be 0..1), skipped", entry, condition, value2);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
|
@ -7723,7 +7777,7 @@ bool PlayerCondition::IsValid(ConditionType condition, uint32 value1, uint32 val
|
|||
FactionEntry const* factionEntry = sFactionStore.LookupEntry(value1);
|
||||
if (!factionEntry)
|
||||
{
|
||||
sLog.outErrorDb("Reputation condition (%u) requires to have reputation non existing faction (%u), skipped", condition, value1);
|
||||
sLog.outErrorDb("Reputation condition (entry %u, type %u) requires to have reputation non existing faction (%u), skipped", entry, condition, value1);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
|
@ -7732,7 +7786,7 @@ bool PlayerCondition::IsValid(ConditionType condition, uint32 value1, uint32 val
|
|||
{
|
||||
if (value1 != ALLIANCE && value1 != HORDE)
|
||||
{
|
||||
sLog.outErrorDb("Team condition (%u) specifies unknown team (%u), skipped", condition, value1);
|
||||
sLog.outErrorDb("Team condition (entry %u, type %u) specifies unknown team (%u), skipped", entry, condition, value1);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
|
@ -7743,12 +7797,12 @@ bool PlayerCondition::IsValid(ConditionType condition, uint32 value1, uint32 val
|
|||
SkillLineEntry const *pSkill = sSkillLineStore.LookupEntry(value1);
|
||||
if (!pSkill)
|
||||
{
|
||||
sLog.outErrorDb("Skill condition (%u) specifies non-existing skill (%u), skipped", condition, value1);
|
||||
sLog.outErrorDb("Skill condition (entry %u, type %u) specifies non-existing skill (%u), skipped", entry, condition, value1);
|
||||
return false;
|
||||
}
|
||||
if (value2 < 1 || value2 > sWorld.GetConfigMaxSkillValue() )
|
||||
{
|
||||
sLog.outErrorDb("Skill condition (%u) specifies invalid skill value (%u), skipped", condition, value2);
|
||||
sLog.outErrorDb("Skill condition (entry %u, type %u) specifies invalid skill value (%u), skipped", entry, condition, value2);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
|
@ -7761,32 +7815,32 @@ bool PlayerCondition::IsValid(ConditionType condition, uint32 value1, uint32 val
|
|||
Quest const *Quest = sObjectMgr.GetQuestTemplate(value1);
|
||||
if (!Quest)
|
||||
{
|
||||
sLog.outErrorDb("Quest condition (%u) specifies non-existing quest (%u), skipped", condition, value1);
|
||||
sLog.outErrorDb("Quest condition (entry %u, type %u) specifies non-existing quest (%u), skipped", entry, condition, value1);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (value2 && condition != CONDITION_QUESTTAKEN)
|
||||
sLog.outErrorDb("Quest condition (%u) has useless data in value2 (%u)!", condition, value2);
|
||||
sLog.outErrorDb("Quest condition (entry %u, type %u) has useless data in value2 (%u)!", entry, condition, value2);
|
||||
break;
|
||||
}
|
||||
case CONDITION_AD_COMMISSION_AURA:
|
||||
{
|
||||
if (value1)
|
||||
sLog.outErrorDb("Quest condition (%u) has useless data in value1 (%u)!", condition, value1);
|
||||
sLog.outErrorDb("Quest condition (entry %u, type %u) has useless data in value1 (%u)!", entry, condition, value1);
|
||||
if (value2)
|
||||
sLog.outErrorDb("Quest condition (%u) has useless data in value2 (%u)!", condition, value2);
|
||||
sLog.outErrorDb("Quest condition (entry %u, type %u) has useless data in value2 (%u)!", entry, condition, value2);
|
||||
break;
|
||||
}
|
||||
case CONDITION_NO_AURA:
|
||||
{
|
||||
if (!sSpellStore.LookupEntry(value1))
|
||||
{
|
||||
sLog.outErrorDb("Aura condition (%u) requires to have non existing spell (Id: %d), skipped", condition, value1);
|
||||
sLog.outErrorDb("Aura condition (entry %u, type %u) requires to have non existing spell (Id: %d), skipped", entry, condition, value1);
|
||||
return false;
|
||||
}
|
||||
if (value2 > MAX_EFFECT_INDEX)
|
||||
{
|
||||
sLog.outErrorDb("Aura condition (%u) requires to have non existing effect index (%u) (must be 0..%u), skipped", condition, value2, MAX_EFFECT_INDEX-1);
|
||||
sLog.outErrorDb("Aura condition (entry %u, type %u) requires to have non existing effect index (%u) (must be 0..%u), skipped", entry, condition, value2, MAX_EFFECT_INDEX-1);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
|
@ -7796,7 +7850,7 @@ bool PlayerCondition::IsValid(ConditionType condition, uint32 value1, uint32 val
|
|||
{
|
||||
if (!sGameEventMgr.IsValidEvent(value1))
|
||||
{
|
||||
sLog.outErrorDb("Active event (%u) condition requires existing event id (%u), skipped", condition, value1);
|
||||
sLog.outErrorDb("(Not)Active event condition (entry %u, type %u) requires existing event id (%u), skipped", entry, condition, value1);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
|
@ -7805,7 +7859,7 @@ bool PlayerCondition::IsValid(ConditionType condition, uint32 value1, uint32 val
|
|||
{
|
||||
if (!value1 && !value2)
|
||||
{
|
||||
sLog.outErrorDb("Area flag (%u) condition has both values like 0, skipped", condition);
|
||||
sLog.outErrorDb("Area flag condition (entry %u, type %u) has both values like 0, skipped", entry, condition);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
|
@ -7814,19 +7868,19 @@ bool PlayerCondition::IsValid(ConditionType condition, uint32 value1, uint32 val
|
|||
{
|
||||
if (!value1 && !value2)
|
||||
{
|
||||
sLog.outErrorDb("Race_class condition (%u) has both values like 0, skipped", condition);
|
||||
sLog.outErrorDb("Race_class condition (entry %u, type %u) has both values like 0, skipped", entry, condition);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (value1 && !(value1 & RACEMASK_ALL_PLAYABLE))
|
||||
{
|
||||
sLog.outErrorDb("Race_class condition (%u) has invalid player class %u, skipped", condition, value1);
|
||||
sLog.outErrorDb("Race_class condition (entry %u, type %u) has invalid player class %u, skipped", entry, condition, value1);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (value2 && !(value2 & CLASSMASK_ALL_PLAYABLE))
|
||||
{
|
||||
sLog.outErrorDb("Race_class condition (%u) has invalid race mask %u, skipped", condition, value2);
|
||||
sLog.outErrorDb("Race_class condition (entry %u, type %u) has invalid race mask %u, skipped", entry, condition, value2);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
|
@ -7835,13 +7889,13 @@ bool PlayerCondition::IsValid(ConditionType condition, uint32 value1, uint32 val
|
|||
{
|
||||
if (!value1 || value1 > sWorld.getConfig(CONFIG_UINT32_MAX_PLAYER_LEVEL))
|
||||
{
|
||||
sLog.outErrorDb("Level condition (%u) has invalid level %u, skipped", condition, value1);
|
||||
sLog.outErrorDb("Level condition (entry %u, type %u)has invalid level %u, skipped", entry, condition, value1);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (value2 > 2)
|
||||
{
|
||||
sLog.outErrorDb("Level condition (%u) has invalid argument %u (must be 0..2), skipped", condition, value2);
|
||||
sLog.outErrorDb("Level condition (entry %u, type %u) has invalid argument %u (must be 0..2), skipped", entry, condition, value2);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -7851,13 +7905,13 @@ bool PlayerCondition::IsValid(ConditionType condition, uint32 value1, uint32 val
|
|||
{
|
||||
if (!sSpellStore.LookupEntry(value1))
|
||||
{
|
||||
sLog.outErrorDb("Spell condition (%u) requires to have non existing spell (Id: %d), skipped", condition, value1);
|
||||
sLog.outErrorDb("Spell condition (entry %u, type %u) requires to have non existing spell (Id: %d), skipped", entry, condition, value1);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (value2 > 1)
|
||||
{
|
||||
sLog.outErrorDb("Spell condition (%u) has invalid argument %u (must be 0..1), skipped", condition, value2);
|
||||
sLog.outErrorDb("Spell condition (entry %u, type %u) has invalid argument %u (must be 0..1), skipped", entry, condition, value2);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -7868,7 +7922,7 @@ bool PlayerCondition::IsValid(ConditionType condition, uint32 value1, uint32 val
|
|||
MapEntry const* mapEntry = sMapStore.LookupEntry(value1);
|
||||
if (!mapEntry || !mapEntry->IsDungeon())
|
||||
{
|
||||
sLog.outErrorDb("Instance script condition (%u) has nonexistent map id %u as first arg, skipped", condition, value1);
|
||||
sLog.outErrorDb("Instance script condition (entry %u, type %u) has nonexistent map id %u as first arg, skipped", entry, condition, value1);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -7879,13 +7933,13 @@ bool PlayerCondition::IsValid(ConditionType condition, uint32 value1, uint32 val
|
|||
{
|
||||
if (!sAchievementStore.LookupEntry(value1))
|
||||
{
|
||||
sLog.outErrorDb("Achievement condition (%u) requires to have non existing achievement (Id: %d), skipped", condition, value1);
|
||||
sLog.outErrorDb("Achievement condition (entry %u, type %u) requires to have non existing achievement (Id: %d), skipped", entry, condition, value1);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (value2 > 1)
|
||||
{
|
||||
sLog.outErrorDb("Achievement condition (%u) has invalid argument %u (must be 0..1), skipped", condition, value2);
|
||||
sLog.outErrorDb("Achievement condition (entry %u, type %u) has invalid argument %u (must be 0..1), skipped", entry, condition, value2);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -7896,7 +7950,7 @@ bool PlayerCondition::IsValid(ConditionType condition, uint32 value1, uint32 val
|
|||
{
|
||||
if (!sHolidaysStore.LookupEntry(value1))
|
||||
{
|
||||
sLog.outErrorDb("Active holiday (%u) condition requires existing holiday id (%u), skipped", condition, value1);
|
||||
sLog.outErrorDb("(Not)Active holiday condition (entry %u, type %u) requires existing holiday id (%u), skipped", entry, condition, value1);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
|
@ -7907,7 +7961,7 @@ bool PlayerCondition::IsValid(ConditionType condition, uint32 value1, uint32 val
|
|||
|
||||
if (bounds.first == bounds.second)
|
||||
{
|
||||
sLog.outErrorDb("CONDITION_LEARNABLE_ABILITY (%u) has spell id %u defined, but this spell is not listed in SkillLineAbility and can not be used, skipping.", condition, value1);
|
||||
sLog.outErrorDb("Learnable ability conditon (entry %u, type %u) has spell id %u defined, but this spell is not listed in SkillLineAbility and can not be used, skipping.", entry, condition, value1);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -7916,7 +7970,7 @@ bool PlayerCondition::IsValid(ConditionType condition, uint32 value1, uint32 val
|
|||
ItemPrototype const *proto = ObjectMgr::GetItemPrototype(value2);
|
||||
if (!proto)
|
||||
{
|
||||
sLog.outErrorDb("CONDITION_LEARNABLE_ABILITY (%u) has item entry %u defined but item does not exist, skipping.", condition, value2);
|
||||
sLog.outErrorDb("Learnable ability conditon (entry %u, type %u) has item entry %u defined but item does not exist, skipping.", entry, condition, value2);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -7926,7 +7980,7 @@ bool PlayerCondition::IsValid(ConditionType condition, uint32 value1, uint32 val
|
|||
case CONDITION_NONE:
|
||||
break;
|
||||
default:
|
||||
sLog.outErrorDb("Condition has bad type of %u, skipped ", condition);
|
||||
sLog.outErrorDb("Condition entry %u has bad type of %d, skipped ", entry, condition);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
@ -8488,8 +8542,8 @@ void ObjectMgr::LoadGossipMenu(std::set<uint32>& gossipScriptSet)
|
|||
m_mGossipMenusMap.clear();
|
||||
// 0 1 2
|
||||
QueryResult* result = WorldDatabase.Query("SELECT entry, text_id, script_id, "
|
||||
// 3 4 5 6 7 8
|
||||
"cond_1, cond_1_val_1, cond_1_val_2, cond_2, cond_2_val_1, cond_2_val_2 FROM gossip_menu");
|
||||
// 3 4 5 6 7 8 9
|
||||
"cond_1, cond_1_val_1, cond_1_val_2, cond_2, cond_2_val_1, cond_2_val_2, condition_id FROM gossip_menu");
|
||||
|
||||
if (!result)
|
||||
{
|
||||
|
|
@ -8525,6 +8579,8 @@ void ObjectMgr::LoadGossipMenu(std::set<uint32>& gossipScriptSet)
|
|||
uint32 cond_2_val_1 = fields[7].GetUInt32();
|
||||
uint32 cond_2_val_2 = fields[8].GetUInt32();
|
||||
|
||||
gMenu.conditionId = fields[9].GetUInt16();
|
||||
|
||||
if (!GetGossipText(gMenu.text_id))
|
||||
{
|
||||
sLog.outErrorDb("Table gossip_menu entry %u are using non-existing text_id %u", gMenu.entry, gMenu.text_id);
|
||||
|
|
@ -8544,13 +8600,13 @@ void ObjectMgr::LoadGossipMenu(std::set<uint32>& gossipScriptSet)
|
|||
gossipScriptSet.erase(gMenu.script_id);
|
||||
}
|
||||
|
||||
if (!PlayerCondition::IsValid(cond_1, cond_1_val_1, cond_1_val_2))
|
||||
if (!PlayerCondition::IsValid(0, cond_1, cond_1_val_1, cond_1_val_2))
|
||||
{
|
||||
sLog.outErrorDb("Table gossip_menu entry %u, invalid condition 1 for id %u", gMenu.entry, gMenu.text_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!PlayerCondition::IsValid(cond_2, cond_2_val_1, cond_2_val_2))
|
||||
if (!PlayerCondition::IsValid(0, cond_2, cond_2_val_1, cond_2_val_2))
|
||||
{
|
||||
sLog.outErrorDb("Table gossip_menu entry %u, invalid condition 2 for id %u", gMenu.entry, gMenu.text_id);
|
||||
continue;
|
||||
|
|
@ -8559,6 +8615,16 @@ void ObjectMgr::LoadGossipMenu(std::set<uint32>& gossipScriptSet)
|
|||
gMenu.cond_1 = GetConditionId(cond_1, cond_1_val_1, cond_1_val_2);
|
||||
gMenu.cond_2 = GetConditionId(cond_2, cond_2_val_1, cond_2_val_2);
|
||||
|
||||
if (gMenu.conditionId)
|
||||
{
|
||||
const PlayerCondition* condition = sConditionStorage.LookupEntry<PlayerCondition>(gMenu.conditionId);
|
||||
if (!condition)
|
||||
{
|
||||
sLog.outErrorDb("Table gossip_menu for menu %u, text-id %u has condition_id %u that does not exist in `conditions`, ignoring", gMenu.entry, gMenu.text_id, gMenu.conditionId);
|
||||
gMenu.conditionId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
m_mGossipMenusMap.insert(GossipMenusMap::value_type(gMenu.entry, gMenu));
|
||||
|
||||
++count;
|
||||
|
|
@ -8593,7 +8659,7 @@ void ObjectMgr::LoadGossipMenuItems(std::set<uint32>& gossipScriptSet)
|
|||
"action_menu_id, action_poi_id, action_script_id, box_coded, box_money, box_text, "
|
||||
"cond_1, cond_1_val_1, cond_1_val_2, "
|
||||
"cond_2, cond_2_val_1, cond_2_val_2, "
|
||||
"cond_3, cond_3_val_1, cond_3_val_2 "
|
||||
"cond_3, cond_3_val_1, cond_3_val_2, condition_id "
|
||||
"FROM gossip_menu_option");
|
||||
|
||||
if (!result)
|
||||
|
|
@ -8664,6 +8730,7 @@ void ObjectMgr::LoadGossipMenuItems(std::set<uint32>& gossipScriptSet)
|
|||
ConditionType cond_3 = (ConditionType)fields[18].GetUInt32();
|
||||
uint32 cond_3_val_1 = fields[19].GetUInt32();
|
||||
uint32 cond_3_val_2 = fields[20].GetUInt32();
|
||||
gMenuItem.conditionId = fields[21].GetUInt16();
|
||||
|
||||
if (gMenuItem.menu_id) // == 0 id is special and not have menu_id data
|
||||
{
|
||||
|
|
@ -8674,17 +8741,17 @@ void ObjectMgr::LoadGossipMenuItems(std::set<uint32>& gossipScriptSet)
|
|||
}
|
||||
}
|
||||
|
||||
if (!PlayerCondition::IsValid(cond_1, cond_1_val_1, cond_1_val_2))
|
||||
if (!PlayerCondition::IsValid(0, cond_1, cond_1_val_1, cond_1_val_2))
|
||||
{
|
||||
sLog.outErrorDb("Table gossip_menu_option menu %u, invalid condition 1 for id %u", gMenuItem.menu_id, gMenuItem.id);
|
||||
continue;
|
||||
}
|
||||
if (!PlayerCondition::IsValid(cond_2, cond_2_val_1, cond_2_val_2))
|
||||
if (!PlayerCondition::IsValid(0, cond_2, cond_2_val_1, cond_2_val_2))
|
||||
{
|
||||
sLog.outErrorDb("Table gossip_menu_option menu %u, invalid condition 2 for id %u", gMenuItem.menu_id, gMenuItem.id);
|
||||
continue;
|
||||
}
|
||||
if (!PlayerCondition::IsValid(cond_3, cond_3_val_1, cond_3_val_2))
|
||||
if (!PlayerCondition::IsValid(0, cond_3, cond_3_val_1, cond_3_val_2))
|
||||
{
|
||||
sLog.outErrorDb("Table gossip_menu_option menu %u, invalid condition 3 for id %u", gMenuItem.menu_id, gMenuItem.id);
|
||||
continue;
|
||||
|
|
@ -8757,6 +8824,16 @@ void ObjectMgr::LoadGossipMenuItems(std::set<uint32>& gossipScriptSet)
|
|||
gMenuItem.cond_2 = GetConditionId(cond_2, cond_2_val_1, cond_2_val_2);
|
||||
gMenuItem.cond_3 = GetConditionId(cond_3, cond_3_val_1, cond_3_val_2);
|
||||
|
||||
if (gMenuItem.conditionId)
|
||||
{
|
||||
const PlayerCondition* condition = sConditionStorage.LookupEntry<PlayerCondition>(gMenuItem.conditionId);
|
||||
if (!condition)
|
||||
{
|
||||
sLog.outErrorDb("Table gossip_menu_option for menu %u, id %u has condition_id %u that does not exist in `conditions`, ignoring", gMenuItem.menu_id, gMenuItem.id, gMenuItem.conditionId);
|
||||
gMenuItem.conditionId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
m_mGossipMenuItemsMap.insert(GossipMenuItemsMap::value_type(gMenuItem.menu_id, gMenuItem));
|
||||
|
||||
++count;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue