Skip to content
Jakl edited this page Apr 5, 2022 · 14 revisions

Description:

On this page, we will document how to add custom spells, modifier conditions, passive listeners, variables, and spell effects to MagicSpells.

Jump to section:

Adding the dependency

MagicSpells uses jitpack.io as its repository-service.
You can find guides on how to add MagicSpells as a dependency for your build-environment here.

Custom Spells:

This example displays a basic instant spell.

package com.example.instant;

import org.bukkit.entity.LivingEntity;

import com.nisovin.magicspells.util.MagicConfig;
import com.nisovin.magicspells.spells.InstantSpell;
import com.nisovin.magicspells.spelleffects.EffectPosition;

public class HelloWorldSpell extends InstantSpell {

	public HelloWorldSpell(MagicConfig config, String spellName) {
		super(config, spellName);
	}

	@Override
	public PostCastAction castSpell(LivingEntity caster, SpellCastState state, float power, String[] args) {
		if (state == SpellCastState.NORMAL) {
			caster.sendMessage("Hello World!");
                        // We should always play the correct effects in the spell.
			playSpellEffects(EffectPosition.CASTER, caster);
		}
		return PostCastAction.HANDLE_NORMALLY;
	}

}
hello_world:
    spell-class: "com.example.instant.HelloWorldSpell"

This example displays a basic targeted spell, and how to handle targets, and spell effects in targeted spells.

package com.example.targeted;

import org.bukkit.entity.LivingEntity;

import com.nisovin.magicspells.util.TargetInfo;
import com.nisovin.magicspells.util.MagicConfig;
import com.nisovin.magicspells.spells.TargetedSpell;
import com.nisovin.magicspells.spells.TargetedEntitySpell;
import com.nisovin.magicspells.spelleffects.EffectPosition;

public class HelloWorldSpell extends TargetedSpell implements TargetedEntitySpell {

	public HelloWorldSpell(MagicConfig config, String spellName) {
		super(config, spellName);
	}

	@Override
	public PostCastAction castSpell(LivingEntity caster, SpellCastState state, float power, String[] args) {
		if (state == SpellCastState.NORMAL) {
			TargetInfo<LivingEntity> targetInfo = getTargetedEntity(caster, power);
			if (targetInfo == null) return noTarget(caster);
			LivingEntity target = targetInfo.getTarget();
			hello(caster, target);
			sendMessages(caster, target);
			return PostCastAction.NO_MESSAGES;
		}
		return PostCastAction.HANDLE_NORMALLY;
	}

	@Override
	public boolean castAtEntity(LivingEntity caster, LivingEntity target, float power) {
		return hello(caster, target);
	}

	@Override
	public boolean castAtEntity(LivingEntity target, float power) {
		return hello(null, target);
	}

	private boolean hello(LivingEntity caster, LivingEntity target) {
		target.sendMessage("Hello World!");
		if (caster == null) playSpellEffects(EffectPosition.TARGET, target);
		else playSpellEffects(caster, target);
		return true;
	}

}
hello_world_targeted:
    spell-class: "com.example.targeted.HelloWorldSpell"

This example includes configuration reading.

package com.example.instant;

import org.bukkit.entity.Player;
import org.bukkit.entity.LivingEntity;

import com.nisovin.magicspells.util.Util;
import com.nisovin.magicspells.util.MagicConfig;
import com.nisovin.magicspells.spells.InstantSpell;

public class RollDiceSpell extends InstantSpell {

	private int min;
	private int max;
	private final String strMessage;

	public RollDiceSpell(MagicConfig config, String spellName) {
		super(config, spellName);
		min = getConfigInt("min", 0);
		max = getConfigInt("max", 10);
		strMessage = getConfigString("message", "Dice: ");
	}

	@Override
	public PostCastAction castSpell(LivingEntity livingEntity, SpellCastState state, float power, String[] args) {
		// Here we are dealing with a spell that only works for Player casters.
		if (state == SpellCastState.NORMAL && livingEntity instanceof Player caster) {
			// We're using Util methods not to create duplicate code.
			int random = min + Util.getRandomInt(max - min + 1);
			caster.sendMessage(strMessage + random);
		}
		return PostCastAction.HANDLE_NORMALLY;
	}

}
roll_dice:
    spell-class: "com.example.instant.RollDiceSpell"
    min: 0
    max: 100
    message: "You rolled: "

Other managers:

This section includes the creation of custom modifier conditions, passive listeners, variables, and spell effects.

If you would like to add these features, you can use the API from your own custom plugin, but if you don't want to add a separate plugin, you could utilise a custom spell class in order to achieve this.

If you are using a custom plugin to load these modules, you could use this resource in order to load these classes in a simpler way. It could also serve as an example for what follows.

If you are using a custom plugin to load these modules, the plugin must "soft depend" on "MagicSpells".

You have to create an event handler for the module you want to add, then add it through its manager there. The events are: ConditionsLoadingEvent, PassiveListenersLoadingEvent, VariablesLoadingEvent, and SpellEffectsLoadingEvent. You can fetch the specific manager from static methods in the MagicSpells class. Each of these managers includes a method to add the module you want.

This example shows how to add a custom variable class. For the sakes of this tutorial, we're adding an existing variable under a different name.

@EventHandler
public void onVariableLoad(VariablesLoadingEvent event) {
	MagicSpells.getVariableManager().addVariable("altitude", new AltitudeVariable());
}
Clone this wiki locally