using Loki.Bot;
using Loki.Bot.Logic.Behaviors;
using Loki.Game;
using Loki.Game.GameData;
using Loki.Game.Inventory;
using Loki.Game.Objects;
using Loki.TreeSharp;
using Loki.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Action = Loki.TreeSharp.Action;
namespace SpecThrow_FireTrap
{
public partial class BETArnd : CombatRoutine
{
#region Flask Logic
private readonly WaitTimer _flaskCd = new WaitTimer(TimeSpan.FromSeconds(0.5));
private IEnumerable<InventoryItem> LifeFlasks
{
get
{
IEnumerable<InventoryItem> inv = EntityManager.Me.Inventory.Flasks.Items;
return from item in inv
let flask = item.Flask
where flask != null && flask.HealthRecover > 0 && flask.CanUse
orderby flask.IsInstantRecovery ? flask.HealthRecover : flask.HealthRecoveredPerSecond descending
select item;
}
}
private IEnumerable<InventoryItem> ManaFlasks
{
get
{
IEnumerable<InventoryItem> inv = EntityManager.Me.Inventory.Flasks.Items;
return from item in inv
let flask = item.Flask
where flask != null && flask.ManaRecover > 0 && flask.CanUse
orderby flask.IsInstantRecovery ? flask.ManaRecover : flask.ManaRecoveredPerSecond descending
select item;
}
}
private IEnumerable<InventoryItem> GraniteFlasks
{
get
{
IEnumerable<InventoryItem> inv = EntityManager.Me.Inventory.Flasks.Items;
return from item in inv
let flask = item.Flask
where flask != null && item.Name == "Granite Flask" && flask.CanUse
select item;
}
}
private IEnumerable<InventoryItem> QuicksilverFlasks
{
get
{
//InternalName: flask_utility_sprint, BuffType: 24, CasterId: 13848, OwnerId: 0, TimeLeft: 00:00:05.0710000, Charges: 1, Description: You have greatly increased Movement Speed
IEnumerable<InventoryItem> inv = EntityManager.Me.Inventory.Flasks.Items;
return from item in inv
let flask = item.Flask
where flask != null && item.Name == "Quicksilver Flask" && flask.CanUse
select item;
}
}
private Composite CreateFlaskLogic()
{
return new PrioritySelector(
new Decorator(ret => _flaskCd.IsFinished && EntityManager.Me.HealthPercent < 70 && LifeFlasks.Count() != 0 && !EntityManager.Me.HasAura("flask_effect_life"),
new Action(ret =>
{
LifeFlasks.First().Use();
_flaskCd.Reset();
})),
new Decorator(ret => _flaskCd.IsFinished && EntityManager.Me.ManaPercent < 50 && ManaFlasks.Count() != 0 && !EntityManager.Me.HasAura("flask_effect_mana"),
new Action(ret =>
{
ManaFlasks.First().Use();
_flaskCd.Reset();
}))
);
}
#endregion
#region LOS/Movement
private readonly Dictionary<string, DateTime> _totemTimers = new Dictionary<string, DateTime>();
internal Composite CreateMoveIntoRange(float range)
{
//// Using some new stuff from the bot!
//return new ActionRunCoroutine(() => GetInRangeCoroutine(range));
return new Decorator(ret => BestTarget.Distance > range,
CommonBehaviors.MoveTo(ret => BestTarget.Position, ret => "CreateMoveIntoRange"));
}
internal Composite CreateMoveToLoS(Monster m)
{
return new Decorator(ret => !BestTarget.IsInRangedLineOfSight && !BestTarget.IsInLineOfSight,
CommonBehaviors.MoveTo(ret => BestTarget.Position, ret => "CreateMoveToLoS"));
}
#endregion
private bool NumberOfMobsNear(PoEObject monster, float distance, int count, bool dead = false)
{
if (monster == null)
{
return false;
}
Vector2i mpos = monster.Position;
int curCount = 0;
foreach (Monster mob in Targeting.Combat.Targets.OfType<Monster>())
{
if (mob.ID == monster.ID)
{
continue;
}
// If we're only checking for dead mobs... then... yeah...
if (dead)
{
if (!mob.IsDead)
continue;
}
else if (mob.IsDead)
continue;
if (mob.Position.Distance(mpos) < distance)
{
curCount++;
}
if (curCount >= count)
{
return true;
}
}
return false;
}
public Monster BestTarget
{
get
{
return Targeting.Combat.Targets.FirstOrDefault() as Monster;
// The stuff below was pseudocode that was not meant to be committed.
// It's some stuff to help avoid target switching.
//if (_bestTargetCached == null)
//{
// _bestTargetCached = new CachePerTick<Monster>(() =>
// {
// // So, we want to check a few small things.
// // First, if we have no ID set, set it to the first thing on the combat list
// if (_bestTargetIdCached == 0)
// {
// _bestTargetIdCached = Targeting.Combat.Targets.First().ID;
// }
// // Now, we know we have an ID set, so we can just grab the object.
// var obj = EntityManager.GetObjectById<Monster>(_bestTargetIdCached);
// if (obj == null || !obj.IsActive)
// {
// // This happens with "stale" or "dead" objects. So just reset ourselves.
// _bestTargetIdCached = 0;
// }
// // Normally, I'd go with a "goto" type thing here, but in this case, it makes sense to just
// // copy/paste some stuff, and return that.
// if (_bestTargetIdCached == 0)
// {
// _bestTargetIdCached = Targeting.Combat.Targets.First().ID;
// obj = EntityManager.GetObjectById<Monster>(_bestTargetIdCached);
// }
// // We have an object, go ahead and return it.
// return obj;
// });
//}
//return _bestTargetCached;
}
}
#region Overrides of CombatRoutine
private bool _eventsHooked;
/// <summary> Gets the name. </summary>
/// <value> The name. </value>
public override string Name { get { return "randomstraw"; } }
public override Composite Buff
{
get
{
return new PrioritySelector(
CreateFlaskLogic()
);
}
}
public override Composite Combat
{
get
{
return new PrioritySelector(
//CreateMoveIntoRange(80),
//CreateMoveToLoS(BestTarget),
SpellManager.CreateSpellCastComposite("Double Strike", ret => !NumberOfMobsNear(BestTarget, 15, 3), on => BestTarget),
SpellManager.CreateSpellCastComposite("Spectral Throw", ret => NumberOfMobsNear(BestTarget, 15, 3), on => BestTarget)
);
}
}
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
/// <filterpriority>2</filterpriority>
public override void Dispose()
{
}
public void SwapWeapons()
{
Input.PressKey(ConfigManager.GetActionKey(ActionKey.WeaponSwap).Item1);
}
/// <summary> Initializes this <see cref="CombatRoutine" />. </summary>
public override void Initialize()
{
if (!_eventsHooked)
{
// When we start the bot, we need to re-register all the available spells. This allows us to swap out skills
// Without restarting the bot.
_eventsHooked = true;
}
}
#endregion
}
}