diff --git a/src/main/java/net/Indyuce/mmoitems/api/ElementalAttack.java b/src/main/java/net/Indyuce/mmoitems/api/ElementalAttack.java index 5376aa81..a85e7463 100644 --- a/src/main/java/net/Indyuce/mmoitems/api/ElementalAttack.java +++ b/src/main/java/net/Indyuce/mmoitems/api/ElementalAttack.java @@ -2,89 +2,118 @@ package net.Indyuce.mmoitems.api; import io.lumine.mythic.lib.MythicLib; import io.lumine.mythic.lib.api.item.NBTItem; -import io.lumine.mythic.lib.api.player.MMOPlayerData; import io.lumine.mythic.lib.player.PlayerMetadata; import net.Indyuce.mmoitems.api.player.PlayerData; import net.Indyuce.mmoitems.api.player.PlayerData.CooldownType; import org.bukkit.entity.LivingEntity; import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.Debug; -import java.nio.file.WatchKey; import java.util.HashMap; import java.util.Map; import java.util.Random; /** * @deprecated Move this over to MythicLib ffs - * Also implementation is bad af + * Also implementation is bad af */ @Deprecated public class ElementalAttack { - private final PlayerMetadata attacker; - private final PlayerData playerData; - private final Map relative = new HashMap<>(); - private final Map absolute = new HashMap<>(); - private final LivingEntity target; - private final double initialDamage; + private final PlayerMetadata attacker; + private final PlayerData playerData; - private static final Random random = new Random(); + /** + * Percentage of the initial damage being dealt as elemental damage + */ + private final Map relative = new HashMap<>(); - public ElementalAttack(PlayerMetadata attacker, NBTItem item, double initialDamage, LivingEntity target) { - this.initialDamage = initialDamage; - this.playerData = PlayerData.get(attacker.getPlayer()); - this.attacker = attacker; - this.target = target; + /** + * Flat damage being dealt as elemental damage + */ + private final Map absolute = new HashMap<>(); - for (Element element : Element.values()) { - double damage = item.getStat(element.name() + "_DAMAGE"); - if (damage > 0) { - relative.put(element, damage); - absolute.put(element, damage / 100 * initialDamage); - } - } - } + /** + * Attack target saved because MI needs to + * access the defense stats from that entity + */ + private final LivingEntity target; - public double getDamageModifier() { + /** + * Damage that is not elemental + */ + private final double regularDamage; - // Elemental defense - for (ItemStack equip : target.getEquipment().getArmorContents()) { - NBTItem nbtEquip = MythicLib.plugin.getVersion().getWrapper().getNBTItem(equip); - if (nbtEquip.getType() != null) - for (Element element : absolute.keySet()) { - double defense = nbtEquip.getStat(element.name() + "_DEFENSE") / 100; - if (defense > 0) { - relative.put(element, relative.get(element) * (1 - defense)); - absolute.put(element, absolute.get(element) * (1 - defense)); - } - } - } + /** + * Initial attack damage (both regular and elemental) + */ + private final double initialDamage; - // Elemental attacks - double p = 1; - if (!playerData.isOnCooldown(CooldownType.ELEMENTAL_ATTACK)) - for (Element element : relative.keySet()) { - double relativeDamage = relative.get(element); - if (random.nextDouble() < (relativeDamage / 100 / p)) { - playerData.applyCooldown(CooldownType.ELEMENTAL_ATTACK, 2); - element.getHandler().elementAttack(attacker, target, relativeDamage, absolute.get(element)); - absolute.put(element, absolute.get(element) * 2); - break; - } - p -= relativeDamage / 100; - } + private static final Random RANDOM = new Random(); - // Calculate final damage again - double finalDamage = 0; + public ElementalAttack(PlayerMetadata attacker, NBTItem item, double initialDamage, LivingEntity target) { + this.initialDamage = initialDamage; + this.playerData = PlayerData.get(attacker.getPlayer()); + this.attacker = attacker; + this.target = target; - for (Element element : absolute.keySet()) { - double partialDamage = absolute.get(element); - if (partialDamage > 0) { - finalDamage += partialDamage; - element.getParticle().displayParticle(target); - } - } + double regularDamage = initialDamage; + for (Element element : Element.values()) { + double relativeDamage = item.getStat(element.name() + "_DAMAGE"); + if (relativeDamage > 0) { + double flatElemental = relativeDamage / 100 * initialDamage; + relative.put(element, relativeDamage); + absolute.put(element, flatElemental); + regularDamage -= flatElemental; + } + } - return finalDamage - initialDamage; - } + this.regularDamage = regularDamage; + } + + public double getDamageModifier() { + + // Elemental defense + for (ItemStack equip : target.getEquipment().getArmorContents()) { + NBTItem nbtEquip = MythicLib.plugin.getVersion().getWrapper().getNBTItem(equip); + if (nbtEquip.getType() != null) + for (Element element : absolute.keySet()) { + double defense = nbtEquip.getStat(element.name() + "_DEFENSE") / 100; + if (defense > 0) { + relative.put(element, relative.get(element) * (1 - defense)); + absolute.put(element, absolute.get(element) * (1 - defense)); + } + } + } + + // Elemental attacks + double correctionCoeff = 1; + if (!playerData.isOnCooldown(CooldownType.ELEMENTAL_ATTACK)) + for (Element element : relative.keySet()) { + double relativeDamage = relative.get(element); + double independentProbability = relativeDamage / 100; + if (RANDOM.nextDouble() < independentProbability / correctionCoeff) { + + // Perform elemental critical strike + playerData.applyCooldown(CooldownType.ELEMENTAL_ATTACK, 2); + element.getHandler().elementAttack(attacker, target, relativeDamage, absolute.get(element)); + + // Multiply corresponding damage by 2 + absolute.put(element, absolute.get(element) * 2); + break; + } + correctionCoeff -= independentProbability; + } + + // Calculate final damage again + double finalDamage = regularDamage; + + for (Element element : absolute.keySet()) { + double partialDamage = absolute.get(element); + if (partialDamage > 0) { + finalDamage += partialDamage; + element.getParticle().displayParticle(target); + } + } + + return finalDamage - initialDamage; + } }