package com.nisovin.magicspells.spells.instant; import org.bukkit.Bukkit; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import org.bukkit.util.Vector; import com.nisovin.magicspells.MagicSpells; import com.nisovin.magicspells.Subspell; import com.nisovin.magicspells.events.SpellTargetEvent; import com.nisovin.magicspells.spelleffects.EffectPosition; import com.nisovin.magicspells.spells.InstantSpell; import com.nisovin.magicspells.util.BoundingBox; import com.nisovin.magicspells.util.MagicConfig; public class BeamSpell extends InstantSpell { float beamWidth; float yOffset; float maxDistance; float interval; String spellNameToCast; Subspell spell; public BeamSpell(MagicConfig config, String spellName) { super(config, spellName); beamWidth = getConfigFloat("beam-width", 2); yOffset = getConfigFloat("y-offset", 0); maxDistance = getConfigFloat("max-distance", 50); interval = getConfigFloat("interval", 0.25f); spellNameToCast = getConfigString("spell", ""); if (interval < 0.01) interval = 0.01f; } @Override public void initialize() { super.initialize(); spell = new Subspell(spellNameToCast); if (!spell.process()) { MagicSpells.error("Beam Spell '" + internalName + "' has invalid spell defined"); } } @Override public PostCastAction castSpell(Player player, SpellCastState state, float power, String[] args) { if (state == SpellCastState.NORMAL) { //float distSq = maxDistance * maxDistance; Vector start = player.getEyeLocation().toVector(); start = start.add(new Vector(0, yOffset, 0)); Vector dir = player.getEyeLocation().getDirection().multiply(interval); Vector pos = start.clone(); float d = 0; while (d < maxDistance) { d += interval; pos.add(dir); if (!isTransparent(pos.toLocation(player.getWorld()).getBlock())) { break; } playSpellEffects(EffectPosition.SPECIAL, pos.toLocation(player.getWorld())); } BoundingBox box = new BoundingBox(start.toLocation(player.getWorld()), pos.toLocation(player.getWorld())); box.expand(beamWidth); for (LivingEntity e : player.getWorld().getLivingEntities()) { if (!e.equals(player) && !e.isDead() && box.contains(e) && (validTargetList == null || validTargetList.canTarget(e))) { double dist = pointLineDist(start, pos, e.getLocation().add(0, 0.8, 0).toVector()); if (dist < beamWidth/2) { SpellTargetEvent event = new SpellTargetEvent(this, player, e, power); Bukkit.getPluginManager().callEvent(event); if (!event.isCancelled()) { spell.castAtEntity(player, event.getTarget(), event.getPower()); playSpellEffects(EffectPosition.TARGET, event.getTarget()); } } } } playSpellEffects(EffectPosition.CASTER, player); } return PostCastAction.HANDLE_NORMALLY; } double pointLineDist(Vector p1, Vector p2, Vector p0) { Vector v1 = p2.clone().subtract(p1); Vector v2 = p1.clone().subtract(p0); Vector v3 = v1.clone().crossProduct(v2); return v3.length() / v1.length(); } }