diff options
Diffstat (limited to 'src/game/Spell.cpp')
-rw-r--r-- | src/game/Spell.cpp | 192 |
1 files changed, 94 insertions, 98 deletions
diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index d0e1e3f9db3..f2f03249e22 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -119,6 +119,14 @@ void SpellCastTargets::setDestination(Unit *target, bool send) m_targetMask |= TARGET_FLAG_DEST_LOCATION; } +void SpellCastTargets::setSource(float x, float y, float z) +{ + m_srcX = x; + m_srcY = y; + m_srcZ = z; + m_targetMask |= TARGET_FLAG_SOURCE_LOCATION; +} + void SpellCastTargets::setGOTarget(GameObject *target) { m_GOTarget = target; @@ -354,6 +362,7 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi focusObject = NULL; m_cast_count = 0; m_glyphIndex = 0; + m_preCastSpell = 0; m_triggeredByAuraSpell = NULL; //Auto Shot & Shoot (wand) @@ -597,7 +606,6 @@ void Spell::FillTargetMap() } } - if(IsChanneledSpell(m_spellInfo) && !tmpUnitMap.empty()) m_needAliveTargetMask |= (1<<i); @@ -701,7 +709,7 @@ void Spell::prepareDataForTriggerSystem() } // Hunter traps spells (for Entrapment trigger) // Gives your Immolation Trap, Frost Trap, Explosive Trap, and Snake Trap .... - if (m_spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && m_spellInfo->SpellFamilyFlags & 0x0000200000000014LL) + if (m_spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && m_spellInfo->SpellFamilyFlags & 0x000020000000001CLL) m_procAttacker |= PROC_FLAG_ON_TRAP_ACTIVATION; } @@ -877,7 +885,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target) return; // Get original caster (if exist) and calculate damage/healing from him data - Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster; + Unit *caster = m_originalCaster ? m_originalCaster : m_caster; // Skip if m_originalCaster not avaiable if (!caster) @@ -970,25 +978,6 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target) int32 damagePoint = damageInfo.damage * 33 / 100; m_caster->CastCustomSpell(m_caster, 32220, &damagePoint, NULL, NULL, true); } - // Bloodthirst - else if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR && m_spellInfo->SpellFamilyFlags & 0x40000000000LL) - { - uint32 BTAura = 0; - switch(m_spellInfo->Id) - { - case 23881: BTAura = 23885; break; - case 23892: BTAura = 23886; break; - case 23893: BTAura = 23887; break; - case 23894: BTAura = 23888; break; - case 25251: BTAura = 25252; break; - case 30335: BTAura = 30339; break; - default: - sLog.outError("Spell::EffectSchoolDMG: Spell %u not handled in BTAura",m_spellInfo->Id); - break; - } - if (BTAura) - m_caster->CastSpell(m_caster,BTAura,true); - } } // Passive spell hits/misses or active spells only misses (only triggers) else @@ -1105,6 +1094,10 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask) unit->IncrDiminishing(m_diminishGroup); } + // Apply additional spell effects to target + if (m_preCastSpell) + m_caster->CastSpell(unit,m_preCastSpell, true, m_CastItem); + for(uint32 effectNumber=0;effectNumber<3;effectNumber++) { if (effectMask & (1<<effectNumber)) @@ -1604,7 +1597,6 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) m_targets.setDestination(((Player*)m_caster)->m_homebindX,((Player*)m_caster)->m_homebindY,((Player*)m_caster)->m_homebindZ, true, ((Player*)m_caster)->m_homebindMapId); break; - case TARGET_IN_FRONT_OF_CASTER: case TARGET_UNIT_CONE_ENEMY_UNKNOWN: if(m_customAttr & SPELL_ATTR_CU_CONE_BACK) @@ -2162,6 +2154,49 @@ void Spell::cast(bool skipCheck) if(m_customAttr & SPELL_ATTR_CU_DIRECT_DAMAGE) CalculateDamageDoneForAllTargets(); + switch(m_spellInfo->SpellFamilyName) + { + case SPELLFAMILY_GENERIC: + { + if (m_spellInfo->Mechanic == MECHANIC_BANDAGE) // Bandages + m_preCastSpell = 11196; // Recently Bandaged + else if(m_spellInfo->SpellIconID == 1662 && m_spellInfo->AttributesEx & 0x20) // Blood Fury (Racial) + m_preCastSpell = 23230; // Blood Fury - Healing Reduction + break; + } + case SPELLFAMILY_MAGE: + { + if (m_spellInfo->SpellFamilyFlags&0x0000008000000000LL) // Ice Block + m_preCastSpell = 41425; // Hypothermia + break; + } + case SPELLFAMILY_PRIEST: + { + if (m_spellInfo->Mechanic == MECHANIC_SHIELD && + m_spellInfo->SpellIconID == 566) // Power Word: Shield + m_preCastSpell = 6788; // Weakened Soul + if (m_spellInfo->Id == 47585) // Dispersion (transform) + m_preCastSpell = 60069; // Dispersion (mana regen) + break; + } + case SPELLFAMILY_PALADIN: + { + if (m_spellInfo->SpellFamilyFlags&0x0000000000400080LL) // Divine Shield, Divine Protection or Hand of Protection + m_preCastSpell = 25771; // Forbearance + break; + } + case SPELLFAMILY_SHAMAN: + { + if (m_spellInfo->Id == 2825) // Bloodlust + m_preCastSpell = 57724; // Sated + else if (m_spellInfo->Id == 32182) // Heroism + m_preCastSpell = 57723; // Exhaustion + break; + } + default: + break; + } + // traded items have trade slot instead of guid in m_itemTargetGUID // set to real guid to be sent later to the client m_targets.updateTradeSlotItem(); @@ -2644,68 +2679,6 @@ void Spell::finish(bool ok) m_caster->resetAttackTimer(RANGED_ATTACK); } - // Post effects apply on spell targets in some spells - if(!m_UniqueTargetInfo.empty()) - { - uint32 spellId = 0; - switch(m_spellInfo->SpellFamilyName) - { - case SPELLFAMILY_GENERIC: - { - if (m_spellInfo->Mechanic == MECHANIC_BANDAGE) // Bandages - spellId = 11196; // Recently Bandaged - else if(m_spellInfo->SpellIconID == 1662 && m_spellInfo->AttributesEx & 0x20) // Blood Fury (Racial) - spellId = 23230; // Blood Fury - Healing Reduction - break; - } - case SPELLFAMILY_MAGE: - { - if (m_spellInfo->SpellFamilyFlags&0x0000008000000000LL) // Ice Block - spellId = 41425; // Hypothermia - break; - } - case SPELLFAMILY_PRIEST: - { - if (m_spellInfo->Mechanic == MECHANIC_SHIELD && - m_spellInfo->SpellIconID == 566) // Power Word: Shield - spellId = 6788; // Weakened Soul - break; - } - case SPELLFAMILY_PALADIN: - { - if (m_spellInfo->SpellFamilyFlags&0x0000000000400080LL) // Divine Shield, Divine Protection or Hand of Protection - spellId = 25771; // Forbearance - break; - } - case SPELLFAMILY_SHAMAN: - { - if (m_spellInfo->Id == 2825) // Bloodlust - spellId = 57724; // Sated - else if (m_spellInfo->Id == 32182) // Heroism - spellId = 57723; // Exhaustion - break; - } - default: - break; - } - if (spellId) - { - for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit) - { - Unit* unit = m_caster->GetGUID()==ihit->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID); - if (unit) - { -// TODO: fix me use cast spell (now post spell can immune by this spell) -// m_caster->CastSpell(unit, spellId, true, m_CastItem); - SpellEntry const *AdditionalSpellInfo = sSpellStore.LookupEntry(spellId); - if (!AdditionalSpellInfo) - continue; - Aura* AdditionalAura = CreateAura(AdditionalSpellInfo, 0, &m_currentBasePoints[0], unit, m_caster, m_CastItem); - unit->AddAura(AdditionalAura); - } - } - } - } // call triggered spell only at successful cast (after clear combo points -> for add some if need) if(!m_TriggerSpells.empty()) TriggerSpell(); @@ -2852,6 +2825,7 @@ void Spell::SendSpellGo() } WorldPacket data(SMSG_SPELL_GO, 50); // guess size + if(m_CastItem) data.append(m_CastItem->GetPackGUID()); else @@ -2949,6 +2923,8 @@ void Spell::WriteAmmoToPacket( WorldPacket * data ) void Spell::WriteSpellGoTargets( WorldPacket * data ) { + // This function also fill data for channeled spells: + // m_needAliveTargetMask req for stop channelig if one target die uint32 hit = m_UniqueGOTargetInfo.size(); // Always hits on GO uint32 miss = 0; for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit) @@ -2968,7 +2944,10 @@ void Spell::WriteSpellGoTargets( WorldPacket * data ) *data << (uint8)hit; for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit) if ((*ihit).missCondition == SPELL_MISS_NONE) // Add only hits + { *data << uint64(ihit->targetGUID); + m_needAliveTargetMask |=ihit->effectMask; + } for(std::list<GOTargetInfo>::iterator ighit= m_UniqueGOTargetInfo.begin();ighit != m_UniqueGOTargetInfo.end();++ighit) *data << uint64(ighit->targetGUID); // Always hits @@ -2984,6 +2963,9 @@ void Spell::WriteSpellGoTargets( WorldPacket * data ) *data << uint8(ihit->reflectResult); } } + // Reset m_needAliveTargetMask for non channeled spell + if(!IsChanneledSpell(m_spellInfo)) + m_needAliveTargetMask = 0; } void Spell::SendLogExecute() @@ -5189,18 +5171,22 @@ void Spell::Delayed() // only called in DealDamage() //if (m_spellState == SPELL_STATE_DELAYED) // return; // spell is active and can't be time-backed + if(isDelayableNoMore()) // Spells may only be delayed twice + return; + // spells not loosing casting time ( slam, dynamites, bombs.. ) //if(!(m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_DAMAGE)) // return; - //check resist chance - int32 resistChance = 100; //must be initialized to 100 for percent modifiers - ((Player*)m_caster)->ApplySpellMod(m_spellInfo->Id,SPELLMOD_NOT_LOSE_CASTING_TIME,resistChance, this); - resistChance += m_caster->GetTotalAuraModifier(SPELL_AURA_RESIST_PUSHBACK) - 100; - if (roll_chance_i(resistChance)) + //check pushback reduce + int32 delaytime = 500; // spellcasting delay is normally 500ms + int32 delayReduce = 100; // must be initialized to 100 for percent modifiers + ((Player*)m_caster)->ApplySpellMod(m_spellInfo->Id,SPELLMOD_NOT_LOSE_CASTING_TIME, delayReduce, this); + delayReduce += m_caster->GetTotalAuraModifier(SPELL_AURA_REDUCE_PUSHBACK) - 100; + if(delayReduce >= 100) return; - int32 delaytime = GetNextDelayAtDamageMsTime(); + delaytime = delaytime * (100 - delayReduce) / 100; if(int32(m_timer) + delaytime > m_casttime) { @@ -5224,14 +5210,18 @@ void Spell::DelayedChannel() if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER || getState() != SPELL_STATE_CASTING) return; - //check resist chance - int32 resistChance = 100; //must be initialized to 100 for percent modifiers - ((Player*)m_caster)->ApplySpellMod(m_spellInfo->Id,SPELLMOD_NOT_LOSE_CASTING_TIME,resistChance, this); - resistChance += m_caster->GetTotalAuraModifier(SPELL_AURA_RESIST_PUSHBACK) - 100; - if (roll_chance_i(resistChance)) + if(isDelayableNoMore()) // Spells may only be delayed twice + return; + + //check pushback reduce + int32 delaytime = GetSpellDuration(m_spellInfo) * 25 / 100; // channeling delay is normally 25% of its time per hit + int32 delayReduce = 100; // must be initialized to 100 for percent modifiers + ((Player*)m_caster)->ApplySpellMod(m_spellInfo->Id,SPELLMOD_NOT_LOSE_CASTING_TIME,delayReduce, this); + delayReduce += m_caster->GetTotalAuraModifier(SPELL_AURA_REDUCE_PUSHBACK) - 100; + if(delayReduce >= 100) return; - int32 delaytime = GetNextDelayAtDamageMsTime(); + delaytime = delaytime * (100 - delayReduce) / 100; if(int32(m_timer) < delaytime) { @@ -5404,7 +5394,13 @@ bool Spell::CheckTarget( Unit* target, uint32 eff, bool hitPhase ) // all ok by some way or another, skip normal check break; default: // normal case - if(target!=m_caster && !target->IsWithinLOSInMap(m_caster)) + // Get GO cast coordinates if original caster -> GO + WorldObject *caster = NULL; + if (m_originalCasterGUID) + caster = ObjectAccessor::GetGameObject(*m_caster, m_originalCasterGUID); + if (!caster) + caster = m_caster; + if(target!=m_caster && !target->IsWithinLOSInMap(caster)) return false; break; } |