From 4bbdacd2502664330c36023a505faa215f544dbd Mon Sep 17 00:00:00 2001 From: nossr50 Date: Fri, 28 Nov 2025 14:33:13 -0800 Subject: [PATCH] spears momentum (wip) --- .../commands/skills/SpearsCommand.java | 26 ++++++- .../gmail/nossr50/config/AdvancedConfig.java | 11 ++- .../datatypes/skills/SubSkillType.java | 1 + .../nossr50/skills/spears/SpearsManager.java | 75 +++++++++++++++++++ .../nossr50/util/skills/CombatUtils.java | 3 +- src/main/resources/advanced.yml | 15 +++- .../resources/locale/locale_en_US.properties | 5 ++ src/main/resources/plugin.yml | 7 +- src/main/resources/skillranks.yml | 23 ++++++ 9 files changed, 159 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/gmail/nossr50/commands/skills/SpearsCommand.java b/src/main/java/com/gmail/nossr50/commands/skills/SpearsCommand.java index 0070836e9..40fefea38 100644 --- a/src/main/java/com/gmail/nossr50/commands/skills/SpearsCommand.java +++ b/src/main/java/com/gmail/nossr50/commands/skills/SpearsCommand.java @@ -1,12 +1,19 @@ package com.gmail.nossr50.commands.skills; +import static com.gmail.nossr50.datatypes.skills.SubSkillType.MACES_CRIPPLE; +import static com.gmail.nossr50.datatypes.skills.SubSkillType.SPEARS_MOMENTUM; import static com.gmail.nossr50.datatypes.skills.SubSkillType.SPEARS_SPEARS_LIMIT_BREAK; import static com.gmail.nossr50.util.skills.SkillUtils.canUseSubskill; import static com.gmail.nossr50.util.text.TextComponentFactory.appendSubSkillTextComponents; import com.gmail.nossr50.datatypes.skills.PrimarySkillType; +import com.gmail.nossr50.locale.LocaleLoader; +import com.gmail.nossr50.mcMMO; +import com.gmail.nossr50.skills.maces.MacesManager; +import com.gmail.nossr50.skills.spears.SpearsManager; import com.gmail.nossr50.util.skills.CombatUtils; +import com.gmail.nossr50.util.skills.RankUtils; import com.gmail.nossr50.util.skills.SkillUtils; import java.util.ArrayList; import java.util.List; @@ -15,13 +22,23 @@ import org.bukkit.entity.Player; public class SpearsCommand extends SkillCommand { - public SpearsCommand() { super(PrimarySkillType.SPEARS); } + String momentumChanceToApply, momentumChanceToApplyLucky, momentumDuration; + @Override protected void dataCalculations(Player player, float skillValue) { + if (SkillUtils.canUseSubskill(player, SPEARS_MOMENTUM)) { + int momentumRank = RankUtils.getRank(player, SPEARS_MOMENTUM); + momentumDuration = String.valueOf( + SpearsManager.getMomentumTickDuration(momentumRank) / 20.0D); + momentumChanceToApply = + mcMMO.p.getAdvancedConfig().getMomentumChanceToApplyOnHit(momentumRank) + "%"; + momentumChanceToApplyLucky = String.valueOf( + mcMMO.p.getAdvancedConfig().getMomentumChanceToApplyOnHit(momentumRank) * 1.33); + } } @Override @@ -39,6 +56,13 @@ public class SpearsCommand extends SkillCommand { SPEARS_SPEARS_LIMIT_BREAK, 1000)))); } + if (SkillUtils.canUseSubskill(player, SPEARS_MOMENTUM)) { + messages.add(getStatMessage(SPEARS_MOMENTUM, momentumChanceToApply) + + (isLucky ? LocaleLoader.getString("Perks.Lucky.Bonus", + momentumChanceToApplyLucky) : "")); + messages.add(getStatMessage(true, true, SPEARS_MOMENTUM, momentumDuration)); + } + return messages; } diff --git a/src/main/java/com/gmail/nossr50/config/AdvancedConfig.java b/src/main/java/com/gmail/nossr50/config/AdvancedConfig.java index 1f44ac78b..648eea7b9 100644 --- a/src/main/java/com/gmail/nossr50/config/AdvancedConfig.java +++ b/src/main/java/com/gmail/nossr50/config/AdvancedConfig.java @@ -11,6 +11,7 @@ import net.md_5.bungee.api.ChatColor; public class AdvancedConfig extends BukkitConfig { int[] defaultCrippleValues = new int[]{10, 15, 20, 25}; + int[] defaultMomentumValues = new int[]{5, 10, 15, 20, 25, 30, 35, 40, 45, 50}; public AdvancedConfig(File dataFolder) { super("advanced.yml", dataFolder); @@ -884,7 +885,13 @@ public class AdvancedConfig extends BukkitConfig { /* MACES */ public double getCrippleChanceToApplyOnHit(int rank) { - String root = "Skills.Maces.Cripple.Chance_To_Apply_On_Hit.Rank_"; - return config.getDouble(root + rank, defaultCrippleValues[rank - 1]); + return config.getDouble("Skills.Maces.Cripple.Chance_To_Apply_On_Hit.Rank_" + rank, + defaultCrippleValues[rank - 1]); + } + + /* SPEARS */ + public double getMomentumChanceToApplyOnHit(int rank) { + return config.getDouble("Skills.Spears.Momentum.Chance_To_Apply_On_Hit.Rank_" + rank, + defaultMomentumValues[rank - 1]); } } diff --git a/src/main/java/com/gmail/nossr50/datatypes/skills/SubSkillType.java b/src/main/java/com/gmail/nossr50/datatypes/skills/SubSkillType.java index b409acc1c..5f662c6fb 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/skills/SubSkillType.java +++ b/src/main/java/com/gmail/nossr50/datatypes/skills/SubSkillType.java @@ -85,6 +85,7 @@ public enum SubSkillType { /* Spears */ SPEARS_SPEARS_LIMIT_BREAK(10), + SPEARS_MOMENTUM(10), /* Swords */ SWORDS_COUNTER_ATTACK(1), diff --git a/src/main/java/com/gmail/nossr50/skills/spears/SpearsManager.java b/src/main/java/com/gmail/nossr50/skills/spears/SpearsManager.java index 61153d869..54c35ff15 100644 --- a/src/main/java/com/gmail/nossr50/skills/spears/SpearsManager.java +++ b/src/main/java/com/gmail/nossr50/skills/spears/SpearsManager.java @@ -1,11 +1,86 @@ package com.gmail.nossr50.skills.spears; +import static com.gmail.nossr50.util.random.ProbabilityUtil.isStaticSkillRNGSuccessful; +import static com.gmail.nossr50.util.skills.RankUtils.getRank; + +import com.gmail.nossr50.datatypes.interactions.NotificationType; import com.gmail.nossr50.datatypes.player.McMMOPlayer; import com.gmail.nossr50.datatypes.skills.PrimarySkillType; +import com.gmail.nossr50.datatypes.skills.SubSkillType; +import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.skills.SkillManager; +import com.gmail.nossr50.util.Permissions; +import com.gmail.nossr50.util.player.NotificationManager; +import java.util.Locale; +import org.bukkit.NamespacedKey; +import org.bukkit.Registry; +import org.bukkit.potion.PotionEffectType; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public class SpearsManager extends SkillManager { + private static @Nullable PotionEffectType swiftnessEffectType; public SpearsManager(McMMOPlayer mmoPlayer) { super(mmoPlayer, PrimarySkillType.SPEARS); } + + private static @Nullable PotionEffectType mockSpigotMatch(@NotNull String input) { + // Replicates match() behaviour for older versions lacking this API + final String filtered = input.toLowerCase(Locale.ROOT).replaceAll("\\s+", "_"); + final NamespacedKey namespacedKey = NamespacedKey.fromString(filtered); + return (namespacedKey != null) ? Registry.EFFECT.get(namespacedKey) : null; + } + + /** + * Process Momentum activation. + */ + public void potentiallyApplyMomentum() { + // Lazy initialized to avoid some backwards compatibility issues + if (swiftnessEffectType == null) { + if (mockSpigotMatch("speed") == null) { + mcMMO.p.getLogger().severe("Unable to find the Speed PotionEffectType, " + + "mcMMO will not function properly."); + throw new IllegalStateException("Unable to find the Speed PotionEffectType!"); + } else { + swiftnessEffectType = mockSpigotMatch("speed"); + } + } + + // TODO: Potentially it should overwrite the effect if we are providing a stronger one + if (swiftnessEffectType == null || getPlayer().getPotionEffect(swiftnessEffectType) != null) { + return; + } + + if (!Permissions.canUseSubSkill(mmoPlayer.getPlayer(), SubSkillType.SPEARS_MOMENTUM)) { + return; + } + + int momentumRank = getRank(getPlayer(), SubSkillType.SPEARS_MOMENTUM); + double momentumOdds = (mcMMO.p.getAdvancedConfig().getMomentumChanceToApplyOnHit(momentumRank) + * mmoPlayer.getAttackStrength()); + + if (isStaticSkillRNGSuccessful(PrimarySkillType.MACES, mmoPlayer, + momentumOdds)) { + if (mmoPlayer.useChatNotifications()) { + NotificationManager.sendPlayerInformation(mmoPlayer.getPlayer(), + NotificationType.SUBSKILL_MESSAGE, "Maces.SubSkill.Momentum.Activated"); + } + + // Momentum is success, Momentum the target + getPlayer().addPotionEffect(swiftnessEffectType.createEffect( + getMomentumTickDuration(momentumRank), + getMomentumStrength())); + // TODO: Consider adding an effect here + // ParticleEffectUtils.playMomentumEffect(target); + } + } + + public static int getMomentumTickDuration(int momentumRank) { + return 20 * (momentumRank * 2); + } + + public static int getMomentumStrength() { + return 2; + } + } diff --git a/src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java b/src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java index ee04e02fc..07c94fb3a 100644 --- a/src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java +++ b/src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java @@ -361,7 +361,8 @@ public final class CombatUtils { event.setDamage(boostedDamage); - // TODO: Apply any non-damage effects here + // Apply any non-damage effects here + spearsManager.potentiallyApplyMomentum(); processCombatXP(mmoPlayer, target, PrimarySkillType.SPEARS); printFinalDamageDebug(player, event, mmoPlayer); diff --git a/src/main/resources/advanced.yml b/src/main/resources/advanced.yml index 4e876fa76..51a9bb487 100644 --- a/src/main/resources/advanced.yml +++ b/src/main/resources/advanced.yml @@ -647,4 +647,17 @@ Skills: Rank_1: 10 Rank_2: 15 Rank_3: 20 - Rank_4: 33 \ No newline at end of file + Rank_4: 33 + Spears: + Momentum: + Chance_To_Apply_On_Hit: + Rank_1: 5 + Rank_2: 10 + Rank_3: 15 + Rank_4: 20 + Rank_5: 25 + Rank_6: 30 + Rank_7: 35 + Rank_8: 40 + Rank_9: 45 + Rank_10: 50 \ No newline at end of file diff --git a/src/main/resources/locale/locale_en_US.properties b/src/main/resources/locale/locale_en_US.properties index 435273742..588acf01f 100644 --- a/src/main/resources/locale/locale_en_US.properties +++ b/src/main/resources/locale/locale_en_US.properties @@ -485,6 +485,11 @@ Spears.SubSkill.SpearsLimitBreak.Name=Spears Limit Break Spears.SubSkill.SpearsLimitBreak.Description=Breaking your limits. Increased damage against tough opponents. Intended for PVP, up to server settings for whether it will boost damage in PVE. Spears.SubSkill.SpearsLimitBreak.Stat=Limit Break Max DMG Spears.SubSkill.SpearAbility.Name=WIP +Spears.SubSkill.Momentum.Name=Momentum +Spears.SubSkill.Momentum.Description=Adds a chance to increase movement speed when attacking. +Spears.SubSkill.Momentum.Stat=Momentum Chance +Spears.SubSkill.Momentum.Stat.Extra=[[DARK_AQUA]]Momentum Duration: &e{0}s +Spears.SubSkill.Momentum.Activated=MOMENTUM ACTIVATED! Spears.Listener=Spears: #SWORDS diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index ff747c98d..7c0689c49 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -659,8 +659,11 @@ permissions: description: Allows access to all Spear abilities children: mcmmo.ability.spears.spearslimitbreak: true + mcmmo.ability.spears.momentum: true mcmmo.ability.spears.spearslimitbreak: description: Adds damage to spears + mcmmo.ability.spears.momentum: + description: Adds a chance to increase movement speed temporarily after hitting an entity mcmmo.ability.swords.*: default: false description: Allows access to all Swords abilities @@ -2387,8 +2390,8 @@ permissions: mcmmo.skills.spears: description: Allows access to the Spears skill children: - mcmmo.ability.smelting.all: true - mcmmo.commands.smelting: true + mcmmo.ability.spears.all: true + mcmmo.commands.spears: true mcmmo.skills.swords: description: Allows access to the Swords skill children: diff --git a/src/main/resources/skillranks.yml b/src/main/resources/skillranks.yml index de56748df..f45023e68 100644 --- a/src/main/resources/skillranks.yml +++ b/src/main/resources/skillranks.yml @@ -428,6 +428,29 @@ Spears: Rank_8: 800 Rank_9: 900 Rank_10: 1000 + SpearsMomentum: + Standard: + Rank_1: 1 + Rank_2: 10 + Rank_3: 15 + Rank_4: 20 + Rank_5: 25 + Rank_6: 40 + Rank_7: 50 + Rank_8: 60 + Rank_9: 80 + Rank_10: 100 + RetroMode: + Rank_1: 1 + Rank_2: 100 + Rank_3: 150 + Rank_4: 200 + Rank_5: 250 + Rank_6: 400 + Rank_7: 500 + Rank_8: 600 + Rank_9: 800 + Rank_10: 1000 Salvage: ScrapCollector: Standard: