From c94039ab45ad06c33a0882bbb15450fa5cf6b98a Mon Sep 17 00:00:00 2001 From: nossr50 Date: Sun, 30 Jun 2024 14:43:03 -0700 Subject: [PATCH] maces wip pt 2 --- Changelog.txt | 13 +++- pom.xml | 2 +- ...{McrankCommand.java => McRankCommand.java} | 2 +- .../{MctopCommand.java => McTopCommand.java} | 14 +++- .../nossr50/commands/skills/MacesCommand.java | 5 +- .../gmail/nossr50/config/GeneralConfig.java | 4 ++ .../com/gmail/nossr50/config/SoundConfig.java | 4 +- .../nossr50/datatypes/player/McMMOPlayer.java | 4 +- src/main/java/com/gmail/nossr50/mcMMO.java | 6 +- .../com/gmail/nossr50/party/PartyManager.java | 1 + .../commands/McRankCommandAsyncTask.java | 2 +- ...ask.java => McRankCommandDisplayTask.java} | 15 ++-- .../nossr50/skills/axes/AxesManager.java | 17 +++-- .../nossr50/skills/maces/MacesManager.java | 62 +++++++++++++--- .../nossr50/skills/swords/SwordsManager.java | 3 +- .../skills/unarmed/UnarmedManager.java | 9 ++- .../commands/CommandRegistrationManager.java | 4 +- .../nossr50/util/commands/CommandUtils.java | 7 +- .../util/platform/PlatformBuilder.java | 13 ++-- .../nossr50/util/random/Probability.java | 13 ++++ .../nossr50/util/random/ProbabilityUtil.java | 39 ++++++++++ .../nossr50/util/skills/CombatUtils.java | 72 ++++++++++--------- .../util/skills/ParticleEffectUtils.java | 30 ++++++-- .../gmail/nossr50/util/skills/SkillTools.java | 34 ++++++--- .../nossr50/util/sounds/SoundManager.java | 30 +++++++- src/main/resources/config.yml | 1 + .../resources/locale/locale_en_US.properties | 3 + src/main/resources/repair.vanilla.yml | 8 +++ src/main/resources/sounds.yml | 6 +- .../com/gmail/nossr50/MMOTestEnvironment.java | 10 +++ 30 files changed, 323 insertions(+), 110 deletions(-) rename src/main/java/com/gmail/nossr50/commands/player/{McrankCommand.java => McRankCommand.java} (98%) rename src/main/java/com/gmail/nossr50/commands/player/{MctopCommand.java => McTopCommand.java} (88%) rename src/main/java/com/gmail/nossr50/runnables/commands/{McrankCommandDisplayTask.java => McRankCommandDisplayTask.java} (81%) diff --git a/Changelog.txt b/Changelog.txt index 7752f7404..e28e6fcc8 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -7,7 +7,18 @@ # TODO: Audit CombatUtils and make sure attack strength is being used Version 2.2.015 Added Maces skill - Fixed a bug where a player's attack cooldown was not being taken into account when adding bonus DMG + Added Mace to repair.vanilla.yml (see notes) + Fixed a bug where spamming attacks would still apply full bonus dmg and full chance to proc abilities (see notes) + + NOTES: + You shouldn't need to update repair.vanilla.yml, it should update automatically + Maces is a new skill that is in early development, feedback is appreciated. + Some ideas I had for the Maces are on hold as they are lacking proper API from Spigot. + This is mostly pertaining to smash attacks, I had some ideas for enhancing them but without the proper API I will hold off for now. + While working on Maces, I noticed a bug where spamming attacks would still apply full bonus damage and full chance to proc abilities, this has been fixed. + When you swing your weapon in Minecraft, you gain an "Attack Strength" value, which is relative to your cooldown, mcMMO was supposed to be making use of this value, but at some point in the past this was broken. + I have fixed this and now mcMMO will use the attack strength value to determine the bonus damage and chance to proc abilities. + For servers modifying Minecraft combat to not have this "cooldown", mcMMO should behave as you would expect, with full damage and full chance to proc abilities. Version 2.2.014 Fixed a bug where Luck Of The Sea was being applied for Super Breaker (and other abilities) diff --git a/pom.xml b/pom.xml index fac3d2289..097e87c37 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 com.gmail.nossr50.mcMMO mcMMO - 2.2.014 + 2.2.015-SNAPSHOT mcMMO https://github.com/mcMMO-Dev/mcMMO diff --git a/src/main/java/com/gmail/nossr50/commands/player/McrankCommand.java b/src/main/java/com/gmail/nossr50/commands/player/McRankCommand.java similarity index 98% rename from src/main/java/com/gmail/nossr50/commands/player/McrankCommand.java rename to src/main/java/com/gmail/nossr50/commands/player/McRankCommand.java index 48586ef59..997220f9a 100644 --- a/src/main/java/com/gmail/nossr50/commands/player/McrankCommand.java +++ b/src/main/java/com/gmail/nossr50/commands/player/McRankCommand.java @@ -20,7 +20,7 @@ import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; -public class McrankCommand implements TabExecutor { +public class McRankCommand implements TabExecutor { @Override public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { switch (args.length) { diff --git a/src/main/java/com/gmail/nossr50/commands/player/MctopCommand.java b/src/main/java/com/gmail/nossr50/commands/player/McTopCommand.java similarity index 88% rename from src/main/java/com/gmail/nossr50/commands/player/MctopCommand.java rename to src/main/java/com/gmail/nossr50/commands/player/McTopCommand.java index 12e966a6c..b1f8256db 100644 --- a/src/main/java/com/gmail/nossr50/commands/player/MctopCommand.java +++ b/src/main/java/com/gmail/nossr50/commands/player/McTopCommand.java @@ -22,7 +22,7 @@ import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; -public class MctopCommand implements TabExecutor { +public class McTopCommand implements TabExecutor { @Override public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) { PrimarySkillType skill = null; @@ -44,6 +44,12 @@ public class MctopCommand implements TabExecutor { return true; } + // Check if the command is for Maces but the MC version is not correct + if (skill == PrimarySkillType.MACES + && !mcMMO.getCompatibilityManager().getMinecraftGameVersion().isAtLeast(1, 21, 0)) { + return true; + } + display(1, skill, sender, command); return true; @@ -58,6 +64,12 @@ public class MctopCommand implements TabExecutor { return true; } + // Check if the command is for Maces but the MC version is not correct + if (skill == PrimarySkillType.MACES + && !mcMMO.getCompatibilityManager().getMinecraftGameVersion().isAtLeast(1, 21, 0)) { + return true; + } + display(Math.abs(Integer.parseInt(args[1])), skill, sender, command); return true; diff --git a/src/main/java/com/gmail/nossr50/commands/skills/MacesCommand.java b/src/main/java/com/gmail/nossr50/commands/skills/MacesCommand.java index e6fde3621..71c553fc9 100644 --- a/src/main/java/com/gmail/nossr50/commands/skills/MacesCommand.java +++ b/src/main/java/com/gmail/nossr50/commands/skills/MacesCommand.java @@ -4,6 +4,7 @@ import com.gmail.nossr50.datatypes.skills.PrimarySkillType; import com.gmail.nossr50.datatypes.skills.SubSkillType; import com.gmail.nossr50.locale.LocaleLoader; import com.gmail.nossr50.mcMMO; +import com.gmail.nossr50.skills.maces.MacesManager; import com.gmail.nossr50.util.skills.CombatUtils; import com.gmail.nossr50.util.skills.RankUtils; import com.gmail.nossr50.util.skills.SkillUtils; @@ -30,8 +31,8 @@ public class MacesCommand extends SkillCommand { protected void dataCalculations(Player player, float skillValue) { if (SkillUtils.canUseSubskill(player, MACES_CRIPPLE)) { int crippleRank = RankUtils.getRank(player, MACES_CRIPPLE); - crippleLengthAgainstPlayers = String.valueOf("INSERT VALUE HERE"); - crippleLengthAgainstMobs = String.valueOf("INSERT VALUE HERE"); + crippleLengthAgainstPlayers = String.valueOf(MacesManager.getCrippleTickDuration(true) / 20.0D); + crippleLengthAgainstMobs = String.valueOf(MacesManager.getCrippleTickDuration(false) / 20.0D); crippleChanceToApply = String.valueOf(mcMMO.p.getAdvancedConfig().getCrippleChanceToApplyOnHit(crippleRank) + "%"); crippleChanceToApplyLucky = String.valueOf(mcMMO.p.getAdvancedConfig().getCrippleChanceToApplyOnHit(crippleRank) * 1.33); diff --git a/src/main/java/com/gmail/nossr50/config/GeneralConfig.java b/src/main/java/com/gmail/nossr50/config/GeneralConfig.java index 801cae25c..84e57c9b2 100644 --- a/src/main/java/com/gmail/nossr50/config/GeneralConfig.java +++ b/src/main/java/com/gmail/nossr50/config/GeneralConfig.java @@ -547,6 +547,10 @@ public class GeneralConfig extends BukkitConfig { return config.getBoolean("Particles.Bleed", true); } + public boolean getCrippleEffectEnabled() { + return config.getBoolean("Particles.Cripple", true); + } + public boolean getDodgeEffectEnabled() { return config.getBoolean("Particles.Dodge", true); } diff --git a/src/main/java/com/gmail/nossr50/config/SoundConfig.java b/src/main/java/com/gmail/nossr50/config/SoundConfig.java index 407b8ef1a..4b80352b6 100644 --- a/src/main/java/com/gmail/nossr50/config/SoundConfig.java +++ b/src/main/java/com/gmail/nossr50/config/SoundConfig.java @@ -50,12 +50,12 @@ public class SoundConfig extends BukkitConfig { public float getVolume(SoundType soundType) { String key = "Sounds." + soundType.toString() + ".Volume"; - return (float) config.getDouble(key); + return (float) config.getDouble(key, 1.0); } public float getPitch(SoundType soundType) { String key = "Sounds." + soundType.toString() + ".Pitch"; - return (float) config.getDouble(key); + return (float) config.getDouble(key, 1.0); } public boolean getIsEnabled(SoundType soundType) { diff --git a/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java b/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java index fde59e455..b8b20262c 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java +++ b/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java @@ -225,7 +225,9 @@ public class McMMOPlayer implements Identified { skillManagers.put(primarySkillType, new WoodcuttingManager(this)); break; case MACES: - skillManagers.put(primarySkillType, new MacesManager(this)); + if (mcMMO.getCompatibilityManager().getMinecraftGameVersion().isAtLeast(1, 21, 0)) { + skillManagers.put(primarySkillType, new MacesManager(this)); + } break; default: throw new InvalidSkillException("The skill named has no manager! Contact the devs!"); diff --git a/src/main/java/com/gmail/nossr50/mcMMO.java b/src/main/java/com/gmail/nossr50/mcMMO.java index 3f23597ba..1c970f5d4 100644 --- a/src/main/java/com/gmail/nossr50/mcMMO.java +++ b/src/main/java/com/gmail/nossr50/mcMMO.java @@ -162,6 +162,9 @@ public class mcMMO extends JavaPlugin { //Filter out any debug messages (if debug/verbose logging is not enabled) getLogger().setFilter(new LogFilter(this)); + //Platform Manager + platformManager = new PlatformManager(); + //Folia lib plugin instance foliaLib = new FoliaLib(this); InvalidTickDelayNotifier.disableNotifications = true; @@ -178,9 +181,6 @@ public class mcMMO extends JavaPlugin { //Store this value so other plugins can check it isRetroModeEnabled = generalConfig.getIsRetroMode(); - //Platform Manager - platformManager = new PlatformManager(); - MetadataConstants.MCMMO_METADATA_VALUE = new FixedMetadataValue(this, true); PluginManager pluginManager = getServer().getPluginManager(); diff --git a/src/main/java/com/gmail/nossr50/party/PartyManager.java b/src/main/java/com/gmail/nossr50/party/PartyManager.java index 1a6300ac5..283ebb1f6 100644 --- a/src/main/java/com/gmail/nossr50/party/PartyManager.java +++ b/src/main/java/com/gmail/nossr50/party/PartyManager.java @@ -310,6 +310,7 @@ public final class PartyManager { * @param party The party to remove * @deprecated Use {@link #disbandParty(McMMOPlayer, Party)} */ + @Deprecated public void disbandParty(@NotNull Party party) { requireNonNull(party, "party cannot be null!"); disbandParty(null, party); diff --git a/src/main/java/com/gmail/nossr50/runnables/commands/McRankCommandAsyncTask.java b/src/main/java/com/gmail/nossr50/runnables/commands/McRankCommandAsyncTask.java index 4b24b329a..50f8aff51 100644 --- a/src/main/java/com/gmail/nossr50/runnables/commands/McRankCommandAsyncTask.java +++ b/src/main/java/com/gmail/nossr50/runnables/commands/McRankCommandAsyncTask.java @@ -32,7 +32,7 @@ public class McRankCommandAsyncTask extends CancellableRunnable { public void run() { Map skills = mcMMO.getDatabaseManager().readRank(playerName); - mcMMO.p.getFoliaLib().getImpl().runNextTick(new McrankCommandDisplayTask(skills, sender, playerName, useBoard, useChat)); + mcMMO.p.getFoliaLib().getImpl().runNextTick(new McRankCommandDisplayTask(skills, sender, playerName, useBoard, useChat)); } } diff --git a/src/main/java/com/gmail/nossr50/runnables/commands/McrankCommandDisplayTask.java b/src/main/java/com/gmail/nossr50/runnables/commands/McRankCommandDisplayTask.java similarity index 81% rename from src/main/java/com/gmail/nossr50/runnables/commands/McrankCommandDisplayTask.java rename to src/main/java/com/gmail/nossr50/runnables/commands/McRankCommandDisplayTask.java index 18fbb8854..a6cf28069 100644 --- a/src/main/java/com/gmail/nossr50/runnables/commands/McrankCommandDisplayTask.java +++ b/src/main/java/com/gmail/nossr50/runnables/commands/McRankCommandDisplayTask.java @@ -15,13 +15,14 @@ import java.util.Map; /** * Display the results of McrankCommandAsyncTask to the sender. */ -public class McrankCommandDisplayTask extends CancellableRunnable { +public class McRankCommandDisplayTask extends CancellableRunnable { private final Map skills; private final CommandSender sender; private final String playerName; private final boolean useBoard, useChat; - McrankCommandDisplayTask(Map skills, CommandSender sender, String playerName, boolean useBoard, boolean useChat) { + McRankCommandDisplayTask(Map skills, CommandSender sender, String playerName, + boolean useBoard, boolean useChat) { this.skills = skills; this.sender = sender; this.playerName = playerName; @@ -42,17 +43,17 @@ public class McrankCommandDisplayTask extends CancellableRunnable { } private void displayChat() { -// Player player = mcMMO.p.getServer().getPlayerExact(playerName); Integer rank; sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Heading")); sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Player", playerName)); for (PrimarySkillType skill : SkillTools.NON_CHILD_SKILLS) { -// if (!mcMMO.p.getSkillTools().doesPlayerHaveSkillPermission(player, skill)) { -// continue; -// } - + // Check if the command is for Maces but the MC version is not correct + if (skill == PrimarySkillType.MACES + && !mcMMO.getCompatibilityManager().getMinecraftGameVersion().isAtLeast(1, 21, 0)) { + continue; + } rank = skills.get(skill); sender.sendMessage(LocaleLoader.getString("Commands.mcrank.Skill", mcMMO.p.getSkillTools().getLocalizedSkillName(skill), (rank == null ? LocaleLoader.getString("Commands.mcrank.Unranked") : rank))); } diff --git a/src/main/java/com/gmail/nossr50/skills/axes/AxesManager.java b/src/main/java/com/gmail/nossr50/skills/axes/AxesManager.java index 9fc75038a..1ce677e18 100644 --- a/src/main/java/com/gmail/nossr50/skills/axes/AxesManager.java +++ b/src/main/java/com/gmail/nossr50/skills/axes/AxesManager.java @@ -22,6 +22,9 @@ import org.bukkit.inventory.EntityEquipment; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import static com.gmail.nossr50.util.random.ProbabilityUtil.isSkillRNGSuccessful; +import static com.gmail.nossr50.util.skills.SkillUtils.handleArmorDurabilityChange; + public class AxesManager extends SkillManager { public AxesManager(McMMOPlayer mcMMOPlayer) { super(mcMMOPlayer, PrimarySkillType.AXES); @@ -84,7 +87,7 @@ public class AxesManager extends SkillManager { * @param damage The amount of damage initially dealt by the event */ public double criticalHit(LivingEntity target, double damage) { - if (!ProbabilityUtil.isSkillRNGSuccessful(SubSkillType.AXES_CRITICAL_STRIKES, mmoPlayer)) { + if (!isSkillRNGSuccessful(SubSkillType.AXES_CRITICAL_STRIKES, mmoPlayer, mmoPlayer.getAttackStrength())) { return 0; } @@ -123,8 +126,8 @@ public class AxesManager extends SkillManager { for (ItemStack armor : equipment.getArmorContents()) { if (armor != null && ItemUtils.isArmor(armor)) { - if (ProbabilityUtil.isSkillRNGSuccessful(SubSkillType.AXES_ARMOR_IMPACT, mmoPlayer)) { - SkillUtils.handleArmorDurabilityChange(armor, durabilityDamage, 1); + if (isSkillRNGSuccessful(SubSkillType.AXES_ARMOR_IMPACT, mmoPlayer, mmoPlayer.getAttackStrength())) { + handleArmorDurabilityChange(armor, durabilityDamage, 1); } } } @@ -140,15 +143,15 @@ public class AxesManager extends SkillManager { * @param target The {@link LivingEntity} being affected by the ability */ public double greaterImpact(@NotNull LivingEntity target) { - //static chance (3rd param) - if (!ProbabilityUtil.isSkillRNGSuccessful(SubSkillType.AXES_GREATER_IMPACT, mmoPlayer)) { + if (!isSkillRNGSuccessful(SubSkillType.AXES_GREATER_IMPACT, mmoPlayer, mmoPlayer.getAttackStrength())) { return 0; } Player player = getPlayer(); ParticleEffectUtils.playGreaterImpactEffect(target); - target.setVelocity(player.getLocation().getDirection().normalize().multiply(Axes.greaterImpactKnockbackMultiplier)); + target.setVelocity( + player.getLocation().getDirection().normalize().multiply(Axes.greaterImpactKnockbackMultiplier)); if (mmoPlayer.useChatNotifications()) { NotificationManager.sendPlayerInformation(player, NotificationType.SUBSKILL_MESSAGE, "Axes.Combat.GI.Proc"); @@ -170,6 +173,6 @@ public class AxesManager extends SkillManager { * @param damage The amount of damage initially dealt by the event */ public void skullSplitterCheck(@NotNull LivingEntity target, double damage) { - CombatUtils.applyAbilityAoE(getPlayer(), target, damage / Axes.skullSplitterModifier, skill); + CombatUtils.applyAbilityAoE(getPlayer(), target, (damage / Axes.skullSplitterModifier) * mmoPlayer.getAttackStrength(), skill); } } diff --git a/src/main/java/com/gmail/nossr50/skills/maces/MacesManager.java b/src/main/java/com/gmail/nossr50/skills/maces/MacesManager.java index cb0aa44c8..fc8f23575 100644 --- a/src/main/java/com/gmail/nossr50/skills/maces/MacesManager.java +++ b/src/main/java/com/gmail/nossr50/skills/maces/MacesManager.java @@ -1,5 +1,6 @@ package com.gmail.nossr50.skills.maces; +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; @@ -8,20 +9,32 @@ import com.gmail.nossr50.skills.SkillManager; import com.gmail.nossr50.util.Permissions; import com.gmail.nossr50.util.player.NotificationManager; import com.gmail.nossr50.util.random.ProbabilityUtil; +import com.gmail.nossr50.util.skills.ParticleEffectUtils; import com.gmail.nossr50.util.skills.RankUtils; -import com.gmail.nossr50.util.sounds.SoundManager; -import com.gmail.nossr50.util.sounds.SoundType; -import org.bukkit.SoundCategory; +import org.bukkit.NamespacedKey; +import org.bukkit.Registry; import org.bukkit.entity.LivingEntity; -import org.bukkit.potion.PotionEffect; +import org.bukkit.entity.Player; import org.bukkit.potion.PotionEffectType; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Locale; public class MacesManager extends SkillManager { + private static @Nullable PotionEffectType slowEffectType; + public MacesManager(McMMOPlayer mmoPlayer) { super(mmoPlayer, PrimarySkillType.MACES); } + 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; + } + /** * Get the Crush damage bonus. * @@ -34,7 +47,7 @@ public class MacesManager extends SkillManager { int rank = RankUtils.getRank(getPlayer(), SubSkillType.MACES_CRUSH); if (rank > 0) { - return (1.0D + (rank * 0.5D)); + return (0.5D + (rank * 1.D)); } return 0; @@ -46,8 +59,20 @@ public class MacesManager extends SkillManager { * @param target The defending entity */ public void processCripple(@NotNull LivingEntity target) { + // Lazy initialized to avoid some backwards compatibility issues + if (slowEffectType == null) { + if (mockSpigotMatch("slowness") == null) { + mcMMO.p.getLogger().severe("Unable to find the Slowness PotionEffectType, " + + "mcMMO will not function properly."); + throw new IllegalStateException("Unable to find the Slowness PotionEffectType!"); + } else { + slowEffectType = mockSpigotMatch("slowness"); + } + } + + boolean isPlayerTarget = target instanceof Player; // Don't apply Cripple if the target is already Slowed - if (target.getPotionEffect(PotionEffectType.SLOWNESS) != null) { + if (slowEffectType == null || target.getPotionEffect(slowEffectType) != null) { return; } @@ -60,15 +85,30 @@ public class MacesManager extends SkillManager { * mmoPlayer.getAttackStrength()); if (ProbabilityUtil.isStaticSkillRNGSuccessful(PrimarySkillType.MACES, mmoPlayer, crippleOdds)) { + if (mmoPlayer.useChatNotifications()) { + NotificationManager.sendPlayerInformation(mmoPlayer.getPlayer(), + NotificationType.SUBSKILL_MESSAGE, "Maces.SubSkill.Cripple.Activated"); + } + // Cripple is success, Cripple the target - target.addPotionEffect(PotionEffectType.SLOWNESS.createEffect(getCrippleTickDuration(), 1)); - // TODO: Play some kind of Smash effect / sound - SoundManager.sendCategorizedSound(getPlayer(), target.getLocation(), SoundType.CRIPPLE, SoundCategory.PLAYERS); + target.addPotionEffect(slowEffectType.createEffect( + getCrippleTickDuration(isPlayerTarget), + getCrippleStrength(isPlayerTarget))); + ParticleEffectUtils.playCrippleEffect(target); } } - public int getCrippleTickDuration() { + public static int getCrippleTickDuration(boolean isPlayerTarget) { // TODO: Make configurable - return 20 * 5; + if (isPlayerTarget) { + return 20; + } else { + return 30; + } + } + + public static int getCrippleStrength(boolean isPlayerTarget) { + // TODO: Make configurable + return isPlayerTarget ? 1 : 2; } } diff --git a/src/main/java/com/gmail/nossr50/skills/swords/SwordsManager.java b/src/main/java/com/gmail/nossr50/skills/swords/SwordsManager.java index 48957df91..b798d2a7e 100644 --- a/src/main/java/com/gmail/nossr50/skills/swords/SwordsManager.java +++ b/src/main/java/com/gmail/nossr50/skills/swords/SwordsManager.java @@ -75,7 +75,8 @@ public class SwordsManager extends SkillManager { return; //Don't apply bleed } - double ruptureOdds = mcMMO.p.getAdvancedConfig().getRuptureChanceToApplyOnHit(getRuptureRank()); + double ruptureOdds = mcMMO.p.getAdvancedConfig().getRuptureChanceToApplyOnHit(getRuptureRank()) + * mmoPlayer.getAttackStrength(); if (ProbabilityUtil.isStaticSkillRNGSuccessful(PrimarySkillType.SWORDS, mmoPlayer, ruptureOdds)) { if (target instanceof Player defender) { diff --git a/src/main/java/com/gmail/nossr50/skills/unarmed/UnarmedManager.java b/src/main/java/com/gmail/nossr50/skills/unarmed/UnarmedManager.java index 4d728abe6..193c19dfd 100644 --- a/src/main/java/com/gmail/nossr50/skills/unarmed/UnarmedManager.java +++ b/src/main/java/com/gmail/nossr50/skills/unarmed/UnarmedManager.java @@ -22,6 +22,8 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import static com.gmail.nossr50.util.random.ProbabilityUtil.isSkillRNGSuccessful; + public class UnarmedManager extends SkillManager { public UnarmedManager(McMMOPlayer mcMMOPlayer) { @@ -98,7 +100,8 @@ public class UnarmedManager extends SkillManager { * @param defender The defending player */ public void disarmCheck(@NotNull Player defender) { - if (ProbabilityUtil.isSkillRNGSuccessful(SubSkillType.UNARMED_DISARM, mmoPlayer) && !hasIronGrip(defender)) { + if (isSkillRNGSuccessful(SubSkillType.UNARMED_DISARM, mmoPlayer, mmoPlayer.getAttackStrength()) + && !hasIronGrip(defender)) { if (EventUtils.callDisarmEvent(defender).isCancelled()) { return; } @@ -121,7 +124,7 @@ public class UnarmedManager extends SkillManager { * Check for arrow deflection. */ public boolean deflectCheck() { - if (ProbabilityUtil.isSkillRNGSuccessful(SubSkillType.UNARMED_ARROW_DEFLECT, mmoPlayer)) { + if (isSkillRNGSuccessful(SubSkillType.UNARMED_ARROW_DEFLECT, mmoPlayer)) { NotificationManager.sendPlayerInformation(getPlayer(), NotificationType.SUBSKILL_MESSAGE, "Combat.ArrowDeflect"); return true; } @@ -178,7 +181,7 @@ public class UnarmedManager extends SkillManager { private boolean hasIronGrip(@NotNull Player defender) { if (!Misc.isNPCEntityExcludingVillagers(defender) && Permissions.isSubSkillEnabled(defender, SubSkillType.UNARMED_IRON_GRIP) - && ProbabilityUtil.isSkillRNGSuccessful(SubSkillType.UNARMED_IRON_GRIP, UserManager.getPlayer(defender))) { + && isSkillRNGSuccessful(SubSkillType.UNARMED_IRON_GRIP, UserManager.getPlayer(defender))) { NotificationManager.sendPlayerInformation(defender, NotificationType.SUBSKILL_MESSAGE, "Unarmed.Ability.IronGrip.Defender"); NotificationManager.sendPlayerInformation(getPlayer(), NotificationType.SUBSKILL_MESSAGE, "Unarmed.Ability.IronGrip.Attacker"); diff --git a/src/main/java/com/gmail/nossr50/util/commands/CommandRegistrationManager.java b/src/main/java/com/gmail/nossr50/util/commands/CommandRegistrationManager.java index b2ffd029b..31a6e0176 100644 --- a/src/main/java/com/gmail/nossr50/util/commands/CommandRegistrationManager.java +++ b/src/main/java/com/gmail/nossr50/util/commands/CommandRegistrationManager.java @@ -215,7 +215,7 @@ public final class CommandRegistrationManager { command.setPermission("mcmmo.commands.mcrank;mcmmo.commands.mcrank.others;mcmmo.commands.mcrank.others.far;mcmmo.commands.mcrank.others.offline"); command.setPermissionMessage(permissionsMessage); command.setUsage(LocaleLoader.getString("Commands.Usage.1", "mcrank", "[" + LocaleLoader.getString("Commands.Usage.Player") + "]")); - command.setExecutor(new McrankCommand()); + command.setExecutor(new McRankCommand()); } private static void registerMcstatsCommand() { @@ -233,7 +233,7 @@ public final class CommandRegistrationManager { command.setPermission("mcmmo.commands.mctop"); // Only need the main one, not the individual skill ones command.setPermissionMessage(permissionsMessage); command.setUsage(LocaleLoader.getString("Commands.Usage.2", "mctop", "[" + LocaleLoader.getString("Commands.Usage.Skill") + "]", "[" + LocaleLoader.getString("Commands.Usage.Page") + "]")); - command.setExecutor(new MctopCommand()); + command.setExecutor(new McTopCommand()); } private static void registerMcpurgeCommand() { diff --git a/src/main/java/com/gmail/nossr50/util/commands/CommandUtils.java b/src/main/java/com/gmail/nossr50/util/commands/CommandUtils.java index be38e4f9c..ff6a234e9 100644 --- a/src/main/java/com/gmail/nossr50/util/commands/CommandUtils.java +++ b/src/main/java/com/gmail/nossr50/util/commands/CommandUtils.java @@ -216,13 +216,14 @@ public final class CommandUtils { return LocaleLoader.getString("Skills.Stats", LocaleLoader.getString(StringUtils.getCapitalized(skill.toString()) + ".Listener") + " ", profile.getSkillLevel(skill), profile.getSkillXpLevel(skill), profile.getXpToLevel(skill)); } - private static void printGroupedSkillData(Player inspectTarget, CommandSender display, String header, List skillGroup) { + private static void printGroupedSkillData(Player inspectTarget, CommandSender display, + String header, List skillGroup) { if (UserManager.getPlayer(inspectTarget) == null) return; - PlayerProfile profile = UserManager.getPlayer(inspectTarget).getProfile(); + final PlayerProfile profile = UserManager.getPlayer(inspectTarget).getProfile(); - List displayData = new ArrayList<>(); + final List displayData = new ArrayList<>(); displayData.add(header); for (PrimarySkillType primarySkillType : skillGroup) { diff --git a/src/main/java/com/gmail/nossr50/util/platform/PlatformBuilder.java b/src/main/java/com/gmail/nossr50/util/platform/PlatformBuilder.java index a2930137e..733bf58a0 100644 --- a/src/main/java/com/gmail/nossr50/util/platform/PlatformBuilder.java +++ b/src/main/java/com/gmail/nossr50/util/platform/PlatformBuilder.java @@ -28,15 +28,10 @@ public class PlatformBuilder { } public @Nullable Platform build() { - switch(serverSoftwareType) { - - case PAPER: - case SPIGOT: - case CRAFT_BUKKIT: - return createBukkitPlatform(); - default: - return null; - } + return switch (serverSoftwareType) { + case PAPER, SPIGOT, CRAFT_BUKKIT -> createBukkitPlatform(); + default -> null; + }; } private BukkitPlatform createBukkitPlatform() { diff --git a/src/main/java/com/gmail/nossr50/util/random/Probability.java b/src/main/java/com/gmail/nossr50/util/random/Probability.java index 3b9225b97..6873371a2 100644 --- a/src/main/java/com/gmail/nossr50/util/random/Probability.java +++ b/src/main/java/com/gmail/nossr50/util/random/Probability.java @@ -94,4 +94,17 @@ public interface Probability { double probabilityValue = getValue() * probabilityMultiplier; return isSuccessfulRoll(probabilityValue); } + + /** + * Modify and then Simulate an outcome on a probability and return true or false for the result of that outcome. + * + * @param probabilityMultiplier probability will be multiplied by this before success is checked + * @param finalProbabilityMultiplier probability will be multiplied by this after the first multiplier, + * should be between 0 and 1 + * @return true if the probability succeeded, false if it failed + */ + default boolean evaluate(double probabilityMultiplier, double finalProbabilityMultiplier) { + double probabilityValue = getValue() * probabilityMultiplier; + return isSuccessfulRoll(probabilityValue * finalProbabilityMultiplier); + } } diff --git a/src/main/java/com/gmail/nossr50/util/random/ProbabilityUtil.java b/src/main/java/com/gmail/nossr50/util/random/ProbabilityUtil.java index ca4a67de8..715673496 100644 --- a/src/main/java/com/gmail/nossr50/util/random/ProbabilityUtil.java +++ b/src/main/java/com/gmail/nossr50/util/random/ProbabilityUtil.java @@ -188,6 +188,45 @@ public class ProbabilityUtil { } } + /** + * This is one of several Skill RNG evaluation methods. + * This one specifically allows for a probability multiplier to be passed in. + * This probability multiplier is applied after any lucky modifiers, affecting the final result. + *

