TF-ProjectKorra/src/com/projectkorra/projectkorra/avatar/AvatarState.java
Christopher Martin 787b303c9f
1.9.1 (#1145)
## Additions
* Adds a built-in bending board sidebar to visualize bound abilities and cooldowns.
  * The board respects worlds where bending is disabled.
  * Players can use the command `/pk board` to toggle the visibility of their board.
  * Includes an API that community developers can use in BendingBoardManager.
  * Adds the `"Properties.BendingBoard"` config option to enable or disable the board server.
  * Adds language file configuration options to control BendingBoard visuals.
    * `"Board.Title"`
      * Controls the title at the top of the board.
      * Supports the standard Minecraft color codes.
    * `"Board.SelectionPrefix"`
      * Controls the prefix shown corresponding to your current hot bar slot.
      * Supports the standard Minecraft color codes.
    * `"Board.EmptySlot"`
      * Controls what is shown for empty slots.
      * Supports the standard Minecraft color codes.
      * `{slot_number}` can be used as a placeholder for the slot number.
    * `"Board.MiscSeparator"`
      * Controls the separation between hot bar binds and temporary cooldowns such as Combos.
      * Supports the standard Minecraft color codes.
* Adds support for KingdomsX version 1.10.19.1
* Adds ability permission check to passive abilities. They should now respect their `bending.ability.<ability name>` permissions.
* Adds `AbilityVelocityAffectEntityEvent`
  * A cancellable event that will fire whenever an ability would alter the velocity of an entity.
* Adds the `Abilities.Earth.EarthSmash.Shoot.CollisionRadius` configuration option
  * Sets the collision radius of shot EarthSmash.

## Fixes
* Fixes FireBlast going through liquids.
* Fixes duplication involving waterlogged containers.
* Fixes being able to not enter the name of a Preset when using the `/pk preset create <name>` command.
* Fixes getDayFactor() not being applied correctly and occasionally producing the wrong value.
* Fixes a rounding issue with some Fire ability damage configuration options.
* Fixes an error when attempting to start EarthGrab.
* Fixes PhaseChange error when melting snow.
* Fixes a memory/process leak in how cooldowns were removed.
  * A player's cooldowns could only be removed when they were online. If a player's cooldown expired while they weren't online, their cooldown would attempt to revert every tick until the player rejoined. This has been resolved so cooldowns can revert while a player is offline.
  * A side effect of this fix is that it is now possible for `PlayerCooldownChangeEvents` to fire while their corresponding Player is offline.
* Fixes an issue with `MultiAbilityManager#hasMultiAbilityBound` where it would return true if any MultiAbility is bound, not if the specified MultiAbility was bound.

## Misc Changes
* Updates Towny version to 0.96.2.0
* DensityShift sand blocks can now be used as a bendable source.
* Changes AvatarState so that its cooldown is applied when the ability ends instead of when it starts.
* Changes togglable abilities such as AvatarState, Illumination, and TremorSense to visually show when they are enabled in the BendingBoard and on BendingPreview in the same way as the ChiBlocking Stances.
* Updated the text of some ability descriptions and instructions.
* Adds new cache to PhaseChange to greatly improve the performance of water/ice updates.
2021-06-07 16:58:29 -07:00

239 lines
6.4 KiB
Java

package com.projectkorra.projectkorra.avatar;
import java.util.HashMap;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import com.projectkorra.projectkorra.ability.AvatarAbility;
import com.projectkorra.projectkorra.attribute.Attribute;
public class AvatarState extends AvatarAbility {
private static final HashMap<String, Long> START_TIMES = new HashMap<>();
private boolean regenEnabled;
private boolean speedEnabled;
private boolean resistanceEnabled;
private boolean fireResistanceEnabled;
private int regenPower;
private int speedPower;
private int resistancePower;
private int fireResistancePower;
@Attribute(Attribute.DURATION)
private long duration;
@Attribute(Attribute.COOLDOWN)
private long cooldown;
private double factor;
public AvatarState(final Player player) {
super(player);
final AvatarState oldAbil = getAbility(player, AvatarState.class);
if (oldAbil != null) {
oldAbil.remove();
return;
} else if (this.bPlayer.isOnCooldown(this)) {
return;
}
this.regenEnabled = getConfig().getBoolean("Abilities.Avatar.AvatarState.PotionEffects.Regeneration.Enabled");
this.speedEnabled = getConfig().getBoolean("Abilities.Avatar.AvatarState.PotionEffects.Speed.Enabled");
this.resistanceEnabled = getConfig().getBoolean("Abilities.Avatar.AvatarState.PotionEffects.DamageResistance.Enabled");
this.fireResistanceEnabled = getConfig().getBoolean("Abilities.Avatar.AvatarState.PotionEffects.FireResistance.Enabled");
this.regenPower = getConfig().getInt("Abilities.Avatar.AvatarState.PotionEffects.Regeneration.Power") - 1;
this.speedPower = getConfig().getInt("Abilities.Avatar.AvatarState.PotionEffects.Speed.Power") - 1;
this.resistancePower = getConfig().getInt("Abilities.Avatar.AvatarState.PotionEffects.DamageResistance.Power") - 1;
this.fireResistancePower = getConfig().getInt("Abilities.Avatar.AvatarState.PotionEffects.FireResistance.Power") - 1;
this.duration = getConfig().getLong("Abilities.Avatar.AvatarState.Duration");
this.cooldown = getConfig().getLong("Abilities.Avatar.AvatarState.Cooldown");
this.factor = getConfig().getDouble("Abilities.Avatar.AvatarState.PowerMultiplier");
playAvatarSound(player.getLocation());
this.start();
if (this.duration != 0) {
START_TIMES.put(player.getName(), System.currentTimeMillis());
player.getUniqueId();
}
}
@Override
public void progress() {
if (!this.bPlayer.canBendIgnoreBindsCooldowns(this)) {
this.remove();
return;
}
if (START_TIMES.containsKey(this.player.getName())) {
if (START_TIMES.get(this.player.getName()) + this.duration < System.currentTimeMillis()) {
START_TIMES.remove(this.player.getName());
this.remove();
return;
}
}
this.addPotionEffects();
}
@Override
public void remove() {
this.bPlayer.addCooldown(this, true);
super.remove();
}
private void addPotionEffects() {
if (this.regenEnabled) {
this.addProgressPotionEffect(PotionEffectType.REGENERATION, this.regenPower);
}
if (this.speedEnabled) {
this.addProgressPotionEffect(PotionEffectType.SPEED, this.speedPower);
}
if (this.resistanceEnabled) {
this.addProgressPotionEffect(PotionEffectType.DAMAGE_RESISTANCE, this.resistancePower);
}
if (this.fireResistanceEnabled) {
this.addProgressPotionEffect(PotionEffectType.FIRE_RESISTANCE, this.fireResistancePower);
}
}
private void addProgressPotionEffect(final PotionEffectType effect, final int power) {
if (!this.player.hasPotionEffect(effect) || this.player.getPotionEffect(effect).getAmplifier() < power || (this.player.getPotionEffect(effect).getAmplifier() == power && this.player.getPotionEffect(effect).getDuration() == 1)) {
this.player.addPotionEffect(new PotionEffect(effect, 10, power, true, false), true);
}
}
public static double getValue(final double value) {
final double factor = getConfig().getDouble("Abilities.Avatar.AvatarState.PowerMultiplier");
return factor * value;
}
public static int getValue(final int value) {
return (int) getValue((double) value);
}
public static double getValue(final double value, final Player player) {
final AvatarState astate = getAbility(player, AvatarState.class);
if (astate != null) {
return astate.getFactor() * value;
}
return value;
}
@Override
public String getName() {
return "AvatarState";
}
@Override
public Location getLocation() {
return this.player != null ? this.player.getLocation() : null;
}
@Override
public long getCooldown() {
return this.cooldown;
}
@Override
public boolean isSneakAbility() {
return false;
}
@Override
public boolean isHarmlessAbility() {
return true;
}
public boolean isRegenEnabled() {
return this.regenEnabled;
}
public void setRegenEnabled(final boolean regenEnabled) {
this.regenEnabled = regenEnabled;
}
public boolean isSpeedEnabled() {
return this.speedEnabled;
}
public void setSpeedEnabled(final boolean speedEnabled) {
this.speedEnabled = speedEnabled;
}
public boolean isResistanceEnabled() {
return this.resistanceEnabled;
}
public void setResistanceEnabled(final boolean resistanceEnabled) {
this.resistanceEnabled = resistanceEnabled;
}
public boolean isFireResistanceEnabled() {
return this.fireResistanceEnabled;
}
public void setFireResistanceEnabled(final boolean fireResistanceEnabled) {
this.fireResistanceEnabled = fireResistanceEnabled;
}
public int getRegenPower() {
return this.regenPower;
}
public void setRegenPower(final int regenPower) {
this.regenPower = regenPower;
}
public int getSpeedPower() {
return this.speedPower;
}
public void setSpeedPower(final int speedPower) {
this.speedPower = speedPower;
}
public int getResistancePower() {
return this.resistancePower;
}
public void setResistancePower(final int resistancePower) {
this.resistancePower = resistancePower;
}
public int getFireResistancePower() {
return this.fireResistancePower;
}
public void setFireResistancePower(final int fireResistancePower) {
this.fireResistancePower = fireResistancePower;
}
public long getDuration() {
return this.duration;
}
public void setDuration(final long duration) {
this.duration = duration;
}
public double getFactor() {
return this.factor;
}
public void setFactor(final double factor) {
this.factor = factor;
}
public static HashMap<String, Long> getStartTimes() {
return START_TIMES;
}
public void setCooldown(final long cooldown) {
this.cooldown = cooldown;
}
}