moved flags to mythicLib, entityHandler rework

This commit is contained in:
Indyuce 2021-08-25 14:56:04 +02:00
parent c07fc26eca
commit f5ea91fd44
75 changed files with 1586 additions and 1696 deletions

View File

@ -21,14 +21,10 @@ import net.Indyuce.mmoitems.command.MMOItemsCommandTreeRoot;
import net.Indyuce.mmoitems.comp.*;
import net.Indyuce.mmoitems.comp.denizen.DenizenHook;
import net.Indyuce.mmoitems.comp.eco.VaultSupport;
import net.Indyuce.mmoitems.comp.enchants.advanced_enchants.AdvancedEnchantmentsHook;
import net.Indyuce.mmoitems.comp.enchants.CrazyEnchantsStat;
import net.Indyuce.mmoitems.comp.enchants.EnchantPlugin;
import net.Indyuce.mmoitems.comp.enchants.MythicEnchantsSupport;
import net.Indyuce.mmoitems.comp.flags.DefaultFlags;
import net.Indyuce.mmoitems.comp.flags.FlagPlugin;
import net.Indyuce.mmoitems.comp.flags.ResidenceFlags;
import net.Indyuce.mmoitems.comp.flags.WorldGuardFlags;
import net.Indyuce.mmoitems.comp.enchants.advanced_enchants.AdvancedEnchantmentsHook;
import net.Indyuce.mmoitems.comp.inventory.*;
import net.Indyuce.mmoitems.comp.itemglow.ItemGlowListener;
import net.Indyuce.mmoitems.comp.itemglow.NoGlowListener;
@ -96,7 +92,6 @@ public class MMOItems extends LuminePlugin {
private EquipListener equipListener;
private PlaceholderParser placeholderParser = new DefaultPlaceholderParser();
private FlagPlugin flagPlugin = new DefaultFlags();
private VaultSupport vaultSupport;
private RPGHandler rpgPlugin;
@ -104,14 +99,6 @@ public class MMOItems extends LuminePlugin {
public void load() {
plugin = this;
if (getServer().getPluginManager().getPlugin("WorldGuard") != null)
try {
flagPlugin = new WorldGuardFlags();
getLogger().log(Level.INFO, "Hooked onto WorldGuard");
} catch (Exception exception) {
getLogger().log(Level.WARNING, "Could not initialize support with WorldGuard 7: " + exception.getMessage());
}
if (getServer().getPluginManager().getPlugin("WorldEdit") != null)
try {
new WorldEditSupport();
@ -237,10 +224,6 @@ public class MMOItems extends LuminePlugin {
PlayerData.get(player).getInventory().updateCheck();
}, 100, getConfig().getInt("inventory-update-delay"));
if (Bukkit.getPluginManager().getPlugin("Residence") != null) {
flagPlugin = new ResidenceFlags();
getLogger().log(Level.INFO, "Hooked onto Residence");
}
if (Bukkit.getPluginManager().getPlugin("mcMMO") != null)
Bukkit.getPluginManager().registerEvents(new McMMONonRPGHook(), this);
@ -371,14 +354,6 @@ public class MMOItems extends LuminePlugin {
return setManager;
}
public FlagPlugin getFlags() {
return flagPlugin;
}
public void setFlags(FlagPlugin value) {
flagPlugin = value;
}
public RPGHandler getRPG() {
return rpgPlugin;
}

View File

@ -6,14 +6,16 @@ import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.item.ItemTag;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.api.item.SupportedNBTTagValues;
import io.lumine.mythic.lib.comp.target.InteractionType;
import net.Indyuce.mmoitems.api.Type;
import net.Indyuce.mmoitems.api.player.PlayerData;
import org.apache.commons.codec.binary.Base64;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.attribute.Attribute;
import org.bukkit.entity.*;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
@ -28,366 +30,398 @@ import java.util.*;
@SuppressWarnings("unused")
public class MMOUtils {
/**
* @return The skull texture URL from a given player head
*/
public static String getSkullTextureURL(ItemStack item) {
try {
ItemMeta meta = item.getItemMeta();
Field profileField = meta.getClass().getDeclaredField("profile");
profileField.setAccessible(true);
Collection<Property> properties = ((GameProfile) profileField.get(item.getItemMeta())).getProperties().get("textures");
Property property = properties.toArray(new Property[0])[0];
return new String(Base64.decodeBase64(property.getValue())).replace("{textures:{SKIN:{url:\"", "").replace("\"}}}", "");
} catch (Exception e) {
return "";
}
}
/**
* @return The skull texture URL from a given player head
*/
public static String getSkullTextureURL(ItemStack item) {
try {
ItemMeta meta = item.getItemMeta();
Field profileField = meta.getClass().getDeclaredField("profile");
profileField.setAccessible(true);
Collection<Property> properties = ((GameProfile) profileField.get(item.getItemMeta())).getProperties().get("textures");
Property property = properties.toArray(new Property[0])[0];
return new String(Base64.decodeBase64(property.getValue())).replace("{textures:{SKIN:{url:\"", "").replace("\"}}}", "");
} catch (Exception e) {
return "";
}
}
/**
* @param item The item stack you are testing.
* @param type MMOItem Type you are expecting {@link Type#getId()}
* @param id MMOItem ID you are expecting
* @return If the given item is the desired MMOItem
*/
public static boolean isMMOItem(@Nullable ItemStack item, @NotNull String type, @NotNull String id) {
if (item == null)
return false;
/**
* @param item The item stack you are testing.
* @param type MMOItem Type you are expecting {@link Type#getId()}
* @param id MMOItem ID you are expecting
* @return If the given item is the desired MMOItem
*/
public static boolean isMMOItem(@Nullable ItemStack item, @NotNull String type, @NotNull String id) {
if (item == null)
return false;
// Make it into an NBT Item
NBTItem asNBT = NBTItem.get(item);
// Make it into an NBT Item
NBTItem asNBT = NBTItem.get(item);
// ID Matches?
String itemID = getID(asNBT);
// ID Matches?
String itemID = getID(asNBT);
// Not a MMOItem
if (itemID == null)
return false;
// Not a MMOItem
if (itemID == null)
return false;
// ID matches?
if (!itemID.equals(id))
return false;
// ID matches?
if (!itemID.equals(id))
return false;
// If the type matches too, we are set.
return asNBT.getType().equals(type);
}
// If the type matches too, we are set.
return asNBT.getType().equals(type);
}
/**
* @param nbtItem The NBTItem you are testing
* @return The MMOItem Type of this item, if it is a MMOItem
*/
@Nullable
public static Type getType(@Nullable NBTItem nbtItem) {
if (nbtItem == null || !nbtItem.hasType())
return null;
/**
* @param nbtItem The NBTItem you are testing
* @return The MMOItem Type of this item, if it is a MMOItem
*/
@Nullable
public static Type getType(@Nullable NBTItem nbtItem) {
if (nbtItem == null || !nbtItem.hasType())
return null;
// Try that one instead
return MMOItems.plugin.getTypes().get(nbtItem.getType());
}
// Try that one instead
return MMOItems.plugin.getTypes().get(nbtItem.getType());
}
/**
* @param nbtItem The NBTItem you are testing
* @return The MMOItem ID of this item, if it is a MMOItem
*/
@Nullable
public static String getID(@Nullable NBTItem nbtItem) {
if (nbtItem == null || !nbtItem.hasType())
return null;
/**
* @param nbtItem The NBTItem you are testing
* @return The MMOItem ID of this item, if it is a MMOItem
*/
@Nullable
public static String getID(@Nullable NBTItem nbtItem) {
if (nbtItem == null || !nbtItem.hasType())
return null;
ItemTag type = ItemTag.getTagAtPath("MMOITEMS_ITEM_ID", nbtItem, SupportedNBTTagValues.STRING);
if (type == null)
return null;
ItemTag type = ItemTag.getTagAtPath("MMOITEMS_ITEM_ID", nbtItem, SupportedNBTTagValues.STRING);
if (type == null)
return null;
return (String) type.getValue();
}
return (String) type.getValue();
}
/**
* * Returns either the normalized vector, or null vector if input is null
* vector which cannot be normalized.
*
* @param vector Vector which can be of length 0
* @return Normalized vector or 0 depending on input
*/
public static Vector normalize(Vector vector) {
return vector.getX() == 0 && vector.getY() == 0 ? vector : vector.normalize();
}
/**
* * Returns either the normalized vector, or null vector if input is null
* vector which cannot be normalized.
*
* @param vector Vector which can be of length 0
* @return Normalized vector or 0 depending on input
*/
public static Vector normalize(Vector vector) {
return vector.getX() == 0 && vector.getY() == 0 ? vector : vector.normalize();
}
/**
* Double.parseDouble(String) cannot be used when asking for player input in
* stat edition because the exception message is confusing. This method has
* a better exception message
*
* @param format Format to parse into a number
* @return Parsed double
*/
public static double parseDouble(String format) {
try {
return Double.parseDouble(format);
} catch (IllegalArgumentException exception) {
throw new IllegalArgumentException("Could not read number from '" + format + "'");
}
}
/**
* Double.parseDouble(String) cannot be used when asking for player input in
* stat edition because the exception message is confusing. This method has
* a better exception message
*
* @param format Format to parse into a number
* @return Parsed double
*/
public static double parseDouble(String format) {
try {
return Double.parseDouble(format);
} catch (IllegalArgumentException exception) {
throw new IllegalArgumentException("Could not read number from '" + format + "'");
}
}
/**
* Returns an UUID from thay string, or null if it is not in UUID format.
*/
@Nullable
public static UUID UUIDFromString(@org.jetbrains.annotations.Nullable String anything) {
if (anything == null)
return null;
/**
* Returns an UUID from thay string, or null if it is not in UUID format.
*/
@Nullable
public static UUID UUIDFromString(@org.jetbrains.annotations.Nullable String anything) {
if (anything == null)
return null;
// Correct Format?
if (anything.matches("[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}"))
// Correct Format?
if (anything.matches("[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}"))
// Return thay
return UUID.fromString(anything);
// Return thay
return UUID.fromString(anything);
// No
return null;
}
// No
return null;
}
public static LivingEntity getDamager(EntityDamageByEntityEvent event) {
public static LivingEntity getDamager(EntityDamageByEntityEvent event) {
// Check direct damager
if (event.getDamager() instanceof LivingEntity) return (LivingEntity) event.getDamager();
// Check direct damager
if (event.getDamager() instanceof LivingEntity) return (LivingEntity) event.getDamager();
/*
* Checks projectile and add damage type, which supports every vanilla
* projectile like snowballs, tridents and arrows
*/
if (event.getDamager() instanceof Projectile) {
Projectile proj = (Projectile) event.getDamager();
if (proj.getShooter() instanceof LivingEntity)
return (LivingEntity) proj.getShooter();
}
/*
* Checks projectile and add damage type, which supports every vanilla
* projectile like snowballs, tridents and arrows
*/
if (event.getDamager() instanceof Projectile) {
Projectile proj = (Projectile) event.getDamager();
if (proj.getShooter() instanceof LivingEntity)
return (LivingEntity) proj.getShooter();
}
return null;
}
return null;
}
/**
* The last 5 seconds of nausea are useless, night vision flashes in the
* last 10 seconds, blindness takes a few seconds to decay as well, and
* there can be small server lags. It's best to apply a specific duration
* for every type of permanent effect.
*
* @param type Potion effect type
* @return The duration that MMOItems should be using to give player
* "permanent" potion effects, depending on the potion effect type
*/
public static int getEffectDuration(PotionEffectType type) {
return type.equals(PotionEffectType.NIGHT_VISION) || type.equals(PotionEffectType.CONFUSION) ? 260 : type.equals(PotionEffectType.BLINDNESS) ? 140 : 80;
}
/**
* The last 5 seconds of nausea are useless, night vision flashes in the
* last 10 seconds, blindness takes a few seconds to decay as well, and
* there can be small server lags. It's best to apply a specific duration
* for every type of permanent effect.
*
* @param type Potion effect type
* @return The duration that MMOItems should be using to give player
* "permanent" potion effects, depending on the potion effect type
*/
public static int getEffectDuration(PotionEffectType type) {
return type.equals(PotionEffectType.NIGHT_VISION) || type.equals(PotionEffectType.CONFUSION) ? 260 : type.equals(PotionEffectType.BLINDNESS) ? 140 : 80;
}
@NotNull public static String getDisplayName(@Nullable ItemStack item) {
if (item == null) { return "null"; }
return (item.hasItemMeta() && item.getItemMeta().hasDisplayName()) ?
item.getItemMeta().getDisplayName() :
caseOnWords(item.getType().name().toLowerCase().replace("_", " "));
}
@NotNull
public static String getDisplayName(@Nullable ItemStack item) {
if (item == null) {
return "null";
}
return (item.hasItemMeta() && item.getItemMeta().hasDisplayName()) ?
item.getItemMeta().getDisplayName() :
caseOnWords(item.getType().name().toLowerCase().replace("_", " "));
}
/**
* Super useful to display enum names like DIAMOND_SWORD in chat
*
* @param s String with lower cases and spaces only
* @return Same string with capital letters at the beginning of each word.
*/
public static String caseOnWords(String s) {
StringBuilder builder = new StringBuilder(s);
boolean isLastSpace = true;
for (int i = 0; i < builder.length(); i++) {
char ch = builder.charAt(i);
if (isLastSpace && ch >= 'a' && ch <= 'z') {
builder.setCharAt(i, (char) (ch + ('A' - 'a')));
isLastSpace = false;
} else isLastSpace = ch == ' ';
}
return builder.toString();
}
/**
* Super useful to display enum names like DIAMOND_SWORD in chat
*
* @param s String with lower cases and spaces only
* @return Same string with capital letters at the beginning of each word.
*/
public static String caseOnWords(String s) {
StringBuilder builder = new StringBuilder(s);
boolean isLastSpace = true;
for (int i = 0; i < builder.length(); i++) {
char ch = builder.charAt(i);
if (isLastSpace && ch >= 'a' && ch <= 'z') {
builder.setCharAt(i, (char) (ch + ('A' - 'a')));
isLastSpace = false;
} else isLastSpace = ch == ' ';
}
return builder.toString();
}
/**
* @param item The item to check
* @param lore Whether or not MI should check for an item lore
* @return If the item is not null, has an itemMeta and has a display name.
* If 'lore' is true, also checks if the itemMeta has a lore.
*/
public static boolean isMetaItem(ItemStack item, boolean lore) {
return item != null && item.getType() != Material.AIR && item.getItemMeta() != null && item.getItemMeta().getDisplayName() != null && (!lore || item.getItemMeta().getLore() != null);
}
/**
* @param item The item to check
* @param lore Whether or not MI should check for an item lore
* @return If the item is not null, has an itemMeta and has a display name.
* If 'lore' is true, also checks if the itemMeta has a lore.
*/
public static boolean isMetaItem(ItemStack item, boolean lore) {
return item != null && item.getType() != Material.AIR && item.getItemMeta() != null && item.getItemMeta().getDisplayName() != null && (!lore || item.getItemMeta().getLore() != null);
}
//region Restoration
/**
* @param player Player to heal
* @param saturation Saturation amount
* <br>
* Negative values are just ignored
*/
public static void saturate(@NotNull Player player, double saturation) { saturate(player, saturation, false); }
/**
* @param player Player to heal
* @param saturation Saturation amount
* @param allowNegatives If passing a negative saturation value will desaturatie the entity x)
* <br>
* If <code>false</code>, negative values are just ignored
*/
public static void saturate(@NotNull Player player, double saturation, boolean allowNegatives) { if (saturation > 0 || allowNegatives) player.setSaturation(Math.min(0, Math.min(20, player.getSaturation() + (float) saturation))); }
//region Restoration
/**
* @param player Player to heal
* @param feed Food amount
* <br>
* Negative values are just ignored
*/
public static void feed(@NotNull Player player, int feed) { feed(player, feed, false); }
/**
* @param player Player to heal
* @param feed Food amount
* @param allowNegatives If passing a negative feed value will hunger the entity x)
* <br>
* If <code>false</code>, negative values are just ignored
*/
public static void feed(@NotNull Player player, int feed, boolean allowNegatives) { if (feed > 0 || allowNegatives) player.setFoodLevel(Math.max(Math.min(20, player.getFoodLevel() + feed), 0)); }
/**
* @param player Player to heal
* @param saturation Saturation amount
* <br>
* Negative values are just ignored
*/
public static void saturate(@NotNull Player player, double saturation) {
saturate(player, saturation, false);
}
/**
* @param player Player to heal
* @param heal Heal amount
* <br>
* Negative values are just ignored
*/
public static void heal(@NotNull LivingEntity player, double heal) { heal(player, heal, false); }
/**
* @param player Player to heal
* @param heal Heal amount
* @param allowNegatives If passing a negative health value will damage the entity x)
* <br>
* If <code>false</code>, negative values are just ignored
*/
public static void heal(@NotNull LivingEntity player, double heal, boolean allowNegatives) { if (heal > 0 || allowNegatives) player.setHealth(Math.min(player.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue(), player.getHealth() + heal)); }
//endregion
/**
* @param player Player to heal
* @param saturation Saturation amount
* @param allowNegatives If passing a negative saturation value will desaturatie the entity x)
* <br>
* If <code>false</code>, negative values are just ignored
*/
public static void saturate(@NotNull Player player, double saturation, boolean allowNegatives) {
if (saturation > 0 || allowNegatives)
player.setSaturation(Math.min(0, Math.min(20, player.getSaturation() + (float) saturation)));
}
public static boolean canDamage(Player player, Entity target) {
return canDamage(player, null, target);
}
/**
* @param player Player to heal
* @param feed Food amount
* <br>
* Negative values are just ignored
*/
public static void feed(@NotNull Player player, int feed) {
feed(player, feed, false);
}
public static boolean canDamage(Entity target) {
return canDamage(null, null, target);
}
/**
* @param player Player to heal
* @param feed Food amount
* @param allowNegatives If passing a negative feed value will hunger the entity x)
* <br>
* If <code>false</code>, negative values are just ignored
*/
public static void feed(@NotNull Player player, int feed, boolean allowNegatives) {
if (feed > 0 || allowNegatives) player.setFoodLevel(Math.max(Math.min(20, player.getFoodLevel() + feed), 0));
}
/**
* @param player Player hitting the entity
* @param loc If the given location is not null, this method checks if this
* location is inside the bounding box of the entity hit
* @param target The entity being hit
* @return If the entity can be damaged, by a specific player, at a specific
* spot
*/
public static boolean canDamage(@Nullable Player player, @Nullable Location loc, Entity target) {
/**
* @param player Player to heal
* @param heal Heal amount
* <br>
* Negative values are just ignored
*/
public static void heal(@NotNull LivingEntity player, double heal) {
heal(player, heal, false);
}
/*
* Cannot hit himself or non-living entities. Careful, some entities are
* weirdly considered as livingEntities like the armor stand. Also check
* if the entity is dead since a dying entity (dying effect takes some
* time) can still be targeted but we dont want that
*/
if (target.equals(player) || target.isDead() || !(target instanceof LivingEntity) || target instanceof ArmorStand)
return false;
/**
* @param player Player to heal
* @param heal Heal amount
* @param allowNegatives If passing a negative health value will damage the entity x)
* <br>
* If <code>false</code>, negative values are just ignored
*/
public static void heal(@NotNull LivingEntity player, double heal, boolean allowNegatives) {
if (heal > 0 || allowNegatives)
player.setHealth(Math.min(player.getAttribute(Attribute.GENERIC_MAX_HEALTH).getValue(), player.getHealth() + heal));
}
//endregion
/*
* Extra plugin compatibility, everything is handled via MMOLib because
* the same system is used by MMOCore
*/
if (MythicLib.plugin.getEntities().findCustom(target)) return false;
/**
* Interaction type is set to OFFENSE_SKILL by default. No bounding box checks
*
* @param source Player targeting the entity
* @param target The entity being hit
* @return If the entity can be damaged, by a specific player, at a specific spot
*/
public static boolean canTarget(Player source, Entity target) {
return canTarget(source, null, target, InteractionType.OFFENSE_SKILL);
}
/*
* The ability player damage option is cached for quicker access in the
* config manager instance since it is used in runnables
*/
if (target instanceof Player && (!MMOItems.plugin.getLanguage().abilityPlayerDamage || !MMOItems.plugin.getFlags().isPvpAllowed(target.getLocation())))
return false;
/**
* Interaction type is set to OFFENSE_SKILL by default.
*
* @param source Player targeting the entity
* @param loc If the given location is not null, this method checks if this
* location is inside the bounding box of the entity hit
* @param target The entity being hit
* @return If the entity can be damaged, by a specific player, at a specific spot
*/
public static boolean canTarget(Player source, Location loc, Entity target) {
return canTarget(source, loc, target, InteractionType.OFFENSE_SKILL);
}
return loc == null || MythicLib.plugin.getVersion().getWrapper().isInBoundingBox(target, loc);
}
/**
* No bounding box checks
*
* @param source Player targeting the entity
* @param target The entity being hit
* @param interaction Type of interaction
* @return If the entity can be damaged, by a specific player, at a specific spot
*/
public static boolean canTarget(Player source, Entity target, InteractionType interaction) {
return canTarget(source, null, target, interaction);
}
private static final String[] romanChars = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};
private static final int[] romanValues = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
/**
* @param source Player targeting the entity
* @param loc If the given location is not null, this method checks if this
* location is inside the bounding box of the entity hit
* @param target The entity being hit
* @param interaction Type of interaction
* @return If the entity can be damaged, by a specific player, at a specific spot
*/
public static boolean canTarget(@Nullable Player source, @Nullable Location loc, Entity target, InteractionType interaction) {
/**
* @param input Integer from 1 to 3999
* @return Roman display of given int
*/
public static String intToRoman(int input) {
if (input < 1 || input > 3999) throw new IllegalArgumentException("Input must be between 1 and 3999");
// Check for easy checks and other as well
if (!MythicLib.plugin.getEntities().canTarget(source, target, interaction))
return false;
StringBuilder format = new StringBuilder();
// Check for bounding box
return loc == null || MythicLib.plugin.getVersion().getWrapper().isInBoundingBox(target, loc);
}
for (int i = 0; i < romanChars.length; i++)
while (input >= romanValues[i]) {
format.append(romanChars[i]);
input -= romanValues[i];
}
private static final String[] romanChars = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};
private static final int[] romanValues = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
return format.toString();
}
/**
* @param input Integer from 1 to 3999
* @return Roman display of given int
*/
public static String intToRoman(int input) {
if (input < 1 || input > 3999) throw new IllegalArgumentException("Input must be between 1 and 3999");
public static double truncation(double x, int n) {
double pow = Math.pow(10.0, n);
return Math.floor(x * pow) / pow;
}
StringBuilder format = new StringBuilder();
/**
* @param v Vector to rotate
* @param loc The position is not actually being used here, only the pitch and yaw
* @return Vector facing direction given by location
*/
public static Vector rotateFunc(Vector v, Location loc) {
double yaw = loc.getYaw() / 180 * Math.PI;
double pitch = loc.getPitch() / 180 * Math.PI;
v = rotAxisX(v, pitch);
v = rotAxisY(v, -yaw);
return v;
}
for (int i = 0; i < romanChars.length; i++)
while (input >= romanValues[i]) {
format.append(romanChars[i]);
input -= romanValues[i];
}
private static Vector rotAxisX(Vector v, double a) {
double y = v.getY() * Math.cos(a) - v.getZ() * Math.sin(a);
double z = v.getY() * Math.sin(a) + v.getZ() * Math.cos(a);
return v.setY(y).setZ(z);
}
return format.toString();
}
private static Vector rotAxisY(Vector v, double b) {
double x = v.getX() * Math.cos(b) + v.getZ() * Math.sin(b);
double z = v.getX() * -Math.sin(b) + v.getZ() * Math.cos(b);
return v.setX(x).setZ(z);
}
public static double truncation(double x, int n) {
double pow = Math.pow(10.0, n);
return Math.floor(x * pow) / pow;
}
private static Vector rotAxisZ(Vector v, double c) {
double x = v.getX() * Math.cos(c) - v.getY() * Math.sin(c);
double y = v.getX() * Math.sin(c) + v.getY() * Math.cos(c);
return v.setX(x).setY(y);
}
/**
* @param v Vector to rotate
* @param loc The position is not actually being used here, only the pitch and yaw
* @return Vector facing direction given by location
*/
public static Vector rotateFunc(Vector v, Location loc) {
double yaw = loc.getYaw() / 180 * Math.PI;
double pitch = loc.getPitch() / 180 * Math.PI;
v = rotAxisX(v, pitch);
v = rotAxisY(v, -yaw);
return v;
}
/**
* @param loc Where we are looking for nearby entities
* @return List of all entities surrounding a location. This method loops
* through the 9 surrounding chunks and collect all entities from
* them. This list can be cached and used multiple times in the same
* tick for projectile based spells which need to run entity
* checkups
*/
public static List<Entity> getNearbyChunkEntities(Location loc) {
List<Entity> entities = new ArrayList<>();
private static Vector rotAxisX(Vector v, double a) {
double y = v.getY() * Math.cos(a) - v.getZ() * Math.sin(a);
double z = v.getY() * Math.sin(a) + v.getZ() * Math.cos(a);
return v.setY(y).setZ(z);
}
int cx = loc.getChunk().getX();
int cz = loc.getChunk().getZ();
private static Vector rotAxisY(Vector v, double b) {
double x = v.getX() * Math.cos(b) + v.getZ() * Math.sin(b);
double z = v.getX() * -Math.sin(b) + v.getZ() * Math.cos(b);
return v.setX(x).setZ(z);
}
for (int x = -1; x < 2; x++)
for (int z = -1; z < 2; z++)
entities.addAll(Arrays.asList(loc.getWorld().getChunkAt(cx + x, cz + z).getEntities()));
private static Vector rotAxisZ(Vector v, double c) {
double x = v.getX() * Math.cos(c) - v.getY() * Math.sin(c);
double y = v.getX() * Math.sin(c) + v.getY() * Math.cos(c);
return v.setX(x).setY(y);
}
return entities;
}
/**
* @param loc Where we are looking for nearby entities
* @return List of all entities surrounding a location. This method loops
* through the 9 surrounding chunks and collect all entities from
* them. This list can be cached and used multiple times in the same
* tick for projectile based spells which need to run entity
* checkups
*/
public static List<Entity> getNearbyChunkEntities(Location loc) {
List<Entity> entities = new ArrayList<>();
public static ItemStack readIcon(String string) throws IllegalArgumentException {
String[] split = string.split(":");
Material material = Material.valueOf(split[0].toUpperCase().replace("-", "_").replace(" ", "_"));
return split.length > 1 ? MythicLib.plugin.getVersion().getWrapper().textureItem(material, Integer.parseInt(split[1])) : new ItemStack(material);
}
int cx = loc.getChunk().getX();
int cz = loc.getChunk().getZ();
for (int x = -1; x < 2; x++)
for (int z = -1; z < 2; z++)
entities.addAll(Arrays.asList(loc.getWorld().getChunkAt(cx + x, cz + z).getEntities()));
return entities;
}
public static ItemStack readIcon(String string) throws IllegalArgumentException {
String[] split = string.split(":");
Material material = Material.valueOf(split[0].toUpperCase().replace("-", "_").replace(" ", "_"));
return split.length > 1 ? MythicLib.plugin.getVersion().getWrapper().textureItem(material, Integer.parseInt(split[1])) : new ItemStack(material);
}
}

View File

@ -49,7 +49,7 @@ public class Arcane_Hail extends LocationAbility {
Location loc1 = loc.clone().add(randomCoordMultiplier() * radius, 0, randomCoordMultiplier() * radius);
loc1.getWorld().playSound(loc1, VersionSound.ENTITY_ENDERMAN_HURT.toSound(), 1, 0);
for (Entity entity : MMOUtils.getNearbyChunkEntities(loc1))
if (MMOUtils.canDamage(attack.getDamager(), entity) && entity.getLocation().distanceSquared(loc1) <= 4)
if (MMOUtils.canTarget(attack.getDamager(), entity) && entity.getLocation().distanceSquared(loc1) <= 4)
new AttackMetadata(new DamageMetadata(damage, DamageType.SKILL, DamageType.MAGIC), attack.getStats()).damage((LivingEntity) entity);
loc1.getWorld().spawnParticle(Particle.SPELL_WITCH, loc1, 12, 0, 0, 0, .1);
loc1.getWorld().spawnParticle(Particle.SMOKE_NORMAL, loc1, 6, 0, 0, 0, .1);

View File

@ -52,7 +52,7 @@ public class Black_Hole extends LocationAbility {
}
for (Entity entity : MMOUtils.getNearbyChunkEntities(loc))
if (entity.getLocation().distanceSquared(loc) < Math.pow(radius, 2) && MMOUtils.canDamage(attack.getDamager(), entity))
if (entity.getLocation().distanceSquared(loc) < Math.pow(radius, 2) && MMOUtils.canTarget(attack.getDamager(), entity))
entity.setVelocity(MMOUtils.normalize(loc.clone().subtract(entity.getLocation()).toVector()).multiply(.5));
}
}.runTaskTimer(MMOItems.plugin, 0, 1);

