Esempio n. 1
0
        /// <summary>
        /// Get a SkillMeta object
        /// </summary>
        /// <param name="skill"></param>
        /// <returns></returns>
        public static SkillMeta GetSkillMeta(Skill skill)
        {
            SkillMeta s;
            if (_skillMetas.TryGetValue(skill, out s))
                return s;

            Logger.LogVerbose("GetSkillInfo found no SkillMeta for {0}", skill.Name);
            
            var newMeta = new SkillMeta(skill);
            SetSkillMeta(newMeta);

            return newMeta;
        }
Esempio n. 2
0
 public SkillMeta(Skill skill)
 {
     Skill = skill;
 }
Esempio n. 3
0
        /// <summary>
        /// Finds a target location using skill metadata.
        /// </summary>
        /// <param name="skill">skill to be used</param>
        /// <returns>target position</returns>
        public static TrinityCacheObject GetBestAreaEffectTarget(Skill skill)
        {
            // Avoid bot choosing a target that is too far away (and potentially running towards it) when there is danger close by.
            var searchRange = (float)(skill.IsGeneratorOrPrimary && Enemies.CloseNearby.Units.Any() ? skill.Meta.CastRange * 0.5 : skill.Meta.CastRange);

            TrinityCacheObject target;
            switch (skill.Meta.AreaEffectShape)
            {
                case AreaEffectShapeType.Beam:
                    target = TargetUtil.GetBestPierceTarget(searchRange);
                    break;
                case AreaEffectShapeType.Circle:
                    target = TargetUtil.GetBestClusterUnit(skill.AreaEffectRadius, searchRange);
                    break;
                case AreaEffectShapeType.Cone:
                    target = TargetUtil.GetBestArcTarget(searchRange, skill.AreaEffectRadius);
                    break;
                default:
                    target = TargetUtil.GetBestClusterUnit(skill.AreaEffectRadius, searchRange);
                    break;
            }

            return target ?? CurrentTarget;
        }
Esempio n. 4
0
        /// <summary>
        /// Converts a skill into a TrinityPower for casting
        /// </summary>
        /// <returns></returns>
        public static TrinityPower GetTrinityPower(Skill skill)
        {
            var ticksBefore = skill.Meta.BeforeUseDelay == 0 ? 0 : (int)Math.Round(BotMain.TicksPerSecond * (skill.Meta.BeforeUseDelay / 1000));
            var ticksAfter = skill.Meta.AfterUseDelay == 0 ? 0 : (int)Math.Round(BotMain.TicksPerSecond * (skill.Meta.AfterUseDelay / 1000));

            if (skill.Meta.IsCastOnSelf)
            {
                Logger.Log(LogCategory.Targetting, "Calculating TargetPosition for {0} as Self. CurrentTarget={1}", skill.Name, CurrentTarget != null ? CurrentTarget.InternalName : "");
                return skill.ToPower(ticksBefore, ticksAfter);
            }

            var castRange = (skill.Meta.CastRange <= 0) ? (int)Math.Round(skill.Meta.MaxTargetDistance * 0.5) : skill.Meta.CastRange;

            if (skill.Meta.TargetPositionSelector != null)
            {                
                var targetPosition = skill.Meta.TargetPositionSelector(skill.Meta);

                Logger.Log(LogCategory.Targetting, "Calculating TargetPosition for {0} using TargetPositionSelector at {1} Dist={2} PlayerIsFacing(CastPosition={3} CurrentTarget={4}) CurrentTarget={5}", 
                    skill.Name,
                    targetPosition, 
                    Player.Position.Distance(targetPosition), 
                    Player.IsFacing(targetPosition),
                    Player.IsFacing(CurrentTarget.Position),
                    CurrentTarget.InternalName
                    );

                return skill.ToPower(castRange, targetPosition, ticksBefore, ticksAfter);
            }

            if (skill.Meta.TargetUnitSelector != null)
            {
                var targetUnit = skill.Meta.TargetUnitSelector(skill.Meta);

                Logger.Log(LogCategory.Targetting, "Calculating TargetPosition for {0} using TargetUnitSelector at {1} Dist={2} PlayerIsFacing(CastPosition={3} CurrentTarget={4}) CurrentTarget={5}",
                    skill.Name,
                    targetUnit.Position,
                    Player.Position.Distance(targetUnit.Position),
                    Player.IsFacing(targetUnit.Position),
                    Player.IsFacing(CurrentTarget.Position),
                    CurrentTarget.InternalName
                    );

                return skill.ToPower(castRange, targetUnit.Position, targetUnit.ACDGuid, ticksBefore, ticksAfter);
            }


            if (skill.Meta.IsAreaEffectSkill)
            {
                var target = GetBestAreaEffectTarget(skill);

                Logger.Log(LogCategory.Targetting, "Calculating TargetPosition for {0} using AreaEffectTargetting at {1} Dist={2} PlayerIsFacing(CastPosition={3} CurrentTarget={4}) CurrentTarget={5} AreaShape={6} AreaRadius={7} ",
                    skill.Name,
                    target,
                    Player.Position.Distance(target.Position),
                    Player.IsFacing(target.Position),
                    Player.IsFacing(CurrentTarget.Position),
                    CurrentTarget.InternalName,
                    skill.Meta.AreaEffectShape,
                    skill.AreaEffectRadius
                    );

                return skill.ToPower(castRange, target.Position, target.ACDGuid, ticksBefore, ticksAfter);
            }

            return skill.ToPower(castRange, CurrentTarget.Position);
        }
