diff --git a/ACManager.csproj b/ACManager.csproj
index 9af7cec..bc71921 100644
--- a/ACManager.csproj
+++ b/ACManager.csproj
@@ -91,6 +91,7 @@
+
diff --git a/FilterCore.cs b/FilterCore.cs
index 3e79d3c..f33f705 100644
--- a/FilterCore.cs
+++ b/FilterCore.cs
@@ -135,6 +135,10 @@ private void FilterCore_ClientDispatch(object sender, NetworkMessageEventArgs e)
Machine.ManaThreshold = Machine.Utility.BotSettings.ManaThreshold;
Machine.StaminaThreshold = Machine.Utility.BotSettings.StaminaThreshold;
Machine.DefaultHeading = Machine.Utility.BotSettings.DefaultHeading;
+ Machine.DesiredLandBlock = Machine.Utility.BotSettings.DesiredLandBlock;
+ Machine.DesiredBotLocationX = Machine.Utility.BotSettings.DesiredBotLocationX;
+ Machine.DesiredBotLocationY = Machine.Utility.BotSettings.DesiredBotLocationY;
+ Machine.EnablePositioning = Machine.Utility.BotSettings.BotPositioning;
Machine.LoggedIn = true;
}
diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs
index 1d8a995..a7fee65 100644
--- a/Properties/AssemblyInfo.cs
+++ b/Properties/AssemblyInfo.cs
@@ -31,5 +31,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("2.0.0")]
-[assembly: AssemblyFileVersion("2.0.0")]
+[assembly: AssemblyVersion("2.1.0")]
+[assembly: AssemblyFileVersion("2.1.0")]
diff --git a/Settings/BotSettings.cs b/Settings/BotSettings.cs
index de79bae..415e2c6 100644
--- a/Settings/BotSettings.cs
+++ b/Settings/BotSettings.cs
@@ -30,6 +30,18 @@ public class BotSettings
[XmlElement(IsNullable = false)]
public double DefaultHeading;
+ [XmlElement(IsNullable = false)]
+ public int DesiredLandBlock;
+
+ [XmlElement(IsNullable = false)]
+ public double DesiredBotLocationX;
+
+ [XmlElement(IsNullable = false)]
+ public double DesiredBotLocationY;
+
+ [XmlElement(IsNullable = false)]
+ public bool BotPositioning = false;
+
public List Advertisements = new List();
}
diff --git a/StateMachine/Machine.cs b/StateMachine/Machine.cs
index 3737de0..d77c6f6 100644
--- a/StateMachine/Machine.cs
+++ b/StateMachine/Machine.cs
@@ -188,6 +188,26 @@ internal class Machine
///
public double DefaultHeading { get; set; }
+ ///
+ /// Navigation landblock to maintain.
+ ///
+ public int DesiredLandBlock { get; set; }
+
+ ///
+ /// X coordinate in the landblock to maintain.
+ ///
+ public double DesiredBotLocationX { get; set; }
+
+ ///
+ /// Y coordinate in the landblock to maintain.
+ ///
+ public double DesiredBotLocationY { get; set; }
+
+ ///
+ /// Enable/disable navigation.
+ ///
+ public bool EnablePositioning { get; set; } = false;
+
///
/// Create the state machine in the StoppedState and begin processing commands on intervals (every time a frame is rendered).
///
@@ -221,7 +241,7 @@ private void Clock(object sender, EventArgs e)
// Gets the character's skill levels
Skills = Core.CharacterFilter.EffectiveSkill;
-
+
if (NextState == null)
{
CurrentState.Process(this);
diff --git a/StateMachine/States/Idle.cs b/StateMachine/States/Idle.cs
index 471db4b..cfeae62 100644
--- a/StateMachine/States/Idle.cs
+++ b/StateMachine/States/Idle.cs
@@ -27,7 +27,21 @@ public void Process(Machine machine)
{
if (machine.Enabled)
{
- if (machine.SpellsToCast.Count > 0 && machine.Core.CharacterFilter.Name.Equals(machine.NextCharacter)) // If there is a portal in the queue and it is on this character, enter casting state
+ if (!(machine.Core.Actions.Landcell == machine.DesiredLandBlock && Math.Abs(machine.Core.Actions.LocationX - machine.DesiredBotLocationX) < 1 && Math.Abs(machine.Core.Actions.LocationY - machine.DesiredBotLocationY) < 1) && machine.EnablePositioning) // If bot is not in the correct spot, get there
+ {
+ if (machine.DesiredLandBlock.Equals(0) && machine.DesiredBotLocationX.Equals(0) && machine.DesiredBotLocationY.Equals(0)) // no location settings, use current location
+ {
+ machine.DesiredLandBlock = machine.Core.Actions.Landcell;
+ machine.DesiredBotLocationX = machine.Core.Actions.LocationX;
+ machine.DesiredBotLocationY = machine.Core.Actions.LocationY;
+ Debug.ToChat("Bot location set to current location since one was not set previously.");
+ }
+ else // location settings were set - reposition the bot
+ {
+ machine.NextState = Positioning.GetInstance;
+ }
+ }
+ else if (machine.SpellsToCast.Count > 0 && machine.Core.CharacterFilter.Name.Equals(machine.NextCharacter)) // If there is a portal in the queue and it is on this character, enter casting state
{
if ((machine.Core.Actions.Heading <= machine.NextHeading + 2 && machine.Core.Actions.Heading >= machine.NextHeading - 2) || machine.NextHeading.Equals(-1))
{
diff --git a/StateMachine/States/Positioning.cs b/StateMachine/States/Positioning.cs
new file mode 100644
index 0000000..ead6ef3
--- /dev/null
+++ b/StateMachine/States/Positioning.cs
@@ -0,0 +1,132 @@
+using System;
+
+namespace ACManager.StateMachine.States
+{
+ ///
+ /// State that is used to place the bot in the desired (X, Y) coordinate location in the world.
+ ///
+ class Positioning : StateBase, IState
+ {
+ double tempHeading;
+ bool autoRunEnabled = false;
+
+ public void Enter(Machine machine)
+ {
+
+ }
+
+ public void Exit(Machine machine)
+ {
+
+ }
+
+ public void Process(Machine machine)
+ {
+ if (machine.Enabled)
+ {
+ if (!(Math.Abs(machine.Core.Actions.LocationX - machine.DesiredBotLocationX) < 1 && Math.Abs(machine.Core.Actions.LocationY - machine.DesiredBotLocationY) < 1 && machine.Core.Actions.Landcell == machine.DesiredLandBlock))
+ {
+ tempHeading = GetHeading(machine.Core.Actions.Landcell, machine.DesiredLandBlock, machine.Core.Actions.LocationX, machine.Core.Actions.LocationY, machine.DesiredBotLocationX, machine.DesiredBotLocationY);
+
+ if (machine.Core.Actions.Heading <= tempHeading + 2 && machine.Core.Actions.Heading >= tempHeading - 2)
+ {
+ if (!autoRunEnabled)
+ {
+ machine.Core.Actions.SetAutorun(true);
+ autoRunEnabled = !autoRunEnabled;
+ }
+ }
+ else
+ {
+ if (autoRunEnabled)
+ {
+ machine.Core.Actions.SetAutorun(false);
+ autoRunEnabled = !autoRunEnabled;
+ }
+ machine.Core.Actions.Heading = tempHeading;
+
+ }
+ }
+ else // Have made it to the desired location
+ {
+ if (autoRunEnabled)
+ {
+ machine.Core.Actions.SetAutorun(false);
+ autoRunEnabled = !autoRunEnabled;
+ }
+ machine.NextState = Idle.GetInstance;
+ }
+ }
+ else
+ {
+ machine.NextState = Idle.GetInstance;
+ }
+ }
+
+ public override string ToString()
+ {
+ return nameof(Positioning);
+ }
+
+ private double GetHeading(int currentLB, int targetLB, double currentX, double currentY, double targetX, double targetY)
+ {
+ int currentLBint, targetLBint, currentLB_EW, currentLB_NS, targetLB_EW, targetLB_NS, headingModifier;
+
+ currentLBint = LandblockToInt(currentLB);
+ targetLBint = LandblockToInt(targetLB);
+
+ currentLB_EW = EWLandblockToInt(currentLB);
+ currentLB_NS = NSLandblockToInt(currentLB);
+
+ targetLB_EW = EWLandblockToInt(targetLB);
+ targetLB_NS = NSLandblockToInt(targetLB);
+
+ if (currentLBint.Equals(targetLBint))
+ {
+ if (currentX < targetX)
+ {
+ headingModifier = 90;
+ }
+ else
+ {
+ headingModifier = 270;
+ }
+ }
+ else if (currentLB_EW < targetLB_EW)
+ {
+ headingModifier = 90;
+ }
+ else
+ {
+ headingModifier = 270;
+ }
+ return headingModifier - RadToDegrees(Math.Atan(CalculateCoordDiff(currentLB_NS, targetLB_NS, currentY, targetY) / CalculateCoordDiff(currentLB_EW, targetLB_EW, currentX, targetX)));
+ }
+
+ private double RadToDegrees(double radians)
+ {
+ return radians * (180 / Math.PI);
+ }
+
+ private int LandblockToInt(int landblock)
+ {
+ return Convert.ToInt32(landblock.ToString("X").Substring(0, 3), 16);
+ }
+
+ private int EWLandblockToInt(int landblock)
+ {
+ return Convert.ToInt32(landblock.ToString("X").Substring(0, 2), 16);
+ }
+
+ private int NSLandblockToInt(int landblock)
+ {
+ return Convert.ToInt32(landblock.ToString("X").Substring(2, 2), 16);
+ }
+
+ private double CalculateCoordDiff(int currentLBEW_NS, int targetLBEW_NS, double currentXY, double targetXY)
+ {
+ return currentXY + ((currentLBEW_NS - targetLBEW_NS) * 192) - targetXY;
+ }
+
+ }
+}
diff --git a/Views/PortalBotView.cs b/Views/PortalBotView.cs
index 51bdf52..b12558d 100644
--- a/Views/PortalBotView.cs
+++ b/Views/PortalBotView.cs
@@ -15,8 +15,12 @@ internal class PortalBotView : IDisposable
private CoreManager Core { get; set; }
internal HudView View { get; set; }
internal HudCheckBox BotEnabled { get; set; }
+ internal HudButton ClearLocation { get; set; }
+ internal HudButton SetLocation { get; set; }
+ internal HudStaticText LocationSetpoint { get; set; }
internal HudCheckBox RespondToGeneralChat { get; set; }
internal HudCheckBox AdsEnabled { get; set; }
+ internal HudCheckBox BotPositioning { get; set; }
internal HudTextBox AdInterval { get; set; }
internal HudButton SetHeading { get; set; }
internal HudTextBox DefaultHeading { get; set; }
@@ -53,12 +57,24 @@ public PortalBotView(FilterCore parent, CoreManager core)
BotEnabled = View != null ? (HudCheckBox)View["Bot"] : new HudCheckBox();
BotEnabled.Change += BotEnabled_Change;
+ ClearLocation = View != null ? (HudButton)View["ClearLocation"] : new HudButton();
+ ClearLocation.Hit += ClearLocation_Hit;
+
+ LocationSetpoint = View != null ? (HudStaticText)View["LocationSetpoint"] : new HudStaticText();
+ LocationSetpoint.TextAlignment = VirindiViewService.WriteTextFormats.Center;
+
+ SetLocation = View != null ? (HudButton)View["SetLocation"] : new HudButton();
+ SetLocation.Hit += SetLocation_Hit;
+
RespondToGeneralChat = View != null ? (HudCheckBox)View["GeneralChatResponse"] : new HudCheckBox();
RespondToGeneralChat.Change += RespondToGeneralChat_Change;
AdsEnabled = View != null ? (HudCheckBox)View["AdsEnabled"] : new HudCheckBox();
AdsEnabled.Change += AdsEnabled_Change;
+ BotPositioning = View != null ? (HudCheckBox)View["BotPositioning"] : new HudCheckBox();
+ BotPositioning.Change += BotPositioning_Change;
+
AdInterval = View != null ? (HudTextBox)View["AdInterval"] : new HudTextBox();
AdInterval.Change += AdInterval_Change;
@@ -126,6 +142,43 @@ public PortalBotView(FilterCore parent, CoreManager core)
catch (Exception ex) { Debug.LogException(ex); }
}
+ private void ClearLocation_Hit(object sender, EventArgs e)
+ {
+ try
+ {
+ Filter.Machine.DesiredLandBlock = Filter.Machine.Utility.BotSettings.DesiredLandBlock = 0;
+ Filter.Machine.DesiredBotLocationX = Filter.Machine.Utility.BotSettings.DesiredBotLocationX = 0;
+ Filter.Machine.DesiredBotLocationY = Filter.Machine.Utility.BotSettings.DesiredBotLocationY = 0;
+ LocationSetpoint.Text = "No location set";
+ Filter.Machine.Utility.SaveBotSettings();
+ }
+ catch (Exception ex) { Debug.LogException(ex); }
+ }
+
+ private void BotPositioning_Change(object sender, EventArgs e)
+ {
+ try
+ {
+ Filter.Machine.EnablePositioning = Filter.Machine.Utility.BotSettings.BotPositioning = BotPositioning.Checked;
+ Filter.Machine.Utility.SaveBotSettings();
+ Debug.ToChat($"The bot will {(Filter.Machine.EnablePositioning ? "now" : "no longer")} try to automatically position itself to the set navigation point.");
+ }
+ catch (Exception ex) { Debug.LogException(ex); }
+ }
+
+ private void SetLocation_Hit(object sender, EventArgs e)
+ {
+ try
+ {
+ Filter.Machine.DesiredLandBlock = Filter.Machine.Utility.BotSettings.DesiredLandBlock = Filter.Machine.Core.Actions.Landcell;
+ Filter.Machine.DesiredBotLocationX = Filter.Machine.Utility.BotSettings.DesiredBotLocationX = Filter.Machine.Core.Actions.LocationX;
+ Filter.Machine.DesiredBotLocationY = Filter.Machine.Utility.BotSettings.DesiredBotLocationY = Filter.Machine.Core.Actions.LocationY;
+ LocationSetpoint.Text = $"{Filter.Machine.DesiredLandBlock.ToString("X").Substring(0, 4)} - X: { Math.Round(Filter.Machine.DesiredBotLocationX, 2)} Y: {Math.Round(Filter.Machine.DesiredBotLocationY, 2)}";
+ Filter.Machine.Utility.SaveBotSettings();
+ }
+ catch (Exception ex) { Debug.LogException(ex); }
+ }
+
private void SetHeading_Hit(object sender, EventArgs e)
{
try
@@ -228,6 +281,8 @@ private void LoadSettings()
StamThresholdText.Text = $"{StaminaThreshold.Position}%";
AdsEnabled.Checked = Filter.Machine.Utility.BotSettings.AdsEnabled;
BotEnabled.Checked = Filter.Machine.Utility.BotSettings.BotEnabled;
+ BotPositioning.Checked = Filter.Machine.Utility.BotSettings.BotPositioning;
+ LocationSetpoint.Text = $"{Filter.Machine.Utility.BotSettings.DesiredLandBlock.ToString("X").Substring(0,4)} - X: { Math.Round(Filter.Machine.Utility.BotSettings.DesiredBotLocationX, 2)} Y: {Math.Round(Filter.Machine.Utility.BotSettings.DesiredBotLocationY, 2)}";
}
catch (Exception ex)
{
@@ -297,7 +352,6 @@ private void BotEnabled_Change(object sender, EventArgs e)
try
{
Filter.Machine.Enabled = Filter.Machine.Utility.BotSettings.BotEnabled = BotEnabled.Checked;
- Debug.ToChat($"{(Filter.Machine.Utility.BotSettings.BotEnabled ? "Starting machine..." : "Stopping machine...")}");
if (Filter.Machine.Utility.BotSettings.BotEnabled)
{
Filter.Machine.ChatManager.Broadcast($"/me is running ACManager Bot {Filter.Machine.Utility.Version}. Whisper /help to get started.");
@@ -873,8 +927,11 @@ protected virtual void Dispose(bool disposing)
{
Filter = null;
BotEnabled.Change -= BotEnabled_Change;
+ ClearLocation.Hit -= ClearLocation_Hit;
+ SetLocation.Hit -= SetHeading_Hit;
RespondToGeneralChat.Change -= RespondToGeneralChat_Change;
AdsEnabled.Change -= AdsEnabled_Change;
+ BotPositioning.Change -= BotPositioning_Change;
AdInterval.Change -= AdInterval_Change;
SetHeading.Hit -= SetHeading_Hit;
DefaultHeading.Change -= DefaultHeading_Change;
diff --git a/Views/mainView.xml b/Views/mainView.xml
index ad913d1..ca30043 100644
--- a/Views/mainView.xml
+++ b/Views/mainView.xml
@@ -22,27 +22,27 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Views/portalBotView.xml b/Views/portalBotView.xml
index 269e5dd..6415452 100644
--- a/Views/portalBotView.xml
+++ b/Views/portalBotView.xml
@@ -4,15 +4,20 @@
-
+
+
+
+
+
+
-
+