Fix Blast Mining Fixes #5021

This commit is contained in:
nossr50 2024-07-13 16:39:04 -07:00
parent ce8464fcfe
commit 2debcbefd0
8 changed files with 83 additions and 140 deletions

View File

@ -1,4 +1,7 @@
Version 2.2.017
Fixed Blast Mining being almost completely broken
Reworked Blast Mining to drop non-mining related blocks too
Reworked Blast Mining to use your pickaxe when determining drops (will apply Silk Touch)
Fixed shift-clicking ingredients into the brewing stand not working on older versions of Minecraft
Added a setting in advanced.yml to ignore attack cooldowns (see notes)
Fixed a bug with Mace permissions (thanks SrBedrock)

View File

@ -48,7 +48,7 @@ public class MiningCommand extends SkillCommand {
blastMiningRank = miningManager.getBlastMiningTier();
bonusTNTDrops = miningManager.getDropMultiplier();
oreBonus = percent.format(miningManager.getOreBonus() / 30.0D); // Base received in TNT is 30%
oreBonus = percent.format(miningManager.getOreBonus()); // Base received in TNT is 30%
// debrisReduction = percent.format(miningManager.getDebrisReduction() / 30.0D); // Base received in TNT is 30%
blastDamageDecrease = percent.format(miningManager.getBlastDamageModifier() / 100.0D);
blastRadiusIncrease = miningManager.getBlastRadiusModifier();

View File

@ -75,7 +75,8 @@ public class Roll extends AcrobaticsSubSkill {
*/
if (canRoll(mmoPlayer)) {
entityDamageEvent.setDamage(rollCheck(mmoPlayer, entityDamageEvent.getFinalDamage()));
entityDamageEvent.setDamage(
rollCheck(mmoPlayer, entityDamageEvent.getFinalDamage(), mmoPlayer.getPlayer().isSneaking()));
if (entityDamageEvent.getFinalDamage() == 0) {
entityDamageEvent.setCancelled(true);
@ -189,64 +190,24 @@ public class Roll extends AcrobaticsSubSkill {
&& Permissions.isSubSkillEnabled(mmoPlayer.getPlayer(), SubSkillType.ACROBATICS_ROLL);
}
/**
* Handle the damage reduction and XP gain from the Roll ability
*
* @param damage The amount of damage initially dealt by the event
* @return the modified event damage if the ability was successful, the original event damage otherwise
*/
@VisibleForTesting
public double rollCheck(McMMOPlayer mmoPlayer, double damage) {
int skillLevel = mmoPlayer.getSkillLevel(getPrimarySkill());
if (mmoPlayer.getPlayer().isSneaking()) {
return gracefulRollCheck(mmoPlayer, damage, skillLevel);
}
double modifiedDamage = calculateModifiedRollDamage(damage, mcMMO.p.getAdvancedConfig().getRollDamageThreshold());
if (!isFatal(mmoPlayer, modifiedDamage)
&& ProbabilityUtil.isSkillRNGSuccessful(SubSkillType.ACROBATICS_ROLL, mmoPlayer)) {
NotificationManager.sendPlayerInformation(mmoPlayer.getPlayer(), NotificationType.SUBSKILL_MESSAGE, "Acrobatics.Roll.Text");
SoundManager.sendCategorizedSound(mmoPlayer.getPlayer(), mmoPlayer.getPlayer().getLocation(), SoundType.ROLL_ACTIVATED, SoundCategory.PLAYERS);
//mmoPlayer.getPlayer().sendMessage(LocaleLoader.getString("Acrobatics.Roll.Text"));
//if (!SkillUtils.cooldownExpired((long) mcMMOmmoPlayer.getPlayer().getTeleportATS(), Config.getInstance().getXPAfterTeleportCooldown())) {
if (!isExploiting(mmoPlayer) && mmoPlayer.getAcrobaticsManager().canGainRollXP())
SkillUtils.applyXpGain(mmoPlayer, getPrimarySkill(), calculateRollXP(mmoPlayer, damage, true), XPGainReason.PVE);
//}
addFallLocation(mmoPlayer);
return modifiedDamage;
} else if (!isFatal(mmoPlayer, damage)) {
//if (!SkillUtils.cooldownExpired((long) mmoPlayer.getTeleportATS(), Config.getInstance().getXPAfterTeleportCooldown())) {
if (!isExploiting(mmoPlayer) && mmoPlayer.getAcrobaticsManager().canGainRollXP())
SkillUtils.applyXpGain(mmoPlayer, getPrimarySkill(), calculateRollXP(mmoPlayer, damage, false), XPGainReason.PVE);
//}
}
addFallLocation(mmoPlayer);
return damage;
}
private int getActivationChance(McMMOPlayer mmoPlayer) {
return PerksUtils.handleLuckyPerks(mmoPlayer, getPrimarySkill());
}
/**
* Handle the damage reduction and XP gain from the Graceful Roll ability
* Handle the damage reduction and XP gain from the Roll / Graceful Roll ability
*
* @param damage The amount of damage initially dealt by the event
* @return the modified event damage if the ability was successful, the original event damage otherwise
*/
private double gracefulRollCheck(McMMOPlayer mmoPlayer, double damage, int skillLevel) {
double modifiedDamage = calculateModifiedRollDamage(damage, mcMMO.p.getAdvancedConfig().getRollDamageThreshold() * 2);
final Probability gracefulProbability = getGracefulProbability(mmoPlayer);
private double rollCheck(McMMOPlayer mmoPlayer, double damage, boolean isGracefulRoll) {
final Probability probability
= isGracefulRoll ? getGracefulProbability(mmoPlayer) : getNonGracefulProbability(mmoPlayer);
double modifiedDamage = calculateModifiedRollDamage(damage,
mcMMO.p.getAdvancedConfig().getRollDamageThreshold() * 2);
if (!isFatal(mmoPlayer, modifiedDamage)
//TODO: Graceful isn't sending out an event
&& ProbabilityUtil.isStaticSkillRNGSuccessful(PrimarySkillType.ACROBATICS, mmoPlayer, gracefulProbability)) {
&& ProbabilityUtil.isStaticSkillRNGSuccessful(PrimarySkillType.ACROBATICS, mmoPlayer, probability)) {
NotificationManager.sendPlayerInformation(mmoPlayer.getPlayer(), NotificationType.SUBSKILL_MESSAGE, "Acrobatics.Ability.Proc");
SoundManager.sendCategorizedSound(mmoPlayer.getPlayer(), mmoPlayer.getPlayer().getLocation(), SoundType.ROLL_ACTIVATED, SoundCategory.PLAYERS,0.5F);
if (!isExploiting(mmoPlayer) && mmoPlayer.getAcrobaticsManager().canGainRollXP())
@ -270,6 +231,11 @@ public class Roll extends AcrobaticsSubSkill {
return Probability.ofValue(gracefulOdds);
}
public static Probability getNonGracefulProbability(McMMOPlayer mmoPlayer) {
double gracefulOdds = ProbabilityUtil.getSubSkillProbability(SubSkillType.ACROBATICS_ROLL, mmoPlayer).getValue();
return Probability.ofValue(gracefulOdds);
}
/**
* Check if the player is "farming" Acrobatics XP using
* exploits in the game.

View File

@ -756,7 +756,7 @@ public class EntityListener implements Listener {
if (WorldBlacklist.isWorldBlacklisted(event.getEntity().getWorld()))
return;
Entity entity = event.getEntity();
final Entity entity = event.getEntity();
if (!(entity instanceof TNTPrimed) || !entity.hasMetadata(MetadataConstants.METADATA_KEY_TRACKED_TNT)) {
return;
@ -764,13 +764,14 @@ public class EntityListener implements Listener {
// We can make this assumption because we (should) be the only ones
// using this exact metadata
Player player = pluginRef.getServer().getPlayerExact(entity.getMetadata(MetadataConstants.METADATA_KEY_TRACKED_TNT).get(0).asString());
final Player player = pluginRef.getServer().getPlayerExact(
entity.getMetadata(MetadataConstants.METADATA_KEY_TRACKED_TNT).get(0).asString());
if (!UserManager.hasPlayerDataKey(player)) {
return;
}
//Profile not loaded
// Profile is not loaded
if (UserManager.getPlayer(player) == null) {
return;
}
@ -781,7 +782,7 @@ public class EntityListener implements Listener {
return;
}
MiningManager miningManager = UserManager.getPlayer(player).getMiningManager();
final MiningManager miningManager = UserManager.getPlayer(player).getMiningManager();
if (miningManager.canUseBiggerBombs()) {
event.setRadius(miningManager.biggerBombs(event.getRadius()));

View File

@ -10,58 +10,17 @@ import org.bukkit.entity.TNTPrimed;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
public class BlastMining {
// The order of the values is extremely important, a few methods depend on it to work properly
/* public enum Tier {
EIGHT(8),
SEVEN(7),
SIX(6),
FIVE(5),
FOUR(4),
THREE(3),
TWO(2),
ONE(1);
int numerical;
private Tier(int numerical) {
this.numerical = numerical;
}
public int toNumerical() {
return numerical;
}
protected int getLevel() {
return mcMMO.p.getAdvancedConfig().getBlastMiningRankLevel(this);
}
}*/
public final static int MAXIMUM_REMOTE_DETONATION_DISTANCE = 100;
public static double getBlastRadiusModifier(int rank) {
return mcMMO.p.getAdvancedConfig().getBlastRadiusModifier(rank);
}
public static double getBlastDamageDecrease(int rank) {
return mcMMO.p.getAdvancedConfig().getBlastDamageDecrease(rank);
}
public static int getDemolitionExpertUnlockLevel() {
/*List<Tier> tierList = Arrays.asList(Tier.values());
for (Tier tier : tierList) {
if (tier.getBlastDamageDecrease() > 0) {
continue;
}
return tier == Tier.EIGHT ? tier.getLevel() : tierList.get(tierList.indexOf(tier) - 1).getLevel();
}*/
for(int i = 0; i < SubSkillType.MINING_BLAST_MINING.getNumRanks()-1; i++) {
if (getBlastDamageDecrease(i+1) > 0)
return RankUtils.getRankUnlockLevel(SubSkillType.MINING_BLAST_MINING, i+1);
@ -71,15 +30,6 @@ public class BlastMining {
}
public static int getBiggerBombsUnlockLevel() {
/*List<Tier> tierList = Arrays.asList(Tier.values());
for (Tier tier : tierList) {
if (tier.getBlastRadiusModifier() > 1.0) {
continue;
}
return tier == Tier.EIGHT ? tier.getLevel() : tierList.get(tierList.indexOf(tier) - 1).getLevel();
}*/
for(int i = 0; i < SubSkillType.MINING_BLAST_MINING.getNumRanks()-1; i++) {
if (getBlastRadiusModifier(i+1) > 0)
return RankUtils.getRankUnlockLevel(SubSkillType.MINING_BLAST_MINING, i+1);
@ -104,7 +54,7 @@ public class BlastMining {
return false;
}
MiningManager miningManager = UserManager.getPlayer(defender).getMiningManager();
final MiningManager miningManager = UserManager.getPlayer(defender).getMiningManager();
if (!miningManager.canUseDemolitionsExpertise()) {
return false;

View File

@ -17,7 +17,6 @@ import com.gmail.nossr50.util.random.Probability;
import com.gmail.nossr50.util.random.ProbabilityUtil;
import com.gmail.nossr50.util.skills.RankUtils;
import com.gmail.nossr50.util.skills.SkillUtils;
import org.apache.commons.lang3.RandomUtils;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
@ -30,8 +29,11 @@ import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import static com.gmail.nossr50.util.ItemUtils.isPickaxe;
public class MiningManager extends SkillManager {
public static final String BUDDING_AMETHYST = "budding_amethyst";
@ -51,7 +53,7 @@ public class MiningManager extends SkillManager {
Player player = getPlayer();
return canUseBlastMining() && player.isSneaking()
&& (ItemUtils.isPickaxe(getPlayer().getInventory().getItemInMainHand()) || player.getInventory().getItemInMainHand().getType() == mcMMO.p.getGeneralConfig().getDetonatorItem())
&& (isPickaxe(getPlayer().getInventory().getItemInMainHand()) || player.getInventory().getItemInMainHand().getType() == mcMMO.p.getGeneralConfig().getDetonatorItem())
&& Permissions.remoteDetonation(player);
}
@ -168,69 +170,76 @@ public class MiningManager extends SkillManager {
* @param yield The % of blocks to drop
* @param event The {@link EntityExplodeEvent}
*/
//TODO: Rewrite this garbage
public void blastMiningDropProcessing(float yield, EntityExplodeEvent event) {
if (yield == 0)
return;
//Strip out only stuff that gives mining XP
var increasedYieldFromBonuses = yield + (yield * getOreBonus());
// Strip out only stuff that gives mining XP
List<BlockState> ores = new ArrayList<>();
List<BlockState> notOres = new ArrayList<>();
for (Block targetBlock : event.blockList()) {
BlockState blockState = targetBlock.getState();
//Containers usually have 0 XP unless someone edited their config in a very strange way
if (ExperienceConfig.getInstance().getXp(PrimarySkillType.MINING, targetBlock) != 0
&& !(targetBlock instanceof Container)
&& !mcMMO.getUserBlockTracker().isIneligible(targetBlock)) {
if (BlockUtils.isOre(blockState)) {
if(mcMMO.getUserBlockTracker().isIneligible(targetBlock))
continue;
if (ExperienceConfig.getInstance().getXp(PrimarySkillType.MINING, targetBlock) != 0) {
if (BlockUtils.isOre(blockState) && !(targetBlock instanceof Container)) {
ores.add(blockState);
} else {
notOres.add(blockState);
}
} else {
notOres.add(blockState);
}
}
int xp = 0;
float oreBonus = (float) (getOreBonus() / 100);
float debrisReduction = (float) (getDebrisReduction() / 100);
int dropMultiplier = getDropMultiplier();
float debrisYield = yield - debrisReduction;
//Drop "debris" based on skill modifiers
for(BlockState blockState : notOres) {
if (isDropIllegal(blockState.getType()))
continue;
if (Probability.ofPercent(50).evaluate()) {
ItemUtils.spawnItem(getPlayer(), Misc.getBlockCenter(blockState), new ItemStack(blockState.getType()), ItemSpawnReason.BLAST_MINING_DEBRIS_NON_ORES); // Initial block that would have been dropped
ItemUtils.spawnItem(getPlayer(),
Misc.getBlockCenter(blockState),
new ItemStack(blockState.getType()),
ItemSpawnReason.BLAST_MINING_DEBRIS_NON_ORES); // Initial block that would have been dropped
}
}
for (BlockState blockState : ores) {
if (isDropIllegal(blockState.getType()))
// currentOreYield only used for drop calculations for ores
float currentOreYield = increasedYieldFromBonuses;
if (isDropIllegal(blockState.getType())) {
continue;
}
if (RandomUtils.nextFloat() < (yield + oreBonus)) {
xp += Mining.getBlockXp(blockState);
// Always give XP for every ore destroyed
xp += Mining.getBlockXp(blockState);
while(currentOreYield > 0) {
if (Probability.ofValue(currentOreYield).evaluate()) {
Collection<ItemStack> oreDrops = isPickaxe(mmoPlayer.getPlayer().getInventory().getItemInMainHand())
? blockState.getBlock().getDrops(mmoPlayer.getPlayer().getInventory().getItemInMainHand())
: List.of(new ItemStack(blockState.getType()));
ItemUtils.spawnItems(getPlayer(), Misc.getBlockCenter(blockState),
oreDrops, ItemSpawnReason.BLAST_MINING_ORES);
ItemUtils.spawnItem(getPlayer(), Misc.getBlockCenter(blockState), new ItemStack(blockState.getType()), ItemSpawnReason.BLAST_MINING_ORES); // Initial block that would have been dropped
if (mcMMO.p.getAdvancedConfig().isBlastMiningBonusDropsEnabled() && !mcMMO.getUserBlockTracker().isIneligible(blockState)) {
for (int i = 1; i < dropMultiplier; i++) {
// Bukkit.broadcastMessage("Bonus Drop on Ore: "+blockState.getType().toString());
ItemUtils.spawnItem(getPlayer(), Misc.getBlockCenter(blockState), new ItemStack(blockState.getType()), ItemSpawnReason.BLAST_MINING_ORES_BONUS_DROP); // Initial block that would have been dropped
if (mcMMO.p.getAdvancedConfig().isBlastMiningBonusDropsEnabled()) {
for (int i = 1; i < dropMultiplier; i++) {
ItemUtils.spawnItems(getPlayer(),
Misc.getBlockCenter(blockState),
oreDrops,
ItemSpawnReason.BLAST_MINING_ORES_BONUS_DROP);
}
}
}
currentOreYield = Math.max(currentOreYield - 1, 0);
}
}
//Replace the event blocklist with the newYield list
// Replace the event blocklist with the newYield list
event.setYield(0F);
// event.blockList().clear();
// event.blockList().addAll(notOres);
applyXpGain(xp, XPGainReason.PVE);
}
@ -273,10 +282,11 @@ public class MiningManager extends SkillManager {
*
* @return the Blast Mining tier
*/
public double getOreBonus() {
return getOreBonus(getBlastMiningTier());
public float getOreBonus() {
return (float) (mcMMO.p.getAdvancedConfig().getOreBonus(getBlastMiningTier()) / 100F);
}
@Deprecated(since = "2.2.017", forRemoval = true)
public static double getOreBonus(int rank) {
return mcMMO.p.getAdvancedConfig().getOreBonus(rank);
}

View File

@ -681,6 +681,21 @@ public final class ItemUtils {
return enchantmentWrappers.get(randomIndex);
}
/**
* Drop items at a given location.
*
* @param location The location to drop the items at
* @param itemStacks The items to drop
*/
public static void spawnItems(@Nullable Player player,
@NotNull Location location,
@NotNull Collection<ItemStack> itemStacks,
@NotNull ItemSpawnReason itemSpawnReason) {
for (ItemStack is : itemStacks) {
spawnItem(player, location, is, itemSpawnReason);
}
}
/**
* Drop items at a given location.
*

View File

@ -165,8 +165,6 @@ Alchemy.Listener=Alchemy:
Alchemy.Ability.Locked.0=LOCKED UNTIL {0}+ SKILL (CATALYSIS)
Alchemy.SkillName=ALCHEMY
#ARCHERY
Archery.SubSkill.SkillShot.Name=Skill Shot
Archery.SubSkill.SkillShot.Description=Increases damage done with bows
Archery.SubSkill.SkillShot.Stat=Skill Shot Bonus Damage