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 5d6aa9e5b..59c918a1e 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java +++ b/src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java @@ -22,6 +22,7 @@ import com.gmail.nossr50.locale.LocaleLoader; import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.party.PartyManager; import com.gmail.nossr50.party.ShareHandler; +import com.gmail.nossr50.runnables.skills.AbilityCooldownTask; import com.gmail.nossr50.runnables.skills.AbilityDisableTask; import com.gmail.nossr50.runnables.skills.ToolLowerTask; import com.gmail.nossr50.skills.SkillManager; @@ -389,6 +390,7 @@ public class McMMOPlayer implements Identified { * @param isActive True if the ability is active, false otherwise */ public void setAbilityMode(SuperAbilityType ability, boolean isActive) { + // TODO: This should reject "one and done" type abilities abilityMode.put(ability, isActive); } @@ -960,6 +962,67 @@ public class McMMOPlayer implements Identified { mcMMO.p.getFoliaLib().getImpl().runAtEntityLater(player, new AbilityDisableTask(this, superAbilityType), (long) ticks * Misc.TICK_CONVERSION_FACTOR); } + /** + * Check to see if an ability can be activated. + * + * @param bowType The type of bow (crossbow, bow) + */ + public void checkAbilityActivationProjectiles(BowType bowType) { + PrimarySkillType primarySkillType = bowType == BowType.CROSSBOW ? PrimarySkillType.CROSSBOWS : PrimarySkillType.ARCHERY; + + // TODO: Refactor this crappy logic + ToolType tool = bowType == BowType.CROSSBOW ? ToolType.CROSSBOW : ToolType.BOW; + SuperAbilityType superAbilityType = bowType == BowType.CROSSBOW ? SuperAbilityType.SUPER_SHOTGUN : SuperAbilityType.EXPLOSIVE_SHOT; + SubSkillType subSkillType = superAbilityType.getSubSkillTypeDefinition(); + + if (getAbilityMode(superAbilityType) || !superAbilityType.getPermissions(player)) { + return; + } + + //TODO: This is hacky and temporary solution until skills are move to the new system + //Potential problems with this include skills with two super abilities (ie mining) + if(!RankUtils.hasUnlockedSubskill(player, subSkillType)) + { + int diff = RankUtils.getSuperAbilityUnlockRequirement(superAbilityType) - getSkillLevel(primarySkillType); + + //Inform the player they are not yet skilled enough + NotificationManager.sendPlayerInformation(player, + NotificationType.ABILITY_COOLDOWN, + "Skills.AbilityGateRequirementFail", + String.valueOf(diff), + mcMMO.p.getSkillTools().getLocalizedSkillName(primarySkillType)); + return; + } + + // Call the event + if (EventUtils.callPlayerAbilityActivateEvent(player, primarySkillType).isCancelled()) { + return; + } + + if (useChatNotifications()) { + NotificationManager.sendPlayerInformation(player, NotificationType.SUPER_ABILITY, superAbilityType.getAbilityOn()); + } + + if (mcMMO.p.getAdvancedConfig().sendAbilityNotificationToOtherPlayers()) { + SkillUtils.sendSkillMessage(player, NotificationType.SUPER_ABILITY_ALERT_OTHERS, superAbilityType.getAbilityPlayer()); + } + + //Sounds + SoundManager.worldSendSound(player.getWorld(), player.getLocation(), SoundType.ABILITY_ACTIVATED_GENERIC); + + // TODO: Fire the ability + profile.setAbilityDATS(superAbilityType, System.currentTimeMillis()); + setAbilityMode(superAbilityType, true); + setToolPreparationMode(tool, false); + + if(!mcMMO.isServerShutdownExecuted()) { + mcMMO.p.getFoliaLib().getImpl().runAtEntityLater( + player, + new AbilityCooldownTask(this, superAbilityType), + (long) PerksUtils.handleCooldownPerks(player, superAbilityType.getCooldown()) * Misc.TICK_CONVERSION_FACTOR); + } + } + public void processAbilityActivation(@NotNull PrimarySkillType primarySkillType) { if (!mcMMO.p.getSkillTools().doesPlayerHaveSkillPermission(getPlayer(), primarySkillType)) { return; diff --git a/src/main/java/com/gmail/nossr50/datatypes/skills/SuperAbilityType.java b/src/main/java/com/gmail/nossr50/datatypes/skills/SuperAbilityType.java index 5c5728b0f..43e44a22f 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/skills/SuperAbilityType.java +++ b/src/main/java/com/gmail/nossr50/datatypes/skills/SuperAbilityType.java @@ -102,6 +102,7 @@ public enum SuperAbilityType { * Defining their associated SubSkillType definitions * This is a bit of a band-aid fix until the new skill system is in place */ + // TODO: This is stupid static { BERSERK.subSkillTypeDefinition = SubSkillType.UNARMED_BERSERK; SUPER_BREAKER.subSkillTypeDefinition = SubSkillType.MINING_SUPER_BREAKER; @@ -111,6 +112,8 @@ public enum SuperAbilityType { TREE_FELLER.subSkillTypeDefinition = SubSkillType.WOODCUTTING_TREE_FELLER; SERRATED_STRIKES.subSkillTypeDefinition = SubSkillType.SWORDS_SERRATED_STRIKES; BLAST_MINING.subSkillTypeDefinition = SubSkillType.MINING_BLAST_MINING; + TRIDENTS_SUPER_ABILITY.subSkillTypeDefinition = SubSkillType.TRIDENTS_TRIDENTS_SUPER_ABILITY; + SUPER_SHOTGUN.subSkillTypeDefinition = SubSkillType.CROSSBOWS_SUPER_SHOTGUN; } private final String abilityOn; @@ -193,6 +196,8 @@ public enum SuperAbilityType { * @param player Player to check permissions for * @return true if the player has permissions, false otherwise */ + // TODO: Add unit tests + // TODO: This is stupid public boolean getPermissions(Player player) { return switch (this) { case BERSERK -> Permissions.berserk(player); diff --git a/src/main/java/com/gmail/nossr50/listeners/PlayerListener.java b/src/main/java/com/gmail/nossr50/listeners/PlayerListener.java index a63b7650e..f27a69fcc 100644 --- a/src/main/java/com/gmail/nossr50/listeners/PlayerListener.java +++ b/src/main/java/com/gmail/nossr50/listeners/PlayerListener.java @@ -24,6 +24,7 @@ import com.gmail.nossr50.skills.taming.TamingManager; import com.gmail.nossr50.util.*; import com.gmail.nossr50.util.player.UserManager; import com.gmail.nossr50.util.scoreboards.ScoreboardManager; +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.sounds.SoundManager; @@ -915,6 +916,12 @@ public class PlayerListener implements Listener { break; } + // Projectile Skills + // Check if the player is holding a bow or crossbow + if (ItemUtils.isCrossbow(heldItem) || ItemUtils.isBow(heldItem)) { + CombatUtils.processProjectileSkillSuperAbilityActivation(mcMMOPlayer, heldItem); + } + /* CALL OF THE WILD CHECKS */ Material type = heldItem.getType(); TamingManager tamingManager = mcMMOPlayer.getTamingManager(); diff --git a/src/main/java/com/gmail/nossr50/runnables/skills/AbilityCooldownTask.java b/src/main/java/com/gmail/nossr50/runnables/skills/AbilityCooldownTask.java index 69e080972..9c7d8bfd8 100644 --- a/src/main/java/com/gmail/nossr50/runnables/skills/AbilityCooldownTask.java +++ b/src/main/java/com/gmail/nossr50/runnables/skills/AbilityCooldownTask.java @@ -21,9 +21,7 @@ public class AbilityCooldownTask extends CancellableRunnable { return; } - mcMMOPlayer.setAbilityInformed(ability, true); - + mcMMOPlayer.setAbilityInformed(ability, true); // TODO: ?? What does this do again? NotificationManager.sendPlayerInformation(mcMMOPlayer.getPlayer(), NotificationType.ABILITY_REFRESHED, ability.getAbilityRefresh()); - //mcMMOPlayer.getPlayer().sendMessage(ability.getAbilityRefresh()); } } diff --git a/src/main/java/com/gmail/nossr50/util/ItemUtils.java b/src/main/java/com/gmail/nossr50/util/ItemUtils.java index c41a3d486..a6ad59a18 100644 --- a/src/main/java/com/gmail/nossr50/util/ItemUtils.java +++ b/src/main/java/com/gmail/nossr50/util/ItemUtils.java @@ -36,14 +36,33 @@ public final class ItemUtils { * @param item Item to check * @return true if the item is a bow, false otherwise */ + // TODO: Unit tests public static boolean isBow(@NotNull ItemStack item) { return mcMMO.getMaterialMapStore().isBow(item.getType().getKey().getKey()); } + // TODO: Unit tests public static boolean isCrossbow(@NotNull ItemStack item) { return mcMMO.getMaterialMapStore().isCrossbow(item.getType().getKey().getKey()); } + // TODO: Unit tests + public static boolean isBowOrCrossbow(@NotNull ItemStack item) { + return isBow(item) || isCrossbow(item); + } + + // TODO: Unit tests + public static BowType getBowType(@NotNull ItemStack item) { + if (isBow(item)) { + return BowType.BOW; + } else if (isCrossbow(item)) { + return BowType.CROSSBOW; + } + + throw new IllegalArgumentException(item + " is not a bow or crossbow"); + } + + // TODO: Unit tests public static boolean isTrident(@NotNull ItemStack item) { return mcMMO.getMaterialMapStore().isTrident(item.getType().getKey().getKey()); } 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 e6397d954..399a875ec 100644 --- a/src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java +++ b/src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java @@ -49,6 +49,14 @@ public final class CombatUtils { return mcMMO.getMetadataService().getMobMetadataService(); } + // TODO: Unit tests + public static void processProjectileSkillSuperAbilityActivation(McMMOPlayer mmoPlayer, ItemStack heldItem) { + if (heldItem != null && mmoPlayer != null) { + if (ItemUtils.isBowOrCrossbow(heldItem)) + mmoPlayer.checkAbilityActivationProjectiles(ItemUtils.getBowType(heldItem)); + } + } + //Likely.. because who knows what plugins are throwing around public static boolean isDamageLikelyFromNormalCombat(@NotNull DamageCause damageCause) { return switch (damageCause) {