Reimplement wave AI, split out some UI code into a ui module, update TODO
This commit is contained in:
parent
2f63695ee9
commit
75debe1905
24
TODO.md
24
TODO.md
@ -2,19 +2,33 @@
|
||||
|
||||
[X] Mobs spawn in waves
|
||||
[X] Mobs move towards goal
|
||||
[ ] Mobs carry bomb to goal
|
||||
[X] Mobs carry bomb to goal
|
||||
[X] Mobs arm bomb
|
||||
[X] Bomb explodes
|
||||
|
||||
# Malloc Beta
|
||||
|
||||
[ ] Join games
|
||||
[ ] Leave games
|
||||
[ ] One arena config
|
||||
|
||||
# Scaled waves
|
||||
|
||||
[ ] Weaker mobs, more of them
|
||||
[ ] Mob categories
|
||||
[ ] Spawnpoint categories
|
||||
|
||||
# UX
|
||||
|
||||
[X] Wave boss bar
|
||||
[X] Mob count boss bar
|
||||
[X] Stage titles
|
||||
[ ] EXPLOSIONS
|
||||
[X] EXPLOSIONS
|
||||
[ ] Target catches on fire more it is lit
|
||||
[ ] Colored titles
|
||||
[ ] Clickable /ready in chat
|
||||
[ ] Sidebar
|
||||
[ ] List of mobs in next wave
|
||||
|
||||
# Social
|
||||
|
||||
@ -27,9 +41,9 @@
|
||||
# Mechanics
|
||||
|
||||
[ ] Coin drops
|
||||
[ ] Mob tracking should prioritize bomb
|
||||
[ ] Mobs recover dropped bombs
|
||||
[ ] Bomb carriers are slower
|
||||
[X] Mob tracking should prioritize bomb
|
||||
[X] Mobs recover dropped bombs
|
||||
[X] Bomb carriers are slower
|
||||
[ ] Bonus coins for complete coin pickup
|
||||
[ ] Infinite weapons + armor
|
||||
[ ] Ammo/health spawns
|
||||
|
@ -40,14 +40,6 @@ public class GameEventHandler implements Listener {
|
||||
|
||||
@EventHandler
|
||||
public void onEntityDamage(EntityDamageEvent evt) {
|
||||
if (evt.getEntity() instanceof Player) {
|
||||
Player player = (Player)evt.getEntity();
|
||||
if (player.getHealth() - evt.getFinalDamage() <= 0) {
|
||||
evt.setCancelled(true);
|
||||
m_runner.handlePlayerDeath(player);
|
||||
}
|
||||
} else {
|
||||
m_runner.handleEntityDamage(evt);
|
||||
}
|
||||
m_runner.handleEntityDamage(evt);
|
||||
}
|
||||
}
|
||||
|
@ -22,21 +22,24 @@ public class SetStageCommand implements CommandExecutor {
|
||||
GameRunner runner = m_plugin.getRunnerForWorld(world);
|
||||
String stateName = args[0].toLowerCase();
|
||||
boolean ret = false;
|
||||
if (stateName.equals("idle")) {
|
||||
ret = runner.requestTransition(GameRunner.Stage.Idle);
|
||||
} else if (stateName.equals("warmup")) {
|
||||
ret = runner.requestTransition(GameRunner.Stage.Warmup);
|
||||
} else if (stateName.equals("playing")) {
|
||||
ret = runner.requestTransition(GameRunner.Stage.Playing);
|
||||
} else if (stateName.equals("gameover")) {
|
||||
ret = runner.requestTransition(GameRunner.Stage.GameOver);
|
||||
GameRunner.Stage decodedStage = null;
|
||||
GameRunner.Stage stages[] = GameRunner.Stage.Idle.getDeclaringClass().getEnumConstants();
|
||||
for(GameRunner.Stage stage : stages) {
|
||||
if (stage.toString().toLowerCase().equals(stateName)) {
|
||||
decodedStage = stage;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (decodedStage != null) {
|
||||
sender.sendMessage("Requesting transition to " + decodedStage);
|
||||
if (!runner.requestTransition(decodedStage)) {
|
||||
sender.sendMessage("Could not transition to " + decodedStage);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
sender.sendMessage("Unknown state " + stateName);
|
||||
return false;
|
||||
}
|
||||
if (!ret) {
|
||||
sender.sendMessage("Could not set state to " + stateName);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
30
src/main/java/gg/malloc/defense/engine/BombFuse.java
Normal file
30
src/main/java/gg/malloc/defense/engine/BombFuse.java
Normal file
@ -0,0 +1,30 @@
|
||||
package gg.malloc.defense.engine;
|
||||
|
||||
public class BombFuse {
|
||||
int m_bombFuseCount = 0;
|
||||
int m_bombFuseTarget = 10;
|
||||
|
||||
public double getProgress() {
|
||||
return Math.max(0.0, Math.min(1.0, (double)m_bombFuseCount / (double)m_bombFuseTarget));
|
||||
}
|
||||
|
||||
public boolean isLit() {
|
||||
return m_bombFuseCount > 0;
|
||||
}
|
||||
|
||||
public boolean isExploded() {
|
||||
return m_bombFuseCount > m_bombFuseTarget;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
m_bombFuseCount = 0;
|
||||
}
|
||||
|
||||
public void tickLit() {
|
||||
m_bombFuseCount += 1;
|
||||
}
|
||||
|
||||
public void tickDecay() {
|
||||
m_bombFuseCount -= 1;
|
||||
}
|
||||
}
|
@ -1,30 +1,35 @@
|
||||
package gg.malloc.defense.engine;
|
||||
|
||||
import gg.malloc.defense.model.Game;
|
||||
import gg.malloc.defense.model.Arena;
|
||||
import gg.malloc.defense.model.Game;
|
||||
import gg.malloc.defense.model.Spawner;
|
||||
import gg.malloc.defense.model.Wave;
|
||||
|
||||
import gg.malloc.defense.ui.BombCarrier;
|
||||
import gg.malloc.defense.ui.BossBars;
|
||||
|
||||
import gg.malloc.defense.Plugin;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.SoundCategory;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.boss.BarColor;
|
||||
import org.bukkit.boss.BarStyle;
|
||||
import org.bukkit.boss.BossBar;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
import org.bukkit.event.entity.EntityTargetEvent;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.EntityTargetEvent;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.ArmorStand;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.attribute.AttributeModifier;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
public class GameRunner {
|
||||
Arena m_arena;
|
||||
@ -32,18 +37,11 @@ public class GameRunner {
|
||||
Stage m_stage;
|
||||
Plugin m_plugin;
|
||||
|
||||
BossBar m_gameBar = Bukkit.createBossBar("Malloc Defense", BarColor.PURPLE, BarStyle.SOLID);
|
||||
BossBar m_waveBar = Bukkit.createBossBar("Malloc Defense", BarColor.PURPLE, BarStyle.SOLID);
|
||||
BossBar m_bombBar = Bukkit.createBossBar("Bomb HP", BarColor.RED, BarStyle.SOLID);
|
||||
|
||||
BukkitTask m_countdownTask;
|
||||
|
||||
MobManager m_mobs;
|
||||
WaveManager m_waves;
|
||||
PlayerManager m_players;
|
||||
|
||||
LivingEntity m_bombTarget = null;
|
||||
int m_bombHP = 100;
|
||||
BombFuse m_bombFuse;
|
||||
|
||||
Logger m_log;
|
||||
|
||||
@ -55,126 +53,96 @@ public class GameRunner {
|
||||
GameOver
|
||||
}
|
||||
|
||||
class WaveManager {
|
||||
int m_currentWaveNum = 0;
|
||||
int m_currentBatch = 0;
|
||||
Wave m_currentWave = null;
|
||||
Game m_game;
|
||||
|
||||
WaveManager(Game game) {
|
||||
m_game = game;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
m_currentWaveNum = 0;
|
||||
m_currentBatch = 0;
|
||||
m_currentWave = null;
|
||||
}
|
||||
|
||||
Wave currentWave() {
|
||||
return m_currentWave;
|
||||
}
|
||||
|
||||
int currentWaveNum() {
|
||||
return m_currentWaveNum;
|
||||
}
|
||||
|
||||
int currentBatchNum() {
|
||||
return m_currentBatch;
|
||||
}
|
||||
|
||||
double progress() {
|
||||
return (double)m_currentWaveNum / (double)m_game.getWaveCount();
|
||||
}
|
||||
|
||||
boolean isLastWave() {
|
||||
return m_currentWaveNum >= m_game.getWaveCount();
|
||||
}
|
||||
|
||||
boolean isLastBatch() {
|
||||
return m_currentBatch >= m_currentWave.batchCount();
|
||||
}
|
||||
|
||||
void nextBatch() {
|
||||
m_currentBatch += 1;
|
||||
}
|
||||
|
||||
void next() {
|
||||
m_currentWaveNum += 1;
|
||||
m_currentBatch = 0;
|
||||
m_currentWave = m_game.getWave(m_currentWaveNum);
|
||||
}
|
||||
}
|
||||
TickTask m_fuseTask;
|
||||
TickTask m_countdownTask;
|
||||
TickTask m_bombSmokeTask;
|
||||
TickTask m_bombCrackleTask;
|
||||
|
||||
BossBars m_bars;
|
||||
|
||||
public GameRunner(Plugin plugin, Game game, Arena arena) {
|
||||
m_plugin = plugin;
|
||||
m_game = game;
|
||||
m_arena = arena;
|
||||
m_stage = Stage.Idle;
|
||||
m_gameBar.setVisible(true);
|
||||
m_waveBar.setVisible(false);
|
||||
m_bombBar.setVisible(false);
|
||||
m_mobs = new MobManager(m_game);
|
||||
m_mobs = new MobManager();
|
||||
m_waves = new WaveManager(m_game);
|
||||
m_players = new PlayerManager();
|
||||
m_bombFuse = new BombFuse();
|
||||
m_bars = new BossBars(this, m_game, m_waves, m_players, m_bombFuse, m_mobs);
|
||||
m_log = m_plugin.getLogger();
|
||||
|
||||
m_fuseTask = new TickTask(m_plugin, () -> {
|
||||
if (m_bombFuse.isLit()) {
|
||||
m_bombFuse.tickDecay();
|
||||
m_bars.update();
|
||||
}
|
||||
}, 80);
|
||||
|
||||
m_countdownTask = new TickTask(m_plugin, () -> {
|
||||
if (m_warmupCountdown == 0) {
|
||||
requestTransition(Stage.Playing);
|
||||
} else {
|
||||
m_bars.update();
|
||||
broadcastMessage("Starting game in " + m_warmupCountdown);
|
||||
m_warmupCountdown--;
|
||||
m_bars.setCountdownProgress((double)m_warmupCountdown / 10.0);
|
||||
m_bars.update();
|
||||
}
|
||||
}, 20);
|
||||
|
||||
m_bombSmokeTask = new TickTask(m_plugin, () -> {
|
||||
Location targetLoc = m_arena.bombTarget().getLocation();
|
||||
m_arena.getWorld().spawnParticle(Particle.SMOKE_LARGE, targetLoc, 35, 4, 2, 4);
|
||||
m_arena.getWorld().spawnParticle(Particle.SMALL_FLAME, targetLoc, 30, 3, 2, 3);
|
||||
}, 5);
|
||||
m_bombCrackleTask = new TickTask(m_plugin, () -> {
|
||||
Location targetLoc = m_arena.bombTarget().getLocation();
|
||||
m_arena.getWorld().playSound(targetLoc, Sound.BLOCK_CAMPFIRE_CRACKLE, SoundCategory.NEUTRAL, 1.0f, 1.0f);
|
||||
}, 35);
|
||||
}
|
||||
|
||||
int m_warmupCountdown = 0;
|
||||
|
||||
public void handleEntityRetargeting(EntityTargetEvent evt) {
|
||||
if (m_mobs.contains(evt.getEntity()) && evt.getReason() == EntityTargetEvent.TargetReason.FORGOT_TARGET) {
|
||||
evt.setTarget(m_bombTarget);
|
||||
}
|
||||
m_mobs.handleEntityRetarget(evt);
|
||||
}
|
||||
|
||||
public void handleEntityDamage(EntityDamageEvent evt) {
|
||||
if (evt.getEntity() == m_bombTarget && evt instanceof EntityDamageByEntityEvent) {
|
||||
m_mobs.handleEntityDamage(evt);
|
||||
if (m_mobs.bombWasHit()) {
|
||||
EntityDamageByEntityEvent entityEvt = (EntityDamageByEntityEvent)evt;
|
||||
if (m_mobs.contains(entityEvt.getDamager())) {
|
||||
entityEvt.getDamager().setGlowing(true);
|
||||
m_bombHP -= 1;
|
||||
broadcastMessage("The bomb has been struck!");
|
||||
m_arena.getWorld().playSound(m_bombTarget.getLocation(), Sound.ENTITY_ZOMBIE_ATTACK_IRON_DOOR, 1.5f, 0.9f);
|
||||
updateMobBars();
|
||||
if (m_bombHP <= 0) {
|
||||
m_arena.getWorld().strikeLightningEffect(m_bombTarget.getLocation());
|
||||
requestTransition(Stage.GameOver);
|
||||
}
|
||||
m_log.info("Target attacked!");
|
||||
entityEvt.getDamager().setGlowing(true);
|
||||
m_bombFuse.tickLit();
|
||||
m_arena.getWorld().playSound(m_arena.bombTarget().getLocation(), Sound.ENTITY_ZOMBIE_ATTACK_IRON_DOOR, 1.5f, 0.9f);
|
||||
m_bars.update();
|
||||
if (m_bombFuse.isExploded()) {
|
||||
m_arena.getWorld().strikeLightningEffect(m_arena.bombTarget().getLocation());
|
||||
m_arena.getWorld().playSound(m_arena.bombTarget().getLocation(), Sound.ENTITY_GENERIC_EXPLODE, SoundCategory.NEUTRAL, 1.3f, 1.0f);
|
||||
m_arena.getWorld().spawnParticle(Particle.EXPLOSION_HUGE, m_arena.bombTarget().getLocation(), 8, 5, 2, 5);
|
||||
requestTransition(Stage.GameOver);
|
||||
m_bombSmokeTask.start();
|
||||
m_bombCrackleTask.start();
|
||||
}
|
||||
} else if (evt.getEntity() instanceof Player) {
|
||||
Player player = (Player)evt.getEntity();
|
||||
if (m_players.contains(player) && player.getHealth() - evt.getFinalDamage() <= 0) {
|
||||
evt.setCancelled(true);
|
||||
handlePlayerDeath(player);
|
||||
}
|
||||
evt.setCancelled(true);
|
||||
} else {
|
||||
m_mobs.handleEntityDamage(evt);
|
||||
}
|
||||
}
|
||||
|
||||
private void countdownTick() {
|
||||
if (m_warmupCountdown == 0) {
|
||||
requestTransition(Stage.Playing);
|
||||
} else {
|
||||
updateMobBars();
|
||||
broadcastMessage("Starting game in " + m_warmupCountdown);
|
||||
m_warmupCountdown--;
|
||||
m_countdownTask = m_plugin.getServer().getScheduler().runTaskLater(m_plugin, () -> {
|
||||
countdownTick();
|
||||
}, 20);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean enterIdle() {
|
||||
m_bombHP = 100;
|
||||
m_bombFuse.reset();
|
||||
m_waves.reset();
|
||||
m_mobs.clear();
|
||||
m_bombSmokeTask.stop();
|
||||
m_bombCrackleTask.stop();
|
||||
m_players.requestTransitionForAll(PlayerManager.State.Idle);
|
||||
if (m_bombTarget != null) {
|
||||
m_bombTarget.remove();
|
||||
m_bombTarget = null;
|
||||
}
|
||||
if (m_countdownTask != null) {
|
||||
m_countdownTask.cancel();
|
||||
m_countdownTask = null;
|
||||
}
|
||||
m_fuseTask.stop();
|
||||
m_countdownTask.stop();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -204,25 +172,22 @@ public class GameRunner {
|
||||
|
||||
private boolean enterCountdown() {
|
||||
m_warmupCountdown = 10;
|
||||
countdownTick();
|
||||
m_bars.setCountdownProgress(1.0);
|
||||
m_countdownTask.start();
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean enterPlaying() {
|
||||
m_log.info("Starting wave " + m_waves.currentWaveNum());
|
||||
if (m_bombTarget == null) {
|
||||
m_bombTarget = (LivingEntity)m_arena.getWorld().spawnEntity(m_arena.bombTarget().getLocation(), EntityType.ARMOR_STAND);
|
||||
}
|
||||
ArmorStand bombStand = (ArmorStand)m_bombTarget;
|
||||
bombStand.setCustomName("Bomb Target");
|
||||
bombStand.setVisible(true);
|
||||
bombStand.setCustomNameVisible(true);
|
||||
bombStand.setGlowing(true);
|
||||
m_mobs.spawnTarget(m_arena.bombTarget().getLocation());
|
||||
// TODO: Set helmet with custom model data
|
||||
for(Player p : m_players.getPlayers()) {
|
||||
if (m_players.requestTransition(p, PlayerManager.State.Playing)) {
|
||||
p.teleport(m_arena.getWorld().getSpawnLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN);
|
||||
}
|
||||
}
|
||||
m_countdownTask.stop();
|
||||
m_fuseTask.start();
|
||||
spawnNextBatch();
|
||||
broadcastTitle("Wave " + m_waves.currentWaveNum());
|
||||
return true;
|
||||
@ -230,80 +195,28 @@ public class GameRunner {
|
||||
|
||||
private boolean enterGameOver() {
|
||||
broadcastTitle("Game Over!");
|
||||
if (m_countdownTask != null) {
|
||||
m_countdownTask.cancel();
|
||||
m_countdownTask = null;
|
||||
}
|
||||
broadcastMessage("The bomb blew up!");
|
||||
m_countdownTask.stop();
|
||||
m_fuseTask.stop();
|
||||
m_mobs.clear();
|
||||
for(Player p : m_players.getPlayers()) {
|
||||
for(Player p : new ArrayList<Player>(m_players.getPlayers())) {
|
||||
removePlayer(p);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void updateMobBars() {
|
||||
m_gameBar.setVisible(true);
|
||||
switch(m_stage) {
|
||||
case Idle:
|
||||
m_gameBar.setProgress(1.0);
|
||||
m_gameBar.setTitle("Waiting for players...");
|
||||
m_gameBar.setColor(BarColor.PURPLE);
|
||||
m_waveBar.setVisible(false);
|
||||
m_bombBar.setVisible(false);
|
||||
break;
|
||||
case Warmup:
|
||||
m_gameBar.setProgress(m_waves.progress());
|
||||
m_gameBar.setTitle("Wave " + m_waves.currentWaveNum() + " / " + m_game.getWaveCount());
|
||||
m_gameBar.setColor(BarColor.PURPLE);
|
||||
m_waveBar.setVisible(true);
|
||||
m_waveBar.setColor(BarColor.BLUE);
|
||||
m_waveBar.setTitle("Warmup - Waiting for players to get ready...");
|
||||
m_waveBar.setProgress(m_players.readyProgress());
|
||||
m_bombBar.setVisible(false);
|
||||
break;
|
||||
case Countdown:
|
||||
m_gameBar.setProgress(m_waves.progress());
|
||||
m_gameBar.setTitle("Wave " + m_waves.currentWaveNum() + " / " + m_game.getWaveCount());
|
||||
m_gameBar.setColor(BarColor.PURPLE);
|
||||
m_waveBar.setVisible(true);
|
||||
m_waveBar.setColor(BarColor.YELLOW);
|
||||
m_waveBar.setTitle("Wave starting!");
|
||||
m_waveBar.setProgress((double)m_warmupCountdown / (double)10);
|
||||
m_bombBar.setVisible(false);
|
||||
break;
|
||||
case Playing:
|
||||
m_gameBar.setProgress(m_waves.progress());
|
||||
m_gameBar.setTitle("Wave " + m_waves.currentWaveNum() + " / " + m_game.getWaveCount());
|
||||
m_gameBar.setColor(BarColor.PURPLE);
|
||||
if (m_mobs.createdMobs() > 0) {
|
||||
m_waveBar.setVisible(true);
|
||||
m_waveBar.setColor(BarColor.GREEN);
|
||||
m_waveBar.setTitle("Mobs remaining: " + m_mobs.remainingMobs());
|
||||
m_waveBar.setProgress(m_mobs.progress());
|
||||
} else {
|
||||
m_waveBar.setVisible(false);
|
||||
}
|
||||
m_bombBar.setVisible(true);
|
||||
m_bombBar.setProgress((double)m_bombHP / (double)100);
|
||||
break;
|
||||
case GameOver:
|
||||
m_gameBar.setColor(BarColor.RED);
|
||||
m_gameBar.setProgress(1.0);
|
||||
m_gameBar.setTitle("Game Over!");
|
||||
m_waveBar.setVisible(false);
|
||||
m_bombBar.setVisible(false);
|
||||
break;
|
||||
}
|
||||
public Stage getStage() {
|
||||
return m_stage;
|
||||
}
|
||||
|
||||
private void spawnNextBatch() {
|
||||
broadcastMessage("Spawning batch " + m_waves.currentBatchNum());
|
||||
Spawner spawner = new GameSpawner(m_arena, m_mobs, m_players, m_bombTarget);
|
||||
Spawner spawner = new GameSpawner(m_arena, m_mobs, m_players);
|
||||
m_waves.currentWave().spawnBatch(spawner, m_waves.currentBatchNum());
|
||||
updateMobBars();
|
||||
m_bars.update();
|
||||
}
|
||||
|
||||
public void handlePlayerDeath(Player player) {
|
||||
private void handlePlayerDeath(Player player) {
|
||||
if (m_players.requestTransition(player, PlayerManager.State.Dead)) {
|
||||
m_arena.getWorld().strikeLightningEffect(player.getLocation());
|
||||
if (!m_players.isAnyoneAlive()) {
|
||||
@ -316,9 +229,9 @@ public class GameRunner {
|
||||
}
|
||||
|
||||
public void handleEntityDeath(Entity entity) {
|
||||
boolean wasCarrier = m_mobs.isBombCarrier(entity);
|
||||
if (m_mobs.killMob(entity)) {
|
||||
broadcastMessage("Killed game entity " + entity);
|
||||
updateMobBars();
|
||||
m_bars.update();
|
||||
if (m_mobs.remainingMobs() <= 3) {
|
||||
m_log.info("Starting next batch!");
|
||||
if (m_waves.isLastBatch()) {
|
||||
@ -381,7 +294,7 @@ public class GameRunner {
|
||||
if (attemptTransition(stage)) {
|
||||
m_log.info("Game transition: " + m_stage + " -> " + stage);
|
||||
m_stage = stage;
|
||||
updateMobBars();
|
||||
m_bars.update();
|
||||
return true;
|
||||
}
|
||||
m_log.severe("Failed to complete transition: " + m_stage + " -> " + stage);
|
||||
@ -389,10 +302,11 @@ public class GameRunner {
|
||||
}
|
||||
|
||||
public void addPlayer(Player p) {
|
||||
if (m_players.contains(p)) {
|
||||
return;
|
||||
}
|
||||
m_players.addPlayer(p);
|
||||
m_gameBar.addPlayer(p);
|
||||
m_waveBar.addPlayer(p);
|
||||
m_bombBar.addPlayer(p);
|
||||
m_bars.addPlayer(p);
|
||||
if (m_stage == Stage.Idle || m_stage == Stage.Warmup) {
|
||||
if (m_players.requestTransition(p, PlayerManager.State.Playing)) {
|
||||
p.teleport(m_arena.getWorld().getSpawnLocation(), PlayerTeleportEvent.TeleportCause.PLUGIN);
|
||||
@ -405,8 +319,7 @@ public class GameRunner {
|
||||
}
|
||||
|
||||
public void removePlayer(Player p) {
|
||||
m_gameBar.removePlayer(p);
|
||||
m_waveBar.removePlayer(p);
|
||||
m_bars.removePlayer(p);
|
||||
m_players.removePlayer(p);
|
||||
if (m_players.isEmpty()) {
|
||||
requestTransition(Stage.Idle);
|
||||
@ -429,8 +342,4 @@ public class GameRunner {
|
||||
p.sendMessage(string);
|
||||
}
|
||||
}
|
||||
|
||||
void registerSpawnedMob(Entity entity) {
|
||||
m_mobs.addEntity(entity);
|
||||
}
|
||||
}
|
||||
|
@ -8,32 +8,44 @@ import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.bukkit.inventory.EntityEquipment;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.attribute.AttributeModifier;
|
||||
|
||||
public class GameSpawner implements Spawner {
|
||||
Arena m_arena;
|
||||
MobManager m_manager;
|
||||
PlayerManager m_players;
|
||||
LivingEntity m_bombTarget;
|
||||
int m_spawnIdx = 0;
|
||||
|
||||
public GameSpawner(Arena arena, MobManager manager, PlayerManager players, LivingEntity bombTarget) {
|
||||
public GameSpawner(Arena arena, MobManager manager, PlayerManager players) {
|
||||
m_arena = arena;
|
||||
m_manager = manager;
|
||||
m_players = players;
|
||||
m_bombTarget = bombTarget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entity spawnMob(EntityType type) {
|
||||
public LivingEntity spawnBombCarrier(EntityType type) {
|
||||
if (m_manager.bombCount() == 0) {
|
||||
return m_manager.addBombCarrier(spawnMob(type));
|
||||
} else {
|
||||
return spawnMob(type);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LivingEntity spawnMob(EntityType type) {
|
||||
Spawnpoint[] spawnpoints = m_arena.spawnpoints();
|
||||
m_spawnIdx %= spawnpoints.length;
|
||||
//m_log.fine("Spawning " + type + " at " + spawnpoints[m_spawnIdx]);
|
||||
Entity newMob = m_arena.getWorld().spawnEntity(spawnpoints[m_spawnIdx].getLocation(), type);
|
||||
LivingEntity livingMob = (LivingEntity)newMob;
|
||||
livingMob.setRemoveWhenFarAway(false);
|
||||
m_manager.addEntity(newMob);
|
||||
m_manager.addEntity(livingMob);
|
||||
m_spawnIdx += 1;
|
||||
((Mob)newMob).setTarget(m_bombTarget);
|
||||
return newMob;
|
||||
return livingMob;
|
||||
}
|
||||
}
|
||||
|
@ -2,48 +2,61 @@ package gg.malloc.defense.engine;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.ArmorStand;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.EntityTargetEvent;
|
||||
|
||||
import gg.malloc.defense.model.Game;
|
||||
|
||||
import gg.malloc.defense.ui.BombCarrier;
|
||||
|
||||
public class MobManager {
|
||||
HashSet<Entity> m_livingMobs = new HashSet<>();
|
||||
HashSet<LivingEntity> m_livingMobs = new HashSet<>();
|
||||
HashSet<LivingEntity> m_bombCarriers = new HashSet<>();
|
||||
HashSet<LivingEntity> m_droppedBombs = new HashSet<>();
|
||||
|
||||
int m_createdMobs = 0;
|
||||
int m_killedMobs = 0;
|
||||
|
||||
Game m_game;
|
||||
|
||||
MobManager(Game game) {
|
||||
m_game = game;
|
||||
}
|
||||
|
||||
public void handleEntityDamage(EntityDamageEvent evt) {
|
||||
Entity entity = evt.getEntity();
|
||||
//m_log.info("Damage " + entity);
|
||||
//m_log.info("Living Mobs " + m_livingMobs);
|
||||
if (m_livingMobs.contains(entity)) {
|
||||
m_game.onMobDamaged(entity);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean contains(Entity entity) {
|
||||
return m_livingMobs.contains(entity);
|
||||
}
|
||||
|
||||
public boolean isBombCarrier(Entity entity) {
|
||||
return m_bombCarriers.contains(entity);
|
||||
}
|
||||
|
||||
public boolean killMob(Entity entity) {
|
||||
if (m_livingMobs.contains(entity)) {
|
||||
m_killedMobs += 1;
|
||||
if (m_bombCarriers.remove(entity)) {
|
||||
dropBomb(entity.getLocation());
|
||||
}
|
||||
return m_livingMobs.remove(entity);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
for(Entity e : m_livingMobs) {
|
||||
for(LivingEntity e : m_livingMobs) {
|
||||
e.remove();
|
||||
}
|
||||
for(LivingEntity e : m_droppedBombs) {
|
||||
e.remove();
|
||||
}
|
||||
if (m_bombTarget != null) {
|
||||
m_bombTarget.remove();
|
||||
}
|
||||
m_bombTarget = null;
|
||||
m_droppedBombs.clear();
|
||||
m_livingMobs.clear();
|
||||
m_bombCarriers.clear();
|
||||
m_createdMobs = 0;
|
||||
m_killedMobs = 0;
|
||||
}
|
||||
@ -64,13 +77,106 @@ public class MobManager {
|
||||
return (double)m_killedMobs / (double)m_createdMobs;
|
||||
}
|
||||
|
||||
public void addEntity(Entity entity) {
|
||||
//m_log.fine("Registered new mob " + entity);
|
||||
public void addEntity(LivingEntity entity) {
|
||||
m_livingMobs.add(entity);
|
||||
Mob asMob = (Mob)entity;
|
||||
if (m_droppedBombs.size() > 0) {
|
||||
asMob.setTarget(m_droppedBombs.iterator().next());
|
||||
} else {
|
||||
asMob.setTarget(m_bombTarget);
|
||||
}
|
||||
m_createdMobs += 1;
|
||||
}
|
||||
|
||||
public int bombCount() {
|
||||
return m_bombCarriers.size() + m_droppedBombs.size();
|
||||
}
|
||||
|
||||
public LivingEntity addBombCarrier(LivingEntity entity) {
|
||||
m_bombCarriers.add(entity);
|
||||
((Mob)entity).setTarget(m_bombTarget);
|
||||
return new BombCarrier(entity).inHand();
|
||||
}
|
||||
|
||||
public void removeBombCarrier(LivingEntity entity) {
|
||||
m_bombCarriers.remove(entity);
|
||||
}
|
||||
|
||||
public boolean empty() {
|
||||
return m_livingMobs.size() == 0;
|
||||
}
|
||||
|
||||
public LivingEntity dropBomb(Location location) {
|
||||
ArmorStand droppedBomb = (ArmorStand)(new BombCarrier((LivingEntity)location.getWorld().spawnEntity(location, EntityType.ARMOR_STAND)).onHead());
|
||||
droppedBomb.setCustomName("The Bomb");
|
||||
droppedBomb.setVisible(true);
|
||||
droppedBomb.setCustomNameVisible(true);
|
||||
droppedBomb.setGlowing(true);
|
||||
m_droppedBombs.add(droppedBomb);
|
||||
for(LivingEntity ent : m_livingMobs) {
|
||||
if (!m_bombCarriers.contains(ent)) {
|
||||
((Mob)ent).setTarget(droppedBomb);
|
||||
}
|
||||
}
|
||||
return droppedBomb;
|
||||
}
|
||||
|
||||
boolean m_bombWasHit = false;
|
||||
|
||||
public boolean bombWasHit() {
|
||||
return m_bombWasHit;
|
||||
}
|
||||
|
||||
public void handleEntityDamage(EntityDamageEvent evt) {
|
||||
Entity entity = evt.getEntity();
|
||||
m_bombWasHit = false;
|
||||
|
||||
if (entity == m_bombTarget && evt instanceof EntityDamageByEntityEvent) {
|
||||
EntityDamageByEntityEvent entityEvt = (EntityDamageByEntityEvent)evt;
|
||||
evt.setCancelled(true);
|
||||
if (m_bombCarriers.contains(entityEvt.getDamager())) {
|
||||
m_bombWasHit = true;
|
||||
}
|
||||
} if (m_droppedBombs.contains(entity)) {
|
||||
evt.setCancelled(true);
|
||||
EntityDamageByEntityEvent entityEvt = (EntityDamageByEntityEvent)evt;
|
||||
if (m_livingMobs.contains(entityEvt.getDamager())) {
|
||||
evt.getEntity().remove();
|
||||
m_droppedBombs.remove(evt.getEntity());
|
||||
addBombCarrier((LivingEntity)entityEvt.getDamager());
|
||||
for(LivingEntity ent : m_livingMobs) {
|
||||
if (!m_bombCarriers.contains(ent)) {
|
||||
((Mob)ent).setTarget(m_bombTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (m_livingMobs.contains(evt.getEntity())) {
|
||||
//m_game.onMobDamaged(evt.getEntity());
|
||||
}
|
||||
}
|
||||
|
||||
LivingEntity m_bombTarget;
|
||||
|
||||
public LivingEntity spawnTarget(Location location) {
|
||||
assert(m_bombTarget == null);
|
||||
m_bombTarget = (LivingEntity)location.getWorld().spawnEntity(location, EntityType.ARMOR_STAND);
|
||||
ArmorStand bombStand = (ArmorStand)m_bombTarget;
|
||||
bombStand.setCustomName("Bomb Target");
|
||||
bombStand.setVisible(true);
|
||||
bombStand.setCustomNameVisible(true);
|
||||
bombStand.setGlowing(true);
|
||||
return m_bombTarget;
|
||||
}
|
||||
|
||||
public void handleEntityRetarget(EntityTargetEvent evt) {
|
||||
if (m_livingMobs.contains(evt.getEntity())) {
|
||||
if (m_bombCarriers.contains(evt.getEntity())) {
|
||||
evt.setTarget(m_bombTarget);
|
||||
} if (m_droppedBombs.size() > 0) {
|
||||
evt.setTarget(m_droppedBombs.iterator().next());
|
||||
} else if (evt.getReason() == EntityTargetEvent.TargetReason.FORGOT_TARGET) {
|
||||
evt.setTarget(m_bombTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,10 @@ public class PlayerManager {
|
||||
return allSuccess;
|
||||
}
|
||||
|
||||
public boolean contains(Player player) {
|
||||
return m_playerStates.containsKey(player);
|
||||
}
|
||||
|
||||
public boolean requestTransition(Player player, State toState) {
|
||||
State currentState = m_playerStates.get(player);
|
||||
if (currentState == toState) {
|
||||
|
40
src/main/java/gg/malloc/defense/engine/TickTask.java
Normal file
40
src/main/java/gg/malloc/defense/engine/TickTask.java
Normal file
@ -0,0 +1,40 @@
|
||||
package gg.malloc.defense.engine;
|
||||
|
||||
import gg.malloc.defense.Plugin;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
public class TickTask {
|
||||
Runnable m_runnable;
|
||||
int m_interval;
|
||||
BukkitTask m_task = null;
|
||||
Plugin m_plugin;
|
||||
boolean m_cancelled = false;
|
||||
|
||||
public TickTask(Plugin plugin, Runnable runnable, int interval) {
|
||||
m_plugin = plugin;
|
||||
m_runnable = runnable;
|
||||
m_interval = interval;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
m_cancelled = false;
|
||||
if (m_task == null) {
|
||||
tick();
|
||||
}
|
||||
}
|
||||
|
||||
private void tick() {
|
||||
m_runnable.run();
|
||||
if (!m_cancelled) {
|
||||
m_task = m_plugin.getServer().getScheduler().runTaskLater(m_plugin, () -> {tick();}, m_interval);
|
||||
}
|
||||
}
|
||||
|
||||
void stop() {
|
||||
m_cancelled = true;
|
||||
if (m_task != null) {
|
||||
m_task.cancel();
|
||||
m_task = null;
|
||||
}
|
||||
}
|
||||
}
|
55
src/main/java/gg/malloc/defense/engine/WaveManager.java
Normal file
55
src/main/java/gg/malloc/defense/engine/WaveManager.java
Normal file
@ -0,0 +1,55 @@
|
||||
package gg.malloc.defense.engine;
|
||||
|
||||
import gg.malloc.defense.model.Wave;
|
||||
import gg.malloc.defense.model.Game;
|
||||
|
||||
public class WaveManager {
|
||||
int m_currentWaveNum = 0;
|
||||
int m_currentBatch = 0;
|
||||
Wave m_currentWave = null;
|
||||
Game m_game;
|
||||
|
||||
public WaveManager(Game game) {
|
||||
m_game = game;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
m_currentWaveNum = 0;
|
||||
m_currentBatch = 0;
|
||||
m_currentWave = null;
|
||||
}
|
||||
|
||||
public Wave currentWave() {
|
||||
return m_currentWave;
|
||||
}
|
||||
|
||||
public int currentWaveNum() {
|
||||
return m_currentWaveNum;
|
||||
}
|
||||
|
||||
public int currentBatchNum() {
|
||||
return m_currentBatch;
|
||||
}
|
||||
|
||||
public double progress() {
|
||||
return (double)m_currentWaveNum / (double)m_game.getWaveCount();
|
||||
}
|
||||
|
||||
public boolean isLastWave() {
|
||||
return m_currentWaveNum >= m_game.getWaveCount();
|
||||
}
|
||||
|
||||
public boolean isLastBatch() {
|
||||
return m_currentBatch >= m_currentWave.batchCount();
|
||||
}
|
||||
|
||||
public void nextBatch() {
|
||||
m_currentBatch += 1;
|
||||
}
|
||||
|
||||
public void next() {
|
||||
m_currentWaveNum += 1;
|
||||
m_currentBatch = 0;
|
||||
m_currentWave = m_game.getWave(m_currentWaveNum);
|
||||
}
|
||||
}
|
@ -6,6 +6,9 @@ import gg.malloc.defense.model.Spawner;
|
||||
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Mob;
|
||||
import org.bukkit.attribute.AttributeModifier;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
@ -55,6 +58,8 @@ public class ScaledWaves implements Game {
|
||||
|
||||
@Override
|
||||
public void spawnBatch(Spawner spawner, int batch) {
|
||||
double healthScale = -0.5;
|
||||
AttributeModifier modifier = new AttributeModifier("Scaled Health", healthScale, AttributeModifier.Operation.MULTIPLY_SCALAR_1);
|
||||
assert(m_mobsPerBatch > 0);
|
||||
for(int i = 0; i < m_mobsPerBatch; i++) {
|
||||
EntityType selectedType = null;
|
||||
@ -67,8 +72,9 @@ public class ScaledWaves implements Game {
|
||||
}
|
||||
}
|
||||
assert(selectedType != null);
|
||||
Entity newMob = spawner.spawnMob(selectedType);
|
||||
Mob newMob = (Mob)spawner.spawnBombCarrier(selectedType);
|
||||
newMob.setCustomName("Mob " + i + "/" + m_mobsPerBatch);
|
||||
newMob.getAttribute(Attribute.GENERIC_MAX_HEALTH).addModifier(modifier);
|
||||
}
|
||||
if (m_hasRavager) {
|
||||
Entity newMob = spawner.spawnMob(EntityType.RAVAGER);
|
||||
|
@ -1,8 +1,9 @@
|
||||
package gg.malloc.defense.model;
|
||||
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
|
||||
public interface Spawner {
|
||||
Entity spawnMob(EntityType type);
|
||||
LivingEntity spawnMob(EntityType type);
|
||||
LivingEntity spawnBombCarrier(EntityType type);
|
||||
}
|
||||
|
37
src/main/java/gg/malloc/defense/ui/BombCarrier.java
Normal file
37
src/main/java/gg/malloc/defense/ui/BombCarrier.java
Normal file
@ -0,0 +1,37 @@
|
||||
package gg.malloc.defense.ui;
|
||||
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.inventory.EntityEquipment;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.Material;
|
||||
|
||||
public class BombCarrier {
|
||||
LivingEntity m_entity;
|
||||
|
||||
public BombCarrier(LivingEntity entity) {
|
||||
m_entity = entity;
|
||||
}
|
||||
|
||||
public LivingEntity inHand() {
|
||||
EntityEquipment equipment = m_entity.getEquipment();
|
||||
equipment.setItemInOffHand(makeBombHelmet());
|
||||
//equipment.setItemInOffHandDropChance(0.0f);
|
||||
return m_entity;
|
||||
}
|
||||
|
||||
public LivingEntity onHead() {
|
||||
EntityEquipment equipment = m_entity.getEquipment();
|
||||
equipment.setHelmet(makeBombHelmet());
|
||||
//equipment.setHelmetDropChance(0.0f);
|
||||
return m_entity;
|
||||
}
|
||||
|
||||
static ItemStack makeBombHelmet() {
|
||||
ItemStack bombItem = new ItemStack(Material.CARVED_PUMPKIN);
|
||||
ItemMeta meta = bombItem.getItemMeta();
|
||||
meta.setCustomModelData(33197);
|
||||
bombItem.setItemMeta(meta);
|
||||
return bombItem;
|
||||
}
|
||||
}
|
116
src/main/java/gg/malloc/defense/ui/BossBars.java
Normal file
116
src/main/java/gg/malloc/defense/ui/BossBars.java
Normal file
@ -0,0 +1,116 @@
|
||||
package gg.malloc.defense.ui;
|
||||
|
||||
import gg.malloc.defense.engine.GameRunner;
|
||||
import gg.malloc.defense.engine.WaveManager;
|
||||
import gg.malloc.defense.engine.PlayerManager;
|
||||
import gg.malloc.defense.engine.MobManager;
|
||||
import gg.malloc.defense.engine.BombFuse;
|
||||
|
||||
import gg.malloc.defense.model.Game;
|
||||
|
||||
import org.bukkit.boss.BossBar;
|
||||
import org.bukkit.boss.BarStyle;
|
||||
import org.bukkit.boss.BarColor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class BossBars {
|
||||
BossBar m_gameBar = Bukkit.createBossBar("Malloc Defense", BarColor.PURPLE, BarStyle.SOLID);
|
||||
BossBar m_waveBar = Bukkit.createBossBar("Malloc Defense", BarColor.PURPLE, BarStyle.SOLID);
|
||||
BossBar m_bombBar = Bukkit.createBossBar("Bomb Fuse", BarColor.RED, BarStyle.SOLID);
|
||||
|
||||
GameRunner m_runner;
|
||||
MobManager m_mobs;
|
||||
WaveManager m_waves;
|
||||
PlayerManager m_players;
|
||||
BombFuse m_fuse;
|
||||
Game m_game;
|
||||
|
||||
double m_countdownProgress;
|
||||
|
||||
public void setCountdownProgress(double v) {
|
||||
m_countdownProgress = v;
|
||||
}
|
||||
|
||||
public BossBars(GameRunner runner, Game game, WaveManager waves, PlayerManager players, BombFuse fuse, MobManager mobs) {
|
||||
m_runner = runner;
|
||||
m_game = game;
|
||||
m_waves = waves;
|
||||
m_players = players;
|
||||
m_fuse = fuse;
|
||||
m_mobs = mobs;
|
||||
m_gameBar.setVisible(true);
|
||||
m_waveBar.setVisible(false);
|
||||
m_bombBar.setVisible(false);
|
||||
}
|
||||
|
||||
public void addPlayer(Player p) {
|
||||
m_gameBar.addPlayer(p);
|
||||
m_waveBar.addPlayer(p);
|
||||
m_bombBar.addPlayer(p);
|
||||
}
|
||||
|
||||
public void removePlayer(Player p) {
|
||||
m_gameBar.removePlayer(p);
|
||||
m_waveBar.removePlayer(p);
|
||||
m_bombBar.removePlayer(p);
|
||||
}
|
||||
|
||||
public void update() {
|
||||
switch(m_runner.getStage()) {
|
||||
case Idle:
|
||||
m_gameBar.setProgress(1.0);
|
||||
m_gameBar.setTitle("Waiting for players...");
|
||||
m_gameBar.setColor(BarColor.PURPLE);
|
||||
m_waveBar.setVisible(false);
|
||||
m_bombBar.setVisible(false);
|
||||
break;
|
||||
case Warmup:
|
||||
m_gameBar.setProgress(m_waves.progress());
|
||||
m_gameBar.setTitle("Wave " + m_waves.currentWaveNum() + " / " + m_game.getWaveCount());
|
||||
m_gameBar.setColor(BarColor.PURPLE);
|
||||
m_waveBar.setVisible(true);
|
||||
m_waveBar.setColor(BarColor.BLUE);
|
||||
m_waveBar.setTitle("Warmup - Waiting for players to get ready...");
|
||||
m_waveBar.setProgress(m_players.readyProgress());
|
||||
m_bombBar.setVisible(false);
|
||||
break;
|
||||
case Countdown:
|
||||
m_gameBar.setProgress(m_waves.progress());
|
||||
m_gameBar.setTitle("Wave " + m_waves.currentWaveNum() + " / " + m_game.getWaveCount());
|
||||
m_gameBar.setColor(BarColor.PURPLE);
|
||||
m_waveBar.setVisible(true);
|
||||
m_waveBar.setColor(BarColor.YELLOW);
|
||||
m_waveBar.setTitle("Wave starting!");
|
||||
m_waveBar.setProgress(m_countdownProgress);
|
||||
m_bombBar.setVisible(false);
|
||||
break;
|
||||
case Playing:
|
||||
m_gameBar.setProgress(m_waves.progress());
|
||||
m_gameBar.setTitle("Wave " + m_waves.currentWaveNum() + " / " + m_game.getWaveCount());
|
||||
m_gameBar.setColor(BarColor.PURPLE);
|
||||
if (m_mobs.createdMobs() > 0) {
|
||||
m_waveBar.setVisible(true);
|
||||
m_waveBar.setColor(BarColor.GREEN);
|
||||
m_waveBar.setTitle("Mobs remaining: " + m_mobs.remainingMobs());
|
||||
m_waveBar.setProgress(m_mobs.progress());
|
||||
} else {
|
||||
m_waveBar.setVisible(false);
|
||||
}
|
||||
if (m_fuse.isLit()) {
|
||||
m_bombBar.setVisible(true);
|
||||
m_bombBar.setProgress(1.0 - m_fuse.getProgress());
|
||||
} else {
|
||||
m_bombBar.setVisible(false);
|
||||
}
|
||||
break;
|
||||
case GameOver:
|
||||
m_gameBar.setColor(BarColor.RED);
|
||||
m_gameBar.setProgress(1.0);
|
||||
m_gameBar.setTitle("Game Over!");
|
||||
m_waveBar.setVisible(false);
|
||||
m_bombBar.setVisible(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
15
src/main/java/gg/malloc/defense/ui/Items.java
Normal file
15
src/main/java/gg/malloc/defense/ui/Items.java
Normal file
@ -0,0 +1,15 @@
|
||||
package gg.malloc.defense.engine;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.Material;
|
||||
|
||||
public class Items {
|
||||
static ItemStack makeBombHelmet() {
|
||||
ItemStack bombItem = new ItemStack(Material.CARVED_PUMPKIN);
|
||||
ItemMeta meta = bombItem.getItemMeta();
|
||||
meta.setCustomModelData(0);
|
||||
bombItem.setItemMeta(meta);
|
||||
return bombItem;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user