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 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 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) Added a setting in advanced.yml to ignore attack cooldowns (see notes)
Fixed a bug with Mace permissions (thanks SrBedrock) Fixed a bug with Mace permissions (thanks SrBedrock)

View File

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

View File

@ -75,7 +75,8 @@ public class Roll extends AcrobaticsSubSkill {
*/ */
if (canRoll(mmoPlayer)) { if (canRoll(mmoPlayer)) {
entityDamageEvent.setDamage(rollCheck(mmoPlayer, entityDamageEvent.getFinalDamage())); entityDamageEvent.setDamage(
rollCheck(mmoPlayer, entityDamageEvent.getFinalDamage(), mmoPlayer.getPlayer().isSneaking()));
if (entityDamageEvent.getFinalDamage() == 0) { if (entityDamageEvent.getFinalDamage() == 0) {
entityDamageEvent.setCancelled(true); entityDamageEvent.setCancelled(true);
@ -189,64 +190,24 @@ public class Roll extends AcrobaticsSubSkill {
&& Permissions.isSubSkillEnabled(mmoPlayer.getPlayer(), SubSkillType.ACROBATICS_ROLL); && 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) { private int getActivationChance(McMMOPlayer mmoPlayer) {
return PerksUtils.handleLuckyPerks(mmoPlayer, getPrimarySkill()); 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 * @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 * @return the modified event damage if the ability was successful, the original event damage otherwise
*/ */
private double gracefulRollCheck(McMMOPlayer mmoPlayer, double damage, int skillLevel) { private double rollCheck(McMMOPlayer mmoPlayer, double damage, boolean isGracefulRoll) {
double modifiedDamage = calculateModifiedRollDamage(damage, mcMMO.p.getAdvancedConfig().getRollDamageThreshold() * 2); final Probability probability
= isGracefulRoll ? getGracefulProbability(mmoPlayer) : getNonGracefulProbability(mmoPlayer);
final Probability gracefulProbability = getGracefulProbability(mmoPlayer); double modifiedDamage = calculateModifiedRollDamage(damage,
mcMMO.p.getAdvancedConfig().getRollDamageThreshold() * 2);
if (!isFatal(mmoPlayer, modifiedDamage) if (!isFatal(mmoPlayer, modifiedDamage)
//TODO: Graceful isn't sending out an event && ProbabilityUtil.isStaticSkillRNGSuccessful(PrimarySkillType.ACROBATICS, mmoPlayer, probability)) {
&& ProbabilityUtil.isStaticSkillRNGSuccessful(PrimarySkillType.ACROBATICS, mmoPlayer, gracefulProbability)) {
NotificationManager.sendPlayerInformation(mmoPlayer.getPlayer(), NotificationType.SUBSKILL_MESSAGE, "Acrobatics.Ability.Proc"); NotificationManager.sendPlayerInformation(mmoPlayer.getPlayer(), NotificationType.SUBSKILL_MESSAGE, "Acrobatics.Ability.Proc");
SoundManager.sendCategorizedSound(mmoPlayer.getPlayer(), mmoPlayer.getPlayer().getLocation(), SoundType.ROLL_ACTIVATED, SoundCategory.PLAYERS,0.5F); SoundManager.sendCategorizedSound(mmoPlayer.getPlayer(), mmoPlayer.getPlayer().getLocation(), SoundType.ROLL_ACTIVATED, SoundCategory.PLAYERS,0.5F);
if (!isExploiting(mmoPlayer) && mmoPlayer.getAcrobaticsManager().canGainRollXP()) if (!isExploiting(mmoPlayer) && mmoPlayer.getAcrobaticsManager().canGainRollXP())
@ -270,6 +231,11 @@ public class Roll extends AcrobaticsSubSkill {
return Probability.ofValue(gracefulOdds); 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 * Check if the player is "farming" Acrobatics XP using
* exploits in the game. * exploits in the game.

View File

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

View File

@ -10,58 +10,17 @@ import org.bukkit.entity.TNTPrimed;
import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.EntityDamageByEntityEvent;
public class BlastMining { 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 final static int MAXIMUM_REMOTE_DETONATION_DISTANCE = 100;
public static double getBlastRadiusModifier(int rank) { public static double getBlastRadiusModifier(int rank) {
return mcMMO.p.getAdvancedConfig().getBlastRadiusModifier(rank); return mcMMO.p.getAdvancedConfig().getBlastRadiusModifier(rank);
} }
public static double getBlastDamageDecrease(int rank) { public static double getBlastDamageDecrease(int rank) {
return mcMMO.p.getAdvancedConfig().getBlastDamageDecrease(rank); return mcMMO.p.getAdvancedConfig().getBlastDamageDecrease(rank);
} }
public static int getDemolitionExpertUnlockLevel() { 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++) { for(int i = 0; i < SubSkillType.MINING_BLAST_MINING.getNumRanks()-1; i++) {
if (getBlastDamageDecrease(i+1) > 0) if (getBlastDamageDecrease(i+1) > 0)
return RankUtils.getRankUnlockLevel(SubSkillType.MINING_BLAST_MINING, i+1); return RankUtils.getRankUnlockLevel(SubSkillType.MINING_BLAST_MINING, i+1);
@ -71,15 +30,6 @@ public class BlastMining {
} }
public static int getBiggerBombsUnlockLevel() { 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++) { for(int i = 0; i < SubSkillType.MINING_BLAST_MINING.getNumRanks()-1; i++) {
if (getBlastRadiusModifier(i+1) > 0) if (getBlastRadiusModifier(i+1) > 0)
return RankUtils.getRankUnlockLevel(SubSkillType.MINING_BLAST_MINING, i+1); return RankUtils.getRankUnlockLevel(SubSkillType.MINING_BLAST_MINING, i+1);
@ -104,7 +54,7 @@ public class BlastMining {
return false; return false;
} }
MiningManager miningManager = UserManager.getPlayer(defender).getMiningManager(); final MiningManager miningManager = UserManager.getPlayer(defender).getMiningManager();
if (!miningManager.canUseDemolitionsExpertise()) { if (!miningManager.canUseDemolitionsExpertise()) {
return false; 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.random.ProbabilityUtil;
import com.gmail.nossr50.util.skills.RankUtils; import com.gmail.nossr50.util.skills.RankUtils;
import com.gmail.nossr50.util.skills.SkillUtils; import com.gmail.nossr50.util.skills.SkillUtils;
import org.apache.commons.lang3.RandomUtils;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.BlockState; import org.bukkit.block.BlockState;
@ -30,8 +29,11 @@ import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.List; import java.util.List;
import static com.gmail.nossr50.util.ItemUtils.isPickaxe;
public class MiningManager extends SkillManager { public class MiningManager extends SkillManager {
public static final String BUDDING_AMETHYST = "budding_amethyst"; public static final String BUDDING_AMETHYST = "budding_amethyst";
@ -51,7 +53,7 @@ public class MiningManager extends SkillManager {
Player player = getPlayer(); Player player = getPlayer();
return canUseBlastMining() && player.isSneaking() 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); && Permissions.remoteDetonation(player);
} }
@ -168,69 +170,76 @@ public class MiningManager extends SkillManager {
* @param yield The % of blocks to drop * @param yield The % of blocks to drop
* @param event The {@link EntityExplodeEvent} * @param event The {@link EntityExplodeEvent}
*/ */
//TODO: Rewrite this garbage
public void blastMiningDropProcessing(float yield, EntityExplodeEvent event) { public void blastMiningDropProcessing(float yield, EntityExplodeEvent event) {
if (yield == 0) if (yield == 0)
return; 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> ores = new ArrayList<>();
List<BlockState> notOres = new ArrayList<>(); List<BlockState> notOres = new ArrayList<>();
for (Block targetBlock : event.blockList()) { for (Block targetBlock : event.blockList()) {
BlockState blockState = targetBlock.getState(); 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 if(mcMMO.getUserBlockTracker().isIneligible(targetBlock))
&& !(targetBlock instanceof Container) continue;
&& !mcMMO.getUserBlockTracker().isIneligible(targetBlock)) {
if (BlockUtils.isOre(blockState)) { if (ExperienceConfig.getInstance().getXp(PrimarySkillType.MINING, targetBlock) != 0) {
if (BlockUtils.isOre(blockState) && !(targetBlock instanceof Container)) {
ores.add(blockState); ores.add(blockState);
} else {
notOres.add(blockState);
} }
} else {
notOres.add(blockState);
} }
} }
int xp = 0; int xp = 0;
float oreBonus = (float) (getOreBonus() / 100);
float debrisReduction = (float) (getDebrisReduction() / 100);
int dropMultiplier = getDropMultiplier(); int dropMultiplier = getDropMultiplier();
float debrisYield = yield - debrisReduction;
//Drop "debris" based on skill modifiers
for(BlockState blockState : notOres) { for(BlockState blockState : notOres) {
if (isDropIllegal(blockState.getType())) if (isDropIllegal(blockState.getType()))
continue; continue;
if (Probability.ofPercent(50).evaluate()) { 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) { for (BlockState blockState : ores) {
if (isDropIllegal(blockState.getType())) // currentOreYield only used for drop calculations for ores
float currentOreYield = increasedYieldFromBonuses;
if (isDropIllegal(blockState.getType())) {
continue; continue;
}
if (RandomUtils.nextFloat() < (yield + oreBonus)) { // Always give XP for every ore destroyed
xp += Mining.getBlockXp(blockState); 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()) {
for (int i = 1; i < dropMultiplier; i++) {
if (mcMMO.p.getAdvancedConfig().isBlastMiningBonusDropsEnabled() && !mcMMO.getUserBlockTracker().isIneligible(blockState)) { ItemUtils.spawnItems(getPlayer(),
for (int i = 1; i < dropMultiplier; i++) { Misc.getBlockCenter(blockState),
// Bukkit.broadcastMessage("Bonus Drop on Ore: "+blockState.getType().toString()); oreDrops,
ItemUtils.spawnItem(getPlayer(), Misc.getBlockCenter(blockState), new ItemStack(blockState.getType()), ItemSpawnReason.BLAST_MINING_ORES_BONUS_DROP); // Initial block that would have been dropped 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.setYield(0F);
// event.blockList().clear();
// event.blockList().addAll(notOres);
applyXpGain(xp, XPGainReason.PVE); applyXpGain(xp, XPGainReason.PVE);
} }
@ -273,10 +282,11 @@ public class MiningManager extends SkillManager {
* *
* @return the Blast Mining tier * @return the Blast Mining tier
*/ */
public double getOreBonus() { public float getOreBonus() {
return getOreBonus(getBlastMiningTier()); return (float) (mcMMO.p.getAdvancedConfig().getOreBonus(getBlastMiningTier()) / 100F);
} }
@Deprecated(since = "2.2.017", forRemoval = true)
public static double getOreBonus(int rank) { public static double getOreBonus(int rank) {
return mcMMO.p.getAdvancedConfig().getOreBonus(rank); return mcMMO.p.getAdvancedConfig().getOreBonus(rank);
} }

View File

@ -681,6 +681,21 @@ public final class ItemUtils {
return enchantmentWrappers.get(randomIndex); 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. * 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.Ability.Locked.0=LOCKED UNTIL {0}+ SKILL (CATALYSIS)
Alchemy.SkillName=ALCHEMY Alchemy.SkillName=ALCHEMY
#ARCHERY #ARCHERY
Archery.SubSkill.SkillShot.Name=Skill Shot Archery.SubSkill.SkillShot.Name=Skill Shot
Archery.SubSkill.SkillShot.Description=Increases damage done with bows Archery.SubSkill.SkillShot.Description=Increases damage done with bows
Archery.SubSkill.SkillShot.Stat=Skill Shot Bonus Damage Archery.SubSkill.SkillShot.Stat=Skill Shot Bonus Damage