package com.nisovin.magicspells.spells.instant; import java.util.HashMap; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; import com.nisovin.magicspells.MagicSpells; import com.nisovin.magicspells.Spell; import com.nisovin.magicspells.spelleffects.EffectPosition; import com.nisovin.magicspells.spells.InstantSpell; import com.nisovin.magicspells.spells.TargetedEntitySpell; import com.nisovin.magicspells.util.MagicConfig; import com.nisovin.magicspells.util.MagicLocation; public class RecallSpell extends InstantSpell implements TargetedEntitySpell { private String markSpellName; private boolean allowCrossWorld; private int maxRange; private boolean useBedLocation; private String strNoMark; private String strOtherWorld; private String strTooFar; private String strRecallFailed; private HashMap<String,MagicLocation> marks; public RecallSpell(MagicConfig config, String spellName) { super(config, spellName); markSpellName = getConfigString("mark-spell", "mark"); allowCrossWorld = getConfigBoolean("allow-cross-world", true); maxRange = getConfigInt("max-range", 0); useBedLocation = getConfigBoolean("use-bed-location", false); strNoMark = getConfigString("str-no-mark", "You have no mark to recall to."); strOtherWorld = getConfigString("str-other-world", "Your mark is in another world."); strTooFar = getConfigString("str-too-far", "You mark is too far away."); strRecallFailed = getConfigString("str-recall-failed", "Could not recall."); } @Override public void initialize() { super.initialize(); Spell spell = MagicSpells.getSpellByInternalName(markSpellName); if (spell != null && spell instanceof MarkSpell) { marks = ((MarkSpell)spell).getMarks(); } else { MagicSpells.error("Failed to get marks list for '" + internalName + "' spell"); } } @Override public PostCastAction castSpell(Player player, SpellCastState state, float power, String[] args) { if (state == SpellCastState.NORMAL) { Location mark = null; if (args != null && args.length == 1 && player.hasPermission("magicspells.advanced." + internalName)) { Player target = Bukkit.getPlayer(args[0]); if (useBedLocation) { if (target != null) { mark = target.getBedSpawnLocation(); } } else if (marks != null) { MagicLocation loc = marks.get(target != null ? target.getName().toLowerCase() : args[0].toLowerCase()); if (loc != null) { mark = loc.getLocation(); } } } else { mark = getRecallLocation(player); } if (mark == null) { sendMessage(player, strNoMark); return PostCastAction.ALREADY_HANDLED; } else if (!allowCrossWorld && !mark.getWorld().getName().equals(player.getLocation().getWorld().getName())) { // can't cross worlds sendMessage(player, strOtherWorld); return PostCastAction.ALREADY_HANDLED; } else if (maxRange > 0 && mark.toVector().distanceSquared(player.getLocation().toVector()) > maxRange*maxRange) { // too far sendMessage(player, strTooFar); return PostCastAction.ALREADY_HANDLED; } else { // all good! Location from = player.getLocation(); boolean teleported = player.teleport(mark); if (teleported) { playSpellEffects(EffectPosition.CASTER, from); playSpellEffects(EffectPosition.TARGET, mark); } else { // fail -- teleport prevented MagicSpells.error("Recall teleport blocked for " + player.getName()); sendMessage(player, strRecallFailed); return PostCastAction.ALREADY_HANDLED; } } } return PostCastAction.HANDLE_NORMALLY; } Location getRecallLocation(Player caster) { if (useBedLocation) { return caster.getBedSpawnLocation(); } else if (marks != null) { MagicLocation loc = marks.get(caster.getName().toLowerCase()); if (loc != null) { return loc.getLocation(); } } return null; } @Override public boolean castAtEntity(Player caster, LivingEntity target, float power) { Location mark = getRecallLocation(caster); if (mark != null) { target.teleport(mark); return true; } return false; } @Override public boolean castAtEntity(LivingEntity target, float power) { return false; } }