mirror of
https://github.com/garbagemule/MobArena.git
synced 2025-03-23 12:10:34 +01:00
Add support for boss health bars.
Three different types of health bars are implemented behind a basic Strategy Pattern. A new per-arena setting, boss-health-bar, can be used to configure which one of the three types (if any) of health bar should be used for bosses in the given arena: - `boss-bar` creates a boss bar at the top of the screen as if the players were fighting an ender dragon or a wither. - `title` uses the Chapters/Titles API in Bukkit to display the health of the boss as a "subtitle" whenever it takes damage. - `name` sets the entitiy's health along with an optional custom name above the entity's head.
This commit is contained in:
parent
c4362474a1
commit
2aecea401d
src/main
java/com/garbagemule/MobArena
ArenaImpl.javaArenaListener.javaMASpawnThread.java
healthbar
BossHealthBar.javaCreatesHealthBar.javaCreatesHealthString.javaHealthBar.javaNameHealthBar.javaNullHealthBar.javaTitleHealthBar.java
waves
resources/res
@ -25,6 +25,7 @@ import com.garbagemule.MobArena.util.ClassChests;
|
||||
import com.garbagemule.MobArena.util.inventory.InventoryManager;
|
||||
import com.garbagemule.MobArena.util.timer.AutoStartTimer;
|
||||
import com.garbagemule.MobArena.util.timer.StartDelayTimer;
|
||||
import com.garbagemule.MobArena.waves.MABoss;
|
||||
import com.garbagemule.MobArena.waves.SheepBouncer;
|
||||
import com.garbagemule.MobArena.waves.WaveManager;
|
||||
import org.bukkit.Bukkit;
|
||||
@ -1118,6 +1119,14 @@ public class ArenaImpl implements Arena
|
||||
|
||||
private void clearPlayer(Player p)
|
||||
{
|
||||
// Remove from boss health bar
|
||||
monsterManager.getBossMonsters().forEach(entity -> {
|
||||
MABoss boss = monsterManager.getBoss(entity);
|
||||
if (boss != null) {
|
||||
boss.getHealthBar().removePlayer(p);
|
||||
}
|
||||
});
|
||||
|
||||
// Remove pets.
|
||||
monsterManager.removePets(p);
|
||||
|
||||
|
@ -635,6 +635,7 @@ public class ArenaListener
|
||||
event.getDrops().addAll(drops);
|
||||
}
|
||||
boss.setDead(true);
|
||||
boss.getHealthBar().setProgress(0);
|
||||
}
|
||||
|
||||
List<ItemStack> loot = monsters.getLoot(damagee);
|
||||
@ -685,6 +686,10 @@ public class ArenaListener
|
||||
}
|
||||
}
|
||||
|
||||
MABoss boss = (damagee instanceof LivingEntity)
|
||||
? monsters.getBoss((LivingEntity) damagee)
|
||||
: null;
|
||||
|
||||
// Pet wolf
|
||||
if (damagee instanceof Wolf && arena.hasPet(damagee)) {
|
||||
onPetDamage(event, (Wolf) damagee, damager);
|
||||
@ -701,6 +706,10 @@ public class ArenaListener
|
||||
else if (damagee instanceof Snowman && event.getCause() == DamageCause.MELTING) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
// Boss monster
|
||||
else if (boss != null) {
|
||||
onBossDamage(event, boss, damager);
|
||||
}
|
||||
// Regular monster
|
||||
else if (monsters.getMonsters().contains(damagee)) {
|
||||
onMonsterDamage(event, damagee, damager);
|
||||
@ -739,6 +748,16 @@ public class ArenaListener
|
||||
private void onMountDamage(EntityDamageEvent event, Horse mount, Entity damager) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
private void onBossDamage(EntityDamageEvent event, MABoss boss, Entity damager) {
|
||||
onMonsterDamage(event, boss.getEntity(), damager);
|
||||
if (event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
double progress = boss.getHealth() / boss.getMaxHealth();
|
||||
boss.getHealthBar().setProgress(progress);
|
||||
}
|
||||
|
||||
private void onMonsterDamage(EntityDamageEvent event, Entity monster, Entity damager) {
|
||||
if (damager instanceof Player) {
|
||||
|
@ -3,6 +3,8 @@ package com.garbagemule.MobArena;
|
||||
import com.garbagemule.MobArena.events.ArenaCompleteEvent;
|
||||
import com.garbagemule.MobArena.events.NewWaveEvent;
|
||||
import com.garbagemule.MobArena.framework.Arena;
|
||||
import com.garbagemule.MobArena.healthbar.CreatesHealthBar;
|
||||
import com.garbagemule.MobArena.healthbar.HealthBar;
|
||||
import com.garbagemule.MobArena.region.ArenaRegion;
|
||||
import com.garbagemule.MobArena.things.Thing;
|
||||
import com.garbagemule.MobArena.waves.MABoss;
|
||||
@ -31,6 +33,7 @@ public class MASpawnThread implements Runnable
|
||||
private RewardManager rewardManager;
|
||||
private WaveManager waveManager;
|
||||
private MonsterManager monsterManager;
|
||||
private CreatesHealthBar createsHealthBar;
|
||||
|
||||
private int playerCount, monsterLimit;
|
||||
private boolean waveClear, bossClear, preBossClear, wavesAsLevel;
|
||||
@ -48,6 +51,7 @@ public class MASpawnThread implements Runnable
|
||||
this.rewardManager = arena.getRewardManager();
|
||||
this.waveManager = arena.getWaveManager();
|
||||
this.monsterManager = arena.getMonsterManager();
|
||||
this.createsHealthBar = new CreatesHealthBar(arena.getSettings().getString("boss-health-bar", "none"));
|
||||
|
||||
reset();
|
||||
}
|
||||
@ -195,6 +199,10 @@ public class MASpawnThread implements Runnable
|
||||
BossWave bw = (BossWave) w;
|
||||
double maxHealth = bw.getMaxHealth(playerCount);
|
||||
MABoss boss = monsterManager.addBoss(e, maxHealth);
|
||||
HealthBar healthbar = createsHealthBar.create(e, bw.getBossName());
|
||||
arena.getPlayersInArena().forEach(healthbar::addPlayer);
|
||||
healthbar.setProgress(1);
|
||||
boss.setHealthBar(healthbar);
|
||||
boss.setReward(bw.getReward());
|
||||
boss.setDrops(bw.getDrops());
|
||||
bw.addMABoss(boss);
|
||||
|
@ -0,0 +1,49 @@
|
||||
package com.garbagemule.MobArena.healthbar;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.boss.BarColor;
|
||||
import org.bukkit.boss.BarFlag;
|
||||
import org.bukkit.boss.BarStyle;
|
||||
import org.bukkit.boss.BossBar;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
class BossHealthBar implements HealthBar {
|
||||
|
||||
private static final double LOW_HEALTH = 0.25;
|
||||
|
||||
private final BossBar bar;
|
||||
|
||||
BossHealthBar(String title) {
|
||||
bar = Bukkit.createBossBar(
|
||||
title.isEmpty() ? "Boss" : title,
|
||||
BarColor.GREEN,
|
||||
BarStyle.SOLID,
|
||||
BarFlag.PLAY_BOSS_MUSIC,
|
||||
BarFlag.DARKEN_SKY
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProgress(double progress) {
|
||||
if (progress <= LOW_HEALTH && bar.getColor() != BarColor.RED) {
|
||||
bar.setColor(BarColor.RED);
|
||||
}
|
||||
bar.setProgress(progress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPlayer(Player player) {
|
||||
bar.addPlayer(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePlayer(Player player) {
|
||||
bar.removePlayer(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAll() {
|
||||
bar.removeAll();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package com.garbagemule.MobArena.healthbar;
|
||||
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
public class CreatesHealthBar {
|
||||
|
||||
private final String type;
|
||||
private final CreatesHealthString createsHealthString;
|
||||
|
||||
public CreatesHealthBar(String type) {
|
||||
this.type = type;
|
||||
this.createsHealthString = new CreatesHealthString();
|
||||
}
|
||||
|
||||
public HealthBar create(Entity entity, String title) {
|
||||
String name = (title != null) ? title : "";
|
||||
|
||||
switch (type) {
|
||||
case "boss-bar":
|
||||
return new BossHealthBar(name);
|
||||
case "title":
|
||||
return new TitleHealthBar(name, createsHealthString);
|
||||
case "name":
|
||||
return new NameHealthBar(entity, name, createsHealthString);
|
||||
default:
|
||||
return new NullHealthBar();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.garbagemule.MobArena.healthbar;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
class CreatesHealthString {
|
||||
|
||||
private static final int TOTAL_BARS = 20;
|
||||
private static final int LOW_BARS = TOTAL_BARS / 4;
|
||||
|
||||
String create(double progress) {
|
||||
int bars = (int) (progress * TOTAL_BARS);
|
||||
|
||||
String current = IntStream.range(0, bars)
|
||||
.mapToObj(i -> "|")
|
||||
.collect(Collectors.joining());
|
||||
|
||||
String lost = IntStream.range(bars, TOTAL_BARS)
|
||||
.mapToObj(i -> "|")
|
||||
.collect(Collectors.joining());
|
||||
|
||||
ChatColor color = (bars <= LOW_BARS) ? ChatColor.RED : ChatColor.GREEN;
|
||||
|
||||
return color + current + ChatColor.GRAY + lost;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package com.garbagemule.MobArena.healthbar;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public interface HealthBar {
|
||||
|
||||
void setProgress(double progress);
|
||||
|
||||
void addPlayer(Player player);
|
||||
|
||||
void removePlayer(Player player);
|
||||
|
||||
void removeAll();
|
||||
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package com.garbagemule.MobArena.healthbar;
|
||||
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
class NameHealthBar implements HealthBar {
|
||||
|
||||
private final Entity entity;
|
||||
private final String title;
|
||||
private final CreatesHealthString createsHealthString;
|
||||
|
||||
NameHealthBar(Entity entity, String title, CreatesHealthString createsHealthString) {
|
||||
this.entity = entity;
|
||||
this.title = title;
|
||||
this.createsHealthString = createsHealthString;
|
||||
|
||||
entity.setCustomNameVisible(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProgress(double progress) {
|
||||
String health = createsHealthString.create(progress);
|
||||
String name = title.isEmpty() ? health : title + " " + health;
|
||||
|
||||
entity.setCustomName(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPlayer(Player player) {
|
||||
// OK BOSS
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePlayer(Player player) {
|
||||
// OK BOSS
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAll() {
|
||||
// OK BOSS
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package com.garbagemule.MobArena.healthbar;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
class NullHealthBar implements HealthBar {
|
||||
|
||||
@Override
|
||||
public void setProgress(double progress) {
|
||||
// OK BOSS
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPlayer(Player player) {
|
||||
// OK BOSS
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePlayer(Player player) {
|
||||
// OK BOSS
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAll() {
|
||||
// OK BOSS
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
package com.garbagemule.MobArena.healthbar;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
class TitleHealthBar implements HealthBar {
|
||||
|
||||
private static final int FADE_IN_TICKS = 5;
|
||||
private static final int STAY_TICKS = 40;
|
||||
private static final int FADE_OUT_TICKS = 10;
|
||||
|
||||
private final String title;
|
||||
private final CreatesHealthString createsHealthString;
|
||||
private final Set<Player> players;
|
||||
|
||||
TitleHealthBar(String title, CreatesHealthString createsHealthString) {
|
||||
this.title = title;
|
||||
this.createsHealthString = createsHealthString;
|
||||
this.players = new HashSet<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProgress(double progress) {
|
||||
String health = createsHealthString.create(progress);
|
||||
String message = title.isEmpty() ? health : title + " " + health;
|
||||
|
||||
players.forEach(player -> player.sendTitle(
|
||||
"",
|
||||
message,
|
||||
FADE_IN_TICKS,
|
||||
STAY_TICKS,
|
||||
FADE_OUT_TICKS
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPlayer(Player player) {
|
||||
players.add(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePlayer(Player player) {
|
||||
players.remove(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAll() {
|
||||
players.clear();
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package com.garbagemule.MobArena.waves;
|
||||
|
||||
import com.garbagemule.MobArena.healthbar.HealthBar;
|
||||
import com.garbagemule.MobArena.things.Thing;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
@ -13,6 +14,7 @@ public class MABoss
|
||||
private boolean dead;
|
||||
private Thing reward;
|
||||
private List<ItemStack> drops;
|
||||
private HealthBar healthbar;
|
||||
|
||||
/**
|
||||
* Create an MABoss from the given entity with the given max health.
|
||||
@ -73,6 +75,7 @@ public class MABoss
|
||||
*/
|
||||
public void setDead(boolean dead) {
|
||||
this.dead = dead;
|
||||
healthbar.removeAll();
|
||||
}
|
||||
|
||||
public void setReward(Thing reward) {
|
||||
@ -90,4 +93,12 @@ public class MABoss
|
||||
public List<ItemStack> getDrops() {
|
||||
return drops;
|
||||
}
|
||||
|
||||
public HealthBar getHealthBar() {
|
||||
return healthbar;
|
||||
}
|
||||
|
||||
public void setHealthBar(HealthBar healthbar) {
|
||||
this.healthbar = healthbar;
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ auto-start-timer: 0
|
||||
start-delay-timer: 0
|
||||
auto-ready: false
|
||||
use-class-chests: false
|
||||
boss-health-bar: boss-bar
|
||||
display-waves-as-level: false
|
||||
display-timer-as-level: false
|
||||
use-scoreboards: true
|
||||
|
Loading…
Reference in New Issue
Block a user