From fb5d2fa2e5d557cc9f827d75612dc674e779295c Mon Sep 17 00:00:00 2001 From: Kitzunu <24550914+Kitzunu@users.noreply.github.com> Date: Thu, 25 Mar 2021 01:19:57 +0100 Subject: [PATCH] fix(Core/Spell): Make use of SPELL_ATTR7_IGNORE_COLD_WEATHER_FLYING (#4933) --- src/server/game/Entities/Player/Player.cpp | 12 ++++- src/server/game/Entities/Player/Player.h | 2 +- src/server/game/Spells/SpellInfo.cpp | 53 ++++++++++++--------- src/server/game/Spells/SpellInfo.h | 2 +- src/server/shared/DataStores/DBCStructure.h | 5 ++ 5 files changed, 47 insertions(+), 27 deletions(-) diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 1c4326290..c42170116 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -25520,11 +25520,19 @@ uint32 Player::CalculateTalentsPoints() const return uint32(talentPointsForLevel * sWorld->getRate(RATE_TALENT)); } -bool Player::canFlyInZone(uint32 mapid, uint32 zone) const +bool Player::canFlyInZone(uint32 mapid, uint32 zone, SpellInfo const* bySpell) const { // continent checked in SpellInfo::CheckLocation at cast and area update uint32 v_map = GetVirtualMapForMapAndZone(mapid, zone); - return v_map != 571 || HasSpell(54197); // 54197 = Cold Weather Flying + if (v_map == 571 && !bySpell->HasAttribute(SPELL_ATTR7_IGNORE_COLD_WEATHER_FLYING)) + { + if (!HasSpell(54197)) // 54197 = Cold Weather Flying + { + return false; + } + } + + return true; } void Player::learnSpellHighRank(uint32 spellid) diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 1893d1436..c9230ae82 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -2354,7 +2354,7 @@ public: } void HandleFall(MovementInfo const& movementInfo); - [[nodiscard]] bool canFlyInZone(uint32 mapid, uint32 zone) const; + [[nodiscard]] bool canFlyInZone(uint32 mapid, uint32 zone, SpellInfo const* bySpell) const; void SetClientControl(Unit* target, bool allowMove, bool packetOnly = false); diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 22968df35..91cf54c2a 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -1450,7 +1450,7 @@ SpellCastResult SpellInfo::CheckShapeshift(uint32 form) const return SPELL_CAST_OK; } -SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 area_id, Player const* player) const +SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 area_id, Player const* player /*= nullptr*/, bool strict /*= true*/) const { // normal case if (AreaGroupId > 0) @@ -1473,7 +1473,7 @@ SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 a } // continent limitation (virtual continent) - if (AttributesEx4 & SPELL_ATTR4_CAST_ONLY_IN_OUTLAND) + if (HasAttribute(SPELL_ATTR4_CAST_ONLY_IN_OUTLAND)) { uint32 v_map = GetVirtualMapForMapAndZone(map_id, zone_id); MapEntry const* mapEntry = sMapStore.LookupEntry(v_map); @@ -1481,8 +1481,35 @@ SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 a return SPELL_FAILED_INCORRECT_AREA; } + // continent limitation (virtual continent) + if (HasAttribute(SPELL_ATTR4_CAST_ONLY_IN_OUTLAND)) + { + if (strict) + { + AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(area_id); + if (!areaEntry) + { + areaEntry = sAreaTableStore.LookupEntry(zone_id); + } + + if (!areaEntry || !areaEntry->IsFlyable() || !player->canFlyInZone(map_id, zone_id, this)) + { + return SPELL_FAILED_INCORRECT_AREA; + } + } + else + { + uint32 const v_map = GetVirtualMapForMapAndZone(map_id, zone_id); + MapEntry const* mapEntry = sMapStore.LookupEntry(v_map); + if (!mapEntry || mapEntry->Expansion() < 1 || !mapEntry->IsContinent()) + { + return SPELL_FAILED_INCORRECT_AREA; + } + } + } + // raid instance limitation - if (AttributesEx6 & SPELL_ATTR6_NOT_IN_RAID_INSTANCE) + if (HasAttribute(SPELL_ATTR6_NOT_IN_RAID_INSTANCE)) { MapEntry const* mapEntry = sMapStore.LookupEntry(map_id); if (!mapEntry || mapEntry->IsRaid()) @@ -1536,26 +1563,6 @@ SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 a } } - // aura limitations - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - { - if (!Effects[i].IsAura()) - continue; - switch (Effects[i].ApplyAuraName) - { - case SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED: - case SPELL_AURA_FLY: - { - SkillLineAbilityMapBounds bounds = sSpellMgr->GetSkillLineAbilityMapBounds(Id); - for (SkillLineAbilityMap::const_iterator skillIter = bounds.first; skillIter != bounds.second; ++skillIter) - { - if (skillIter->second->skillId == SKILL_MOUNTS) - if (player && !player->canFlyInZone(map_id, zone_id)) - return SPELL_FAILED_INCORRECT_AREA; - } - } - } - } return SPELL_CAST_OK; } diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index f3f076100..7557bc022 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -455,7 +455,7 @@ public: bool IsAuraExclusiveBySpecificPerCasterWith(SpellInfo const* spellInfo) const; SpellCastResult CheckShapeshift(uint32 form) const; - SpellCastResult CheckLocation(uint32 map_id, uint32 zone_id, uint32 area_id, Player const* player = nullptr) const; + SpellCastResult CheckLocation(uint32 map_id, uint32 zone_id, uint32 area_id, Player const* player = nullptr, bool strict = true) const; SpellCastResult CheckTarget(Unit const* caster, WorldObject const* target, bool implicit = true) const; SpellCastResult CheckExplicitTarget(Unit const* caster, WorldObject const* target, Item const* itemTarget = nullptr) const; bool CheckTargetCreatureType(Unit const* target) const; diff --git a/src/server/shared/DataStores/DBCStructure.h b/src/server/shared/DataStores/DBCStructure.h index 604c15803..a33d3a241 100644 --- a/src/server/shared/DataStores/DBCStructure.h +++ b/src/server/shared/DataStores/DBCStructure.h @@ -522,6 +522,11 @@ struct AreaTableEntry return true; return (flags & AREA_FLAG_SANCTUARY); } + + [[nodiscard]] bool IsFlyable() const + { + return flags & AREA_FLAG_OUTLAND && !(flags & AREA_FLAG_NO_FLY_ZONE); + } }; #define MAX_GROUP_AREA_IDS 6