Skip to content
JasperLorelai edited this page Jan 28, 2024 · 14 revisions

Description:

On this page, we will document how to add custom spells, modifier conditions, passive listeners, etc. 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.
Or use the example below:

repositories {
    maven {url "https://jitpack.io"}
}

dependencies {
    implementation "com.github.TheComputerGeek2.MagicSpells:core:main-SNAPSHOT"
}

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. However, if you don't want to add a separate plugin, you could utilise a custom spell class 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());
}

Custom Cleansers:

Warning

Since Beta 14.

It's possible to register custom cleansers for the Cleanse Spell to list under its remove option. You can find some examples of how to implement a cleanser here.

import com.nisovin.magicspells.spells.targeted.cleanse.util.Cleansers;
. . .
Cleansers.addCleanserClass(/* <Class which extends Cleanser>*/);
Clone this wiki locally