diff --git a/editor/js/component.js b/editor/js/component.js index 75cdb6a1..5296ee76 100644 --- a/editor/js/component.js +++ b/editor/js/component.js @@ -193,7 +193,8 @@ var Mechanic = { WARP_SWAP: { name: 'Warp Swap', container: false, construct: MechanicWarpSwap }, WARP_TARGET: { name: 'Warp Target', container: false, construct: MechanicWarpTarget }, WARP_VALUE: { name: 'Warp Value', container: false, construct: MechanicWarpValue }, - WOLF: { name: 'Wolf', container: true, construct: MechanicWolf } + WOLF: { name: 'Wolf', container: true, construct: MechanicWolf }, + SET_GLOW: { name: 'Set Glow', container: false, construct: MechanicSetGlow } }; var saveIndex; @@ -2504,6 +2505,9 @@ function MechanicParticleProjectile() .setTooltip('How long in seconds before the projectile will expire in case it doesn\'t hit anything') ); + //Add missile options (homing projectile) + addMissileOptions(this, true); + addEffectOptions(this, true); } @@ -3239,6 +3243,21 @@ function MechanicWolf() ); } +extend('MechanicSetGlow', 'Component'); +function MechanicSetGlow() +{ + this.super('Set Glow', Type.MECHANIC, false); + + this.description = 'glow target with color (only caster can see it)'; + + this.data.push(new ListValue('Glow Color', 'color', getGlowColors(), 'White') + .setTooltip('The color of glowing') + ); + this.data.push(new AttributeValue('Duration', 'seconds', 10, 0) + .setTooltip('How long should it glow for') + ); +} + // The active component being edited or added to var activeComponent = undefined; @@ -3391,7 +3410,29 @@ function addParticleOptions(component) { component.data.push(new DoubleValue('Speed', 'speed', 0.1).setTooltip('Speed of the particle. For some particles controls other parameters, such as size.') ); } +function addMissileOptions(component, optional) +{ + var opt = appendNone; + if(optional){ + opt = appendMissileOptional; + component.data.push(new ListValue('Use Missile', 'use-missile', [ 'True', 'False' ], 'False') + .setTooltip('Whether or not to use the missile (homing projectile)..') + ); + } + component.data.push(opt(new StringValue('Missile Target', 'missile_target', "none") + .setTooltip('The target you would like to home at')) + ); + component.data.push(opt(new DoubleValue('Missile Threshold', 'missile_threshold', 3) + .setTooltip('The threshold of the missile')) + ); + component.data.push(opt(new DoubleValue('Missile Angle', 'missile_angle', 3) + .setTooltip('The angle of the missile will turn')) + ); + component.data.push(opt(new DoubleValue('Missile Delay', 'missile_delay', 0) + .setTooltip('The delay before auto homing the target')) + ); +} function addEffectOptions(component, optional) { var opt = appendNone; @@ -3469,6 +3510,11 @@ function appendOptional(value) value.requireValue('use-effect', [ 'True' ]); return value; } +function appendMissileOptional(value) +{ + value.requireValue('use-missile', [ 'True' ]); + return value; +} function appendNone(value) { diff --git a/editor/js/data/data.js b/editor/js/data/data.js index 0a7018b9..591b02a2 100644 --- a/editor/js/data/data.js +++ b/editor/js/data/data.js @@ -66,6 +66,9 @@ function getBadPotions() { function getDyes() { return DYES; } +function getGlowColors(){ + return GLOW_COLORS; +} const GOOD_POTIONS = [ "Speed", @@ -118,4 +121,22 @@ const DYES = [ 'RED', 'WHITE', 'YELLOW' +]; +const GLOW_COLORS = ['BLACK', + 'DARK_BLUE', + 'DARK_GREEN', + 'DARK_AQUA', + 'DARK_RED', + 'DARK_PURPLE', + 'GOLD', + 'GRAY', + 'DARK_GRAY', + 'BLUE', + 'GREEN', + 'AQUA', + 'RED', + 'PURPLE', + 'YELLOW', + 'WHITE', + 'NONE' ]; \ No newline at end of file diff --git a/lib/GlowAPI_v1.4.6-SNAPSHOT.jar b/lib/GlowAPI_v1.4.6-SNAPSHOT.jar new file mode 100644 index 00000000..8c07398c Binary files /dev/null and b/lib/GlowAPI_v1.4.6-SNAPSHOT.jar differ diff --git a/pom.xml b/pom.xml index 7ec3a53d..b19cd4b9 100644 --- a/pom.xml +++ b/pom.xml @@ -142,9 +142,16 @@ LibsDisguises LibsDisguises - 10.0.19 + 10.0.26 provided + + com.github.InventivetalentDev + GlowAPI + 1.4.6-SNAPSHOT + system + ${basedir}/lib/GlowAPI_v1.4.6-SNAPSHOT.jar + me.clip placeholderapi diff --git a/src/main/java/com/sucy/skill/SkillAPI.java b/src/main/java/com/sucy/skill/SkillAPI.java index 60527e3c..e40586cc 100644 --- a/src/main/java/com/sucy/skill/SkillAPI.java +++ b/src/main/java/com/sucy/skill/SkillAPI.java @@ -74,7 +74,7 @@ *

