package com.nisovin.magicspells.spells.instant; import java.util.HashSet; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityDamageEvent.DamageCause; 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.spells.TargetedLocationSpell; import com.nisovin.magicspells.util.MagicConfig; public class FirenovaSpell extends InstantSpell implements TargetedLocationSpell { private int range; private int tickSpeed; private MagicMaterial mat; private boolean burnTallGrass; private boolean checkPlugins; private HashSet<Player> fireImmunity; public FirenovaSpell(MagicConfig config, String spellName) { super(config, spellName); range = getConfigInt("range", 3); tickSpeed = getConfigInt("tick-speed", 5); burnTallGrass = getConfigBoolean("burn-tall-grass", true); checkPlugins = getConfigBoolean("check-plugins", true); mat = MagicSpells.getItemNameResolver().resolveBlock(getConfigString("block-type", "51:15")); if (mat.getMaterial() == Material.FIRE) { fireImmunity = new HashSet<Player>(); } } @Override public PostCastAction castSpell(Player player, SpellCastState state, float power, String[] args) { if (state == SpellCastState.NORMAL) { if (fireImmunity != null) { fireImmunity.add(player); } new FirenovaAnimation(player); playSpellEffects(EffectPosition.CASTER, player); } return PostCastAction.HANDLE_NORMALLY; } @Override public boolean castAtLocation(Player caster, Location target, float power) { return castAtLocation(target, power); } @Override public boolean castAtLocation(Location target, float power) { new FirenovaAnimation(target); return true; } @EventHandler public void onEntityDamage(EntityDamageEvent event) { if (event.isCancelled() || fireImmunity == null) return; if (event.getEntity() instanceof Player && (event.getCause() == DamageCause.FIRE || event.getCause() == DamageCause.FIRE_TICK) && fireImmunity.size() > 0) { Player player = (Player)event.getEntity(); if (fireImmunity.contains(player)) { // caster is taking damage, cancel it event.setCancelled(true); player.setFireTicks(0); } else if (checkPlugins) { // check if nearby players are taking damage Location loc = player.getLocation(); for (Player p : fireImmunity) { if (Math.abs(p.getLocation().getX() - loc.getX()) < range+2 && Math.abs(p.getLocation().getZ() - loc.getZ()) < range+2 && Math.abs(p.getLocation().getY() - loc.getY()) < range) { // nearby, check plugins for pvp EntityDamageByEntityEvent evt = new EntityDamageByEntityEvent(p, player, DamageCause.ENTITY_ATTACK, event.getDamage()); Bukkit.getServer().getPluginManager().callEvent(evt); if (evt.isCancelled()) { event.setCancelled(true); player.setFireTicks(0); break; } } } } } } private class FirenovaAnimation implements Runnable { Player player; int i = 0; Block center; HashSet<Block> fireBlocks = new HashSet<Block>(); int taskId; public FirenovaAnimation(Player player) { this.player = player; center = player.getLocation().getBlock(); taskId = MagicSpells.scheduleRepeatingTask(this, 0, tickSpeed); } public FirenovaAnimation(Location location) { center = location.getBlock(); taskId = MagicSpells.scheduleRepeatingTask(this, 0, tickSpeed); } public void run() { // remove old fire blocks for (Block block : fireBlocks) { if (block.getType() == mat.getMaterial()) { block.setType(Material.AIR); } } fireBlocks.clear(); i += 1; if (i <= range) { // set next ring on fire int bx = center.getX(); int y = center.getY(); int bz = center.getZ(); for (int x = bx - i; x <= bx + i; x++) { for (int z = bz - i; z <= bz + i; z++) { if (Math.abs(x-bx) == i || Math.abs(z-bz) == i) { Block b = center.getWorld().getBlockAt(x,y,z); if (b.getType() == Material.AIR || (burnTallGrass && b.getType() == Material.LONG_GRASS)) { Block under = b.getRelative(BlockFace.DOWN); if (under.getType() == Material.AIR || (burnTallGrass && under.getType() == Material.LONG_GRASS)) { b = under; } mat.setBlock(b, false); fireBlocks.add(b); } else if (b.getRelative(BlockFace.UP).getType() == Material.AIR || (burnTallGrass && b.getRelative(BlockFace.UP).getType() == Material.LONG_GRASS)) { b = b.getRelative(BlockFace.UP); mat.setBlock(b, false); fireBlocks.add(b); } } } } } else if (i > range+1) { // stop if done Bukkit.getServer().getScheduler().cancelTask(taskId); if (fireImmunity != null && player != null) { fireImmunity.remove(player); } } } } }