diff --git a/Bots/Instructions.cs b/Bots/Instructions.cs
index 0ec1abd7c..b23532d10 100644
--- a/Bots/Instructions.cs
+++ b/Bots/Instructions.cs
@@ -143,53 +143,5 @@ namespace MCGalaxy.Bots {
}
bot.NextInstruction(); return true;
}
-
-
- internal static void DoKill(PlayerBot bot) {
- ushort x = (ushort)Math.Round((decimal)bot.pos[0] / 32);
- ushort y = (ushort)((bot.pos[1] - 33) / 32);
- ushort z = (ushort)Math.Round((decimal)bot.pos[2] / 32);
- Player[] players = PlayerInfo.Online.Items;
-
- foreach (Player p in players) {
- if ((ushort)(p.pos[0] / 32) == x
- && Math.Abs((ushort)(p.pos[1] / 32) - y) < 2
- && (ushort)(p.pos[2] / 32) == z) {
- p.HandleDeath(Block.Zero);
- }
- }
- }
-
- internal static void DoHunt(PlayerBot bot) {
- int dist = 75 * 32;
- Player[] players = PlayerInfo.Online.Items;
- foreach (Player p in players) {
- if (p.level != bot.level || p.invincible) continue;
-
- int dx = p.pos[0] - bot.pos[0], dy = p.pos[1] - bot.pos[1], dz = p.pos[2] - bot.pos[2];
- int curDist = Math.Abs(dx) + Math.Abs(dy) + Math.Abs(dz);
- if (curDist >= dist) continue;
-
- dist = curDist;
- bot.foundPos = p.pos;
- bot.movement = true;
-
- Vec3F32 dir = new Vec3F32(dx, dy, dz);
- dir = Vec3F32.Normalise(dir);
- byte yaw, pitch;
- DirUtils.GetYawPitch(dir, out yaw, out pitch);
-
- // If we are very close to a player, switch from trying to look
- // at them to just facing the opposite direction to them
- if (Math.Abs(dx) >= 4 || Math.Abs(dz) >= 4) {
- bot.rot[0] = yaw;
- } else if (p.rot[0] < 128) {
- bot.rot[0] = (byte)(p.rot[0] + 128);
- } else {
- bot.rot[0] = (byte)(p.rot[0] - 128);
- }
- bot.rot[1] = pitch;
- }
- }
}
}
diff --git a/Bots/Instructions/ComplexInstructions.cs b/Bots/Instructions/ComplexInstructions.cs
index b33efcd1e..4f27d93d7 100644
--- a/Bots/Instructions/ComplexInstructions.cs
+++ b/Bots/Instructions/ComplexInstructions.cs
@@ -16,8 +16,80 @@
permissions and limitations under the Licenses.
*/
using System;
-using System.Collections.Generic;
-using System.IO;
namespace MCGalaxy.Bots {
+
+ /// Causes the bot to move towards the closest human, within a defined search radius.
+ public sealed class HuntInstruction : BotInstruction {
+ public override string Name { get { return "Hunt"; } }
+
+ const int searchRadius = 75;
+ public override bool Execute(PlayerBot bot, InstructionData data) {
+ int dist = searchRadius * 32;
+ Player[] players = PlayerInfo.Online.Items;
+ Player closest = null;
+
+ foreach (Player p in players) {
+ if (p.level != bot.level || p.invincible) continue;
+
+ int dx = p.pos[0] - bot.pos[0], dy = p.pos[1] - bot.pos[1], dz = p.pos[2] - bot.pos[2];
+ int curDist = Math.Abs(dx) + Math.Abs(dy) + Math.Abs(dz);
+ if (curDist >= dist) continue;
+ closest = p;
+ }
+
+ if (closest == null) return true;
+ MoveTowards(bot, closest);
+ return false;
+ }
+
+ static void MoveTowards(PlayerBot bot, Player p) {
+ int dx = p.pos[0] - bot.pos[0], dy = p.pos[1] - bot.pos[1], dz = p.pos[2] - bot.pos[2];
+ bot.foundPos = p.pos;
+ bot.movement = true;
+
+ Vec3F32 dir = new Vec3F32(dx, dy, dz);
+ dir = Vec3F32.Normalise(dir);
+ byte yaw, pitch;
+ DirUtils.GetYawPitch(dir, out yaw, out pitch);
+
+ // If we are very close to a player, switch from trying to look
+ // at them to just facing the opposite direction to them
+ if (Math.Abs(dx) >= 4 || Math.Abs(dz) >= 4) {
+ bot.rot[0] = yaw;
+ } else if (p.rot[0] < 128) {
+ bot.rot[0] = (byte)(p.rot[0] + 128);
+ } else {
+ bot.rot[0] = (byte)(p.rot[0] - 128);
+ }
+ bot.rot[1] = pitch;
+ }
+
+ public override InstructionData Parse(string[] args) {
+ return default(InstructionData);
+ }
+ }
+
+ /// Causes the bot to kill nearby humans.
+ public sealed class KillInstruction : BotInstruction {
+ public override string Name { get { return "Kill"; } }
+
+ public override bool Execute(PlayerBot bot, InstructionData data) {
+ Player[] players = PlayerInfo.Online.Items;
+ foreach (Player p in players) {
+ int dx = Math.Abs(bot.pos[0] - p.pos[0]);
+ int dy = Math.Abs(bot.pos[1] - p.pos[1]);
+ int dz = Math.Abs(bot.pos[2] - p.pos[2]);
+
+ if (dx <= 8 && dy <= 16 && dz <= 8) {
+ p.HandleDeath(Block.Zero);
+ }
+ }
+ return true;
+ }
+
+ public override InstructionData Parse(string[] args) {
+ return default(InstructionData);
+ }
+ }
}
diff --git a/Bots/Instructions/Instruction.cs b/Bots/Instructions/Instruction.cs
index cf2b8a0a9..66c0887c7 100644
--- a/Bots/Instructions/Instruction.cs
+++ b/Bots/Instructions/Instruction.cs
@@ -22,7 +22,7 @@ using System.IO;
namespace MCGalaxy.Bots {
/// Represents an action that a bot will perform
- public abstract class Instruction {
+ public abstract class BotInstruction {
/// Gets the identifying name for this instruction.
public abstract string Name { get; }
@@ -34,12 +34,25 @@ namespace MCGalaxy.Bots {
/// Parses the given line which contains the metadata for this instruction.
public abstract InstructionData Parse(string[] args);
+
+ /// All instructions that bots can execute.
+ public static List Instructions = new List() {
+ new HuntInstruction(), new KillInstruction(),
+ };
+
+ /// Finds the instruction which has the given identifying name.
+ public static BotInstruction Find(string name) {
+ foreach (BotInstruction ins in Instructions) {
+ if (ins.Name.CaselessEq(name)) return ins;
+ }
+ return null;
+ }
}
public struct InstructionData {
public string type, newscript;
public int seconds, rotspeed;
public ushort x, y, z;
- public byte rotx, roty;
+ public byte rotx, roty;
}
}
diff --git a/Bots/PlayerBot.cs b/Bots/PlayerBot.cs
index 6686bb86f..3c639cccf 100644
--- a/Bots/PlayerBot.cs
+++ b/Bots/PlayerBot.cs
@@ -206,11 +206,17 @@ namespace MCGalaxy {
// Script handling
void BotTimerFunc(object sender, ElapsedEventArgs e) {
- if (kill) Instructions.DoKill(this);
+ if (kill) {
+ InstructionData data = default(InstructionData);
+ BotInstruction.Find("kill").Execute(this, data);
+ }
movement = false;
if (Waypoints.Count == 0) {
- if (hunt) Instructions.DoHunt(this);
+ if (hunt) {
+ InstructionData data = default(InstructionData);
+ BotInstruction.Find("hunt").Execute(this, data);
+ }
} else {
bool doNextInstruction = !DoInstruction();
if (cur == Waypoints.Count) cur = 0;
@@ -225,8 +231,11 @@ namespace MCGalaxy {
bool DoInstruction() {
Func instruction;
- if (!Instructions.Defined.TryGetValue(Waypoints[cur].type, out instruction))
- return false;
+ if (!Instructions.Defined.TryGetValue(Waypoints[cur].type, out instruction)) {
+ BotInstruction botIns = BotInstruction.Find(Waypoints[cur].type);
+ if (botIns == null) return false;
+ return botIns.Execute(this, Waypoints[cur]);
+ }
return instruction(this);
}
diff --git a/Bots/ScriptFile.cs b/Bots/ScriptFile.cs
index da3b1e601..17cfd9be8 100644
--- a/Bots/ScriptFile.cs
+++ b/Bots/ScriptFile.cs
@@ -27,7 +27,7 @@ namespace MCGalaxy.Bots {
string[] codes = File.ReadAllLines(file);
if (codes[0] != "#Version 2") { Player.Message(p, "Invalid file version. Remake"); return false; }
- PlayerBot.InstructionData newPos = new PlayerBot.InstructionData();
+ InstructionData newPos = new InstructionData();
try { bot.Waypoints.Clear(); } catch { }
bot.cur = 0; bot.countdown = 0; bot.movementSpeed = 3;