+ * This helper method is for specific {@link SubSkillType}, + * which help mcMMO understand where the RNG values used in our calculations come from this {@link SubSkillType} + *

+ * 1) Determine where the RNG values come from for the passed {@link SubSkillType} + * NOTE: In the config file, there are values which are static and which are more dynamic, + * this is currently a bit hardcoded and will need to be updated manually + *

+ * 2) Determine whether to use Lucky multiplier and influence the outcome + *

+ * 3) + * Creates a {@link Probability} and pipes it to {@link ProbabilityUtil} which processes the result and returns it + *

+ * This also calls a {@link SubSkillEvent} which can be cancelled, if it is cancelled this will return false + * The outcome of the probability can also be modified by this event that is called + * + * @param subSkillType target subskill + * @param mmoPlayer target player + * can be null (null players are given odds equivalent to a player with no levels or luck) + * @return true if the Skill RNG succeeds, false if it fails + */ + public static boolean isSkillRNGSuccessful(@NotNull SubSkillType subSkillType, @Nullable McMMOPlayer mmoPlayer, + double probabilityMultiplier) { + final Probability probability = getSkillProbability(subSkillType, mmoPlayer); + + //Luck + boolean isLucky = mmoPlayer != null && Permissions.lucky(mmoPlayer.getPlayer(), subSkillType.getParentSkill()); + + if (isLucky) { + return probability.evaluate(LUCKY_MODIFIER, probabilityMultiplier); + } else { + return probability.evaluate(); + } + } + /** * Returns the {@link Probability} for a specific {@link SubSkillType} for a specific {@link Player}. * This does not take into account perks such as lucky for the player. 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 6c82189dd..9dfb3abdb 100644 --- a/src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java +++ b/src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java @@ -60,7 +60,7 @@ public final class CombatUtils { return; } - McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player); + final McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player); //Make sure the profiles been loaded if (mcMMOPlayer == null) { @@ -84,7 +84,8 @@ public final class CombatUtils { } if (canUseLimitBreak(player, target, SubSkillType.SWORDS_SWORDS_LIMIT_BREAK)) { - boostedDamage += (getLimitBreakDamage(player, target, SubSkillType.SWORDS_SWORDS_LIMIT_BREAK) * mcMMOPlayer.getAttackStrength()); + boostedDamage += (getLimitBreakDamage + (player, target, SubSkillType.SWORDS_SWORDS_LIMIT_BREAK) * mcMMOPlayer.getAttackStrength()); } event.setDamage(boostedDamage); @@ -98,9 +99,12 @@ public final class CombatUtils { printFinalDamageDebug(player, event, mcMMOPlayer); } - private static void printFinalDamageDebug(@NotNull Player player, @NotNull EntityDamageByEntityEvent event, @NotNull McMMOPlayer mcMMOPlayer, @Nullable String @Nullable ... extraInfoLines) { + private static void printFinalDamageDebug(@NotNull Player player, @NotNull EntityDamageByEntityEvent event, + @NotNull McMMOPlayer mcMMOPlayer, + @Nullable String @Nullable ...extraInfoLines) { if (mcMMOPlayer.isDebugMode()) { player.sendMessage("Final Damage value after mcMMO modifiers: "+ event.getFinalDamage()); + player.sendMessage("Your current attack strength: "+ player.getAttackCooldown()); if (extraInfoLines != null) { for(String str : extraInfoLines) { if (str != null) @@ -117,14 +121,14 @@ public final class CombatUtils { double boostedDamage = event.getDamage(); - McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player); + final McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player); //Make sure the profiles been loaded if (mcMMOPlayer == null) { return; } - TridentsManager tridentsManager = mcMMOPlayer.getTridentsManager(); + final TridentsManager tridentsManager = mcMMOPlayer.getTridentsManager(); // if (tridentsManager.canActivateAbility()) { // mcMMOPlayer.checkAbilityActivation(PrimarySkillType.TRIDENTS); @@ -135,7 +139,8 @@ public final class CombatUtils { } if (canUseLimitBreak(player, target, SubSkillType.TRIDENTS_TRIDENTS_LIMIT_BREAK)) { - boostedDamage += (getLimitBreakDamage(player, target, SubSkillType.TRIDENTS_TRIDENTS_LIMIT_BREAK) * mcMMOPlayer.getAttackStrength()); + boostedDamage += (getLimitBreakDamage( + player, target, SubSkillType.TRIDENTS_TRIDENTS_LIMIT_BREAK) * mcMMOPlayer.getAttackStrength()); } event.setDamage(boostedDamage); @@ -151,21 +156,21 @@ public final class CombatUtils { double boostedDamage = event.getDamage(); - McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player); + final McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player); //Make sure the profiles been loaded if (mcMMOPlayer == null) { return; } - TridentsManager tridentsManager = mcMMOPlayer.getTridentsManager(); + final TridentsManager tridentsManager = mcMMOPlayer.getTridentsManager(); if (SkillUtils.canUseSubskill(player, SubSkillType.TRIDENTS_IMPALE)) { - boostedDamage += (tridentsManager.impaleDamageBonus() * mcMMOPlayer.getAttackStrength()); + boostedDamage += (tridentsManager.impaleDamageBonus()); } if (canUseLimitBreak(player, target, SubSkillType.TRIDENTS_TRIDENTS_LIMIT_BREAK)) { - boostedDamage += (getLimitBreakDamage(player, target, SubSkillType.TRIDENTS_TRIDENTS_LIMIT_BREAK) * mcMMOPlayer.getAttackStrength()); + boostedDamage += (getLimitBreakDamage(player, target, SubSkillType.TRIDENTS_TRIDENTS_LIMIT_BREAK)); } event.setDamage(boostedDamage); @@ -178,7 +183,7 @@ public final class CombatUtils { @NotNull EntityDamageByEntityEvent event, @NotNull Arrow arrow) { double initialDamage = event.getDamage(); - McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player); + final McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player); //Make sure the profiles been loaded if (mcMMOPlayer == null) { @@ -233,10 +238,11 @@ public final class CombatUtils { // Apply Limit Break DMG if (canUseLimitBreak(player, target, SubSkillType.MACES_MACES_LIMIT_BREAK)) { - boostedDamage += (getLimitBreakDamage(player, target, SubSkillType.MACES_MACES_LIMIT_BREAK) * mcMMOPlayer.getAttackStrength()); + boostedDamage += (getLimitBreakDamage( + player, target, SubSkillType.MACES_MACES_LIMIT_BREAK) * mcMMOPlayer.getAttackStrength()); } - // Apply Crush + // Apply Crush DMG boostedDamage += (macesManager.getCrushDamage() * mcMMOPlayer.getAttackStrength()); event.setDamage(boostedDamage); @@ -250,34 +256,35 @@ public final class CombatUtils { printFinalDamageDebug(player, event, mcMMOPlayer); } - private static void processAxeCombat(@NotNull LivingEntity target, @NotNull Player player, @NotNull EntityDamageByEntityEvent event) { + private static void processAxeCombat(@NotNull LivingEntity target, @NotNull Player player, + @NotNull EntityDamageByEntityEvent event) { if (event.getCause() == DamageCause.THORNS) { return; } double boostedDamage = event.getDamage(); - McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player); + final McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player); //Make sure the profiles been loaded if (mcMMOPlayer == null) { return; } - AxesManager axesManager = mcMMOPlayer.getAxesManager(); + final AxesManager axesManager = mcMMOPlayer.getAxesManager(); if (axesManager.canActivateAbility()) { mcMMOPlayer.checkAbilityActivation(PrimarySkillType.AXES); } if (axesManager.canUseAxeMastery()) { - boostedDamage+=axesManager.axeMastery(); + boostedDamage += axesManager.axeMastery() * mcMMOPlayer.getAttackStrength(); } if (axesManager.canImpact(target)) { axesManager.impactCheck(target); } else if (axesManager.canGreaterImpact(target)) { - boostedDamage+=axesManager.greaterImpact(target); + boostedDamage += axesManager.greaterImpact(target) * mcMMOPlayer.getAttackStrength(); } if (axesManager.canUseSkullSplitter(target)) { @@ -305,14 +312,14 @@ public final class CombatUtils { double boostedDamage = event.getDamage(); - McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player); + final McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player); //Make sure the profiles been loaded if (mcMMOPlayer == null) { return; } - UnarmedManager unarmedManager = mcMMOPlayer.getUnarmedManager(); + final UnarmedManager unarmedManager = mcMMOPlayer.getUnarmedManager(); if (unarmedManager.canActivateAbility()) { mcMMOPlayer.checkAbilityActivation(PrimarySkillType.UNARMED); @@ -331,7 +338,8 @@ public final class CombatUtils { } if (canUseLimitBreak(player, target, SubSkillType.UNARMED_UNARMED_LIMIT_BREAK)) { - boostedDamage+=(getLimitBreakDamage(player, target, SubSkillType.UNARMED_UNARMED_LIMIT_BREAK) * mcMMOPlayer.getAttackStrength()); + boostedDamage+=(getLimitBreakDamage( + player, target, SubSkillType.UNARMED_UNARMED_LIMIT_BREAK) * mcMMOPlayer.getAttackStrength()); } event.setDamage(boostedDamage); @@ -345,14 +353,14 @@ public final class CombatUtils { double boostedDamage = initialDamage; if (master != null && master.isOnline() && master.isValid()) { - McMMOPlayer mcMMOPlayer = UserManager.getPlayer(master); + final McMMOPlayer mcMMOPlayer = UserManager.getPlayer(master); //Make sure the profiles been loaded if (mcMMOPlayer == null) { return; } - TamingManager tamingManager = mcMMOPlayer.getTamingManager(); + final TamingManager tamingManager = mcMMOPlayer.getTamingManager(); if (tamingManager.canUseFastFoodService()) { tamingManager.fastFoodService(wolf, event.getDamage()); @@ -378,7 +386,7 @@ public final class CombatUtils { @NotNull EntityDamageByEntityEvent event, @NotNull Arrow arrow) { double initialDamage = event.getDamage(); - McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player); + final McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player); //Make sure the profiles been loaded if (mcMMOPlayer == null) { @@ -386,7 +394,7 @@ public final class CombatUtils { return; } - ArcheryManager archeryManager = mcMMOPlayer.getArcheryManager(); + final ArcheryManager archeryManager = mcMMOPlayer.getArcheryManager(); double boostedDamage = event.getDamage(); @@ -451,8 +459,8 @@ public final class CombatUtils { return; } - McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player); - AcrobaticsManager acrobaticsManager = mcMMOPlayer.getAcrobaticsManager(); + final McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player); + final AcrobaticsManager acrobaticsManager = mcMMOPlayer.getAcrobaticsManager(); if (acrobaticsManager.canDodge(target)) { event.setDamage(acrobaticsManager.dodgeCheck(painSourceRoot, event.getDamage())); @@ -463,7 +471,7 @@ public final class CombatUtils { return; } - SwordsManager swordsManager = mcMMOPlayer.getSwordsManager(); + final SwordsManager swordsManager = mcMMOPlayer.getSwordsManager(); if (swordsManager.canUseCounterAttack(painSource)) { swordsManager.counterAttackChecks((LivingEntity) painSource, event.getDamage()); @@ -472,12 +480,6 @@ public final class CombatUtils { } if (painSourceRoot instanceof Player player && entityType == EntityType.PLAYER) { -// final McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player); -// if (mcMMOPlayer != null) { -// Bukkit.broadcastMessage("DEBUG: AttackStrength of painSource: " + mcMMOPlayer.getAttackStrength()); -// System.out.println("DEBUG: AttackStrength of painSource: " + mcMMOPlayer.getAttackStrength()); -// } - if (!UserManager.hasPlayerDataKey(player)) { return; } @@ -832,7 +834,7 @@ public final class CombatUtils { NotificationManager.sendPlayerInformation((Player)entity, NotificationType.SUBSKILL_MESSAGE, "Swords.Combat.SS.Struck"); } - McMMOPlayer mmoAttacker = UserManager.getPlayer(attacker); + final McMMOPlayer mmoAttacker = UserManager.getPlayer(attacker); if (mmoAttacker != null) { mmoAttacker.getSwordsManager().processRupture(livingEntity); diff --git a/src/main/java/com/gmail/nossr50/util/skills/ParticleEffectUtils.java b/src/main/java/com/gmail/nossr50/util/skills/ParticleEffectUtils.java index c0e17bbe8..a205dfdea 100644 --- a/src/main/java/com/gmail/nossr50/util/skills/ParticleEffectUtils.java +++ b/src/main/java/com/gmail/nossr50/util/skills/ParticleEffectUtils.java @@ -1,13 +1,14 @@ package com.gmail.nossr50.util.skills; +import com.gmail.nossr50.datatypes.interactions.NotificationType; +import com.gmail.nossr50.datatypes.player.McMMOPlayer; import com.gmail.nossr50.mcMMO; +import com.gmail.nossr50.util.player.NotificationManager; +import com.gmail.nossr50.util.player.UserManager; import com.gmail.nossr50.util.sounds.SoundManager; import com.gmail.nossr50.util.sounds.SoundType; import org.apache.commons.lang3.RandomUtils; -import org.bukkit.Effect; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.World; +import org.bukkit.*; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.entity.LivingEntity; @@ -29,7 +30,26 @@ public final class ParticleEffectUtils { return; } - livingEntity.getWorld().playEffect(getParticleLocation(livingEntity), Effect.STEP_SOUND, Material.REDSTONE_WIRE); + livingEntity.getWorld().playEffect(getParticleLocation(livingEntity), + Effect.STEP_SOUND, Material.REDSTONE_WIRE); + } + + public static void playCrippleEffect(@NotNull LivingEntity livingEntity) { + if (!mcMMO.p.getGeneralConfig().getCrippleEffectEnabled()) { + return; + } + + SoundManager.sendCategorizedSound(livingEntity.getLocation(), SoundType.CRIPPLE, SoundCategory.PLAYERS, 0.2F); + livingEntity.getWorld().playEffect(getParticleLocation(livingEntity), Effect.ANVIL_BREAK, null, 20); + + if (livingEntity instanceof Player player) { + final McMMOPlayer mmoPlayer = UserManager.getPlayer(player); + boolean useChatNotification = mmoPlayer == null || mmoPlayer.useChatNotifications(); + if (useChatNotification) { + NotificationManager.sendPlayerInformation( + player, NotificationType.SUBSKILL_MESSAGE, "Maces.SubSkill.Cripple.Proc"); + } + } } private static @NotNull Location getParticleLocation(@NotNull LivingEntity livingEntity) { diff --git a/src/main/java/com/gmail/nossr50/util/skills/SkillTools.java b/src/main/java/com/gmail/nossr50/util/skills/SkillTools.java index 151c7e649..8afb05594 100644 --- a/src/main/java/com/gmail/nossr50/util/skills/SkillTools.java +++ b/src/main/java/com/gmail/nossr50/util/skills/SkillTools.java @@ -23,8 +23,8 @@ import java.util.*; public class SkillTools { private final mcMMO pluginRef; - - //TODO: Figure out which ones we don't need, this was copy pasted from a diff branch + // TODO: Java has immutable types now, switch to those + // TODO: Figure out which ones we don't need, this was copy pasted from a diff branch public final @NotNull ImmutableList LOCALIZED_SKILL_NAMES; public final @NotNull ImmutableList FORMATTED_SUBSKILL_NAMES; public final @NotNull ImmutableSet EXACT_SUBSKILL_NAMES; @@ -156,14 +156,28 @@ public class SkillTools { * Build categorized skill lists */ - COMBAT_SKILLS = ImmutableList.of( - PrimarySkillType.ARCHERY, - PrimarySkillType.AXES, - PrimarySkillType.CROSSBOWS, - PrimarySkillType.SWORDS, - PrimarySkillType.TAMING, - PrimarySkillType.TRIDENTS, - PrimarySkillType.UNARMED); + // We are in a game version with Maces + if (mcMMO.getCompatibilityManager().getMinecraftGameVersion().isAtLeast(1, 21, 0)) { + COMBAT_SKILLS = ImmutableList.of( + PrimarySkillType.ARCHERY, + PrimarySkillType.AXES, + PrimarySkillType.CROSSBOWS, + PrimarySkillType.MACES, + PrimarySkillType.SWORDS, + PrimarySkillType.TAMING, + PrimarySkillType.TRIDENTS, + PrimarySkillType.UNARMED); + } else { + // No Maces in this version + COMBAT_SKILLS = ImmutableList.of( + PrimarySkillType.ARCHERY, + PrimarySkillType.AXES, + PrimarySkillType.CROSSBOWS, + PrimarySkillType.SWORDS, + PrimarySkillType.TAMING, + PrimarySkillType.TRIDENTS, + PrimarySkillType.UNARMED); + } GATHERING_SKILLS = ImmutableList.of( PrimarySkillType.EXCAVATION, PrimarySkillType.FISHING, diff --git a/src/main/java/com/gmail/nossr50/util/sounds/SoundManager.java b/src/main/java/com/gmail/nossr50/util/sounds/SoundManager.java index 431c332cc..c89bf86e7 100644 --- a/src/main/java/com/gmail/nossr50/util/sounds/SoundManager.java +++ b/src/main/java/com/gmail/nossr50/util/sounds/SoundManager.java @@ -24,15 +24,39 @@ public class SoundManager { */ public static void sendSound(Player player, Location location, SoundType soundType) { if (SoundConfig.getInstance().getIsEnabled(soundType)) - player.playSound(location, getSound(soundType), SoundCategory.MASTER, getVolume(soundType), getPitch(soundType)); + player.playSound(location, getSound(soundType), + SoundCategory.MASTER, getVolume(soundType), getPitch(soundType)); } - public static void sendCategorizedSound(Player player, Location location, SoundType soundType, SoundCategory soundCategory) { + public static void sendCategorizedSound(Location location, SoundType soundType, SoundCategory soundCategory) { + if (SoundConfig.getInstance().getIsEnabled(soundType)) { + final World world = location.getWorld(); + if (world != null) { + world.playSound(location, getSound(soundType), soundCategory, + getVolume(soundType), getPitch(soundType)); + } + } + } + + public static void sendCategorizedSound(Location location, SoundType soundType, SoundCategory soundCategory, + float pitchModifier) { + if (SoundConfig.getInstance().getIsEnabled(soundType)) { + final World world = location.getWorld(); + if (world != null) { + float totalPitch = Math.min(2.0F, (getPitch(soundType) + pitchModifier)); + world.playSound(location, getSound(soundType), soundCategory, getVolume(soundType), totalPitch); + } + } + } + + public static void sendCategorizedSound(Player player, Location location, + SoundType soundType, SoundCategory soundCategory) { if (SoundConfig.getInstance().getIsEnabled(soundType)) player.playSound(location, getSound(soundType), soundCategory, getVolume(soundType), getPitch(soundType)); } - public static void sendCategorizedSound(Player player, Location location, SoundType soundType, SoundCategory soundCategory, float pitchModifier) { + public static void sendCategorizedSound(Player player, Location location, + SoundType soundType, SoundCategory soundCategory, float pitchModifier) { float totalPitch = Math.min(2.0F, (getPitch(soundType) + pitchModifier)); if (SoundConfig.getInstance().getIsEnabled(soundType)) diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index fede55679..fdb93cc40 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -694,6 +694,7 @@ Particles: Flux: true Greater_Impact: true Call_of_the_Wild: true + Cripple: true # These settings determine if fireworks should get launched when a player levels-up, # this will happen by default for every 100 levels. diff --git a/src/main/resources/locale/locale_en_US.properties b/src/main/resources/locale/locale_en_US.properties index cdafe8f50..5dd946a60 100644 --- a/src/main/resources/locale/locale_en_US.properties +++ b/src/main/resources/locale/locale_en_US.properties @@ -458,6 +458,7 @@ Tridents.SubSkill.TridentAbility.Name=WIP Tridents.Listener=Tridents: #MACES +Commands.McTop.MacesNotSupported=[[GREEN]]Maces are not supported in this version of Minecraft. Maces.SkillName=MACES Maces.Ability.Lower=&7You lower your mace. Maces.Ability.Ready=&3You &6ready&3 your Mace. @@ -467,6 +468,8 @@ Maces.SubSkill.MacesLimitBreak.Stat=Limit Break Max DMG Maces.SubSkill.Crush.Name=Crush Maces.SubSkill.Crush.Description=Adds bonus damage to your attacks. Maces.SubSkill.Crush.Stat=Crush Damage +Maces.SubSkill.Cripple.Proc=**CRIPPLED** +Maces.SubSkill.Cripple.Activated=CRIPPLED TARGET! Maces.SubSkill.Cripple.Name=Cripple Maces.SubSkill.Cripple.Description=Adds a chance to cripple your target. Maces.SubSkill.Cripple.Stat=Cripple Chance diff --git a/src/main/resources/repair.vanilla.yml b/src/main/resources/repair.vanilla.yml index 72ba687bd..52165805f 100644 --- a/src/main/resources/repair.vanilla.yml +++ b/src/main/resources/repair.vanilla.yml @@ -284,4 +284,12 @@ Repairables: ItemMaterialCategory: OTHER RepairMaterial: PRISMARINE_CRYSTALS MinimumQuantity: 16 + MaximumDurability: 250 + MACE: + MinimumLevel: 0 + XpMultiplier: 3 + ItemType: TOOL + ItemMaterialCategory: OTHER + RepairMaterial: BREEZE_ROD + MinimumQuantity: 4 MaximumDurability: 250 \ No newline at end of file diff --git a/src/main/resources/sounds.yml b/src/main/resources/sounds.yml index 8f88c574f..b6d4fcba4 100644 --- a/src/main/resources/sounds.yml +++ b/src/main/resources/sounds.yml @@ -67,4 +67,8 @@ Sounds: BLEED: Enable: true Volume: 2.0 - Pitch: 2.0 \ No newline at end of file + Pitch: 2.0 + CRIPPLE: + Enable: true + Volume: 1.0 + Pitch: 0.5 \ No newline at end of file diff --git a/src/test/java/com/gmail/nossr50/MMOTestEnvironment.java b/src/test/java/com/gmail/nossr50/MMOTestEnvironment.java index 984c5f123..3baa1a98d 100644 --- a/src/test/java/com/gmail/nossr50/MMOTestEnvironment.java +++ b/src/test/java/com/gmail/nossr50/MMOTestEnvironment.java @@ -13,6 +13,8 @@ import com.gmail.nossr50.datatypes.skills.PrimarySkillType; import com.gmail.nossr50.datatypes.skills.SubSkillType; import com.gmail.nossr50.util.*; import com.gmail.nossr50.util.blockmeta.ChunkManager; +import com.gmail.nossr50.util.compat.CompatibilityManager; +import com.gmail.nossr50.util.platform.MinecraftGameVersion; import com.gmail.nossr50.util.player.UserManager; import com.gmail.nossr50.util.skills.RankUtils; import com.gmail.nossr50.util.skills.SkillTools; @@ -67,8 +69,16 @@ public abstract class MMOTestEnvironment { protected ChunkManager chunkManager; protected MaterialMapStore materialMapStore; + protected CompatibilityManager compatibilityManager; + protected void mockBaseEnvironment(Logger logger) throws InvalidSkillException { + compatibilityManager = mock(CompatibilityManager.class); + final MinecraftGameVersion minecraftGameVersion = mock(MinecraftGameVersion.class); + when(compatibilityManager.getMinecraftGameVersion()).thenReturn(minecraftGameVersion); + // TODO: We should change minecraftGameVersion to be a passed in parameter instead of always returning true + when(minecraftGameVersion.isAtLeast(anyInt(), anyInt(), anyInt())).thenReturn(true); mockedMcMMO = mockStatic(mcMMO.class); + when(mcMMO.getCompatibilityManager()).thenReturn(compatibilityManager); mcMMO.p = mock(mcMMO.class); when(mcMMO.p.getLogger()).thenReturn(logger);