Ahmedramadan24's picture
Add plugins/SilkroadBot.Plugin.Protection/ProtectionPlugin.cs
cd011a2 verified
using SilkroadBot.Plugins.SDK.Attributes;
using SilkroadBot.Plugins.SDK.Interfaces;
using SilkroadBot.Plugins.SDK.Models;
using SilkroadBot.Domain.Models;
namespace SilkroadBot.Plugin.Protection;
/// <summary>
/// Protection plugin - monitors character safety and takes protective actions.
/// Handles auto-healing, flee behavior, disconnect protection, and death recovery.
/// </summary>
[Plugin("protection", "Character Protection", "Auto-healing, flee behavior, and death recovery")]
public class ProtectionPlugin : PluginBase
{
public override string Id => "protection";
public override string Name => "Character Protection";
public override Version Version => new(1, 0, 0);
public override string Author => "SilkroadBot Team";
public override string Description => "Automatic character protection: healing, fleeing, and recovery";
private CancellationTokenSource? _monitorCts;
// Configuration
private double _healThreshold = 60.0;
private double _mpPotThreshold = 30.0;
private double _fleeThreshold = 15.0;
private int _maxMonstersBeforeFlee = 5;
private int _checkIntervalMs = 500;
private bool _autoResurrect = true;
private WorldPosition _safePosition;
public override async Task InitializeAsync(IPluginContext context)
{
await base.InitializeAsync(context);
await LoadConfigurationAsync();
}
public override Task StartAsync(CancellationToken ct = default)
{
_monitorCts = CancellationTokenSource.CreateLinkedTokenSource(ct);
_ = Task.Run(() => ProtectionLoopAsync(_monitorCts.Token));
return base.StartAsync(ct);
}
public override Task StopAsync()
{
_monitorCts?.Cancel();
return base.StopAsync();
}
private async Task ProtectionLoopAsync(CancellationToken ct)
{
Log(LogLevel.Information, "Protection monitoring active");
while (!ct.IsCancellationRequested)
{
try
{
var state = Context.GetGameState();
await CheckProtectionRules(state);
await Task.Delay(_checkIntervalMs, ct);
}
catch (OperationCanceledException) { break; }
catch (Exception ex)
{
Log(LogLevel.Error, $"Protection check error: {ex.Message}");
await Task.Delay(2000, ct);
}
}
}
private async Task CheckProtectionRules(GameStateSnapshot state)
{
// Rule 1: Death recovery
if (state.IsDead)
{
await HandleDeath(state);
return;
}
// Rule 2: Critical HP - Flee
if (state.HPPercentage < _fleeThreshold && state.IsInCombat)
{
await HandleFlee(state);
return;
}
// Rule 3: Low HP - Heal
if (state.HPPercentage < _healThreshold)
{
await HandleHeal(state);
}
// Rule 4: Low MP - Potion
if (state.MPPercentage < _mpPotThreshold)
{
await HandleMPRestore(state);
}
// Rule 5: Too many monsters
if (state.NearbyEntityCount > _maxMonstersBeforeFlee && state.IsInCombat)
{
Log(LogLevel.Warning, $"Too many enemies nearby ({state.NearbyEntityCount}). Consider fleeing.");
}
}
private async Task HandleDeath(GameStateSnapshot state)
{
Log(LogLevel.Warning, "Character is dead!");
if (_autoResurrect)
{
Log(LogLevel.Information, "Attempting auto-resurrect...");
// TODO: Send resurrect packet (nearest spawn point)
await Task.Delay(3000);
}
}
private async Task HandleFlee(GameStateSnapshot state)
{
Log(LogLevel.Warning, $"HP critically low ({state.HPPercentage:F1}%)! Fleeing to safety...");
// Use navigation to flee to safe position
var nav = Context.NavigationService;
if (nav != null)
{
var path = await nav.FindPathAsync(state.Position, _safePosition);
if (path.Count > 0)
{
Log(LogLevel.Information, $"Flee path found ({path.Count} waypoints)");
// TODO: Execute movement along path
}
}
}
private async Task HandleHeal(GameStateSnapshot state)
{
Log(LogLevel.Debug, $"HP below threshold ({state.HPPercentage:F1}%). Using health potion...");
// TODO: Send use HP potion packet
await Task.CompletedTask;
}
private async Task HandleMPRestore(GameStateSnapshot state)
{
Log(LogLevel.Debug, $"MP below threshold ({state.MPPercentage:F1}%). Using MP potion...");
// TODO: Send use MP potion packet
await Task.CompletedTask;
}
private Task LoadConfigurationAsync()
{
_healThreshold = Context.Configuration.Get("healThreshold", 60.0);
_mpPotThreshold = Context.Configuration.Get("mpPotThreshold", 30.0);
_fleeThreshold = Context.Configuration.Get("fleeThreshold", 15.0);
_maxMonstersBeforeFlee = Context.Configuration.Get("maxMonsters", 5);
_checkIntervalMs = Context.Configuration.Get("checkIntervalMs", 500);
_autoResurrect = Context.Configuration.Get("autoResurrect", true);
return Task.CompletedTask;
}
}