public static bool AbilityAvailable(this EliteAPI api, string ability)
        {
            // IF YOU HAVE INPAIRMENT/AMNESIA THEN BLOCK JOB ABILITY CASTING
            if (api.HasStatus(StatusEffect.No_Job_Abilities) || api.HasStatus(StatusEffect.Amnesia))
            {
                return(false);
            }

            var apiAbility = api.Resources.GetAbility(ability, 0);

            //int recast = api.Recast.GetAbilityRecast(apiAbility);
            return(api.Player.HasAbility(apiAbility.ID) && api.GetAbilityRecast(ability) == 0);
        }
        public static bool SpellAvailable(this EliteAPI api, string spell)
        {
            // IF YOU HAVE OMERTA THEN BLOCK MAGIC CASTING
            if (api.HasStatus(StatusEffect.No_Magic_Casting))
            {
                return(false);
            }

            var apiSpell = api.Resources.GetSpell(spell, 0);

            var mainLevelReq = apiSpell.LevelRequired[api.Player.MainJob];
            var subLevelReq  = apiSpell.LevelRequired[api.Player.SubJob];

            // First check for definite no.
            // If our main either can't learn it, or isn't high enough, and similar for our sub.
            if ((mainLevelReq == -1 || mainLevelReq > api.Player.MainJobLevel) && (subLevelReq == -1 || subLevelReq > api.Player.SubJobLevel))
            {
                return(false);
            }

            // Then check for special case where we need job points
            if (mainLevelReq > 99)
            {
                var jobPointsTuple = Data.JobPointSpells[spell];
                if (api.Player.MainJob != (byte)jobPointsTuple.Item1 || api.Player.GetJobPoints(api.Player.MainJob).SpentJobPoints < jobPointsTuple.Item2)
                {
                    return(false);
                }
            }

            // If we get here, we qualify for the spell. So make sure we own it, and that it's off cooldown.
            return(api.Player.HasSpell(apiSpell.ID) && (api.Recast.GetSpellRecast(apiSpell.Index) == 0));
        }
        public static int ShadowsRemaining(this EliteAPI api)
        {
            if (api.HasStatus(StatusEffect.Utsusemi_4_Shadows_Left))
            {
                return(4);
            }
            else if (api.HasStatus(StatusEffect.Utsusemi_3_Shadows_Left))
            {
                return(3);
            }
            else if (api.HasStatus(StatusEffect.Utsusemi_2_Shadows_Left))
            {
                return(2);
            }
            else if (api.HasStatus(StatusEffect.Utsusemi_1_Shadow_Left))
            {
                return(1);
            }

            return(0);
        }
 public static bool HasStatus(this EliteAPI api, StatusEffect effect)
 {
     return(api.HasStatus((short)effect));
 }
        public static int CurrentSCHCharges(this EliteAPI api)
        {
            if (api != null)
            {
                int MainJob = api.Player.MainJob;
                int SubJob  = api.Player.SubJob;

                if (MainJob == (int)Job.SCH || SubJob == (int)Job.SCH)
                {
                    if (api.HasStatus(StatusEffect.Light_Arts) || api.HasStatus(StatusEffect.Addendum_White))
                    {
                        // Stragem charge recast = ability ID 231?
                        int currentRecastTimer = api.Recast.GetAbilityRecast(231);

                        int SpentPoints = api.Player.GetJobPoints((int)Job.SCH).SpentJobPoints;

                        int MainLevel = api.Player.MainJobLevel;
                        int SubLevel  = api.Player.SubJobLevel;

                        int baseTimer   = 240;
                        int baseCharges = 1;

                        // Generate the correct timer between charges depending on level / Job Points
                        if (MainJob == (int)Job.SCH)
                        {
                            if (SpentPoints >= 550)
                            {
                                baseTimer   = 33;
                                baseCharges = 5;
                            }
                            else if (MainLevel >= 90)
                            {
                                baseTimer   = 48;
                                baseCharges = 5;
                            }
                            else if (MainLevel >= 70 && MainLevel < 90)
                            {
                                baseTimer   = 60;
                                baseCharges = 4;
                            }
                            else if (MainLevel >= 50 && MainLevel < 70)
                            {
                                baseTimer   = 80;
                                baseCharges = 3;
                            }
                            else if (MainLevel >= 30 && MainLevel < 50)
                            {
                                baseTimer   = 120;
                                baseCharges = 2;
                            }
                            else if (MainLevel >= 10 && MainLevel < 30)
                            {
                                baseTimer   = 240;
                                baseCharges = 1;
                            }
                        }
                        else if (SubJob == (int)Job.SCH)
                        {
                            if (SubLevel >= 30 && SubLevel < 50)
                            {
                                baseTimer   = 120;
                                baseCharges = 2;
                            }
                        }

                        // Now knowing what the time between charges is lets calculate how many
                        // charges are available

                        if (currentRecastTimer == 0)
                        {
                            return(baseCharges);
                        }
                        else
                        {
                            int t = currentRecastTimer / 60;

                            int stratsUsed = t / baseTimer;

                            int currentCharges = (int)Math.Ceiling((decimal)baseCharges - stratsUsed);

                            return((baseTimer == 120) ? currentCharges-- : currentCharges);
                        }
                    }
                }
            }

            return(-1);
        }
