package com.nisovin.magicspells.spells.instant;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.util.BlockIterator;
import com.nisovin.magicspells.MagicSpells;
import com.nisovin.magicspells.materials.MagicMaterial;
import com.nisovin.magicspells.spelleffects.EffectPosition;
import com.nisovin.magicspells.spells.InstantSpell;
import com.nisovin.magicspells.util.MagicConfig;
public class PhaseSpell extends InstantSpell {
private int range;
private int maxDistance;
private List<MagicMaterial> allowedPassThru;
private String strCantPhase;
public PhaseSpell(MagicConfig config, String spellName) {
super(config, spellName);
range = getConfigInt("range", 5);
maxDistance = getConfigInt("max-distance", 15);
List<String> passThru = getConfigStringList("allowed-pass-thru-blocks", null);
allowedPassThru = new ArrayList<MagicMaterial>();
for (String s : passThru) {
MagicMaterial m = MagicSpells.getItemNameResolver().resolveBlock(s);
if (m != null) {
allowedPassThru.add(m);
}
}
strCantPhase = getConfigString("str-cant-phase", "Unable to find place to phase to.");
if (allowedPassThru.size() == 0) {
allowedPassThru = null;
}
}
@Override
public PostCastAction castSpell(Player player, SpellCastState state, float power, String[] args) {
if (state == SpellCastState.NORMAL) {
int range = Math.round(this.range * power);
int distance = Math.round(maxDistance * power);
BlockIterator iter;
try {
iter = new BlockIterator(player, distance*2);
} catch (IllegalStateException e) {
sendMessage(player, strCantPhase);
return PostCastAction.ALREADY_HANDLED;
}
Block start = null;
int i = 0;
Location location = null;
// get wall block
while (start == null && i++ < range*2 && iter.hasNext()) {
Block b = iter.next();
if (b.getType() != Material.AIR && player.getLocation().distanceSquared(b.getLocation()) < range*range) {
start = b;
break;
}
}
// find landing spot
if (start != null) {
if (allowedPassThru != null && !canPassThru(start)) {
// can't phase through the block
location = null;
} else {
// get next empty space
Block end = null;
while (end == null && i++ < distance*2 && iter.hasNext()) {
Block b = iter.next();
// check for suitable landing location
if (b.getType() == Material.AIR && b.getRelative(0, 1, 0).getType() == Material.AIR && player.getLocation().distanceSquared(b.getLocation()) < distance*distance) {
location = b.getLocation();
break;
}
// check for invalid pass-thru block
if (allowedPassThru != null && !canPassThru(b)) {
location = null;
break;
}
}
}
}
// check for fail
if (location == null) {
// no location to tp to
sendMessage(player, strCantPhase);
//fizzle(player);
return PostCastAction.ALREADY_HANDLED;
}
// teleport
location.setX(location.getX() + .5);
location.setZ(location.getZ() + .5);
location.setPitch(player.getLocation().getPitch());
location.setYaw(player.getLocation().getYaw());
playSpellEffects(EffectPosition.CASTER, player.getLocation());
playSpellEffects(EffectPosition.TARGET, location);
player.teleport(location);
}
return PostCastAction.HANDLE_NORMALLY;
}
private boolean canPassThru(Block block) {
if (allowedPassThru == null) return true;
for (MagicMaterial mat : allowedPassThru) {
if (mat.equals(block)) return true;
}
return false;
}
}