mirror of
https://gitlab.com/phoenix-dvpmt/mmoitems.git
synced 2025-03-09 12:49:06 +01:00
fixed things
This commit is contained in:
parent
f5ea91fd44
commit
7082cae74d
4
pom.xml
4
pom.xml
@ -4,7 +4,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>net.Indyuce</groupId>
|
||||
<artifactId>MMOItems</artifactId>
|
||||
<version>6.6.0</version>
|
||||
<version>6.6.1</version>
|
||||
<name>MMOItems</name>
|
||||
<description>A great item solution for your RPG server!!</description>
|
||||
|
||||
@ -139,7 +139,7 @@
|
||||
<dependency>
|
||||
<groupId>io.lumine</groupId>
|
||||
<artifactId>MythicLib</artifactId>
|
||||
<version>1.1.2</version>
|
||||
<version>1.1.3</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
@ -4,9 +4,11 @@ import com.evill4mer.RealDualWield.Api.PlayerDamageEntityWithOffhandEvent;
|
||||
import io.lumine.mythic.lib.MythicLib;
|
||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||
import io.lumine.mythic.lib.api.player.EquipmentSlot;
|
||||
import io.lumine.mythic.lib.api.stat.StatMap;
|
||||
import io.lumine.mythic.lib.damage.DamageMetadata;
|
||||
import io.lumine.mythic.lib.damage.DamageType;
|
||||
import net.Indyuce.mmoitems.api.ItemAttackMetadata;
|
||||
import net.Indyuce.mmoitems.api.Type;
|
||||
import net.Indyuce.mmoitems.api.TypeSet;
|
||||
import net.Indyuce.mmoitems.api.interaction.weapon.Weapon;
|
||||
import net.Indyuce.mmoitems.api.player.PlayerData;
|
||||
@ -17,43 +19,58 @@ import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
public class RealDualWieldHook implements Listener {
|
||||
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||
public void a(PlayerDamageEntityWithOffhandEvent event) {
|
||||
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||
public void a(PlayerDamageEntityWithOffhandEvent event) {
|
||||
|
||||
// Citizens NPC support; also check if it's not a useless event
|
||||
if (event.getDamage() == 0 || !(event.getEntity() instanceof LivingEntity) || event.getEntity().hasMetadata("NPC"))
|
||||
return;
|
||||
/*
|
||||
* Citizens and Sentinels NPC support; damage = 0 check to ignore safety
|
||||
* checks; check for entity attack
|
||||
*/
|
||||
if (event.getDamage() == 0 || !(event.getEntity() instanceof LivingEntity) || event.getEntity().hasMetadata("NPC") || event.getPlayer().hasMetadata("NPC"))
|
||||
return;
|
||||
|
||||
// Custom damage check
|
||||
LivingEntity target = (LivingEntity) event.getEntity();
|
||||
if (MythicLib.plugin.getDamage().findInfo(target) != null)
|
||||
return;
|
||||
// Custom damage check
|
||||
LivingEntity target = (LivingEntity) event.getEntity();
|
||||
if (MythicLib.plugin.getDamage().findInfo(target) != null)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Must apply attack conditions before apply any effects.
|
||||
* The event must be cancelled before anything is applied
|
||||
*/
|
||||
Player player = event.getPlayer();
|
||||
PlayerData playerData = PlayerData.get(player);
|
||||
NBTItem offhandItem = MythicLib.plugin.getVersion().getWrapper().getNBTItem(player.getInventory().getItemInOffHand());
|
||||
/*
|
||||
* Must apply attack conditions before apply any effects. the event must
|
||||
* be cancelled before anything is applied
|
||||
*/
|
||||
Player player = event.getPlayer();
|
||||
PlayerData playerData = PlayerData.get(player);
|
||||
NBTItem item = MythicLib.plugin.getVersion().getWrapper().getNBTItem(player.getInventory().getItemInMainHand());
|
||||
ItemAttackMetadata attackMeta = null;
|
||||
|
||||
if (offhandItem.hasType()) {
|
||||
Weapon weapon = new Weapon(playerData, offhandItem);
|
||||
if (item.hasType() && Type.get(item.getType()) != Type.BLOCK) {
|
||||
Weapon weapon = new Weapon(playerData, item);
|
||||
|
||||
if (weapon.getMMOItem().getType().getItemSet() == TypeSet.RANGE) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
if (weapon.getMMOItem().getType().getItemSet() == TypeSet.RANGE) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!weapon.checkItemRequirements()) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!weapon.checkItemRequirements()) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Cast on-hit abilities and add extra damage to the Bukkit event
|
||||
ItemAttackMetadata attack = new ItemAttackMetadata(new DamageMetadata(event.getDamage(), DamageType.WEAPON, DamageType.PHYSICAL), playerData.getMMOPlayerData().getStatMap().cache(EquipmentSlot.OFF_HAND));
|
||||
attack.applyEffects(offhandItem, target);
|
||||
event.setDamage(attack.getDamage().getDamage());
|
||||
}
|
||||
if (!weapon.handleTargetedAttack(attackMeta = getAttack(playerData, event), target).isSuccessful()) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Cast on-hit abilities and add the extra damage to the damage event
|
||||
(attackMeta == null ? attackMeta = getAttack(playerData, event) : attackMeta).applyEffects(item, target);
|
||||
|
||||
// Finally update Bukkit event
|
||||
event.setDamage(attackMeta.getDamage().getDamage());
|
||||
}
|
||||
|
||||
private ItemAttackMetadata getAttack(PlayerData playerData, PlayerDamageEntityWithOffhandEvent event) {
|
||||
StatMap.CachedStatMap cachedStatMap = playerData.getMMOPlayerData().getStatMap().cache(EquipmentSlot.OFF_HAND);
|
||||
return new ItemAttackMetadata(new DamageMetadata(event.getDamage(), DamageType.WEAPON, DamageType.PHYSICAL), cachedStatMap);
|
||||
}
|
||||
}
|
||||
|
@ -1,126 +0,0 @@
|
||||
package net.Indyuce.mmoitems.comp.mythicmobs;
|
||||
|
||||
import io.lumine.xikage.mythicmobs.MythicMobs;
|
||||
import io.lumine.xikage.mythicmobs.adapters.bukkit.BukkitItemStack;
|
||||
import io.lumine.xikage.mythicmobs.api.bukkit.events.MythicDropLoadEvent;
|
||||
import io.lumine.xikage.mythicmobs.drops.Drop;
|
||||
import io.lumine.xikage.mythicmobs.drops.DropMetadata;
|
||||
import io.lumine.xikage.mythicmobs.drops.IMultiDrop;
|
||||
import io.lumine.xikage.mythicmobs.drops.LootBag;
|
||||
import io.lumine.xikage.mythicmobs.drops.droppables.ItemDrop;
|
||||
import io.lumine.xikage.mythicmobs.io.MythicLineConfig;
|
||||
import io.lumine.xikage.mythicmobs.skills.SkillMetadata;
|
||||
import io.lumine.xikage.mythicmobs.skills.placeholders.Placeholder;
|
||||
import net.Indyuce.mmoitems.MMOItems;
|
||||
import net.Indyuce.mmoitems.api.Type;
|
||||
import net.Indyuce.mmoitems.api.droptable.item.DropItem;
|
||||
import net.Indyuce.mmoitems.api.droptable.item.MMOItemDropItem;
|
||||
import net.Indyuce.mmoitems.api.player.PlayerData;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class MythicMobsHook implements Listener {
|
||||
|
||||
/*
|
||||
* has been moved over to MythicMobs because MMOItems needs access to MythicMobs
|
||||
* abilities and therefore must be enabled after MythicMobs
|
||||
*/
|
||||
|
||||
/*
|
||||
* MUST NOT BE REMOVED - this class must be kept ad vitam aeternam in case we
|
||||
* need to change something in MM compatibility and sent it back to MM devs
|
||||
*/
|
||||
public MythicMobsHook() {
|
||||
/*MythicMobs.inst().getPlaceholderManager().register("mmoitems.skill",
|
||||
Placeholder.meta((metadata, arg) -> String.valueOf(PlayerData
|
||||
.get(metadata.getCaster().getEntity().getUniqueId()).getAbilityData().getCachedModifier(arg))));*/
|
||||
Bukkit.getPluginManager().registerEvents(this, MMOItems.plugin);
|
||||
// MMOItems.plugin.getCrafting().registerIngredient("mythicitem", config -> new MythicItemIngredient(config),
|
||||
// new ConditionalDisplay("&8" + AltChar.check + " &7#amount# #item#", "&c" + AltChar.cross + " &7#amount# #item#"),
|
||||
// nbt -> nbt.hasTag("MYTHIC_TYPE"), nbt -> nbt.getString("MYTHIC_TYPE").toLowerCase());
|
||||
}
|
||||
|
||||
/*
|
||||
* registers custom drop types
|
||||
*/
|
||||
@EventHandler
|
||||
public void a(MythicDropLoadEvent event) {
|
||||
if (event.getDropName().equalsIgnoreCase("mmoitems") || event.getDropName().equalsIgnoreCase("mmoitem"))
|
||||
event.register(new MMOItemsDrop(event.getConfig()));
|
||||
}
|
||||
|
||||
/*
|
||||
* register placeholders when MM is reloaded. the skill placeholder let players
|
||||
* retrieve cached ability values.
|
||||
*/
|
||||
/*@EventHandler
|
||||
public void b(MythicReloadedEvent event) {
|
||||
MythicMobs.inst().getPlaceholderManager().register("mmoitems.skill",
|
||||
Placeholder.meta((metadata, arg) -> String.valueOf(PlayerData
|
||||
.get(metadata.getCaster().getEntity().getUniqueId()).getAbilityData().getCachedModifier(arg))));
|
||||
}*/
|
||||
|
||||
private void registerSkillPlaceholders() {
|
||||
/*
|
||||
Placeholder.meta((meta, arg) -> {
|
||||
|
||||
SkillMetadata skillMeta = (SkillMetadata) meta;
|
||||
skillMeta.getVariables().get("MMOStats");
|
||||
|
||||
|
||||
return null;
|
||||
|
||||
} );
|
||||
|
||||
MythicMobs.inst().getPlaceholderManager().register("modifier",
|
||||
Placeholder.meta((metadata, arg) -> String.valueOf(PlayerData
|
||||
.get(metadata.getCaster().getEntity().getUniqueId()).getAbilityData().getCachedModifier(arg))));*/
|
||||
|
||||
}
|
||||
|
||||
public static class MMOItemsDrop extends Drop implements IMultiDrop {
|
||||
private DropItem dropItem;
|
||||
|
||||
public MMOItemsDrop(MythicLineConfig config) {
|
||||
super(config.getLine(), config);
|
||||
|
||||
/*
|
||||
* TODO move try-catch to the MythicDropLoadEvent method and make the dropItem
|
||||
* field final
|
||||
*/
|
||||
try {
|
||||
String typeFormat = config.getString("type").toUpperCase().replace("-", "_");
|
||||
Validate.isTrue(MMOItems.plugin.getTypes().has(typeFormat),
|
||||
"Could not find type with ID " + typeFormat);
|
||||
|
||||
Type type = MMOItems.plugin.getTypes().get(typeFormat);
|
||||
String id = config.getString("id");
|
||||
|
||||
Validate.notNull(id, "MMOItems ID cannot be null");
|
||||
|
||||
dropItem = new MMOItemDropItem(type, id, 1, config.getDouble("unidentified", 0), 1, 1);
|
||||
|
||||
} catch (IllegalArgumentException exception) {
|
||||
MMOItems.plugin.getLogger().log(Level.WARNING, "Could not load drop item: " + exception.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO remove null check with extra method from MythicDropLoadEvent
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public LootBag get(DropMetadata metadata) {
|
||||
LootBag loot = new LootBag(metadata);
|
||||
if (dropItem != null)
|
||||
// TODO fix null
|
||||
loot.add(new ItemDrop(this.getLine(), (MythicLineConfig) this.getConfig(),
|
||||
new BukkitItemStack(dropItem.getItem(null, 1))));
|
||||
return loot;
|
||||
}
|
||||
}
|
||||
}
|
@ -10,10 +10,6 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/*
|
||||
* this loads mmoitems comp for mythic mobs
|
||||
* since MythicMobsHook is purely for documentation
|
||||
*/
|
||||
public class MythicMobsLoader {
|
||||
|
||||
public MythicMobsLoader() {
|
||||
|
@ -20,57 +20,58 @@ import java.util.HashSet;
|
||||
import java.util.Optional;
|
||||
|
||||
public class MythicMobsAbility extends Ability<MythicMobsAbilityMetadata> {
|
||||
private final Skill skill;
|
||||
private final Skill skill;
|
||||
|
||||
public MythicMobsAbility(String id, FileConfiguration config) {
|
||||
super(id, config.getString("name"), CastingMode.ON_HIT, CastingMode.WHEN_HIT, CastingMode.LEFT_CLICK, CastingMode.RIGHT_CLICK, CastingMode.SHIFT_LEFT_CLICK, CastingMode.SHIFT_RIGHT_CLICK);
|
||||
public MythicMobsAbility(String id, FileConfiguration config) {
|
||||
super(id, config.getString("name"), CastingMode.ON_HIT, CastingMode.WHEN_HIT, CastingMode.LEFT_CLICK, CastingMode.RIGHT_CLICK, CastingMode.SHIFT_LEFT_CLICK, CastingMode.SHIFT_RIGHT_CLICK);
|
||||
|
||||
String skillName = config.getString("mythicmobs-skill-id");
|
||||
Validate.notNull(skillName, "Could not find MM skill name");
|
||||
String skillName = config.getString("mythicmobs-skill-id");
|
||||
Validate.notNull(skillName, "Could not find MM skill name");
|
||||
|
||||
Optional<io.lumine.xikage.mythicmobs.skills.Skill> opt = MythicMobs.inst().getSkillManager().getSkill(skillName);
|
||||
Validate.isTrue(opt.isPresent(), "Could not find MM skill " + skillName);
|
||||
skill = opt.get();
|
||||
Optional<io.lumine.xikage.mythicmobs.skills.Skill> opt = MythicMobs.inst().getSkillManager().getSkill(skillName);
|
||||
Validate.isTrue(opt.isPresent(), "Could not find MM skill " + skillName);
|
||||
skill = opt.get();
|
||||
|
||||
addModifier("cooldown", 10);
|
||||
addModifier("mana", 0);
|
||||
addModifier("stamina", 0);
|
||||
addModifier("cooldown", 10);
|
||||
addModifier("mana", 0);
|
||||
addModifier("stamina", 0);
|
||||
|
||||
for (String mod : config.getKeys(false))
|
||||
if (!mod.equals("name") && !mod.equals("mythicmobs-skill-id") && !mod.equals("self-only"))
|
||||
addModifier(mod.toLowerCase().replace("_", "-").replace(" ", "-"), config.getInt(mod));
|
||||
}
|
||||
for (String mod : config.getKeys(false))
|
||||
if (!mod.equals("name") && !mod.equals("mythicmobs-skill-id") && !mod.equals("self-only"))
|
||||
addModifier(mod.toLowerCase().replace("_", "-").replace(" ", "-"), config.getInt(mod));
|
||||
}
|
||||
|
||||
public String getInternalName() {
|
||||
return skill.getInternalName();
|
||||
}
|
||||
public String getInternalName() {
|
||||
return skill.getInternalName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void whenCast(ItemAttackMetadata attackMeta, MythicMobsAbilityMetadata ability) {
|
||||
LivingEntity target = ability.getTarget();
|
||||
@Override
|
||||
public void whenCast(ItemAttackMetadata attackMeta, MythicMobsAbilityMetadata ability) {
|
||||
LivingEntity target = ability.getTarget();
|
||||
|
||||
// TODO what's the difference between trigger and caster.
|
||||
AbstractEntity trigger = BukkitAdapter.adapt(attackMeta.getDamager());
|
||||
SkillCaster caster = new GenericCaster(trigger);
|
||||
// TODO what's the difference between trigger and caster.
|
||||
AbstractEntity trigger = BukkitAdapter.adapt(attackMeta.getDamager());
|
||||
SkillCaster caster = new GenericCaster(trigger);
|
||||
|
||||
HashSet<AbstractEntity> targetEntities = new HashSet<>();
|
||||
HashSet<AbstractLocation> targetLocations = new HashSet<>();
|
||||
HashSet<AbstractEntity> targetEntities = new HashSet<>();
|
||||
HashSet<AbstractLocation> targetLocations = new HashSet<>();
|
||||
|
||||
targetEntities.add(BukkitAdapter.adapt(target));
|
||||
targetEntities.add(BukkitAdapter.adapt(target));
|
||||
|
||||
SkillMetadata data = new SkillMetadata(SkillTrigger.API, caster, trigger, BukkitAdapter.adapt(attackMeta.getDamager().getEyeLocation()), targetEntities, targetLocations, 1);
|
||||
SkillMetadata data = new SkillMetadata(SkillTrigger.CAST, caster, trigger, BukkitAdapter.adapt(attackMeta.getDamager().getEyeLocation()), targetEntities, targetLocations, 1);
|
||||
|
||||
// Stats are cached inside a variable.
|
||||
/*data.getVariables().putObject();*/
|
||||
// Stats are cached inside a variable
|
||||
data.getVariables().putObject("MMOStatMap", attackMeta.getStats());
|
||||
data.getVariables().putObject("MMOSkill", ability.getAbility());
|
||||
|
||||
if (skill.usable(data, SkillTrigger.API))
|
||||
skill.execute(data);
|
||||
else
|
||||
attackMeta.setSuccessful(false);
|
||||
}
|
||||
if (skill.usable(data, SkillTrigger.CAST))
|
||||
skill.execute(data);
|
||||
else
|
||||
attackMeta.setSuccessful(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MythicMobsAbilityMetadata canBeCast(ItemAttackMetadata attackMeta, LivingEntity target, AbilityData data) {
|
||||
return new MythicMobsAbilityMetadata(data, target);
|
||||
}
|
||||
@Override
|
||||
public MythicMobsAbilityMetadata canBeCast(ItemAttackMetadata attackMeta, LivingEntity target, AbilityData data) {
|
||||
return new MythicMobsAbilityMetadata(data, target);
|
||||
}
|
||||
}
|
||||
|
@ -44,305 +44,307 @@ import org.bukkit.inventory.ItemStack;
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
public class ItemUse implements Listener {
|
||||
private static final DecimalFormat DIGIT = new DecimalFormat("0.#");
|
||||
private static final DecimalFormat DIGIT = new DecimalFormat("0.#");
|
||||
|
||||
@EventHandler
|
||||
public void rightClickEffects(PlayerInteractEvent event) {
|
||||
if (!event.hasItem())
|
||||
// || event.getHand() != EquipmentSlot.HAND
|
||||
return;
|
||||
@EventHandler
|
||||
public void rightClickEffects(PlayerInteractEvent event) {
|
||||
if (!event.hasItem())
|
||||
// || event.getHand() != EquipmentSlot.HAND
|
||||
return;
|
||||
|
||||
NBTItem item = MythicLib.plugin.getVersion().getWrapper().getNBTItem(event.getItem());
|
||||
if (!item.hasType())
|
||||
return;
|
||||
NBTItem item = MythicLib.plugin.getVersion().getWrapper().getNBTItem(event.getItem());
|
||||
if (!item.hasType())
|
||||
return;
|
||||
|
||||
/**
|
||||
* Some consumables must be fully eaten through the vanilla eating
|
||||
* animation and are handled there {@link #handleVanillaEatenConsumables(PlayerItemConsumeEvent)}
|
||||
*/
|
||||
Player player = event.getPlayer();
|
||||
UseItem useItem = UseItem.getItem(player, item, item.getType());
|
||||
if (useItem instanceof Consumable && ((Consumable) useItem).hasVanillaEating())
|
||||
return;
|
||||
/**
|
||||
* Some consumables must be fully eaten through the vanilla eating
|
||||
* animation and are handled there {@link #handleVanillaEatenConsumables(PlayerItemConsumeEvent)}
|
||||
*/
|
||||
Player player = event.getPlayer();
|
||||
UseItem useItem = UseItem.getItem(player, item, item.getType());
|
||||
if (useItem instanceof Consumable && ((Consumable) useItem).hasVanillaEating())
|
||||
return;
|
||||
|
||||
// (BUG FIX) Cancel the event to prevent things like shield blocking
|
||||
if (!useItem.checkItemRequirements()) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
// (BUG FIX) Cancel the event to prevent things like shield blocking
|
||||
if (!useItem.checkItemRequirements()) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Commands & consummables
|
||||
if (event.getAction().name().contains("RIGHT_CLICK")) {
|
||||
if (!useItem.getPlayerData().isOnCooldown(useItem.getMMOItem().getId())) {
|
||||
Message.ITEM_ON_COOLDOWN
|
||||
.format(ChatColor.RED, "#left#", DIGIT.format(useItem.getPlayerData().getItemCooldown(useItem.getMMOItem().getId())))
|
||||
.send(player);
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
// Commands & consummables
|
||||
if (event.getAction().name().contains("RIGHT_CLICK")) {
|
||||
if (!useItem.getPlayerData().isOnCooldown(useItem.getMMOItem().getId())) {
|
||||
Message.ITEM_ON_COOLDOWN
|
||||
.format(ChatColor.RED, "#left#", DIGIT.format(useItem.getPlayerData().getItemCooldown(useItem.getMMOItem().getId())))
|
||||
.send(player);
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (useItem instanceof Consumable) {
|
||||
event.setCancelled(true);
|
||||
Consumable.ConsumableConsumeResult result = ((Consumable) useItem).useOnPlayer();
|
||||
if (result == Consumable.ConsumableConsumeResult.CANCEL)
|
||||
return;
|
||||
if (useItem instanceof Consumable) {
|
||||
event.setCancelled(true);
|
||||
Consumable.ConsumableConsumeResult result = ((Consumable) useItem).useOnPlayer();
|
||||
if (result == Consumable.ConsumableConsumeResult.CANCEL)
|
||||
return;
|
||||
|
||||
else if (result == Consumable.ConsumableConsumeResult.CONSUME)
|
||||
event.getItem().setAmount(event.getItem().getAmount() - 1);
|
||||
}
|
||||
else if (result == Consumable.ConsumableConsumeResult.CONSUME)
|
||||
event.getItem().setAmount(event.getItem().getAmount() - 1);
|
||||
}
|
||||
|
||||
useItem.getPlayerData().applyItemCooldown(useItem.getMMOItem().getId(), useItem.getNBTItem().getStat("ITEM_COOLDOWN"));
|
||||
useItem.executeCommands();
|
||||
}
|
||||
useItem.getPlayerData().applyItemCooldown(useItem.getMMOItem().getId(), useItem.getNBTItem().getStat("ITEM_COOLDOWN"));
|
||||
useItem.executeCommands();
|
||||
}
|
||||
|
||||
if (useItem instanceof UntargetedWeapon) {
|
||||
UntargetedWeapon weapon = (UntargetedWeapon) useItem;
|
||||
if ((event.getAction().name().contains("RIGHT_CLICK") && weapon.getWeaponType() == WeaponType.RIGHT_CLICK)
|
||||
|| (event.getAction().name().contains("LEFT_CLICK") && weapon.getWeaponType() == WeaponType.LEFT_CLICK))
|
||||
weapon.untargetedAttack(event.getHand());
|
||||
}
|
||||
}
|
||||
if (useItem instanceof UntargetedWeapon) {
|
||||
UntargetedWeapon weapon = (UntargetedWeapon) useItem;
|
||||
if ((event.getAction().name().contains("RIGHT_CLICK") && weapon.getWeaponType() == WeaponType.RIGHT_CLICK)
|
||||
|| (event.getAction().name().contains("LEFT_CLICK") && weapon.getWeaponType() == WeaponType.LEFT_CLICK))
|
||||
weapon.untargetedAttack(event.getHand());
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||
public void meleeAttacks(EntityDamageByEntityEvent event) {
|
||||
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||
public void meleeAttacks(EntityDamageByEntityEvent event) {
|
||||
|
||||
/*
|
||||
* Citizens and Sentinels NPC support; damage = 0 check to ignore safety
|
||||
* checks; check for entity attack
|
||||
*/
|
||||
if (event.getDamage() == 0 || event.getCause() != DamageCause.ENTITY_ATTACK || !(event.getEntity() instanceof LivingEntity)
|
||||
|| !(event.getDamager() instanceof Player) || event.getEntity().hasMetadata("NPC") || event.getDamager().hasMetadata("NPC"))
|
||||
return;
|
||||
/*
|
||||
* Citizens and Sentinels NPC support; damage = 0 check to ignore safety
|
||||
* checks; check for entity attack
|
||||
*/
|
||||
if (event.getDamage() == 0 || event.getCause() != DamageCause.ENTITY_ATTACK || !(event.getEntity() instanceof LivingEntity)
|
||||
|| !(event.getDamager() instanceof Player) || event.getEntity().hasMetadata("NPC") || event.getDamager().hasMetadata("NPC"))
|
||||
return;
|
||||
|
||||
// Custom damage check
|
||||
LivingEntity target = (LivingEntity) event.getEntity();
|
||||
if (MythicLib.plugin.getDamage().findInfo(target) != null)
|
||||
return;
|
||||
// Custom damage check
|
||||
LivingEntity target = (LivingEntity) event.getEntity();
|
||||
if (MythicLib.plugin.getDamage().findInfo(target) != null)
|
||||
return;
|
||||
|
||||
Player player = (Player) event.getDamager();
|
||||
/*
|
||||
* Must apply attack conditions before apply any effects. the event must
|
||||
* be cancelled before anything is applied
|
||||
*/
|
||||
Player player = (Player) event.getDamager();
|
||||
PlayerData playerData = PlayerData.get(player);
|
||||
NBTItem item = MythicLib.plugin.getVersion().getWrapper().getNBTItem(player.getInventory().getItemInMainHand());
|
||||
ItemAttackMetadata attackMeta = null;
|
||||
|
||||
/*
|
||||
* Must apply attack conditions before apply any effects. the event must
|
||||
* be cancelled before anything is applied
|
||||
*/
|
||||
PlayerData playerData = PlayerData.get(player);
|
||||
NBTItem item = MythicLib.plugin.getVersion().getWrapper().getNBTItem(player.getInventory().getItemInMainHand());
|
||||
ItemAttackMetadata attackMeta = null;
|
||||
if (item.hasType() && Type.get(item.getType()) != Type.BLOCK) {
|
||||
Weapon weapon = new Weapon(playerData, item);
|
||||
|
||||
if (item.hasType() && Type.get(item.getType()) != Type.BLOCK) {
|
||||
Weapon weapon = new Weapon(playerData, item);
|
||||
if (weapon.getMMOItem().getType().getItemSet() == TypeSet.RANGE) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (weapon.getMMOItem().getType().getItemSet() == TypeSet.RANGE) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
if (!weapon.checkItemRequirements()) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!weapon.checkItemRequirements()) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
if (!weapon.handleTargetedAttack(attackMeta = getAttack(playerData, event), target).isSuccessful()) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
StatMap.CachedStatMap cachedStatMap = playerData.getMMOPlayerData().getStatMap().cache(EquipmentSlot.MAIN_HAND);
|
||||
attackMeta = new ItemAttackMetadata(new DamageMetadata(event.getDamage(), DamageType.WEAPON, DamageType.PHYSICAL), cachedStatMap);
|
||||
if (!weapon.handleTargetedAttack(attackMeta, target).isSuccessful()) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Cast on-hit abilities and add the extra damage to the damage event
|
||||
(attackMeta == null ? attackMeta = getAttack(playerData, event) : attackMeta).applyEffects(item, target);
|
||||
|
||||
// Cast on-hit abilities and add the extra damage to the damage event
|
||||
attackMeta.applyEffects(item, target);
|
||||
// Finally update Bukkit event
|
||||
event.setDamage(attackMeta.getDamage().getDamage());
|
||||
}
|
||||
|
||||
// Finally update Bukkit event
|
||||
event.setDamage(attackMeta.getDamage().getDamage());
|
||||
}
|
||||
private ItemAttackMetadata getAttack(PlayerData playerData, EntityDamageByEntityEvent event) {
|
||||
StatMap.CachedStatMap cachedStatMap = playerData.getMMOPlayerData().getStatMap().cache(EquipmentSlot.MAIN_HAND);
|
||||
return new ItemAttackMetadata(new DamageMetadata(event.getDamage(), DamageType.WEAPON, DamageType.PHYSICAL), cachedStatMap);
|
||||
}
|
||||
|
||||
/*
|
||||
* Event priority set to LOW to fix an infinite-exp glitch with
|
||||
* MMOCore. MMOCore experience source listens on HIGH and must be
|
||||
* higher than this event otherwise the exp is given even if the
|
||||
* block is not broken.
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void specialToolAbilities(BlockBreakEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
Block block = event.getBlock();
|
||||
if (player.getGameMode() == GameMode.CREATIVE)
|
||||
return;
|
||||
/**
|
||||
* Event priority set to LOW to fix an infinite-exp glitch with
|
||||
* MMOCore. MMOCore experience source listens on HIGH and must be
|
||||
* higher than this event otherwise the exp is given even if the
|
||||
* block is not broken.
|
||||
*/
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void specialToolAbilities(BlockBreakEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
Block block = event.getBlock();
|
||||
if (player.getGameMode() == GameMode.CREATIVE)
|
||||
return;
|
||||
|
||||
NBTItem item = MythicLib.plugin.getVersion().getWrapper().getNBTItem(player.getInventory().getItemInMainHand());
|
||||
if (!item.hasType())
|
||||
return;
|
||||
NBTItem item = MythicLib.plugin.getVersion().getWrapper().getNBTItem(player.getInventory().getItemInMainHand());
|
||||
if (!item.hasType())
|
||||
return;
|
||||
|
||||
Tool tool = new Tool(player, item);
|
||||
if (!tool.checkItemRequirements()) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
Tool tool = new Tool(player, item);
|
||||
if (!tool.checkItemRequirements()) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (tool.miningEffects(block))
|
||||
event.setCancelled(true);
|
||||
}
|
||||
if (tool.miningEffects(block))
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void rightClickWeaponInteractions(PlayerInteractEntityEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
if (!(event.getRightClicked() instanceof LivingEntity))
|
||||
return;
|
||||
@EventHandler
|
||||
public void rightClickWeaponInteractions(PlayerInteractEntityEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
if (!(event.getRightClicked() instanceof LivingEntity))
|
||||
return;
|
||||
|
||||
NBTItem item = MythicLib.plugin.getVersion().getWrapper().getNBTItem(player.getInventory().getItemInMainHand());
|
||||
if (!item.hasType())
|
||||
return;
|
||||
NBTItem item = MythicLib.plugin.getVersion().getWrapper().getNBTItem(player.getInventory().getItemInMainHand());
|
||||
if (!item.hasType())
|
||||
return;
|
||||
|
||||
LivingEntity target = (LivingEntity) event.getRightClicked();
|
||||
if (!MMOUtils.canTarget(player, target, InteractionType.OFFENSE_ACTION))
|
||||
return;
|
||||
LivingEntity target = (LivingEntity) event.getRightClicked();
|
||||
if (!MMOUtils.canTarget(player, target, InteractionType.OFFENSE_ACTION))
|
||||
return;
|
||||
|
||||
UseItem weapon = UseItem.getItem(player, item, item.getType());
|
||||
if (!weapon.checkItemRequirements())
|
||||
return;
|
||||
UseItem weapon = UseItem.getItem(player, item, item.getType());
|
||||
if (!weapon.checkItemRequirements())
|
||||
return;
|
||||
|
||||
// Special staff attack
|
||||
if (weapon instanceof Staff)
|
||||
((Staff) weapon).specialAttack(target);
|
||||
// Special staff attack
|
||||
if (weapon instanceof Staff)
|
||||
((Staff) weapon).specialAttack(target);
|
||||
|
||||
// Special gauntlet attack
|
||||
if (weapon instanceof Gauntlet)
|
||||
((Gauntlet) weapon).specialAttack(target);
|
||||
}
|
||||
// Special gauntlet attack
|
||||
if (weapon instanceof Gauntlet)
|
||||
((Gauntlet) weapon).specialAttack(target);
|
||||
}
|
||||
|
||||
// TODO: Rewrite this with a custom 'ApplyMMOItemEvent'?
|
||||
@EventHandler
|
||||
public void gemStonesAndItemStacks(InventoryClickEvent event) {
|
||||
Player player = (Player) event.getWhoClicked();
|
||||
if (event.getAction() != InventoryAction.SWAP_WITH_CURSOR)
|
||||
return;
|
||||
// TODO: Rewrite this with a custom 'ApplyMMOItemEvent'?
|
||||
@EventHandler
|
||||
public void gemStonesAndItemStacks(InventoryClickEvent event) {
|
||||
Player player = (Player) event.getWhoClicked();
|
||||
if (event.getAction() != InventoryAction.SWAP_WITH_CURSOR)
|
||||
return;
|
||||
|
||||
NBTItem item = MythicLib.plugin.getVersion().getWrapper().getNBTItem(event.getCursor());
|
||||
if (!item.hasType())
|
||||
return;
|
||||
NBTItem item = MythicLib.plugin.getVersion().getWrapper().getNBTItem(event.getCursor());
|
||||
if (!item.hasType())
|
||||
return;
|
||||
|
||||
UseItem useItem = UseItem.getItem(player, item, item.getType());
|
||||
if (!useItem.checkItemRequirements())
|
||||
return;
|
||||
UseItem useItem = UseItem.getItem(player, item, item.getType());
|
||||
if (!useItem.checkItemRequirements())
|
||||
return;
|
||||
|
||||
if (useItem instanceof ItemSkin) {
|
||||
NBTItem picked = MythicLib.plugin.getVersion().getWrapper().getNBTItem(event.getCurrentItem());
|
||||
if (!picked.hasType())
|
||||
return;
|
||||
if (useItem instanceof ItemSkin) {
|
||||
NBTItem picked = MythicLib.plugin.getVersion().getWrapper().getNBTItem(event.getCurrentItem());
|
||||
if (!picked.hasType())
|
||||
return;
|
||||
|
||||
ItemSkin.ApplyResult result = ((ItemSkin) useItem).applyOntoItem(picked, Type.get(picked.getType()));
|
||||
if (result.getType() == ItemSkin.ResultType.NONE)
|
||||
return;
|
||||
ItemSkin.ApplyResult result = ((ItemSkin) useItem).applyOntoItem(picked, Type.get(picked.getType()));
|
||||
if (result.getType() == ItemSkin.ResultType.NONE)
|
||||
return;
|
||||
|
||||
event.setCancelled(true);
|
||||
item.getItem().setAmount(item.getItem().getAmount() - 1);
|
||||
event.setCancelled(true);
|
||||
item.getItem().setAmount(item.getItem().getAmount() - 1);
|
||||
|
||||
if (result.getType() == ItemSkin.ResultType.FAILURE)
|
||||
return;
|
||||
if (result.getType() == ItemSkin.ResultType.FAILURE)
|
||||
return;
|
||||
|
||||
event.setCurrentItem(result.getResult());
|
||||
}
|
||||
event.setCurrentItem(result.getResult());
|
||||
}
|
||||
|
||||
if (useItem instanceof GemStone) {
|
||||
NBTItem picked = MythicLib.plugin.getVersion().getWrapper().getNBTItem(event.getCurrentItem());
|
||||
if (!picked.hasType())
|
||||
return;
|
||||
if (useItem instanceof GemStone) {
|
||||
NBTItem picked = MythicLib.plugin.getVersion().getWrapper().getNBTItem(event.getCurrentItem());
|
||||
if (!picked.hasType())
|
||||
return;
|
||||
|
||||
GemStone.ApplyResult result = ((GemStone) useItem).applyOntoItem(picked, Type.get(picked.getType()));
|
||||
if (result.getType() == GemStone.ResultType.NONE)
|
||||
return;
|
||||
GemStone.ApplyResult result = ((GemStone) useItem).applyOntoItem(picked, Type.get(picked.getType()));
|
||||
if (result.getType() == GemStone.ResultType.NONE)
|
||||
return;
|
||||
|
||||
event.setCancelled(true);
|
||||
item.getItem().setAmount(item.getItem().getAmount() - 1);
|
||||
event.setCancelled(true);
|
||||
item.getItem().setAmount(item.getItem().getAmount() - 1);
|
||||
|
||||
if (result.getType() == GemStone.ResultType.FAILURE)
|
||||
return;
|
||||
if (result.getType() == GemStone.ResultType.FAILURE)
|
||||
return;
|
||||
|
||||
event.setCurrentItem(result.getResult());
|
||||
}
|
||||
event.setCurrentItem(result.getResult());
|
||||
}
|
||||
|
||||
if (useItem instanceof Consumable && event.getCurrentItem() != null && event.getCurrentItem().getType() != Material.AIR)
|
||||
if (((Consumable) useItem).useOnItem(event, MythicLib.plugin.getVersion().getWrapper().getNBTItem(event.getCurrentItem()))) {
|
||||
event.setCancelled(true);
|
||||
event.getCursor().setAmount(event.getCursor().getAmount() - 1);
|
||||
}
|
||||
}
|
||||
if (useItem instanceof Consumable && event.getCurrentItem() != null && event.getCurrentItem().getType() != Material.AIR)
|
||||
if (((Consumable) useItem).useOnItem(event, MythicLib.plugin.getVersion().getWrapper().getNBTItem(event.getCurrentItem()))) {
|
||||
event.setCancelled(true);
|
||||
event.getCursor().setAmount(event.getCursor().getAmount() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void handleCustomBows(EntityShootBowEvent event) {
|
||||
if (!(event.getProjectile() instanceof Arrow) || !(event.getEntity() instanceof Player))
|
||||
return;
|
||||
@EventHandler
|
||||
public void handleCustomBows(EntityShootBowEvent event) {
|
||||
if (!(event.getProjectile() instanceof Arrow) || !(event.getEntity() instanceof Player))
|
||||
return;
|
||||
|
||||
NBTItem item = NBTItem.get(event.getBow());
|
||||
Type type = Type.get(item.getType());
|
||||
NBTItem item = NBTItem.get(event.getBow());
|
||||
Type type = Type.get(item.getType());
|
||||
|
||||
PlayerData playerData = PlayerData.get((Player) event.getEntity());
|
||||
if (type != null) {
|
||||
Weapon weapon = new Weapon(playerData, item);
|
||||
if (!weapon.checkItemRequirements() || !weapon.applyWeaponCosts()) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
PlayerData playerData = PlayerData.get((Player) event.getEntity());
|
||||
if (type != null) {
|
||||
Weapon weapon = new Weapon(playerData, item);
|
||||
if (!weapon.checkItemRequirements() || !weapon.applyWeaponCosts()) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
/*if (!checkDualWield((Player) event.getEntity(), item, bowSlot)) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
// Have to get hand manually because 1.15 and below does not have event.getHand()
|
||||
ItemStack itemInMainHand = playerData.getPlayer().getInventory().getItemInMainHand();
|
||||
EquipmentSlot bowSlot = (itemInMainHand.isSimilar(event.getBow())) ? EquipmentSlot.MAIN_HAND : EquipmentSlot.OFF_HAND;
|
||||
// Have to get hand manually because 1.15 and below does not have event.getHand()
|
||||
ItemStack itemInMainHand = playerData.getPlayer().getInventory().getItemInMainHand();
|
||||
EquipmentSlot bowSlot = (itemInMainHand.isSimilar(event.getBow())) ? EquipmentSlot.MAIN_HAND : EquipmentSlot.OFF_HAND;
|
||||
|
||||
Arrow arrow = (Arrow) event.getProjectile();
|
||||
if (item.getStat("ARROW_VELOCITY") > 0)
|
||||
arrow.setVelocity(arrow.getVelocity().multiply(item.getStat("ARROW_VELOCITY")));
|
||||
MMOItems.plugin.getEntities().registerCustomProjectile(item, playerData.getStats().newTemporary(bowSlot), event.getProjectile(), type != null,
|
||||
event.getForce());
|
||||
}
|
||||
Arrow arrow = (Arrow) event.getProjectile();
|
||||
if (item.getStat("ARROW_VELOCITY") > 0)
|
||||
arrow.setVelocity(arrow.getVelocity().multiply(item.getStat("ARROW_VELOCITY")));
|
||||
MMOItems.plugin.getEntities().registerCustomProjectile(item, playerData.getStats().newTemporary(bowSlot), event.getProjectile(), type != null,
|
||||
event.getForce());
|
||||
}
|
||||
|
||||
/**
|
||||
* Consumables which can be eaten using the
|
||||
* vanilla eating animation are handled here.
|
||||
*/
|
||||
@EventHandler
|
||||
public void handleVanillaEatenConsumables(PlayerItemConsumeEvent event) {
|
||||
NBTItem item = MythicLib.plugin.getVersion().getWrapper().getNBTItem(event.getItem());
|
||||
if (!item.hasType())
|
||||
return;
|
||||
/**
|
||||
* Consumables which can be eaten using the
|
||||
* vanilla eating animation are handled here.
|
||||
*/
|
||||
@EventHandler
|
||||
public void handleVanillaEatenConsumables(PlayerItemConsumeEvent event) {
|
||||
NBTItem item = MythicLib.plugin.getVersion().getWrapper().getNBTItem(event.getItem());
|
||||
if (!item.hasType())
|
||||
return;
|
||||
|
||||
Player player = event.getPlayer();
|
||||
UseItem useItem = UseItem.getItem(player, item, item.getType());
|
||||
if (!useItem.checkItemRequirements()) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
Player player = event.getPlayer();
|
||||
UseItem useItem = UseItem.getItem(player, item, item.getType());
|
||||
if (!useItem.checkItemRequirements()) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (useItem instanceof Consumable) {
|
||||
if (useItem instanceof Consumable) {
|
||||
|
||||
if (!useItem.getPlayerData().isOnCooldown(useItem.getMMOItem().getId())) {
|
||||
Message.ITEM_ON_COOLDOWN
|
||||
.format(ChatColor.RED, "#left#", DIGIT.format(useItem.getPlayerData().getItemCooldown(useItem.getMMOItem().getId())))
|
||||
.send(player);
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
if (!useItem.getPlayerData().isOnCooldown(useItem.getMMOItem().getId())) {
|
||||
Message.ITEM_ON_COOLDOWN
|
||||
.format(ChatColor.RED, "#left#", DIGIT.format(useItem.getPlayerData().getItemCooldown(useItem.getMMOItem().getId())))
|
||||
.send(player);
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
Consumable.ConsumableConsumeResult result = ((Consumable) useItem).useOnPlayer();
|
||||
Consumable.ConsumableConsumeResult result = ((Consumable) useItem).useOnPlayer();
|
||||
|
||||
// No effects are applied and not consumed
|
||||
if (result == Consumable.ConsumableConsumeResult.CANCEL) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
// No effects are applied and not consumed
|
||||
if (result == Consumable.ConsumableConsumeResult.CANCEL) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Item is not consumed but its effects are applied anyways
|
||||
if (result == Consumable.ConsumableConsumeResult.NOT_CONSUME)
|
||||
event.setCancelled(true);
|
||||
// Item is not consumed but its effects are applied anyways
|
||||
if (result == Consumable.ConsumableConsumeResult.NOT_CONSUME)
|
||||
event.setCancelled(true);
|
||||
|
||||
useItem.getPlayerData().applyItemCooldown(useItem.getMMOItem().getId(), useItem.getNBTItem().getStat("ITEM_COOLDOWN"));
|
||||
useItem.executeCommands();
|
||||
}
|
||||
}
|
||||
useItem.getPlayerData().applyItemCooldown(useItem.getMMOItem().getId(), useItem.getNBTItem().getStat("ITEM_COOLDOWN"));
|
||||
useItem.executeCommands();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import io.lumine.mythic.lib.comp.mythicmobs.MythicSkillInfo;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
||||
@ -13,7 +14,7 @@ import net.Indyuce.mmoitems.MMOItems;
|
||||
import net.Indyuce.mmoitems.ability.Ability;
|
||||
import net.Indyuce.mmoitems.ability.Ability.CastingMode;
|
||||
|
||||
public class AbilityData {
|
||||
public class AbilityData implements MythicSkillInfo {
|
||||
private final Ability ability;
|
||||
private final CastingMode castMode;
|
||||
private final Map<String, Double> modifiers = new HashMap<>();
|
||||
@ -90,8 +91,9 @@ public class AbilityData {
|
||||
return modifiers.containsKey(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getModifier(String path) {
|
||||
return modifiers.containsKey(path) ? modifiers.get(path) : ability.getDefaultValue(path);
|
||||
return modifiers.getOrDefault(path, ability.getDefaultValue(path));
|
||||
}
|
||||
|
||||
public JsonObject toJson() {
|
||||
|
Loading…
Reference in New Issue
Block a user