test
This commit is contained in:
parent
aee3a7f22c
commit
152c74fa15
5 changed files with 122 additions and 26 deletions
Binary file not shown.
|
Before Width: | Height: | Size: 7.1 MiB After Width: | Height: | Size: 7.2 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 6.3 MiB After Width: | Height: | Size: 5.9 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 338 KiB After Width: | Height: | Size: 332 KiB |
|
|
@ -351,12 +351,18 @@ public class BossRunExecutor : GameExecutor
|
||||||
for (var phase = 1; phase <= 3; phase++)
|
for (var phase = 1; phase <= 3; phase++)
|
||||||
{
|
{
|
||||||
if (_stopped) return;
|
if (_stopped) return;
|
||||||
Log.Information("=== Boss phase {Phase}/4 ===", phase);
|
var preWp = _nav.WorldPosition;
|
||||||
|
Log.Information("=== Boss phase {Phase}/4 === fightArea=({FX:F0},{FY:F0}) charPos=({CX:F1},{CY:F1})",
|
||||||
|
phase, fightWorldX, fightWorldY, preWp.X, preWp.Y);
|
||||||
|
|
||||||
var lastBossPos = await AttackBossUntilGone(fightWorldX, fightWorldY);
|
var lastBossPos = await AttackBossUntilGone(fightWorldX, fightWorldY);
|
||||||
if (_stopped) return;
|
if (_stopped) return;
|
||||||
|
|
||||||
// Update fight area to where the boss was last seen
|
// Update fight area to where the boss was last seen
|
||||||
|
var postWp = _nav.WorldPosition;
|
||||||
|
Log.Information("Phase {Phase} ended: charPos=({CX:F1},{CY:F1}) lastBossPos={Boss}",
|
||||||
|
phase, postWp.X, postWp.Y,
|
||||||
|
lastBossPos != null ? $"({lastBossPos.Value.X:F1},{lastBossPos.Value.Y:F1})" : "null");
|
||||||
if (lastBossPos != null)
|
if (lastBossPos != null)
|
||||||
{
|
{
|
||||||
fightWorldX = lastBossPos.Value.X;
|
fightWorldX = lastBossPos.Value.X;
|
||||||
|
|
@ -380,16 +386,27 @@ public class BossRunExecutor : GameExecutor
|
||||||
|
|
||||||
// 4th fight - no well after
|
// 4th fight - no well after
|
||||||
if (_stopped) return;
|
if (_stopped) return;
|
||||||
Log.Information("=== Boss phase 4/4 ===");
|
{
|
||||||
|
var p4wp = _nav.WorldPosition;
|
||||||
|
Log.Information("=== Boss phase 4/4 === fightArea=({FX:F0},{FY:F0}) charPos=({CX:F1},{CY:F1})",
|
||||||
|
fightWorldX, fightWorldY, p4wp.X, p4wp.Y);
|
||||||
|
}
|
||||||
var finalBossPos = await AttackBossUntilGone(fightWorldX, fightWorldY);
|
var finalBossPos = await AttackBossUntilGone(fightWorldX, fightWorldY);
|
||||||
if (_stopped) return;
|
if (_stopped) return;
|
||||||
|
|
||||||
// Update fight area from phase 4 if we got detections
|
// Update fight area from phase 4 if we got detections
|
||||||
|
{
|
||||||
|
var p4postWp = _nav.WorldPosition;
|
||||||
|
Log.Information("Phase 4 ended: charPos=({CX:F1},{CY:F1}) finalBossPos={Boss}",
|
||||||
|
p4postWp.X, p4postWp.Y,
|
||||||
|
finalBossPos != null ? $"({finalBossPos.Value.X:F1},{finalBossPos.Value.Y:F1})" : "null");
|
||||||
|
}
|
||||||
if (finalBossPos != null)
|
if (finalBossPos != null)
|
||||||
{
|
{
|
||||||
fightWorldX = finalBossPos.Value.X;
|
fightWorldX = finalBossPos.Value.X;
|
||||||
fightWorldY = finalBossPos.Value.Y;
|
fightWorldY = finalBossPos.Value.Y;
|
||||||
}
|
}
|
||||||
|
Log.Information("Ring phase: using fightArea=({FX:F0},{FY:F0})", fightWorldX, fightWorldY);
|
||||||
|
|
||||||
// Walk to known ring position and look for the template
|
// Walk to known ring position and look for the template
|
||||||
await WalkToWorldPosition(-440, -330);
|
await WalkToWorldPosition(-440, -330);
|
||||||
|
|
@ -606,6 +623,19 @@ public class BossRunExecutor : GameExecutor
|
||||||
const int screenCy = 720;
|
const int screenCy = 720;
|
||||||
const double screenToWorld = 97.0 / 835.0;
|
const double screenToWorld = 97.0 / 835.0;
|
||||||
(double X, double Y)? lastBossWorldPos = null;
|
(double X, double Y)? lastBossWorldPos = null;
|
||||||
|
var yoloLogCount = 0;
|
||||||
|
|
||||||
|
// Subscribe to YOLO events for real-time chase updates
|
||||||
|
// (main loop is too slow due to template matching to effectively track boss)
|
||||||
|
void OnBossDetected(BossSnapshot snapshot)
|
||||||
|
{
|
||||||
|
if (snapshot.Bosses.Count == 0) return;
|
||||||
|
var boss = snapshot.Bosses[0];
|
||||||
|
_combatTargetX = boss.Cx;
|
||||||
|
_combatTargetY = boss.Cy;
|
||||||
|
_combat.SetChaseTarget(boss.Cx, boss.Cy);
|
||||||
|
}
|
||||||
|
_bossDetector.BossDetected += OnBossDetected;
|
||||||
|
|
||||||
Log.Information("Boss is alive, engaging");
|
Log.Information("Boss is alive, engaging");
|
||||||
var (combatTask, cts) = StartCombatLoop(screenCx, screenCy);
|
var (combatTask, cts) = StartCombatLoop(screenCx, screenCy);
|
||||||
|
|
@ -620,39 +650,22 @@ public class BossRunExecutor : GameExecutor
|
||||||
{
|
{
|
||||||
if (_stopped) return lastBossWorldPos;
|
if (_stopped) return lastBossWorldPos;
|
||||||
|
|
||||||
// Update attack target from YOLO (fast, no capture)
|
// Update lastBossWorldPos from latest YOLO (for phase tracking)
|
||||||
var snapshot = _bossDetector.Latest;
|
var snapshot = _bossDetector.Latest;
|
||||||
if (snapshot.Bosses.Count > 0)
|
if (snapshot.Bosses.Count > 0)
|
||||||
{
|
{
|
||||||
var boss = snapshot.Bosses[0];
|
var boss = snapshot.Bosses[0];
|
||||||
_combatTargetX = boss.Cx;
|
|
||||||
_combatTargetY = boss.Cy;
|
|
||||||
|
|
||||||
var wp = _nav.WorldPosition;
|
var wp = _nav.WorldPosition;
|
||||||
lastBossWorldPos = (
|
lastBossWorldPos = (
|
||||||
wp.X + (boss.Cx - screenCx) * screenToWorld,
|
wp.X + (boss.Cx - screenCx) * screenToWorld,
|
||||||
wp.Y + (boss.Cy - screenCy) * screenToWorld);
|
wp.Y + (boss.Cy - screenCy) * screenToWorld);
|
||||||
|
|
||||||
// Walk toward boss to stay as close as possible
|
yoloLogCount++;
|
||||||
var bossDx = boss.Cx - screenCx;
|
if (yoloLogCount % 5 == 1) // log every 5th detection
|
||||||
var bossDy = boss.Cy - screenCy;
|
Log.Information("YOLO boss: screen=({Sx},{Sy}) charWorld=({Cx:F1},{Cy:F1}) bossWorld=({Bx:F1},{By:F1}) conf={Conf:F2}",
|
||||||
var bossDist = Math.Sqrt(bossDx * bossDx + bossDy * bossDy);
|
boss.Cx, boss.Cy, wp.X, wp.Y,
|
||||||
|
lastBossWorldPos.Value.X, lastBossWorldPos.Value.Y, boss.Confidence);
|
||||||
if (bossDist > 50)
|
|
||||||
{
|
|
||||||
var dirX = bossDx / bossDist;
|
|
||||||
var dirY = bossDy / bossDist;
|
|
||||||
|
|
||||||
var keys = new List<int>();
|
|
||||||
if (dirY < -0.3) keys.Add(InputSender.VK.W);
|
|
||||||
if (dirY > 0.3) keys.Add(InputSender.VK.S);
|
|
||||||
if (dirX < -0.3) keys.Add(InputSender.VK.A);
|
|
||||||
if (dirX > 0.3) keys.Add(InputSender.VK.D);
|
|
||||||
|
|
||||||
foreach (var k in keys) await _game.KeyDown(k);
|
|
||||||
await Helpers.Sleep(150);
|
|
||||||
foreach (var k in keys) await _game.KeyUp(k);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check death + healthbar (combat keeps running in background)
|
// Check death + healthbar (combat keeps running in background)
|
||||||
|
|
@ -686,6 +699,8 @@ public class BossRunExecutor : GameExecutor
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
_bossDetector.BossDetected -= OnBossDetected;
|
||||||
|
_combat.ClearChaseTarget();
|
||||||
await StopCombatLoop(combatTask, cts);
|
await StopCombatLoop(combatTask, cts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,11 @@ public class CombatManager
|
||||||
private long _lastOrbitMs;
|
private long _lastOrbitMs;
|
||||||
private int _nextOrbitMs = OrbitStepMinMs;
|
private int _nextOrbitMs = OrbitStepMinMs;
|
||||||
|
|
||||||
|
// Chase — walks toward a screen position instead of orbiting
|
||||||
|
private volatile int _chaseX = -1;
|
||||||
|
private volatile int _chaseY = -1;
|
||||||
|
private readonly HashSet<int> _chaseKeys = new();
|
||||||
|
|
||||||
// Smoothed mouse position — lerps toward target to avoid jitter
|
// Smoothed mouse position — lerps toward target to avoid jitter
|
||||||
private double _smoothX = 1280;
|
private double _smoothX = 1280;
|
||||||
private double _smoothY = 720;
|
private double _smoothY = 720;
|
||||||
|
|
@ -39,6 +44,18 @@ public class CombatManager
|
||||||
|
|
||||||
public bool IsHolding => _holding;
|
public bool IsHolding => _holding;
|
||||||
|
|
||||||
|
public void SetChaseTarget(int screenX, int screenY)
|
||||||
|
{
|
||||||
|
_chaseX = screenX;
|
||||||
|
_chaseY = screenY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearChaseTarget()
|
||||||
|
{
|
||||||
|
_chaseX = -1;
|
||||||
|
_chaseY = -1;
|
||||||
|
}
|
||||||
|
|
||||||
public CombatManager(IGameController game, HudReader hudReader, FlaskManager flasks)
|
public CombatManager(IGameController game, HudReader hudReader, FlaskManager flasks)
|
||||||
{
|
{
|
||||||
_game = game;
|
_game = game;
|
||||||
|
|
@ -52,7 +69,16 @@ public class CombatManager
|
||||||
public async Task Tick(int x, int y, int jitter = 30)
|
public async Task Tick(int x, int y, int jitter = 30)
|
||||||
{
|
{
|
||||||
await _flasks.Tick();
|
await _flasks.Tick();
|
||||||
|
|
||||||
|
if (_chaseX >= 0)
|
||||||
|
{
|
||||||
|
await UpdateChase();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_chaseKeys.Count > 0) await ReleaseChaseKeys();
|
||||||
await UpdateOrbit();
|
await UpdateOrbit();
|
||||||
|
}
|
||||||
|
|
||||||
// Lerp smoothed position toward target
|
// Lerp smoothed position toward target
|
||||||
_smoothX += (x - _smoothX) * SmoothFactor;
|
_smoothX += (x - _smoothX) * SmoothFactor;
|
||||||
|
|
@ -106,6 +132,55 @@ public class CombatManager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Walk toward chase target using held WASD keys. Replaces orbit when active.
|
||||||
|
/// </summary>
|
||||||
|
private async Task UpdateChase()
|
||||||
|
{
|
||||||
|
// Release orbit key when entering chase mode
|
||||||
|
if (_orbitIndex >= 0)
|
||||||
|
{
|
||||||
|
await _game.KeyUp(OrbitKeys[_orbitIndex]);
|
||||||
|
_orbitIndex = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int screenCx = 1280, screenCy = 720;
|
||||||
|
var cx = _chaseX;
|
||||||
|
var cy = _chaseY;
|
||||||
|
var dx = cx - screenCx;
|
||||||
|
var dy = cy - screenCy;
|
||||||
|
var dist = Math.Sqrt(dx * dx + dy * dy);
|
||||||
|
|
||||||
|
var wanted = new HashSet<int>();
|
||||||
|
if (dist > 100)
|
||||||
|
{
|
||||||
|
var dirX = dx / dist;
|
||||||
|
var dirY = dy / dist;
|
||||||
|
if (dirY < -0.3) wanted.Add(InputSender.VK.W);
|
||||||
|
if (dirY > 0.3) wanted.Add(InputSender.VK.S);
|
||||||
|
if (dirX < -0.3) wanted.Add(InputSender.VK.A);
|
||||||
|
if (dirX > 0.3) wanted.Add(InputSender.VK.D);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var k in _chaseKeys.Except(wanted).ToList())
|
||||||
|
{
|
||||||
|
await _game.KeyUp(k);
|
||||||
|
_chaseKeys.Remove(k);
|
||||||
|
}
|
||||||
|
foreach (var k in wanted.Except(_chaseKeys).ToList())
|
||||||
|
{
|
||||||
|
await _game.KeyDown(k);
|
||||||
|
_chaseKeys.Add(k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ReleaseChaseKeys()
|
||||||
|
{
|
||||||
|
foreach (var k in _chaseKeys)
|
||||||
|
await _game.KeyUp(k);
|
||||||
|
_chaseKeys.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Cycle WASD directions to orbit in a small circle while attacking.
|
/// Cycle WASD directions to orbit in a small circle while attacking.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -150,6 +225,9 @@ public class CombatManager
|
||||||
_smoothX = 1280;
|
_smoothX = 1280;
|
||||||
_smoothY = 720;
|
_smoothY = 720;
|
||||||
await ReleaseOrbit();
|
await ReleaseOrbit();
|
||||||
|
await ReleaseChaseKeys();
|
||||||
|
_chaseX = -1;
|
||||||
|
_chaseY = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -164,5 +242,8 @@ public class CombatManager
|
||||||
_holding = false;
|
_holding = false;
|
||||||
}
|
}
|
||||||
await ReleaseOrbit();
|
await ReleaseOrbit();
|
||||||
|
await ReleaseChaseKeys();
|
||||||
|
_chaseX = -1;
|
||||||
|
_chaseY = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue