diff options
Diffstat (limited to 'src/game/SpellEffects.cpp')
-rw-r--r-- | src/game/SpellEffects.cpp | 4492 |
1 files changed, 2498 insertions, 1994 deletions
diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 885adeccf31..d5ee8a0b731 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 @@ -19,10 +19,8 @@ */ #include "Common.h" -#include "SharedDefines.h" #include "Database/DatabaseEnv.h" #include "WorldPacket.h" -#include "WorldSession.h" #include "Opcodes.h" #include "Log.h" #include "UpdateMask.h" @@ -32,7 +30,6 @@ #include "Player.h" #include "SkillExtraItems.h" #include "Unit.h" -#include "CreatureAI.h" #include "Spell.h" #include "DynamicObject.h" #include "SpellAuras.h" @@ -47,6 +44,7 @@ #include "Creature.h" #include "Totem.h" #include "CreatureAI.h" +#include "BattleGroundMgr.h" #include "BattleGround.h" #include "BattleGroundEY.h" #include "BattleGroundWS.h" @@ -60,6 +58,9 @@ #include "CellImpl.h" #include "GridNotifiers.h" #include "GridNotifiersImpl.h" +#include "SkillDiscovery.h" +#include "Formulas.h" +#include "Vehicle.h" pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= { @@ -104,8 +105,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::EffectJump, // 41 SPELL_EFFECT_JUMP + &Spell::EffectJump, // 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 @@ -122,22 +123,22 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectSummonPet, // 56 SPELL_EFFECT_SUMMON_PET &Spell::EffectLearnPetSpell, // 57 SPELL_EFFECT_LEARN_PET_SPELL &Spell::EffectWeaponDmg, // 58 SPELL_EFFECT_WEAPON_DAMAGE - &Spell::EffectOpenSecretSafe, // 59 SPELL_EFFECT_OPEN_LOCK_ITEM + &Spell::EffectCreateRandomItem, // 59 SPELL_EFFECT_CREATE_RANDOM_ITEM create item base at spell specific loot &Spell::EffectProficiency, // 60 SPELL_EFFECT_PROFICIENCY &Spell::EffectSendEvent, // 61 SPELL_EFFECT_SEND_EVENT &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 +151,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::EffectWMODamage, // 87 SPELL_EFFECT_WMO_DAMAGE + &Spell::EffectWMORepair, // 88 SPELL_EFFECT_WMO_REPAIR + &Spell::EffectUnused, // 89 SPELL_EFFECT_WMO_CHANGE + &Spell::EffectKillCredit, // 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::EffectCharge, // 96 SPELL_EFFECT_CHARGE + &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 +176,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 +196,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::EffectEnergizePct, //137 SPELL_EFFECT_ENERGIZE_PCT + &Spell::EffectJump2, //138 SPELL_EFFECT_138 Leap + &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::EffectPlayerPull, //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 +218,15 @@ 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 item or create item template and replace by some randon spell loot item + &Spell::EffectMilling, //158 SPELL_EFFECT_MILLING milling + &Spell::EffectRenamePet, //159 SPELL_EFFECT_ALLOW_RENAME_PET allow rename pet once again + &Spell::EffectNULL, //160 SPELL_EFFECT_160 unused + &Spell::EffectNULL, //161 SPELL_EFFECT_TALENT_SPEC_COUNT second talent spec (learn/revert) + &Spell::EffectNULL, //162 SPELL_EFFECT_TALENT_SPEC_SELECT activate primary/secondary spec }; void Spell::EffectNULL(uint32 /*i*/) @@ -269,18 +279,17 @@ void Spell::EffectInstaKill(uint32 /*i*/) case 1863: spellID=18791; break; //succubus case 17252: spellID=35701; break; //fellguard default: - sLog.outError("EffectInstaKill: Unhandled creature entry (%u) case.",entry); + sLog.outError("EffectInstaKill: Unhandled creature entry (%u) case.", entry); return; } - m_caster->CastSpell(m_caster,spellID,true); + m_caster->CastSpell(m_caster, spellID, true); } - if(m_caster==unitTarget) // prevent interrupt message + if(m_caster == unitTarget) // prevent interrupt message finish(); - uint32 health = unitTarget->GetHealth(); - m_caster->DealDamage(unitTarget, health, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + m_caster->DealDamage(unitTarget, unitTarget->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); } void Spell::EffectEnvirinmentalDMG(uint32 i) @@ -291,13 +300,13 @@ void Spell::EffectEnvirinmentalDMG(uint32 i) // Note: this hack with damage replace required until GO casting not implemented // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support // 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]; + damage = m_spellInfo->CalculateSimpleValue(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) - ((Player*)m_caster)->EnvironmentalDamage(m_caster->GetGUID(),DAMAGE_FIRE,damage); + ((Player*)m_caster)->EnvironmentalDamage(DAMAGE_FIRE, damage); } void Spell::EffectSchoolDMG(uint32 effect_idx) @@ -315,7 +324,7 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) //Gore if(m_spellInfo->SpellIconID == 2269 ) { - damage+= (uint32)unitTarget->GetMap()->rand32()%2 ? damage : 0; + damage += (rand()%2 ? damage : 0); } // Meteor like spells (divided damage to targets) @@ -331,14 +340,48 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) switch(m_spellInfo->Id) // better way to check unknown { - case 35354: //Hand of Death - { - if(unitTarget && unitTarget->HasAura(38528,0)) //Protection of Elune + // Positive/Negative Charge + case 28062: + case 28085: + case 39090: + case 39093: + if(!m_triggeredByAuraSpell) + break; + if(unitTarget == m_caster) { - damage = 0; + uint8 count = 0; + for(std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) + if(ihit->targetGUID != m_caster->GetGUID()) + if(Player *target = ObjectAccessor::FindPlayer(ihit->targetGUID)) + if(target->HasAura(m_triggeredByAuraSpell->Id)) + ++count; + if(count) + { + uint32 spellId; + switch(m_spellInfo->Id) + { + case 28062: spellId = 29659; break; + case 28085: spellId = 29660; break; + case 39090: spellId = 39089; break; + case 39093: spellId = 39092; break; + } + Aura *aur = m_caster->GetAura(spellId); + if(!aur) + { + m_caster->CastSpell(m_caster, spellId, true); + aur = m_caster->GetAura(spellId); + } + if(aur) + aur->SetStackAmount(count); + } } + else if(unitTarget->HasAura(m_triggeredByAuraSpell->Id)) + damage = 0; + break; + // Consumption + case 28865: + damage = (m_caster->GetMap()->IsHeroic() ? 4250 : 2750); break; - } // percent from health with min case 25599: // Thundercrash { @@ -347,6 +390,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 +412,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)); @@ -376,121 +426,122 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) break; } - case SPELLFAMILY_MAGE: - { - // Arcane Blast - if(m_spellInfo->SpellFamilyFlags & 0x20000000LL) - { - m_caster->CastSpell(m_caster,36032,true); - } - break; - } 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 && m_spellInfo->Category==1209) 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); + if(unitTarget->HasAuraState(AURA_STATE_IMMOLATE, m_spellInfo, m_caster)) + damage += int32(damage*0.25f); } - - // Conflagrate - consumes immolate - if (m_spellInfo->TargetAuraState == AURA_STATE_IMMOLATE) + // Conflagrate - consumes immolate or shadowflame + else if (m_spellInfo->TargetAuraState == AURA_STATE_IMMOLATE) { // for caster applied auras only - Unit::AuraList const &mPeriodic = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); - for(Unit::AuraList::const_iterator i = mPeriodic.begin(); i != mPeriodic.end(); ++i) + Unit::AuraEffectList const &mPeriodic = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); + for(Unit::AuraEffectList::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)->GetSpellProto()->SpellFamilyFlags[2] & 2) && (*i)->GetCasterGUID()==m_caster->GetGUID() ) { - unitTarget->RemoveAurasByCasterSpell((*i)->GetId(), m_caster->GetGUID()); + uint32 pdamage = (*i)->GetAmount() > 0 ? (*i)->GetAmount() : 0; + damage += pdamage * 4; // 4 ticks of 3 seconds = 12 secs + //damage = m_caster->SpellDamageBonus(unitTarget, (*i)->GetSpellProto(), damage, DOT, (*i)->GetParentAura()->GetStackAmount()); + // Glyph of Conflagrate + if (!m_caster->HasAura(56235)) + unitTarget->RemoveAurasDueToSpell((*i)->GetId(), m_caster->GetGUID()); break; } } } + // Shadow Bite + else if (m_spellInfo->SpellFamilyFlags[1] & 0x400000) + { + if (m_caster->GetTypeId() == TYPEID_UNIT && ((Creature *)m_caster)->isPet()) + { + // Get DoTs on target by owner (5% increase by dot) + damage += 5 * unitTarget->GetDoTsByCaster(m_caster->GetOwnerGUID()) / 100; + } + } + 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]; - damage += int32(m_caster->GetPower(POWER_ENERGY) * multiple); - m_caster->SetPower(POWER_ENERGY,0); + // 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]; + int32 energy = -(m_caster->ModifyPower(POWER_ENERGY, -30)); + damage += int32(energy * multiple); + damage += int32(((Player*)m_caster)->GetComboPoints() * ap * 7 / 100); } // 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) + Unit::AuraEffectList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraEffectList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i) + if((*i)->GetSpellProto()->SpellFamilyFlags[1] & 0x00000440 && (*i)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_DRUID) { - damage = int32(damage*(100.0f+(*i)->GetModifier()->m_amount)/100.0f); + damage = int32(damage*(100.0f+(*i)->GetAmount())/100.0f); break; } } @@ -499,78 +550,97 @@ 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 - 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() ) + Aura *poison = 0; + // Lookup for Deadly poison (only attacker applied) + Unit::AuraEffectList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); + for(Unit::AuraEffectList::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)->GetParentAura(); + 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->RemoveAuraFromStack(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.21f); + } + // 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 = m_caster->GetMap()->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); + 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.1f); bool found = false; // check dazed affect - Unit::AuraList const& decSpeedList = unitTarget->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED); - for(Unit::AuraList::const_iterator iter = decSpeedList.begin(); iter != decSpeedList.end(); ++iter) + Unit::AuraEffectList const& decSpeedList = unitTarget->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED); + for(Unit::AuraEffectList::const_iterator iter = decSpeedList.begin(); iter != decSpeedList.end(); ++iter) { if((*iter)->GetSpellProto()->SpellIconID==15 && (*iter)->GetSpellProto()->Dispel==0) { @@ -583,28 +653,27 @@ 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) - { - 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; + // Hammer of the Righteous + if(m_spellInfo->SpellFamilyFlags[1]&0x00040000) + { + // Add main hand dps * effect[2] amount + float average = (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(average * IN_MILISECONDS) / m_caster->GetAttackTime(BASE_ATTACK); + } + // Shield of Righteousness + else if(m_spellInfo->SpellFamilyFlags[1]&0x00100000) + { + damage+=int32(m_caster->GetShieldBlockValue()); } break; } @@ -624,6 +693,8 @@ void Spell::EffectDummy(uint32 i) uint32 spell_id = 0; int32 bp = 0; + bool triggered = true; + SpellCastTargets targets; // selection by spell family switch(m_spellInfo->SpellFamilyName) @@ -664,9 +735,9 @@ 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)) + creatureTarget->GetOrientation(), 0, 0, 0, 0, 100, GO_STATE_READY)) { delete pGameObj; return; @@ -708,7 +779,7 @@ void Spell::EffectDummy(uint32 i) return; uint32 spell_id = 0; - switch(m_caster->GetMap()->urand(1,5)) + switch(urand(1,5)) { case 1: spell_id = 8064; break; // Sleepy case 2: spell_id = 8065; break; // Invigorate @@ -716,7 +787,7 @@ void Spell::EffectDummy(uint32 i) case 4: spell_id = 8067; break; // Party Time! case 5: spell_id = 8068; break; // Healthy Spirit } - m_caster->CastSpell(m_caster,spell_id,true,NULL); + m_caster->CastSpell(m_caster, spell_id, true, NULL); return; } case 8213: // Savory Deviate Delight @@ -725,7 +796,7 @@ void Spell::EffectDummy(uint32 i) return; uint32 spell_id = 0; - switch(m_caster->GetMap()->urand(1,2)) + switch(urand(1,2)) { // Flip Out - ninja case 1: spell_id = (m_caster->getGender() == GENDER_MALE ? 8219 : 8220); break; @@ -738,7 +809,7 @@ void Spell::EffectDummy(uint32 i) case 8593: // Symbol of life (restore creature to life) case 31225: // Shimmering Vessel (restore creature to life) { - if(!unitTarget || unitTarget->GetTypeId()!=TYPEID_UNIT) + if(!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT) return; ((Creature*)unitTarget)->setDeathState(JUST_ALIVED); return; @@ -760,24 +831,27 @@ void Spell::EffectDummy(uint32 i) switch (m_spellInfo->Id) { - case 12850: damage *= 0.2f; break; - case 12162: damage *= 0.4f; break; - case 12868: damage *= 0.6f; break; + case 12162: damage *= 0.16f; break; // Rank 1 + case 12850: damage *= 0.32f; break; // Rank 2 + case 12868: damage *= 0.48f; break; // Rank 3 default: sLog.outError("Spell::EffectDummy: Spell %u not handled in DW",m_spellInfo->Id); return; }; - int32 deepWoundsDotBasePoints0 = int32(damage / 4); + // get remaining damage of old Deep Wound aura + AuraEffect* deepWound = unitTarget->GetAuraEffect(12721, 0); + if(deepWound) + { + int32 remainingTicks = deepWound->GetParentAura()->GetAuraDuration() / deepWound->GetAuraAmplitude(); + damage += remainingTicks * deepWound->GetAmount(); + } + + // 1 tick/sec * 6 sec = 6 ticks + int32 deepWoundsDotBasePoints0 = int32(damage / 6); 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) @@ -785,7 +859,7 @@ void Spell::EffectDummy(uint32 i) uint32 spell_id = 0; - uint32 roll = m_caster->GetMap()->urand(0, 99); + uint32 roll = urand(0, 99); if(roll < 2) // 2% for 30 sec self root (off-like chance unknown) spell_id = 16566; @@ -814,30 +888,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 { @@ -845,25 +895,24 @@ void Spell::EffectDummy(uint32 i) return; Creature* creatureTarget = (Creature*)unitTarget; - creatureTarget->setDeathState(JUST_DIED); - creatureTarget->RemoveCorpse(); - creatureTarget->SetHealth(0); // just for nice GM-mode view + + creatureTarget->ForcedDespawn(); return; } case 16589: // Noggenfogger Elixir { - if(m_caster->GetTypeId()!=TYPEID_PLAYER) + if(m_caster->GetTypeId() != TYPEID_PLAYER) return; uint32 spell_id = 0; - switch(m_caster->GetMap()->urand(1,3)) + switch(urand(1, 3)) { case 1: spell_id = 16595; break; case 2: spell_id = 16593; break; default:spell_id = 16591; break; } - m_caster->CastSpell(m_caster,spell_id,true,NULL); + m_caster->CastSpell(m_caster, spell_id, true, NULL); return; } case 17251: // Spirit Healer Res @@ -874,7 +923,7 @@ void Spell::EffectDummy(uint32 i) if(m_originalCaster->GetTypeId() == TYPEID_PLAYER) { WorldPacket data(SMSG_SPIRIT_HEALER_CONFIRM, 8); - data << unitTarget->GetGUID(); + data << uint64(unitTarget->GetGUID()); ((Player*)m_originalCaster)->GetSession()->SendPacket( &data ); } return; @@ -886,12 +935,12 @@ void Spell::EffectDummy(uint32 i) uint32 spell_id = roll_chance_i(50) ? 17269 : 17270; - m_caster->CastSpell(m_caster,spell_id,true,NULL); + m_caster->CastSpell(m_caster, spell_id, true, NULL); return; } case 20577: // Cannibalize if (unitTarget) - m_caster->CastSpell(m_caster,20578,false,NULL); + m_caster->CastSpell(m_caster, 20578, false, NULL); return; case 23019: // Crystal Prison Dummy DND { @@ -902,57 +951,56 @@ void Spell::EffectDummy(uint32 i) if(creatureTarget->isPet()) return; - 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"); + sLog.outDebug("SummonGameObject at SpellEfects.cpp EffectDummy for Spell 23019"); + + creatureTarget->ForcedDespawn(); + WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8); data << uint64(Crystal_Prison->GetGUID()); - m_caster->SendMessageToSet(&data,true); + 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); + m_caster->CastSpell(m_caster, 19804, true, m_CastItem); return; case 23075: // Mithril Mechanical Dragonling if (!m_CastItem) return; - m_caster->CastSpell(m_caster,12749,true,m_CastItem); + m_caster->CastSpell(m_caster, 12749, true, m_CastItem); return; case 23076: // Mechanical Dragonling if (!m_CastItem) return; - m_caster->CastSpell(m_caster,4073,true,m_CastItem); + m_caster->CastSpell(m_caster, 4073, true, m_CastItem); return; case 23133: // Gnomish Battle Chicken if (!m_CastItem) return; - m_caster->CastSpell(m_caster,13166,true,m_CastItem); + m_caster->CastSpell(m_caster, 13166, true, m_CastItem); return; case 23448: // Ultrasafe Transporter: Gadgetzan - backfires { - int32 r = m_caster->GetMap()->irand(0, 119); + int32 r = irand(0, 119); if ( r < 20 ) // 1/6 polymorph - m_caster->CastSpell(m_caster,23444,true); + m_caster->CastSpell(m_caster, 23444, true); else if ( r < 100 ) // 4/6 evil twin - m_caster->CastSpell(m_caster,23445,true); + m_caster->CastSpell(m_caster, 23445, true); else // 1/6 miss the target - m_caster->CastSpell(m_caster,36902,true); + m_caster->CastSpell(m_caster, 36902, true); return; } case 23453: // Ultrasafe Transporter: Gadgetzan if ( roll_chance_i(50) ) // success - m_caster->CastSpell(m_caster,23441,true); + m_caster->CastSpell(m_caster, 23441, true); else // failure - m_caster->CastSpell(m_caster,23446,true); + m_caster->CastSpell(m_caster, 23446, true); return; case 23645: // Hourglass Sand m_caster->RemoveAurasDueToSpell(23170); return; case 23725: // Gift of Life (warrior bwl trinket) - m_caster->CastSpell(m_caster,23782,true); - m_caster->CastSpell(m_caster,23783,true); + m_caster->CastSpell(m_caster, 23782, true); + m_caster->CastSpell(m_caster, 23783, true); return; case 25860: // Reindeer Transformation { @@ -962,7 +1010,7 @@ void Spell::EffectDummy(uint32 i) float flyspeed = m_caster->GetSpeedRate(MOVE_FLIGHT); float speed = m_caster->GetSpeedRate(MOVE_RUN); - m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); + m_caster->RemoveAurasByType(SPELL_AURA_MOUNTED); //5 different spells used depending on mounted speed and if mount can fly or not if (flyspeed >= 4.1f) @@ -982,21 +1030,20 @@ void Spell::EffectDummy(uint32 i) // return; -- implemented at client side case 28006: // Arcane Cloaking { - if( unitTarget->GetTypeId() == TYPEID_PLAYER ) - m_caster->CastSpell(unitTarget,29294,true); - return; - } - case 28730: // Arcane Torrent (Mana) - { - Aura * dummy = m_caster->GetDummyAura(28734); - if (dummy) - { - int32 bp = damage * dummy->GetStackAmount(); - m_caster->CastCustomSpell(m_caster, 28733, &bp, NULL, NULL, true); - m_caster->RemoveAurasDueToSpell(28734); - } + if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER ) + m_caster->CastSpell(unitTarget, 29294, true); return; } + // Polarity Shift + case 28089: + if(unitTarget) + unitTarget->CastSpell(unitTarget, roll_chance_i(50) ? 28059 : 28084, true, NULL, NULL, m_caster->GetGUID()); + break; + // Polarity Shift + case 39096: + if(unitTarget) + unitTarget->CastSpell(unitTarget, roll_chance_i(50) ? 39088 : 39091, true, NULL, NULL, m_caster->GetGUID()); + break; case 29200: // Purify Helboar Meat { if( m_caster->GetTypeId() != TYPEID_PLAYER ) @@ -1026,6 +1073,13 @@ void Spell::EffectDummy(uint32 i) else // backfire 20% m_caster->CastSpell(unitTarget, 30504, true, m_CastItem); return; + case 55004: //Nitro Boosts + if(!m_CastItem) return; + if(roll_chance_i(95)) //success + m_caster->CastSpell(m_caster, 54861, true, m_CastItem); + else //backfire 5% + m_caster->CastSpell(m_caster, 46014, true, m_CastItem); + return; case 33060: // Make a Wish { if(m_caster->GetTypeId()!=TYPEID_PLAYER) @@ -1033,7 +1087,7 @@ void Spell::EffectDummy(uint32 i) uint32 spell_id = 0; - switch(m_caster->GetMap()->urand(1,5)) + switch(urand(1,5)) { case 1: spell_id = 33053; break; case 2: spell_id = 33057; break; @@ -1042,7 +1096,7 @@ void Spell::EffectDummy(uint32 i) case 5: spell_id = 33064; break; } - m_caster->CastSpell(m_caster,spell_id,true,NULL); + m_caster->CastSpell(m_caster, spell_id, true, NULL); return; } case 35745: @@ -1055,7 +1109,7 @@ void Spell::EffectDummy(uint32 i) default: return; } - m_caster->CastSpell(m_caster,spell_id,true); + m_caster->CastSpell(m_caster, spell_id, true); return; } case 37674: // Chaos Blast @@ -1064,14 +1118,14 @@ void Spell::EffectDummy(uint32 i) return; int32 basepoints0 = 100; - m_caster->CastCustomSpell(unitTarget,37675,&basepoints0,NULL,NULL,true); + m_caster->CastCustomSpell(unitTarget, 37675, &basepoints0, NULL, NULL, true); return; } case 40802: // Mingo's Fortune Generator (Mingo's Fortune Giblets) { // selecting one from Bloodstained Fortune item uint32 newitemid; - switch(m_caster->GetMap()->urand(1,20)) + switch(urand(1, 20)) { case 1: newitemid = 32688; break; case 2: newitemid = 32689; break; @@ -1097,7 +1151,7 @@ void Spell::EffectDummy(uint32 i) return; } - DoCreateItem(i,newitemid); + DoCreateItem(i, newitemid); return; } // Demon Broiled Surprise @@ -1118,42 +1172,10 @@ void Spell::EffectDummy(uint32 i) Creature* creatureTarget = (Creature*)unitTarget; - creatureTarget->setDeathState(JUST_DIED); - creatureTarget->RemoveCorpse(); - creatureTarget->SetHealth(0); // just for nice GM-mode view + creatureTarget->ForcedDespawn(); //cast spell Raptor Capture Credit - 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[m_caster->GetMap()->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); - + m_caster->CastSpell(m_caster, 42337, true, NULL); return; } case 34665: //Administer Antidote @@ -1164,7 +1186,7 @@ void Spell::EffectDummy(uint32 i) if(!unitTarget) return; - TemporarySummon* tempSummon = dynamic_cast<TemporarySummon*>(unitTarget); + TempSummon* tempSummon = dynamic_cast<TempSummon*>(unitTarget); if(!tempSummon) return; @@ -1181,7 +1203,7 @@ void Spell::EffectDummy(uint32 i) return; pCreature->SetHealth(health); - ((Player*)m_caster)->KilledMonster(16992,pCreature->GetGUID()); + ((Player*)m_caster)->RewardPlayerAndGroupAtEvent(16992, pCreature); if (pCreature->IsAIEnabled) pCreature->AI()->AttackStart(m_caster); @@ -1232,6 +1254,49 @@ void Spell::EffectDummy(uint32 i) m_caster->CastSpell(m_caster, 30452, true, NULL); return; } + case 51592: // Pickup Primordial Hatchling + { + if(!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT) + return; + + Creature* creatureTarget = (Creature*)unitTarget; + + creatureTarget->ForcedDespawn(); + return; + + } + case 52308: + { + switch(i) + { + case 0: + { + uint32 spellID = m_spellInfo->CalculateSimpleValue(0); + uint32 reqAuraID = m_spellInfo->CalculateSimpleValue(1); + + if (m_caster->HasAuraEffect(reqAuraID,0)) + m_caster->CastSpell(m_caster,spellID,true,NULL); + return; + } + case 1: + return; // additional data for dummy[0] + } + return; + } + case 52759: // Ancestral Awakening + if (!unitTarget) + return; + m_caster->CastCustomSpell(unitTarget, 52752, &damage, NULL, NULL, true); + return; + case 53341: + case 53343: + { + m_caster->CastSpell(m_caster, 54586, true); + return; + } + case 58418: // Portal to Orgrimmar + case 58420: // Portal to Stormwind + return; // implemented in EffectScript[0] } //All IconID Check in there @@ -1253,7 +1318,7 @@ void Spell::EffectDummy(uint32 i) // FIXME: custom spell required this aura state by some unknown reason, we not need remove it anyway m_caster->ModifyAuraState(AURA_STATE_BERSERKING,true); - m_caster->CastCustomSpell(m_caster,26635,&hasteModBasePoints0,&hasteModBasePoints1,&hasteModBasePoints2,true,NULL); + m_caster->CastCustomSpell(m_caster, 26635, &hasteModBasePoints0, &hasteModBasePoints1, &hasteModBasePoints2, true, NULL); return; } } @@ -1281,12 +1346,7 @@ void Spell::EffectDummy(uint32 i) (GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_FROST) && spellInfo->Id != 11958 && GetSpellRecoveryTime(spellInfo) > 0 ) { - ((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); + ((Player*)m_caster)->RemoveSpellCooldown(classspell, true); } } return; @@ -1297,7 +1357,7 @@ void Spell::EffectDummy(uint32 i) { //Polymorph Cast Visual Rank 1 const uint32 spell_list[6] = {32813, 32816, 32817, 32818, 32819, 32820}; - unitTarget->CastSpell( unitTarget, spell_list[m_caster->GetMap()->urand(0, 5)], true); + unitTarget->CastSpell( unitTarget, spell_list[urand(0, 5)], true); } return; } @@ -1305,65 +1365,134 @@ 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); + 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=0; + // Glyph of Execution bonus + if (AuraEffect *aura = m_caster->GetDummyAura(58367)) + rage+=aura->GetAmount(); + spell_id = 20647; - bp = damage+int32(m_caster->GetPower(POWER_RAGE) * m_spellInfo->DmgMultiplier[i]); - m_caster->SetPower(POWER_RAGE,0); + // Sudden death cost modifier + if (Aura * aur = m_caster->GetAura(52437)) + { + rage += m_powerCost; + m_caster->ModifyPower(POWER_RAGE,- m_powerCost); + if (m_caster->GetPower(POWER_RAGE)<100) + m_caster->SetPower(POWER_RAGE,100); + m_caster->RemoveAura(aur); + } + else + { + rage += m_caster->GetPower(POWER_RAGE); + m_caster->SetPower(POWER_RAGE,0); + } + + bp = damage+int32(rage * m_spellInfo->DmgMultiplier[i] + + m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f); break; } - if(m_spellInfo->Id==21977) //Warrior's Wrath + // Concussion Blow + if(m_spellInfo->SpellFamilyFlags[0] & 0x4000000) { - if(!unitTarget) - return; - - m_caster->CastSpell(unitTarget,21887,true); // spell mod + m_damage+= uint32(damage * m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100); 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 = uint32(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(unitTarget && (int32(unitTarget->GetHealth()) > damage)) { // Shouldn't Appear in Combat Log - m_caster->ModifyHealth(-dmg); + unitTarget->ModifyHealth(-damage); - int32 mana = dmg; - - Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY); - for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr) + int32 mana = damage; + // Improved Life Tap mod + Unit::AuraEffectList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraEffectList::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; + mana = ((*itr)->GetAmount() + 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::AuraEffectList const& mod = m_caster->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER); + for(Unit::AuraEffectList::const_iterator itr = mod.begin(); itr != mod.end(); ++itr) + { + if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 1982) + { + manaFeedVal = (*itr)->GetAmount(); + break; + } + } 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); @@ -1371,52 +1500,60 @@ void Spell::EffectDummy(uint32 i) } break; case SPELLFAMILY_PRIEST: - switch(m_spellInfo->Id ) + // Penance + if (m_spellInfo->SpellFamilyFlags[1] & 0x00800000) { - case 28598: // Touch of Weakness triggered spell + if (!unitTarget || !unitTarget->isAlive()) + return; + + int hurt = 0; + int heal = 0; + switch(m_spellInfo->Id) { - if(!unitTarget || !m_triggeredByAuraSpell) + 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; - - uint32 spellid = 0; - switch(m_triggeredByAuraSpell->Id) - { - case 2652: spellid = 2943; break; // Rank 1 - case 19261: spellid = 19249; break; // Rank 2 - case 19262: spellid = 19251; break; // Rank 3 - case 19264: spellid = 19252; break; // Rank 4 - case 19265: spellid = 19253; break; // Rank 5 - case 19266: spellid = 19254; break; // Rank 6 - case 25461: spellid = 25460; break; // Rank 7 - default: - sLog.outError("Spell::EffectDummy: Spell 28598 triggered by unhandled spell %u",m_triggeredByAuraSpell->Id); - return; - } - m_caster->CastSpell(unitTarget, spellid, true, NULL); - return; } + if (m_caster->IsFriendlyTo(unitTarget)) + m_caster->CastSpell(unitTarget, heal, true, 0); + else + m_caster->CastSpell(unitTarget, hurt, true, 0); + return; } break; case SPELLFAMILY_DRUID: - switch(m_spellInfo->Id ) + // Starfall + if (m_spellInfo->SpellFamilyFlags[2] & 0x100) { - case 5420: // Tree of Life passive + //Shapeshifting into an animal form or mounting cancels the effect. + if(m_caster->GetCreatureType() == CREATURE_TYPE_BEAST || m_caster->IsMounted()) { - // 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); + if(m_triggeredByAuraSpell) + m_caster->RemoveAurasDueToSpell(m_triggeredByAuraSpell->Id); return; } + + //Any effect which causes you to lose control of your character will supress the starfall effect. + if(m_caster->hasUnitState(UNIT_STAT_STUNNED | UNIT_STAT_FLEEING | UNIT_STAT_ROOT | UNIT_STAT_CONFUSED)) + return; + + m_caster->CastSpell(unitTarget, damage, true); + return; } break; case SPELLFAMILY_ROGUE: + // Hunger for Blood + if (m_spellInfo->SpellFamilyFlags[1] & 0x1000000) + { + m_caster->CastSpell(m_caster, 63848, true); + break; + } 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) @@ -1452,36 +1589,31 @@ 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()) + if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags[1] & 0x00000240 || spellInfo->SpellFamilyFlags[0] & 0x00000860)) + ((Player*)m_caster)->RemoveSpellCooldown(classspell,true); + } return; - - uint32 spell_id = 0; - switch (m_spellInfo->Id) + } + 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 @@ -1497,14 +1629,7 @@ void Spell::EffectDummy(uint32 i) SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell); if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && spellInfo->Id != 23989 && GetSpellRecoveryTime(spellInfo) > 0 ) - { - ((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); - } + ((Player*)m_caster)->RemoveSpellCooldown(classspell,true); } return; } @@ -1524,6 +1649,13 @@ void Spell::EffectDummy(uint32 i) case SPELLFAMILY_PALADIN: switch(m_spellInfo->SpellIconID) { + // Divine Storm + if (m_spellInfo->SpellFamilyFlags[1] & 0x20000) + { + int32 damage=m_currentBasePoints[0] * damage /100; + m_caster->CastCustomSpell(unitTarget, 54172, &damage , 0, 0, true); + return; + } case 156: // Holy Shock { if(!unitTarget) @@ -1539,6 +1671,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; @@ -1551,43 +1685,38 @@ void Spell::EffectDummy(uint32 i) return; } - case 561: // Judgement of command + } + + switch(m_spellInfo->Id) + { + case 20425: // Judgement of command { if(!unitTarget) return; - uint32 spell_id = m_spellInfo->EffectBasePoints[i]+1;//m_currentBasePoints[i]+1; - SpellEntry const* spell_proto = sSpellStore.LookupEntry(spell_id); + SpellEntry const* spell_proto = sSpellStore.LookupEntry(damage); if(!spell_proto) return; - if( !unitTarget->hasUnitState(UNIT_STAT_STUNNED) && m_caster->GetTypeId()==TYPEID_PLAYER) + if(unitTarget->hasUnitState(UNIT_STAT_STUNNED) && m_caster->GetTypeId()==TYPEID_PLAYER) { - // decreased damage (/2) for non-stunned target. + // always critical for stunned target SpellModifier *mod = new SpellModifier; - mod->op = SPELLMOD_DAMAGE; - mod->value = -50; - mod->type = SPELLMOD_PCT; + mod->op = SPELLMOD_CRITICAL_CHANCE; + mod->value = 100; + mod->type = SPELLMOD_FLAT; 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); - // mod deleted ((Player*)m_caster)->AddSpellMod(mod, false); } else - m_caster->CastSpell(unitTarget,spell_proto,true,NULL); + m_caster->CastSpell(unitTarget, spell_proto, true, NULL); return; } - } - - switch(m_spellInfo->Id) - { case 31789: // Righteous Defense (step 1) { // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target) @@ -1595,17 +1724,8 @@ void Spell::EffectDummy(uint32 i) // non-standard cast requirement check if (!unitTarget || unitTarget->getAttackers().empty()) { - // clear cooldown at fail if(m_caster->GetTypeId()==TYPEID_PLAYER) - { - ((Player*)m_caster)->RemoveSpellCooldown(m_spellInfo->Id); - - WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8)); - data << uint32(m_spellInfo->Id); - data << uint64(m_caster->GetGUID()); - ((Player*)m_caster)->GetSession()->SendPacket(&data); - } - + ((Player*)m_caster)->RemoveSpellCooldown(m_spellInfo->Id,true); SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT); return; } @@ -1647,15 +1767,17 @@ void Spell::EffectDummy(uint32 i) default: return; // ignore for not healing classes } - m_caster->CastSpell(m_caster,spell_id,true); + m_caster->CastSpell(m_caster, spell_id, true); return; } } 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) { @@ -1663,13 +1785,8 @@ 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); + sLog.outError("Spell::EffectDummy: Spell %u not handled in RW", m_spellInfo->Id); return; } @@ -1677,16 +1794,16 @@ void Spell::EffectDummy(uint32 i) if(!spellInfo) { - sLog.outError("WORLD: unknown spell id %i\n", spell_id); + sLog.outError("WORLD: unknown spell id %i", spell_id); return; } if(m_caster->GetTypeId() != TYPEID_PLAYER) return; - for(int i = BASE_ATTACK; i <= OFF_ATTACK; ++i) + for(uint8 j = BASE_ATTACK; j <= OFF_ATTACK; ++j) { - if(Item* item = ((Player*)m_caster)->GetWeaponForAttack(WeaponAttackType(i))) + if(Item* item = ((Player*)m_caster)->GetWeaponForAttack(WeaponAttackType(j))) { if(item->IsFitToSpellRequirements(m_spellInfo)) { @@ -1705,18 +1822,162 @@ void Spell::EffectDummy(uint32 i) } return; } - - if(m_spellInfo->Id == 39610) // Mana-Tide Totem effect + // Cleansing Totem + if(m_spellInfo->SpellFamilyFlags[0] & 0x04000000 && m_spellInfo->SpellIconID==1673) + { + m_caster->CastSpell(unitTarget, 52025, true, 0, 0, m_originalCasterGUID); + return; + } + // 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 (AuraEffect *dummy = owner->GetDummyAura(55441)) + damage+=dummy->GetAmount(); // 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); + 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) + { + if (m_caster->GetAura(SPELL_AURA_DUMMY, SPELLFAMILY_SHAMAN, 0x200000)) + { + m_damage += m_damage * damage / 100; + } + } + 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; + } + // Scourge Strike + if(m_spellInfo->SpellFamilyFlags[1] & 0x8000000) + { + m_damage = float (m_damage) * (float(damage * unitTarget->GetDiseasesByCaster(m_caster->GetGUID()) + 100.0f) / 100.0f); return; } + // Death Coil + if(m_spellInfo->SpellFamilyFlags[0] & 0x002000) + { + if(m_caster->IsFriendlyTo(unitTarget)) + { + if(unitTarget->GetCreatureType() != CREATURE_TYPE_UNDEAD) + return; + + int32 bp = damage * 1.5f; + m_caster->CastCustomSpell(unitTarget, 47633, &bp, NULL, NULL, true); + } + else + { + int32 bp = damage; + m_caster->CastCustomSpell(unitTarget, 47632, &bp, NULL, NULL, true); + } + return; + } + // Hungering Cold + if (m_spellInfo->SpellFamilyFlags[1] & 0x1000) + { + unitTarget->CastSpell(m_caster, 51209, true); + return; + } + // Death Grip + if(m_spellInfo->Id == 49560) + { + if (unitTarget->m_Vehicle) + unitTarget->m_Vehicle->CastSpell(m_caster, damage, true); + else + unitTarget->CastSpell(m_caster, damage, true); + return; + } + else if(m_spellInfo->Id == 46584) // Raise dead + { + if ( m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + // Do we have talent Master of Ghouls? + if(m_caster->HasAura(52143)) + // summon as pet + bp = 52150; + else + // or guardian + bp = 46585; + + if (m_targets.HasDst()) + { + targets.setDestination(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ); + } + else + { + targets.setDestination(m_caster); + // Corpse not found - take reagents ( only not triggered cast can take them) + triggered = false; + } + // Remove cooldown - summon spellls have category + ((Player*)m_caster)->RemoveSpellCooldown(m_spellInfo->Id,true); + spell_id=48289; + } + // Raise dead - take reagents and trigger summon spells + else if (m_spellInfo->Id ==48289) + { + if (m_targets.HasDst()) + targets.setDestination(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ); + spell_id = m_currentBasePoints[0]; + } + // Corpse Explosion + else if(m_spellInfo->SpellIconID == 1737) + { + // Dummy effect 1 is used only for targeting and damage amount + if (i!=0) + return; + int32 bp = 0; + // Living ghoul as a target + if (unitTarget->isAlive()) + { + bp = unitTarget->GetMaxHealth()*0.25f; + } + // Some corpse + else + { + bp = damage; + } + m_caster->CastCustomSpell(unitTarget,m_spellInfo->CalculateSimpleValue(1),&bp,NULL,NULL,true); + // Suicide + unitTarget->CastCustomSpell(unitTarget,43999,&bp,NULL,NULL,true); + // Set corpse look + unitTarget->SetDisplayId(25537+urand(0,3)); + } break; } @@ -1731,19 +1992,27 @@ void Spell::EffectDummy(uint32 i) return; } - Spell* spell = new Spell(m_caster, spellInfo, true, m_originalCasterGUID, NULL, true); - if(bp) spell->m_currentBasePoints[0] = bp; - SpellCastTargets targets; targets.setUnitTarget(unitTarget); + Spell* spell = new Spell(m_caster, spellInfo, triggered, m_originalCasterGUID, NULL, true); + if(bp) spell->m_currentBasePoints[0] = bp; spell->prepare(&targets); } // pet auras - if(PetAura const* petSpell = spellmgr.GetPetAura(m_spellInfo->Id)) + if(PetAura const* petSpell = spellmgr.GetPetAura(m_spellInfo->Id,i)) { m_caster->AddPetAura(petSpell); return; } + + // Script based implementation. Must be used only for not good for implementation in core spell effects + // So called only for not proccessed cases + if(gameObjTarget) + Script->EffectDummyGameObj(m_caster, m_spellInfo->Id, i, gameObjTarget); + else if(unitTarget && unitTarget->GetTypeId()==TYPEID_UNIT) + Script->EffectDummyCreature(m_caster, m_spellInfo->Id, i, (Creature*)unitTarget); + else if(itemTarget) + Script->EffectDummyItem(m_caster, m_spellInfo->Id, i, itemTarget); } void Spell::EffectTriggerSpellWithValue(uint32 i) @@ -1755,7 +2024,7 @@ void Spell::EffectTriggerSpellWithValue(uint32 i) if(!spellInfo) { - sLog.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i\n", m_spellInfo->Id,triggered_spell_id); + sLog.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id); return; } @@ -1781,8 +2050,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()]); } @@ -1802,7 +2071,7 @@ void Spell::EffectForceCast(uint32 i) return; } - unitTarget->CastSpell(unitTarget,spellInfo,true,NULL,NULL,m_originalCasterGUID); + unitTarget->CastSpell(unitTarget, spellInfo, true, NULL, NULL, m_originalCasterGUID); } void Spell::EffectTriggerSpell(uint32 i) @@ -1815,16 +2084,15 @@ void Spell::EffectTriggerSpell(uint32 i) // Vanish case 18461: { - m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT); - m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED); - m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED); + m_caster->RemoveMovementImpairingAuras(); + m_caster->RemoveAurasByType(SPELL_AURA_MOD_STALKED); // if this spell is given to NPC it must handle rest by it's own AI if ( m_caster->GetTypeId() != TYPEID_PLAYER ) return; // get highest rank of the Stealth spell - bool found = false; + uint32 spellId = 0; SpellEntry const *spellInfo; const PlayerSpellMap& sp_list = ((Player*)m_caster)->GetSpellMap(); for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr) @@ -1837,24 +2105,36 @@ 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) { - found=true; + spellId = spellInfo->Id; break; } } // no Stealth spell found - if (!found) + if (!spellId) return; // reset cooldown on it if needed - if(((Player*)m_caster)->HasSpellCooldown(spellInfo->Id)) - ((Player*)m_caster)->RemoveSpellCooldown(spellInfo->Id); + if(((Player*)m_caster)->HasSpellCooldown(spellId)) + ((Player*)m_caster)->RemoveSpellCooldown(spellId); + // Push stealth to list because it must be handled after combat remove m_TriggerSpells.push_back(spellInfo); return; } + // Demonic Empowerment -- succubus + case 54437: + { + unitTarget->RemoveMovementImpairingAuras(); + unitTarget->RemoveAurasByType(SPELL_AURA_MOD_STALKED); + unitTarget->RemoveAurasByType(SPELL_AURA_MOD_STUN); + + // Cast Lesser Invisibility + triggered_spell_id = 7870; + break; + } // just skip case 23770: // Sayge's Dark Fortune of * // not exist, common cooldown can be implemented in scripts if need. @@ -1866,8 +2146,8 @@ void Spell::EffectTriggerSpell(uint32 i) if (!spell) return; - for (int i=0; i < spell->StackAmount; ++i) - m_caster->CastSpell(unitTarget,spell->Id, true, m_CastItem, NULL, m_originalCasterGUID); + for (int j=0; j < spell->StackAmount; ++j) + m_caster->CastSpell(unitTarget, spell->Id, true, m_CastItem, NULL, m_originalCasterGUID); return; } // Mercurial Shield - (need add max stack of 26464 Mercurial Shield) @@ -1877,14 +2157,14 @@ void Spell::EffectTriggerSpell(uint32 i) if (!spell) return; - for (int i=0; i < spell->StackAmount; ++i) - m_caster->CastSpell(unitTarget,spell->Id, true, m_CastItem, NULL, m_originalCasterGUID); + for (int j=0; j < spell->StackAmount; ++j) + m_caster->CastSpell(unitTarget, spell->Id, true, m_CastItem, NULL, m_originalCasterGUID); return; } // Righteous Defense case 31980: { - m_caster->CastSpell(unitTarget, 31790, true,m_CastItem,NULL,m_originalCasterGUID); + m_caster->CastSpell(unitTarget, 31790, true, m_CastItem, NULL, m_originalCasterGUID); return; } // Cloak of Shadows @@ -1892,7 +2172,7 @@ void Spell::EffectTriggerSpell(uint32 i) { uint32 dispelMask = GetDispellMask(DISPEL_ALL); Unit::AuraMap& Auras = m_caster->GetAuras(); - for(Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end(); ++iter) + for(Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end();) { // remove all harmful spells on you... SpellEntry const* spell = iter->second->GetSpellProto(); @@ -1901,16 +2181,17 @@ void Spell::EffectTriggerSpell(uint32 i) // ignore positive and passive auras && !iter->second->IsPositive() && !iter->second->IsPassive()) { - m_caster->RemoveAurasDueToSpell(spell->Id); - iter = Auras.begin(); + m_caster->RemoveAura(iter); } + else + iter++; } return; } // Priest Shadowfiend (34433) need apply mana gain trigger aura on pet case 41967: { - if (Unit *pet = m_caster->GetPet()) + if (Unit *pet = m_caster->GetGuardianPet()) pet->CastSpell(pet, 28305, true); return; } @@ -1925,37 +2206,11 @@ void Spell::EffectTriggerSpell(uint32 i) return; } - // some triggered spells require specific equipment - if(spellInfo->EquippedItemClass >=0 && m_caster->GetTypeId()==TYPEID_PLAYER) - { - // main hand weapon required - if(spellInfo->AttributesEx3 & SPELL_ATTR_EX3_MAIN_HAND) - { - Item* item = ((Player*)m_caster)->GetWeaponForAttack(BASE_ATTACK); - - // skip spell if no weapon in slot or broken - if(!item || item->IsBroken() ) - return; - - // skip spell if weapon not fit to triggered spell - if(!item->IsFitToSpellRequirements(spellInfo)) - return; - } - - // offhand hand weapon required - if(spellInfo->AttributesEx3 & SPELL_ATTR_EX3_REQ_OFFHAND) - { - Item* item = ((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK); - - // skip spell if no weapon in slot or broken - if(!item || item->IsBroken() ) - return; - - // skip spell if weapon not fit to triggered spell - if(!item->IsFitToSpellRequirements(spellInfo)) - return; - } - } + // Remove spell cooldown (not category) if spell triggering spell with cooldown and same category + // Needed by freezing arrow and few other spells + if (m_caster->GetTypeId() == TYPEID_PLAYER && m_spellInfo->CategoryRecoveryTime && spellInfo->CategoryRecoveryTime + && m_spellInfo->Category == spellInfo->Category) + ((Player*)m_caster)->RemoveSpellCooldown(spellInfo->Id); // some triggered spells must be casted instantly (for example, if next effect case instant kill caster) bool instant = false; @@ -1995,12 +2250,71 @@ 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 ); + // Remove spell cooldown (not category) if spell triggering spell with cooldown and same category + // Needed by freezing arrow and few other spells + if (m_caster->GetTypeId() == TYPEID_PLAYER && m_spellInfo->CategoryRecoveryTime && spellInfo->CategoryRecoveryTime + && m_spellInfo->Category == spellInfo->Category) + ((Player*)m_caster)->RemoveSpellCooldown(spellInfo->Id); - 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::EffectJump(uint32 i) +{ + if(m_caster->isInFlight()) + return; + + // Init dest coordinates + float x,y,z,o; + if(m_targets.HasDst()) + { + x = m_targets.m_destX; + y = m_targets.m_destY; + z = m_targets.m_destZ; + + if(m_spellInfo->EffectImplicitTargetA[i] == TARGET_DEST_TARGET_BACK) + { + // explicit cast data from client or server-side cast + // some spell at client send caster + Unit* pTarget = NULL; + if(m_targets.getUnitTarget() && m_targets.getUnitTarget()!=m_caster) + pTarget = m_targets.getUnitTarget(); + else if(m_caster->getVictim()) + pTarget = m_caster->getVictim(); + else if(m_caster->GetTypeId() == TYPEID_PLAYER) + pTarget = ObjectAccessor::GetUnit(*m_caster, ((Player*)m_caster)->GetSelection()); + + o = pTarget ? pTarget->GetOrientation() : m_caster->GetOrientation(); + } + else + o = m_caster->GetOrientation(); + } + else if(m_targets.getUnitTarget()) + { + m_targets.getUnitTarget()->GetContactPoint(m_caster,x,y,z,CONTACT_DISTANCE); + o = m_caster->GetOrientation(); + } + else if(m_targets.getGOTarget()) + { + m_targets.getGOTarget()->GetContactPoint(m_caster,x,y,z,CONTACT_DISTANCE); + o = m_caster->GetOrientation(); + } + else + { + sLog.outError( "Spell::EffectJump - unsupported target mode for spell ID %u", m_spellInfo->Id ); + return; + } + + //m_caster->NearTeleportTo(x,y,z,o,true); + float speedZ; + if(m_spellInfo->EffectMiscValue[i]) + speedZ = float(m_spellInfo->EffectMiscValue[i])/10; + else if(m_spellInfo->EffectMiscValueB[i]) + speedZ = float(m_spellInfo->EffectMiscValueB[i])/10; + else + speedZ = 10.0f; + float speedXY = m_caster->GetExactDistance2d(x, y) * 10.0f / speedZ; + m_caster->GetMotionMaster()->MoveJump(x, y, z, speedXY, speedZ); } void Spell::EffectTeleportUnits(uint32 i) @@ -2014,6 +2328,7 @@ void Spell::EffectTeleportUnits(uint32 i) sLog.outError( "Spell::EffectTeleportUnits - does not have destination for spell ID %u\n", m_spellInfo->Id ); return; } + // Init dest coordinates int32 mapid = m_targets.m_mapId; if(mapid < 0) mapid = (int32)unitTarget->GetMapId(); @@ -2022,16 +2337,11 @@ void Spell::EffectTeleportUnits(uint32 i) float z = m_targets.m_destZ; float orientation = m_targets.getUnitTarget() ? m_targets.getUnitTarget()->GetOrientation() : unitTarget->GetOrientation(); sLog.outDebug("Spell::EffectTeleportUnits - teleport unit to %u %f %f %f\n", mapid, x, y, z); - // Teleport - if(unitTarget->GetTypeId() == TYPEID_PLAYER) - ((Player*)unitTarget)->TeleportTo(mapid, x, y, z, orientation, TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0)); - else - { - MapManager::Instance().GetMap(mapid, m_caster)->CreatureRelocation((Creature*)unitTarget, x, y, z, orientation); - WorldPacket data; - unitTarget->BuildTeleportAckMsg(&data, x, y, z, orientation); - unitTarget->SendMessageToSet(&data, false); - } + + if(mapid == unitTarget->GetMapId()) + unitTarget->NearTeleportTo(x, y, z, orientation, unitTarget == m_caster); + else if(unitTarget->GetTypeId() == TYPEID_PLAYER) + ((Player*)unitTarget)->TeleportTo(mapid, x, y, z, orientation, unitTarget==m_caster ? TELE_TO_SPELL : 0); // post effects for TARGET_DST_DB switch ( m_spellInfo->Id ) @@ -2039,13 +2349,13 @@ void Spell::EffectTeleportUnits(uint32 i) // Dimensional Ripper - Everlook case 23442: { - int32 r = m_caster->GetMap()->irand(0, 119); + int32 r = irand(0, 119); if ( r >= 70 ) // 7/12 success { if ( r < 100 ) // 4/12 evil twin - m_caster->CastSpell(m_caster,23445,true); + m_caster->CastSpell(m_caster, 23445, true); else // 1/12 fire - m_caster->CastSpell(m_caster,23449,true); + m_caster->CastSpell(m_caster, 23449, true); } return; } @@ -2054,41 +2364,41 @@ void Spell::EffectTeleportUnits(uint32 i) { if ( roll_chance_i(50) ) // 50% success { - int32 rand_eff = m_caster->GetMap()->urand(1,7); + int32 rand_eff = urand(1, 7); switch ( rand_eff ) { case 1: // soul split - evil - m_caster->CastSpell(m_caster,36900,true); + m_caster->CastSpell(m_caster, 36900, true); break; case 2: // soul split - good - m_caster->CastSpell(m_caster,36901,true); + m_caster->CastSpell(m_caster, 36901, true); break; case 3: // Increase the size - m_caster->CastSpell(m_caster,36895,true); + m_caster->CastSpell(m_caster, 36895, true); break; case 4: // Decrease the size - m_caster->CastSpell(m_caster,36893,true); + m_caster->CastSpell(m_caster, 36893, true); break; case 5: // Transform { if (((Player*)m_caster)->GetTeam() == ALLIANCE ) - m_caster->CastSpell(m_caster,36897,true); + m_caster->CastSpell(m_caster, 36897, true); else - m_caster->CastSpell(m_caster,36899,true); + m_caster->CastSpell(m_caster, 36899, true); break; } case 6: // chicken - m_caster->CastSpell(m_caster,36940,true); + m_caster->CastSpell(m_caster, 36940, true); break; case 7: // evil twin - m_caster->CastSpell(m_caster,23445,true); + m_caster->CastSpell(m_caster, 23445, true); break; } } @@ -2099,28 +2409,28 @@ void Spell::EffectTeleportUnits(uint32 i) { if ( roll_chance_i(50) ) // 50% success { - int32 rand_eff = m_caster->GetMap()->urand(1,4); + int32 rand_eff = urand(1, 4); switch ( rand_eff ) { case 1: // soul split - evil - m_caster->CastSpell(m_caster,36900,true); + m_caster->CastSpell(m_caster, 36900, true); break; case 2: // soul split - good - m_caster->CastSpell(m_caster,36901,true); + m_caster->CastSpell(m_caster, 36901, true); break; case 3: // Increase the size - m_caster->CastSpell(m_caster,36895,true); + m_caster->CastSpell(m_caster, 36895, true); break; case 4: // Transform { if (((Player*)m_caster)->GetTeam() == ALLIANCE ) - m_caster->CastSpell(m_caster,36897,true); + m_caster->CastSpell(m_caster, 36897, true); else - m_caster->CastSpell(m_caster,36899,true); + m_caster->CastSpell(m_caster, 36899, true); break; } } @@ -2132,84 +2442,16 @@ void Spell::EffectTeleportUnits(uint32 i) 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; - if(!caster) - return; - - sLog.outDebug("Spell: Aura is: %u", m_spellInfo->EffectApplyAuraName[i]); - - Aura* Aur = CreateAura(m_spellInfo, i, &damage, unitTarget, caster, m_CastItem); - - // Now Reduce spell duration using data received at spell hit - int32 duration = Aur->GetAuraMaxDuration(); - unitTarget->ApplyDiminishingToDuration(m_diminishGroup,duration,caster,m_diminishLevel); - Aur->setDiminishGroup(m_diminishGroup); - - // if Aura removed and deleted, do not continue. - if(duration== 0 && !(Aur->IsPermanent())) - { - delete Aur; - return; - } - - if(duration != Aur->GetAuraMaxDuration()) - { - Aur->SetAuraMaxDuration(duration); - Aur->SetAuraDuration(duration); - } - - bool added = unitTarget->AddAura(Aur); - - // Aura not added and deleted in AddAura call; - if (!added) - return; - - // found crash at character loading, broken pointer to Aur... - // Aur was deleted in AddAura()... - if(!Aur) - return; - - // TODO Make a way so it works for every related spell! - if(unitTarget->GetTypeId()==TYPEID_PLAYER ||( unitTarget->GetTypeId()==TYPEID_UNIT && ((Creature*)unitTarget)->isPet() ) ) // 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]); - } - } + if (m_spellAura) + if (AuraEffect * AurEff = m_spellAura->GetPartAura(i)) + unitTarget->HandleAuraEffect(AurEff, true); +} - // Prayer of Mending (jump animation), we need formal caster instead original for correct animation - if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && (m_spellInfo->SpellFamilyFlags & 0x00002000000000LL)) - m_caster->CastSpell(unitTarget, 41637, true, NULL, Aur, m_originalCasterGUID); +void Spell::EffectApplyAreaAura(uint32 i) +{ + if (m_spellAura) + if (AuraEffect * AurEff = m_spellAura->GetPartAura(i)) + unitTarget->HandleAuraEffect(AurEff, true); } void Spell::EffectUnlearnSpecialization( uint32 i ) @@ -2259,7 +2501,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) @@ -2268,70 +2511,17 @@ void Spell::EffectPowerDrain(uint32 i) if(Player *modOwner = m_caster->GetSpellModOwner()) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, manaMultiplier); - int32 gain = int32(new_damage*manaMultiplier); + int32 gain = int32(new_damage * manaMultiplier); - m_caster->ModifyPower(POWER_MANA,gain); - //send log - m_caster->SendEnergizeSpellLog(m_caster, m_spellInfo->Id,gain,POWER_MANA); + m_caster->EnergizeBySpell(m_caster, m_spellInfo->Id, gain, POWER_MANA); } } void Spell::EffectSendEvent(uint32 EffectIndex) { - if (m_caster->GetTypeId() == TYPEID_PLAYER && ((Player*)m_caster)->InBattleGround()) - { - BattleGround* bg = ((Player *)m_caster)->GetBattleGround(); - if(bg && bg->GetStatus() == STATUS_IN_PROGRESS) - { - switch(m_spellInfo->Id) - { - case 23333: // Pickup Horde Flag - /*do not uncomment . - if(bg->GetTypeID()==BATTLEGROUND_WS) - bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget); - sLog.outDebug("Send Event Horde Flag Picked Up"); - break; - /* not used : - case 23334: // Drop Horde Flag - if(bg->GetTypeID()==BATTLEGROUND_WS) - bg->EventPlayerDroppedFlag((Player*)m_caster); - sLog.outDebug("Drop Horde Flag"); - break; - */ - case 23335: // Pickup Alliance Flag - /*do not uncomment ... (it will cause crash, because of null targetobject!) anyway this is a bad way to call that event, because it would cause recursion - if(bg->GetTypeID()==BATTLEGROUND_WS) - bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget); - sLog.outDebug("Send Event Alliance Flag Picked Up"); - break; - /* not used : - case 23336: // Drop Alliance Flag - if(bg->GetTypeID()==BATTLEGROUND_WS) - bg->EventPlayerDroppedFlag((Player*)m_caster); - sLog.outDebug("Drop Alliance Flag"); - break; - case 23385: // Alliance Flag Returns - if(bg->GetTypeID()==BATTLEGROUND_WS) - bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget); - sLog.outDebug("Alliance Flag Returned"); - break; - case 23386: // Horde Flag Returns - if(bg->GetTypeID()==BATTLEGROUND_WS) - bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget); - sLog.outDebug("Horde Flag Returned"); - break;*/ - case 34976: - /* - if(bg->GetTypeID()==BATTLEGROUND_EY) - bg->EventPlayerClickedOnFlag((Player*)m_caster, gameObjTarget); - */ - break; - default: - sLog.outDebug("Unknown spellid %u in BG event", m_spellInfo->Id); - break; - } - } - } + /* + we do not handle a flag dropping or clicking on flag in battleground by sendevent system + */ sLog.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo->EffectMiscValue[EffectIndex], m_spellInfo->Id); sWorld.ScriptsStart(sEventScripts, m_spellInfo->EffectMiscValue[EffectIndex], m_caster, focusObject); } @@ -2352,16 +2542,26 @@ void Spell::EffectPowerBurn(uint32 i) if(damage < 0) return; + Unit* caster = m_originalCaster ? m_originalCaster : m_caster; + + // burn x% of target's mana, up to maximum of 2x% of caster's mana (Mana Burn) + if(m_spellInfo->ManaCostPercentage) + { + uint32 maxdamage = m_caster->GetMaxPower(powertype) * damage * 2 / 100; + damage = unitTarget->GetMaxPower(powertype) * damage / 100; + if(damage > maxdamage) damage = maxdamage; + } + int32 curPower = int32(unitTarget->GetPower(powertype)); - // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4) uint32 power = damage; + // 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); int32 new_damage = (curPower < power) ? curPower : power; - unitTarget->ModifyPower(powertype,-new_damage); + unitTarget->ModifyPower(powertype, -new_damage); float multiplier = m_spellInfo->EffectMultipleValue[i]; if(Player *modOwner = m_caster->GetSpellModOwner()) @@ -2397,60 +2597,79 @@ void Spell::SpellDamageHeal(uint32 /*i*/) { // Amount of heal - depends from stacked Holy Energy int damageAmount = 0; - Unit::AuraList const& mDummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY); - for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i) + Unit::AuraEffectList const& mDummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraEffectList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i) if((*i)->GetId() == 45062) - damageAmount+=(*i)->GetModifierValue(); + damageAmount+=(*i)->GetAmount(); if (damageAmount) m_caster->RemoveAurasDueToSpell(45062); addhealth += damageAmount; } // Swiftmend - consumes Regrowth or Rejuvenation - else if (m_spellInfo->TargetAuraState == AURA_STATE_SWIFTMEND && unitTarget->HasAuraState(AURA_STATE_SWIFTMEND)) + else if (m_spellInfo->TargetAuraState == AURA_STATE_SWIFTMEND && unitTarget->HasAuraState(AURA_STATE_SWIFTMEND, m_spellInfo, m_caster)) { - Unit::AuraList const& RejorRegr = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_HEAL); + Unit::AuraEffectList const& RejorRegr = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_HEAL); // find most short by duration - Aura *targetAura = NULL; - for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i) + AuraEffect *targetAura = NULL; + for(Unit::AuraEffectList::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()) + if(!targetAura || (*i)->GetParentAura()->GetAuraDuration() < targetAura->GetParentAura()->GetAuraDuration()) targetAura = *i; } } if(!targetAura) { - sLog.outError("Target(GUID:" I64FMTD ") has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget->GetGUID()); + sLog.outError("Target(GUID:" UI64FMTD ") has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget->GetGUID()); return; } - int32 tickheal = targetAura->GetModifierValuePerStack(); + int32 tickheal = targetAura->GetAmount(); 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]) { case 0x10: tickcount = 4; break; // Rejuvenation case 0x40: tickcount = 6; break; // Regrowth } } addhealth += tickheal * tickcount; - unitTarget->RemoveAurasByCasterSpell(targetAura->GetId(), targetAura->GetCasterGUID()); + + // Glyph of Swiftmend + if(!caster->GetDummyAura(54824)) + unitTarget->RemoveAura(targetAura->GetId(), targetAura->GetCasterGUID()); //addhealth += tickheal * tickcount; //addhealth = caster->SpellHealingBonus(m_spellInfo, addhealth,HEAL, unitTarget); } + // Riptide - increase healing done by Chain Heal + else if (m_spellInfo->SpellFamilyName==SPELLFAMILY_SHAMAN && m_spellInfo->SpellFamilyFlags[0] & 0x100) + { + addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, addhealth, HEAL); + if (AuraEffect * aurEff = unitTarget->GetAura(SPELL_AURA_PERIODIC_HEAL, SPELLFAMILY_SHAMAN, 0, 0, 0x10, m_originalCasterGUID)) + { + addhealth *= 1.25f; + // consume aura + unitTarget->RemoveAura(aurEff->GetParentAura()); + } + } + // Death Pact - return pct of max health to caster + else if (m_spellInfo->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT && m_spellInfo->SpellFamilyFlags[0] & 0x00080000) + { + addhealth = int32(caster->GetMaxHealth()*damage/100.0f); + } else - addhealth = caster->SpellHealingBonus(m_spellInfo, addhealth,HEAL, unitTarget); + addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, addhealth, HEAL); m_damage -= addhealth; } @@ -2468,14 +2687,11 @@ void Spell::EffectHealPct( uint32 /*i*/ ) return; uint32 addhealth = unitTarget->GetMaxHealth() * damage / 100; - caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, false); + if(Player* modOwner = m_caster->GetSpellModOwner()) + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DAMAGE, addhealth, this); - int32 gain = unitTarget->ModifyHealth( int32(addhealth) ); + int32 gain = caster->DealHeal(unitTarget, addhealth, m_spellInfo); unitTarget->getHostilRefManager().threatAssist(m_caster, float(gain) * 0.5f, m_spellInfo); - - if(caster->GetTypeId()==TYPEID_PLAYER) - if(BattleGround *bg = ((Player*)caster)->GetBattleGround()) - bg->UpdatePlayerScore(((Player*)caster), SCORE_HEALING_DONE, gain); } } @@ -2491,9 +2707,8 @@ void Spell::EffectHealMechanical( uint32 /*i*/ ) if (!caster) return; - uint32 addhealth = caster->SpellHealingBonus(m_spellInfo, uint32(damage), HEAL, unitTarget); - caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, false); - unitTarget->ModifyHealth( int32(damage) ); + uint32 addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, uint32(damage), HEAL); + caster->DealHeal(unitTarget, addhealth, m_spellInfo); } } @@ -2516,18 +2731,14 @@ void Spell::EffectHealthLeech(uint32 i) int32 new_damage = int32(damage*multiplier); uint32 curHealth = unitTarget->GetHealth(); - new_damage = m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, new_damage, m_IsTriggeredSpell, true); + new_damage = m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, new_damage ); if(curHealth < new_damage) new_damage = curHealth; if(m_caster->isAlive()) { - new_damage = m_caster->SpellHealingBonus(m_spellInfo, new_damage, HEAL, m_caster); - - m_caster->ModifyHealth(new_damage); - - if(m_caster->GetTypeId() == TYPEID_PLAYER) - m_caster->SendHealSpellLog(m_caster, m_spellInfo->Id, uint32(new_damage)); + new_damage = m_caster->SpellHealingBonus(m_caster, m_spellInfo, new_damage, HEAL); + m_caster->DealHeal(m_caster, uint32(new_damage), m_spellInfo); } // m_healthLeech+=tmpvalue; // m_damage+=new_damage; @@ -2557,7 +2768,7 @@ void Spell::DoCreateItem(uint32 i, uint32 itemtype) /*int32 basePoints = m_currentBasePoints[i]; int32 randomPoints = m_spellInfo->EffectDieSides[i]; if (randomPoints) - num_to_add = basePoints + m_caster->GetMap()->irand(1, randomPoints); + num_to_add = basePoints + irand(1, randomPoints); else num_to_add = basePoints + 1;*/ } @@ -2575,8 +2786,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; @@ -2626,7 +2837,7 @@ void Spell::DoCreateItem(uint32 i, uint32 itemtype) // set the "Crafted by ..." property of the item if( pItem->GetProto()->Class != ITEM_CLASS_CONSUMABLE && pItem->GetProto()->Class != ITEM_CLASS_QUEST) - pItem->SetUInt32Value(ITEM_FIELD_CREATOR,player->GetGUIDLow()); + pItem->SetUInt32Value(ITEM_FIELD_CREATOR, player->GetGUIDLow()); // send info to the client if(pItem) @@ -2642,9 +2853,43 @@ void Spell::EffectCreateItem(uint32 i) DoCreateItem(i,m_spellInfo->EffectItemType[i]); } +void Spell::EffectCreateItem2(uint32 i) +{ + if(m_caster->GetTypeId()!=TYPEID_PLAYER) + return; + Player* player = (Player*)m_caster; + + uint32 item_id = m_spellInfo->EffectItemType[i]; + DoCreateItem(i, item_id); + + // special case: fake item replaced by generate using spell_loot_template + if(IsLootCraftingSpell(m_spellInfo)) + { + if(!player->HasItemCount(item_id, 1)) + return; + + // remove reagent + uint32 count = 1; + player->DestroyItemCount(item_id, count, true); + + // create some random items + player->AutoStoreLoot(m_spellInfo->Id, LootTemplates_Spell); + } +} + +void Spell::EffectCreateRandomItem(uint32 i) +{ + if(m_caster->GetTypeId()!=TYPEID_PLAYER) + return; + Player* player = (Player*)m_caster; + + // create some random items + player->AutoStoreLoot(m_spellInfo->Id, LootTemplates_Spell); +} + 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); @@ -2656,7 +2901,6 @@ void Spell::EffectPersistentAA(uint32 i) delete dynObj; return; } - dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65); dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x01eeeeee); caster->AddDynObject(dynObj); dynObj->GetMap()->Add(dynObj); @@ -2672,6 +2916,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; @@ -2702,13 +2948,10 @@ void Spell::EffectEnergize(uint32 i) if(damage < 0) return; - Powers power = Powers(m_spellInfo->EffectMiscValue[i]); - if(unitTarget->GetMaxPower(power) == 0) return; - unitTarget->ModifyPower(power,damage); - m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, damage, power); + m_caster->EnergizeBySpell(unitTarget, m_spellInfo->Id, damage, power); // Mad Alchemist's Potion if (m_spellInfo->Id == 45051) @@ -2747,13 +2990,13 @@ void Spell::EffectEnergize(uint32 i) if (!elixirs.empty()) { // cast random elixir on target - uint32 rand_spell = m_caster->GetMap()->urand(0,elixirs.size()-1); + uint32 rand_spell = urand(0,elixirs.size()-1); m_caster->CastSpell(unitTarget,elixirs[rand_spell],true,m_CastItem); } } } -void Spell::EffectEnergisePct(uint32 i) +void Spell::EffectEnergizePct(uint32 i) { if(!unitTarget) return; @@ -2770,8 +3013,7 @@ void Spell::EffectEnergisePct(uint32 i) return; uint32 gain = damage * maxPower / 100; - unitTarget->ModifyPower(power, gain); - m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, damage, power); + m_caster->EnergizeBySpell(unitTarget, m_spellInfo->Id, gain, power); } void Spell::SendLoot(uint64 guid, LootType loottype) @@ -2811,6 +3053,7 @@ void Spell::SendLoot(uint64 guid, LootType loottype) { sLog.outDebug("Goober ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->goober.eventId,gameObjTarget->GetDBTableGUIDLow()); sWorld.ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->goober.eventId, player, gameObjTarget); + gameObjTarget->EventInform(gameObjTarget->GetGOInfo()->goober.eventId); } // cast goober spell @@ -2850,6 +3093,8 @@ void Spell::SendLoot(uint64 guid, LootType loottype) gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster); // Don't return, let loots been taken + default: + break; } } @@ -2857,7 +3102,7 @@ void Spell::SendLoot(uint64 guid, LootType loottype) player->SendLoot(guid, loottype); } -void Spell::EffectOpenLock(uint32 /*i*/) +void Spell::EffectOpenLock(uint32 effIndex) { if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER) { @@ -2867,7 +3112,6 @@ void Spell::EffectOpenLock(uint32 /*i*/) Player* player = (Player*)m_caster; - LootType loottype = LOOT_CORPSE; uint32 lockId = 0; uint64 guid = 0; @@ -2879,7 +3123,7 @@ void Spell::EffectOpenLock(uint32 /*i*/) if( goInfo->type == GAMEOBJECT_TYPE_BUTTON && goInfo->button.noDamageImmune || goInfo->type == GAMEOBJECT_TYPE_GOOBER && goInfo->goober.losOK ) { - //isAllowUseBattleGroundObject() already called in CanCast() + //CanUseBattleGroundObject() already called in CheckCast() // in battleground check if(BattleGround *bg = player->GetBattleGround()) { @@ -2891,7 +3135,7 @@ void Spell::EffectOpenLock(uint32 /*i*/) } else if (goInfo->type == GAMEOBJECT_TYPE_FLAGSTAND) { - //isAllowUseBattleGroundObject() already called in CanCast() + //CanUseBattleGroundObject() already called in CheckCast() // in battleground check if(BattleGround *bg = player->GetBattleGround()) { @@ -2918,93 +3162,39 @@ void Spell::EffectOpenLock(uint32 /*i*/) return; } - if(!lockId) // possible case for GO and maybe for items. - { - SendLoot(guid, loottype); - return; - } - - // Get LockInfo - LockEntry const *lockInfo = sLockStore.LookupEntry(lockId); + SkillType skillId = SKILL_NONE; + int32 reqSkillValue = 0; + int32 skillValue; - if (!lockInfo) + SpellCastResult res = CanOpenLock(effIndex, lockId, skillId, reqSkillValue, skillValue); + if(res != SPELL_CAST_OK) { - sLog.outError( "Spell::EffectOpenLock: %s [guid = %u] has an unknown lockId: %u!", - (gameObjTarget ? "gameobject" : "item"), GUID_LOPART(guid), lockId); - SendCastResult(SPELL_FAILED_BAD_TARGETS); + SendCastResult(res); return; } - // check key - for(int i = 0; i < 5; ++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]) - { - SendLoot(guid, loottype); - return; - } - } - - uint32 SkillId = 0; - // Check and skill-up skill - if( m_spellInfo->Effect[1] == SPELL_EFFECT_SKILL ) - SkillId = m_spellInfo->EffectMiscValue[1]; - // pickpocketing spells - else if( m_spellInfo->EffectMiscValue[0] == LOCKTYPE_PICKLOCK ) - SkillId = SKILL_LOCKPICKING; - - // skill bonus provided by casting spell (mostly item spells) - uint32 spellSkillBonus = uint32(damage/*m_currentBasePoints[0]+1*/); - - uint32 reqSkillValue = lockInfo->requiredminingskill; - - if(lockInfo->requiredlockskill) // required pick lock skill applying - { - if(SkillId != SKILL_LOCKPICKING) // wrong skill (cheating?) - { - SendCastResult(SPELL_FAILED_FIZZLE); - return; - } - - reqSkillValue = lockInfo->requiredlockskill; - } - else if(SkillId == SKILL_LOCKPICKING) // apply picklock skill to wrong target - { - SendCastResult(SPELL_FAILED_BAD_TARGETS); - return; - } + SendLoot(guid, LOOT_SKINNING); - if ( SkillId ) + // not allow use skill grow at item base open + if(!m_CastItem && skillId != SKILL_NONE) { - loottype = LOOT_SKINNING; - if ( player->GetSkillValue(SkillId) + spellSkillBonus < reqSkillValue ) - { - SendCastResult(SPELL_FAILED_LOW_CASTLEVEL); - return; - } - // update skill if really known - uint32 SkillValue = player->GetPureSkillValue(SkillId); - if(SkillValue) // non only item base skill + if(uint32 pureSkillValue = player->GetPureSkillValue(skillId)) { if(gameObjTarget) { // Allow one skill-up until respawned if ( !gameObjTarget->IsInSkillupList( player->GetGUIDLow() ) && - player->UpdateGatherSkill(SkillId, SkillValue, reqSkillValue) ) + player->UpdateGatherSkill(skillId, pureSkillValue, reqSkillValue) ) gameObjTarget->AddToSkillupList( player->GetGUIDLow() ); } else if(itemTarget) { // Do one skill-up - uint32 SkillValue = player->GetPureSkillValue(SkillId); - player->UpdateGatherSkill(SkillId, SkillValue, reqSkillValue); + player->UpdateGatherSkill(skillId, pureSkillValue, reqSkillValue); } } } - - SendLoot(guid, loottype); } void Spell::EffectSummonChangeItem(uint32 i) @@ -3032,10 +3222,10 @@ void Spell::EffectSummonChangeItem(uint32 i) if( !pNewItem ) return; - for(uint8 i= PERM_ENCHANTMENT_SLOT; i<=TEMP_ENCHANTMENT_SLOT; ++i) + for(uint8 j= PERM_ENCHANTMENT_SLOT; j<=TEMP_ENCHANTMENT_SLOT; ++j) { - if(m_CastItem->GetEnchantmentId(EnchantmentSlot(i))) - pNewItem->SetEnchantment(EnchantmentSlot(i), m_CastItem->GetEnchantmentId(EnchantmentSlot(i)), m_CastItem->GetEnchantmentDuration(EnchantmentSlot(i)), m_CastItem->GetEnchantmentCharges(EnchantmentSlot(i))); + if(m_CastItem->GetEnchantmentId(EnchantmentSlot(j))) + pNewItem->SetEnchantment(EnchantmentSlot(j), m_CastItem->GetEnchantmentId(EnchantmentSlot(j)), m_CastItem->GetEnchantmentDuration(EnchantmentSlot(j)), m_CastItem->GetEnchantmentCharges(EnchantmentSlot(j))); } if(m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) < m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY)) @@ -3050,7 +3240,7 @@ void Spell::EffectSummonChangeItem(uint32 i) uint8 msg = player->CanStoreItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true ); if( msg == EQUIP_ERR_OK ) { - player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true); + player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true); // prevent crash at access and unexpected charges counting with item update queue corrupt if(m_CastItem==m_targets.getItemTarget()) @@ -3068,7 +3258,7 @@ void Spell::EffectSummonChangeItem(uint32 i) uint8 msg = player->CanBankItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true ); if( msg == EQUIP_ERR_OK ) { - player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true); + player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true); // prevent crash at access and unexpected charges counting with item update queue corrupt if(m_CastItem==m_targets.getItemTarget()) @@ -3086,7 +3276,7 @@ void Spell::EffectSummonChangeItem(uint32 i) uint8 msg = player->CanEquipItem( m_CastItem->GetSlot(), dest, pNewItem, true ); if( msg == EQUIP_ERR_OK ) { - player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true); + player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), true); // prevent crash at access and unexpected charges counting with item update queue corrupt if(m_CastItem==m_targets.getItemTarget()) @@ -3104,11 +3294,6 @@ void Spell::EffectSummonChangeItem(uint32 i) delete pNewItem; } -void Spell::EffectOpenSecretSafe(uint32 i) -{ - EffectOpenLock(i); //no difference for now -} - void Spell::EffectProficiency(uint32 /*i*/) { if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) @@ -3116,114 +3301,183 @@ void Spell::EffectProficiency(uint32 /*i*/) Player *p_target = (Player*)unitTarget; uint32 subClassMask = m_spellInfo->EquippedItemSubClassMask; - if(m_spellInfo->EquippedItemClass == 2 && !(p_target->GetWeaponProficiency() & subClassMask)) + if(m_spellInfo->EquippedItemClass == ITEM_CLASS_WEAPON && !(p_target->GetWeaponProficiency() & subClassMask)) { p_target->AddWeaponProficiency(subClassMask); - p_target->SendProficiency(uint8(0x02),p_target->GetWeaponProficiency()); + p_target->SendProficiency(ITEM_CLASS_WEAPON, p_target->GetWeaponProficiency()); } - if(m_spellInfo->EquippedItemClass == 4 && !(p_target->GetArmorProficiency() & subClassMask)) + if(m_spellInfo->EquippedItemClass == ITEM_CLASS_ARMOR && !(p_target->GetArmorProficiency() & subClassMask)) { p_target->AddArmorProficiency(subClassMask); - p_target->SendProficiency(uint8(0x04),p_target->GetArmorProficiency()); + p_target->SendProficiency(ITEM_CLASS_ARMOR, p_target->GetArmorProficiency()); } } -void Spell::EffectApplyAreaAura(uint32 i) +void Spell::EffectSummonType(uint32 i) { - if(!unitTarget) - return; - if(!unitTarget->isAlive()) + uint32 entry = m_spellInfo->EffectMiscValue[i]; + if(!entry) return; - AreaAura* Aur = new AreaAura(m_spellInfo, i, &damage, unitTarget, m_caster, m_CastItem); - unitTarget->AddAura(Aur); -} - -void Spell::EffectSummonType(uint32 i) -{ - switch(m_spellInfo->EffectMiscValueB[i]) + SummonPropertiesEntry const *properties = sSummonPropertiesStore.LookupEntry(m_spellInfo->EffectMiscValueB[i]); + if(!properties) { - case SUMMON_TYPE_GUARDIAN: - EffectSummonGuardian(i); - break; - case SUMMON_TYPE_POSESSED: - case SUMMON_TYPE_POSESSED2: - case SUMMON_TYPE_POSESSED3: - EffectSummonPossessed(i); - break; - case SUMMON_TYPE_WILD: - EffectSummonWild(i); - break; - case SUMMON_TYPE_DEMON: - EffectSummonDemon(i); - break; - case SUMMON_TYPE_SUMMON: - EffectSummon(i); - break; - case SUMMON_TYPE_CRITTER: - case SUMMON_TYPE_CRITTER2: - case SUMMON_TYPE_CRITTER3: - EffectSummonCritter(i); - break; - case SUMMON_TYPE_TOTEM_SLOT1: - case SUMMON_TYPE_TOTEM_SLOT2: - case SUMMON_TYPE_TOTEM_SLOT3: - case SUMMON_TYPE_TOTEM_SLOT4: - case SUMMON_TYPE_TOTEM: - EffectSummonTotem(i); - break; - case SUMMON_TYPE_UNKNOWN1: - case SUMMON_TYPE_UNKNOWN3: - case SUMMON_TYPE_UNKNOWN4: - case SUMMON_TYPE_UNKNOWN5: - break; - default: - sLog.outError("EffectSummonType: Unhandled summon type %u", m_spellInfo->EffectMiscValueB[i]); - break; + sLog.outError("EffectSummonType: Unhandled summon type %u", m_spellInfo->EffectMiscValueB[i]); + return; } -} -void Spell::EffectSummon(uint32 i) -{ - uint32 pet_entry = m_spellInfo->EffectMiscValue[i]; - if(!pet_entry) + if(!m_originalCaster) return; - if(!m_originalCaster || m_originalCaster->GetTypeId() != TYPEID_PLAYER) - { - EffectSummonWild(i); - return; - } + int32 duration = GetSpellDuration(m_spellInfo); + if(Player* modOwner = m_originalCaster->GetSpellModOwner()) + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration); - Player *owner = (Player*)m_originalCaster; + float x, y, z; + GetSummonPosition(i, x, y, z); - if(owner->GetPetGUID()) - return; + /*//totem must be at same Z in case swimming caster and etc. + if( fabs( z - m_caster->GetPositionZ() ) > 5 ) + z = m_caster->GetPositionZ(); - // Summon in dest location - float x,y,z; - if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) + uint32 level = m_caster->getLevel(); + + // level of creature summoned using engineering item based at engineering skill level + if(m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem) { - x = m_targets.m_destX; - y = m_targets.m_destY; - z = m_targets.m_destZ; - } - else - m_caster->GetClosePoint(x,y,z,owner->GetObjectSize()); + ItemPrototype const *proto = m_CastItem->GetProto(); + if(proto && proto->RequiredSkill == SKILL_ENGINERING) + { + uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING); + if(skill202) + { + level = skill202/5; + } + } + }*/ - Pet *spawnCreature = owner->SummonPet(pet_entry, x, y, z, m_caster->GetOrientation(), SUMMON_PET, GetSpellDuration(m_spellInfo)); - if(!spawnCreature) - return; + TempSummon *summon = NULL; - spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS, 0); - spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0); - spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id); + switch(properties->Category) + { + default: + switch(properties->Type) + { + case SUMMON_TYPE_PET: + case SUMMON_TYPE_GUARDIAN: + case SUMMON_TYPE_MINION: + SummonGuardian(entry, properties); + break; + case SUMMON_TYPE_VEHICLE: + case SUMMON_TYPE_VEHICLE2: + { + Vehicle *vehicle = m_caster->SummonVehicle(entry, x, y, z, m_caster->GetOrientation()); + if(!vehicle) + return; + + //vehicle->SetUInt64Value(UNIT_FIELD_SUMMONEDBY, m_caster->GetGUID()); + if(m_originalCaster) + vehicle->setFaction(m_originalCaster->getFaction()); + vehicle->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id); + break; + } + case SUMMON_TYPE_TOTEM: + { + summon = m_caster->GetMap()->SummonCreature(entry, x, y, z, m_caster->GetOrientation(), properties, duration, m_originalCaster); + if(!summon || !summon->isTotem()) + return; + + if(damage) // if not spell info, DB values used + { + summon->SetMaxHealth(damage); + summon->SetHealth(damage); + } + + //summon->SetUInt32Value(UNIT_CREATED_BY_SPELL,m_spellInfo->Id); + + if(m_originalCaster->GetTypeId() == TYPEID_PLAYER + && properties->Slot >= SUMMON_SLOT_TOTEM + && properties->Slot < MAX_TOTEM_SLOT) + { + //summon->SendUpdateToPlayer((Player*)m_originalCaster); + WorldPacket data(SMSG_TOTEM_CREATED, 1+8+4+4); + data << uint8(properties->Slot-1); + data << uint64(m_originalCaster->GetGUID()); + data << uint32(duration); + data << uint32(m_spellInfo->Id); + ((Player*)m_originalCaster)->SendDirectMessage(&data); + } + break; + } + case SUMMON_TYPE_MINIPET: + { + summon = m_caster->GetMap()->SummonCreature(entry, x, y, z, m_caster->GetOrientation(), properties, duration, m_originalCaster); + if(!summon || !summon->HasSummonMask(SUMMON_MASK_MINION)) + return; - std::string name = owner->GetName(); - name.append(petTypeSuffix[spawnCreature->getPetType()]); - spawnCreature->SetName( name ); + //summon->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as summon... + summon->SelectLevel(summon->GetCreatureInfo()); // some summoned creaters have different from 1 DB data for level/hp + summon->SetUInt32Value(UNIT_NPC_FLAGS, summon->GetCreatureInfo()->npcflag); - spawnCreature->SetReactState( REACT_DEFENSIVE ); + summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + summon->AI()->EnterEvadeMode(); + + std::string name = m_originalCaster->GetName(); + name.append(petTypeSuffix[3]); + summon->SetName( name ); + break; + } + default: + { + float radius = GetSpellRadiusForHostile(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); + + int32 amount = damage > 0 ? damage : 1; + if (m_spellInfo->Id == 18662) // Curse of Doom + amount = 1; + + for(uint32 count = 0; count < amount; ++count) + { + float px, py, pz; + GetSummonPosition(i, px, py, pz, radius, count); + + TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN; + + m_originalCaster->SummonCreature(entry,px,py,pz,m_caster->GetOrientation(),summonType,duration); + } + break; + } + }//switch + break; + case SUMMON_CATEGORY_PET: + SummonGuardian(entry, properties); + break; + case SUMMON_CATEGORY_PUPPET: + summon = m_caster->GetMap()->SummonCreature(entry, x, y, z, m_caster->GetOrientation(), properties, duration, m_originalCaster); + break; + case SUMMON_CATEGORY_VEHICLE: + { + float x, y, z; + m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE); + Vehicle *vehicle = m_caster->SummonVehicle(entry, x, y, z, m_caster->GetOrientation()); + if(!vehicle) + return; + + vehicle->SetUInt64Value(UNIT_FIELD_SUMMONEDBY, m_caster->GetGUID()); + vehicle->setFaction(m_caster->getFaction()); + vehicle->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id); + + if(damage) + m_caster->CastSpell(vehicle, damage, true); + m_caster->EnterVehicle(vehicle); + break; + } + } + + if(summon) + { + summon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id); + } } void Spell::EffectLearnSpell(uint32 i) @@ -3241,8 +3495,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() ); } @@ -3252,8 +3506,7 @@ void Spell::EffectDispel(uint32 i) if(!unitTarget) return; - // Fill possible dispel list - std::vector <Aura *> dispel_list; + std::list < Aura * > dispel_list; // Create dispel mask by dispel type uint32 dispel_type = m_spellInfo->EffectMiscValue[i]; @@ -3262,7 +3515,7 @@ void Spell::EffectDispel(uint32 i) for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) { Aura *aur = (*itr).second; - if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask) + if (aur && ((1<<aur->GetSpellProto()->Dispel) & dispelMask)) { if(aur->GetSpellProto()->Dispel == DISPEL_MAGIC) { @@ -3277,80 +3530,67 @@ void Spell::EffectDispel(uint32 i) if(positive == unitTarget->IsFriendlyTo(m_caster)) continue; } - // Add every aura stack to dispel list - for(uint32 stack_amount = 0; stack_amount < aur->GetStackAmount(); ++stack_amount) + for (uint8 i = aur->GetStackAmount();i!=0;--i) dispel_list.push_back(aur); } } // Ok if exist some buffs for dispel try dispel it - if (!dispel_list.empty()) + if (uint32 list_size = dispel_list.size()) { - std::list < std::pair<uint32,uint64> > success_list;// (spell_id,casterGuid) - std::list < uint32 > fail_list; // spell_id - int32 list_size = dispel_list.size(); + uint32 failCount = 0; + std::list < Aura * > success_list; + WorldPacket dataFail(SMSG_DISPEL_FAILED, 8+8+4+4+damage*4); // dispel N = damage buffs (or while exist buffs for dispel) - for (int32 count=0; count < damage && list_size > 0; ++count) + for (int32 count=0; count < damage && list_size > 0; ++count, list_size = dispel_list.size()) { // Random select buff for dispel - Aura *aur = dispel_list[m_caster->GetMap()->urand(0, list_size-1)]; - - 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()) + std::list < Aura * > ::iterator itr = dispel_list.begin(); + for (uint32 i=urand(0, list_size-1);i>0;--i) + itr++; + + if (GetDispelChance((*itr)->GetCaster(), (*itr)->GetId())) { - if ( Player* modOwner = caster->GetSpellModOwner() ) - modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_RESIST_DISPEL_CHANCE, miss_chance, this); + success_list.push_back(*itr); + dispel_list.erase(itr); } - // Try dispel - if (roll_chance_i(miss_chance)) - fail_list.push_back(aur->GetId()); else - success_list.push_back(std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID())); - // Remove buff from list for prevent doubles - for (std::vector<Aura *>::iterator j = dispel_list.begin(); j != dispel_list.end(); ) { - Aura *dispelled = *j; - if (dispelled->GetId() == aur->GetId() && dispelled->GetCasterGUID() == aur->GetCasterGUID()) + if (!failCount) { - j = dispel_list.erase(j); - --list_size; - break; + // Failed to dispell + dataFail << uint64(m_caster->GetGUID()); // Caster GUID + dataFail << uint64(unitTarget->GetGUID()); // Victim GUID + dataFail << uint32(m_spellInfo->Id); // dispel spell id } - else - ++j; + failCount++; + dataFail << uint32((*itr)->GetId()); // Spell Id } } - // Send success log and really remove auras - if (!success_list.empty()) + if (failCount) + { + m_caster->SendMessageToSet(&dataFail, true); + } + if (success_list.size()) { - int32 count = success_list.size(); - WorldPacket data(SMSG_SPELLDISPELLOG, 8+8+4+1+4+count*5); - data.append(unitTarget->GetPackGUID()); // Victim GUID - data.append(m_caster->GetPackGUID()); // Caster GUID - data << uint32(m_spellInfo->Id); // dispel spell id - data << uint8(0); // not used - data << uint32(count); // count - for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j) + WorldPacket dataSuccess(SMSG_SPELLDISPELLOG, 8+8+4+1+4+damage*5); + // Send packet header + dataSuccess.append(unitTarget->GetPackGUID()); // Victim GUID + dataSuccess.append(m_caster->GetPackGUID()); // Caster GUID + dataSuccess << uint32(m_spellInfo->Id); // dispel spell id + dataSuccess << uint8(0); // not used + dataSuccess << uint32(success_list.size()); // count + for (std::list < Aura * > ::iterator itr = success_list.begin();itr!=success_list.end();++itr) { - 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 - unitTarget->RemoveAurasDueToSpellByDispel(spellInfo->Id, j->second, m_caster); - } - m_caster->SendMessageToSet(&data, true); + // Send dispelled spell info + dataSuccess << uint32((*itr)->GetId()); // Spell Id + dataSuccess << uint8(0); // 0 - dispelled !=0 cleansed + unitTarget->RemoveAurasDueToSpellByDispel((*itr)->GetId(), (*itr)->GetCasterGUID(), m_caster); + } + m_caster->SendMessageToSet(&dataSuccess, 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) @@ -3361,6 +3601,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; @@ -3369,18 +3610,6 @@ void Spell::EffectDispel(uint32 i) m_caster->CastSpell(m_caster, heal_spell, true); } } - // Send fail log to client - if (!fail_list.empty()) - { - // Failed to dispell - WorldPacket data(SMSG_DISPEL_FAILED, 8+8+4+4*fail_list.size()); - data << uint64(m_caster->GetGUID()); // Caster GUID - data << uint64(unitTarget->GetGUID()); // Victim GUID - data << uint32(m_spellInfo->Id); // dispel spell id - for (std::list< uint32 >::iterator j = fail_list.begin(); j != fail_list.end(); ++j) - data << uint32(*j); // Spell Id - m_caster->SendMessageToSet(&data, true); - } } } @@ -3412,17 +3641,15 @@ void Spell::EffectDistract(uint32 /*i*/) if ( unitTarget->GetTypeId() == TYPEID_PLAYER ) { // For players just turn them - WorldPacket data; - ((Player*)unitTarget)->BuildTeleportAckMsg(&data, unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle); - ((Player*)unitTarget)->GetSession()->SendPacket( &data ); ((Player*)unitTarget)->SetPosition(unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle, false); + ((Player*)unitTarget)->SendTeleportAckMsg(); } else { // Set creature Distracted, Stop it, And turn it unitTarget->SetOrientation(angle); unitTarget->StopMoving(); - unitTarget->GetMotionMaster()->MoveDistract(damage*1000); + unitTarget->GetMotionMaster()->MoveDistract(damage * IN_MILISECONDS); } } @@ -3440,7 +3667,7 @@ void Spell::EffectPickPocket(uint32 /*i*/) { int32 chance = 10 + int32(m_caster->getLevel()) - int32(unitTarget->getLevel()); - if (chance > m_caster->GetMap()->irand(0, 19)) + if (chance > irand(0, 19)) { // Stealing successful //sLog.outDebug("Sending loot from pickpocket"); @@ -3450,8 +3677,7 @@ void Spell::EffectPickPocket(uint32 /*i*/) { // Reveal action + get attack m_caster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TALK); - if (((Creature*)unitTarget)->IsAIEnabled) - ((Creature*)unitTarget)->AI()->AttackStart(m_caster); + m_caster->CombatStart(unitTarget); } } } @@ -3461,7 +3687,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)) @@ -3469,7 +3695,6 @@ void Spell::EffectAddFarsight(uint32 i) delete dynObj; return; } - dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65); dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x80000002); m_caster->AddDynObject(dynObj); @@ -3477,190 +3702,8 @@ void Spell::EffectAddFarsight(uint32 i) dynObj->GetMap()->Add(dynObj); //grid will also be loaded // Need to update visibility of object for client to accept farsight guid + ((Player*)m_caster)->SetViewpoint(dynObj, true); ((Player*)m_caster)->UpdateVisibilityOf(dynObj); - ((Player*)m_caster)->SetFarsightTarget(dynObj); -} - -void Spell::EffectSummonWild(uint32 i) -{ - uint32 creature_entry = m_spellInfo->EffectMiscValue[i]; - if(!creature_entry) - return; - - uint32 level = m_caster->getLevel(); - - // level of creature summoned using engineering item based at engineering skill level - if(m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem) - { - ItemPrototype const *proto = m_CastItem->GetProto(); - if(proto && proto->RequiredSkill == SKILL_ENGINERING) - { - uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING); - if(skill202) - { - level = skill202/5; - } - } - } - - // select center of summon position - float center_x = m_targets.m_destX; - float center_y = m_targets.m_destY; - float center_z = m_targets.m_destZ; - - float radius = GetSpellRadius(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) - { - // Summon 1 unit in dest location - if (count == 0) - { - px = m_targets.m_destX; - py = m_targets.m_destY; - pz = m_targets.m_destZ; - } - // Summon in random point all other units if location present - else - m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz); - } - // Summon if dest location not present near caster - else - m_caster->GetClosePoint(px,py,pz,3.0f); - - int32 duration = GetSpellDuration(m_spellInfo); - - TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN; - - if(m_originalCaster) - m_originalCaster->SummonCreature(creature_entry,px,py,pz,m_caster->GetOrientation(),summonType,duration); - else - m_caster->SummonCreature(creature_entry,px,py,pz,m_caster->GetOrientation(),summonType,duration); - } -} - -void Spell::EffectSummonGuardian(uint32 i) -{ - uint32 pet_entry = m_spellInfo->EffectMiscValue[i]; - if(!pet_entry) - return; - - // Jewelery statue case (totem like) - if(m_spellInfo->SpellIconID==2056) - { - EffectSummonTotem(i); - return; - } - - Player *caster = NULL; - if(m_originalCaster) - { - if(m_originalCaster->GetTypeId() == TYPEID_PLAYER) - caster = (Player*)m_originalCaster; - else if(((Creature*)m_originalCaster)->isTotem()) - caster = m_originalCaster->GetCharmerOrOwnerPlayerOrPlayerItself(); - } - - if(!caster) - { - EffectSummonWild(i); - return; - } - - // set timer for unsummon - int32 duration = GetSpellDuration(m_spellInfo); - - // Search old Guardian only for players (if casted spell not have duration or cooldown) - // FIXME: some guardians have control spell applied and controlled by player and anyway player can't summon in this time - // so this code hack in fact - if(duration <= 0 || GetSpellRecoveryTime(m_spellInfo)==0) - if(caster->HasGuardianWithEntry(pet_entry)) - return; // find old guardian, ignore summon - - // in another case summon new - uint32 level = caster->getLevel(); - - // level of pet summoned using engineering item based at engineering skill level - if(m_CastItem) - { - ItemPrototype const *proto = m_CastItem->GetProto(); - if(proto && proto->RequiredSkill == SKILL_ENGINERING) - { - uint16 skill202 = caster->GetSkillValue(SKILL_ENGINERING); - if(skill202) - { - level = skill202/5; - } - } - } - - // select center of summon position - float center_x = m_targets.m_destX; - float center_y = m_targets.m_destY; - float center_z = m_targets.m_destZ; - - float radius = GetSpellRadius(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) - { - // Summon 1 unit in dest location - if (count == 0) - { - px = m_targets.m_destX; - py = m_targets.m_destY; - pz = m_targets.m_destZ; - } - // Summon in random point all other units if location present - else - m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz); - } - // Summon if dest location not present near caster - else - m_caster->GetClosePoint(px,py,pz,m_caster->GetObjectSize()); - - Pet *spawnCreature = caster->SummonPet(m_spellInfo->EffectMiscValue[i], px, py, pz, m_caster->GetOrientation(), GUARDIAN_PET, duration); - if(!spawnCreature) - return; - - spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,0); - spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id); - spawnCreature->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE); - } -} - -void Spell::EffectSummonPossessed(uint32 i) -{ - uint32 entry = m_spellInfo->EffectMiscValue[i]; - if(!entry) - return; - - if(m_caster->GetTypeId() != TYPEID_PLAYER) - return; - - uint32 level = m_caster->getLevel(); - - float x, y, z; - m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE); - - int32 duration = GetSpellDuration(m_spellInfo); - - Pet* pet = ((Player*)m_caster)->SummonPet(entry, x, y, z, m_caster->GetOrientation(), POSSESSED_PET, duration); - if(!pet) - return; - - pet->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id); - pet->SetCharmedOrPossessedBy(m_caster, true); } void Spell::EffectTeleUnitsFaceCaster(uint32 i) @@ -3671,16 +3714,12 @@ void Spell::EffectTeleUnitsFaceCaster(uint32 i) if(unitTarget->isInFlight()) 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); - if(unitTarget->GetTypeId() == TYPEID_PLAYER) - ((Player*)unitTarget)->TeleportTo(mapid, fx, fy, fz, -m_caster->GetOrientation(), TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0)); - else - m_caster->GetMap()->CreatureRelocation((Creature*)m_caster, fx, fy, fz, -m_caster->GetOrientation()); + unitTarget->NearTeleportTo(fx,fy,fz,-m_caster->GetOrientation(),unitTarget==m_caster); } void Spell::EffectLearnSkill(uint32 i) @@ -3701,13 +3740,27 @@ void Spell::EffectAddHonor(uint32 /*i*/) if(unitTarget->GetTypeId() != TYPEID_PLAYER) return; - sLog.outDebug("SpellEffect::AddHonor called for spell_id %u , that rewards %d honor points to player: %u", m_spellInfo->Id, damage, ((Player*)unitTarget)->GetGUIDLow()); - - // TODO: find formula for honor reward based on player's level! + // not scale value for item based reward (/10 value expected) + if(m_CastItem) + { + ((Player*)unitTarget)->RewardHonor(NULL, 1, damage/10); + sLog.outError("SpellEffect::AddHonor (spell_id %u) rewards %d honor points (item %u) for player: %u", m_spellInfo->Id, damage/10, m_CastItem->GetEntry(),((Player*)unitTarget)->GetGUIDLow()); + return; + } - // now fixed only for level 70 players: - if (((Player*)unitTarget)->getLevel() == 70) + // do not allow to add too many honor for player (50 * 21) = 1040 at level 70, or (50 * 31) = 1550 at level 80 + if( damage <= 50) + { + uint32 honor_reward = MaNGOS::Honor::hk_honor_at_level(unitTarget->getLevel(), damage); + ((Player*)unitTarget)->RewardHonor(NULL, 1, honor_reward); + sLog.outDebug("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (scale) to player: %u", m_spellInfo->Id, honor_reward, ((Player*)unitTarget)->GetGUIDLow()); + } + else + { + //maybe we have correct honor_gain in damage already ((Player*)unitTarget)->RewardHonor(NULL, 1, damage); + sLog.outError("SpellEffect::AddHonor (spell_id %u) rewards %u honor points (non scale) for player: %u", m_spellInfo->Id, damage, ((Player*)unitTarget)->GetGUIDLow()); + } } void Spell::EffectTradeSkill(uint32 /*i*/) @@ -3719,7 +3772,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; @@ -3728,11 +3781,27 @@ void Spell::EffectEnchantItemPerm(uint32 i) Player* p_caster = (Player*)m_caster; - p_caster->UpdateCraftSkill(m_spellInfo->Id); - - if (m_spellInfo->EffectMiscValue[i]) + // Handle vellums + if (itemTarget->IsWeaponVellum() || itemTarget->IsArmorVellum()) { - uint32 enchant_id = m_spellInfo->EffectMiscValue[i]; + // destroy one vellum from stack + uint32 count=1; + p_caster->DestroyItemCount(itemTarget,count,true); + unitTarget=p_caster; + // and add a scroll + DoCreateItem(effect_idx,m_spellInfo->EffectItemType[effect_idx]); + itemTarget=NULL; + m_targets.setItemTarget(NULL); + } + else + { + // do not increase skill if vellum used + if (!(m_CastItem && m_CastItem->GetProto()->Flags & ITEM_FLAGS_TRIGGERED_CAST)) + p_caster->UpdateCraftSkill(m_spellInfo->Id); + + uint32 enchant_id = m_spellInfo->EffectMiscValue[effect_idx]; + if (!enchant_id) + return; SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id); if(!pEnchant) @@ -3761,6 +3830,64 @@ void Spell::EffectEnchantItemPerm(uint32 i) } } +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(uint8 i = 0; i < 3; ++i) + { + if(pEnchant->type[i]==ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET) + { + add_socket = true; + break; + } + } + if(!add_socket) + { + 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; + } + } + + // 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) ) + { + 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) { if(m_caster->GetTypeId() != TYPEID_PLAYER) @@ -3844,26 +3971,26 @@ void Spell::EffectEnchantItemTmp(uint32 i) uint32 duration; // rogue family enchantments exception by duration - if(m_spellInfo->Id==38615) + if(m_spellInfo->Id == 38615) duration = 1800; // 30 mins // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints) - else if(m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE) + else if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE) duration = 3600; // 1 hour // shaman family enchantments - else if(m_spellInfo->SpellFamilyName==SPELLFAMILY_SHAMAN) + 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) + else if(m_spellInfo->Id == 29702) duration = 300; // 5 mins - else if(m_spellInfo->Id==37360) + else if(m_spellInfo->Id == 37360) duration = 300; // 5 mins // default case else @@ -3877,18 +4004,18 @@ void Spell::EffectEnchantItemTmp(uint32 i) 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(temp): %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()); + 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,TEMP_ENCHANTMENT_SLOT,false); + item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT, false); - itemTarget->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, duration*1000, 0); + itemTarget->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, duration * 1000, 0); // add new enchanting if equipped - item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT,true); + item_owner->ApplyEnchantment(itemTarget, TEMP_ENCHANTMENT_SLOT, true); } void Spell::EffectTameCreature(uint32 /*i*/) @@ -3915,24 +4042,25 @@ void Spell::EffectTameCreature(uint32 /*i*/) finish(); Pet* pet = m_caster->CreateTamedPetFrom(creatureTarget,m_spellInfo->Id); - if(!pet) return; + if(!pet) // in versy specific state like near world end/etc. + return; + + // "kill" original creature + creatureTarget->ForcedDespawn(); - // kill original creature - creatureTarget->setDeathState(JUST_DIED); - 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); + m_caster->SetMinion(pet, true); if(m_caster->GetTypeId() == TYPEID_PLAYER) { @@ -3952,14 +4080,16 @@ void Spell::EffectSummonPet(uint32 i) owner = m_originalCaster->GetCharmerOrOwnerPlayerOrPlayerItself(); } + uint32 petentry = m_spellInfo->EffectMiscValue[i]; + if(!owner) { - EffectSummonWild(i); + SummonPropertiesEntry const *properties = sSummonPropertiesStore.LookupEntry(67); + if(properties) + SummonGuardian(petentry, properties); return; } - uint32 petentry = m_spellInfo->EffectMiscValue[i]; - Pet *OldSummon = owner->GetPet(); // if pet requested type already exist @@ -4009,10 +4139,6 @@ 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); - pet->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL)); - // generate new name for summon pet std::string new_name=objmgr.GeneratePetName(petentry); if(!new_name.empty()) @@ -4036,7 +4162,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); @@ -4045,6 +4170,9 @@ void Spell::EffectLearnPetSpell(uint32 i) void Spell::EffectTaunt(uint32 /*i*/) { + if (!unitTarget) + return; + // this effect use before aura Taunt apply for prevent taunt already attacking target // for spell as marked "non effective at already attacking target" if(!unitTarget || !unitTarget->CanHaveThreatList() @@ -4068,7 +4196,7 @@ void Spell::EffectTaunt(uint32 /*i*/) if(HostilReference* forcedVictim = unitTarget->getThreatManager().getOnlineContainer().getReferenceByTarget(m_caster)) unitTarget->getThreatManager().setCurrentVictim(forcedVictim); - if(((Creature*)unitTarget)->IsAIEnabled) + if(((Creature*)unitTarget)->IsAIEnabled && !((Creature*)unitTarget)->HasReactState(REACT_PASSIVE)) ((Creature*)unitTarget)->AI()->AttackStart(m_caster); } @@ -4086,7 +4214,7 @@ void Spell::SpellDamageWeaponDmg(uint32 i) // multiple weapon dmg effect workaround // execute only the last weapon damage // and handle all effects at once - for (int j = 0; j < 3; j++) + for (int j = 0; j < 3; ++j) { switch(m_spellInfo->Effect[j]) { @@ -4101,7 +4229,6 @@ void Spell::SpellDamageWeaponDmg(uint32 i) } // some spell specific modifiers - //float weaponDamagePercentMod = 1.0f; // applied to weapon damage (and to fixed effect damage bonus if customBonusDamagePercentMod not set float totalDamagePercentMod = 1.0f; // applied to final bonus+weapon damage int32 fixed_bonus = 0; int32 spell_bonus = 0; // bonus specific for spell @@ -4111,26 +4238,21 @@ 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; + SpellEntry const *spellInfo = NULL; uint32 stack = 0; - Unit::AuraList const& list = unitTarget->GetAurasByType(SPELL_AURA_MOD_RESISTANCE); - for(Unit::AuraList::const_iterator itr=list.begin();itr!=list.end();++itr) + if (AuraEffect * aur = unitTarget->GetAura(SPELL_AURA_MOD_RESISTANCE,SPELLFAMILY_WARRIOR,SPELLFAMILYFLAG_WARRIOR_SUNDERARMOR, 0, 0, m_caster->GetGUID())) { - SpellEntry const *proto = (*itr)->GetSpellProto(); - if(proto->SpellFamilyName == SPELLFAMILY_WARRIOR - && proto->SpellFamilyFlags == SPELLFAMILYFLAG_WARRIOR_SUNDERARMOR) - { - int32 duration = GetSpellDuration(proto); - (*itr)->SetAuraDuration(duration); - (*itr)->UpdateAuraDuration(); - stack = (*itr)->GetStackAmount(); - break; - } + aur->GetParentAura()->RefreshAura(); + spellInfo = aur->GetSpellProto(); + stack = aur->GetParentAura()->GetStackAmount(); } - for(int j = 0; j < 3; j++) + for(uint8 j = 0; j < 3; j++) { if(m_spellInfo->Effect[j] == SPELL_EFFECT_NORMALIZED_WEAPON_DMG) { @@ -4139,7 +4261,7 @@ void Spell::SpellDamageWeaponDmg(uint32 i) } } - if(stack < 5) + if(!spellInfo) { // get highest rank of the Sunder Armor spell const PlayerSpellMap& sp_list = ((Player*)m_caster)->GetSpellMap(); @@ -4149,68 +4271,104 @@ void Spell::SpellDamageWeaponDmg(uint32 i) if(!itr->second->active || itr->second->disabled || itr->second->state == PLAYERSPELL_REMOVED) continue; - SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first); - if (!spellInfo) + SpellEntry const *spellProto = sSpellStore.LookupEntry(itr->first); + if (!spellProto) continue; - if (spellInfo->SpellFamilyFlags == SPELLFAMILYFLAG_WARRIOR_SUNDERARMOR - && spellInfo->Id != m_spellInfo->Id - && spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR) + if (spellProto->SpellFamilyFlags[0] & SPELLFAMILYFLAG_WARRIOR_SUNDERARMOR + && spellProto->Id != m_spellInfo->Id + && spellProto->SpellFamilyName == SPELLFAMILY_WARRIOR) { - m_caster->CastSpell(unitTarget, spellInfo, true); + spellInfo = spellProto; break; } } } + if (!spellInfo) + break; + int32 count = 1; + // Glyph of Devastate + if (AuraEffect * aurEff = m_caster->GetDummyAura(58388)) + count += aurEff->GetAmount(); + for (;count>0;count--) + m_caster->CastSpell(unitTarget, spellInfo, true); + 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); + ((Player*)m_caster)->AddComboPoints(unitTarget, 1, this); + } + // Fan of Knives + else if(m_spellInfo->SpellFamilyFlags[1] & 0x40000) + { + // 50% more damage with daggers + if (Item* item = ((Player*)m_caster)->GetWeaponForAttack(m_attackType)) + if (item->GetProto()->SubClass == ITEM_SUBCLASS_WEAPON_DAGGER) + totalDamagePercentMod *= 1.5f; } // Mutilate (for each hand) - else if(m_spellInfo->SpellFamilyFlags & 0x600000000LL) + else if(m_spellInfo->SpellFamilyFlags[1] & 0x6) { - Unit::AuraMap const& auras = unitTarget->GetAuras(); - for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr) + bool found = false; + // fast check + if(unitTarget->HasAuraState(AURA_STATE_DEADLY_POISON, m_spellInfo, m_caster)) + found = true; + // full aura scan + else { - if(itr->second->GetSpellProto()->Dispel == DISPEL_POISON) + Unit::AuraMap const& auras = unitTarget->GetAuras(); + for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr) { - totalDamagePercentMod *= 1.5f; // 150% if poisoned - break; + if(itr->second->GetSpellProto()->Dispel == DISPEL_POISON) + { + found = true; + break; + } } } + + if(found) + 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)); } + + // Seal of Command Unleashed + else if(m_spellInfo->Id==20467) + { + spell_bonus += int32(0.16f*m_caster->GetTotalAttackPowerValue(BASE_ATTACK)); + spell_bonus += int32(0.25f*m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo))); + } break; } case SPELLFAMILY_SHAMAN: { // 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) + Unit::AuraEffectList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); + for(Unit::AuraEffectList::const_iterator citr = m_OverrideClassScript.begin(); citr != m_OverrideClassScript.end(); ++citr) { // Stormstrike AP Buff - if ( (*i)->GetModifier()->m_miscvalue == 5634 ) + if ( (*citr)->GetMiscValue() == 5634 ) { - m_caster->CastSpell(m_caster,38430,true,NULL,*i); + m_caster->CastSpell(m_caster, 38430, true, NULL, *citr); break; } } @@ -4220,13 +4378,33 @@ 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); + ((Player*)m_caster)->AddComboPoints(unitTarget,1, this); } break; } + case SPELLFAMILY_DEATHKNIGHT: + { + // Obliterate (12.5% more damage per disease) + if (m_spellInfo->SpellFamilyFlags[1] & 0x20000) + { + bool consumeDiseases = true; + // Annihilation + if (AuraEffect * aurEff = m_caster->GetDummyAura(SPELLFAMILY_DEATHKNIGHT, 2710)) + { + // Do not consume diseases if roll sucesses + if (roll_chance_i(aurEff->GetAmount())) + consumeDiseases = false; + } + totalDamagePercentMod *= (float(CalculateDamage(2, unitTarget) * unitTarget->GetDiseasesByCaster(m_caster->GetGUID(), consumeDiseases) / 2) + 100.0f) / 100.0f; + } + // Blood-Caked Strike - Blood-Caked Blade // Blood Strike + else if (m_spellInfo->SpellIconID == 1736 || m_spellInfo->SpellFamilyFlags[0] & 0x400000) + totalDamagePercentMod *= (float(unitTarget->GetDiseasesByCaster(m_caster->GetGUID())) * 12.5f + 100.0f) / 100.0f; + break; + } } bool normalized = false; @@ -4237,14 +4415,15 @@ void Spell::SpellDamageWeaponDmg(uint32 i) { case SPELL_EFFECT_WEAPON_DAMAGE: case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: - fixed_bonus += CalculateDamage(j,unitTarget); + fixed_bonus += CalculateDamage(j, unitTarget); break; case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: - fixed_bonus += CalculateDamage(j,unitTarget); + fixed_bonus += CalculateDamage(j, unitTarget); normalized = true; break; case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: weaponDamagePercentMod *= float(CalculateDamage(j,unitTarget)) / 100.0f; + break; default: break; // not weapon damage effect, just skip } @@ -4305,33 +4484,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*/) @@ -4352,23 +4504,13 @@ void Spell::EffectHealMaxHealth(uint32 /*i*/) if(!unitTarget->isAlive()) return; - uint32 addhealth = unitTarget->GetMaxHealth() - unitTarget->GetHealth(); - - // Lay on Hands - if(m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN && m_spellInfo->SpellFamilyFlags & 0x0000000000008000) - { - if(!m_originalCaster) - return; - addhealth = addhealth > m_originalCaster->GetMaxHealth() ? m_originalCaster->GetMaxHealth() : addhealth; - uint32 LoHamount = unitTarget->GetHealth() + m_originalCaster->GetMaxHealth(); - LoHamount = LoHamount > unitTarget->GetMaxHealth() ? unitTarget->GetMaxHealth() : LoHamount; - unitTarget->SetHealth(LoHamount); - } + int32 addhealth; + if(m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN) // Lay on Hands + addhealth = m_caster->GetMaxHealth(); else - unitTarget->SetHealth(unitTarget->GetMaxHealth()); - + addhealth = unitTarget->GetMaxHealth() - unitTarget->GetHealth(); if(m_originalCaster) - m_originalCaster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, false); + m_originalCaster->DealHeal(unitTarget, addhealth, m_spellInfo); } void Spell::EffectInterruptCast(uint32 i) @@ -4389,7 +4531,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, unitTarget, m_originalCaster->CalcSpellDuration(m_spellInfo), false); unitTarget->ProhibitSpellScholl(GetSpellSchoolMask(unitTarget->m_currentSpells[i]->m_spellInfo), duration/*GetSpellDuration(m_spellInfo)*/); } unitTarget->InterruptSpell(i,false); @@ -4408,7 +4550,7 @@ void Spell::EffectSummonObjectWild(uint32 i) if( !target ) target = m_caster; - float x,y,z; + float x, y, z; if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) { x = m_targets.m_destX; @@ -4416,19 +4558,19 @@ void Spell::EffectSummonObjectWild(uint32 i) z = m_targets.m_destZ; } else - m_caster->GetClosePoint(x,y,z,DEFAULT_WORLD_OBJECT_SIZE); + m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE); 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.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY)) { 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)... @@ -4469,9 +4611,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.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY)) { - linkedGO->SetRespawnTime(duration > 0 ? duration/1000 : 0); + linkedGO->SetRespawnTime(duration > 0 ? duration/IN_MILISECONDS : 0); linkedGO->SetSpellId(m_spellInfo->Id); m_caster->AddGameObject(linkedGO); @@ -4490,450 +4632,822 @@ 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(uint8 j = 0; j < 4; ++j) + if(unitTarget->HasAuraEffect(spells[j],0)) + return; - switch(m_caster->GetMap()->urand(0,3)) - { - case 0: - iTmpSpellId = 26272; + // select spell + uint32 iTmpSpellId = spells[urand(0,3)]; + + // cast + unitTarget->CastSpell(unitTarget, iTmpSpellId, true); + return; + } + // Bending Shinbone + case 8856: + { + if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER) + return; + + uint32 spell_id = 0; + switch(urand(1, 5)) + { + case 1: spell_id = 8854; break; + default: spell_id = 8855; break; + } + + m_caster->CastSpell(m_caster,spell_id,true,NULL); + return; + } + // Brittle Armor - need remove one 24575 Brittle Armor aura + case 24590: + unitTarget->RemoveAuraFromStack(24575); + return; + // Mercurial Shield - need remove one 26464 Mercurial Shield aura + case 26465: + unitTarget->RemoveAuraFromStack(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 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; + } + + 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; + + // Onyxia Scale Cloak + if(unitTarget->GetDummyAura(22683)) + return; + + // Shadow Flame + m_caster->CastSpell(unitTarget, 22682, true); + return; + } + // Summon Black Qiraji Battle Tank + case 26656: + { + if(!unitTarget) + return; + + // Prevent stacking of mounts + unitTarget->RemoveAurasByType(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); + return; + } + // Piccolo of the Flaming Fire + case 17512: + { + if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE); + return; + } + // Escape artist + case 20589: + { + if(!unitTarget) + return; + // It is said that removing effects by script should include dispel resist mods + unitTarget->RemoveAurasByTypeWithDispel(SPELL_AURA_MOD_ROOT, this); + unitTarget->RemoveAurasByTypeWithDispel(SPELL_AURA_MOD_DECREASE_SPEED, this); + return; + } + // Decimate + case 28374: + case 54426: + if(unitTarget) + { + int32 damage = (int32)unitTarget->GetHealth() - (int32)unitTarget->GetMaxHealth() * 0.05f; + if(damage > 0) + m_caster->CastCustomSpell(28375, SPELLVALUE_BASE_POINT0, damage, unitTarget); + } + return; + // 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; - case 1: - iTmpSpellId = 26157; + } + // 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();) + { + Aura *aur = iter->second; + if (!aur->IsPositive()) //only remove negative spells + { + // check for mechanic mask + if(GetAllSpellMechanicMask(aur->GetSpellProto()) & mechanic_mask) + { + unitTarget->RemoveAura(iter); + } + else + iter++; + } + else + iter++; + } break; - case 2: - iTmpSpellId = 26273; + } + case 38358: + if(unitTarget) + m_caster->CastSpell(unitTarget, 38353, true); + return; + /*// Flame Crash + case 41126: + { + if(!unitTarget) + return; + + unitTarget->CastSpell(unitTarget, 41131, true); break; - case 3: - iTmpSpellId = 26274; + }*/ + // Draw Soul + case 40904: + { + if(!unitTarget) + return; + + unitTarget->CastSpell(m_caster, 40903, true); break; - } + } + case 48025: // Headless Horseman's Mount + { + if(!unitTarget) + return; - unitTarget->CastSpell(unitTarget, iTmpSpellId, true); + 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; - 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; - // Bending Shinbone - case 8856: - { - if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER) - return; + int bag=19; + int slot=0; + Item* item = NULL; - uint32 spell_id = 0; - switch(m_caster->GetMap()->urand(1,5)) - { - case 1: spell_id = 8854; break; - default: spell_id = 8855; break; - } + 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; - m_caster->CastSpell(m_caster,spell_id,true,NULL); - return; - } + unitTarget->CastSpell(unitTarget, 44870, true); + break; + } + // spell of Brutallus - Stomp + case 45185: + { + if(!unitTarget) + 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) + if(unitTarget->HasAura(46394)) // spell of Brutallus - Burn + unitTarget->RemoveAurasDueToSpell(46394); + + break; + } + // Negative Energy + case 46289: { - rank = 1; + if(!unitTarget) + return; + + m_caster->CastSpell(unitTarget, 46285, true); break; - } - else if((*i)->GetId() == 18693) + } + // Goblin Weather Machine + case 46203: { - rank = 2; + if(!unitTarget) + return; + + uint32 spellId = 0; + 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; - 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 - }; + ((Player*)unitTarget)->ModifyMoney(5000 * GOLD); - 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; + break; + } + // Vigilance + case 50725: + { + if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + + // Remove Taunt cooldown + ((Player*)unitTarget)->RemoveSpellCooldown(355, true); - 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; - } + } + // Emblazon Runeblade + case 51770: + { + if(!m_originalCaster) + return; - unitTarget->CastSpell(unitTarget,spellid,false); - return; - } + m_originalCaster->CastSpell(m_originalCaster, damage, false); + break; + } + // Summon Ghouls On Scarlet Crusade + case 51904: + { + if(!m_targets.HasDst()) + 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; + float x, y, z; + float radius = GetSpellRadius(m_spellInfo, effIndex, true); + for(uint32 i = 0; i < 15; ++i) + { + m_caster->GetRandomPoint(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, radius, x, y, z); + m_caster->CastSpell(x, y, z, 54522, true); + } + break; + } + // Sky Darkener Assault + case 52124: + if(unitTarget) + m_caster->CastSpell(unitTarget, 52125, false); + return; + case 52479: // Gift of the Harvester + if(unitTarget && m_originalCaster) + m_originalCaster->CastSpell(unitTarget, urand(0, 1) ? damage : 52505, true); + return; + // 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; + } + case 53110: // Devour Humanoid + if(unitTarget) + unitTarget->CastSpell(m_caster, damage, true); + return; + // Winged Steed of the Ebon Blade + case 54729: + { + if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; - // Onyxia Scale Cloak - if(unitTarget->GetDummyAura(22683)) - return; + // Prevent stacking of mounts + unitTarget->RemoveAurasByType(SPELL_AURA_MOUNTED); - // Shadow Flame - m_caster->CastSpell(unitTarget, 22682, true); - return; - } - break; + // Triggered spell id dependent of riding skill + if(uint16 skillval = ((Player*)unitTarget)->GetSkillValue(SKILL_RIDING)) + { + if (skillval >= 300) + unitTarget->CastSpell(unitTarget, 54727, true); + else + unitTarget->CastSpell(unitTarget, 54726, true); + } + return; + } + case 58418: // Portal to Orgrimmar + case 58420: // Portal to Stormwind + { + if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER || effIndex!=0) + return; - // Summon Black Qiraji Battle Tank - case 26656: - { - if(!unitTarget) - return; + uint32 spellID = m_spellInfo->CalculateSimpleValue(0); + uint32 questID = m_spellInfo->CalculateSimpleValue(1); - // Prevent stacking of mounts - unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); + if (((Player*)unitTarget)->GetQuestStatus(questID) == QUEST_STATUS_COMPLETE && !((Player*)unitTarget)->GetQuestRewardStatus (questID)) + unitTarget->CastSpell(unitTarget, spellID, true); - // 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; + return; + } + case 58941: // Rock Shards + if(unitTarget && m_originalCaster) + { + for(uint32 i = 0; i < 3; ++i) + { + m_originalCaster->CastSpell(unitTarget, 58689, true); + m_originalCaster->CastSpell(unitTarget, 58692, true); + } + if(m_originalCaster->GetMap()->IsHeroic()) + { + m_originalCaster->CastSpell(unitTarget, 60883, true); + m_originalCaster->CastSpell(unitTarget, 60884, true); + } + else + { + m_originalCaster->CastSpell(unitTarget, 58695, true); + m_originalCaster->CastSpell(unitTarget, 58696, true); + } + } + return; + case 59317: // Teleporting + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; - // 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; + // return from top + if (((Player*)unitTarget)->GetAreaId() == 4637) + unitTarget->CastSpell(unitTarget, 59316, true); + // teleport atop + else + unitTarget->CastSpell(unitTarget, 59314, true); - // don't overwrite an existing aura - for(uint8 i=0; i<5; i++) - if(unitTarget->HasAura(spellid+i, 0)) return; - unitTarget->CastSpell(unitTarget, spellid+m_caster->GetMap()->urand(0, 4), true); - break; - } - - // 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; - } + // 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(m_caster->GetTypeId() != TYPEID_PLAYER) + return; - // Mirren's Drinking Hat - case 29830: - { - uint32 item = 0; - switch ( m_caster->GetMap()->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 + // learn random explicit discovery recipe (if any) + if(uint32 discoveredSpell = GetExplicitDiscoverySpell(m_spellInfo->Id, (Player*)m_caster)) + ((Player*)m_caster)->learnSpell(discoveredSpell, false); + return; + } + case 62428: // Load into Catapult + if(m_caster->m_Vehicle && m_caster->GetTypeId() == TYPEID_UNIT && ((Creature*)m_caster)->isVehicle()) + if(Unit *passenger = ((Vehicle*)m_caster)->GetPassenger(0)) + passenger->CastSpell(m_caster->m_Vehicle, damage, true); + 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::AuraEffectList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraEffectList::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; + 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 + }; - uint32 spellId; - switch((uint32)m_caster->GetMap()->rand32()%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) + 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 + case 47871: + itemtype=itypes[6][rank];break; // Demonic Healthstone + case 47878: + itemtype=itypes[7][rank];break; // Fel Healthstone + default: + return; + } + DoCreateItem( effIndex, itemtype ); return; - - if(unitTarget) + } + // Everlasting Affliction + case 47422: + // Refresh corruption on target + if (AuraEffect * aur = unitTarget->GetAura(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_WARLOCK, 0x2, 0, 0, m_caster->GetGUID())) + aur->GetParentAura()->RefreshAura(); + return; + // Demonic Empowerment + case 47193: { - switch(((Player*)unitTarget)->GetBaseSkillValue(762)) + if(!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || !((Creature *)unitTarget)->isPet()) + return; + CreatureInfo const * ci = objmgr.GetCreatureTemplate(unitTarget->GetEntry()); + switch (ci->family) { - 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 CREATURE_FAMILY_SUCCUBUS: + unitTarget->CastSpell(unitTarget, 54435, true); + break; + case CREATURE_FAMILY_VOIDWALKER: + { + SpellEntry const* spellInfo = sSpellStore.LookupEntry(54443); + int32 hp = unitTarget->GetMaxHealth() * m_caster->CalculateSpellDamage(spellInfo, 0, spellInfo->EffectBasePoints[0], unitTarget) /100; + unitTarget->CastCustomSpell(unitTarget, 54443,&hp, NULL, NULL,true); + //unitTarget->CastSpell(unitTarget, 54441, true); + break; + } + case CREATURE_FAMILY_FELGUARD: + unitTarget->CastSpell(unitTarget, 54508, true); + break; + case CREATURE_FAMILY_FELHUNTER: + unitTarget->CastSpell(unitTarget, 54509, true); + break; + case CREATURE_FAMILY_IMP: + unitTarget->CastSpell(unitTarget, 54444, true); + break; } + 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: + { + if (!unitTarget) + return; + // Refresh Shadow Word: Pain on target + if (AuraEffect * aur = unitTarget->GetAura(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, 0x8000, 0, 0, m_caster->GetGUID())) + aur->GetParentAura()->RefreshAura(); + return; + } + // Divine Hymn + case 47951: { - 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; + Unit * target=NULL; + unitTarget->CastSpell(target, 59600, false); + unitTarget->CastSpell(target, 47953, false); + 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) + // Invigoration + case 53412: { - slot = 0; - bag++; + if (AuraEffect * aurEff = unitTarget->GetDummyAura(SPELLFAMILY_HUNTER, 3487)) + { + if (roll_chance_i(aurEff->GetAmount())) + unitTarget->CastSpell(unitTarget, 53398, true); + } + break; } + // Heart of the Pheonix + case 55709: + { + int pct = 100; + if (unitTarget->GetTypeId()==TYPEID_UNIT && ((Creature*)unitTarget)->isPet()) + if (Unit* owner = ((Creature*)unitTarget)->GetOwner()) + owner->CastCustomSpell(unitTarget, 54114, &pct, NULL, NULL, true); + break; + } + // Chimera Shot + case 53209: + { + 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; + if (!aura->GetPartAura(0)) + continue; + + // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting. + if (familyFlag[0] & 0x4000) + { + spellId = 53353; // 53353 Chimera Shot - Serpent + basePoint = aura->GetPartAura(0)->GetAmount() * 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) + { + int32 tickCount = aura->GetPartAura(0)->GetTickNumber(); + spellId = 53358; // 53358 Chimera Shot - Viper + // Amount of one aura tick + basePoint = aura->GetPartAura(0)->GetAmount() * aura->GetTarget()->GetMaxPower(POWER_MANA) / 100 ; + int32 casterBasePoint = aura->GetPartAura(0)->GetAmount() * unitTarget->GetMaxPower(POWER_MANA) / 50 ; + if (basePoint > casterBasePoint) + basePoint = casterBasePoint; + basePoint = basePoint * tickCount * 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 + //} + + // Refresh aura duration + aura->RefreshAura(); + break; + } + if (spellId) + m_caster->CastCustomSpell(unitTarget, spellId, &basePoint, 0, 0, true); + 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; - // spell of Brutallus - Stomp - case 45185: - { - if(unitTarget->HasAura(46394, 0)) // spell of Brutallus - Burn - unitTarget->RemoveAurasDueToSpell(46394); - break; - } - // Negative Energy - case 46289: m_caster->CastSpell(unitTarget, 46285, 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 || m_spellInfo->SpellFamilyFlags[2] & 0x8) { + if(!unitTarget || !unitTarget->isAlive()) + return; + uint32 spellId1 = 0; uint32 spellId2 = 0; - // all seals have aura dummy - 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) + // Judgement self add switch + switch (m_spellInfo->Id) { - 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 ) - 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) - continue; - - // 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) + 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::AuraMap & sealAuras = m_caster->GetAuras(); + for(Unit::AuraMap::iterator iter = sealAuras.begin(); iter != sealAuras.end();) + { + if (IsSealSpell(iter->second->GetSpellProto())) { - if ((*i)->GetSpellProto()->SpellIconID == 205 && (*i)->GetSpellProto()->Attributes == 0x01D0LL) + if (AuraEffect * aureff = iter->second->GetPartAura(2)) + if (aureff->GetAuraName()==SPELL_AURA_DUMMY) + { + if (sSpellStore.LookupEntry(aureff->GetAmount())) + spellId2 = aureff->GetAmount(); + break; + } + if (!spellId2) { - int32 chance = (*i)->GetModifier()->m_amount; - if ( roll_chance_i(chance) ) + switch (iter->first) { - 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); + // Seal of light, Seal of wisdom, Seal of justice + case 20165: + case 20166: + case 20164: + spellId2 = 54158; } - break; } + break; } + else + ++iter; + } + 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; + + // 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->HasAuraEffect(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; + } + case SPELLFAMILY_DEATHKNIGHT: + { + // Pestilence + if ( m_spellInfo->SpellFamilyFlags[1]&0x10000 ) + { + // Get diseases on target of spell + if (m_targets.getUnitTarget() && // Glyph of Disease - cast on unit target too to refresh aura + (m_targets.getUnitTarget() != unitTarget || m_caster->GetAura(63334))) + { + // And spread them on target + // Blood Plague + if (m_targets.getUnitTarget()->GetAura(55078)) + m_caster->CastSpell(unitTarget, 55078, true); + // Frost Fever + if (m_targets.getUnitTarget()->GetAura(55095)) + m_caster->CastSpell(unitTarget, 55095, true); + } } + break; } } @@ -4949,7 +5463,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) { @@ -4969,9 +5483,9 @@ 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); + ((Player *)m_caster)->RemoveAurasByType(SPELL_AURA_MOD_ROOT); } } @@ -4986,7 +5500,7 @@ void Spell::EffectAddComboPoints(uint32 /*i*/) if(damage <= 0) return; - ((Player*)m_caster)->AddComboPoints(unitTarget, damage); + ((Player*)m_caster)->AddComboPoints(unitTarget, damage, this); } void Spell::EffectDuel(uint32 i) @@ -5004,6 +5518,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; @@ -5029,11 +5544,12 @@ 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(), - m_caster->GetOrientation(), 0, 0, 0, 0, 0, 1)) + m_caster->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY)) { delete pGameObj; return; @@ -5042,7 +5558,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); @@ -5050,9 +5566,9 @@ void Spell::EffectDuel(uint32 i) //END // Send request - WorldPacket data(SMSG_DUEL_REQUESTED, 16); - data << pGameObj->GetGUID(); - data << caster->GetGUID(); + WorldPacket data(SMSG_DUEL_REQUESTED, 8 + 8); + data << uint64(pGameObj->GetGUID()); + data << uint64(caster->GetGUID()); caster->GetSession()->SendPacket(&data); target->GetSession()->SendPacket(&data); @@ -5071,8 +5587,8 @@ void Spell::EffectDuel(uint32 i) duel2->startTimer = 0; target->duel = duel2; - caster->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID()); - target->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID()); + caster->SetUInt64Value(PLAYER_DUEL_ARBITER, pGameObj->GetGUID()); + target->SetUInt64Value(PLAYER_DUEL_ARBITER, pGameObj->GetGUID()); } void Spell::EffectStuck(uint32 /*i*/) @@ -5098,7 +5614,7 @@ void Spell::EffectStuck(uint32 /*i*/) SpellEntry const *spellInfo = sSpellStore.LookupEntry(8690); if(!spellInfo) return; - Spell spell(pTarget,spellInfo,true,0); + Spell spell(pTarget, spellInfo, true, 0); spell.SendSpellCooldown(); } @@ -5111,15 +5627,15 @@ void Spell::EffectSummonPlayer(uint32 /*i*/) if(unitTarget->GetDummyAura(23445)) return; - float x,y,z; - m_caster->GetClosePoint(x,y,z,unitTarget->GetObjectSize()); + float x, y, z; + m_caster->GetClosePoint(x, y, z, unitTarget->GetObjectSize()); ((Player*)unitTarget)->SetSummonPoint(m_caster->GetMapId(),x,y,z); 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); } @@ -5142,89 +5658,41 @@ void Spell::EffectActivateObject(uint32 effect_idx) sWorld.ScriptCommandStart(activateCommand, delay_secs, m_caster, gameObjTarget); } -void Spell::EffectSummonTotem(uint32 i) +void Spell::EffectApplyGlyph(uint32 i) { - uint8 slot = 0; - switch(m_spellInfo->EffectMiscValueB[i]) - { - case SUMMON_TYPE_TOTEM_SLOT1: slot = 0; break; - case SUMMON_TYPE_TOTEM_SLOT2: slot = 1; break; - case SUMMON_TYPE_TOTEM_SLOT3: slot = 2; break; - case SUMMON_TYPE_TOTEM_SLOT4: slot = 3; break; - // Battle standard case - case SUMMON_TYPE_TOTEM: slot = 254; break; - // jewelery statue case, like totem without slot - case SUMMON_TYPE_GUARDIAN: slot = 255; break; - default: return; - } - - if(slot < MAX_TOTEM) - { - uint64 guid = m_caster->m_TotemSlot[slot]; - if(guid != 0) - { - Creature *OldTotem = ObjectAccessor::GetCreature(*m_caster, guid); - if(OldTotem && OldTotem->isTotem()) - ((Totem*)OldTotem)->UnSummon(); - } - } - - uint32 team = 0; - if (m_caster->GetTypeId()==TYPEID_PLAYER) - team = ((Player*)m_caster)->GetTeam(); - - Totem* pTotem = new Totem; - - if(!pTotem->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), m_caster->GetMap(), m_spellInfo->EffectMiscValue[i], team )) - { - delete pTotem; + if(m_caster->GetTypeId() != TYPEID_PLAYER) return; - } - - float angle = slot < MAX_TOTEM ? M_PI/MAX_TOTEM - (slot*2*M_PI/MAX_TOTEM) : 0; - - float x,y,z; - m_caster->GetClosePoint(x,y,z,pTotem->GetObjectSize(),2.0f,angle); - - // totem must be at same Z in case swimming caster and etc. - if( fabs( z - m_caster->GetPositionZ() ) > 5 ) - z = m_caster->GetPositionZ(); - - pTotem->Relocate(x, y, z, m_caster->GetOrientation()); - - if(slot < MAX_TOTEM) - m_caster->m_TotemSlot[slot] = pTotem->GetGUID(); - pTotem->SetOwner(m_caster->GetGUID()); - pTotem->SetTypeBySummonSpell(m_spellInfo); // must be after Create call where m_spells initilized - - int32 duration=GetSpellDuration(m_spellInfo); - if(Player* modOwner = m_caster->GetSpellModOwner()) - modOwner->ApplySpellMod(m_spellInfo->Id,SPELLMOD_DURATION, duration); - pTotem->SetDuration(duration); + Player *player = (Player*)m_caster; - if (damage) // if not spell info, DB values used + // apply new one + if(uint32 glyph = m_spellInfo->EffectMiscValue[i]) { - pTotem->SetMaxHealth(damage); - pTotem->SetHealth(damage); - } - - 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(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 mismatch + } + } - pTotem->Summon(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); + } + } - if(slot < MAX_TOTEM && m_caster->GetTypeId() == TYPEID_PLAYER) - { - WorldPacket data(SMSG_TOTEM_CREATED, 1+8+4+4); - data << uint8(slot); - data << uint64(pTotem->GetGUID()); - data << uint32(duration); - data << uint32(m_spellInfo->Id); - ((Player*)m_caster)->SendDirectMessage(&data); + player->CastSpell(m_caster, gp->SpellId, true); + player->SetGlyph(m_glyphIndex, glyph); + player->SendTalentsInfoData(false); + } } } @@ -5265,8 +5733,8 @@ void Spell::EffectEnchantHeldItem(uint32 i) return; // Apply the temporary enchantment - item->SetEnchantment(slot, enchant_id, duration*1000, 0); - item_owner->ApplyEnchantment(item,slot,true); + item->SetEnchantment(slot, enchant_id, duration*IN_MILISECONDS, 0); + item_owner->ApplyEnchantment(item, slot, true); } } @@ -5298,7 +5766,7 @@ void Spell::EffectInebriate(uint32 /*i*/) currentDrunk = 0xFFFF; else currentDrunk += drunkMod; - player->SetDrunkValue(currentDrunk, m_CastItem?m_CastItem->GetEntry():0); + player->SetDrunkValue(currentDrunk, m_CastItem ? m_CastItem->GetEntry() : 0); } void Spell::EffectFeedPet(uint32 i) @@ -5308,7 +5776,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(); @@ -5318,15 +5787,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*/) @@ -5334,13 +5803,13 @@ void Spell::EffectDismissPet(uint32 /*i*/) if(m_caster->GetTypeId() != TYPEID_PLAYER) return; - Pet* pet = m_caster->GetPet(); + Pet* pet = ((Player*)m_caster)->GetPet(); // not let dismiss dead pet if(!pet||!pet->isAlive()) return; - ((Player*)m_caster)->RemovePet(pet,PET_SAVE_NOT_IN_SLOT); + ((Player*)m_caster)->RemovePet(pet, PET_SAVE_NOT_IN_SLOT); } void Spell::EffectSummonObject(uint32 i) @@ -5362,18 +5831,21 @@ void Spell::EffectSummonObject(uint32 i) { GameObject* obj = NULL; if( m_caster ) - obj = ObjectAccessor::GetGameObject(*m_caster, guid); + obj = m_caster->GetMap()->GetGameObject(guid); - if(obj) obj->Delete(); + if(obj) + { + // Recast case - null spell id to make auras not be removed on object remove from world + if (m_spellInfo->Id == obj->GetSpellId()) + obj->SetSpellId(0); + obj->Delete(); + } m_caster->m_ObjectSlot[slot] = 0; } GameObject* pGameObj = new GameObject; - float rot2 = sin(m_caster->GetOrientation()/2); - float rot3 = cos(m_caster->GetOrientation()/2); - - float x,y,z; + float x, y, z; // If dest location if present if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) { @@ -5383,10 +5855,11 @@ void Spell::EffectSummonObject(uint32 i) } // Summon in random point all other units if location present else - m_caster->GetClosePoint(x,y,z,DEFAULT_WORLD_OBJECT_SIZE); + 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.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY)) { delete pGameObj; return; @@ -5394,14 +5867,14 @@ 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); map->Add(pGameObj); WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8); - data << pGameObj->GetGUID(); - m_caster->SendMessageToSet(&data,true); + data << uint64(pGameObj->GetGUID()); + m_caster->SendMessageToSet(&data, true); m_caster->m_ObjectSlot[slot] = pGameObj->GetGUID(); } @@ -5457,8 +5930,8 @@ void Spell::EffectAddExtraAttacks(uint32 /*i*/) if(!unitTarget || !unitTarget->isAlive()) return; - //if( unitTarget->m_extraAttacks ) - // return; + if( unitTarget->m_extraAttacks ) + return; Unit *victim = unitTarget->getVictim(); @@ -5478,18 +5951,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) @@ -5501,7 +5970,7 @@ void Spell::EffectMomentMove(uint32 i) return; uint32 mapid = m_caster->GetMapId(); - float dist = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); + float dist = m_caster->GetSpellRadiusForTarget(unitTarget, sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); float x,y,z; float destx,desty,destz,ground,floor; float orientation = unitTarget->GetOrientation(), step = dist/10.0f; @@ -5540,11 +6009,7 @@ void Spell::EffectMomentMove(uint32 i) { return; } - - if(unitTarget->GetTypeId() == TYPEID_PLAYER) - ((Player*)unitTarget)->TeleportTo(mapid, destx, desty, destz+0.07531f, unitTarget->GetOrientation(), TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0)); - else - unitTarget->GetMap()->CreatureRelocation((Creature*)unitTarget, destx, desty, destz,unitTarget->GetOrientation()); + unitTarget->NearTeleportTo(destx, desty, destz + 0.07531, orientation, unitTarget==m_caster); } @@ -5564,7 +6029,7 @@ void Spell::EffectReputation(uint32 i) if(!factionEntry) return; - _player->ModifyFactionReputation(factionEntry,rep_change); + _player->GetReputationMgr().ModifyReputation(factionEntry, rep_change); } void Spell::EffectQuestComplete(uint32 i) @@ -5658,97 +6123,11 @@ void Spell::EffectCharge(uint32 /*i*/) m_caster->Attack(target, true); } -void Spell::EffectSummonCritter(uint32 i) -{ - if(m_caster->GetTypeId() != TYPEID_PLAYER) - return; - Player* player = (Player*)m_caster; - - uint32 pet_entry = m_spellInfo->EffectMiscValue[i]; - if(!pet_entry) - return; - - Pet* old_critter = player->GetMiniPet(); - - // for same pet just despawn - if(old_critter && old_critter->GetEntry() == pet_entry) - { - player->RemoveMiniPet(); - return; - } - - // despawn old pet before summon new - if(old_critter) - player->RemoveMiniPet(); - - // summon new pet - Pet* critter = new Pet(MINI_PET); - - Map *map = m_caster->GetMap(); - uint32 pet_number = objmgr.GeneratePetNumber(); - if(!critter->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), - map, pet_entry, pet_number)) - { - sLog.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo->Id, pet_entry); - delete critter; - return; - } - - float x,y,z; - // If dest location if present - if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) - { - x = m_targets.m_destX; - y = m_targets.m_destY; - z = m_targets.m_destZ; - } - // Summon if dest location not present near caster - else - m_caster->GetClosePoint(x,y,z,critter->GetObjectSize()); - - critter->Relocate(x,y,z,m_caster->GetOrientation()); - - if(!critter->IsPositionValid()) - { - sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %f Y: %f)", - critter->GetGUIDLow(), critter->GetEntry(), critter->GetPositionX(), critter->GetPositionY()); - delete critter; - return; - } - - critter->SetOwnerGUID(m_caster->GetGUID()); - critter->SetCreatorGUID(m_caster->GetGUID()); - critter->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction()); - critter->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id); - - critter->AIM_Initialize(); - critter->InitPetCreateSpells(); // e.g. disgusting oozeling has a create spell as critter... - critter->SetMaxHealth(1); - critter->SetHealth(1); - critter->SetLevel(1); - - // set timer for unsummon - int32 duration = GetSpellDuration(m_spellInfo); - if(duration > 0) - critter->SetDuration(duration); - - std::string name = player->GetName(); - name.append(petTypeSuffix[critter->getPetType()]); - critter->SetName( name ); - player->SetMiniPet(critter); - - map->Add((Creature*)critter); -} - void Spell::EffectKnockBack(uint32 i) { if(!unitTarget) return; - // Effect only works on players - if(unitTarget->GetTypeId()!=TYPEID_PLAYER) - return; - float x, y; if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) { @@ -5761,31 +6140,26 @@ void Spell::EffectKnockBack(uint32 i) y = m_caster->GetPositionY(); } - float dx = unitTarget->GetPositionX() - x; - float dy = unitTarget->GetPositionY() - y; - float vcos, vsin; - if(dx < 0.001f && dy < 0.001f) + float speedxy = float(m_spellInfo->EffectMiscValue[i])/10; + float speedz = float(damage/10); + + unitTarget->KnockbackFrom(x, y, speedxy, speedz); +} + +void Spell::EffectJump2(uint32 i) +{ + float speedxy = float(m_spellInfo->EffectMiscValue[i])/10; + float speedz = float(damage/10); + if(!speedxy) { - float angle = m_caster->GetMap()->rand_norm()*2*M_PI; - vcos = cos(angle); - vsin = sin(angle); + if(m_targets.getUnitTarget()) + m_caster->JumpTo(m_targets.getUnitTarget(), speedz); } else { - float dist = sqrt((dx*dx) + (dy*dy)); - vcos = dx / dist; - vsin = dy / dist; + //1891: Disengage + m_caster->JumpTo(speedxy, speedz, m_spellInfo->SpellIconID != 1891); } - - 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) - - ((Player*)unitTarget)->GetSession()->SendPacket(&data); } void Spell::EffectSendTaxi(uint32 i) @@ -5793,38 +6167,7 @@ void Spell::EffectSendTaxi(uint32 i) if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; - TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(m_spellInfo->EffectMiscValue[i]); - if(!entry) - return; - - std::vector<uint32> nodes; - - nodes.resize(2); - nodes[0] = entry->from; - nodes[1] = entry->to; - - uint32 mountid = 0; - switch(m_spellInfo->Id) - { - 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 - mountid = 22840; - break; - case 34905: //Stealth Flight - mountid = 6851; - break; - case 41533: //Fly of the Netherwing - case 41540: //Fly of the Netherwing - mountid = 23468; - break; - } - - ((Player*)unitTarget)->ActivateTaxiPathTo(nodes,mountid); - + ((Player*)unitTarget)->ActivateTaxiPathTo(m_spellInfo->EffectMiscValue[i],m_spellInfo->Id); } void Spell::EffectPlayerPull(uint32 i) @@ -5839,7 +6182,7 @@ void Spell::EffectPlayerPull(uint32 i) float vsin = sin(unitTarget->GetAngle(m_caster)); float vcos = cos(unitTarget->GetAngle(m_caster)); - WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4)); + 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 @@ -5858,22 +6201,21 @@ void Spell::EffectDispelMechanic(uint32 i) uint32 mechanic = m_spellInfo->EffectMiscValue[i]; + std::queue < std::pair < uint32, uint64 > > 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(); iter != Auras.end(); iter++) { - next = iter; - ++next; - SpellEntry const *spell = sSpellStore.LookupEntry(iter->second->GetSpellProto()->Id); - if(spell->Mechanic == mechanic || spell->EffectMechanic[iter->second->GetEffIndex()] == mechanic) - { - unitTarget->RemoveAurasDueToSpell(spell->Id); - if(Auras.empty()) - break; - else - next = Auras.begin(); - } + if((GetAllSpellMechanicMask(iter->second->GetSpellProto()) & (1<<(mechanic))) && GetDispelChance(iter->second->GetCaster(), iter->second->GetId())) + { + dispel_list.push(std::make_pair(iter->second->GetId(), iter->second->GetCasterGUID() ) ); + } + } + + for(;dispel_list.size();dispel_list.pop()) + { + unitTarget->RemoveAura(dispel_list.front().first, dispel_list.front().second, AURA_REMOVE_BY_ENEMY_SPELL); } - return; } void Spell::EffectSummonDeadPet(uint32 /*i*/) @@ -5888,39 +6230,43 @@ void Spell::EffectSummonDeadPet(uint32 /*i*/) return; if(damage < 0) return; + pet->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0); pet->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); pet->setDeathState( ALIVE ); pet->clearUnitState(UNIT_STAT_ALL_STATE); pet->SetHealth( uint32(pet->GetMaxHealth()*(float(damage)/100))); - pet->AIM_Initialize(); - - _player->PetSpellInitialize(); + //pet->AIM_Initialize(); + //_player->PetSpellInitialize(); pet->SavePetToDB(PET_SAVE_AS_CURRENT); } void Spell::EffectDestroyAllTotems(uint32 /*i*/) { - float mana = 0; - for(int slot = 0; slot < MAX_TOTEM; ++slot) + int32 mana = 0; + for(uint8 slot = SUMMON_SLOT_TOTEM; slot < MAX_TOTEM_SLOT; ++slot) { - if(!m_caster->m_TotemSlot[slot]) + if(!m_caster->m_SummonSlot[slot]) continue; - Creature* totem = ObjectAccessor::GetCreature(*m_caster,m_caster->m_TotemSlot[slot]); + Creature* totem = m_caster->GetMap()->GetCreature(m_caster->m_SummonSlot[slot]); if(totem && totem->isTotem()) { uint32 spell_id = totem->GetUInt32Value(UNIT_CREATED_BY_SPELL); SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id); if(spellInfo) - mana += spellInfo->manaCost * damage / 100; + { + mana += spellInfo->manaCost; + mana += spellInfo->ManaCostPercentage * m_caster->GetCreateMana() / 100; + } ((Totem*)totem)->UnSummon(); } } + mana = mana * damage / 100; - int32 gain = m_caster->ModifyPower(POWER_MANA,int32(mana)); - m_caster->SendEnergizeSpellLog(m_caster, m_spellInfo->Id, gain, POWER_MANA); + if (mana) + m_caster->CastCustomSpell(m_caster, 39104, &mana, NULL, NULL, true); } void Spell::EffectDurabilityDamage(uint32 i) @@ -5934,7 +6280,7 @@ void Spell::EffectDurabilityDamage(uint32 i) // Possibly its mean -1 all player equipped items and -2 all items if(slot < 0) { - ((Player*)unitTarget)->DurabilityPointsLossAll(damage,(slot < -1)); + ((Player*)unitTarget)->DurabilityPointsLossAll(damage, (slot < -1)); return; } @@ -5942,8 +6288,8 @@ void Spell::EffectDurabilityDamage(uint32 i) if(slot >= INVENTORY_SLOT_BAG_END) return; - if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0,slot)) - ((Player*)unitTarget)->DurabilityPointsLoss(item,damage); + if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0, slot)) + ((Player*)unitTarget)->DurabilityPointsLoss(item, damage); } void Spell::EffectDurabilityDamagePCT(uint32 i) @@ -5957,7 +6303,7 @@ void Spell::EffectDurabilityDamagePCT(uint32 i) // Possibly its mean -1 all player equipped items and -2 all items if(slot < 0) { - ((Player*)unitTarget)->DurabilityLossAll(double(damage)/100.0f,(slot < -1)); + ((Player*)unitTarget)->DurabilityLossAll(double(damage)/100.0f, (slot < -1)); return; } @@ -5968,8 +6314,8 @@ void Spell::EffectDurabilityDamagePCT(uint32 i) if(damage <= 0) return; - if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0,slot)) - ((Player*)unitTarget)->DurabilityLoss(item,double(damage)/100.0f); + if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0, slot)) + ((Player*)unitTarget)->DurabilityLoss(item, double(damage)/100.0f); } void Spell::EffectModifyThreatPercent(uint32 /*effIndex*/) @@ -5992,7 +6338,7 @@ void Spell::EffectTransmitted(uint32 effIndex) return; } - float fx,fy,fz; + float fx, fy, fz; if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) { @@ -6003,23 +6349,24 @@ 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])); - m_caster->GetClosePoint(fx,fy,fz,DEFAULT_WORLD_OBJECT_SIZE, dis); + 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)); - float dis = m_caster->GetMap()->rand_norm() * (max_dis - min_dis) + min_dis; + //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); + m_caster->GetClosePoint(fx, fy, fz, DEFAULT_WORLD_OBJECT_SIZE, dis); } Map *cMap = m_caster->GetMap(); if(goinfo->type==GAMEOBJECT_TYPE_FISHINGNODE) { - if ( !cMap->IsInWater(fx,fy,fz-0.5f)) // Hack to prevent fishing bobber from failing to land on fishing hole + if ( !cMap->IsInWater(fx, fy, fz-0.5f)) // Hack to prevent fishing bobber from failing to land on fishing hole { // but this is not proper, we really need to ignore not materialized objects SendCastResult(SPELL_FAILED_NOT_HERE); SendChannelUpdate(0); @@ -6027,18 +6374,18 @@ void Spell::EffectTransmitted(uint32 effIndex) } // replace by water level in this case - fz = cMap->GetWaterLevel(fx,fy); + fz = cMap->GetWaterLevel(fx, fy); } // if gameobject is summoning object, it should be spawned right on caster's position else if(goinfo->type==GAMEOBJECT_TYPE_SUMMONING_RITUAL) { - m_caster->GetPosition(fx,fy,fz); + m_caster->GetPosition(fx, fy, fz); } 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.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY)) { delete pGameObj; return; @@ -6051,16 +6398,12 @@ void Spell::EffectTransmitted(uint32 effIndex) case GAMEOBJECT_TYPE_FISHINGNODE: { m_caster->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT,pGameObj->GetGUID()); - // Orientation3 - pGameObj->SetFloatValue(GAMEOBJECT_ROTATION + 2, 0.88431775569915771 ); - // Orientation4 - pGameObj->SetFloatValue(GAMEOBJECT_ROTATION + 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)) // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME) - int32 lastSec; - switch(m_caster->GetMap()->urand(0, 3)) + int32 lastSec = 0; + switch(urand(0, 3)) { case 0: lastSec = 3; break; case 1: lastSec = 7; break; @@ -6068,12 +6411,12 @@ 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: { - if(m_caster->GetTypeId()==TYPEID_PLAYER) + if(m_caster->GetTypeId() == TYPEID_PLAYER) { pGameObj->AddUniqueUse((Player*)m_caster); m_caster->AddGameObject(pGameObj); // will removed at spell cancel @@ -6088,14 +6431,14 @@ 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() ); //pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() ); pGameObj->SetSpellId(m_spellInfo->Id); - DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted\n"); + DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted"); //m_caster->AddGameObject(pGameObj); //m_ObjToDel.push_back(pGameObj); @@ -6109,9 +6452,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.0f, 0.0f, 0.0f, 0.0f, 100, GO_STATE_READY)) { - 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() ); @@ -6149,6 +6492,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"); @@ -6156,26 +6521,34 @@ void Spell::EffectSkill(uint32 /*i*/) void Spell::EffectSummonDemon(uint32 i) { - float px = m_targets.m_destX; - float py = m_targets.m_destY; - float pz = m_targets.m_destZ; + float radius = GetSpellRadiusForFriend(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); - Creature* Charmed = m_caster->SummonCreature(m_spellInfo->EffectMiscValue[i], px, py, pz, m_caster->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,3600000); - if (!Charmed) - return; + int32 amount = damage > 0 ? damage : 1; - // might not always work correctly, maybe the creature that dies from CoD casts the effect on itself and is therefore the caster? - Charmed->SetLevel(m_caster->getLevel()); + for(uint32 count = 0; count < amount; ++count) + { + float px, py, pz; + GetSummonPosition(i, px, py, pz, radius, count); - // TODO: Add damage/mana/hp according to level + int32 duration = GetSpellDuration(m_spellInfo); - if (m_spellInfo->EffectMiscValue[i] == 89) // Inferno summon - { - // Enslave demon effect, without mana cost and cooldown - m_caster->CastSpell(Charmed, 20882, true); // FIXME: enslave does not scale with level, level 62+ minions cannot be enslaved + Creature* Charmed = m_caster->SummonCreature(m_spellInfo->EffectMiscValue[i], px, py, pz, m_caster->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,duration); + if (!Charmed) // something fatal, not attempt more + return; + + // might not always work correctly, maybe the creature that dies from CoD casts the effect on itself and is therefore the caster? + Charmed->SetLevel(m_caster->getLevel()); + + // TODO: Add damage/mana/hp according to level + + if (m_spellInfo->EffectMiscValue[i] == 89) // Inferno summon + { + // Enslave demon effect, without mana cost and cooldown + m_caster->CastSpell(Charmed, 20882, true); // FIXME: enslave does not scale with level, level 62+ minions cannot be enslaved - // Inferno effect - Charmed->CastSpell(Charmed, 22703, true, 0); + // Inferno effect + Charmed->CastSpell(Charmed, 22703, true, 0); + } } } @@ -6217,7 +6590,7 @@ void Spell::EffectStealBeneficialBuff(uint32 i) if(!unitTarget || unitTarget==m_caster) // can't steal from self return; - std::vector <Aura *> steal_list; + std::list <Aura *> steal_list; // Create dispel mask by dispel type uint32 dispelMask = GetDispellMask( DispelType(m_spellInfo->EffectMiscValue[i]) ); Unit::AuraMap const& auras = unitTarget->GetAuras(); @@ -6227,53 +6600,38 @@ void Spell::EffectStealBeneficialBuff(uint32 i) if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask) { // Need check for passive? this - if (aur->IsPositive() && !aur->IsPassive()) + if (aur->IsPositive() && !aur->IsPassive() && !(aur->GetSpellProto()->AttributesEx4 & SPELL_ATTR_EX4_NOT_STEALABLE)) steal_list.push_back(aur); } } // Ok if exist some buffs for dispel try dispel it - if (!steal_list.empty()) + if (uint32 list_size = steal_list.size()) { - std::list < std::pair<uint32,uint64> > success_list; - int32 list_size = steal_list.size(); + std::list < Aura * > success_list; + // dispel N = damage buffs (or while exist buffs for dispel) - for (int32 count=0; count < damage && list_size > 0; ++count) + for (int32 count=0; count < damage && list_size > 0; ++count, list_size = steal_list.size()) { // Random select buff for dispel - Aura *aur = steal_list[m_caster->GetMap()->urand(0, list_size-1)]; - // Not use chance for steal - // TODO possible need do it - success_list.push_back( std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID())); - - // Remove buff from list for prevent doubles - for (std::vector<Aura *>::iterator j = steal_list.begin(); j != steal_list.end(); ) - { - Aura *stealed = *j; - if (stealed->GetId() == aur->GetId() && stealed->GetCasterGUID() == aur->GetCasterGUID()) - { - j = steal_list.erase(j); - --list_size; - } - else - ++j; - } + std::list < Aura * > ::iterator itr = steal_list.begin(); + for (uint32 i=urand(0, list_size-1);i>0;--i) + itr++; + success_list.push_back(*itr); + steal_list.erase(itr); } - // Really try steal and send log - if (!success_list.empty()) + if (success_list.size()) { - int32 count = success_list.size(); - WorldPacket data(SMSG_SPELLSTEALLOG, 8+8+4+1+4+count*5); + WorldPacket data(SMSG_SPELLSTEALLOG, 8+8+4+1+4+damage*5); data.append(unitTarget->GetPackGUID()); // Victim GUID data.append(m_caster->GetPackGUID()); // Caster GUID data << uint32(m_spellInfo->Id); // dispel spell id data << uint8(0); // not used - data << uint32(count); // count - for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j) + data << uint32(success_list.size()); // count + for (std::list < Aura * > ::iterator itr = success_list.begin();itr!=success_list.end();++itr) { - SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first); - data << uint32(spellInfo->Id); // Spell Id + data << uint32((*itr)->GetId()); // Spell Id data << uint8(0); // 0 - steals !=0 transfers - unitTarget->RemoveAurasDueToSpellBySteal(spellInfo->Id, j->second, m_caster); + unitTarget->RemoveAurasDueToSpellBySteal((*itr)->GetId(), (*itr)->GetCasterGUID(), m_caster); } m_caster->SendMessageToSet(&data, true); } @@ -6285,7 +6643,15 @@ void Spell::EffectKillCredit(uint32 i) if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; - ((Player*)unitTarget)->KilledMonster(m_spellInfo->EffectMiscValue[i], 0); + int32 creatureEntry = m_spellInfo->EffectMiscValue[i]; + if(!creatureEntry) + { + if(m_spellInfo->Id == 42793) // Burn Body + creatureEntry = 24008; // Fallen Combatant + } + + if(creatureEntry) + ((Player*)unitTarget)->RewardPlayerAndGroupAtEvent(creatureEntry, unitTarget); } void Spell::EffectQuestFail(uint32 i) @@ -6296,9 +6662,147 @@ 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(100, unitTarget->GetGUID()); + m_caster->SetReducedThreatPercent((uint32)damage, unitTarget->GetGUID()); +} + +void Spell::EffectWMODamage(uint32 /*i*/) +{ + if(gameObjTarget && gameObjTarget->GetGoType() == GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING) + gameObjTarget->TakenDamage((uint32)damage); +} + +void Spell::EffectWMORepair(uint32 /*i*/) +{ + if(gameObjTarget && gameObjTarget->GetGoType() == GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING) + gameObjTarget->Rebuild(); +} + +void Spell::SummonGuardian(uint32 entry, SummonPropertiesEntry const *properties) +{ + Unit *caster = m_originalCaster; + if(caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem()) + caster = ((Totem*)caster)->GetOwner(); + if(!caster) + return; + + // in another case summon new + uint32 level = caster->getLevel(); + + // level of pet summoned using engineering item based at engineering skill level + if(m_CastItem && caster->GetTypeId() == TYPEID_PLAYER) + { + ItemPrototype const *proto = m_CastItem->GetProto(); + if(proto && proto->RequiredSkill == SKILL_ENGINERING) + { + uint16 skill202 = ((Player*)caster)->GetSkillValue(SKILL_ENGINERING); + if(skill202) + { + level = skill202/5; + } + } + } + + //float radius = GetSpellRadiusForFriend(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); + float radius = 5.0f; + int32 amount = damage > 0 ? damage : 1; + switch(m_spellInfo->Id) + { + case 1122: // Inferno + break; + } + int32 duration = GetSpellDuration(m_spellInfo); + TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN; + Map *map = caster->GetMap(); + + for(uint32 count = 0; count < amount; ++count) + { + float px, py, pz; + GetSummonPosition(0, px, py, pz, radius, count); + + TempSummon *summon = map->SummonCreature(entry, px, py, pz, m_caster->GetOrientation(), properties, duration, caster); + if(!summon) + return; + + if(summon->HasSummonMask(SUMMON_MASK_GUARDIAN)) + ((Guardian*)summon)->InitStatsForLevel(level); + + summon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id); + + summon->AI()->EnterEvadeMode(); + } +} + +void Spell::GetSummonPosition(uint32 i, float &x, float &y, float &z, float radius, uint32 count) +{ + if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) + { + // Summon 1 unit in dest location + if (count == 0) + { + x = m_targets.m_destX; + y = m_targets.m_destY; + z = m_targets.m_destZ; + } + // Summon in random point all other units if location present + else + { + //This is a workaround. Do not have time to write much about it + switch(m_spellInfo->EffectImplicitTargetA[i]) + { + case TARGET_MINION: + case TARGET_DEST_CASTER_RANDOM: + m_caster->GetGroundPointAroundUnit(x, y, z, radius * rand_norm(), rand_norm()*2*M_PI); + break; + case TARGET_DEST_DEST_RANDOM: + case TARGET_DEST_TARGET_RANDOM: + m_caster->GetRandomPoint(m_targets.m_destX,m_targets.m_destY,m_targets.m_destZ,radius,x,y,z); + break; + default: + x = m_targets.m_destX; + y = m_targets.m_destY; + z = m_targets.m_destZ; + break; + } + } + } + // Summon if dest location not present near caster + else + m_caster->GetClosePoint(x,y,z,3.0f); } +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); +}
\ No newline at end of file |