Example #6
0
        public EngineAction Run(GeoConfig Config)
        {
            _config = Config;

            EngineAction actionResult = new EngineAction
            {
                Target = Target.Me
            };

            if (Config.EntrustEnabled && !PL.HasStatus((StatusEffect)584) && CheckEngagedStatus() == true && PL.AbilityAvailable(Ability.Entrust))
            {
                actionResult.JobAbility = Ability.Entrust;
                return(actionResult);
            }
            else if (Config.DematerializeEnabled && CheckEngagedStatus() == true && PL.Player.Pet.HealthPercent >= 90 && PL.AbilityAvailable(Ability.Dematerialize))
            {
                actionResult.JobAbility = Ability.Dematerialize;
                return(actionResult);
            }
            else if (Config.EclipticAttritionEnabled && CheckEngagedStatus() == true && PL.Player.Pet.HealthPercent >= 90 && PL.AbilityAvailable(Ability.EclipticAttrition) && !PL.HasStatus(516) && EclipticStillUp != true)
            {
                actionResult.JobAbility = Ability.EclipticAttrition;
                return(actionResult);
            }
            else if (Config.LifeCycleEnabled && CheckEngagedStatus() == true && PL.Player.Pet.HealthPercent <= 30 && PL.Player.Pet.HealthPercent >= 5 && PL.Player.HPP >= 90 && PL.AbilityAvailable(Ability.LifeCycle))
            {
                actionResult.JobAbility = Ability.LifeCycle;
                return(actionResult);
            }

            // TODO: Fix up this logic, I think something was lost in the refactoring.
            // Need to see if there's a situation where both of these JA's would be activated for the cast.
            // For now the old logic seems to be use RA on it's own, or check for FC + Cast.
            if (Config.RadialArcanaEnabled && (PL.Player.MP <= Config.RadialArcanaMP) && PL.AbilityAvailable(Ability.RadialArcana) && !PL.Player.Buffs.Contains((short)StatusEffect.Weakness))
            {
                // Check if a pet is already active
                if (PL.Player.Pet.HealthPercent >= 1 && PL.Player.Pet.Distance <= 9)
                {
                    actionResult.JobAbility = Ability.RadialArcana;
                    return(actionResult);
                }
                else if (PL.Player.Pet.HealthPercent >= 1 && PL.Player.Pet.Distance >= 9 && PL.AbilityAvailable(Ability.FullCircle))
                {
                    actionResult.JobAbility = Ability.FullCircle;
                }

                actionResult.Spell = ReturnGeoSpell(Config.RadialArcanaSpell, 2);
            }
            else if (Config.FullCircleEnabled)
            {
                // When out of range Distance is 59 Yalms regardless, Must be within 15 yalms to gain
                // the effect

                //Check if "pet" is active and out of range of the monitored player
                if (PL.Player.Pet.HealthPercent >= 1)
                {
                    if (Config.FullCircleGeoTarget == true && Config.LuopanSpellTarget != "")
                    {
                        ushort PetsIndex = PL.Player.PetIndex;

                        XiEntity PetsEntity = PL.Entity.GetEntity(PetsIndex);

                        int FullCircle_CharID = 0;

                        for (int x = 0; x < 2048; x++)
                        {
                            XiEntity entity = PL.Entity.GetEntity(x);

                            if (entity.Name != null && entity.Name.ToLower().Equals(Config.LuopanSpellTarget.ToLower()))
                            {
                                FullCircle_CharID = Convert.ToInt32(entity.TargetID);
                                break;
                            }
                        }

                        if (FullCircle_CharID != 0)
                        {
                            XiEntity FullCircleEntity = PL.Entity.GetEntity(FullCircle_CharID);

                            float fX = PetsEntity.X - FullCircleEntity.X;
                            float fY = PetsEntity.Y - FullCircleEntity.Y;
                            float fZ = PetsEntity.Z - FullCircleEntity.Z;

                            float generatedDistance = (float)Math.Sqrt((fX * fX) + (fY * fY) + (fZ * fZ));

                            if (generatedDistance >= 10)
                            {
                                FullCircleTimer.Enabled = true;
                            }
                        }
                    }
                    else if (Config.FullCircleGeoTarget == false && Monitored.Player.Status == 1)
                    {
                        ushort PetsIndex = PL.Player.PetIndex;

                        XiEntity PetsEntity = Monitored.Entity.GetEntity(PetsIndex);

                        if (PetsEntity.Distance >= 10)
                        {
                            FullCircleTimer.Enabled = true;
                        }
                    }
                }
            }
            // ENTRUSTED INDI SPELL CASTING, WILL BE CAST SO LONG AS ENTRUST IS ACTIVE
            else if (Config.GeoSpellsEnabled && PL.HasStatus((StatusEffect)584) && PL.Player.Status != 33)
            {
                string SpellCheckedResult = ReturnGeoSpell(Config.EntrustSpell, 1);
                if (SpellCheckedResult == "SpellError_Cancel")
                {
                    Config.GeoSpellsEnabled = false;
                    actionResult.Error      = "An error has occurred with Entrusted INDI spell casting, please report what spell was active at the time.";
                }
                else if (SpellCheckedResult == "SpellRecast" || SpellCheckedResult == "SpellUnknown")
                {
                }
                else
                {
                    actionResult.Target = string.IsNullOrEmpty(Config.EntrustSpellTarget) ? Monitored.Player.Name : Config.EntrustSpellTarget;
                    actionResult.Spell  = SpellCheckedResult;
                }
            }
            // CAST NON ENTRUSTED INDI SPELL
            else if (Config.GeoSpellsEnabled && !PL.HasStatus(612) && PL.Player.Status != 33 && (CheckEngagedStatus() == true || !Config.IndiWhenEngaged))
            {
                string SpellCheckedResult = ReturnGeoSpell(Config.IndiSpell, 1);

                if (SpellCheckedResult == "SpellError_Cancel")
                {
                    Config.GeoSpellsEnabled = false;
                    actionResult.Error      = "An error has occurred with INDI spell casting, please report what spell was active at the time.";
                }
                else if (SpellCheckedResult == "SpellRecast" || SpellCheckedResult == "SpellUnknown")
                {
                }
                else
                {
                    actionResult.Spell = SpellCheckedResult;
                }
            }
            // GEO SPELL CASTING
            else if (Config.LuopanSpellsEnabled && (PL.Player.Pet.HealthPercent < 1) && (CheckEngagedStatus() == true))
            {
                // Use BLAZE OF GLORY if ENABLED
                if (Config.BlazeOfGloryEnabled && PL.AbilityAvailable(Ability.BlazeOfGlory) && CheckEngagedStatus() == true && GEO_EnemyCheck() == true)
                {
                    actionResult.JobAbility = Ability.BlazeOfGlory;
                    return(actionResult);
                }

                // Grab GEO spell name
                string SpellCheckedResult = ReturnGeoSpell(Config.GeoSpell, 2);

                if (SpellCheckedResult == "SpellError_Cancel")
                {
                    Config.GeoSpellsEnabled = false;
                    actionResult.Error      = "An error has occurred with GEO spell casting, please report what spell was active at the time.";
                }
                else if (SpellCheckedResult == "SpellRecast" || SpellCheckedResult == "SpellUnknown")
                {
                    // Do nothing and continue on with the program
                }
                else
                {
                    if (PL.Resources.GetSpell(SpellCheckedResult, 0).ValidTargets == 5)
                    { // PLAYER CHARACTER TARGET
                        actionResult.Target = string.IsNullOrEmpty(Config.LuopanSpellTarget) ? Monitored.Player.Name : Config.LuopanSpellTarget;

                        if (PL.HasStatus(516)) // IF ECLIPTIC IS UP THEN ACTIVATE THE BOOL
                        {
                            EclipticStillUp = true;
                        }

                        actionResult.Spell = SpellCheckedResult;
                    }
                    else
                    { // ENEMY BASED TARGET NEED TO ASSURE PLAYER IS ENGAGED
                        if (CheckEngagedStatus() == true)
                        {
                            int GrabbedTargetID = GrabGEOTargetID();

                            if (GrabbedTargetID != 0)
                            {
                                PL.Target.SetTarget(GrabbedTargetID);

                                if (PL.HasStatus(516)) // IF ECLIPTIC IS UP THEN ACTIVATE THE BOOL
                                {
                                    EclipticStillUp = true;
                                }

                                actionResult.Target = "<t>";
                                actionResult.Spell  = SpellCheckedResult;
                            }
                        }
                    }
                }
            }

            return(actionResult);
        }