Fixed projectile particles for lutes

This commit is contained in:
Indyuce 2022-12-21 00:19:51 +01:00
parent 76877b0eb6
commit 0bb66bd2b2
11 changed files with 165 additions and 266 deletions

View File

@ -1,7 +1,5 @@
package net.Indyuce.mmoitems.api.interaction.weapon.untargeted;
import com.google.gson.JsonObject;
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.api.player.EquipmentSlot;
@ -11,90 +9,81 @@ import io.lumine.mythic.lib.player.PlayerMetadata;
import io.lumine.mythic.lib.version.VersionSound;
import net.Indyuce.mmoitems.ItemStats;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.util.MMOUtils;
import net.Indyuce.mmoitems.api.util.SoundReader;
import net.Indyuce.mmoitems.stat.LuteAttackEffectStat.LuteAttackEffect;
import net.Indyuce.mmoitems.stat.data.ProjectileParticlesData;
import net.Indyuce.mmoitems.util.MMOUtils;
import org.bukkit.Location;
import org.bukkit.Particle;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import javax.annotation.Nullable;
import java.util.List;
public class Lute extends UntargetedWeapon {
public Lute(Player player, NBTItem item) {
super(player, item, UntargetedWeaponType.RIGHT_CLICK);
}
public Lute(Player player, NBTItem item) {
super(player, item, UntargetedWeaponType.RIGHT_CLICK);
}
@Override
public boolean canAttack(EquipmentSlot slot) {
return true;
}
@Override
public boolean canAttack(EquipmentSlot slot) {
return true;
}
@Override
public void applyAttackEffect(PlayerMetadata stats, EquipmentSlot slot) {
double attackDamage = requireNonZero(stats.getStat("ATTACK_DAMAGE"), 7);
double range = requireNonZero(getNBTItem().getStat(ItemStats.RANGE.getId()), MMOItems.plugin.getConfig().getDouble("default.range"));
Vector weight = new Vector(0, -.003 * getNBTItem().getStat(ItemStats.NOTE_WEIGHT.getId()), 0);
@Override
public void applyAttackEffect(PlayerMetadata stats, EquipmentSlot slot) {
final double attackDamage = requireNonZero(stats.getStat("ATTACK_DAMAGE"), 7);
final double range = requireNonZero(getNBTItem().getStat(ItemStats.RANGE.getId()), MMOItems.plugin.getConfig().getDouble("default.range"));
final Vector weight = new Vector(0, -.003 * getNBTItem().getStat(ItemStats.NOTE_WEIGHT.getId()), 0);
LuteAttackEffect effect = LuteAttackEffect.get(getNBTItem());
SoundReader sound = new SoundReader(getNBTItem().getString("MMOITEMS_LUTE_ATTACK_SOUND"), VersionSound.BLOCK_NOTE_BLOCK_BELL.toSound());
if (effect != null) {
effect.getAttack().handle(stats, attackDamage, getNBTItem(), range, weight, sound);
return;
}
final @Nullable LuteAttackEffect effect = LuteAttackEffect.get(getNBTItem());
final SoundReader sound = new SoundReader(getNBTItem().getString("MMOITEMS_LUTE_ATTACK_SOUND"), VersionSound.BLOCK_NOTE_BLOCK_BELL.toSound());
final @NotNull ProjectileParticlesData projParticle = getNBTItem().hasTag("MMOITEMS_PROJECTILE_PARTICLES") ?
new ProjectileParticlesData(getNBTItem().getString("MMOITEMS_PROJECTILE_PARTICLES")) : ProjectileParticlesData.DEFAULT;
new BukkitRunnable() {
final Vector vec = getPlayer().getEyeLocation().getDirection().multiply(.4);
final Location loc = getPlayer().getEyeLocation();
int ti = 0;
// Custom attack handler
if (effect != null) {
effect.getAttack().handle(stats, attackDamage, getNBTItem(), range, weight, sound, projParticle);
return;
}
public void run() {
if (ti++ > range)
cancel();
// If the item has projectile particle attribute, use selected particle
if (getNBTItem().hasTag("MMOITEMS_PROJECTILE_PARTICLES")) {
JsonObject obj = MythicLib.plugin.getJson().parse(getNBTItem().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(player, particle, loc, red, green, blue);
// If it's not colored, just shoot the particle
} else {
ProjectileParticlesData.shootParticle(player, 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, 0, 1, 0, 0, 1);
}
// Basic lute attack
new BukkitRunnable() {
final Vector vec = getPlayer().getEyeLocation().getDirection().multiply(.4);
final Location loc = getPlayer().getEyeLocation();
int ti = 0;
// Play the sound
sound.play(loc, 2, (float) (.5 + (double) ti / range));
public void run() {
if (ti++ > range)
cancel();
// Damage entities
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;
}
// Display custom particle
projParticle.shootParticle(loc);
for (Entity target : entities)
if (UtilityMethods.canTarget(getPlayer(), loc, target, InteractionType.OFFENSE_ACTION)) {
stats.attack((LivingEntity) target, attackDamage, DamageType.WEAPON, DamageType.MAGIC, DamageType.PROJECTILE);
cancel();
return;
}
}
}
}.runTaskTimer(MMOItems.plugin, 0, 1);
}
// Play the sound
sound.play(loc, 2, (float) (.5 + (double) ti / range));
// Damage entities
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;
}
for (Entity target : entities)
if (UtilityMethods.canTarget(getPlayer(), loc, target, InteractionType.OFFENSE_ACTION)) {
stats.attack((LivingEntity) target, attackDamage, DamageType.WEAPON, DamageType.MAGIC, DamageType.PROJECTILE);
cancel();
return;
}
}
}
}.runTaskTimer(MMOItems.plugin, 0, 1);
}
}

