From c25602b429b28f06d2d4f6a6aee8aa2f32faf914 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Fri, 9 Sep 2016 19:15:54 +1000 Subject: [PATCH] Bots should rotate when hunting to face the target player. --- Bots/Instructions.cs | 25 +++++++++++++++++------- Bots/PlayerBot.cs | 2 +- Commands/Fun/CmdGun.cs | 2 +- Commands/Fun/CmdMissile.cs | 2 +- Commands/Fun/WeaponCmd.cs | 2 +- util/Math/DirUtils.cs | 39 +++++++++++++------------------------- 6 files changed, 35 insertions(+), 37 deletions(-) diff --git a/Bots/Instructions.cs b/Bots/Instructions.cs index 44696f400..0ec1abd7c 100644 --- a/Bots/Instructions.cs +++ b/Bots/Instructions.cs @@ -165,19 +165,30 @@ namespace MCGalaxy.Bots { Player[] players = PlayerInfo.Online.Items; foreach (Player p in players) { if (p.level != bot.level || p.invincible) continue; - int curDist = Math.Abs(p.pos[0] - bot.pos[0]) + Math.Abs(p.pos[1] - bot.pos[1]) + Math.Abs(p.pos[2] - bot.pos[2]); + + 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.foundRot = p.rot; bot.movement = true; - bot.rot[1] = (byte)(255 - bot.foundRot[1]); - if (bot.foundRot[0] < 128) - bot.rot[0] = (byte)(bot.foundRot[0] + 128); - else - bot.rot[0] = (byte)(bot.foundRot[0] - 128); + 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/PlayerBot.cs b/Bots/PlayerBot.cs index 2968ca90d..9a6a5c233 100644 --- a/Bots/PlayerBot.cs +++ b/Bots/PlayerBot.cs @@ -45,7 +45,7 @@ namespace MCGalaxy { public struct Pos { public string type, newscript; public int seconds, rotspeed; public ushort x, y, z; public byte rotx, roty; } public ushort[] pos = new ushort[3], oldpos = new ushort[3], foundPos = new ushort[3]; - public byte[] rot = new byte[2], oldrot = new byte[2], foundRot = new byte[2]; + public byte[] rot = new byte[2], oldrot = new byte[2]; public bool movement = false; public int movementSpeed = 3; internal bool jumping = false; diff --git a/Commands/Fun/CmdGun.cs b/Commands/Fun/CmdGun.cs index c8d91e04a..6019eb144 100644 --- a/Commands/Fun/CmdGun.cs +++ b/Commands/Fun/CmdGun.cs @@ -38,7 +38,7 @@ namespace MCGalaxy.Commands { void DoShoot(Player p, byte type, byte extType) { CatchPos bp = (CatchPos)p.blockchangeObject; - Vec3F32 dir = DirUtils.GetDirVector(p.rot[0], p.rot[1]); + Vec3F32 dir = DirUtils.GetFlatDirVector(p.rot[0], p.rot[1]); double bigDiag = Math.Sqrt(Math.Sqrt(p.level.Width * p.level.Width + p.level.Length * p.level.Length) + p.level.Height * p.level.Height + p.level.Width * p.level.Width); diff --git a/Commands/Fun/CmdMissile.cs b/Commands/Fun/CmdMissile.cs index c07912f03..773d343cd 100644 --- a/Commands/Fun/CmdMissile.cs +++ b/Commands/Fun/CmdMissile.cs @@ -51,7 +51,7 @@ namespace MCGalaxy.Commands { while (true) { Vec3U16 start = MakePos(p); total++; - Vec3F32 dir = DirUtils.GetDirVector(p.rot[0], p.rot[1]); + Vec3F32 dir = DirUtils.GetFlatDirVector(p.rot[0], p.rot[1]); Vec3U16 lookedAt; int i; diff --git a/Commands/Fun/WeaponCmd.cs b/Commands/Fun/WeaponCmd.cs index 54235b922..709922eb6 100644 --- a/Commands/Fun/WeaponCmd.cs +++ b/Commands/Fun/WeaponCmd.cs @@ -79,7 +79,7 @@ namespace MCGalaxy.Commands { void DoAim(Player p) { List lastSent = new List(), toSend = new List(); while (p.aiming) { - Vec3F32 dir = DirUtils.GetDirVector(p.rot[0], p.rot[1]); + Vec3F32 dir = DirUtils.GetFlatDirVector(p.rot[0], p.rot[1]); try { ushort x = (ushort)Math.Round((ushort)(p.pos[0] / 32) + dir.X * 3); ushort y = (ushort)Math.Round((ushort)(p.pos[1] / 32) + dir.Y * 3); diff --git a/util/Math/DirUtils.cs b/util/Math/DirUtils.cs index 1040729a3..d7720f4c7 100644 --- a/util/Math/DirUtils.cs +++ b/util/Math/DirUtils.cs @@ -75,7 +75,7 @@ namespace MCGalaxy { dirY = -1; } - public static Vec3F32 GetDirVector(byte yaw, byte pitch) { + public static Vec3F32 GetFlatDirVector(byte yaw, byte pitch) { const double packed2Rad = (2 * Math.PI) / 256.0; double x = Math.Sin(yaw * packed2Rad); double y = -Math.Sin(pitch * packed2Rad); // e.g. 64 -> PI/2, result should be -1 @@ -83,7 +83,7 @@ namespace MCGalaxy { return new Vec3F32((float)x, (float)y, (float)z); } - public static Vec3F32 GetAdjDirVector(byte yaw, byte pitch) { + public static Vec3F32 GetDirVector(byte yaw, byte pitch) { const double packed2Rad = (2 * Math.PI) / 256.0; double x = Math.Sin(yaw * packed2Rad) * Math.Cos(pitch * packed2Rad); double y = -Math.Sin(pitch * packed2Rad); @@ -92,35 +92,22 @@ namespace MCGalaxy { } public static void GetYawPitch(Vec3F32 dir, out byte yaw, out byte pitch) { - // y = -sin(pitch) -> pitch = arcsin(-y) - // x = sin(yaw) * cos(pitch) -> yaw = arcsin(x/cos(pitch)) - // z = -cos(yaw) * cos(pitch) -> yaw = arccos(-z/cos(pitch)) + // y = -sin(pitch) -> pitch = arcsin(-y) + // x = sin(yaw) -> yaw = arcsin(x) + // z = -cos(yaw) -> yaw = arccos(-z) + + // We ignore the cos(pitch) multiplication by the x/z components, since + // this does not affect the resulting yaw const double rad2Packed = 256.0 / (2 * Math.PI); + // NOTE: This conversion method **does** lose information - // a) If pitch is 0, yaw cannot be properly recalculated + // a) If x and z are 0, yaw cannot be properly recalculated // b) Pitch will always be from 0-64 or 192-256, therefore flipped heads lost // However since we have X/Z, this problem does not occur for yaw, // as we can use both values to determine which side of unit circle yaw is in - // c) Resulting yaw/pitch may be 1 or 2 values off due to rounding - - double pitchRad = Math.Asin(-dir.Y); - double cosPitch = Math.Cos(pitchRad); - double yawRad = Math.Asin(dir.X / cosPitch); - yaw = (byte)(yawRad * rad2Packed); - pitch = (byte)(pitchRad * rad2Packed); - yaw = AdjustYaw(dir, yaw); + // c) Resulting yaw/pitch may be 1 or 2 values off due to rounding + yaw = (byte)(Math.Atan2(dir.X, -dir.Z) * rad2Packed); + pitch = (byte)(Math.Asin(-dir.Y) * rad2Packed); } - - static byte AdjustYaw(Vec3F32 dir, byte yaw) { - // Other side of unit circle - if (dir.Z > 0) return (byte)(128 - yaw); - const double epsilon = 0.0000001; - - if (dir.Z >= 0 && dir.Z < +epsilon) return 192; // exactly +X - if (dir.Z <= 0 && dir.Z > -epsilon) return 64; // exactly -X - if (dir.X >= 0 && dir.X < +epsilon) return 0; // exactly -Z - if (dir.X <= 0 && dir.X > -epsilon) return 128; // exactly +Z - return yaw; - } } }