diff --git a/Framework/Util/MathFunctions.cs b/Framework/Util/MathFunctions.cs index 6863df173..f45afda71 100644 --- a/Framework/Util/MathFunctions.cs +++ b/Framework/Util/MathFunctions.cs @@ -92,6 +92,11 @@ public static class MathFunctions return a + (b - a) * f; } + public static float DegToRad(float degrees) + { + return degrees * (2.0f * PI / 360.0f); + } + #region Fuzzy public static bool fuzzyEq(double a, double b) { @@ -109,13 +114,14 @@ public static class MathFunctions { return !fuzzyEq(a, b); } - public static bool fuzzyLe(double a, double b) { return a < b + eps(a, b); } - - + public static bool fuzzyGe(double a, double b) + { + return a > b - eps(a, b); + } #endregion public static int ApplyPct(ref int Base, float pct) diff --git a/Game/Spells/Auras/Aura.cs b/Game/Spells/Auras/Aura.cs index e36f22c18..b4d9cfb8c 100644 --- a/Game/Spells/Auras/Aura.cs +++ b/Game/Spells/Auras/Aura.cs @@ -952,10 +952,6 @@ namespace Game.Spells if (GetSpellInfo().IsSingleTarget()) return false; - // Can't be saved - aura handler relies on calculated amount and changes it - if (HasEffectType(AuraType.ConvertRune)) - return false; - // No point in saving this, since the stable dialog can't be open on aura load anyway. if (HasEffectType(AuraType.OpenStable)) return false; diff --git a/Game/Spells/Spell.cs b/Game/Spells/Spell.cs index 2ac984135..5422e0592 100644 --- a/Game/Spells/Spell.cs +++ b/Game/Spells/Spell.cs @@ -478,8 +478,9 @@ namespace Game.Spells WorldObject target = Global.ObjAccessor.GetUnit(m_caster, channelTarget); CallScriptObjectTargetSelectHandlers(ref target, effIndex, targetType); // unit target may be no longer avalible - teleported out of map for example - if (target && target.IsTypeId(TypeId.Unit)) - AddUnitTarget(target.ToUnit(), 1u << (int)effIndex); + Unit unitTarget = target ? target.ToUnit() : null; + if (unitTarget) + AddUnitTarget(unitTarget, 1u << (int)effIndex); else Log.outDebug(LogFilter.Spells, "SPELL: cannot find channel spell target for spell ID {0}, effect {1}", m_spellInfo.Id, effIndex); } @@ -636,13 +637,12 @@ namespace Game.Spells return; var condList = effect.ImplicitTargetConditions; - float coneAngle = MathFunctions.PiOver2; float radius = effect.CalcRadius(m_caster) * m_spellValue.RadiusMod; GridMapTypeMask containerTypeMask = GetSearcherTypeMask(objectType, condList); if (containerTypeMask != 0) { - var spellCone = new WorldObjectSpellConeTargetCheck(coneAngle, radius, m_caster, m_spellInfo, selectionType, condList); + var spellCone = new WorldObjectSpellConeTargetCheck(MathFunctions.DegToRad(m_spellInfo.ConeAngle), radius, m_caster, m_spellInfo, selectionType, condList); var searcher = new WorldObjectListSearcher(m_caster, targets, spellCone, containerTypeMask); SearchTargets(searcher, containerTypeMask, m_caster, m_caster.GetPosition(), radius); @@ -7637,7 +7637,9 @@ namespace Game.Spells else { if (!_caster.IsWithinBoundaryRadius(target.ToUnit())) - if (!_caster.isInFront(target, _coneAngle)) + // ConeAngle > 0 -> select targets in front + // ConeAngle < 0 -> select targets in back + if (_caster.HasInArc(_coneAngle, target) != MathFunctions.fuzzyGe(_coneAngle, 0.0f)) return false; } return base.Invoke(target); diff --git a/Game/Spells/SpellInfo.cs b/Game/Spells/SpellInfo.cs index b6a19b942..3136ac8bf 100644 --- a/Game/Spells/SpellInfo.cs +++ b/Game/Spells/SpellInfo.cs @@ -228,6 +228,8 @@ namespace Game.Spells if (_target != null) { targets = (SpellCastTargetFlags)_target.Targets; + ConeAngle = _target.ConeAngle; + Width = _target.Width; TargetCreatureType = _target.TargetCreatureType; MaxAffectedTargets = _target.MaxAffectedTargets; MaxTargetLevel = _target.MaxTargetLevel; @@ -2629,6 +2631,8 @@ namespace Game.Spells 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; } @@ -3640,7 +3644,7 @@ namespace Game.Spells 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 new StaticData(SpellTargetObjectTypes.None, SpellTargetReferenceTypes.None, SpellTargetSelectionCategories.Nyi, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.None), // 109 - new StaticData(SpellTargetObjectTypes.Unit, SpellTargetReferenceTypes.Caster, SpellTargetSelectionCategories.Cone, SpellTargetCheckTypes.Default, SpellTargetDirectionTypes.Front), // 110 TARGET_DEST_UNK_110 + 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 diff --git a/Game/Spells/SpellManager.cs b/Game/Spells/SpellManager.cs index 3c0d7512b..5606f34db 100644 --- a/Game/Spells/SpellManager.cs +++ b/Game/Spells/SpellManager.cs @@ -2646,9 +2646,6 @@ namespace Game.Entities if (!spellInfo._IsPositiveEffect(2, false)) spellInfo.AttributesCu |= SpellCustomAttributes.NegativeEff2; - if (spellInfo.GetSpellVisual() == 3879) - spellInfo.AttributesCu |= SpellCustomAttributes.ConeBack; - if (talentSpells.Contains(spellInfo.Id)) spellInfo.AttributesCu |= SpellCustomAttributes.IsTalent; @@ -2680,6 +2677,10 @@ namespace Game.Entities spellInfo.Speed = MotionMaster.SPEED_CHARGE; break; } + + if (effect.TargetA.GetSelectionCategory() == SpellTargetSelectionCategories.Cone || effect.TargetB.GetSelectionCategory() == SpellTargetSelectionCategories.Cone) + if (MathFunctions.fuzzyEq(spellInfo.ConeAngle, 0.0f)) + spellInfo.ConeAngle = 90.0f; } if (spellInfo.ActiveIconFileDataId == 135754) // flight