package com.nisovin.magicspells.spells.targeted;
import java.util.Random;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityExplodeEvent;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import com.nisovin.magicspells.MagicSpells;
import com.nisovin.magicspells.events.SpellTargetLocationEvent;
import com.nisovin.magicspells.spells.TargetedLocationSpell;
import com.nisovin.magicspells.spells.TargetedSpell;
import com.nisovin.magicspells.util.MagicConfig;
public class ExplodeSpell extends TargetedSpell implements TargetedLocationSpell {
private int explosionSize;
private int backfireChance;
private boolean simulateTnt;
private boolean preventBlockDamage;
private boolean preventPlayerDamage;
private float damageMultiplier;
private boolean addFire;
private boolean ignoreCanceled;
private long currentTick = 0;
private float currentPower = 0;
public ExplodeSpell(MagicConfig config, String spellName) {
super(config, spellName);
explosionSize = getConfigInt("explosion-size", 4);
backfireChance = getConfigInt("backfire-chance", 0);
simulateTnt = getConfigBoolean("simulate-tnt", true);
preventBlockDamage = getConfigBoolean("prevent-block-damage", false);
preventPlayerDamage = getConfigBoolean("prevent-player-damage", false);
damageMultiplier = getConfigFloat("damage-multiplier", 0);
addFire = getConfigBoolean("add-fire", false);
ignoreCanceled = getConfigBoolean("ignore-canceled", false);
}
public PostCastAction castSpell(Player player, SpellCastState state, float power, String[] args) {
if (state == SpellCastState.NORMAL) {
Block target = null;
try {
target = getTargetedBlock(player, power);
} catch (IllegalStateException e) {
target = null;
}
if (target != null && target.getType() != Material.AIR) {
SpellTargetLocationEvent event = new SpellTargetLocationEvent(this, player, target.getLocation(), power);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
target = null;
} else {
target = event.getTargetLocation().getBlock();
power = event.getPower();
}
}
if (target == null || target.getType() == Material.AIR) {
// fail: no target
return noTarget(player);
} else {
boolean exploded = explode(player, target.getLocation(), power);
if (!exploded && !ignoreCanceled) {
return noTarget(player);
}
}
}
return PostCastAction.HANDLE_NORMALLY;
}
private boolean explode(Player player, Location target, float power) {
// check plugins
if (simulateTnt) {
boolean cancelled = MagicSpells.getVolatileCodeHandler().simulateTnt(target, player, explosionSize * power, addFire);
if (cancelled) {
return false;
}
}
// backfire chance
if (backfireChance > 0) {
Random rand = new Random();
if (rand.nextInt(10000) < backfireChance) {
target = player.getLocation();
}
}
// save current explosion data
currentTick = Bukkit.getWorlds().get(0).getFullTime();
currentPower = power;
// cause explosion
boolean ret = MagicSpells.getVolatileCodeHandler().createExplosionByPlayer(player, target, explosionSize * power, addFire, !preventBlockDamage);
if (ret) {
playSpellEffects(player, target);
}
return ret;
}
@Override
public boolean castAtLocation(Player caster, Location target, float power) {
return explode(caster, target, power);
}
@Override
public boolean castAtLocation(Location target, float power) {
return false;
}
@EventHandler(priority=EventPriority.HIGH)
public void onEntityDamage(EntityDamageEvent event) {
if ((damageMultiplier > 0 || preventPlayerDamage)
&& !event.isCancelled()
&& (event.getCause() == DamageCause.BLOCK_EXPLOSION || event.getCause() == DamageCause.ENTITY_EXPLOSION)
&& currentTick == Bukkit.getWorlds().get(0).getFullTime()) {
if (preventPlayerDamage && event.getEntity() instanceof Player) {
event.setCancelled(true);
} else if (damageMultiplier > 0) {
event.setDamage(Math.round(event.getDamage() * damageMultiplier * currentPower));
}
}
}
@EventHandler
public void onExplode(EntityExplodeEvent event) {
if (event.isCancelled() || !preventBlockDamage) {
return;
}
if (currentTick == Bukkit.getWorlds().get(0).getFullTime()) {
event.blockList().clear();
event.setYield(0);
}
}
}