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)
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -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, 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
|
||||
SetCanDelayTeleport(false);
|
||||
}
|
||||
@@ -15750,6 +15710,30 @@ void Player::SetQuestStatus(uint32 quest_id, QuestStatus status)
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
@@ -1061,11 +1061,8 @@ SpellAreaMapBounds SpellMgr::GetSpellAreaMapBounds(uint32 spell_id) const
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -1099,11 +1096,11 @@ bool SpellArea::IsFitToRequirements(Player const* player, uint32 newZone, uint32
|
||||
return false;
|
||||
|
||||
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;
|
||||
|
||||
if (questEnd) // not in expected forbidden quest state
|
||||
if (!player || player->GetQuestRewardStatus(questEnd))
|
||||
if (!player || (((1 << player->GetQuestStatus(questEnd)) & questEndStatus) == 0))
|
||||
return false;
|
||||
|
||||
if (auraSpell) // not have expected aura
|
||||
@@ -2433,12 +2430,11 @@ void SpellMgr::LoadSpellAreas()
|
||||
|
||||
mSpellAreaMap.clear(); // need for reload case
|
||||
mSpellAreaForQuestMap.clear();
|
||||
mSpellAreaForActiveQuestMap.clear();
|
||||
mSpellAreaForQuestEndMap.clear();
|
||||
mSpellAreaForAuraMap.clear();
|
||||
|
||||
// 0 1 2 3 4 5 6 7 8
|
||||
QueryResult result = WorldDatabase.Query("SELECT spell, area, quest_start, quest_start_active, quest_end, aura_spell, racemask, gender, autocast FROM spell_area");
|
||||
// 0 1 2 3 4 5 6 7 8 9
|
||||
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)
|
||||
{
|
||||
@@ -2457,12 +2453,13 @@ void SpellMgr::LoadSpellAreas()
|
||||
spellArea.spellId = spell;
|
||||
spellArea.areaId = fields[1].GetUInt32();
|
||||
spellArea.questStart = fields[2].GetUInt32();
|
||||
spellArea.questStartCanActive = fields[3].GetBool();
|
||||
spellArea.questEnd = fields[4].GetUInt32();
|
||||
spellArea.auraSpell = fields[5].GetInt32();
|
||||
spellArea.raceMask = fields[6].GetUInt32();
|
||||
spellArea.gender = Gender(fields[7].GetUInt8());
|
||||
spellArea.autocast = fields[8].GetBool();
|
||||
spellArea.questStartStatus = fields[3].GetUInt32();
|
||||
spellArea.questEndStatus = fields[4].GetUInt32();
|
||||
spellArea.questEnd = fields[5].GetUInt32();
|
||||
spellArea.auraSpell = fields[6].GetInt32();
|
||||
spellArea.raceMask = fields[7].GetUInt32();
|
||||
spellArea.gender = Gender(fields[8].GetUInt8());
|
||||
spellArea.autocast = fields[9].GetBool();
|
||||
|
||||
if (SpellInfo const* spellInfo = GetSpellInfo(spell))
|
||||
{
|
||||
@@ -2494,7 +2491,7 @@ void SpellMgr::LoadSpellAreas()
|
||||
continue;
|
||||
|
||||
// duplicate by requirements
|
||||
ok =false;
|
||||
ok = false;
|
||||
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);
|
||||
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)
|
||||
@@ -2605,12 +2596,7 @@ void SpellMgr::LoadSpellAreas()
|
||||
|
||||
// for search at quest start/reward
|
||||
if (spellArea.questStart)
|
||||
{
|
||||
if (spellArea.questStartCanActive)
|
||||
mSpellAreaForActiveQuestMap.insert(SpellAreaForQuestMap::value_type(spellArea.questStart, sa));
|
||||
else
|
||||
mSpellAreaForQuestMap.insert(SpellAreaForQuestMap::value_type(spellArea.questStart, sa));
|
||||
}
|
||||
|
||||
// for search at quest start/reward
|
||||
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
|
||||
uint32 raceMask; // can be applied only to races
|
||||
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
|
||||
|
||||
// helpers
|
||||
@@ -681,7 +682,7 @@ class SpellMgr
|
||||
|
||||
// Spell area
|
||||
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;
|
||||
SpellAreaForAuraMapBounds GetSpellAreaForAuraMapBounds(uint32 spell_id) const;
|
||||
SpellAreaForAreaMapBounds GetSpellAreaForAreaMapBounds(uint32 area_id) const;
|
||||
@@ -740,7 +741,6 @@ class SpellMgr
|
||||
EnchantCustomAttribute mEnchantCustomAttr;
|
||||
SpellAreaMap mSpellAreaMap;
|
||||
SpellAreaForQuestMap mSpellAreaForQuestMap;
|
||||
SpellAreaForQuestMap mSpellAreaForActiveQuestMap;
|
||||
SpellAreaForQuestMap mSpellAreaForQuestEndMap;
|
||||
SpellAreaForAuraMap mSpellAreaForAuraMap;
|
||||
SpellAreaForAreaMap mSpellAreaForAreaMap;
|
||||
|
||||
Reference in New Issue
Block a user