Advertisement
siewdass

wow

May 25th, 2025 (edited)
193
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 19.85 KB | None | 0 0
  1. Unit.cpp
  2.  
  3. void Unit::InterruptSpell(CurrentSpellTypes spellType, bool withDelayed, bool withInstant, SpellCastResult result, Optional<SpellCastResult> resultOther /*= {}*/)
  4. {
  5.    
  6.     //TC_LOG_DEBUG("entities.unit", "Interrupt spell for unit {}.", GetEntry());
  7.     Spell* spell = m_currentSpells[spellType];
  8.        
  9.     if (spell
  10.         && (withDelayed || spell->getState() != SPELL_STATE_DELAYED)
  11.         && (withInstant || spell->GetCastTime() > 0 || spell->getState() == SPELL_STATE_CASTING))
  12.     {
  13.         // for example, do not let self-stun aura interrupt itself
  14.         if (!spell->IsInterruptable())
  15.             return;
  16.  
  17.         // send autorepeat cancel message for autorepeat spells
  18.         if (spellType == CURRENT_AUTOREPEAT_SPELL)
  19.             if (GetTypeId() == TYPEID_PLAYER)
  20.                 ToPlayer()->SendAutoRepeatCancel(this);
  21.  
  22.         if (spell->getState() != SPELL_STATE_FINISHED)
  23.             spell->cancel(result, resultOther);
  24.         else
  25.         {
  26.             m_currentSpells[spellType] = nullptr;
  27.             spell->SetReferencedFromCurrent(false);
  28.         }
  29.  
  30.         if (GetTypeId() == TYPEID_UNIT && IsAIEnabled())
  31.             ToCreature()->AI()->OnSpellFailed(spell->GetSpellInfo());
  32.     }
  33. }
  34.  
  35. void Unit::_UpdateAutoRepeatSpell()
  36. {
  37.     SpellInfo const* autoRepeatSpellInfo = m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo;
  38.  
  39.     // check "realtime" interrupts
  40.     if ((GetTypeId() == TYPEID_PLAYER && ToPlayer()->isMoving()) || IsNonMeleeSpellCast(false, false, false, (autoRepeatSpellInfo->Id == 75 || autoRepeatSpellInfo->Id == 5019)))
  41.     {
  42.         // cancel wand shoot
  43.         if (autoRepeatSpellInfo->Id != 75 && autoRepeatSpellInfo->Id != 5019)
  44.             InterruptSpell(CURRENT_AUTOREPEAT_SPELL);
  45.         m_AutoRepeatFirstCast = true;
  46.         return;
  47.     }
  48.  
  49.     // apply delay (Auto Shot (spellID 75) not affected)
  50.     if (m_AutoRepeatFirstCast && getAttackTimer(RANGED_ATTACK) < 500 && autoRepeatSpellInfo->Id != 75 && autoRepeatSpellInfo->Id != 5019)
  51.         setAttackTimer(RANGED_ATTACK, 500);
  52.     m_AutoRepeatFirstCast = false;
  53.  
  54.     // castroutine
  55.     if (isAttackReady(RANGED_ATTACK))
  56.     {
  57.         // Check if able to cast
  58.         SpellCastResult result = m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->CheckCast(true);
  59.         if (result != SPELL_CAST_OK)
  60.         {
  61.             if (autoRepeatSpellInfo->Id != 75 && autoRepeatSpellInfo->Id != 5019)
  62.                 InterruptSpell(CURRENT_AUTOREPEAT_SPELL);
  63.             else if (GetTypeId() == TYPEID_PLAYER)
  64.                 Spell::SendCastResult(ToPlayer(), autoRepeatSpellInfo, 1, result);
  65.  
  66.             return;
  67.         }
  68.  
  69.         // we want to shoot
  70.         Spell* spell = new Spell(this, autoRepeatSpellInfo, TRIGGERED_FULL_MASK);
  71.         spell->prepare(m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_targets);
  72.  
  73.         // all went good, reset attack
  74.         resetAttackTimer(RANGED_ATTACK);
  75.     }
  76. }
  77.  
  78. bool Unit::IsNonMeleeSpellCast(bool withDelayed, bool skipChanneled, bool skipAutorepeat, bool isAutoshoot, bool skipInstant) const
  79. {
  80.     // We don't do loop here to explicitly show that melee spell is excluded.
  81.     // Maybe later some special spells will be excluded too.
  82.  
  83.     // generic spells are cast when they are not finished and not delayed
  84.     if (m_currentSpells[CURRENT_GENERIC_SPELL] &&
  85.         (m_currentSpells[CURRENT_GENERIC_SPELL]->getState() != SPELL_STATE_FINISHED) &&
  86.         (withDelayed || m_currentSpells[CURRENT_GENERIC_SPELL]->getState() != SPELL_STATE_DELAYED))
  87.     {
  88.         if (!skipInstant || m_currentSpells[CURRENT_GENERIC_SPELL]->GetCastTime())
  89.         {
  90.             if (!isAutoshoot || !(m_currentSpells[CURRENT_GENERIC_SPELL]->m_spellInfo->HasAttribute(SPELL_ATTR2_NOT_RESET_AUTO_ACTIONS)))
  91.                 return true;
  92.         }
  93.     }
  94.     // channeled spells may be delayed, but they are still considered cast
  95.     if (!skipChanneled && m_currentSpells[CURRENT_CHANNELED_SPELL] &&
  96.         (m_currentSpells[CURRENT_CHANNELED_SPELL]->getState() != SPELL_STATE_FINISHED))
  97.     {
  98.         if (!isAutoshoot || !(m_currentSpells[CURRENT_CHANNELED_SPELL]->m_spellInfo->HasAttribute(SPELL_ATTR2_NOT_RESET_AUTO_ACTIONS)))
  99.             return true;
  100.     }
  101.     // autorepeat spells may be finished or delayed, but they are still considered cast
  102.     if (!skipAutorepeat && m_currentSpells[CURRENT_AUTOREPEAT_SPELL] )
  103.         return true;
  104.  
  105.     return false;
  106. }
  107.  
  108. void Unit::SetCurrentCastSpell(Spell* pSpell)
  109. {
  110.     ASSERT(pSpell);                                         // NULL may be never passed here, use InterruptSpell or InterruptNonMeleeSpells
  111.  
  112.     CurrentSpellTypes CSpellType = pSpell->GetCurrentContainer();
  113.  
  114.     if (pSpell == m_currentSpells[CSpellType])             // avoid breaking self
  115.         return;
  116.  
  117.     // break same type spell if it is not delayed
  118.     InterruptSpell(CSpellType, false);
  119.  
  120.     // special breakage effects:
  121.     switch (CSpellType)
  122.     {
  123.         case CURRENT_GENERIC_SPELL:
  124.         {
  125.             // generic spells always break channeled not delayed spells
  126.             InterruptSpell(CURRENT_CHANNELED_SPELL, false);
  127.  
  128.             // autorepeat breaking
  129.             if (m_currentSpells[CURRENT_AUTOREPEAT_SPELL])
  130.             {
  131.                 // break autorepeat if not Auto Shot
  132.                 if (m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->GetSpellInfo()->Id != 75 &&
  133.                     m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->GetSpellInfo()->Id != 5019)
  134.                     InterruptSpell(CURRENT_AUTOREPEAT_SPELL);
  135.                 m_AutoRepeatFirstCast = true;
  136.             }
  137.             if (pSpell->GetCastTime() > 0)
  138.                 AddUnitState(UNIT_STATE_CASTING);
  139.  
  140.             break;
  141.         }
  142.         case CURRENT_CHANNELED_SPELL:
  143.         {
  144.             // channel spells always break generic non-delayed and any channeled spells
  145.             InterruptSpell(CURRENT_GENERIC_SPELL, false);
  146.             InterruptSpell(CURRENT_CHANNELED_SPELL);
  147.  
  148.             // it also does break autorepeat if not Auto Shot
  149.             if (m_currentSpells[CURRENT_AUTOREPEAT_SPELL] &&
  150.                 m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->GetSpellInfo()->Id != 75 &&
  151.                 m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->GetSpellInfo()->Id != 5019)
  152.                 InterruptSpell(CURRENT_AUTOREPEAT_SPELL);
  153.             AddUnitState(UNIT_STATE_CASTING);
  154.  
  155.             break;
  156.         }
  157.         case CURRENT_AUTOREPEAT_SPELL:
  158.         {
  159.             // only Auto Shoot does not break anything
  160.             if (pSpell->GetSpellInfo()->Id != 75 && pSpell->GetSpellInfo()->Id != 5019)
  161.             {
  162.                 // generic autorepeats break generic non-delayed and channeled non-delayed spells
  163.                 InterruptSpell(CURRENT_GENERIC_SPELL, false);
  164.                 InterruptSpell(CURRENT_CHANNELED_SPELL, false);
  165.             }
  166.             // special action: set first cast flag
  167.             m_AutoRepeatFirstCast = true;
  168.  
  169.             break;
  170.         }
  171.         default:
  172.             break; // other spell types don't break anything now
  173.     }
  174.  
  175.     // current spell (if it is still here) may be safely deleted now
  176.     if (m_currentSpells[CSpellType])
  177.         m_currentSpells[CSpellType]->SetReferencedFromCurrent(false);
  178.  
  179.     // set new current spell
  180.     m_currentSpells[CSpellType] = pSpell;
  181.     pSpell->SetReferencedFromCurrent(true);
  182.  
  183.     pSpell->m_selfContainer = &(m_currentSpells[pSpell->GetCurrentContainer()]);
  184. }
  185.  
  186. /* -------------------------------------------------------------------------------- */
  187.  
  188. Spellhistory.cpp
  189.  
  190. void SpellHistory::StartCooldown(SpellInfo const* spellInfo, uint32 itemId, Spell* spell /*= nullptr*/, bool onHold /*= false*/)
  191. {
  192.     if (spellInfo->Id == 5019)
  193.         return;
  194.  
  195.     // init cooldown values
  196.     uint32 categoryId = 0;
  197.     int32 cooldown = -1;
  198.     int32 categoryCooldown = -1;
  199.  
  200.     GetCooldownDurations(spellInfo, itemId, &cooldown, &categoryId, &categoryCooldown);
  201.  
  202.     Clock::time_point curTime = GameTime::GetSystemTime();
  203.     Clock::time_point catrecTime;
  204.     Clock::time_point recTime;
  205.     bool needsCooldownPacket = false;
  206.  
  207.     // overwrite time for selected category
  208.     if (onHold)
  209.     {
  210.         // use +MONTH as infinite cooldown marker
  211.         catrecTime = categoryCooldown > 0 ? (curTime + InfinityCooldownDelay) : curTime;
  212.         recTime = cooldown > 0 ? (curTime + InfinityCooldownDelay) : catrecTime;
  213.     }
  214.     else
  215.     {
  216.         // shoot spells used equipped item cooldown values already assigned in GetAttackTime(RANGED_ATTACK)
  217.         // prevent 0 cooldowns set by another way
  218.         if (cooldown <= 0 && categoryCooldown <= 0 && (categoryId == 76 || (spellInfo->IsAutoRepeatRangedSpell() && spellInfo->Id != 75 && spellInfo->Id != 5019)))
  219.             cooldown = _owner->GetAttackTime(RANGED_ATTACK);
  220.  
  221.         // Now we have cooldown data (if found any), time to apply mods
  222.         if (Player* modOwner = _owner->GetSpellModOwner())
  223.         {
  224.             if (cooldown >= 0)
  225.                 modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_COOLDOWN, cooldown, spell);
  226.  
  227.             if (categoryCooldown >= 0 && !spellInfo->HasAttribute(SPELL_ATTR6_IGNORE_CATEGORY_COOLDOWN_MODS))
  228.                 modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_COOLDOWN, categoryCooldown, spell);
  229.         }
  230.  
  231.         if (int32 cooldownMod = _owner->GetTotalAuraModifier(SPELL_AURA_MOD_COOLDOWN))
  232.         {
  233.             // Apply SPELL_AURA_MOD_COOLDOWN only to own spells
  234.             Player* playerOwner = GetPlayerOwner();
  235.             if (!playerOwner || playerOwner->HasSpell(spellInfo->Id))
  236.             {
  237.                 needsCooldownPacket = true;
  238.                 cooldown += cooldownMod * IN_MILLISECONDS;   // SPELL_AURA_MOD_COOLDOWN does not affect category cooldows, verified with shaman shocks
  239.             }
  240.         }
  241.  
  242.         // replace negative cooldowns by 0
  243.         if (cooldown < 0)
  244.             cooldown = 0;
  245.  
  246.         if (categoryCooldown < 0)
  247.             categoryCooldown = 0;
  248.  
  249.         // no cooldown after applying spell mods
  250.         if (cooldown == 0 && categoryCooldown == 0)
  251.             return;
  252.  
  253.         catrecTime = categoryCooldown ? curTime + std::chrono::duration_cast<Clock::duration>(std::chrono::milliseconds(categoryCooldown)) : curTime;
  254.         recTime = cooldown ? curTime + std::chrono::duration_cast<Clock::duration>(std::chrono::milliseconds(cooldown)) : catrecTime;
  255.     }
  256.  
  257.     // self spell cooldown
  258.     if (recTime != curTime)
  259.     {
  260.         AddCooldown(spellInfo->Id, itemId, recTime, categoryId, catrecTime, onHold);
  261.  
  262.         if (needsCooldownPacket)
  263.         {
  264.             if (Player* playerOwner = GetPlayerOwner())
  265.             {
  266.                 WorldPacket spellCooldown;
  267.                 BuildCooldownPacket(spellCooldown, SPELL_COOLDOWN_FLAG_NONE, spellInfo->Id, cooldown);
  268.                 playerOwner->SendDirectMessage(&spellCooldown);
  269.             }
  270.         }
  271.     }
  272. }
  273.  
  274. /* -------------------------------------------------------------------------------- */
  275.  
  276. Spell.cpp
  277.  
  278. SpellCastResult Spell::prepare(SpellCastTargets const& targets, AuraEffect const* triggeredByAura)
  279. {
  280.     if (m_CastItem)
  281.     {
  282.         m_castItemGUID = m_CastItem->GetGUID();
  283.         m_castItemEntry = m_CastItem->GetEntry();
  284.     }
  285.     else
  286.     {
  287.         m_castItemGUID.Clear();
  288.         m_castItemEntry = 0;
  289.     }
  290.  
  291.     InitExplicitTargets(targets);
  292.  
  293.     // Fill aura scaling information
  294.     if (Unit* unitCaster = m_caster->ToUnit())
  295.     {
  296.         if (unitCaster->IsControlledByPlayer() && !m_spellInfo->IsPassive() && m_spellInfo->SpellLevel && !m_spellInfo->IsChanneled() && !(_triggeredCastFlags & TRIGGERED_IGNORE_AURA_SCALING))
  297.         {
  298.             for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects())
  299.             {
  300.                 if (spellEffectInfo.IsEffect(SPELL_EFFECT_APPLY_AURA))
  301.                 {
  302.                     // Change aura with ranks only if basepoints are taken from spellInfo and aura is positive
  303.                     if (m_spellInfo->IsPositiveEffect(spellEffectInfo.EffectIndex))
  304.                     {
  305.                         m_auraScaleMask |= (1 << spellEffectInfo.EffectIndex);
  306.                         if (m_spellValue->EffectBasePoints[spellEffectInfo.EffectIndex] != spellEffectInfo.BasePoints)
  307.                         {
  308.                             m_auraScaleMask = 0;
  309.                             break;
  310.                         }
  311.                     }
  312.                 }
  313.             }
  314.         }
  315.     }
  316.  
  317.     m_spellState = SPELL_STATE_PREPARING;
  318.  
  319.     if (triggeredByAura)
  320.         m_triggeredByAuraSpell  = triggeredByAura->GetSpellInfo();
  321.  
  322.     // create and add update event for this spell
  323.     _spellEvent = new SpellEvent(this);
  324.     m_caster->m_Events.AddEvent(_spellEvent, m_caster->m_Events.CalculateTime(1ms));
  325.  
  326.     // check disables
  327.     if (DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, m_caster))
  328.     {
  329.         SendCastResult(SPELL_FAILED_SPELL_UNAVAILABLE);
  330.         finish(false);
  331.         return SPELL_FAILED_SPELL_UNAVAILABLE;
  332.     }
  333.  
  334.     // Prevent casting at cast another spell (ServerSide check)
  335.     if (!(_triggeredCastFlags & TRIGGERED_IGNORE_CAST_IN_PROGRESS) &&
  336.         m_caster->ToUnit() &&
  337.         m_caster->ToUnit()->IsNonMeleeSpellCast(false, true, false, true) &&
  338.         m_cast_count && m_spellInfo->Id != 5019)
  339.     {    
  340.         SendCastResult(SPELL_FAILED_SPELL_IN_PROGRESS);
  341.         finish(false);
  342.         return SPELL_FAILED_SPELL_IN_PROGRESS;
  343.     }
  344.  
  345.     LoadScripts();
  346.  
  347.     // Fill cost data (do not use power for item casts)
  348.     m_powerCost = m_CastItem ? 0 : m_spellInfo->CalcPowerCost(m_caster, m_spellSchoolMask, this);
  349.  
  350.     // Set combo point requirement
  351.     if ((_triggeredCastFlags & TRIGGERED_IGNORE_COMBO_POINTS) || m_CastItem)
  352.         m_needComboPoints = false;
  353.  
  354.     uint32 param1 = 0, param2 = 0;
  355.     SpellCastResult result = CheckCast(true, &param1, &param2);
  356.     if (result != SPELL_CAST_OK && !IsAutoRepeat())          //always cast autorepeat dummy for triggering
  357.     {
  358.         // Periodic auras should be interrupted when aura triggers a spell which can't be cast
  359.         // for example bladestorm aura should be removed on disarm as of patch 3.3.5
  360.         // channeled periodic spells should be affected by this (arcane missiles, penance, etc)
  361.         // a possible alternative sollution for those would be validating aura target on unit state change
  362.         if (triggeredByAura && triggeredByAura->IsPeriodic() && !triggeredByAura->GetBase()->IsPassive())
  363.         {
  364.             SendChannelUpdate(0);
  365.             triggeredByAura->GetBase()->SetDuration(0);
  366.         }
  367.  
  368.         if (param1 || param2)
  369.             SendCastResult(result, &param1, &param2);
  370.         else
  371.             SendCastResult(result);
  372.  
  373.         finish(false);
  374.         return result;
  375.     }
  376.  
  377.     // Prepare data for triggers
  378.     prepareDataForTriggerSystem();
  379.  
  380.     if (Player* player = m_caster->ToPlayer())
  381.     {
  382.         if (!player->GetCommandStatus(CHEAT_CASTTIME))
  383.         {
  384.             // calculate cast time (calculated after first CheckCast check to prevent charge counting for first CheckCast fail)
  385.             m_casttime = m_spellInfo->CalcCastTime(this);
  386.         }
  387.         else
  388.             m_casttime = 0; // Set cast time to 0 if .cheat casttime is enabled.
  389.     }
  390.     else
  391.         m_casttime = m_spellInfo->CalcCastTime(this);
  392.  
  393.     SpellCastResult movementResult = SPELL_CAST_OK;
  394.     if (m_caster->IsUnit() && m_caster->ToUnit()->isMoving())
  395.         movementResult = CheckMovement();
  396.  
  397.     // Creatures focus their target when possible
  398.     if (m_casttime && m_caster->IsCreature() && !m_spellInfo->IsNextMeleeSwingSpell() && !IsAutoRepeat() && !m_caster->ToUnit()->HasUnitFlag(UNIT_FLAG_POSSESSED))
  399.     {
  400.         // Channeled spells and some triggered spells do not focus a cast target. They face their target later on via channel object guid and via spell attribute or not at all
  401.         bool const focusTarget = !m_spellInfo->IsChanneled() && !(_triggeredCastFlags & TRIGGERED_IGNORE_SET_FACING);
  402.         if (focusTarget && m_targets.GetObjectTarget() && m_caster != m_targets.GetObjectTarget())
  403.             m_caster->ToCreature()->SetSpellFocus(this, m_targets.GetObjectTarget());
  404.         else
  405.             m_caster->ToCreature()->SetSpellFocus(this, nullptr);
  406.     }
  407.  
  408.     if (movementResult != SPELL_CAST_OK)
  409.     {
  410.         if (m_caster->ToUnit()->IsControlledByPlayer() || !CanStopMovementForSpellCasting(m_caster->ToUnit()->GetMotionMaster()->GetCurrentMovementGeneratorType()))
  411.         {
  412.             SendCastResult(movementResult);
  413.             finish(movementResult);
  414.             return movementResult;
  415.         }
  416.         else
  417.         {
  418.             // Creatures (not controlled) give priority to spell casting over movement.
  419.             // We assume that the casting is always valid and the current movement
  420.             // is stopped immediately (because spells are updated before movement, so next Unit::Update would cancel the spell before stopping movement)
  421.             // and future attempts are stopped by by Unit::IsMovementPreventedByCasting in movement generators to prevent casting interruption.
  422.             m_caster->ToUnit()->StopMoving();
  423.         }
  424.     }
  425.  
  426.     // set timer base at cast time
  427.     ReSetTimer();
  428.  
  429.     TC_LOG_DEBUG("spells", "Spell::prepare: spell id {} source {} caster {} customCastFlags {} mask {}", m_spellInfo->Id, m_caster->GetEntry(), m_originalCaster ? m_originalCaster->GetEntry() : -1, _triggeredCastFlags, m_targets.GetTargetMask());
  430.  
  431.     //Containers for channeled spells have to be set
  432.     /// @todoApply this to all cast spells if needed
  433.     // Why check duration? 29350: channelled triggers channelled
  434.     if ((_triggeredCastFlags & TRIGGERED_CAST_DIRECTLY) && (!m_spellInfo->IsChanneled() || !m_spellInfo->GetMaxDuration()))
  435.         cast(true);
  436.     else
  437.     {
  438.         if (Unit* unitCaster = m_caster->ToUnit())
  439.         {
  440.             // stealth must be removed at cast starting (at show channel bar)
  441.             // skip triggered spell (item equip spell casting and other not explicit character casts/item uses)
  442.             if (!(_triggeredCastFlags & TRIGGERED_IGNORE_AURA_INTERRUPT_FLAGS) &&
  443.                 m_spellInfo->IsBreakingStealth() &&
  444.                 m_spellInfo->Id != 75)  // 5019 ahora interrumpe stealth
  445.             {
  446.                 unitCaster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CAST);
  447.                 for (SpellEffectInfo const& spellEffectInfo : m_spellInfo->GetEffects())
  448.                 {
  449.                     if (spellEffectInfo.GetUsedTargetObjectType() == TARGET_OBJECT_TYPE_UNIT)
  450.                     {
  451.                         unitCaster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_SPELL_ATTACK);
  452.                         break;
  453.                     }
  454.                 }
  455.             }
  456.  
  457.             unitCaster->SetCurrentCastSpell(this);
  458.         }
  459.         SendSpellStart();
  460.  
  461.         if (!(_triggeredCastFlags & TRIGGERED_IGNORE_GCD))
  462.             TriggerGlobalCooldown();
  463.  
  464.         // Call CreatureAI hook OnSpellStart
  465.         if (Creature* caster = m_caster->ToCreature())
  466.                 if (caster->IsAIEnabled())
  467.                     caster->AI()->OnSpellStart(GetSpellInfo());
  468.  
  469.             // commented out !m_spellInfo->StartRecoveryTime, it forces instant spells with global cooldown to be processed in spell::update
  470.             // as a result a spell that passed CheckCast and should be processed instantly may suffer from this delayed process
  471.             // the easiest bug to observe is LoS check in AddUnitTarget, even if spell passed the CheckCast LoS check the situation can change in spell::update
  472.             // because target could be relocated in the meantime, making the spell fly to the air (no targets can be registered, so no effects processed, nothing in combat log)
  473.             if (!m_casttime && /*!m_spellInfo->StartRecoveryTime && */ GetCurrentContainer() == CURRENT_GENERIC_SPELL)
  474.                 cast(true);
  475.  
  476.         return SPELL_CAST_OK;
  477.     }
  478.     return SPELL_CAST_OK;
  479. }
  480.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement