public static async Task <bool> Pull() { if (Target == null || !Target.CanAttack) { return(false); } if (EikoSettingsModel.Instance.UseOpener) { return(await Common_Utils.Opener()); } if (Me.Pet != null && PetManager.PetMode != PetMode.Obey) { PetManager.DoAction(Spells.Obey.LocalizedName, Target); } if (Me.ClassLevel >= 26) { return(await Spells.BioII.CastDot(Target, EikoSettingsModel.Instance.UseDoTs)); } if (Me.ClassLevel >= 38) { return(await Spells.RuinII.Use(Target, true)); } return(await Spells.Ruin.Use(Target, true)); }
public static void PetCast(this PetSpellData spell, GameObject tar, [CallerMemberName] string name = "") { if (Core.Me.Pet == null) { return; } if (tar == null) { return; } if (Core.Me.Pet.IsCasting) { return; } if (spell.Cooldown != TimeSpan.Zero) { return; } if (!PetManager.CanCast(spell, tar)) { return; } PetManager.DoAction(spell.LocalizedName, tar); }
private async Task <bool> Obey() { if (PetManager.ActivePetType == PetType.Garuda_Egi && PetManager.PetMode != PetMode.Obey) { if (await Coroutine.Wait(1000, () => PetManager.DoAction("Obey", Core.Player))) { Logging.Write(Colors.GreenYellow, @"[ShinraEx] Casting >>> Obey"); return(await Coroutine.Wait(3000, () => PetManager.PetMode == PetMode.Obey)); } } return(false); }
public async Task <bool> Sic() { if (PetManager.ActivePetType == PetType.Ifrit_Egi && PetManager.PetMode != PetMode.Sic) { if (await Coroutine.Wait(1000, () => PetManager.DoAction("Sic", Core.Player))) { Logging.Write(Colors.GreenYellow, @"[Shadow] Casting >>> Sic"); return(await Coroutine.Wait(3000, () => PetManager.PetMode == PetMode.Sic)); } } return(false); }
private async Task <bool> Sic() { if (PetManager.PetMode != PetMode.Sic) { if (await Coroutine.Wait(1000, () => PetManager.DoAction("Sic", Core.Player))) { Logging.Write(Colors.GreenYellow, @"[ShinraEx] Casting >>> Sic"); return(await Coroutine.Wait(3000, () => PetManager.PetMode == PetMode.Sic)); } } return(false); }
public static async Task <bool> PetCleanse() { CleanseTarget = CheckPet(); if (!PartyManager.IsInParty) { CleanseTarget = CheckSelf(); } else { CleanseTarget = CheckParty(); } if (CleanseTarget != null) { return(PetManager.DoAction(Spells.FeyCaress.LocalizedName, Me.Pet)); } return(false); }
public override async Task <bool> Execute(ObservableCollection <IGambitCondition> conditions) { if (Core.Me.Pet == null) { return(false); } GameObject target = null; if (OnPet) { target = Core.Me.Pet; } if (OnTarget) { target = Core.Me.CurrentTarget; } if (OnPlayer) { target = Core.Me; } if (target == null) { return(false); } if (conditions.Any(condition => !condition.Check(target))) { return(false); } if (!PetManager.CanCast(SpellName, target)) { return(false); } if (PetManager.DoAction(SpellName, target)) { return(false); } return(await Task.FromResult(false)); }
public static async Task <bool> Summon() { if (Core.Me.ClassLevel < 4) { return(false); } // Don't try to summon if we're mounted or moving if (Core.Me.IsMounted || MovementManager.IsMoving) { return(false); } if ((int)PetManager.ActivePetType == (int)SummonerSettings.Instance.SelectedPet) { return(false); } switch (SummonerSettings.Instance.SelectedPet) { case SummonerPets.None: return(PetManager.DoAction("Away", Core.Me)); case SummonerPets.Ifrit: return(await Spells.Summon3.Cast(Core.Me)); case SummonerPets.Titan: return(await Spells.Summon2.Cast(Core.Me)); case SummonerPets.Garuda: return(await Spells.Summon.Cast(Core.Me)); default: return(false); } }
private static async Task <bool> Opener() { if (Target == null || !Target.CanAttack) { return(false); } foreach (var item in Paine_OpenerViewModel.Instance.GuiOpenerList.Where(x => x.IsItem)) { Logger.KefkaLog(item.SpellName + @" Is loaded in the Queue."); var useableItem = InventoryManager.FilledSlots.FirstOrDefault(a => a.Item.Id == item.SpellId); if (useableItem == null || !useableItem.IsValid || !useableItem.CanUse()) { Logger.KefkaLog(item.SpellName + @" is on cooldown. Skipping Opener."); PaineSettingsModel.Instance.UseOpener = false; return(await Combat()); } } foreach (var spell in Paine_OpenerViewModel.Instance.GuiOpenerList.Where(x => !x.IsItem && !x.IsPet && x.SpellId != Spells.Infuriate.Id)) { Logger.KefkaLog(spell.SpellName + @" Is loaded in the Queue."); var openerSpell = DataManager.GetSpellData(spell.SpellId); if (openerSpell.Cooldown.TotalMilliseconds > 0) { Logger.KefkaLog(spell.SpellName + @" is on cooldown. Skipping Opener."); PaineSettingsModel.Instance.UseOpener = false; return(await Combat()); } } foreach (var petSpell in Paine_OpenerViewModel.Instance.GuiOpenerList.Where(x => !x.IsItem && x.IsPet)) { Logger.KefkaLog(petSpell.SpellName + @" Is loaded in the Queue."); var petOpenerSpell = DataManager.GetPetSpellData(petSpell.SpellName); if (petOpenerSpell.Cooldown.TotalMilliseconds > 0) { Logger.KefkaLog(petSpell.SpellName + @" is on cooldown. Skipping Opener."); PaineSettingsModel.Instance.UseOpener = false; return(await Combat()); } } Logger.KefkaLog("We made it through the Opener pre-checks!"); var openerQueue = new Queue <OpenerSpellInfo>(Paine_OpenerViewModel.Instance.GuiOpenerList); if (openerQueue.Count == 0) { Logger.KefkaLog(@"Opener queue is empty, please use the Reset Opener button to reset!"); openerQueue.Clear(); PaineSettingsModel.Instance.UseOpener = false; return(await Combat()); } while (Target != null && openerQueue.Count > 0) { var nextOpener = openerQueue.Peek(); Logger.KefkaLog(@"Next Opener Skill: {0}", nextOpener.SpellName); if (nextOpener.IsItem) { var openerItem = InventoryManager.FilledSlots.FirstOrDefault(r => r.RawItemId == nextOpener.SpellId); if (await Items.UsePotion(openerItem.Item, true)) { openerQueue.Dequeue(); continue; } } if (nextOpener.IsPet) { var petOpenerSpell = DataManager.GetPetSpellData(nextOpener.SpellName); if (petOpenerSpell == null) { openerQueue.Dequeue(); continue; } if (PetManager.DoAction(petOpenerSpell.Name, Target)) { Logger.KefkaLog("We're inside of the PetSpell Section."); openerQueue.Dequeue(); continue; } } var openerSpell = DataManager.GetSpellData(nextOpener.SpellId); await Coroutine.Wait(3000, () => ActionManager.CanCast(openerSpell, Target) || ActionManager.CanCast(openerSpell, Me)); if (openerSpell == null) { openerQueue.Dequeue(); } if (openerSpell?.Range == 0) { if (await openerSpell.Use(Me, true)) { Logger.KefkaLog("We're inside of the Regular Spell (ME) Section."); openerQueue.Dequeue(); continue; } } if (await openerSpell.Use(Target, true)) { Logger.KefkaLog("We're inside of the Regular Spell (TARGET) Section."); openerQueue.Dequeue(); } await Coroutine.Yield(); } Logger.KefkaLog(@"Opener has completed, or was interrupted!"); Core.OverlayManager.AddToast(() => "Opener Complete!", TimeSpan.FromMilliseconds(750), MainSettingsModel.Instance.ToastColor(true), Colors.White, new FontFamily("High Tower Text Italic"), new FontWeight(), 52); openerQueue.Clear(); PaineSettingsModel.Instance.UseOpener = false; return(await Combat()); }
public static async Task <bool> ExecuteOpener() { if (OpenerFinished || Me.ClassLevel < 70) { return(false); } if (ShinraEx.Settings.CooldownMode == CooldownModes.Disabled) { AbortOpener("Please enable cooldown mode to use an opener."); return(false); } #region GetOpener switch (Me.CurrentJob) { case ClassJobType.Bard: current = BardOpener.List; usePotion = ShinraEx.Settings.BardPotion; potionStep = 0; potionType = PotionIds.Dex; break; case ClassJobType.BlackMage: current = BlackMageOpener.List; usePotion = ShinraEx.Settings.BlackMagePotion; potionStep = 7; potionType = PotionIds.Int; break; case ClassJobType.DarkKnight: current = DarkKnightOpener.List; usePotion = ShinraEx.Settings.DarkKnightPotion; potionStep = 3; potionType = PotionIds.Str; break; case ClassJobType.Dragoon: current = DragoonOpener.List; usePotion = ShinraEx.Settings.DragoonPotion; potionStep = 7; potionType = PotionIds.Str; break; case ClassJobType.Machinist: current = MachinistOpener.List; usePotion = ShinraEx.Settings.MachinistPotion; potionStep = 0; potionType = PotionIds.Dex; break; case ClassJobType.Monk: current = MonkOpener.List; usePotion = ShinraEx.Settings.MonkPotion; potionStep = 4; potionType = PotionIds.Str; break; case ClassJobType.Ninja: current = NinjaOpener.List; usePotion = ShinraEx.Settings.NinjaPotion; potionStep = 7; potionType = PotionIds.Dex; break; case ClassJobType.Paladin: current = PaladinOpener.List; usePotion = ShinraEx.Settings.PaladinPotion; potionStep = 8; potionType = PotionIds.Str; break; case ClassJobType.RedMage: current = RedMageOpener.List; usePotion = ShinraEx.Settings.RedMagePotion; potionStep = 3; potionType = PotionIds.Int; break; case ClassJobType.Samurai: current = SamuraiOpener.List; usePotion = ShinraEx.Settings.SamuraiPotion; potionStep = 4; potionType = PotionIds.Str; break; case ClassJobType.Summoner: current = SummonerOpener.List; usePotion = ShinraEx.Settings.SummonerPotion; potionStep = 2; potionType = PotionIds.Int; break; case ClassJobType.Warrior: current = WarriorOpener.List; usePotion = ShinraEx.Settings.WarriorPotion; potionStep = 5; potionType = PotionIds.Str; break; default: current = null; break; } if (current == null) { return(false); } #endregion if (OpenerStep >= current.Count) { AbortOpener("ShinraEx >>> Opener Finished"); return(false); } if (usePotion && OpenerStep == potionStep) { if (await UsePotion(potionType)) { return(true); } } var spell = current.ElementAt(OpenerStep); resetTime = DateTime.Now.AddSeconds(10); #region Job-Specific switch (Me.CurrentJob) { case ClassJobType.Bard: if (Resource.Bard.Repertoire == 3) { await Bard.PitchPerfect.Cast(null, false); } break; case ClassJobType.BlackMage: if ((spell.Name == BlackMage.BlizzardIV.Name || spell.Name == BlackMage.FireIV.Name) && !Resource.BlackMage.Enochian) { AbortOpener("Aborted opener due to Enochian."); return(true); } break; case ClassJobType.DarkKnight: if (spell.Name == DarkKnight.BloodWeapon.Name && Me.HasAura(DarkKnight.Grit.Name)) { Debug($"Skipping opener step {OpenerStep} due to Grit >>> {spell.Name}"); OpenerStep++; return(true); } if ((spell.Name == DarkKnight.Bloodspiller.Name || spell.Name == DarkKnight.Delirium.Name) && Resource.DarkKnight.BlackBlood < 50) { Debug($"Skipping opener step {OpenerStep} due to Blood >>> {spell.Name}"); OpenerStep++; return(true); } if (spell.Name == DarkKnight.BlackestNight.Name && ShinraEx.Settings.DarkKnightOffTank) { await UpdateHealManager(); var target = HealManager.FirstOrDefault(hm => hm.IsTank() && !hm.IsMe); if (target != null && await DarkKnight.BlackestNight.Cast(target, false)) { Debug($"Casting opener step {OpenerStep} on the main tank >>> {spell.Name}"); OpenerStep++; return(true); } } break; case ClassJobType.Dragoon: if (OpenerStep > 4 && Resource.Dragoon.Timer == TimeSpan.Zero) { AbortOpener("Aborted opener due to Blood of the Dragon."); return(true); } if (spell.Name == Dragoon.DragonSight.Name) { var target = Managers.DragonSight.FirstOrDefault(); if (target == null) { break; } if (await Dragoon.DragonSight.Cast(target, false)) { Debug($"Executed opener step {OpenerStep} >>> {spell.Name}"); OpenerStep++; return(true); } } break; case ClassJobType.Machinist: if (PetManager.ActivePetType != PetType.Rook_Autoturret) { var castLocation = ShinraEx.Settings.MachinistTurretLocation == CastLocations.Self ? Me : Target; if (await Machinist.RookAutoturret.Cast(castLocation, false)) { return(true); } } if (Pet != null) { if (await Machinist.Hypercharge.Cast(null, false)) { return(true); } } break; case ClassJobType.Monk: switch (OpenerStep) { case 0 when !Me.HasAura(109): if (Me.HasAura(108)) { await Monk.TwinSnakes.Cast(); } await Monk.Bootshine.Cast(); return(true); case 0 when !Me.HasAura(105): await Monk.FistsOfWind.Cast(null, false); return(true); } if (spell.Name == Monk.RiddleOfWind.Name && Monk.RiddleOfWind.Cooldown() > 0) { return(true); } if (spell.Name == Monk.ForbiddenChakra.Name && Resource.Monk.FithChakra != 5) { Debug($"Skipping opener step {OpenerStep} due to Chakras >>> {spell.Name}"); OpenerStep++; return(true); } if (spell.Name == Monk.TornadoKick.Name && Resource.Monk.GreasedLightning != 3) { Debug($"Skipping opener step {OpenerStep} due to Greased Lightning >>> {spell.Name}"); OpenerStep++; return(true); } if (spell.Name == Monk.PerfectBalance.Name) { if (Monk.PerfectBalance.Cooldown() <= 0) { AbortOpener("Aborted opener due to Perfect Balance."); return(true); } if (Monk.Bootshine.Cooldown() > 700) { return(true); } } if (ShinraEx.LastSpell.Name != Monk.PerfectBalance.Name && Monk.PerfectBalance.Cooldown() > 0 && ActionManager.CanCast(Monk.Bootshine.Name, Target) && !ActionManager.CanCast(spell.Name, Target) && !ActionManager.CanCast(spell.Name, Me)) { AbortOpener("Aborted opener due to Perfect Balance."); return(true); } break; case ClassJobType.Ninja: if (OpenerStep == 1 && (Resource.Ninja.HutonTimer == TimeSpan.Zero || Ninja.Ninjutsu.Cooldown() > 0)) { AbortOpener("Aborted opener due to Ninjutsu."); return(true); } if (spell.Name == Ninja.Kassatsu.Name && Ninja.Kassatsu.Cooldown() > 0) { AbortOpener("Aborted opener due to Kassatsu."); return(true); } if (spell.Name == Ninja.TrickAttack.Name && !Me.HasAura(Ninja.Suiton.Name)) { Debug($"Skipping opener step {OpenerStep} due to Suiton >>> {spell.Name}"); OpenerStep++; return(true); } break; case ClassJobType.RedMage: if (!ActionManager.HasSpell("Swiftcast")) { AbortOpener("Aborting opener as Swiftcast is not set."); return(false); } if (spell.Name == RedMage.Verstone.Name && !Me.HasAura("Verstone Ready")) { AbortOpener("Aborting opener due to cooldowns."); return(false); } if (spell.Name == RedMage.EnchantedRiposte.Name && (Resource.RedMage.WhiteMana < 80 || Resource.RedMage.BlackMana < 80)) { AbortOpener("Aborted opener due to mana levels."); return(true); } break; case ClassJobType.Samurai: if (spell.Name == Samurai.MeikyoShisui.Name && Samurai.MeikyoShisui.Cooldown() > 0 || OpenerStep > 9 && !Me.HasAura(Samurai.MeikyoShisui.Name)) { AbortOpener("Aborted opener due to Meikyo Shisui."); return(true); } if (spell.Name == Samurai.HissatsuGuren.Name && Resource.Samurai.Kenki < 70) { Debug($"Skipping opener step {OpenerStep} due to Kenki >>> {spell.Name}"); OpenerStep++; return(true); } if (spell.Name == Samurai.Higanbana.Name && MovementManager.IsMoving) { return(true); } break; case ClassJobType.Summoner: if (!ActionManager.HasSpell("Swiftcast")) { AbortOpener("Aborting opener as Swiftcast is not set."); return(false); } if (PetManager.ActivePetType == PetType.Ifrit_Egi && PetManager.PetMode != PetMode.Sic) { if (await Coroutine.Wait(1000, () => PetManager.DoAction("Sic", Me))) { Logging.Write(Colors.GreenYellow, @"[ShinraEx] Casting >>> Sic"); return(await Coroutine.Wait(3000, () => PetManager.PetMode == PetMode.Sic)); } } if (OpenerStep == 1) { if (PetManager.ActivePetType == PetType.Garuda_Egi && PetManager.PetMode == PetMode.Obey) { if (await Summoner.Contagion.Cast()) { return(true); } } if (Resource.Arcanist.Aetherflow < 3 && Summoner.Aetherflow.Cooldown() > 15000) { AbortOpener("Aborting opener due to Aetherflow charges."); return(false); } } if (spell.Name == Summoner.SummonIII.Name) { if (!ShinraEx.Settings.SummonerOpenerGaruda || PetManager.ActivePetType == PetType.Ifrit_Egi || !Me.HasAura(Summoner.Role.Swiftcast.Name)) { Debug($"Skipping opener step {OpenerStep} due to Swiftcast/not using Garuda >>> {spell.Name}"); OpenerStep++; return(true); } } if (spell.Name == Summoner.Fester.Name) { if (Resource.Arcanist.Aetherflow > 0 && spell.Cooldown() > 0) { return(true); } if (Resource.Arcanist.Aetherflow == 0) { Debug($"Skipping opener step {OpenerStep} due to Aetherflow charges >>> {spell.Name}"); OpenerStep++; return(true); } } if (spell.Name == Summoner.DreadwyrmTrance.Name && Resource.Arcanist.AetherAttunement < 3) { await Coroutine.Wait(2000, () => Resource.Arcanist.AetherAttunement == 3); if (Resource.Arcanist.AetherAttunement < 3) { AbortOpener("Aborting opener due to Aethertrail Attunement."); return(false); } } break; case ClassJobType.Warrior: if (OpenerStep == 0 && !Me.HasAura(Warrior.Deliverance.Name)) { if (ShinraEx.LastSpell.Name != Warrior.Deliverance.Name && Warrior.Deliverance.Cooldown() > 3000) { AbortOpener("Aborting opener due to Deliverance cooldown."); return(false); } await Warrior.Deliverance.Cast(); return(true); } if (spell.Name == Warrior.FellCleave.Name) { if (Resource.Warrior.BeastGauge < 50 && !Me.HasAura(1177)) { Debug($"Skipping opener step {OpenerStep} due to Beast Gauge >>> {spell.Name}"); OpenerStep++; return(true); } } if (spell.Name == Warrior.InnerRelease.Name) { if (DataManager.GetSpellData(31).Cooldown.TotalMilliseconds > 700) { return(true); } } break; } #endregion if (await spell.Cast(null, false)) { Debug($"Executed opener step {OpenerStep} >>> {spell.Name}"); OpenerStep++; if (spell.Name == "Swiftcast") { await Coroutine.Wait(3000, () => Me.HasAura("Swiftcast")); } if (OpenerStep == 1) { DisplayToast("ShinraEx >>> Opener Started", 2500); } #region Job-Specific // Bard if (spell.Name == Bard.IronJaws.Name) { DotManager.Add(Target); } // Machinist if (spell.Name == Machinist.Flamethrower.Name) { await Coroutine.Wait(3000, () => Me.HasAura(Machinist.Flamethrower.Name)); await Coroutine.Wait(5000, () => Resource.Machinist.Heat == 100 || !Me.HasAura(Machinist.Flamethrower.Name)); } // Red Mage if (spell.Name == RedMage.Manafication.Name) { await Coroutine.Wait(3000, () => ActionManager.CanCast(RedMage.CorpsACorps.Name, Target)); } #endregion } else if (spell.Cooldown(true) > 3000 && spell.Cooldown() > 500 && !Me.IsCasting) { Debug($"Skipped opener step {OpenerStep} due to cooldown >>> {spell.Name}"); OpenerStep++; } return(true); }
public async Task <bool> Cast(GameObject target = null, bool checkGCDType = true) { #region Target if (target == null) { switch (CastType) { case CastType.Target: case CastType.TargetLocation: if (!Core.Player.HasTarget) { return(false); } target = Core.Player.CurrentTarget; break; default: target = Core.Player; break; } } #endregion #region RecentSpell RecentSpell.RemoveAll(t => DateTime.UtcNow > t); if (RecentSpell.ContainsKey(target.ObjectId.ToString("X") + "-" + Name)) { return(false); } #endregion #region CapabilityManager if (RoutineManager.IsAnyDisallowed(CapabilityFlags.Movement | CapabilityFlags.Facing)) { return(false); } #endregion #region Cooldown if (ShinraEx.Settings.CooldownMode == CooldownModes.Disabled) { if ((SpellType == SpellType.Buff || SpellType == SpellType.Cooldown) && Cooldown(true) > 2500) { return(false); } } #endregion #region AoE if (SpellType == SpellType.AoE && ShinraEx.Settings.RotationMode != Modes.Multi) { if (RoutineManager.IsAnyDisallowed(CapabilityFlags.Aoe)) { return(false); } var enemyCount = Helpers.Enemies.Count(eu => eu.Distance2D(target) - eu.CombatReach - target.CombatReach <= DataManager.GetSpellData(ID).Radius); if (ShinraEx.Settings.CustomAoE) { if (enemyCount < ShinraEx.Settings.CustomAoECount) { return(false); } } else { switch (Core.Player.CurrentJob) { case ClassJobType.Arcanist: case ClassJobType.Summoner: if (enemyCount < 2) { return(false); } break; default: if (enemyCount < 3) { return(false); } break; } } } #endregion #region Directional switch (ID) { // Cone case 41: case 70: case 106: case 7483: case 7488: { if (!Helpers.InView(Core.Player.Location, Core.Player.Heading, target.Location)) { return(false); } break; } // Line case 86: case 7496: { if (!Core.Player.IsFacing(target)) { return(false); } break; } } #endregion #region Pet switch (SpellType) { case SpellType.Pet when Core.Player.Pet == null: case SpellType.Pet when PetManager.PetMode != PetMode.Obey: case SpellType.Pet when Core.Player.IsMounted: case SpellType.Pet when !PetManager.CanCast(Name, target): case SpellType.Pet when !await Coroutine.Wait(5000, () => PetManager.DoAction(Name, target)): return(false); case SpellType.Pet: { ShinraEx.LastSpell = this; #region AddRecent var key = target.ObjectId.ToString("X") + "-" + Name; var val = DateTime.UtcNow + TimeSpan.FromSeconds(3); RecentSpell.Add(key, val); #endregion Logging.Write(Colors.GreenYellow, $@"[ShinraEx] Casting >>> {Name}"); return(true); } case SpellType.Card when Core.Player.IsMounted: case SpellType.Card when !ActionManager.CanCast(ID, target) || RecentSpell.ContainsKey("Card"): case SpellType.Card when !await Coroutine.Wait(1000, () => ActionManager.DoAction(ID, target)): return(false); case SpellType.Card: { ShinraEx.LastSpell = this; #region AddRecent var val = DateTime.UtcNow + TimeSpan.FromSeconds(.5); if (ID == 3593) { val += TimeSpan.FromSeconds(2); } RecentSpell.Add("Card", val); #endregion Logging.Write(Colors.GreenYellow, $@"[ShinraEx] Casting >>> {Name}"); return(true); } } #endregion #region Card if (ShinraEx.Settings.AstrologianCardOnly && Core.Player.CurrentJob == ClassJobType.Astrologian) { return(false); } #endregion #region Ninjutsu if (SpellType == SpellType.Ninjutsu || SpellType == SpellType.Mudra) { #region Movement if (BotManager.Current.IsAutonomous) { switch (ActionManager.InSpellInRangeLOS(2247, target)) { case SpellRangeCheck.ErrorNotInLineOfSight: await CommonTasks.MoveAndStop(new MoveToParameters(target.Location), 0f); return(false); case SpellRangeCheck.ErrorNotInRange: await CommonTasks.MoveAndStop(new MoveToParameters(target.Location), 0f); return(false); case SpellRangeCheck.ErrorNotInFront: if (!target.InLineOfSight()) { await CommonTasks.MoveAndStop(new MoveToParameters(target.Location), 0f); return(false); } target.Face(); return(false); case SpellRangeCheck.Success: if (MovementManager.IsMoving) { Navigator.PlayerMover.MoveStop(); } break; } } #endregion #region IsMounted if (Core.Player.IsMounted) { return(false); } #endregion #region CanCast if (ShinraEx.Settings.QueueSpells && !ActionManager.CanCastOrQueue(DataManager.GetSpellData(ID), target) || !ActionManager.CanCast(ID, target)) { return(false); } #endregion #region DoAction if (!await Coroutine.Wait(1000, () => ActionManager.DoAction(ID, target))) { return(false); } #endregion #region Wait await Coroutine.Wait(2000, () => !ActionManager.CanCast(ID, target)); #endregion ShinraEx.LastSpell = this; #region AddRecent if (SpellType == SpellType.Mudra) { var key = target.ObjectId.ToString("X") + "-" + Name; var val = DateTime.UtcNow + TimeSpan.FromSeconds(1); RecentSpell.Add(key, val); } #endregion Logging.Write(Colors.GreenYellow, $@"[ShinraEx] Casting >>> {Name}"); return(true); } #endregion #region CanAttack var bc = target as BattleCharacter; if (!target.CanAttack && CastType != CastType.Self && CastType != CastType.SelfLocation && (bc == null || !bc.IsFate)) { switch (SpellType) { case SpellType.Damage: case SpellType.DoT: case SpellType.Cooldown: return(false); } } #endregion #region HasSpell if (!ActionManager.HasSpell(ID)) { return(false); } #endregion #region Movement if (BotManager.Current.IsAutonomous) { switch (ActionManager.InSpellInRangeLOS(ID, target)) { case SpellRangeCheck.ErrorNotInLineOfSight: await CommonTasks.MoveAndStop(new MoveToParameters(target.Location), 0f); Helpers.Debug($"LineOfSight >>> {Name}"); return(false); case SpellRangeCheck.ErrorNotInRange: await CommonTasks.MoveAndStop(new MoveToParameters(target.Location), 0f); Helpers.Debug($"Range >>> {Name}"); return(false); case SpellRangeCheck.ErrorNotInFront: if (!target.InLineOfSight()) { await CommonTasks.MoveAndStop(new MoveToParameters(target.Location), 0f); Helpers.Debug($"Facing >>> {Name}"); return(false); } target.Face(); return(false); case SpellRangeCheck.Success: if (CastType == CastType.TargetLocation && Core.Player.Distance2D(target) + Core.Player.CombatReach + target.CombatReach > 25) { await CommonTasks.MoveAndStop(new MoveToParameters(target.Location), 0f); await Coroutine.Wait(1000, () => Core.Player.Distance2D(target) + Core.Player.CombatReach + target.CombatReach <= 25); return(false); } Navigator.PlayerMover.MoveStop(); break; } if (Core.Player.HasTarget && !MovementManager.IsMoving && Core.Player.IsMounted) { Logging.Write(Colors.Yellow, @"[ShinraEx] Dismounting..."); ActionManager.Dismount(); await Coroutine.Sleep(1000); } } #endregion #region IsMounted if (Core.Player.IsMounted) { return(false); } #endregion #region StopCasting if (SpellType == SpellType.Heal) { if (Core.Player.IsCasting && !Helpers.HealingSpells.Contains(Core.Player.SpellCastInfo.Name)) { var stopCasting = false; switch (Core.Player.CurrentJob) { case ClassJobType.Astrologian: stopCasting = ShinraEx.Settings.AstrologianInterruptDamage; break; case ClassJobType.Scholar: stopCasting = ShinraEx.Settings.ScholarInterruptDamage; break; case ClassJobType.WhiteMage: stopCasting = ShinraEx.Settings.WhiteMageInterruptDamage; break; } if (stopCasting) { Helpers.Debug($@"Trying to cast {Name}"); Logging.Write(Colors.Yellow, $@"[ShinraEx] Interrupting >>> {Core.Player.SpellCastInfo.Name}"); ActionManager.StopCasting(); await Coroutine.Wait(500, () => !Core.Player.IsCasting); } } } #endregion #region CanCast switch (CastType) { case CastType.TargetLocation: case CastType.SelfLocation: if (!ActionManager.CanCastLocation(ID, target.Location) || Core.Player.IsCasting) { return(false); } break; default: if (ShinraEx.Settings.QueueSpells && GCDType == GCDType.On) { if (!ActionManager.CanCastOrQueue(DataManager.GetSpellData(ID), target)) { return(false); } } else { if (!ActionManager.CanCast(ID, target)) { return(false); } } break; } if (MovementManager.IsMoving && DataManager.GetSpellData(ID).AdjustedCastTime.TotalMilliseconds > 0) { if (!BotManager.Current.IsAutonomous) { return(false); } Navigator.PlayerMover.MoveStop(); } #endregion #region InView if (GameSettingsManager.FaceTargetOnAction == false && CastType == CastType.Target && SpellType != SpellType.Heal && SpellType != SpellType.Buff && !Helpers.InView(Core.Player.Location, Core.Player.Heading, target.Location)) { return(false); } #endregion #region GCD if (GCDType == GCDType.Off && checkGCDType) { switch (Core.Player.CurrentJob) { case ClassJobType.Arcanist: case ClassJobType.Scholar: case ClassJobType.Summoner: if (DataManager.GetSpellData(163).Cooldown.TotalMilliseconds < 1000) { return(false); } break; case ClassJobType.Archer: case ClassJobType.Bard: if (DataManager.GetSpellData(97).Cooldown.TotalMilliseconds < 1000) { return(false); } break; case ClassJobType.Astrologian: if (DataManager.GetSpellData(3594).Cooldown.TotalMilliseconds < 1000) { return(false); } break; case ClassJobType.Conjurer: case ClassJobType.WhiteMage: if (DataManager.GetSpellData(119).Cooldown.TotalMilliseconds < 1000) { return(false); } break; case ClassJobType.DarkKnight: if (DataManager.GetSpellData(3617).Cooldown.TotalMilliseconds < 1000) { return(false); } break; case ClassJobType.Gladiator: case ClassJobType.Paladin: if (DataManager.GetSpellData(9).Cooldown.TotalMilliseconds < 1000) { return(false); } break; case ClassJobType.Lancer: case ClassJobType.Dragoon: if (ID == 8801 || ID == 8802) { if (DataManager.GetSpellData(75).Cooldown.TotalMilliseconds < 1500) { return(false); } else if (DataManager.GetSpellData(75).Cooldown.TotalMilliseconds < 1000) { return(false); } } break; case ClassJobType.Machinist: if (DataManager.GetSpellData(2866).Cooldown.TotalMilliseconds < 1000) { return(false); } break; case ClassJobType.Marauder: case ClassJobType.Warrior: if (DataManager.GetSpellData(31).Cooldown.TotalMilliseconds < 1000) { return(false); } break; case ClassJobType.Pugilist: case ClassJobType.Monk: if (DataManager.GetSpellData(53).Cooldown.TotalMilliseconds < 1000) { return(false); } break; case ClassJobType.RedMage: if (DataManager.GetSpellData(7504).Cooldown.TotalMilliseconds < 1000) { return(false); } break; case ClassJobType.Rogue: case ClassJobType.Ninja: if (DataManager.GetSpellData(2240).Cooldown.TotalMilliseconds < 1000) { return(false); } break; case ClassJobType.Samurai: if (DataManager.GetSpellData(7477).Cooldown.TotalMilliseconds < 1000) { return(false); } break; case ClassJobType.Thaumaturge: case ClassJobType.BlackMage: if (DataManager.GetSpellData(142).Cooldown.TotalMilliseconds < 1000) { return(false); } break; } } #endregion #region DoAction switch (CastType) { case CastType.TargetLocation: if (ShinraEx.Settings.RandomCastLocations) { var randX = target.CombatReach * _rand.NextDouble() * GetMultiplier(); var randZ = target.CombatReach * _rand.NextDouble() * GetMultiplier(); var randXYZ = new Vector3((float)randX, 0f, (float)randZ); var newLocation = target.Location + randXYZ; if (!await Coroutine.Wait(1000, () => ActionManager.DoActionLocation(ID, newLocation))) { return(false); } } else { if (!await Coroutine.Wait(1000, () => ActionManager.DoActionLocation(ID, target.Location))) { return(false); } } break; case CastType.SelfLocation: if (ShinraEx.Settings.RandomCastLocations) { var randX = (1f * _rand.NextDouble() + 1f) * GetMultiplier(); var randZ = (1f * _rand.NextDouble() + 1f) * GetMultiplier(); var randXYZ = new Vector3((float)randX, 0f, (float)randZ); var newLocation = target.Location + randXYZ; if (!await Coroutine.Wait(1000, () => ActionManager.DoActionLocation(ID, newLocation))) { return(false); } } else { if (!await Coroutine.Wait(1000, () => ActionManager.DoActionLocation(ID, target.Location))) { return(false); } } break; default: if (SpellType == SpellType.PVP) { if (!await Coroutine.Wait(1000, () => ActionManager.DoPvPCombo(Combo, target))) { return(false); } Logging.Write(Colors.Orange, $@"DoAction Combo {Combo} 0x{target.ObjectId:X}"); } else { if (!await Coroutine.Wait(1000, () => ActionManager.DoAction(ID, target))) { return(false); } } break; } #endregion #region Wait switch (CastType) { case CastType.SelfLocation: case CastType.TargetLocation: await Coroutine.Wait(3000, () => !ActionManager.CanCastLocation(ID, target.Location)); break; default: await Coroutine.Wait(3000, () => !ActionManager.CanCast(ID, target)); break; } #endregion ShinraEx.LastSpell = this; Logging.Write(Colors.GreenYellow, $@"[ShinraEx] Casting >>> {Name}{(SpellType == SpellType.PVP ? " Combo" : "")}"); #region AddRecent if (SpellType != SpellType.Damage && SpellType != SpellType.AoE && SpellType != SpellType.Heal && SpellType != SpellType.PVP && await CastComplete(this)) { var key = target.ObjectId.ToString("X") + "-" + Name; var val = DateTime.UtcNow + DataManager.GetSpellData(ID).AdjustedCastTime + TimeSpan.FromSeconds(3); RecentSpell.Add(key, val); } if (SpellType == SpellType.Damage || SpellType == SpellType.DoT) { if (!Helpers.OpenerFinished && !RecentSpell.ContainsKey("Opener") && await CastComplete(this, true)) { var val = DateTime.UtcNow + DataManager.GetSpellData(ID).AdjustedCastTime + TimeSpan.FromSeconds(3); RecentSpell.Add("Opener", val); } } #endregion return(true); }
public async Task <bool> Cast(GameObject target = null) { #region Target if (target == null) { switch (CastType) { case CastType.TargetLocation: if (!Core.Player.HasTarget) { return(false); } target = Core.Player.CurrentTarget; break; case CastType.Target: if (!Core.Player.HasTarget) { return(false); } target = Core.Player.CurrentTarget; break; default: target = Core.Player; break; } } #endregion #region Recent Spell Check RecentSpell.RemoveAll(t => DateTime.UtcNow > t); if (RecentSpell.ContainsKey(target.ObjectId.ToString("X") + "-" + Name)) { return(false); } #endregion #region Bard Song Check if (Core.Player.CurrentJob == ClassJobType.Bard && SpellType == SpellType.Buff) { if (Core.Player.HasAura(135, true) || Core.Player.HasAura(137, true)) { return(false); } } #endregion #region AoE Check if (SpellType == SpellType.AoE && Ultima.UltSettings.SmartTarget) { var EnemyCount = Helpers.EnemyUnit.Count(eu => eu.Distance2D(target) - eu.CombatReach - target.CombatReach <= DataManager.GetSpellData(ID).Radius); switch (Core.Player.CurrentJob) { case ClassJobType.Arcanist: case ClassJobType.Scholar: case ClassJobType.Summoner: if (EnemyCount < 2) { return(false); } break; case ClassJobType.Archer: case ClassJobType.Bard: if (EnemyCount < 3) { return(false); } break; case ClassJobType.Astrologian: if (EnemyCount < 3) { return(false); } break; case ClassJobType.Conjurer: case ClassJobType.WhiteMage: if (EnemyCount < 3) { return(false); } break; case ClassJobType.DarkKnight: if (EnemyCount < 3) { return(false); } break; case ClassJobType.Gladiator: case ClassJobType.Paladin: if (EnemyCount < 3) { return(false); } break; case ClassJobType.Lancer: case ClassJobType.Dragoon: if (EnemyCount < 3) { return(false); } break; case ClassJobType.Machinist: if (EnemyCount < 3) { return(false); } break; case ClassJobType.Marauder: case ClassJobType.Warrior: if (EnemyCount < 3) { return(false); } break; case ClassJobType.Pugilist: case ClassJobType.Monk: if (EnemyCount < 3) { return(false); } break; case ClassJobType.Rogue: case ClassJobType.Ninja: if (EnemyCount < 3) { return(false); } break; case ClassJobType.Thaumaturge: case ClassJobType.BlackMage: if (EnemyCount < 3) { return(false); } break; case ClassJobType.Samurai: if (EnemyCount < 3) { return(false); } break; case ClassJobType.RedMage: if (EnemyCount < 3) { return(false); } break; } } #region Cone Check if (ID == 106 || ID == 41 || ID == 70) { if (!Helpers.InView(Core.Player.Location, Core.Player.Heading, target.Location)) { return(false); } } #endregion #region Rectangle Check if (ID == 86) { if (!Core.Player.IsFacing(target)) { return(false); } } #endregion #endregion #region Pet Exception if (SpellType == SpellType.Pet) { if (Core.Player.Pet == null) { return(false); } if (PetManager.PetMode != PetMode.Obey) { if (!await Coroutine.Wait(1000, () => PetManager.DoAction("Obey", Core.Player))) { return(false); } Logging.Write(Colors.OrangeRed, @"[Ultima] Ability: Pet Obey"); } #region IsMounted Check if (Core.Player.IsMounted) { return(false); } #endregion #region CanCast if (!PetManager.CanCast(Name, target)) { return(false); } #endregion #region DoAction if (!await Coroutine.Wait(5000, () => PetManager.DoAction(Name, target))) { return(false); } #endregion Ultima.LastSpell = this; #region Recent Spell Add var key = target.ObjectId.ToString("X") + "-" + Name; var val = DateTime.UtcNow + DataManager.GetSpellData(Name).AdjustedCastTime + TimeSpan.FromSeconds(5); RecentSpell.Add(key, val); #endregion Logging.Write(Colors.OrangeRed, @"[Ultima] Ability: " + Name); return(true); } #endregion #region Card Exception if (SpellType == SpellType.Card) { if (!await Coroutine.Wait(1000, () => ActionManager.DoAction(ID, target))) { return(false); } Ultima.LastSpell = this; #region Recent Spell Add var key = target.ObjectId.ToString("X") + "-" + Name; var val = DateTime.UtcNow + DataManager.GetSpellData(3590).AdjustedCastTime + TimeSpan.FromSeconds(5); RecentSpell.Add(key, val); #endregion Logging.Write(Colors.OrangeRed, @"[Ultima] Ability: " + Name); return(true); } #endregion #region CanAttack Check if (!target.CanAttack && CastType != CastType.Self) { switch (SpellType) { case SpellType.Damage: case SpellType.DoT: case SpellType.Movement: case SpellType.Cooldown: case SpellType.Interrupt: case SpellType.Execute: case SpellType.Knockback: case SpellType.Debuff: case SpellType.Flank: case SpellType.Behind: return(false); } } #endregion #region Ninjutsu Exception if (SpellType == SpellType.Ninjutsu || SpellType == SpellType.Mudra) { #region Player Movement if (BotManager.Current.IsAutonomous) { switch (ActionManager.InSpellInRangeLOS(2247, target)) { case SpellRangeCheck.ErrorNotInLineOfSight: await CommonTasks.MoveAndStop(new MoveToParameters(target.Location), 0f); return(false); case SpellRangeCheck.ErrorNotInRange: await CommonTasks.MoveAndStop(new MoveToParameters(target.Location), 0f); return(false); case SpellRangeCheck.ErrorNotInFront: if (!target.InLineOfSight()) { await CommonTasks.MoveAndStop(new MoveToParameters(target.Location), 0f); return(false); } target.Face(); return(false); case SpellRangeCheck.Success: if (MovementManager.IsMoving) { Navigator.PlayerMover.MoveStop(); } break; } } #endregion #region IsMounted Check if (Core.Player.IsMounted) { return(false); } #endregion #region CanCast if (Ultima.UltSettings.QueueSpells) { if (!ActionManager.CanCastOrQueue(DataManager.GetSpellData(ID), target)) { return(false); } } else { if (!ActionManager.CanCast(ID, target)) { return(false); } } #endregion #region Wait For Animation if (Ultima.LastSpell.ID != 0 && Ultima.LastSpell.SpellType != SpellType.Ninjutsu && Ultima.LastSpell.SpellType != SpellType.Mudra) { await Coroutine.Wait(1000, () => DataManager.GetSpellData(Ultima.LastSpell.ID).Cooldown.TotalMilliseconds <= DataManager.GetSpellData(Ultima.LastSpell.ID).AdjustedCooldown.TotalMilliseconds - 1000); } #endregion #region DoAction if (!await Coroutine.Wait(1000, () => ActionManager.DoAction(ID, target))) { return(false); } #endregion #region Wait For Cast Completion await Coroutine.Wait(2000, () => !ActionManager.CanCast(ID, target)); #endregion Ultima.LastSpell = this; #region Recent Spell Add if (SpellType == SpellType.Mudra) { var key = target.ObjectId.ToString("X") + "-" + Name; var val = DateTime.UtcNow + DataManager.GetSpellData(ID).AdjustedCastTime + TimeSpan.FromSeconds(1); RecentSpell.Add(key, val); } #endregion Logging.Write(Colors.OrangeRed, @"[Ultima] Ability: " + Name); return(true); } #endregion #region HasSpell Check if (!ActionManager.HasSpell(ID)) { return(false); } #endregion #region Player Movement if (BotManager.Current.IsAutonomous) { switch (ActionManager.InSpellInRangeLOS(ID, target)) { case SpellRangeCheck.ErrorNotInLineOfSight: await CommonTasks.MoveAndStop(new MoveToParameters(target.Location), 0f); return(false); case SpellRangeCheck.ErrorNotInRange: await CommonTasks.MoveAndStop(new MoveToParameters(target.Location), 0f); return(false); case SpellRangeCheck.ErrorNotInFront: if (!target.InLineOfSight()) { await CommonTasks.MoveAndStop(new MoveToParameters(target.Location), 0f); return(false); } target.Face(); return(false); case SpellRangeCheck.Success: if (CastType == CastType.TargetLocation && Core.Player.Distance2D(target) + Core.Player.CombatReach + target.CombatReach > 25) { await CommonTasks.MoveAndStop(new MoveToParameters(target.Location), 0f); await Coroutine.Wait(1000, () => Core.Player.Distance2D(target) + Core.Player.CombatReach + target.CombatReach <= 25); return(false); } Navigator.PlayerMover.MoveStop(); break; } if (Core.Player.HasTarget && !MovementManager.IsMoving && Core.Player.IsMounted) { Logging.Write(Colors.Yellow, @"[Ultima] Dismounting..."); ActionManager.Dismount(); await Coroutine.Sleep(1000); } } #endregion #region IsMounted Check if (Core.Player.IsMounted) { return(false); } #endregion #region CanCast Check switch (CastType) { case CastType.TargetLocation: case CastType.SelfLocation: if (!ActionManager.CanCastLocation(ID, target.Location)) { return(false); } break; default: if (Ultima.UltSettings.QueueSpells) { if (!ActionManager.CanCastOrQueue(DataManager.GetSpellData(ID), target)) { return(false); } } else { if (!ActionManager.CanCast(ID, target)) { return(false); } } break; } if (MovementManager.IsMoving && DataManager.GetSpellData(ID).AdjustedCastTime.TotalMilliseconds > 0) { if (!BotManager.Current.IsAutonomous) { return(false); } Navigator.PlayerMover.MoveStop(); } #endregion #region InView Check if (GameSettingsManager.FaceTargetOnAction == false && CastType == CastType.Target && SpellType != SpellType.Heal && SpellType != SpellType.Defensive && !Helpers.InView(Core.Player.Location, Core.Player.Heading, target.Location)) { return(false); } #endregion #region Off-GCD Check if (GCDType == GCDType.Off) { switch (Core.Player.CurrentJob) { case ClassJobType.Arcanist: case ClassJobType.Scholar: case ClassJobType.Summoner: if (Core.Player.ClassLevel >= 38 && Core.Player.CurrentManaPercent > 40 && DataManager.GetSpellData(163).Cooldown.TotalMilliseconds <= 1000) { return(false); } break; case ClassJobType.Archer: case ClassJobType.Bard: if (DataManager.GetSpellData(97).Cooldown.TotalMilliseconds <= 700) { return(false); } break; case ClassJobType.Astrologian: if (DataManager.GetSpellData(3596).Cooldown.TotalMilliseconds <= 1000) { return(false); } break; case ClassJobType.Conjurer: case ClassJobType.WhiteMage: if (DataManager.GetSpellData(119).Cooldown.TotalMilliseconds <= 1000) { return(false); } break; case ClassJobType.DarkKnight: if (DataManager.GetSpellData(3617).Cooldown.TotalMilliseconds <= 1000) { return(false); } break; case ClassJobType.Gladiator: case ClassJobType.Paladin: if (DataManager.GetSpellData(9).Cooldown.TotalMilliseconds <= 1000) { return(false); } break; case ClassJobType.Lancer: case ClassJobType.Dragoon: if (DataManager.GetSpellData(75).Cooldown.TotalMilliseconds <= 1000) { return(false); } break; case ClassJobType.Machinist: if (DataManager.GetSpellData(2866).Cooldown.TotalMilliseconds <= 1000) { return(false); } break; case ClassJobType.Marauder: case ClassJobType.Warrior: if (DataManager.GetSpellData(31).Cooldown.TotalMilliseconds <= 1000) { return(false); } break; case ClassJobType.Pugilist: case ClassJobType.Monk: if (DataManager.GetSpellData(53).Cooldown.TotalMilliseconds <= 1000) { return(false); } break; case ClassJobType.Rogue: case ClassJobType.Ninja: if (DataManager.GetSpellData(2240).Cooldown.TotalMilliseconds <= 1000) { return(false); } break; case ClassJobType.Thaumaturge: case ClassJobType.BlackMage: if (DataManager.GetSpellData(142).Cooldown.TotalMilliseconds <= 1000) { return(false); } break; case ClassJobType.Samurai: if (DataManager.GetSpellData(8821).Cooldown.TotalMilliseconds <= 1000) { return(false); } break; case ClassJobType.RedMage: if (DataManager.GetSpellData(7503).Cooldown.TotalMilliseconds <= 1000) { return(false); } break; } } #endregion #region DoAction switch (CastType) { case CastType.TargetLocation: if (Ultima.UltSettings.RandomCastLocation) { var rndx = (target.CombatReach * _rnd.NextDouble() * GetMultiplier()); var rndz = (target.CombatReach * _rnd.NextDouble() * GetMultiplier()); var rndxz = new Vector3((float)rndx, 0f, (float)rndz); var tarloc = target.Location; var rndloc = tarloc + rndxz; if (!await Coroutine.Wait(1000, () => ActionManager.DoActionLocation(ID, rndloc))) { return(false); } } else { if (!await Coroutine.Wait(1000, () => ActionManager.DoActionLocation(ID, target.Location))) { return(false); } } break; case CastType.SelfLocation: if (Ultima.UltSettings.RandomCastLocation) { var rndx = ((1f * _rnd.NextDouble() + 1f) * GetMultiplier()); var rndz = ((1f * _rnd.NextDouble() + 1f) * GetMultiplier()); var rndxz = new Vector3((float)rndx, 0f, (float)rndz); var tarloc = target.Location; var rndloc = tarloc + rndxz; if (!await Coroutine.Wait(1000, () => ActionManager.DoActionLocation(ID, rndloc))) { return(false); } } else { if (!await Coroutine.Wait(1000, () => ActionManager.DoActionLocation(ID, target.Location))) { return(false); } } break; default: if (!await Coroutine.Wait(1000, () => ActionManager.DoAction(ID, target))) { return(false); } break; } #endregion #region Wait For Cast Completion switch (CastType) { case CastType.SelfLocation: case CastType.TargetLocation: await Coroutine.Wait(3000, () => !ActionManager.CanCastLocation(ID, target.Location)); break; default: await Coroutine.Wait(3000, () => !ActionManager.CanCast(ID, target)); break; } #endregion Ultima.LastSpell = this; #region Recent Spell Add if (SpellType != SpellType.Damage && SpellType != SpellType.Heal && SpellType != SpellType.AoE && SpellType != SpellType.Behind && SpellType != SpellType.Flank) { var key = target.ObjectId.ToString("X") + "-" + Name; var val = DateTime.UtcNow + DataManager.GetSpellData(ID).AdjustedCastTime + TimeSpan.FromSeconds(5); RecentSpell.Add(key, val); } if (SpellType == SpellType.Heal) { var key = target.ObjectId.ToString("X") + "-" + Name; var val = DateTime.UtcNow + DataManager.GetSpellData(ID).AdjustedCastTime + TimeSpan.FromSeconds(3); RecentSpell.Add(key, val); } #endregion Logging.Write(Colors.OrangeRed, @"[Ultima] Ability: " + Name); return(true); }
public static async Task SetGlamours(string Glamour) { if (Me.CurrentJob == ClassJobType.Summoner && !QuestLogManager.IsQuestCompleted(67896)) { switch (EikoSettingsModel.selectedGarudaGlamour) { default: if (EikoSettingsModel.Instance.SelectedGarudaGlamour != GarudaGlamour.None) { EikoSettingsModel.Instance.SelectedGarudaGlamour = GarudaGlamour.None; } break; } switch (EikoSettingsModel.selectedTitanGlamour) { default: if (EikoSettingsModel.Instance.SelectedTitanGlamour != TitanGlamour.None) { EikoSettingsModel.Instance.SelectedTitanGlamour = TitanGlamour.None; } break; } switch (EikoSettingsModel.selectedIfritGlamour) { default: if (EikoSettingsModel.Instance.SelectedIfritGlamour != IfritGlamour.None) { EikoSettingsModel.Instance.SelectedIfritGlamour = IfritGlamour.None; } break; } return; } if (Me.CurrentJob == ClassJobType.Arcanist) { switch (EikoSettingsModel.selectedGarudaGlamour) { default: if (EikoSettingsModel.Instance.SelectedGarudaGlamour != GarudaGlamour.EmeraldCarbuncle) { EikoSettingsModel.Instance.SelectedGarudaGlamour = GarudaGlamour.EmeraldCarbuncle; } break; } switch (EikoSettingsModel.selectedTitanGlamour) { default: if (EikoSettingsModel.Instance.SelectedTitanGlamour != TitanGlamour.TopazCarbuncle) { EikoSettingsModel.Instance.SelectedTitanGlamour = TitanGlamour.TopazCarbuncle; } break; } return; } if (Glamour == "Garuda") { switch (EikoSettingsModel.selectedGarudaGlamour) { case GarudaGlamour.None: ChatManager.SendChat("/egiglamour \"Garuda-Egi\""); break; case GarudaGlamour.EmeraldCarbuncle: ChatManager.SendChat("/egiglamour \"Garuda-Egi\" \"Emerald Carbuncle\""); break; case GarudaGlamour.TopazCarbuncle: ChatManager.SendChat("/egiglamour \"Garuda-Egi\" \"Topaz Carbuncle\""); break; case GarudaGlamour.RubyCarbuncle: ChatManager.SendChat("/egiglamour \"Garuda-Egi\" \"Ruby Carbuncle\""); break; default: ChatManager.SendChat("/egiglamour \"Garuda-Egi\""); break; } if (EikoSettingsModel.Instance.SelectedEikoSummon == EikoSummonMode.Garuda) { PetManager.DoAction(Spells.Away.Name, Me); Thread.Sleep(500); await Summon(); } } if (Glamour == "Titan") { switch (EikoSettingsModel.selectedTitanGlamour) { case TitanGlamour.None: ChatManager.SendChat("/egiglamour \"Titan-Egi\""); break; case TitanGlamour.EmeraldCarbuncle: ChatManager.SendChat("/egiglamour \"Titan-Egi\" \"Emerald Carbuncle\""); break; case TitanGlamour.TopazCarbuncle: ChatManager.SendChat("/egiglamour \"Titan-Egi\" \"Topaz Carbuncle\""); break; case TitanGlamour.RubyCarbuncle: ChatManager.SendChat("/egiglamour \"Titan-Egi\" \"Ruby Carbuncle\""); break; default: ChatManager.SendChat("/egiglamour \"Titan-Egi\""); break; } if (EikoSettingsModel.Instance.SelectedEikoSummon == EikoSummonMode.Titan) { PetManager.DoAction(Spells.Away.Name, Me); Thread.Sleep(500); await Summon(); } } if (Glamour == "Ifrit") { switch (EikoSettingsModel.selectedIfritGlamour) { case IfritGlamour.None: ChatManager.SendChat("/egiglamour \"Ifrit-Egi\""); break; case IfritGlamour.EmeraldCarbuncle: ChatManager.SendChat("/egiglamour \"Ifrit-Egi\" \"Emerald Carbuncle\""); break; case IfritGlamour.TopazCarbuncle: ChatManager.SendChat("/egiglamour \"Ifrit-Egi\" \"Topaz Carbuncle\""); break; case IfritGlamour.RubyCarbuncle: ChatManager.SendChat("/egiglamour \"Ifrit-Egi\" \"Ruby Carbuncle\""); break; default: ChatManager.SendChat("/egiglamour \"Ifrit-Egi\""); break; } if (EikoSettingsModel.Instance.SelectedEikoSummon == EikoSummonMode.Ifrit) { PetManager.DoAction(Spells.Away.Name, Me); Thread.Sleep(500); await Summon(); } } }
private static async Task <bool> Summon() { if (!EikoSettingsModel.Instance.UseSummonPets || !ActionManager.CanCast(Spells.Summon, Me) || Me.ClassLevel <= 3 || Me.IsCasting || CombatHelper.LastSpell == Spells.Summon || CombatHelper.LastSpell == Spells.SummonII || CombatHelper.LastSpell == Spells.SummonIII || ActionManager.LastSpell == Spells.Summon || ActionManager.LastSpell == Spells.SummonII || ActionManager.LastSpell == Spells.SummonIII || Me.Pet?.NpcId == 6566) { return(false); } if (Me.Pet == null && summonLimiterCount < 2) { if (DateTime.Now < summonLimiter) { return(false); } summonLimiter = DateTime.Now.AddMilliseconds(500); summonLimiterCount++; return(false); } if (Me.Pet != null && summonLimiterCount != 0) { summonLimiterCount = 0; } switch (Me.CurrentJob) { case ClassJobType.Arcanist: switch (EikoSettingsModel.Instance.SelectedEikoSummon) { case EikoSummonMode.None: break; case EikoSummonMode.Garuda: if (previousEikoSummon == EikoSummonMode.Titan && Me.ClassLevel > 14) { EikoSettingsModel.Instance.SelectedEikoSummon = EikoSummonMode.Titan; break; } if (Me.Pet == null || PetManager.ActivePetType != PetType.Emerald_Carbuncle) { await Spells.Summon.Use(Me, true); PetManager.DoAction(Spells.Guard.LocalizedName, Me); return(true); } break; case EikoSummonMode.Titan: if (Me.ClassLevel <= 14) { previousEikoSummon = EikoSummonMode.Titan; EikoSettingsModel.Instance.SelectedEikoSummon = EikoSummonMode.Garuda; break; } if (Me.Pet == null || PetManager.ActivePetType != PetType.Topaz_Carbuncle) { await Spells.SummonII.Use(Me, true); PetManager.DoAction(Spells.Guard.LocalizedName, Me); return(true); } break; } break; case ClassJobType.Summoner: switch (EikoSettingsModel.Instance.SelectedEikoSummon) { case EikoSummonMode.None: break; case EikoSummonMode.Garuda: if (previousEikoSummon == EikoSummonMode.Titan && Me.ClassLevel > 14) { EikoSettingsModel.Instance.SelectedEikoSummon = EikoSummonMode.Titan; break; } if (Me.Pet == null || PetManager.ActivePetType != PetType.Garuda_Egi) { await Spells.Summon.Use(Me, true); PetManager.DoAction(Spells.Guard.LocalizedName, Me); return(true); } break; case EikoSummonMode.Titan: if (previousEikoSummon == EikoSummonMode.Ifrit && Me.ClassLevel > 29) { EikoSettingsModel.Instance.SelectedEikoSummon = EikoSummonMode.Ifrit; break; } if (Me.ClassLevel <= 14) { previousEikoSummon = EikoSummonMode.Titan; EikoSettingsModel.Instance.SelectedEikoSummon = EikoSummonMode.Garuda; break; } if (Me.Pet == null || PetManager.ActivePetType != PetType.Titan_Egi) { await Spells.SummonII.Use(Me, true); PetManager.DoAction(Spells.Guard.LocalizedName, Me); return(true); } break; case EikoSummonMode.Ifrit: if (Me.ClassLevel <= 14) { previousEikoSummon = EikoSummonMode.Ifrit; EikoSettingsModel.Instance.SelectedEikoSummon = EikoSummonMode.Garuda; } if (Me.ClassLevel <= 29) { previousEikoSummon = EikoSummonMode.Ifrit; EikoSettingsModel.Instance.SelectedEikoSummon = EikoSummonMode.Titan; } if (Me.Pet == null || PetManager.ActivePetType != PetType.Ifrit_Egi) { await Spells.SummonIII.Use(Me, true); PetManager.DoAction(Spells.Guard.LocalizedName, Me); return(true); } break; } break; } return(false); }
private static async Task <bool> PetActions() { if (Target == null || !Target.CanAttack || Me.Pet == null || !EikoSettingsModel.Instance.UseBuffs || !Target.HealthCheck(false) || !Target.TimeToDeathCheck() || !PetManager.LockTimer.IsFinished) { return(false); } if (PetManager.LockTimer.WaitTime.Seconds != 2) { PetManager.LockTimer = new WaitTimer(new TimeSpan(0, 0, 0, 2)); } if (Me.Pet.CurrentTargetId != Me.CurrentTargetObjId || Me.Pet.TargetCharacter == null || PetManager.PetMode != PetMode.Obey) { PetManager.DoAction(Spells.Obey.LocalizedName, Target); } if (PetManager.PetStance != PetStance.Guard) { PetManager.DoAction(Spells.Guard.LocalizedName, Me); } if (!DreadwormTrance) { if (await Aetherpact()) { return(true); } if (await Rouse()) { return(true); } if (await Enkindle()) { return(true); } } switch (EikoSettingsModel.Instance.SelectedEikoSummon) { case EikoSummonMode.Garuda: if (EikoSettingsModel.Instance.UseContagion && Me.ClassLevel >= 40 && PetManager.CanCast(Spells.Contagion.LocalizedName, Target) && DreadwormTrance && Target.HasAura(BioAura(), true, 5000) && Target.HasAura(MiasmaAura(), true, 5000) && Spells.TriDisaster.Cooldown.TotalSeconds > 5 || Me.ClassLevel < 56) { return(PetManager.DoAction(Spells.Contagion.LocalizedName, Target)); } if (PetManager.CanCast(Spells.AerialSlash.LocalizedName, Target) && !DreadwormTrance) { return(PetManager.DoAction(Spells.AerialSlash.LocalizedName, Target)); } break; case EikoSummonMode.Titan: if (PetManager.CanCast(Spells.MountainBuster.LocalizedName, Me.Pet)) { return(PetManager.DoAction(Spells.MountainBuster.LocalizedName, Me.Pet)); } if (PetManager.CanCast(Spells.EarthenWard.LocalizedName, Me.Pet)) { return(PetManager.DoAction(Spells.EarthenWard.LocalizedName, Me.Pet)); } if (PetManager.CanCast(Spells.Landslide.LocalizedName, Target) && (Target.CanStun() || ((Character)Target).IsCasting)) { return(PetManager.DoAction(Spells.Landslide.LocalizedName, Target)); } break; case EikoSummonMode.Ifrit: if (PetManager.CanCast(Spells.CrimsonCyclone.LocalizedName, Target) && (Target.CanStun() || ((Character)Target).IsCasting)) { return(PetManager.DoAction(Spells.CrimsonCyclone.LocalizedName, Target)); } if (PetManager.CanCast(Spells.RadiantShield.LocalizedName, Me.Pet)) { return(PetManager.DoAction(Spells.RadiantShield.LocalizedName, Me.Pet)); } if (PetManager.CanCast(Spells.FlamingCrush.LocalizedName, Me.Pet)) { return(PetManager.DoAction(Spells.FlamingCrush.LocalizedName, Me.Pet)); } break; } return(false); }
private static async Task <bool> Heel() { return(Me.Pet != null && !Me.IsMounted && EikoSettingsModel.Instance.UseHeel && Me.Distance(Me.Pet) > EikoSettingsModel.Instance.HeelDistance && PetManager.DoAction(Spells.Heel.LocalizedName, Me.Pet)); }
internal static async Task <bool> Opener() { if (Target == null || !Target.CanAttack) { return(false); } #region RoutineSwitch ThreadSafeObservableCollection <OpenerSpellInfo> openerList = null; switch (MainSettingsModel.Instance.CurrentRoutine) { case "Barret": openerList = Barret_OpenerViewModel.Instance.GuiOpenerList; break; case "Beatrix": openerList = Beatrix_OpenerViewModel.Instance.GuiOpenerList; break; case "Cecil": openerList = Cecil_OpenerViewModel.Instance.GuiOpenerList; break; case "Cyan": openerList = Cyan_OpenerViewModel.Instance.GuiOpenerList; break; case "Edward": openerList = Edward_OpenerViewModel.Instance.GuiOpenerList; break; case "Eiko": openerList = Eiko_OpenerViewModel.Instance.GuiOpenerList; break; case "Elayne": openerList = Elayne_OpenerViewModel.Instance.GuiOpenerList; break; case "Freya": openerList = Freya_OpenerViewModel.Instance.GuiOpenerList; break; case "Paine": openerList = Paine_OpenerViewModel.Instance.GuiOpenerList; break; case "Sabin": openerList = Sabin_OpenerViewModel.Instance.GuiOpenerList; break; case "Shadow": openerList = Shadow_OpenerViewModel.Instance.GuiOpenerList; break; case "Vivi": openerList = Vivi_OpenerViewModel.Instance.GuiOpenerList; break; } #endregion RoutineSwitch if (openerList != null) { var openerQueue = new Queue <OpenerSpellInfo>(openerList); if (openerQueue.Count == 0) { Logger.KefkaLog(@"Opener queue is empty, please use the Reset Opener button to reset!"); openerQueue.Clear(); OpenerManager.ResetOpeners(); return(false); } while (Target != null && openerQueue.Count > 0) { var nextOpener = openerQueue.Peek(); Logger.KefkaLog(@"Next Opener Skill: {0}", nextOpener.SpellName); if (nextOpener.SpellName.Contains("Delay")) { var waitTime = TimeSpan.FromSeconds(nextOpener.SpellId).Duration(); await Coroutine.Wait(waitTime, () => false); openerQueue.Dequeue(); continue; } if (nextOpener.IsItem) { var openerItem = InventoryManager.FilledSlots.FirstOrDefault(r => r.RawItemId == nextOpener.SpellId); if (await Items.UsePotion(openerItem.Item, true)) { openerQueue.Dequeue(); continue; } } if (nextOpener.IsPet) { var petOpenerSpell = DataManager.GetPetSpellData(nextOpener.SpellName); if (petOpenerSpell == null) { openerQueue.Dequeue(); continue; } if (PetManager.DoAction(petOpenerSpell.Name, Target)) { Logger.KefkaLog("We're inside of the PetSpell Section."); openerQueue.Dequeue(); continue; } } var openerSpell = DataManager.GetSpellData(nextOpener.SpellId); await Coroutine.Wait(3000, () => ActionManager.CanCast(openerSpell, Target) || ActionManager.CanCast(openerSpell, Me)); if (openerSpell == null) { openerQueue.Dequeue(); } #region Routine Nuance Catches switch (MainSettingsModel.Instance.CurrentRoutine) { case "Barret": break; case "Beatrix": break; case "Cecil": break; case "Cyan": break; case "Edward": if (openerSpell == Spells.PitchPerfect) { await Coroutine.Wait((int)CombatHelper.GcdTimeRemaining, () => ActionResourceManager.Bard.Repertoire == 3); if (ActionResourceManager.Bard.Repertoire != 3) { openerQueue.Dequeue(); continue; } if (await Spells.PitchPerfect.Use(Target, true)) { openerQueue.Dequeue(); continue; } } break; case "Eiko": break; case "Elayne": if (openerSpell == Spells.Verfire || openerSpell == Spells.Verstone) { await Coroutine.Wait((int)CombatHelper.GcdTimeRemaining, () => Me.HasAura(Auras.VerfireReady) || Me.HasAura(Auras.VerstoneReady)); if (!Me.HasAura(Auras.VerfireReady) && !Me.HasAura(Auras.VerstoneReady)) { openerQueue.Dequeue(); continue; } if (Me.HasAura(Auras.VerfireReady)) { if (await Spells.Verfire.Use(Target, true)) { openerQueue.Dequeue(); continue; } } if (Me.HasAura(Auras.VerstoneReady)) { if (await Spells.Verstone.Use(Target, true)) { openerQueue.Dequeue(); continue; } } } break; case "Freya": if (openerSpell == Spells.DragonSight) { if (await FreyaRotation.DragonSightOpener()) { openerQueue.Dequeue(); continue; } } break; case "Paine": break; case "Sabin": break; case "Shadow": break; case "Vivi": break; } #endregion Routine Nuance Catches if (openerSpell?.Range == 0 && openerSpell.SpellType != SpellType.Weaponskill) { if (await openerSpell.UseOpenerSpell(Me, true)) { Logger.KefkaLog("We're inside of the Regular Spell (ME) Section."); openerQueue.Dequeue(); continue; } } if (await openerSpell.UseOpenerSpell(Target, true)) { Logger.KefkaLog("We're inside of the Regular Spell (TARGET) Section."); openerQueue.Dequeue(); } await Coroutine.Yield(); } Logger.KefkaLog(@"Opener has completed, or was interrupted!"); Core.OverlayManager.AddToast(() => "Opener Complete!", TimeSpan.FromMilliseconds(750), MainSettingsModel.Instance.ToastColor(true), Colors.White, new FontFamily("High Tower Text Italic"), new FontWeight(), 52); openerQueue.Clear(); } OpenerManager.ResetOpeners(); return(false); }
private static async Task <bool> PetAction() { if (Me.HasAura(Auras.Dissipation) || Me.Pet == null || HealManager.Any(hm => hm.HasAura(Auras.FeyUnion)) || CombatHelper.GcdTimeRemaining < 10) { return(false); } var target = HealManager.FirstOrDefault(hm => hm.InCombat); switch (SuritoSettingsModel.Instance.SelectedSuritoSummon) { case SuritoSummonMode.Eos: if (SuritoSettingsModel.Instance.UseWhisperingDawn && PetManager.CanCast(Spells.WhisperingDawn.LocalizedName, Me.Pet) && HealManager.Count(hm => hm.Distance2D(Me.Pet) <= 15 && hm.CurrentHealthPercent <= SuritoSettingsModel.Instance.WhisperingDawnHpPct) >= SuritoSettingsModel.Instance.PetAoEPlayerCount) { return(PetManager.DoAction(Spells.WhisperingDawn.LocalizedName, Me.Pet)); } if (SuritoSettingsModel.Instance.UseFeyCovenant && PetManager.CanCast(Spells.FeyCovenant.LocalizedName, Me.Pet) && HealManager.Count(hm => hm.Distance2D(Me.Pet) <= 15 && hm.CurrentHealthPercent <= SuritoSettingsModel.Instance.FeyCovenantHpPct) >= SuritoSettingsModel.Instance.PetAoEPlayerCount) { return(PetManager.DoAction(Spells.FeyCovenant.LocalizedName, Me.Pet)); } if (SuritoSettingsModel.Instance.UseFeyIllumination && PetManager.CanCast(Spells.FeyIllumination.LocalizedName, Me.Pet) && HealManager.Count(hm => hm.Distance2D(Me.Pet) <= 15 && hm.CurrentHealthPercent <= SuritoSettingsModel.Instance.FeyIlluninationHpPct) >= SuritoSettingsModel.Instance.PetAoEPlayerCount) { return(PetManager.DoAction(Spells.FeyIllumination.LocalizedName, Me.Pet)); } if (SuritoSettingsModel.Instance.UseEmbrace) { target = HealManager.FirstOrDefault(hm => hm.CurrentHealthPercent <= SuritoSettingsModel.Instance.EmbraceHpPct); if (target != null && PetManager.CanCast(Spells.Embrace.LocalizedName, target)) { return(PetManager.DoAction(Spells.Embrace.LocalizedName, target)); } } break; case SuritoSummonMode.Selene: if (SuritoSettingsModel.Instance.UseEmbrace) { target = HealManager.FirstOrDefault(hm => hm.CurrentHealthPercent <= SuritoSettingsModel.Instance.EmbraceHpPct); if (target != null && PetManager.CanCast(Spells.Embrace.LocalizedName, target)) { return(PetManager.DoAction(Spells.Embrace.LocalizedName, target)); } } if (SuritoSettingsModel.Instance.UseSilentDusk) { target = HealManager.FirstOrDefault(hm => hm.CanSilence()); if (target != null && PetManager.CanCast(Spells.SilentDusk.LocalizedName, target)) { return(PetManager.DoAction(Spells.SilentDusk.LocalizedName, target)); } } if (SuritoSettingsModel.Instance.UseFeyCaress && PetManager.CanCast(Spells.FeyCaress.LocalizedName, Me.Pet) && HealManager.Count(hm => hm.Distance2D(Me.Pet) <= 20) >= SuritoSettingsModel.Instance.PetAoEPlayerCount) { return(await CleanseManager.PetCleanse()); } if (SuritoSettingsModel.Instance.UseFeyWind && PetManager.CanCast(Spells.FeyWind.LocalizedName, Me.Pet) && HealManager.Count(hm => hm.IsDps() && hm.Distance2D(Me.Pet) <= 20) >= SuritoSettingsModel.Instance.PetAoEPlayerCount) { return(PetManager.DoAction(Spells.FeyWind.LocalizedName, Me.Pet)); } break; } return(false); }
private static async Task <bool> Summon() { if (!SuritoSettingsModel.Instance.UseSummon || Me.ClassLevel < 4 || Me.HasAura(Auras.Dissipation) || (Me.InCombat && !SuritoSettingsModel.Instance.UseSummonInCombat)) { return(false); } switch (SuritoSettingsModel.Instance.SelectedSuritoSummon) { case SuritoSummonMode.None: break; case SuritoSummonMode.Eos: if (previousSuritoSummon == SuritoSummonMode.Selene && Me.ClassLevel > 14) { SuritoSettingsModel.Instance.SelectedSuritoSummon = SuritoSummonMode.Selene; break; } if (ActionManager.LastSpell == Spells.Summon) { return(false); } if (Me.Pet == null || Me.Pet.EnglishName != "Eos") { if (ActionManager.CanCast(Spells.Swiftcast, Me) && SuritoSettingsModel.Instance.SwiftcastSummon) { if (await Spells.Swiftcast.CastBuff(Me, true, Auras.Swiftcast)) { await Spells.Summon.Use(Me, true); } } if (await Spells.Summon.Use(Me, true)) { PetManager.DoAction(Spells.Guard.LocalizedName, Me); PetManager.DoAction(Spells.Obey.LocalizedName, Me); return(true); } } break; case SuritoSummonMode.Selene: if (Me.ClassLevel <= 14) { previousSuritoSummon = SuritoSummonMode.Selene; SuritoSettingsModel.Instance.SelectedSuritoSummon = SuritoSummonMode.Eos; break; } if (ActionManager.LastSpell == Spells.SummonII) { return(false); } if (Me.Pet == null || Me.Pet.EnglishName != "Selene") { if (ActionManager.CanCast(Spells.Swiftcast, Me) && SuritoSettingsModel.Instance.SwiftcastSummon) { if (await Spells.Swiftcast.CastBuff(Me, true, Auras.Swiftcast)) { await Spells.SummonII.Use(Me, true); } } if (await Spells.SummonII.Use(Me, true)) { PetManager.DoAction(Spells.Guard.LocalizedName, Me); PetManager.DoAction(Spells.Obey.LocalizedName, Me); } return(true); } break; } return(false); }
private async Task <bool> Opener() { if (!Shinra.Settings.SummonerOpener || Shinra.OpenerFinished || Core.Player.ClassLevel < 70) { return(false); } #region Custom Logic if (PetManager.ActivePetType == PetType.Ifrit_Egi && PetManager.PetMode != PetMode.Sic) { if (await Coroutine.Wait(1000, () => PetManager.DoAction("Sic", Core.Player))) { Logging.Write(Colors.GreenYellow, @"[Shinra] Casting >>> Sic"); return(await Coroutine.Wait(3000, () => PetManager.PetMode == PetMode.Sic)); } } if (Shinra.OpenerStep == 1) { if (PetManager.ActivePetType == PetType.Garuda_Egi && PetManager.PetMode == PetMode.Obey) { if (await MySpells.Contagion.Cast()) { return(true); } } if (ResourceArcanist.Aetherflow < 3 || MySpells.Aetherflow.Cooldown() > 15000) { Helpers.Debug("Aborting opener due to Aetherflow charges."); Shinra.OpenerFinished = true; return(true); } } #endregion if (Shinra.Settings.SummonerPotion && Shinra.OpenerStep == 2) { if (await Helpers.UsePotion(Helpers.PotionIds.Int)) { return(true); } } var spell = MyOpener.Spells.ElementAt(Shinra.OpenerStep); #region Custom Logic if (spell.Name == MySpells.SummonIII.Name) { if (PetManager.ActivePetType == PetType.Ifrit_Egi || !Core.Player.HasAura(MySpells.Role.Swiftcast.Name)) { Shinra.OpenerStep++; return(true); } } if (spell.Name == MySpells.Fester.Name && ResourceArcanist.Aetherflow > 0) { if (spell.Cooldown() > 0) { return(true); } } #endregion Helpers.Debug($"Executing opener step {Shinra.OpenerStep} >>> {spell.Name}"); if (await spell.Cast(null, false) || spell.Cooldown(true) > 2500 && spell.Cooldown() > 0 && !Core.Player.IsCasting) { Shinra.OpenerStep++; if (spell.Name == MySpells.Role.Swiftcast.Name) { await Coroutine.Wait(1000, () => Core.Player.HasAura(MySpells.Role.Swiftcast.Name)); } } if (Shinra.OpenerStep >= MyOpener.Spells.Count) { Helpers.Debug("Opener finished."); Shinra.OpenerFinished = true; } return(true); }