diff --git a/Plugins/Mineplex.Game.Nano/src/mineplex/game/nano/game/components/compass/GameCompassComponent.java b/Plugins/Mineplex.Game.Nano/src/mineplex/game/nano/game/components/compass/GameCompassComponent.java index 0662d78eb..4b2d4fc70 100644 --- a/Plugins/Mineplex.Game.Nano/src/mineplex/game/nano/game/components/compass/GameCompassComponent.java +++ b/Plugins/Mineplex.Game.Nano/src/mineplex/game/nano/game/components/compass/GameCompassComponent.java @@ -97,6 +97,7 @@ public class GameCompassComponent extends GameComponent double dist = UtilMath.offset(player, closest); + player.setCompassTarget(closest.getLocation()); UtilTextBottom.display(C.cWhiteB + "Target: " + closestTeam.getChatColour() + closest.getName() + C.cWhiteB + " Distance: " + closestTeam.getChatColour() + _distanceFormat.format(dist), player); } } diff --git a/Plugins/Mineplex.Game.Nano/src/mineplex/game/nano/game/games/minekart/Kart.java b/Plugins/Mineplex.Game.Nano/src/mineplex/game/nano/game/games/minekart/Kart.java index 446b4fdbf..ea88e556a 100644 --- a/Plugins/Mineplex.Game.Nano/src/mineplex/game/nano/game/games/minekart/Kart.java +++ b/Plugins/Mineplex.Game.Nano/src/mineplex/game/nano/game/games/minekart/Kart.java @@ -1,7 +1,7 @@ package mineplex.game.nano.game.games.minekart; +import org.bukkit.DyeColor; import org.bukkit.Location; -import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.entity.Sheep; import org.bukkit.util.Vector; @@ -14,7 +14,7 @@ public class Kart { private final Player _driver; - private final LivingEntity _vehicle; + private final Sheep _vehicle; private int _lap, _lapCheckpoint, _lapKeyCheckpoint; @@ -28,6 +28,8 @@ public class Kart private boolean _crashed; private long _crashedAt; + private long _completedAt; + Kart(Player driver) { _driver = driver; @@ -39,6 +41,8 @@ public class Kart UtilEnt.ghost(_vehicle, true, false); UtilEnt.setFakeHead(_vehicle, true); + _vehicle.setColor(DyeColor.RED); + _vehicle.setPassenger(driver); _lap = 1; @@ -57,11 +61,17 @@ public class Kart return _driver; } - public LivingEntity getVehicle() + public Sheep getVehicle() { return _vehicle; } + public Location getParticleLocation() + { + Location location = _vehicle.getLocation().add(0, 0.3, 0); + return location.subtract(location.getDirection().multiply(0.4)); + } + public void setLap(int lap) { _lap = lap; @@ -154,15 +164,21 @@ public class Kart _driftPower = 0; } + public boolean canBoost() + { + return UtilTime.elapsed(_driftLast, 500); + } + public boolean isBoosting() { - return !UtilTime.elapsed(_driftLast, 1000); + return !UtilTime.elapsed(_driftLast, 1200); } public void setCrashed(boolean crashed) { _crashed = crashed; _driftDirection = null; + _driftPower = 0; _driftLast = 0; if (crashed) @@ -180,4 +196,14 @@ public class Kart { return _crashedAt; } + + public void complete() + { + _completedAt = System.currentTimeMillis(); + } + + public long getCompletedAt() + { + return _completedAt; + } } diff --git a/Plugins/Mineplex.Game.Nano/src/mineplex/game/nano/game/games/minekart/KartController.java b/Plugins/Mineplex.Game.Nano/src/mineplex/game/nano/game/games/minekart/KartController.java index 12532accf..a6d1247ce 100644 --- a/Plugins/Mineplex.Game.Nano/src/mineplex/game/nano/game/games/minekart/KartController.java +++ b/Plugins/Mineplex.Game.Nano/src/mineplex/game/nano/game/games/minekart/KartController.java @@ -2,9 +2,14 @@ package mineplex.game.nano.game.games.minekart; import org.bukkit.Location; import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; import org.bukkit.util.Vector; import mineplex.core.common.util.UtilAlg; +import mineplex.core.common.util.UtilParticle; +import mineplex.core.common.util.UtilParticle.ParticleType; +import mineplex.core.common.util.UtilParticle.ViewDist; public class KartController { @@ -14,73 +19,152 @@ public class KartController LEFT, RIGHT } - void applyAirDrag(Kart kart) + void applyAirResistance(Kart kart) { - if (kart.getFrontWaysInput() != 0) - { - return; - } + Vector velocity = kart.getVelocity(); - Vector velocity = kart.getVelocity().multiply(0.95); - - if (velocity.length() < 0.05) + if (kart.getFrontWaysInput() == 0 && velocity.length() < 0.1) { velocity.multiply(0); } + else + { + velocity.multiply(1 - (Math.log(velocity.length() + 1) / 50)); + } } void collideBlock(Kart kart) - { - Location location = kart.getVehicle().getLocation().add(0, 0.5, 0); - - kart.getDriver().sendMessage("y=" + kart.getVehicle().getLocation().getY() % 1); - - if (location.getBlock().getType() != Material.AIR) - { - kart.getVelocity().multiply(-1); - kart.getVelocity().setY(0.5); - kart.setCrashed(true); - } - } - - void accelerate(Kart kart) { if (kart.isCrashed()) { return; } - Vector velocity = kart.getVelocity(); - Vector facing = UtilAlg.getTrajectory(kart.getYaw(), 0).multiply(0.03 * kart.getFrontWaysInput()); - velocity.add(facing); + Location location = kart.getVehicle().getLocation(); + Block next = location.getBlock(); + + if (next.getType() != Material.AIR) + { + Vector velocity = kart.getVelocity(); + double length = velocity.length(); + + if (next.getRelative(BlockFace.UP).getType() != Material.AIR) + { + if (length > 0.4) + { + velocity.multiply(-0.6); + } + else + { + velocity.normalize().multiply(-0.4); + } + + velocity.setY(0.4); + kart.setCrashed(true); + } + else if (next.getType() == Material.SOUL_SAND) + { + if (velocity.length() > 0.3) + { + velocity.multiply(0.95); + } + } + else + { + double blockY = location.getY() % 1; + double y = 0.42 - (blockY / 3); + + velocity.add(new Vector(0, y, 0)); + } + } } - void turn(Kart kart) + void accelerate(Kart kart) { - double velocityLength = kart.getVelocity().length(); - - if (velocityLength < 0.1) + if (kart.isCrashed() || kart.getFrontWaysInput() <= 0) { return; } - float velocityInverse = (float) (2 - velocityLength); - float rotation = 3 * kart.getSidewaysInput() * velocityInverse; + Vector velocity = kart.getVelocity(); - kart.setYaw(kart.getYaw() - rotation); + if (velocity.lengthSquared() == 0) + { + kart.setVelocity(UtilAlg.getTrajectory(kart.getYaw(), 0).multiply(0.001 * kart.getFrontWaysInput())); + } + + Vector acceleration = new Vector(velocity.getX(), 0, velocity.getZ()); + + if (acceleration.lengthSquared() > 0) + { + acceleration.normalize(); + } + + velocity.add(acceleration.multiply(0.01)); + } + + void brake(Kart kart) + { + if (kart.getFrontWaysInput() >= 0) + { + return; + } + + kart.getVelocity().multiply(0.95); + } + + void turn(Kart kart) + { + Vector velocity = kart.getVelocity(); + double speed = velocity.length(); + + if (speed < 0.05) + { + return; + } + + float velocityInverse = (float) (2 - speed); + float newYaw = kart.getYaw() - (3 * kart.getSidewaysInput() * velocityInverse); + + kart.setYaw(newYaw); + + Vector turn = UtilAlg.getTrajectory(newYaw, 0); + + turn.subtract(new Vector(velocity.getX(), 0, velocity.getZ()).normalize()).multiply(0.033); + + velocity.add(turn); + + speed = (speed + (velocity.length() * 3)) / 4; + + velocity.normalize().multiply(speed); } void drift(Kart kart) { - if (kart.getDriftDirection() != null && kart.getVelocity().lengthSquared() > 0) + if (kart.isBoosting()) { - float power = 0.05F * (kart.getDriftDirection() == DriftDirection.LEFT ? kart.getSidewaysInput() : -kart.getSidewaysInput()); - - kart.setDriftPower(kart.getDriftPower() + power); + UtilParticle.PlayParticleToAll(ParticleType.FLAME, kart.getParticleLocation(), null, 0.1F, 2, ViewDist.NORMAL); } - else if (kart.getDriftPower() > 0.2) + + if (!kart.canBoost()) { - Vector facing = UtilAlg.getTrajectory(kart.getYaw(), 0).multiply(kart.getVelocity().length() + (kart.getDriftPower() / 2)); + return; + } + + if (kart.getDriftDirection() != null && kart.getVelocity().length() > 0.1) + { + float power = kart.getDriftPower() + (0.05F * (kart.getDriftDirection() == DriftDirection.LEFT ? kart.getSidewaysInput() : -kart.getSidewaysInput())); + + if (power > 0.3) + { + UtilParticle.PlayParticleToAll(ParticleType.FIREWORKS_SPARK, kart.getParticleLocation(), null, 0.1F, power > 0.6 ? 2 : 1, ViewDist.NORMAL); + } + + kart.setDriftPower(power); + } + else if (kart.getDriftPower() > 0.3) + { + Vector facing = UtilAlg.getTrajectory(kart.getYaw(), 0).multiply(0.5 + (kart.getDriftPower() * 0.6)); kart.setVelocity(facing); kart.setDriftLast(); } @@ -90,7 +174,7 @@ public class KartController } } - void applyTopSpeed(Kart kart) + void applyTopSpeed(Kart kart, int position) { if (kart.isCrashed()) { @@ -99,14 +183,11 @@ public class KartController Vector velocity = kart.getVelocity(); double length = velocity.length(); - double max = kart.isBoosting() ? 1.5 : 0.7; + double max = kart.isBoosting() ? 1.5 : 0.7 + (position / 100F); if (length > max) { - kart.setVelocity(velocity.clone() - .setY(0) - .normalize() - .multiply(max)); + velocity.multiply(0.98); } } } diff --git a/Plugins/Mineplex.Game.Nano/src/mineplex/game/nano/game/games/minekart/MineKart.java b/Plugins/Mineplex.Game.Nano/src/mineplex/game/nano/game/games/minekart/MineKart.java index d605900e7..ee936c9ac 100644 --- a/Plugins/Mineplex.Game.Nano/src/mineplex/game/nano/game/games/minekart/MineKart.java +++ b/Plugins/Mineplex.Game.Nano/src/mineplex/game/nano/game/games/minekart/MineKart.java @@ -5,6 +5,7 @@ import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import net.minecraft.server.v1_8_R3.PacketPlayInSteerVehicle; @@ -14,15 +15,20 @@ import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; +import mineplex.core.common.util.C; +import mineplex.core.common.util.F; import mineplex.core.common.util.UtilAlg; import mineplex.core.common.util.UtilEnt; import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilPlayer; +import mineplex.core.common.util.UtilTextMiddle; import mineplex.core.common.util.UtilTime; import mineplex.core.packethandler.IPacketHandler; import mineplex.core.packethandler.PacketInfo; import mineplex.core.updater.UpdateType; import mineplex.core.updater.event.UpdateEvent; import mineplex.game.nano.NanoManager; +import mineplex.game.nano.game.GamePlacements; import mineplex.game.nano.game.GameType; import mineplex.game.nano.game.SoloGame; import mineplex.game.nano.game.event.PlayerGameApplyEvent; @@ -33,14 +39,47 @@ import mineplex.game.nano.game.games.minekart.KartController.DriftDirection; public class MineKart extends SoloGame implements IPacketHandler { + private static final int LAPS = 3; + private int _spawnIndex; private final List _checkpoints, _keyCheckpoints; private Location _faceLocation; private final Map _karts; + private final List _positions; private final KartController _controller; + private final Comparator _positionSorter = (o1, o2) -> + { + boolean o1Complete = o1.getCompletedAt() != 0, o2Complete = o2.getCompletedAt() != 0; + + if (o1Complete && o2Complete) + { + return Long.compare(o1.getCompletedAt(), o2.getCompletedAt()); + } + else if (o1Complete) + { + return -1; + } + else if (o2Complete) + { + return 1; + } + + if (o1.getLap() != o2.getLap()) + { + return Integer.compare(o2.getLap(), o1.getLap()); + } + + if (o1.getLapKeyCheckpoint() != o2.getLapKeyCheckpoint()) + { + return Integer.compare(o2.getLapKeyCheckpoint(), o1.getLapKeyCheckpoint()); + } + + return Integer.compare(o2.getLapCheckpoint(), o1.getLapCheckpoint()); + }; + public MineKart(NanoManager manager) { super(manager, GameType.MINEKART, new String[] @@ -51,13 +90,72 @@ public class MineKart extends SoloGame implements IPacketHandler _checkpoints = new ArrayList<>(); _keyCheckpoints = new ArrayList<>(); _karts = new HashMap<>(); + _positions = new ArrayList<>(); _controller = new KartController(); _teamComponent.setAdjustSpawnYaw(false); _damageComponent.setDamage(false); + _playerComponent.setHideParticles(true); + manager.getPacketHandler().addPacketHandler(this, PacketPlayInSteerVehicle.class); + + _scoreboardComponent.setSidebar((player, scoreboard) -> + { + scoreboard.writeNewLine(); + + scoreboard.write(C.cYellowB + "Racers"); + + if (getState() == GameState.Prepare || _positions.isEmpty()) + { + scoreboard.write(getAllPlayers().size() + " Players"); + } + else + { + scoreboard.writeNewLine(); + + boolean hasShownPlayer = false; + + for (int i = 0; i < Math.min(_positions.size(), hasShownPlayer ? 11 : 9); i++) + { + Kart kart = _positions.get(i); + Player other = kart.getDriver(); + + if (player.equals(other)) + { + hasShownPlayer = true; + } + + scoreboard.write(kart.getLap() + " " + (player.equals(other) ? C.cGreen : (UtilPlayer.isSpectator(other) ? C.cGray + C.Strike : C.cYellow)) + other.getName()); + } + + if (!hasShownPlayer) + { + Kart kart = null; + + for (Kart other : _positions) + { + if (player.equals(other.getDriver())) + { + kart = other; + break; + } + } + + if (kart != null) + { + scoreboard.writeNewLine(); + + scoreboard.write(kart.getLap() + " " + C.cGreen + player.getName()); + } + } + } + + scoreboard.writeNewLine(); + + scoreboard.draw(); + }); } @Override @@ -99,6 +197,12 @@ public class MineKart extends SoloGame implements IPacketHandler _keyCheckpoints.sort(Comparator.comparingInt(KartCheckpoint::getIndex)); } + @Override + public boolean endGame() + { + return getAlivePlayers().isEmpty(); + } + @Override public void disable() { @@ -161,6 +265,7 @@ public class MineKart extends SoloGame implements IPacketHandler Kart kart = new Kart(player); _karts.put(player, kart); + _positions.add(kart); _worldComponent.setCreatureAllowOverride(false); }, 1); @@ -178,6 +283,11 @@ public class MineKart extends SoloGame implements IPacketHandler { LivingEntity vehicle = kart.getVehicle(); + if (!vehicle.isValid()) + { + return; + } + if (vehicle.getPassenger() == null || !vehicle.getPassenger().equals(player)) { vehicle.setPassenger(player); @@ -202,9 +312,25 @@ public class MineKart extends SoloGame implements IPacketHandler if (checkpoint.getIndex() == 0 && kart.getLapKeyCheckpoint() == _keyCheckpoints.size() - 1) { - kart.setLap(kart.getLap() + 1); + int lap = kart.getLap() + 1; + kart.setLapKeyCheckpoint(0); - player.sendMessage("Lap = " + kart.getLap()); + + if (lap == LAPS + 1) + { + kart.complete(); + announce(F.main(getManager().getName(), F.name(player.getName()) + " completed the race in " + F.time(UtilTime.MakeStr(kart.getCompletedAt() - getStateTime())) + "!"), Sound.FIREWORK_BLAST); + addSpectator(player, false, true); + } + else + { + kart.setLap(lap); + + boolean finalLap = lap == LAPS; + + UtilTextMiddle.display(C.cYellowB + "Lap " + lap, finalLap ? C.cAquaB + "FINAL LAP" : "", 10, 40, 10, player); + player.sendMessage(F.main(getManager().getName(), "Lap " + F.count(lap) + (finalLap ? F.color(" FINAL LAP", C.cAquaB) : "") + "!")); + } } } @@ -215,28 +341,27 @@ public class MineKart extends SoloGame implements IPacketHandler if (UtilTime.elapsed(kart.getCrashedAt(), 1000) && UtilEnt.isGrounded(kart.getVehicle())) { kart.setCrashed(false); - player.sendMessage("setCrashed(false)"); } else { - player.sendMessage("canControl = false"); canControl = false; } } - _controller.applyAirDrag(kart); - - _controller.collideBlock(kart); + _controller.applyAirResistance(kart); // Accelerate if (canControl) { - _controller.turn(kart); _controller.accelerate(kart); + _controller.brake(kart); _controller.drift(kart); - _controller.applyTopSpeed(kart); + _controller.turn(kart); + _controller.applyTopSpeed(kart, _positions.indexOf(kart)); } + _controller.collideBlock(kart); + double velocityLength = kart.getVelocity().length(); location.add(kart.getVelocity()); @@ -248,6 +373,8 @@ public class MineKart extends SoloGame implements IPacketHandler player.setLevel((int) (velocityLength * 100)); player.setExp(kart.getDriftPower()); }); + + _positions.sort(_positionSorter); } @EventHandler @@ -264,6 +391,14 @@ public class MineKart extends SoloGame implements IPacketHandler } } + @Override + public GamePlacements getGamePlacements() + { + return GamePlacements.fromTeamPlacements(_positions.stream() + .map(Kart::getDriver) + .collect(Collectors.toList())); + } + public KartCheckpoint getCheckpoint(int index) { return _checkpoints.stream()