Modularise /missile

This commit is contained in:
UnknownShadow200 2017-06-06 13:40:54 +10:00
parent d087fd3049
commit a6cd642356
5 changed files with 102 additions and 80 deletions

View File

@ -14,6 +14,7 @@ permissions and limitations under the Licenses.
*/
using System;
using System.Windows.Forms;
using MCGalaxy.Gui.Popups;
namespace MCGalaxy.Gui {

View File

@ -291,7 +291,7 @@ namespace MCGalaxy {
return c;
}
static int Hex(char value) {
public static int Hex(char value) {
if (value >= '0' && value <= '9')
return (int)(value - '0');
if (value >= 'a' && value <= 'f')

View File

@ -56,7 +56,7 @@ namespace MCGalaxy.Commands.Fun {
pos.Z = (ushort)Math.Round(start.Z + (double)(dir.Z * t));
byte by = p.level.GetTile(pos.X, pos.Y, pos.Z);
if (by != Block.air && !allBlocks.Contains(pos) && HandlesHitBlock(p, by, bp, pos, true))
if (by != Block.air && !allBlocks.Contains(pos) && HandlesHitBlock(p, by, bp.ending, pos, true))
break;
p.level.Blockchange(pos.X, pos.Y, pos.Z, block);

View File

@ -21,7 +21,7 @@ using System.Threading;
using MCGalaxy.Drawing.Ops;
using MCGalaxy.Maths;
namespace MCGalaxy.Commands.Fun {
namespace MCGalaxy.Commands.Fun {
public sealed class CmdMissile : WeaponCmd {
public override string name { get { return "missile"; } }
@ -34,93 +34,115 @@ namespace MCGalaxy.Commands.Fun {
}
p.RevertBlock(x, y, z);
if (!CommandParser.IsBlockAllowed(p, "place ", block)) return;
MissileArgs args = new MissileArgs();
args.player = p;
args.block = block;
CatchPos bp = (CatchPos)p.blockchangeObject;
args.ending = bp.ending;
args.pos = MakePos(p);
Thread gunThread = new Thread(() => DoShoot(p, block));
Thread gunThread = new Thread(() => DoShoot(args));
gunThread.Name = "MCG_Missile";
gunThread.Start();
}
class MissileArgs {
public Player player;
public ExtBlock block;
public EndType ending;
public Vec3U16 pos;
public List<Vec3U16> previous = new List<Vec3U16>();
public List<Vec3U16> allBlocks = new List<Vec3U16>();
public List<Vec3S32> buffer = new List<Vec3S32>();
public int iterations;
}
void DoShoot(Player p, ExtBlock block) {
CatchPos bp = (CatchPos)p.blockchangeObject;
List<Vec3U16> previous = new List<Vec3U16>(), allBlocks = new List<Vec3U16>();
Vec3U16 pos = MakePos(p);
int total = 0;
List<Vec3S32> buffer = new List<Vec3S32>(2);
void DoShoot(MissileArgs args) {
Player p = args.player;
while (true) {
Vec3U16 start = MakePos(p);
total++;
Vec3F32 dir = DirUtils.GetFlatDirVector(p.Rot.RotY, p.Rot.HeadX);
args.iterations++;
Vec3U16 target = MissileTarget(args);
FindNext(target, ref args.pos, args.buffer);
Vec3U16 lookedAt;
int i;
for (i = 1; ; i++) {
lookedAt.X = (ushort)Math.Round(start.X + (double)(dir.X * i));
lookedAt.Y = (ushort)Math.Round(start.Y + (double)(dir.Y * i));
lookedAt.Z = (ushort)Math.Round(start.Z + (double)(dir.Z * i));
byte tile = p.level.GetTile(lookedAt.X, lookedAt.Y, lookedAt.Z);
if (tile == Block.Invalid) break;
if (tile != Block.air && !allBlocks.Contains(lookedAt) && HandlesHitBlock(p, tile, bp, pos, false))
break;
Player hit = GetPlayer(p, lookedAt, true);
if (hit != null) {
lookedAt = MakePos(hit); break;
}
}
lookedAt.X = (ushort)Math.Round(start.X + (double)(dir.X * (i - 1)));
lookedAt.Y = (ushort)Math.Round(start.Y + (double)(dir.Y * (i - 1)));
lookedAt.Z = (ushort)Math.Round(start.Z + (double)(dir.Z * (i - 1)));
FindNext(lookedAt, ref pos, buffer);
byte by = p.level.GetTile(pos.X, pos.Y, pos.Z);
if (total > 3) {
if (by != Block.air && !allBlocks.Contains(pos) && HandlesHitBlock(p, by, bp, pos, true))
break;
p.level.Blockchange(pos.X, pos.Y, pos.Z, block);
previous.Add(pos);
allBlocks.Add(pos);
Player hitP = GetPlayer(p, pos, true);
if (hitP != null) {
if (p.level.physics >= 3 && bp.ending >= EndType.Explode) {
hitP.HandleDeath((ExtBlock)Block.stone, " was blown up by " + p.ColoredName, true);
} else {
hitP.HandleDeath((ExtBlock)Block.stone, " was hit a missile from " + p.ColoredName);
}
break;
}
if (pos.X == lookedAt.X && pos.Y == lookedAt.Y && pos.Z == lookedAt.Z) {
if (p.level.physics >= 3 && bp.ending >= EndType.Explode && p.allowTnt) {
p.level.MakeExplosion(lookedAt.X, lookedAt.Y, lookedAt.Z, 2);
break;
}
}
if (previous.Count > 12) {
p.level.Blockchange(previous[0].X, previous[0].Y, previous[0].Z, ExtBlock.Air, true);
previous.RemoveAt(0);
}
Thread.Sleep(100);
}
if (args.iterations <= 3) continue;
if (!MoveMissile(args, args.pos, target)) break;
Thread.Sleep(100);
}
if (bp.ending == EndType.Teleport) {
int index = previous.Count - 3;
if (index >= 0 && index < previous.Count)
DoTeleport(p, previous[index]);
if (args.ending == EndType.Teleport) {
int index = args.previous.Count - 3;
if (index >= 0 && index < args.previous.Count)
DoTeleport(p, args.previous[index]);
}
foreach (Vec3U16 pos1 in previous) {
foreach (Vec3U16 pos1 in args.previous) {
p.level.Blockchange(pos1.X, pos1.Y, pos1.Z, ExtBlock.Air, true);
Thread.Sleep(100);
}
}
static Vec3U16 MissileTarget(MissileArgs args) {
Player p = args.player;
Vec3U16 start = MakePos(p);
Vec3F32 dir = DirUtils.GetFlatDirVector(p.Rot.RotY, p.Rot.HeadX);
Vec3U16 target;
int i;
for (i = 1; ; i++) {
target.X = (ushort)Math.Round(start.X + (double)(dir.X * i));
target.Y = (ushort)Math.Round(start.Y + (double)(dir.Y * i));
target.Z = (ushort)Math.Round(start.Z + (double)(dir.Z * i));
byte tile = p.level.GetTile(target.X, target.Y, target.Z);
if (tile == Block.Invalid) break;
if (tile != Block.air && !args.allBlocks.Contains(target) && HandlesHitBlock(p, tile, args.ending, target, false))
break;
Player hit = GetPlayer(p, target, true);
if (hit != null) return MakePos(hit);
}
target.X = (ushort)Math.Round(start.X + (double)(dir.X * (i - 1)));
target.Y = (ushort)Math.Round(start.Y + (double)(dir.Y * (i - 1)));
target.Z = (ushort)Math.Round(start.Z + (double)(dir.Z * (i - 1)));
return target;
}
static bool MoveMissile(MissileArgs args, Vec3U16 pos, Vec3U16 target) {
Player p = args.player;
byte tile = p.level.GetTile(pos.X, pos.Y, pos.Z);
if (tile != Block.air && !args.allBlocks.Contains(pos) && HandlesHitBlock(p, tile, args.ending, pos, true))
return false;
p.level.Blockchange(pos.X, pos.Y, pos.Z, args.block);
args.previous.Add(pos);
args.allBlocks.Add(pos);
Player hitP = GetPlayer(p, pos, true);
if (hitP != null) {
if (p.level.physics >= 3 && args.ending >= EndType.Explode) {
hitP.HandleDeath((ExtBlock)Block.stone, " was blown up by " + p.ColoredName, true);
} else {
hitP.HandleDeath((ExtBlock)Block.stone, " was hit a missile from " + p.ColoredName);
}
return false;
}
if (pos == target && p.level.physics >= 3 && args.ending >= EndType.Explode) {
p.level.MakeExplosion(target.X, target.Y, target.Z, 2);
return false;
}
if (args.previous.Count > 12) {
p.level.Blockchange(args.previous[0].X, args.previous[0].Y, args.previous[0].Z, ExtBlock.Air, true);
args.previous.RemoveAt(0);
}
return true;
}
static Vec3U16 MakePos(Player p) {
return (Vec3U16)p.Pos.BlockCoords;
}

View File

@ -137,7 +137,7 @@ namespace MCGalaxy.Commands.Fun {
protected abstract void PlacedMark(Player p, ushort x, ushort y, ushort z, ExtBlock block);
protected Player GetPlayer(Player p, Vec3U16 pos, bool skipSelf) {
protected static Player GetPlayer(Player p, Vec3U16 pos, bool skipSelf) {
Player[] players = PlayerInfo.Online.Items;
foreach (Player pl in players) {
if (pl.level != p.level) continue;
@ -161,11 +161,10 @@ namespace MCGalaxy.Commands.Fun {
}
}
protected bool HandlesHitBlock(Player p, byte type, CatchPos bp, Vec3U16 pos, bool doExplode) {
if (p.level.physics < 2 || bp.ending == EndType.Teleport
|| bp.ending == EndType.Normal) return true;
protected static bool HandlesHitBlock(Player p, byte type, EndType ending, Vec3U16 pos, bool doExplode) {
if (p.level.physics < 2 || ending == EndType.Teleport || ending == EndType.Normal) return true;
if (bp.ending == EndType.Destroy) {
if (ending == EndType.Destroy) {
if ((!Block.FireKill(type) && !Block.NeedRestart(type)) && type != Block.glass) {
return true;
}