mirror of
https://gitlab.com/phoenix-dvpmt/mmoitems.git
synced 2025-01-03 06:37:47 +01:00
Custom item types commit 2
This commit is contained in:
parent
bb1eeed501
commit
eba4b3ff80
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
* <p>
|
||||
* 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());
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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 {
|
||||
|
@ -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);
|
||||
;
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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<Integer, EntityData> entities = new HashMap<>();
|
||||
|
||||
private final Map<Integer, ProjectileData> 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.
|
||||
* <p>
|
||||
* 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()));
|
||||
}
|
||||
}
|
@ -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()) {
|
||||
|
||||
|
@ -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<VectorSkillResult> 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user