You can retrieve a reference to this through Bukkit the same way as any other plugin.

*/ public class SkillAPI extends JavaPlugin { - private static SkillAPI singleton; + public static SkillAPI singleton; private final HashMap skills = new HashMap<>(); private final HashMap classes = new HashMap<>(); diff --git a/src/main/java/com/sucy/skill/api/projectile/ParticleProjectile.java b/src/main/java/com/sucy/skill/api/projectile/ParticleProjectile.java index 926dffca..42124fd0 100644 --- a/src/main/java/com/sucy/skill/api/projectile/ParticleProjectile.java +++ b/src/main/java/com/sucy/skill/api/projectile/ParticleProjectile.java @@ -26,6 +26,7 @@ */ package com.sucy.skill.api.projectile; +import com.sucy.skill.SkillAPI; import com.sucy.skill.api.Settings; import com.sucy.skill.api.event.ParticleProjectileExpireEvent; import com.sucy.skill.api.event.ParticleProjectileHitEvent; @@ -34,8 +35,10 @@ import com.sucy.skill.api.util.ParticleHelper; import org.bukkit.Bukkit; import org.bukkit.Location; +import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; import org.bukkit.event.Event; +import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.util.Vector; import java.util.ArrayList; @@ -75,7 +78,12 @@ public class ParticleProjectile extends CustomProjectile private int freq; private int life; private Vector gravity; - private boolean pierce; + private boolean pierce; + private Entity missileTarget; + private double missileThreshold; + private double missileAngle; + private double missileDelay; + private boolean missileStarted = false; /** * Constructor @@ -96,10 +104,42 @@ public ParticleProjectile(LivingEntity shooter, int level, Location loc, Setting this.life = (int) (settings.getDouble(LIFESPAN, 2) * 20); this.gravity = new Vector(0, settings.getDouble(GRAVITY, 0), 0); this.pierce = settings.getBool(PIERCE, false); + this.missileTarget = null; + steps = (int) Math.ceil(vel.length() * 2); + vel.multiply(1.0 / steps); + gravity.multiply(1.0 / steps); + Bukkit.getPluginManager().callEvent(new ParticleProjectileLaunchEvent(this)); + } + public ParticleProjectile(LivingEntity shooter, int level, Location loc, Settings settings, Entity missileTarget, double missileThreshold, double missileAngle, double missileDelay) + { + super(shooter); + this.loc = loc; + this.settings = settings; + this.vel = loc.getDirection().multiply(settings.getAttr(SPEED, level, 1.0)); + this.freq = (int) (20 * settings.getDouble(FREQUENCY, 0.5)); + this.life = (int) (settings.getDouble(LIFESPAN, 2) * 20); + this.gravity = new Vector(0, settings.getDouble(GRAVITY, 0), 0); + this.pierce = settings.getBool(PIERCE, false); + this.missileTarget = missileTarget; + this.missileThreshold = missileThreshold; + this.missileAngle = missileAngle; + this.missileDelay = missileDelay; steps = (int) Math.ceil(vel.length() * 2); vel.multiply(1.0 / steps); gravity.multiply(1.0 / steps); + //Missile delay + if(missileDelay == 0){ + missileStarted = true; + }else { + new BukkitRunnable() { + + @Override + public void run() { + missileStarted = true; + } + }.runTaskLater(SkillAPI.singleton, Math.round(missileDelay * 20)); + } Bukkit.getPluginManager().callEvent(new ParticleProjectileLaunchEvent(this)); } @@ -224,6 +264,28 @@ public void run() cancel(); Bukkit.getPluginManager().callEvent(new ParticleProjectileExpireEvent(this)); } + + //Missile + if(missileTarget!=null && missileStarted){ + final Vector vel = getVelocity(); + final double speed = vel.length(); + final Vector dir = vel.multiply(1 / speed); + final Vector towards = missileTarget.getLocation().toVector().subtract(getLocation().toVector()); + final Vector targetDir = towards.normalize(); + final double dot = dir.dot(targetDir);//degree of inaccurate + if (dot >= missileThreshold) { + setVelocity(targetDir.multiply(speed)); + } else { + Vector currentDir = vel.normalize(); + Vector sum = currentDir.add(targetDir); + Vector newDir = sum.divide(new Vector(2,2,2)); + Vector normalizedNewDir = newDir.normalize(); + setVelocity(normalizedNewDir.multiply(speed)); + //final double m = Math.sin() + //baseProjectile.setVelocity(result); + } + + } } /** @@ -240,7 +302,7 @@ public void run() * * @return list of fired projectiles */ - public static ArrayList spread(LivingEntity shooter, int level, Vector center, Location loc, Settings settings, double angle, int amount, ProjectileCallback callback) + public static ArrayList spread(LivingEntity shooter, int level, Vector center, Location loc, Settings settings, double angle, int amount, ProjectileCallback callback, Entity missileTarget, double missileThreshold, double missileAngle, double missileDelay) { ArrayList dirs = calcSpread(center, angle, amount); ArrayList list = new ArrayList(); @@ -248,7 +310,7 @@ public static ArrayList spread(LivingEntity shooter, int lev { Location l = loc.clone(); l.setDirection(dir); - ParticleProjectile p = new ParticleProjectile(shooter, level, l, settings); + ParticleProjectile p = new ParticleProjectile(shooter, level, l, settings, missileTarget, missileThreshold, missileAngle, missileDelay); p.setCallback(callback); list.add(p); } @@ -269,7 +331,7 @@ public static ArrayList spread(LivingEntity shooter, int lev * * @return list of fired projectiles */ - public static ArrayList rain(LivingEntity shooter, int level, Location center, Settings settings, double radius, double height, int amount, ProjectileCallback callback) + public static ArrayList rain(LivingEntity shooter, int level, Location center, Settings settings, double radius, double height, int amount, ProjectileCallback callback, Entity missileTarget, double missileThreshold, double missileAngle, double missileDelay) { Vector vel = new Vector(0, 1, 0); ArrayList locs = calcRain(center, radius, height, amount); @@ -277,7 +339,7 @@ public static ArrayList rain(LivingEntity shooter, int level for (Location l : locs) { l.setDirection(vel); - ParticleProjectile p = new ParticleProjectile(shooter, level, l, settings); + ParticleProjectile p = new ParticleProjectile(shooter, level, l, settings, missileTarget, missileThreshold, missileAngle, missileDelay); p.setCallback(callback); list.add(p); } diff --git a/src/main/java/com/sucy/skill/dynamic/ComponentRegistry.java b/src/main/java/com/sucy/skill/dynamic/ComponentRegistry.java index e9f9ab81..59fcaa0c 100644 --- a/src/main/java/com/sucy/skill/dynamic/ComponentRegistry.java +++ b/src/main/java/com/sucy/skill/dynamic/ComponentRegistry.java @@ -291,5 +291,6 @@ private static void register(final EffectComponent component) { register(new WarpTargetMechanic()); register(new WarpValueMechanic()); register(new WolfMechanic()); + register(new SetGlowMechanic()); } } diff --git a/src/main/java/com/sucy/skill/dynamic/mechanic/ParticleProjectileMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/ParticleProjectileMechanic.java index 5015fcdb..5884164f 100644 --- a/src/main/java/com/sucy/skill/dynamic/mechanic/ParticleProjectileMechanic.java +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/ParticleProjectileMechanic.java @@ -40,6 +40,7 @@ import com.sucy.skill.cast.IndicatorType; import com.sucy.skill.cast.ProjectileIndicator; import com.sucy.skill.dynamic.TempEntity; +import com.sucy.skill.dynamic.target.RememberTarget; import org.bukkit.Location; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; @@ -66,6 +67,13 @@ public class ParticleProjectileMechanic extends MechanicComponent implements Pro private static final String UPWARD = "upward"; private static final String FORWARD = "forward"; + //Missile + private static final String MISSILE_TARGET = "missile_target"; + private static final String MISSILE_THRESHOLD = "missile_threshold"; + private static final String MISSILE_ANGLE = "missile_angle"; + private static final String MISSILE_DELAY = "missile_delay"; + + //Effect private static final String USE_EFFECT = "use-effect"; private static final String EFFECT_KEY = "effect-key"; @@ -144,6 +152,18 @@ public boolean execute(LivingEntity caster, int level, List target copy.set(ParticleProjectile.SPEED, parseValues(caster, ParticleProjectile.SPEED, level, 1), 0); copy.set(ParticleHelper.PARTICLES_KEY, parseValues(caster, ParticleHelper.PARTICLES_KEY, level, 1), 0); copy.set(ParticleHelper.RADIUS_KEY, parseValues(caster, ParticleHelper.RADIUS_KEY, level, 0), 0); + final List missileTargets = RememberTarget.remember(caster, settings.getString(MISSILE_TARGET, "_none")); + + LivingEntity missileTarget = null; + double missileThreshold = 0; + double missileAngle = 0; + double missileDelay = 0; + if(missileTargets.size() > 0) { + missileTarget = missileTargets.get(0); + missileThreshold = settings.getDouble(MISSILE_THRESHOLD); + missileAngle = settings.getDouble(MISSILE_ANGLE); + missileDelay = settings.getDouble(MISSILE_DELAY); + } // Fire from each target for (LivingEntity target : targets) { @@ -154,7 +174,7 @@ public boolean execute(LivingEntity caster, int level, List target if (spread.equals("rain")) { double radius = parseValues(caster, RADIUS, level, 2.0); double height = parseValues(caster, HEIGHT, level, 8.0); - list = ParticleProjectile.rain(caster, level, loc, copy, radius, height, amount, this); + list = ParticleProjectile.rain(caster, level, loc, copy, radius, height, amount, this, missileTarget, missileThreshold, missileAngle, missileDelay); } else { Vector dir = target.getLocation().getDirection(); @@ -179,7 +199,7 @@ public boolean execute(LivingEntity caster, int level, List target copy, angle, amount, - this + this, missileTarget, missileThreshold, missileAngle, missileDelay ); } diff --git a/src/main/java/com/sucy/skill/dynamic/mechanic/SetGlowMechanic.java b/src/main/java/com/sucy/skill/dynamic/mechanic/SetGlowMechanic.java new file mode 100644 index 00000000..33c037cb --- /dev/null +++ b/src/main/java/com/sucy/skill/dynamic/mechanic/SetGlowMechanic.java @@ -0,0 +1,83 @@ +/** + * SkillAPI + * com.sucy.skill.dynamic.mechanic.WolfMechanic + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Steven Sucy + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software") to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package com.sucy.skill.dynamic.mechanic; + +import com.rit.sucy.text.TextFormatter; +import com.sucy.skill.SkillAPI; +import com.sucy.skill.api.skills.PassiveSkill; +import com.sucy.skill.api.skills.Skill; +import com.sucy.skill.dynamic.DynamicSkill; +import com.sucy.skill.listener.MechanicListener; +import com.sucy.skill.task.RemoveTask; +import org.bukkit.Bukkit; +import org.bukkit.DyeColor; +import org.bukkit.Sound; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Wolf; +import org.inventivetalent.glow.GlowAPI; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Applies a flag to each target + */ +public class SetGlowMechanic extends MechanicComponent { + private static final String COLOR = "color"; + private static final String SECONDS = "seconds"; + + /** + * Executes the component + * + * @param caster caster of the skill + * @param level level of the skill + * @param targets targets to apply to + * + * @return true if applied to something, false otherwise + */ + @Override + public boolean execute(LivingEntity caster, int level, List targets) { + if (!(caster instanceof Player)) { + return false; + } + + final Player player = (Player) caster; + String color = settings.getString(COLOR); + double seconds = settings.getDouble(SECONDS); + GlowAPI.setGlowing(targets, GlowAPI.Color.valueOf(color), player); + return true; + } + + @Override + public String getKey() { + return "set glow"; + } + +}