This commit is contained in:
2026-04-02 20:51:21 +02:00
parent 1e3c2b176d
commit 49156bcda4
2 changed files with 236 additions and 21 deletions

View File

@@ -11,6 +11,19 @@
<Button x:Name="StartButton" Content="Start Bot" Width="120"/>
<Button x:Name="StopButton" Content="Stop Bot" Width="120" IsEnabled="False"/>
<CheckBox x:Name="MultiplayerCheckBox" Content="Multiplayer" VerticalAlignment="Center"/>
<TextBlock Text="Aggro:" VerticalAlignment="Center"/>
<ComboBox x:Name="AggressivenessProfileBox" Width="150" SelectedIndex="2">
<ComboBoxItem Content="Conservative"/>
<ComboBoxItem Content="Balanced"/>
<ComboBoxItem Content="Aggressive"/>
<ComboBoxItem Content="Extreme"/>
</ComboBox>
<TextBlock Text="Mode Profile:" VerticalAlignment="Center"/>
<ComboBox x:Name="ModeOptimizationProfileBox" Width="200" SelectedIndex="0">
<ComboBoxItem Content="Auto"/>
<ComboBoxItem Content="Singleplayer Optimized"/>
<ComboBoxItem Content="Multiplayer Optimized"/>
</ComboBox>
<TextBlock Text="API Key:" VerticalAlignment="Center"/>
<TextBox x:Name="ApiKeyBox" Width="360" Watermark="GUID player token"/>
<TextBlock x:Name="StatusText" VerticalAlignment="Center" Text="Idle"/>

View File

