diff --git a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/MMOItems.java b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/MMOItems.java index c5af0b8a..b04f8ba3 100644 --- a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/MMOItems.java +++ b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/MMOItems.java @@ -4,8 +4,8 @@ import io.lumine.mythic.lib.api.item.NBTItem; import io.lumine.mythic.lib.api.util.ui.FriendlyFeedbackMessage; import io.lumine.mythic.lib.api.util.ui.FriendlyFeedbackProvider; import io.lumine.mythic.lib.version.SpigotPlugin; -import net.Indyuce.mmoitems.api.ItemTier; import net.Indyuce.mmoitems.api.DeathItemsHandler; +import net.Indyuce.mmoitems.api.ItemTier; import net.Indyuce.mmoitems.api.Type; import net.Indyuce.mmoitems.api.crafting.MMOItemUIFilter; import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem; @@ -68,7 +68,6 @@ public class MMOItems extends JavaPlugin { private final LoreFormatManager loreManager = new LoreFormatManager(); private final TemplateManager templateManager = new TemplateManager(); private final SkillManager skillManager = new SkillManager(); - private final EntityManager entityManager = new EntityManager(); private final RecipeManager recipeManager = new RecipeManager(); private final LayoutManager layoutManager = new LayoutManager(); private final TypeManager typeManager = new TypeManager(); @@ -187,7 +186,6 @@ public class MMOItems extends JavaPlugin { // This ones are not implementing Reloadable MMOItemReforger.reload(); - Bukkit.getPluginManager().registerEvents(entityManager, this); Bukkit.getPluginManager().registerEvents(dropTableManager, this); // Load Dist module @@ -452,10 +450,6 @@ public class MMOItems extends JavaPlugin { return tierManager; } - public EntityManager getEntities() { - return entityManager; - } - public DropTableManager getDropTables() { return dropTableManager; } diff --git a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/Type.java b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/Type.java index a43fa714..73f694a6 100644 --- a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/Type.java +++ b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/Type.java @@ -42,7 +42,7 @@ public class Type implements CooldownObject { public static final Type WHIP = new Type("WHIP", true, ModifierSource.RANGED_WEAPON); public static final Type STAFF = new Type("STAFF", true, ModifierSource.RANGED_WEAPON); public static final Type BOW = new Type("BOW", true, ModifierSource.RANGED_WEAPON); - public static final Type CROSSBOW = new Type("CROSSBOW", false, ModifierSource.RANGED_WEAPON); + public static final Type CROSSBOW = new Type("CROSSBOW", true, ModifierSource.RANGED_WEAPON); public static final Type MUSKET = new Type("MUSKET", true, ModifierSource.RANGED_WEAPON); public static final Type LUTE = new Type("LUTE", true, ModifierSource.RANGED_WEAPON); @@ -142,7 +142,7 @@ public class Type implements CooldownObject { } public void postload(ConfigurationSection config) { - onLeftClick = config.contains("on-left-click") ? new SimpleSkill(TriggerType.CAST, MythicLib.plugin.getSkills().loadSkillHandler(config.get("on-left-click"))) : null; + onLeftClick = config.contains("on-left-click") ? new SimpleSkill(MythicLib.plugin.getSkills().loadSkillHandler(config.get("on-left-click"))) : null; onRightClick = config.contains("on-right-click") ? new SimpleSkill(MythicLib.plugin.getSkills().loadSkillHandler(config.get("on-right-click"))) : null; onAttack = config.contains("on-attack") ? new SimpleSkill(MythicLib.plugin.getSkills().loadSkillHandler(config.get("on-attack"))) : null; onEntityInteract = config.contains("on-entity-interact") ? new SimpleSkill(MythicLib.plugin.getSkills().loadSkillHandler(config.get("on-entity-interact"))) : null; diff --git a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/interaction/UseItem.java b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/interaction/UseItem.java index 32e42716..8fcc031f 100644 --- a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/interaction/UseItem.java +++ b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/interaction/UseItem.java @@ -7,7 +7,6 @@ import net.Indyuce.mmoitems.ItemStats; import net.Indyuce.mmoitems.MMOItems; import net.Indyuce.mmoitems.api.Type; import net.Indyuce.mmoitems.api.interaction.weapon.Weapon; -import net.Indyuce.mmoitems.api.interaction.weapon.untargeted.Crossbow; import net.Indyuce.mmoitems.api.interaction.weapon.untargeted.Lute; import net.Indyuce.mmoitems.api.interaction.weapon.untargeted.Musket; import net.Indyuce.mmoitems.api.item.mmoitem.VolatileMMOItem; @@ -129,7 +128,6 @@ public class UseItem { if (type.corresponds(Type.SKIN)) return new ItemSkin(playerData, item); if (type.corresponds(Type.GEM_STONE)) return new GemStone(playerData, item); if (type.corresponds(Type.MUSKET)) return new Musket(playerData, item); - if (type.corresponds(Type.CROSSBOW)) return new Crossbow(playerData, item); if (type.corresponds(Type.LUTE)) return new Lute(playerData, item); return type.isWeapon() ? new Weapon(playerData, item) : new UseItem(playerData, item); diff --git a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/interaction/projectile/ProjectileData.java b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/interaction/projectile/ProjectileData.java deleted file mode 100644 index 7d90fb76..00000000 --- a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/interaction/projectile/ProjectileData.java +++ /dev/null @@ -1,81 +0,0 @@ -package net.Indyuce.mmoitems.api.interaction.projectile; - -import io.lumine.mythic.lib.MythicLib; -import io.lumine.mythic.lib.api.item.NBTItem; -import io.lumine.mythic.lib.player.PlayerMetadata; -import net.Indyuce.mmoitems.stat.data.PotionEffectData; -import org.apache.commons.lang.Validate; -import org.bukkit.entity.LivingEntity; -import org.bukkit.potion.PotionEffectType; - -/** - * Since MMOItems 6.7.5 vanilla bows and custom bows are - * not treated the same way: - * - vanilla bows see NO changes in their damage computations - * - custom bows override - */ -public class ProjectileData { - private final NBTItem sourceItem; - private final PlayerMetadata shooter; - private final double damageMultiplier; - - @Deprecated - public ProjectileData(PlayerMetadata shooter, NBTItem sourceItem, boolean customWeapon, double damageMultiplier) { - this(shooter, sourceItem, damageMultiplier); - } - - public ProjectileData(PlayerMetadata shooter, NBTItem sourceItem, double damageMultiplier) { - this.shooter = shooter; - this.sourceItem = sourceItem; - this.damageMultiplier = damageMultiplier; - } - - public NBTItem getSourceItem() { - return sourceItem; - } - - public PlayerMetadata getShooter() { - return shooter; - } - - public double getDamageMultiplier() { - return damageMultiplier; - } - - /** - * Used to check if that projectile data is linked to - * a projectile that want sent using a MMOItems bow. - *

- * If so, it needs to apply on-hit effects like - * elemental damage or on-hit potion effects - */ - @Deprecated - public boolean isCustomWeapon() { - return true; - } - - /** - * Will throw an error if it's not a custom bow - * - * @return Damage of custom bow - */ - public double getDamage() { - Validate.isTrue(isCustomWeapon(), "Not a custom bow"); - return shooter.getStat("ATTACK_DAMAGE") * damageMultiplier; - } - - /** - * @see {@link #getDamage()} - */ - @Deprecated - public void setDamage(double damage) { - Validate.isTrue(isCustomWeapon(), "Not a custom bow"); - shooter.setStat("ATTACK_DAMAGE", damage); - } - - public void applyPotionEffects(LivingEntity target) { - if (sourceItem.hasTag("MMOITEMS_ARROW_POTION_EFFECTS")) - for (ArrowPotionEffectArrayItem entry : MythicLib.plugin.getJson().parse(sourceItem.getString("MMOITEMS_ARROW_POTION_EFFECTS"), ArrowPotionEffectArrayItem[].class)) - target.addPotionEffect(new PotionEffectData(PotionEffectType.getByName(entry.type), entry.duration, entry.level).toEffect()); - } -} diff --git a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/interaction/weapon/untargeted/Crossbow.java b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/interaction/weapon/untargeted/Crossbow.java deleted file mode 100644 index 249fa33a..00000000 --- a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/interaction/weapon/untargeted/Crossbow.java +++ /dev/null @@ -1,62 +0,0 @@ -package net.Indyuce.mmoitems.api.interaction.weapon.untargeted; - -import io.lumine.mythic.lib.api.item.NBTItem; -import io.lumine.mythic.lib.api.player.EquipmentSlot; -import io.lumine.mythic.lib.player.PlayerMetadata; -import io.lumine.mythic.lib.skill.trigger.TriggerType; -import io.lumine.mythic.lib.util.CustomProjectile; -import net.Indyuce.mmoitems.MMOItems; -import net.Indyuce.mmoitems.api.CustomSound; -import net.Indyuce.mmoitems.api.interaction.weapon.Weapon; -import net.Indyuce.mmoitems.api.player.PlayerData; -import net.Indyuce.mmoitems.listener.CustomSoundListener; -import org.bukkit.GameMode; -import org.bukkit.Material; -import org.bukkit.Sound; -import org.bukkit.entity.Arrow; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; - -@Deprecated -public class Crossbow extends Weapon implements LegacyWeapon { - private boolean consumesArrow; - - @Deprecated - public Crossbow(Player player, NBTItem item) { - super(player, item); - } - - public Crossbow(PlayerData player, NBTItem item) { - super(player, item); - } - - @Override - public boolean canAttack(boolean rightClick, EquipmentSlot slot) { - if (!rightClick) return false; - - consumesArrow = !getNBTItem().getBoolean("MMOITEMS_DISABLE_ARROW_CONSUMPTION"); - return player.getGameMode() == GameMode.CREATIVE || !consumesArrow || getPlayer().getInventory().containsAtLeast(new ItemStack(Material.ARROW), 1); - } - - @Override - public void applyAttackEffect(PlayerMetadata stats, EquipmentSlot slot) { - - // Consume arrow - if (getPlayer().getGameMode() != GameMode.CREATIVE && consumesArrow) - getPlayer().getInventory().removeItem(new ItemStack(Material.ARROW)); - - final Arrow arrow = getPlayer().launchProjectile(Arrow.class); - arrow.setVelocity(getPlayer().getEyeLocation().getDirection().multiply(3 * requireNonZero(stats.getStat("ARROW_VELOCITY"), 1))); - getPlayer().setVelocity(getPlayer().getVelocity().setX(0).setZ(0)); - - // Play custom sound - CustomSoundListener.playSound(getNBTItem().getItem(), CustomSound.ON_CROSSBOW, player, Sound.ENTITY_ARROW_SHOOT); - - // Register custom projectile - MMOItems.plugin.getEntities().registerCustomProjectile(getNBTItem(), stats, arrow, 1); - - // Trigger abilities - stats.getData().triggerSkills(TriggerType.SHOOT_BOW, slot, arrow); - new CustomProjectile(stats.getData(), CustomProjectile.ProjectileType.ARROW, arrow, slot); - } -} diff --git a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/interaction/weapon/untargeted/LegacyWeapon.java b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/interaction/weapon/untargeted/LegacyWeapon.java index d541819f..1d95f00b 100644 --- a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/interaction/weapon/untargeted/LegacyWeapon.java +++ b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/api/interaction/weapon/untargeted/LegacyWeapon.java @@ -4,7 +4,7 @@ import io.lumine.mythic.lib.api.player.EquipmentSlot; import io.lumine.mythic.lib.player.PlayerMetadata; /** - * These weapon types need to be adapted to + * These weapon types need to be adapted to raw YAML scripts. */ @Deprecated public interface LegacyWeapon { diff --git a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/comp/mythicmobs/mechanics/MMOItemsOnUseAura.java b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/comp/mythicmobs/mechanics/MMOItemsOnUseAura.java index ed3d3ef0..39ebf3ed 100644 --- a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/comp/mythicmobs/mechanics/MMOItemsOnUseAura.java +++ b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/comp/mythicmobs/mechanics/MMOItemsOnUseAura.java @@ -222,11 +222,11 @@ public class MMOItemsOnUseAura extends Aura implements ITargetedEntitySkill { } enum UseItemTypes { - CROSSBOW(Crossbow.class), + // CROSSBOW(Crossbow.class), // GAUNTLET(Gauntlet.class), LUTE(Lute.class), MUSKET(Musket.class), - STAFF(Staff.class), + // STAFF(Staff.class), // WHIP(Whip.class); ; diff --git a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/listener/ItemUse.java b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/listener/ItemUse.java index 030b1434..ea0f2b70 100644 --- a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/listener/ItemUse.java +++ b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/listener/ItemUse.java @@ -7,18 +7,18 @@ import io.lumine.mythic.lib.api.item.NBTItem; import io.lumine.mythic.lib.api.player.EquipmentSlot; import io.lumine.mythic.lib.comp.interaction.InteractionType; import io.lumine.mythic.lib.damage.MeleeAttackMetadata; +import io.lumine.mythic.lib.entity.ProjectileMetadata; +import io.lumine.mythic.lib.entity.ProjectileType; import io.lumine.mythic.lib.skill.Skill; import io.lumine.mythic.lib.skill.trigger.TriggerMetadata; import io.lumine.mythic.lib.skill.trigger.TriggerType; -import net.Indyuce.mmoitems.MMOItems; import net.Indyuce.mmoitems.api.Type; import net.Indyuce.mmoitems.api.event.item.SpecialWeaponAttackEvent; import net.Indyuce.mmoitems.api.interaction.*; -import net.Indyuce.mmoitems.api.interaction.projectile.ProjectileData; +import net.Indyuce.mmoitems.api.interaction.projectile.ArrowParticles; import net.Indyuce.mmoitems.api.interaction.weapon.Weapon; import net.Indyuce.mmoitems.api.player.PlayerData; import net.Indyuce.mmoitems.api.util.message.Message; -import net.Indyuce.mmoitems.manager.EntityManager; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.GameMode; @@ -223,8 +223,6 @@ public class ItemUse implements Listener { /** * This handler registers arrows from custom MMOItems bows - * - * @see {@link EntityManager#onHitEffects(PlayerAttackEvent)} */ @EventHandler public void handleCustomBows(EntityShootBowEvent event) { @@ -244,11 +242,16 @@ public class ItemUse implements Listener { // Have to get hand manually because 1.15 and below does not have event.getHand() final ItemStack itemInMainHand = playerData.getPlayer().getInventory().getItemInMainHand(); final EquipmentSlot bowSlot = itemInMainHand.isSimilar(event.getBow()) ? EquipmentSlot.MAIN_HAND : EquipmentSlot.OFF_HAND; - final ProjectileData projData = MMOItems.plugin.getEntities().registerCustomProjectile(item, playerData.getStats().newTemporary(bowSlot), event.getProjectile(), event.getForce()); + final ProjectileMetadata proj = ProjectileMetadata.create(playerData.getStats().newTemporary(bowSlot), ProjectileType.ARROW, event.getProjectile()); + proj.setSourceItem(item); + proj.setCustomDamage(true); + proj.setDamageMultiplier(event.getForce()); + if (item.hasTag("MMOITEMS_ARROW_PARTICLES")) + new ArrowParticles((AbstractArrow) event.getProjectile(), item); final AbstractArrow arrow = (AbstractArrow) event.getProjectile(); // Apply arrow velocity - final double arrowVelocity = projData.getShooter().getStat("ARROW_VELOCITY"); + final double arrowVelocity = proj.getShooter().getStat("ARROW_VELOCITY"); if (arrowVelocity > 0) arrow.setVelocity(arrow.getVelocity().multiply(arrowVelocity)); } } diff --git a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/manager/EntityManager.java b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/manager/EntityManager.java deleted file mode 100644 index 02ebd2fc..00000000 --- a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/manager/EntityManager.java +++ /dev/null @@ -1,153 +0,0 @@ -package net.Indyuce.mmoitems.manager; - -import io.lumine.mythic.lib.api.event.PlayerAttackEvent; -import io.lumine.mythic.lib.api.item.NBTItem; -import io.lumine.mythic.lib.damage.ProjectileAttackMetadata; -import io.lumine.mythic.lib.player.PlayerMetadata; -import net.Indyuce.mmoitems.MMOItems; -import net.Indyuce.mmoitems.api.interaction.projectile.ArrowParticles; -import net.Indyuce.mmoitems.api.interaction.projectile.EntityData; -import net.Indyuce.mmoitems.api.interaction.projectile.ProjectileData; -import org.bukkit.Bukkit; -import org.bukkit.entity.*; -import org.bukkit.enchantments.Enchantment; -import org.bukkit.entity.AbstractArrow; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.entity.EntityDeathEvent; -import org.bukkit.event.entity.ProjectileHitEvent; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.WeakHashMap; - -public class EntityManager implements Listener { - - /** - * Entity data used by abilities or staff attacks that utilize entities like - * evoker fangs or shulker missiles. It can correspond to the damage the - * entity is supposed to deal, etc - */ - private final Map entities = new HashMap<>(); - - private final Map projectiles = new WeakHashMap<>(); - - @Deprecated - public void registerCustomProjectile(@NotNull NBTItem sourceItem, @NotNull PlayerMetadata attacker, @NotNull Entity entity, boolean customWeapon, double damageMultiplicator) { - registerCustomProjectile(sourceItem, attacker, entity, damageMultiplicator); - } - - /** - * Registers a custom projectile. This is used for bows, crossbows and tridents. - * - * @param sourceItem Item used to shoot the projectile - * @param attacker Cached stats of the player shooting the projectile - * @param entity The custom entity - * @param damageMultiplicator The damage coefficient. For bows, this is basically the pull force. - * For tridents or anything else this is always set to 1 - */ - @NotNull - public ProjectileData registerCustomProjectile(@NotNull NBTItem sourceItem, @NotNull PlayerMetadata attacker, @NotNull Entity entity, double damageMultiplicator) { - - // Initialize projectile data - final ProjectileData projectileData = new ProjectileData(attacker, sourceItem, damageMultiplicator); - - /* - * Load arrow particles if the entity is an arrow and if the item has - * arrow particles. Currently projectiles are only arrows so there is no - * problem with other projectiles like snowballs etc. - */ - if (entity instanceof AbstractArrow && sourceItem.hasTag("MMOITEMS_ARROW_PARTICLES")) - new ArrowParticles((AbstractArrow) entity, sourceItem); - - projectiles.put(entity.getEntityId(), projectileData); - return projectileData; - } - - public void registerCustomEntity(Entity entity, EntityData data) { - entities.put(entity.getEntityId(), data); - } - - public boolean isCustomProjectile(Projectile projectile) { - return projectiles.containsKey(projectile.getEntityId()); - } - - public boolean isCustomEntity(Entity entity) { - return entities.containsKey(entity.getEntityId()); - } - - public ProjectileData getProjectileData(Projectile projectile) { - return Objects.requireNonNull(projectiles.get(projectile.getEntityId()), "Provided entity is not a custom projectile"); - } - - public EntityData getEntityData(Entity entity) { - return Objects.requireNonNull(entities.get(entity.getEntityId()), "Provided entity is not a custom entity"); - } - - public void unregisterCustomProjectile(Projectile projectile) { - projectiles.remove(projectile.getEntityId()); - } - - public void unregisterCustomEntity(Entity entity) { - entities.remove(entity.getEntityId()); - } - - /** - * This event is called on LOWEST and only edits the custom bow base damage. - * It does NOT take into account the base damage passed in Bow#getDamage() - * and fully overrides any change. - * - * This applies to tridents, arrows, spectral arrows etc. - *

- * Event order: ProjectileHit -> EntityDamage / EntityDeathEvent - */ - @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) - public void customProjectileDamage(EntityDamageByEntityEvent event) { - if (!(event.getDamager() instanceof Projectile) || !(event.getEntity() instanceof LivingEntity) || event.getEntity().hasMetadata("NPC")) - return; - - final Projectile projectile = (Projectile) event.getDamager(); - final ProjectileData data = projectiles.get(projectile.getEntityId()); - if (data == null) - return; - - // Calculate custom base damage - double baseDamage = data.getDamage(); - - // Apply power vanilla enchant - if (projectile instanceof AbstractArrow && data.getSourceItem().getItem().hasItemMeta() - && data.getSourceItem().getItem().getItemMeta().getEnchants().containsKey(Enchantment.ARROW_DAMAGE)) - baseDamage *= 1.25 + (.25 * data.getSourceItem().getItem().getItemMeta().getEnchantLevel(Enchantment.ARROW_DAMAGE)); - - event.setDamage(baseDamage); - } - - @EventHandler(ignoreCancelled = true) - public void onHitEffects(PlayerAttackEvent event) { - if (!(event.getAttack() instanceof ProjectileAttackMetadata)) - return; - - final ProjectileAttackMetadata projAttack = (ProjectileAttackMetadata) event.getAttack(); - final @Nullable ProjectileData data = projectiles.get(projAttack.getProjectile().getEntityId()); - if (data == null) - return; - - // Apply MMOItems specific modifications - data.applyPotionEffects(event.getEntity()); - } - - @EventHandler(priority = EventPriority.MONITOR) - public void unregisterProjectileData(ProjectileHitEvent event) { - Bukkit.getScheduler().scheduleSyncDelayedTask(MMOItems.plugin, () -> unregisterCustomProjectile(event.getEntity())); - } - - @EventHandler(priority = EventPriority.MONITOR) - public void unregisterEntityData(EntityDeathEvent event) { - Bukkit.getScheduler().scheduleSyncDelayedTask(MMOItems.plugin, () -> unregisterCustomEntity(event.getEntity())); - } -} \ No newline at end of file diff --git a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/manager/SkillManager.java b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/manager/SkillManager.java index 259bc83c..789166fe 100644 --- a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/manager/SkillManager.java +++ b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/manager/SkillManager.java @@ -6,7 +6,6 @@ import io.lumine.mythic.lib.skill.handler.SkillHandler; import net.Indyuce.mmoitems.MMOItems; import net.Indyuce.mmoitems.api.ConfigFile; import net.Indyuce.mmoitems.skill.RegisteredSkill; -import net.Indyuce.mmoitems.skill.ShulkerMissile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -81,8 +80,6 @@ public class SkillManager { if (clearBefore) skills.clear(); - MythicLib.plugin.getSkills().registerSkillHandler(new ShulkerMissile()); - File skillFolder = new File(MMOItems.plugin.getDataFolder() + "/skill"); if (!skillFolder.exists()) { diff --git a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/skill/ShulkerMissile.java b/MMOItems-API/src/main/java/net/Indyuce/mmoitems/skill/ShulkerMissile.java deleted file mode 100644 index a46ae90e..00000000 --- a/MMOItems-API/src/main/java/net/Indyuce/mmoitems/skill/ShulkerMissile.java +++ /dev/null @@ -1,146 +0,0 @@ -package net.Indyuce.mmoitems.skill; - -import io.lumine.mythic.lib.UtilityMethods; -import io.lumine.mythic.lib.api.item.NBTItem; -import io.lumine.mythic.lib.comp.interaction.InteractionType; -import io.lumine.mythic.lib.damage.DamageMetadata; -import io.lumine.mythic.lib.damage.DamageType; -import io.lumine.mythic.lib.player.PlayerMetadata; -import io.lumine.mythic.lib.skill.SkillMetadata; -import io.lumine.mythic.lib.skill.handler.SkillHandler; -import io.lumine.mythic.lib.skill.result.def.VectorSkillResult; -import net.Indyuce.mmoitems.MMOItems; -import net.Indyuce.mmoitems.api.interaction.projectile.EntityData; -import org.bukkit.Color; -import org.bukkit.Location; -import org.bukkit.Particle; -import org.bukkit.Sound; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; -import org.bukkit.entity.ShulkerBullet; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.potion.PotionEffect; -import org.bukkit.potion.PotionEffectType; -import org.bukkit.scheduler.BukkitRunnable; -import org.bukkit.util.Vector; -import org.jetbrains.annotations.NotNull; - -import javax.annotation.Nullable; - -public class ShulkerMissile extends SkillHandler implements Listener { - public ShulkerMissile() { - super("SHULKER_MISSILE"); - - registerModifiers("damage", "effect-duration", "duration"); - } - - @NotNull - @Override - public VectorSkillResult getResult(SkillMetadata meta) { - return new VectorSkillResult(meta); - } - - @Override - public void whenCast(VectorSkillResult result, SkillMetadata skillMeta) { - double duration = skillMeta.getParameter("duration"); - - Player caster = skillMeta.getCaster().getPlayer(); - - new BukkitRunnable() { - double n = 0; - - public void run() { - if (n++ > 3) { - cancel(); - return; - } - - Vector vec = result.getTarget(); - caster.getWorld().playSound(caster.getLocation(), Sound.ENTITY_WITHER_SHOOT, 2, 2); - ShulkerBullet shulkerBullet = (ShulkerBullet) caster.getWorld().spawnEntity(caster.getLocation().add(0, 1, 0), - EntityType.SHULKER_BULLET); - shulkerBullet.setShooter(caster); - - MMOItems.plugin.getEntities().registerCustomEntity(shulkerBullet, new ShulkerMissileEntityData(skillMeta.getCaster(), new DamageMetadata(skillMeta.getParameter("damage"), DamageType.SKILL, DamageType.MAGIC, DamageType.PROJECTILE), skillMeta.getParameter("effect-duration"), null)); - - new BukkitRunnable() { - double ti = 0; - - public void run() { - if (shulkerBullet.isDead() || ti++ >= duration * 20) { - shulkerBullet.remove(); - cancel(); - } else - shulkerBullet.setVelocity(vec); - } - }.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; - - ShulkerMissileEntityData data = (ShulkerMissileEntityData) MMOItems.plugin.getEntities().getEntityData(damager); - if (!UtilityMethods.canTarget(data.caster.getPlayer(), null, entity, data.isWeaponAttack() ? InteractionType.OFFENSE_ACTION : InteractionType.OFFENSE_SKILL)) { - event.setCancelled(true); - return; - } - - event.setDamage(data.damage.getDamage()); - - new BukkitRunnable() { - final Location loc = entity.getLocation(); - double y = 0; - - public void run() { - - // 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)); - } - - 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 PlayerMetadata caster; - private final DamageMetadata damage; - private final double duration; - - @Nullable - private final NBTItem weapon; - - public ShulkerMissileEntityData(PlayerMetadata caster, DamageMetadata damage, double duration, NBTItem weapon) { - this.caster = caster; - this.damage = damage; - this.duration = duration; - this.weapon = weapon; - } - - public boolean isWeaponAttack() { - return damage.hasType(DamageType.WEAPON); - } - } -} diff --git a/MMOItems-Dist/src/main/java/net/Indyuce/mmoitems/listener/PlayerListener.java b/MMOItems-Dist/src/main/java/net/Indyuce/mmoitems/listener/PlayerListener.java index cd185325..0d36aaff 100644 --- a/MMOItems-Dist/src/main/java/net/Indyuce/mmoitems/listener/PlayerListener.java +++ b/MMOItems-Dist/src/main/java/net/Indyuce/mmoitems/listener/PlayerListener.java @@ -1,18 +1,25 @@ package net.Indyuce.mmoitems.listener; import io.lumine.mythic.lib.MythicLib; +import io.lumine.mythic.lib.api.event.PlayerAttackEvent; import io.lumine.mythic.lib.api.event.armorequip.ArmorEquipEvent; import io.lumine.mythic.lib.api.item.NBTItem; import io.lumine.mythic.lib.api.player.EquipmentSlot; +import io.lumine.mythic.lib.damage.ProjectileAttackMetadata; +import io.lumine.mythic.lib.entity.ProjectileMetadata; +import io.lumine.mythic.lib.entity.ProjectileType; import net.Indyuce.mmoitems.MMOItems; import net.Indyuce.mmoitems.api.DeathItemsHandler; import net.Indyuce.mmoitems.api.Type; +import net.Indyuce.mmoitems.api.interaction.projectile.ArrowPotionEffectArrayItem; import net.Indyuce.mmoitems.api.interaction.util.InteractItem; import net.Indyuce.mmoitems.api.interaction.weapon.Weapon; import net.Indyuce.mmoitems.api.player.PlayerData; import net.Indyuce.mmoitems.api.util.DeathDowngrading; +import net.Indyuce.mmoitems.stat.data.PotionEffectData; import net.Indyuce.mmoitems.util.MMOUtils; import org.bukkit.Material; +import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.entity.Trident; import org.bukkit.event.EventHandler; @@ -24,8 +31,10 @@ import org.bukkit.event.player.PlayerItemHeldEvent; import org.bukkit.event.player.PlayerRespawnEvent; import org.bukkit.event.player.PlayerSwapHandItemsEvent; import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffectType; import org.bukkit.scheduler.BukkitRunnable; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Iterator; @@ -119,17 +128,37 @@ public class PlayerListener implements Listener { return; } - MMOItems.plugin.getEntities().registerCustomProjectile(nbtItem, playerData.getStats().newTemporary(EquipmentSlot.fromBukkit(item.getSlot())), event.getEntity(), 1); + final ProjectileMetadata proj = ProjectileMetadata.create(playerData.getStats().newTemporary(EquipmentSlot.fromBukkit(item.getSlot())), ProjectileType.TRIDENT, event.getEntity()); + proj.setSourceItem(nbtItem); + proj.setCustomDamage(true); } } + @EventHandler(ignoreCancelled = true) + public void registerArrowSpecialEffects(PlayerAttackEvent event) { + if (!(event.getAttack() instanceof ProjectileAttackMetadata)) return; + + final ProjectileAttackMetadata projAttack = (ProjectileAttackMetadata) event.getAttack(); + final @Nullable ProjectileMetadata data = ProjectileMetadata.get(projAttack.getProjectile()); + if (data == null || data.getSourceItem() == null) return; + + // Apply MMOItems-specific effects + applyPotionEffects(data, event.getEntity()); + } + + private void applyPotionEffects(ProjectileMetadata proj, LivingEntity target) { + if (proj.getSourceItem().hasTag("MMOITEMS_ARROW_POTION_EFFECTS")) + for (ArrowPotionEffectArrayItem entry : MythicLib.plugin.getJson().parse(proj.getSourceItem().getString("MMOITEMS_ARROW_POTION_EFFECTS"), ArrowPotionEffectArrayItem[].class)) + target.addPotionEffect(new PotionEffectData(PotionEffectType.getByName(entry.type), entry.duration, entry.level).toEffect()); + } + /** * 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 * * @deprecated This does cost some performance and that update - * method NEEDS some improvement in the future + * method NEEDS some improvement in the future */ @Deprecated @EventHandler @@ -143,7 +172,7 @@ public class PlayerListener implements Listener { * player cast abilities or attacks with not the correct stats * * @deprecated This does cost some performance and that update - * method NEEDS some improvement in the future + * method NEEDS some improvement in the future */ @Deprecated @EventHandler