diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/EcoBoss.java b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/EcoBoss.java index cd184b4..30d3d23 100644 --- a/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/EcoBoss.java +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/EcoBoss.java @@ -227,6 +227,18 @@ public class EcoBoss extends PluginDependent { */ private final Map> effectNames; + /** + * The target distance. + */ + @Getter + private final double targetDistance; + + /** + * The targeting mode. + */ + @Getter + private final TargetMode targetMode; + /** * Create a new Boss. * @@ -444,6 +456,10 @@ public class EcoBoss extends PluginDependent { } }); + // Targeting + this.targetDistance = this.getConfig().getDouble("attacks.target.range"); + this.targetMode = TargetMode.getByName(this.getConfig().getString("attacks.target.mode")); + if (this.getConfig().getBool("enabled")) { EcoBosses.addBoss(this); } diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/LivingEcoBoss.java b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/LivingEcoBoss.java index 8da6a0e..c1433b2 100644 --- a/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/LivingEcoBoss.java +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/LivingEcoBoss.java @@ -71,7 +71,7 @@ public class LivingEcoBoss extends PluginDependent { // Tickers this.tickers = new HashSet<>(); this.tickers.add(new HealthPlaceholderTicker()); - this.tickers.add(new TargetTicker()); + this.tickers.add(new TargetTicker(boss.getTargetMode(), boss.getTargetDistance())); if (boss.isBossbarEnabled()) { this.tickers.add( new BossBarTicker( diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/tick/tickers/TargetTicker.java b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/tick/tickers/TargetTicker.java index 0534aa7..9426612 100644 --- a/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/tick/tickers/TargetTicker.java +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/tick/tickers/TargetTicker.java @@ -2,23 +2,57 @@ package com.willfp.ecobosses.bosses.tick.tickers; import com.willfp.ecobosses.bosses.EcoBoss; import com.willfp.ecobosses.bosses.tick.BossTicker; +import com.willfp.ecobosses.bosses.util.obj.TargetMode; import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Mob; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; +import java.util.List; + public class TargetTicker implements BossTicker { + /** + * The targeting mode. + */ + private final TargetMode mode; + + /** + * The maximum range. + */ + private final double range; + + /** + * Create new target ticker. + * + * @param mode The targeting mode. + * @param range The range. + */ + public TargetTicker(@NotNull final TargetMode mode, + final double range) { + this.mode = mode; + this.range = range; + } + @Override public void tick(@NotNull final EcoBoss boss, @NotNull final LivingEntity entity, final long tick) { + Mob mob = (Mob) entity; if (tick % 10 == 0) { - for (Entity nearbyEntity : entity.getNearbyEntities(10, 5, 10)) { - if (nearbyEntity instanceof Player && entity instanceof Mob) { - ((Mob) entity).setTarget((Player) nearbyEntity); + List nearbyPlayers = new ArrayList<>(); + for (Entity nearbyEntity : entity.getNearbyEntities(range, range, range)) { + if (nearbyEntity instanceof Player) { + nearbyPlayers.add((Player) nearbyEntity); } } + + if (nearbyPlayers.isEmpty()) { + return; + } + + mob.setTarget(mode.getTarget(nearbyPlayers, entity)); } } } diff --git a/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/util/obj/TargetMode.java b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/util/obj/TargetMode.java new file mode 100644 index 0000000..ba5a3df --- /dev/null +++ b/eco-core/core-plugin/src/main/java/com/willfp/ecobosses/bosses/util/obj/TargetMode.java @@ -0,0 +1,114 @@ +package com.willfp.ecobosses.bosses.util.obj; + +import com.willfp.eco.util.NumberUtils; +import lombok.Getter; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.BiFunction; + +public class TargetMode { + /** + * All registered target modes. + */ + private static final Map VALUES = new HashMap<>(); + + /** + * Random nearby player. + */ + public static final TargetMode RANDOM = new TargetMode("random", (list, entity) -> { + return list.get(NumberUtils.randInt(0, list.size() - 1)); + }); + + /** + * Closest player. + */ + public static final TargetMode CLOSEST = new TargetMode("closest", (list, entity) -> { + Player player = null; + double nearestD2 = 10000; + for (Player nearbyPlayer : list) { + double d2 = nearbyPlayer.getLocation().distanceSquared(entity.getLocation()); + if (d2 < nearestD2) { + player = nearbyPlayer; + } + } + return player; + }); + + /** + * Player with lowest health. + */ + public static final TargetMode LOWEST_HEALTH = new TargetMode("lowest-health", (list, entity) -> { + Player player = null; + double lowest = 100; + for (Player nearbyPlayer : list) { + double health = nearbyPlayer.getHealth(); + if (health < lowest) { + player = nearbyPlayer; + } + } + return player; + }); + + /** + * Player with highest health. + */ + public static final TargetMode HIGHEST_HEALTH = new TargetMode("highest-health", (list, entity) -> { + Player player = null; + double highest = 0; + for (Player nearbyPlayer : list) { + double health = nearbyPlayer.getHealth(); + if (health > highest) { + player = nearbyPlayer; + } + } + return player; + }); + + /** + * The name of the target mode. + */ + @Getter + private final String name; + + /** + * The function to find a player out of a list. + */ + private final BiFunction, LivingEntity, Player> function; + + protected TargetMode(@NotNull final String name, + @NotNull final BiFunction, LivingEntity, Player> function) { + this.name = name; + this.function = function; + + VALUES.put(name, this); + } + + /** + * Get target from list of players. + * + * @param list The list. + * @param entity The boss. + * @return The target. + */ + public Player getTarget(@NotNull final List list, + @NotNull final LivingEntity entity) { + return function.apply(list, entity); + } + + /** + * Get target mode by name. + * + * @param name The name. + * @return The target mode, or null if not found. + */ + @Nullable + public static TargetMode getByName(@NotNull final String name) { + return VALUES.get(name); + } +} diff --git a/eco-core/core-plugin/src/main/resources/bosses/alpha_wolf.yml b/eco-core/core-plugin/src/main/resources/bosses/alpha_wolf.yml index 6cdd7ff..5fe7f57 100644 --- a/eco-core/core-plugin/src/main/resources/bosses/alpha_wolf.yml +++ b/eco-core/core-plugin/src/main/resources/bosses/alpha_wolf.yml @@ -93,6 +93,11 @@ attacks: # Chance to shuffle your hotbar as a percentage - set to 0 to disable. shuffle-chance: 0 + # How the boss decides who to attack + target: + distance: 15 # The distance to check for nearby players. + mode: random + sounds: # Sounds are formatted like this: # sound:volume:pitch diff --git a/eco-core/core-plugin/src/main/resources/bosses/illusioner.yml b/eco-core/core-plugin/src/main/resources/bosses/illusioner.yml index f316341..83c599c 100644 --- a/eco-core/core-plugin/src/main/resources/bosses/illusioner.yml +++ b/eco-core/core-plugin/src/main/resources/bosses/illusioner.yml @@ -94,6 +94,11 @@ attacks: # Chance to shuffle your hotbar as a percentage - set to 0 to disable. shuffle-chance: 10 + # How the boss decides who to attack + target: + distance: 15 # The distance to check for nearby players. + mode: random + sounds: # Sounds are formatted like this: # sound:volume:pitch diff --git a/eco-core/core-plugin/src/main/resources/bosses/steel_golem.yml b/eco-core/core-plugin/src/main/resources/bosses/steel_golem.yml index 8f44353..44a416e 100644 --- a/eco-core/core-plugin/src/main/resources/bosses/steel_golem.yml +++ b/eco-core/core-plugin/src/main/resources/bosses/steel_golem.yml @@ -95,6 +95,11 @@ attacks: # Chance to shuffle your hotbar as a percentage - set to 0 to disable. shuffle-chance: 30 + # How the boss decides who to attack + target: + distance: 15 # The distance to check for nearby players. + mode: random + sounds: # Sounds are formatted like this: # sound:volume:pitch diff --git a/eco-core/core-plugin/src/main/resources/bosses/tarantula.yml b/eco-core/core-plugin/src/main/resources/bosses/tarantula.yml index 26af663..e332a75 100644 --- a/eco-core/core-plugin/src/main/resources/bosses/tarantula.yml +++ b/eco-core/core-plugin/src/main/resources/bosses/tarantula.yml @@ -96,6 +96,11 @@ attacks: # Chance to shuffle your hotbar as a percentage - set to 0 to disable. shuffle-chance: 0 + # How the boss decides who to attack + target: + distance: 15 # The distance to check for nearby players. + mode: random + sounds: # Sounds are formatted like this: # sound:volume:pitch