Core/Spells: Allow skipping automatic removal of auras from spell_area when condition is no longer met (mostly used for cosmetic cutscenes after quest completion)

This commit is contained in:
funjoker authored and Ovahlord committed 2020-01-11 03:38:28 +01:00
1 parent 131986d1c2
commit 590ad14856
5 files changed
+21 -13

No files matched your search

@@ -0,0 +1,2 @@
ALTER TABLE `spell_area` CHANGE `autocast` `flags` TINYINT(3) UNSIGNED NOT NULL DEFAULT '3' AFTER `gender`;
UPDATE `spell_area` SET `flags`=`flags` | 2;
+4 -4
View File
@@ -16190,9 +16190,9 @@ void Player::SendQuestUpdate(uint32 questId)
{
for (SpellAreaForQuestAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
{
if (!itr->second->IsFitToRequirements(this, zone, area))
if (itr->second->flags & SPELL_AREA_FLAG_AUTOREMOVE && !itr->second->IsFitToRequirements(this, zone, area))
RemoveAurasDueToSpell(itr->second->spellId);
else if (itr->second->autocast)
else if (itr->second->flags & SPELL_AREA_FLAG_AUTOCAST)
if (!HasAura(itr->second->spellId))
CastSpell(this, itr->second->spellId, true);
}
@@ -25190,7 +25190,7 @@ void Player::UpdateZoneDependentAuras(uint32 newZone)
// Some spells applied at enter into zone (with subzones), aura removed in UpdateAreaDependentAuras that called always at zone->area update
SpellAreaForAreaMapBounds saBounds = sSpellMgr->GetSpellAreaForAreaMapBounds(newZone);
for (SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
if (itr->second->autocast && itr->second->IsFitToRequirements(this, newZone, 0))
if (itr->second->flags & SPELL_AREA_FLAG_AUTOCAST && itr->second->IsFitToRequirements(this, newZone, 0))
if (!HasAura(itr->second->spellId))
CastSpell(this, itr->second->spellId, true);
}
@@ -25210,7 +25210,7 @@ void Player::UpdateAreaDependentAuras(uint32 newArea)
// some auras applied at subzone enter
SpellAreaForAreaMapBounds saBounds = sSpellMgr->GetSpellAreaForAreaMapBounds(newArea);
for (SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
if (itr->second->autocast && itr->second->IsFitToRequirements(this, m_zoneUpdateId, newArea))
if (itr->second->flags & SPELL_AREA_FLAG_AUTOCAST && itr->second->IsFitToRequirements(this, m_zoneUpdateId, newArea))
if (!HasAura(itr->second->spellId))
CastSpell(this, itr->second->spellId, true);
}
+2 -2
View File
@@ -1183,10 +1183,10 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
for (SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
{
// some auras remove at aura remove
if (!itr->second->IsFitToRequirements(target->ToPlayer(), zone, area))
if (itr->second->flags & SPELL_AREA_FLAG_AUTOREMOVE && !itr->second->IsFitToRequirements(target->ToPlayer(), zone, area))
target->RemoveAurasDueToSpell(itr->second->spellId);
// some auras applied at aura apply
else if (itr->second->autocast)
else if (itr->second->flags & SPELL_AREA_FLAG_AUTOCAST)
{
if (!target->HasAura(itr->second->spellId))
target->CastSpell(target, itr->second->spellId, true);
+6 -6
View File
@@ -2435,7 +2435,7 @@ void SpellMgr::LoadSpellAreas()
mSpellAreaForQuestAreaMap.clear();
// 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");
QueryResult result = WorldDatabase.Query("SELECT spell, area, quest_start, quest_start_status, quest_end_status, quest_end, aura_spell, racemask, gender, flags FROM spell_area");
if (!result)
{
TC_LOG_INFO("server.loading", ">> Loaded 0 spell area requirements. DB table `spell_area` is empty.");
@@ -2459,11 +2459,11 @@ void SpellMgr::LoadSpellAreas()
spellArea.auraSpell = fields[6].GetInt32();
spellArea.raceMask = fields[7].GetUInt32();
spellArea.gender = Gender(fields[8].GetUInt8());
spellArea.autocast = fields[9].GetBool();
spellArea.flags = fields[9].GetUInt8();
if (SpellInfo const* spellInfo = GetSpellInfo(spell))
{
if (spellArea.autocast)
if (spellArea.flags & SPELL_AREA_FLAG_AUTOCAST)
const_cast<SpellInfo*>(spellInfo)->Attributes |= SPELL_ATTR0_CANT_CANCEL;
}
else
@@ -2539,13 +2539,13 @@ void SpellMgr::LoadSpellAreas()
}
// not allow autocast chains by auraSpell field (but allow use as alternative if not present)
if (spellArea.autocast && spellArea.auraSpell > 0)
if (spellArea.flags & SPELL_AREA_FLAG_AUTOCAST && spellArea.auraSpell > 0)
{
bool chain = false;
SpellAreaForAuraMapBounds saBound = GetSpellAreaForAuraMapBounds(spellArea.spellId);
for (SpellAreaForAuraMap::const_iterator itr = saBound.first; itr != saBound.second; ++itr)
{
if (itr->second->autocast && itr->second->auraSpell > 0)
if (itr->second->flags & SPELL_AREA_FLAG_AUTOCAST && itr->second->auraSpell > 0)
{
chain = true;
break;
@@ -2561,7 +2561,7 @@ void SpellMgr::LoadSpellAreas()
SpellAreaMapBounds saBound2 = GetSpellAreaMapBounds(spellArea.auraSpell);
for (SpellAreaMap::const_iterator itr2 = saBound2.first; itr2 != saBound2.second; ++itr2)
{
if (itr2->second.autocast && itr2->second.auraSpell > 0)
if (itr2->second.flags & SPELL_AREA_FLAG_AUTOCAST && itr2->second.auraSpell > 0)
{
chain = true;
break;
+7 -1
View File
@@ -461,6 +461,12 @@ class TC_GAME_API PetAura
};
typedef std::map<uint32, PetAura> SpellPetAuraMap;
enum SpellAreaFlag
{
SPELL_AREA_FLAG_AUTOCAST = 0x1, // if has autocast, spell is applied on enter
SPELL_AREA_FLAG_AUTOREMOVE = 0x2 // if has autoremove, spell is remove automatically inside zone/area (always removed on leaving area or zone)
};
struct TC_GAME_API SpellArea
{
uint32 spellId;
@@ -472,7 +478,7 @@ struct TC_GAME_API SpellArea
Gender gender; // can be applied only to gender
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
uint8 flags; // if SPELL_AREA_FLAG_AUTOCAST then auto applied at area enter, in other case just allowed to cast || if SPELL_AREA_FLAG_AUTOREMOVE then auto removed inside area (will allways be removed on leaved even without flag)
// helpers
bool IsFitToRequirements(Player const* player, uint32 newZone, uint32 newArea) const;