package com.nisovin.magicspells.spells; import java.util.ArrayList; import java.util.List; import java.util.Random; 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.Subspell; import com.nisovin.magicspells.events.SpellCastEvent; import com.nisovin.magicspells.events.SpellCastedEvent; import com.nisovin.magicspells.events.SpellTargetEvent; import com.nisovin.magicspells.events.SpellTargetLocationEvent; import com.nisovin.magicspells.spelleffects.EffectPosition; import com.nisovin.magicspells.spells.passive.PassiveManager; import com.nisovin.magicspells.spells.passive.PassiveTrigger; import com.nisovin.magicspells.util.CastItem; import com.nisovin.magicspells.util.MagicConfig; import com.nisovin.magicspells.util.Util; public class PassiveSpell extends Spell { private static PassiveManager manager; private Random random = new Random(); private boolean disabled = false; private List<String> triggers; private float chance; private boolean castWithoutTarget; private int delay; private boolean cancelDefaultAction; private boolean ignoreCancelled; private boolean sendFailureMessages; private List<String> spellNames; private List<Subspell> spells; public PassiveSpell(MagicConfig config, String spellName) { super(config, spellName); if (manager == null) manager = new PassiveManager(); triggers = getConfigStringList("triggers", null); chance = getConfigFloat("chance", 100F) / 100F; castWithoutTarget = getConfigBoolean("cast-without-target", false); delay = getConfigInt("delay", -1); cancelDefaultAction = getConfigBoolean("cancel-default-action", false); ignoreCancelled = getConfigBoolean("ignore-cancelled", true); sendFailureMessages = getConfigBoolean("send-failure-messages", false); spellNames = getConfigStringList("spells", null); } public static PassiveManager getManager() { return manager; } public List<Subspell> getActivatedSpells() { return spells; } @Override public void initialize() { super.initialize(); // create spell list spells = new ArrayList<Subspell>(); if (spellNames != null) { for (String spellName : spellNames) { Subspell spell = new Subspell(spellName); if (spell.process()) { spells.add(spell); } } } if (spells.size() == 0) { MagicSpells.error("Passive spell '" + name + "' has no spells defined!"); return; } // get trigger int trigCount = 0; if (triggers != null) { for (String strigger : triggers) { String type = strigger; String var = null; if (strigger.contains(" ")) { String[] data = Util.splitParams(strigger, 2); type = data[0]; var = data[1]; } type = type.toLowerCase(); PassiveTrigger trigger = PassiveTrigger.getByName(type); if (trigger != null) { manager.registerSpell(this, trigger, var); trigCount++; } else { MagicSpells.error("Invalid trigger '" + strigger + "' on passive spell '" + internalName + "'"); } } } if (trigCount == 0) { MagicSpells.error("Passive spell '" + name + "' has no triggers defined!"); return; } } @Override public PostCastAction castSpell(Player player, SpellCastState state, float power, String[] args) { return PostCastAction.ALREADY_HANDLED; } public boolean activate(Player caster) { return activate(caster, null, null); } public boolean activate(Player caster, float power) { return activate(caster, null, null, power); } public boolean activate(Player caster, LivingEntity target) { return activate(caster, target, null, 1F); } public boolean activate(Player caster, Location location) { return activate(caster, null, location, 1F); } public boolean activate(final Player caster, final LivingEntity target, final Location location) { return activate(caster, target, location, 1F); } public boolean activate(final Player caster, final LivingEntity target, final Location location, final float power) { if (delay < 0) { return activateSpells(caster, target, location, power); } else { Bukkit.getScheduler().scheduleSyncDelayedTask(MagicSpells.plugin, new Runnable() { public void run() { activateSpells(caster, target, location, power); } }, delay); return false; } } private boolean activateSpells(Player caster, LivingEntity target, Location location, float basePower) { SpellCastState state = getCastState(caster); MagicSpells.debug(3, "Activating passive spell '" + name + "' for player " + caster.getName() + " (state: " + state + ")"); if (!disabled && (chance >= .999 || random.nextFloat() <= chance) && state == SpellCastState.NORMAL) { disabled = true; SpellCastEvent event = new SpellCastEvent(this, caster, SpellCastState.NORMAL, basePower, null, this.cooldown, this.reagents.clone(), 0); Bukkit.getPluginManager().callEvent(event); if (!event.isCancelled() && event.getSpellCastState() == SpellCastState.NORMAL) { if (event.haveReagentsChanged() && !hasReagents(caster, event.getReagents())) { disabled = false; return false; } setCooldown(caster, event.getCooldown()); basePower = event.getPower(); boolean spellEffectsDone = false; for (Subspell spell : spells) { MagicSpells.debug(3, " Casting spell effect '" + spell.getSpell().getName() + "'"); if (castWithoutTarget) { MagicSpells.debug(3, " Casting without target"); spell.cast(caster, basePower); if (!spellEffectsDone) { playSpellEffects(EffectPosition.CASTER, caster); spellEffectsDone = true; } } else if (spell.isTargetedEntitySpell() && target != null && !isActuallyNonTargeted(spell.getSpell())) { MagicSpells.debug(3, " Casting at entity"); SpellTargetEvent targetEvent = new SpellTargetEvent(this, caster, target, basePower); Bukkit.getPluginManager().callEvent(targetEvent); if (!targetEvent.isCancelled()) { target = targetEvent.getTarget(); spell.castAtEntity(caster, target, targetEvent.getPower()); if (!spellEffectsDone) { playSpellEffects(caster, target); spellEffectsDone = true; } } else { MagicSpells.debug(3, " Target cancelled (TE)"); } } else if (spell.isTargetedLocationSpell() && (location != null || target != null)) { MagicSpells.debug(3, " Casting at location"); Location loc = null; if (location != null) { loc = location; } else if (target != null) { loc = target.getLocation(); } if (loc != null) { SpellTargetLocationEvent targetEvent = new SpellTargetLocationEvent(this, caster, loc, basePower); Bukkit.getPluginManager().callEvent(targetEvent); if (!targetEvent.isCancelled()) { loc = targetEvent.getTargetLocation(); spell.castAtLocation(caster, loc, targetEvent.getPower()); if (!spellEffectsDone) { playSpellEffects(caster, loc); spellEffectsDone = true; } } else { MagicSpells.debug(3, " Target cancelled (TL)"); } } } else { MagicSpells.debug(3, " Casting normally"); float power = basePower; if (target != null) { SpellTargetEvent targetEvent = new SpellTargetEvent(this, caster, target, power); Bukkit.getPluginManager().callEvent(targetEvent); if (!targetEvent.isCancelled()) { power = targetEvent.getPower(); } else { MagicSpells.debug(3, " Target cancelled (UE)"); continue; } } else if (location != null) { SpellTargetLocationEvent targetEvent = new SpellTargetLocationEvent(this, caster, location, basePower); Bukkit.getPluginManager().callEvent(targetEvent); if (!targetEvent.isCancelled()) { power = targetEvent.getPower(); } else { MagicSpells.debug(3, " Target cancelled (UL)"); continue; } } spell.cast(caster, power); if (!spellEffectsDone) { playSpellEffects(EffectPosition.CASTER, caster); spellEffectsDone = true; } } } removeReagents(caster, event.getReagents()); sendMessage(caster, strCastSelf); SpellCastedEvent event2 = new SpellCastedEvent(this, caster, SpellCastState.NORMAL, basePower, null, event.getCooldown(), event.getReagents(), PostCastAction.HANDLE_NORMALLY); Bukkit.getPluginManager().callEvent(event2); disabled = false; return true; } else { MagicSpells.debug(3, " Passive spell canceled"); disabled = false; return false; } } else if (state != SpellCastState.NORMAL && sendFailureMessages) { if (state == SpellCastState.ON_COOLDOWN) { MagicSpells.sendMessage(caster, formatMessage(strOnCooldown, "%c", Math.round(getCooldown(caster))+"")); } else if (state == SpellCastState.MISSING_REAGENTS) { MagicSpells.sendMessage(caster, strMissingReagents); if (MagicSpells.showStrCostOnMissingReagents() && strCost != null && !strCost.isEmpty()) { MagicSpells.sendMessage(caster, " (" + strCost + ")"); } } } return false; } private boolean isActuallyNonTargeted(Spell spell) { if (spell instanceof ExternalCommandSpell) { return !((ExternalCommandSpell)spell).requiresPlayerTarget(); } else if (spell instanceof BuffSpell) { return !((BuffSpell)spell).isTargeted(); } return false; } public boolean cancelDefaultAction() { return cancelDefaultAction; } public boolean ignoreCancelled() { return ignoreCancelled; } @Override public boolean canBind(CastItem item) { return false; } @Override public boolean canCastWithItem() { return false; } @Override public boolean canCastByCommand() { return false; } public static void resetManager() { if (manager != null) { manager.turnOff(); manager = null; } } }