Skip to content

3. Getting Started: Custom Spells & Spell Trees

CAS_ual_TY edited this page Jun 4, 2024 · 9 revisions

Getting Started: Custom Spells & Spell Trees

Custom Data Pack

How to get started making a data pack.


Making a Data Pack

Follow these steps (or alternatively check out the wiki https://minecraft.fandom.com/wiki/Tutorials/Creating_a_data_pack):

  1. Pick a namespace (only lowercase, numbers and underscore) for your data pack. Eg. the default data pack has namespace spells_and_shields.
  2. Make a new zip folder. You may name it however you like. The zip folder must have the following structure:
- `<namespace>.zip` ZIP Folder.
| - `pack.mcmeta` file (more about that below).
| - `data` folder
  | - `<namespace>` folder
    | - `spells_and_shields` folder
      | - `spells` folder
      | - `spell_trees` folder
  1. The pack.mcmeta file must have the following contents:
{
  "pack": {
    "pack_format": 10,
    "description": "Your description..."
  }
}

Tips

All kinds of tips and recommendations starting with a general section followed by spell trees and spells specific sections.


General Tips

General tips for data pack making.


Ask for Help

Always ask for help. Do not hesitate! Use the official Discord server for this mod: https://discord.gg/3zXwr2atcY


Custom Resources (Textures, Sounds, and Translation)

By adding your own resource pack with your own assets in addition to your data pack you can use custom textures for spells and spell trees and also add custom sounds and language translation files. You may put these in your own namespace folder again but make sure you reference them correctly in your data pack (<namespace>:... instead of spells_and_shields: for references). This will not be explained here but there is a wiki page explaining it: https://minecraft.fandom.com/wiki/Tutorials/Creating_a_resource_pack


Tips for Spell Trees

These tips specifically apply for making of spell trees.


Tiered Spells

Spell nodes can override the mana cost and the parameters of a spell. If eg. the damage of a spell is set via parameter you can add a spell into a spell tree multiple times with different mana costs and damage for each. This allows you to basically do tiered spells.


Tips for Spells

These tips specifically apply for making of spells.


Enable Debugging for Spells

This is a big one. If you are making your own spells make sure you enable debugging in the common config (set debugSpells = true). This will constantly (between every spell action) print out all information about the current spell context to the console (also viewable in logs) whenever you fire a spell. This will also make it a lot easier to understand the entire system if you are getting started. If you are on a dedicated server the information is only printed to the server.

However, printing to console lags a lot. So make sure you disable it again and never have this option enabled if players are actually playing with this mod.


Reset = Death

If a player has infinitely repeating delayed spell effects on them or a particle emitter that is running for a very long time and this is the result of a mistake do the following:

  • Fix the spell that caused this
  • Kill the player

Killing the player will always make them get rid of any delayed spells and particle emitters on them.

Make sure you read the introduction to spells first.


Advanced Topics (WIP)


UUIDs

UUID is an abbreviation for "universal unique identifier" and is used to identify unique things. Every entity and every player has a UUID, and so does every attribute modifier and every delayed spell instance.

With entities they can be used in a way where you find some target but want to affect it later. You need to use something that can be saved as variable since targets can not be saved to the extra tag nor transferred on delayed spells. So, what you can do in such a case is getting the UUID of the target you want to affect later and saving it to a string. You add the string to your extra tag and later on you try to retrieve the entity using this string. Keep in mind that at a later point this entity might not exist anymore (eg. the player left the server, the entity is in a chunk that is not loaded anymore, or it died, etc.) so you need to check for this eventuality.

When it comes to attribute modifiers and delayed spells, you only really use UUIDs in case you need to access them later on to change or remove them. If you never need to do that and just want them to run out on their own then you do not have to give them a specific UUID.

There are actions and functions for everything mentioned in here. Additionally, there is a function that lets you generate a UUID based on your input, eg. the input of "ABCDE" will always result in the same UUID when using this function. It is guaranteed that if you use the ID of a spell and the slot the spell is in as an input for this function you get a set UUID that will stay the same for these inputs, but is different if you change any of these inputs. This is usefull for toggled spells, equipment (passive) spells, timed spells, permanent spells, ... which should not overlap even if equipped twice but in different slots.

If you need to generate a static UUID, you can just use this online tool: https://www.uuidgenerator.net/


Delayed Spells

Delayed spells can be attached to entities. They run the spell on a custom event for an entity after a customizable amount of time. This can be used in a lot of ways that will be explained here.

For one, they allow hooking into events of targets the delayed spell instance was attached to, instead of only being able to hook into events fired from the perspective of a spell holder.

Repeating Effects

To infinitely repeat something you just attach the delayed spell to an entity and have it attach itself again when it fires.

Lets say the activation refire attaches a delayed spell that also fires the refire event when the delay has run out. If refire has been activated once then the delayed spell will be attached, run out and execute, attached again, run out and execute again, etc. infinitely. Add some effect triggered by the same activation and now this effect will be infinitely repeated.

So to start this infinite repetition, simply activate refire whenever the desired event is fired. To remove this infinitely repeating spell you have to give the delayed spell a UUID by which you can remove it without firing its activation.

Toggling Effects (WIP)


Particle Emitters

Particle emitters allow you to repeat a particle effect over a certain amount of time with a set delay. They serve as an easy way to eg. display over-time effects, add particles to projectiles, show an affected area, etc.. They always have a set amount of time after which they disappear.


Templates (WIP)

Single Activation + Mana Cost + Item Cost

Activate something once, requiring mana cost and an item cost (customizable amount). This spell adheres to the configuration file; players disabling item costs in there affects this spell.

{
  "s1/title": ...,
  "s2/icon": ...,
  "s3/mana_cost": ...,
  "s4/tooltip": ...,
  "s5/spell_events": [
    "active"
  ],
  "s6/spell_parameters": [
    {
      "type": "spells_and_shields:string",
      "value": ..., // <--- your item ID here, eg. '"minecraft:glowstone_dust"'
      "var/name": "item"
    },
    {
      "type": "spells_and_shields:string",
      "value": ..., // <--- the amount of items required, eg. '1'
      "var/name": "item_amount"
    }
  ],
  "s7/spell_actions": [
    {
      "type": "spells_and_shields:has_mana",
      "activation": "active",
      "amount": "<<mana_cost>>",
      "t/target": "owner"
    },
    {
      "type": "spells_and_shields:boolean_activation",
      "a/to_activate": "consume",
      "activation": "active",
      "d/boolean/activate_if_true": true,
      "d/boolean/deactivate_if_false": false,
      "d/boolean/input": "<< !item_costs() >>"
    },
    {
      "type": "spells_and_shields:player_has_items",
      "activation": "active",
      "d/boolean/creative_bypass": true,
      "d/boolean/must_be_in_hand": true,
      "d/int/amount": "<<item_amount>>",
      "d/string/item": "<<item>>",
      "t/source": "owner"
    },
    {
      "type": "spells_and_shields:activate",
      "a/to_activate": "consume",
      "activation": "active"
    },
    {
      "type": "spells_and_shields:activate",
      "a/to_activate": "shoot",
      "activation": "consume"
    },
    {
      "type": "spells_and_shields:burn_mana",
      "activation": "consume",
      "d/double/mana_amount": "<<mana_cost>>",
      "ts/targets": "owner"
    },
    {
      "type": "spells_and_shields:boolean_activation",
      "a/to_activate": "consume",
      "activation": "consume",
      "d/boolean/activate_if_true": false,
      "d/boolean/deactivate_if_false": true,
      "d/boolean/input": "<< item_costs() >>"
    },
    {
      "type": "spells_and_shields:consume_player_items",
      "activation": "consume",
      "d/boolean/must_be_in_hand": true,
      "d/int/amount": "<<item_amount>>",
      "d/string/item": "<<item>>",
      "t/source": "owner"
    },
    ... // <--- your actions here, the activation if the checks were successfull is "shoot"
  ]
}