Core/Spells: Rename SpellAttr1 to use official attribute names

* Implemented SPELL_ATTR1_NO_SKILL_INCREASE, SPELL_ATTR1_AURA_STAYS_AFTER_COMBAT, SPELL_ATTR1_DISPEL_ALL_STACKS
This commit is contained in:
Shauren authored and Ovahlord committed 2022-09-12 09:15:31 +02:00
1 parent cbc2234f1b
commit ca7d36873f
15 files changed
+184 -143

No files matched your search

@@ -3145,7 +3145,7 @@ void Creature::SetSpellFocus(Spell const* focusSpell, WorldObject const* target)
ObjectGuid newTarget = [&]()
{
// Spells that do not allow turning or channeled spells that will track their channel target do not set a unit field target
if (turnDisabled || noTurnDuringCast || spellInfo->HasAttribute(SPELL_ATTR1_CHANNEL_TRACK_TARGET) || target == this)
if (turnDisabled || noTurnDuringCast || spellInfo->HasAttribute(SPELL_ATTR1_TRACK_TARGET_IN_CHANNEL) || target == this)
return ObjectGuid::Empty;
return target->GetGUID();
+1 -1
View File
@@ -3192,7 +3192,7 @@ bool WorldObject::IsValidAssistTarget(WorldObject const* target, SpellInfo const
Unit* WorldObject::GetMagicHitRedirectTarget(Unit* victim, SpellInfo const* spellInfo)
{
// Patch 1.2 notes: Spell Reflection no longer reflects abilities
if (spellInfo->HasAttribute(SPELL_ATTR0_IS_ABILITY) || spellInfo->HasAttribute(SPELL_ATTR1_CANT_BE_REDIRECTED) || spellInfo->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES))
if (spellInfo->HasAttribute(SPELL_ATTR0_IS_ABILITY) || spellInfo->HasAttribute(SPELL_ATTR1_NO_REDIRECTION) || spellInfo->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES))
return victim;
Unit::AuraEffectList const& magnetAuras = victim->GetAuraEffectsByType(SPELL_AURA_SPELL_MAGNET);
+9 -8
View File
@@ -5207,12 +5207,15 @@ inline int32 SkillGainChance(Player const* player, uint32 SkillValue, uint32 Gra
return chance;
}
bool Player::UpdateCraftSkill(uint32 spellid)
bool Player::UpdateCraftSkill(SpellInfo const* spellInfo)
{
TC_LOG_DEBUG("entities.player.skills", "Player::UpdateCraftSkill: Player '%s' (%s), SpellID: %d",
GetName().c_str(), GetGUID().ToString().c_str(), spellid);
if (spellInfo->HasAttribute(SPELL_ATTR1_NO_SKILL_INCREASE))
return false;
SkillLineAbilityMapBounds bounds = sSpellMgr->GetSkillLineAbilityMapBounds(spellid);
TC_LOG_DEBUG("entities.player.skills", "Player::UpdateCraftSkill: Player '%s' (%s), SpellID: %d",
GetName().c_str(), GetGUID().ToString().c_str(), spellInfo->Id);
SkillLineAbilityMapBounds bounds = sSpellMgr->GetSkillLineAbilityMapBounds(spellInfo->Id);
for (SkillLineAbilityMap::const_iterator _spell_idx = bounds.first; _spell_idx != bounds.second; ++_spell_idx)
{
@@ -5221,10 +5224,9 @@ bool Player::UpdateCraftSkill(uint32 spellid)
uint32 SkillValue = GetPureSkillValue(_spell_idx->second->SkillLine);
// Alchemy Discoveries here
SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(spellid);
if (spellEntry && spellEntry->Mechanic == MECHANIC_DISCOVERY)
if (spellInfo && spellInfo->Mechanic == MECHANIC_DISCOVERY)
{
if (uint32 discoveredSpell = GetSkillDiscoverySpell(_spell_idx->second->SkillLine, spellid, this))
if (uint32 discoveredSpell = GetSkillDiscoverySpell(_spell_idx->second->SkillLine, spellInfo->Id, this))
LearnSpell(discoveredSpell, false);
}
@@ -5234,7 +5236,6 @@ bool Player::UpdateCraftSkill(uint32 spellid)
if (craft_skill_points)
{
craft_skill_points *= craft_skill_gain;
TC_LOG_INFO("entities.player", "craft_skill_points is %u, spellID: %u, skillID: %u", craft_skill_points, spellid, _spell_idx->second->SkillLine);
return UpdateSkillPro(_spell_idx->second->SkillLine, SkillGainChance(this, SkillValue,
_spell_idx->second->TrivialSkillLineRankHigh,
(_spell_idx->second->TrivialSkillLineRankHigh + _spell_idx->second->TrivialSkillLineRankLow) / 2,
+1 -1
View File
@@ -1754,7 +1754,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
bool UpdateSkill(uint32 skill_id, uint32 step);
bool UpdateSkillPro(uint16 skillId, int32 chance, uint32 step);
bool UpdateCraftSkill(uint32 spellid);
bool UpdateCraftSkill(SpellInfo const* spellInfo);
bool UpdateGatherSkill(uint32 SkillId, uint32 SkillValue, uint32 RedLevel, uint32 Multiplicator = 1);
bool UpdateFishingSkill();
void GiveXpForGather(uint32 const& skillId);
+29 -9
View File
@@ -443,7 +443,7 @@ void Unit::Update(uint32 p_time)
{
// Prioritize tracking channeled spells above unit targets if they should both be present at the same time.
Spell const* channeledSpell = GetCurrentSpell(CURRENT_CHANNELED_SPELL);
if (channeledSpell && channeledSpell->GetSpellInfo()->HasAttribute(SPELL_ATTR1_CHANNEL_TRACK_TARGET))
if (channeledSpell && channeledSpell->GetSpellInfo()->HasAttribute(SPELL_ATTR1_TRACK_TARGET_IN_CHANNEL))
{
ObjectGuid const channelGuid = GetChannelObjectGuid();
if (!channelGuid.IsEmpty() && channelGuid != GetGUID())
@@ -3651,7 +3651,7 @@ void Unit::RemoveAurasDueToSpellByDispel(uint32 spellId, uint32 dispellerSpellId
}
}
void Unit::RemoveAurasDueToSpellBySteal(uint32 spellId, ObjectGuid casterGUID, WorldObject* stealer)
void Unit::RemoveAurasDueToSpellBySteal(uint32 spellId, ObjectGuid casterGUID, WorldObject* stealer, int32 stolenCharges /*= 1*/)
{
AuraMapBoundsNonConst range = m_ownedAuras.equal_range(spellId);
for (AuraMap::iterator iter = range.first; iter != range.second;)
@@ -3685,9 +3685,9 @@ void Unit::RemoveAurasDueToSpellBySteal(uint32 spellId, ObjectGuid casterGUID, W
if (Aura* oldAura = unitStealer->GetAura(aura->GetId(), aura->GetCasterGUID()))
{
if (stealCharge)
oldAura->ModCharges(1);
oldAura->ModCharges(stolenCharges);
else
oldAura->ModStackAmount(1);
oldAura->ModStackAmount(stolenCharges);
oldAura->SetDuration(int32(dur));
}
else
@@ -3712,16 +3712,16 @@ void Unit::RemoveAurasDueToSpellBySteal(uint32 spellId, ObjectGuid casterGUID, W
caster->GetLimitedCastAuras(aura->GetId()).push_back(aura);
}
// FIXME: using aura->GetMaxDuration() maybe not blizzlike but it fixes stealing of spells like Innervate
newAura->SetLoadedState(aura->GetMaxDuration(), int32(dur), stealCharge ? 1 : aura->GetCharges(), 1, recalculateMask, aura->GetCritChance(), aura->CanApplyResilience(), &damage[0]);
newAura->SetLoadedState(aura->GetMaxDuration(), int32(dur), stealCharge ? stolenCharges : aura->GetCharges(), stolenCharges, recalculateMask, aura->GetCritChance(), aura->CanApplyResilience(), &damage[0]);
newAura->ApplyForTargets();
}
}
}
if (stealCharge)
aura->ModCharges(-1, AuraRemoveFlags::ByEnemySpell);
aura->ModCharges(-stolenCharges, AuraRemoveFlags::ByEnemySpell);
else
aura->ModStackAmount(-1, AuraRemoveFlags::ByEnemySpell);
aura->ModStackAmount(-stolenCharges, AuraRemoveFlags::ByEnemySpell);
return;
}
@@ -4033,7 +4033,27 @@ void Unit::RemoveAurasOnEvade()
// don't remove vehicle auras, passengers aren't supposed to drop off the vehicle
// don't remove clone caster on evade (to be verified)
RemoveAllAurasExceptType(SPELL_AURA_CONTROL_VEHICLE, SPELL_AURA_CLONE_CASTER);
auto evadeAuraCheck = [](Aura const* aura)
{
if (aura->HasEffectType(SPELL_AURA_CONTROL_VEHICLE))
return false;
if (aura->HasEffectType(SPELL_AURA_CLONE_CASTER))
return false;
if (aura->GetSpellInfo()->HasAttribute(SPELL_ATTR1_AURA_STAYS_AFTER_COMBAT))
return false;
return true;
};
auto evadeAuraApplicationCheck = [&evadeAuraCheck](AuraApplication const* aurApp)
{
return evadeAuraCheck(aurApp->GetBase());
};
RemoveAppliedAuras(evadeAuraApplicationCheck);
RemoveOwnedAuras(evadeAuraCheck);
}
void Unit::RemoveAllAurasOnDeath()
@@ -7303,7 +7323,7 @@ bool Unit::IsImmunedToDamage(SpellInfo const* spellInfo) const
if (spellInfo->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES) && spellInfo->HasAttribute(SPELL_ATTR3_IGNORE_HIT_RESULT))
return false;
if (spellInfo->HasAttribute(SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE) || spellInfo->HasAttribute(SPELL_ATTR2_UNAFFECTED_BY_AURA_SCHOOL_IMMUNE))
if (spellInfo->HasAttribute(SPELL_ATTR1_IMMUNITY_TO_HOSTILE_AND_FRIENDLY_EFFECTS) || spellInfo->HasAttribute(SPELL_ATTR2_UNAFFECTED_BY_AURA_SCHOOL_IMMUNE))
return false;
if (uint32 schoolMask = spellInfo->GetSchoolMask())
+3 -3
View File
@@ -115,12 +115,12 @@ class DispelableAura
uint8 GetDispelCharges() const { return _charges; }
void IncrementCharges() { ++_charges; }
bool DecrementCharge()
bool DecrementCharge(uint8 charges)
{
if (!_charges)
return false;
--_charges;
_charges -= charges;
return _charges > 0;
}
@@ -1344,7 +1344,7 @@ class TC_GAME_API Unit : public WorldObject
void RemoveAurasDueToSpell(uint32 spellId, ObjectGuid casterGUID = ObjectGuid::Empty, uint8 reqEffMask = 0, AuraRemoveFlags removeMode = AuraRemoveFlags::ByDefault);
void RemoveAuraFromStack(uint32 spellId, ObjectGuid casterGUID = ObjectGuid::Empty, AuraRemoveFlags removeMode = AuraRemoveFlags::ByDefault);
void RemoveAurasDueToSpellByDispel(uint32 spellId, uint32 dispellerSpellId, ObjectGuid casterGUID, WorldObject* dispeller, uint8 chargesRemoved = 1);
void RemoveAurasDueToSpellBySteal(uint32 spellId, ObjectGuid casterGUID, WorldObject* stealer);
void RemoveAurasDueToSpellBySteal(uint32 spellId, ObjectGuid casterGUID, WorldObject* stealer, int32 stolenCharges = 1);
void RemoveAurasDueToItemSpell(uint32 spellId, ObjectGuid castItemGuid);
void RemoveAurasByType(AuraType auraType, ObjectGuid casterGUID = ObjectGuid::Empty, Aura* except = nullptr, bool negative = true, bool positive = true);
void RemoveNotOwnLimitedTargetAuras(bool onPhaseChange = false);
+34 -33
View File
@@ -387,40 +387,41 @@ enum SpellAttr0 : uint32
SPELL_ATTR0_NO_AURA_CANCEL = 0x80000000 // No Aura Cancel DESCRIPTION Prevents the player from voluntarily canceling a positive aura
};
enum SpellAttr1
// EnumUtils: DESCRIBE THIS
enum SpellAttr1 : uint32
{
SPELL_ATTR1_DISMISS_PET = 0x00000001, // 0 for spells without this flag client doesn't allow to summon pet if caster has a pet
SPELL_ATTR1_DRAIN_ALL_POWER = 0x00000002, // 1 use all power (Only paladin Lay of Hands and Bunyanize)
SPELL_ATTR1_CHANNELED = 0x00000004, // 2 Is Channeled
SPELL_ATTR1_CANT_BE_REDIRECTED = 0x00000008, // 3
SPELL_ATTR1_UNK4 = 0x00000010, // 4 stealth and whirlwind
SPELL_ATTR1_NOT_BREAK_STEALTH = 0x00000020, // 5 Not break stealth
SPELL_ATTR1_SELF_CHANNELED = 0x00000040, // 6 Is Self Channeled
SPELL_ATTR1_CANT_BE_REFLECTED = 0x00000080, // 7
SPELL_ATTR1_CANT_TARGET_IN_COMBAT = 0x00000100, // 8 can target only out of combat units
SPELL_ATTR1_MELEE_COMBAT_START = 0x00000200, // 9 player starts melee combat after this spell is cast
SPELL_ATTR1_NO_THREAT = 0x00000400, // 10 no generates threat on cast 100% (old NO_INITIAL_AGGRO)
SPELL_ATTR1_DONT_REFRESH_DURATION_ON_RECAST = 0x00000800, // 11 aura will not refresh its duration when recast
SPELL_ATTR1_IS_PICKPOCKET = 0x00001000, // 12 Pickpocket
SPELL_ATTR1_FARSIGHT = 0x00002000, // 13 Client removes farsight on aura loss
SPELL_ATTR1_CHANNEL_TRACK_TARGET = 0x00004000, // 14 Client automatically forces player to face target when channeling
SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY = 0x00008000, // 15 remove auras on immunity
SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE = 0x00010000, // 16 on immuniy
SPELL_ATTR1_UNAUTOCASTABLE_BY_PET = 0x00020000, // 17
SPELL_ATTR1_UNK18 = 0x00040000, // 18 stun, polymorph, daze, hex
SPELL_ATTR1_CANT_TARGET_SELF = 0x00080000, // 19
SPELL_ATTR1_FINISHING_MOVE_DAMAGE = 0x00100000, // 20 Finishing Move - Damage
SPELL_ATTR1_UNK21 = 0x00200000, // 21
SPELL_ATTR1_FINISHING_MOVE_DURATION = 0x00400000, // 22 Finishing Move - Duration
SPELL_ATTR1_UNK23 = 0x00800000, // 23
SPELL_ATTR1_IS_FISHING = 0x01000000, // 24 only fishing spells
SPELL_ATTR1_UNK25 = 0x02000000, // 25
SPELL_ATTR1_UNK26 = 0x04000000, // 26 works correctly with [target=focus] and [target=mouseover] macros?
SPELL_ATTR1_DISCOUNT_POWER_ON_MISS = 0x08000000, // 27 Discount Power On Miss
SPELL_ATTR1_DONT_DISPLAY_IN_AURA_BAR = 0x10000000, // 28 client doesn't display these spells in aura bar
SPELL_ATTR1_CHANNEL_DISPLAY_SPELL_NAME = 0x20000000, // 29 spell name is displayed in cast bar instead of 'channeling' text
SPELL_ATTR1_ENABLE_AT_DODGE = 0x40000000, // 30 Overpower
SPELL_ATTR1_CAST_WHEN_LEARNED = 0x80000000 // 31 Cast When Learned
SPELL_ATTR1_DISMISS_PET_FIRST = 0x00000001, // Dismiss Pet First DESCRIPTION Without this attribute, summoning spells will fail if caster already has a pet
SPELL_ATTR1_USE_ALL_MANA = 0x00000002, // Use All Mana DESCRIPTION Ignores listed power cost and drains entire pool instead
SPELL_ATTR1_IS_CHANNELLED = 0x00000004, // Is Channelled DESCRIPTION Both "channeled" attributes have identical handling in server & client
SPELL_ATTR1_NO_REDIRECTION = 0x00000008, // No Redirection DESCRIPTION Spell will not be attracted by SPELL_MAGNET auras (Grounding Totem)
SPELL_ATTR1_NO_SKILL_INCREASE = 0x00000010, // No Skill Increase
SPELL_ATTR1_ALLOW_WHILE_STEALTHED = 0x00000020, // Allow While Stealthed
SPELL_ATTR1_IS_SELF_CHANNELLED = 0x00000040, // Is Self Channelled DESCRIPTION Both "channeled" attributes have identical handling in server & client
SPELL_ATTR1_NO_REFLECTION = 0x00000080, // No Reflection DESCRIPTION Spell will pierce through Spell Reflection and similar
SPELL_ATTR1_ONLY_PEACEFUL_TARGETS = 0x00000100, // Only Peaceful Targets DESCRIPTION Target cannot be in combat
SPELL_ATTR1_INITIATES_COMBAT_ENABLES_AUTO_ATTACK = 0x00000200, // Initiates Combat (Enables Auto-Attack) (client only) DESCRIPTION Caster will begin auto-attacking the target on cast
SPELL_ATTR1_NO_THREAT = 0x00000400, // Does not generate threat DESCRIPTION Also does not cause target to engage
SPELL_ATTR1_AURA_UNIQUE = 0x00000800, // Aura Unique DESCRIPTION Aura will not refresh its duration when recast
SPELL_ATTR1_FAILURE_BREAKS_STEALTH = 0x00001000, // Failure Breaks Stealth
SPELL_ATTR1_TOGGLE_FAR_SIGHT = 0x00002000, // Toggle Far Sight (client only)
SPELL_ATTR1_TRACK_TARGET_IN_CHANNEL = 0x00004000, // Track Target in Channel DESCRIPTION While channeling, adjust facing to face target
SPELL_ATTR1_IMMUNITY_PURGES_EFFECT = 0x00008000, // Immunity Purges Effect DESCRIPTION For immunity spells, cancel all auras that this spell would make you immune to when the spell is applied
SPELL_ATTR1_IMMUNITY_TO_HOSTILE_AND_FRIENDLY_EFFECTS = 0x00010000, /*WRONG IMPL*/ // Immunity to Hostile & Friendly Effects DESCRIPTION Will not pierce Divine Shield, Ice Block and other full invulnerabilities
SPELL_ATTR1_NO_AUTOCAST_AI = 0x00020000, // No AutoCast (AI)
SPELL_ATTR1_PREVENTS_ANIM = 0x00040000, /*NYI*/ // Prevents Anim DESCRIPTION Auras apply UNIT_FLAG_PREVENT_EMOTES_FROM_CHAT_TEXT
SPELL_ATTR1_EXCLUDE_CASTER = 0x00080000, // Exclude Caster
SPELL_ATTR1_FINISHING_MOVE_DAMAGE = 0x00100000, // Finishing Move - Damage
SPELL_ATTR1_THREAT_ONLY_ON_MISS = 0x00200000, /*NYI*/ // Threat only on Miss
SPELL_ATTR1_FINISHING_MOVE_DURATION = 0x00400000, // Finishing Move - Duration
SPELL_ATTR1_IGNORE_OWNERS_DEATH = 0x00800000, /*NYI*/ // Ignore Owner's Death
SPELL_ATTR1_SPECIAL_SKILLUP = 0x01000000, // Special Skillup
SPELL_ATTR1_AURA_STAYS_AFTER_COMBAT = 0x02000000, // Aura Stays After Combat
SPELL_ATTR1_REQUIRE_ALL_TARGETS = 0x04000000, /*NYI, UNK*/ // Require All Targets
SPELL_ATTR1_DISCOUNT_POWER_ON_MISS = 0x08000000, // Discount Power On Miss
SPELL_ATTR1_NO_AURA_ICON = 0x10000000, // No Aura Icon (client only)
SPELL_ATTR1_NAME_IN_CHANNEL_BAR = 0x20000000, // Name in Channel Bar (client only)
SPELL_ATTR1_DISPEL_ALL_STACKS = 0x40000000, // Dispel All Stacks
SPELL_ATTR1_CAST_WHEN_LEARNED = 0x80000000 // Cast When Learned
};
enum SpellAttr2
@@ -3325,7 +3325,7 @@ void AuraEffect::HandleAuraModSchoolImmunity(AuraApplication const* aurApp, uint
target->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::StealthOrInvis);
// remove all flag auras (they are positive, but they must be removed when you are immune)
if (GetSpellInfo()->HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY)
if (GetSpellInfo()->HasAttribute(SPELL_ATTR1_IMMUNITY_PURGES_EFFECT)
&& GetSpellInfo()->HasAttribute(SPELL_ATTR2_DAMAGE_REDUCED_SHIELD))
target->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::StealthOrInvis);
}
+1 -1
View File
@@ -1037,7 +1037,7 @@ bool Aura::ModStackAmount(int32 num, AuraRemoveFlags removeMode /*= AuraRemoveFl
EnumFlag<AuraRemoveFlags> removeFlags = removeMode;
bool refresh = stackAmount >= GetStackAmount() && (m_spellInfo->StackAmount || !m_spellInfo->HasAttribute(SPELL_ATTR1_DONT_REFRESH_DURATION_ON_RECAST));
bool refresh = stackAmount >= GetStackAmount() && (m_spellInfo->StackAmount || !m_spellInfo->HasAttribute(SPELL_ATTR1_AURA_UNIQUE));
// Update stack amount
SetStackAmount(stackAmount);
+59 -49
View File
@@ -667,7 +667,7 @@ m_caster((info->HasAttribute(SPELL_ATTR6_CAST_BY_CHARMER) && caster->GetCharmerO
// Determine if spell can be reflected back to the caster
// Patch 1.2 notes: Spell Reflection no longer reflects abilities
m_canReflect = caster->IsUnit() && m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC && !m_spellInfo->HasAttribute(SPELL_ATTR0_IS_ABILITY)
&& !m_spellInfo->HasAttribute(SPELL_ATTR1_CANT_BE_REFLECTED) && !m_spellInfo->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES)
&& !m_spellInfo->HasAttribute(SPELL_ATTR1_NO_REFLECTION) && !m_spellInfo->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES)
&& !m_spellInfo->IsPassive();
CleanupTargetList();
@@ -2673,7 +2673,7 @@ void Spell::TargetInfo::DoDamageAndTriggers(Spell* spell)
}
// Failed Pickpocket, reveal rogue
if (MissCondition == SPELL_MISS_RESIST && spell->m_spellInfo->HasAttribute(SPELL_ATTR0_CU_PICKPOCKET) && spell->unitTarget->GetTypeId() == TYPEID_UNIT)
if (MissCondition == SPELL_MISS_RESIST && spell->m_spellInfo->HasAttribute(SPELL_ATTR1_FAILURE_BREAKS_STEALTH) && spell->unitTarget->GetTypeId() == TYPEID_UNIT)
{
Unit* unitCaster = ASSERT_NOTNULL(spell->m_caster->ToUnit());
unitCaster->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Interacting);
@@ -3566,7 +3566,7 @@ void Spell::_cast(bool skipCheck)
}
if (Unit* unitCaster = m_caster->ToUnit())
if (m_spellInfo->HasAttribute(SPELL_ATTR1_DISMISS_PET))
if (m_spellInfo->HasAttribute(SPELL_ATTR1_DISMISS_PET_FIRST))
if (Creature* pet = ObjectAccessor::GetCreature(*m_caster, unitCaster->GetPetGUID()))
pet->DespawnOrUnsummon();
@@ -4941,27 +4941,10 @@ void Spell::SendChannelStart(uint32 duration)
if (!unitCaster)
return;
ObjectGuid channelTarget = m_targets.GetObjectTargetGUID();
if (!channelTarget && !m_spellInfo->NeedsExplicitUnitTarget())
{
// this is for TARGET_SELECT_CATEGORY_NEARBY
if (m_UniqueTargetInfo.size() + m_UniqueGOTargetInfo.size() == 1)
channelTarget = !m_UniqueTargetInfo.empty() ? m_UniqueTargetInfo.front().TargetGUID : m_UniqueGOTargetInfo.front().TargetGUID;
else
{
// We assume that when we have a channel spell with more than one unique unit target that there is a caster and a target.
// We don't want the caster but the target so we are looking for a non-caster entry within the target list
for (auto& itr : m_UniqueTargetInfo)
{
if (itr.TargetGUID != m_caster->GetGUID())
channelTarget = itr.TargetGUID;
}
}
}
// There must always be a channel target
if (!channelTarget)
channelTarget = m_caster->GetGUID();
WorldPackets::Spells::ChannelStart packet;
packet.CasterGUID = m_caster->GetGUID();
packet.SpellID = m_spellInfo->Id;
packet.ChannelDuration = duration;
uint32 castFlags = CAST_FLAG_HAS_TRAJECTORY;
uint32 schoolImmunityMask = unitCaster->GetSchoolImmunityMask();
@@ -4970,15 +4953,6 @@ void Spell::SendChannelStart(uint32 duration)
if (schoolImmunityMask || mechanicImmunityMask)
castFlags |= CAST_FLAG_IMMUNITY;
uint8 ticks = m_spellInfo->GetMaxTicks();
if (m_spellInfo->HasAttribute(SPELL_ATTR5_START_PERIODIC_AT_APPLY))
++ticks;
WorldPackets::Spells::ChannelStart packet;
packet.CasterGUID = m_caster->GetGUID();
packet.SpellID = m_spellInfo->Id;
packet.ChannelDuration = duration;
if (castFlags & CAST_FLAG_IMMUNITY)
{
packet.InterruptImmunities.emplace();
@@ -4986,26 +4960,62 @@ void Spell::SendChannelStart(uint32 duration)
packet.InterruptImmunities->Immunities = mechanicImmunityMask; // CastImmunities
}
if (!m_targets.HasDst())
{
uint32 channelAuraMask = 0;
uint32 explicitTargetEffectMask = 0xFFFFFFFF;
// if there is an explicit target, only add channel objects from effects that also hit it
if (!m_targets.GetUnitTargetGUID().IsEmpty())
{
auto explicitTargetItr = std::find_if(m_UniqueTargetInfo.begin(), m_UniqueTargetInfo.end(), [&](TargetInfo const& target)
{
return target.TargetGUID == m_targets.GetUnitTargetGUID();
});
if (explicitTargetItr != m_UniqueTargetInfo.end())
explicitTargetEffectMask = explicitTargetItr->EffectMask;
}
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
{
SpellEffectInfo const& spellEffectInfo = m_spellInfo->Effects[i];
if (spellEffectInfo.IsEffect(SPELL_EFFECT_APPLY_AURA) && (explicitTargetEffectMask & (1u << i)))
channelAuraMask |= 1 << i;
}
for (TargetInfo const& target : m_UniqueTargetInfo)
{
if (!(target.EffectMask & channelAuraMask))
continue;
SpellAttr1 requiredAttribute = target.TargetGUID != unitCaster->GetGUID() ? SPELL_ATTR1_IS_CHANNELLED : SPELL_ATTR1_IS_SELF_CHANNELLED;
if (!m_spellInfo->HasAttribute(requiredAttribute))
continue;
unitCaster->SetChannelObjectGuid(target.TargetGUID);
}
for (GOTargetInfo const& target : m_UniqueGOTargetInfo)
if (target.EffectMask & channelAuraMask)
unitCaster->SetChannelObjectGuid(target.TargetGUID);
}
else if (m_spellInfo->HasAttribute(SPELL_ATTR1_IS_SELF_CHANNELLED))
unitCaster->SetChannelObjectGuid(unitCaster->GetGUID());
if (m_spellInfo->HasAttribute(SPELL_ATTR8_HEAL_PREDICTION))
{
castFlags |= CAST_FLAG_HEAL_PREDICTION;
WorldPackets::Spells::SpellHealPrediction predict;
UpdateSpellHealPrediction(predict);
packet.HealPrediction.emplace(channelTarget, predict);
packet.HealPrediction.emplace(unitCaster->GetChannelObjectGuid(), predict);
}
m_caster->SendMessageToSet(packet.Write(), true);
m_timer = duration;
if (channelTarget)
{
unitCaster->SetChannelObjectGuid(channelTarget);
if (Creature* creatureCaster = m_caster->ToCreature())
if (!creatureCaster->HasSpellFocus(this))
creatureCaster->SetSpellFocus(this, ObjectAccessor::GetWorldObject(*creatureCaster, channelTarget));
}
if (Creature* creatureCaster = m_caster->ToCreature())
if (!creatureCaster->HasSpellFocus(this))
creatureCaster->SetSpellFocus(this, ObjectAccessor::GetWorldObject(*creatureCaster, unitCaster->GetChannelObjectGuid()));
m_caster->SetUInt32Value(UNIT_CHANNEL_SPELL, m_spellInfo->Id);
}
@@ -5550,7 +5560,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint
{
if (m_spellInfo->HasAttribute(SPELL_ATTR0_USES_RANGED_SLOT)
|| m_spellInfo->IsNextMeleeSwingSpell()
|| m_spellInfo->HasAttribute(SPELL_ATTR1_MELEE_COMBAT_START)
|| m_spellInfo->HasAttribute(SPELL_ATTR1_INITIATES_COMBAT_ENABLES_AUTO_ATTACK)
|| m_spellInfo->HasAttribute(SPELL_ATTR2_INITIATE_COMBAT_POST_CAST)
|| m_spellInfo->HasEffect(SPELL_EFFECT_ATTACK)
|| m_spellInfo->HasEffect(SPELL_EFFECT_NORMALIZED_WEAPON_DMG)
@@ -6157,7 +6167,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint
switch (SummonProperties->Control)
{
case SUMMON_CATEGORY_PET:
if (!m_spellInfo->HasAttribute(SPELL_ATTR1_DISMISS_PET) && unitCaster->GetPetGUID())
if (!m_spellInfo->HasAttribute(SPELL_ATTR1_DISMISS_PET_FIRST) && unitCaster->GetPetGUID())
return SPELL_FAILED_ALREADY_HAVE_SUMMON;
[[fallthrough]]; // check both GetPetGUID() and GetCharmGUID for SUMMON_CATEGORY_PET*/
case SUMMON_CATEGORY_PUPPET:
@@ -6173,7 +6183,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint
{
if (m_targets.GetUnitTarget()->GetTypeId() != TYPEID_PLAYER)
return SPELL_FAILED_BAD_TARGETS;
if (!m_spellInfo->HasAttribute(SPELL_ATTR1_DISMISS_PET) && m_targets.GetUnitTarget()->GetPetGUID())
if (!m_spellInfo->HasAttribute(SPELL_ATTR1_DISMISS_PET_FIRST) && m_targets.GetUnitTarget()->GetPetGUID())
return SPELL_FAILED_ALREADY_HAVE_SUMMON;
}
break;
@@ -6192,7 +6202,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint
if (Pet* pet = unitCaster->ToPlayer()->GetPet())
pet->CastSpell(pet, 32752, pet->GetGUID());
}
else if (!m_spellInfo->HasAttribute(SPELL_ATTR1_DISMISS_PET))
else if (!m_spellInfo->HasAttribute(SPELL_ATTR1_DISMISS_PET_FIRST))
return SPELL_FAILED_ALREADY_HAVE_SUMMON;
}
@@ -6325,7 +6335,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint
if (m_spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_MOD_CHARM
|| m_spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_MOD_POSSESS)
{
if (!m_spellInfo->HasAttribute(SPELL_ATTR1_DISMISS_PET) && unitCaster->GetPetGUID())
if (!m_spellInfo->HasAttribute(SPELL_ATTR1_DISMISS_PET_FIRST) && unitCaster->GetPetGUID())
return SPELL_FAILED_ALREADY_HAVE_SUMMON;
if (unitCaster->GetCharmedGUID())
@@ -7712,7 +7722,7 @@ bool Spell::IsIgnoringCooldowns() const
bool Spell::IsFocusDisabled() const
{
return ((_triggeredCastFlags & TRIGGERED_IGNORE_SET_FACING) != 0
|| (m_spellInfo->IsChanneled() && !m_spellInfo->HasAttribute(SpellAttr1(SPELL_ATTR1_CHANNEL_TRACK_TARGET | SPELL_ATTR1_SELF_CHANNELED))));
|| (m_spellInfo->IsChanneled() && !m_spellInfo->HasAttribute(SPELL_ATTR1_TRACK_TARGET_IN_CHANNEL)));
}
bool Spell::IsProcDisabled() const
+21 -12
View File
@@ -1370,7 +1370,7 @@ void Spell::DoCreateItem(uint32 /*i*/, uint32 itemtype)
// we succeeded in creating at least one item, so a levelup is possible
if (bgType == 0)
player->UpdateCraftSkill(m_spellInfo->Id);
player->UpdateCraftSkill(m_spellInfo);
}
/*
@@ -1406,7 +1406,7 @@ void Spell::EffectCreateItem2(SpellEffIndex effIndex)
if (m_spellInfo->IsLootCrafting())
{
player->AutoStoreLoot(m_spellInfo->Id, LootTemplates_Spell, false);
player->UpdateCraftSkill(m_spellInfo->Id);
player->UpdateCraftSkill(m_spellInfo);
}
else // If there's no random loot entries for this spell, pick the item associated with this spell
{
@@ -2069,12 +2069,17 @@ void Spell::EffectDispel(SpellEffIndex effIndex)
return false;
});
uint8 dispelledCharges = 1;
if (itr->GetAura()->GetSpellInfo()->HasAttribute(SPELL_ATTR1_DISPEL_ALL_STACKS))
dispelledCharges = itr->GetDispelCharges();
if (successItr == successList.end())
successList.emplace_back(itr->GetAura(), 0, 1);
successList.emplace_back(itr->GetAura(), 0, dispelledCharges);
else
successItr->IncrementCharges();
if (!itr->DecrementCharge())
if (!itr->DecrementCharge(dispelledCharges))
{
--remaining;
std::swap(*itr, dispelList[remaining]);
@@ -2316,7 +2321,7 @@ void Spell::EffectEnchantItemPerm(SpellEffIndex effIndex)
{
// do not increase skill if vellum used
if (!(m_CastItem && m_CastItem->GetTemplate()->GetFlags() & ITEM_FLAG_NO_REAGENT_COST))
player->UpdateCraftSkill(m_spellInfo->Id);
player->UpdateCraftSkill(m_spellInfo);
uint32 enchant_id = m_spellInfo->Effects[effIndex].MiscValue;
if (!enchant_id)
@@ -3976,7 +3981,7 @@ void Spell::EffectDisEnchant(SpellEffIndex /*effIndex*/)
if (Player* caster = m_caster->ToPlayer())
{
caster->UpdateCraftSkill(m_spellInfo->Id);
caster->UpdateCraftSkill(m_spellInfo);
caster->SendLoot(itemTarget->GetGUID(), LOOT_DISENCHANTING);
}
@@ -5135,7 +5140,7 @@ void Spell::EffectStealBeneficialBuff(SpellEffIndex effIndex)
// Ok if exist some buffs for dispel try dispel it
uint32 failCount = 0;
DispelList successList;
std::vector<std::tuple<uint32, ObjectGuid, int32>> successList;
successList.reserve(damage);
WorldPacket dataFail(SMSG_DISPEL_FAILED, 8 + 8 + 4 + 4 + damage * 4);
@@ -5148,8 +5153,12 @@ void Spell::EffectStealBeneficialBuff(SpellEffIndex effIndex)
if (itr->RollDispel())
{
successList.emplace_back(itr->GetAura()->GetId(), itr->GetAura()->GetCasterGUID());
if (!itr->DecrementCharge())
uint8 stolenCharges = 1;
if (itr->GetAura()->GetSpellInfo()->HasAttribute(SPELL_ATTR1_DISPEL_ALL_STACKS))
stolenCharges = itr->GetDispelCharges();
successList.emplace_back(itr->GetAura()->GetId(), itr->GetAura()->GetCasterGUID(), int32(stolenCharges));
if (!itr->DecrementCharge(stolenCharges))
{
--remaining;
std::swap(*itr, stealList[remaining]);
@@ -5182,11 +5191,11 @@ void Spell::EffectStealBeneficialBuff(SpellEffIndex effIndex)
dataSuccess << uint32(m_spellInfo->Id); // dispel spell id
dataSuccess << uint8(0); // not used
dataSuccess << uint32(successList.size()); // count
for (auto itr = successList.begin(); itr != successList.end(); ++itr)
for (auto const& [spellId, auraCaster, stolenCharges] : successList)
{
dataSuccess << uint32(itr->first); // Spell Id
dataSuccess << uint32(spellId); // Spell Id
dataSuccess << uint8(0); // 0 - steals !=0 transfers
unitTarget->RemoveAurasDueToSpellBySteal(itr->first, itr->second, m_caster);
unitTarget->RemoveAurasDueToSpellBySteal(spellId, auraCaster, m_caster, stolenCharges);
}
m_caster->SendMessageToSet(&dataSuccess, true);
}
+16 -16
View File
@@ -1319,7 +1319,7 @@ bool SpellInfo::IsAutocastable() const
{
if (IsPassive())
return false;
if (HasAttribute(SPELL_ATTR1_UNAUTOCASTABLE_BY_PET))
if (HasAttribute(SPELL_ATTR1_NO_AUTOCAST_AI))
return false;
return true;
}
@@ -1460,7 +1460,7 @@ bool SpellInfo::IsPositiveEffect(uint8 effIndex) const
bool SpellInfo::IsChanneled() const
{
return HasAttribute(SpellAttr1(SPELL_ATTR1_CHANNELED | SPELL_ATTR1_SELF_CHANNELED));
return HasAttribute(SpellAttr1(SPELL_ATTR1_IS_CHANNELLED | SPELL_ATTR1_IS_SELF_CHANNELLED));
}
bool SpellInfo::IsMoveAllowedChannel() const
@@ -1480,7 +1480,7 @@ bool SpellInfo::IsNextMeleeSwingSpell() const
bool SpellInfo::IsBreakingStealth() const
{
return !HasAttribute(SPELL_ATTR1_NOT_BREAK_STEALTH);
return !HasAttribute(SPELL_ATTR1_ALLOW_WHILE_STEALTHED);
}
bool SpellInfo::IsRangedWeaponSpell() const
@@ -1568,7 +1568,7 @@ bool SpellInfo::CanPierceImmuneAura(SpellInfo const* auraSpellInfo) const
return true;
// these spells (Cyclone for example) can pierce all...
if (HasAttribute(SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE) || HasAttribute(SPELL_ATTR2_UNAFFECTED_BY_AURA_SCHOOL_IMMUNE))
if (HasAttribute(SPELL_ATTR1_IMMUNITY_TO_HOSTILE_AND_FRIENDLY_EFFECTS) || HasAttribute(SPELL_ATTR2_UNAFFECTED_BY_AURA_SCHOOL_IMMUNE))
{
// ...but not these (Divine shield, Ice block, Cyclone and Banish for example)
if (auraSpellInfo->Mechanic != MECHANIC_IMMUNE_SHIELD &&
@@ -1578,7 +1578,7 @@ bool SpellInfo::CanPierceImmuneAura(SpellInfo const* auraSpellInfo) const
}
// Dispels other auras on immunity, check if this spell makes the unit immune to aura
if (HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY) && CanSpellProvideImmunityAgainstAura(auraSpellInfo))
if (HasAttribute(SPELL_ATTR1_IMMUNITY_PURGES_EFFECT) && CanSpellProvideImmunityAgainstAura(auraSpellInfo))
return true;
return false;
@@ -1595,7 +1595,7 @@ bool SpellInfo::CanDispelAura(SpellInfo const* auraSpellInfo) const
return true;
// These auras (Cyclone for example) are not dispelable
if ((auraSpellInfo->HasAttribute(SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE) && auraSpellInfo->Mechanic != MECHANIC_NONE)
if ((auraSpellInfo->HasAttribute(SPELL_ATTR1_IMMUNITY_TO_HOSTILE_AND_FRIENDLY_EFFECTS) && auraSpellInfo->Mechanic != MECHANIC_NONE)
|| auraSpellInfo->HasAttribute(SPELL_ATTR2_UNAFFECTED_BY_AURA_SCHOOL_IMMUNE))
return false;
@@ -1876,7 +1876,7 @@ SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 a
SpellCastResult SpellInfo::CheckTarget(WorldObject const* caster, WorldObject const* target, bool implicit /*= true*/) const
{
if (HasAttribute(SPELL_ATTR1_CANT_TARGET_SELF) && caster == target)
if (HasAttribute(SPELL_ATTR1_EXCLUDE_CASTER) && caster == target)
return SPELL_FAILED_BAD_TARGETS;
// check visibility - ignore stealth for implicit (area) targets
@@ -1889,7 +1889,7 @@ SpellCastResult SpellInfo::CheckTarget(WorldObject const* caster, WorldObject co
if (unitTarget)
{
// spells cannot be cast if target has a pet in combat either
if (HasAttribute(SPELL_ATTR1_CANT_TARGET_IN_COMBAT) && (unitTarget->IsInCombat() || unitTarget->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT)))
if (HasAttribute(SPELL_ATTR1_ONLY_PEACEFUL_TARGETS) && (unitTarget->IsInCombat() || unitTarget->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT)))
return SPELL_FAILED_TARGET_AFFECTING_COMBAT;
// only spells with SPELL_ATTR3_ONLY_TARGET_GHOSTS can target ghosts
@@ -3105,7 +3105,7 @@ void SpellInfo::ApplyAllSpellImmunitiesTo(Unit* target, uint8 effIndex, bool app
{
target->ApplySpellImmune(Id, IMMUNITY_SCHOOL, schoolImmunity, apply);
if (apply && HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY))
if (apply && HasAttribute(SPELL_ATTR1_IMMUNITY_PURGES_EFFECT))
{
target->RemoveAppliedAuras([this, schoolImmunity](AuraApplication const* aurApp) -> bool
{
@@ -3127,7 +3127,7 @@ void SpellInfo::ApplyAllSpellImmunitiesTo(Unit* target, uint8 effIndex, bool app
if (mechanicImmunity & (1 << i))
target->ApplySpellImmune(Id, IMMUNITY_MECHANIC, i, apply);
if(apply && HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY))
if(apply && HasAttribute(SPELL_ATTR1_IMMUNITY_PURGES_EFFECT))
target->RemoveAurasWithMechanic(mechanicImmunity, AuraRemoveFlags::ByDefault, Id);
}
@@ -3135,7 +3135,7 @@ void SpellInfo::ApplyAllSpellImmunitiesTo(Unit* target, uint8 effIndex, bool app
{
target->ApplySpellImmune(Id, IMMUNITY_DISPEL, dispelImmunity, apply);
if (apply && HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY))
if (apply && HasAttribute(SPELL_ATTR1_IMMUNITY_PURGES_EFFECT))
{
target->RemoveAppliedAuras([dispelImmunity](AuraApplication const* aurApp) -> bool
{
@@ -3159,7 +3159,7 @@ void SpellInfo::ApplyAllSpellImmunitiesTo(Unit* target, uint8 effIndex, bool app
for (AuraType auraType : immuneInfo->AuraTypeImmune)
{
target->ApplySpellImmune(Id, IMMUNITY_STATE, auraType, apply);
if (apply && HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY))
if (apply && HasAttribute(SPELL_ATTR1_IMMUNITY_PURGES_EFFECT))
target->RemoveAurasByType(auraType);
}
@@ -3176,7 +3176,7 @@ bool SpellInfo::CanSpellProvideImmunityAgainstAura(SpellInfo const* auraSpellInf
{
ImmunityInfo const* immuneInfo = _immunityInfo + i;
if (!auraSpellInfo->HasAttribute(SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE) && !auraSpellInfo->HasAttribute(SPELL_ATTR2_UNAFFECTED_BY_AURA_SCHOOL_IMMUNE))
if (!auraSpellInfo->HasAttribute(SPELL_ATTR1_IMMUNITY_TO_HOSTILE_AND_FRIENDLY_EFFECTS) && !auraSpellInfo->HasAttribute(SPELL_ATTR2_UNAFFECTED_BY_AURA_SCHOOL_IMMUNE))
{
if (uint32 schoolImmunity = immuneInfo->SchoolImmuneMask)
if ((auraSpellInfo->SchoolMask & schoolImmunity) != 0)
@@ -3249,7 +3249,7 @@ bool SpellInfo::CanSpellProvideImmunityAgainstAura(SpellInfo const* auraSpellInf
// based on client Spell_C::CancelsAuraEffect
bool SpellInfo::SpellCancelsAuraEffect(SpellInfo const* auraSpellInfo, uint8 auraEffIndex) const
{
if (!HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY))
if (!HasAttribute(SPELL_ATTR1_IMMUNITY_PURGES_EFFECT))
return false;
if (auraSpellInfo->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES))
@@ -3534,7 +3534,7 @@ int32 SpellInfo::CalcPowerCost(WorldObject const* caster, SpellSchoolMask school
return 0;
// Spell drain all exist power on cast (Only paladin lay of Hands)
if (HasAttribute(SPELL_ATTR1_DRAIN_ALL_POWER))
if (HasAttribute(SPELL_ATTR1_USE_ALL_MANA))
{
// If power type - health drain all
if (PowerType == POWER_HEALTH)
@@ -3923,7 +3923,7 @@ bool _isPositiveEffectImpl(SpellInfo const* spellInfo, uint8 effIndex, std::unor
}
// Special case: effects which determine positivity of whole spell
if (spellInfo->HasAttribute(SPELL_ATTR1_DONT_REFRESH_DURATION_ON_RECAST)) // @todo: rename to and handle SPELL_ATTR1_AURA_UNIQUE
if (spellInfo->HasAttribute(SPELL_ATTR1_AURA_UNIQUE)) // @todo: rename to and handle SPELL_ATTR1_AURA_UNIQUE
{
// check for targets, there seems to be an assortment of dummy triggering spells that should be negative
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+6 -6
View File
@@ -3705,7 +3705,7 @@ void SpellMgr::LoadSpellInfoCorrections()
// spell should dispel area aura, but doesn't have the attribute
// may be db data bug, or blizz may keep reapplying area auras every update with checking immunity
// that will be clear if we get more spells with problem like this
spellInfo->AttributesEx |= SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY;
spellInfo->AttributesEx |= SPELL_ATTR1_IMMUNITY_PURGES_EFFECT;
});
// Spinning Up (Mimiron)
@@ -3925,7 +3925,7 @@ void SpellMgr::LoadSpellInfoCorrections()
ApplySpellFix({ 69783, 69797, 69799, 69802 }, [](SpellInfo* spellInfo)
{
// Those spells are cast on creatures with same entry as caster while they have TARGET_UNIT_NEARBY_ENTRY.
spellInfo->AttributesEx |= SPELL_ATTR1_CANT_TARGET_SELF;
spellInfo->AttributesEx |= SPELL_ATTR1_EXCLUDE_CASTER;
});
// Awaken Plagued Zombies
@@ -4784,7 +4784,7 @@ void SpellMgr::LoadSpellInfoCorrections()
// Spore Cloud
ApplySpellFix({ 75701 }, [](SpellInfo* spellInfo)
{
spellInfo->AttributesEx &= ~SPELL_ATTR1_CHANNELED;
spellInfo->AttributesEx &= ~SPELL_ATTR1_IS_CHANNELLED;
});
// Noxious Spores
@@ -4857,7 +4857,7 @@ void SpellMgr::LoadSpellInfoCorrections()
// Gaze of Occu'thar
ApplySpellFix({ 96942, 101009 }, [](SpellInfo* spellInfo)
{
spellInfo->AttributesEx &= ~SPELL_ATTR1_CHANNELED;
spellInfo->AttributesEx &= ~SPELL_ATTR1_IS_CHANNELLED;
});
// Meteor Slash
@@ -4968,7 +4968,7 @@ void SpellMgr::LoadSpellInfoCorrections()
100190
}, [](SpellInfo* spellInfo)
{
spellInfo->AttributesEx &= ~SPELL_ATTR1_CHANNELED;
spellInfo->AttributesEx &= ~SPELL_ATTR1_IS_CHANNELLED;
});
// Fixate
@@ -5202,7 +5202,7 @@ void SpellMgr::LoadSpellInfoCorrections()
// Nurture
ApplySpellFix({ 85425 }, [](SpellInfo* spellInfo)
{
spellInfo->AttributesEx &= ~SPELL_ATTR1_SELF_CHANNELED;
spellInfo->AttributesEx &= ~SPELL_ATTR1_IS_CHANNELLED;
});
// Soothing Breeze
@@ -1050,7 +1050,7 @@ struct npc_thorim_trashAI : public ScriptedAI
static Unit* GetHealTarget(SpellInfo const* spellInfo, Unit* caster)
{
Unit* healTarget = nullptr;
if (!spellInfo->HasAttribute(SPELL_ATTR1_CANT_TARGET_SELF) && !roll_chance_f(caster->GetHealthPct()) && ((caster->GetHealth() + GetRemainingHealOn(caster) + GetTotalHeal(spellInfo, caster)) <= caster->GetMaxHealth()))
if (!spellInfo->HasAttribute(SPELL_ATTR1_EXCLUDE_CASTER) && !roll_chance_f(caster->GetHealthPct()) && ((caster->GetHealth() + GetRemainingHealOn(caster) + GetTotalHeal(spellInfo, caster)) <= caster->GetMaxHealth()))
healTarget = caster;
else
healTarget = GetUnitWithMostMissingHp(spellInfo, caster);
+1 -1
View File
@@ -2729,7 +2729,7 @@ class spell_gen_profession_research : public SpellScriptLoader
if (uint32 discoveredSpellId = GetExplicitDiscoverySpell(spellId, caster))
caster->LearnSpell(discoveredSpellId, false);
caster->UpdateCraftSkill(spellId);
caster->UpdateCraftSkill(GetSpellInfo());
}
void Register() override