package com.nisovin.magicspells.spells; import java.util.ArrayList; import java.util.List; import java.util.Random; import org.bukkit.entity.Player; import com.nisovin.magicspells.MagicSpells; import com.nisovin.magicspells.Subspell; import com.nisovin.magicspells.castmodifiers.ModifierSet; import com.nisovin.magicspells.util.MagicConfig; public class RandomSpell extends InstantSpell { static Random random = new Random(); boolean pseudoRandom; boolean checkIndividualCooldowns; boolean checkIndividualModifiers; List<String> rawOptions; RandomOptionSet options; public RandomSpell(MagicConfig config, String spellName) { super(config, spellName); pseudoRandom = getConfigBoolean("pseudo-random", true); checkIndividualCooldowns = getConfigBoolean("check-individual-cooldowns", true); checkIndividualModifiers = getConfigBoolean("check-individual-modifiers", true); rawOptions = getConfigStringList("spells", null); } @Override public void initialize() { super.initialize(); options = new RandomOptionSet(); for (String s : rawOptions) { String[] split = s.split(" "); Subspell spell = new Subspell(split[0]); int weight = 0; try { weight = Integer.parseInt(split[1]); } catch (NumberFormatException e) { } if (spell.process() && weight > 0) { options.add(new SpellOption(spell, weight)); } else { MagicSpells.error("Invalid spell option on RandomSpell '" + internalName + "': " + s); } } rawOptions.clear(); rawOptions = null; } @Override public PostCastAction castSpell(Player player, SpellCastState state, float power, String[] args) { if (state == SpellCastState.NORMAL) { RandomOptionSet set = options; if (checkIndividualCooldowns || checkIndividualModifiers) { set = new RandomOptionSet(); for (SpellOption o : options.options) { if (checkIndividualCooldowns) { if (o.spell.getSpell().onCooldown(player)) { continue; } } if (checkIndividualModifiers) { ModifierSet modifiers = o.spell.getSpell().getModifiers(); if (modifiers != null && !modifiers.check(player)) { continue; } } set.add(o); } } if (set.options.size() > 0) { Subspell spell = set.choose(); if (spell != null) { return spell.cast(player, power); } else { return PostCastAction.ALREADY_HANDLED; } } else { return PostCastAction.ALREADY_HANDLED; } } return PostCastAction.HANDLE_NORMALLY; } class SpellOption { Subspell spell; int weight; int adjustedWeight; public SpellOption(Subspell spell, int weight) { this.spell = spell; this.weight = weight; this.adjustedWeight = weight; } } class RandomOptionSet { List<SpellOption> options = new ArrayList<SpellOption>(); int total = 0; public void add(SpellOption option) { options.add(option); total += option.adjustedWeight; } public Subspell choose() { int r = random.nextInt(total); int x = 0; Subspell spell = null; for (int i = 0; i < options.size(); i++) { SpellOption o = options.get(i); if (r < o.adjustedWeight + x && spell == null) { spell = o.spell; if (pseudoRandom) { o.adjustedWeight = 0; } else { break; } } else { x += o.adjustedWeight; if (pseudoRandom) { o.adjustedWeight += o.weight; } } } return spell; } } }