View File

@ -57,7 +57,7 @@ public class Contamination extends LocationAbility {
if (j % 10 == 0) {
loc.getWorld().playSound(loc, VersionSound.ENTITY_ENDERMAN_HURT.toSound(), 2, 1);
for (Entity entity : MMOUtils.getNearbyChunkEntities(loc))
if (MMOUtils.canDamage(attack.getDamager(), entity) && entity.getLocation().distanceSquared(loc) <= 25)
if (MMOUtils.canTarget(attack.getDamager(), entity) && entity.getLocation().distanceSquared(loc) <= 25)
new AttackMetadata(new DamageMetadata(dps, DamageType.SKILL, DamageType.MAGIC), attack.getStats()).damage((LivingEntity) entity, false);
}
}

View File

@ -37,7 +37,7 @@ public class Corrosion extends LocationAbility {
loc.getWorld().playSound(loc, Sound.BLOCK_BREWING_STAND_BREW, 2, 0);
for (Entity entity : MMOUtils.getNearbyChunkEntities(loc))
if (entity.getLocation().distanceSquared(loc) < radiusSquared && MMOUtils.canDamage(attack.getDamager(), entity)) {
if (entity.getLocation().distanceSquared(loc) < radiusSquared && MMOUtils.canTarget(attack.getDamager(), entity)) {
((LivingEntity) entity).removePotionEffect(PotionEffectType.POISON);
((LivingEntity) entity).addPotionEffect(new PotionEffect(PotionEffectType.POISON, duration, amplifier));
}

View File

@ -48,7 +48,7 @@ public class Corrupt extends LocationAbility {
}
for (Entity entity : MMOUtils.getNearbyChunkEntities(loc))
if (MMOUtils.canDamage(attack.getDamager(), entity) && entity.getLocation().distanceSquared(loc) <= radius * radius) {
if (MMOUtils.canTarget(attack.getDamager(), entity) && entity.getLocation().distanceSquared(loc) <= radius * radius) {
new AttackMetadata(new DamageMetadata(damage, DamageType.SKILL, DamageType.MAGIC), attack.getStats()).damage((LivingEntity) entity);
((LivingEntity) entity).removePotionEffect(PotionEffectType.WITHER);
((LivingEntity) entity).addPotionEffect(new PotionEffect(PotionEffectType.WITHER, (int) (duration * 20), (int) amplifier));

View File

@ -44,7 +44,7 @@ public class Freeze extends LocationAbility {
loc.getWorld().playSound(loc, VersionSound.ENTITY_FIREWORK_ROCKET_LARGE_BLAST.toSound(), 2, 1);
for (Entity entity : MMOUtils.getNearbyChunkEntities(loc))
if (entity.getLocation().distanceSquared(loc) < radiusSquared && MMOUtils.canDamage(attack.getDamager(), entity)) {
if (entity.getLocation().distanceSquared(loc) < radiusSquared && MMOUtils.canTarget(attack.getDamager(), entity)) {
((LivingEntity) entity).removePotionEffect(PotionEffectType.SLOW);
((LivingEntity) entity).addPotionEffect(new PotionEffect(PotionEffectType.SLOW, duration, amplifier));
}

View File

@ -60,7 +60,7 @@ public class Freezing_Curse extends LocationAbility {
double duration = ability.getModifier("duration");
double damage = ability.getModifier("damage");
for (Entity entity : MMOUtils.getNearbyChunkEntities(loc))
if (entity.getLocation().distanceSquared(loc) < radius * radius && MMOUtils.canDamage(attack.getDamager(), entity)) {
if (entity.getLocation().distanceSquared(loc) < radius * radius && MMOUtils.canTarget(attack.getDamager(), entity)) {
new AttackMetadata(new DamageMetadata(damage, DamageType.SKILL, DamageType.MAGIC), attack.getStats()).damage((LivingEntity) entity);
((LivingEntity) entity).removePotionEffect(PotionEffectType.SLOW);
((LivingEntity) entity).addPotionEffect(new PotionEffect(PotionEffectType.SLOW, (int) (duration * 20), (int) amplifier));

View File

@ -35,7 +35,7 @@ public class Ignite extends LocationAbility {
loc.getWorld().playSound(loc, VersionSound.ENTITY_FIREWORK_ROCKET_LARGE_BLAST.toSound(), 2, 1);
for (Entity entity : MMOUtils.getNearbyChunkEntities(loc))
if (entity.getLocation().distanceSquared(loc) < radiusSquared && MMOUtils.canDamage(attack.getDamager(), entity))
if (entity.getLocation().distanceSquared(loc) < radiusSquared && MMOUtils.canTarget(attack.getDamager(), entity))
entity.setFireTicks(Math.min(entity.getFireTicks() + ignite, maxIgnite));
}
}

View File

@ -63,7 +63,7 @@ public class Life_Ender extends LocationAbility {
source.getWorld().spawnParticle(Particle.SMOKE_LARGE, source, 0, Math.cos(j), 0, Math.sin(j), .5);
for (Entity entity : MMOUtils.getNearbyChunkEntities(source))
if (entity.getLocation().distanceSquared(source) < radius * radius && MMOUtils.canDamage(attack.getDamager(), entity)) {
if (entity.getLocation().distanceSquared(source) < radius * radius && MMOUtils.canTarget(attack.getDamager(), entity)) {
new AttackMetadata(new DamageMetadata(damage, DamageType.SKILL, DamageType.MAGIC), attack.getStats()).damage((LivingEntity) entity);
entity.setVelocity(entity.getLocation().subtract(source).toVector().setY(.75).normalize().multiply(knockback));
}

View File

@ -32,7 +32,7 @@ public class Lightning_Beam extends LocationAbility {
double radius = ability.getModifier("radius");
for (Entity entity : MMOUtils.getNearbyChunkEntities(loc))
if (MMOUtils.canDamage(attack.getDamager(), entity) && entity.getLocation().distanceSquared(loc) <= radius * radius)
if (MMOUtils.canTarget(attack.getDamager(), entity) && entity.getLocation().distanceSquared(loc) <= radius * radius)
new AttackMetadata(new DamageMetadata(damage, DamageType.SKILL, DamageType.MAGIC), attack.getStats()).damage((LivingEntity) entity);
attack.getDamager().getWorld().playSound(attack.getDamager().getLocation(), VersionSound.ENTITY_FIREWORK_ROCKET_BLAST.toSound(), 1, 0);

View File

@ -38,7 +38,7 @@ public class Minor_Explosion extends LocationAbility {
loc.getWorld().playSound(loc, Sound.ENTITY_GENERIC_EXPLODE, 2, 1);
for (Entity entity : MMOUtils.getNearbyChunkEntities(loc))
if (entity.getLocation().distanceSquared(loc) < radiusSquared && MMOUtils.canDamage(attack.getDamager(), entity)) {
if (entity.getLocation().distanceSquared(loc) < radiusSquared && MMOUtils.canTarget(attack.getDamager(), entity)) {
new AttackMetadata(new DamageMetadata(damage, DamageType.SKILL, DamageType.MAGIC), attack.getStats()).damage((LivingEntity) entity);
entity.setVelocity(MMOUtils.normalize(entity.getLocation().subtract(loc).toVector().setY(0)).setY(.2).multiply(2 * knockback));
}

View File

@ -68,7 +68,7 @@ public class Snowman_Turret extends LocationAbility {
if (ti % 2 == 0)
for (Entity entity : MMOUtils.getNearbyChunkEntities(snowman.getLocation()))
if (!entity.equals(snowman) && MMOUtils.canDamage(attack.getDamager(), entity)
if (!entity.equals(snowman) && MMOUtils.canTarget(attack.getDamager(), entity)
&& entity.getLocation().distanceSquared(snowman.getLocation()) < radiusSquared) {
snowman.getWorld().playSound(snowman.getLocation(), Sound.ENTITY_SNOWBALL_THROW, 1, 1.3f);
Snowball snowball = snowman.launchProjectile(Snowball.class);

View File

@ -62,7 +62,7 @@ public class Arcane_Rift extends Ability<VectorAbilityMetadata> {
loc.getWorld().spawnParticle(Particle.SPELL_WITCH, loc, 5, .5, 0, .5, 0);
for (Entity entity : MMOUtils.getNearbyChunkEntities(loc))
if (MMOUtils.canDamage(attack.getDamager(), entity) && loc.distanceSquared(entity.getLocation()) < 2 && !hit.contains(entity.getEntityId())) {
if (MMOUtils.canTarget(attack.getDamager(), entity) && loc.distanceSquared(entity.getLocation()) < 2 && !hit.contains(entity.getEntityId())) {
hit.add(entity.getEntityId());
new AttackMetadata(new DamageMetadata(damage, DamageType.SKILL, DamageType.MAGIC), attack.getStats()).damage((LivingEntity) entity);
((LivingEntity) entity).addPotionEffect(new PotionEffect(PotionEffectType.SLOW, (int) (slowDuration * 20), (int) slowAmplifier));

View File

@ -61,7 +61,7 @@ public class Earthquake extends Ability<VectorAbilityMetadata> {
loc.getWorld().playSound(loc, Sound.BLOCK_GRAVEL_BREAK, 2, 1);
for (Entity entity : MMOUtils.getNearbyChunkEntities(loc))
if (MMOUtils.canDamage(attack.getDamager(), entity) && loc.distanceSquared(entity.getLocation()) < 2 && !hit.contains(entity.getEntityId())) {
if (MMOUtils.canTarget(attack.getDamager(), entity) && loc.distanceSquared(entity.getLocation()) < 2 && !hit.contains(entity.getEntityId())) {
hit.add(entity.getEntityId());
new AttackMetadata(new DamageMetadata(damage, DamageType.SKILL, DamageType.MAGIC), attack.getStats()).damage((LivingEntity) entity);
((LivingEntity) entity).addPotionEffect(new PotionEffect(PotionEffectType.SLOW, (int) (slowDuration * 20), (int) slowAmplifier));

View File

@ -51,7 +51,7 @@ public class Item_Bomb extends ItemAbility implements Listener {
double slowAmplifier = ability.getModifier("slow-amplifier");
for (Entity entity : item.getEntity().getNearbyEntities(radius, radius, radius))
if (MMOUtils.canDamage(attack.getDamager(), entity)) {
if (MMOUtils.canTarget(attack.getDamager(), entity)) {
new AttackMetadata(new DamageMetadata(damage, DamageType.SKILL, DamageType.PHYSICAL), attack.getStats()).damage((LivingEntity) entity);
((LivingEntity) entity).removePotionEffect(PotionEffectType.SLOW);
((LivingEntity) entity).addPotionEffect(new PotionEffect(PotionEffectType.SLOW, (int) (slowDuration * 20), (int) slowAmplifier));

View File

@ -62,7 +62,7 @@ public class Item_Throw extends ItemAbility implements Listener {
item.getEntity().getWorld().spawnParticle(Particle.CRIT, item.getEntity().getLocation(), 0);
for (Entity target : item.getEntity().getNearbyEntities(1, 1, 1))
if (MMOUtils.canDamage(attack.getDamager(), target)) {
if (MMOUtils.canTarget(attack.getDamager(), target)) {
new AttackMetadata(new DamageMetadata(ability.getModifier("damage"), DamageType.SKILL, DamageType.PHYSICAL, DamageType.PROJECTILE), attack.getStats()).damage((LivingEntity) target);
item.close();
cancel();

View File

@ -57,7 +57,7 @@ public class Burning_Hands extends SimpleAbility {
if (entity.getLocation().distanceSquared(loc) < 60
&& attack.getDamager().getEyeLocation().getDirection()
.angle(entity.getLocation().toVector().subtract(attack.getDamager().getLocation().toVector())) < Math.PI / 6
&& MMOUtils.canDamage(attack.getDamager(), entity))
&& MMOUtils.canTarget(attack.getDamager(), entity))
new AttackMetadata(new DamageMetadata(damage, DamageType.SKILL, DamageType.MAGIC), attack.getStats()).damage((LivingEntity) entity);
}

View File

@ -37,7 +37,7 @@ public class Circular_Slash extends SimpleAbility {
attack.getDamager().getWorld().playSound(attack.getDamager().getLocation(), Sound.ENTITY_ZOMBIE_ATTACK_IRON_DOOR, 2, .5f);
attack.getDamager().addPotionEffect(new PotionEffect(PotionEffectType.SLOW, 2, 254));
for (Entity entity : attack.getDamager().getNearbyEntities(radius, radius, radius)) {
if (MMOUtils.canDamage(attack.getDamager(), entity)) {
if (MMOUtils.canTarget(attack.getDamager(), entity)) {
new AttackMetadata(new DamageMetadata(damage, DamageType.SKILL, DamageType.PHYSICAL), attack.getStats()).damage((LivingEntity) entity);
Vector v1 = entity.getLocation().toVector();
Vector v2 = attack.getDamager().getLocation().toVector();

View File

@ -51,7 +51,7 @@ public class Firefly extends SimpleAbility {
}
for (Entity entity : attack.getDamager().getNearbyEntities(1, 1, 1))
if (MMOUtils.canDamage(attack.getDamager(), entity)) {
if (MMOUtils.canTarget(attack.getDamager(), entity)) {
double damage = ability.getModifier("damage");
double knockback = ability.getModifier("knockback");

View File

@ -49,7 +49,7 @@ public class Frozen_Aura extends SimpleAbility implements Listener {
if (ti % 7 == 0)
for (Entity entity : MMOUtils.getNearbyChunkEntities(attack.getDamager().getLocation()))
if (entity.getLocation().distanceSquared(attack.getDamager().getLocation()) < radiusSquared && MMOUtils.canDamage(attack.getDamager(), entity)) {
if (entity.getLocation().distanceSquared(attack.getDamager().getLocation()) < radiusSquared && MMOUtils.canTarget(attack.getDamager(), entity)) {
((LivingEntity) entity).removePotionEffect(PotionEffectType.SLOW);
((LivingEntity) entity).addPotionEffect(new PotionEffect(PotionEffectType.SLOW, 40, (int) amplifier));
}

View File

@ -47,7 +47,7 @@ public class Light_Dash extends SimpleAbility {
attack.getDamager().getWorld().spawnParticle(Particle.SMOKE_LARGE, attack.getDamager().getLocation().add(0, 1, 0), 0);
attack.getDamager().getWorld().playSound(attack.getDamager().getLocation(), VersionSound.ENTITY_ENDER_DRAGON_FLAP.toSound(), 1, 2);
for (Entity entity : attack.getDamager().getNearbyEntities(1, 1, 1))
if (!hit.contains(entity.getEntityId()) && MMOUtils.canDamage(attack.getDamager(), entity)) {
if (!hit.contains(entity.getEntityId()) && MMOUtils.canTarget(attack.getDamager(), entity)) {
hit.add(entity.getEntityId());
new AttackMetadata(new DamageMetadata(damage, DamageType.SKILL, DamageType.PHYSICAL), attack.getStats()).damage((LivingEntity) entity);
}

View File

@ -37,7 +37,7 @@ public class Overload extends SimpleAbility {
attack.getDamager().addPotionEffect(new PotionEffect(PotionEffectType.SLOW, 2, 254));
for (Entity entity : attack.getDamager().getNearbyEntities(radius, radius, radius))
if (MMOUtils.canDamage(attack.getDamager(), entity))
if (MMOUtils.canTarget(attack.getDamager(), entity))
new AttackMetadata(new DamageMetadata(damage, DamageType.SKILL, DamageType.MAGIC), attack.getStats()).damage((LivingEntity) entity);
double step = 12 + (radius * 2.5);

View File

@ -87,7 +87,7 @@ public class Present_Throw extends SimpleAbility {
item.getEntity().getWorld().spawnParticle(Particle.FIREWORKS_SPARK, item.getEntity().getLocation().add(0, .1, 0), 128, 0, 0, 0, .25);
item.getEntity().getWorld().playSound(item.getEntity().getLocation(), VersionSound.ENTITY_FIREWORK_ROCKET_TWINKLE.toSound(), 2, 1.5f);
for (Entity entity : MMOUtils.getNearbyChunkEntities(item.getEntity().getLocation()))
if (entity.getLocation().distanceSquared(item.getEntity().getLocation()) < radiusSquared && MMOUtils.canDamage(attack.getDamager(), entity))
if (entity.getLocation().distanceSquared(item.getEntity().getLocation()) < radiusSquared && MMOUtils.canTarget(attack.getDamager(), entity))
new AttackMetadata(new DamageMetadata(damage, DamageType.SKILL, DamageType.MAGIC, DamageType.PROJECTILE), attack.getStats()).damage((LivingEntity) entity);
item.close();
cancel();

View File

@ -38,7 +38,7 @@ public class Sky_Smash extends SimpleAbility {
loc.getWorld().spawnParticle(Particle.SMOKE_LARGE, loc, 16, 0, 0, 0, .1);
for (Entity entity : MMOUtils.getNearbyChunkEntities(loc))
if (MMOUtils.canDamage(attack.getDamager(), entity) && entity.getLocation().distanceSquared(loc) < 10) {
if (MMOUtils.canTarget(attack.getDamager(), entity) && entity.getLocation().distanceSquared(loc) < 10) {
new AttackMetadata(new DamageMetadata(damage, DamageType.SKILL, DamageType.PHYSICAL), attack.getStats()).damage((LivingEntity) entity);
Location loc1 = attack.getDamager().getEyeLocation().clone();
loc1.setPitch(-70);

View File

@ -46,7 +46,7 @@ public class Throw_Up extends SimpleAbility implements Listener {
if (j % 5 == 0)
for (Entity entity : MMOUtils.getNearbyChunkEntities(loc))
if (entity.getLocation().distanceSquared(loc) < 40 && attack.getDamager().getEyeLocation().getDirection().angle(entity.getLocation().toVector().subtract(attack.getDamager().getLocation().toVector())) < Math.PI / 6 && MMOUtils.canDamage(attack.getDamager(), entity))
if (entity.getLocation().distanceSquared(loc) < 40 && attack.getDamager().getEyeLocation().getDirection().angle(entity.getLocation().toVector().subtract(attack.getDamager().getLocation().toVector())) < Math.PI / 6 && MMOUtils.canTarget(attack.getDamager(), entity))
new AttackMetadata(new DamageMetadata(dps, DamageType.SKILL, DamageType.PHYSICAL, DamageType.PROJECTILE), attack.getStats()).damage((LivingEntity) entity);
loc.getWorld().playSound(loc, Sound.ENTITY_ZOMBIE_HURT, 1, 1);

View File

@ -59,7 +59,7 @@ public class Tactical_Grenade extends TargetAbility {
loc.getWorld().playSound(loc, Sound.ENTITY_GENERIC_EXPLODE, 2, 1);
for (Entity entity : MMOUtils.getNearbyChunkEntities(loc))
if (!hit.contains(entity.getEntityId()) && MMOUtils.canDamage(attack.getDamager(), entity) && entity.getLocation().distanceSquared(loc) < radius * radius) {
if (!hit.contains(entity.getEntityId()) && MMOUtils.canTarget(attack.getDamager(), entity) && entity.getLocation().distanceSquared(loc) < radius * radius) {
/*
* stop the runnable as soon as the grenade finally hits

View File

@ -72,7 +72,7 @@ public class Bouncy_Fireball extends VectorAbility {
for (Entity entity : MMOUtils.getNearbyChunkEntities(loc))
if (entity.getLocation().distanceSquared(loc) < radius * radius)
if (MMOUtils.canDamage(attack.getDamager(), entity)) {
if (MMOUtils.canTarget(attack.getDamager(), entity)) {
new AttackMetadata(new DamageMetadata(damage, DamageType.SKILL, DamageType.MAGIC, DamageType.PROJECTILE), attack.getStats()).damage((LivingEntity) entity);
entity.setFireTicks((int) (ignite * 20));
}

View File

@ -73,7 +73,7 @@ public class Corrupted_Fangs extends VectorAbility implements Listener {
if (event.getDamager() instanceof EvokerFangs && entities.contains(event.getDamager().getEntityId())) {
event.setCancelled(true);
if (MMOUtils.canDamage(attackMeta.getDamager(), event.getEntity()))
if (MMOUtils.canTarget(attackMeta.getDamager(), event.getEntity()))
attackMeta.damage((LivingEntity) event.getEntity());
}
}

View File

@ -59,13 +59,13 @@ public class Cursed_Beam extends VectorAbility {
}
for (Entity target : entities)
if (MMOUtils.canDamage(attack.getDamager(), loc, target)) {
if (MMOUtils.canTarget(attack.getDamager(), loc, target)) {
effect(target);
double damage = ability.getModifier("damage");
loc.getWorld().playSound(loc, VersionSound.ENTITY_ENDERMAN_TELEPORT.toSound(), 2, .7f);
for (Entity entity : entities)
if (MMOUtils.canDamage(attack.getDamager(), entity) && loc.distanceSquared(entity.getLocation().add(0, 1, 0)) < 9) {
if (MMOUtils.canTarget(attack.getDamager(), entity) && loc.distanceSquared(entity.getLocation().add(0, 1, 0)) < 9) {
new AttackMetadata(new DamageMetadata(damage, DamageType.SKILL, DamageType.MAGIC, DamageType.PROJECTILE), attack.getStats()).damage((LivingEntity) entity);
((LivingEntity) entity).addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, (int) (duration * 20), 0));
}

View File

@ -96,7 +96,7 @@ public class Explosive_Turkey extends VectorAbility implements Listener {
chicken.getWorld().playSound(chicken.getLocation(), Sound.ENTITY_GENERIC_EXPLODE, 2, 1.5f);
for (Entity entity : MMOUtils.getNearbyChunkEntities(chicken.getLocation()))
if (!entity.isDead() && entity.getLocation().distanceSquared(chicken.getLocation()) < radiusSquared
&& MMOUtils.canDamage(attack.getDamager(), entity)) {
&& MMOUtils.canTarget(attack.getDamager(), entity)) {
new AttackMetadata(new DamageMetadata(damage, DamageType.SKILL, DamageType.MAGIC, DamageType.PROJECTILE), attack.getStats()).damage((LivingEntity) entity);
entity.setVelocity(entity.getLocation().toVector().subtract(chicken.getLocation().toVector()).multiply(.1 * knockback)
.setY(.4 * knockback));

View File

@ -56,7 +56,7 @@ public class Fire_Meteor extends VectorAbility {
double knockback = ability.getModifier("knockback");
double radius = ability.getModifier("radius");
for (Entity entity : MMOUtils.getNearbyChunkEntities(loc))
if (MMOUtils.canDamage(attack.getDamager(), entity) && entity.getLocation().distanceSquared(loc) < radius * radius) {
if (MMOUtils.canTarget(attack.getDamager(), entity) && entity.getLocation().distanceSquared(loc) < radius * radius) {
new AttackMetadata(new DamageMetadata(damage, DamageType.SKILL, DamageType.MAGIC, DamageType.PROJECTILE), attack.getStats()).damage((LivingEntity) entity);
entity.setVelocity(entity.getLocation().toVector().subtract(loc.toVector()).multiply(.1 * knockback).setY(.4 * knockback));
}

View File

@ -54,7 +54,7 @@ public class Firebolt extends VectorAbility {
if (random.nextDouble() < .3)
loc.getWorld().spawnParticle(Particle.LAVA, loc, 0);
for (Entity target : entities)
if (MMOUtils.canDamage(attack.getDamager(), loc, target)) {
if (MMOUtils.canTarget(attack.getDamager(), loc, target)) {
loc.getWorld().spawnParticle(Particle.FLAME, loc, 32, 0, 0, 0, .1);
loc.getWorld().spawnParticle(Particle.LAVA, loc, 8, 0, 0, 0, 0);
loc.getWorld().spawnParticle(Particle.EXPLOSION_LARGE, loc, 0);

View File

@ -44,7 +44,7 @@ public class Heavy_Charge extends VectorAbility {
}
for (Entity target : attack.getDamager().getNearbyEntities(1, 1, 1))
if (MMOUtils.canDamage(attack.getDamager(), target)) {
if (MMOUtils.canTarget(attack.getDamager(), target)) {
attack.getDamager().getWorld().playSound(attack.getDamager().getLocation(), Sound.ENTITY_ZOMBIE_ATTACK_IRON_DOOR, 1, 1);
attack.getDamager().getWorld().spawnParticle(Particle.EXPLOSION_LARGE, target.getLocation().add(0, 1, 0), 0);
target.setVelocity(attack.getDamager().getVelocity().setY(0.3).multiply(1.7 * knockback));

View File

@ -59,7 +59,7 @@ public class Holy_Missile extends VectorAbility {
}
for (Entity entity : entities)
if (MMOUtils.canDamage(attack.getDamager(), loc, entity)) {
if (MMOUtils.canTarget(attack.getDamager(), loc, entity)) {
loc.getWorld().spawnParticle(Particle.EXPLOSION_LARGE, loc, 1);
loc.getWorld().spawnParticle(Particle.FIREWORKS_SPARK, loc, 32, 0, 0, 0, .2);
loc.getWorld().playSound(loc, Sound.ENTITY_GENERIC_EXPLODE, 2, 1);

View File

@ -69,7 +69,7 @@ public class Ice_Crystal extends VectorAbility {
}
for (Entity entity : entities)
if (MMOUtils.canDamage(attack.getDamager(), loc, entity)) {
if (MMOUtils.canTarget(attack.getDamager(), loc, entity)) {
loc.getWorld().spawnParticle(Particle.EXPLOSION_LARGE, loc, 0);
loc.getWorld().spawnParticle(Particle.FIREWORKS_SPARK, loc, 48, 0, 0, 0, .2);
loc.getWorld().playSound(loc, Sound.ENTITY_GENERIC_EXPLODE, 2, 1);

View File

@ -1,6 +1,7 @@
package net.Indyuce.mmoitems.ability.list.vector;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.comp.target.InteractionType;
import io.lumine.mythic.lib.damage.DamageMetadata;
import io.lumine.mythic.lib.damage.DamageType;
import net.Indyuce.mmoitems.MMOItems;
@ -37,7 +38,7 @@ public class Shulker_Missile extends VectorAbility implements Listener {
addModifier("duration", 5);
addModifier("mana", 0);
addModifier("stamina", 0);
}
}
@Override
public void whenCast(ItemAttackMetadata attack, VectorAbilityMetadata ability) {
@ -70,27 +71,26 @@ public class Shulker_Missile extends VectorAbility implements Listener {
cancel();
} else
shulkerBullet.setVelocity(vec);
}
}.runTaskTimer(MMOItems.plugin, 0, 1);
}
}.runTaskTimer(MMOItems.plugin, 0, 3);
}
}
}.runTaskTimer(MMOItems.plugin, 0, 1);
}
}.runTaskTimer(MMOItems.plugin, 0, 3);
}
@EventHandler
public void a(EntityDamageByEntityEvent event) {
if (event.getDamager() instanceof ShulkerBullet && event.getEntity() instanceof LivingEntity) {
ShulkerBullet damager = (ShulkerBullet) event.getDamager();
LivingEntity entity = (LivingEntity) event.getEntity();
if (!MMOItems.plugin.getEntities().isCustomEntity(damager))
return;
@EventHandler
public void a(EntityDamageByEntityEvent event) {
if (event.getDamager() instanceof ShulkerBullet && event.getEntity() instanceof LivingEntity) {
ShulkerBullet damager = (ShulkerBullet) event.getDamager();
LivingEntity entity = (LivingEntity) event.getEntity();
if (!MMOItems.plugin.getEntities().isCustomEntity(damager))
return;
if (!MMOUtils.canDamage(entity)) {
ShulkerMissileEntityData data = (ShulkerMissileEntityData) MMOItems.plugin.getEntities().getEntityData(damager);
if (!MMOUtils.canTarget(data.attackMeta.getDamager(), null, entity, data.isWeaponAttack() ? InteractionType.OFFENSE_ACTION : InteractionType.OFFENSE_SKILL)) {
event.setCancelled(true);
return;
}
ShulkerMissileEntityData data = (ShulkerMissileEntityData) MMOItems.plugin.getEntities().getEntityData(damager);
// Void spirit
if (data.isWeaponAttack())
data.attackMeta.applyEffects(data.weapon, entity);
@ -106,23 +106,23 @@ public class Shulker_Missile extends VectorAbility implements Listener {
// Potion effect should apply right after the damage with a 1 tick delay.
if (y == 0) {
entity.removePotionEffect(PotionEffectType.LEVITATION);
entity.addPotionEffect(new PotionEffect(PotionEffectType.LEVITATION, (int) (data.duration * 20), 0));
}
entity.addPotionEffect(new PotionEffect(PotionEffectType.LEVITATION, (int) (data.duration * 20), 0));
}
for (int j1 = 0; j1 < 3; j1++) {
y += .04;
for (int j = 0; j < 2; j++) {
double xz = y * Math.PI * 1.3 + (j * Math.PI);
loc.getWorld().spawnParticle(Particle.REDSTONE, loc.clone().add(Math.cos(xz), y, Math.sin(xz)), 1,
new Particle.DustOptions(Color.MAROON, 1));
}
}
if (y >= 2)
cancel();
}
}.runTaskTimer(MMOItems.plugin, 0, 1);
}
}
for (int j1 = 0; j1 < 3; j1++) {
y += .04;
for (int j = 0; j < 2; j++) {
double xz = y * Math.PI * 1.3 + (j * Math.PI);
loc.getWorld().spawnParticle(Particle.REDSTONE, loc.clone().add(Math.cos(xz), y, Math.sin(xz)), 1,
new Particle.DustOptions(Color.MAROON, 1));
}
}
if (y >= 2)
cancel();
}
}.runTaskTimer(MMOItems.plugin, 0, 1);
}
}
public static class ShulkerMissileEntityData implements EntityData {
private final ItemAttackMetadata attackMeta;
@ -159,6 +159,6 @@ public class Shulker_Missile extends VectorAbility implements Listener {
public boolean isWeaponAttack() {
return attackMeta.getDamage().hasType(DamageType.WEAPON);
}
}
}
}
}

View File

@ -56,7 +56,7 @@ public class TNT_Throw extends VectorAbility implements Listener {
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void a(EntityDamageByEntityEvent event) {
if (event.getDamager().equals(tnt) && !MMOUtils.canDamage(player, event.getEntity()))
if (event.getDamager().equals(tnt) && !MMOUtils.canTarget(player, event.getEntity()))
event.setCancelled(true);
}
}

View File

@ -38,7 +38,7 @@ public class Thrust extends VectorAbility {
for (double j = 0; j < 7; j += .5) {
loc.add(vec);
for (Entity entity : MMOUtils.getNearbyChunkEntities(loc))
if (MMOUtils.canDamage(attack.getDamager(), loc, entity))
if (MMOUtils.canTarget(attack.getDamager(), loc, entity))
new AttackMetadata(new DamageMetadata(damage, DamageType.SKILL, DamageType.PHYSICAL), attack.getStats()).damage((LivingEntity) entity);
loc.getWorld().spawnParticle(Particle.SMOKE_LARGE, loc, 0);
}

View File

@ -1,6 +1,7 @@
package net.Indyuce.mmoitems.ability.metadata;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.comp.target.InteractionType;
import net.Indyuce.mmoitems.MMOUtils;
import net.Indyuce.mmoitems.ability.AbilityMetadata;
import net.Indyuce.mmoitems.stat.data.AbilityData;
@ -13,7 +14,7 @@ public class FriendlyTargetAbilityMetadata extends AbilityMetadata {
public FriendlyTargetAbilityMetadata(AbilityData ability, Player caster, LivingEntity target) {
super(ability);
this.target = target != null ? target : MythicLib.plugin.getVersion().getWrapper().rayTrace(caster, 50, entity -> (entity instanceof Player && MMOUtils.canDamage(caster, entity))).getHit();
this.target = target != null ? target : MythicLib.plugin.getVersion().getWrapper().rayTrace(caster, 50, entity -> entity instanceof Player && MMOUtils.canTarget(caster, entity, InteractionType.SUPPORT_SKILL)).getHit();
}
public LivingEntity getTarget() {

View File

@ -1,6 +1,7 @@
package net.Indyuce.mmoitems.ability.metadata;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.comp.target.InteractionType;
import net.Indyuce.mmoitems.MMOUtils;
import net.Indyuce.mmoitems.ability.AbilityMetadata;
import net.Indyuce.mmoitems.stat.data.AbilityData;
@ -13,7 +14,7 @@ public class TargetAbilityMetadata extends AbilityMetadata {
public TargetAbilityMetadata(AbilityData ability, Player caster, LivingEntity target) {
super(ability);
this.target = target != null ? target : MythicLib.plugin.getVersion().getWrapper().rayTrace(caster, 50, entity -> MMOUtils.canDamage(caster, entity)).getHit();
this.target = target != null ? target : MythicLib.plugin.getVersion().getWrapper().rayTrace(caster, 50, entity -> MMOUtils.canTarget(caster, entity, InteractionType.OFFENSE_SKILL)).getHit();
}
public LivingEntity getTarget() {
@ -21,7 +22,7 @@ public class TargetAbilityMetadata extends AbilityMetadata {
}
@Override
public boolean isSuccessful() {
return target != null;
}
public boolean isSuccessful() {
return target != null;
}
}

View File

@ -1,6 +1,7 @@
package net.Indyuce.mmoitems.api;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.comp.target.InteractionType;
import io.lumine.mythic.lib.damage.DamageMetadata;
import io.lumine.mythic.lib.damage.DamageType;
import io.lumine.mythic.lib.version.VersionMaterial;
@ -52,7 +53,7 @@ public enum Element {
Vector vec = target.getLocation().subtract(attack.getDamager().getLocation()).toVector().normalize().multiply(1.7).setY(.5);
target.setVelocity(vec);
for (Entity entity : target.getNearbyEntities(3, 1, 3))
if (MMOUtils.canDamage(attack.getDamager(), entity)) {
if (MMOUtils.canTarget(attack.getDamager(), entity, InteractionType.OFFENSE_ACTION)) {
entity.playEffect(EntityEffect.HURT);
entity.setVelocity(vec);
}
@ -71,14 +72,14 @@ public enum Element {
target.setVelocity(new Vector(0, 1, 0));
for (Entity entity : target.getNearbyEntities(3, 1, 3))
if (MMOUtils.canDamage(attack.getDamager(), entity))
if (MMOUtils.canTarget(attack.getDamager(), entity, InteractionType.OFFENSE_ACTION))
entity.setVelocity(new Vector(0, 1, 0));
}, 29, 33),
THUNDER(VersionMaterial.GUNPOWDER.toMaterial(), ChatColor.YELLOW, new ElementParticle(Particle.FIREWORKS_SPARK, .05f, 8), (attack, target, damage, absolute) -> {
target.getWorld().playSound(target.getLocation(), VersionSound.ENTITY_FIREWORK_ROCKET_LARGE_BLAST.toSound(), 2, 0);
for (Entity entity : target.getNearbyEntities(3, 2, 3))
if (MMOUtils.canDamage(attack.getDamager(), entity))
if (MMOUtils.canTarget(attack.getDamager(), entity, InteractionType.OFFENSE_ACTION))
MythicLib.plugin.getDamage().damage(new ItemAttackMetadata(new DamageMetadata(attack.getDamage().getDamage() * damage / 100, DamageType.WEAPON), attack.getStats()), (LivingEntity) entity);
attack.getDamage().add(absolute);

View File

@ -1,6 +1,7 @@
package net.Indyuce.mmoitems.api;
import io.lumine.mythic.lib.api.stat.modifier.ModifierSource;
import io.lumine.mythic.lib.comp.target.InteractionType;
import io.lumine.mythic.lib.version.VersionSound;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.MMOUtils;
@ -38,7 +39,7 @@ public enum TypeSet {
if (entity.getLocation().distanceSquared(loc) < 40
&& attack.getDamager().getEyeLocation().getDirection()
.angle(entity.getLocation().subtract(attack.getDamager().getLocation()).toVector()) < Math.PI / 3
&& MMOUtils.canDamage(attack.getDamager(), entity) && !entity.equals(target)) {
&& MMOUtils.canTarget(attack.getDamager(), entity, InteractionType.OFFENSE_ACTION) && !entity.equals(target)) {
ItemAttackMetadata subAttack = new ItemAttackMetadata(attack.getDamage().clone(), attack.getStats());
subAttack.getDamage().multiply(.4);
subAttack.applyEffectsAndDamage(weapon.getNBTItem(), (LivingEntity) entity);
@ -67,7 +68,7 @@ public enum TypeSet {
if (entity.getLocation().distanceSquared(attack.getDamager().getLocation()) < 40
&& attack.getDamager().getEyeLocation().getDirection()
.angle(entity.getLocation().toVector().subtract(attack.getDamager().getLocation().toVector())) < Math.PI / 18
&& MMOUtils.canDamage(attack.getDamager(), entity) && !entity.equals(target)) {
&& MMOUtils.canTarget(attack.getDamager(), entity, InteractionType.OFFENSE_ACTION) && !entity.equals(target)) {
ItemAttackMetadata subAttack = new ItemAttackMetadata(attack.getDamage().clone(), attack.getStats());
subAttack.getDamage().multiply(.4);
subAttack.applyEffectsAndDamage(weapon.getNBTItem(), (LivingEntity) entity);
@ -93,7 +94,7 @@ public enum TypeSet {
double bluntRating = weapon.getValue(attack.getStats().getStat("BLUNT_RATING"),
MMOItems.plugin.getConfig().getDouble("default.blunt-rating")) / 100;
for (Entity entity : target.getNearbyEntities(bluntPower, bluntPower, bluntPower))
if (MMOUtils.canDamage(attack.getDamager(), entity) && !entity.equals(target)) {
if (MMOUtils.canTarget(attack.getDamager(), entity, InteractionType.OFFENSE_ACTION) && !entity.equals(target)) {
ItemAttackMetadata subAttack = new ItemAttackMetadata(attack.getDamage().clone(), attack.getStats());
subAttack.getDamage().multiply(bluntRating);
subAttack.applyEffectsAndDamage(weapon.getNBTItem(), (LivingEntity) entity);

View File

@ -4,12 +4,12 @@ import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.item.ItemTag;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.api.util.SmartGive;
import io.lumine.mythic.lib.comp.flags.CustomFlag;
import net.Indyuce.mmoitems.ItemStats;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.Type;
import net.Indyuce.mmoitems.api.event.item.ConsumableConsumedEvent;
import net.Indyuce.mmoitems.api.item.util.LoreUpdate;
import net.Indyuce.mmoitems.comp.flags.FlagPlugin.CustomFlag;
import net.Indyuce.mmoitems.stat.type.ConsumableItemInteraction;
import net.Indyuce.mmoitems.stat.type.PlayerConsumable;
import org.bukkit.Bukkit;
@ -20,147 +20,147 @@ import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
public class Consumable extends UseItem {
public Consumable(Player player, NBTItem item) {
super(player, item);
}
public Consumable(Player player, NBTItem item) {
super(player, item);
}
@Override
public boolean checkItemRequirements() {
return MMOItems.plugin.getFlags().isFlagAllowed(player, CustomFlag.MI_CONSUMABLES) && playerData.getRPG().canUse(getNBTItem(), true);
}
@Override
public boolean checkItemRequirements() {
return MythicLib.plugin.getFlags().isFlagAllowed(player, CustomFlag.MI_CONSUMABLES) && playerData.getRPG().canUse(getNBTItem(), true);
}
/**
* Applies a consumable onto an item
*
* @param event The click event
* @param target The item on which the consumable is being applied
* @return If the consumable was successfully applied on the item
*/
public boolean useOnItem(@NotNull InventoryClickEvent event, @NotNull NBTItem target) {
if (event.getClickedInventory() != event.getWhoClicked().getInventory())
return false;
/**
* Applies a consumable onto an item
*
* @param event The click event
* @param target The item on which the consumable is being applied
* @return If the consumable was successfully applied on the item
*/
public boolean useOnItem(@NotNull InventoryClickEvent event, @NotNull NBTItem target) {
if (event.getClickedInventory() != event.getWhoClicked().getInventory())
return false;
// Make sure it is an MMOItem
Type targetType = MMOItems.getType(target);
// Make sure it is an MMOItem
Type targetType = MMOItems.getType(target);
for (ConsumableItemInteraction action : MMOItems.plugin.getStats().getConsumableActions())
if (action.handleConsumableEffect(event, playerData, this, target, targetType))
return true;
for (ConsumableItemInteraction action : MMOItems.plugin.getStats().getConsumableActions())
if (action.handleConsumableEffect(event, playerData, this, target, targetType))
return true;
return false;
}
return false;
}
/**
* @deprecated Use {@link Consumable#useOnPlayer()}
*/
@Deprecated
public boolean useWithoutItem() {
return useOnPlayer() == ConsumableConsumeResult.CONSUME;
}
/**
* @deprecated Use {@link Consumable#useOnPlayer()}
*/
@Deprecated
public boolean useWithoutItem() {
return useOnPlayer() == ConsumableConsumeResult.CONSUME;
}
/**
* @return If the item should be consumed
*/
public ConsumableConsumeResult useOnPlayer() {
NBTItem nbtItem = getNBTItem();
/**
* @return If the item should be consumed
*/
public ConsumableConsumeResult useOnPlayer() {
NBTItem nbtItem = getNBTItem();
// Inedible stat cancels this operation from the beginning
if (nbtItem.getBoolean(ItemStats.INEDIBLE.getNBTPath()))
return ConsumableConsumeResult.CANCEL;
// Inedible stat cancels this operation from the beginning
if (nbtItem.getBoolean(ItemStats.INEDIBLE.getNBTPath()))
return ConsumableConsumeResult.CANCEL;
// So a consumable is being consumed, eh
ConsumableConsumedEvent event = new ConsumableConsumedEvent(playerData, mmoitem, this);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled())
return ConsumableConsumeResult.CANCEL;
// So a consumable is being consumed, eh
ConsumableConsumedEvent event = new ConsumableConsumedEvent(playerData, mmoitem, this);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled())
return ConsumableConsumeResult.CANCEL;
// Run through all
for (PlayerConsumable sc : MMOItems.plugin.getStats().getPlayerConsumables())
sc.onConsume(mmoitem, player);
// Run through all
for (PlayerConsumable sc : MMOItems.plugin.getStats().getPlayerConsumables())
sc.onConsume(mmoitem, player);
/**
* If the item does not have a maximum amount of uses, this will always
* return 0 and that portion will just skip.
*
* If the item does have a max amount of uses but it's the last
* use, this portion will skip and the item will be consumed anyways.
*/
int usesLeft = nbtItem.getInteger(ItemStats.MAX_CONSUME.getNBTPath());
if (usesLeft > 1) {
usesLeft -= 1;
nbtItem.addTag(new ItemTag(ItemStats.MAX_CONSUME.getNBTPath(), usesLeft));
/**
* If the item does not have a maximum amount of uses, this will always
* return 0 and that portion will just skip.
*
* If the item does have a max amount of uses but it's the last
* use, this portion will skip and the item will be consumed anyways.
*/
int usesLeft = nbtItem.getInteger(ItemStats.MAX_CONSUME.getNBTPath());
if (usesLeft > 1) {
usesLeft -= 1;
nbtItem.addTag(new ItemTag(ItemStats.MAX_CONSUME.getNBTPath(), usesLeft));
/**
* This dynamically updates the item lore
*/
String format = MythicLib.inst().parseColors(MMOItems.plugin.getLanguage().getStatFormat("max-consume"));
String old = format.replace("#", "" + (usesLeft + 1));
String replaced = format.replace("#", "" + usesLeft);
ItemStack newItem = new LoreUpdate(nbtItem.toItem(), old, replaced).updateLore();
/**
* This dynamically updates the item lore
*/
String format = MythicLib.inst().parseColors(MMOItems.plugin.getLanguage().getStatFormat("max-consume"));
String old = format.replace("#", "" + (usesLeft + 1));
String replaced = format.replace("#", "" + usesLeft);
ItemStack newItem = new LoreUpdate(nbtItem.toItem(), old, replaced).updateLore();
/**
* This fixes the issue when players right click stacked consumables
*/
ItemStack oldItem = nbtItem.getItem();
if (oldItem.getAmount() > 1) {
newItem.setAmount(1);
/**
* This fixes the issue when players right click stacked consumables
*/
ItemStack oldItem = nbtItem.getItem();
if (oldItem.getAmount() > 1) {
newItem.setAmount(1);
if (player.getInventory().getItemInMainHand().equals(oldItem))
player.getInventory().setItemInMainHand(newItem);
else if (player.getInventory().getItemInOffHand().equals(oldItem))
player.getInventory().setItemInOffHand(newItem);
if (player.getInventory().getItemInMainHand().equals(oldItem))
player.getInventory().setItemInMainHand(newItem);
else if (player.getInventory().getItemInOffHand().equals(oldItem))
player.getInventory().setItemInOffHand(newItem);
oldItem.setAmount(oldItem.getAmount() - 1);
new SmartGive(player).give(oldItem);
oldItem.setAmount(oldItem.getAmount() - 1);
new SmartGive(player).give(oldItem);
/**
* Player just holding one item
*/
} else {
if (player.getInventory().getItemInMainHand().equals(oldItem))
player.getInventory().setItemInMainHand(newItem);
else if (player.getInventory().getItemInOffHand().equals(oldItem))
player.getInventory().setItemInOffHand(newItem);
}
/**
* Player just holding one item
*/
} else {
if (player.getInventory().getItemInMainHand().equals(oldItem))
player.getInventory().setItemInMainHand(newItem);
else if (player.getInventory().getItemInOffHand().equals(oldItem))
player.getInventory().setItemInOffHand(newItem);
}
return ConsumableConsumeResult.NOT_CONSUME;
}
return ConsumableConsumeResult.NOT_CONSUME;
}
return !event.isConsumed() || nbtItem.getBoolean(ItemStats.DISABLE_RIGHT_CLICK_CONSUME.getNBTPath()) ? ConsumableConsumeResult.NOT_CONSUME : ConsumableConsumeResult.CONSUME;
}
return !event.isConsumed() || nbtItem.getBoolean(ItemStats.DISABLE_RIGHT_CLICK_CONSUME.getNBTPath()) ? ConsumableConsumeResult.NOT_CONSUME : ConsumableConsumeResult.CONSUME;
}
/**
* @return If an item should be eaten not when right clicked, but after
* the eating animation. This does check if the item is actually edible
*/
public boolean hasVanillaEating() {
return (getItem().getType().isEdible() || getItem().getType() == Material.POTION || getItem().getType() == Material.MILK_BUCKET)
&& getNBTItem().hasTag("MMOITEMS_VANILLA_EATING");
}
/**
* @return If an item should be eaten not when right clicked, but after
* the eating animation. This does check if the item is actually edible
*/
public boolean hasVanillaEating() {
return (getItem().getType().isEdible() || getItem().getType() == Material.POTION || getItem().getType() == Material.MILK_BUCKET)
&& getNBTItem().hasTag("MMOITEMS_VANILLA_EATING");
}
public static enum ConsumableConsumeResult {
public static enum ConsumableConsumeResult {
/**
* No consumable effects or command or cooldowns are applied at all.
* <p>
* This is also used by non edible consumables.
*/
CANCEL,
/**
* No consumable effects or command or cooldowns are applied at all.
* <p>
* This is also used by non edible consumables.
*/
CANCEL,
/**
* Consume was a success and the item needs to be removed
* from the player's inventory.
*/
CONSUME,
/**
* Consume was a success and the item needs to be removed
* from the player's inventory.
*/
CONSUME,
/**
* Consume was a success but the item should not be consumed.
* This is used to handle the 'Max Consumes' item stat.
* consumables with "Disable right click consume' also use this.
* <p>
* Using {@link ConsumableConsumedEvent#setConsumed(boolean)}, external plugins can also make it
* so the consumable is not consumed but its effects are applied.
*/
NOT_CONSUME;
}
/**
* Consume was a success but the item should not be consumed.
* This is used to handle the 'Max Consumes' item stat.
* consumables with "Disable right click consume' also use this.
* <p>
* Using {@link ConsumableConsumedEvent#setConsumed(boolean)}, external plugins can also make it
* so the consumable is not consumed but its effects are applied.
*/
NOT_CONSUME;
}
}

View File

@ -1,64 +1,64 @@
package net.Indyuce.mmoitems.api.interaction;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.UtilityMethods;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.comp.flags.CustomFlag;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.comp.flags.FlagPlugin.CustomFlag;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Particle;
import org.bukkit.Sound;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
public class Tool extends UseItem {
public Tool(Player player, NBTItem item) {
super(player, item);
}
public Tool(Player player, NBTItem item) {
super(player, item);
}
@Override
public boolean checkItemRequirements() {
return MMOItems.plugin.getFlags().isFlagAllowed(player, CustomFlag.MI_TOOLS) && playerData.getRPG().canUse(getNBTItem(), true);
}
@Override
public boolean checkItemRequirements() {
return MythicLib.plugin.getFlags().isFlagAllowed(player, CustomFlag.MI_TOOLS) && playerData.getRPG().canUse(getNBTItem(), true);
}
public boolean miningEffects(Block block) {
boolean cancel = false;
if (getNBTItem().getBoolean("MMOITEMS_AUTOSMELT"))
if (block.getType() == Material.IRON_ORE || block.getType() == Material.GOLD_ORE) {
ItemStack item = new ItemStack(Material.valueOf(block.getType().name().replace("_ORE", "_INGOT")));
public boolean miningEffects(Block block) {
boolean cancel = false;
UtilityMethods.dropItemNaturally(block.getLocation(), item);
block.getWorld().spawnParticle(Particle.CLOUD, block.getLocation().add(.5, .5, .5), 0);
block.setType(Material.AIR);
cancel = true;
}
if (getNBTItem().getBoolean("MMOITEMS_AUTOSMELT"))
if (block.getType() == Material.IRON_ORE || block.getType() == Material.GOLD_ORE) {
ItemStack item = new ItemStack(Material.valueOf(block.getType().name().replace("_ORE", "_INGOT")));
if (getNBTItem().getBoolean("MMOITEMS_BOUNCING_CRACK"))
new BukkitRunnable() {
final Vector v = player.getEyeLocation().getDirection().multiply(.5);
final Location loc = block.getLocation().clone().add(.5, .5, .5);
int j = 0;
UtilityMethods.dropItemNaturally(block.getLocation(), item);
block.getWorld().spawnParticle(Particle.CLOUD, block.getLocation().add(.5, .5, .5), 0);
block.setType(Material.AIR);
cancel = true;
}
public void run() {
j++;
if (j > 10)
cancel();
if (getNBTItem().getBoolean("MMOITEMS_BOUNCING_CRACK"))
new BukkitRunnable() {
final Vector v = player.getEyeLocation().getDirection().multiply(.5);
final Location loc = block.getLocation().clone().add(.5, .5, .5);
int j = 0;
loc.add(v);
Block block = loc.getBlock();
if (block.getType() == Material.AIR || MMOItems.plugin.getLanguage().isBlacklisted(block.getType()))
return;
public void run() {
j++;
if (j > 10)
cancel();
block.breakNaturally(getItem());
loc.getWorld().playSound(loc, Sound.BLOCK_GRAVEL_BREAK, 1, 1);
}
}.runTaskTimer(MMOItems.plugin, 0, 1);
loc.add(v);
Block block = loc.getBlock();
if (block.getType() == Material.AIR || MMOItems.plugin.getLanguage().isBlacklisted(block.getType()))
return;
block.breakNaturally(getItem());
loc.getWorld().playSound(loc, Sound.BLOCK_GRAVEL_BREAK, 1, 1);
}
}.runTaskTimer(MMOItems.plugin, 0, 1);
/*if (getNBTItem().hasTag("MMOITEMS_BREAK_SIZE")) {
int breakSize = getNBTItem().getInteger("MMOITEMS_BREAK_SIZE");
@ -67,6 +67,6 @@ public class Tool extends UseItem {
System.out.println("Debug: Facing - " + face);
}
}*/
return cancel;
}
return cancel;
}
}

View File

@ -1,6 +1,8 @@
package net.Indyuce.mmoitems.api.interaction;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.comp.flags.CustomFlag;
import net.Indyuce.mmoitems.ItemStats;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.Type;
@ -9,7 +11,6 @@ import net.Indyuce.mmoitems.api.interaction.weapon.Weapon;
import net.Indyuce.mmoitems.api.interaction.weapon.untargeted.*;
import net.Indyuce.mmoitems.api.item.mmoitem.VolatileMMOItem;
import net.Indyuce.mmoitems.api.player.PlayerData;
import net.Indyuce.mmoitems.comp.flags.FlagPlugin.CustomFlag;
import net.Indyuce.mmoitems.stat.data.CommandData;
import net.Indyuce.mmoitems.stat.data.CommandListData;
import org.bukkit.Bukkit;
@ -20,128 +21,128 @@ import org.jetbrains.annotations.NotNull;
import java.util.Random;
public class UseItem {
protected final Player player;
protected final PlayerData playerData;
protected final VolatileMMOItem mmoitem;
protected final Player player;
protected final PlayerData playerData;
protected final VolatileMMOItem mmoitem;
protected static final Random RANDOM = new Random();
protected static final Random RANDOM = new Random();
public UseItem(Player player, NBTItem nbtItem) {
this(PlayerData.get(player), nbtItem);
}
public UseItem(Player player, NBTItem nbtItem) {
this(PlayerData.get(player), nbtItem);
}
public UseItem(PlayerData playerData, NBTItem nbtItem) {
this.player = playerData.getPlayer();
this.playerData = playerData;
this.mmoitem = new VolatileMMOItem(nbtItem);
}
public UseItem(PlayerData playerData, NBTItem nbtItem) {
this.player = playerData.getPlayer();
this.playerData = playerData;
this.mmoitem = new VolatileMMOItem(nbtItem);
}
public Player getPlayer() {
return player;
}
public Player getPlayer() {
return player;
}
public PlayerData getPlayerData() {
return playerData;
}
public PlayerData getPlayerData() {
return playerData;
}
public VolatileMMOItem getMMOItem() {
return mmoitem;
}
public VolatileMMOItem getMMOItem() {
return mmoitem;
}
public NBTItem getNBTItem() {
return mmoitem.getNBT();
}
public NBTItem getNBTItem() {
return mmoitem.getNBT();
}
public ItemStack getItem() {
return mmoitem.getNBT().getItem();
}
public ItemStack getItem() {
return mmoitem.getNBT().getItem();
}
/**
* Apply item costs and requirements. This method should be overriden to
* check for WorldGuard flags as well as the two-handed restriction.
*
* @return If the item can be used
*/
public boolean checkItemRequirements() {
return playerData.getRPG().canUse(mmoitem.getNBT(), true);
}
/**
* Apply item costs and requirements. This method should be overriden to
* check for WorldGuard flags as well as the two-handed restriction.
*
* @return If the item can be used
*/
public boolean checkItemRequirements() {
return playerData.getRPG().canUse(mmoitem.getNBT(), true);
}
/**
* Execute commands after checking for WG flags;
* this does NOT check for the command cooldown.
*/
public void executeCommands() {
if (MMOItems.plugin.getFlags().isFlagAllowed(player, CustomFlag.MI_COMMANDS) && mmoitem.hasData(ItemStats.COMMANDS))
((CommandListData) mmoitem.getData(ItemStats.COMMANDS)).getCommands().forEach(this::scheduleCommandExecution);
}
/**
* Execute commands after checking for WG flags;
* this does NOT check for the command cooldown.
*/
public void executeCommands() {
if (MythicLib.plugin.getFlags().isFlagAllowed(player, CustomFlag.MI_COMMANDS) && mmoitem.hasData(ItemStats.COMMANDS))
((CommandListData) mmoitem.getData(ItemStats.COMMANDS)).getCommands().forEach(this::scheduleCommandExecution);
}
/**
* Instantly fires the command if it has no delay
* or schedule its execution if it does have some
*
* @param command Command to execute
*/
private void scheduleCommandExecution(CommandData command) {
String parsed = MMOItems.plugin.getPlaceholderParser().parse(player, command.getCommand());
/**
* Instantly fires the command if it has no delay
* or schedule its execution if it does have some
*
* @param command Command to execute
*/
private void scheduleCommandExecution(CommandData command) {
String parsed = MMOItems.plugin.getPlaceholderParser().parse(player, command.getCommand());
if (!command.hasDelay())
dispatchCommand(parsed, command.isConsoleCommand(), command.hasOpPerms());
else
Bukkit.getScheduler().runTaskLater(MMOItems.plugin, () -> dispatchCommand(parsed, command.isConsoleCommand(), command.hasOpPerms()),
(long) command.getDelay() * 20);
}
if (!command.hasDelay())
dispatchCommand(parsed, command.isConsoleCommand(), command.hasOpPerms());
else
Bukkit.getScheduler().runTaskLater(MMOItems.plugin, () -> dispatchCommand(parsed, command.isConsoleCommand(), command.hasOpPerms()),
(long) command.getDelay() * 20);
}
/**
* Dispatches a command
*
* @param parsed Command with placeholders already parsed
* @param console If the console should dispatch the command, when
* set to false the player dispatches it.
* @param op Very dangerous option, dispatches the command
* as a server administrator
*/
private void dispatchCommand(String parsed, boolean console, boolean op) {
if (console) {
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), parsed);
return;
}
/**
* Dispatches a command
*
* @param parsed Command with placeholders already parsed
* @param console If the console should dispatch the command, when
* set to false the player dispatches it.
* @param op Very dangerous option, dispatches the command
* as a server administrator
*/
private void dispatchCommand(String parsed, boolean console, boolean op) {
if (console) {
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), parsed);
return;
}
if (op && !player.isOp()) {
player.setOp(true);
try {
Bukkit.dispatchCommand(player, parsed);
} catch (Exception ignored) {
player.setOp(false);
} finally {
player.setOp(false);
}
} else
Bukkit.dispatchCommand(player, parsed);
}
if (op && !player.isOp()) {
player.setOp(true);
try {
Bukkit.dispatchCommand(player, parsed);
} catch (Exception ignored) {
player.setOp(false);
} finally {
player.setOp(false);
}
} else
Bukkit.dispatchCommand(player, parsed);
}
public static UseItem getItem(Player player, NBTItem item, String type) {
return getItem(player, item, Type.get(type));
}
public static UseItem getItem(Player player, NBTItem item, String type) {
return getItem(player, item, Type.get(type));
}
public static UseItem getItem(@NotNull Player player, @NotNull NBTItem item, @NotNull Type type) {
if (type.corresponds(Type.CONSUMABLE))
return new Consumable(player, item);
if (type.corresponds(Type.SKIN))
return new ItemSkin(player, item);
if (type.corresponds(Type.GEM_STONE))
return new GemStone(player, item);
if (type.corresponds(Type.MUSKET))
return new Musket(player, item);
if (type.corresponds(Type.CROSSBOW))
return new Crossbow(player, item);
if (type.corresponds(Type.GAUNTLET))
return new Gauntlet(player, item);
if (type.corresponds(Type.WHIP))
return new Whip(player, item);
if (type.corresponds(Type.LUTE))
return new Lute(player, item);
if (type.corresponds(Type.STAFF))
return new Staff(player, item);
return type.isWeapon() ? new Weapon(player, item) : new UseItem(player, item);
}
public static UseItem getItem(@NotNull Player player, @NotNull NBTItem item, @NotNull Type type) {
if (type.corresponds(Type.CONSUMABLE))
return new Consumable(player, item);
if (type.corresponds(Type.SKIN))
return new ItemSkin(player, item);
if (type.corresponds(Type.GEM_STONE))
return new GemStone(player, item);
if (type.corresponds(Type.MUSKET))
return new Musket(player, item);
if (type.corresponds(Type.CROSSBOW))
return new Crossbow(player, item);
if (type.corresponds(Type.GAUNTLET))
return new Gauntlet(player, item);
if (type.corresponds(Type.WHIP))
return new Whip(player, item);
if (type.corresponds(Type.LUTE))
return new Lute(player, item);
if (type.corresponds(Type.STAFF))
return new Staff(player, item);
return type.isWeapon() ? new Weapon(player, item) : new UseItem(player, item);
}
}

View File

@ -1,15 +1,14 @@
package net.Indyuce.mmoitems.api.interaction.weapon;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.comp.flags.CustomFlag;
import net.Indyuce.mmoitems.ItemStats;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.ItemAttackMetadata;
import net.Indyuce.mmoitems.api.interaction.UseItem;
import net.Indyuce.mmoitems.api.player.PlayerData;
import net.Indyuce.mmoitems.api.player.PlayerData.CooldownType;
import net.Indyuce.mmoitems.api.util.message.Message;
import net.Indyuce.mmoitems.comp.flags.FlagPlugin;
import net.Indyuce.mmoitems.comp.flags.FlagPlugin.CustomFlag;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.entity.LivingEntity;
@ -18,102 +17,96 @@ import org.bukkit.entity.Player;
import javax.annotation.Nullable;
public class Weapon extends UseItem {
public Weapon(Player player, NBTItem item) {
this(PlayerData.get(player), item);
}
public Weapon(Player player, NBTItem item) {
this(PlayerData.get(player), item);
}
public Weapon(PlayerData playerData, NBTItem item) {
super(playerData, item);
}
public Weapon(PlayerData playerData, NBTItem item) {
super(playerData, item);
}
@Override
public boolean checkItemRequirements() {
if (playerData.areHandsFull()) {
Message.HANDS_TOO_CHARGED.format(ChatColor.RED).send(getPlayer());
return false;
}
@Override
public boolean checkItemRequirements() {
if (playerData.areHandsFull()) {
Message.HANDS_TOO_CHARGED.format(ChatColor.RED).send(getPlayer());
return false;
}
// Check for class, level...
boolean asCanUse = playerData.getRPG().canUse(getNBTItem(), true);
// Check for class, level... then flags
return playerData.getRPG().canUse(getNBTItem(), true) && MythicLib.plugin.getFlags().isFlagAllowed(getPlayer(), CustomFlag.MI_WEAPONS);
}
// Check for flags
FlagPlugin flagPlugin = MMOItems.plugin.getFlags();
boolean asFlagAllowed = flagPlugin == null || flagPlugin.isFlagAllowed(getPlayer(), CustomFlag.MI_WEAPONS);
/**
* Only applies mana and stamina weapon costs
*
* @return If the attack was cast successfully
*/
public boolean applyWeaponCosts() {
return applyWeaponCosts(0, null);
}
return asCanUse && asFlagAllowed;
}
/**
* Applies cooldown, mana and stamina weapon costs
*
* @param attackSpeed The weapon attack speed
* @param cooldown The weapon cooldown type. When set to null, no
* cooldown will be applied. This is made to handle
* @return If requirements were met ie the attack was cast successfully
*/
public boolean applyWeaponCosts(double attackSpeed, @Nullable CooldownType cooldown) {
if (cooldown != null && getPlayerData().isOnCooldown(cooldown))
return false;
/**
* Only applies mana and stamina weapon costs
*
* @return If the attack was cast successfully
*/
public boolean applyWeaponCosts() {
return applyWeaponCosts(0, null);
}
double manaCost = getNBTItem().getStat("MANA_COST");
if (manaCost > 0 && playerData.getRPG().getMana() < manaCost) {
Message.NOT_ENOUGH_MANA.format(ChatColor.RED).send(getPlayer());
return false;
}
/**
* Applies cooldown, mana and stamina weapon costs
*
* @param attackSpeed The weapon attack speed
* @param cooldown The weapon cooldown type. When set to null, no
* cooldown will be applied. This is made to handle
* @return If requirements were met ie the attack was cast successfully
*/
public boolean applyWeaponCosts(double attackSpeed, @Nullable CooldownType cooldown) {
if (cooldown != null && getPlayerData().isOnCooldown(cooldown))
return false;
double staminaCost = getNBTItem().getStat("STAMINA_COST");
if (staminaCost > 0 && playerData.getRPG().getStamina() < staminaCost) {
Message.NOT_ENOUGH_STAMINA.format(ChatColor.RED).send(getPlayer());
return false;
}
double manaCost = getNBTItem().getStat("MANA_COST");
if (manaCost > 0 && playerData.getRPG().getMana() < manaCost) {
Message.NOT_ENOUGH_MANA.format(ChatColor.RED).send(getPlayer());
return false;
}
if (manaCost > 0)
playerData.getRPG().giveMana(-manaCost);
double staminaCost = getNBTItem().getStat("STAMINA_COST");
if (staminaCost > 0 && playerData.getRPG().getStamina() < staminaCost) {
Message.NOT_ENOUGH_STAMINA.format(ChatColor.RED).send(getPlayer());
return false;
}
if (staminaCost > 0)
playerData.getRPG().giveStamina(-staminaCost);
if (manaCost > 0)
playerData.getRPG().giveMana(-manaCost);
if (cooldown != null)
getPlayerData().applyCooldown(cooldown, attackSpeed);
if (staminaCost > 0)
playerData.getRPG().giveStamina(-staminaCost);
return true;
}
if (cooldown != null)
getPlayerData().applyCooldown(cooldown, attackSpeed);
public ItemAttackMetadata handleTargetedAttack(ItemAttackMetadata attackMeta, LivingEntity target) {
return true;
}
// Handle weapon cooldown, mana and stamina costs
double attackSpeed = getNBTItem().getStat(ItemStats.ATTACK_SPEED.getId());
attackSpeed = attackSpeed == 0 ? 1.493 : 1 / attackSpeed;
if (!applyWeaponCosts())
return attackMeta.setSuccessful(false);
public ItemAttackMetadata handleTargetedAttack(ItemAttackMetadata attackMeta, LivingEntity target) {
// Handle item set attack effects
if (getMMOItem().getType().getItemSet().hasAttackEffect() && !getNBTItem().getBoolean("MMOITEMS_DISABLE_ATTACK_PASSIVE"))
getMMOItem().getType().getItemSet().applyAttackEffect(attackMeta, target, this);
// Handle weapon cooldown, mana and stamina costs
double attackSpeed = getNBTItem().getStat(ItemStats.ATTACK_SPEED.getId());
attackSpeed = attackSpeed == 0 ? 1.493 : 1 / attackSpeed;
if (!applyWeaponCosts())
return attackMeta.setSuccessful(false);
return attackMeta;
}
// Handle item set attack effects
if (getMMOItem().getType().getItemSet().hasAttackEffect() && !getNBTItem().getBoolean("MMOITEMS_DISABLE_ATTACK_PASSIVE"))
getMMOItem().getType().getItemSet().applyAttackEffect(attackMeta, target, this);
protected Location getGround(Location loc) {
for (int j = 0; j < 20; j++) {
if (loc.getBlock().getType().isSolid())
return loc;
loc.add(0, -1, 0);
}
return loc;
}
return attackMeta;
}
protected Location getGround(Location loc) {
for (int j = 0; j < 20; j++) {
if (loc.getBlock().getType().isSolid())
return loc;
loc.add(0, -1, 0);
}
return loc;
}
// returns default getValue if stat equals 0
public double getValue(double a, double def) {
return a <= 0 ? def : a;
}
// returns default getValue if stat equals 0
public double getValue(double a, double def) {
return a <= 0 ? def : a;
}
}

View File

@ -4,6 +4,7 @@ import com.google.gson.JsonObject;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.api.stat.StatMap;
import io.lumine.mythic.lib.comp.target.InteractionType;
import io.lumine.mythic.lib.damage.DamageMetadata;
import io.lumine.mythic.lib.damage.DamageType;
import io.lumine.mythic.lib.version.VersionSound;
@ -101,7 +102,7 @@ public class Lute extends UntargetedWeapon {
}
for (Entity target : entities)
if (MMOUtils.canDamage(getPlayer(), loc, target)) {
if (MMOUtils.canTarget(getPlayer(), loc, target, InteractionType.OFFENSE_ACTION)) {
attackMeta.applyEffectsAndDamage(getNBTItem(), (LivingEntity) target);
cancel();
return;

View File

@ -4,6 +4,7 @@ import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.MMORayTraceResult;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.api.stat.StatMap;
import io.lumine.mythic.lib.comp.target.InteractionType;
import io.lumine.mythic.lib.damage.DamageMetadata;
import io.lumine.mythic.lib.damage.DamageType;
import net.Indyuce.mmoitems.ItemStats;
@ -57,7 +58,7 @@ public class Musket extends UntargetedWeapon {
Vector vec = loc.getDirection();
MMORayTraceResult trace = MythicLib.plugin.getVersion().getWrapper().rayTrace(stats.getPlayer(), vec, range,
entity -> MMOUtils.canDamage(stats.getPlayer(), entity));
entity -> MMOUtils.canTarget(stats.getPlayer(), entity, InteractionType.OFFENSE_ACTION));
if (trace.hasHit()) {
ItemAttackMetadata attackMeta = new ItemAttackMetadata(new DamageMetadata(attackDamage, DamageType.WEAPON, DamageType.PROJECTILE, DamageType.PHYSICAL), stats);
attackMeta.applyEffectsAndDamage(getNBTItem(), trace.getHit());

View File

@ -4,6 +4,7 @@ import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.MMORayTraceResult;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.api.stat.StatMap;
import io.lumine.mythic.lib.comp.target.InteractionType;
import io.lumine.mythic.lib.damage.DamageMetadata;
import io.lumine.mythic.lib.damage.DamageType;
import io.lumine.mythic.lib.version.VersionSound;
@ -59,7 +60,7 @@ public class Staff extends UntargetedWeapon {
Location loc = getPlayer().getEyeLocation().add(new Vector(Math.cos(a), 0, Math.sin(a)).multiply(.5));
MMORayTraceResult trace = MythicLib.plugin.getVersion().getWrapper().rayTrace(stats.getPlayer(), range,
entity -> MMOUtils.canDamage(stats.getPlayer(), entity));
entity -> MMOUtils.canTarget(stats.getPlayer(), entity, InteractionType.OFFENSE_ACTION));
if (trace.hasHit())
attackMeta.applyEffectsAndDamage(getNBTItem(), trace.getHit());
trace.draw(loc, getPlayer().getEyeLocation().getDirection(), 2,

View File

@ -4,6 +4,7 @@ import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.MMORayTraceResult;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.api.stat.StatMap;
import io.lumine.mythic.lib.comp.target.InteractionType;
import io.lumine.mythic.lib.damage.DamageMetadata;
import io.lumine.mythic.lib.damage.DamageType;
import io.lumine.mythic.lib.version.VersionSound;
@ -46,7 +47,7 @@ public class Whip extends UntargetedWeapon {
Location loc = getPlayer().getEyeLocation().add(new Vector(Math.cos(a), 0, Math.sin(a)).multiply(.5));
MMORayTraceResult trace = MythicLib.plugin.getVersion().getWrapper().rayTrace(stats.getPlayer(), range,
entity -> MMOUtils.canDamage(stats.getPlayer(), entity));
entity -> MMOUtils.canTarget(stats.getPlayer(), entity, InteractionType.OFFENSE_ACTION));
if (trace.hasHit())
new ItemAttackMetadata(new DamageMetadata(attackDamage, DamageType.WEAPON, DamageType.PROJECTILE, DamageType.PHYSICAL), stats).applyEffects(getNBTItem(), trace.getHit());
trace.draw(loc, getPlayer().getEyeLocation().getDirection(), 2,

View File

@ -3,6 +3,7 @@ package net.Indyuce.mmoitems.api.interaction.weapon.untargeted.lute;
import com.google.gson.JsonObject;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.comp.target.InteractionType;
import io.lumine.mythic.lib.damage.DamageMetadata;
import io.lumine.mythic.lib.damage.DamageType;
import net.Indyuce.mmoitems.MMOItems;
@ -21,53 +22,53 @@ import java.util.List;
public class BruteLuteAttack implements LuteAttackHandler {
@Override
public void handle(ItemAttackMetadata attack, NBTItem nbt, double attackDamage, double range, Vector weight, SoundReader sound) {
new BukkitRunnable() {
final Vector vec = attack.getDamager().getEyeLocation().getDirection().multiply(.4);
final Location loc = attack.getDamager().getEyeLocation();
int ti = 0;
@Override
public void handle(ItemAttackMetadata attack, NBTItem nbt, double attackDamage, double range, Vector weight, SoundReader sound) {
new BukkitRunnable() {
final Vector vec = attack.getDamager().getEyeLocation().getDirection().multiply(.4);
final Location loc = attack.getDamager().getEyeLocation();
int ti = 0;
public void run() {
if (ti++ > range)
cancel();
public void run() {
if (ti++ > range)
cancel();
List<Entity> entities = MMOUtils.getNearbyChunkEntities(loc);
for (int j = 0; j < 3; j++) {
loc.add(vec.add(weight));
if (loc.getBlock().getType().isSolid()) {
cancel();
break;
}
List<Entity> entities = MMOUtils.getNearbyChunkEntities(loc);
for (int j = 0; j < 3; j++) {
loc.add(vec.add(weight));
if (loc.getBlock().getType().isSolid()) {
cancel();
break;
}
if (nbt.hasTag("MMOITEMS_PROJECTILE_PARTICLES")) {
JsonObject obj = MythicLib.plugin.getJson().parse(nbt.getString("MMOITEMS_PROJECTILE_PARTICLES"), JsonObject.class);
Particle particle = Particle.valueOf(obj.get("Particle").getAsString());
// If the selected particle is colored, use the provided color
if (ProjectileParticlesData.isColorable(particle)) {
double red = Double.parseDouble(String.valueOf(obj.get("Red")));
double green = Double.parseDouble(String.valueOf(obj.get("Green")));
double blue = Double.parseDouble(String.valueOf(obj.get("Blue")));
ProjectileParticlesData.shootParticle(attack.getDamager(), particle, loc, red, green, blue);
// If it's not colored, just shoot the particle
} else {
ProjectileParticlesData.shootParticle(attack.getDamager(), particle, loc, 0, 0, 0);
}
// If no particle has been provided via projectile particle attribute, default to this particle
} else
loc.getWorld().spawnParticle(Particle.NOTE, loc, 2, .1, .1, .1, 0);
if (nbt.hasTag("MMOITEMS_PROJECTILE_PARTICLES")) {
JsonObject obj = MythicLib.plugin.getJson().parse(nbt.getString("MMOITEMS_PROJECTILE_PARTICLES"), JsonObject.class);
Particle particle = Particle.valueOf(obj.get("Particle").getAsString());
// If the selected particle is colored, use the provided color
if (ProjectileParticlesData.isColorable(particle)) {
double red = Double.parseDouble(String.valueOf(obj.get("Red")));
double green = Double.parseDouble(String.valueOf(obj.get("Green")));
double blue = Double.parseDouble(String.valueOf(obj.get("Blue")));
ProjectileParticlesData.shootParticle(attack.getDamager(), particle, loc, red, green, blue);
// If it's not colored, just shoot the particle
} else {
ProjectileParticlesData.shootParticle(attack.getDamager(), particle, loc, 0, 0, 0);
}
// If no particle has been provided via projectile particle attribute, default to this particle
} else
loc.getWorld().spawnParticle(Particle.NOTE, loc, 2, .1, .1, .1, 0);
if (j == 0) sound.play(loc, 2, (float) (.5 + (double) ti / range));
if (j == 0) sound.play(loc, 2, (float) (.5 + (double) ti / range));
for (Entity target : entities)
if (MMOUtils.canDamage(attack.getDamager(), loc, target)) {
new ItemAttackMetadata(new DamageMetadata(attackDamage, DamageType.WEAPON, DamageType.PHYSICAL, DamageType.PROJECTILE), attack.getStats()).applyEffectsAndDamage(nbt, (LivingEntity) target);
cancel();
return;
}
}
}
}.runTaskTimer(MMOItems.plugin, 0, 1);
}
for (Entity target : entities)
if (MMOUtils.canTarget(attack.getDamager(), loc, target, InteractionType.OFFENSE_ACTION)) {
new ItemAttackMetadata(new DamageMetadata(attackDamage, DamageType.WEAPON, DamageType.PHYSICAL, DamageType.PROJECTILE), attack.getStats()).applyEffectsAndDamage(nbt, (LivingEntity) target);
cancel();
return;
}
}
}
}.runTaskTimer(MMOItems.plugin, 0, 1);
}
}

View File

@ -3,6 +3,7 @@ package net.Indyuce.mmoitems.api.interaction.weapon.untargeted.lute;
import com.google.gson.JsonObject;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.comp.target.InteractionType;
import io.lumine.mythic.lib.damage.DamageMetadata;
import io.lumine.mythic.lib.damage.DamageType;
import net.Indyuce.mmoitems.MMOItems;
@ -67,7 +68,7 @@ public class CircularLuteAttack implements LuteAttackHandler {
if (j == 0) sound.play(loc, 2, (float) (.5 + (double) ti / range));
for (Entity target : entities)
if (MMOUtils.canDamage(attack.getDamager(), loc, target)) {
if (MMOUtils.canTarget(attack.getDamager(), loc, target, InteractionType.OFFENSE_ACTION)) {
new ItemAttackMetadata(new DamageMetadata(attackDamage, DamageType.WEAPON, DamageType.PROJECTILE), attack.getStats()).applyEffectsAndDamage(nbt, (LivingEntity) target);
cancel();
return;

View File

@ -3,6 +3,7 @@ package net.Indyuce.mmoitems.api.interaction.weapon.untargeted.lute;
import com.google.gson.JsonObject;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.comp.target.InteractionType;
import io.lumine.mythic.lib.damage.DamageMetadata;
import io.lumine.mythic.lib.damage.DamageType;
import net.Indyuce.mmoitems.MMOItems;
@ -60,7 +61,7 @@ public class SimpleLuteAttack implements LuteAttackHandler {
if (j == 0) sound.play(loc, 2, (float) (.5 + (double) ti / range));
for (Entity target : entities)
if (MMOUtils.canDamage(attack.getDamager(), loc, target)) {
if (MMOUtils.canTarget(attack.getDamager(), loc, target, InteractionType.OFFENSE_ACTION)) {
new ItemAttackMetadata(new DamageMetadata(attackDamage, DamageType.WEAPON, DamageType.PROJECTILE), attack.getStats()).applyEffectsAndDamage(nbt, (LivingEntity) target);
cancel();
return;

View File

@ -3,6 +3,7 @@ package net.Indyuce.mmoitems.api.interaction.weapon.untargeted.lute;
import com.google.gson.JsonObject;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.comp.target.InteractionType;
import io.lumine.mythic.lib.damage.DamageMetadata;
import io.lumine.mythic.lib.damage.DamageType;
import net.Indyuce.mmoitems.MMOItems;
@ -58,7 +59,7 @@ public class SlashLuteAttack implements LuteAttackHandler {
}.runTaskTimer(MMOItems.plugin, 0, 1);
for (Entity entity : MMOUtils.getNearbyChunkEntities(attack.getDamager().getLocation()))
if (entity.getLocation().distanceSquared(attack.getDamager().getLocation()) < 40 && attack.getDamager().getEyeLocation().getDirection().angle(entity.getLocation().toVector().subtract(attack.getDamager().getLocation().toVector())) < Math.PI / 6 && MMOUtils.canDamage(attack.getDamager(), entity))
if (entity.getLocation().distanceSquared(attack.getDamager().getLocation()) < 40 && attack.getDamager().getEyeLocation().getDirection().angle(entity.getLocation().toVector().subtract(attack.getDamager().getLocation().toVector())) < Math.PI / 6 && MMOUtils.canTarget(attack.getDamager(), entity, InteractionType.OFFENSE_ACTION))
new ItemAttackMetadata(new DamageMetadata(attackDamage, DamageType.WEAPON, DamageType.PROJECTILE), attack.getStats()).applyEffectsAndDamage(nbt, (LivingEntity) entity);
}
}

View File

@ -3,6 +3,7 @@ package net.Indyuce.mmoitems.api.interaction.weapon.untargeted.lute;
import com.google.gson.JsonObject;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.comp.target.InteractionType;
import io.lumine.mythic.lib.damage.DamageMetadata;
import io.lumine.mythic.lib.damage.DamageType;
import net.Indyuce.mmoitems.MMOItems;
@ -65,7 +66,7 @@ public class WaveLuteAttack implements LuteAttackHandler {
if (j == 0) sound.play(loc, 2, (float) (.5 + (double) ti / range));
for (Entity target : entities)
if (MMOUtils.canDamage(attack.getDamager(), loc, target)) {
if (MMOUtils.canTarget(attack.getDamager(), loc, target, InteractionType.OFFENSE_ACTION)) {
new ItemAttackMetadata(new DamageMetadata(attackDamage, DamageType.WEAPON, DamageType.PROJECTILE), attack.getStats()).applyEffectsAndDamage(nbt, (LivingEntity) target);
cancel();
return;

View File

@ -3,6 +3,7 @@ package net.Indyuce.mmoitems.api.interaction.weapon.untargeted.staff;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.MMORayTraceResult;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.comp.target.InteractionType;
import io.lumine.mythic.lib.version.VersionSound;
import net.Indyuce.mmoitems.MMOUtils;
import net.Indyuce.mmoitems.api.ItemAttackMetadata;
@ -17,7 +18,7 @@ public class LightningSpirit implements StaffAttackHandler {
Location loc = attackMeta.getDamager().getEyeLocation();
MMORayTraceResult trace = MythicLib.plugin.getVersion().getWrapper().rayTrace(attackMeta.getDamager(), range,
entity -> MMOUtils.canDamage(attackMeta.getDamager(), entity));
entity -> MMOUtils.canTarget(attackMeta.getDamager(), entity, InteractionType.OFFENSE_ACTION));
if (trace.hasHit())
attackMeta.applyEffects(nbt, trace.getHit());
trace.draw(loc, attackMeta.getDamager().getEyeLocation().getDirection(), 2,

View File

@ -1,6 +1,7 @@
package net.Indyuce.mmoitems.api.interaction.weapon.untargeted.staff;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.comp.target.InteractionType;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.MMOUtils;
import net.Indyuce.mmoitems.api.ItemAttackMetadata;
@ -45,7 +46,7 @@ public class ManaSpirit implements StaffAttackHandler {
loc.getWorld().spawnParticle(Particle.REDSTONE, loc.clone().add(vec), 1, new Particle.DustOptions(Color.AQUA, 1));
}
for (Entity target : targets)
if (MMOUtils.canDamage(attackMeta.getDamager(), loc, target)) {
if (MMOUtils.canTarget(attackMeta.getDamager(), loc, target, InteractionType.OFFENSE_ACTION)) {
attackMeta.applyEffects(nbt, (LivingEntity) target);
loc.getWorld().spawnParticle(Particle.EXPLOSION_LARGE, loc, 0);
cancel();

View File

@ -1,6 +1,7 @@
package net.Indyuce.mmoitems.api.interaction.weapon.untargeted.staff;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.comp.target.InteractionType;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.MMOUtils;
import net.Indyuce.mmoitems.api.ItemAttackMetadata;
@ -16,37 +17,37 @@ import java.util.List;
public class NetherSpirit implements StaffAttackHandler {
@Override
public void handle(ItemAttackMetadata attackMeta, NBTItem nbt, double attackDamage, double range) {
new BukkitRunnable() {
final Vector vec = attackMeta.getDamager().getEyeLocation().getDirection().multiply(.3);
final Location loc = attackMeta.getDamager().getEyeLocation();
int ti = 0;
@Override
public void handle(ItemAttackMetadata attackMeta, NBTItem nbt, double attackDamage, double range) {
new BukkitRunnable() {
final Vector vec = attackMeta.getDamager().getEyeLocation().getDirection().multiply(.3);
final Location loc = attackMeta.getDamager().getEyeLocation();
int ti = 0;
public void run() {
if (ti++ % 2 == 0)
loc.getWorld().playSound(loc, Sound.BLOCK_FIRE_AMBIENT, 2, 2);
List<Entity> targets = MMOUtils.getNearbyChunkEntities(loc);
for (int j = 0; j < 3; j++) {
loc.add(vec);
if (loc.getBlock().getType().isSolid()) {
cancel();
break;
}
public void run() {
if (ti++ % 2 == 0)
loc.getWorld().playSound(loc, Sound.BLOCK_FIRE_AMBIENT, 2, 2);
List<Entity> targets = MMOUtils.getNearbyChunkEntities(loc);
for (int j = 0; j < 3; j++) {
loc.add(vec);
if (loc.getBlock().getType().isSolid()) {
cancel();
break;
}
loc.getWorld().spawnParticle(Particle.FLAME, loc, 2, .07, .07, .07, 0);
loc.getWorld().spawnParticle(Particle.SMOKE_NORMAL, loc, 0);
for (Entity target : targets)
if (MMOUtils.canDamage(attackMeta.getDamager(), loc, target)) {
attackMeta.applyEffects(nbt, (LivingEntity) target);
loc.getWorld().spawnParticle(Particle.EXPLOSION_LARGE, loc, 0);
cancel();
return;
}
}
if (ti >= range)
cancel();
}
}.runTaskTimer(MMOItems.plugin, 0, 1);
}
loc.getWorld().spawnParticle(Particle.FLAME, loc, 2, .07, .07, .07, 0);
loc.getWorld().spawnParticle(Particle.SMOKE_NORMAL, loc, 0);
for (Entity target : targets)
if (MMOUtils.canTarget(attackMeta.getDamager(), loc, target, InteractionType.OFFENSE_ACTION)) {
attackMeta.applyEffects(nbt, (LivingEntity) target);
loc.getWorld().spawnParticle(Particle.EXPLOSION_LARGE, loc, 0);
cancel();
return;
}
}
if (ti >= range)
cancel();
}
}.runTaskTimer(MMOItems.plugin, 0, 1);
}
}

View File

@ -1,6 +1,7 @@
package net.Indyuce.mmoitems.api.interaction.weapon.untargeted.staff;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.comp.target.InteractionType;
import io.lumine.mythic.lib.version.VersionSound;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.MMOUtils;
@ -37,7 +38,7 @@ public class SunfireSpirit implements StaffAttackHandler {
loc.getWorld().spawnParticle(Particle.EXPLOSION_LARGE, loc, 0);
loc.getWorld().playSound(loc, VersionSound.ENTITY_FIREWORK_ROCKET_BLAST.toSound(), 2, 2);
for (Entity target : MMOUtils.getNearbyChunkEntities(loc))
if (MMOUtils.canDamage(attackMeta.getDamager(), target) && target.getLocation().distanceSquared(loc) <= 9)
if (MMOUtils.canTarget(attackMeta.getDamager(), target, InteractionType.OFFENSE_ACTION) && target.getLocation().distanceSquared(loc) <= 9)
attackMeta.applyEffectsAndDamage(nbt, (LivingEntity) target);
cancel();
break;

View File

@ -1,6 +1,7 @@
package net.Indyuce.mmoitems.api.interaction.weapon.untargeted.staff;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.comp.target.InteractionType;
import io.lumine.mythic.lib.version.VersionSound;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.MMOUtils;
@ -35,7 +36,7 @@ public class ThunderSpirit implements StaffAttackHandler {
loc.getWorld().spawnParticle(Particle.FIREWORKS_SPARK, loc, 24, 0, 0, 0, .12);
loc.getWorld().playSound(loc, VersionSound.ENTITY_FIREWORK_ROCKET_BLAST.toSound(), 2, 2);
for (Entity target : MMOUtils.getNearbyChunkEntities(loc))
if (MMOUtils.canDamage(attackMeta.getDamager(), target) && target.getLocation().distanceSquared(loc) <= 9)
if (MMOUtils.canTarget(attackMeta.getDamager(), target, InteractionType.OFFENSE_ACTION) && target.getLocation().distanceSquared(loc) <= 9)
attackMeta.applyEffectsAndDamage(nbt, (LivingEntity) target);
cancel();
}

View File

@ -3,6 +3,7 @@ package net.Indyuce.mmoitems.api.interaction.weapon.untargeted.staff;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.MMORayTraceResult;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.comp.target.InteractionType;
import net.Indyuce.mmoitems.MMOUtils;
import net.Indyuce.mmoitems.api.ItemAttackMetadata;
import org.bukkit.Color;
@ -19,7 +20,7 @@ public class XRaySpirit implements StaffAttackHandler {
double a = Math.toRadians(attackMeta.getDamager().getEyeLocation().getYaw() + 160);
Location loc = attackMeta.getDamager().getEyeLocation().add(new Vector(Math.cos(a), 0, Math.sin(a)).multiply(.5));
MMORayTraceResult trace = MythicLib.plugin.getVersion().getWrapper().rayTrace(attackMeta.getDamager(), range, entity -> MMOUtils.canDamage(attackMeta.getDamager(), entity));
MMORayTraceResult trace = MythicLib.plugin.getVersion().getWrapper().rayTrace(attackMeta.getDamager(), range, entity -> MMOUtils.canTarget(attackMeta.getDamager(), entity, InteractionType.OFFENSE_ACTION));
if (trace.hasHit())
attackMeta.applyEffectsAndDamage(nbt, trace.getHit());
trace.draw(loc, attackMeta.getDamager().getEyeLocation().getDirection(), 2, Color.BLACK);

File diff suppressed because it is too large Load Diff

View File

@ -1,21 +0,0 @@
package net.Indyuce.mmoitems.comp.flags;
import org.bukkit.Location;
import org.bukkit.entity.Player;
public class DefaultFlags implements FlagPlugin {
@Override
public boolean isPvpAllowed(Location loc) {
return true;
}
@Override
public boolean isFlagAllowed(Player player, CustomFlag flag) {
return true;
}
@Override
public boolean isFlagAllowed(Location loc, CustomFlag flag) {
return true;
}
}

View File

@ -1,24 +0,0 @@
package net.Indyuce.mmoitems.comp.flags;
import org.bukkit.Location;
import org.bukkit.entity.Player;
public interface FlagPlugin {
boolean isPvpAllowed(Location loc);
boolean isFlagAllowed(Player player, CustomFlag flag);
boolean isFlagAllowed(Location loc, CustomFlag flag);
enum CustomFlag {
MI_ABILITIES,
MI_WEAPONS,
MI_COMMANDS,
MI_CONSUMABLES,
MI_TOOLS;
public String getPath() {
return name().toLowerCase().replace("_", "-");
}
}
}

View File

@ -1,35 +0,0 @@
package net.Indyuce.mmoitems.comp.flags;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import com.bekvon.bukkit.residence.Residence;
import com.bekvon.bukkit.residence.containers.Flags;
import com.bekvon.bukkit.residence.protection.ClaimedResidence;
import com.bekvon.bukkit.residence.protection.FlagPermissions;
public class ResidenceFlags implements FlagPlugin {
public ResidenceFlags() {
for (CustomFlag flag : CustomFlag.values())
FlagPermissions.addFlag(flag.getPath());
}
@Override
public boolean isPvpAllowed(Location loc) {
ClaimedResidence res = Residence.getInstance().getResidenceManager().getByLoc(loc);
return res == null || res.getPermissions().has(Flags.pvp, true);
}
@SuppressWarnings("deprecation")
@Override
public boolean isFlagAllowed(Player player, CustomFlag flag) {
ClaimedResidence res = Residence.getInstance().getResidenceManager().getByLoc(player);
return res == null || res.getPermissions().playerHas(player, flag.getPath(), true);
}
@Override
public boolean isFlagAllowed(Location loc, CustomFlag flag) {
ClaimedResidence res = Residence.getInstance().getResidenceManager().getByLoc(loc);
return res == null || res.getPermissions().has(flag.getPath(), true, true);
}
}

View File

@ -1,58 +0,0 @@
package net.Indyuce.mmoitems.comp.flags;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.flags.Flags;
import com.sk89q.worldguard.protection.flags.StateFlag;
import com.sk89q.worldguard.protection.flags.registry.FlagRegistry;
import net.Indyuce.mmoitems.MMOItems;
public class WorldGuardFlags implements FlagPlugin {
private final WorldGuard worldguard;
private final WorldGuardPlugin worldguardPlugin;
private final Map<String, StateFlag> flags = new HashMap<>();
public WorldGuardFlags() {
this.worldguard = WorldGuard.getInstance();
this.worldguardPlugin = ((WorldGuardPlugin) MMOItems.plugin.getServer().getPluginManager().getPlugin("WorldGuard"));
FlagRegistry registry = worldguard.getFlagRegistry();
for (CustomFlag customFlag : CustomFlag.values()) {
StateFlag flag = new StateFlag(customFlag.getPath(), true);
try {
registry.register(flag);
flags.put(customFlag.getPath(), flag);
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
public boolean isPvpAllowed(Location loc) {
return getApplicableRegion(loc).queryState(null, Flags.PVP) != StateFlag.State.DENY;
}
@Override
public boolean isFlagAllowed(Location loc, CustomFlag customFlag) {
return getApplicableRegion(loc).queryValue(null, flags.get(customFlag.getPath())) != StateFlag.State.DENY;
}
@Override
public boolean isFlagAllowed(Player player, CustomFlag customFlag) {
return getApplicableRegion(player.getLocation()).queryValue(worldguardPlugin.wrapPlayer(player), flags.get(customFlag.getPath())) != StateFlag.State.DENY;
}
private ApplicableRegionSet getApplicableRegion(Location loc) {
return worldguard.getPlatform().getRegionContainer().createQuery().getApplicableRegions(BukkitAdapter.adapt(loc));
}
}

View File

@ -5,14 +5,13 @@ import io.lumine.mythic.lib.api.util.AltChar;
import io.lumine.mythic.lib.version.VersionMaterial;
import net.Indyuce.mmocore.MMOCore;
import net.Indyuce.mmocore.api.block.BlockType;
import net.Indyuce.mmocore.api.droptable.condition.Condition;
import net.Indyuce.mmocore.api.droptable.dropitem.DropItem;
import net.Indyuce.mmocore.api.load.MMOLoader;
import net.Indyuce.mmocore.api.quest.objective.Objective;
import net.Indyuce.mmocore.api.quest.trigger.Trigger;
import net.Indyuce.mmocore.experience.Profession;
import net.Indyuce.mmocore.experience.provider.ExperienceDispenser;
import net.Indyuce.mmocore.experience.source.type.ExperienceSource;
import net.Indyuce.mmocore.loot.droptable.condition.Condition;
import net.Indyuce.mmocore.loot.droptable.dropitem.DropItem;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.block.CustomBlock;
import net.Indyuce.mmoitems.api.crafting.ConditionalDisplay;

View File

@ -3,7 +3,7 @@ package net.Indyuce.mmoitems.comp.mmocore.load;
import org.apache.commons.lang.Validate;
import org.bukkit.inventory.ItemStack;
import net.Indyuce.mmocore.api.droptable.dropitem.DropItem;
import net.Indyuce.mmocore.loot.droptable.dropitem.DropItem;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.ItemTier;
import net.Indyuce.mmoitems.api.item.build.MMOItemBuilder;

View File

@ -5,7 +5,7 @@ import net.Indyuce.mmoitems.api.player.PlayerData;
import org.apache.commons.lang.Validate;
import org.bukkit.inventory.ItemStack;
import net.Indyuce.mmocore.api.loot.LootBuilder;
import net.Indyuce.mmocore.loot.LootBuilder;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.Type;
import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem;

View File

@ -7,7 +7,7 @@ import net.Indyuce.mmoitems.api.player.PlayerData;
import org.apache.commons.lang.Validate;
import org.bukkit.inventory.ItemStack;
import net.Indyuce.mmocore.api.loot.LootBuilder;
import net.Indyuce.mmocore.loot.LootBuilder;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.Type;
import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem;

View File

@ -4,6 +4,7 @@ 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.comp.target.InteractionType;
import io.lumine.mythic.lib.damage.DamageMetadata;
import io.lumine.mythic.lib.damage.DamageType;
import net.Indyuce.mmoitems.MMOItems;
@ -194,7 +195,7 @@ public class ItemUse implements Listener {
return;
LivingEntity target = (LivingEntity) event.getRightClicked();
if (!MMOUtils.canDamage(player, target))
if (!MMOUtils.canTarget(player, target, InteractionType.OFFENSE_ACTION))
return;
UseItem weapon = UseItem.getItem(player, item, item.getType());

View File

@ -34,141 +34,141 @@ import java.util.Iterator;
import java.util.Map;
public class PlayerListener implements Listener {
private final Map<Player, ArrayList<ItemStack>> deathItems = new HashMap<>();
private final Map<Player, ArrayList<ItemStack>> deathItems = new HashMap<>();
@EventHandler
public void loadPlayerData(PlayerJoinEvent event) {
MMOItems.plugin.getRecipes().refreshRecipeBook(event.getPlayer());
PlayerData.load(event.getPlayer());
}
@EventHandler
public void loadPlayerData(PlayerJoinEvent event) {
MMOItems.plugin.getRecipes().refreshRecipeBook(event.getPlayer());
PlayerData.load(event.getPlayer());
}
@EventHandler(priority = EventPriority.HIGH)
public void savePlayerData(PlayerQuitEvent event) {
PlayerData.get(event.getPlayer()).save();
}
@EventHandler(priority = EventPriority.HIGH)
public void savePlayerData(PlayerQuitEvent event) {
PlayerData.get(event.getPlayer()).save();
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void castWhenHitAbilities(EntityDamageByEntityEvent event) {
if (!(event.getEntity() instanceof Player) || event.getEntity().hasMetadata("NPC"))
return;
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void castWhenHitAbilities(EntityDamageByEntityEvent event) {
if (!(event.getEntity() instanceof Player) || event.getEntity().hasMetadata("NPC"))
return;
LivingEntity damager = MMOUtils.getDamager(event);
if (damager == null)
return;
LivingEntity damager = MMOUtils.getDamager(event);
if (damager == null)
return;
Player player = (Player) event.getEntity();
PlayerData.get(player).castAbilities(damager, CastingMode.WHEN_HIT);
}
Player player = (Player) event.getEntity();
PlayerData.get(player).castAbilities(damager, CastingMode.WHEN_HIT);
}
@EventHandler(priority = EventPriority.LOW)
public void castClickAbilities(PlayerInteractEvent event) {
if (event.getAction() == Action.PHYSICAL)
return;
@EventHandler(priority = EventPriority.LOW)
public void castClickAbilities(PlayerInteractEvent event) {
if (event.getAction() == Action.PHYSICAL)
return;
Player player = event.getPlayer();
boolean left = event.getAction() == Action.LEFT_CLICK_AIR || event.getAction() == Action.LEFT_CLICK_BLOCK;
CastingMode castMode = player.isSneaking() ? (left ? CastingMode.SHIFT_LEFT_CLICK : CastingMode.SHIFT_RIGHT_CLICK) : (left ? CastingMode.LEFT_CLICK : CastingMode.RIGHT_CLICK);
PlayerData.get(player).castAbilities(null, castMode);
}
Player player = event.getPlayer();
boolean left = event.getAction() == Action.LEFT_CLICK_AIR || event.getAction() == Action.LEFT_CLICK_BLOCK;
CastingMode castMode = player.isSneaking() ? (left ? CastingMode.SHIFT_LEFT_CLICK : CastingMode.SHIFT_RIGHT_CLICK) : (left ? CastingMode.LEFT_CLICK : CastingMode.RIGHT_CLICK);
PlayerData.get(player).castAbilities(null, castMode);
}
/*
* Prevent players from dropping items which are bound to them with a
* soulbound. Items are cached inside a map waiting for the player to
* respawn. If he does not respawn the items are dropped on the ground, this
* way there don't get lost
*/
@EventHandler(priority = EventPriority.HIGH)
public void onDeath(PlayerDeathEvent event) {
if (event.getKeepInventory() || !MMOItems.plugin.getLanguage().keepSoulboundOnDeath)
return;
/*
* Prevent players from dropping items which are bound to them with a
* soulbound. Items are cached inside a map waiting for the player to
* respawn. If he does not respawn the items are dropped on the ground, this
* way there don't get lost
*/
@EventHandler(priority = EventPriority.HIGH)
public void onDeath(PlayerDeathEvent event) {
if (event.getKeepInventory() || !MMOItems.plugin.getLanguage().keepSoulboundOnDeath)
return;
Player player = event.getEntity();
SoulboundInfo soulboundInfo = new SoulboundInfo(player);
Player player = event.getEntity();
SoulboundInfo soulboundInfo = new SoulboundInfo(player);
Iterator<ItemStack> iterator = event.getDrops().iterator();
while (iterator.hasNext()) {
ItemStack item = iterator.next();
NBTItem nbt = NBTItem.get(item);
Iterator<ItemStack> iterator = event.getDrops().iterator();
while (iterator.hasNext()) {
ItemStack item = iterator.next();
NBTItem nbt = NBTItem.get(item);
if (nbt.hasTag("MMOITEMS_DISABLE_DEATH_DROP") && nbt.getBoolean("MMOITEMS_DISABLE_DEATH_DROP")) {
iterator.remove();
if (!deathItems.containsKey(player))
deathItems.put(player, new ArrayList<>());
if (nbt.hasTag("MMOITEMS_DISABLE_DEATH_DROP") && nbt.getBoolean("MMOITEMS_DISABLE_DEATH_DROP")) {
iterator.remove();
if (!deathItems.containsKey(player))
deathItems.put(player, new ArrayList<>());
deathItems.get(player).add(item);
}
deathItems.get(player).add(item);
}
/*
* not a perfect check but it's very sufficient and so we avoid
* using a JsonParser followed by map checkups in the SoulboundData
* constructor
*/
else if (nbt.hasTag("MMOITEMS_SOULBOUND") && nbt.getString("MMOITEMS_SOULBOUND").contains(player.getUniqueId().toString())) {
iterator.remove();
soulboundInfo.add(item);
}
}
/*
* not a perfect check but it's very sufficient and so we avoid
* using a JsonParser followed by map checkups in the SoulboundData
* constructor
*/
else if (nbt.hasTag("MMOITEMS_SOULBOUND") && nbt.getString("MMOITEMS_SOULBOUND").contains(player.getUniqueId().toString())) {
iterator.remove();
soulboundInfo.add(item);
}
}
if (soulboundInfo.hasItems())
soulboundInfo.setup();
}
if (soulboundInfo.hasItems())
soulboundInfo.setup();
}
@EventHandler
public void onRespawn(PlayerRespawnEvent event) {
Player player = event.getPlayer();
@EventHandler
public void onRespawn(PlayerRespawnEvent event) {
Player player = event.getPlayer();
if (MMOItems.plugin.getLanguage().keepSoulboundOnDeath)
SoulboundInfo.read(player);
if (MMOItems.plugin.getLanguage().keepSoulboundOnDeath)
SoulboundInfo.read(player);
if (deathItems.containsKey(player)) {
Schedulers.sync().runLater( () -> {
player.getInventory().addItem(deathItems.get(player).toArray(new ItemStack[0]));
deathItems.remove(player);
}, 10);
}
}
if (deathItems.containsKey(player)) {
Schedulers.sync().runLater(() -> {
player.getInventory().addItem(deathItems.get(player).toArray(new ItemStack[0]));
deathItems.remove(player);
}, 10);
}
}
@EventHandler
public void onArmorEquip(ArmorEquipEvent event) {
Player p = event.getPlayer();
RPGPlayer rpgPlayer = PlayerData.get(p.getUniqueId()).getRPG();
NBTItem item = NBTItem.get(event.getNewArmorPiece());
@EventHandler
public void onArmorEquip(ArmorEquipEvent event) {
Player p = event.getPlayer();
RPGPlayer rpgPlayer = PlayerData.get(p.getUniqueId()).getRPG();
NBTItem item = NBTItem.get(event.getNewArmorPiece());
if (!rpgPlayer.canUse(item, true))
event.setCancelled(true);
}
if (!rpgPlayer.canUse(item, true))
event.setCancelled(true);
}
@EventHandler(ignoreCancelled = true)
public void registerTridents(ProjectileLaunchEvent event) {
if (!(event.getEntity() instanceof Trident) || !(event.getEntity().getShooter() instanceof Player))
return;
@EventHandler(ignoreCancelled = true)
public void registerTridents(ProjectileLaunchEvent event) {
if (!(event.getEntity() instanceof Trident) || !(event.getEntity().getShooter() instanceof Player))
return;
InteractItem item = new InteractItem((Player) event.getEntity().getShooter(), Material.TRIDENT);
if (!item.hasItem())
return;
InteractItem item = new InteractItem((Player) event.getEntity().getShooter(), Material.TRIDENT);
if (!item.hasItem())
return;
NBTItem nbtItem = MythicLib.plugin.getVersion().getWrapper().getNBTItem(item.getItem());
Type type = Type.get(nbtItem.getType());
PlayerData playerData = PlayerData.get((Player) event.getEntity().getShooter());
NBTItem nbtItem = MythicLib.plugin.getVersion().getWrapper().getNBTItem(item.getItem());
Type type = Type.get(nbtItem.getType());
PlayerData playerData = PlayerData.get((Player) event.getEntity().getShooter());
if (type != null) {
Weapon weapon = new Weapon(playerData, nbtItem);
if (!weapon.checkItemRequirements() || !weapon.applyWeaponCosts()) {
event.setCancelled(true);
return;
}
}
if (type != null) {
Weapon weapon = new Weapon(playerData, nbtItem);
if (!weapon.checkItemRequirements() || !weapon.applyWeaponCosts()) {
event.setCancelled(true);
return;
}
}
MMOItems.plugin.getEntities().registerCustomProjectile(nbtItem, playerData.getStats().newTemporary(EquipmentSlot.fromBukkit(item.getSlot())), event.getEntity(), type != null);
}
MMOItems.plugin.getEntities().registerCustomProjectile(nbtItem, playerData.getStats().newTemporary(EquipmentSlot.fromBukkit(item.getSlot())), event.getEntity(), type != null);
}
/**
* Fixes an issue where
* @param event
*/
@EventHandler
public void registerInventoryUpdates(PlayerSwapHandItemsEvent event) {
PlayerData playerData = PlayerData.get(event.getPlayer());
playerData.updateInventory();
}
/**
* Fixes an issue where quickly swapping items in hand just
* does not update the player's inventory which can make the
* player cast abilities or attacks with not the correct stats
*/
@EventHandler
public void registerInventoryUpdates(PlayerSwapHandItemsEvent event) {
PlayerData.get(event.getPlayer()).updateInventory();
}
}

View File

@ -194,9 +194,6 @@ two-handed-item-restriction: true
# the item ability cooldown progress bar.
cooldown-progress-bar-char:
# When toggled off, players can't damage each other using item abilities.
ability-player-damage: true
# Displays a message on the action bar instead of on the chat.
# Can be used to reduce chat spam.
# Might interfere with other action bar plugins.