Core/SpellAreas: Changed the way quest_start and quest_end works.
They now follow this rule: The player's quest status of quest_start must have the mask defined in quest_start_status in order for the spell to be applied/kept. The player's quest status of quest_end must _NOT_ have the mask defined in quest_end_status in order for the spell to be removed To generate the mask: Take the QuestStatus enum in QuestDef.h, use (1 << theValueYouWant) to obtain a mask and you can use | to combine masks. This expands the usage of the spell_area table, making possible to give a player an aura while he has a quest, but remove it as soon as the quest is completed (not rewarded). Feature request by @Svannon
This commit is contained in:
@@ -0,0 +1,4 @@
|
|||||||
|
ALTER TABLE `spell_area` ADD COLUMN `quest_start_status` INT(11) NOT NULL DEFAULT 64; -- default is QUEST_STATUS_REWARDED
|
||||||
|
ALTER TABLE `spell_area` ADD COLUMN `quest_end_status` INT(11) NOT NULL DEFAULT 11; -- default is QUEST_STATUS_COMPLETE | QUEST_STATUS_NONE | QUEST_STATUS_INCOMPLETE
|
||||||
|
UPDATE spell_area SET `quest_start_status` = (1 << 6) | (1 << 3) | (1 << 1) WHERE `quest_start_active` = 1;
|
||||||
|
ALTER TABLE spell_area DROP COLUMN `quest_start_active`;
|
||||||
@@ -14980,19 +14980,6 @@ void Player::AddQuest(Quest const* quest, Object* questGiver)
|
|||||||
if (questGiver && quest->GetQuestStartScript() != 0)
|
if (questGiver && quest->GetQuestStartScript() != 0)
|
||||||
GetMap()->ScriptsStart(sQuestStartScripts, quest->GetQuestStartScript(), questGiver, this);
|
GetMap()->ScriptsStart(sQuestStartScripts, quest->GetQuestStartScript(), questGiver, this);
|
||||||
|
|
||||||
// Some spells applied at quest activation
|
|
||||||
SpellAreaForQuestMapBounds saBounds = sSpellMgr->GetSpellAreaForQuestMapBounds(quest_id, true);
|
|
||||||
if (saBounds.first != saBounds.second)
|
|
||||||
{
|
|
||||||
uint32 zone, area;
|
|
||||||
GetZoneAndAreaId(zone, area);
|
|
||||||
|
|
||||||
for (SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
|
|
||||||
if (itr->second->autocast && itr->second->IsFitToRequirements(this, zone, area))
|
|
||||||
if (!HasAura(itr->second->spellId))
|
|
||||||
CastSpell(this, itr->second->spellId, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateForQuestWorldObjects();
|
UpdateForQuestWorldObjects();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -15181,33 +15168,6 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
|
|||||||
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT);
|
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT);
|
||||||
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST, quest->GetQuestId());
|
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST, quest->GetQuestId());
|
||||||
|
|
||||||
uint32 zone = 0;
|
|
||||||
uint32 area = 0;
|
|
||||||
|
|
||||||
// remove auras from spells with quest reward state limitations
|
|
||||||
SpellAreaForQuestMapBounds saEndBounds = sSpellMgr->GetSpellAreaForQuestEndMapBounds(quest_id);
|
|
||||||
if (saEndBounds.first != saEndBounds.second)
|
|
||||||
{
|
|
||||||
GetZoneAndAreaId(zone, area);
|
|
||||||
|
|
||||||
for (SpellAreaForAreaMap::const_iterator itr = saEndBounds.first; itr != saEndBounds.second; ++itr)
|
|
||||||
if (!itr->second->IsFitToRequirements(this, zone, area))
|
|
||||||
RemoveAurasDueToSpell(itr->second->spellId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Some spells applied at quest reward
|
|
||||||
SpellAreaForQuestMapBounds saBounds = sSpellMgr->GetSpellAreaForQuestMapBounds(quest_id, false);
|
|
||||||
if (saBounds.first != saBounds.second)
|
|
||||||
{
|
|
||||||
if (!zone || !area)
|
|
||||||
GetZoneAndAreaId(zone, area);
|
|
||||||
|
|
||||||
for (SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
|
|
||||||
if (itr->second->autocast && itr->second->IsFitToRequirements(this, zone, area))
|
|
||||||
if (!HasAura(itr->second->spellId))
|
|
||||||
CastSpell(this, itr->second->spellId, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
//lets remove flag for delayed teleports
|
//lets remove flag for delayed teleports
|
||||||
SetCanDelayTeleport(false);
|
SetCanDelayTeleport(false);
|
||||||
}
|
}
|
||||||
@@ -15750,6 +15710,30 @@ void Player::SetQuestStatus(uint32 quest_id, QuestStatus status)
|
|||||||
m_QuestStatusSave[quest_id] = true;
|
m_QuestStatusSave[quest_id] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32 zone = 0, area = 0;
|
||||||
|
|
||||||
|
SpellAreaForQuestMapBounds saBounds = sSpellMgr->GetSpellAreaForQuestMapBounds(quest_id);
|
||||||
|
if (saBounds.first != saBounds.second)
|
||||||
|
{
|
||||||
|
GetZoneAndAreaId(zone, area);
|
||||||
|
|
||||||
|
for (SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
|
||||||
|
if (itr->second->autocast && itr->second->IsFitToRequirements(this, zone, area))
|
||||||
|
if (!HasAura(itr->second->spellId))
|
||||||
|
CastSpell(this, itr->second->spellId, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
saBounds = sSpellMgr->GetSpellAreaForQuestEndMapBounds(quest_id);
|
||||||
|
if (saBounds.first != saBounds.second)
|
||||||
|
{
|
||||||
|
if (!zone || !area)
|
||||||
|
GetZoneAndAreaId(zone, area);
|
||||||
|
|
||||||
|
for (SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
|
||||||
|
if (!itr->second->IsFitToRequirements(this, zone, area))
|
||||||
|
RemoveAurasDueToSpell(itr->second->spellId);
|
||||||
|
}
|
||||||
|
|
||||||
UpdateForQuestWorldObjects();
|
UpdateForQuestWorldObjects();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1061,11 +1061,8 @@ SpellAreaMapBounds SpellMgr::GetSpellAreaMapBounds(uint32 spell_id) const
|
|||||||
return SpellAreaMapBounds(mSpellAreaMap.lower_bound(spell_id), mSpellAreaMap.upper_bound(spell_id));
|
return SpellAreaMapBounds(mSpellAreaMap.lower_bound(spell_id), mSpellAreaMap.upper_bound(spell_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
SpellAreaForQuestMapBounds SpellMgr::GetSpellAreaForQuestMapBounds(uint32 quest_id, bool active) const
|
SpellAreaForQuestMapBounds SpellMgr::GetSpellAreaForQuestMapBounds(uint32 quest_id) const
|
||||||
{
|
{
|
||||||
if (active)
|
|
||||||
return SpellAreaForQuestMapBounds(mSpellAreaForActiveQuestMap.lower_bound(quest_id), mSpellAreaForActiveQuestMap.upper_bound(quest_id));
|
|
||||||
else
|
|
||||||
return SpellAreaForQuestMapBounds(mSpellAreaForQuestMap.lower_bound(quest_id), mSpellAreaForQuestMap.upper_bound(quest_id));
|
return SpellAreaForQuestMapBounds(mSpellAreaForQuestMap.lower_bound(quest_id), mSpellAreaForQuestMap.upper_bound(quest_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1099,11 +1096,11 @@ bool SpellArea::IsFitToRequirements(Player const* player, uint32 newZone, uint32
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (questStart) // not in expected required quest state
|
if (questStart) // not in expected required quest state
|
||||||
if (!player || ((!questStartCanActive || !player->IsActiveQuest(questStart)) && !player->GetQuestRewardStatus(questStart)))
|
if (!player || (((1 << player->GetQuestStatus(questStart)) & questStartStatus) == 0))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (questEnd) // not in expected forbidden quest state
|
if (questEnd) // not in expected forbidden quest state
|
||||||
if (!player || player->GetQuestRewardStatus(questEnd))
|
if (!player || (((1 << player->GetQuestStatus(questEnd)) & questEndStatus) == 0))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (auraSpell) // not have expected aura
|
if (auraSpell) // not have expected aura
|
||||||
@@ -2433,12 +2430,11 @@ void SpellMgr::LoadSpellAreas()
|
|||||||
|
|
||||||
mSpellAreaMap.clear(); // need for reload case
|
mSpellAreaMap.clear(); // need for reload case
|
||||||
mSpellAreaForQuestMap.clear();
|
mSpellAreaForQuestMap.clear();
|
||||||
mSpellAreaForActiveQuestMap.clear();
|
|
||||||
mSpellAreaForQuestEndMap.clear();
|
mSpellAreaForQuestEndMap.clear();
|
||||||
mSpellAreaForAuraMap.clear();
|
mSpellAreaForAuraMap.clear();
|
||||||
|
|
||||||
// 0 1 2 3 4 5 6 7 8
|
// 0 1 2 3 4 5 6 7 8 9
|
||||||
QueryResult result = WorldDatabase.Query("SELECT spell, area, quest_start, quest_start_active, quest_end, aura_spell, racemask, gender, autocast FROM spell_area");
|
QueryResult result = WorldDatabase.Query("SELECT spell, area, quest_start, quest_start_status, quest_end_status, quest_end, aura_spell, racemask, gender, autocast FROM spell_area");
|
||||||
|
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
@@ -2457,12 +2453,13 @@ void SpellMgr::LoadSpellAreas()
|
|||||||
spellArea.spellId = spell;
|
spellArea.spellId = spell;
|
||||||
spellArea.areaId = fields[1].GetUInt32();
|
spellArea.areaId = fields[1].GetUInt32();
|
||||||
spellArea.questStart = fields[2].GetUInt32();
|
spellArea.questStart = fields[2].GetUInt32();
|
||||||
spellArea.questStartCanActive = fields[3].GetBool();
|
spellArea.questStartStatus = fields[3].GetUInt32();
|
||||||
spellArea.questEnd = fields[4].GetUInt32();
|
spellArea.questEndStatus = fields[4].GetUInt32();
|
||||||
spellArea.auraSpell = fields[5].GetInt32();
|
spellArea.questEnd = fields[5].GetUInt32();
|
||||||
spellArea.raceMask = fields[6].GetUInt32();
|
spellArea.auraSpell = fields[6].GetInt32();
|
||||||
spellArea.gender = Gender(fields[7].GetUInt8());
|
spellArea.raceMask = fields[7].GetUInt32();
|
||||||
spellArea.autocast = fields[8].GetBool();
|
spellArea.gender = Gender(fields[8].GetUInt8());
|
||||||
|
spellArea.autocast = fields[9].GetBool();
|
||||||
|
|
||||||
if (SpellInfo const* spellInfo = GetSpellInfo(spell))
|
if (SpellInfo const* spellInfo = GetSpellInfo(spell))
|
||||||
{
|
{
|
||||||
@@ -2494,7 +2491,7 @@ void SpellMgr::LoadSpellAreas()
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// duplicate by requirements
|
// duplicate by requirements
|
||||||
ok =false;
|
ok = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2524,12 +2521,6 @@ void SpellMgr::LoadSpellAreas()
|
|||||||
sLog->outError(LOG_FILTER_SQL, "Spell %u listed in `spell_area` have wrong end quest (%u) requirement", spell, spellArea.questEnd);
|
sLog->outError(LOG_FILTER_SQL, "Spell %u listed in `spell_area` have wrong end quest (%u) requirement", spell, spellArea.questEnd);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spellArea.questEnd == spellArea.questStart && !spellArea.questStartCanActive)
|
|
||||||
{
|
|
||||||
sLog->outError(LOG_FILTER_SQL, "Spell %u listed in `spell_area` have quest (%u) requirement for start and end in same time", spell, spellArea.questEnd);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spellArea.auraSpell)
|
if (spellArea.auraSpell)
|
||||||
@@ -2605,12 +2596,7 @@ void SpellMgr::LoadSpellAreas()
|
|||||||
|
|
||||||
// for search at quest start/reward
|
// for search at quest start/reward
|
||||||
if (spellArea.questStart)
|
if (spellArea.questStart)
|
||||||
{
|
|
||||||
if (spellArea.questStartCanActive)
|
|
||||||
mSpellAreaForActiveQuestMap.insert(SpellAreaForQuestMap::value_type(spellArea.questStart, sa));
|
|
||||||
else
|
|
||||||
mSpellAreaForQuestMap.insert(SpellAreaForQuestMap::value_type(spellArea.questStart, sa));
|
mSpellAreaForQuestMap.insert(SpellAreaForQuestMap::value_type(spellArea.questStart, sa));
|
||||||
}
|
|
||||||
|
|
||||||
// for search at quest start/reward
|
// for search at quest start/reward
|
||||||
if (spellArea.questEnd)
|
if (spellArea.questEnd)
|
||||||
|
|||||||
@@ -495,7 +495,8 @@ struct SpellArea
|
|||||||
int32 auraSpell; // spell aura must be applied for spell apply)if possitive) and it must not be applied in other case
|
int32 auraSpell; // spell aura must be applied for spell apply)if possitive) and it must not be applied in other case
|
||||||
uint32 raceMask; // can be applied only to races
|
uint32 raceMask; // can be applied only to races
|
||||||
Gender gender; // can be applied only to gender
|
Gender gender; // can be applied only to gender
|
||||||
bool questStartCanActive; // if true then quest start can be active (not only rewarded)
|
uint32 questStartStatus; // QuestStatus that quest_start must have in order to keep the spell
|
||||||
|
uint32 questEndStatus; // QuestStatus that the quest_end must have in order to keep the spell (if the quest_end's status is different than this, the spell will be dropped)
|
||||||
bool autocast; // if true then auto applied at area enter, in other case just allowed to cast
|
bool autocast; // if true then auto applied at area enter, in other case just allowed to cast
|
||||||
|
|
||||||
// helpers
|
// helpers
|
||||||
@@ -681,7 +682,7 @@ class SpellMgr
|
|||||||
|
|
||||||
// Spell area
|
// Spell area
|
||||||
SpellAreaMapBounds GetSpellAreaMapBounds(uint32 spell_id) const;
|
SpellAreaMapBounds GetSpellAreaMapBounds(uint32 spell_id) const;
|
||||||
SpellAreaForQuestMapBounds GetSpellAreaForQuestMapBounds(uint32 quest_id, bool active) const;
|
SpellAreaForQuestMapBounds GetSpellAreaForQuestMapBounds(uint32 quest_id) const;
|
||||||
SpellAreaForQuestMapBounds GetSpellAreaForQuestEndMapBounds(uint32 quest_id) const;
|
SpellAreaForQuestMapBounds GetSpellAreaForQuestEndMapBounds(uint32 quest_id) const;
|
||||||
SpellAreaForAuraMapBounds GetSpellAreaForAuraMapBounds(uint32 spell_id) const;
|
SpellAreaForAuraMapBounds GetSpellAreaForAuraMapBounds(uint32 spell_id) const;
|
||||||
SpellAreaForAreaMapBounds GetSpellAreaForAreaMapBounds(uint32 area_id) const;
|
SpellAreaForAreaMapBounds GetSpellAreaForAreaMapBounds(uint32 area_id) const;
|
||||||
@@ -740,7 +741,6 @@ class SpellMgr
|
|||||||
EnchantCustomAttribute mEnchantCustomAttr;
|
EnchantCustomAttribute mEnchantCustomAttr;
|
||||||
SpellAreaMap mSpellAreaMap;
|
SpellAreaMap mSpellAreaMap;
|
||||||
SpellAreaForQuestMap mSpellAreaForQuestMap;
|
SpellAreaForQuestMap mSpellAreaForQuestMap;
|
||||||
SpellAreaForQuestMap mSpellAreaForActiveQuestMap;
|
|
||||||
SpellAreaForQuestMap mSpellAreaForQuestEndMap;
|
SpellAreaForQuestMap mSpellAreaForQuestEndMap;
|
||||||
SpellAreaForAuraMap mSpellAreaForAuraMap;
|
SpellAreaForAuraMap mSpellAreaForAuraMap;
|
||||||
SpellAreaForAreaMap mSpellAreaForAreaMap;
|
SpellAreaForAreaMap mSpellAreaForAreaMap;
|
||||||
|
|||||||
Reference in New Issue
Block a user