diff --git a/Changelog.txt b/Changelog.txt
index 93bd05e84..7752f7404 100644
--- a/Changelog.txt
+++ b/Changelog.txt
@@ -1,3 +1,14 @@
+# TODO: Add Maces to repair
+# TODO: Add subskills
+# TODO: Add Maces to combat utils
+# TODO: Skill ideas... Base DMG buff, Base Smash Buff, Momentum
+# TODO: Maces guide command
+# TODO: Maces Locale entries
+# 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
+
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 adc806edc..fac3d2289 100644
--- a/pom.xml
+++ b/pom.xml
@@ -376,7 +376,7 @@
org.spigotmc
spigot-api
- 1.20.6-R0.1-SNAPSHOT
+ 1.21-R0.1-SNAPSHOT
provided
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 176a9e9a4..e6fde3621 100644
--- a/src/main/java/com/gmail/nossr50/commands/skills/MacesCommand.java
+++ b/src/main/java/com/gmail/nossr50/commands/skills/MacesCommand.java
@@ -1,52 +1,80 @@
-//package com.gmail.nossr50.commands.skills;
-//
-//import com.gmail.nossr50.datatypes.player.McMMOPlayer;
-//import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
-//import com.gmail.nossr50.util.player.UserManager;
-//import com.gmail.nossr50.util.skills.CombatUtils;
-//import com.gmail.nossr50.util.skills.SkillUtils;
-//import com.gmail.nossr50.util.text.TextComponentFactory;
-//import net.kyori.adventure.text.Component;
-//import org.bukkit.ChatColor;
-//import org.bukkit.entity.Player;
-//
-//import java.util.ArrayList;
-//import java.util.List;
-//
-//import static com.gmail.nossr50.datatypes.skills.SubSkillType.MACES_MACES_LIMIT_BREAK;
-//
-//public class MacesCommand extends SkillCommand {
-//
-// public MacesCommand() {
-// super(PrimarySkillType.MACES);
-// }
-//
-// @Override
-// protected void dataCalculations(Player player, float skillValue) {}
-//
-// @Override
-// protected void permissionsCheck(Player player) {}
-//
-// @Override
-// protected List statsDisplay(Player player, float skillValue, boolean hasEndurance, boolean isLucky) {
-// List messages = new ArrayList<>();
-//
-// if (SkillUtils.canUseSubskill(player, MACES_MACES_LIMIT_BREAK)) {
-// messages.add(getStatMessage(MACES_MACES_LIMIT_BREAK,
-// String.valueOf(CombatUtils.getLimitBreakDamageAgainstQuality(player, MACES_MACES_LIMIT_BREAK, 1000))));
-// }
-//
-// messages.add(ChatColor.GRAY + "The Maces skill is a work in progress and is still being developed," +
-// " feedback would be appreciated in the mcMMO discord server.");
-// return messages;
-// }
-//
-// @Override
-// protected List getTextComponents(Player player) {
-// List textComponents = new ArrayList<>();
-//
-// TextComponentFactory.getSubSkillTextComponents(player, textComponents, PrimarySkillType.MACES);
-//
-// return textComponents;
-// }
-//}
+package com.gmail.nossr50.commands.skills;
+
+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.util.skills.CombatUtils;
+import com.gmail.nossr50.util.skills.RankUtils;
+import com.gmail.nossr50.util.skills.SkillUtils;
+import com.gmail.nossr50.util.text.TextComponentFactory;
+import net.kyori.adventure.text.Component;
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.gmail.nossr50.datatypes.skills.SubSkillType.MACES_CRIPPLE;
+import static com.gmail.nossr50.datatypes.skills.SubSkillType.MACES_MACES_LIMIT_BREAK;
+
+public class MacesCommand extends SkillCommand {
+
+ public MacesCommand() {
+ super(PrimarySkillType.MACES);
+ }
+
+ String crippleChanceToApply, crippleChanceToApplyLucky, crippleLengthAgainstPlayers, crippleLengthAgainstMobs;
+
+ @Override
+ 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");
+
+ crippleChanceToApply = String.valueOf(mcMMO.p.getAdvancedConfig().getCrippleChanceToApplyOnHit(crippleRank) + "%");
+ crippleChanceToApplyLucky = String.valueOf(mcMMO.p.getAdvancedConfig().getCrippleChanceToApplyOnHit(crippleRank) * 1.33);
+ }
+ }
+
+ @Override
+ protected void permissionsCheck(Player player) {}
+
+ @Override
+ protected List statsDisplay(Player player, float skillValue, boolean hasEndurance, boolean isLucky) {
+ final List messages = new ArrayList<>();
+
+ if (SkillUtils.canUseSubskill(player, MACES_MACES_LIMIT_BREAK)) {
+ messages.add(getStatMessage(MACES_MACES_LIMIT_BREAK,
+ String.valueOf(CombatUtils.getLimitBreakDamageAgainstQuality(player,
+ MACES_MACES_LIMIT_BREAK, 1000))));
+ }
+
+ if (SkillUtils.canUseSubskill(player, MACES_CRIPPLE)) {
+ messages.add(getStatMessage(MACES_CRIPPLE, crippleChanceToApply)
+ + (isLucky ? LocaleLoader.getString("Perks.Lucky.Bonus", crippleChanceToApplyLucky) : ""));
+ messages.add(getStatMessage(true, true, MACES_CRIPPLE,
+ crippleLengthAgainstPlayers,
+ crippleLengthAgainstMobs));
+ }
+
+ if (SkillUtils.canUseSubskill(player, SubSkillType.MACES_CRUSH)) {
+ messages.add(getStatMessage(SubSkillType.MACES_CRUSH,
+ String.valueOf(mmoPlayer.getMacesManager().getCrushDamage())));
+ }
+
+ messages.add(ChatColor.GRAY + "The Maces skill is a work in progress and is still being developed," +
+ " feedback would be appreciated in the mcMMO discord server.");
+ return messages;
+ }
+
+ @Override
+ protected List getTextComponents(Player player) {
+ List textComponents = new ArrayList<>();
+
+ TextComponentFactory.getSubSkillTextComponents(player, textComponents, PrimarySkillType.MACES);
+
+ return textComponents;
+ }
+}
diff --git a/src/main/java/com/gmail/nossr50/config/AdvancedConfig.java b/src/main/java/com/gmail/nossr50/config/AdvancedConfig.java
index 15b7d74c8..cf2f37eee 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 java.util.ArrayList;
import java.util.List;
public class AdvancedConfig extends BukkitConfig {
+ int[] defaultCrippleValues = new int[]{10, 15, 20, 25};
public AdvancedConfig(File dataFolder) {
super("advanced.yml", dataFolder);
@@ -937,4 +938,10 @@ public class AdvancedConfig extends BukkitConfig {
public boolean isKnockOnWoodXPOrbEnabled() {
return config.getBoolean("Skills.Woodcutting.TreeFeller.Knock_On_Wood.Add_XP_Orbs_To_Drops", true);
}
+
+ /* 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]);
+ }
}
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 464719ce0..fde59e455 100644
--- a/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java
+++ b/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java
@@ -112,7 +112,6 @@ public class McMMOPlayer implements Identified {
private int respawnATS;
private int teleportATS;
private long databaseATS;
- private double attackStrength; //captured during arm swing events
//private int chimeraWingLastUse;
private Location teleportCommence;
@@ -151,7 +150,6 @@ public class McMMOPlayer implements Identified {
experienceBarManager = new ExperienceBarManager(this);
debugMode = false; //Debug mode helps solve support issues, players can toggle it on or off
- attackStrength = 1.0D;
this.playerAuthor = new PlayerAuthor(player);
@@ -239,7 +237,7 @@ public class McMMOPlayer implements Identified {
}
public double getAttackStrength() {
- return attackStrength;
+ return player.getAttackCooldown();
}
public @NotNull PrimarySkillType getLastSkillShownScoreboard() {
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 53e84ec5d..3af58f56d 100644
--- a/src/main/java/com/gmail/nossr50/datatypes/skills/SubSkillType.java
+++ b/src/main/java/com/gmail/nossr50/datatypes/skills/SubSkillType.java
@@ -59,6 +59,8 @@ public enum SubSkillType {
/* Maces */
MACES_MACES_LIMIT_BREAK(10),
+ MACES_CRUSH(4),
+ MACES_CRIPPLE(4),
/* Mining */
MINING_BIGGER_BOMBS(1),
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 d309ad9cb..cb0aa44c8 100644
--- a/src/main/java/com/gmail/nossr50/skills/maces/MacesManager.java
+++ b/src/main/java/com/gmail/nossr50/skills/maces/MacesManager.java
@@ -2,10 +2,73 @@ package com.gmail.nossr50.skills.maces;
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 com.gmail.nossr50.util.random.ProbabilityUtil;
+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.entity.LivingEntity;
+import org.bukkit.potion.PotionEffect;
+import org.bukkit.potion.PotionEffectType;
+import org.jetbrains.annotations.NotNull;
public class MacesManager extends SkillManager {
public MacesManager(McMMOPlayer mmoPlayer) {
super(mmoPlayer, PrimarySkillType.MACES);
}
+
+ /**
+ * Get the Crush damage bonus.
+ *
+ * @return the Crush damage bonus.
+ */
+ public double getCrushDamage() {
+ if (!Permissions.canUseSubSkill(mmoPlayer.getPlayer(), SubSkillType.MACES_CRUSH))
+ return 0;
+
+ int rank = RankUtils.getRank(getPlayer(), SubSkillType.MACES_CRUSH);
+
+ if (rank > 0) {
+ return (1.0D + (rank * 0.5D));
+ }
+
+ return 0;
+ }
+
+ /**
+ * Process Cripple attack.
+ *
+ * @param target The defending entity
+ */
+ public void processCripple(@NotNull LivingEntity target) {
+ // Don't apply Cripple if the target is already Slowed
+ if (target.getPotionEffect(PotionEffectType.SLOWNESS) != null) {
+ return;
+ }
+
+ if (!Permissions.canUseSubSkill(mmoPlayer.getPlayer(), SubSkillType.MACES_CRIPPLE)) {
+ return;
+ }
+
+ int crippleRank = RankUtils.getRank(getPlayer(), SubSkillType.MACES_CRIPPLE);
+ double crippleOdds = (mcMMO.p.getAdvancedConfig().getCrippleChanceToApplyOnHit(crippleRank)
+ * mmoPlayer.getAttackStrength());
+
+ if (ProbabilityUtil.isStaticSkillRNGSuccessful(PrimarySkillType.MACES, mmoPlayer, crippleOdds)) {
+ // 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);
+ }
+ }
+
+ public int getCrippleTickDuration() {
+ // TODO: Make configurable
+ return 20 * 5;
+ }
}
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 ced2cbf25..b2ffd029b 100644
--- a/src/main/java/com/gmail/nossr50/util/commands/CommandRegistrationManager.java
+++ b/src/main/java/com/gmail/nossr50/util/commands/CommandRegistrationManager.java
@@ -32,95 +32,47 @@ public final class CommandRegistrationManager {
private static final String permissionsMessage = LocaleLoader.getString("mcMMO.NoPermission");
private static void registerSkillCommands() {
- for (PrimarySkillType skill : PrimarySkillType.values()) {
- if (skill == PrimarySkillType.MACES)
+ for (PrimarySkillType primarySkillType : PrimarySkillType.values()) {
+ if (primarySkillType == PrimarySkillType.MACES
+ && !mcMMO.getCompatibilityManager().getMinecraftGameVersion().isAtLeast(1, 21, 0)) {
continue;
+ }
- String commandName = skill.toString().toLowerCase(Locale.ENGLISH);
- String localizedName = mcMMO.p.getSkillTools().getLocalizedSkillName(skill).toLowerCase(Locale.ENGLISH);
+ final String commandName = primarySkillType.toString().toLowerCase(Locale.ENGLISH);
+ final String localizedName = mcMMO.p.getSkillTools().getLocalizedSkillName(primarySkillType).toLowerCase(Locale.ENGLISH);
- PluginCommand command;
+ final PluginCommand command = mcMMO.p.getCommand(commandName);
+ if (command == null) {
+ mcMMO.p.getLogger().severe("Command not found: " + commandName);
+ continue;
+ }
- command = mcMMO.p.getCommand(commandName);
command.setDescription(LocaleLoader.getString("Commands.Description.Skill", StringUtils.getCapitalized(localizedName)));
command.setPermission("mcmmo.commands." + commandName);
command.setPermissionMessage(permissionsMessage);
command.setUsage(LocaleLoader.getString("Commands.Usage.0", commandName));
command.setUsage(command.getUsage() + "\n" + LocaleLoader.getString("Commands.Usage.2", commandName, "?", "[" + LocaleLoader.getString("Commands.Usage.Page") + "]"));
- switch (skill) {
- case ACROBATICS:
- command.setExecutor(new AcrobaticsCommand());
- break;
-
- case ALCHEMY:
- command.setExecutor(new AlchemyCommand());
- break;
-
- case ARCHERY:
- command.setExecutor(new ArcheryCommand());
- break;
-
- case AXES:
- command.setExecutor(new AxesCommand());
- break;
- case CROSSBOWS:
- command.setExecutor(new CrossbowsCommand());
- break;
-
- case EXCAVATION:
- command.setExecutor(new ExcavationCommand());
- break;
-
- case FISHING:
- command.setExecutor(new FishingCommand());
- break;
-
- case HERBALISM:
- command.setExecutor(new HerbalismCommand());
- break;
-
- case MACES:
- // command.setExecutor(new MacesCommand());
- break;
-
- case MINING:
- command.setExecutor(new MiningCommand());
- break;
-
- case REPAIR:
- command.setExecutor(new RepairCommand());
- break;
-
- case SALVAGE:
- command.setExecutor(new SalvageCommand());
- break;
-
- case SMELTING:
- command.setExecutor(new SmeltingCommand());
- break;
-
- case SWORDS:
- command.setExecutor(new SwordsCommand());
- break;
-
- case TAMING:
- command.setExecutor(new TamingCommand());
- break;
- case TRIDENTS:
- command.setExecutor(new TridentsCommand());
- break;
-
- case UNARMED:
- command.setExecutor(new UnarmedCommand());
- break;
-
- case WOODCUTTING:
- command.setExecutor(new WoodcuttingCommand());
- break;
-
- default:
- throw new IllegalStateException("Unexpected value: " + skill);
+ switch (primarySkillType) {
+ case ACROBATICS -> command.setExecutor(new AcrobaticsCommand());
+ case ALCHEMY -> command.setExecutor(new AlchemyCommand());
+ case ARCHERY -> command.setExecutor(new ArcheryCommand());
+ case AXES -> command.setExecutor(new AxesCommand());
+ case CROSSBOWS -> command.setExecutor(new CrossbowsCommand());
+ case EXCAVATION -> command.setExecutor(new ExcavationCommand());
+ case FISHING -> command.setExecutor(new FishingCommand());
+ case HERBALISM -> command.setExecutor(new HerbalismCommand());
+ case MACES -> command.setExecutor(new MacesCommand());
+ case MINING -> command.setExecutor(new MiningCommand());
+ case REPAIR -> command.setExecutor(new RepairCommand());
+ case SALVAGE -> command.setExecutor(new SalvageCommand());
+ case SMELTING -> command.setExecutor(new SmeltingCommand());
+ case SWORDS -> command.setExecutor(new SwordsCommand());
+ case TAMING -> command.setExecutor(new TamingCommand());
+ case TRIDENTS -> command.setExecutor(new TridentsCommand());
+ case UNARMED -> command.setExecutor(new UnarmedCommand());
+ case WOODCUTTING -> command.setExecutor(new WoodcuttingCommand());
+ default -> throw new IllegalStateException("Unexpected value: " + primarySkillType);
}
}
}
diff --git a/src/main/java/com/gmail/nossr50/util/platform/PlatformManager.java b/src/main/java/com/gmail/nossr50/util/platform/PlatformManager.java
index 721df8091..a638dabfd 100644
--- a/src/main/java/com/gmail/nossr50/util/platform/PlatformManager.java
+++ b/src/main/java/com/gmail/nossr50/util/platform/PlatformManager.java
@@ -85,14 +85,11 @@ public class PlatformManager {
}
public String getServerSoftwareStr() {
- switch(getServerSoftware()) {
- case PAPER:
- return "Paper";
- case SPIGOT:
- return "Spigot";
- default:
- return "CraftBukkit";
- }
+ return switch (getServerSoftware()) {
+ case PAPER -> "Paper";
+ case SPIGOT -> "Spigot";
+ default -> "CraftBukkit";
+ };
}
public @Nullable CompatibilityManager getCompatibilityManager() {
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 fb5834ad9..6c82189dd 100644
--- a/src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java
+++ b/src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java
@@ -13,6 +13,7 @@ import com.gmail.nossr50.runnables.skills.AwardCombatXpTask;
import com.gmail.nossr50.skills.acrobatics.AcrobaticsManager;
import com.gmail.nossr50.skills.archery.ArcheryManager;
import com.gmail.nossr50.skills.axes.AxesManager;
+import com.gmail.nossr50.skills.maces.MacesManager;
import com.gmail.nossr50.skills.swords.SwordsManager;
import com.gmail.nossr50.skills.taming.TamingManager;
import com.gmail.nossr50.skills.tridents.TridentsManager;
@@ -20,6 +21,7 @@ import com.gmail.nossr50.skills.unarmed.UnarmedManager;
import com.gmail.nossr50.util.*;
import com.gmail.nossr50.util.player.NotificationManager;
import com.gmail.nossr50.util.player.UserManager;
+import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.attribute.Attribute;
@@ -72,10 +74,6 @@ public final class CombatUtils {
mcMMOPlayer.checkAbilityActivation(PrimarySkillType.SWORDS);
}
- if (target.getHealth() - event.getFinalDamage() > 0) {
- swordsManager.processRupture(target);
- }
-
//Add Stab Damage
if (swordsManager.canUseStab()) {
boostedDamage += (swordsManager.getStabDamage() * mcMMOPlayer.getAttackStrength());
@@ -90,6 +88,11 @@ public final class CombatUtils {
}
event.setDamage(boostedDamage);
+
+ if (target.getHealth() - event.getFinalDamage() > 0) {
+ swordsManager.processRupture(target);
+ }
+
processCombatXP(mcMMOPlayer, target, PrimarySkillType.SWORDS);
printFinalDamageDebug(player, event, mcMMOPlayer);
@@ -210,29 +213,40 @@ public final class CombatUtils {
delayArrowMetaCleanup(arrow);
}
- private static void processMacesCombat(@NotNull LivingEntity target, @NotNull Player player, @NotNull EntityDamageByEntityEvent event) {
+ private static void processMacesCombat(@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;
}
- // MacesManager macesManager = mcMMOPlayer.getMacesManager();
+ final MacesManager macesManager = mcMMOPlayer.getMacesManager();
+ // Apply Limit Break DMG
if (canUseLimitBreak(player, target, SubSkillType.MACES_MACES_LIMIT_BREAK)) {
boostedDamage += (getLimitBreakDamage(player, target, SubSkillType.MACES_MACES_LIMIT_BREAK) * mcMMOPlayer.getAttackStrength());
}
- event.setDamage(boostedDamage);
- processCombatXP(mcMMOPlayer, target, PrimarySkillType.MACES);
+ // Apply Crush
+ boostedDamage += (macesManager.getCrushDamage() * mcMMOPlayer.getAttackStrength());
+ event.setDamage(boostedDamage);
+
+ // Apply Cripple
+ if (target.getHealth() - event.getFinalDamage() > 0) {
+ macesManager.processCripple(target);
+ }
+
+ processCombatXP(mcMMOPlayer, target, PrimarySkillType.MACES);
printFinalDamageDebug(player, event, mcMMOPlayer);
}
@@ -416,7 +430,9 @@ public final class CombatUtils {
*
* @param event The event to run the combat checks on.
*/
- public static void processCombatAttack(@NotNull EntityDamageByEntityEvent event, @NotNull Entity painSourceRoot, @NotNull LivingEntity target) {
+ public static void processCombatAttack(@NotNull EntityDamageByEntityEvent event,
+ @NotNull Entity painSourceRoot,
+ @NotNull LivingEntity target) {
Entity painSource = event.getDamager();
EntityType entityType = painSource.getType();
@@ -456,6 +472,11 @@ 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;
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 c809444fa..431c332cc 100644
--- a/src/main/java/com/gmail/nossr50/util/sounds/SoundManager.java
+++ b/src/main/java/com/gmail/nossr50/util/sounds/SoundManager.java
@@ -9,6 +9,15 @@ import org.bukkit.World;
import org.bukkit.entity.Player;
public class SoundManager {
+ public static Sound CRIPPLE_SOUND;
+ static {
+ try {
+ CRIPPLE_SOUND = Sound.valueOf("ITEM_MACE_SMASH_GROUND");
+ } catch (IllegalArgumentException e) {
+ CRIPPLE_SOUND = Sound.BLOCK_ANVIL_PLACE;
+ }
+ }
+
/**
* Sends a sound to the player
* @param soundType the type of sound
@@ -74,6 +83,7 @@ public class SoundManager {
case DEFLECT_ARROWS, BLEED -> Sound.ENTITY_ENDER_EYE_DEATH;
case GLASS -> Sound.BLOCK_GLASS_BREAK;
case ITEM_CONSUMED -> Sound.ITEM_BOTTLE_EMPTY;
+ case CRIPPLE -> CRIPPLE_SOUND;
};
}
diff --git a/src/main/java/com/gmail/nossr50/util/sounds/SoundType.java b/src/main/java/com/gmail/nossr50/util/sounds/SoundType.java
index 5b4a083f3..21c1a0d93 100644
--- a/src/main/java/com/gmail/nossr50/util/sounds/SoundType.java
+++ b/src/main/java/com/gmail/nossr50/util/sounds/SoundType.java
@@ -16,6 +16,7 @@ public enum SoundType {
BLEED,
GLASS,
ITEM_CONSUMED,
+ CRIPPLE,
TIRED;
public boolean usesCustomPitch() {
diff --git a/src/main/resources/advanced.yml b/src/main/resources/advanced.yml
index 7d56c4e37..bbbf2ea44 100644
--- a/src/main/resources/advanced.yml
+++ b/src/main/resources/advanced.yml
@@ -633,4 +633,11 @@ Skills:
ChanceMax: 100.0
MaxBonusLevel:
Standard: 100
- RetroMode: 1000
\ No newline at end of file
+ RetroMode: 1000
+ Maces:
+ Cripple:
+ Chance_To_Apply_On_Hit:
+ Rank_1: 10
+ Rank_2: 15
+ Rank_3: 20
+ Rank_4: 33
\ 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 f2fcc7a26..cdafe8f50 100644
--- a/src/main/resources/locale/locale_en_US.properties
+++ b/src/main/resources/locale/locale_en_US.properties
@@ -464,6 +464,13 @@ Maces.Ability.Ready=&3You &6ready&3 your Mace.
Maces.SubSkill.MacesLimitBreak.Name=Maces Limit Break
Maces.SubSkill.MacesLimitBreak.Description=Breaking your limits. Increased damage against tough opponents. Intended for PVP, up to server settings for whether it will boost damage in PVE.
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.Name=Cripple
+Maces.SubSkill.Cripple.Description=Adds a chance to cripple your target.
+Maces.SubSkill.Cripple.Stat=Cripple Chance
+Maces.SubSkill.Cripple.Stat.Extra=[[DARK_AQUA]]Cripple Duration: &e{0}s&a vs Players, &e{1}s&a vs Mobs.
Maces.Listener=Maces:
#SWORDS
@@ -899,6 +906,7 @@ Commands.XPGain.Crossbows=Attacking Monsters
Commands.XPGain.Excavation=Digging and finding treasures
Commands.XPGain.Fishing=Fishing (Go figure!)
Commands.XPGain.Herbalism=Harvesting Herbs
+Commands.XPGain.Maces=Attacking Monsters
Commands.XPGain.Mining=Mining Stone & Ore
Commands.XPGain.Repair=Repairing
Commands.XPGain.Swords=Attacking Monsters
diff --git a/src/main/resources/skillranks.yml b/src/main/resources/skillranks.yml
index e6cea3643..66e2cb06e 100644
--- a/src/main/resources/skillranks.yml
+++ b/src/main/resources/skillranks.yml
@@ -444,28 +444,51 @@ Salvage:
Rank_7: 850
Rank_8: 1000
Maces:
- Standard:
- Rank_1: 10
- Rank_2: 20
- Rank_3: 30
- Rank_4: 40
- Rank_5: 50
- Rank_6: 60
- Rank_7: 70
- Rank_8: 80
- Rank_9: 90
- Rank_10: 100
- RetroMode:
- Rank_1: 100
- Rank_2: 200
- Rank_3: 300
- Rank_4: 400
- Rank_5: 500
- Rank_6: 600
- Rank_7: 700
- Rank_8: 800
- Rank_9: 900
- Rank_10: 1000
+ MacesLimitBreak:
+ Standard:
+ Rank_1: 10
+ Rank_2: 20
+ Rank_3: 30
+ Rank_4: 40
+ Rank_5: 50
+ Rank_6: 60
+ Rank_7: 70
+ Rank_8: 80
+ Rank_9: 90
+ Rank_10: 100
+ RetroMode:
+ Rank_1: 100
+ Rank_2: 200
+ Rank_3: 300
+ Rank_4: 400
+ Rank_5: 500
+ Rank_6: 600
+ Rank_7: 700
+ Rank_8: 800
+ Rank_9: 900
+ Rank_10: 1000
+ Cripple:
+ Standard:
+ Rank_1: 5
+ Rank_2: 20
+ Rank_3: 40
+ Rank_4: 80
+ RetroMode:
+ Rank_1: 50
+ Rank_2: 200
+ Rank_3: 400
+ Rank_4: 800
+ Crush:
+ Standard:
+ Rank_1: 10
+ Rank_2: 25
+ Rank_3: 75
+ Rank_4: 90
+ RetroMode:
+ Rank_1: 100
+ Rank_2: 250
+ Rank_3: 750
+ Rank_4: 900
Mining:
MotherLode:
Standard:
diff --git a/src/test/java/com/gmail/nossr50/skills/woodcutting/WoodcuttingTest.java b/src/test/java/com/gmail/nossr50/skills/woodcutting/WoodcuttingTest.java
index 01c7c1549..06eecb43b 100644
--- a/src/test/java/com/gmail/nossr50/skills/woodcutting/WoodcuttingTest.java
+++ b/src/test/java/com/gmail/nossr50/skills/woodcutting/WoodcuttingTest.java
@@ -17,9 +17,7 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
-import java.util.Collection;
import java.util.Collections;
-import java.util.List;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;