diff --git a/build.gradle b/build.gradle index 0225d8c..0f549bc 100644 --- a/build.gradle +++ b/build.gradle @@ -61,8 +61,8 @@ allprojects { } dependencies { - compileOnly 'com.willfp:eco:6.24.0' - implementation 'com.willfp:libreforge:3.26.1' + compileOnly 'com.willfp:eco:6.29.0' + implementation 'com.willfp:libreforge:3.28.0' compileOnly 'org.jetbrains:annotations:23.0.0' diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecobosses/bosses/ConfiguredGoal.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecobosses/bosses/ConfiguredGoal.kt new file mode 100644 index 0000000..e98713b --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecobosses/bosses/ConfiguredGoal.kt @@ -0,0 +1,8 @@ +package com.willfp.ecobosses.bosses + +import com.willfp.eco.core.entities.ai.Goal + +data class ConfiguredGoal>( + val priority: Int, + val goal: T +) 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 d22e70b..1936ce6 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 @@ -5,12 +5,18 @@ import com.willfp.eco.core.config.interfaces.Config import com.willfp.eco.core.entities.CustomEntity import com.willfp.eco.core.entities.Entities import com.willfp.eco.core.entities.TestableEntity +import com.willfp.eco.core.entities.ai.EntityController +import com.willfp.eco.core.entities.ai.EntityGoal +import com.willfp.eco.core.entities.ai.EntityGoals +import com.willfp.eco.core.entities.ai.TargetGoal +import com.willfp.eco.core.entities.ai.TargetGoals import com.willfp.eco.core.items.CustomItem import com.willfp.eco.core.items.Items import com.willfp.eco.core.items.builder.ItemStackBuilder import com.willfp.eco.core.recipe.Recipes import com.willfp.eco.core.recipe.parts.EmptyTestableItem import com.willfp.eco.core.recipe.recipes.CraftingRecipe +import com.willfp.eco.util.NamespacedKeyUtils import com.willfp.eco.util.toComponent import com.willfp.ecobosses.events.BossKillEvent import com.willfp.ecobosses.lifecycle.BossLifecycle @@ -37,6 +43,7 @@ import org.bukkit.Bukkit import org.bukkit.Location import org.bukkit.Material import org.bukkit.entity.LivingEntity +import org.bukkit.entity.Mob import org.bukkit.entity.Player import org.bukkit.inventory.ItemStack import org.bukkit.persistence.PersistentDataType @@ -172,6 +179,22 @@ class EcoBoss( locations } + val hasCustomAI = config.getBool("customai.enabled") + + val targetGoals = config.getSubsections("customai.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(config.getSubsection("args")) ?: return@mapNotNull null + ConfiguredGoal(config.getInt("priority"), goal) + } + + val entityGoals = config.getSubsections("customai.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(config.getSubsection("args")) ?: return@mapNotNull null + ConfiguredGoal(config.getInt("priority"), goal) + } + val spawnConditions = config.getSubsections("spawn.conditions").mapNotNull { Conditions.compile(it, "$id Spawn Conditions") } @@ -305,7 +328,7 @@ class EcoBoss( } fun spawn(location: Location): LivingEcoBoss { - val mob = mob.spawn(location) as LivingEntity + val mob = mob.spawn(location) as Mob mob.isPersistent = true mob.isCustomNameVisible = true mob.removeWhenFarAway = false @@ -315,6 +338,16 @@ class EcoBoss( this.id ) + if (hasCustomAI) { + val controller = EntityController.getFor(mob) + .clearAllGoals() + + @Suppress("UNCHECKED_CAST") // What could go wrong? + targetGoals.forEach { controller.addTargetGoal(it.priority, it.goal as TargetGoal) } + @Suppress("UNCHECKED_CAST") + entityGoals.forEach { controller.addEntityGoal(it.priority, it.goal as EntityGoal) } + } + val boss = LivingEcoBoss( plugin, mob.uniqueId, diff --git a/eco-core/core-plugin/src/main/resources/ecobosses.yml b/eco-core/core-plugin/src/main/resources/ecobosses.yml index 41dd6b0..b9bcfc9 100644 --- a/eco-core/core-plugin/src/main/resources/ecobosses.yml +++ b/eco-core/core-plugin/src/main/resources/ecobosses.yml @@ -26,6 +26,10 @@ bosses: # Supported placeholders: %health%, %time% (formats as minutes:seconds, eg 1:56) displayName: "&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. + 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. effects: # Effects are done from the player's perspective: to treat the player as the victim, use the self_as_victim option in args - id: run_chain args: diff --git a/gradle.properties b/gradle.properties index 8848a61..9174caf 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,2 @@ -version = 8.12.1 +version = 8.15.0 plugin-name = EcoBosses \ No newline at end of file