using System;using System.Collections.Generic;
using System.Linq;
using Styx;
using Styx.CommonBot;
using Styx.CommonBot.Routines;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using Action = Styx.TreeSharp.Action;
namespace Armed
{
internal class Afflicted : CombatRoutine
{
#region Generic Wrapper Stuff
private Composite _buffs;
private Composite _combat;
public override string Name { get { return "Afflicted"; } }
public override WoWClass Class { get { return WoWClass.Warlock; } }
public override Composite CombatBehavior
{
get { return _combat ?? (_combat = CreateCombat()); }
}
private WoWUnit GetTargetMissingDebuff(WoWUnit near, string debuff, float distance = -1f)
{
return UnfriendlyUnits.FirstOrDefault(u => u.Location.Distance(near.Location) <= distance && !u.HasAura(debuff, 1, true));
}
private int EnemiesNearTarget(float range)
{
var target = StyxWoW.Me.CurrentTarget;
if (target == null)
return 0;
var tarLoc = target.Location;
return UnfriendlyUnits.Count(u => u.Guid != target.Guid && u.Location.Distance(tarLoc) <= range);
}
private IEnumerable<WoWUnit> UnfriendlyUnits
{
get
{
return
ObjectManager.GetObjectsOfType<WoWUnit>(true, false).Where(u => !u.IsDead && u.CanSelect && u.Attackable && !u.IsFriendly);
}
}
private void UseTrinkets()
{
WoWItem firstTrinket = StyxWoW.Me.Inventory.Equipped.Trinket1;
WoWItem secondTrinket = StyxWoW.Me.Inventory.Equipped.Trinket2;
if (firstTrinket != null && CanUseEquippedItem(firstTrinket))
firstTrinket.Use();
if (secondTrinket != null && CanUseEquippedItem(secondTrinket))
secondTrinket.Use();
}
private static bool CanUseEquippedItem(WoWItem item)
{
// Check for engineering tinkers!
var itemSpell = Lua.GetReturnVal<string>("return GetItemSpell(" + item.Entry + ")", 0);
if (string.IsNullOrEmpty(itemSpell))
return false;
return item.Usable && item.Cooldown <= 0;
}
private Composite Cast(string spell, Selection<bool> reqs = null, Selection<WoWUnit> onTarget = null)
{
return
new Decorator(
ret => ((reqs != null && reqs(ret)) || (reqs == null)) && SpellManager.CanCast(spell),
new Action(ret => SpellManager.Cast(spell, (onTarget != null ? onTarget(ret) : null))));
}
private Composite Debuff(string spell, Selection<bool> reqs = null, Selection<WoWUnit> onTarget = null, int msLeft = 0)
{
return
new Decorator(
ret => ((reqs != null && reqs(ret)) || (reqs == null)) && SpellManager.CanCast(spell) && !(onTarget != null ? onTarget(ret) : StyxWoW.Me.CurrentTarget).HasAura(spell, 0, true, msLeft),
new Action(ret => SpellManager.Cast(spell, (onTarget != null ? onTarget(ret) : null))));
}
public static TimeSpan GetSpellCooldown(string spell)
{
SpellFindResults results;
if (SpellManager.FindSpell(spell, out results))
{
if (results.Override != null)
return results.Override.CooldownTimeLeft;
return results.Original.CooldownTimeLeft;
}
return TimeSpan.MaxValue;
}
private delegate T Selection<out T>(object context);
#endregion
#region Actual Logic
public Composite CreateCombat()
{
return new PrioritySelector(
// Free haste. Use it on CD.
Cast("Dark Soul: Misery"),
CreateAoeCombat(),
// Debuff CoE, refresh when <= 1500ms left on the debuff.
Debuff("Curse of the Elements", msLeft:1500),
Debuff("Haunt", msLeft:2000),
Debuff("Agony", msLeft:1500),
Debuff("Corruption", msLeft:1500),
Debuff("Unstable Affliction", msLeft:1500),
new Decorator(ret=>!StyxWoW.Me.IsMoving,
new PrioritySelector(
Cast("Drain Soul", ret=>StyxWoW.Me.CurrentTarget.HealthPercent < 20),
Cast("Malefic Grasp")
)),
Cast("Fel Flame", ret=>!StyxWoW.Me.IsChanneling)
);
}
public Composite CreateAoeCombat()
{
// More than 4 mobs near our current target, start the AOE rotation.
return new Decorator(ret => EnemiesNearTarget(15) >= 4,
new PrioritySelector(
Cast("Soulburn", ret=>!StyxWoW.Me.HasAura("Soulburn")),
Cast("Curse of the Elements", null, ret => GetTargetMissingDebuff(StyxWoW.Me.CurrentTarget, "Curse of the Elements", 15f)),
Cast("Seed of Corruption")
));
}
#endregion
}
public static class Extensions
{
public static bool HasAura(this WoWUnit unit, string aura, int stacks, bool isMyAura = false, int msLeft = 0)
{
var result = unit.GetAuraByName(aura);
if (result == null)
return false;
if (isMyAura && result.CreatorGuid != StyxWoW.Me.Guid)
return false;
if (result.TimeLeft.TotalMilliseconds > msLeft)
return result.StackCount >= stacks;
return false;
}
}
}