diff options
Diffstat (limited to 'src/server/game/Spells/Spell.cpp')
| -rw-r--r-- | src/server/game/Spells/Spell.cpp | 488 |
1 files changed, 281 insertions, 207 deletions
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 1e53256eec5..621e8cd185d 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -2947,7 +2947,8 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered if ((_triggeredCastFlags & TRIGGERED_IGNORE_COMBO_POINTS) || m_CastItem || !m_caster->m_playerMovingMe) m_needComboPoints = false; - SpellCastResult result = CheckCast(true); + uint32 param1 = 0, param2 = 0; + SpellCastResult result = CheckCast(true, ¶m1, ¶m2); if (result != SPELL_CAST_OK && !IsAutoRepeat()) //always cast autorepeat dummy for triggering { // Periodic auras should be interrupted when aura triggers a spell which can't be cast @@ -2968,7 +2969,10 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered m_caster->ToPlayer()->SetSpellModTakingSpell(this, false); } - SendCastResult(result); + if (param1 || param2) + SendCastResult(result, ¶m1, ¶m2); + else + SendCastResult(result); finish(false); return; @@ -3155,10 +3159,11 @@ void Spell::cast(bool skipCheck) // skip check if done already (for instant cast spells for example) if (!skipCheck) { - SpellCastResult castResult = CheckCast(false); + uint32 param1 = 0, param2 = 0; + SpellCastResult castResult = CheckCast(false, ¶m1, ¶m2); if (castResult != SPELL_CAST_OK) { - SendCastResult(castResult); + SendCastResult(castResult, ¶m1, ¶m2); SendInterrupted(0); //restore spell mods if (m_caster->GetTypeId() == TYPEID_PLAYER) @@ -3704,7 +3709,7 @@ void Spell::finish(bool ok) m_caster->AttackStop(); } -void Spell::WriteCastResultInfo(WorldPacket& data, Player* caster, SpellInfo const* spellInfo, uint8 castCount, SpellCastResult result, SpellCustomErrors customError) +void Spell::WriteCastResultInfo(WorldPacket& data, Player* caster, SpellInfo const* spellInfo, uint8 castCount, SpellCastResult result, SpellCustomErrors customError, uint32* param1 /*= nullptr*/, uint32* param2 /*= nullptr*/) { data << uint8(castCount); // single cast or multi 2.3 (0/1) data << uint32(spellInfo->Id); @@ -3712,115 +3717,185 @@ void Spell::WriteCastResultInfo(WorldPacket& data, Player* caster, SpellInfo con switch (result) { case SPELL_FAILED_REQUIRES_SPELL_FOCUS: - data << uint32(spellInfo->RequiresSpellFocus); // SpellFocusObject.dbc id + if (param1) + data << uint32(*param1); + else + data << uint32(spellInfo->RequiresSpellFocus); // SpellFocusObject.dbc id break; case SPELL_FAILED_REQUIRES_AREA: // AreaTable.dbc id - // hardcode areas limitation case - switch (spellInfo->Id) + if (param1) + data << uint32(*param1); + else { - case 41617: // Cenarion Mana Salve - case 41619: // Cenarion Healing Salve - data << uint32(3905); - break; - case 41618: // Bottled Nethergon Energy - case 41620: // Bottled Nethergon Vapor - data << uint32(3842); - break; - case 45373: // Bloodberry Elixir - data << uint32(4075); - break; - default: // default case (don't must be) - data << uint32(0); - break; + // hardcode areas limitation case + switch (spellInfo->Id) + { + case 41617: // Cenarion Mana Salve + case 41619: // Cenarion Healing Salve + data << uint32(3905); + break; + case 41618: // Bottled Nethergon Energy + case 41620: // Bottled Nethergon Vapor + data << uint32(3842); + break; + case 45373: // Bloodberry Elixir + data << uint32(4075); + break; + default: // default case (don't must be) + data << uint32(0); + break; + } } break; case SPELL_FAILED_TOTEMS: - if (spellInfo->Totem[0]) - data << uint32(spellInfo->Totem[0]); - if (spellInfo->Totem[1]) - data << uint32(spellInfo->Totem[1]); + if (param1) + { + data << uint32(*param1); + if (param2) + data << uint32(*param2); + } + else + { + if (spellInfo->Totem[0]) + data << uint32(spellInfo->Totem[0]); + if (spellInfo->Totem[1]) + data << uint32(spellInfo->Totem[1]); + } break; case SPELL_FAILED_TOTEM_CATEGORY: - if (spellInfo->TotemCategory[0]) - data << uint32(spellInfo->TotemCategory[0]); - if (spellInfo->TotemCategory[1]) - data << uint32(spellInfo->TotemCategory[1]); + if (param1) + { + data << uint32(*param1); + if (param2) + data << uint32(*param2); + } + else + { + if (spellInfo->TotemCategory[0]) + data << uint32(spellInfo->TotemCategory[0]); + if (spellInfo->TotemCategory[1]) + data << uint32(spellInfo->TotemCategory[1]); + } break; case SPELL_FAILED_EQUIPPED_ITEM_CLASS: case SPELL_FAILED_EQUIPPED_ITEM_CLASS_MAINHAND: case SPELL_FAILED_EQUIPPED_ITEM_CLASS_OFFHAND: - data << uint32(spellInfo->EquippedItemClass); - data << uint32(spellInfo->EquippedItemSubClassMask); + if (param1 && param2) + { + data << uint32(*param1); + data << uint32(*param2); + } + else + { + data << uint32(spellInfo->EquippedItemClass); + data << uint32(spellInfo->EquippedItemSubClassMask); + } break; case SPELL_FAILED_TOO_MANY_OF_ITEM: { - uint32 item = 0; - for (int8 eff = 0; eff < MAX_SPELL_EFFECTS; eff++) - if (spellInfo->Effects[eff].ItemType) - item = spellInfo->Effects[eff].ItemType; - ItemTemplate const* proto = sObjectMgr->GetItemTemplate(item); - if (proto && proto->ItemLimitCategory) - data << uint32(proto->ItemLimitCategory); - break; + if (param1) + data << uint32(*param1); + else + { + uint32 item = 0; + for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS && !item; ++effIndex) + if (uint32 itemType = spellInfo->Effects[effIndex].ItemType) + item = itemType; + + ItemTemplate const* proto = sObjectMgr->GetItemTemplate(item); + if (proto && proto->ItemLimitCategory) + data << uint32(proto->ItemLimitCategory); + } + break; } case SPELL_FAILED_CUSTOM_ERROR: data << uint32(customError); break; case SPELL_FAILED_REAGENTS: { - uint32 missingItem = 0; - for (uint32 i = 0; i < MAX_SPELL_REAGENTS; i++) + if (param1) + data << uint32(*param1); + else { - if (spellInfo->Reagent[i] <= 0) - continue; + uint32 missingItem = 0; + for (uint32 i = 0; i < MAX_SPELL_REAGENTS; i++) + { + if (spellInfo->Reagent[i] <= 0) + continue; - uint32 itemid = spellInfo->Reagent[i]; - uint32 itemcount = spellInfo->ReagentCount[i]; + uint32 itemid = spellInfo->Reagent[i]; + uint32 itemcount = spellInfo->ReagentCount[i]; - if (!caster->HasItemCount(itemid, itemcount)) - { - missingItem = itemid; - break; + if (!caster->HasItemCount(itemid, itemcount)) + { + missingItem = itemid; + break; + } } - } - data << uint32(missingItem); // first missing item + data << uint32(missingItem); // first missing item + } break; } case SPELL_FAILED_PREVENTED_BY_MECHANIC: - data << uint32(spellInfo->Mechanic); + if (param1) + data << uint32(*param1); + else + data << uint32(spellInfo->Mechanic); break; case SPELL_FAILED_NEED_EXOTIC_AMMO: - data << uint32(spellInfo->EquippedItemSubClassMask); + if (param1) + data << uint32(*param1); + else + data << uint32(spellInfo->EquippedItemSubClassMask); break; case SPELL_FAILED_NEED_MORE_ITEMS: - data << uint32(0); // Item entry - data << uint32(0); // Count + if (param1 && param2) + { + data << uint32(*param1); + data << uint32(*param2); + } + else + { + data << uint32(0); // Item entry + data << uint32(0); // Count + } break; case SPELL_FAILED_MIN_SKILL: - data << uint32(0); // SkillLine.dbc Id - data << uint32(0); // Amount + if (param1 && param2) + { + data << uint32(*param1); + data << uint32(*param2); + } + else + { + data << uint32(0); // SkillLine.dbc Id + data << uint32(0); // Amount + } break; case SPELL_FAILED_FISHING_TOO_LOW: - data << uint32(0); // Skill level + if (param1) + data << uint32(*param1); + else + data << uint32(0); // Skill level break; default: break; } } -void Spell::SendCastResult(Player* caster, SpellInfo const* spellInfo, uint8 castCount, SpellCastResult result, SpellCustomErrors customError /*= SPELL_CUSTOM_ERROR_NONE*/) +void Spell::SendCastResult(Player* caster, SpellInfo const* spellInfo, uint8 castCount, SpellCastResult result, SpellCustomErrors customError /*= SPELL_CUSTOM_ERROR_NONE*/, uint32* param1 /*= nullptr*/, uint32* param2 /*= nullptr*/) { if (result == SPELL_CAST_OK) return; WorldPacket data(SMSG_CAST_FAILED, 1 + 4 + 1); - WriteCastResultInfo(data, caster, spellInfo, castCount, result, customError); + WriteCastResultInfo(data, caster, spellInfo, castCount, result, customError, param1, param2); - caster->GetSession()->SendPacket(&data); + caster->SendDirectMessage(&data); } -void Spell::SendCastResult(SpellCastResult result) +void Spell::SendCastResult(SpellCastResult result, uint32* param1 /*= nullptr*/, uint32* param2 /*= nullptr*/) const { if (result == SPELL_CAST_OK) return; @@ -3828,13 +3903,13 @@ void Spell::SendCastResult(SpellCastResult result) if (m_caster->GetTypeId() != TYPEID_PLAYER) return; - if (m_caster->ToPlayer()->GetSession()->PlayerLoading()) // don't send cast results at loading time + if (m_caster->ToPlayer()->IsLoading()) // don't send cast results at loading time return; if (_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) result = SPELL_FAILED_DONT_REPORT; - SendCastResult(m_caster->ToPlayer(), m_spellInfo, m_cast_count, result, m_customError); + SendCastResult(m_caster->ToPlayer(), m_spellInfo, m_cast_count, result, m_customError, param1, param2); } void Spell::SendPetCastResult(SpellCastResult result) @@ -4483,7 +4558,7 @@ void Spell::TakeAmmo() } } -SpellCastResult Spell::CheckRuneCost(uint32 runeCostID) +SpellCastResult Spell::CheckRuneCost(uint32 runeCostID) const { if (m_spellInfo->PowerType != POWER_RUNE || !runeCostID) return SPELL_CAST_OK; @@ -4508,7 +4583,7 @@ SpellCastResult Spell::CheckRuneCost(uint32 runeCostID) { runeCost[i] = src->RuneCost[i]; if (Player* modOwner = m_caster->GetSpellModOwner()) - modOwner->ApplySpellMod<SPELLMOD_COST>(m_spellInfo->Id, runeCost[i], this); + modOwner->ApplySpellMod<SPELLMOD_COST>(m_spellInfo->Id, runeCost[i], const_cast<Spell*>(this)); } runeCost[RUNE_DEATH] = MAX_RUNES; // calculated later @@ -4744,7 +4819,7 @@ void Spell::HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGOT } } -SpellCastResult Spell::CheckCast(bool strict) +SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint32* param2 /*= nullptr*/) { // check death state if (!m_caster->IsAlive() && !m_spellInfo->IsPassive() && !(m_spellInfo->HasAttribute(SPELL_ATTR0_CASTABLE_WHILE_DEAD) || (IsTriggered() && !m_triggeredByAuraSpell))) @@ -4807,13 +4882,15 @@ SpellCastResult Spell::CheckCast(bool strict) bool checkForm = true; // Ignore form req aura Unit::AuraEffectList const& ignore = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_SHAPESHIFT); - for (Unit::AuraEffectList::const_iterator i = ignore.begin(); i != ignore.end(); ++i) + for (AuraEffect const* aurEff : ignore) { - if (!(*i)->IsAffectedOnSpell(m_spellInfo)) + if (!aurEff->IsAffectedOnSpell(m_spellInfo)) continue; + checkForm = false; break; } + if (checkForm) { // Cannot be used in this stance/form @@ -5021,7 +5098,7 @@ SpellCastResult Spell::CheckCast(bool strict) // always (except passive spells) check items (only player related checks) if (!m_spellInfo->IsPassive()) { - castResult = CheckItems(); + castResult = CheckItems(param1, param2); if (castResult != SPELL_CAST_OK) return castResult; } @@ -5041,7 +5118,7 @@ SpellCastResult Spell::CheckCast(bool strict) if (!(_triggeredCastFlags & TRIGGERED_IGNORE_CASTER_AURAS)) { - castResult = CheckCasterAuras(); + castResult = CheckCasterAuras(param1); if (castResult != SPELL_CAST_OK) return castResult; } @@ -5055,6 +5132,7 @@ SpellCastResult Spell::CheckCast(bool strict) bool hasNonDispelEffect = false; uint32 dispelMask = 0; for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + { if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_DISPEL) { if (m_spellInfo->Effects[i].IsTargetingArea() || m_spellInfo->HasAttribute(SPELL_ATTR1_MELEE_COMBAT_START)) @@ -5070,6 +5148,7 @@ SpellCastResult Spell::CheckCast(bool strict) hasNonDispelEffect = true; break; } + } if (!hasNonDispelEffect && !hasDispellableAura && dispelMask && !IsTriggered()) { @@ -5653,139 +5732,110 @@ SpellCastResult Spell::CheckPetCast(Unit* target) return CheckCast(true); } -SpellCastResult Spell::CheckCasterAuras() const +SpellCastResult Spell::CheckCasterAuras(uint32* param1) const { // spells totally immuned to caster auras (wsg flag drop, give marks etc) if (m_spellInfo->HasAttribute(SPELL_ATTR6_IGNORE_CASTER_AURAS)) return SPELL_CAST_OK; - uint8 school_immune = 0; - uint32 mechanic_immune = 0; - uint32 dispel_immune = 0; - - // Check if the spell grants school or mechanic immunity. - // We use bitmasks so the loop is done only once and not on every aura check below. - if (m_spellInfo->HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY)) + bool usableWhileStunned = m_spellInfo->HasAttribute(SPELL_ATTR5_USABLE_WHILE_STUNNED); + bool usableWhileFeared = m_spellInfo->HasAttribute(SPELL_ATTR5_USABLE_WHILE_FEARED); + bool usableWhileConfused = m_spellInfo->HasAttribute(SPELL_ATTR5_USABLE_WHILE_CONFUSED); + if (m_spellInfo->HasAttribute(SPELL_ATTR7_USABLE_IN_STUN_FEAR_CONFUSION)) { - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - { - if (m_spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_SCHOOL_IMMUNITY) - school_immune |= uint32(m_spellInfo->Effects[i].MiscValue); - else if (m_spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_MECHANIC_IMMUNITY) - mechanic_immune |= 1 << uint32(m_spellInfo->Effects[i].MiscValue); - else if (m_spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_DISPEL_IMMUNITY) - dispel_immune |= SpellInfo::GetDispelMask(DispelType(m_spellInfo->Effects[i].MiscValue)); - } - // immune movement impairment and loss of control - if (m_spellInfo->Id == 42292 || m_spellInfo->Id == 59752 || m_spellInfo->Id == 19574 || m_spellInfo->Id == 53490) - mechanic_immune = IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK; + usableWhileStunned = true; + usableWhileFeared = true; + usableWhileConfused = true; } - bool usableInStun = m_spellInfo->HasAttribute(SPELL_ATTR5_USABLE_WHILE_STUNNED); - // Glyph of Pain Suppression // there is no other way to handle it if (m_spellInfo->Id == 33206 && !m_caster->HasAura(63248)) - usableInStun = false; + usableWhileStunned = false; // Check whether the cast should be prevented by any state you might have. - SpellCastResult prevented_reason = SPELL_CAST_OK; - // Have to check if there is a stun aura. Otherwise will have problems with ghost aura apply while logging out - uint32 unitflag = m_caster->GetUInt32Value(UNIT_FIELD_FLAGS); // Get unit state - if (unitflag & UNIT_FLAG_STUNNED) - { - // spell is usable while stunned, check if caster has allowed stun auras, another stun types must prevent cast spell - if (usableInStun) - { - static uint32 const allowedStunMask = - 1 << MECHANIC_STUN - | 1 << MECHANIC_FREEZE - | 1 << MECHANIC_SAPPED - | 1 << MECHANIC_SLEEP; - - bool foundNotStun = false; - Unit::AuraEffectList const& stunAuras = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_STUN); - for (Unit::AuraEffectList::const_iterator i = stunAuras.begin(); i != stunAuras.end(); ++i) - { - uint32 mechanicMask = (*i)->GetSpellInfo()->GetAllEffectsMechanicMask(); - if (mechanicMask && !(mechanicMask & allowedStunMask)) - { - foundNotStun = true; - break; - } - } - if (foundNotStun) - prevented_reason = SPELL_FAILED_STUNNED; - } - else - prevented_reason = SPELL_FAILED_STUNNED; - } - else if (unitflag & UNIT_FLAG_CONFUSED && !m_spellInfo->HasAttribute(SPELL_ATTR5_USABLE_WHILE_CONFUSED)) - prevented_reason = SPELL_FAILED_CONFUSED; - else if (unitflag & UNIT_FLAG_FLEEING && !m_spellInfo->HasAttribute(SPELL_ATTR5_USABLE_WHILE_FEARED)) - prevented_reason = SPELL_FAILED_FLEEING; - else if (unitflag & UNIT_FLAG_SILENCED && m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE) - prevented_reason = SPELL_FAILED_SILENCED; - else if (unitflag & UNIT_FLAG_PACIFIED && m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_PACIFY) - prevented_reason = SPELL_FAILED_PACIFIED; + SpellCastResult result = SPELL_CAST_OK; + + // Get unit state + uint32 const unitflag = m_caster->GetUInt32Value(UNIT_FIELD_FLAGS); + if (m_caster->GetCharmerGUID() && !CheckCasterNotImmunedCharmAuras(param1)) + result = SPELL_FAILED_CHARMED; + else if (unitflag & UNIT_FLAG_STUNNED && !usableWhileStunned && CheckCasterNotImmunedStunAuras(param1)) + result = SPELL_FAILED_STUNNED; + else if (unitflag & UNIT_FLAG_SILENCED && m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE && CheckCasterNotImmunedSilenceAuras(param1)) + result = SPELL_FAILED_SILENCED; + else if (unitflag & UNIT_FLAG_PACIFIED && m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_PACIFY && CheckCasterNotImmunedPacifyAuras(param1)) + result = SPELL_FAILED_PACIFIED; + else if (unitflag & UNIT_FLAG_FLEEING && !usableWhileFeared && CheckCasterNotImmunedFearAuras(param1)) + result = SPELL_FAILED_FLEEING; + else if (unitflag & UNIT_FLAG_CONFUSED && !usableWhileConfused && CheckCasterNotImmunedDisorientAuras(param1)) + result = SPELL_FAILED_CONFUSED; // Attr must make flag drop spell totally immune from all effects - if (prevented_reason != SPELL_CAST_OK) + if (result != SPELL_CAST_OK) + return (param1 && *param1) ? SPELL_FAILED_PREVENTED_BY_MECHANIC : result; + + return SPELL_CAST_OK; +} + +// based on sub_00804430 from 12340 client +bool Spell::CheckCasterHasNotImmunedAuraType(AuraType auraType, uint32* param1) const +{ + // Checking auras is needed now, because you are prevented by some state but the spell grants immunity. + Unit::AuraEffectList const& auraEffects = m_caster->GetAuraEffectsByType(auraType); + if (auraEffects.empty()) + return false; + + for (AuraEffect const* aurEff : auraEffects) { - if (school_immune || mechanic_immune || dispel_immune) - { - //Checking auras is needed now, because you are prevented by some state but the spell grants immunity. - Unit::AuraApplicationMap const& auras = m_caster->GetAppliedAuras(); - for (Unit::AuraApplicationMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) - { - Aura const* aura = itr->second->GetBase(); - SpellInfo const* auraInfo = aura->GetSpellInfo(); - if (auraInfo->GetAllEffectsMechanicMask() & mechanic_immune) - continue; - if (auraInfo->GetSchoolMask() & school_immune && !auraInfo->HasAttribute(SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE)) - continue; - if (auraInfo->GetDispelMask() & dispel_immune) - continue; + SpellInfo const* auraInfo = aurEff->GetSpellInfo(); + if (m_spellInfo->CanSpellCastOverrideAuraEffect(auraInfo, aurEff->GetEffIndex())) + continue; - //Make a second check for spell failed so the right SPELL_FAILED message is returned. - //That is needed when your casting is prevented by multiple states and you are only immune to some of them. - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - { - if (AuraEffect* part = aura->GetEffect(i)) - { - switch (part->GetAuraType()) - { - case SPELL_AURA_MOD_STUN: - if (!usableInStun || !(auraInfo->GetAllEffectsMechanicMask() & (1<<MECHANIC_STUN))) - return SPELL_FAILED_STUNNED; - break; - case SPELL_AURA_MOD_CONFUSE: - if (!m_spellInfo->HasAttribute(SPELL_ATTR5_USABLE_WHILE_CONFUSED)) - return SPELL_FAILED_CONFUSED; - break; - case SPELL_AURA_MOD_FEAR: - if (!m_spellInfo->HasAttribute(SPELL_ATTR5_USABLE_WHILE_FEARED)) - return SPELL_FAILED_FLEEING; - break; - case SPELL_AURA_MOD_SILENCE: - case SPELL_AURA_MOD_PACIFY: - case SPELL_AURA_MOD_PACIFY_SILENCE: - if (m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_PACIFY) - return SPELL_FAILED_PACIFIED; - else if (m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE) - return SPELL_FAILED_SILENCED; - break; - default: break; - } - } - } - } + if (param1) + { + *param1 = auraInfo->Effects[aurEff->GetEffIndex()].Mechanic; + if (!*param1) + *param1 = auraInfo->Mechanic; } - // You are prevented from casting and the spell cast does not grant immunity. Return a failed error. - else - return prevented_reason; + return true; } - return SPELL_CAST_OK; + + return false; +} + +bool Spell::CheckCasterNotImmunedCharmAuras(uint32* param1) const +{ + return CheckCasterHasNotImmunedAuraType(SPELL_AURA_MOD_CHARM, param1) || + CheckCasterHasNotImmunedAuraType(SPELL_AURA_AOE_CHARM, param1) || + CheckCasterHasNotImmunedAuraType(SPELL_AURA_MOD_POSSESS, param1); +} + +bool Spell::CheckCasterNotImmunedStunAuras(uint32* param1) const +{ + return CheckCasterHasNotImmunedAuraType(SPELL_AURA_MOD_STUN, param1); +} + +bool Spell::CheckCasterNotImmunedSilenceAuras(uint32* param1) const +{ + return CheckCasterHasNotImmunedAuraType(SPELL_AURA_MOD_SILENCE, param1) || + CheckCasterHasNotImmunedAuraType(SPELL_AURA_MOD_PACIFY_SILENCE, param1); +} + +bool Spell::CheckCasterNotImmunedPacifyAuras(uint32* param1) const +{ + return CheckCasterHasNotImmunedAuraType(SPELL_AURA_MOD_PACIFY, param1) || + CheckCasterHasNotImmunedAuraType(SPELL_AURA_MOD_PACIFY_SILENCE, param1); +} + +bool Spell::CheckCasterNotImmunedFearAuras(uint32* param1) const +{ + return CheckCasterHasNotImmunedAuraType(SPELL_AURA_MOD_FEAR, param1); +} + +bool Spell::CheckCasterNotImmunedDisorientAuras(uint32* param1) const +{ + return CheckCasterHasNotImmunedAuraType(SPELL_AURA_MOD_CONFUSE, param1); } bool Spell::CanAutoCast(Unit* target) @@ -5844,7 +5894,7 @@ bool Spell::CanAutoCast(Unit* target) return false; } -SpellCastResult Spell::CheckRange(bool strict) +SpellCastResult Spell::CheckRange(bool strict) const { // Don't check for instant cast spells if (!strict && m_casttime == 0) @@ -5874,20 +5924,20 @@ SpellCastResult Spell::CheckRange(bool strict) if (m_targets.HasDst() && !m_targets.HasTraj()) { if (m_caster->GetExactDistSq(m_targets.GetDstPos()) > maxRange) - return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_OUT_OF_RANGE : SPELL_FAILED_DONT_REPORT; + return SPELL_FAILED_OUT_OF_RANGE; if (minRange > 0.0f && m_caster->GetExactDistSq(m_targets.GetDstPos()) < minRange) - return !(_triggeredCastFlags & TRIGGERED_DONT_REPORT_CAST_ERROR) ? SPELL_FAILED_OUT_OF_RANGE : SPELL_FAILED_DONT_REPORT; + return SPELL_FAILED_OUT_OF_RANGE; } return SPELL_CAST_OK; } -std::pair<float, float> Spell::GetMinMaxRange(bool strict) +std::pair<float, float> Spell::GetMinMaxRange(bool strict) const { float rangeMod = 0.0f; float minRange = 0.0f; float maxRange = 0.0f; - if (strict && IsNextMeleeSwingSpell()) + if (strict && m_spellInfo->IsNextMeleeSwingSpell()) { maxRange = 100.0f; return std::pair<float, float>(minRange, maxRange); @@ -5929,14 +5979,14 @@ std::pair<float, float> Spell::GetMinMaxRange(bool strict) maxRange *= ranged->GetTemplate()->RangedModRange * 0.01f; if (Player* modOwner = m_caster->GetSpellModOwner()) - modOwner->ApplySpellMod<SPELLMOD_RANGE>(m_spellInfo->Id, maxRange, this); + modOwner->ApplySpellMod<SPELLMOD_RANGE>(m_spellInfo->Id, maxRange, const_cast<Spell*>(this)); maxRange += rangeMod; return std::pair<float, float>(minRange, maxRange); } -SpellCastResult Spell::CheckPower() +SpellCastResult Spell::CheckPower() const { // item cast not used power if (m_CastItem) @@ -5972,12 +6022,15 @@ SpellCastResult Spell::CheckPower() return SPELL_CAST_OK; } -SpellCastResult Spell::CheckItems() +SpellCastResult Spell::CheckItems(uint32* param1 /*= nullptr*/, uint32* param2 /*= nullptr*/) const { Player* player = m_caster->ToPlayer(); if (!player) return SPELL_CAST_OK; + if (m_spellInfo->HasAttribute(SPELL_ATTR2_IGNORE_ITEM_CHECK)) + return SPELL_CAST_OK; + if (!m_CastItem) { if (m_castItemGUID) @@ -6053,10 +6106,11 @@ SpellCastResult Spell::CheckItems() // check target item if (m_targets.GetItemTargetGUID()) { - if (!m_targets.GetItemTarget()) + Item* item = m_targets.GetItemTarget(); + if (!item) return SPELL_FAILED_ITEM_GONE; - if (!m_targets.GetItemTarget()->IsFitToSpellRequirements(m_spellInfo)) + if (!item->IsFitToSpellRequirements(m_spellInfo)) return SPELL_FAILED_EQUIPPED_ITEM_CLASS; } // if not item target then required item must be equipped @@ -6106,7 +6160,11 @@ SpellCastResult Spell::CheckItems() } } if (!player->HasItemCount(itemid, itemcount)) + { + if (param1) + *param1 = itemid; return SPELL_FAILED_REAGENTS; + } } } @@ -6310,21 +6368,29 @@ SpellCastResult Spell::CheckItems() } case SPELL_EFFECT_PROSPECTING: { - if (!m_targets.GetItemTarget()) + Item* item = m_targets.GetItemTarget(); + if (!item) return SPELL_FAILED_CANT_BE_PROSPECTED; //ensure item is a prospectable ore - if (!(m_targets.GetItemTarget()->GetTemplate()->Flags & ITEM_FLAG_IS_PROSPECTABLE)) + if (!(item->GetTemplate()->Flags & ITEM_FLAG_IS_PROSPECTABLE)) return SPELL_FAILED_CANT_BE_PROSPECTED; //prevent prospecting in trade slot - if (m_targets.GetItemTarget()->GetOwnerGUID() != m_caster->GetGUID()) + if (item->GetOwnerGUID() != m_caster->GetGUID()) return SPELL_FAILED_CANT_BE_PROSPECTED; //Check for enough skill in jewelcrafting - uint32 item_prospectingskilllevel = m_targets.GetItemTarget()->GetTemplate()->RequiredSkillRank; - if (item_prospectingskilllevel >player->GetSkillValue(SKILL_JEWELCRAFTING)) + uint32 item_prospectingskilllevel = item->GetTemplate()->RequiredSkillRank; + if (item_prospectingskilllevel > player->GetSkillValue(SKILL_JEWELCRAFTING)) return SPELL_FAILED_LOW_CASTLEVEL; //make sure the player has the required ores in inventory - if (m_targets.GetItemTarget()->GetCount() < 5) + if (item->GetCount() < 5) + { + if (param1 && param2) + { + *param1 = item->GetEntry(); + *param2 = 5; + } return SPELL_FAILED_NEED_MORE_ITEMS; + } if (!LootTemplates_Prospecting.HaveLootFor(m_targets.GetItemTargetEntry())) return SPELL_FAILED_CANT_BE_PROSPECTED; @@ -6333,21 +6399,29 @@ SpellCastResult Spell::CheckItems() } case SPELL_EFFECT_MILLING: { - if (!m_targets.GetItemTarget()) + Item* item = m_targets.GetItemTarget(); + if (!item) return SPELL_FAILED_CANT_BE_MILLED; //ensure item is a millable herb - if (!(m_targets.GetItemTarget()->GetTemplate()->Flags & ITEM_FLAG_IS_MILLABLE)) + if (!(item->GetTemplate()->Flags & ITEM_FLAG_IS_MILLABLE)) return SPELL_FAILED_CANT_BE_MILLED; //prevent milling in trade slot - if (m_targets.GetItemTarget()->GetOwnerGUID() != m_caster->GetGUID()) + if (item->GetOwnerGUID() != m_caster->GetGUID()) return SPELL_FAILED_CANT_BE_MILLED; //Check for enough skill in inscription - uint32 item_millingskilllevel = m_targets.GetItemTarget()->GetTemplate()->RequiredSkillRank; + uint32 item_millingskilllevel = item->GetTemplate()->RequiredSkillRank; if (item_millingskilllevel > player->GetSkillValue(SKILL_INSCRIPTION)) return SPELL_FAILED_LOW_CASTLEVEL; //make sure the player has the required herbs in inventory - if (m_targets.GetItemTarget()->GetCount() < 5) + if (item->GetCount() < 5) + { + if (param1 && param2) + { + *param1 = item->GetEntry(); + *param2 = 5; + } return SPELL_FAILED_NEED_MORE_ITEMS; + } if (!LootTemplates_Milling.HaveLootFor(m_targets.GetItemTargetEntry())) return SPELL_FAILED_CANT_BE_MILLED; |
