mirror of
https://github.com/mcMMO-Dev/mcMMO.git
synced 2025-07-22 07:14:44 +02:00
182 lines
6.6 KiB
Java
182 lines
6.6 KiB
Java
package com.gmail.nossr50.skills.acrobatics;
|
|
|
|
import org.bukkit.Location;
|
|
import org.bukkit.Material;
|
|
import org.bukkit.enchantments.Enchantment;
|
|
import org.bukkit.entity.Entity;
|
|
import org.bukkit.entity.LightningStrike;
|
|
import org.bukkit.entity.Player;
|
|
import org.bukkit.inventory.ItemStack;
|
|
|
|
import com.gmail.nossr50.config.Config;
|
|
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
|
|
import com.gmail.nossr50.datatypes.skills.SecondaryAbility;
|
|
import com.gmail.nossr50.datatypes.skills.SkillType;
|
|
import com.gmail.nossr50.locale.LocaleLoader;
|
|
import com.gmail.nossr50.skills.SkillManager;
|
|
import com.gmail.nossr50.util.Misc;
|
|
import com.gmail.nossr50.util.Permissions;
|
|
import com.gmail.nossr50.util.skills.ParticleEffectUtils;
|
|
import com.gmail.nossr50.util.skills.SkillUtils;
|
|
|
|
public class AcrobaticsManager extends SkillManager {
|
|
private int fallTries = 0;
|
|
Location lastFallLocation;
|
|
|
|
public AcrobaticsManager(McMMOPlayer mcMMOPlayer) {
|
|
super(mcMMOPlayer, SkillType.ACROBATICS);
|
|
}
|
|
|
|
public boolean canRoll() {
|
|
return !exploitPrevention() && Permissions.secondaryAbilityEnabled(getPlayer(), SecondaryAbility.ROLL);
|
|
}
|
|
|
|
public boolean canDodge(Entity damager) {
|
|
if (Permissions.secondaryAbilityEnabled(getPlayer(), SecondaryAbility.DODGE)) {
|
|
if (damager instanceof LightningStrike && Acrobatics.dodgeLightningDisabled) {
|
|
return false;
|
|
}
|
|
|
|
return skill.shouldProcess(damager);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Handle the damage reduction and XP gain from the Dodge 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
|
|
*/
|
|
public double dodgeCheck(double damage) {
|
|
double modifiedDamage = Acrobatics.calculateModifiedDodgeDamage(damage, Acrobatics.dodgeDamageModifier);
|
|
Player player = getPlayer();
|
|
|
|
if (!isFatal(modifiedDamage) && SkillUtils.activationSuccessful(SecondaryAbility.DODGE, player, getSkillLevel(), activationChance)) {
|
|
ParticleEffectUtils.playDodgeEffect(player);
|
|
|
|
if (mcMMOPlayer.useChatNotifications()) {
|
|
player.sendMessage(LocaleLoader.getString("Acrobatics.Combat.Proc"));
|
|
}
|
|
|
|
// Why do we check respawn cooldown here?
|
|
if (SkillUtils.cooldownExpired(mcMMOPlayer.getRespawnATS(), Misc.PLAYER_RESPAWN_COOLDOWN_SECONDS)) {
|
|
applyXpGain((float) (damage * Acrobatics.dodgeXpModifier));
|
|
}
|
|
|
|
return modifiedDamage;
|
|
}
|
|
|
|
return damage;
|
|
}
|
|
|
|
/**
|
|
* 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
|
|
*/
|
|
public double rollCheck(double damage) {
|
|
Player player = getPlayer();
|
|
|
|
if (player.isSneaking() && Permissions.secondaryAbilityEnabled(player, SecondaryAbility.GRACEFUL_ROLL)) {
|
|
return gracefulRollCheck(damage);
|
|
}
|
|
|
|
double modifiedDamage = Acrobatics.calculateModifiedRollDamage(damage, Acrobatics.rollThreshold);
|
|
|
|
if (!isFatal(modifiedDamage) && SkillUtils.activationSuccessful(SecondaryAbility.ROLL, player, getSkillLevel(), activationChance)) {
|
|
player.sendMessage(LocaleLoader.getString("Acrobatics.Roll.Text"));
|
|
applyXpGain(calculateRollXP(damage, true));
|
|
|
|
return modifiedDamage;
|
|
}
|
|
else if (!isFatal(damage)) {
|
|
applyXpGain(calculateRollXP(damage, false));
|
|
}
|
|
|
|
lastFallLocation = player.getLocation();
|
|
|
|
return damage;
|
|
}
|
|
|
|
/**
|
|
* Handle the damage reduction and XP gain from the 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(double damage) {
|
|
double modifiedDamage = Acrobatics.calculateModifiedRollDamage(damage, Acrobatics.gracefulRollThreshold);
|
|
|
|
if (!isFatal(modifiedDamage) && SkillUtils.activationSuccessful(SecondaryAbility.GRACEFUL_ROLL, getPlayer(), getSkillLevel(), activationChance)) {
|
|
getPlayer().sendMessage(LocaleLoader.getString("Acrobatics.Ability.Proc"));
|
|
applyXpGain(calculateRollXP(damage, true));
|
|
|
|
return modifiedDamage;
|
|
}
|
|
else if (!isFatal(damage)) {
|
|
applyXpGain(calculateRollXP(damage, false));
|
|
}
|
|
|
|
return damage;
|
|
}
|
|
|
|
/**
|
|
* Check if the player is "farming" Acrobatics XP using
|
|
* exploits in the game.
|
|
*
|
|
* @return true if exploits are detected, false otherwise
|
|
*/
|
|
public boolean exploitPrevention() {
|
|
if (!Config.getInstance().getAcrobaticsPreventAFK()) {
|
|
return false;
|
|
}
|
|
|
|
Player player = getPlayer();
|
|
|
|
if (player.getItemInHand().getType() == Material.ENDER_PEARL || player.isInsideVehicle()) {
|
|
return true;
|
|
}
|
|
|
|
Location fallLocation = player.getLocation();
|
|
|
|
boolean sameLocation = (lastFallLocation != null && Misc.isNear(lastFallLocation, fallLocation, 2));
|
|
|
|
fallTries = sameLocation ? fallTries + 1 : Math.max(fallTries - 1, 0);
|
|
lastFallLocation = fallLocation;
|
|
|
|
return fallTries > Config.getInstance().getAcrobaticsAFKMaxTries();
|
|
}
|
|
|
|
private boolean isFatal(double damage) {
|
|
int discount=1;
|
|
// If the player has resistance active, carry resistance checking
|
|
if(getPlayer().hasPotionEffect(PotionEffectType.DAMAGE_RESISTANCE)){
|
|
Iterator potions=getPlayer().getActivePotionEffects().iterator();
|
|
while(potions.hasNext()){
|
|
PotionEffect potion=(PotionEffect)potions.next();
|
|
if(potion.getType()==PotionEffectType.DAMAGE_RESISANCE)
|
|
{//Having resistance allows you to recieve less damage
|
|
int coupon=potion.getAmplifier();
|
|
discount=Math.min(0,1-(coupon*0.2));
|
|
continue;
|
|
}
|
|
}
|
|
}//...Which is accounted here
|
|
return getPlayer().getHealth() - damage*discount <= 0;
|
|
}
|
|
|
|
private float calculateRollXP(double damage, boolean isRoll) {
|
|
ItemStack boots = getPlayer().getInventory().getBoots();
|
|
float xp = (float) (damage * (isRoll ? Acrobatics.rollXpModifier : Acrobatics.fallXpModifier));
|
|
|
|
if (boots != null && boots.containsEnchantment(Enchantment.PROTECTION_FALL)) {
|
|
xp *= Acrobatics.featherFallXPModifier;
|
|
}
|
|
|
|
return xp;
|
|
}
|
|
}
|