Files
CypherCore/Game/Spells/SpellInfo.cs
T
hondacrx 3bc1b07889 Defined TARGET_GAMEOBJECT_CONE_109
Fixed SpellPowerEntry structure * ManaCosts are signed
2017-07-27 17:31:01 -04:00

3696 lines
205 KiB
C#

/*
* Copyright (C) 2012-2017 CypherCore <http://github.com/CypherCore>
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using Framework.Constants;
using Framework.Dynamic;
using Game.BattleGrounds;
using Game.Conditions;
using Game.DataStorage;
using Game.Entities;
using Game.Maps;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Game.Spells
{
public class SpellInfo
{
public SpellInfo(SpellInfoLoadHelper data, Dictionary<uint, SpellEffectRecord[]> effectsMap, MultiMap<uint, SpellXSpellVisualRecord> visuals, Dictionary<uint, SpellEffectScalingRecord> effectScaling)
{
Id = data.Entry.Id;
_effects = new Dictionary<uint, SpellEffectInfo[]>();
// SpellDifficultyEntry
if (effectsMap != null)
{
foreach (var pair in effectsMap)
{
if (!_effects.ContainsKey(pair.Key))
_effects[pair.Key] = new SpellEffectInfo[pair.Value.Length];
for (int i = 0; i < pair.Value.Length; ++i)
{
SpellEffectRecord effect = pair.Value[i];
if (effect == null)
continue;
var scaling = effectScaling.LookupByKey(effect.Id);
_effects[pair.Key][effect.EffectIndex] = new SpellEffectInfo(scaling, this, effect.EffectIndex, effect);
}
}
}
SpellName = data.Entry.Name;
SpellMiscRecord _misc = data.Misc;
if (_misc != null)
{
Attributes = (SpellAttr0)_misc.Attributes;
AttributesEx = (SpellAttr1)_misc.AttributesEx;
AttributesEx2 = (SpellAttr2)_misc.AttributesExB;
AttributesEx3 = (SpellAttr3)_misc.AttributesExC;
AttributesEx4 = (SpellAttr4)_misc.AttributesExD;
AttributesEx5 = (SpellAttr5)_misc.AttributesExE;
AttributesEx6 = (SpellAttr6)_misc.AttributesExF;
AttributesEx7 = (SpellAttr7)_misc.AttributesExG;
AttributesEx8 = (SpellAttr8)_misc.AttributesExH;
AttributesEx9 = (SpellAttr9)_misc.AttributesExI;
AttributesEx10 = (SpellAttr10)_misc.AttributesExJ;
AttributesEx11 = (SpellAttr11)_misc.AttributesExK;
AttributesEx12 = (SpellAttr12)_misc.AttributesExL;
AttributesEx13 = (SpellAttr13)_misc.AttributesExM;
CastTimeEntry = CliDB.SpellCastTimesStorage.LookupByKey(_misc.CastingTimeIndex);
DurationEntry = CliDB.SpellDurationStorage.LookupByKey(_misc.DurationIndex);
RangeIndex = _misc.RangeIndex;
RangeEntry = CliDB.SpellRangeStorage.LookupByKey(_misc.RangeIndex);
Speed = _misc.Speed;
SchoolMask = (SpellSchoolMask)_misc.SchoolMask;
AttributesCu = 0;
IconFileDataId = _misc.IconFileDataID;
ActiveIconFileDataId = _misc.ActiveIconFileDataID;
}
if (visuals != null)
_visuals = visuals;
// sort all visuals so that the ones without a condition requirement are last on the list
foreach (var key in _visuals.Keys.ToList())
_visuals[key] = _visuals[key].OrderByDescending(x => x.PlayerConditionID).ToList();
// SpellScalingEntry
SpellScalingRecord _scaling = data.Scaling;
if (_scaling != null)
{
Scaling._Class = _scaling.ScalingClass;
Scaling.MinScalingLevel = _scaling.MinScalingLevel;
Scaling.MaxScalingLevel = _scaling.MaxScalingLevel;
Scaling.ScalesFromItemLevel = _scaling.ScalesFromItemLevel;
}
// SpellAuraOptionsEntry
SpellAuraOptionsRecord _options = data.AuraOptions;
if (_options != null)
{
SpellProcsPerMinuteRecord _ppm = CliDB.SpellProcsPerMinuteStorage.LookupByKey(_options.SpellProcsPerMinuteID);
ProcFlags = (ProcFlags)_options.ProcTypeMask;
ProcChance = _options.ProcChance;
ProcCharges = _options.ProcCharges;
ProcCooldown = _options.ProcCategoryRecovery;
ProcBasePPM = _ppm != null ? _ppm.BaseProcRate : 0.0f;
ProcPPMMods = Global.DB2Mgr.GetSpellProcsPerMinuteMods(_options.SpellProcsPerMinuteID);
StackAmount = _options.CumulativeAura;
}
// SpellAuraRestrictionsEntry
SpellAuraRestrictionsRecord _aura = data.AuraRestrictions;
if (_aura != null)
{
CasterAuraState = (AuraStateType)_aura.CasterAuraState;
TargetAuraState = (AuraStateType)_aura.TargetAuraState;
CasterAuraStateNot = (AuraStateType)_aura.ExcludeCasterAuraState;
TargetAuraStateNot = (AuraStateType)_aura.ExcludeTargetAuraState;
CasterAuraSpell = _aura.CasterAuraSpell;
TargetAuraSpell = _aura.TargetAuraSpell;
ExcludeCasterAuraSpell = _aura.ExcludeCasterAuraSpell;
ExcludeTargetAuraSpell = _aura.ExcludeTargetAuraSpell;
}
RequiredAreasID = -1;
// SpellCastingRequirementsEntry
SpellCastingRequirementsRecord _castreq = data.CastingRequirements;
if (_castreq != null)
{
RequiresSpellFocus = _castreq.RequiresSpellFocus;
FacingCasterFlags = _castreq.FacingCasterFlags;
RequiredAreasID = _castreq.RequiredAreasID;
}
// SpellCategoriesEntry
SpellCategoriesRecord _categorie = data.Categories;
if (_categorie != null)
{
CategoryId = _categorie.Category;
Dispel = (DispelType)_categorie.DispelType;
Mechanic = (Mechanics)_categorie.Mechanic;
StartRecoveryCategory = _categorie.StartRecoveryCategory;
DmgClass = (SpellDmgClass)_categorie.DefenseType;
PreventionType = (SpellPreventionType)_categorie.PreventionType;
ChargeCategoryId = _categorie.ChargeCategory;
}
// SpellClassOptionsEntry
SpellFamilyFlags = new FlagArray128();
SpellClassOptionsRecord _class = data.ClassOptions;
if (_class != null)
{
SpellFamilyName = (SpellFamilyNames)_class.SpellClassSet;
SpellFamilyFlags = _class.SpellClassMask;
}
// SpellCooldownsEntry
SpellCooldownsRecord _cooldowns = data.Cooldowns;
if (_cooldowns != null)
{
RecoveryTime = _cooldowns.RecoveryTime;
CategoryRecoveryTime = _cooldowns.CategoryRecoveryTime;
StartRecoveryTime = _cooldowns.StartRecoveryTime;
}
EquippedItemClass = ItemClass.None;
EquippedItemSubClassMask = -1;
EquippedItemInventoryTypeMask = -1;
// SpellEquippedItemsEntry
SpellEquippedItemsRecord _equipped = data.EquippedItems;
if (_equipped != null)
{
EquippedItemClass = (ItemClass)_equipped.EquippedItemClass;
EquippedItemSubClassMask = _equipped.EquippedItemSubClassMask;
EquippedItemInventoryTypeMask = _equipped.EquippedItemInventoryTypeMask;
}
// SpellInterruptsEntry
SpellInterruptsRecord _interrupt = data.Interrupts;
if (_interrupt != null)
{
InterruptFlags = (SpellInterruptFlags)_interrupt.InterruptFlags;
// TODO: 6.x these flags have 2 parts
AuraInterruptFlags = (SpellAuraInterruptFlags)_interrupt.AuraInterruptFlags[0];
ChannelInterruptFlags = (SpellChannelInterruptFlags)_interrupt.ChannelInterruptFlags[0];
}
// SpellLevelsEntry
SpellLevelsRecord _levels = data.Levels;
if (_levels != null)
{
MaxLevel = _levels.MaxLevel;
BaseLevel = _levels.BaseLevel;
SpellLevel = _levels.SpellLevel;
}
// SpellPowerEntry
PowerCosts = Global.DB2Mgr.GetSpellPowers(Id, Difficulty.None, out _hasPowerDifficultyData);
// SpellReagentsEntry
SpellReagentsRecord _reagents = data.Reagents;
for (var i = 0; i < SpellConst.MaxReagents; ++i)
{
Reagent[i] = _reagents != null ? _reagents.Reagent[i] : 0;
ReagentCount[i] = _reagents != null ? _reagents.ReagentCount[i] : 0u;
}
// SpellShapeshiftEntry
SpellShapeshiftRecord _shapeshift = data.Shapeshift;
if (_shapeshift != null)
{
Stances = MathFunctions.MakePair64(_shapeshift.ShapeshiftMask[0], _shapeshift.ShapeshiftMask[1]);
StancesNot = MathFunctions.MakePair64(_shapeshift.ShapeshiftExclude[0], _shapeshift.ShapeshiftExclude[1]);
}
// SpellTargetRestrictionsEntry
SpellTargetRestrictionsRecord _target = data.TargetRestrictions;
if (_target != null)
{
targets = (SpellCastTargetFlags)_target.Targets;
ConeAngle = _target.ConeAngle;
Width = _target.Width;
TargetCreatureType = _target.TargetCreatureType;
MaxAffectedTargets = _target.MaxAffectedTargets;
MaxTargetLevel = _target.MaxTargetLevel;
}
// SpellTotemsEntry
SpellTotemsRecord _totem = data.Totems;
for (var i = 0; i < 2; ++i)
{
TotemCategory[i] = _totem != null ? _totem.RequiredTotemCategoryID[i] : 0u;
Totem[i] = _totem != null ? _totem.Totem[i] : 0;
}
ChainEntry = null;
ExplicitTargetMask = 0;
}
public bool HasEffect(Difficulty difficulty, SpellEffectName effect)
{
var effects = GetEffectsForDifficulty(difficulty);
foreach (var eff in effects)
{
if (eff != null && eff.IsEffect(effect))
return true;
}
return false;
}
public bool HasEffect(SpellEffectName effect)
{
foreach (var pair in _effects)
{
foreach (SpellEffectInfo eff in pair.Value)
{
if (eff != null && eff.IsEffect(effect))
return true;
}
}
return false;
}
public bool HasAura(Difficulty difficulty, AuraType aura)
{
var effects = GetEffectsForDifficulty(difficulty);
foreach (SpellEffectInfo effect in effects)
{
if (effect != null && effect.IsAura(aura))
return true;
}
return false;
}
public bool HasAreaAuraEffect(Difficulty difficulty)
{
var effects = GetEffectsForDifficulty(difficulty);
foreach (SpellEffectInfo effect in effects)
{
if (effect != null && effect.IsAreaAuraEffect())
return true;
}
return false;
}
public bool HasAreaAuraEffect()
{
foreach (var pair in _effects)
{
foreach (SpellEffectInfo effect in pair.Value)
{
if (effect != null && effect.IsAreaAuraEffect())
return true;
}
}
return false;
}
public bool IsExplicitDiscovery()
{
SpellEffectInfo effect0 = GetEffect(Difficulty.None, 0);
SpellEffectInfo effect1 = GetEffect(Difficulty.None, 1);
return ((effect0 != null && (effect0.Effect == SpellEffectName.CreateRandomItem || effect0.Effect == SpellEffectName.CreateLoot))
&& effect1 != null && effect1.Effect == SpellEffectName.ScriptEffect)
|| Id == 64323;
}
public bool IsLootCrafting()
{
return HasEffect(SpellEffectName.CreateRandomItem) || HasEffect(SpellEffectName.CreateLoot);
}
public bool IsQuestTame()
{
SpellEffectInfo effect0 = GetEffect(Difficulty.None, 0);
SpellEffectInfo effect1 = GetEffect(Difficulty.None, 1);
return effect0 != null && effect1 != null && effect0.Effect == SpellEffectName.Threat && effect1.Effect == SpellEffectName.ApplyAura
&& effect1.ApplyAuraName == AuraType.Dummy;
}
public bool IsProfession(Difficulty difficulty = Difficulty.None)
{
var effects = GetEffectsForDifficulty(difficulty);
foreach (SpellEffectInfo effect in effects)
{
if (effect != null && effect.Effect == SpellEffectName.Skill)
{
uint skill = (uint)effect.MiscValue;
if (Global.SpellMgr.IsProfessionSkill(skill))
return true;
}
}
return false;
}
public bool IsPrimaryProfession(Difficulty difficulty)
{
var effects = GetEffectsForDifficulty(difficulty);
foreach (SpellEffectInfo effect in effects)
{
if (effect != null && effect.Effect == SpellEffectName.Skill)
{
uint skill = (uint)effect.MiscValue;
if (Global.SpellMgr.IsPrimaryProfessionSkill(skill))
return true;
}
}
return false;
}
public bool IsPrimaryProfessionFirstRank(Difficulty difficulty = Difficulty.None)
{
return IsPrimaryProfession(difficulty) && GetRank() == 1;
}
public bool IsAbilityOfSkillType(SkillType skillType)
{
var bounds = Global.SpellMgr.GetSkillLineAbilityMapBounds(Id);
foreach (var spell_idx in bounds)
if (spell_idx.SkillLine == (uint)skillType)
return true;
return false;
}
public bool IsAffectingArea(Difficulty difficulty)
{
var effects = GetEffectsForDifficulty(difficulty);
foreach (SpellEffectInfo effect in effects)
{
if (effect != null && effect.IsEffect() && (effect.IsTargetingArea() || effect.IsEffect(SpellEffectName.PersistentAreaAura) || effect.IsAreaAuraEffect()))
return true;
}
return false;
}
// checks if spell targets are selected from area, doesn't include spell effects in check (like area wide auras for example)
public bool IsTargetingArea(Difficulty difficulty)
{
var effects = GetEffectsForDifficulty(difficulty);
foreach (SpellEffectInfo effect in effects)
{
if (effect != null && effect.IsEffect() && effect.IsTargetingArea())
return true;
}
return false;
}
public bool NeedsExplicitUnitTarget()
{
return Convert.ToBoolean(GetExplicitTargetMask() & SpellCastTargetFlags.UnitMask);
}
public bool NeedsToBeTriggeredByCaster(SpellInfo triggeringSpell, Difficulty difficulty)
{
if (NeedsExplicitUnitTarget())
return true;
if (triggeringSpell.IsChanneled())
{
SpellCastTargetFlags mask = 0;
var effects = GetEffectsForDifficulty(difficulty);
foreach (SpellEffectInfo effect in effects)
{
if (effect != null && (effect.TargetA.GetTarget() != Targets.UnitCaster && effect.TargetA.GetTarget() != Targets.DestCaster
&& effect.TargetB.GetTarget() != Targets.UnitCaster && effect.TargetB.GetTarget() != Targets.DestCaster))
{
mask |= effect.GetProvidedTargetMask();
}
}
if (mask.HasAnyFlag(SpellCastTargetFlags.UnitMask))
return true;
}
return false;
}
public bool IsPassive()
{
return HasAttribute(SpellAttr0.Passive);
}
public bool IsAutocastable()
{
if (IsPassive())
return false;
if (HasAttribute(SpellAttr1.UnautocastableByPet))
return false;
return true;
}
public bool IsStackableWithRanks()
{
if (IsPassive())
return false;
// All stance spells. if any better way, change it.
var effects = GetEffectsForDifficulty(Difficulty.None);
foreach (SpellEffectInfo effect in effects)
{
if (effect == null)
continue;
switch (SpellFamilyName)
{
case SpellFamilyNames.Paladin:
// Paladin aura Spell
if (effect.Effect == SpellEffectName.ApplyAreaAuraRaid)
return false;
break;
case SpellFamilyNames.Druid:
// Druid form Spell
if (effect.Effect == SpellEffectName.ApplyAura &&
effect.ApplyAuraName == AuraType.ModShapeshift)
return false;
break;
}
}
return true;
}
public bool IsPassiveStackableWithRanks()
{
return IsPassive() && !HasEffect(SpellEffectName.ApplyAura);
}
public bool IsMultiSlotAura()
{
return IsPassive() || Id == 55849 || Id == 40075 || Id == 44413; // Power Spark, Fel Flak Fire, Incanter's Absorption
}
public bool IsStackableOnOneSlotWithDifferentCasters()
{
// TODO: Re-verify meaning of SPELL_ATTR3_STACK_FOR_DIFF_CASTERS and update conditions here
return StackAmount > 1 && !IsChanneled() && !HasAttribute(SpellAttr3.StackForDiffCasters);
}
public bool IsCooldownStartedOnEvent()
{
if (HasAttribute(SpellAttr0.DisabledWhileActive))
return true;
SpellCategoryRecord category = CliDB.SpellCategoryStorage.LookupByKey(CategoryId);
return category != null && category.Flags.HasAnyFlag(SpellCategoryFlags.CooldownStartsOnEvent);
}
public bool IsDeathPersistent()
{
return HasAttribute(SpellAttr3.DeathPersistent);
}
public bool IsRequiringDeadTarget()
{
return HasAttribute(SpellAttr3.OnlyTargetGhosts);
}
public bool IsAllowingDeadTarget()
{
return HasAttribute(SpellAttr2.CanTargetDead)
|| Convert.ToBoolean(targets & (SpellCastTargetFlags.CorpseAlly | SpellCastTargetFlags.CorpseEnemy | SpellCastTargetFlags.UnitDead));
}
public bool IsGroupBuff()
{
var effects = GetEffectsForDifficulty(Difficulty.None);
foreach (SpellEffectInfo effect in effects)
{
if (effect == null)
continue;
switch (effect.TargetA.GetCheckType())
{
case SpellTargetCheckTypes.Party:
case SpellTargetCheckTypes.Raid:
case SpellTargetCheckTypes.RaidClass:
return true;
default:
break;
}
}
return false;
}
public bool CanBeUsedInCombat()
{
return !HasAttribute(SpellAttr0.CantUsedInCombat);
}
public bool IsPositive()
{
return !HasAttribute(SpellCustomAttributes.Negative);
}
public bool IsPositiveEffect(uint effIndex)
{
switch (effIndex)
{
default:
case 0:
return !HasAttribute(SpellCustomAttributes.NegativeEff0);
case 1:
return !HasAttribute(SpellCustomAttributes.NegativeEff1);
case 2:
return !HasAttribute(SpellCustomAttributes.NegativeEff2);
}
}
public bool IsChanneled()
{
return HasAttribute(SpellAttr1.Channeled1 | SpellAttr1.Channeled2);
}
public bool NeedsComboPoints()
{
return HasAttribute(SpellAttr1.ReqComboPoints1 | SpellAttr1.ReqComboPoints2);
}
public bool IsBreakingStealth()
{
return !HasAttribute(SpellAttr1.NotBreakStealth);
}
public bool IsRangedWeaponSpell()
{
return (SpellFamilyName == SpellFamilyNames.Hunter && !SpellFamilyFlags[1].HasAnyFlag(0x10000000u)) // for 53352, cannot find better way
|| Convert.ToBoolean(EquippedItemSubClassMask & (int)ItemSubClassWeapon.MaskRanged);
}
public bool IsAutoRepeatRangedSpell()
{
return HasAttribute(SpellAttr2.AutorepeatFlag);
}
public bool HasInitialAggro()
{
return !(HasAttribute(SpellAttr1.NoThreat) || HasAttribute(SpellAttr3.NoInitialAggro));
}
bool IsAffectedBySpellMods()
{
return !HasAttribute(SpellAttr3.NoDoneBonus);
}
public bool IsAffectedBySpellMod(SpellModifier mod)
{
if (!IsAffectedBySpellMods())
return false;
SpellInfo affectSpell = Global.SpellMgr.GetSpellInfo(mod.spellId);
// False if affect_spell == NULL or spellFamily not equal
if (affectSpell == null || affectSpell.SpellFamilyName != SpellFamilyName)
return false;
// true
if (mod.mask & SpellFamilyFlags)
return true;
return false;
}
public bool CanPierceImmuneAura(SpellInfo aura)
{
// these spells pierce all avalible spells (Resurrection Sickness for example)
if (HasAttribute(SpellAttr0.UnaffectedByInvulnerability))
return true;
// these spells (Cyclone for example) can pierce all... | ...but not these (Divine shield, Ice block, Cyclone and Banish for example)
if (HasAttribute(SpellAttr1.UnaffectedBySchoolImmune)
&& !(aura != null && (aura.Mechanic == Mechanics.Immune_Shield || aura.Mechanic == Mechanics.Invulnerability || aura.Mechanic == Mechanics.Banish)))
return true;
return false;
}
public bool CanDispelAura(SpellInfo aura)
{
// These spells (like Mass Dispel) can dispell all auras
if (HasAttribute(SpellAttr0.UnaffectedByInvulnerability) && !aura.IsDeathPersistent())
return true;
// These auras (like Divine Shield) can't be dispelled
if (aura.HasAttribute(SpellAttr0.UnaffectedByInvulnerability))
return false;
// These auras (Cyclone for example) are not dispelable
if (aura.HasAttribute(SpellAttr1.UnaffectedBySchoolImmune))
return false;
return true;
}
public bool IsSingleTarget()
{
// all other single target spells have if it has AttributesEx5
if (HasAttribute(SpellAttr5.SingleTargetSpell))
return true;
switch (GetSpellSpecific())
{
case SpellSpecificType.Judgement:
return true;
default:
break;
}
return false;
}
public bool IsAuraExclusiveBySpecificWith(SpellInfo spellInfo)
{
SpellSpecificType spellSpec1 = GetSpellSpecific();
SpellSpecificType spellSpec2 = spellInfo.GetSpellSpecific();
switch (spellSpec1)
{
case SpellSpecificType.WarlockArmor:
case SpellSpecificType.MageArmor:
case SpellSpecificType.ElementalShield:
case SpellSpecificType.MagePolymorph:
case SpellSpecificType.Presence:
case SpellSpecificType.Charm:
case SpellSpecificType.Scroll:
case SpellSpecificType.WarriorEnrage:
case SpellSpecificType.MageArcaneBrillance:
case SpellSpecificType.PriestDivineSpirit:
return spellSpec1 == spellSpec2;
case SpellSpecificType.Food:
return spellSpec2 == SpellSpecificType.Food
|| spellSpec2 == SpellSpecificType.FoodAndDrink;
case SpellSpecificType.Drink:
return spellSpec2 == SpellSpecificType.Drink
|| spellSpec2 == SpellSpecificType.FoodAndDrink;
case SpellSpecificType.FoodAndDrink:
return spellSpec2 == SpellSpecificType.Food
|| spellSpec2 == SpellSpecificType.Drink
|| spellSpec2 == SpellSpecificType.FoodAndDrink;
default:
return false;
}
}
public bool IsAuraExclusiveBySpecificPerCasterWith(SpellInfo spellInfo)
{
SpellSpecificType spellSpec = GetSpellSpecific();
switch (spellSpec)
{
case SpellSpecificType.Seal:
case SpellSpecificType.Hand:
case SpellSpecificType.Aura:
case SpellSpecificType.Sting:
case SpellSpecificType.Curse:
case SpellSpecificType.Bane:
case SpellSpecificType.Aspect:
case SpellSpecificType.Judgement:
case SpellSpecificType.WarlockCorruption:
return spellSpec == spellInfo.GetSpellSpecific();
default:
return false;
}
}
public SpellCastResult CheckShapeshift(ShapeShiftForm form)
{
// talents that learn spells can have stance requirements that need ignore
// (this requirement only for client-side stance show in talent description)
/* TODO: 6.x fix this in proper way (probably spell flags/attributes?)
if (CliDB.GetTalentSpellCost(Id) > 0 &&
(Effects[0].Effect == SpellEffects.LearnSpell || Effects[1].Effect == SpellEffects.LearnSpell || Effects[2].Effect == SpellEffects.LearnSpell))
return SpellCastResult.SpellCastOk;
*/
//if (HasAttribute(SPELL_ATTR13_ACTIVATES_REQUIRED_SHAPESHIFT))
// return SPELL_CAST_OK;
ulong stanceMask = (form != 0 ? 1ul << ((int)form - 1) : 0);
if (Convert.ToBoolean(stanceMask & StancesNot)) // can explicitly not be casted in this stance
return SpellCastResult.NotShapeshift;
if (Convert.ToBoolean(stanceMask & Stances)) // can explicitly be casted in this stance
return SpellCastResult.SpellCastOk;
bool actAsShifted = false;
SpellShapeshiftFormRecord shapeInfo = null;
if (form > 0)
{
shapeInfo = CliDB.SpellShapeshiftFormStorage.LookupByKey(form);
if (shapeInfo == null)
{
Log.outError(LogFilter.Spells, "GetErrorAtShapeshiftedCast: unknown shapeshift {0}", form);
return SpellCastResult.SpellCastOk;
}
actAsShifted = !shapeInfo.Flags.HasAnyFlag(SpellShapeshiftFormFlags.IsNotAShapeshift);
}
if (actAsShifted)
{
if (HasAttribute(SpellAttr0.NotShapeshift) || (shapeInfo != null && shapeInfo.Flags.HasAnyFlag(SpellShapeshiftFormFlags.PreventUsingOwnSkills))) // not while shapeshifted
return SpellCastResult.NotShapeshift;
else if (Stances != 0) // needs other shapeshift
return SpellCastResult.OnlyShapeshift;
}
else
{
// needs shapeshift
if (!HasAttribute(SpellAttr2.NotNeedShapeshift) && Stances != 0)
return SpellCastResult.OnlyShapeshift;
}
return SpellCastResult.SpellCastOk;
}
public SpellCastResult CheckLocation(uint map_id, uint zone_id, uint area_id, Player player)
{
// normal case
if (RequiredAreasID > 0)
{
bool found = false;
List<uint> areaGroupMembers = Global.DB2Mgr.GetAreasForGroup((uint)RequiredAreasID);
foreach (uint areaId in areaGroupMembers)
{
if (areaId == zone_id || areaId == area_id)
{
found = true;
break;
}
}
if (!found)
return SpellCastResult.IncorrectArea;
}
// continent limitation (virtual continent)
if (HasAttribute(SpellAttr4.CastOnlyInOutland))
{
uint v_map = Global.DB2Mgr.GetVirtualMapForMapAndZone(map_id, zone_id);
var map = CliDB.MapStorage.LookupByKey(v_map);
if (map == null || map.ExpansionID < 1 || !map.IsContinent())
return SpellCastResult.IncorrectArea;
}
var mapEntry = CliDB.MapStorage.LookupByKey(map_id);
// raid instance limitation
if (HasAttribute(SpellAttr6.NotInRaidInstance))
{
if (mapEntry == null || mapEntry.IsRaid())
return SpellCastResult.NotInRaidInstance;
}
// DB base check (if non empty then must fit at least single for allow)
var saBounds = Global.SpellMgr.GetSpellAreaMapBounds(Id);
if (!saBounds.Empty())
{
foreach (var bound in saBounds)
{
if (bound.IsFitToRequirements(player, zone_id, area_id))
return SpellCastResult.SpellCastOk;
}
return SpellCastResult.IncorrectArea;
}
// bg spell checks
switch (Id)
{
case 23333: // Warsong Flag
case 23335: // Silverwing Flag
return map_id == 489 && player != null && player.InBattleground() ? SpellCastResult.SpellCastOk : SpellCastResult.RequiresArea;
case 34976: // Netherstorm Flag
return map_id == 566 && player != null && player.InBattleground() ? SpellCastResult.SpellCastOk : SpellCastResult.RequiresArea;
case 2584: // Waiting to Resurrect
case 22011: // Spirit Heal Channel
case 22012: // Spirit Heal
case 24171: // Resurrection Impact Visual
case 42792: // Recently Dropped Flag
case 43681: // Inactive
case 44535: // Spirit Heal (mana)
if (mapEntry == null)
return SpellCastResult.IncorrectArea;
return zone_id == 4197 || (mapEntry.IsBattleground() && player != null && player.InBattleground()) ? SpellCastResult.SpellCastOk : SpellCastResult.RequiresArea;
case 44521: // Preparation
{
if (player == null)
return SpellCastResult.RequiresArea;
if (mapEntry == null)
return SpellCastResult.IncorrectArea;
if (!mapEntry.IsBattleground())
return SpellCastResult.RequiresArea;
Battleground bg = player.GetBattleground();
return bg && bg.GetStatus() == BattlegroundStatus.WaitJoin ? SpellCastResult.SpellCastOk : SpellCastResult.RequiresArea;
}
case 32724: // Gold Team (Alliance)
case 32725: // Green Team (Alliance)
case 35774: // Gold Team (Horde)
case 35775: // Green Team (Horde)
if (mapEntry == null)
return SpellCastResult.IncorrectArea;
return mapEntry.IsBattleArena() && player != null && player.InBattleground() ? SpellCastResult.SpellCastOk : SpellCastResult.RequiresArea;
case 32727: // Arena Preparation
{
if (player == null)
return SpellCastResult.RequiresArea;
if (mapEntry == null)
return SpellCastResult.IncorrectArea;
if (!mapEntry.IsBattleArena())
return SpellCastResult.RequiresArea;
Battleground bg = player.GetBattleground();
return bg && bg.GetStatus() == BattlegroundStatus.WaitJoin ? SpellCastResult.SpellCastOk : SpellCastResult.RequiresArea;
}
}
// aura limitations
if (player)
{
foreach (SpellEffectInfo effect in GetEffectsForDifficulty(player.GetMap().GetDifficultyID()))
{
if (effect == null || !effect.IsAura())
continue;
switch (effect.ApplyAuraName)
{
case AuraType.Fly:
{
var bounds = Global.SpellMgr.GetSkillLineAbilityMapBounds(Id);
foreach (var skillRecord in bounds)
{
if (skillRecord.SkillLine == (int)SkillType.Mounts)
if (!player.CanFlyInZone(map_id, zone_id))
return SpellCastResult.IncorrectArea;
}
break;
}
case AuraType.Mounted:
{
uint mountType = (uint)effect.MiscValueB;
MountRecord mountEntry = Global.DB2Mgr.GetMount(Id);
if (mountEntry != null)
mountType = mountEntry.MountTypeId;
if (mountType != 0 && player.GetMountCapability(mountType) == null)
return SpellCastResult.NotHere;
break;
}
}
}
}
return SpellCastResult.SpellCastOk;
}
public SpellCastResult CheckTarget(Unit caster, WorldObject target, bool Implicit = true)
{
if (HasAttribute(SpellAttr1.CantTargetSelf) && caster == target)
return SpellCastResult.BadTargets;
// check visibility - ignore stealth for implicit (area) targets
if (!HasAttribute(SpellAttr6.CanTargetInvisible) && !caster.CanSeeOrDetect(target, Implicit))
return SpellCastResult.BadTargets;
Unit unitTarget = target.ToUnit();
// creature/player specific target checks
if (unitTarget != null)
{
if (HasAttribute(SpellAttr1.CantTargetInCombat))
{
if (unitTarget.IsInCombat())
return SpellCastResult.TargetAffectingCombat;
// player with active pet counts as a player in combat
else if (unitTarget.IsTypeId(TypeId.Player))
{
Pet pet = unitTarget.ToPlayer().GetPet();
if (pet)
if (pet.GetVictim() && !pet.HasUnitState(UnitState.Controlled))
return SpellCastResult.TargetAffectingCombat;
}
}
// only spells with SPELL_ATTR3_ONLY_TARGET_GHOSTS can target ghosts
if (HasAttribute(SpellAttr3.OnlyTargetGhosts) != unitTarget.HasAuraType(AuraType.Ghost))
{
if (HasAttribute(SpellAttr3.OnlyTargetGhosts))
return SpellCastResult.TargetNotGhost;
else
return SpellCastResult.BadTargets;
}
if (caster != unitTarget)
{
if (caster.IsTypeId(TypeId.Player))
{
// Do not allow these spells to target creatures not tapped by us (Banish, Polymorph, many quest spells)
if (HasAttribute(SpellAttr2.CantTargetTapped))
{
Creature targetCreature = unitTarget.ToCreature();
if (targetCreature != null)
if (targetCreature.hasLootRecipient() && !targetCreature.isTappedBy(caster.ToPlayer()))
return SpellCastResult.CantCastOnTapped;
}
if (HasAttribute(SpellCustomAttributes.PickPocket))
{
if (unitTarget.IsTypeId(TypeId.Player))
return SpellCastResult.BadTargets;
else if ((unitTarget.GetCreatureTypeMask() & (uint)CreatureType.MaskHumanoidOrUndead) == 0)
return SpellCastResult.TargetNoPockets;
}
// Not allow disarm unarmed player
if (Mechanic == Mechanics.Disarm)
{
if (unitTarget.IsTypeId(TypeId.Player))
{
Player player = unitTarget.ToPlayer();
if (player.GetWeaponForAttack(WeaponAttackType.BaseAttack) == null || !player.IsUseEquipedWeapon(true))
return SpellCastResult.TargetNoWeapons;
}
else if (unitTarget.GetVirtualItemId(0) == 0)
return SpellCastResult.TargetNoWeapons;
}
}
}
}
// corpse specific target checks
else if (target.IsTypeId(TypeId.Corpse))
{
Corpse corpseTarget = target.ToCorpse();
// cannot target bare bones
if (corpseTarget.GetCorpseType() == CorpseType.Bones)
return SpellCastResult.BadTargets;
// we have to use owner for some checks (aura preventing resurrection for example)
Player owner = Global.ObjAccessor.FindPlayer(corpseTarget.GetOwnerGUID());
if (owner != null)
unitTarget = owner;
// we're not interested in corpses without owner
else
return SpellCastResult.BadTargets;
}
// other types of objects - always valid
else
return SpellCastResult.SpellCastOk;
// corpseOwner and unit specific target checks
if (HasAttribute(SpellAttr3.OnlyTargetPlayers) && !unitTarget.IsTypeId(TypeId.Player))
return SpellCastResult.TargetNotPlayer;
if (!IsAllowingDeadTarget() && !unitTarget.IsAlive())
return SpellCastResult.TargetsDead;
// check this flag only for implicit targets (chain and area), allow to explicitly target units for spells like Shield of Righteousness
if (Implicit && HasAttribute(SpellAttr6.CantTargetCrowdControlled) && !unitTarget.CanFreeMove())
return SpellCastResult.BadTargets;
if (!CheckTargetCreatureType(unitTarget))
{
if (target.IsTypeId(TypeId.Player))
return SpellCastResult.TargetIsPlayer;
else
return SpellCastResult.BadTargets;
}
// check GM mode and GM invisibility - only for player casts (npc casts are controlled by AI) and negative spells
if (unitTarget != caster && (caster.IsControlledByPlayer() || !IsPositive()) && unitTarget.IsTypeId(TypeId.Player))
{
if (!unitTarget.ToPlayer().IsVisible())
return SpellCastResult.BmOrInvisgod;
if (unitTarget.ToPlayer().IsGameMaster())
return SpellCastResult.BmOrInvisgod;
}
// not allow casting on flying player
if (unitTarget.HasUnitState(UnitState.InFlight) && !HasAttribute(SpellCustomAttributes.AllowInflightTarget))
return SpellCastResult.BadTargets;
/* TARGET_UNIT_MASTER gets blocked here for passengers, because the whole idea of this check is to
not allow passengers to be implicitly hit by spells, however this target type should be an exception,
if this is left it kills spells that award kill credit from vehicle to master (few spells),
the use of these 2 covers passenger target check, logically, if vehicle cast this to master it should always hit
him, because it would be it's passenger, there's no such case where this gets to fail legitimacy, this problem
cannot be solved from within the check in other way since target type cannot be called for the spell currently
Spell examples: [ID - 52864 Devour Water, ID - 52862 Devour Wind, ID - 49370 Wyrmrest Defender: Destabilize Azure Dragonshrine Effect] */
if (!caster.IsVehicle() && !(caster.GetCharmerOrOwner() == target))
{
if (TargetAuraState != 0 && !unitTarget.HasAuraState(TargetAuraState, this, caster))
return SpellCastResult.TargetAurastate;
if (TargetAuraStateNot != 0 && unitTarget.HasAuraState(TargetAuraStateNot, this, caster))
return SpellCastResult.TargetAurastate;
}
if (TargetAuraSpell != 0 && !unitTarget.HasAura(TargetAuraSpell))
return SpellCastResult.TargetAurastate;
if (ExcludeTargetAuraSpell != 0 && unitTarget.HasAura(ExcludeTargetAuraSpell))
return SpellCastResult.TargetAurastate;
if (unitTarget.HasAuraType(AuraType.PreventResurrection))
if (HasEffect(caster.GetMap().GetDifficultyID(), SpellEffectName.SelfResurrect) || HasEffect(caster.GetMap().GetDifficultyID(), SpellEffectName.Resurrect))
return SpellCastResult.TargetCannotBeResurrected;
if (HasAttribute(SpellAttr8.BattleResurrection))
{
Map map = caster.GetMap();
if (map)
{
InstanceMap iMap = map.ToInstanceMap();
if (iMap)
{
InstanceScript instance = iMap.GetInstanceScript();
if (instance != null)
if (instance.GetCombatResurrectionCharges() == 0 && instance.IsEncounterInProgress())
return SpellCastResult.TargetCannotBeResurrected;
}
}
}
return SpellCastResult.SpellCastOk;
}
public SpellCastResult CheckExplicitTarget(Unit caster, WorldObject target, Item itemTarget = null)
{
SpellCastTargetFlags neededTargets = GetExplicitTargetMask();
if (target == null)
{
if (Convert.ToBoolean(neededTargets & (SpellCastTargetFlags.UnitMask | SpellCastTargetFlags.GameobjectMask | SpellCastTargetFlags.CorpseMask)))
if (!Convert.ToBoolean(neededTargets & SpellCastTargetFlags.GameobjectItem) || itemTarget == null)
return SpellCastResult.BadTargets;
return SpellCastResult.SpellCastOk;
}
Unit unitTarget = target.ToUnit();
if (unitTarget != null)
{
if (Convert.ToBoolean(neededTargets & (SpellCastTargetFlags.UnitEnemy | SpellCastTargetFlags.UnitAlly | SpellCastTargetFlags.UnitRaid | SpellCastTargetFlags.UnitParty | SpellCastTargetFlags.UnitMinipet | SpellCastTargetFlags.UnitPassenger)))
{
if (Convert.ToBoolean(neededTargets & SpellCastTargetFlags.UnitEnemy))
if (caster._IsValidAttackTarget(unitTarget, this))
return SpellCastResult.SpellCastOk;
if (neededTargets.HasAnyFlag(SpellCastTargetFlags.UnitAlly)
|| (neededTargets.HasAnyFlag(SpellCastTargetFlags.UnitParty) && caster.IsInPartyWith(unitTarget))
|| (neededTargets.HasAnyFlag(SpellCastTargetFlags.UnitRaid) && caster.IsInRaidWith(unitTarget)))
if (caster._IsValidAssistTarget(unitTarget, this))
return SpellCastResult.SpellCastOk;
if (Convert.ToBoolean(neededTargets & SpellCastTargetFlags.UnitMinipet))
if (unitTarget.GetGUID() == caster.GetCritterGUID())
return SpellCastResult.SpellCastOk;
if (Convert.ToBoolean(neededTargets & SpellCastTargetFlags.UnitPassenger))
if (unitTarget.IsOnVehicle(caster))
return SpellCastResult.SpellCastOk;
return SpellCastResult.BadTargets;
}
}
return SpellCastResult.SpellCastOk;
}
public SpellCastResult CheckVehicle(Unit caster)
{
// All creatures should be able to cast as passengers freely, restriction and attribute are only for players
if (!caster.IsTypeId(TypeId.Player))
return SpellCastResult.SpellCastOk;
Vehicle vehicle = caster.GetVehicle();
if (vehicle)
{
VehicleSeatFlags checkMask = 0;
foreach (SpellEffectInfo effect in GetEffectsForDifficulty(caster.GetMap().GetDifficultyID()))
{
if (effect != null && effect.ApplyAuraName == AuraType.ModShapeshift)
{
var shapeShiftFromEntry = CliDB.SpellShapeshiftFormStorage.LookupByKey((uint)effect.MiscValue);
if (shapeShiftFromEntry != null && !shapeShiftFromEntry.Flags.HasAnyFlag(SpellShapeshiftFormFlags.IsNotAShapeshift))
checkMask |= VehicleSeatFlags.Uncontrolled;
break;
}
}
if (HasAura(caster.GetMap().GetDifficultyID(), AuraType.Mounted))
checkMask |= VehicleSeatFlags.CanCastMountSpell;
if (checkMask == 0)
checkMask = VehicleSeatFlags.CanAttack;
var vehicleSeat = vehicle.GetSeatForPassenger(caster);
if (!HasAttribute(SpellAttr6.CastableWhileOnVehicle) && !HasAttribute(SpellAttr0.CastableWhileMounted)
&& (vehicleSeat.Flags[0] & (uint)checkMask) != (uint)checkMask)
return SpellCastResult.CantDoThatRightNow;
// Can only summon uncontrolled minions/guardians when on controlled vehicle
if (vehicleSeat.Flags[0].HasAnyFlag((uint)(VehicleSeatFlags.CanControl | VehicleSeatFlags.Unk2)))
{
foreach (SpellEffectInfo effect in GetEffectsForDifficulty(caster.GetMap().GetDifficultyID()))
{
if (effect == null || effect.Effect != SpellEffectName.Summon)
continue;
var props = CliDB.SummonPropertiesStorage.LookupByKey(effect.MiscValueB);
if (props != null && props.Category != SummonCategory.Wild)
return SpellCastResult.CantDoThatRightNow;
}
}
}
return SpellCastResult.SpellCastOk;
}
public bool CheckTargetCreatureType(Unit target)
{
// Curse of Doom & Exorcism: not find another way to fix spell target check :/
if (SpellFamilyName == SpellFamilyNames.Warlock && GetCategory() == 1179)
{
// not allow cast at player
if (target.IsTypeId(TypeId.Player))
return false;
else
return true;
}
// if target is magnet (i.e Grounding Totem) the check is skipped
//if (target.IsMagnet())
//return true;
uint creatureType = target.GetCreatureTypeMask();
return TargetCreatureType == 0 || creatureType == 0 || Convert.ToBoolean(creatureType & TargetCreatureType);
}
public SpellSchoolMask GetSchoolMask()
{
return SchoolMask;
}
public uint GetAllEffectsMechanicMask()
{
uint mask = 0;
if (Mechanic != 0)
mask |= (uint)(1 << (int)Mechanic);
foreach (var pair in _effects)
{
foreach (SpellEffectInfo effect in pair.Value)
{
if (effect != null && effect.IsEffect() && effect.Mechanic != 0)
mask |= (uint)(1 << (int)effect.Mechanic);
}
}
return mask;
}
public uint GetEffectMechanicMask(byte effIndex)
{
uint mask = 0;
if (Mechanic != 0)
mask |= (uint)(1 << (int)Mechanic);
foreach (var pair in _effects)
{
foreach (SpellEffectInfo effect in pair.Value)
{
if (effect != null && effect.EffectIndex == effIndex && effect.IsEffect() && effect.Mechanic != 0)
mask |= (uint)(1 << (int)effect.Mechanic);
}
}
return mask;
}
public uint GetSpellMechanicMaskByEffectMask(uint effectMask)
{
uint mask = 0;
if (Mechanic != 0)
mask |= (uint)(1 << (int)Mechanic);
foreach (var pair in _effects)
{
foreach (SpellEffectInfo effect in pair.Value)
{
if (effect != null && Convert.ToBoolean(effectMask & (1 << (int)effect.EffectIndex)) && effect.Mechanic != 0)
mask |= (uint)(1 << (int)effect.Mechanic);
}
}
return mask;
}
public Mechanics GetEffectMechanic(uint effIndex, Difficulty difficulty)
{
SpellEffectInfo effect = GetEffect(difficulty, effIndex);
if (effect != null && effect.IsEffect() && effect.Mechanic != 0)
return effect.Mechanic;
if (Mechanic != 0)
return Mechanic;
return Mechanics.None;
}
public uint GetDispelMask()
{
return GetDispelMask(Dispel);
}
public static uint GetDispelMask(DispelType type)
{
// If dispel all
if (type == DispelType.ALL)
return (uint)DispelType.AllMask;
else
return (uint)(1 << (int)type);
}
public SpellCastTargetFlags GetExplicitTargetMask()
{
return (SpellCastTargetFlags)ExplicitTargetMask;
}
public AuraStateType GetAuraState(Difficulty difficulty)
{
// Seals
if (GetSpellSpecific() == SpellSpecificType.Seal)
return AuraStateType.Judgement;
// Conflagrate aura state on Immolate and Shadowflame
if (SpellFamilyName == SpellFamilyNames.Warlock &&
// Immolate
(SpellFamilyFlags[0].HasAnyFlag(4u) ||
// Shadowflame
SpellFamilyFlags[2].HasAnyFlag(2u)))
return AuraStateType.Conflagrate;
// Faerie Fire (druid versions)
if (SpellFamilyName == SpellFamilyNames.Druid && SpellFamilyFlags[0].HasAnyFlag(0x400u))
return AuraStateType.FaerieFire;
// Sting (hunter's pet ability)
if (GetCategory() == 1133)
return AuraStateType.FaerieFire;
// Victorious
if (SpellFamilyName == SpellFamilyNames.Warrior && SpellFamilyFlags[1].HasAnyFlag(0x40000u))
return AuraStateType.WarriorVictoryRush;
// Swiftmend state on Regrowth & Rejuvenation
if (SpellFamilyName == SpellFamilyNames.Druid && SpellFamilyFlags[0].HasAnyFlag(0x50u))
return AuraStateType.Swiftmend;
// Deadly poison aura state
if (SpellFamilyName == SpellFamilyNames.Rogue && SpellFamilyFlags[0].HasAnyFlag(0x10000u))
return AuraStateType.DeadlyPoison;
// Enrage aura state
if (Dispel == DispelType.Enrage)
return AuraStateType.Enrage;
// Bleeding aura state
if (Convert.ToBoolean(GetAllEffectsMechanicMask() & 1 << (int)Mechanics.Bleed))
return AuraStateType.Bleeding;
if (Convert.ToBoolean(GetSchoolMask() & SpellSchoolMask.Frost))
{
foreach (SpellEffectInfo effect in GetEffectsForDifficulty(difficulty))
if (effect != null && effect.IsAura() && (effect.ApplyAuraName == AuraType.ModStun
|| effect.ApplyAuraName == AuraType.ModRoot))
return AuraStateType.Frozen;
}
switch (Id)
{
case 71465: // Divine Surge
case 50241: // Evasive Charges
return AuraStateType.Unk22;
default:
break;
}
return AuraStateType.None;
}
public SpellSpecificType GetSpellSpecific()
{
switch (SpellFamilyName)
{
case SpellFamilyNames.Generic:
{
// Food / Drinks (mostly)
if (AuraInterruptFlags.HasAnyFlag(SpellAuraInterruptFlags.NotSeated))
{
bool food = false;
bool drink = false;
foreach (var pair in _effects)
{
foreach (SpellEffectInfo effect in pair.Value)
{
if (effect == null || !effect.IsAura())
continue;
switch (effect.ApplyAuraName)
{
// Food
case AuraType.ModRegen:
case AuraType.ObsModHealth:
food = true;
break;
// Drink
case AuraType.ModPowerRegen:
case AuraType.ObsModPower:
drink = true;
break;
default:
break;
}
}
}
if (food && drink)
return SpellSpecificType.FoodAndDrink;
else if (food)
return SpellSpecificType.Food;
else if (drink)
return SpellSpecificType.Drink;
}
// scrolls effects
else
{
SpellInfo firstRankSpellInfo = GetFirstRankSpell();
switch (firstRankSpellInfo.Id)
{
case 8118: // Strength
case 8099: // Stamina
case 8112: // Spirit
case 8096: // Intellect
case 8115: // Agility
case 8091: // Armor
return SpellSpecificType.Scroll;
case 12880: // Enrage (Enrage)
case 57518: // Enrage (Wrecking Crew)
return SpellSpecificType.WarriorEnrage;
}
}
break;
}
case SpellFamilyNames.Mage:
{
// family flags 18(Molten), 25(Frost/Ice), 28(Mage)
if (SpellFamilyFlags[0].HasAnyFlag(0x12040000u))
return SpellSpecificType.MageArmor;
// Arcane brillance and Arcane intelect (normal check fails because of flags difference)
if (SpellFamilyFlags[0].HasAnyFlag(0x400u))
return SpellSpecificType.MageArcaneBrillance;
SpellEffectInfo effect = GetEffect(Difficulty.None, 0);
if (effect != null && SpellFamilyFlags[0].HasAnyFlag(0x1000000u) && effect.ApplyAuraName == AuraType.ModConfuse)
return SpellSpecificType.MagePolymorph;
break;
}
case SpellFamilyNames.Warrior:
{
if (Id == 12292) // Death Wish
return SpellSpecificType.WarriorEnrage;
break;
}
case SpellFamilyNames.Warlock:
{
// Warlock (Bane of Doom | Bane of Agony | Bane of Havoc)
if (Id == 603 || Id == 980 || Id == 80240)
return SpellSpecificType.Bane;
// only warlock curses have this
if (Dispel == DispelType.Curse)
return SpellSpecificType.Curse;
// Warlock (Demon Armor | Demon Skin | Fel Armor)
if (SpellFamilyFlags[1].HasAnyFlag(0x20000020u) || SpellFamilyFlags[2].HasAnyFlag(0x00000010u))
return SpellSpecificType.WarlockArmor;
//seed of corruption and corruption
if (SpellFamilyFlags[1].HasAnyFlag(0x10u) || SpellFamilyFlags[0].HasAnyFlag(0x2u))
return SpellSpecificType.WarlockCorruption;
break;
}
case SpellFamilyNames.Priest:
{
// Divine Spirit and Prayer of Spirit
if (SpellFamilyFlags[0].HasAnyFlag(0x20u))
return SpellSpecificType.PriestDivineSpirit;
break;
}
case SpellFamilyNames.Hunter:
{
// only hunter stings have this
if (Dispel == DispelType.Poison)
return SpellSpecificType.Sting;
// only hunter aspects have this (but not all aspects in hunter family)
if (SpellFamilyFlags & new FlagArray128(0x00380000, 0x00440000, 0x00001010))
return SpellSpecificType.Aspect;
break;
}
case SpellFamilyNames.Paladin:
{
// Collection of all the seal family flags. No other paladin spell has any of those.
if (SpellFamilyFlags[1].HasAnyFlag(0x26000C00u))
return SpellSpecificType.Seal;
if (SpellFamilyFlags[0].HasAnyFlag(0x00002190u))
return SpellSpecificType.Hand;
// Judgement
if (Id == 20271)
return SpellSpecificType.Judgement;
// only paladin auras have this (for palaldin class family)
if (SpellFamilyFlags[2].HasAnyFlag(0x00000020u))
return SpellSpecificType.Aura;
break;
}
case SpellFamilyNames.Shaman:
{
// family flags 10 (Lightning), 42 (Earth), 37 (Water), proc shield from T2 8 pieces bonus
if (SpellFamilyFlags[1].HasAnyFlag(0x420u) || SpellFamilyFlags[0].HasAnyFlag(0x00000400u) || Id == 23552)
return SpellSpecificType.ElementalShield;
break;
}
case SpellFamilyNames.Deathknight:
if (Id == 48266 || Id == 48263 || Id == 48265)
return SpellSpecificType.Presence;
break;
}
foreach (var pair in _effects)
{
foreach (SpellEffectInfo effect in pair.Value)
{
if (effect != null && effect.Effect == SpellEffectName.ApplyAura)
{
switch (effect.ApplyAuraName)
{
case AuraType.ModCharm:
case AuraType.ModPossessPet:
case AuraType.ModPossess:
case AuraType.AoeCharm:
return SpellSpecificType.Charm;
case AuraType.TrackCreatures:
// @workaround For non-stacking tracking spells (We need generic solution)
if (Id == 30645) // Gas Cloud Tracking
return SpellSpecificType.Normal;
break;
case AuraType.TrackResources:
case AuraType.TrackStealthed:
return SpellSpecificType.Tracker;
}
}
}
}
return SpellSpecificType.Normal;
}
public float GetMinRange(bool positive = false)
{
if (RangeEntry == null)
return 0.0f;
if (positive)
return RangeEntry.MinRangeFriend;
return RangeEntry.MinRangeHostile;
}
public float GetMaxRange(bool positive = false, Unit caster = null, Spell spell = null)
{
if (RangeEntry == null)
return 0.0f;
float range;
if (positive)
range = RangeEntry.MaxRangeFriend;
else
range = RangeEntry.MaxRangeHostile;
if (caster != null)
{
Player modOwner = caster.GetSpellModOwner();
if (modOwner != null)
modOwner.ApplySpellMod(Id, SpellModOp.Range, ref range, spell);
}
return range;
}
public int CalcDuration(Unit caster = null)
{
int duration = GetDuration();
if (caster)
{
Player modOwner = caster.GetSpellModOwner();
if (modOwner)
modOwner.ApplySpellMod(Id, SpellModOp.Duration, ref duration);
}
return duration;
}
public int GetDuration()
{
if (DurationEntry == null)
return 0;
return (DurationEntry.Duration == -1) ? -1 : Math.Abs(DurationEntry.Duration);
}
public int GetMaxDuration()
{
if (DurationEntry == null)
return 0;
return (DurationEntry.MaxDuration == -1) ? -1 : Math.Abs(DurationEntry.MaxDuration);
}
public int CalcCastTime(uint level = 0, Spell spell = null)
{
int castTime = 0;
if (CastTimeEntry != null)
{
int calcLevel = spell != null ? (int)spell.GetCaster().getLevel() : 0;
if (MaxLevel != 0 && calcLevel > MaxLevel)
calcLevel = (int)MaxLevel;
if (HasAttribute(SpellAttr13.Unk17))
calcLevel *= 5;
if (MaxLevel != 0 && calcLevel > MaxLevel)
calcLevel = (int)MaxLevel;
if (BaseLevel != 0)
calcLevel -= (int)BaseLevel;
if (calcLevel < 0)
calcLevel = 0;
castTime = (int)(CastTimeEntry.CastTime + CastTimeEntry.CastTimePerLevel * level);
if (castTime < CastTimeEntry.MinCastTime)
castTime = CastTimeEntry.MinCastTime;
}
if (castTime <= 0)
return 0;
if (spell != null)
spell.GetCaster().ModSpellCastTime(this, ref castTime, spell);
if (HasAttribute(SpellAttr0.ReqAmmo) && (!IsAutoRepeatRangedSpell()) && !HasAttribute(SpellAttr9.AimedShot))
castTime += 500;
return (castTime > 0) ? castTime : 0;
}
public uint GetMaxTicks(Difficulty difficulty)
{
int DotDuration = GetDuration();
if (DotDuration == 0)
return 1;
// 200% limit
if (DotDuration > 30000)
DotDuration = 30000;
foreach (SpellEffectInfo effect in GetEffectsForDifficulty(difficulty))
{
if (effect != null && effect.Effect == SpellEffectName.ApplyAura)
{
switch (effect.ApplyAuraName)
{
case AuraType.PeriodicDamage:
case AuraType.PeriodicDamagePercent:
case AuraType.PeriodicHeal:
case AuraType.ObsModHealth:
case AuraType.ObsModPower:
case AuraType.Unk48:
case AuraType.PowerBurn:
case AuraType.PeriodicLeech:
case AuraType.PeriodicManaLeech:
case AuraType.PeriodicEnergize:
case AuraType.PeriodicDummy:
case AuraType.PeriodicTriggerSpell:
case AuraType.PeriodicTriggerSpellWithValue:
case AuraType.PeriodicHealthFunnel:
if (effect.ApplyAuraPeriod != 0)
return (uint)(DotDuration / effect.ApplyAuraPeriod);
break;
}
}
}
return 6;
}
public uint GetRecoveryTime()
{
return RecoveryTime > CategoryRecoveryTime ? RecoveryTime : CategoryRecoveryTime;
}
public List<SpellPowerCost> CalcPowerCost(Unit caster, SpellSchoolMask schoolMask)
{
List<SpellPowerCost> costs = new List<SpellPowerCost>();
var collector = new Action<List<SpellPowerRecord>>(powers =>
{
int healthCost = 0;
foreach (SpellPowerRecord power in powers)
{
if (power.RequiredAura != 0 && !caster.HasAura(power.RequiredAura))
continue;
// Spell drain all exist power on cast (Only paladin lay of Hands)
if (HasAttribute(SpellAttr1.DrainAllPower))
{
// If power type - health drain all
if (power.PowerType == PowerType.Health)
{
healthCost = (int)caster.GetHealth();
continue;
}
// Else drain all power
if (power.PowerType < PowerType.Max)
{
SpellPowerCost cost = new SpellPowerCost();
cost.Power = power.PowerType;
cost.Amount = caster.GetPower(cost.Power);
costs.Add(cost);
continue;
}
Log.outError(LogFilter.Spells, "SpellInfo.GetCostDataList: Unknown power type '{0}' in spell {1}", power.PowerType, Id);
continue;
}
// Base powerCost
int powerCost = (int)power.ManaCost;
// PCT cost from total amount
if (power.ManaCostPercentage != 0)
{
switch (power.PowerType)
{
// health as power used
case PowerType.Health:
powerCost += (int)MathFunctions.CalculatePct(caster.GetMaxHealth(), power.ManaCostPercentage);
break;
case PowerType.Mana:
powerCost += (int)MathFunctions.CalculatePct(caster.GetCreateMana(), power.ManaCostPercentage);
break;
case PowerType.Rage:
case PowerType.Focus:
case PowerType.Energy:
powerCost += MathFunctions.CalculatePct(caster.GetMaxPower(power.PowerType), power.ManaCostPercentage);
break;
case PowerType.Runes:
case PowerType.RunicPower:
Log.outDebug(LogFilter.Spells, "GetCostDataList: Not implemented yet!");
break;
default:
Log.outError(LogFilter.Spells, "GetCostDataList: Unknown power type '{0}' in spell {1}", power.PowerType, Id);
continue;
}
}
if (power.HealthCostPercentage != 0)
healthCost += (int)MathFunctions.CalculatePct(caster.GetMaxHealth(), power.HealthCostPercentage);
if (power.PowerType != PowerType.Health)
{
// Flat mod from caster auras by spell school and power type
var auras = caster.GetAuraEffectsByType(AuraType.ModPowerCostSchool);
foreach (var eff in auras)
{
if (!Convert.ToBoolean(eff.GetMiscValue() & (int)schoolMask))
continue;
if (!Convert.ToBoolean(eff.GetMiscValueB() & (1 << (int)power.PowerType)))
continue;
powerCost += eff.GetAmount();
}
}
// Shiv - costs 20 + weaponSpeed*10 energy (apply only to non-triggered spell with energy cost)
if (HasAttribute(SpellAttr4.SpellVsExtendCost))
{
uint speed = 0;
SpellShapeshiftFormRecord ss = CliDB.SpellShapeshiftFormStorage.LookupByKey(caster.GetShapeshiftForm());
if (ss != null)
speed = ss.CombatRoundTime;
else
{
WeaponAttackType slot = WeaponAttackType.BaseAttack;
if (HasAttribute(SpellAttr3.ReqOffhand))
slot = WeaponAttackType.OffAttack;
speed = caster.GetBaseAttackTime(slot);
}
powerCost += (int)(speed / 100);
}
// Apply cost mod by spell
Player modOwner = caster.GetSpellModOwner();
if (modOwner)
{
if (power.PowerIndex == 0)
modOwner.ApplySpellMod(Id, SpellModOp.Cost, ref powerCost);
else if (power.PowerIndex == 1)
modOwner.ApplySpellMod(Id, SpellModOp.SpellCost2, ref powerCost);
}
if (!caster.IsControlledByPlayer() && MathFunctions.fuzzyEq(power.ManaCostPercentage, 0.0f) && SpellLevel != 0)
{
if (HasAttribute(SpellAttr0.LevelDamageCalculation))
{
GtNpcManaCostScalerRecord spellScaler = CliDB.NpcManaCostScalerGameTable.GetRow(SpellLevel);
GtNpcManaCostScalerRecord casterScaler = CliDB.NpcManaCostScalerGameTable.GetRow(caster.getLevel());
if (spellScaler != null && casterScaler != null)
powerCost *= (int)(casterScaler.Scaler / spellScaler.Scaler);
}
}
// PCT mod from user auras by spell school and power type
var aurasPct = caster.GetAuraEffectsByType(AuraType.ModPowerCostSchoolPct);
foreach (var eff in aurasPct)
{
if (!Convert.ToBoolean(eff.GetMiscValue() & (int)schoolMask))
continue;
if (!Convert.ToBoolean(eff.GetMiscValueB() & (1 << (int)power.PowerType)))
continue;
powerCost += MathFunctions.CalculatePct(powerCost, eff.GetAmount());
}
if (power.PowerType == PowerType.Health)
{
healthCost += powerCost;
continue;
}
bool found = false;
for (var i = 0; i < costs.Count; ++i)
{
var cost = costs[i];
if (cost.Power == power.PowerType)
{
cost.Amount += powerCost;
found = true;
}
}
if (!found)
{
SpellPowerCost cost = new SpellPowerCost();
cost.Power = power.PowerType;
cost.Amount = powerCost;
costs.Add(cost);
}
}
if (healthCost > 0)
{
SpellPowerCost cost = new SpellPowerCost();
cost.Power = PowerType.Health;
cost.Amount = healthCost;
costs.Add(cost);
}
});
if (!_hasPowerDifficultyData) // optimization - use static data for 99.5% cases (4753 of 4772 in build 6.1.0.19702)
collector(PowerCosts);
else
collector(Global.DB2Mgr.GetSpellPowers(Id, caster.GetMap().GetDifficultyID()));
// POWER_RUNES is handled by SpellRuneCost.db2, and cost.Amount is always 0 (see Spell.TakeRunePower)
costs.RemoveAll(cost => cost.Power != PowerType.Runes && cost.Amount <= 0);
return costs;
}
float CalcPPMHasteMod(SpellProcsPerMinuteModRecord mod, Unit caster)
{
float haste = caster.GetFloatValue(UnitFields.ModHaste);
float rangedHaste = caster.GetFloatValue(UnitFields.ModRangedHaste);
float spellHaste = caster.GetFloatValue(UnitFields.ModCastHaste);
float regenHaste = caster.GetFloatValue(UnitFields.ModHasteRegen);
switch (mod.Param)
{
case 1:
return (1.0f / haste - 1.0f) * mod.Coeff;
case 2:
return (1.0f / rangedHaste - 1.0f) * mod.Coeff;
case 3:
return (1.0f / spellHaste - 1.0f) * mod.Coeff;
case 4:
return (1.0f / regenHaste - 1.0f) * mod.Coeff;
case 5:
return (1.0f / Math.Min(Math.Min(Math.Min(haste, rangedHaste), spellHaste), regenHaste) - 1.0f) * mod.Coeff;
default:
break;
}
return 0.0f;
}
float CalcPPMCritMod(SpellProcsPerMinuteModRecord mod, Unit caster)
{
if (!caster.IsTypeId(TypeId.Player))
return 0.0f;
float crit = caster.GetFloatValue(PlayerFields.CritPercentage);
float rangedCrit = caster.GetFloatValue(PlayerFields.RangedCritPercentage);
float spellCrit = caster.GetFloatValue(PlayerFields.SpellCritPercentage1);
switch (mod.Param)
{
case 1:
return crit * mod.Coeff * 0.01f;
case 2:
return rangedCrit * mod.Coeff * 0.01f;
case 3:
return spellCrit * mod.Coeff * 0.01f;
case 4:
return Math.Min(Math.Min(crit, rangedCrit), spellCrit) * mod.Coeff * 0.01f;
default:
break;
}
return 0.0f;
}
float CalcPPMItemLevelMod(SpellProcsPerMinuteModRecord mod, int itemLevel)
{
if (itemLevel == mod.Param)
return 0.0f;
float itemLevelPoints = ItemEnchantment.GetRandomPropertyPoints((uint)itemLevel, ItemQuality.Rare, InventoryType.Chest, 0);
float basePoints = ItemEnchantment.GetRandomPropertyPoints(mod.Param, ItemQuality.Rare, InventoryType.Chest, 0);
if (itemLevelPoints == basePoints)
return 0.0f;
return ((itemLevelPoints / basePoints) - 1.0f) * mod.Coeff;
}
public float CalcProcPPM(Unit caster, int itemLevel)
{
float ppm = ProcBasePPM;
if (!caster)
return ppm;
foreach (SpellProcsPerMinuteModRecord mod in ProcPPMMods)
{
switch (mod.Type)
{
case SpellProcsPerMinuteModType.Haste:
{
ppm *= 1.0f + CalcPPMHasteMod(mod, caster);
break;
}
case SpellProcsPerMinuteModType.Crit:
{
ppm *= 1.0f + CalcPPMCritMod(mod, caster);
break;
}
case SpellProcsPerMinuteModType.Class:
{
if (caster.getClassMask().HasAnyFlag(mod.Param))
ppm *= 1.0f + mod.Coeff;
break;
}
case SpellProcsPerMinuteModType.Spec:
{
Player plrCaster = caster.ToPlayer();
if (plrCaster)
if (plrCaster.GetUInt32Value(PlayerFields.CurrentSpecId) == mod.Param)
ppm *= 1.0f + mod.Coeff;
break;
}
case SpellProcsPerMinuteModType.Race:
{
if (caster.getRaceMask().HasAnyFlag(mod.Param))
ppm *= 1.0f + mod.Coeff;
break;
}
case SpellProcsPerMinuteModType.ItemLevel:
{
ppm *= 1.0f + CalcPPMItemLevelMod(mod, itemLevel);
break;
}
case SpellProcsPerMinuteModType.Battleground:
{
if (caster.GetMap().IsBattlegroundOrArena())
ppm *= 1.0f + mod.Coeff;
break;
}
default:
break;
}
}
return ppm;
}
public bool IsRanked()
{
return ChainEntry != null;
}
public byte GetRank()
{
if (ChainEntry == null)
return 1;
return ChainEntry.rank;
}
public SpellInfo GetFirstRankSpell()
{
if (ChainEntry == null)
return this;
return ChainEntry.first;
}
SpellInfo GetLastRankSpell()
{
if (ChainEntry == null)
return null;
return ChainEntry.last;
}
public SpellInfo GetNextRankSpell()
{
if (ChainEntry == null)
return null;
return ChainEntry.next;
}
SpellInfo GetPrevRankSpell()
{
if (ChainEntry == null)
return null;
return ChainEntry.prev;
}
public SpellInfo GetAuraRankForLevel(uint level)
{
// ignore passive spells
if (IsPassive())
return this;
bool needRankSelection = false;
foreach (SpellEffectInfo effect in GetEffectsForDifficulty(Difficulty.None))
{
if (effect != null && IsPositiveEffect(effect.EffectIndex) &&
(effect.Effect == SpellEffectName.ApplyAura ||
effect.Effect == SpellEffectName.ApplyAreaAuraParty ||
effect.Effect == SpellEffectName.ApplyAreaAuraRaid) &&
effect.Scaling.Coefficient != 0)
{
needRankSelection = true;
break;
}
}
// not required
if (!needRankSelection)
return this;
for (SpellInfo nextSpellInfo = this; nextSpellInfo != null; nextSpellInfo = nextSpellInfo.GetPrevRankSpell())
{
// if found appropriate level
if ((level + 10) >= nextSpellInfo.SpellLevel)
return nextSpellInfo;
// one rank less then
}
// not found
return null;
}
public bool IsRankOf(SpellInfo spellInfo)
{
return GetFirstRankSpell() == spellInfo.GetFirstRankSpell();
}
public bool IsDifferentRankOf(SpellInfo spellInfo)
{
if (Id == spellInfo.Id)
return false;
return IsRankOf(spellInfo);
}
public bool IsHighRankOf(SpellInfo spellInfo)
{
if (ChainEntry != null && spellInfo.ChainEntry != null)
{
if (ChainEntry.first == spellInfo.ChainEntry.first)
if (ChainEntry.rank > spellInfo.ChainEntry.rank)
return true;
}
return false;
}
public uint GetSpellXSpellVisualId(Unit caster = null)
{
if (caster)
{
Difficulty difficulty = caster.GetMap().GetDifficultyID();
DifficultyRecord difficultyEntry = CliDB.DifficultyStorage.LookupByKey(difficulty);
while (difficultyEntry != null)
{
var visualList = _visuals.LookupByKey(difficulty);
if (visualList != null)
{
foreach (SpellXSpellVisualRecord visual in visualList)
{
PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(visual.PlayerConditionID);
if (playerCondition == null || (caster.IsTypeId(TypeId.Player) && ConditionManager.IsPlayerMeetingCondition(caster.ToPlayer(), playerCondition)))
return visual.Id;
}
}
difficultyEntry = CliDB.DifficultyStorage.LookupByKey(difficultyEntry.FallbackDifficultyID);
}
}
var defaultList = _visuals.LookupByKey(Difficulty.None);
if (defaultList != null)
{
foreach (var visual in defaultList)
{
PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(visual.PlayerConditionID);
if (playerCondition == null || (caster && caster.IsTypeId(TypeId.Player) && ConditionManager.IsPlayerMeetingCondition(caster.ToPlayer(), playerCondition)))
return visual.Id;
}
}
return 0;
}
public uint GetSpellVisual(Unit caster = null)
{
var visual = CliDB.SpellXSpellVisualStorage.LookupByKey(GetSpellXSpellVisualId(caster));
if (visual != null)
{
//if (visual->LowViolenceSpellVisualID && forPlayer->GetViolenceLevel() operator 2)
// return visual->LowViolenceSpellVisualID;
return visual.SpellVisualID;
}
return 0;
}
public void _InitializeExplicitTargetMask()
{
bool srcSet = false;
bool dstSet = false;
SpellCastTargetFlags targetMask = targets;
// prepare target mask using effect target entries
foreach (var pair in _effects)
{
foreach (SpellEffectInfo effect in pair.Value)
{
if (effect == null || !effect.IsEffect())
continue;
targetMask |= effect.TargetA.GetExplicitTargetMask(srcSet, dstSet);
targetMask |= effect.TargetB.GetExplicitTargetMask(srcSet, dstSet);
// add explicit target flags based on spell effects which have SpellEffectImplicitTargetTypes.Explicit and no valid target provided
if (effect.GetImplicitTargetType() != SpellEffectImplicitTargetTypes.Explicit)
continue;
// extend explicit target mask only if valid targets for effect could not be provided by target types
SpellCastTargetFlags effectTargetMask = effect.GetMissingTargetMask(srcSet, dstSet, (uint)targetMask);
// don't add explicit object/dest flags when spell has no max range
if (GetMaxRange(true) == 0.0f && GetMaxRange(false) == 0.0f)
effectTargetMask &= ~(SpellCastTargetFlags.UnitMask | SpellCastTargetFlags.Gameobject | SpellCastTargetFlags.CorpseMask | SpellCastTargetFlags.DestLocation);
targetMask |= effectTargetMask;
}
}
ExplicitTargetMask = (uint)targetMask;
}
public bool _IsPositiveEffect(uint effIndex, bool deep)
{
// not found a single positive spell with this attribute
if (HasAttribute(SpellAttr0.Negative1))
return false;
switch (SpellFamilyName)
{
case SpellFamilyNames.Generic:
switch (Id)
{
case 29214: // Wrath of the Plaguebringer
case 34700: // Allergic Reaction
case 54836: // Wrath of the Plaguebringer
return false;
case 30877: // Tag Murloc
case 61716: // Rabbit Costume
case 61734: // Noblegarden Bunny
case 62344: // Fists of Stone
case 61819: // Manabonked! (item)
case 61834: // Manabonked! (minigob)
case 73523: // Rigor Mortis
return true;
}
break;
case SpellFamilyNames.Priest:
switch (Id)
{
case 64844: // Divine Hymn
case 64904: // Hymn of Hope
case 47585: // Dispersion
return true;
}
break;
case SpellFamilyNames.Rogue:
switch (Id)
{
// Envenom must be considered as a positive effect even though it deals damage
case 32645: // Envenom
return true;
}
break;
}
if (Mechanic == Mechanics.Immune_Shield)
return true;
// Special case: effects which determine positivity of whole spell
foreach (var pair in _effects)
{
foreach (SpellEffectInfo effect in pair.Value)
{
if (effect != null && effect.IsAura() && effect.ApplyAuraName == AuraType.ModStealth)
return true;
}
}
foreach (var pair in _effects)
{
foreach (SpellEffectInfo effect in pair.Value)
{
if (effect == null || effect.EffectIndex != effIndex)
continue;
switch (effect.Effect)
{
case SpellEffectName.Dummy:
// some explicitly required dummy effect sets
switch (Id)
{
case 28441:
return false; // AB Effect 000
}
break;
// always positive effects (check before target checks that provided non-positive result in some case for positive effects)
case SpellEffectName.Heal:
case SpellEffectName.LearnSpell:
case SpellEffectName.SkillStep:
case SpellEffectName.HealPct:
case SpellEffectName.EnergizePct:
return true;
case SpellEffectName.ApplyAreaAuraEnemy:
return false;
// non-positive aura use
case SpellEffectName.ApplyAura:
case SpellEffectName.ApplyAreaAuraFriend:
{
switch (effect.ApplyAuraName)
{
case AuraType.ModDamageDone: // dependent from bas point sign (negative . negative)
case AuraType.ModStat:
case AuraType.ModSkill:
case AuraType.ModSkill2:
case AuraType.ModDodgePercent:
case AuraType.ModHealingPct:
case AuraType.ModHealingDone:
case AuraType.ModHealingDonePercent:
if (effect.CalcValue() < 0)
return false;
break;
case AuraType.ModDamageTaken: // dependent from bas point sign (positive . negative)
if (effect.CalcValue() > 0)
return false;
break;
case AuraType.ModCritPct:
case AuraType.ModSpellCritChance:
if (effect.CalcValue() > 0)
return true; // some expected positive spells have SPELL_ATTR1_NEGATIVE
break;
case AuraType.AddTargetTrigger:
return true;
case AuraType.PeriodicTriggerSpellWithValue:
case AuraType.PeriodicTriggerSpell:
if (!deep)
{
var spellTriggeredProto = Global.SpellMgr.GetSpellInfo(effect.TriggerSpell);
if (spellTriggeredProto != null)
{
// negative targets of main spell return early
foreach (var pair2 in spellTriggeredProto._effects)
{
foreach (SpellEffectInfo eff in pair2.Value)
{
if (eff == null || eff.Effect == 0)
continue;
// if non-positive trigger cast targeted to positive target this main cast is non-positive
// this will place this spell auras as debuffs
if (_IsPositiveTarget(eff.TargetA.getTarget(), eff.TargetB.getTarget()) && !spellTriggeredProto._IsPositiveEffect(eff.EffectIndex, true))
return false;
}
}
}
}
break;
case AuraType.ProcTriggerSpell:
// many positive auras have negative triggered spells at damage for example and this not make it negative (it can be canceled for example)
break;
case AuraType.ModStun: //have positive and negative spells, we can't sort its correctly at this moment.
bool more = false;
foreach (var pair2 in _effects)
{
foreach (SpellEffectInfo eff in pair2.Value)
{
if (eff != null && eff.EffectIndex != 0)
{
more = true;
break;
}
}
}
if (effIndex == 0 && !more)
return false; // but all single stun aura spells is negative
break;
case AuraType.ModPacifySilence:
if (Id == 24740) // Wisp Costume
return true;
return false;
case AuraType.ModRoot:
case AuraType.ModRoot2:
case AuraType.ModSilence:
case AuraType.Ghost:
case AuraType.PeriodicLeech:
case AuraType.ModStalked:
case AuraType.PeriodicDamagePercent:
case AuraType.PreventResurrection:
return false;
case AuraType.PeriodicDamage: // used in positive spells also.
// part of negative spell if casted at self (prevent cancel)
if (effect.TargetA.GetTarget() == Targets.UnitCaster)
return false;
break;
case AuraType.ModDecreaseSpeed: // used in positive spells also
// part of positive spell if casted at self
if (effect.TargetA.GetTarget() != Targets.UnitCaster)
return false;
// but not this if this first effect (didn't find better check)
if (HasAttribute(SpellAttr0.Negative1) && effIndex == 0)
return false;
break;
case AuraType.MechanicImmunity:
{
// non-positive immunities
switch ((Mechanics)effect.MiscValue)
{
case Mechanics.Bandage:
case Mechanics.Shield:
case Mechanics.Mount:
case Mechanics.Invulnerability:
return false;
}
break;
}
case AuraType.AddFlatModifier: // mods
case AuraType.AddPctModifier:
{
// non-positive mods
switch ((SpellModOp)effect.MiscValue)
{
case SpellModOp.Cost: // dependent from bas point sign (negative . positive)
if (effect.CalcValue() > 0)
{
if (!deep)
{
bool negative = true;
for (uint i = 0; i < SpellConst.MaxEffects; ++i)
{
if (i != effIndex)
{
if (_IsPositiveEffect(i, true))
{
negative = false;
break;
}
}
}
if (negative)
return false;
}
}
break;
}
break;
}
}
break;
}
}
// non-positive targets
if (!_IsPositiveTarget(effect.TargetA.getTarget(), effect.TargetB.getTarget()))
return false;
// negative spell if triggered spell is negative
if (!deep && effect.ApplyAuraName != 0 && effect.TriggerSpell != 0)
{
SpellInfo spellTriggeredProto = Global.SpellMgr.GetSpellInfo(effect.TriggerSpell);
if (spellTriggeredProto != null)
if (!spellTriggeredProto._IsPositiveSpell())
return false;
}
}
}
// ok, positive
return true;
}
public bool _IsPositiveSpell()
{
// spells with at least one negative effect are considered negative
// some self-applied spells have negative effects but in self casting case negative check ignored.
for (byte i = 0; i < SpellConst.MaxEffects; ++i)
if (!_IsPositiveEffect(i, true))
return false;
return true;
}
bool _IsPositiveTarget(uint targetA, uint targetB)
{
// non-positive targets
switch ((Targets)targetA)
{
case Targets.UnitNearbyEnemy:
case Targets.UnitEnemy:
case Targets.UnitSrcAreaEnemy:
case Targets.UnitDestAreaEnemy:
case Targets.UnitConeEnemy24:
case Targets.UnitConeEnemy104:
case Targets.DestDynobjEnemy:
case Targets.DestEnemy:
return false;
default:
break;
}
if (targetB != 0)
return _IsPositiveTarget(targetB, 0);
return true;
}
public void _UnloadImplicitTargetConditionLists()
{
// find the same instances of ConditionList and delete them.
foreach (var pair in _effects)
{
for (uint i = 0; i < pair.Value.Length; ++i)
{
SpellEffectInfo effect = pair.Value[i];
if (effect == null)
continue;
var cur = effect.ImplicitTargetConditions;
if (cur == null)
continue;
for (var j = i; j < pair.Value.Length; ++j)
{
SpellEffectInfo eff = pair.Value[j];
if (eff != null && eff.ImplicitTargetConditions == cur)
eff.ImplicitTargetConditions = null;
}
}
}
}
public static SpellCastTargetFlags GetTargetFlagMask(SpellTargetObjectTypes objType)
{
switch (objType)
{
case SpellTargetObjectTypes.Dest:
return SpellCastTargetFlags.DestLocation;
case SpellTargetObjectTypes.UnitAndDest:
return SpellCastTargetFlags.DestLocation | SpellCastTargetFlags.Unit;
case SpellTargetObjectTypes.CorpseAlly:
return SpellCastTargetFlags.CorpseAlly;
case SpellTargetObjectTypes.CorpseEnemy:
return SpellCastTargetFlags.CorpseEnemy;
case SpellTargetObjectTypes.Corpse:
return SpellCastTargetFlags.CorpseAlly | SpellCastTargetFlags.CorpseEnemy;
case SpellTargetObjectTypes.Unit:
return SpellCastTargetFlags.Unit;
case SpellTargetObjectTypes.Gobj:
return SpellCastTargetFlags.Gameobject;
case SpellTargetObjectTypes.GobjItem:
return SpellCastTargetFlags.GameobjectItem;
case SpellTargetObjectTypes.Item:
return SpellCastTargetFlags.Item;
case SpellTargetObjectTypes.Src:
return SpellCastTargetFlags.SourceLocation;
default:
return SpellCastTargetFlags.None;
}
}
public uint GetCategory()
{
return CategoryId;
}
public SpellEffectInfo[] GetEffectsForDifficulty(Difficulty difficulty)
{
SpellEffectInfo[] effList = new SpellEffectInfo[SpellConst.MaxEffects];
// downscale difficulty if original was not found
DifficultyRecord difficultyEntry = CliDB.DifficultyStorage.LookupByKey(difficulty);
while (difficultyEntry != null)
{
var effectArray = _effects.LookupByKey(difficulty);
if (effectArray != null)
{
foreach (SpellEffectInfo effect in effectArray)
{
if (effect == null)
continue;
if (effList[effect.EffectIndex] == null)
effList[effect.EffectIndex] = effect;
}
}
difficultyEntry = CliDB.DifficultyStorage.LookupByKey(difficultyEntry.FallbackDifficultyID);
}
// DIFFICULTY_NONE effects are the default effects, always active if current difficulty's effects don't overwrite
var effects = _effects.LookupByKey(Difficulty.None);
if (effects != null)
{
foreach (SpellEffectInfo effect in effects)
{
if (effect == null)
continue;
if (effList[effect.EffectIndex] == null)
effList[effect.EffectIndex] = effect;
}
}
return effList;
}
public SpellEffectInfo GetEffect(uint index) { return GetEffect(Difficulty.None, index); }
public SpellEffectInfo GetEffect(Difficulty difficulty, uint index)
{
DifficultyRecord difficultyEntry = CliDB.DifficultyStorage.LookupByKey(difficulty);
while (difficultyEntry != null)
{
var effectArray = _effects.LookupByKey(difficulty);
if (effectArray != null)
if (effectArray.Length > index && effectArray[index] != null)
return effectArray[index];
difficultyEntry = CliDB.DifficultyStorage.LookupByKey(difficultyEntry.FallbackDifficultyID);
}
var spellEffectInfos = _effects.LookupByKey(Difficulty.None);
if (spellEffectInfos != null)
if (spellEffectInfos.Length > index)
return spellEffectInfos[index];
return null;
}
public bool HasAttribute(SpellAttr0 attribute) { return Convert.ToBoolean(Attributes & attribute); }
public bool HasAttribute(SpellAttr1 attribute) { return Convert.ToBoolean(AttributesEx & attribute); }
public bool HasAttribute(SpellAttr2 attribute) { return Convert.ToBoolean(AttributesEx2 & attribute); }
public bool HasAttribute(SpellAttr3 attribute) { return Convert.ToBoolean(AttributesEx3 & attribute); }
public bool HasAttribute(SpellAttr4 attribute) { return Convert.ToBoolean(AttributesEx4 & attribute); }
public bool HasAttribute(SpellAttr5 attribute) { return Convert.ToBoolean(AttributesEx5 & attribute); }
public bool HasAttribute(SpellAttr6 attribute) { return Convert.ToBoolean(AttributesEx6 & attribute); }
public bool HasAttribute(SpellAttr7 attribute) { return Convert.ToBoolean(AttributesEx7 & attribute); }
public bool HasAttribute(SpellAttr8 attribute) { return Convert.ToBoolean(AttributesEx8 & attribute); }
public bool HasAttribute(SpellAttr9 attribute) { return Convert.ToBoolean(AttributesEx9 & attribute); }
public bool HasAttribute(SpellAttr10 attribute) { return Convert.ToBoolean(AttributesEx10 & attribute); }
public bool HasAttribute(SpellAttr11 attribute) { return Convert.ToBoolean(AttributesEx11 & attribute); }
public bool HasAttribute(SpellAttr12 attribute) { return Convert.ToBoolean(AttributesEx12 & attribute); }
public bool HasAttribute(SpellAttr13 attribute) { return Convert.ToBoolean(AttributesEx13 & attribute); }
public bool HasAttribute(SpellCustomAttributes attribute) { return Convert.ToBoolean(AttributesCu & attribute); }
#region Fields
public uint Id;
uint CategoryId;
public DispelType Dispel { get; set; }
public Mechanics Mechanic { get; set; }
public SpellAttr0 Attributes { get; set; }
public SpellAttr1 AttributesEx { get; set; }
public SpellAttr2 AttributesEx2 { get; set; }
public SpellAttr3 AttributesEx3 { get; set; }
public SpellAttr4 AttributesEx4 { get; set; }
public SpellAttr5 AttributesEx5 { get; set; }
public SpellAttr6 AttributesEx6 { get; set; }
public SpellAttr7 AttributesEx7 { get; set; }
public SpellAttr8 AttributesEx8 { get; set; }
public SpellAttr9 AttributesEx9 { get; set; }
public SpellAttr10 AttributesEx10 { get; set; }
public SpellAttr11 AttributesEx11 { get; set; }
public SpellAttr12 AttributesEx12 { get; set; }
public SpellAttr13 AttributesEx13 { get; set; }
public SpellCustomAttributes AttributesCu { get; set; }
public ulong Stances { get; set; }
public ulong StancesNot { get; set; }
public SpellCastTargetFlags targets { get; set; }
public uint TargetCreatureType { get; set; }
public uint RequiresSpellFocus { get; set; }
public uint FacingCasterFlags { get; set; }
public AuraStateType CasterAuraState { get; set; }
public AuraStateType TargetAuraState { get; set; }
public AuraStateType CasterAuraStateNot { get; set; }
public AuraStateType TargetAuraStateNot { get; set; }
public uint CasterAuraSpell { get; set; }
public uint TargetAuraSpell { get; set; }
public uint ExcludeCasterAuraSpell { get; set; }
public uint ExcludeTargetAuraSpell { get; set; }
public SpellCastTimesRecord CastTimeEntry { get; set; }
public uint RecoveryTime { get; set; }
public uint CategoryRecoveryTime { get; set; }
public uint StartRecoveryCategory { get; set; }
public uint StartRecoveryTime { get; set; }
public SpellInterruptFlags InterruptFlags { get; set; }
public SpellAuraInterruptFlags AuraInterruptFlags { get; set; }
public SpellChannelInterruptFlags ChannelInterruptFlags { get; set; }
public ProcFlags ProcFlags { get; set; }
public uint ProcChance { get; set; }
public uint ProcCharges { get; set; }
public uint ProcCooldown { get; set; }
public float ProcBasePPM { get; set; }
List<SpellProcsPerMinuteModRecord> ProcPPMMods = new List<SpellProcsPerMinuteModRecord>();
public uint MaxLevel { get; set; }
public uint BaseLevel { get; set; }
public uint SpellLevel { get; set; }
public SpellDurationRecord DurationEntry { get; set; }
public List<SpellPowerRecord> PowerCosts = new List<SpellPowerRecord>();
public uint RangeIndex { get; set; }
public SpellRangeRecord RangeEntry { get; set; }
public float Speed { get; set; }
public uint StackAmount { get; set; }
public uint[] Totem = new uint[SpellConst.MaxTotems];
public int[] Reagent = new int[SpellConst.MaxReagents];
public uint[] ReagentCount = new uint[SpellConst.MaxReagents];
public ItemClass EquippedItemClass { get; set; }
public int EquippedItemSubClassMask { get; set; }
public int EquippedItemInventoryTypeMask { get; set; }
public uint[] TotemCategory = new uint[SpellConst.MaxTotems];
public uint IconFileDataId { get; set; }
public uint ActiveIconFileDataId { get; set; }
public LocalizedString SpellName { get; set; }
public float ConeAngle { get; set; }
public float Width { get; set; }
public uint MaxTargetLevel { get; set; }
public uint MaxAffectedTargets { get; set; }
public SpellFamilyNames SpellFamilyName { get; set; }
public FlagArray128 SpellFamilyFlags { get; set; }
public SpellDmgClass DmgClass { get; set; }
public SpellPreventionType PreventionType { get; set; }
public int RequiredAreasID { get; set; }
public SpellSchoolMask SchoolMask { get; set; }
public uint ChargeCategoryId;
// SpellScalingEntry
public ScalingInfo Scaling;
public uint ExplicitTargetMask { get; set; }
public SpellChainNode ChainEntry { get; set; }
internal Dictionary<uint, SpellEffectInfo[]> _effects;
MultiMap<uint, SpellXSpellVisualRecord> _visuals = new MultiMap<uint, SpellXSpellVisualRecord>();
bool _hasPowerDifficultyData;
#endregion
public struct ScalingInfo
{
public int _Class { get; set; }
public uint MinScalingLevel;
public uint MaxScalingLevel;
public uint ScalesFromItemLevel;
}
}
public class SpellEffectInfo
{
public SpellEffectInfo(SpellEffectScalingRecord spellEffectScaling, SpellInfo spellInfo, uint effIndex, SpellEffectRecord _effect)
{
_spellInfo = spellInfo;
EffectIndex = effIndex;
TargetA = new SpellImplicitTargetInfo();
TargetB = new SpellImplicitTargetInfo();
SpellClassMask = new FlagArray128();
if (_effect != null)
{
EffectIndex = _effect.EffectIndex;
Effect = (SpellEffectName)_effect.Effect;
ApplyAuraName = (AuraType)_effect.EffectAura;
ApplyAuraPeriod = _effect.EffectAuraPeriod;
DieSides = (int)_effect.EffectDieSides;
RealPointsPerLevel = _effect.EffectRealPointsPerLevel;
BasePoints = (int)_effect.EffectBasePoints;
PointsPerResource = _effect.EffectPointsPerResource;
Amplitude = _effect.EffectAmplitude;
ChainAmplitude = _effect.EffectChainAmplitude;
BonusCoefficient = _effect.EffectBonusCoefficient;
MiscValue = _effect.EffectMiscValue;
MiscValueB = _effect.EffectMiscValueB;
Mechanic = (Mechanics)_effect.EffectMechanic;
PositionFacing = _effect.EffectPosFacing;
TargetA = new SpellImplicitTargetInfo((Targets)_effect.ImplicitTarget[0]);
TargetB = new SpellImplicitTargetInfo((Targets)_effect.ImplicitTarget[1]);
RadiusEntry = CliDB.SpellRadiusStorage.LookupByKey(_effect.EffectRadiusIndex);
MaxRadiusEntry = CliDB.SpellRadiusStorage.LookupByKey(_effect.EffectRadiusMaxIndex);
ChainTargets = _effect.EffectChainTargets;
ItemType = _effect.EffectItemType;
TriggerSpell = _effect.EffectTriggerSpell;
SpellClassMask = _effect.EffectSpellClassMask;
BonusCoefficientFromAP = _effect.BonusCoefficientFromAP;
}
ImplicitTargetConditions = null;
Scaling.Coefficient = spellEffectScaling != null ? spellEffectScaling.Coefficient : 0.0f;
Scaling.Variance = spellEffectScaling != null ? spellEffectScaling.Variance : 0.0f;
Scaling.ResourceCoefficient = spellEffectScaling != null ? spellEffectScaling.ResourceCoefficient : 0.0f;
}
public bool IsEffect()
{
return Effect != 0;
}
public bool IsEffect(SpellEffectName effectName)
{
return Effect == effectName;
}
public bool IsAura()
{
return (IsUnitOwnedAuraEffect() || Effect == SpellEffectName.PersistentAreaAura) && ApplyAuraName != 0;
}
public bool IsAura(AuraType aura)
{
return IsAura() && ApplyAuraName == aura;
}
public bool IsTargetingArea()
{
return TargetA.IsArea() || TargetB.IsArea();
}
public bool IsAreaAuraEffect()
{
if (Effect == SpellEffectName.ApplyAreaAuraParty ||
Effect == SpellEffectName.ApplyAreaAuraRaid ||
Effect == SpellEffectName.ApplyAreaAuraFriend ||
Effect == SpellEffectName.ApplyAreaAuraEnemy ||
Effect == SpellEffectName.ApplyAreaAuraPet ||
Effect == SpellEffectName.ApplyAreaAuraOwner)
return true;
return false;
}
public bool IsFarUnitTargetEffect()
{
return (Effect == SpellEffectName.SummonPlayer)
|| (Effect == SpellEffectName.SummonRafFriend)
|| (Effect == SpellEffectName.Resurrect)
|| (Effect == SpellEffectName.SkinPlayerCorpse);
}
bool IsFarDestTargetEffect()
{
return Effect == SpellEffectName.TeleportUnitsOld;
}
public bool IsUnitOwnedAuraEffect()
{
return IsAreaAuraEffect() || Effect == SpellEffectName.ApplyAura;
}
public int CalcValue(Unit caster = null, int? bp = null, Unit target = null, int itemLevel = -1)
{
float throwAway;
return CalcValue(out throwAway, caster, bp, target, itemLevel);
}
public int CalcValue(out float variance, Unit caster = null, int? bp = null, Unit target = null, int itemLevel = -1)
{
variance = 0.0f;
float basePointsPerLevel = RealPointsPerLevel;
int basePoints = bp.HasValue ? bp.Value : BasePoints;
float comboDamage = PointsPerResource;
float value;
// base amount modification based on spell lvl vs caster lvl
if (Scaling.Coefficient != 0.0f)
{
uint level = _spellInfo.SpellLevel;
if (target && _spellInfo.IsPositiveEffect(EffectIndex) && (Effect == SpellEffectName.ApplyAura))
level = target.getLevel();
else if (caster)
level = caster.getLevel();
if (!_spellInfo.HasAttribute(SpellAttr11.ScalesWithItemLevel) && _spellInfo.HasAttribute(SpellAttr10.UseSpellBaseLevelForScaling))
level = _spellInfo.BaseLevel;
if (_spellInfo.Scaling.MinScalingLevel != 0 && _spellInfo.Scaling.MinScalingLevel > level)
level = _spellInfo.Scaling.MinScalingLevel;
if (_spellInfo.Scaling.MaxScalingLevel != 0 && _spellInfo.Scaling.MaxScalingLevel < level)
level = _spellInfo.Scaling.MaxScalingLevel;
value = 0.0f;
if (level > 0)
{
if (_spellInfo.Scaling._Class == 0)
return 0;
if (_spellInfo.Scaling.ScalesFromItemLevel == 0)
{
if (!_spellInfo.HasAttribute(SpellAttr11.ScalesWithItemLevel))
value = CliDB.GetSpellScalingColumnForClass(CliDB.SpellScalingGameTable.GetRow(level), _spellInfo.Scaling._Class);
else
{
uint effectiveItemLevel = (uint)(itemLevel != -1 ? itemLevel : 1);
value = ItemEnchantment.GetRandomPropertyPoints(effectiveItemLevel, ItemQuality.Rare, InventoryType.Chest, 0);
if (IsAura() && ApplyAuraName == AuraType.ModRating)
{
GtCombatRatingsMultByILvlRecord ratingMult = CliDB.CombatRatingsMultByILvlGameTable.GetRow(effectiveItemLevel);
if (ratingMult != null)
value *= ratingMult.ArmorMultiplier;
}
}
}
else
value = ItemEnchantment.GetRandomPropertyPoints(_spellInfo.Scaling.ScalesFromItemLevel, ItemQuality.Rare, InventoryType.Chest, 0);
}
value *= Scaling.Coefficient;
if (value != 0.0f && value < 1.0f)
value = 1.0f;
if (Scaling.Variance != 0f)
{
float delta = Math.Abs(Scaling.Variance * 0.5f);
float valueVariance = RandomHelper.FRand(-delta, delta);
value += value * valueVariance;
variance = valueVariance;
}
basePoints = (int)Math.Round(value);
if (Scaling.ResourceCoefficient != 0f)
comboDamage = Scaling.ResourceCoefficient * value;
}
else
{
if (caster != null)
{
int level = (int)caster.getLevel();
if (level > _spellInfo.MaxLevel && _spellInfo.MaxLevel > 0)
level = (int)_spellInfo.MaxLevel;
else if (level < _spellInfo.BaseLevel)
level = (int)_spellInfo.BaseLevel;
if (!_spellInfo.IsPassive())
level -= (int)_spellInfo.SpellLevel;
basePoints += (int)(level * basePointsPerLevel);
}
// roll in a range <1;EffectDieSides> as of patch 3.3.3
int randomPoints = DieSides;
switch (randomPoints)
{
case 0:
break;
case 1:
basePoints += 1;
break; // range 1..1
default:
{
// range can have positive (1..rand) and negative (rand..1) values, so order its for irand
int randvalue = (randomPoints >= 1) ? RandomHelper.IRand(1, randomPoints) : RandomHelper.IRand(randomPoints, 1);
basePoints += randvalue;
break;
}
}
}
value = basePoints;
// random damage
if (caster != null)
{
// bonus amount from combo points
if (caster.m_playerMovingMe != null && comboDamage != 0)
{
byte comboPoints = caster.m_playerMovingMe.GetComboPoints();
if (comboPoints != 0)
value += comboDamage * comboPoints;
}
value = caster.ApplyEffectModifiers(_spellInfo, EffectIndex, value);
if (!caster.IsControlledByPlayer() && _spellInfo.SpellLevel != 0 && _spellInfo.SpellLevel != caster.getLevel() &&
basePointsPerLevel == 0 && _spellInfo.HasAttribute(SpellAttr0.LevelDamageCalculation))
{
bool canEffectScale = false;
switch (Effect)
{
case SpellEffectName.SchoolDamage:
case SpellEffectName.Dummy:
case SpellEffectName.PowerDrain:
case SpellEffectName.HealthLeech:
case SpellEffectName.Heal:
case SpellEffectName.WeaponDamage:
case SpellEffectName.PowerBurn:
case SpellEffectName.ScriptEffect:
case SpellEffectName.NormalizedWeaponDmg:
case SpellEffectName.ForceCastWithValue:
case SpellEffectName.TriggerSpellWithValue:
case SpellEffectName.TriggerMissileSpellWithValue:
canEffectScale = true;
break;
default:
break;
}
switch (ApplyAuraName)
{
case AuraType.PeriodicDamage:
case AuraType.Dummy:
case AuraType.PeriodicHeal:
case AuraType.DamageShield:
case AuraType.ProcTriggerDamage:
case AuraType.PeriodicLeech:
case AuraType.PeriodicManaLeech:
case AuraType.SchoolAbsorb:
case AuraType.PeriodicTriggerSpellWithValue:
canEffectScale = true;
break;
default:
break;
}
if (canEffectScale)
{
GtNpcManaCostScalerRecord spellScaler = CliDB.NpcManaCostScalerGameTable.GetRow(_spellInfo.SpellLevel);
GtNpcManaCostScalerRecord casterScaler = CliDB.NpcManaCostScalerGameTable.GetRow(caster.getLevel());
if (spellScaler != null && casterScaler != null)
value *= casterScaler.Scaler / spellScaler.Scaler;
}
}
}
return (int)value;
}
public int CalcBaseValue(int value)
{
if (DieSides == 0)
return value;
else
return value - 1;
}
public float CalcValueMultiplier(Unit caster, Spell spell = null)
{
float multiplier = Amplitude;
Player modOwner = (caster != null ? caster.GetSpellModOwner() : null);
if (modOwner != null)
modOwner.ApplySpellMod(_spellInfo.Id, SpellModOp.ValueMultiplier, ref multiplier, spell);
return multiplier;
}
public float CalcDamageMultiplier(Unit caster, Spell spell = null)
{
float multiplierPercent = ChainAmplitude * 100.0f;
Player modOwner = (caster != null ? caster.GetSpellModOwner() : null);
if (modOwner != null)
modOwner.ApplySpellMod(_spellInfo.Id, SpellModOp.DamageMultiplier, ref multiplierPercent, spell);
return multiplierPercent / 100.0f;
}
public bool HasRadius()
{
return RadiusEntry != null;
}
public bool HasMaxRadius()
{
return MaxRadiusEntry != null;
}
public float CalcRadius(Unit caster = null, Spell spell = null)
{
SpellRadiusRecord entry = RadiusEntry;
if (!HasRadius() && HasMaxRadius())
entry = MaxRadiusEntry;
if (entry == null)
return 0.0f;
float radius = entry.RadiusMin;
// Client uses max if min is 0
if (radius == 0.0f)
radius = entry.RadiusMax;
if (caster != null)
{
radius += entry.RadiusPerLevel * caster.getLevel();
radius = Math.Min(radius, entry.RadiusMax);
Player modOwner = caster.GetSpellModOwner();
if (modOwner != null)
modOwner.ApplySpellMod(_spellInfo.Id, SpellModOp.Radius, ref radius, spell);
}
return radius;
}
public SpellCastTargetFlags GetProvidedTargetMask()
{
return SpellInfo.GetTargetFlagMask(TargetA.GetObjectType()) | SpellInfo.GetTargetFlagMask(TargetB.GetObjectType());
}
public SpellCastTargetFlags GetMissingTargetMask(bool srcSet = false, bool dstSet = false, uint mask = 0)
{
var effImplicitTargetMask = SpellInfo.GetTargetFlagMask(GetUsedTargetObjectType());
var providedTargetMask = (SpellInfo.GetTargetFlagMask(TargetA.GetObjectType()) | SpellInfo.GetTargetFlagMask(TargetB.GetObjectType()) | (SpellCastTargetFlags)mask);
// remove all flags covered by effect target mask
if (Convert.ToBoolean(providedTargetMask & SpellCastTargetFlags.UnitMask))
effImplicitTargetMask &= ~SpellCastTargetFlags.UnitMask;
if (Convert.ToBoolean(providedTargetMask & SpellCastTargetFlags.CorpseMask))
effImplicitTargetMask &= ~(SpellCastTargetFlags.UnitMask | SpellCastTargetFlags.CorpseMask);
if (Convert.ToBoolean(providedTargetMask & SpellCastTargetFlags.GameobjectItem))
effImplicitTargetMask &= ~(SpellCastTargetFlags.GameobjectItem | SpellCastTargetFlags.Gameobject | SpellCastTargetFlags.Item);
if (Convert.ToBoolean(providedTargetMask & SpellCastTargetFlags.Gameobject))
effImplicitTargetMask &= ~(SpellCastTargetFlags.Gameobject | SpellCastTargetFlags.GameobjectItem);
if (Convert.ToBoolean(providedTargetMask & SpellCastTargetFlags.Item))
effImplicitTargetMask &= ~(SpellCastTargetFlags.Item | SpellCastTargetFlags.GameobjectItem);
if (dstSet || Convert.ToBoolean(providedTargetMask & SpellCastTargetFlags.DestLocation))
effImplicitTargetMask &= ~SpellCastTargetFlags.DestLocation;
if (srcSet || Convert.ToBoolean(providedTargetMask & SpellCastTargetFlags.SourceLocation))
effImplicitTargetMask &= ~SpellCastTargetFlags.SourceLocation;
return effImplicitTargetMask;
}
public SpellEffectImplicitTargetTypes GetImplicitTargetType()
{
return _data[(int)Effect].ImplicitTargetType;
}
public SpellTargetObjectTypes GetUsedTargetObjectType()
{
return _data[(int)Effect].UsedTargetObjectType;
}
public class StaticData
{
public StaticData(SpellEffectImplicitTargetTypes implicittarget, SpellTargetObjectTypes usedtarget)
{
ImplicitTargetType = implicittarget;
UsedTargetObjectType = usedtarget;
}
public SpellEffectImplicitTargetTypes ImplicitTargetType; // defines what target can be added to effect target list if there's no valid target type provided for effect
public SpellTargetObjectTypes UsedTargetObjectType; // defines valid target object type for spell effect
}
static StaticData[] _data = new StaticData[(int)SpellEffectName.TotalSpellEffects]
{
// implicit target type used target object type
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 0
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 1 SPELL_EFFECT_INSTAKILL
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 2 SPELL_EFFECT_SCHOOL_DAMAGE
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 3 SPELL_EFFECT_DUMMY
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 4 SPELL_EFFECT_PORTAL_TELEPORT
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.UnitAndDest), // 5 SPELL_EFFECT_TELEPORT_UNITS
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 6 SPELL_EFFECT_APPLY_AURA
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 7 SPELL_EFFECT_ENVIRONMENTAL_DAMAGE
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 8 SPELL_EFFECT_POWER_DRAIN
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 9 SPELL_EFFECT_HEALTH_LEECH
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 10 SPELL_EFFECT_HEAL
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 11 SPELL_EFFECT_BIND
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 12 SPELL_EFFECT_PORTAL
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 13 SPELL_EFFECT_RITUAL_BASE
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 14 SPELL_EFFECT_RITUAL_SPECIALIZE
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 15 SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 16 SPELL_EFFECT_QUEST_COMPLETE
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 17 SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.CorpseAlly), // 18 SPELL_EFFECT_RESURRECT
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 19 SPELL_EFFECT_ADD_EXTRA_ATTACKS
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.Unit), // 20 SPELL_EFFECT_DODGE
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.Unit), // 21 SPELL_EFFECT_EVADE
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.Unit), // 22 SPELL_EFFECT_PARRY
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.Unit), // 23 SPELL_EFFECT_BLOCK
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 24 SPELL_EFFECT_CREATE_ITEM
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.Unit), // 25 SPELL_EFFECT_WEAPON
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.Unit), // 26 SPELL_EFFECT_DEFENSE
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Dest), // 27 SPELL_EFFECT_PERSISTENT_AREA_AURA
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Dest), // 28 SPELL_EFFECT_SUMMON
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.UnitAndDest), // 29 SPELL_EFFECT_LEAP
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.Unit), // 30 SPELL_EFFECT_ENERGIZE
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 31 SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 32 SPELL_EFFECT_TRIGGER_MISSILE
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.GobjItem), // 33 SPELL_EFFECT_OPEN_LOCK
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.Unit), // 34 SPELL_EFFECT_SUMMON_CHANGE_ITEM
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 35 SPELL_EFFECT_APPLY_AREA_AURA_PARTY
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 36 SPELL_EFFECT_LEARN_SPELL
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.Unit), // 37 SPELL_EFFECT_SPELL_DEFENSE
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 38 SPELL_EFFECT_DISPEL
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.Unit), // 39 SPELL_EFFECT_LANGUAGE
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 40 SPELL_EFFECT_DUAL_WIELD
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 41 SPELL_EFFECT_JUMP
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.Dest), // 42 SPELL_EFFECT_JUMP_DEST
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.UnitAndDest), // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 44 SPELL_EFFECT_SKILL_STEP
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 45 SPELL_EFFECT_ADD_HONOR
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.Unit), // 46 SPELL_EFFECT_SPAWN
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.Unit), // 47 SPELL_EFFECT_TRADE_SKILL
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.Unit), // 48 SPELL_EFFECT_STEALTH
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.Unit), // 49 SPELL_EFFECT_DETECT
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Dest), // 50 SPELL_EFFECT_TRANS_DOOR
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.Unit), // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.Unit), // 52 SPELL_EFFECT_GUARANTEE_HIT
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Item), // 53 SPELL_EFFECT_ENCHANT_ITEM
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Item), // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 55 SPELL_EFFECT_TAMECREATURE
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Dest), // 56 SPELL_EFFECT_SUMMON_PET
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 57 SPELL_EFFECT_LEARN_PET_SPELL
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 58 SPELL_EFFECT_WEAPON_DAMAGE
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 59 SPELL_EFFECT_CREATE_RANDOM_ITEM
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.Unit), // 60 SPELL_EFFECT_PROFICIENCY
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 61 SPELL_EFFECT_SEND_EVENT
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 62 SPELL_EFFECT_POWER_BURN
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 63 SPELL_EFFECT_THREAT
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 64 SPELL_EFFECT_TRIGGER_SPELL
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 66 SPELL_EFFECT_CREATE_MANA_GEM
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 67 SPELL_EFFECT_HEAL_MAX_HEALTH
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 68 SPELL_EFFECT_INTERRUPT_CAST
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.UnitAndDest), // 69 SPELL_EFFECT_DISTRACT
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 70 SPELL_EFFECT_PULL
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 71 SPELL_EFFECT_PICKPOCKET
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Dest), // 72 SPELL_EFFECT_ADD_FARSIGHT
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 73 SPELL_EFFECT_UNTRAIN_TALENTS
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.Unit), // 74 SPELL_EFFECT_APPLY_GLYPH
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 75 SPELL_EFFECT_HEAL_MECHANICAL
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Dest), // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 77 SPELL_EFFECT_SCRIPT_EFFECT
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.Unit), // 78 SPELL_EFFECT_ATTACK
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.Unit), // 79 SPELL_EFFECT_SANCTUARY
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 80 SPELL_EFFECT_ADD_COMBO_POINTS
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Dest), // 81 SPELL_EFFECT_CREATE_HOUSE
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 82 SPELL_EFFECT_BIND_SIGHT
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.UnitAndDest), // 83 SPELL_EFFECT_DUEL
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.Unit), // 84 SPELL_EFFECT_STUCK
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 85 SPELL_EFFECT_SUMMON_PLAYER
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Gobj), // 86 SPELL_EFFECT_ACTIVATE_OBJECT
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Gobj), // 87 SPELL_EFFECT_GAMEOBJECT_DAMAGE
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Gobj), // 88 SPELL_EFFECT_GAMEOBJECT_REPAIR
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Gobj), // 89 SPELL_EFFECT_GAMEOBJECT_SET_DESTRUCTION_STATE
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 90 SPELL_EFFECT_KILL_CREDIT
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 91 SPELL_EFFECT_THREAT_ALL
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.Unit), // 93 SPELL_EFFECT_FORCE_DESELECT
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.Unit), // 94 SPELL_EFFECT_SELF_RESURRECT
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 95 SPELL_EFFECT_SKINNING
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 96 SPELL_EFFECT_CHARGE
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.Unit), // 97 SPELL_EFFECT_CAST_BUTTON
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 98 SPELL_EFFECT_KNOCK_BACK
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Item), // 99 SPELL_EFFECT_DISENCHANT
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 100 SPELL_EFFECT_INEBRIATE
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Item), // 101 SPELL_EFFECT_FEED_PET
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 102 SPELL_EFFECT_DISMISS_PET
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 103 SPELL_EFFECT_REPUTATION
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Dest), // 104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Dest), // 105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Dest), // 106 SPELL_EFFECT_CHANGE_RAID_MARKER
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Dest), // 107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 108 SPELL_EFFECT_DISPEL_MECHANIC
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Dest), // 109 SPELL_EFFECT_SUMMON_DEAD_PET
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.Unit), // 110 SPELL_EFFECT_DESTROY_ALL_TOTEMS
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 111 SPELL_EFFECT_DURABILITY_DAMAGE
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 112 SPELL_EFFECT_112
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.CorpseAlly), // 113 SPELL_EFFECT_RESURRECT_NEW
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 114 SPELL_EFFECT_ATTACK_ME
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.CorpseEnemy), // 116 SPELL_EFFECT_SKIN_PLAYER_CORPSE
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 117 SPELL_EFFECT_SPIRIT_HEAL
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.Unit), // 118 SPELL_EFFECT_SKILL
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 119 SPELL_EFFECT_APPLY_AREA_AURA_PET
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 120 SPELL_EFFECT_TELEPORT_GRAVEYARD
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 121 SPELL_EFFECT_NORMALIZED_WEAPON_DMG
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 122 SPELL_EFFECT_122
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 123 SPELL_EFFECT_SEND_TAXI
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 124 SPELL_EFFECT_PULL_TOWARDS
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 125 SPELL_EFFECT_MODIFY_THREAT_PERCENT
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Item), // 127 SPELL_EFFECT_PROSPECTING
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 130 SPELL_EFFECT_REDIRECT_THREAT
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.Unit), // 131 SPELL_EFFECT_PLAY_SOUND
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 132 SPELL_EFFECT_PLAY_MUSIC
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 133 SPELL_EFFECT_UNLEARN_SPECIALIZATION
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.Unit), // 134 SPELL_EFFECT_KILL_CREDIT2
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Dest), // 135 SPELL_EFFECT_CALL_PET
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 136 SPELL_EFFECT_HEAL_PCT
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 137 SPELL_EFFECT_ENERGIZE_PCT
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 138 SPELL_EFFECT_LEAP_BACK
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 139 SPELL_EFFECT_CLEAR_QUEST
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 140 SPELL_EFFECT_FORCE_CAST
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 141 SPELL_EFFECT_FORCE_CAST_WITH_VALUE
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.UnitAndDest), // 144 SPELL_EFFECT_KNOCK_BACK_DEST
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.UnitAndDest), // 145 SPELL_EFFECT_PULL_TOWARDS_DEST
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 146 SPELL_EFFECT_ACTIVATE_RUNE
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 147 SPELL_EFFECT_QUEST_FAIL
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 148 SPELL_EFFECT_TRIGGER_MISSILE_SPELL_WITH_VALUE
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Dest), // 149 SPELL_EFFECT_CHARGE_DEST
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 150 SPELL_EFFECT_QUEST_START
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 151 SPELL_EFFECT_TRIGGER_SPELL_2
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 152 SPELL_EFFECT_SUMMON_RAF_FRIEND
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 153 SPELL_EFFECT_CREATE_TAMED_PET
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 154 SPELL_EFFECT_DISCOVER_TAXI
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.Unit), // 155 SPELL_EFFECT_TITAN_GRIP
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Item), // 156 SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 157 SPELL_EFFECT_CREATE_ITEM_2
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Item), // 158 SPELL_EFFECT_MILLING
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 159 SPELL_EFFECT_ALLOW_RENAME_PET
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 160 SPELL_EFFECT_160
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 161 SPELL_EFFECT_TALENT_SPEC_COUNT
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 162 SPELL_EFFECT_TALENT_SPEC_SELECT
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 163 SPELL_EFFECT_163
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 164 SPELL_EFFECT_REMOVE_AURA
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 165 SPELL_EFFECT_165
new StaticData(SpellEffectImplicitTargetTypes.Caster, SpellTargetObjectTypes.Unit), // 166 SPELL_EFFECT_GIVE_CURRENCY
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 167 SPELL_EFFECT_167
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 168 SPELL_EFFECT_168
new StaticData(SpellEffectImplicitTargetTypes.Caster, SpellTargetObjectTypes.Unit), // 169 SPELL_EFFECT_DESTROY_ITEM
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 170 SPELL_EFFECT_170
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.Dest), // 171 SPELL_EFFECT_171
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 172 SPELL_EFFECT_172
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 173 SPELL_EFFECT_UNLOCK_GUILD_VAULT_TAB
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 174 SPELL_EFFECT_174
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 175 SPELL_EFFECT_175
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 176 SPELL_EFFECT_176
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 177 SPELL_EFFECT_177
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 178 SPELL_EFFECT_178
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.Dest), // 179 SPELL_EFFECT_CREATE_AREATRIGGER
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 180 SPELL_EFFECT_UPDATE_AREATRIGGER
new StaticData(SpellEffectImplicitTargetTypes.Caster, SpellTargetObjectTypes.Unit), // 181 SPELL_EFFECT_REMOVE_TALENT
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 182 SPELL_EFFECT_182
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 183 SPELL_EFFECT_183
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 184 SPELL_EFFECT_REPUTATION_2
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 185 SPELL_EFFECT_185
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 186 SPELL_EFFECT_186
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 187 SPELL_EFFECT_RANDOMIZE_ARCHAEOLOGY_DIGSITES
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 188 SPELL_EFFECT_188
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 189 SPELL_EFFECT_LOOT
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 190 SPELL_EFFECT_190
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 191 SPELL_EFFECT_TELEPORT_TO_DIGSITE
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 192 SPELL_EFFECT_192
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 193 SPELL_EFFECT_193
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 194 SPELL_EFFECT_194
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 195 SPELL_EFFECT_195
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 196 SPELL_EFFECT_196
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 197 SPELL_EFFECT_197
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.Dest), // 198 SPELL_EFFECT_PLAY_SCENE
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 199 SPELL_EFFECT_199
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 200 SPELL_EFFECT_HEAL_BATTLEPET_PCT
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 201 SPELL_EFFECT_ENABLE_BATTLE_PETS
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 202 SPELL_EFFECT_202
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 203 SPELL_EFFECT_203
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 204 SPELL_EFFECT_CHANGE_BATTLEPET_QUALITY
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 205 SPELL_EFFECT_LAUNCH_QUEST_CHOICE
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Item), // 206 SPELL_EFFECT_ALTER_ITEM
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 207 SPELL_EFFECT_LAUNCH_QUEST_TASK
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 208 SPELL_EFFECT_208
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 209 SPELL_EFFECT_209
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 210 SPELL_EFFECT_LEARN_GARRISON_BUILDING
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 211 SPELL_EFFECT_LEARN_GARRISON_SPECIALIZATION
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 212 SPELL_EFFECT_212
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 213 SPELL_EFFECT_213
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 214 SPELL_EFFECT_CREATE_GARRISON
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 215 SPELL_EFFECT_UPGRADE_CHARACTER_SPELLS
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 216 SPELL_EFFECT_CREATE_SHIPMENT
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 217 SPELL_EFFECT_UPGRADE_GARRISON
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 218 SPELL_EFFECT_218
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 219 SPELL_EFFECT_CREATE_CONVERSATION
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 220 SPELL_EFFECT_ADD_GARRISON_FOLLOWER
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 221 SPELL_EFFECT_221
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 222 SPELL_EFFECT_CREATE_HEIRLOOM_ITEM
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 223 SPELL_EFFECT_CHANGE_ITEM_BONUSES
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 224 SPELL_EFFECT_ACTIVATE_GARRISON_BUILDING
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 225 SPELL_EFFECT_GRANT_BATTLEPET_LEVEL
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 226 SPELL_EFFECT_226
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 227 SPELL_EFFECT_227
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 228 SPELL_EFFECT_228
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 229 SPELL_EFFECT_SET_FOLLOWER_QUALITY
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 230 SPELL_EFFECT_INCREASE_FOLLOWER_ITEM_LEVEL
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 231 SPELL_EFFECT_INCREASE_FOLLOWER_EXPERIENCE
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 232 SPELL_EFFECT_REMOVE_PHASE
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 233 SPELL_EFFECT_RANDOMIZE_FOLLOWER_ABILITIES
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 234 SPELL_EFFECT_234
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 235 SPELL_EFFECT_235
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 236 SPELL_EFFECT_GIVE_EXPERIENCE
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 237 SPELL_EFFECT_GIVE_RESTED_EXPERIENCE_BONUS
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 238 SPELL_EFFECT_INCREASE_SKILL
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 239 SPELL_EFFECT_END_GARRISON_BUILDING_CONSTRUCTION
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 240 SPELL_EFFECT_240
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 241 SPELL_EFFECT_241
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 242 SPELL_EFFECT_242
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Item), // 243 SPELL_EFFECT_APPLY_ENCHANT_ILLUSION
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 244 SPELL_EFFECT_LEARN_FOLLOWER_ABILITY
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 245 SPELL_EFFECT_UPGRADE_HEIRLOOM
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 246 SPELL_EFFECT_FINISH_GARRISON_MISSION
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 247 SPELL_EFFECT_ADD_GARRISON_MISSION
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 248 SPELL_EFFECT_FINISH_SHIPMENT
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 249 SPELL_EFFECT_249
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 250 SPELL_EFFECT_TAKE_SCREENSHOT
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 251 SPELL_EFFECT_SET_GARRISON_CACHE_SIZE
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 252 SPELL_EFFECT_252
new StaticData(SpellEffectImplicitTargetTypes.Explicit, SpellTargetObjectTypes.Unit), // 253 SPELL_EFFECT_GIVE_HONOR
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None), // 254 SPELL_EFFECT_254
new StaticData(SpellEffectImplicitTargetTypes.None, SpellTargetObjectTypes.None) // 255 SPELL_EFFECT_255
};
#region Fields
SpellInfo _spellInfo;
public uint EffectIndex;
public SpellEffectName Effect;
public AuraType ApplyAuraName;
public uint ApplyAuraPeriod;
public int DieSides;
public float RealPointsPerLevel;
public int BasePoints;
public float PointsPerResource;
public float Amplitude;
public float ChainAmplitude;
public float BonusCoefficient;
public int MiscValue;
public int MiscValueB;
public Mechanics Mechanic;
public float PositionFacing;
public SpellImplicitTargetInfo TargetA;
public SpellImplicitTargetInfo TargetB;
public SpellRadiusRecord RadiusEntry;
public SpellRadiusRecord MaxRadiusEntry;
public uint ChainTargets;
public uint ItemType;
public uint TriggerSpell;
public FlagArray128 SpellClassMask;
public float BonusCoefficientFromAP;
public List<Condition> ImplicitTargetConditions;
public ScalingInfo Scaling;
#endregion
public struct ScalingInfo
{
public float Coefficient;
public float Variance;
public float ResourceCoefficient;
}
}
public class SpellImplicitTargetInfo
{
public SpellImplicitTargetInfo(Targets target = 0)
{
_target = target;
}
public bool IsArea()
{
return GetSelectionCategory() == SpellTargetSelectionCategories.Area || GetSelectionCategory() == SpellTargetSelectionCategories.Cone;
}
public SpellTargetSelectionCategories GetSelectionCategory()
{
return _data[(int)_target].SelectionCategory;
}
public SpellTargetReferenceTypes GetReferenceType()
{
return _data[(int)_target].ReferenceType;
}
public SpellTargetObjectTypes GetObjectType()
{
return _data[(int)_target].ObjectType;
}
public SpellTargetCheckTypes GetCheckType()
{
return _data[(int)_target].SelectionCheckType;
}
SpellTargetDirectionTypes GetDirectionType()
{
return _data[(int)_target].DirectionType;
}
public float CalcDirectionAngle()
{
float pi = MathFunctions.PI;
switch (GetDirectionType())
{
case SpellTargetDirectionTypes.Front:
return 0.0f;
case SpellTargetDirectionTypes.Back:
return pi;
case SpellTargetDirectionTypes.Right:
return -pi / 2;
case SpellTargetDirectionTypes.Left:
return pi / 2;
case SpellTargetDirectionTypes.FrontRight:
return -pi / 4;
case SpellTargetDirectionTypes.BackRight:
return -3 * pi / 4;
case SpellTargetDirectionTypes.BackLeft:
return 3 * pi / 4;
case SpellTargetDirectionTypes.FrontLeft:
return pi / 4;
case SpellTargetDirectionTypes.Random:
return (float)RandomHelper.NextDouble() * (2 * pi);
default:
return 0.0f;
}
}
public Targets GetTarget()
{
return _target;
}
public uint getTarget()
{
return (uint)_target;
}
public SpellCastTargetFlags GetExplicitTargetMask(bool srcSet, bool dstSet)
{
SpellCastTargetFlags targetMask = 0;
if (GetTarget() == Targets.DestTraj)
{
if (!srcSet)
targetMask = SpellCastTargetFlags.SourceLocation;
if (!dstSet)
targetMask |= SpellCastTargetFlags.DestLocation;
}
else
{
switch (GetReferenceType())
{
case SpellTargetReferenceTypes.Src:
if (srcSet)
break;
targetMask = SpellCastTargetFlags.SourceLocation;
break;
case SpellTargetReferenceTypes.Dest:
if (dstSet)
break;
targetMask = SpellCastTargetFlags.DestLocation;
break;
case SpellTargetReferenceTypes.Target:
switch (GetObjectType())
{
case SpellTargetObjectTypes.Gobj:
targetMask = SpellCastTargetFlags.Gameobject;
break;
case SpellTargetObjectTypes.GobjItem:
targetMask = SpellCastTargetFlags.GameobjectItem;
break;
case SpellTargetObjectTypes.UnitAndDest:
case SpellTargetObjectTypes.Unit:
case SpellTargetObjectTypes.Dest:
switch (GetCheckType())
{
case SpellTargetCheckTypes.Enemy:
targetMask = SpellCastTargetFlags.UnitEnemy;
break;
case SpellTargetCheckTypes.Ally:
targetMask = SpellCastTargetFlags.UnitAlly;
break;
case SpellTargetCheckTypes.Party:
targetMask = SpellCastTargetFlags.UnitParty;
break;
case SpellTargetCheckTypes.Raid:
targetMask = SpellCastTargetFlags.UnitRaid;
break;
case SpellTargetCheckTypes.Passenger:
targetMask = SpellCastTargetFlags.UnitPassenger;
break;
case SpellTargetCheckTypes.RaidClass:
default:
targetMask = SpellCastTargetFlags.Unit;
break;
}
break;
default:
break;
}
break;
default:
break;
}
}
switch (GetObjectType())
{
case SpellTargetObjectTypes.Src:
srcSet = true;
break;
case SpellTargetObjectTypes.Dest:
case SpellTargetObjectTypes.UnitAndDest:
dstSet = true;
break;
default:
break;
}
return targetMask;
}
Targets _target;
public struct StaticData
{
public StaticData(SpellTargetObjectTypes obj, SpellTargetReferenceTypes reference,
SpellTargetSelectionCategories selection, SpellTargetCheckTypes selectionCheck, SpellTargetDirectionTypes direction)
{
ObjectType = obj;
ReferenceType = reference;
SelectionCategory = selection;
SelectionCheckType = selectionCheck;
DirectionType = direction;
}
public SpellTargetObjectTypes ObjectType; // type of object returned by target type
public SpellTargetReferenceTypes ReferenceType; // defines which object is used as a reference when selecting target
public SpellTargetSelectionCategories SelectionCategory;
public SpellTargetCheckTypes SelectionCheckType; // defines selection criteria
public SpellTargetDirectionTypes DirectionType; // direction for cone and dest targets
}
static StaticData[] _data = new StaticData[(int)Targets.TotalSpellTargets]
{
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 0
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 1 TARGET_UNIT_CASTER
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Nearby, SpellTargetCheckTypes.Enemy, SpellTargetDirectionTypes.None), // 2 TARGET_UNIT_NEARBY_ENEMY
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Nearby, SpellTargetCheckTypes.Party, SpellTargetDirectionTypes.None), // 3 TARGET_UNIT_NEARBY_PARTY
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Nearby, SpellTargetCheckTypes.Ally, SpellTargetDirectionTypes.None), // 4 TARGET_UNIT_NEARBY_ALLY
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 5 TARGET_UNIT_PET
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Target, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Enemy, SpellTargetDirectionTypes.None), // 6 TARGET_UNIT_TARGET_ENEMY
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Src, SpellTargetSelectionCategories.Area, SpellTargetCheckTypes.Entry, SpellTargetDirectionTypes.None), // 7 TARGET_UNIT_SRC_AREA_ENTRY
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Dest, SpellTargetSelectionCategories.Area, SpellTargetCheckTypes.Entry, SpellTargetDirectionTypes.None), // 8 TARGET_UNIT_DEST_AREA_ENTRY
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 9 TARGET_DEST_HOME
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 10
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Src, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 11 TARGET_UNIT_SRC_AREA_UNK_11
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 12
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 13
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 14
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Src, SpellTargetSelectionCategories.Area, SpellTargetCheckTypes.Enemy, SpellTargetDirectionTypes.None), // 15 TARGET_UNIT_SRC_AREA_ENEMY
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Dest, SpellTargetSelectionCategories.Area, SpellTargetCheckTypes.Enemy, SpellTargetDirectionTypes.None), // 16 TARGET_UNIT_DEST_AREA_ENEMY
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 17 TARGET_DEST_DB
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 18 TARGET_DEST_CASTER
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 19
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Area, SpellTargetCheckTypes.Party, SpellTargetDirectionTypes.None), // 20 TARGET_UNIT_CASTER_AREA_PARTY
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Target, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Ally, SpellTargetDirectionTypes.None), // 21 TARGET_UNIT_TARGET_ALLY
new StaticData(SpellTargetObjectTypes.Src, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 22 TARGET_SRC_CASTER
new StaticData(SpellTargetObjectTypes.Gobj, SpellTargetReferenceTypes.Target, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 23 TARGET_GAMEOBJECT_TARGET
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Cone, SpellTargetCheckTypes.Enemy, SpellTargetDirectionTypes.Front), // 24 TARGET_UNIT_CONE_ENEMY_24
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Target, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 25 TARGET_UNIT_TARGET_ANY
new StaticData(SpellTargetObjectTypes.GobjItem, SpellTargetReferenceTypes.Target, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 26 TARGET_GAMEOBJECT_ITEM_TARGET
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 27 TARGET_UNIT_MASTER
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Dest, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Enemy, SpellTargetDirectionTypes.None), // 28 TARGET_DEST_DYNOBJ_ENEMY
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Dest, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Ally, SpellTargetDirectionTypes.None), // 29 TARGET_DEST_DYNOBJ_ALLY
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Src, SpellTargetSelectionCategories.Area, SpellTargetCheckTypes.Ally, SpellTargetDirectionTypes.None), // 30 TARGET_UNIT_SRC_AREA_ALLY
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Dest, SpellTargetSelectionCategories.Area, SpellTargetCheckTypes.Ally, SpellTargetDirectionTypes.None), // 31 TARGET_UNIT_DEST_AREA_ALLY
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.FrontLeft), // 32 TARGET_DEST_CASTER_SUMMON
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Src, SpellTargetSelectionCategories.Area, SpellTargetCheckTypes.Party, SpellTargetDirectionTypes.None), // 33 TARGET_UNIT_SRC_AREA_PARTY
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Dest, SpellTargetSelectionCategories.Area, SpellTargetCheckTypes.Party, SpellTargetDirectionTypes.None), // 34 TARGET_UNIT_DEST_AREA_PARTY
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Target, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Party, SpellTargetDirectionTypes.None), // 35 TARGET_UNIT_TARGET_PARTY
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 36 TARGET_DEST_CASTER_UNK_36
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Last, SpellTargetSelectionCategories.Area, SpellTargetCheckTypes.Party, SpellTargetDirectionTypes.None), // 37 TARGET_UNIT_LASTTARGET_AREA_PARTY
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Nearby, SpellTargetCheckTypes.Entry, SpellTargetDirectionTypes.None), // 38 TARGET_UNIT_NEARBY_ENTRY
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 39 TARGET_DEST_CASTER_FISHING
new StaticData(SpellTargetObjectTypes.Gobj, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Nearby, SpellTargetCheckTypes.Entry, SpellTargetDirectionTypes.None), // 40 TARGET_GAMEOBJECT_NEARBY_ENTRY
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.FrontRight), // 41 TARGET_DEST_CASTER_FRONT_RIGHT
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.BackRight), // 42 TARGET_DEST_CASTER_BACK_RIGHT
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.BackLeft), // 43 TARGET_DEST_CASTER_BACK_LEFT
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.FrontLeft), // 44 TARGET_DEST_CASTER_FRONT_LEFT
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Target, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Ally, SpellTargetDirectionTypes.None), // 45 TARGET_UNIT_TARGET_CHAINHEAL_ALLY
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Nearby, SpellTargetCheckTypes.Entry, SpellTargetDirectionTypes.None), // 46 TARGET_DEST_NEARBY_ENTRY
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.Front), // 47 TARGET_DEST_CASTER_FRONT
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.Back), // 48 TARGET_DEST_CASTER_BACK
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.Right), // 49 TARGET_DEST_CASTER_RIGHT
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.Left), // 50 TARGET_DEST_CASTER_LEFT
new StaticData(SpellTargetObjectTypes.Gobj, SpellTargetReferenceTypes.Src, SpellTargetSelectionCategories.Area, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 51 TARGET_GAMEOBJECT_SRC_AREA
new StaticData(SpellTargetObjectTypes.Gobj, SpellTargetReferenceTypes.Dest, SpellTargetSelectionCategories.Area, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 52 TARGET_GAMEOBJECT_DEST_AREA
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Target, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Enemy, SpellTargetDirectionTypes.None), // 53 TARGET_DEST_TARGET_ENEMY
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Cone, SpellTargetCheckTypes.Enemy, SpellTargetDirectionTypes.Front), // 54 TARGET_UNIT_CONE_ENEMY_54
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 55 TARGET_DEST_CASTER_FRONT_LEAP
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Area, SpellTargetCheckTypes.Raid, SpellTargetDirectionTypes.None), // 56 TARGET_UNIT_CASTER_AREA_RAID
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Target, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Raid, SpellTargetDirectionTypes.None), // 57 TARGET_UNIT_TARGET_RAID
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Nearby, SpellTargetCheckTypes.Raid, SpellTargetDirectionTypes.None), // 58 TARGET_UNIT_NEARBY_RAID
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Cone, SpellTargetCheckTypes.Ally, SpellTargetDirectionTypes.Front), // 59 TARGET_UNIT_CONE_ALLY
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Cone, SpellTargetCheckTypes.Entry, SpellTargetDirectionTypes.Front), // 60 TARGET_UNIT_CONE_ENTRY
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Target, SpellTargetSelectionCategories.Area, SpellTargetCheckTypes.RaidClass, SpellTargetDirectionTypes.None), // 61 TARGET_UNIT_TARGET_AREA_RAID_CLASS
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 62 TARGET_UNK_62
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Target, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 63 TARGET_DEST_TARGET_ANY
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Target, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.Front), // 64 TARGET_DEST_TARGET_FRONT
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Target, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.Back), // 65 TARGET_DEST_TARGET_BACK
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Target, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.Right), // 66 TARGET_DEST_TARGET_RIGHT
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Target, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.Left), // 67 TARGET_DEST_TARGET_LEFT
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Target, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.FrontRight), // 68 TARGET_DEST_TARGET_FRONT_RIGHT
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Target, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.BackRight), // 69 TARGET_DEST_TARGET_BACK_RIGHT
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Target, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.BackLeft), // 70 TARGET_DEST_TARGET_BACK_LEFT
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Target, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.FrontLeft), // 71 TARGET_DEST_TARGET_FRONT_LEFT
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.Random), // 72 TARGET_DEST_CASTER_RANDOM
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.Random), // 73 TARGET_DEST_CASTER_RADIUS
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Target, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.Random), // 74 TARGET_DEST_TARGET_RANDOM
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Target, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.Random), // 75 TARGET_DEST_TARGET_RADIUS
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Channel, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 76 TARGET_DEST_CHANNEL_TARGET
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Channel, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 77 TARGET_UNIT_CHANNEL_TARGET
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Dest, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.Front), // 78 TARGET_DEST_DEST_FRONT
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Dest, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.Back), // 79 TARGET_DEST_DEST_BACK
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Dest, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.Right), // 80 TARGET_DEST_DEST_RIGHT
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Dest, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.Left), // 81 TARGET_DEST_DEST_LEFT
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Dest, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.FrontRight), // 82 TARGET_DEST_DEST_FRONT_RIGHT
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Dest, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.BackRight), // 83 TARGET_DEST_DEST_BACK_RIGHT
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Dest, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.BackLeft), // 84 TARGET_DEST_DEST_BACK_LEFT
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Dest, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.FrontLeft), // 85 TARGET_DEST_DEST_FRONT_LEFT
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Dest, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.Random), // 86 TARGET_DEST_DEST_RANDOM
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Dest, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 87 TARGET_DEST_DEST
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Dest, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 88 TARGET_DEST_DYNOBJ_NONE
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Dest, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 89 TARGET_DEST_TRAJ
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Target, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 90 TARGET_UNIT_TARGET_MINIPET
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Dest, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.Random), // 91 TARGET_DEST_DEST_RADIUS
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 92 TARGET_UNIT_SUMMONER
new StaticData(SpellTargetObjectTypes.Corpse,SpellTargetReferenceTypes.Src, SpellTargetSelectionCategories.Area, SpellTargetCheckTypes.Enemy, SpellTargetDirectionTypes.None), // 93 TARGET_CORPSE_SRC_AREA_ENEMY
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 94 TARGET_UNIT_VEHICLE
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Target, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Passenger,SpellTargetDirectionTypes.None), // 95 TARGET_UNIT_TARGET_PASSENGER
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 96 TARGET_UNIT_PASSENGER_0
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 97 TARGET_UNIT_PASSENGER_1
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 98 TARGET_UNIT_PASSENGER_2
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 99 TARGET_UNIT_PASSENGER_3
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 100 TARGET_UNIT_PASSENGER_4
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 101 TARGET_UNIT_PASSENGER_5
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 102 TARGET_UNIT_PASSENGER_6
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 103 TARGET_UNIT_PASSENGER_7
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Cone, SpellTargetCheckTypes.Enemy, SpellTargetDirectionTypes.Front), // 104 TARGET_UNIT_CONE_ENEMY_104
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 105 TARGET_UNIT_UNK_105
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Channel, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 106 TARGET_DEST_CHANNEL_CASTER
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.Dest, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 107 TARGET_UNK_DEST_AREA_UNK_107
new StaticData(SpellTargetObjectTypes.Gobj, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Cone, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.Front), // 108 TARGET_GAMEOBJECT_CONE_108
new StaticData(SpellTargetObjectTypes.Gobj, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Cone, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.Front), // 109 TARGET_GAMEOBJECT_CONE_109
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Cone, SpellTargetCheckTypes.Entry , SpellTargetDirectionTypes.Front), // 110 TARGET_DEST_UNK_110
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 111
new StaticData(SpellTargetObjectTypes.Dest, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 112
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 113
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 114
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 115
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 116
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 117
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Area, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 118
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Area, SpellTargetCheckTypes.Raid, SpellTargetDirectionTypes.None), // 119
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Area, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 120
new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Target, SpellTargetSelectionCategories.Default, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 121
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 122
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 123
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 124
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 125
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 126
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 127
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 128
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 129
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 130
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 131
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 132
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 133
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 134
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 135
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 136
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 137
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 138
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 139
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 140
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 141
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 142
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 143
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 144
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 145
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 146
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 147
new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None) // 148)
};
}
public class SpellPowerCost
{
public PowerType Power;
public int Amount;
}
}