From 7cec9f3e30a7c4a1f8c0d1b3467844bf7abd5cac Mon Sep 17 00:00:00 2001 From: Auxilor Date: Thu, 29 Sep 2022 08:40:30 +0100 Subject: [PATCH] Added separator ambivalence to boss configs and Model Engine animation support --- .../com/willfp/ecobosses/bosses/Bosses.kt | 4 +- .../com/willfp/ecobosses/bosses/EcoBoss.kt | 64 ++++++++++++------- .../src/main/resources/bosses/_example.yml | 28 ++++---- 3 files changed, 59 insertions(+), 37 deletions(-) diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecobosses/bosses/Bosses.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecobosses/bosses/Bosses.kt index bde9fe1..0341fbf 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecobosses/bosses/Bosses.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecobosses/bosses/Bosses.kt @@ -7,6 +7,7 @@ import com.willfp.eco.core.config.ConfigType import com.willfp.eco.core.config.TransientConfig import com.willfp.eco.core.config.updating.ConfigUpdater import com.willfp.ecobosses.EcoBossesPlugin +import com.willfp.libreforge.separatorAmbivalent import org.bukkit.entity.Entity import org.bukkit.entity.LivingEntity import java.io.File @@ -56,7 +57,8 @@ object Bosses { val ecoBossesYml = TransientConfig(File(plugin.dataFolder, "ecobosses.yml"), ConfigType.YAML) for (bossConfig in ecoBossesYml.getSubsections("bosses")) { - addNewBoss(EcoBoss(bossConfig.getString("id"), bossConfig, plugin)) + // Boss configs are separator ambivalent in order to preserve backwards compatibility + addNewBoss(EcoBoss(bossConfig.getString("id"), bossConfig.separatorAmbivalent(), plugin)) } } diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecobosses/bosses/EcoBoss.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecobosses/bosses/EcoBoss.kt index e5e0df7..93fbd52 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecobosses/bosses/EcoBoss.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecobosses/bosses/EcoBoss.kt @@ -49,14 +49,15 @@ import org.bukkit.entity.Mob import org.bukkit.entity.Player import org.bukkit.inventory.ItemStack import org.bukkit.persistence.PersistentDataType -import java.util.* +import java.util.Objects +import java.util.UUID class EcoBoss( override val id: String, val config: Config, private val plugin: EcoPlugin ) : Holder { - val displayName: String = config.getString("displayName") + val displayName: String = config.getString("display-name") val lifespan = config.getInt("lifespan") @@ -66,23 +67,23 @@ class EcoBoss( val targetMode = TargetMode.getByID(config.getString("target.mode"))!! - val isBossBarEnabled = config.getBool("bossBar.enabled") + val isBossBarEnabled = config.getBool("boss-bar.enabled") - val bossBarRadius = config.getDouble("bossBar.radius") + val bossBarRadius = config.getDouble("boss-bar.radius") - val isPreventingMounts = config.getBool("defence.preventMounts") + val isPreventingMounts = config.getBool("defence.prevent-mounts") - val isImmuneToExplosions = config.getBool("defence.explosionImmune") + val isImmuneToExplosions = config.getBool("defence.explosion-immune") - val isImmuneToFire = config.getBool("defence.fireImmune") + val isImmuneToFire = config.getBool("defence.fire-immune") - val isImmuneToDrowning = config.getBool("defence.drowningImmune") + val isImmuneToDrowning = config.getBool("defence.drowning-immune") - val isImmuneToSuffocation = config.getBool("defence.suffocationImmune") + val isImmuneToSuffocation = config.getBool("defence.suffocation-immune") - val meleeDamageMultiplier = config.getDouble("defence.meleeDamageMultiplier") + val meleeDamageMultiplier = config.getDouble("defence.melee-damage-multiplier") - val projectileDamageMultiplier = config.getDouble("defence.projectileDamageMultiplier") + val projectileDamageMultiplier = config.getDouble("defence.projectile-damage-multiplier") val canTeleport = config.getBool("defence.teleportation.enabled") @@ -175,16 +176,16 @@ class EcoBoss( locations } - val hasCustomAI = config.getBool("customai.enabled") + val hasCustomAI = config.getBool("custom-ai.enabled") - val targetGoals = config.getSubsections("customai.target-goals").mapNotNull { + val targetGoals = config.getSubsections("custom-ai.target-goals").mapNotNull { val key = NamespacedKeyUtils.fromStringOrNull(it.getString("key")) ?: return@mapNotNull null val deserializer = TargetGoals.getByKey(key) ?: return@mapNotNull null val goal = deserializer.deserialize(it.getSubsection("args")) ?: return@mapNotNull null ConfiguredGoal(it.getInt("priority"), goal) } - val entityGoals = config.getSubsections("customai.ai-goals").mapNotNull { + val entityGoals = config.getSubsections("custom-ai.ai-goals").mapNotNull { val key = NamespacedKeyUtils.fromStringOrNull(it.getString("key")) ?: return@mapNotNull null val deserializer = EntityGoals.getByKey(key) ?: return@mapNotNull null val goal = deserializer.deserialize(it.getSubsection("args")) ?: return@mapNotNull null @@ -195,9 +196,9 @@ class EcoBoss( Conditions.compile(it, "$id Spawn Conditions") } - private val bossBarColor = BossBar.Color.valueOf(config.getString("bossBar.color").uppercase()) + private val bossBarColor = BossBar.Color.valueOf(config.getString("boss-bar.color").uppercase()) - private val bossBarStyle = BossBar.Overlay.valueOf(config.getString("bossBar.style").uppercase()) + private val bossBarStyle = BossBar.Overlay.valueOf(config.getString("boss-bar.style").uppercase()) private val sounds: Map = run { val map = mutableMapOf() @@ -238,10 +239,10 @@ class EcoBoss( private val commandRewards: Map> = run { val map = mutableMapOf>() - for (rank in config.getSubsection("rewards.topDamagerCommands").getKeys(false)) { + for (rank in config.getSubsection("rewards.top-damager-commands").getKeys(false)) { val rankRewards = mutableListOf() - for (config in config.getSubsections("rewards.topDamagerCommands.$rank")) { + for (config in config.getSubsections("rewards.top-damager-commands.$rank")) { rankRewards.add( CommandReward( config.getDouble("chance"), @@ -256,12 +257,12 @@ class EcoBoss( map } - private val nearbyCommandRewardRadius = config.getDouble("rewards.nearbyPlayerCommands.radius") + private val nearbyCommandRewardRadius = config.getDouble("rewards.nearby-player-commands.radius") private val nearbyCommands: Iterable = run { val list = mutableListOf() - for (config in config.getSubsections("rewards.nearbyPlayerCommands.commands")) { + for (config in config.getSubsections("rewards.nearby-player-commands.commands")) { list.add( CommandReward( config.getDouble("chance"), @@ -298,7 +299,9 @@ class EcoBoss( private val mob: TestableEntity = Entities.lookup(config.getString("mob")) - private val modelEngineID = config.getStringOrNull("modelEngineID") + private val modelEngineID = config.getStringOrNull("model-engine-id") + + private val modelEngineAnimation = config.getStringOrNull("model-engine-animation") private val currentlyAlive = mutableMapOf() @@ -346,13 +349,30 @@ class EcoBoss( entityGoals.forEach { controller.addEntityGoal(it.priority, it.goal as EntityGoal) } } - if (modelEngineID != null && Bukkit.getPluginManager().isPluginEnabled("modelEngine")) { + if (modelEngineID != null && Bukkit.getPluginManager().isPluginEnabled("ModelEngine")) { val model = ModelEngineAPI.createActiveModel(modelEngineID) if (model == null) { plugin.logger.warning("Invalid Model Engine ID for boss $id") } + if (modelEngineAnimation != null) { + val animationHandler = model.animationHandler + val animationProperty = animationHandler.getAnimation(modelEngineAnimation) + + if (animationProperty != null) { + animationHandler.playAnimation(animationProperty, true) + } else { + plugin.logger.warning("Animation $modelEngineAnimation not found in model $modelEngineID, defaulting to walk!") + val animationPropertyWalk = animationHandler.getAnimation("walk") + if (animationPropertyWalk != null) { + animationHandler.playAnimation(animationPropertyWalk, true) + } else { + plugin.logger.warning("Walk animation not found in $modelEngineID!") + } + } + } + val modelled = ModelEngineAPI.createModeledEntity(mob) modelled.addModel(model, true) modelled.isBaseEntityVisible = false diff --git a/eco-core/core-plugin/src/main/resources/bosses/_example.yml b/eco-core/core-plugin/src/main/resources/bosses/_example.yml index f31d319..8250455 100644 --- a/eco-core/core-plugin/src/main/resources/bosses/_example.yml +++ b/eco-core/core-plugin/src/main/resources/bosses/_example.yml @@ -9,14 +9,14 @@ mob: iron_golem attack-damage:90 movement-speed:1.5 follow-range:16 health:1200 # If you're using model engine, you can specify the ID here -modelEngineID: "" +model-engine-id: "" # Supported placeholders: %health%, %time% (formats as minutes:seconds, eg 1:56) -displayName: "&8Steel Golem &7| &c%health%♥ &7| &e%time%" +display-name: "&8Steel Golem &7| &c%health%♥ &7| &e%time%" influence: 40 # The distance at which effects will be applied to players -customai: # Custom mob AI using the entity goal system. +custom-ai: # Custom mob AI using the entity goal system. enabled: false # If custom AI should be enabled, this will override the vanilla mob behaviour. target-goals: [ ] # How the boss decides who to attack, if the target mode isn't being used. ai-goals: [ ] # How the boss should behave. @@ -35,14 +35,14 @@ conditions: [ ] # Conditions to apply effects to players; useful if you don't wa lifespan: 120 # The lifespan of the boss before it despawns, in seconds. Set to a massive number to disable. defence: - preventMounts: true # If the boss shouldn't be able to get into boats, minecarts, etc - explosionImmune: true # If the boss should be immune to explosions - fireImmune: true # If the boss should be immune to fire damage - drowningImmune: true # If the boss should be immune to drowning damage - suffocationImmune: true # If the boss should be immune to suffocation + prevent-mounts: true # If the boss shouldn't be able to get into boats, minecarts, etc + explosion-immune: true # If the boss should be immune to explosions + fire-immune: true # If the boss should be immune to fire damage + drowning-immune: true # If the boss should be immune to drowning damage + suffocation-immune: true # If the boss should be immune to suffocation - meleeDamageMultiplier: 0.8 # Incoming melee damage will be multiplied by this value. Set to 0 to render immune against melee - projectileDamageMultiplier: 0.2 # Same as melee multiplier, but for projectiles + melee-damage-multiplier: 0.8 # Incoming melee damage will be multiplied by this value. Set to 0 to render immune against melee + projectile-damage-multiplier: 0.2 # Same as melee multiplier, but for projectiles teleportation: # Teleport every x ticks in order to avoid being caged in obsidian or similar enabled: true # If the boss should teleport @@ -54,7 +54,7 @@ rewards: minimum: 30000 maximum: 60000 - topDamagerCommands: + top-damager-commands: # You can specify as many ranks as you want (adding 4, 5, etc) # You can use %player% as a placeholder for the player name 1: @@ -64,7 +64,7 @@ rewards: 2: [ ] 3: [ ] - nearbyPlayerCommands: + nearby-player-commands: # Commands to be executed for all players near the boss death location radius: 10 # Uses the same syntax as top damager commands (chance and a list of commands, can use %player%) @@ -83,7 +83,7 @@ target: # The distance to scan for players range: 40 -bossBar: +boss-bar: # If the boss should have a boss bar enabled: true color: white # Options: blue, green, pink, purple, red, white, yellow @@ -108,7 +108,7 @@ spawn: top: netherite_block middle: iron_block bottom: magma_block - notInWorlds: [ ] # If spawn totems should be disallowed in certain worlds, specify them here + not-in-worlds: [ ] # If spawn totems should be disallowed in certain worlds, specify them here egg: enabled: true # If the boss should have a spawn egg item: evoker_spawn_egg unbreaking:1 hide_enchants