#region ChangeLogs
/*
* v1.0 December 7th, 2013
* - Initial build
*
* v1.1 December 8th, 2013
* - Fix: Trying to find non existant party member.
* - Fix: Change the ground casting to the latest.
* - Performance: Added an update timer
*
* v1.2
* - Function: Lower level AoE rotations
*
* v1.3
* - Fix: Ground target trying to attack when there's no enemy selected.
* - Fix: Readjust priorities. Straight shot keeps getting superseeded by ballads.
* - Change: Separate the ballad switches into Mage, Army, Foe. Not much use of Foe when there's no BLM.
*
* v1.4
* - Change: Party member in another map is considered null as well. Change the error message to reflect that.
* - Change: Change attack pattern behaviour. Previous: Cast whatever is in the priority. Current: AoE until TP threshold then do single until TP recover.
* - Function: Detect if you're currently moving. Don't try to ballad when you're moving.
*
* Known error:
* - Red error message when trying to attack.
* Possible cause: Trying to cast skill on a dead enemy.
* Note: The way the bot work(I think) is it queue/spam the next attack. So there's an attack in the queue but no target. Need to find how to flush the queue.
* - Trying to cast ballad twice.
* Possible cause: Previous attempt at casting the ballad was interrupted.
* Note: The interrupted spell was interrupted so the bot tried to cast it again while the old one is still in the queue. Added a function to detect movement to minimize the happening but, still, needs to find out how to flush the queue.
*
* ToDo:
* - Party member error.
* - Retrieve variable values from external file.
* - UI.
* - On the fly changes to variables.
*
*/
#endregion
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Windows.Forms;
using ff14bot;
using ff14bot.Behavior;
using ff14bot.Enums;
using ff14bot.Helpers;
using ff14bot.Managers;
using ff14bot.Navigation;
using ff14bot.Objects;
using TreeSharp;
using Action = TreeSharp.Action;
namespace Kupo.Rotations
{
public class PugilistMonk : KupoRoutine
{
// Variables Start
// Diagnostic purposes
private static double m_checkTimer = 100; // Check party status every n miliseconds.
// AoE
private static bool m_useAOE = false; // Set to false to only use single target.
private static int m_AOERange = 5; // Radius to check for other enemy.
private static int m_AOEEnemy = 1; // How many other enemy before running the AoE rotation.
private static int m_AOETP = 30; // In percent. Stop using the AoE rotation when our TP is lower than how many.
private static bool m_useGroundSpell = false; // Set to false to not use any ground spells. Need to set separate from m_useAOE.
private static bool m_useRainofDeath = false; // Set to false to not use Rain of Death(10% damage reduction). Need to set separate from m_useAOE.
// Caveat: While separate from m_useAOE. It also control the AoE behaviour.
// If m_useRainofDeath set to false. You will only do Wide Volley, if you have it, or Quick Nock.
// Might be useful since Rain of Death cost 200TP
// Helper variables. Don't change.
private bool m_isMoving = false;
private Vector3 m_oldLocation = Core.Player.Location;
private DateTime m_startTime = DateTime.UtcNow;
// Helper variables end
private Composite CastGroundSpell(string spell, Selection<Vector3> onLocation, Selection<bool> reqs = null, int msLeft = 0, bool ignoreCanCast = false)
{
return
new Decorator(
ret =>
{
if (reqs != null && !reqs(ret)) return false;
if (!ignoreCanCast && !Actionmanager.CanCast(spell, Core.Player.CurrentTarget)) return false;
if (Extensions.DoubleCastPreventionDict.Contains(Core.Player.CurrentTarget, spell)) return false;
if (!Core.Player.HasAura(spell, true, msLeft)) return true;
return true;
},
new Action(
ret =>
{
var castingSpell = Core.Player.SpellCastInfo;
if (castingSpell != null && castingSpell.SpellData.Name != spell) Actionmanager.StopCasting();
Logging.Write("Casting Ground Spell " + spell + " at " + onLocation(ret));
if (Actionmanager.DoActionLocation(spell, onLocation(ret)))
{
Extensions.UpdateDoubleCastDict(spell, Core.Player.CurrentTarget);
}
}));
}
public override int PullRange
{
get { return 20; }
}
public override ClassJobType[] Class
{
get { return new ClassJobType[] { ClassJobType.Pugilist, ClassJobType.Monk, }; }
}
protected override Composite CreatePreCombatBuffs()
{
return SummonChocobo();
}
protected override Composite CreateRest()
{
return DefaultRestBehavior(r => Core.Player.CurrentTPPercent);
}
protected override Composite CreatePull()
{
return new PrioritySelector(
r => Actionmanager.InSpellInRangeLOS("Perfect Balance", Core.Target),
new Decorator(r => (r as SpellRangeCheck?) == SpellRangeCheck.ErrorNotInRange, new Action(r => Navigator.MoveTo(Core.Target.Location))),
Cast("Perfect Balance", r => (r as SpellRangeCheck?) == SpellRangeCheck.Success || (r as SpellRangeCheck?) == SpellRangeCheck.ErrorNotInFront)
);
}
protected override Composite CreateCombatBuffs()
{
return new PrioritySelector(
);
}
protected override Composite CreateCombat()
{
return new PrioritySelector(
Cast("Internal Release", r => Actionmanager.LastSpell.Name == "Bootshine", r => Core.Player),
Cast("Blood for Blood", r => Actionmanager.LastSpell.Name == "Dragon Kick", r => Core.Player),
Cast("Featherfoot", r => Core.Player.CurrentHealthPercent < 50, r => Core.Player),
Cast("Mantra", r => Core.Player.CurrentHealthPercent < 50, r => Core.Player),
Cast("Bloodbath", r => Core.Player.CurrentHealthPercent < 50, r => Core.Player),
Cast("Foresight", r => Core.Player.CurrentHealthPercent < 50, r => Core.Player),
Cast("Second Wind", r => Core.Player.CurrentHealthPercent < 80, r => Core.Player),
Cast("Invigorate", r => Core.Player.CurrentTPPercent < 50, r => Core.Player),
Cast("Snap Punch", r => Core.Player.HasMyAura("Perfect Balance"),
Cast("Snap Punch", r => Core.Player.HasMyAura("Perfect Balance"),
Cast("Snap Punch", r => Core.Player.HasMyAura("Perfect Balance"),
Cast("Perfect Balance", r => !Core.Player.HasMyAura("Perfect Balance"), r =>Core.Player)
);
}
}
}