@@ -9,6 +9,7 @@ using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Layout;
using Avalonia.Media;
using Avalonia.Controls.Primitives;
using Avalonia.Threading;
namespace DDApplication;
@@ -77,6 +78,9 @@ public partial class MainWindow : Window
private bool _lastUnderPressure;
private int _pressureStreak;
private LevelProfile _currentLevelProfile = LevelProfile.Unknown;
private bool _isMultiplayerMode;
private AggressivenessProfile _selectedAggressiveness = AggressivenessProfile.Aggressive;
private ModeOptimizationProfile _selectedModeOptimization = ModeOptimizationProfile.Auto;
public MainWindow()
{
@@ -87,6 +91,20 @@ public partial class MainWindow : Window
ApiKeyBox.Text = _configuredApiKey;
MultiplayerCheckBox.IsChecked = _multiplayerModeDefault;
AggressivenessProfileBox.SelectedIndex = 2;
ModeOptimizationProfileBox.SelectedIndex = 0;
SyncProfileSelectionState();
MultiplayerCheckBox.PropertyChanged += (_, e) =>
{
if (e.Property == ToggleButton.IsCheckedProperty)
{
SyncProfileSelectionState();
}
};
AggressivenessProfileBox.SelectionChanged += (_, _) => SyncProfileSelectionState();
ModeOptimizationProfileBox.SelectionChanged += (_, _) => SyncProfileSelectionState();
LogList.ItemsSource = _logEntries;
StartButton.Click += async (_, _) => await StartBotAsync();
@@ -125,6 +143,8 @@ public partial class MainWindow : Window
StopButton.IsEnabled = true;
ApiKeyBox.IsEnabled = false;
MultiplayerCheckBox.IsEnabled = false;
AggressivenessProfileBox.IsEnabled = false;
ModeOptimizationProfileBox.IsEnabled = false;
ResetKnowledgeState();
@@ -189,6 +209,8 @@ public partial class MainWindow : Window
StopButton.IsEnabled = false;
ApiKeyBox.IsEnabled = true;
MultiplayerCheckBox.IsEnabled = true;
AggressivenessProfileBox.IsEnabled = true;
ModeOptimizationProfileBox.IsEnabled = true;
SetStatus("Stopped.");
}
@@ -481,7 +503,7 @@ public partial class MainWindow : Window
_pressureStreak = Math.Max(_pressureStreak - 1, 0);
}
var underPressure = hpRatio < PressureHpThreshold(profile) || _recentDamageTicks > 0 || closeThreats >= PressureThreatThreshold(profile) || _survivalTicks > 0 || _pressureStreak >= 2;
var underPressure = hpRatio < PressureHpThresholdAdjusted(profile) || _recentDamageTicks > 0 || closeThreats >= PressureThreatThresholdAdjusted(profile) || _survivalTicks > 0 || _pressureStreak >= 2;
_lastUnderPressure = underPressure;
var predictedEnemy = PredictEnemyRelative();
@@ -575,8 +597,8 @@ public partial class MainWindow : Window
});
}
var specialThreatThreshold = SpecialThreatThreshold(profile);
var specialHpFloor = SpecialHpFloor(profile);
var specialThreatThreshold = SpecialThreatThresholdAdjusted(profile);
var specialHpFloor = SpecialHpFloorAdjusted(profile);
if (Ready(BotAction.Special) && closeThreats >= specialThreatThreshold && (hpRatio >= specialHpFloor || closeThreats > specialThreatThreshold))
{
@@ -609,7 +631,7 @@ public partial class MainWindow : Window
{
var retreatDirection = Opposite(immediateDir.Value);
if (Ready(BotAction.Dash) && (hpRatio < DashHpThreshold(profile) || _pressureStreak >= 3 || _survivalTicks > 0))
if (Ready(BotAction.Dash) && (hpRatio < DashHpThresholdAdjusted(profile) || _pressureStreak >= 3 || _survivalTicks > 0))
{
return new BotDecision(
"dash-retreat",
@@ -1001,24 +1023,144 @@ public partial class MainWindow : Window
_ => 2,
};
private bool ShouldUseImmediateHit(LevelProfile profile, double hpRatio, int closeThreats, bool underPressure) => profile switch
private bool ShouldUseImmediateHit(LevelProfile profile, double hpRatio, int closeThreats, bool underPressure)
{
LevelProfile.Default => hpRatio >= 0.05,
LevelProfile.BiggerMap => hpRatio >= 0.05,
LevelProfile.MoreBots => hpRatio >= 0.05,
LevelProfile.NewBots => hpRatio >= 0.05,
_ => hpRatio >= 0.05,
var hpFloor = SelectedAggressiveness switch
{
AggressivenessProfile.Conservative => 0.30,
AggressivenessProfile.Balanced => 0.16,
AggressivenessProfile.Aggressive => 0.05,
AggressivenessProfile.Extreme => 0.01,
_ => 0.05,
};
private bool ShouldRetreatOnImmediate(LevelProfile profile, double hpRatio, int closeThreats) => profile switch
if (IsMultiplayerOptimized)
{
LevelProfile.Default => hpRatio < 0.02,
LevelProfile.BiggerMap => hpRatio < 0.02,
LevelProfile.MoreBots => hpRatio < 0.02,
LevelProfile.NewBots => hpRatio < 0.02,
_ => hpRatio < 0.02,
hpFloor = Math.Max(hpFloor, 0.18);
}
return hpRatio >= hpFloor || (!underPressure && closeThreats <= 1);
}
private bool ShouldRetreatOnImmediate(LevelProfile profile, double hpRatio, int closeThreats)
{
var hpRetreat = SelectedAggressiveness switch
{
AggressivenessProfile.Conservative => 0.30,
AggressivenessProfile.Balanced => 0.18,
AggressivenessProfile.Aggressive => 0.02,
AggressivenessProfile.Extreme => 0.01,
_ => 0.02,
};
if (IsMultiplayerOptimized)
{
hpRetreat = Math.Max(hpRetreat, 0.20);
}
return hpRatio < hpRetreat || (IsMultiplayerOptimized && closeThreats >= 3);
}
private double PressureHpThresholdAdjusted(LevelProfile profile)
{
var value = PressureHpThreshold(profile);
value += SelectedAggressiveness switch
{
AggressivenessProfile.Conservative => 0.20,
AggressivenessProfile.Balanced => 0.08,
AggressivenessProfile.Aggressive => 0.00,
AggressivenessProfile.Extreme => -0.05,
_ => 0.00,
};
if (IsMultiplayerOptimized)
{
value += 0.08;
}
return Math.Clamp(value, 0.01, 0.95);
}
private int PressureThreatThresholdAdjusted(LevelProfile profile)
{
var value = PressureThreatThreshold(profile);
value += SelectedAggressiveness switch
{
AggressivenessProfile.Conservative => -2,
AggressivenessProfile.Balanced => -1,
AggressivenessProfile.Aggressive => 0,
AggressivenessProfile.Extreme => 1,
_ => 0,
};
if (IsMultiplayerOptimized)
{
value -= 1;
}
return Math.Clamp(value, 1, 8);
}
private int SpecialThreatThresholdAdjusted(LevelProfile profile)
{
var value = SpecialThreatThreshold(profile);
value += SelectedAggressiveness switch
{
AggressivenessProfile.Conservative => 1,
AggressivenessProfile.Balanced => 0,
AggressivenessProfile.Aggressive => 0,
AggressivenessProfile.Extreme => -1,
_ => 0,
};
if (IsMultiplayerOptimized)
{
value += 1;
}
return Math.Clamp(value, 1, 6);
}
private double SpecialHpFloorAdjusted(LevelProfile profile)
{
var value = SpecialHpFloor(profile);
value += SelectedAggressiveness switch
{
AggressivenessProfile.Conservative => 0.20,
AggressivenessProfile.Balanced => 0.10,
AggressivenessProfile.Aggressive => 0.00,
AggressivenessProfile.Extreme => -0.05,
_ => 0.00,
};
if (IsMultiplayerOptimized)
{
value += 0.10;
}
return Math.Clamp(value, 0.01, 0.95);
}
private double DashHpThresholdAdjusted(LevelProfile profile)
{
var value = DashHpThreshold(profile);
value += SelectedAggressiveness switch
{
AggressivenessProfile.Conservative => 0.18,
AggressivenessProfile.Balanced => 0.10,
AggressivenessProfile.Aggressive => 0.00,
AggressivenessProfile.Extreme => -0.03,
_ => 0.00,
};
if (IsMultiplayerOptimized)
{
value += 0.10;
}
return Math.Clamp(value, 0.01, 0.95);
}
private (int X, int Y)? PredictEnemyRelative()
{
if (!_nearestEnemy.HasValue)
@@ -1121,7 +1263,21 @@ public partial class MainWindow : Window
return true;
}
return DeathHeatFor(direction) >= 4.0;
var deathHeatLimit = SelectedAggressiveness switch
{
AggressivenessProfile.Conservative => 2.5,
AggressivenessProfile.Balanced => 3.2,
AggressivenessProfile.Aggressive => 4.0,
AggressivenessProfile.Extreme => 5.0,
_ => 4.0,
};
if (IsMultiplayerOptimized)
{
deathHeatLimit -= 0.6;
}
return DeathHeatFor(direction) >= deathHeatLimit;
}
private void MarkVisit(int x, int y, double amount)
@@ -1235,7 +1391,7 @@ public partial class MainWindow : Window
$"Level: {_levelName} | Kills: {_kills} | Deaths: {_deaths} | K/D: {kdr} | " +
$"HP: {_currentHealth.ToString("0.0", CultureInfo.InvariantCulture)}/{_maxHealth.ToString("0.0", CultureInfo.InvariantCulture)} ({hpPercent.ToString("0", CultureInfo.InvariantCulture)}%) | " +
$"Progress: {_progress.ToString("0.0", CultureInfo.InvariantCulture)}% | Remaining: {_remainingTime.ToString("0.00", CultureInfo.InvariantCulture)} min | " +
$"Pos (estimated): ({_x}, {_y}) | Profile: {_currentLevelProfile} | SurvivalMode: {(_survivalTicks > 0 ? "ON" : "OFF")}";
$"Pos (estimated): ({_x}, {_y}) | Profile: {_currentLevelProfile} | Aggro: {SelectedAggressiveness} | Mode: {SelectedModeOptimization} | SurvivalMode: {(_survivalTicks > 0 ? "ON" : "OFF")}";
var nearest = _nearestEnemy.HasValue ? $"({_nearestEnemy.Value.X}, {_nearestEnemy.Value.Y})" : "none";
var radar = _lastRadar.Count == 0
@@ -1276,7 +1432,38 @@ public partial class MainWindow : Window
Dispatcher.UIThread.Post(() => StatusText.Text = text);
}
private bool IsMultiplayerMode => MultiplayerCheckBox.IsChecked == true;
private bool IsMultiplayerMode => _isMultiplayerMode;
private AggressivenessProfile SelectedAggressiveness => _selectedAggressiveness;
private ModeOptimizationProfile SelectedModeOptimization => _selectedModeOptimization;
private bool IsMultiplayerOptimized => SelectedModeOptimization switch
{
ModeOptimizationProfile.SingleplayerOptimized => false,
ModeOptimizationProfile.MultiplayerOptimized => true,
_ => _isMultiplayerMode,
};
private void SyncProfileSelectionState()
{
_isMultiplayerMode = MultiplayerCheckBox.IsChecked == true;
_selectedAggressiveness = AggressivenessProfileBox.SelectedIndex switch
{
0 => AggressivenessProfile.Conservative,
1 => AggressivenessProfile.Balanced,
2 => AggressivenessProfile.Aggressive,
3 => AggressivenessProfile.Extreme,
_ => AggressivenessProfile.Aggressive,
};
_selectedModeOptimization = ModeOptimizationProfileBox.SelectedIndex switch
{
1 => ModeOptimizationProfile.SingleplayerOptimized,
2 => ModeOptimizationProfile.MultiplayerOptimized,
_ => ModeOptimizationProfile.Auto,
};
}
private void AppendLog(string message)
{
@@ -1382,6 +1569,21 @@ public partial class MainWindow : Window
NewBots,
}
private enum AggressivenessProfile
{
Conservative,
Balanced,
Aggressive,
Extreme,
}
private enum ModeOptimizationProfile
{
Auto,
SingleplayerOptimized,
MultiplayerOptimized,
}
private enum Direction
{
North = 0,