Esempio n. 5
0
        /// <summary>
        /// Checks if a skill can and should be cast.
        /// </summary>
        /// <param name="skill">the Skill to check</param>
        /// <param name="condition">function to test against</param>
        //public static bool CanCast(Skill skill, Func<SkillMeta, bool> condition)
        //{
        //    return CanCast(skill, null, condition);
        //}

        /// <summary>
        /// Checks if a skill can and should be cast.
        /// </summary>
        /// <param name="skill">the Skill to check</param>
        /// <param name="changes">action to modify existing skill data</param>
        //public static bool CanCast(Skill skill, Action<SkillMeta> changes)
        //{
        //    return CanCast(skill, null, c => { changes(c); return true; });
        //}

        /// <summary>
        /// Checks if a skill can and should be cast.
        /// </summary>
        /// <param name="skill">the Skill to check</param>
        /// <param name="cd">Optional combat data to use</param>
        /// <param name="adhocCondition">Optional function to test against</param>
        public static bool CanCast(Skill skill, SkillMeta sm = null)
        {
            try
            {
                var meta = (sm != null) ? skill.Meta.Apply(sm) : skill.Meta;

                Func<string> check = () =>
                {
                    if (!Hotbar.Contains(skill.SNOPower))
                        return "NotOnHotbar";

                    if (Player.IsIncapacitated)
                        return "IsIncapacitated";

                    //var adhocConditionResult = (adhocCondition == null) || adhocCondition(meta);
                    var metaConditionResult = (meta.CastCondition == null) || meta.CastCondition(meta);

                    if (!meta.CastFlags.HasFlag(CanCastFlags.NoTimer) && !SNOPowerUseTimer(skill.SNOPower))
                        return "PowerUseTimer";

                    if (!meta.CastFlags.HasFlag(CanCastFlags.NoPowerManager) && !PowerManager.CanCast(skill.SNOPower))
                        return "PowerManager";

                    // Note: ZetaDia.Me.IsInCombat is unrealiable and only kicks in after an ability has hit a monster
                    if (meta.IsCombatOnly && CurrentTarget == null)
                        return "IsInCombat";

                    // This is already checked above...?
                    //if (meta.ReUseDelay > 0 && TimeSincePowerUse(skill.SNOPower) < meta.ReUseDelay)
                    //    return "ReUseDelay";

                    //if (meta.IsEliteOnly && Enemies.Nearby.EliteCount == 0)
                    //    return false;

                    //if (meta.MaxTargetDistance > CurrentTarget.Distance)
                    //    return false;

                    var resourceCost = (meta.RequiredResource > 0) ? meta.RequiredResource : skill.Cost;
                    if (resourceCost > 0 && !skill.IsGeneratorOrPrimary)
                    {
                        var actualResource = (skill.Resource == Resource.Discipline) ? Player.SecondaryResource : Player.PrimaryResource;
                        if (actualResource < resourceCost)
                            return string.Format("NotEnoughResource({0}/{1})", Math.Round(actualResource), resourceCost);
                    }

                    //if (meta.IsEliteOnly && !CurrentTarget.IsBossOrEliteRareUnique)
                    //    return false;

                    //if (!adhocConditionResult)
                    //    return "AdHocConditionFailure";

                    if (!metaConditionResult)
                        return "ConditionFailure";

                    return string.Empty;
                };

                var failReason = check();

                if (!string.IsNullOrEmpty(failReason))
                {
                    Logger.Log(TrinityLogLevel.Verbose, LogCategory.SkillSelection, "   >>   CanCast Failed: {0} ({1}) Reason={2}",
                        skill.Name, (int)skill.SNOPower, failReason);
                    
                    return false;
                }

                return true;
            }
            catch (Exception ex)
            {
                Logger.Log("Exception in CanCast for {0}. {1} {2}", skill.Name, ex.Message, ex.InnerException);
            }

            return false;
        }
Esempio n. 6
0
        /// <summary>
        /// Checks a skill against the convention of elements ring
        /// </summary>
        internal static bool ShouldWaitForConventionElement(Skill skill)
        {
            if (!Settings.Combat.Misc.UseConventionElementOnly)
                return false;

            return Legendary.ConventionOfElements.IsEquipped && CacheData.Buffs.ConventionElement != skill.Element;
        }