boss ready
This commit is contained in:
parent
89c3a0a077
commit
64a6ab694b
21 changed files with 857 additions and 249 deletions
154
src/Poe2Trade.Bot/CombatManager.cs
Normal file
154
src/Poe2Trade.Bot/CombatManager.cs
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
using System.Diagnostics;
|
||||
using Poe2Trade.Core;
|
||||
using Poe2Trade.Game;
|
||||
using Poe2Trade.Screen;
|
||||
using Serilog;
|
||||
|
||||
namespace Poe2Trade.Bot;
|
||||
|
||||
/// <summary>
|
||||
/// Manages the attack state machine (click → hold) with mana monitoring and flask usage.
|
||||
/// Call <see cref="Tick"/> each combat loop iteration, <see cref="Reset"/> between phases,
|
||||
/// and <see cref="ReleaseAll"/> when done.
|
||||
/// </summary>
|
||||
public class CombatManager
|
||||
{
|
||||
private static readonly Random Rng = new();
|
||||
|
||||
// Orbit: cycle W→D→S→A to dodge in a small circle
|
||||
private static readonly int[] OrbitKeys =
|
||||
[InputSender.VK.W, InputSender.VK.D, InputSender.VK.S, InputSender.VK.A];
|
||||
private const int OrbitStepMs = 400; // time per direction
|
||||
|
||||
private readonly IGameController _game;
|
||||
private readonly HudReader _hudReader;
|
||||
private readonly FlaskManager _flasks;
|
||||
|
||||
private bool _holding;
|
||||
private int _manaStableCount;
|
||||
private readonly Stopwatch _orbitSw = Stopwatch.StartNew();
|
||||
private int _orbitIndex = -1;
|
||||
private long _lastOrbitMs;
|
||||
|
||||
public bool IsHolding => _holding;
|
||||
|
||||
public CombatManager(IGameController game, HudReader hudReader, FlaskManager flasks)
|
||||
{
|
||||
_game = game;
|
||||
_hudReader = hudReader;
|
||||
_flasks = flasks;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// One combat iteration: flask check, mana-based click/hold, mouse jitter toward target.
|
||||
/// </summary>
|
||||
public async Task Tick(int x, int y, int jitter = 30)
|
||||
{
|
||||
await _flasks.Tick();
|
||||
await UpdateOrbit();
|
||||
|
||||
var mana = _hudReader.Current.ManaPct;
|
||||
|
||||
if (!_holding)
|
||||
{
|
||||
if (mana >= 0.80f)
|
||||
_manaStableCount++;
|
||||
else
|
||||
_manaStableCount = 0;
|
||||
|
||||
var targetX = x + Rng.Next(-jitter, jitter + 1);
|
||||
var targetY = y + Rng.Next(-jitter, jitter + 1);
|
||||
await _game.MoveMouseFast(targetX, targetY);
|
||||
|
||||
_game.LeftMouseDown();
|
||||
await Helpers.Sleep(Rng.Next(20, 35));
|
||||
_game.LeftMouseUp();
|
||||
_game.RightMouseDown();
|
||||
await Helpers.Sleep(Rng.Next(20, 35));
|
||||
_game.RightMouseUp();
|
||||
|
||||
await Helpers.Sleep(Rng.Next(50, 80));
|
||||
|
||||
if (_manaStableCount >= 5)
|
||||
{
|
||||
Log.Information("Mana stable at {Mana:P0}, switching to hold attack", mana);
|
||||
_game.LeftMouseDown();
|
||||
_game.RightMouseDown();
|
||||
_holding = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var targetX = x + Rng.Next(-jitter, jitter + 1);
|
||||
var targetY = y + Rng.Next(-jitter, jitter + 1);
|
||||
await _game.MoveMouseFast(targetX, targetY);
|
||||
|
||||
if (mana < 0.30f)
|
||||
{
|
||||
Log.Information("Mana dropped to {Mana:P0}, releasing to recover", mana);
|
||||
_game.LeftMouseUp();
|
||||
_game.RightMouseUp();
|
||||
_holding = false;
|
||||
_manaStableCount = 0;
|
||||
}
|
||||
|
||||
await Helpers.Sleep(Rng.Next(80, 120));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Cycle WASD directions to orbit in a small circle while attacking.
|
||||
/// </summary>
|
||||
private async Task UpdateOrbit()
|
||||
{
|
||||
var now = _orbitSw.ElapsedMilliseconds;
|
||||
if (now - _lastOrbitMs < OrbitStepMs) return;
|
||||
_lastOrbitMs = now;
|
||||
|
||||
// Release previous direction
|
||||
if (_orbitIndex >= 0)
|
||||
await _game.KeyUp(OrbitKeys[_orbitIndex]);
|
||||
|
||||
// Advance to next direction
|
||||
_orbitIndex = (_orbitIndex + 1) % OrbitKeys.Length;
|
||||
await _game.KeyDown(OrbitKeys[_orbitIndex]);
|
||||
}
|
||||
|
||||
private async Task ReleaseOrbit()
|
||||
{
|
||||
if (_orbitIndex >= 0)
|
||||
{
|
||||
await _game.KeyUp(OrbitKeys[_orbitIndex]);
|
||||
_orbitIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset state for a new combat phase (releases held buttons if any).
|
||||
/// </summary>
|
||||
public async Task Reset()
|
||||
{
|
||||
if (_holding)
|
||||
{
|
||||
_game.LeftMouseUp();
|
||||
_game.RightMouseUp();
|
||||
}
|
||||
_holding = false;
|
||||
_manaStableCount = 0;
|
||||
await ReleaseOrbit();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Release any held mouse buttons and movement keys. Call in finally blocks.
|
||||
/// </summary>
|
||||
public async Task ReleaseAll()
|
||||
{
|
||||
if (_holding)
|
||||
{
|
||||
_game.LeftMouseUp();
|
||||
_game.RightMouseUp();
|
||||
_holding = false;
|
||||
}
|
||||
await ReleaseOrbit();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue