From 63da63c7d75471f77b283459cb3a8ee48ec4bf6b Mon Sep 17 00:00:00 2001 From: Auxilor Date: Thu, 11 May 2023 14:41:39 +0100 Subject: [PATCH] Reimplemented xp gain display, libreforge effects, and skill crits --- .../com/willfp/ecoskills/EcoSkillsPlugin.kt | 39 ++++++- .../ecoskills/actionbar/ActionBarHandler.kt | 27 +++-- .../com/willfp/ecoskills/api/EcoSkillsAPI.kt | 3 + .../api/event/PlayerSkillXPGainEvent.kt | 2 +- .../libreforge/ConditionHasSkillLevel.kt | 31 +++++ .../ecoskills/libreforge/EffectAddStat.kt | 44 +++++++ .../libreforge/EffectAddStatTemporarily.kt | 54 +++++++++ .../ecoskills/libreforge/EffectGiveSkillXp.kt | 32 +++++ .../libreforge/EffectMakeSkillCrit.kt | 40 +++++++ .../libreforge/EffectMultiplyAllStats.kt | 49 ++++++++ .../libreforge/EffectMultiplyStat.kt | 44 +++++++ .../EffectMultiplyStatTemporarily.kt | 54 +++++++++ .../libreforge/EffectSkillXpMultiplier.kt | 26 +++++ .../ecoskills/libreforge/FilterSkill.kt | 21 ++++ .../ecoskills/libreforge/FilterSkillCrit.kt | 20 ++++ .../libreforge/TriggerGainSkillXp.kt | 30 +++++ .../com/willfp/ecoskills/skills/Skill.kt | 44 ++++--- .../com/willfp/ecoskills/skills/SkillCrits.kt | 15 +++ .../willfp/ecoskills/skills/SkillLevelMap.kt | 2 +- .../ecoskills/skills/SkillXPAccumulator.kt | 7 ++ .../skills/display/DamageIndicatorListener.kt | 110 ++++++++++++++++++ .../ecoskills/skills/display/GainXPDisplay.kt | 80 +++++++++++++ .../LevelUpDisplay.kt} | 12 +- .../skills/display/TemporaryBossBars.kt | 60 ++++++++++ .../core-plugin/src/main/resources/config.yml | 84 ++++++++++--- .../src/main/resources/skills/_example.yml | 13 +++ 26 files changed, 882 insertions(+), 61 deletions(-) create mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/ConditionHasSkillLevel.kt create mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/EffectAddStat.kt create mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/EffectAddStatTemporarily.kt create mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/EffectGiveSkillXp.kt create mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/EffectMakeSkillCrit.kt create mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/EffectMultiplyAllStats.kt create mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/EffectMultiplyStat.kt create mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/EffectMultiplyStatTemporarily.kt create mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/EffectSkillXpMultiplier.kt create mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/FilterSkill.kt create mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/FilterSkillCrit.kt create mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/TriggerGainSkillXp.kt create mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/SkillCrits.kt create mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/display/DamageIndicatorListener.kt create mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/display/GainXPDisplay.kt rename eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/{SkillLevelUpListener.kt => display/LevelUpDisplay.kt} (65%) create mode 100644 eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/display/TemporaryBossBars.kt diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/EcoSkillsPlugin.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/EcoSkillsPlugin.kt index fba4b42..976c3f3 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/EcoSkillsPlugin.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/EcoSkillsPlugin.kt @@ -8,15 +8,31 @@ import com.willfp.ecoskills.actionbar.ActionBarHandler import com.willfp.ecoskills.commands.CommandEcoSkills import com.willfp.ecoskills.commands.CommandSkills import com.willfp.ecoskills.effects.Effects +import com.willfp.ecoskills.libreforge.ConditionHasSkillLevel +import com.willfp.ecoskills.libreforge.EffectAddStat +import com.willfp.ecoskills.libreforge.EffectAddStatTemporarily +import com.willfp.ecoskills.libreforge.EffectGiveSkillXp +import com.willfp.ecoskills.libreforge.EffectMultiplyAllStats +import com.willfp.ecoskills.libreforge.EffectMultiplyStat +import com.willfp.ecoskills.libreforge.EffectMultiplyStatTemporarily +import com.willfp.ecoskills.libreforge.EffectSkillXpMultiplier +import com.willfp.ecoskills.libreforge.FilterSkill +import com.willfp.ecoskills.libreforge.TriggerGainSkillXp +import com.willfp.ecoskills.libreforge.TriggerLevelUpSkill import com.willfp.ecoskills.skills.EcoSkillsTopPlaceholder -import com.willfp.ecoskills.skills.Skill -import com.willfp.ecoskills.skills.SkillLevelUpListener import com.willfp.ecoskills.skills.Skills +import com.willfp.ecoskills.skills.display.DamageIndicatorListener +import com.willfp.ecoskills.skills.display.GainXPDisplay +import com.willfp.ecoskills.skills.display.LevelUpDisplay +import com.willfp.ecoskills.skills.display.TemporaryBossBarHandler import com.willfp.ecoskills.stats.Stats import com.willfp.libreforge.SimpleProvidedHolder +import com.willfp.libreforge.conditions.Conditions +import com.willfp.libreforge.filters.Filters import com.willfp.libreforge.loader.LibreforgePlugin import com.willfp.libreforge.loader.configs.ConfigCategory import com.willfp.libreforge.registerHolderProvider +import com.willfp.libreforge.triggers.Triggers import org.bukkit.event.Listener internal lateinit var plugin: EcoSkillsPlugin @@ -42,11 +58,24 @@ class EcoSkillsPlugin : LibreforgePlugin() { } override fun handleEnable() { + com.willfp.libreforge.effects.Effects.register(EffectAddStat) + com.willfp.libreforge.effects.Effects.register(EffectMultiplyStat) + com.willfp.libreforge.effects.Effects.register(EffectSkillXpMultiplier) + com.willfp.libreforge.effects.Effects.register(EffectGiveSkillXp) + com.willfp.libreforge.effects.Effects.register(EffectMultiplyAllStats) + com.willfp.libreforge.effects.Effects.register(EffectAddStatTemporarily(this)) + com.willfp.libreforge.effects.Effects.register(EffectMultiplyStatTemporarily(this)) + Conditions.register(ConditionHasSkillLevel) + Triggers.register(TriggerGainSkillXp) + Triggers.register(TriggerLevelUpSkill) + Filters.register(FilterSkill) + EcoSkillsTopPlaceholder(this).register() } override fun handleReload() { - ActionBarHandler(this).beginTickingActionBar() + ActionBarHandler(this).startTicking() + TemporaryBossBarHandler(this).startTicking() } override fun loadPluginCommands(): List { @@ -58,7 +87,9 @@ class EcoSkillsPlugin : LibreforgePlugin() { override fun loadListeners(): List { return listOf( - SkillLevelUpListener(this), + LevelUpDisplay(this), + GainXPDisplay(this), + DamageIndicatorListener(this), ActionBarGamemodeListener ) } diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/actionbar/ActionBarHandler.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/actionbar/ActionBarHandler.kt index 73bb0de..7a14898 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/actionbar/ActionBarHandler.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/actionbar/ActionBarHandler.kt @@ -18,6 +18,15 @@ private val blacklist = mutableMapOf() private val whitelist = mutableMapOf() +fun Player.sendCompatibleActionBarMessage(message: String) { + // Have to use the shit method for compatibility. + @Suppress("DEPRECATION") + this.spigot().sendMessage( + net.md_5.bungee.api.ChatMessageType.ACTION_BAR, + *net.md_5.bungee.api.chat.TextComponent.fromLegacyText(message) + ) +} + fun Player.pausePersistentActionBar() { if (isSendingPersistentActionBar) { return @@ -32,15 +41,9 @@ private val Player.isPersistentActionBarPaused: Boolean return time > System.currentTimeMillis() } -private fun Player.sendPersistentActionBar(string: String) { +private fun Player.sendPersistentActionBar(message: String) { whitelist[this.uniqueId] = System.currentTimeMillis() + TICK_DURATION - - // Have to use the shit method for compatibility. - @Suppress("DEPRECATION") - this.spigot().sendMessage( - net.md_5.bungee.api.ChatMessageType.ACTION_BAR, - *net.md_5.bungee.api.chat.TextComponent.fromLegacyText(string) - ) + sendCompatibleActionBarMessage(message) } private val Player.isSendingPersistentActionBar: Boolean @@ -53,11 +56,7 @@ object ActionBarGamemodeListener : Listener { @EventHandler fun handle(event: PlayerGameModeChangeEvent) { if (event.newGameMode in setOf(GameMode.CREATIVE, GameMode.SPECTATOR)) { - @Suppress("DEPRECATION") - event.player.spigot().sendMessage( - net.md_5.bungee.api.ChatMessageType.ACTION_BAR, - *net.md_5.bungee.api.chat.TextComponent.fromLegacyText("") - ) + event.player.sendCompatibleActionBarMessage("") } } } @@ -96,7 +95,7 @@ class ActionBarHandler( ) } - internal fun beginTickingActionBar() { + internal fun startTicking() { plugin.scheduler.runTimer(5, 5) { for (player in Bukkit.getOnlinePlayers()) { trySendMessage(player) diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/api/EcoSkillsAPI.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/api/EcoSkillsAPI.kt index 8991d82..ef65e74 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/api/EcoSkillsAPI.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/api/EcoSkillsAPI.kt @@ -33,6 +33,9 @@ fun OfflinePlayer.giveSkillXP(skill: Skill, xp: Double): Unit = fun OfflinePlayer.getRequiredXP(skill: Skill) = skill.getXPRequired(this.getSkillLevel(skill)) +fun OfflinePlayer.getFormattedRequiredXP(skill: Skill) = + skill.getFormattedXPRequired(this.getSkillLevel(skill)) + fun OfflinePlayer.getSkillProgress(skill: Skill): Double { val currentXP = getSkillXP(skill) val requiredXP = getRequiredXP(skill) diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/api/event/PlayerSkillXPGainEvent.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/api/event/PlayerSkillXPGainEvent.kt index f278158..4430bcd 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/api/event/PlayerSkillXPGainEvent.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/api/event/PlayerSkillXPGainEvent.kt @@ -8,7 +8,7 @@ import org.bukkit.event.HandlerList class PlayerSkillXPGainEvent( who: Player, skill: Skill, - var xp: Double + var gainedXP: Double ) : PlayerSkillEvent(who, skill), Cancellable { private var _cancelled = false diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/ConditionHasSkillLevel.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/ConditionHasSkillLevel.kt new file mode 100644 index 0000000..b5b8107 --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/ConditionHasSkillLevel.kt @@ -0,0 +1,31 @@ +package com.willfp.ecoskills.libreforge + +import com.willfp.eco.core.config.interfaces.Config +import com.willfp.ecoskills.api.event.PlayerSkillLevelUpEvent +import com.willfp.ecoskills.api.getSkillLevel +import com.willfp.ecoskills.skills.Skills +import com.willfp.libreforge.NoCompileData +import com.willfp.libreforge.arguments +import com.willfp.libreforge.conditions.Condition +import com.willfp.libreforge.updateEffects +import org.bukkit.entity.Player +import org.bukkit.event.EventHandler +import org.bukkit.event.EventPriority + +object ConditionHasSkillLevel : Condition("has_skill_level") { + override val arguments = arguments { + require("skill", "You must specify the skill!") + require("level", "You must specify the skill level!") + } + + override fun isMet(player: Player, config: Config, compileData: NoCompileData): Boolean { + val skill = Skills.getByID(config.getString("skill").lowercase()) ?: return false + + return player.getSkillLevel(skill) >= config.getIntFromExpression("level", player) + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + fun handle(event: PlayerSkillLevelUpEvent) { + event.player.updateEffects() + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/EffectAddStat.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/EffectAddStat.kt new file mode 100644 index 0000000..369fdd1 --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/EffectAddStat.kt @@ -0,0 +1,44 @@ +package com.willfp.ecoskills.libreforge + +import com.willfp.eco.core.config.interfaces.Config +import com.willfp.ecoskills.api.addStatModifier +import com.willfp.ecoskills.api.modifiers.ModifierOperation +import com.willfp.ecoskills.api.modifiers.StatModifier +import com.willfp.ecoskills.api.removeStatModifier +import com.willfp.ecoskills.stats.Stats +import com.willfp.libreforge.NoCompileData +import com.willfp.libreforge.ProvidedHolder +import com.willfp.libreforge.arguments +import com.willfp.libreforge.effects.Effect +import com.willfp.libreforge.effects.Identifiers +import org.bukkit.entity.Player + +object EffectAddStat : Effect("add_stat") { + override val arguments = arguments { + require("stat", "You must specify the stat!") + require("amount", "You must specify the amount to add/remove!") + } + + override fun onEnable( + player: Player, + config: Config, + identifiers: Identifiers, + holder: ProvidedHolder, + compileData: NoCompileData + ) { + val stat = Stats.getByID(config.getString("stat")) ?: return + + player.addStatModifier( + StatModifier( + identifiers.uuid, + stat, + config.getDoubleFromExpression("amount", player), + ModifierOperation.ADD + ) + ) + } + + override fun onDisable(player: Player, identifiers: Identifiers, holder: ProvidedHolder) { + player.removeStatModifier(identifiers.uuid) + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/EffectAddStatTemporarily.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/EffectAddStatTemporarily.kt new file mode 100644 index 0000000..ab7ee73 --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/EffectAddStatTemporarily.kt @@ -0,0 +1,54 @@ +package com.willfp.ecoskills.libreforge + +import com.willfp.eco.core.EcoPlugin +import com.willfp.eco.core.config.interfaces.Config +import com.willfp.eco.util.NumberUtils +import com.willfp.ecoskills.api.addStatModifier +import com.willfp.ecoskills.api.modifiers.ModifierOperation +import com.willfp.ecoskills.api.modifiers.StatModifier +import com.willfp.ecoskills.api.removeStatModifier +import com.willfp.ecoskills.stats.Stats +import com.willfp.libreforge.NoCompileData +import com.willfp.libreforge.arguments +import com.willfp.libreforge.effects.Effect +import com.willfp.libreforge.getDoubleFromExpression +import com.willfp.libreforge.getIntFromExpression +import com.willfp.libreforge.triggers.TriggerData +import com.willfp.libreforge.triggers.TriggerParameter +import java.util.UUID + +class EffectAddStatTemporarily( + private val plugin: EcoPlugin +) : Effect("add_stat_temporarily") { + override val parameters = setOf( + TriggerParameter.PLAYER + ) + + override val arguments = arguments { + require("stat", "You must specify the stat!") + require("amount", "You must specify the amount to add/remove!") + require("duration", "You must specify the duration for the boost!") + } + + override fun onTrigger(config: Config, data: TriggerData, compileData: NoCompileData): Boolean { + val player = data.player ?: return false + val stat = Stats.getByID(config.getString("stat")) ?: return false + val amount = config.getDoubleFromExpression("amount", data) + val uuid = UUID.nameUUIDFromBytes("ast_${NumberUtils.randInt(0, 1000000)}".toByteArray()) + + player.addStatModifier( + StatModifier( + uuid, + stat, + amount, + ModifierOperation.ADD + ) + ) + + plugin.scheduler.runLater(config.getIntFromExpression("duration", data).toLong()) { + player.removeStatModifier(uuid) + } + + return true + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/EffectGiveSkillXp.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/EffectGiveSkillXp.kt new file mode 100644 index 0000000..89453b3 --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/EffectGiveSkillXp.kt @@ -0,0 +1,32 @@ +package com.willfp.ecoskills.libreforge + +import com.willfp.eco.core.config.interfaces.Config +import com.willfp.ecoskills.api.giveSkillXP +import com.willfp.ecoskills.skills.Skills +import com.willfp.libreforge.NoCompileData +import com.willfp.libreforge.arguments +import com.willfp.libreforge.effects.Effect +import com.willfp.libreforge.getDoubleFromExpression +import com.willfp.libreforge.triggers.TriggerData +import com.willfp.libreforge.triggers.TriggerParameter + +object EffectGiveSkillXp : Effect("give_skill_xp") { + override val parameters = setOf( + TriggerParameter.PLAYER + ) + + override val arguments = arguments { + require("amount", "You must specify the amount of xp to give!") + require("skill", "You must specify the skill to give xp for!") + } + + override fun onTrigger(config: Config, data: TriggerData, compileData: NoCompileData): Boolean { + val player = data.player ?: return false + + val skill = Skills.getByID(config.getString("skill")) ?: return false + + player.giveSkillXP(skill, config.getDoubleFromExpression("amount", data)) + + return true + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/EffectMakeSkillCrit.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/EffectMakeSkillCrit.kt new file mode 100644 index 0000000..ce65f06 --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/EffectMakeSkillCrit.kt @@ -0,0 +1,40 @@ +package com.willfp.ecoskills.libreforge + +import com.willfp.eco.core.config.interfaces.Config +import com.willfp.ecoskills.api.addStatModifier +import com.willfp.ecoskills.api.modifiers.ModifierOperation +import com.willfp.ecoskills.api.modifiers.StatModifier +import com.willfp.ecoskills.api.removeStatModifier +import com.willfp.ecoskills.skills.skillCrit +import com.willfp.ecoskills.stats.Stats +import com.willfp.libreforge.NoCompileData +import com.willfp.libreforge.ProvidedHolder +import com.willfp.libreforge.arguments +import com.willfp.libreforge.effects.Effect +import com.willfp.libreforge.effects.Identifiers +import com.willfp.libreforge.effects.RunOrder +import com.willfp.libreforge.getDoubleFromExpression +import com.willfp.libreforge.triggers.TriggerData +import com.willfp.libreforge.triggers.TriggerParameter +import org.bukkit.entity.Player +import org.bukkit.event.entity.EntityDamageByEntityEvent + +object EffectMakeSkillCrit : Effect("make_skill_crit") { + override val runOrder = RunOrder.EARLY + + override val arguments = arguments { + require("multiplier", "You must specify the damage multiplier!") + } + + override val parameters = setOf( + TriggerParameter.EVENT + ) + + override fun onTrigger(config: Config, data: TriggerData, compileData: NoCompileData): Boolean { + val event = data.event as? EntityDamageByEntityEvent ?: return false + + event.skillCrit *= config.getDoubleFromExpression("multiplier", data) + + return true + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/EffectMultiplyAllStats.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/EffectMultiplyAllStats.kt new file mode 100644 index 0000000..db46cea --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/EffectMultiplyAllStats.kt @@ -0,0 +1,49 @@ +package com.willfp.ecoskills.libreforge + +import com.willfp.eco.core.config.interfaces.Config +import com.willfp.ecoskills.api.addStatModifier +import com.willfp.ecoskills.api.modifiers.ModifierOperation +import com.willfp.ecoskills.api.modifiers.StatModifier +import com.willfp.ecoskills.api.removeStatModifier +import com.willfp.ecoskills.stats.Stats +import com.willfp.libreforge.NoCompileData +import com.willfp.libreforge.ProvidedHolder +import com.willfp.libreforge.arguments +import com.willfp.libreforge.effects.Effect +import com.willfp.libreforge.effects.Identifiers +import org.bukkit.entity.Player + +object EffectMultiplyAllStats : Effect("multiply_all_stats") { + override val arguments = arguments { + require("multiplier", "You must specify the multiplier!") + } + + override fun onEnable( + player: Player, + config: Config, + identifiers: Identifiers, + holder: ProvidedHolder, + compileData: NoCompileData + ) { + val factory = identifiers.makeFactory() + + for ((offset, stat) in Stats.values().withIndex()) { + player.addStatModifier( + StatModifier( + factory.makeIdentifiers(offset).uuid, + stat, + config.getDoubleFromExpression("multiplier", player), + ModifierOperation.MULTIPLY + ) + ) + } + } + + override fun onDisable(player: Player, identifiers: Identifiers, holder: ProvidedHolder) { + val factory = identifiers.makeFactory() + + for (offset in Stats.values().indices) { + player.removeStatModifier(factory.makeIdentifiers(offset).uuid) + } + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/EffectMultiplyStat.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/EffectMultiplyStat.kt new file mode 100644 index 0000000..be333df --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/EffectMultiplyStat.kt @@ -0,0 +1,44 @@ +package com.willfp.ecoskills.libreforge + +import com.willfp.eco.core.config.interfaces.Config +import com.willfp.ecoskills.api.addStatModifier +import com.willfp.ecoskills.api.modifiers.ModifierOperation +import com.willfp.ecoskills.api.modifiers.StatModifier +import com.willfp.ecoskills.api.removeStatModifier +import com.willfp.ecoskills.stats.Stats +import com.willfp.libreforge.NoCompileData +import com.willfp.libreforge.ProvidedHolder +import com.willfp.libreforge.arguments +import com.willfp.libreforge.effects.Effect +import com.willfp.libreforge.effects.Identifiers +import org.bukkit.entity.Player + +object EffectMultiplyStat : Effect("multiply_stat") { + override val arguments = arguments { + require("stat", "You must specify the stat!") + require("multiplier", "You must specify the multiplier!") + } + + override fun onEnable( + player: Player, + config: Config, + identifiers: Identifiers, + holder: ProvidedHolder, + compileData: NoCompileData + ) { + val stat = Stats.getByID(config.getString("stat")) ?: return + + player.addStatModifier( + StatModifier( + identifiers.uuid, + stat, + config.getDoubleFromExpression("multiplier", player), + ModifierOperation.MULTIPLY + ) + ) + } + + override fun onDisable(player: Player, identifiers: Identifiers, holder: ProvidedHolder) { + player.removeStatModifier(identifiers.uuid) + } +} \ No newline at end of file diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/EffectMultiplyStatTemporarily.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/EffectMultiplyStatTemporarily.kt new file mode 100644 index 0000000..74a3c5e --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/EffectMultiplyStatTemporarily.kt @@ -0,0 +1,54 @@ +package com.willfp.ecoskills.libreforge + +import com.willfp.eco.core.EcoPlugin +import com.willfp.eco.core.config.interfaces.Config +import com.willfp.eco.util.NumberUtils +import com.willfp.ecoskills.api.addStatModifier +import com.willfp.ecoskills.api.modifiers.ModifierOperation +import com.willfp.ecoskills.api.modifiers.StatModifier +import com.willfp.ecoskills.api.removeStatModifier +import com.willfp.ecoskills.stats.Stats +import com.willfp.libreforge.NoCompileData +import com.willfp.libreforge.arguments +import com.willfp.libreforge.effects.Effect +import com.willfp.libreforge.getDoubleFromExpression +import com.willfp.libreforge.getIntFromExpression +import com.willfp.libreforge.triggers.TriggerData +import com.willfp.libreforge.triggers.TriggerParameter +import java.util.UUID + +class EffectMultiplyStatTemporarily( + private val plugin: EcoPlugin +) : Effect("add_stat_temporarily") { + override val parameters = setOf( + TriggerParameter.PLAYER + ) + + override val arguments = arguments { + require("stat", "You must specify the stat!") + require("amount", "You must specify the amount to add/remove!") + require("duration", "You must specify the duration for the boost!") + } + + override fun onTrigger(config: Config, data: TriggerData, compileData: NoCompileData): Boolean { + val player = data.player ?: return false + val stat = Stats.getByID(config.getString("stat")) ?: return false + val multiplier = config.getDoubleFromExpression("multiplier", data) + val uuid = UUID.nameUUIDFromBytes("mst_${NumberUtils.randInt(0, 1000000)}".toByteArray()) + + player.addStatModifier( + StatModifier( + uuid, + stat, + multiplier, + ModifierOperation.MULTIPLY + ) + ) + + plugin.scheduler.runLater(config.getIntFromExpression("duration", data).toLong()) { + player.removeStatModifier(uuid) + } + + return true + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/EffectSkillXpMultiplier.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/EffectSkillXpMultiplier.kt new file mode 100644 index 0000000..9e14313 --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/EffectSkillXpMultiplier.kt @@ -0,0 +1,26 @@ +package com.willfp.ecoskills.libreforge + +import com.willfp.ecoskills.api.event.PlayerSkillXPGainEvent +import com.willfp.ecoskills.skills.Skill +import com.willfp.ecoskills.skills.Skills +import com.willfp.libreforge.effects.templates.MultiMultiplierEffect +import org.bukkit.event.EventHandler + +object EffectSkillXpMultiplier : MultiMultiplierEffect("skill_xp_multiplier") { + override val key = "skills" + + override fun getElement(key: String): Skill? { + return Skills.getByID(key) + } + + override fun getAllElements(): Collection { + return Skills.values() + } + + @EventHandler(ignoreCancelled = true) + fun handle(event: PlayerSkillXPGainEvent) { + val player = event.player + + event.gainedXP *= getMultiplier(player, event.skill) + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/FilterSkill.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/FilterSkill.kt new file mode 100644 index 0000000..a724f8e --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/FilterSkill.kt @@ -0,0 +1,21 @@ +package com.willfp.ecoskills.libreforge + +import com.willfp.eco.core.config.interfaces.Config +import com.willfp.ecoskills.api.event.SkillEvent +import com.willfp.libreforge.NoCompileData +import com.willfp.libreforge.filters.Filter +import com.willfp.libreforge.triggers.TriggerData + +object FilterSkill : Filter>("skill") { + override fun getValue(config: Config, data: TriggerData?, key: String): Collection { + return config.getStrings(key) + } + + override fun isMet(data: TriggerData, value: Collection, compileData: NoCompileData): Boolean { + val event = data.event as? SkillEvent ?: return true + + return value.any { skillName -> + skillName.equals(event.skill.id, ignoreCase = true) + } + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/FilterSkillCrit.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/FilterSkillCrit.kt new file mode 100644 index 0000000..9102081 --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/FilterSkillCrit.kt @@ -0,0 +1,20 @@ +package com.willfp.ecoskills.libreforge + +import com.willfp.eco.core.config.interfaces.Config +import com.willfp.ecoskills.skills.isSkillCrit +import com.willfp.libreforge.NoCompileData +import com.willfp.libreforge.filters.Filter +import com.willfp.libreforge.triggers.TriggerData +import org.bukkit.event.entity.EntityDamageByEntityEvent + +object FilterSkillCrit : Filter("skill_crit") { + override fun getValue(config: Config, data: TriggerData?, key: String): Boolean { + return config.getBool(key) + } + + override fun isMet(data: TriggerData, value: Boolean, compileData: NoCompileData): Boolean { + val event = data.event as? EntityDamageByEntityEvent ?: return true + + return event.isSkillCrit == value + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/TriggerGainSkillXp.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/TriggerGainSkillXp.kt new file mode 100644 index 0000000..2151bc4 --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/libreforge/TriggerGainSkillXp.kt @@ -0,0 +1,30 @@ +package com.willfp.ecoskills.libreforge + +import com.willfp.ecoskills.api.event.PlayerSkillXPGainEvent +import com.willfp.libreforge.triggers.Trigger +import com.willfp.libreforge.triggers.TriggerData +import com.willfp.libreforge.triggers.TriggerParameter +import org.bukkit.event.EventHandler + +object TriggerGainSkillXp : Trigger("gain_skill_xp") { + override val parameters = setOf( + TriggerParameter.PLAYER, + TriggerParameter.LOCATION, + TriggerParameter.EVENT + ) + + @EventHandler(ignoreCancelled = true) + fun handle(event: PlayerSkillXPGainEvent) { + val player = event.player + + this.dispatch( + player, + TriggerData( + player = player, + location = player.location, + event = event, + value = event.gainedXP + ) + ) + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/Skill.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/Skill.kt index 5540d04..0ae253f 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/Skill.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/Skill.kt @@ -11,6 +11,7 @@ import com.willfp.eco.util.formatEco import com.willfp.eco.util.toNiceString import com.willfp.eco.util.toNumeral import com.willfp.ecoskills.EcoSkillsPlugin +import com.willfp.ecoskills.api.getFormattedRequiredXP import com.willfp.ecoskills.api.getRequiredXP import com.willfp.ecoskills.api.getSkillLevel import com.willfp.ecoskills.api.getSkillProgress @@ -91,7 +92,7 @@ class Skill( }.register() PlayerPlaceholder(plugin, "${id}_required_xp") { - getXPRequired(it.getSkillLevel(this)).toNiceString() + getFormattedXPRequired(it.getSkillLevel(this)) }.register() PlayerPlaceholder(plugin, "${id}_percentage_progress") { @@ -100,7 +101,7 @@ class Skill( } override fun onRegister() { - val accumulator = SkillXPAccumulator(this) + val accumulator = SkillXPAccumulator(plugin, this) for (counter in xpGainMethods) { counter.bind(accumulator) @@ -133,6 +134,15 @@ class Skill( return Double.POSITIVE_INFINITY } + fun getFormattedXPRequired(level: Int): String { + val required = getXPRequired(level) + return if (required.isInfinite()) { + plugin.langYml.getFormattedString("infinity") + } else { + required.toNiceString() + } + } + /** * Add skill placeholders into [strings], to be shown to a [player]. */ @@ -145,38 +155,38 @@ class Skill( val withPlaceholders = strings.map { s -> s.replace("%percentage_progress%", (player.getSkillProgress(this) * 100).toNiceString()) .replace("%current_xp%", player.getSkillXP(this).toNiceString()) - .replace("%required_xp%", player.getRequiredXP(this).let { req -> - if (req.isInfinite()) { - plugin.langYml.getFormattedString("infinity") - } else { - req.toNiceString() - } - }) + .replace("%required_xp%", player.getFormattedRequiredXP(this)) .replace("%description%", this.getDescription(player)) .replace("%skill%", this.name) .replace("%level%", level.toString()) .replace("%level_numeral%", level.toNumeral()) } - // Replace the placeholder "%rewards%" with level up messages. - val processed = withPlaceholders.map { s -> + // Replace multi-line placeholders. + val processed = withPlaceholders.flatMap { s -> val margin = s.count { it == ' ' } + if (s.contains("%rewards%")) { - getRewardMessages(level, margin) + getRewardMessages(level).addMargin(margin) + } else if (s.contains("%gui_lore%")) { + config.getStrings("gui.lore").addMargin(margin) } else { listOf(s) } } - return processed.flatten().formatEco(player) + return processed.formatEco(player) + } + + private fun List.addMargin(margin: Int): List { + return this.map { s -> " ".repeat(margin) + s } } /** - * Get the reward messages for a certain [level], with a [margin]. + * Get the reward messages for a certain [level]. */ private fun getRewardMessages( - level: Int, - margin: Int = 0 + level: Int ): List = rewardMessages.getOrPut(level) { // Determine the highest level of messages from the config that is not greater than the provided level. val highestConfiguredLevel = config.getSubsection("reward-messages") @@ -195,7 +205,7 @@ class Skill( placeholderContext( injectable = LevelInjectable(level) ) - ).map { " ".repeat(margin) + it } + ) } internal fun handleLevelUp(player: OfflinePlayer, level: Int) { diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/SkillCrits.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/SkillCrits.kt new file mode 100644 index 0000000..0a95fcb --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/SkillCrits.kt @@ -0,0 +1,15 @@ +package com.willfp.ecoskills.skills + +import org.bukkit.event.entity.EntityDamageByEntityEvent +import java.util.WeakHashMap + +private val map = WeakHashMap() + +var EntityDamageByEntityEvent.skillCrit: Double + get() = map[this] ?: 1.0 + set(value) { + map[this] = value + } + +val EntityDamageByEntityEvent.isSkillCrit: Boolean + get() = map.containsKey(this) diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/SkillLevelMap.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/SkillLevelMap.kt index 386299d..3beab83 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/SkillLevelMap.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/SkillLevelMap.kt @@ -72,7 +72,7 @@ class SkillLevelMap( Bukkit.getPluginManager().callEvent(event) - giveXP(skill, event.xp) + giveXP(skill, event.gainedXP) } else { giveXP(skill, xp) } diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/SkillXPAccumulator.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/SkillXPAccumulator.kt index 6af9b14..bb09c9e 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/SkillXPAccumulator.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/SkillXPAccumulator.kt @@ -1,13 +1,20 @@ package com.willfp.ecoskills.skills +import com.willfp.eco.core.EcoPlugin +import com.willfp.eco.core.integrations.afk.AFKManager import com.willfp.ecoskills.api.gainSkillXP import com.willfp.libreforge.counters.Accumulator import org.bukkit.entity.Player class SkillXPAccumulator( + private val plugin: EcoPlugin, private val skill: Skill ) : Accumulator { override fun accept(player: Player, count: Double) { + if (plugin.configYml.getBool("skills.prevent-levelling-while-afk") && AFKManager.isAfk(player)) { + return + } + player.gainSkillXP(skill, count) } } diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/display/DamageIndicatorListener.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/display/DamageIndicatorListener.kt new file mode 100644 index 0000000..9428581 --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/display/DamageIndicatorListener.kt @@ -0,0 +1,110 @@ +package com.willfp.ecoskills.skills.display + +import com.willfp.eco.core.EcoPlugin +import com.willfp.eco.core.Prerequisite +import com.willfp.eco.core.integrations.hologram.HologramManager +import com.willfp.eco.util.NumberUtils +import com.willfp.eco.util.formatEco +import com.willfp.eco.util.toNiceString +import com.willfp.ecoskills.skills.isSkillCrit +import org.bukkit.GameMode +import org.bukkit.Location +import org.bukkit.entity.Allay +import org.bukkit.entity.Player +import org.bukkit.event.EventHandler +import org.bukkit.event.EventPriority +import org.bukkit.event.Listener +import org.bukkit.event.entity.EntityDamageByEntityEvent +import org.bukkit.event.entity.EntityRegainHealthEvent + +class DamageIndicatorListener( + private val plugin: EcoPlugin +) : Listener { + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + fun onEntityDamageByEntity(event: EntityDamageByEntityEvent) { + if (!plugin.configYml.getBool("damage-indicators.enabled")) { + return + } + + val victim = event.entity + + if (event.entity == event.damager) { + return + } + + if (event.damage == 0.0) { + return + } + + if (victim is Player && victim.isBlocking) { + return + } + + val location = victim.location.clone() + .add(0.0, victim.height, 0.0) + .withHoloOffset() + + var text: String = if (event.isSkillCrit) { + plugin.configYml.getString("damage-indicators.format.crit") + } else { + plugin.configYml.getString("damage-indicators.format.normal") + } + + text = if (plugin.configYml.getBool("damage-indicators.final-damage")) { + text.replace("%damage%", NumberUtils.format(event.finalDamage)) + } else { + text.replace("%damage%", NumberUtils.format(event.damage)) + }.formatEco() + + val holo = HologramManager.createHologram(location, listOf(text)) + + plugin.scheduler.runLater(30) { + holo.remove() + } + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + fun onHeal(event: EntityRegainHealthEvent) { + if (!plugin.configYml.getBool("damage-indicators.healing.enabled")) { + return + } + + val entity = event.entity + + if (entity is Player && entity.gameMode == GameMode.SPECTATOR) { + return + } + + if (Prerequisite.HAS_1_19.isMet) { + if (entity is Allay) { + return + } + } + + val location = entity.location.clone() + .add(0.0, entity.height, 0.0) + .withHoloOffset() + + val text = plugin.configYml.getString("damage-indicators.healing.format") + .replace("%damage%", event.amount.toNiceString()) + .formatEco() + + val holo = HologramManager.createHologram(location, listOf(text)) + + plugin.scheduler.runLater(30) { + holo.remove() + } + } + + private fun Location.withHoloOffset(): Location { + val x = plugin.configYml.getDouble("damage-indicators.max-x-offset") + val y = plugin.configYml.getDouble("damage-indicators.max-y-offset") + val z = plugin.configYml.getDouble("damage-indicators.max-z-offset") + + return this.add( + NumberUtils.randFloat(-x, x), + NumberUtils.randFloat(-y, y), + NumberUtils.randFloat(-z, z) + ) + } +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/display/GainXPDisplay.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/display/GainXPDisplay.kt new file mode 100644 index 0000000..2afa614 --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/display/GainXPDisplay.kt @@ -0,0 +1,80 @@ +package com.willfp.ecoskills.skills.display + +import com.willfp.eco.core.EcoPlugin +import com.willfp.eco.core.sound.PlayableSound +import com.willfp.eco.util.formatEco +import com.willfp.eco.util.toNiceString +import com.willfp.ecoskills.actionbar.sendCompatibleActionBarMessage +import com.willfp.ecoskills.api.event.PlayerSkillXPGainEvent +import com.willfp.ecoskills.api.getFormattedRequiredXP +import com.willfp.ecoskills.api.getRequiredXP +import com.willfp.ecoskills.api.getSkillProgress +import com.willfp.ecoskills.api.getSkillXP +import org.bukkit.boss.BarColor +import org.bukkit.boss.BarStyle +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener + +class GainXPDisplay( + private val plugin: EcoPlugin +) : Listener { + private val sound = if (plugin.configYml.getBool("skills.gain-xp.sound.enabled")) { + PlayableSound.create( + plugin.configYml.getSubsection("skills.gain-xp.sound") + ) + } else null + + @EventHandler + fun handle(event: PlayerSkillXPGainEvent) { + val player = event.player + + // Run next tick because level up calls before xp is added + plugin.scheduler.run { + handleActionBar(event) + handleBossBar(event) + + sound?.playTo(player) + } + } + + private fun handleBossBar(event: PlayerSkillXPGainEvent) { + if (!plugin.configYml.getBool("skills.gain-xp.boss-bar.enabled")) { + return + } + + val player = event.player + val skill = event.skill + + val message = plugin.configYml.getString("skills.gain-xp.boss-bar.message") + .formatMessage(event) + + player.sendTemporaryBossBar( + message, + event.skill.id, + this.plugin.configYml.getInt("skills.progress.boss-bar.duration"), + BarColor.valueOf(this.plugin.configYml.getString("skills.progress.boss-bar.color").uppercase()), + BarStyle.valueOf(this.plugin.configYml.getString("skills.progress.boss-bar.style").uppercase()), + player.getSkillProgress(skill).coerceIn(0.0..1.0) + ) + } + + private fun handleActionBar(event: PlayerSkillXPGainEvent) { + if (!plugin.configYml.getBool("skills.gain-xp.action-bar.enabled")) { + return + } + + val player = event.player + + val message = plugin.configYml.getString("skills.gain-xp.action-bar.message") + .formatMessage(event) + + player.sendCompatibleActionBarMessage(message) + } + + private fun String.formatMessage(event: PlayerSkillXPGainEvent): String = + this.replace("%skill%", event.skill.name) + .replace("%current_xp%", event.player.getSkillXP(event.skill).toNiceString()) + .replace("%required_xp%", event.player.getFormattedRequiredXP(event.skill)) + .replace("%gained_xp%", event.gainedXP.toNiceString()) + .formatEco(event.player) +} diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/SkillLevelUpListener.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/display/LevelUpDisplay.kt similarity index 65% rename from eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/SkillLevelUpListener.kt rename to eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/display/LevelUpDisplay.kt index 985b206..fdcb01b 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/SkillLevelUpListener.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/display/LevelUpDisplay.kt @@ -1,4 +1,4 @@ -package com.willfp.ecoskills.skills +package com.willfp.ecoskills.skills.display import com.willfp.eco.core.EcoPlugin import com.willfp.eco.core.sound.PlayableSound @@ -6,12 +6,12 @@ import com.willfp.ecoskills.api.event.PlayerSkillLevelUpEvent import org.bukkit.event.EventHandler import org.bukkit.event.Listener -class SkillLevelUpListener( +class LevelUpDisplay( private val plugin: EcoPlugin ) : Listener { - private val sound = if (plugin.configYml.getBool("level-up.sound.enabled")) { + private val sound = if (plugin.configYml.getBool("skills.level-up.sound.enabled")) { PlayableSound.create( - plugin.configYml.getSubsection("level-up.sound") + plugin.configYml.getSubsection("skills.level-up.sound") ) } else null @@ -21,8 +21,8 @@ class SkillLevelUpListener( val skill = event.skill val level = event.level - if (plugin.configYml.getBool("level-up.message.enabled")) { - val rawMessage = plugin.configYml.getStrings("level-up.message.message") + if (plugin.configYml.getBool("skills.level-up.message.enabled")) { + val rawMessage = plugin.configYml.getStrings("skills.level-up.message.message") val formatted = skill.addPlaceholdersInto( rawMessage, diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/display/TemporaryBossBars.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/display/TemporaryBossBars.kt new file mode 100644 index 0000000..498cf6a --- /dev/null +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/ecoskills/skills/display/TemporaryBossBars.kt @@ -0,0 +1,60 @@ +package com.willfp.ecoskills.skills.display + +import com.willfp.eco.core.EcoPlugin +import com.willfp.eco.util.namespacedKeyOf +import org.bukkit.Bukkit +import org.bukkit.NamespacedKey +import org.bukkit.boss.BarColor +import org.bukkit.boss.BarStyle +import org.bukkit.entity.Player +import java.util.UUID + +// Maps BossBar's to their expiry time +private val bossBars = mutableMapOf() + +fun Player.sendTemporaryBossBar( + message: String, + identifier: String, // The identifier for the boss bar (e.g. The skill name) + duration: Int, // In milliseconds + barColor: BarColor, + barStyle: BarStyle, + progress: Double // Progress between 0 and 1 +) { + val idBytes = (this.uniqueId.hashCode() shl 5) xor identifier.hashCode() + + val key = namespacedKeyOf("ecoskills", idBytes.toString()) + + val bossBar = Bukkit.getBossBar(key) ?: Bukkit.createBossBar( + key, + message, + barColor, + barStyle + ) + + bossBar.setTitle(message) + bossBar.progress = progress + bossBar.addPlayer(this) + + bossBars[key] = System.currentTimeMillis() + duration +} + +class TemporaryBossBarHandler( + private val plugin: EcoPlugin +) { + internal fun startTicking() { + plugin.scheduler.runTimer(5, 5) { + val iterator = bossBars.iterator() + + while (iterator.hasNext()) { + val (key, expiry) = iterator.next() + + if (System.currentTimeMillis() > expiry) { + val bossBar = Bukkit.getBossBar(key) ?: continue + bossBar.removeAll() + Bukkit.removeBossBar(key) + iterator.remove() + } + } + } + } +} diff --git a/eco-core/core-plugin/src/main/resources/config.yml b/eco-core/core-plugin/src/main/resources/config.yml index 43fbd15..43d7a51 100644 --- a/eco-core/core-plugin/src/main/resources/config.yml +++ b/eco-core/core-plugin/src/main/resources/config.yml @@ -57,7 +57,7 @@ gui: lore: - "&8&o%description%" - "&f" - - "%rewards%" + - "%gui_lore%" - "&f" - "&fProgress to next level:" - "&8» &e%percentage_progress%" @@ -230,22 +230,70 @@ persistent-action-bar: # The worlds that the action bar should be disabled in. disabled-in-worlds: [ ] -level-up: - message: +damage-indicators: + # Requires a compatible Hologram plugin to be installed + enabled: true + final-damage: false # If final damage (with reductions applied) should be used. + + format: + normal: "&7%damage%" + crit: "&f✧ %damage% &f✧" + + healing: enabled: true + format: "&a+%damage%" + + max-x-offset: 0.6 + max-y-offset: 0.6 + max-z-offset: 0.6 + +skills: + prevent-levelling-while-afk: true # If the player is AFK then don't give xp + + # Ways to tell the player about skill xp gain + gain-xp: + action-bar: + # If the action bar should be used + enabled: true + # The actionbar message that should be sent + message: "&f%skill% &8| &9(%current_xp%/%required_xp%) &e+%gained_xp%" + boss-bar: + # If the boss bar should be used + enabled: false + # The boss bar message that should be sent + format: "&f%skill% &8| &9(%current_xp%/%required_xp%)" + # The color of the boss bar (from https://hub.spigotmc.org/javadocs/spigot/org/bukkit/boss/BarColor.html) + color: blue + # The style of the boss bar (from https://hub.spigotmc.org/javadocs/spigot/org/bukkit/boss/BarStyle.html) + style: solid + # How long the boss bar should last (in milliseconds) + duration: 2500 + sound: + # If a sound should be played + enabled: true + # The sound that should be played + sound: entity_experience_orb_pickup + # Pitch between 0.5 and 2 + pitch: 2 + # The volume + volume: 0.1 + + level-up: message: - - "&f" - - " &#ff00aeYou levelled up &d%skill%&#ff00ae to &eLevel %level_numeral%&#ff00ae!" - - "&f" - - " &#ff00ae&lREWARDS:" - - "%rewards%" - - "&f" - sound: - # If a sound should be played - enabled: true - # The sound that should be played - sound: entity_player_levelup - # Pitch between 0.5 and 2 - pitch: 0.8 - # The volume - volume: 1.0 + enabled: true + message: + - "&f" + - " &#ff00aeYou levelled up &d%skill%&#ff00ae to &eLevel %level_numeral%&#ff00ae!" + - "&f" + - " &#ff00ae&lREWARDS:" + - "%rewards%" + - "&f" + sound: + # If a sound should be played + enabled: true + # The sound that should be played + sound: entity_player_levelup + # Pitch between 0.5 and 2 + pitch: 0.8 + # The volume + volume: 1.0 diff --git a/eco-core/core-plugin/src/main/resources/skills/_example.yml b/eco-core/core-plugin/src/main/resources/skills/_example.yml index 6cfecb6..752a93f 100644 --- a/eco-core/core-plugin/src/main/resources/skills/_example.yml +++ b/eco-core/core-plugin/src/main/resources/skills/_example.yml @@ -14,6 +14,19 @@ gui: icon: player_head texture:eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZmIxYzI2OGVmZWM4ZDdkODhhMWNiODhjMmJmYTA5N2ZhNTcwMzc5NDIyOTlmN2QyMDIxNTlmYzkzY2QzMDM2ZCJ9fX0= + lore: + - "&fImproves Stats:" + - "&8» &r%ecoskills_defense_name%" + - "&8» &r%ecoskills_ferocity_name%" + - "&f" + - "&fEffects:" + - "&8» &r&6Versatile Tools %ecoskills_versatile_tools_numeral%" + - " %ecoskills_versatile_tools_description%" + - "&8» &r&6Spelunking %ecoskills_spelunking_numeral%" + - " %ecoskills_spelunking_description%" + - "&8» &r&6Dynamic Mining %ecoskills_dynamic_mining_numeral%" + - " %ecoskills_dynamic_mining_description%" + position: row: 3 column: 3