View File

@ -1,37 +1,34 @@
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.UtilityMethods;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.comp.target.InteractionType;
import io.lumine.mythic.lib.damage.DamageType;
import io.lumine.mythic.lib.player.PlayerMetadata;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.util.MMOUtils;
import net.Indyuce.mmoitems.api.util.SoundReader;
import net.Indyuce.mmoitems.stat.data.ProjectileParticlesData;
import net.Indyuce.mmoitems.util.MMOUtils;
import org.bukkit.Location;
import org.bukkit.Particle;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class BruteLuteAttack implements LuteAttackHandler {
@Override
public void handle(PlayerMetadata caster, double damage, NBTItem nbt, double range, Vector weight, SoundReader sound) {
public void handle(PlayerMetadata caster, double damage, NBTItem nbt, double range, @NotNull Vector weight, @NotNull SoundReader sound, @NotNull ProjectileParticlesData projParticle) {
new BukkitRunnable() {
final Vector vec = caster.getPlayer().getEyeLocation().getDirection().multiply(.4);
final Location loc = caster.getPlayer().getEyeLocation();
int ti = 0;
public void run() {
if (ti++ > range)
cancel();
if (ti++ > range) cancel();
List<Entity> entities = MMOUtils.getNearbyChunkEntities(loc);
for (int j = 0; j < 3; j++) {
@ -41,22 +38,8 @@ public class BruteLuteAttack implements LuteAttackHandler {
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(caster.getPlayer(), particle, loc, red, green, blue);
// If it's not colored, just shoot the particle
} else {
ProjectileParticlesData.shootParticle(caster.getPlayer(), 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);
// Display custom particle
projParticle.shootParticle(loc, 2, .1);
if (j == 0) sound.play(loc, 2, (float) (.5 + (double) ti / range));

View File

@ -1,29 +1,28 @@
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.UtilityMethods;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.comp.target.InteractionType;
import io.lumine.mythic.lib.damage.DamageType;
import io.lumine.mythic.lib.player.PlayerMetadata;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.util.MMOUtils;
import net.Indyuce.mmoitems.api.util.SoundReader;
import net.Indyuce.mmoitems.stat.data.ProjectileParticlesData;
import net.Indyuce.mmoitems.util.MMOUtils;
import org.bukkit.Location;
import org.bukkit.Particle;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import javax.annotation.Nullable;
import java.util.List;
public class CircularLuteAttack implements LuteAttackHandler {
@Override
public void handle(PlayerMetadata caster, double damage, NBTItem nbt, double range, Vector weight, SoundReader sound) {
public void handle(PlayerMetadata caster, double damage, NBTItem nbt, double range, @NotNull Vector weight, @NotNull SoundReader sound, @NotNull ProjectileParticlesData projParticle) {
new BukkitRunnable() {
final Vector vec = caster.getPlayer().getEyeLocation().getDirection().multiply(.4);
final Location loc = caster.getPlayer().getEyeLocation();
@ -40,30 +39,12 @@ public class CircularLuteAttack implements LuteAttackHandler {
break;
}
double a = (double) ti / 3;
Vector vec = MMOUtils.rotateFunc(new Vector(Math.cos(a), Math.sin(a), 0).multiply(.3), loc);
final double angle = (double) ti / 3;
final Vector vec = MMOUtils.rotateFunc(new Vector(Math.cos(angle), Math.sin(angle), 0).multiply(.3), loc);
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(caster.getPlayer(), particle, loc.clone().add(vec), red, green, blue);
ProjectileParticlesData.shootParticle(caster.getPlayer(), particle, loc.clone().add(vec.multiply(-1)), red, green, blue);
// If it's not colored, just shoot the particle
} else {
ProjectileParticlesData.shootParticle(caster.getPlayer(), particle, loc.clone().add(vec), 0, 0, 0);
ProjectileParticlesData.shootParticle(caster.getPlayer(), particle, loc.clone().add(vec.multiply(-1)), 0, 0, 0);
}
// If no particle has been provided via projectile particle attribute, default to this particle
} else {
loc.getWorld().spawnParticle(Particle.NOTE, loc.clone().add(vec), 0);
loc.getWorld().spawnParticle(Particle.NOTE, loc.clone().add(vec.multiply(-1)), 0);
}
// Display custom particle
projParticle.shootParticle(loc.clone().add(vec));
projParticle.shootParticle(loc.clone().add(vec.multiply(-1)));
if (j == 0) sound.play(loc, 2, (float) (.5 + (double) ti / range));

View File

@ -3,12 +3,15 @@ package net.Indyuce.mmoitems.api.interaction.weapon.untargeted.lute;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.player.PlayerMetadata;
import net.Indyuce.mmoitems.api.util.SoundReader;
import net.Indyuce.mmoitems.stat.data.ProjectileParticlesData;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import javax.annotation.Nullable;
import java.util.Random;
public interface LuteAttackHandler {
static final Random random = new Random();
static final Random RANDOM = new Random();
void handle(PlayerMetadata caster, double damage, NBTItem nbt, double range, Vector weight, SoundReader sound);
void handle(PlayerMetadata caster, double damage, NBTItem nbt, double range, @NotNull Vector weight, @NotNull SoundReader sound, @NotNull ProjectileParticlesData projParticle);
}

View File

@ -1,29 +1,27 @@
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.UtilityMethods;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.comp.target.InteractionType;
import io.lumine.mythic.lib.damage.DamageType;
import io.lumine.mythic.lib.player.PlayerMetadata;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.util.MMOUtils;
import net.Indyuce.mmoitems.api.util.SoundReader;
import net.Indyuce.mmoitems.stat.data.ProjectileParticlesData;
import net.Indyuce.mmoitems.util.MMOUtils;
import org.bukkit.Location;
import org.bukkit.Particle;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class SimpleLuteAttack implements LuteAttackHandler {
@Override
public void handle(PlayerMetadata caster, double damage, NBTItem nbt, double range, Vector weight, SoundReader sound) {
public void handle(PlayerMetadata caster, double damage, NBTItem nbt, double range, @NotNull Vector weight, @NotNull SoundReader sound, @NotNull ProjectileParticlesData projParticle) {
new BukkitRunnable() {
final Vector vec = caster.getPlayer().getEyeLocation().getDirection().multiply(.4);
final Location loc = caster.getPlayer().getEyeLocation();
@ -40,23 +38,8 @@ public class SimpleLuteAttack implements LuteAttackHandler {
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(caster.getPlayer(), particle, loc, red, green, blue);
// If it's not colored, just shoot the particle
} else {
ProjectileParticlesData.shootParticle(caster.getPlayer(), 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, 0);
}
// Display custom particle
projParticle.shootParticle(loc);
if (j == 0) sound.play(loc, 2, (float) (.5 + (double) ti / range));

View File

@ -1,27 +1,25 @@
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.UtilityMethods;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.comp.target.InteractionType;
import io.lumine.mythic.lib.damage.DamageType;
import io.lumine.mythic.lib.player.PlayerMetadata;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.util.MMOUtils;
import net.Indyuce.mmoitems.api.util.SoundReader;
import net.Indyuce.mmoitems.stat.data.ProjectileParticlesData;
import net.Indyuce.mmoitems.util.MMOUtils;
import org.bukkit.Location;
import org.bukkit.Particle;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
public class SlashLuteAttack implements LuteAttackHandler {
@Override
public void handle(PlayerMetadata caster, double damage, NBTItem nbt, double range, Vector weight, SoundReader sound) {
public void handle(PlayerMetadata caster, double damage, NBTItem nbt, double range, @NotNull Vector weight, @NotNull SoundReader sound, @NotNull ProjectileParticlesData projParticle) {
new BukkitRunnable() {
final Vector vec = caster.getPlayer().getEyeLocation().getDirection();
final Location loc = caster.getPlayer().getLocation().add(0, 1.3, 0);
@ -32,28 +30,12 @@ public class SlashLuteAttack implements LuteAttackHandler {
sound.play(loc, 2, (float) (.5 + ti / range));
for (int k = -30; k < 30; k += 3)
if (random.nextBoolean()) {
if (RANDOM.nextBoolean()) {
loc.setDirection(vec);
loc.setYaw(loc.getYaw() + k);
loc.setPitch(caster.getPlayer().getEyeLocation().getPitch());
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(caster.getPlayer(), particle, loc.clone().add(loc.getDirection().multiply(1.5 * ti)), red, green, blue);
// If it's not colored, just shoot the particle
} else {
ProjectileParticlesData.shootParticle(caster.getPlayer(), particle, loc.clone().add(loc.getDirection().multiply(1.5 * ti)), 0, 0, 0);
}
// If no particle has been provided via projectile particle attribute, default to this particle
} else {
loc.getWorld().spawnParticle(Particle.NOTE, loc.clone().add(loc.getDirection().multiply(1.5 * ti)), 0);
}
projParticle.shootParticle(loc.clone().add(loc.getDirection().multiply(1.5 * ti)));
}
}
}.runTaskTimer(MMOItems.plugin, 0, 1);

View File

@ -1,29 +1,27 @@
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.UtilityMethods;
import io.lumine.mythic.lib.api.item.NBTItem;
import io.lumine.mythic.lib.comp.target.InteractionType;
import io.lumine.mythic.lib.damage.DamageType;
import io.lumine.mythic.lib.player.PlayerMetadata;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.util.MMOUtils;
import net.Indyuce.mmoitems.api.util.SoundReader;
import net.Indyuce.mmoitems.stat.data.ProjectileParticlesData;
import net.Indyuce.mmoitems.util.MMOUtils;
import org.bukkit.Location;
import org.bukkit.Particle;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class WaveLuteAttack implements LuteAttackHandler {
@Override
public void handle(PlayerMetadata caster, double damage, NBTItem nbt, double range, Vector weight, SoundReader sound) {
public void handle(PlayerMetadata caster, double damage, NBTItem nbt, double range, @NotNull Vector weight, @NotNull SoundReader sound, @NotNull ProjectileParticlesData projParticle) {
new BukkitRunnable() {
final Vector vec = caster.getPlayer().getEyeLocation().getDirection().multiply(.4);
final Location loc = caster.getPlayer().getEyeLocation();
@ -40,28 +38,10 @@ public class WaveLuteAttack implements LuteAttackHandler {
break;
}
Vector vec = MMOUtils.rotateFunc(new Vector(.5, 0, 0), loc);
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(caster.getPlayer(), particle, loc.clone().add(vec.multiply(Math.sin((double) ti / 2))), red, green, blue);
ProjectileParticlesData.shootParticle(caster.getPlayer(), particle, loc.clone().add(vec.multiply(-1)), red, green, blue);
// If it's not colored, just shoot the particle
} else {
ProjectileParticlesData.shootParticle(caster.getPlayer(), particle, loc.clone().add(vec.multiply(Math.sin((double) ti / 2))), 0, 0, 0);
ProjectileParticlesData.shootParticle(caster.getPlayer(), particle, loc.clone().add(vec.multiply(-1)), 0, 0, 0);
}
// If no particle has been provided via projectile particle attribute, default to this particle
} else {
loc.getWorld().spawnParticle(Particle.NOTE, loc.clone().add(vec.multiply(Math.sin((double) ti / 2))), 0);
loc.getWorld().spawnParticle(Particle.NOTE, loc.clone().add(vec.multiply(-1)), 0);
}
// Display particle
final Vector vec = MMOUtils.rotateFunc(new Vector(.5, 0, 0), loc);
projParticle.shootParticle(loc.clone().add(vec.multiply(Math.sin((double) ti / 2))));
projParticle.shootParticle(loc.clone().add(vec.multiply(-1)));
if (j == 0) sound.play(loc, 2, (float) (.5 + (double) ti / range));

View File

@ -3,13 +3,11 @@ package net.Indyuce.mmoitems.stat;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.api.item.ItemTag;
import io.lumine.mythic.lib.api.item.SupportedNBTTagValues;
import io.lumine.mythic.lib.api.util.AltChar;
import io.lumine.mythic.lib.version.VersionMaterial;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.util.MMOUtils;
import net.Indyuce.mmoitems.api.edition.StatEdition;
import net.Indyuce.mmoitems.api.item.build.ItemStackBuilder;
import net.Indyuce.mmoitems.api.item.mmoitem.ReadMMOItem;
@ -17,6 +15,7 @@ import net.Indyuce.mmoitems.gui.edition.EditionInventory;
import net.Indyuce.mmoitems.stat.data.ProjectileParticlesData;
import net.Indyuce.mmoitems.stat.data.type.StatData;
import net.Indyuce.mmoitems.stat.type.ItemStat;
import net.Indyuce.mmoitems.util.MMOUtils;
import org.apache.commons.lang.Validate;
import org.bukkit.ChatColor;
import org.bukkit.Particle;
@ -76,18 +75,13 @@ public class ProjectileParticles extends ItemStat<ProjectileParticlesData, Proje
@Override
public void whenDisplayed(List<String> lore, Optional<ProjectileParticlesData> statData) {
if (statData.isPresent()) {
String dataStr = statData.get().toString();
JsonObject data = MythicLib.plugin.getJson().parse(dataStr, JsonObject.class);
Particle particle = Particle.valueOf(data.get("Particle").getAsString());
final ProjectileParticlesData data = statData.get();
Particle particle = data.getParticle();
lore.add(ChatColor.GRAY + "Current Value: " + ChatColor.GREEN + particle);
if (ProjectileParticlesData.isColorable(particle)) {
String red = String.valueOf(data.get("Red"));
String green = String.valueOf(data.get("Green"));
String blue = String.valueOf(data.get("Blue"));
String colorStr = particle == Particle.NOTE ? red : red + " " + green + " " + blue;
String colorStr = particle == Particle.NOTE ? String.valueOf(data.getRed()) : data.getRed() + " " + data.getGreen() + " " + data.getBlue();
lore.add(ChatColor.GRAY + "Color: " + ChatColor.GREEN + colorStr);
}
} else

View File

@ -8,8 +8,6 @@ import net.Indyuce.mmoitems.api.interaction.weapon.untargeted.staff.*;
import net.Indyuce.mmoitems.api.item.build.ItemStackBuilder;
import net.Indyuce.mmoitems.gui.edition.EditionInventory;
import net.Indyuce.mmoitems.stat.data.StringData;
import net.Indyuce.mmoitems.stat.data.type.StatData;
import net.Indyuce.mmoitems.stat.type.GemStoneStat;
import net.Indyuce.mmoitems.stat.type.StringStat;
import org.jetbrains.annotations.NotNull;
@ -51,14 +49,12 @@ public class StaffSpiritStat extends StringStat {
// targeted cursed projectile."), new CursedSpirit()),
;
private final String lore;
private final String name, defaultLore;
private final StaffAttackHandler handler;
private final String name;
StaffSpirit(String name, String lore, StaffAttackHandler handler) {
StaffSpirit(String name, String defaultLore, StaffAttackHandler handler) {
this.name = name;
this.lore = lore;
this.defaultLore = defaultLore;
this.handler = handler;
}
@ -74,19 +70,16 @@ public class StaffSpiritStat extends StringStat {
return name;
}
/*
* TODO make update
*/
public String getName() {
return MMOItems.plugin.getLanguage().getStaffSpiritName(this);
}
public boolean hasLore() {
return lore != null;
return defaultLore != null;
}
public String getLore() {
return lore;
public String getDefaultLore() {
return defaultLore;
}
public StaffAttackHandler getAttack() {

View File

@ -1,11 +1,11 @@
package net.Indyuce.mmoitems.stat.data;
import net.Indyuce.mmoitems.ItemStats;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem;
import net.Indyuce.mmoitems.stat.data.type.Mergeable;
import net.Indyuce.mmoitems.stat.data.type.StatData;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.jetbrains.annotations.NotNull;
@ -30,7 +30,7 @@ public class EnchantListData implements StatData, Mergeable {
public void addEnchant(Enchantment enchant, int level) {
// Ignore lvl 0 enchants :wazowskibruhmoment:
if (level == 0) { enchants.remove(enchant); } else { enchants.put(enchant, level);}
if (level <= 0) { enchants.remove(enchant); } else { enchants.put(enchant, level);}
}
public void clear() { enchants.clear(); }
@ -50,28 +50,11 @@ public class EnchantListData implements StatData, Mergeable {
@Override
public void merge(StatData data) {
Validate.isTrue(data instanceof EnchantListData, "Cannot merge two different stat data types");
boolean additiveMerge = MMOItems.plugin.getConfig().getBoolean("stat-merging.additive-enchantments", false);
for (Enchantment enchant : ((EnchantListData) data).getEnchants()) {
if (additiveMerge) {
// Additive
enchants.put(enchant, ((EnchantListData) data).getLevel(enchant) + enchants.getOrDefault(enchant, 0));
} else {
// Max Enchantment
addEnchant(enchant,
// Does this one already have the enchant?
enchants.containsKey(enchant) ?
// Use the better of the two
Math.max(((EnchantListData) data).getLevel(enchant), enchants.get(enchant)) :
// No enchant yet, just copy over
((EnchantListData) data).getLevel(enchant));
}
}
Bukkit.broadcastMessage("Merging enchant lists");
final EnchantListData enchantList = (EnchantListData) data;
for (Enchantment enchant : enchantList.getEnchants())
addEnchant(enchant, Math.max(enchants.getOrDefault(enchant, 0), enchantList.getLevel(enchant)));
}
@Override

View File

@ -1,6 +1,7 @@
package net.Indyuce.mmoitems.stat.data;
import com.google.gson.JsonObject;
import io.lumine.mythic.lib.MythicLib;
import io.lumine.mythic.lib.gson.JsonObject;
import net.Indyuce.mmoitems.api.item.build.MMOItemBuilder;
import net.Indyuce.mmoitems.stat.data.random.RandomStatData;
import net.Indyuce.mmoitems.stat.data.type.StatData;
@ -9,7 +10,6 @@ import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Particle;
import org.bukkit.block.data.BlockData;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
public class ProjectileParticlesData implements StatData, RandomStatData<ProjectileParticlesData> {
@ -17,7 +17,11 @@ public class ProjectileParticlesData implements StatData, RandomStatData<Project
private final int red, green, blue;
private final boolean colored;
// Particles that can't be colored
public static final ProjectileParticlesData DEFAULT = new ProjectileParticlesData(Particle.NOTE);
/**
* Uncolored particles
*/
public ProjectileParticlesData(Particle particle) {
this.particle = particle;
this.red = 0;
@ -26,7 +30,9 @@ public class ProjectileParticlesData implements StatData, RandomStatData<Project
this.colored = false;
}
// Particles that can be colored
/**
* Colored particles
*/
public ProjectileParticlesData(Particle particle, int red, int green, int blue) {
this.particle = particle;
this.red = red;
@ -35,6 +41,26 @@ public class ProjectileParticlesData implements StatData, RandomStatData<Project
this.colored = true;
}
/**
* Colored particles
*/
public ProjectileParticlesData(String jsonObject) {
final JsonObject obj = MythicLib.plugin.getGson().fromJson(jsonObject, JsonObject.class);
particle = Particle.valueOf(obj.get("Particle").getAsString());
if (isColorable(particle)) {
colored = true;
red = obj.get("Red").getAsInt();
green = obj.get("Green").getAsInt();
blue = obj.get("Blue").getAsInt();
} else {
colored = false;
red = 0;
green = 0;
blue = 0;
}
}
public Particle getParticle() {
return particle;
}
@ -68,42 +94,44 @@ public class ProjectileParticlesData implements StatData, RandomStatData<Project
return object.toString();
}
public static void shootParticle(Player player, Particle particle, Location loc, double offsetX, double offsetY, double offsetZ) {
public void shootParticle(Location loc) {
shootParticle(loc, 1, 0);
}
public void shootParticle(Location loc, int amount, double offset) {
if (isColorable(particle)) {
switch (particle) {
case REDSTONE:
// REDSTONE particles take dustOptions with RGB values. Normal REDSTONE particles are size 1 but can realistically be anything.
Particle.DustOptions dustOptions = new Particle.DustOptions(Color.fromRGB((int) offsetX, (int) offsetY, (int) offsetZ), 1);
player.getWorld().spawnParticle(Particle.REDSTONE, loc, 25, dustOptions);
Particle.DustOptions dustOptions = new Particle.DustOptions(Color.fromRGB(red, green, blue), 1);
loc.getWorld().spawnParticle(Particle.REDSTONE, loc, amount, offset, offset, offset, 0, dustOptions);
break;
case NOTE:
// NOTE particles only have 24 colors. offsetX must be a number between 0 and 1 in intervals of 1/24. offsetY and offsetZ must be 0. Count should be 0 and "extra" should be 1.
double note = offsetX / 24D;
player.getWorld().spawnParticle(Particle.NOTE, loc, 0, note, 0, 0, 1);
double note = red / 24D;
loc.getWorld().spawnParticle(Particle.NOTE, loc, 0, note, 0, 0, 1);
break;
default:
// SPELL_MOB and SPELL_MOB_AMBIENT must be a value between 0 and 1 in intervals in 1/255. "Extra" must be 1 or the color will not be correct. 0 will be black and anything else will be random.
double red = offsetX / 255D;
double green = offsetY / 255D;
double blue = offsetZ / 255D;
player.getWorld().spawnParticle(particle, loc, 0, red, green, blue, 1);
double red = this.red / 255D;
double green = this.green / 255D;
double blue = this.blue / 255D;
loc.getWorld().spawnParticle(particle, loc, 0, red, green, blue, 1);
}
} else {
} else if (particle == Particle.ITEM_CRACK) {
// Some particles require a material. I don't really want to handle this right now so just make it stone.
if (particle == Particle.ITEM_CRACK || particle == Particle.BLOCK_CRACK || particle == Particle.BLOCK_DUST || particle == Particle.FALLING_DUST) {
if (particle == Particle.ITEM_CRACK) {
ItemStack materialData = new ItemStack(Material.STONE);
player.getWorld().spawnParticle(particle, loc, 0, materialData);
} else {
BlockData fallingDustData = Material.STONE.createBlockData();
player.getWorld().spawnParticle(particle, loc, 0, fallingDustData);
}
} else {
// All non-material and non-colorable particles just get shot normally.
// Changing the count to anything other than 0 will cause certain particles to shoot off in random directions as they take directional parameters via offsets.
player.getWorld().spawnParticle(particle, loc, 0);
}
}
ItemStack materialData = new ItemStack(Material.STONE);
loc.getWorld().spawnParticle(particle, loc, amount, offset, offset, offset, 0, materialData);
} else if (particle == Particle.ITEM_CRACK || particle == Particle.BLOCK_CRACK || particle == Particle.BLOCK_DUST || particle == Particle.FALLING_DUST) {
BlockData fallingDustData = Material.STONE.createBlockData();
loc.getWorld().spawnParticle(particle, loc, amount, offset, offset, offset, 0, fallingDustData);
} else
// All non-material and non-colorable particles just get shot normally.
// Changing the count to anything other than 0 will cause certain particles to shoot off in random directions as they take directional parameters via offsets.
loc.getWorld().spawnParticle(particle, loc, amount, offset, offset, offset, 0);
}
@Override