diff options
Diffstat (limited to 'src/game/SpellEffects.cpp')
-rw-r--r-- | src/game/SpellEffects.cpp | 2134 |
1 files changed, 1305 insertions, 829 deletions
diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index a985e1c9fb1..a36cc22abd2 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -47,6 +47,7 @@ #include "Creature.h" #include "Totem.h" #include "CreatureAI.h" +#include "BattleGroundMgr.h" #include "BattleGround.h" #include "BattleGroundEY.h" #include "BattleGroundWS.h" @@ -60,6 +61,7 @@ #include "CellImpl.h" #include "GridNotifiers.h" #include "GridNotifiersImpl.h" +#include "SkillDiscovery.h" pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= { @@ -104,8 +106,8 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectDispel, // 38 SPELL_EFFECT_DISPEL &Spell::EffectUnused, // 39 SPELL_EFFECT_LANGUAGE &Spell::EffectDualWield, // 40 SPELL_EFFECT_DUAL_WIELD - &Spell::EffectSummonWild, // 41 SPELL_EFFECT_SUMMON_WILD - &Spell::EffectSummonGuardian, // 42 SPELL_EFFECT_SUMMON_GUARDIAN + &Spell::EffectUnused, // 41 SPELL_EFFECT_JUMP + &Spell::EffectUnused, // 42 SPELL_EFFECT_JUMP2 &Spell::EffectTeleUnitsFaceCaster, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER &Spell::EffectLearnSkill, // 44 SPELL_EFFECT_SKILL_STEP &Spell::EffectAddHonor, // 45 SPELL_EFFECT_ADD_HONOR honor/pvp related @@ -128,16 +130,16 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectPowerBurn, // 62 SPELL_EFFECT_POWER_BURN &Spell::EffectThreat, // 63 SPELL_EFFECT_THREAT &Spell::EffectTriggerSpell, // 64 SPELL_EFFECT_TRIGGER_SPELL - &Spell::EffectUnused, // 65 SPELL_EFFECT_HEALTH_FUNNEL unused - &Spell::EffectUnused, // 66 SPELL_EFFECT_POWER_FUNNEL unused + &Spell::EffectApplyAreaAura, // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID + &Spell::EffectUnused, // 66 SPELL_EFFECT_CREATE_MANA_GEM (possibly recharge it, misc - is item ID) &Spell::EffectHealMaxHealth, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH &Spell::EffectInterruptCast, // 68 SPELL_EFFECT_INTERRUPT_CAST &Spell::EffectDistract, // 69 SPELL_EFFECT_DISTRACT &Spell::EffectPull, // 70 SPELL_EFFECT_PULL one spell: Distract Move &Spell::EffectPickPocket, // 71 SPELL_EFFECT_PICKPOCKET &Spell::EffectAddFarsight, // 72 SPELL_EFFECT_ADD_FARSIGHT - &Spell::EffectSummonPossessed, // 73 SPELL_EFFECT_SUMMON_POSSESSED - &Spell::EffectSummonTotem, // 74 SPELL_EFFECT_SUMMON_TOTEM + &Spell::EffectUnused, // 73 SPELL_EFFECT_UNTRAIN_TALENTS + &Spell::EffectApplyGlyph, // 74 SPELL_EFFECT_APPLY_GLYPH &Spell::EffectHealMechanical, // 75 SPELL_EFFECT_HEAL_MECHANICAL one spell: Mechanical Patch Kit &Spell::EffectSummonObjectWild, // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD &Spell::EffectScriptEffect, // 77 SPELL_EFFECT_SCRIPT_EFFECT @@ -150,17 +152,17 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectStuck, // 84 SPELL_EFFECT_STUCK &Spell::EffectSummonPlayer, // 85 SPELL_EFFECT_SUMMON_PLAYER &Spell::EffectActivateObject, // 86 SPELL_EFFECT_ACTIVATE_OBJECT - &Spell::EffectSummonTotem, // 87 SPELL_EFFECT_SUMMON_TOTEM_SLOT1 - &Spell::EffectSummonTotem, // 88 SPELL_EFFECT_SUMMON_TOTEM_SLOT2 - &Spell::EffectSummonTotem, // 89 SPELL_EFFECT_SUMMON_TOTEM_SLOT3 - &Spell::EffectSummonTotem, // 90 SPELL_EFFECT_SUMMON_TOTEM_SLOT4 + &Spell::EffectUnused, // 87 SPELL_EFFECT_WMO_DAMAGE + &Spell::EffectUnused, // 88 SPELL_EFFECT_WMO_REPAIR + &Spell::EffectUnused, // 89 SPELL_EFFECT_WMO_CHANGE + &Spell::EffectUnused, // 90 SPELL_EFFECT_KILL_CREDIT &Spell::EffectUnused, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash &Spell::EffectEnchantHeldItem, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM &Spell::EffectUnused, // 93 SPELL_EFFECT_SUMMON_PHANTASM &Spell::EffectSelfResurrect, // 94 SPELL_EFFECT_SELF_RESURRECT &Spell::EffectSkinning, // 95 SPELL_EFFECT_SKINNING &Spell::EffectUnused, // 96 SPELL_EFFECT_CHARGE - &Spell::EffectSummonCritter, // 97 SPELL_EFFECT_SUMMON_CRITTER + &Spell::EffectUnused, // 97 SPELL_EFFECT_97 &Spell::EffectKnockBack, // 98 SPELL_EFFECT_KNOCK_BACK &Spell::EffectDisEnchant, // 99 SPELL_EFFECT_DISENCHANT &Spell::EffectInebriate, //100 SPELL_EFFECT_INEBRIATE @@ -175,7 +177,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectSummonDeadPet, //109 SPELL_EFFECT_SUMMON_DEAD_PET &Spell::EffectDestroyAllTotems, //110 SPELL_EFFECT_DESTROY_ALL_TOTEMS &Spell::EffectDurabilityDamage, //111 SPELL_EFFECT_DURABILITY_DAMAGE - &Spell::EffectSummonDemon, //112 SPELL_EFFECT_SUMMON_DEMON + &Spell::EffectUnused, //112 SPELL_EFFECT_112 &Spell::EffectResurrectNew, //113 SPELL_EFFECT_RESURRECT_NEW &Spell::EffectTaunt, //114 SPELL_EFFECT_ATTACK_ME &Spell::EffectDurabilityDamagePCT, //115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT @@ -195,21 +197,21 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectApplyAreaAura, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY &Spell::EffectRedirectThreat, //130 SPELL_EFFECT_REDIRECT_THREAT &Spell::EffectUnused, //131 SPELL_EFFECT_131 used in some test spells - &Spell::EffectNULL, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value + &Spell::EffectNULL, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value (SoundEntries.dbc) &Spell::EffectUnlearnSpecialization, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization &Spell::EffectKillCredit, //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry &Spell::EffectNULL, //135 SPELL_EFFECT_CALL_PET &Spell::EffectHealPct, //136 SPELL_EFFECT_HEAL_PCT &Spell::EffectEnergisePct, //137 SPELL_EFFECT_ENERGIZE_PCT &Spell::EffectNULL, //138 SPELL_EFFECT_138 Leap - &Spell::EffectUnused, //139 SPELL_EFFECT_139 unused + &Spell::EffectUnused, //139 SPELL_EFFECT_CLEAR_QUEST (misc - is quest ID) &Spell::EffectForceCast, //140 SPELL_EFFECT_FORCE_CAST &Spell::EffectNULL, //141 SPELL_EFFECT_141 damage and reduce speed? &Spell::EffectTriggerSpellWithValue, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE &Spell::EffectApplyAreaAura, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER &Spell::EffectKnockBack, //144 SPELL_EFFECT_KNOCK_BACK_2 Spectral Blast &Spell::EffectNULL, //145 SPELL_EFFECT_145 Black Hole Effect - &Spell::EffectUnused, //146 SPELL_EFFECT_146 unused + &Spell::EffectActivateRune, //146 SPELL_EFFECT_ACTIVATE_RUNE &Spell::EffectQuestFail, //147 SPELL_EFFECT_QUEST_FAIL quest fail &Spell::EffectUnused, //148 SPELL_EFFECT_148 unused &Spell::EffectNULL, //149 SPELL_EFFECT_149 swoop @@ -217,6 +219,12 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectTriggerRitualOfSummoning, //151 SPELL_EFFECT_TRIGGER_SPELL_2 &Spell::EffectNULL, //152 SPELL_EFFECT_152 summon Refer-a-Friend &Spell::EffectNULL, //153 SPELL_EFFECT_CREATE_PET misc value is creature entry + &Spell::EffectNULL, //154 unused + &Spell::EffectTitanGrip, //155 SPELL_EFFECT_TITAN_GRIP Allows you to equip two-handed axes, maces and swords in one hand, but you attack $49152s1% slower than normal. + &Spell::EffectEnchantItemPrismatic, //156 SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC + &Spell::EffectCreateItem2, //157 SPELL_EFFECT_CREATE_ITEM_2 create/learn item/spell for profession + &Spell::EffectMilling, //158 SPELL_EFFECT_MILLING milling + &Spell::EffectRenamePet //159 SPELL_EFFECT_ALLOW_RENAME_PET allow rename pet once again }; void Spell::EffectNULL(uint32 /*i*/) @@ -293,7 +301,7 @@ void Spell::EffectEnvirinmentalDMG(uint32 i) // currently each enemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc damage = m_spellInfo->EffectBasePoints[i]+m_spellInfo->EffectBaseDice[i]; - m_caster->CalcAbsorbResist(m_caster,GetSpellSchoolMask(m_spellInfo), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist); + m_caster->CalcAbsorbResist(m_caster,GetSpellSchoolMask(m_spellInfo), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist, m_spellInfo); m_caster->SendSpellNonMeleeDamageLog(m_caster, m_spellInfo->Id, damage, GetSpellSchoolMask(m_spellInfo), absorb, resist, false, 0, false); if(m_caster->GetTypeId() == TYPEID_PLAYER) @@ -347,6 +355,13 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) damage = 200; break; } + // Intercept (warrior spell trigger) + case 20253: + case 61491: + { + damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.12f); + break; + } // arcane charge. must only affect demons (also undead?) case 45072: { @@ -362,7 +377,7 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) if(unitTarget->GetGUID() == m_caster->GetGUID() || unitTarget->GetTypeId() != TYPEID_PLAYER) return; - float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[0])); + float radius = GetSpellRadiusForHostile(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[0])); if(!radius) return; float distance = m_caster->GetDistance2d(unitTarget); damage = (distance > radius ) ? 0 : (int32)(m_spellInfo->EffectBasePoints[0]*((radius - distance)/radius)); @@ -374,7 +389,7 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) case SPELLFAMILY_MAGE: { // Arcane Blast - if(m_spellInfo->SpellFamilyFlags & 0x20000000LL) + if(m_spellInfo->SpellFamilyFlags[0] & 0x20000000) { m_caster->CastSpell(m_caster,36032,true); } @@ -383,29 +398,56 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) case SPELLFAMILY_WARRIOR: { // Bloodthirst - if(m_spellInfo->SpellFamilyFlags & 0x40000000000LL) + if(m_spellInfo->SpellFamilyFlags[1] & 0x400) { damage = uint32(damage * (m_caster->GetTotalAttackPowerValue(BASE_ATTACK)) / 100); } // Shield Slam - else if(m_spellInfo->SpellFamilyFlags & 0x100000000LL) + else if(m_spellInfo->SpellFamilyFlags[1] & 0x200) damage += int32(m_caster->GetShieldBlockValue()); // Victory Rush - else if(m_spellInfo->SpellFamilyFlags & 0x10000000000LL) + else if(m_spellInfo->SpellFamilyFlags[1] & 0x100) { damage = uint32(damage * m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100); m_caster->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, false); } + // Revenge ${$m1+$AP*0.207} to ${$M1+$AP*0.207} + else if(m_spellInfo->SpellFamilyFlags[0] & 0x400) + damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.207f); + // Heroic Throw ${$m1+$AP*.50} + else if(m_spellInfo->SpellFamilyFlags[1] & 0x00000001) + damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.5f); + // Shockwave ${$m3/100*$AP} + else if(m_spellInfo->SpellFamilyFlags[1] & 0x00008000) + { + int32 pct = m_caster->CalculateSpellDamage(m_spellInfo, 2, m_spellInfo->EffectBasePoints[2], unitTarget); + if (pct > 0) + damage+= int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * pct / 100); + break; + } + // Thunder Clap + else if(m_spellInfo->SpellFamilyFlags[0] & 0x80) + { + damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 12 / 100); + break; + } break; } case SPELLFAMILY_WARLOCK: { // Incinerate Rank 1 & 2 - if((m_spellInfo->SpellFamilyFlags & 0x00004000000000LL) && m_spellInfo->SpellIconID==2128) + if((m_spellInfo->SpellFamilyFlags[1] & 0x000040) && m_spellInfo->SpellIconID==2128) { // Incinerate does more dmg (dmg*0.25) if the target is Immolated. if(unitTarget->HasAuraState(AURA_STATE_IMMOLATE)) - damage += int32(damage*0.25); + damage += int32(damage*0.25f); + } + // Haunt + else if (m_spellInfo->SpellFamilyFlags[1] & 0x40000) + { + // Save damage for future healing + // TODO: Implement spell proc on aura expire + m_currentBasePoints[1] = int32(damage * m_currentBasePoints[1] / 100); } // Conflagrate - consumes immolate @@ -415,75 +457,52 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) Unit::AuraList const &mPeriodic = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); for(Unit::AuraList::const_iterator i = mPeriodic.begin(); i != mPeriodic.end(); ++i) { - if( (*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && ((*i)->GetSpellProto()->SpellFamilyFlags & 4) && + if( (*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && ((*i)->GetSpellProto()->SpellFamilyFlags[0] & 4) && (*i)->GetCasterGUID()==m_caster->GetGUID() ) { - unitTarget->RemoveAurasDueToCasterSpell((*i)->GetId(), m_caster->GetGUID()); + unitTarget->RemoveAurasByCasterSpell((*i)->GetId(), m_caster->GetGUID()); break; } } } break; } + case SPELLFAMILY_PRIEST: + { + // Shadow Word: Death - deals damage equal to damage done to caster + if (m_spellInfo->SpellFamilyFlags[1] & 0x2) + m_caster->CastCustomSpell(m_caster, 32409, &damage, 0, 0, true); + break; + } case SPELLFAMILY_DRUID: { // Ferocious Bite - if((m_spellInfo->SpellFamilyFlags & 0x000800000) && m_spellInfo->SpellVisual==6587) + if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags[0] & 0x000800000) && m_spellInfo->SpellVisual[0]==6587) { - // converts each extra point of energy into ($f1+$AP/630) additional damage - float multiple = m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 630 + m_spellInfo->DmgMultiplier[effect_idx]; + // converts each extra point of energy into ($f1+$AP/410) additional damage + float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK); + float multiple = ap / 410 + m_spellInfo->DmgMultiplier[effect_idx]; damage += int32(m_caster->GetPower(POWER_ENERGY) * multiple); + damage += int32(((Player*)m_caster)->GetComboPoints() * ap * 7 / 100); m_caster->SetPower(POWER_ENERGY,0); } // Rake - else if(m_spellInfo->SpellFamilyFlags & 0x0000000000001000LL) + else if(m_spellInfo->SpellFamilyFlags[0] & 0x1000) { damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100); } // Swipe - else if(m_spellInfo->SpellFamilyFlags & 0x0010000000000000LL) + else if(m_spellInfo->SpellFamilyFlags[1] & 0x00100000) { damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.08f); } - // Starfire - else if ( m_spellInfo->SpellFamilyFlags & 0x0004LL ) - { - Unit::AuraList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); - for(Unit::AuraList::const_iterator i = m_OverrideClassScript.begin(); i != m_OverrideClassScript.end(); ++i) - { - // Starfire Bonus (caster) - switch((*i)->GetModifier()->m_miscvalue) - { - case 5481: // Nordrassil Regalia - bonus - { - Unit::AuraList const& m_periodicDamageAuras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); - for(Unit::AuraList::const_iterator itr = m_periodicDamageAuras.begin(); itr != m_periodicDamageAuras.end(); ++itr) - { - // Moonfire or Insect Swarm (target debuff from any casters) - if ( (*itr)->GetSpellProto()->SpellFamilyFlags & 0x00200002LL ) - { - int32 mod = (*i)->GetModifier()->m_amount; - damage += damage*mod/100; - break; - } - } - break; - } - case 5148: //Improved Starfire - Ivory Idol of the Moongoddes Aura - { - damage += (*i)->GetModifier()->m_amount; - break; - } - } - } - } //Mangle Bonus for the initial damage of Lacerate and Rake - if((m_spellInfo->SpellFamilyFlags==0x0000000000001000LL && m_spellInfo->SpellIconID==494) || - (m_spellInfo->SpellFamilyFlags==0x0000010000000000LL && m_spellInfo->SpellIconID==2246)) + if((m_spellInfo->SpellFamilyFlags.IsEqual(0x1000,0,0) && m_spellInfo->SpellIconID==494) || + (m_spellInfo->SpellFamilyFlags.IsEqual(0,0x100,0) && m_spellInfo->SpellIconID==2246)) { Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY); for(Unit::AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i) - if((*i)->GetSpellProto()->SpellFamilyFlags & 0x0000044000000000LL && (*i)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_DRUID) + if((*i)->GetSpellProto()->SpellFamilyFlags[1] & 0x00000440 && (*i)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_DRUID) { damage = int32(damage*(100.0f+(*i)->GetModifier()->m_amount)/100.0f); break; @@ -494,72 +513,91 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) case SPELLFAMILY_ROGUE: { // Envenom - if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x800000000LL)) + if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags[1] & 0x8)) { // consume from stack dozes not more that have combo-points if(uint32 combo = ((Player*)m_caster)->GetComboPoints()) { - // count consumed deadly poison doses at target - uint32 doses = 0; - - // remove consumed poison doses + Aura *poison = 0; + // Lookup for Deadly poison (only attacker applied) Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); - for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end() && combo;) - { - // Deadly poison (only attacker applied) - if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE && ((*itr)->GetSpellProto()->SpellFamilyFlags & 0x10000) && - (*itr)->GetSpellProto()->SpellVisual==5100 && (*itr)->GetCasterGUID()==m_caster->GetGUID() ) + for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr) + if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE && + (*itr)->GetSpellProto()->SpellFamilyFlags[0] & 0x10000 && + (*itr)->GetCasterGUID()==m_caster->GetGUID() ) { - --combo; - ++doses; - - unitTarget->RemoveSingleAuraFromStack((*itr)->GetId(), (*itr)->GetEffIndex()); - - itr = auras.begin(); + poison = *itr; + break; } - else - ++itr; + // count consumed deadly poison doses at target + if (poison) + { + uint32 spellId = poison->GetId(); + uint32 doses = poison->GetStackAmount(); + if (doses > combo) + doses = combo; + for (int i=0; i< doses; i++) + unitTarget->RemoveSingleSpellAurasFromStack(spellId); + damage *= doses; + damage += int32(((Player*)m_caster)->GetTotalAttackPowerValue(BASE_ATTACK) * 0.03f * doses); } - - damage *= doses; - damage += int32(((Player*)m_caster)->GetTotalAttackPowerValue(BASE_ATTACK) * 0.03f * doses); - // Eviscerate and Envenom Bonus Damage (item set effect) if(m_caster->GetDummyAura(37169)) damage += ((Player*)m_caster)->GetComboPoints()*40; } } // Eviscerate - else if((m_spellInfo->SpellFamilyFlags & 0x00020000LL) && m_caster->GetTypeId()==TYPEID_PLAYER) + else if((m_spellInfo->SpellFamilyFlags[0] & 0x00020000) && m_caster->GetTypeId()==TYPEID_PLAYER) { if(uint32 combo = ((Player*)m_caster)->GetComboPoints()) { - damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * combo * 0.03f); + float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK); + damage += irand(int32(ap * combo * 0.03f), int32(ap * combo * 0.07f)); // Eviscerate and Envenom Bonus Damage (item set effect) if(m_caster->GetDummyAura(37169)) damage += combo*40; } } + // Gouge + else if(m_spellInfo->SpellFamilyFlags[0] & 0x8) + { + damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.02f); + } + // Instant Poison + else if(m_spellInfo->SpellFamilyFlags[0] & 0x2000) + { + damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.10f); + } + // Wound Poison + else if(m_spellInfo->SpellFamilyFlags[0] & 0x10000000) + { + damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.04f); + } break; } case SPELLFAMILY_HUNTER: { // Mongoose Bite - if((m_spellInfo->SpellFamilyFlags & 0x000000002) && m_spellInfo->SpellVisual==342) + if((m_spellInfo->SpellFamilyFlags[0] & 0x2) && m_spellInfo->SpellVisual[0]==342) { - damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2); + damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f); + } + // Counterattack + else if(m_spellInfo->SpellFamilyFlags[1] & 0x00080000) + { + damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f); } // Arcane Shot - else if((m_spellInfo->SpellFamilyFlags & 0x00000800) && m_spellInfo->maxLevel > 0) + else if((m_spellInfo->SpellFamilyFlags[0] & 0x00000800) && m_spellInfo->maxLevel > 0) { - damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.15); + damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.15f); } // Steady Shot - else if(m_spellInfo->SpellFamilyFlags & 0x100000000LL) + else if(m_spellInfo->SpellFamilyFlags[1] & 0x1) { int32 base = irand((int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MINDAMAGE),(int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MAXDAMAGE)); - damage += int32(float(base)/m_caster->GetAttackTime(RANGED_ATTACK)*2800 + m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.2f); + damage += int32(float(base)/m_caster->GetAttackTime(RANGED_ATTACK)*2800 + m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1f); bool found = false; @@ -578,28 +616,54 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) if(found) damage += m_spellInfo->EffectBasePoints[1]; } - //Explosive Trap Effect - else if(m_spellInfo->SpellFamilyFlags & 0x00000004) + // Explosive Trap Effect + else if(m_spellInfo->SpellFamilyFlags[0] & 0x00000004) { - damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1); + damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1f); } break; } case SPELLFAMILY_PALADIN: { - //Judgement of Vengeance - if((m_spellInfo->SpellFamilyFlags & 0x800000000LL) && m_spellInfo->SpellIconID==2292) + // Judgement of Vengeance/Corruption ${1+0.22*$SPH+0.14*$AP} + 10% for each application of Holy Vengeance/Blood Corruption on the target + if((m_spellInfo->SpellFamilyFlags[1] & 0x400000) && m_spellInfo->SpellIconID==2292) { + float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK); + int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) + + m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget); + damage+=int32(ap * 0.14f) + int32(holy * 22 / 100); + // Get stack of Holy Vengeance/Blood Corruption on the target added by caster uint32 stacks = 0; Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr) - if((*itr)->GetId() == 31803 && (*itr)->GetCasterGUID()==m_caster->GetGUID()) - ++stacks; - if(!stacks) - //No damage if the target isn't affected by this - damage = -1; - else - damage *= stacks; + if(((*itr)->GetId() == 31803 || (*itr)->GetId() == 53742) && (*itr)->GetCasterGUID()==m_caster->GetGUID()) + { + stacks = (*itr)->GetStackAmount(); + break; + } + // + 10% for each application of Holy Vengeance/Blood Corruption on the target + if(stacks) + damage += damage * stacks * 10 /100; + } + // Avenger's Shield ($m1+0.07*$SPH+0.07*$AP) + else if(m_spellInfo->SpellFamilyFlags[0] & 0x4000) + { + float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK); + damage += int32(ap * 0.07f); + } + // Hammer of Wrath ($m1+0.15*$SPH+0.15*$AP) + else if(m_spellInfo->SpellFamilyFlags[1] & 0x00000080) + { + float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK); + damage += int32(ap * 0.15f); + } + // Hammer of the Righteous + else if(m_spellInfo->SpellFamilyFlags[1]&0x00040000) + { + // Add main hand dps * effect[2] amount + float averange = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE)) / 2; + int32 count = m_caster->CalculateSpellDamage(m_spellInfo, 2, m_spellInfo->EffectBasePoints[2], unitTarget); + damage += count * int32(averange * IN_MILISECONDS) / m_caster->GetAttackTime(BASE_ATTACK); } break; } @@ -659,7 +723,7 @@ void Spell::EffectDummy(uint32 i) if (!creatureTarget || !pGameObj) return; - if (!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), 181574, creatureTarget->GetMap(), + if (!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), 181574, creatureTarget->GetMap(), creatureTarget->GetPhaseMask(), creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(), creatureTarget->GetOrientation(), 0, 0, 0, 0, 100, 1)) { @@ -767,12 +831,6 @@ void Spell::EffectDummy(uint32 i) m_caster->CastCustomSpell(unitTarget, 12721, &deepWoundsDotBasePoints0, NULL, NULL, true, NULL); return; } - case 12975: //Last Stand - { - int32 healthModSpellBasePoints0 = int32(m_caster->GetMaxHealth()*0.3); - m_caster->CastCustomSpell(m_caster, 12976, &healthModSpellBasePoints0, NULL, NULL, true, NULL); - return; - } case 13120: // net-o-matic { if(!unitTarget) @@ -809,30 +867,6 @@ void Spell::EffectDummy(uint32 i) } return; } - case 14185: // Preparation Rogue - { - if(m_caster->GetTypeId()!=TYPEID_PLAYER) - return; - - //immediately finishes the cooldown on certain Rogue abilities - const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap(); - for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr) - { - uint32 classspell = itr->first; - SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell); - - if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags & 0x26000000860LL)) - { - ((Player*)m_caster)->RemoveSpellCooldown(classspell); - - WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8)); - data << uint32(classspell); - data << uint64(m_caster->GetGUID()); - ((Player*)m_caster)->GetSession()->SendPacket(&data); - } - } - return; - } case 15998: // Capture Worg Pup case 29435: // Capture Female Kaliri Hatchling { @@ -897,19 +931,20 @@ void Spell::EffectDummy(uint32 i) if(creatureTarget->isPet()) return; + GameObject* Crystal_Prison = m_caster->SummonGameObject(179644, creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(), creatureTarget->GetOrientation(), 0, 0, 0, 0, creatureTarget->GetRespawnTime()-time(NULL)); + sLog.outDebug("SummonGameObject at SpellEfects.cpp EffectDummy for Spell 23019\n"); + creatureTarget->setDeathState(JUST_DIED); creatureTarget->RemoveCorpse(); creatureTarget->SetHealth(0); // just for nice GM-mode view - GameObject* Crystal_Prison = m_caster->SummonGameObject(179644, creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(), creatureTarget->GetOrientation(), 0, 0, 0, 0, creatureTarget->GetRespawnTime()-time(NULL)); - sLog.outDebug("SummonGameObject at SpellEfects.cpp EffectDummy for Spell 23019\n"); WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8); data << uint64(Crystal_Prison->GetGUID()); m_caster->SendMessageToSet(&data,true); return; } - case 23074: // Arc. Dragonling + case 23074: // Arcanite Dragonling if (!m_CastItem) return; m_caster->CastSpell(m_caster,19804,true,m_CastItem); return; @@ -1121,36 +1156,6 @@ void Spell::EffectDummy(uint32 i) m_caster->CastSpell(m_caster,42337,true,NULL); return; } - case 37573: //Temporal Phase Modulator - { - if(!unitTarget) - return; - - TemporarySummon* tempSummon = dynamic_cast<TemporarySummon*>(unitTarget); - if(!tempSummon) - return; - - uint32 health = tempSummon->GetHealth(); - const uint32 entry_list[6] = {21821, 21820, 21817}; - - float x = tempSummon->GetPositionX(); - float y = tempSummon->GetPositionY(); - float z = tempSummon->GetPositionZ(); - float o = tempSummon->GetOrientation(); - - tempSummon->UnSummon(); - - Creature* pCreature = m_caster->SummonCreature(entry_list[urand(0, 2)], x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,180000); - if (!pCreature) - return; - - pCreature->SetHealth(health); - - if(pCreature->IsAIEnabled) - pCreature->AI()->AttackStart(m_caster); - - return; - } case 34665: //Administer Antidote { if(!unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER ) @@ -1227,6 +1232,28 @@ void Spell::EffectDummy(uint32 i) m_caster->CastSpell(m_caster, 30452, true, NULL); return; } + case 53341: + case 53343: + { + m_caster->CastSpell(m_caster,54586,true); + return; + } + case 58418: // Portal to Orgrimmar + { + if(!unitTarget) + return; + + unitTarget->CastSpell(unitTarget, 58419, true); + break; + } + case 58420: // Portal to Stormwind + { + if(!unitTarget) + return; + + unitTarget->CastSpell(unitTarget, 58421, true); + break; + } } //All IconID Check in there @@ -1300,65 +1327,120 @@ void Spell::EffectDummy(uint32 i) break; case SPELLFAMILY_WARRIOR: // Charge - if(m_spellInfo->SpellFamilyFlags & 0x1 && m_spellInfo->SpellVisual == 867) + if(m_spellInfo->SpellFamilyFlags & 0x1 && m_spellInfo->SpellVisual[0] == 867) { int32 chargeBasePoints0 = damage; m_caster->CastCustomSpell(m_caster,34846,&chargeBasePoints0,NULL,NULL,true); return; } + //Slam + if(m_spellInfo->SpellFamilyFlags[0] & 0x200000 && m_spellInfo->SpellIconID == 559) + { + int32 bp0 = damage; + m_caster->CastCustomSpell(unitTarget, 50783, &bp0, NULL, NULL, true, 0); + return; + } // Execute - if(m_spellInfo->SpellFamilyFlags & 0x20000000) + if(m_spellInfo->SpellFamilyFlags[0] & 0x20000000) { if(!unitTarget) return; + uint32 rage = m_caster->GetPower(POWER_RAGE); + // Glyph of Execution bonus + if (Aura *aura = m_caster->GetDummyAura(58367)) + rage+=aura->GetModifier()->m_amount; + spell_id = 20647; - bp = damage+int32(m_caster->GetPower(POWER_RAGE) * m_spellInfo->DmgMultiplier[i]); + bp = damage+int32(rage * m_spellInfo->DmgMultiplier[i] + + m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f); m_caster->SetPower(POWER_RAGE,0); break; } - if(m_spellInfo->Id==21977) //Warrior's Wrath + // Slam + if(m_spellInfo->SpellFamilyFlags[0] & 0x200000) { if(!unitTarget) return; - - m_caster->CastSpell(unitTarget,21887,true); // spell mod + m_damage+=m_caster->CalculateDamage(m_attackType, false); + m_damage+=damage; return; } + switch(m_spellInfo->Id) + { + // Warrior's Wrath + case 21977: + { + if(!unitTarget) + return; + m_caster->CastSpell(unitTarget,21887,true); // spell mod + return; + } + // Last Stand + case 12975: + { + int32 healthModSpellBasePoints0 = int32(m_caster->GetMaxHealth()*0.3); + m_caster->CastCustomSpell(m_caster, 12976, &healthModSpellBasePoints0, NULL, NULL, true, NULL); + return; + } + // Bloodthirst + case 23881: + { + m_caster->CastCustomSpell(unitTarget, 23885, &damage, NULL, NULL, true, NULL); + return; + } + } break; case SPELLFAMILY_WARLOCK: - //Life Tap (only it have this with dummy effect) - if (m_spellInfo->SpellFamilyFlags == 0x40000) + // Life Tap + if (m_spellInfo->SpellFamilyFlags[0] & 0x40000) { - float cost = damage; - - if(Player* modOwner = m_caster->GetSpellModOwner()) - modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COST, cost,this); - - int32 dmg = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(cost > 0 ? cost : 0), SPELL_DIRECT_DAMAGE); - - if(int32(m_caster->GetHealth()) > dmg) + // In 303 exist spirit depend + uint32 spirit = m_caster->GetStat(STAT_SPIRIT); + switch (m_spellInfo->Id) + { + case 1454: damage+=spirit; break; + case 1455: damage+=spirit*15/10; break; + case 1456: damage+=spirit*2; break; + case 11687: damage+=spirit*25/10; break; + case 11688: + case 11689: + case 27222: + case 57946: damage+=spirit*3; break; + default: + sLog.outError("Spell::EffectDummy: %u Life Tap need set spirit multipler", m_spellInfo->Id); + return; + } +// Think its not need (also need remove Life Tap from SpellDamageBonus or add new value) +// damage = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(damage > 0 ? damage : 0), SPELL_DIRECT_DAMAGE); + if(int32(unitTarget->GetHealth()) > damage) { // Shouldn't Appear in Combat Log - m_caster->ModifyHealth(-dmg); - - int32 mana = dmg; + unitTarget->ModifyHealth(-damage); + int32 mana = damage; + // Improved Life Tap mod Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY); for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr) { - // only Imp. Life Tap have this in combination with dummy aura if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 208) mana = ((*itr)->GetModifier()->m_amount + 100)* mana / 100; } - - m_caster->CastCustomSpell(m_caster,31818,&mana,NULL,NULL,true,NULL); + m_caster->CastCustomSpell(unitTarget, 31818, &mana, NULL, NULL, true); // Mana Feed - int32 manaFeedVal = m_caster->CalculateSpellDamage(m_spellInfo,1, m_spellInfo->EffectBasePoints[1],m_caster); - manaFeedVal = manaFeedVal * mana / 100; + int32 manaFeedVal = 0; + Unit::AuraList const& mod = m_caster->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER); + for(Unit::AuraList::const_iterator itr = mod.begin(); itr != mod.end(); ++itr) + { + if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 1982) + manaFeedVal+= (*itr)->GetModifier()->m_amount; + } if(manaFeedVal > 0) - m_caster->CastCustomSpell(m_caster,32553,&manaFeedVal,NULL,NULL,true,NULL); + { + manaFeedVal = manaFeedVal * mana / 100; + m_caster->CastCustomSpell(m_caster, 32553, &manaFeedVal, NULL, NULL, true, NULL); + } } else SendCastResult(SPELL_FAILED_FIZZLE); @@ -1366,6 +1448,30 @@ void Spell::EffectDummy(uint32 i) } break; case SPELLFAMILY_PRIEST: + // Penance + if (m_spellInfo->SpellFamilyFlags[1] & 0x00800000) + { + if (!unitTarget) + return; + + int hurt = 0; + int heal = 0; + switch(m_spellInfo->Id) + { + case 47540: hurt = 47758; heal = 47757; break; + case 53005: hurt = 53001; heal = 52986; break; + case 53006: hurt = 53002; heal = 52987; break; + case 53007: hurt = 53003; heal = 52988; break; + default: + sLog.outError("Spell::EffectDummy: Spell %u Penance need set correct heal/damage spell", m_spellInfo->Id); + return; + } + if (m_caster->IsFriendlyTo(unitTarget)) + m_caster->CastSpell(unitTarget, heal, true, 0); + else + m_caster->CastSpell(unitTarget, hurt, true, 0); + return; + } switch(m_spellInfo->Id ) { case 28598: // Touch of Weakness triggered spell @@ -1393,25 +1499,16 @@ void Spell::EffectDummy(uint32 i) } break; case SPELLFAMILY_DRUID: - switch(m_spellInfo->Id ) + // Starfall + if (m_spellInfo->SpellFamilyFlags[2] & 0x100) { - case 5420: // Tree of Life passive - { - // Tree of Life area effect - int32 health_mod = int32(m_caster->GetStat(STAT_SPIRIT)/4); - m_caster->CastCustomSpell(m_caster,34123,&health_mod,NULL,NULL,true,NULL); - return; - } + m_caster->CastSpell(unitTarget, damage, true, NULL); + return; } break; case SPELLFAMILY_ROGUE: switch(m_spellInfo->Id ) { - case 31231: // Cheat Death - { - m_caster->CastSpell(m_caster,45182,true); - return; - } case 5938: // Shiv { if(m_caster->GetTypeId() != TYPEID_PLAYER) @@ -1447,36 +1544,38 @@ void Spell::EffectDummy(uint32 i) m_caster->CastSpell(unitTarget, 5940, true); return; } - } - break; - case SPELLFAMILY_HUNTER: - // Kill command - if(m_spellInfo->SpellFamilyFlags & 0x00080000000000LL) - { - if(m_caster->getClass()!=CLASS_HUNTER) - return; + case 14185: // Preparation Rogue + { + if(m_caster->GetTypeId()!=TYPEID_PLAYER) + return; - // clear hunter crit aura state - m_caster->ModifyAuraState(AURA_STATE_HUNTER_CRIT_STRIKE,false); + //immediately finishes the cooldown on certain Rogue abilities + const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap(); + for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr) + { + uint32 classspell = itr->first; + SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell); - // additional damage from pet to pet target - Pet* pet = m_caster->GetPet(); - if(!pet || !pet->getVictim()) - return; + if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags[1] & 0x00000240 || spellInfo->SpellFamilyFlags[0] & 0x00000860)) + { + ((Player*)m_caster)->RemoveSpellCooldown(classspell); - uint32 spell_id = 0; - switch (m_spellInfo->Id) + WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8)); + data << uint32(classspell); + data << uint64(m_caster->GetGUID()); + ((Player*)m_caster)->GetSession()->SendPacket(&data); + } + } + return; + } + case 31231: // Cheat Death { - case 34026: spell_id = 34027; break; // rank 1 - default: - sLog.outError("Spell::EffectDummy: Spell %u not handled in KC",m_spellInfo->Id); + m_caster->CastSpell(m_caster,45182,true); return; } - - pet->CastSpell(pet->getVictim(), spell_id, true); - return; } - + break; + case SPELLFAMILY_HUNTER: switch(m_spellInfo->Id) { case 23989: //Readiness talent @@ -1534,6 +1633,8 @@ void Spell::EffectDummy(uint32 i) case 20930: hurt = 25902; heal = 25903; break; case 27174: hurt = 27176; heal = 27175; break; case 33072: hurt = 33073; heal = 33074; break; + case 48824: hurt = 48822; heal = 48820; break; + case 48825: hurt = 48823; heal = 48821; break; default: sLog.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo->Id); return; @@ -1564,10 +1665,7 @@ void Spell::EffectDummy(uint32 i) mod->value = -50; mod->type = SPELLMOD_PCT; mod->spellId = m_spellInfo->Id; - mod->effectId = i; - mod->lastAffected = NULL; - mod->mask = 0x0000020000000000LL; - mod->charges = 0; + mod->mask[1] = 0x00000200; ((Player*)m_caster)->AddSpellMod(mod, true); m_caster->CastSpell(unitTarget,spell_proto,true,NULL); @@ -1583,6 +1681,14 @@ void Spell::EffectDummy(uint32 i) switch(m_spellInfo->Id) { + // Judgement of Righteousness (0.2*$AP+0.32*$SPH) holy added in spellDamagBonus + case 20187: + { + if (!unitTarget) + return; + m_damage+=int32(0.2f*m_caster->GetTotalAttackPowerValue(BASE_ATTACK)); + return; + } case 31789: // Righteous Defense (step 1) { // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target) @@ -1649,8 +1755,10 @@ void Spell::EffectDummy(uint32 i) break; case SPELLFAMILY_SHAMAN: //Shaman Rockbiter Weapon - if (m_spellInfo->SpellFamilyFlags == 0x400000) + if (m_spellInfo->SpellFamilyFlags.IsEqual(0x400000)) { + // TODO: use expect spell for enchant (if exist talent) + // In 3.0.3 no mods present for rockbiter uint32 spell_id = 0; switch(m_spellInfo->Id) { @@ -1658,11 +1766,6 @@ void Spell::EffectDummy(uint32 i) case 8018: spell_id = 36750; break; // Rank 2 case 8019: spell_id = 36755; break; // Rank 3 case 10399: spell_id = 36759; break; // Rank 4 - case 16314: spell_id = 36763; break; // Rank 5 - case 16315: spell_id = 36766; break; // Rank 6 - case 16316: spell_id = 36771; break; // Rank 7 - case 25479: spell_id = 36775; break; // Rank 8 - case 25485: spell_id = 36499; break; // Rank 9 default: sLog.outError("Spell::EffectDummy: Spell %u not handled in RW",m_spellInfo->Id); return; @@ -1700,18 +1803,87 @@ void Spell::EffectDummy(uint32 i) } return; } - - if(m_spellInfo->Id == 39610) // Mana-Tide Totem effect + // Healing Stream Totem + if(m_spellInfo->SpellFamilyFlags[0] & 0x2000) + { + m_caster->CastCustomSpell(unitTarget, 52042, &damage, 0, 0, true, 0, 0, m_originalCasterGUID); + return; + } + // Mana Spring Totem + if(m_spellInfo->SpellFamilyFlags[0] & 0x4000) + { + if(unitTarget->getPowerType()!=POWER_MANA) + return; + m_caster->CastCustomSpell(unitTarget, 52032, &damage, 0, 0, true, 0, 0, m_originalCasterGUID); + return; + } + if(m_spellInfo->Id == 39610) // Mana Tide Totem effect { if(!unitTarget || unitTarget->getPowerType() != POWER_MANA) return; - + // Glyph of Mana Tide + Unit *owner = m_caster->GetOwner(); + if (owner) + if (Aura *dummy = owner->GetDummyAura(55441)) + damage+=dummy->GetModifier()->m_amount; // Regenerate 6% of Total Mana Every 3 secs int32 EffectBasePoints0 = unitTarget->GetMaxPower(POWER_MANA) * damage / 100; m_caster->CastCustomSpell(unitTarget,39609,&EffectBasePoints0,NULL,NULL,true,NULL,NULL,m_originalCasterGUID); return; } + // Lava Lash + if (m_spellInfo->SpellFamilyFlags[2] & 0x00000004) + { + if (m_caster->GetTypeId()!=TYPEID_PLAYER) + return; + Item *item = ((Player*)m_caster)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); + if (item) + { + // Damage is increased if your off-hand weapon is enchanted with Flametongue. + Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr) + { + if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_SHAMAN && + (*itr)->GetSpellProto()->SpellFamilyFlags[0] & 0x200000 && + (*itr)->GetCastItemGUID() == item->GetGUID()) + { + m_damage += m_damage * damage / 100; + return; + } + } + } + return; + } + break; + case SPELLFAMILY_DEATHKNIGHT: + // Death strike dummy aura apply + // Used to proc healing later + if (m_spellInfo->SpellFamilyFlags[0] & 0x00000010) + { + spell_id=45469; + m_caster->CastSpell(m_caster,spell_id,true); + return; + } + // Death Coil + if(m_spellInfo->SpellFamilyFlags[0] & 0x002000) + { + uint32 spell_id = NULL; + damage += m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.15f; + if(m_caster->IsFriendlyTo(unitTarget)) + { + if(unitTarget->GetCreatureType() != CREATURE_TYPE_UNDEAD) + return; + spell_id = 47633; + damage *= 1.5f; + } + else + spell_id = 47632; + + bp = int32(damage); + m_caster->CastCustomSpell(unitTarget,spell_id,&bp,NULL,NULL,true); + return; + } break; } @@ -1725,7 +1897,7 @@ void Spell::EffectDummy(uint32 i) sLog.outError("EffectDummy of spell %u: triggering unknown spell id %i\n", m_spellInfo->Id, spell_id); return; } - + Spell* spell = new Spell(m_caster, spellInfo, true, m_originalCasterGUID, NULL, true); if(bp) spell->m_currentBasePoints[0] = bp; SpellCastTargets targets; @@ -1776,8 +1948,8 @@ void Spell::EffectTriggerRitualOfSummoning(uint32 i) targets.setUnitTarget( unitTarget); spell->prepare(&targets); - m_caster->SetCurrentCastedSpell(spell); - spell->m_selfContainer = &(m_caster->m_currentSpells[spell->GetCurrentContainer()]); + //m_caster->SetCurrentCastedSpell(spell); + //spell->m_selfContainer = &(m_caster->m_currentSpells[spell->GetCurrentContainer()]); } @@ -1831,7 +2003,7 @@ void Spell::EffectTriggerSpell(uint32 i) if (!spellInfo) continue; - if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_STEALTH) + if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && spellInfo->SpellFamilyFlags[0] & SPELLFAMILYFLAG_ROGUE_STEALTH) { spellId = spellInfo->Id; break; @@ -1988,12 +2160,7 @@ void Spell::EffectTriggerMissileSpell(uint32 effect_idx) if (m_CastItem) DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo->Id); - Spell *spell = new Spell(m_caster, spellInfo, true, m_originalCasterGUID ); - - SpellCastTargets targets; - targets.setDestination(m_targets.m_destX,m_targets.m_destY,m_targets.m_destZ); - spell->m_CastItem = m_CastItem; - spell->prepare(&targets, NULL); + m_caster->CastSpell(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, spellInfo->Id, true, m_CastItem, 0, m_originalCasterGUID); } void Spell::EffectTeleportUnits(uint32 i) @@ -2128,17 +2295,12 @@ void Spell::EffectApplyAura(uint32 i) if(!unitTarget) return; - SpellImmuneList const& list = unitTarget->m_spellImmune[IMMUNITY_STATE]; - for(SpellImmuneList::const_iterator itr = list.begin(); itr != list.end(); ++itr) - if(itr->type == m_spellInfo->EffectApplyAuraName[i]) - return; - // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load) if( !unitTarget->isAlive() && m_spellInfo->Id != 20584 && m_spellInfo->Id != 8326 && (unitTarget->GetTypeId()!=TYPEID_PLAYER || !((Player*)unitTarget)->GetSession()->PlayerLoading()) ) return; - Unit* caster = m_originalCasterGUID ? m_originalCaster : m_caster; + Unit* caster = m_originalCaster ? m_originalCaster : m_caster; if(!caster) return; @@ -2151,6 +2313,13 @@ void Spell::EffectApplyAura(uint32 i) unitTarget->ApplyDiminishingToDuration(m_diminishGroup,duration,caster,m_diminishLevel); Aur->setDiminishGroup(m_diminishGroup); + //apply mods only here, area auras don't have duration + duration = caster->ModSpellDuration(m_spellInfo, i, unitTarget, duration); + + //mod duration of channeled aura by spell haste + if (IsChanneledSpell(m_spellInfo)) + caster->ModSpellCastTime(m_spellInfo, duration, this); + // if Aura removed and deleted, do not continue. if(duration== 0 && !(Aur->IsPermanent())) { @@ -2175,33 +2344,8 @@ void Spell::EffectApplyAura(uint32 i) if(!Aur) return; - // TODO Make a way so it works for every related spell! - if(unitTarget->GetTypeId()==TYPEID_PLAYER) // Negative buff should only be applied on players - { - uint32 spellId = 0; - if(m_spellInfo->CasterAuraStateNot==AURA_STATE_WEAKENED_SOUL || m_spellInfo->TargetAuraStateNot==AURA_STATE_WEAKENED_SOUL) - spellId = 6788; // Weakened Soul - else if(m_spellInfo->CasterAuraStateNot==AURA_STATE_FORBEARANCE || m_spellInfo->TargetAuraStateNot==AURA_STATE_FORBEARANCE) - spellId = 25771; // Forbearance - else if(m_spellInfo->CasterAuraStateNot==AURA_STATE_HYPOTHERMIA) - spellId = 41425; // Hypothermia - else if (m_spellInfo->Mechanic == MECHANIC_BANDAGE) // Bandages - spellId = 11196; // Recently Bandaged - else if( (m_spellInfo->AttributesEx & 0x20) && (m_spellInfo->AttributesEx2 & 0x20000) ) - spellId = 23230; // Blood Fury - Healing Reduction - - SpellEntry const *AdditionalSpellInfo = sSpellStore.LookupEntry(spellId); - if (AdditionalSpellInfo) - { - // applied at target by target - Aura* AdditionalAura = CreateAura(AdditionalSpellInfo, 0, NULL, unitTarget,unitTarget, 0); - unitTarget->AddAura(AdditionalAura); - sLog.outDebug("Spell: Additional Aura is: %u", AdditionalSpellInfo->EffectApplyAuraName[0]); - } - } - // Prayer of Mending (jump animation), we need formal caster instead original for correct animation - if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && (m_spellInfo->SpellFamilyFlags & 0x00002000000000LL)) + if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && (m_spellInfo->SpellFamilyFlags[1] & 0x000020)) m_caster->CastSpell(unitTarget, 41637, true, NULL, Aur, m_originalCasterGUID); } @@ -2252,7 +2396,8 @@ void Spell::EffectPowerDrain(uint32 i) unitTarget->ModifyPower(drain_power,-new_damage); - if(drain_power == POWER_MANA) + // Don`t restore from self drain + if(drain_power == POWER_MANA && m_caster != unitTarget) { float manaMultiplier = m_spellInfo->EffectMultipleValue[i]; if(manaMultiplier==0) @@ -2345,10 +2490,24 @@ void Spell::EffectPowerBurn(uint32 i) if(damage < 0) return; + Unit* caster = m_originalCaster ? m_originalCaster : m_caster; + int32 curPower = int32(unitTarget->GetPower(powertype)); - // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4) uint32 power = damage; + //Mana burn take mana % amount from target, but not bigger than amount*2 of caster mana + if ( m_spellInfo->SpellFamilyName==SPELLFAMILY_PRIEST && m_spellInfo->SpellFamilyFlags[0] & 0x10) + { + // Burn percentage of target's mana + power = damage * curPower / 100; + if (caster) + { + uint32 casterPower = damage * caster->GetPower(powertype) / 50; + if (casterPower<curPower) + curPower = casterPower; + } + } + // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4) if ( powertype == POWER_MANA && unitTarget->GetTypeId() == TYPEID_PLAYER ) power -= ((Player*)unitTarget)->GetSpellCritDamageReduction(power); @@ -2393,7 +2552,7 @@ void Spell::SpellDamageHeal(uint32 /*i*/) Unit::AuraList const& mDummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY); for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i) if((*i)->GetId() == 45062) - damageAmount+=(*i)->GetModifierValue(); + damageAmount+=(*i)->GetModifier()->m_amount; if (damageAmount) m_caster->RemoveAurasDueToSpell(45062); @@ -2408,7 +2567,7 @@ void Spell::SpellDamageHeal(uint32 /*i*/) for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i) { if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID - && ((*i)->GetSpellProto()->SpellFamilyFlags == 0x40 || (*i)->GetSpellProto()->SpellFamilyFlags == 0x10) ) + && ((*i)->GetSpellProto()->SpellFamilyFlags.IsEqual(0x40) || (*i)->GetSpellProto()->SpellFamilyFlags.IsEqual(0x10)) ) { if(!targetAura || (*i)->GetAuraDuration() < targetAura->GetAuraDuration()) targetAura = *i; @@ -2421,29 +2580,29 @@ void Spell::SpellDamageHeal(uint32 /*i*/) return; } - int32 tickheal = targetAura->GetModifierValuePerStack(); + int32 tickheal = targetAura->GetModifier()->m_amount; if(Unit* auraCaster = targetAura->GetCaster()) - tickheal = auraCaster->SpellHealingBonus(targetAura->GetSpellProto(), tickheal, DOT, unitTarget); + tickheal = auraCaster->SpellHealingBonus(unitTarget, targetAura->GetSpellProto(), tickheal, DOT); //int32 tickheal = targetAura->GetSpellProto()->EffectBasePoints[idx] + 1; //It is said that talent bonus should not be included - //int32 tickheal = targetAura->GetModifierValue(); + int32 tickcount = 0; if(targetAura->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID) { - switch(targetAura->GetSpellProto()->SpellFamilyFlags)//TODO: proper spellfamily for 3.0.x + switch(targetAura->GetSpellProto()->SpellFamilyFlags[0])//TODO: proper spellfamily for 3.0.x { case 0x10: tickcount = 4; break; // Rejuvenation case 0x40: tickcount = 6; break; // Regrowth } } addhealth += tickheal * tickcount; - unitTarget->RemoveAurasDueToCasterSpell(targetAura->GetId(), targetAura->GetCasterGUID()); + unitTarget->RemoveAurasByCasterSpell(targetAura->GetId(), targetAura->GetCasterGUID()); //addhealth += tickheal * tickcount; //addhealth = caster->SpellHealingBonus(m_spellInfo, addhealth,HEAL, unitTarget); } else - addhealth = caster->SpellHealingBonus(m_spellInfo, addhealth,HEAL, unitTarget); + addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, addhealth, HEAL); m_damage -= addhealth; } @@ -2484,7 +2643,7 @@ void Spell::EffectHealMechanical( uint32 /*i*/ ) if (!caster) return; - uint32 addhealth = caster->SpellHealingBonus(m_spellInfo, uint32(damage), HEAL, unitTarget); + uint32 addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, uint32(damage), HEAL); caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, false); unitTarget->ModifyHealth( int32(damage) ); } @@ -2515,7 +2674,7 @@ void Spell::EffectHealthLeech(uint32 i) if(m_caster->isAlive()) { - new_damage = m_caster->SpellHealingBonus(m_spellInfo, new_damage, HEAL, m_caster); + new_damage = m_caster->SpellHealingBonus(m_caster, m_spellInfo, new_damage, HEAL); m_caster->ModifyHealth(new_damage); @@ -2568,8 +2727,8 @@ void Spell::DoCreateItem(uint32 i, uint32 itemtype) if (num_to_add < 1) num_to_add = 1; - if (num_to_add > pProto->Stackable) - num_to_add = pProto->Stackable; + if (num_to_add > pProto->GetMaxStackSize()) + num_to_add = pProto->GetMaxStackSize(); // init items_count to 1, since 1 item will be created regardless of specialization int items_count=1; @@ -2635,9 +2794,24 @@ void Spell::EffectCreateItem(uint32 i) DoCreateItem(i,m_spellInfo->EffectItemType[i]); } +void Spell::EffectCreateItem2(uint32 i) +{ + // special case: generate using spell_loot_template + if(!m_spellInfo->EffectItemType[i]) + { + if(m_caster->GetTypeId()!=TYPEID_PLAYER) + return; + + // create some random items + ((Player*)m_caster)->AutoStoreLoot(m_spellInfo->Id,LootTemplates_Spell); + return; + } + DoCreateItem(i,m_spellInfo->EffectItemType[i]); +} + void Spell::EffectPersistentAA(uint32 i) { - float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); + float radius = GetSpellRadiusForFriend(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); if(Player* modOwner = m_originalCaster->GetSpellModOwner()) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius); @@ -2665,6 +2839,8 @@ void Spell::EffectEnergize(uint32 i) if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS) return; + Powers power = Powers(m_spellInfo->EffectMiscValue[i]); + // Some level depends spells int multiplier = 0; int level_diff = 0; @@ -2692,11 +2868,18 @@ void Spell::EffectEnergize(uint32 i) if (level_diff > 0) damage -= multiplier * level_diff; + //Judgement of wisdom energize effect + if(m_spellInfo->Id == 20268) + { + if(unitTarget->GetTypeId() == TYPEID_PLAYER) + { + damage = unitTarget->GetCreateMana() * damage / 100; + } + } + if(damage < 0) return; - Powers power = Powers(m_spellInfo->EffectMiscValue[i]); - if(unitTarget->GetMaxPower(power) == 0) return; @@ -2764,7 +2947,7 @@ void Spell::EffectEnergisePct(uint32 i) uint32 gain = damage * maxPower / 100; unitTarget->ModifyPower(power, gain); - m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, damage, power); + m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, gain, power); } void Spell::SendLoot(uint64 guid, LootType loottype) @@ -2931,10 +3114,10 @@ void Spell::EffectOpenLock(uint32 /*i*/) } // check key - for(int i = 0; i < 5; ++i) + for(int i = 0; i < 8; ++i) { - // type==1 This means lockInfo->key[i] is an item - if(lockInfo->keytype[i]==LOCK_KEY_ITEM && lockInfo->key[i] && m_CastItem && m_CastItem->GetEntry()==lockInfo->key[i]) + // Type==1 This means lockInfo->Index[i] is an item + if(lockInfo->Type[i]==LOCK_KEY_ITEM && lockInfo->Index[i] && m_CastItem && m_CastItem->GetEntry()==lockInfo->Index[i]) { SendLoot(guid, loottype); return; @@ -2952,9 +3135,9 @@ void Spell::EffectOpenLock(uint32 /*i*/) // skill bonus provided by casting spell (mostly item spells) uint32 spellSkillBonus = uint32(damage/*m_currentBasePoints[0]+1*/); - uint32 reqSkillValue = lockInfo->requiredminingskill; + uint32 reqSkillValue = lockInfo->Skill[0]; - if(lockInfo->requiredlockskill) // required pick lock skill applying + if(lockInfo->Skill[1]) // required pick lock skill applying { if(SkillId != SKILL_LOCKPICKING) // wrong skill (cheating?) { @@ -2962,7 +3145,7 @@ void Spell::EffectOpenLock(uint32 /*i*/) return; } - reqSkillValue = lockInfo->requiredlockskill; + reqSkillValue = lockInfo->Skill[1]; } else if(SkillId == SKILL_LOCKPICKING) // apply picklock skill to wrong target { @@ -2980,8 +3163,7 @@ void Spell::EffectOpenLock(uint32 /*i*/) } // update skill if really known - uint32 SkillValue = player->GetPureSkillValue(SkillId); - if(SkillValue) // non only item base skill + if(uint32 SkillValue = player->GetPureSkillValue(SkillId)) { if(gameObjTarget) { @@ -2993,7 +3175,6 @@ void Spell::EffectOpenLock(uint32 /*i*/) else if(itemTarget) { // Do one skill-up - uint32 SkillValue = player->GetPureSkillValue(SkillId); player->UpdateGatherSkill(SkillId, SkillValue, reqSkillValue); } } @@ -3146,7 +3327,12 @@ void Spell::EffectSummonType(uint32 i) case SUMMON_TYPE_POSESSED3: EffectSummonPossessed(i); break; + case SUMMON_TYPE_FORCE_OF_NATURE: + case SUMMON_TYPE_GUARDIAN2: + EffectSummonGuardian(i); + break; case SUMMON_TYPE_WILD: + case SUMMON_TYPE_WILD2: EffectSummonWild(i); break; case SUMMON_TYPE_DEMON: @@ -3236,8 +3422,8 @@ void Spell::EffectLearnSpell(uint32 i) Player *player = (Player*)unitTarget; - uint32 spellToLearn = (m_spellInfo->Id==SPELL_ID_GENERIC_LEARN) ? damage : m_spellInfo->EffectTriggerSpell[i]; - player->learnSpell(spellToLearn); + uint32 spellToLearn = ((m_spellInfo->Id==SPELL_ID_GENERIC_LEARN) || (m_spellInfo->Id==SPELL_ID_GENERIC_LEARN_PET)) ? damage : m_spellInfo->EffectTriggerSpell[i]; + player->learnSpell(spellToLearn,false); sLog.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow() ); } @@ -3292,18 +3478,10 @@ void Spell::EffectDispel(uint32 i) SpellEntry const* spellInfo = aur->GetSpellProto(); // Base dispel chance // TODO: possible chance depend from spell level?? - int32 miss_chance = 0; - // Apply dispel mod from aura caster - if (Unit *caster = aur->GetCaster()) - { - if ( Player* modOwner = caster->GetSpellModOwner() ) - modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_RESIST_DISPEL_CHANCE, miss_chance, this); - } - // Try dispel - if (roll_chance_i(miss_chance)) - fail_list.push_back(aur->GetId()); - else + if (aur->GetDispelChance(this)) success_list.push_back(std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID())); + else + fail_list.push_back(aur->GetId()); // Remove buff from list for prevent doubles for (std::vector<Aura *>::iterator j = dispel_list.begin(); j != dispel_list.end(); ) { @@ -3333,19 +3511,14 @@ void Spell::EffectDispel(uint32 i) SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first); data << uint32(spellInfo->Id); // Spell Id data << uint8(0); // 0 - dispelled !=0 cleansed - if(spellInfo->StackAmount!= 0) - { - //Why are Aura's Removed by EffIndex? Auras should be removed as a whole..... - unitTarget->RemoveSingleAuraFromStackByDispel(spellInfo->Id); - } - else + //Why are Aura's Removed by EffIndex? Auras should be removed as a whole..... unitTarget->RemoveAurasDueToSpellByDispel(spellInfo->Id, j->second, m_caster); } m_caster->SendMessageToSet(&data, true); // On succes dispel // Devour Magic - if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->Category == 12) + if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->Category == SPELLCATEGORY_DEVOUR_MAGIC) { uint32 heal_spell = 0; switch (m_spellInfo->Id) @@ -3356,6 +3529,7 @@ void Spell::EffectDispel(uint32 i) case 19736: heal_spell = 19735; break; case 27276: heal_spell = 27278; break; case 27277: heal_spell = 27279; break; + case 48011: heal_spell = 48010; break; default: sLog.outDebug("Spell for Devour Magic %d not handled in Spell::EffectDispel", m_spellInfo->Id); break; @@ -3417,7 +3591,7 @@ void Spell::EffectDistract(uint32 /*i*/) // Set creature Distracted, Stop it, And turn it unitTarget->SetOrientation(angle); unitTarget->StopMoving(); - unitTarget->GetMotionMaster()->MoveDistract(damage*1000); + unitTarget->GetMotionMaster()->MoveDistract(damage*IN_MILISECONDS); } } @@ -3456,7 +3630,7 @@ void Spell::EffectAddFarsight(uint32 i) if (m_caster->GetTypeId() != TYPEID_PLAYER) return; - float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); + float radius = GetSpellRadiusForFriend(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); int32 duration = GetSpellDuration(m_spellInfo); DynamicObject* dynObj = new DynamicObject; if(!dynObj->Create(objmgr.GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, 4, m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, duration, radius)) @@ -3503,7 +3677,7 @@ void Spell::EffectSummonWild(uint32 i) float center_y = m_targets.m_destY; float center_z = m_targets.m_destZ; - float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); + float radius = GetSpellRadiusForHostile(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); int32 amount = damage > 0 ? damage : 1; @@ -3599,12 +3773,13 @@ void Spell::EffectSummonGuardian(uint32 i) float center_y = m_targets.m_destY; float center_z = m_targets.m_destZ; - float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); + float radius = GetSpellRadiusForFriend(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); int32 amount = damage > 0 ? damage : 1; for(int32 count = 0; count < amount; ++count) { + float px, py, pz; // If dest location if present if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) @@ -3666,7 +3841,7 @@ void Spell::EffectTeleUnitsFaceCaster(uint32 i) return; uint32 mapid = m_caster->GetMapId(); - float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); + float dis = m_caster->GetSpellRadiusForTarget(unitTarget, sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); float fx,fy,fz; m_caster->GetClosePoint(fx,fy,fz,unitTarget->GetObjectSize(),dis); @@ -3713,7 +3888,7 @@ void Spell::EffectTradeSkill(uint32 /*i*/) // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75); } -void Spell::EffectEnchantItemPerm(uint32 i) +void Spell::EffectEnchantItemPerm(uint32 effect_idx) { if(m_caster->GetTypeId() != TYPEID_PLAYER) return; @@ -3722,37 +3897,95 @@ void Spell::EffectEnchantItemPerm(uint32 i) Player* p_caster = (Player*)m_caster; + // not grow at item use at item case p_caster->UpdateCraftSkill(m_spellInfo->Id); - if (m_spellInfo->EffectMiscValue[i]) + uint32 enchant_id = m_spellInfo->EffectMiscValue[effect_idx]; + if (!enchant_id) + return; + + SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id); + if(!pEnchant) + return; + + // item can be in trade slot and have owner diff. from caster + Player* item_owner = itemTarget->GetOwner(); + if(!item_owner) + return; + + if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) ) { - uint32 enchant_id = m_spellInfo->EffectMiscValue[i]; + sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)", + p_caster->GetName(),p_caster->GetSession()->GetAccountId(), + itemTarget->GetProto()->Name1,itemTarget->GetEntry(), + item_owner->GetName(),item_owner->GetSession()->GetAccountId()); + } - SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id); - if(!pEnchant) - return; + // remove old enchanting before applying new if equipped + item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,false); - // item can be in trade slot and have owner diff. from caster - Player* item_owner = itemTarget->GetOwner(); - if(!item_owner) - return; + itemTarget->SetEnchantment(PERM_ENCHANTMENT_SLOT, enchant_id, 0, 0); - if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) ) + // add new enchanting if equipped + item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,true); +} + +void Spell::EffectEnchantItemPrismatic(uint32 effect_idx) +{ + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return; + if (!itemTarget) + return; + + Player* p_caster = (Player*)m_caster; + + uint32 enchant_id = m_spellInfo->EffectMiscValue[effect_idx]; + if (!enchant_id) + return; + + SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id); + if(!pEnchant) + return; + + // support only enchantings with add socket in this slot + { + bool add_socket = false; + for(int i = 0; i < 3; ++i) + { + if(pEnchant->type[i]==ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET) + { + add_socket = true; + break; + } + } + if(!add_socket) { - sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)", - p_caster->GetName(),p_caster->GetSession()->GetAccountId(), - itemTarget->GetProto()->Name1,itemTarget->GetEntry(), - item_owner->GetName(),item_owner->GetSession()->GetAccountId()); + sLog.outError("Spell::EffectEnchantItemPrismatic: attempt apply enchant spell %u with SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC (%u) but without ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET (u), not suppoted yet.", + m_spellInfo->Id,SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC,ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET); + return; } + } - // remove old enchanting before applying new if equipped - item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,false); - - itemTarget->SetEnchantment(PERM_ENCHANTMENT_SLOT, enchant_id, 0, 0); + // item can be in trade slot and have owner diff. from caster + Player* item_owner = itemTarget->GetOwner(); + if(!item_owner) + return; - // add new enchanting if equipped - item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,true); + if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) ) + { + sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)", + p_caster->GetName(),p_caster->GetSession()->GetAccountId(), + itemTarget->GetProto()->Name1,itemTarget->GetEntry(), + item_owner->GetName(),item_owner->GetSession()->GetAccountId()); } + + // remove old enchanting before applying new if equipped + item_owner->ApplyEnchantment(itemTarget,PRISMATIC_ENCHANTMENT_SLOT,false); + + itemTarget->SetEnchantment(PRISMATIC_ENCHANTMENT_SLOT, enchant_id, 0, 0); + + // add new enchanting if equipped + item_owner->ApplyEnchantment(itemTarget,PRISMATIC_ENCHANTMENT_SLOT,true); } void Spell::EffectEnchantItemTmp(uint32 i) @@ -3847,13 +4080,13 @@ void Spell::EffectEnchantItemTmp(uint32 i) else if(m_spellInfo->SpellFamilyName==SPELLFAMILY_SHAMAN) duration = 1800; // 30 mins // other cases with this SpellVisual already selected - else if(m_spellInfo->SpellVisual==215) + else if(m_spellInfo->SpellVisual[0]==215) duration = 1800; // 30 mins // some fishing pole bonuses - else if(m_spellInfo->SpellVisual==563) + else if(m_spellInfo->SpellVisual[0]==563) duration = 600; // 10 mins // shaman rockbiter enchantments - else if(m_spellInfo->SpellVisual==0) + else if(m_spellInfo->SpellVisual[0]==0) duration = 1800; // 30 mins else if(m_spellInfo->Id==29702) duration = 300; // 5 mins @@ -3916,14 +4149,16 @@ void Spell::EffectTameCreature(uint32 /*i*/) creatureTarget->RemoveCorpse(); creatureTarget->SetHealth(0); // just for nice GM-mode view + uint32 level = (creatureTarget->getLevel() < (m_caster->getLevel() - 5)) ? (m_caster->getLevel() - 5) : creatureTarget->getLevel(); + // prepare visual effect for levelup - pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel()-1); + pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1); // add to world pet->GetMap()->Add((Creature*)pet); // visual effect for levelup - pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel()); + pet->SetUInt32Value(UNIT_FIELD_LEVEL, level); // caster have pet now m_caster->SetPet(pet); @@ -3991,6 +4226,7 @@ void Spell::EffectSummonPet(uint32 i) owner->GetClosePoint(x, y, z, owner->GetObjectSize()); Pet* pet = owner->SummonPet(petentry, x, y, z, owner->GetOrientation(), SUMMON_PET, 0); if(!pet) + return; if(m_caster->GetTypeId() == TYPEID_UNIT) @@ -4004,9 +4240,12 @@ void Spell::EffectSummonPet(uint32 i) pet->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id); // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later - pet->SetUInt32Value(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE); + if(m_caster->GetTypeId() == TYPEID_PLAYER) + pet->SetUInt32Value(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE); + pet->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL)); + pet->InitTalentForLevel(); // generate new name for summon pet std::string new_name=objmgr.GeneratePetName(petentry); if(!new_name.empty()) @@ -4030,7 +4269,6 @@ void Spell::EffectLearnPetSpell(uint32 i) if(!learn_spellproto) return; - pet->SetTP(pet->m_TrainingPoints - pet->GetTPForSpell(learn_spellproto->Id)); pet->learnSpell(learn_spellproto->Id); pet->SavePetToDB(PET_SAVE_AS_CURRENT); @@ -4094,21 +4332,25 @@ void Spell::SpellDamageWeaponDmg(uint32 i) case SPELLFAMILY_WARRIOR: { // Devastate bonus and sunder armor refresh - if(m_spellInfo->SpellVisual == 671 && m_spellInfo->SpellIconID == 1508) + if(m_spellInfo->SpellFamilyFlags[1] & 0x40) { + if (m_caster->GetTypeId()!=TYPEID_PLAYER) + return; uint32 stack = 0; - + int32 maxStack = 0; Unit::AuraList const& list = unitTarget->GetAurasByType(SPELL_AURA_MOD_RESISTANCE); for(Unit::AuraList::const_iterator itr=list.begin();itr!=list.end();++itr) { SpellEntry const *proto = (*itr)->GetSpellProto(); if(proto->SpellFamilyName == SPELLFAMILY_WARRIOR - && proto->SpellFamilyFlags == SPELLFAMILYFLAG_WARRIOR_SUNDERARMOR) + && proto->SpellFamilyFlags.IsEqual(SPELLFAMILYFLAG_WARRIOR_SUNDERARMOR) + && (*itr)->GetCasterGUID() == m_caster->GetGUID()) { - int32 duration = GetSpellDuration(proto); - (*itr)->SetAuraDuration(duration); - (*itr)->UpdateAuraDuration(); + (*itr)->RefreshAura(); stack = (*itr)->GetStackAmount(); + maxStack = proto->StackAmount; + + ((Player*)m_caster)->ApplySpellMod(proto->Id, SPELLMOD_CHARGES, maxStack, this); break; } } @@ -4122,7 +4364,7 @@ void Spell::SpellDamageWeaponDmg(uint32 i) } } - if(stack < 5) + if(stack < maxStack) { // get highest rank of the Sunder Armor spell const PlayerSpellMap& sp_list = ((Player*)m_caster)->GetSpellMap(); @@ -4136,7 +4378,7 @@ void Spell::SpellDamageWeaponDmg(uint32 i) if (!spellInfo) continue; - if (spellInfo->SpellFamilyFlags == SPELLFAMILYFLAG_WARRIOR_SUNDERARMOR + if (spellInfo->SpellFamilyFlags.IsEqual(SPELLFAMILYFLAG_WARRIOR_SUNDERARMOR) && spellInfo->Id != m_spellInfo->Id && spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR) { @@ -4145,19 +4387,21 @@ void Spell::SpellDamageWeaponDmg(uint32 i) } } } + if (stack) + spell_bonus += stack * CalculateDamage(2, unitTarget); } break; } case SPELLFAMILY_ROGUE: { // Hemorrhage - if(m_spellInfo->SpellFamilyFlags & 0x2000000) + if(m_spellInfo->SpellFamilyFlags[0] & 0x2000000) { if(m_caster->GetTypeId()==TYPEID_PLAYER) ((Player*)m_caster)->AddComboPoints(unitTarget, 1); } // Mutilate (for each hand) - else if(m_spellInfo->SpellFamilyFlags & 0x600000000LL) + else if(m_spellInfo->SpellFamilyFlags[1] & 0x6) { bool found = false; // fast check @@ -4178,16 +4422,16 @@ void Spell::SpellDamageWeaponDmg(uint32 i) } if(found) - totalDamagePercentMod *= 1.5f; // 150% if poisoned + totalDamagePercentMod *= 1.2f; // 120% if poisoned } break; } case SPELLFAMILY_PALADIN: { // Seal of Command - receive benefit from Spell Damage and Healing - if(m_spellInfo->SpellFamilyFlags & 0x00000002000000LL) + if(m_spellInfo->SpellFamilyFlags[0] & 0x2000000) { - spell_bonus += int32(0.20f*m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo))); + spell_bonus += int32(0.23f*m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo))); spell_bonus += int32(0.29f*m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget)); } break; @@ -4196,7 +4440,7 @@ void Spell::SpellDamageWeaponDmg(uint32 i) { // Skyshatter Harness item set bonus // Stormstrike - if(m_spellInfo->SpellFamilyFlags & 0x001000000000LL) + if(m_spellInfo->SpellFamilyFlags[1] & 0x0010) { Unit::AuraList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); for(Unit::AuraList::const_iterator i = m_OverrideClassScript.begin(); i != m_OverrideClassScript.end(); ++i) @@ -4214,7 +4458,7 @@ void Spell::SpellDamageWeaponDmg(uint32 i) case SPELLFAMILY_DRUID: { // Mangle (Cat): CP - if(m_spellInfo->SpellFamilyFlags==0x0000040000000000LL) + if(m_spellInfo->SpellFamilyFlags.IsEqual(0,0x00000400)) { if(m_caster->GetTypeId()==TYPEID_PLAYER) ((Player*)m_caster)->AddComboPoints(unitTarget,1); @@ -4299,33 +4543,6 @@ void Spell::SpellDamageWeaponDmg(uint32 i) // Add melee damage bonuses (also check for negative) m_caster->MeleeDamageBonus(unitTarget, &eff_damage, m_attackType, m_spellInfo); m_damage+= eff_damage; - - // take ammo - if(m_attackType == RANGED_ATTACK && m_caster->GetTypeId() == TYPEID_PLAYER) - { - Item *pItem = ((Player*)m_caster)->GetWeaponForAttack( RANGED_ATTACK ); - - // wands don't have ammo - if(!pItem || pItem->IsBroken() || pItem->GetProto()->SubClass==ITEM_SUBCLASS_WEAPON_WAND) - return; - - if( pItem->GetProto()->InventoryType == INVTYPE_THROWN ) - { - if(pItem->GetMaxStackCount()==1) - { - // decrease durability for non-stackable throw weapon - ((Player*)m_caster)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED); - } - else - { - // decrease items amount for stackable throw weapon - uint32 count = 1; - ((Player*)m_caster)->DestroyItemCount( pItem, count, true); - } - } - else if(uint32 ammo = ((Player*)m_caster)->GetUInt32Value(PLAYER_AMMO_ID)) - ((Player*)m_caster)->DestroyItemCount(ammo, 1, true); - } } void Spell::EffectThreat(uint32 /*i*/) @@ -4370,7 +4587,7 @@ void Spell::EffectInterruptCast(uint32 i) { if(m_originalCaster) { - int32 duration = m_originalCaster->CalculateSpellDuration(m_spellInfo, i, unitTarget); + int32 duration = m_originalCaster->ModSpellDuration(m_spellInfo, i, unitTarget, m_originalCaster->CalcSpellDuration(m_spellInfo)); unitTarget->ProhibitSpellScholl(GetSpellSchoolMask(unitTarget->m_currentSpells[i]->m_spellInfo), duration/*GetSpellDuration(m_spellInfo)*/); } unitTarget->InterruptSpell(i,false); @@ -4402,14 +4619,14 @@ void Spell::EffectSummonObjectWild(uint32 i) Map *map = target->GetMap(); if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map, - x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1)) + m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1)) { delete pGameObj; return; } int32 duration = GetSpellDuration(m_spellInfo); - pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0); + pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0); pGameObj->SetSpellId(m_spellInfo->Id); if(pGameObj->GetGoType() != GAMEOBJECT_TYPE_FLAGDROP) // make dropped flag clickable for other players (not set owner guid (created by) for this)... @@ -4450,9 +4667,9 @@ void Spell::EffectSummonObjectWild(uint32 i) { GameObject* linkedGO = new GameObject; if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, map, - x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1)) + m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1)) { - linkedGO->SetRespawnTime(duration > 0 ? duration/1000 : 0); + linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0); linkedGO->SetSpellId(m_spellInfo->Id); m_caster->AddGameObject(linkedGO); @@ -4471,441 +4688,596 @@ void Spell::EffectScriptEffect(uint32 effIndex) { // TODO: we must implement hunter pet summon at login there (spell 6962) - // by spell id - switch(m_spellInfo->Id) + switch(m_spellInfo->SpellFamilyName) { - // PX-238 Winter Wondervolt TRAP - case 26275: + case SPELLFAMILY_GENERIC: { - if( unitTarget->HasAura(26272,0) - || unitTarget->HasAura(26157,0) - || unitTarget->HasAura(26273,0) - || unitTarget->HasAura(26274,0)) - return; + switch(m_spellInfo->Id) + { + // PX-238 Winter Wondervolt TRAP + case 26275: + { + uint32 spells[4] = { 26272, 26157, 26273, 26274 }; - uint32 iTmpSpellId; + // check presence + for(int j = 0; j < 4; ++j) + if(unitTarget->HasAura(spells[j],0)) + return; - switch(urand(0,3)) - { - case 0: - iTmpSpellId = 26272; - break; - case 1: - iTmpSpellId = 26157; - break; - case 2: - iTmpSpellId = 26273; - break; - case 3: - iTmpSpellId = 26274; - break; - } + // select spell + uint32 iTmpSpellId = spells[urand(0,3)]; - unitTarget->CastSpell(unitTarget, iTmpSpellId, true); + // cast + unitTarget->CastSpell(unitTarget, iTmpSpellId, true); + return; + } + // Bending Shinbone + case 8856: + { + if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER) + return; - return; - } + uint32 spell_id = 0; + switch(urand(1,5)) + { + case 1: spell_id = 8854; break; + default: spell_id = 8855; break; + } - // Bending Shinbone - case 8856: - { - if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER) - return; + m_caster->CastSpell(m_caster,spell_id,true,NULL); + return; + } + // Brittle Armor - need remove one 24575 Brittle Armor aura + case 24590: + unitTarget->RemoveSingleSpellAurasFromStack(24575); + return; + // Mercurial Shield - need remove one 26464 Mercurial Shield aura + case 26465: + unitTarget->RemoveSingleSpellAurasFromStack(26464); + return; + // Orb teleport spells + case 25140: + case 25143: + case 25650: + case 25652: + case 29128: + case 29129: + case 35376: + case 35727: + { + if(!unitTarget) + return; - uint32 spell_id = 0; - switch(urand(1,5)) - { - case 1: spell_id = 8854; break; - default: spell_id = 8855; break; - } + uint32 spellid; + switch(m_spellInfo->Id) + { + case 25140: spellid = 32571; break; + case 25143: spellid = 32572; break; + case 25650: spellid = 30140; break; + case 25652: spellid = 30141; break; + case 29128: spellid = 32568; break; + case 29129: spellid = 32569; break; + case 35376: spellid = 25649; break; + case 35727: spellid = 35730; break; + default: + return; + } - m_caster->CastSpell(m_caster,spell_id,true,NULL); - return; - } + unitTarget->CastSpell(unitTarget,spellid,false); + return; + } + // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell) + case 22539: + case 22972: + case 22975: + case 22976: + case 22977: + case 22978: + case 22979: + case 22980: + case 22981: + case 22982: + case 22983: + case 22984: + case 22985: + { + if(!unitTarget || !unitTarget->isAlive()) + return; - // Healthstone creating spells - case 6201: - case 6202: - case 5699: - case 11729: - case 11730: - case 27230: - { - uint32 itemtype; - uint32 rank = 0; - Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY); - for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i) - { - if((*i)->GetId() == 18692) + // Onyxia Scale Cloak + if(unitTarget->GetDummyAura(22683)) + return; + + // Shadow Flame + m_caster->CastSpell(unitTarget, 22682, true); + return; + } + // Summon Black Qiraji Battle Tank + case 26656: { - rank = 1; + if(!unitTarget) + return; + + // Prevent stacking of mounts + unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); + + // Two separate mounts depending on area id (allows use both in and out of specific instance) + if (unitTarget->GetAreaId() == 3428) + unitTarget->CastSpell(unitTarget, 25863, false); + else + unitTarget->CastSpell(unitTarget, 26655, false); break; } - else if((*i)->GetId() == 18693) + // Piccolo of the Flaming Fire + case 17512: { - rank = 2; + if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE); break; } - } + // Escape artist + case 20589: + { + if(!unitTarget) + return; + // It is said that removing effects by script should include dispel resist mods + unitTarget->RemoveSpellsCausingAuraWithDispel(SPELL_AURA_MOD_ROOT, this); + unitTarget->RemoveSpellsCausingAuraWithDispel(SPELL_AURA_MOD_DECREASE_SPEED, this); + } + // Mirren's Drinking Hat + case 29830: + { + uint32 item = 0; + switch ( urand(1,6) ) + { + case 1:case 2:case 3: + item = 23584;break; // Loch Modan Lager + case 4:case 5: + item = 23585;break; // Stouthammer Lite + case 6: + item = 23586;break; // Aerie Peak Pale Ale + } + if (item) + DoCreateItem(effIndex,item); + break; + } + // Improved Sprint + case 30918: + { + // Removes snares and roots. + uint32 mechanic_mask = (1<<MECHANIC_ROOT) | (1<<MECHANIC_SNARE); + Unit::AuraMap& Auras = unitTarget->GetAuras(); + for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next) + { + next = iter; + ++next; + Aura *aur = iter->second; + if (!aur->IsPositive()) //only remove negative spells + { + // check for mechanic mask + if(GetSpellMechanicMask(aur->GetSpellProto(), aur->GetEffIndex()) & mechanic_mask) + { + unitTarget->RemoveAurasDueToSpell(aur->GetId()); + if(Auras.empty()) + break; + else + next = Auras.begin(); + } + } + } + break; + } + /*// Flame Crash + case 41126: + { + if(!unitTarget) + return; - static uint32 const itypes[6][3] = { - { 5512,19004,19005}, // Minor Healthstone - { 5511,19006,19007}, // Lesser Healthstone - { 5509,19008,19009}, // Healthstone - { 5510,19010,19011}, // Greater Healthstone - { 9421,19012,19013}, // Major Healthstone - {22103,22104,22105} // Master Healthstone - }; + unitTarget->CastSpell(unitTarget, 41131, true); + break; + }*/ + // Draw Soul + case 40904: + { + if(!unitTarget) + return; - switch(m_spellInfo->Id) - { - case 6201: itemtype=itypes[0][rank];break; // Minor Healthstone - case 6202: itemtype=itypes[1][rank];break; // Lesser Healthstone - case 5699: itemtype=itypes[2][rank];break; // Healthstone - case 11729: itemtype=itypes[3][rank];break; // Greater Healthstone - case 11730: itemtype=itypes[4][rank];break; // Major Healthstone - case 27230: itemtype=itypes[5][rank];break; // Master Healthstone - default: - return; - } - DoCreateItem( effIndex, itemtype ); - return; - } - // Brittle Armor - need remove one 24575 Brittle Armor aura - case 24590: - unitTarget->RemoveSingleAuraFromStack(24575, 0); - unitTarget->RemoveSingleAuraFromStack(24575, 1); - return; - // Mercurial Shield - need remove one 26464 Mercurial Shield aura - case 26465: - unitTarget->RemoveSingleAuraFromStack(26464, 0); - return; - // Orb teleport spells - case 25140: - case 25143: - case 25650: - case 25652: - case 29128: - case 29129: - case 35376: - case 35727: - { - if(!unitTarget) - return; + unitTarget->CastSpell(m_caster, 40903, true); + break; + } + case 48025: // Headless Horseman's Mount + { + if(!unitTarget) + return; + + switch(((Player*)unitTarget)->GetBaseSkillValue(762)) + { + case 75: unitTarget->CastSpell(unitTarget, 51621, true); break;; + case 150: unitTarget->CastSpell(unitTarget, 48024, true); break; + case 225: unitTarget->CastSpell(unitTarget, 51617, true); break; + case 300: unitTarget->CastSpell(unitTarget, 48023, true); break; + default: break; + } + break; + } + case 47977: // Magic Broom + { + if(!unitTarget) + return; - uint32 spellid; - switch(m_spellInfo->Id) - { - case 25140: spellid = 32571; break; - case 25143: spellid = 32572; break; - case 25650: spellid = 30140; break; - case 25652: spellid = 30141; break; - case 29128: spellid = 32568; break; - case 29129: spellid = 32569; break; - case 35376: spellid = 25649; break; - case 35727: spellid = 35730; break; - default: - return; - } + if(unitTarget) + { + switch(((Player*)unitTarget)->GetBaseSkillValue(762)) + { + case 75: unitTarget->CastSpell(unitTarget, 42680, true); break;; + case 150: case 225: case 300: unitTarget->CastSpell(unitTarget, 42683, true); break; + default: break; + } + } + break; + } + case 41931: + { + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return; - unitTarget->CastSpell(unitTarget,spellid,false); - return; - } + int bag=19; + int slot=0; + Item* item = NULL; + + while (bag < 256) + { + item = ((Player*)m_caster)->GetItemByPos(bag,slot); + if (item && item->GetEntry() == 38587) break; + slot++; + if (slot == 39) + { + slot = 0; + bag++; + } + } + if (bag < 256) + { + if (((Player*)m_caster)->GetItemByPos(bag,slot)->GetCount() == 1) ((Player*)m_caster)->RemoveItem(bag,slot,true); + else ((Player*)m_caster)->GetItemByPos(bag,slot)->SetCount(((Player*)m_caster)->GetItemByPos(bag,slot)->GetCount()-1); + // Spell 42518 (Braufest - Gratisprobe des Braufest herstellen) + m_caster->CastSpell(m_caster,42518,true); + return; + } + break; + } + // Force Cast - Portal Effect: Sunwell Isle + case 44876: + { + if(!unitTarget) + return; - // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell) - case 22539: - case 22972: - case 22975: - case 22976: - case 22977: - case 22978: - case 22979: - case 22980: - case 22981: - case 22982: - case 22983: - case 22984: - case 22985: - { - if(!unitTarget || !unitTarget->isAlive()) - return; + unitTarget->CastSpell(unitTarget, 44870, true); + break; + } + // Goblin Weather Machine + case 46203: + { + if(!unitTarget) + return; - // Onyxia Scale Cloak - if(unitTarget->GetDummyAura(22683)) - return; + uint32 spellId; + switch(rand()%4) + { + case 0: spellId = 46740; break; + case 1: spellId = 46739; break; + case 2: spellId = 46738; break; + case 3: spellId = 46736; break; + } + unitTarget->CastSpell(unitTarget, spellId, true); + break; + } + //5,000 Gold + case 46642: + { + if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; - // Shadow Flame - m_caster->CastSpell(unitTarget, 22682, true); - return; - } - break; + ((Player*)unitTarget)->ModifyMoney(50000000); - // Summon Black Qiraji Battle Tank - case 26656: - { - if(!unitTarget) - return; + break; + } + // Emblazon Runeblade + case 51770: + { + if(!unitTarget) + return; - // Prevent stacking of mounts - unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); + unitTarget->CastSpell(unitTarget,51771,false); + break; + } + // Death Gate + case 52751: + { + if(!unitTarget || unitTarget->getClass() != CLASS_DEATH_KNIGHT) + return; + // triggered spell is stored in m_spellInfo->EffectBasePoints[0] + unitTarget->CastSpell(unitTarget, damage, false); + break; + } + // random spell learn instead placeholder + case 60893: // Northrend Alchemy Research + case 61177: // Northrend Inscription Research + case 61288: // Minor Inscription Research + case 61756: // Northrend Inscription Research (FAST QA VERSION) + { + if(!IsExplicitDiscoverySpell(m_spellInfo)) + { + sLog.outError("Wrong explicit discovery spell %u structure, or outdated...",m_spellInfo->Id); + return; + } - // Two separate mounts depending on area id (allows use both in and out of specific instance) - if (unitTarget->GetAreaId() == 3428) - unitTarget->CastSpell(unitTarget, 25863, false); - else - unitTarget->CastSpell(unitTarget, 26655, false); - break; - } - // Piccolo of the Flaming Fire - case 17512: - { - if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) - return; - unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE); - break; - } - // Netherbloom - case 28702: - { - if(!unitTarget) - return; - // 25% chance of casting a random buff - if(roll_chance_i(75)) - return; + if(m_caster->GetTypeId()!=TYPEID_PLAYER) + return; + Player* player = (Player*)m_caster; - // triggered spells are 28703 to 28707 - // Note: some sources say, that there was the possibility of - // receiving a debuff. However, this seems to be removed by a patch. - const uint32 spellid = 28703; + // need replace effect 0 item by loot + uint32 reagent_id = m_spellInfo->EffectItemType[0]; - // don't overwrite an existing aura - for(uint8 i=0; i<5; i++) - if(unitTarget->HasAura(spellid+i, 0)) - return; - unitTarget->CastSpell(unitTarget, spellid+urand(0, 4), true); - break; - } + if(!player->HasItemCount(reagent_id,1)) + return; - // Nightmare Vine - case 28720: - { - if(!unitTarget) - return; - // 25% chance of casting Nightmare Pollen - if(roll_chance_i(75)) - return; - unitTarget->CastSpell(unitTarget, 28721, true); - break; - } + // remove reagent + uint32 count = 1; + player->DestroyItemCount (reagent_id,count,true); - // Mirren's Drinking Hat - case 29830: - { - uint32 item = 0; - switch ( urand(1,6) ) - { - case 1: case 2: case 3: item = 23584; break;// Loch Modan Lager - case 4: case 5: item = 23585; break;// Stouthammer Lite - case 6: item = 23586; break;// Aerie Peak Pale Ale + // create some random items + player->AutoStoreLoot(m_spellInfo->Id,LootTemplates_Spell); + + // learn random explicit discovery recipe (if any) + if(uint32 discoveredSpell = GetExplicitDiscoverySpell(m_spellInfo->Id, player)) + player->learnSpell(discoveredSpell,false); + return; + } } - if (item) - DoCreateItem(effIndex,item); break; } - // Improved Sprint - case 30918: + case SPELLFAMILY_WARLOCK: { - // Removes snares and roots. - uint32 mechanic_mask = (1<<MECHANIC_ROOT) | (1<<MECHANIC_SNARE); - Unit::AuraMap& Auras = unitTarget->GetAuras(); - for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next) + switch(m_spellInfo->Id) { - next = iter; - ++next; - Aura *aur = iter->second; - if (!aur->IsPositive()) //only remove negative spells + // Healthstone creating spells + case 6201: + case 6202: + case 5699: + case 11729: + case 11730: + case 27230: + case 47871: + case 47878: { - // check for mechanic mask - if(GetSpellMechanicMask(aur->GetSpellProto(), aur->GetEffIndex()) & mechanic_mask) + uint32 itemtype; + uint32 rank = 0; + Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i) { - unitTarget->RemoveAurasDueToSpell(aur->GetId()); - if(Auras.empty()) + if((*i)->GetId() == 18692) + { + rank = 1; break; - else - next = Auras.begin(); + } + else if((*i)->GetId() == 18693) + { + rank = 2; + break; + } } - } - } - break; - } - // Goblin Weather Machine - case 46203: - { - if(!unitTarget) - return; - - uint32 spellId; - switch(rand()%4) - { - case 0: - spellId=46740; - break; - case 1: - spellId=46739; - break; - case 2: - spellId=46738; - break; - case 3: - spellId=46736; - break; - } - unitTarget->CastSpell(unitTarget, spellId, true); - break; - } - case 48025: // Headless Horseman's Mount - { - if(!unitTarget) - return; + static uint32 const itypes[8][3] = { + { 5512,19004,19005}, // Minor Healthstone + { 5511,19006,19007}, // Lesser Healthstone + { 5509,19008,19009}, // Healthstone + { 5510,19010,19011}, // Greater Healthstone + { 9421,19012,19013}, // Major Healthstone + {22103,22104,22105}, // Master Healthstone + {36889,36890,36891}, // Demonic Healthstone + {36892,36893,36894} // Fel Healthstone + }; - if(unitTarget) - { - switch(((Player*)unitTarget)->GetBaseSkillValue(762)) + switch(m_spellInfo->Id) { - case 75: unitTarget->CastSpell(unitTarget, 51621, true); break;; - case 150: unitTarget->CastSpell(unitTarget, 48024, true); break; - case 225: unitTarget->CastSpell(unitTarget, 51617, true); break; - case 300: unitTarget->CastSpell(unitTarget, 48023, true); break; - default: break; + case 6201: + itemtype=itypes[0][rank];break; // Minor Healthstone + case 6202: + itemtype=itypes[1][rank];break; // Lesser Healthstone + case 5699: + itemtype=itypes[2][rank];break; // Healthstone + case 11729: + itemtype=itypes[3][rank];break; // Greater Healthstone + case 11730: + itemtype=itypes[4][rank];break; // Major Healthstone + case 27230: + itemtype=itypes[5][rank];break; // Master Healthstone + case 47871: + itemtype=itypes[6][rank];break; // Demonic Healthstone + case 47878: + itemtype=itypes[7][rank];break; // Fel Healthstone + default: + return; } + DoCreateItem( effIndex, itemtype ); + return; } - break; + } + break; } - case 47977: // Magic Broom + case SPELLFAMILY_PRIEST: { - if(!unitTarget) - return; - - if(unitTarget) + switch(m_spellInfo->Id) { - switch(((Player*)unitTarget)->GetBaseSkillValue(762)) + // Pain and Suffering + case 47948: { - case 75: unitTarget->CastSpell(unitTarget, 42680, true); break;; - case 150: case 225: case 300: unitTarget->CastSpell(unitTarget, 42683, true); break; - default: break; + if (!unitTarget) + return; + // Refresh Shadow Word: Pain on target + Unit::AuraMap& auras = unitTarget->GetAuras(); + for(Unit::AuraMap::iterator itr = auras.begin(); itr != auras.end(); ++itr) + { + SpellEntry const *spellInfo = (*itr).second->GetSpellProto(); + if( spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && + spellInfo->SpellFamilyFlags[0] & 0x8000 && + (*itr).second->GetCasterGUID() == m_caster->GetGUID()) + { + (*itr).second->RefreshAura(); + return; + } + } + return; } + default: + break; } break; } - } - - if(!unitTarget || !unitTarget->isAlive()) // can we remove this check? - { - sLog.outError("Spell %u in EffectScriptEffect does not have unitTarget", m_spellInfo->Id); - return; - } - - switch(m_spellInfo->Id) - { - // Dreaming Glory - case 28698: unitTarget->CastSpell(unitTarget, 28694, true); break; - // Needle Spine - //case 39835: unitTarget->CastSpell(unitTarget, 39968, true); break; - // Draw Soul - case 40904: unitTarget->CastSpell(m_caster, 40903, true); break; - // Flame Crash - //case 41126: unitTarget->CastSpell(unitTarget, 41131, true); break; - case 41931: + case SPELLFAMILY_HUNTER: { - int bag=19; - int slot=0; - Item* item = NULL; - - while (bag < 256) + switch(m_spellInfo->Id) { - item = ((Player*)m_caster)->GetItemByPos(bag,slot); - if (item && item->GetEntry() == 38587) break; - slot++; - if (slot == 39) + // Chimera Shot + case 53209: { - slot = 0; - bag++; + uint32 spellId = 0; + int32 basePoint = 0; + Unit::AuraMap& Auras = unitTarget->GetAuras(); + for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i) + { + Aura *aura = (*i).second; + if (aura->GetCasterGUID() != m_caster->GetGUID()) + continue; + // Search only Serpent Sting, Viper Sting, Scorpid Sting auras + flag96 familyFlag = aura->GetSpellProto()->SpellFamilyFlags; + if (!(familyFlag[1] & 0x00000080 || familyFlag[0] & 0x0000C000)) + continue; + // Refresh aura duration + aura->RefreshAura(); + + // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting. + if (familyFlag[0] & 0x4000 && aura->GetEffIndex() == 0) + { + spellId = 53353; // 53353 Chimera Shot - Serpent + basePoint = aura->GetModifier()->m_amount * 5 * 40 / 100; + } + // Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting. + if (familyFlag[1] & 0x00000080 && aura->GetEffIndex() == 0) + { + spellId = 53358; // 53358 Chimera Shot - Viper + basePoint = aura->GetModifier()->m_amount * 4 * 60 / 100; + } + // Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute. + if (familyFlag[0] & 0x00008000) + spellId = 53359; // 53359 Chimera Shot - Scorpid + // ?? nothing say in spell desc (possibly need addition check) + //if (familyFlag & 0x0000010000000000LL || // dot + // familyFlag & 0x0000100000000000LL) // stun + //{ + // spellId = 53366; // 53366 Chimera Shot - Wyvern + //} + } + if (spellId) + m_caster->CastCustomSpell(unitTarget, spellId, &basePoint, 0, 0, false); + return; } + default: + break; } - if (bag < 256) - { - if (((Player*)m_caster)->GetItemByPos(bag,slot)->GetCount() == 1) ((Player*)m_caster)->RemoveItem(bag,slot,true); - else ((Player*)m_caster)->GetItemByPos(bag,slot)->SetCount(((Player*)m_caster)->GetItemByPos(bag,slot)->GetCount()-1); - // Spell 42518 (Braufest - Gratisprobe des Braufest herstellen) - m_caster->CastSpell(m_caster,42518,true); - return; - } - } - // Force Cast - Portal Effect: Sunwell Isle - case 44876: unitTarget->CastSpell(unitTarget, 44870, true); break; - //5,000 Gold - case 46642: - { - if(unitTarget->GetTypeId() == TYPEID_PLAYER) - ((Player*)unitTarget)->ModifyMoney(50000000); break; } - } - - if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN ) - { - switch(m_spellInfo->SpellFamilyFlags) + case SPELLFAMILY_PALADIN: { // Judgement - case 0x800000: + if (m_spellInfo->SpellFamilyFlags[0] & 0x800000) { + if(!unitTarget || !unitTarget->isAlive()) + return; + uint32 spellId1 = 0; uint32 spellId2 = 0; - // all seals have aura dummy + // Judgement self add switch + switch (m_spellInfo->Id) + { + case 41467: break; // Judgement + case 53407: spellId1 = 20184; break; // Judgement of Justice + case 20271: // Judgement of Light + case 57774: spellId1 = 20185; break; // Judgement of Light + case 53408: spellId1 = 20186; break; // Judgement of Wisdom + default: + return; + } + // all seals have aura dummy in 2 effect Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY); for(Unit::AuraList::const_iterator itr = m_dummyAuras.begin(); itr != m_dummyAuras.end(); ++itr) { SpellEntry const *spellInfo = (*itr)->GetSpellProto(); - // search seal (all seals have judgement's aura dummy spell id in 2 effect - if ( !spellInfo || !IsSealSpell((*itr)->GetSpellProto()) || (*itr)->GetEffIndex() != 2 ) + if ((*itr)->GetEffIndex() != 2 || !spellInfo || !IsSealSpell(spellInfo)) continue; - - // must be calculated base at raw base points in spell proto, GetModifier()->m_value for S.Righteousness modified by SPELLMOD_DAMAGE - spellId2 = (*itr)->GetSpellProto()->EffectBasePoints[2]+1; - - if(spellId2 <= 1) + spellId2 = (*itr)->GetModifier()->m_amount; + SpellEntry const *judge = sSpellStore.LookupEntry(spellId2); + if (!judge) continue; + break; + } + if (spellId1) + m_caster->CastSpell(unitTarget, spellId1, true); + if (spellId2) + m_caster->CastSpell(unitTarget, spellId2, true); + return; + } + } + case SPELLFAMILY_POTION: + { + switch(m_spellInfo->Id) + { + // Dreaming Glory + case 28698: + { + if(!unitTarget) + return; + unitTarget->CastSpell(unitTarget, 28694, true); + break; + } + // Netherbloom + case 28702: + { + if(!unitTarget) + return; + // 25% chance of casting a random buff + if(roll_chance_i(75)) + return; - // found, remove seal - m_caster->RemoveAurasDueToSpell((*itr)->GetId()); - - // Sanctified Judgement - Unit::AuraList const& m_auras = m_caster->GetAurasByType(SPELL_AURA_DUMMY); - for(Unit::AuraList::const_iterator i = m_auras.begin(); i != m_auras.end(); ++i) - { - if ((*i)->GetSpellProto()->SpellIconID == 205 && (*i)->GetSpellProto()->Attributes == 0x01D0LL) - { - int32 chance = (*i)->GetModifier()->m_amount; - if ( roll_chance_i(chance) ) - { - int32 mana = spellInfo->manaCost; - if ( Player* modOwner = m_caster->GetSpellModOwner() ) - modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_COST, mana); - mana = int32(mana* 0.8f); - m_caster->CastCustomSpell(m_caster,31930,&mana,NULL,NULL,true,NULL,*i); - } - break; - } - } + // triggered spells are 28703 to 28707 + // Note: some sources say, that there was the possibility of + // receiving a debuff. However, this seems to be removed by a patch. + const uint32 spellid = 28703; + // don't overwrite an existing aura + for(uint8 i=0; i<5; i++) + if(unitTarget->HasAura(spellid+i, 0)) + return; + unitTarget->CastSpell(unitTarget, spellid+urand(0, 4), true); break; } - m_caster->CastSpell(unitTarget,spellId2,true); - return; + // Nightmare Vine + case 28720: + { + if(!unitTarget) + return; + // 25% chance of casting Nightmare Pollen + if(roll_chance_i(75)) + return; + unitTarget->CastSpell(unitTarget, 28721, true); + break; + } } + break; } } @@ -4921,7 +5293,7 @@ void Spell::EffectSanctuary(uint32 /*i*/) std::list<Unit*> targets; Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(unitTarget, unitTarget, World::GetMaxVisibleDistance()); - Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(targets, u_check); + Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(unitTarget, targets, u_check); unitTarget->VisitNearbyObject(World::GetMaxVisibleDistance(), searcher); for(std::list<Unit*>::iterator iter = targets.begin(); iter != targets.end(); ++iter) { @@ -4941,7 +5313,7 @@ void Spell::EffectSanctuary(uint32 /*i*/) unitTarget->CombatStop(); unitTarget->getHostilRefManager().deleteReferences(); // stop all fighting // Vanish allows to remove all threat and cast regular stealth so other spells can be used - if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_VANISH)) + if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags[0] & SPELLFAMILYFLAG_ROGUE_VANISH)) { ((Player *)m_caster)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT); } @@ -4976,6 +5348,7 @@ void Spell::EffectDuel(uint32 i) // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities) // Don't have to check the target's map since you cannot challenge someone across maps if(caster->GetMap()->Instanceable()) + //if( mapid != 0 && mapid != 1 && mapid != 530 && mapid != 571 && mapid != 609) { SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here return; @@ -5001,7 +5374,8 @@ void Spell::EffectDuel(uint32 i) uint32 gameobject_id = m_spellInfo->EffectMiscValue[i]; Map *map = m_caster->GetMap(); - if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map, + if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, + map, m_caster->GetPhaseMask(), m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2 , m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2 , m_caster->GetPositionZ(), @@ -5014,7 +5388,7 @@ void Spell::EffectDuel(uint32 i) pGameObj->SetUInt32Value(GAMEOBJECT_FACTION, m_caster->getFaction() ); pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()+1 ); int32 duration = GetSpellDuration(m_spellInfo); - pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0); + pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0); pGameObj->SetSpellId(m_spellInfo->Id); m_caster->AddGameObject(pGameObj); @@ -5091,7 +5465,7 @@ void Spell::EffectSummonPlayer(uint32 /*i*/) WorldPacket data(SMSG_SUMMON_REQUEST, 8+4+4); data << uint64(m_caster->GetGUID()); // summoner guid data << uint32(m_caster->GetZoneId()); // summoner zone - data << uint32(MAX_PLAYER_SUMMON_DELAY*1000); // auto decline after msecs + data << uint32(MAX_PLAYER_SUMMON_DELAY*IN_MILISECONDS); // auto decline after msecs ((Player*)unitTarget)->GetSession()->SendPacket(&data); } @@ -5114,6 +5488,43 @@ void Spell::EffectActivateObject(uint32 effect_idx) sWorld.ScriptCommandStart(activateCommand, delay_secs, m_caster, gameObjTarget); } +void Spell::EffectApplyGlyph(uint32 i) +{ + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + Player *player = (Player*)m_caster; + + // remove old glyph + if(uint32 oldglyph = player->GetGlyph(m_glyphIndex)) + { + if(GlyphPropertiesEntry const *old_gp = sGlyphPropertiesStore.LookupEntry(oldglyph)) + { + player->RemoveAurasDueToSpell(old_gp->SpellId); + player->SetGlyph(m_glyphIndex, 0); + } + } + + // apply new one + if(uint32 glyph = m_spellInfo->EffectMiscValue[i]) + { + if(GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyph)) + { + if(GlyphSlotEntry const *gs = sGlyphSlotStore.LookupEntry(player->GetGlyphSlot(m_glyphIndex))) + { + if(gp->TypeFlags != gs->TypeFlags) + { + SendCastResult(SPELL_FAILED_INVALID_GLYPH); + return; // glyph slot missmatch + } + } + + player->CastSpell(m_caster, gp->SpellId, true); + player->SetGlyph(m_glyphIndex, glyph); + } + } +} + void Spell::EffectSummonTotem(uint32 i) { uint8 slot = 0; @@ -5147,7 +5558,8 @@ void Spell::EffectSummonTotem(uint32 i) Totem* pTotem = new Totem; - if(!pTotem->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), m_caster->GetMap(), m_spellInfo->EffectMiscValue[i], team )) + if(!pTotem->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), m_caster->GetMap(), m_caster->GetPhaseMask(), + m_spellInfo->EffectMiscValue[i], team )) { delete pTotem; return; @@ -5182,10 +5594,9 @@ void Spell::EffectSummonTotem(uint32 i) } pTotem->SetUInt32Value(UNIT_CREATED_BY_SPELL,m_spellInfo->Id); - pTotem->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE); - pTotem->ApplySpellImmune(m_spellInfo->Id,IMMUNITY_STATE,SPELL_AURA_MOD_FEAR,true); - pTotem->ApplySpellImmune(m_spellInfo->Id,IMMUNITY_STATE,SPELL_AURA_TRANSFORM,true); + if(m_caster->GetTypeId() == TYPEID_PLAYER) + pTotem->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE); pTotem->Summon(m_caster); @@ -5237,7 +5648,7 @@ void Spell::EffectEnchantHeldItem(uint32 i) return; // Apply the temporary enchantment - item->SetEnchantment(slot, enchant_id, duration*1000, 0); + item->SetEnchantment(slot, enchant_id, duration*IN_MILISECONDS, 0); item_owner->ApplyEnchantment(item,slot,true); } } @@ -5280,7 +5691,8 @@ void Spell::EffectFeedPet(uint32 i) Player *_player = (Player*)m_caster; - if(!itemTarget) + Item* foodItem = m_targets.getItemTarget(); + if(!foodItem) return; Pet *pet = _player->GetPet(); @@ -5290,15 +5702,15 @@ void Spell::EffectFeedPet(uint32 i) if(!pet->isAlive()) return; - int32 benefit = pet->GetCurrentFoodBenefitLevel(itemTarget->GetProto()->ItemLevel); + int32 benefit = pet->GetCurrentFoodBenefitLevel(foodItem->GetProto()->ItemLevel); if(benefit <= 0) return; uint32 count = 1; - _player->DestroyItemCount(itemTarget,count,true); + _player->DestroyItemCount(foodItem,count,true); // TODO: fix crash when a spell has two effects, both pointed at the same item target - m_caster->CastCustomSpell(m_caster,m_spellInfo->EffectTriggerSpell[i],&benefit,NULL,NULL,true); + m_caster->CastCustomSpell(pet,m_spellInfo->EffectTriggerSpell[i],&benefit,NULL,NULL,true); } void Spell::EffectDismissPet(uint32 /*i*/) @@ -5358,7 +5770,8 @@ void Spell::EffectSummonObject(uint32 i) m_caster->GetClosePoint(x,y,z,DEFAULT_WORLD_OBJECT_SIZE); Map *map = m_caster->GetMap(); - if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), go_id, map, x, y, z, m_caster->GetOrientation(), 0, 0, rot2, rot3, 0, 1)) + if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), go_id, map, + m_caster->GetPhaseMask(), x, y, z, m_caster->GetOrientation(), 0, 0, rot2, rot3, 0, 1)) { delete pGameObj; return; @@ -5366,7 +5779,7 @@ void Spell::EffectSummonObject(uint32 i) //pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL,m_caster->getLevel()); int32 duration = GetSpellDuration(m_spellInfo); - pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0); + pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0); pGameObj->SetSpellId(m_spellInfo->Id); m_caster->AddGameObject(pGameObj); @@ -5437,18 +5850,14 @@ void Spell::EffectAddExtraAttacks(uint32 /*i*/) void Spell::EffectParry(uint32 /*i*/) { - if (unitTarget->GetTypeId() == TYPEID_PLAYER) - { + if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER) ((Player*)unitTarget)->SetCanParry(true); - } } void Spell::EffectBlock(uint32 /*i*/) { - if (unitTarget->GetTypeId() != TYPEID_PLAYER) - return; - - ((Player*)unitTarget)->SetCanBlock(true); + if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER) + ((Player*)unitTarget)->SetCanBlock(true); } void Spell::EffectMomentMove(uint32 i) @@ -5460,7 +5869,7 @@ void Spell::EffectMomentMove(uint32 i) return; uint32 mapid = m_caster->GetMapId(); - float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); + float dis = m_caster->GetSpellRadiusForTarget(unitTarget, sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); // src point float *fx = new float[11], *fy = new float[11], *fz = new float[11]; @@ -5658,8 +6067,8 @@ void Spell::EffectSummonCritter(uint32 i) Map *map = m_caster->GetMap(); uint32 pet_number = objmgr.GeneratePetNumber(); - if(!critter->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), - map, pet_entry, pet_number)) + if(!critter->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(), + pet_entry, pet_number)) { sLog.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo->Id, pet_entry); delete critter; @@ -5748,14 +6157,16 @@ void Spell::EffectKnockBack(uint32 i) vcos = dx / dist; vsin = dy / dist; } + float speedxy = float(m_spellInfo->EffectMiscValue[i])/10; + float speedz = float(damage/-10); WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4)); data.append(unitTarget->GetPackGUID()); data << uint32(0); // Sequence data << float(vcos); // x direction data << float(vsin); // y direction - data << float(m_spellInfo->EffectMiscValue[i])/10; // Horizontal speed - data << float(damage/-10); // Z Movement speed (vertical) + data << float(speedxy); // Horizontal speed + data << float(speedz); // Z Movement speed (vertical) ((Player*)unitTarget)->GetSession()->SendPacket(&data); } @@ -5778,17 +6189,26 @@ void Spell::EffectSendTaxi(uint32 i) uint32 mountid = 0; switch(m_spellInfo->Id) { - case 31606: //Stormcrow Amulet + case 31606: //Stormcrow Amulet mountid = 17447; break; - case 45071: //Quest - Sunwell Daily - Dead Scar Bombing Run - case 45113: //Quest - Sunwell Daily - Ship Bombing Run - case 45353: //Quest - Sunwell Daily - Ship Bombing Run Return + case 45071: //Quest - Sunwell Daily - Dead Scar Bombing Run + case 45113: //Quest - Sunwell Daily - Ship Bombing Run + case 45353: //Quest - Sunwell Daily - Ship Bombing Run Return mountid = 22840; break; - case 34905: //Stealth Flight + case 34905: //Stealth Flight mountid = 6851; break; + case 45883: //Amber Ledge to Beryl Point + mountid = 23524; + break; + case 46064: //Amber Ledge to Coldarra + mountid = 6371; + break; + case 53335: //Stormwind Harbor Flight - Peaceful + mountid = 6852; + break; case 41533: //Fly of the Netherwing case 41540: //Fly of the Netherwing mountid = 23468; @@ -5830,22 +6250,22 @@ void Spell::EffectDispelMechanic(uint32 i) uint32 mechanic = m_spellInfo->EffectMiscValue[i]; + std::deque <Aura *> dispel_list; + Unit::AuraMap& Auras = unitTarget->GetAuras(); - for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next) + for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter++) { - next = iter; - ++next; - SpellEntry const *spell = sSpellStore.LookupEntry(iter->second->GetSpellProto()->Id); + if (!iter->second->GetDispelChance(this)) + continue; + SpellEntry const *spell = iter->second->GetSpellProto(); if(spell->Mechanic == mechanic || spell->EffectMechanic[iter->second->GetEffIndex()] == mechanic) - { - unitTarget->RemoveAurasDueToSpell(spell->Id); - if(Auras.empty()) - break; - else - next = Auras.begin(); - } + dispel_list.push_back(iter->second); + } + for(;!dispel_list.empty();) + { + unitTarget->RemoveAurasDueToSpell(dispel_list.front()->GetId()); + dispel_list.pop_front(); } - return; } void Spell::EffectSummonDeadPet(uint32 /*i*/) @@ -5975,13 +6395,14 @@ void Spell::EffectTransmitted(uint32 effIndex) //FIXME: this can be better check for most objects but still hack else if(m_spellInfo->EffectRadiusIndex[effIndex] && m_spellInfo->speed==0) { - float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[effIndex])); + float dis = GetSpellRadiusForFriend(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[effIndex])); m_caster->GetClosePoint(fx,fy,fz,DEFAULT_WORLD_OBJECT_SIZE, dis); } else { - float min_dis = GetSpellMinRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex)); - float max_dis = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex)); + //GO is always friendly to it's creator, get range for friends + float min_dis = GetSpellMinRangeForFriend(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex)); + float max_dis = GetSpellMaxRangeForFriend(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex)); float dis = rand_norm() * (max_dis - min_dis) + min_dis; m_caster->GetClosePoint(fx,fy,fz,DEFAULT_WORLD_OBJECT_SIZE, dis); @@ -6010,7 +6431,7 @@ void Spell::EffectTransmitted(uint32 effIndex) GameObject* pGameObj = new GameObject; if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), name_id, cMap, - fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1)) + m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1)) { delete pGameObj; return; @@ -6024,9 +6445,9 @@ void Spell::EffectTransmitted(uint32 effIndex) { m_caster->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT,pGameObj->GetGUID()); // Orientation3 - pGameObj->SetFloatValue(GAMEOBJECT_ROTATION + 2, 0.88431775569915771 ); + pGameObj->SetFloatValue(GAMEOBJECT_PARENTROTATION + 2, 0.88431775569915771 ); // Orientation4 - pGameObj->SetFloatValue(GAMEOBJECT_ROTATION + 3, -0.4668855369091033 ); + pGameObj->SetFloatValue(GAMEOBJECT_PARENTROTATION + 3, -0.4668855369091033 ); m_caster->AddGameObject(pGameObj); // will removed at spell cancel // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo)) @@ -6040,7 +6461,7 @@ void Spell::EffectTransmitted(uint32 effIndex) case 3: lastSec = 17; break; } - duration = duration - lastSec*1000 + FISHING_BOBBER_READY_TIME*1000; + duration = duration - lastSec*IN_MILISECONDS + FISHING_BOBBER_READY_TIME*IN_MILISECONDS; break; } case GAMEOBJECT_TYPE_SUMMONING_RITUAL: @@ -6060,7 +6481,7 @@ void Spell::EffectTransmitted(uint32 effIndex) } } - pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0); + pGameObj->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0); pGameObj->SetOwnerGUID(m_caster->GetGUID() ); @@ -6081,9 +6502,9 @@ void Spell::EffectTransmitted(uint32 effIndex) { GameObject* linkedGO = new GameObject; if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, cMap, - fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1)) + m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1)) { - linkedGO->SetRespawnTime(duration > 0 ? duration/1000 : 0); + linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0); //linkedGO->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() ); linkedGO->SetSpellId(m_spellInfo->Id); linkedGO->SetOwnerGUID(m_caster->GetGUID() ); @@ -6121,6 +6542,28 @@ void Spell::EffectProspecting(uint32 /*i*/) ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_PROSPECTING); } +void Spell::EffectMilling(uint32 /*i*/) +{ + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + Player* p_caster = (Player*)m_caster; + if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_HERBS)) + return; + + if(itemTarget->GetCount() < 5) + return; + + if( sWorld.getConfig(CONFIG_SKILL_MILLING)) + { + uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_INSCRIPTION); + uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank; + p_caster->UpdateGatherSkill(SKILL_INSCRIPTION, SkillValue, reqSkillValue); + } + + ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_MILLING); +} + void Spell::EffectSkill(uint32 /*i*/) { sLog.outDebug("WORLD: SkillEFFECT"); @@ -6268,9 +6711,42 @@ void Spell::EffectQuestFail(uint32 i) ((Player*)unitTarget)->FailQuest(m_spellInfo->EffectMiscValue[i]); } +void Spell::EffectActivateRune(uint32 eff_idx) +{ + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + Player *plr = (Player*)m_caster; + + if(plr->getClass() != CLASS_DEATH_KNIGHT) + return; + + for(uint32 j = 0; j < MAX_RUNES; ++j) + { + if(plr->GetRuneCooldown(j) && plr->GetCurrentRune(j) == m_spellInfo->EffectMiscValue[eff_idx]) + { + plr->SetRuneCooldown(j, 0); + } + } +} + +void Spell::EffectTitanGrip(uint32 /*eff_idx*/) +{ + if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER) + ((Player*)unitTarget)->SetCanTitanGrip(true); +} + void Spell::EffectRedirectThreat(uint32 /*i*/) { if(unitTarget) m_caster->SetReducedThreatPercent((uint32)damage, unitTarget->GetGUID()); } +void Spell::EffectRenamePet(uint32 /*eff_idx*/) +{ + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || + !((Creature*)unitTarget)->isPet() || ((Pet*)unitTarget)->getPetType() != HUNTER_PET) + return; + + unitTarget->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_ALLOWED); +} |