That's what I figured (and did) but, still no luck. Figured I'd give what kei said a shot anyways! Edit: Did exactly as above. It's #2 on my list of "What I've already tried," no idea why it's not working. I edited absolutely nothing. Also would like to add, there were no errors or issues when checking out. Here's the breakdown: 1) Created folder in Main Directory\Routines called YourRaidingBuddy 1a) Directory now looks like Main Directory\Routines\YourRaidingBuddy 2) Right-clicked YourRaidingBuddy folder in Routines, hit SVN checkout and made sure the url was: https://subversion.assembla.com/svn/team-random/ 3) SVN added all the items, as of this message it says it's at revision 1227. 4) Restarted the bot, still only shows Kupo and Ultima.
Yea it seems you did everything right. Will just have to wait a few hours until Xcesius comes back on.
Make sure you have an SVN implemented class loaded when you first launch RB; I'm not sure exactly which are currently supported by default, but the Rotations folder has Conjurer, Marauder, and Rogue so I would try one of those to see if it shows up. Then try one in the Class folder; then lastly, try one in the Jobs folder. In the current version, no rotations are actually ironed out (first post still shows Rotations at 0% complete), just the base work; this is meant as a base for you to make your own rotations until things get solidified. If you want a finished product with complete rotations, you may need to wait a bit and use Ultima in the meantime.
Updated Dark Knight, it will always finish to rotation after Spinning or Syp is used even shift is released. Always use Delirium if your HP is above 70% and Dark Arts is down (As delirium = more DPS) Once I finish my 58 quest I might update again or at 60 depends on if the level 58 skill is needed or not. Code: using System.Threading.Tasks; using System.Collections.Generic; using System.Windows.Media; using ff14bot; using ff14bot.Enums; using ff14bot.Managers; using ff14bot.Objects; using ff14bot.Helpers; using YourRaidingBuddy.Helpers; using YourRaidingBuddy.Settings; using YourRaidingBuddy.Books; using System.Windows.Forms; using System.Linq; using YourRaidingBuddy.Interfaces.Settings; namespace YourRaidingBuddy.Rotations { public class DarkKnight : Root { private static LocalPlayer Me { get { return Core.Player; } } //Core.Player.CurrentTarget as BattleCharacter public override ClassJobType[] Class { get { return new[] { ClassJobType.DarkKnight }; } } public override void OnInitialize() { ; } #region NewRotation public static async Task<bool> AutoMode() { if (!Me.CurrentTarget.IsViable()) return false; return await Rotation(); } public static async Task<bool> HotkeyMode() { if (!Me.CurrentTarget.IsViable()) return false; if (VariableBook.HkmMultiTarget) await Unleash(); return await Rotation(); } public static async Task<bool> Rotation() { if (Managers.HotkeyManager.IsKeyDown(System.Windows.Forms.Keys.LShiftKey)) { await PullSingle(); } else { await PullMultiple(); } await Unleash(); await Plunge(); await Darkside(); await DotRotation(); await FinishedRotation(); if (Managers.HotkeyManager.IsKeyDown(System.Windows.Forms.Keys.LShiftKey)) { await EnmityRotation(); } else { await DPSRotation(); } await OffGcdRotation(); await MPGeneratorRotation(); return false; } public static async Task<bool> Darkside() { await Spell.NoneGcdCast("Darkside", Me, () => !Me.HasAura("Darkside") && Me.CurrentManaPercent > 90); return false; } public static async Task<bool> DPSRotation() { await DarkArts(); await Spell.CastSpell("Syphon Strike", () => Actionmanager.LastSpell.Name == "Hard Slash"); await Spell.CastSpell("Hard Slash", () => true); return false; } // We always want to finished out combo. public static async Task<bool> FinishedRotation() { await DarkArts(); await Spell.CastSpell("Souleater", () => Actionmanager.LastSpell.Name == "Syphon Strike" && Me.CurrentTarget.HasAura("Delirium", true, 4000) && ((Me.CurrentHealthPercent < 70 && Me.HasAura("Grit")) || Me.HasAura("Dark Arts"))); await Spell.CastSpell("Delirium", () => Actionmanager.LastSpell.Name == "Syphon Strike"); await Spell.CastSpell("Power Slash", () => Actionmanager.LastSpell.Name == "Spinning Slash"); return false; } public static async Task<bool> DarkArts() { await Spell.NoneGcdCast("Dark Arts", Me, () => Actionmanager.LastSpell.Name == "Syphon Strike" && Me.CurrentManaPercent > 90 && Me.CurrentTarget.HasAura("Delirium", true, 4000)); return false; } static bool triggerUnleash = false; public static async Task<bool> Unleash() { if (triggerUnleash && Actionmanager.CanCast("Unleash", Me)) { await Spell.ApplyCast("Unleash", Me, () => true); triggerUnleash = false; } return false; } static bool triggerPlunge = false; public static async Task<bool> Plunge() { if (triggerPlunge && Actionmanager.CanCast("Plunge", Me.CurrentTarget)) { await Spell.NoneGcdCast("Plunge", Me.CurrentTarget, () => true); triggerPlunge = false; } return false; } public static async Task<bool> PullSingle() { if (Actionmanager.CanCast("Unmend", Me.CurrentTarget) && Me.CurrentTarget.Distance(Me) > 10) { await Spell.CastSpell("Unmend", () => true); triggerPlunge = true; } return false; } public static async Task<bool> PullMultiple() { if (Actionmanager.CanCast("Plunge", Me.CurrentTarget) && Me.CurrentTarget.Distance(Me) > 10) { await Spell.NoneGcdCast("Plunge", Me.CurrentTarget, () => true); triggerUnleash = true; } return false; } public static async Task<bool> DotRotation() { await Spell.ApplyCast("Scourge", Me.CurrentTarget, () => !Me.CurrentTarget.HasAura("Scourge", true, 4000) && Actionmanager.LastSpell.Name != "Syphon Strike" && Actionmanager.LastSpell.Name != "Hard Slash" && Actionmanager.LastSpell.Name != "Spinning Slash"); return false; } // Currently without a way to detect enmity, we will use hotkey to trigger this. public static async Task<bool> EnmityRotation() { await Spell.CastSpell("Spinning Slash", () => Actionmanager.LastSpell.Name == "Hard Slash"); await Spell.CastSpell("Hard Slash", () => true); return false; } public static async Task<bool> OffGcdRotation() { // Offensive await Spell.CastLocation("Salted Earth", Me.CurrentTarget, true); await Spell.NoneGcdCast("Reprisal", Me.CurrentTarget, () => true); await Spell.NoneGcdCast("Low Blow", Me.CurrentTarget, () => true); // Need to solve this problem for an increase in dps. // Leaving it like this allow it to be much more flexible. //await Spell.NoneGcdCast("Plunge", Me.CurrentTarget, () => Me.CurrentTarget.Distance(Me) > 10); // Defensive await Spell.NoneGcdCast("Dark Dance", Me, () => true); return false; } public static async Task<bool> MPGeneratorRotation() { if (Me.CurrentManaPercent < 70 && Me.CurrentTarget.Distance(Me) < 3) { await Spell.NoneGcdCast("Blood Weapon", Me, () => true); await Spell.NoneGcdCast("Blood Price", Me, () => true); await Spell.NoneGcdCast("Sole Survivor", Me, () => true); await Spell.NoneGcdCast("Carve and Spit", Me, () => true); } return false; } #endregion } } Edit: Updated so it check for Grit before using soul eater when HP < 70%. (There's no healing when Grit is off) Edit2: Some very exciting pulling logic coming tonight!!!
This version should no longer use Unleash after Plunge everytime, it will check if there is at least 2 target that is not attacking you first. Unleash will not interrupt any combo. Mana regeneration spell now have its own logic for each spell. Blood Weapon - Will be use when mana < 90% Blood Price - mana < 70% Carve and Spit - No Dark Arts, mana < 70% Sole Survivor - Mana or HP < 70%, Target HP < 5000 Code: using System.Threading.Tasks; using System.Collections.Generic; using System.Windows.Media; using ff14bot; using ff14bot.Enums; using ff14bot.Managers; using ff14bot.Objects; using ff14bot.Helpers; using YourRaidingBuddy.Helpers; using YourRaidingBuddy.Settings; using YourRaidingBuddy.Books; using System.Windows.Forms; using System.Linq; using YourRaidingBuddy.Interfaces.Settings; namespace YourRaidingBuddy.Rotations { public class DarkKnight : Root { private static LocalPlayer Me { get { return Core.Player; } } //Core.Player.CurrentTarget as BattleCharacter public override ClassJobType[] Class { get { return new[] { ClassJobType.DarkKnight }; } } public override void OnInitialize() { ; } #region NewRotation public static async Task<bool> AutoMode() { if (!Me.CurrentTarget.IsViable()) return false; return await Rotation(); } public static async Task<bool> HotkeyMode() { if (!Me.CurrentTarget.IsViable()) return false; if (VariableBook.HkmMultiTarget) await Unleash(); return await Rotation(); } public static async Task<bool> Rotation() { if (Managers.HotkeyManager.IsKeyDown(System.Windows.Forms.Keys.LShiftKey)) { await PullSingle(); } else { await PullMultiple(); } await Unleash(); await Plunge(); await Darkside(); await DotRotation(); await FinishedRotation(); if (Managers.HotkeyManager.IsKeyDown(System.Windows.Forms.Keys.LShiftKey)) { await EnmityRotation(); } else { await DPSRotation(); } await OffGcdRotation(); await MPGeneratorRotation(); return false; } public static async Task<bool> Darkside() { await Spell.NoneGcdCast("Darkside", Me, () => !Me.HasAura("Darkside") && Me.CurrentManaPercent > 90); return false; } public static async Task<bool> DPSRotation() { await DarkArts(); await Spell.CastSpell("Syphon Strike", () => Actionmanager.LastSpell.Name == "Hard Slash"); await Spell.CastSpell("Hard Slash", () => true); return false; } // We always want to finished out combo. public static async Task<bool> FinishedRotation() { await DarkArts(); await Spell.CastSpell("Souleater", () => Actionmanager.LastSpell.Name == "Syphon Strike" && Me.CurrentTarget.HasAura("Delirium", true, 4000) && ((Me.CurrentHealthPercent < 70 && Me.HasAura("Grit")) || Me.HasAura("Dark Arts"))); await Spell.CastSpell("Delirium", () => Actionmanager.LastSpell.Name == "Syphon Strike"); await Spell.CastSpell("Power Slash", () => Actionmanager.LastSpell.Name == "Spinning Slash"); return false; } public static async Task<bool> DarkArts() { await Spell.NoneGcdCast("Dark Arts", Me, () => Actionmanager.LastSpell.Name == "Syphon Strike" && Me.CurrentManaPercent > 90 && Me.CurrentTarget.HasAura("Delirium", true, 4000)); return false; } public static async Task<bool> Unleash() { if (NearbyEnemyUnits(5) - NearbyEnemyUnitsTargettingMe(5) > 1) { await Spell.ApplyCast("Unleash", Me, () => Actionmanager.LastSpell.Name != "Syphon Strike" && Actionmanager.LastSpell.Name != "Hard Slash" && Actionmanager.LastSpell.Name != "Spinning Slash"); } return false; } static bool triggerPlunge = false; public static async Task<bool> Plunge() { if (triggerPlunge && Actionmanager.CanCast("Plunge", Me.CurrentTarget)) { await Spell.NoneGcdCast("Plunge", Me.CurrentTarget, () => true); triggerPlunge = false; } return false; } public static async Task<bool> PullSingle() { if (Actionmanager.CanCast("Unmend", Me.CurrentTarget) && Me.CurrentTarget.Distance(Me) > 10) { await Spell.CastSpell("Unmend", () => true); triggerPlunge = true; } return false; } public static async Task<bool> PullMultiple() { if (Actionmanager.CanCast("Plunge", Me.CurrentTarget) && Me.CurrentTarget.Distance(Me) > 10) { await Spell.NoneGcdCast("Plunge", Me.CurrentTarget, () => true); } return false; } public static async Task<bool> DotRotation() { await Spell.ApplyCast("Scourge", Me.CurrentTarget, () => !Me.CurrentTarget.HasAura("Scourge", true, 4000) && Actionmanager.LastSpell.Name != "Syphon Strike" && Actionmanager.LastSpell.Name != "Hard Slash" && Actionmanager.LastSpell.Name != "Spinning Slash"); return false; } // Currently without a way to detect enmity, we will use hotkey to trigger this. public static async Task<bool> EnmityRotation() { await Spell.CastSpell("Spinning Slash", () => Actionmanager.LastSpell.Name == "Hard Slash"); await Spell.CastSpell("Hard Slash", () => true); return false; } public static async Task<bool> OffGcdRotation() { // Offensive await Spell.CastLocation("Salted Earth", Me.CurrentTarget, true); await Spell.NoneGcdCast("Reprisal", Me.CurrentTarget, () => true); await Spell.NoneGcdCast("Low Blow", Me.CurrentTarget, () => true); // Need to solve this problem for an increase in dps. // Leaving it like this allow it to be much more flexible. //await Spell.NoneGcdCast("Plunge", Me.CurrentTarget, () => Me.CurrentTarget.Distance(Me) > 10); // Defensive await Spell.NoneGcdCast("Dark Dance", Me, () => true); return false; } public static async Task<bool> MPGeneratorRotation() { await Spell.NoneGcdCast("Blood Weapon", Me, () => Me.CurrentManaPercent < 90 && Me.CurrentTarget.Distance(Me) < 3); await Spell.NoneGcdCast("Blood Price", Me, () => Me.CurrentManaPercent < 70 && Me.CurrentTarget.Distance(Me) < 3); await Spell.NoneGcdCast("Carve and Spit", Me, () => !Me.HasAura("Dark Arts") && Me.CurrentManaPercent < 70 && Me.CurrentTarget.Distance(Me) < 3); await Spell.NoneGcdCast("Sole Survivor", Me.CurrentTarget, () => (Me.CurrentManaPercent < 70 || Me.CurrentHealthPercent < 70) && Me.CurrentTarget.Distance(Me) < 3 && Me.CurrentTarget.CurrentHealth < 5000); return false; } public static int NearbyEnemyUnits(int range) { return GameObjectManager.GetObjectsOfType<BattleCharacter>(true) .Where(unit => !IsAboveTheGround(unit) && unit.Distance2D(Core.Player) <= range && unit.CanAttack && unit.IsTargetable && !unit.IsDead) .OrderBy(unit => unit.Distance2D()).ToList().Count(); } public static int NearbyEnemyUnitsTargettingMe(int range) { return GameObjectManager.GetObjectsOfType<BattleCharacter>(true) .Where(unit => !IsAboveTheGround(unit) && unit.Distance2D(Core.Player) <= range && unit.CanAttack && unit.IsTargetable && !unit.IsDead && unit.TargetCharacter == Core.Player) .OrderBy(unit => unit.Distance2D()).ToList().Count(); } public static bool IsAboveTheGround(GameObject u) { var height = u.Z - Core.Player.Z; return height > System.Math.Max(Core.Player.CombatReach - 0.1f + u.CombatReach, 2.5f); } #endregion } }
Not sure if this was aimed at me, but I tried it on multiple jobs/classes, including WAR and MRD most recently. I'm not looking for a "finished, 100%" routine. I really enjoy the ability to customize and make it my own rotation. I want to find what works best with how the routine works, and be able to give that rotation back to the community, or work with another person(s) to make it better. I'm not looking for an already complete and functional CR, I'm aware of the project status so far and I see how the community has been working together to make it something. I just wanted to try and join that.
In this new Dark Knight routine, you will have to change Root.cs TO Code: // By HeinzSkies using System.Threading.Tasks; using System.Collections.Generic; using System.Windows.Media; using ff14bot; using ff14bot.Enums; using ff14bot.Managers; using ff14bot.Objects; using ff14bot.Helpers; using YourRaidingBuddy.Helpers; using YourRaidingBuddy.Settings; using YourRaidingBuddy.Books; using System.Windows.Forms; using System.Linq; using YourRaidingBuddy.Interfaces.Settings; namespace YourRaidingBuddy.Rotations { public class DarkKnight : Root { private static LocalPlayer Me { get { return Core.Player; } } //Core.Player.CurrentTarget as BattleCharacter public override ClassJobType[] Class { get { return new[] { ClassJobType.DarkKnight }; } } public override void OnInitialize() { ; } #region NewRotation public static async Task<bool> AutoMode() { if (!Me.CurrentTarget.IsViable()) return false; return await Rotation(); } public static async Task<bool> HotkeyMode() { if (!Me.CurrentTarget.IsViable()) return false; return await Rotation(); } public static async Task<bool> Rotation() { if (Managers.HotkeyManager.IsKeyDown(System.Windows.Forms.Keys.LShiftKey)) { await PullSingle(); } else { await PullMultiple(); } await Aggro(); await Plunge(); await Darkside(); await DotRotation(); await FinishedRotation(); if (Managers.HotkeyManager.IsKeyDown(System.Windows.Forms.Keys.LShiftKey)) { await EnmityRotation(); } else { await DPSRotation(); } await OffGcdRotation(); await MPGeneratorRotation(); return false; } public static async Task<bool> Darkside() { await Spell.NoneGcdCast("Darkside", Me, () => !Me.HasAura("Darkside") && Me.CurrentManaPercent > 90); return false; } public static async Task<bool> DPSRotation() { await DarkArts(); await Spell.CastSpell("Syphon Strike", () => Actionmanager.LastSpell.Name == "Hard Slash"); await Spell.CastSpell("Hard Slash", () => true); return false; } // We always want to finished out combo. public static async Task<bool> FinishedRotation() { await DarkArts(); await Spell.CastSpell("Souleater", () => Actionmanager.LastSpell.Name == "Syphon Strike" && ((Me.CurrentTarget.HasAura("Delirium", true, 4000) && (Me.CurrentHealthPercent < 70 && Me.HasAura("Grit"))) || Me.HasAura("Dark Arts"))); await Spell.ApplyCast("Delirium", Me.CurrentTarget, () => Actionmanager.LastSpell.Name == "Syphon Strike"); await Spell.CastSpell("Power Slash", () => Actionmanager.LastSpell.Name == "Spinning Slash"); return false; } public static async Task<bool> DarkArts() { await Spell.NoneGcdCast("Dark Arts", Me, () => Actionmanager.LastSpell.Name == "Syphon Strike" && Me.CurrentManaPercent > 90 && Me.CurrentTarget.HasAura("Delirium", true, 4000)); return false; } public static async Task<bool> Aggro() { if (NearbyEnemyUnits(5) - NearbyEnemyUnitsTargettingMe(5) > 1) { await Spell.CastSpell("Unleash", Me, () => Actionmanager.LastSpell.Name != "Syphon Strike" && Actionmanager.LastSpell.Name != "Hard Slash" && Actionmanager.LastSpell.Name != "Spinning Slash"); } else if (NearbyEnemyUnits(15) - NearbyEnemyUnitsTargettingMe(15) > 0) { var target = NearbyEnemyUnitsNotTargettingMe(15); if (target != null) { await Spell.CastSpell("Unmend", target, () => Actionmanager.LastSpell.Name != "Syphon Strike" && Actionmanager.LastSpell.Name != "Hard Slash" && Actionmanager.LastSpell.Name != "Spinning Slash"); } } return false; } static bool triggerPlunge = false; public static async Task<bool> Plunge() { if (triggerPlunge && Actionmanager.CanCast("Plunge", Me.CurrentTarget)) { await Spell.NoneGcdCast("Plunge", Me.CurrentTarget, () => true); triggerPlunge = false; } return false; } public static async Task<bool> PullSingle() { if (Actionmanager.CanCast("Unmend", Me.CurrentTarget) && Me.CurrentTarget.Distance(Me) > 10) { await Spell.CastSpell("Unmend", () => true); triggerPlunge = true; } return false; } public static async Task<bool> PullMultiple() { if (Actionmanager.CanCast("Plunge", Me.CurrentTarget) && Me.CurrentTarget.Distance(Me) > 10) { await Spell.NoneGcdCast("Plunge", Me.CurrentTarget, () => true); } return false; } public static async Task<bool> DotRotation() { await Spell.ApplyCast("Scourge", Me.CurrentTarget, () => !Me.CurrentTarget.HasAura("Scourge", true, 4000) && Actionmanager.LastSpell.Name != "Syphon Strike" && Actionmanager.LastSpell.Name != "Hard Slash" && Actionmanager.LastSpell.Name != "Spinning Slash"); return false; } // Currently without a way to detect enmity, we will use hotkey to trigger this. public static async Task<bool> EnmityRotation() { await Spell.CastSpell("Spinning Slash", () => Actionmanager.LastSpell.Name == "Hard Slash"); await Spell.CastSpell("Hard Slash", () => true); return false; } public static async Task<bool> OffGcdRotation() { // Offensive await Spell.CastLocation("Salted Earth", Me.CurrentTarget, true); await Spell.NoneGcdCast("Reprisal", Me.CurrentTarget, () => true); await Spell.NoneGcdCast("Low Blow", Me.CurrentTarget, () => true); // Need to solve this problem for an increase in dps. // Leaving it like this allow it to be much more flexible. //await Spell.NoneGcdCast("Plunge", Me.CurrentTarget, () => Me.CurrentTarget.Distance(Me) > 10); // Defensive await Spell.NoneGcdCast("Dark Dance", Me, () => Me.CurrentTarget.Distance(Me) < 3); return false; } public static async Task<bool> MPGeneratorRotation() { await Spell.NoneGcdCast("Blood Weapon", Me, () => Me.CurrentManaPercent < 90 && Me.CurrentTarget.Distance(Me) < 3); await Spell.NoneGcdCast("Blood Price", Me, () => Me.CurrentManaPercent < 70 && Me.CurrentTarget.Distance(Me) < 3); await Spell.NoneGcdCast("Carve and Spit", Me, () => !Me.HasAura("Dark Arts") && Me.CurrentManaPercent < 70 && Me.CurrentTarget.Distance(Me) < 3); await Spell.NoneGcdCast("Sole Survivor", Me.CurrentTarget, () => (Me.CurrentManaPercent < 70 || Me.CurrentHealthPercent < 70) && Me.CurrentTarget.Distance(Me) < 3 && Me.CurrentTarget.CurrentHealth < 5000); return false; } public static int NearbyEnemyUnits(int range) { return GameObjectManager.GetObjectsOfType<BattleCharacter>(true) .Where(unit => !IsAboveTheGround(unit) && unit.Distance2D(Core.Player) <= range && unit.CanAttack && unit.IsTargetable && !unit.IsDead) .OrderBy(unit => unit.Distance2D()).ToList().Count(); } public static int NearbyEnemyUnitsTargettingMe(int range) { return GameObjectManager.GetObjectsOfType<BattleCharacter>(true) .Where(unit => !IsAboveTheGround(unit) && unit.Distance2D(Core.Player) <= range && unit.CanAttack && unit.IsTargetable && !unit.IsDead && unit.TargetCharacter == Core.Player) .OrderBy(unit => unit.Distance2D()).ToList().Count(); } public static BattleCharacter NearbyEnemyUnitsNotTargettingMe(int range) { return GameObjectManager.GetObjectsOfType<BattleCharacter>(true) .Where(unit => !IsAboveTheGround(unit) && unit.Distance2D(Core.Player) <= range && unit.CanAttack && unit.IsTargetable && !unit.IsDead && unit.TargetCharacter != Core.Player) .OrderBy(unit => unit.Distance2D()).FirstOrDefault(); } public static bool IsAboveTheGround(GameObject u) { var height = u.Z - Core.Player.Z; return height > System.Math.Max(Core.Player.CombatReach - 0.1f + u.CombatReach, 2.5f); } #endregion } }
Is it possible to make it check for a time left on a DoT instead of it checking for if it's there or not? Trying to make it work with Iron Jaws for Bard but I can't figure out how to go about it.
Somebody already trying to get BLM working? I'm still not sure about the new rotations in Heavensward
I am going to take a swing at blm soon. Just Polishing up warrior atm untill i level blm from 50-60 might take a bit
@Tichy took it down to update it. Updated Ninja CR (Most Credit goes to Xcesius ) Changes: Added Spells: Dream Within a Dream = Will only be casted if Vulnerability UP no idea if this is a DPS increase or not but will keep it like this for now. Duality = Will be casted only with Aeolien Edge Armor Crush = Will be casted if Huton drops below 25 Sec. Keep a eye on the timer and move to flank when you see it drop below huton so you can get the extra dmg. Assassinate = Added it. Invigorate = Will be used if you fall below 550TP. Change Log: Buffs will only be used if the mob has 8k+ hp (Theses numbers may need to be changed we will have to see.) Dots will only be used if the mob has 3k+hp (This means it will not use dots or buffs on dummy's you can change the value to 0 if you wish to test your dps on the dummys.) Re-added Kassatsu for those who wish it to auto cast. Added Emergency Armor Crush Cast = Just hold down Left Shift and it Will stop everything except for Off GCD and do the armor Crush rotation to refresh huton. Comming Up: Finding a way to optimize Armor Crush Adding AoE Adding Auto Goad Adding Second Wind Code: using System; using System.Linq; using System.Threading.Tasks; using System.Windows.Media; using Buddy.Coroutines; using ff14bot; using ff14bot.Enums; using ff14bot.Helpers; using ff14bot.Managers; using ff14bot.Objects; using YourRaidingBuddy.Helpers; using YourRaidingBuddy.Settings; using TreeSharp; using System.Collections.Generic; using YourRaidingBuddy.Books; using YourRaidingBuddy.Interfaces.Settings; namespace YourRaidingBuddy.Rotations { public class Ninja : Root { private static LocalPlayer Me { get { return Core.Player; } } //Core.Player.CurrentTarget as BattleCharacter public override ClassJobType[] Class { get { return new[] { ClassJobType.Ninja, ClassJobType.Rogue }; } } private const int MobHp = 3000; private const int BuffHp = 8000; public override void OnInitialize() { ; } #region NewRotation public static async Task<bool> AutoMode() { if (!Me.CurrentTarget.IsViable()) return false; return await NinjaRotation(); } public static async Task<bool> HotkeyMode() { if (!Me.CurrentTarget.IsViable()) return false; // if (VariableBook.HkmMultiTarget) await NinjaAoE(); return await NinjaRotation(); } public static async Task<bool> NinjaRotation() { if (Managers.HotkeyManager.IsKeyDown(System.Windows.Forms.Keys.LShiftKey)) { await EmergHuton(); } await DoNinjutsu(); //await HutonRefresh(); await DancingEdge(); await Shadow(); await SingleTarget(); await NoneGCD(); return false; } public static async Task<bool> EmergHuton() { await Spell.CastSpell("Armor Crush", () => Actionmanager.LastSpell.Name == "Gust Slash"); await Spell.CastSpell("Gust Slash", () => Actionmanager.LastSpell.Name == "Spinning Edge"); await Spell.CastSpell("Spinning Edge", () => true); return false; } public static async Task<bool> HutonRefresh() { if(!Me.HasAura("Duality") && !Core.Me.HasAura("Huton", true, 24000) && Actionmanager.LastSpell.Name == "Gust Slash") { return await Spell.CastSpell("Armor Crush", () => true); } return false; } public static async Task<bool> DancingEdge() { if(!Me.HasAura("Duality") && !Me.CurrentTarget.HasAura("Dancing Edge", true, 4000) && !Me.CurrentTarget.HasAura("Dancing Edge", false, 4000) && !Me.CurrentTarget.HasAura("Storm's Eye", false) && Actionmanager.LastSpell.Name == "Gust Slash") { return await Spell.CastSpell("Dancing Edge", () => true); } return false; } public static async Task<bool> Shadow() { if((!Me.CurrentTarget.HasAura("Shadow Fang", true, 4000) || !Me.CurrentTarget.HasAura("Shadow Fang", true)) && Me.CurrentTarget.HasAura("Dancing Edge", true) && Actionmanager.LastSpell.Name == "Spinning Edge" && Core.Me.CurrentTarget.CurrentHealth >= MobHp) { return await Spell.CastSpell("Shadow Fang", () => true); } return false; } public static async Task<bool> SingleTarget() { await Spell.CastSpell("Aeolian Edge", () => Me.HasAura("Duality") || Actionmanager.LastSpell.Name == "Gust Slash"); await Spell.CastSpell("Gust Slash", () => Actionmanager.LastSpell.Name == "Spinning Edge"); await Spell.CastSpell("Mutilate", () => Me.CurrentTarget.HasAura(AuraBook.ShadowFang) && (!Me.CurrentTarget.HasAura(AuraBook.Mutilate, true, 4000) || !Me.CurrentTarget.HasAura(AuraBook.Mutilate)) && Core.Me.CurrentTarget.CurrentHealth >= MobHp); await Spell.CastSpell("Spinning Edge", () => true); return false; } public static async Task<bool> NoneGCD() { await Spell.NoneGcdCast("Trick Attack", Me.CurrentTarget, () => Me.HasAura(AuraBook.Suiton) && Me.CurrentTarget.IsBehind); await Spell.NoneGcdCast("Internal Release", Me, () => !Me.HasAura(AuraBook.InternalRelease) && Core.Me.CurrentTarget.CurrentHealth >= BuffHp); await Spell.NoneGcdCast("Blood for Blood", Me, () => !Me.HasAura("Blood for Blood") && Core.Me.CurrentTarget.CurrentHealth >= BuffHp); await Spell.NoneGcdCast("Invigorate", Me, () => Me.CurrentTP < 550); await Spell.NoneGcdCast("Jugulate", Me.CurrentTarget, () => Me.CurrentTarget.HasAura(AuraBook.Mutilate)); await Spell.NoneGcdCast("Mug", Me.CurrentTarget, () => Me.CurrentTarget.HasAura(AuraBook.ShadowFang)); await Spell.NoneGcdCast("Duality", Me, () => Actionmanager.LastSpell.Name == "Gust Slash" && Me.CurrentTarget.HasAura(AuraBook.ShadowFang, true, 5000) && Me.CurrentTarget.HasAura(AuraBook.DancingEdge, true, 5000)); await Spell.NoneGcdCast("Dream Within a Dream", Me.CurrentTarget, () => Me.CurrentTarget.HasAura("Vulnerability Up")); await Spell.NoneGcdCast("Assassinate", Me.CurrentTarget, () => true); return false; } #endregion #region Ninjatsu Copied From Kupo Credits Masta private static bool HasBleedingDebuff() { return Me.CurrentTarget.HasAura("Storm's Eye", false, 2000) || Me.CurrentTarget.HasAura("Dancing Edge"); } private static readonly SpellData Jin = DataManager.GetSpellData(2263); private static readonly SpellData Chi = DataManager.GetSpellData(2261); private static readonly SpellData Ten = DataManager.GetSpellData(2259); private static readonly SpellData Ninjutsu = DataManager.GetSpellData(2260); private static readonly SpellData Jugulate = DataManager.GetSpellData(2251); private static readonly SpellData Kassatsu = DataManager.GetSpellData(2264); private static readonly SpellData Trick_Attack = DataManager.GetSpellData(2258); private static readonly SpellData Sneak_Attack = DataManager.GetSpellData(2250); public static HashSet<uint> OverrideBackstabIds = new HashSet<uint>() { 3240//Cloud of darkness }; private const int HutonRecast = 8000; internal static async Task<bool> DoNinjutsu() { //Exit early if player was inputting something if (Core.Player.HasAura("Mudra")) return true; if (Actionmanager.CanCastOrQueue(Jin, null)) { if (!Core.Player.HasAura("Huton", true, HutonRecast)) { Logger.Write("YourRaidingBuddy Casting " + "Huton" + "Chi Combo!"); await CastHuton(); return false; } var curTarget = Core.Target as BattleCharacter; if (curTarget == null) return false; // if (curTarget.TimeToDeath() <= 3) // return false; //Suiton var taCD = Trick_Attack.Cooldown; //We can start casting suiton before trick attack is ready cause its going to take some time if (taCD.TotalMilliseconds <= 1300) { if (!await CastSuiton()) return false; if (!(Kassatsu.Cooldown.TotalMilliseconds <= 0) || !Core.Player.HasTarget) return false; if (await Coroutine.Wait(2000, () => Actionmanager.DoAction(Kassatsu, null) && Me.CurrentTarget.HasAura("Shadow Fang") && Me.CurrentTarget.HasAura(492))) { Logger.Write("YourRaidingBuddy Casting " + "Raiton"); if (Me.CurrentTarget.HasAura(492)) await CastRaiton(); } return false; } if (taCD.TotalSeconds >= 5) { await CastRaiton(); } return false; } if (Actionmanager.CanCastOrQueue(Chi, null) && Me.CurrentTarget.HasAura("Shadow Fang")) { Logger.Write("YourRaidingBuddy Casting " + "Raiton"); await CastRaiton(); return false; } if (Actionmanager.CanCastOrQueue(Ten, null)) { Logger.Write("YourRaidingBuddy Casting " + "Ten" + "Ninjutsu!"); { await Coroutine.Wait(2000, () => Actionmanager.DoAction(Ten, null)); await CastNinjutsu(); return false; } } return false; } private static async Task CastHuton() { if (await Coroutine.Wait(2000, () => Actionmanager.DoAction(Jin, null))) { if (await Coroutine.Wait(2000, () => Actionmanager.DoAction(Chi, null))) { if (await Coroutine.Wait(2000, () => Actionmanager.DoAction(Ten, null))) { await CastNinjutsu(); } } } } private static async Task<bool> CastRaiton() { if (!await Coroutine.Wait(2000, () => Actionmanager.DoAction(Ten, null))) return false; if (await Coroutine.Wait(2000, () => Actionmanager.DoAction(Chi, null))) { return await CastNinjutsu(); } return false; } private static async Task<bool> CastSuiton() { if (!await Coroutine.Wait(2000, () => Actionmanager.DoAction(Ten, null))) return false; if (!await Coroutine.Wait(2000, () => Actionmanager.DoAction(Chi, null))) return false; if (!await Coroutine.Wait(2000, () => Actionmanager.DoAction(Jin, null))) return false; if (await CastNinjutsu()) { return await Coroutine.Wait(2000, () => Core.Player.HasAura("Suiton")); } return false; } private static async Task<bool> CastNinjutsu() { if (await Coroutine.Wait(2000, () => Core.Player.HasAura("Mudra"))) { bool possibly = false; while (Core.Player.HasAura("Mudra")) { if (Core.Player.HasTarget) { if (Actionmanager.DoAction(Ninjutsu, Core.Target)) { possibly = true; } } if (!Core.Player.InCombat) return false; await Coroutine.Yield(); } await Coroutine.Wait(2000, () => Ninjutsu.Cooldown.TotalSeconds > 10); return possibly; } return false; } #endregion } }
I have a new version for DRK up coming. It takes some ideas from wolfrain62. So it won't apply dots if the target is 3000 or less hp (guess that is the sweet spot? need to adjust around.) It will also use Dark Arts if your mana is >50% on Enmity Rotation for Power Slash also. (Because you want a lot of Enmity when you use that combo right?) Need Xcesius to update the Routine to a new version before I can release this one.
Hello, Anyone else having their Routines stop working entirely after hitting the Stop button? After hitting the Start button again the Routine will not start. The only way to make it start up again is to switch to another Routine and switch back again to YourRaidingBuddy. I checked the log but there are no error messages.
may want to change the MobHP and BuffHP around accidentally swapped those numbers. Updated the code to reflect the fix. Also reduced the clip time of dancing edge from 6 to 4 sec.
New update out --> Added test Summoner rotation (Still not completed fully) Added Warrior Rotation //Credits stewiethecat Added updated Darkknight Rotation //Credits heinzkies Added updated Ninja Rotation //Credits Wolfrain62 Resolved an issue with StopBehaviors