package com.nisovin.magicspells.spells.targeted;
import java.util.HashSet;
import org.bukkit.Bukkit;
import org.bukkit.Effect;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.util.BlockIterator;
import com.nisovin.magicspells.events.SpellTargetLocationEvent;
import com.nisovin.magicspells.spelleffects.EffectPosition;
import com.nisovin.magicspells.spells.TargetedLocationSpell;
import com.nisovin.magicspells.spells.TargetedSpell;
import com.nisovin.magicspells.util.BlockUtils;
import com.nisovin.magicspells.util.MagicConfig;
public class BlinkSpell extends TargetedSpell implements TargetedLocationSpell {
private boolean passThroughCeiling;
private boolean smokeTrail;
private String strCantBlink = null;
public BlinkSpell(MagicConfig config, String spellName) {
super(config, spellName);
passThroughCeiling = getConfigBoolean("pass-through-ceiling", false);
smokeTrail = getConfigBoolean("smoke-trail", true);
strCantBlink = getConfigString("str-cant-blink", "You can't blink there.");
}
@Override
public PostCastAction castSpell(Player player, SpellCastState state, float power, String[] args) {
if (state == SpellCastState.NORMAL) {
int range = getRange(power);
if (range <= 0) range = 25;
if (range > 125) range = 125;
BlockIterator iter;
try {
iter = new BlockIterator(player, range>0&&range<150?range:150);
} catch (IllegalStateException e) {
iter = null;
}
HashSet<Location> smokes = null;
if (smokeTrail) {
smokes = new HashSet<Location>();
}
Block prev = null;
Block found = null;
Block b;
if (iter != null) {
while (iter.hasNext()) {
b = iter.next();
if (BlockUtils.isTransparent(this, b)) {
prev = b;
if (smokeTrail) {
smokes.add(b.getLocation());
}
} else {
found = b;
break;
}
}
}
if (found != null) {
Location loc = null;
if (range > 0 && !inRange(found.getLocation(), player.getLocation(), range)) {
} else if (!passThroughCeiling && found.getRelative(0,-1,0).equals(prev)) {
// trying to move upward
if (BlockUtils.isPathable(prev) && BlockUtils.isPathable(prev.getRelative(0,-1,0))) {
loc = prev.getRelative(0,-1,0).getLocation();
}
} else if (BlockUtils.isPathable(found.getRelative(0,1,0)) && BlockUtils.isPathable(found.getRelative(0,2,0))) {
// try to stand on top
loc = found.getLocation();
loc.setY(loc.getY() + 1);
} else if (prev != null && BlockUtils.isPathable(prev) && BlockUtils.isPathable(prev.getRelative(0,1,0))) {
// no space on top, put adjacent instead
loc = prev.getLocation();
}
if (loc != null) {
SpellTargetLocationEvent event = new SpellTargetLocationEvent(this, player, loc, power);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
loc = null;
} else {
loc = event.getTargetLocation();
}
}
if (loc != null) {
loc.setX(loc.getX()+.5);
loc.setZ(loc.getZ()+.5);
loc.setPitch(player.getLocation().getPitch());
loc.setYaw(player.getLocation().getYaw());
Location origLoc = player.getLocation();
playSpellEffects(EffectPosition.CASTER, origLoc);
teleport(player, loc, smokes);
playSpellEffects(EffectPosition.TARGET, loc);
playSpellEffectsTrail(origLoc, loc);
} else {
return noTarget(player, strCantBlink);
}
} else {
return noTarget(player, strCantBlink);
}
}
return PostCastAction.HANDLE_NORMALLY;
}
private void teleport(Player player, Location location, HashSet<Location> smokeLocs) {
playSpellEffects(player.getLocation(), location);
player.teleport(location);
if (smokeTrail && smokeLocs != null) {
for (Location l : smokeLocs) {
l.getWorld().playEffect(l, Effect.SMOKE, 4);
}
}
}
@Override
public boolean castAtLocation(Player caster, Location target, float power) {
target.setYaw(caster.getLocation().getYaw());
target.setPitch(caster.getLocation().getPitch());
teleport(caster, target, null);
return true;
}
@Override
public boolean castAtLocation(Location target, float power) {
return false;
}
}