Skip to main content

Overview

In this guide, you’ll create a simple fire projectile spell using the spell handler system. The spell will:
  • Launch a flaming projectile that tracks targets
  • Ignite enemies on hit
  • Deal critical damage to already burning enemies
  • Have 3 charges that regenerate over time
This tutorial is based on the flame_flicker demo spell included in the pack.

Understanding the Spell System

The modular spell system uses a handler-based architecture where you wrap your custom skill logic with the Spell handler. The handler automatically manages:
  • Cooldowns and charge systems
  • Warmup/channeling mechanics
  • Stat calculations (damage, crit chance, etc.)
  • Player feedback (sounds, messages, action bar displays)
Every spell needs at least two skills: a cast skill that calls the Spell handler, and an execution skill that contains your actual spell logic.

Creating Your First Spell

1

Create the Cast Skill

The cast skill is what players will trigger (via item, command, or mechanic). It calls the Spell handler with your spell’s configuration.Create a new file in your skills folder called my_fireball-spell.yml:
my_fireball-spell.yml
# Launch a fireball that ignites enemies
my_fireball-cast:
  Skills:
  - skill:Spell{id=my_fireball-exec;
      name=Fireball;
      type=ABILITY,FIRE;
      spellcd=0;
      charges=3;
      chargecd=2;
      charge_delay=1;
      charge_regen=3}
Parameter breakdown:
  • id - The skill to execute when the spell is cast
  • name - Display name shown to players
  • type - Spell categories (used for modifiers and filtering)
  • spellcd - Base cooldown in seconds (0 = no cooldown)
  • charges - Number of charges (0 = no charge system)
  • chargecd - Time to regenerate one charge
  • charge_delay - Delay before first charge starts regenerating
  • charge_regen - Number of charges restored per cycle
2

Create the Execution Skill

The execution skill contains your spell’s actual behavior. It’s called after the Spell handler validates cooldowns and charges.Add this to the same file:
my_fireball-spell.yml
my_fireball-exec:
  Skills:
  - skill:my_fireball-fire{origin=@forward{uel=true;f=1;yo=-0.2}} 
    @forward{yo=-0.2;f=12;uel=true}
This launches the projectile slightly in front of and below the player’s eye level, targeting 12 blocks ahead.
3

Create the Projectile Skill

Now we’ll create the actual projectile that fires:
my_fireball-spell.yml
my_fireball-fire:
  Skills:
  - skill:setRandomID
  - setvarloc{var=originloc;v=@origin}
  - projectile{fo=true;ti=3;syo=0;sfo=0;hnp=true;se=false;ham=true;
      velocity=64;i=1;g=0;mr=12;hr=0.4;vr=0.4;drawhitbox=false;
      onTick=my_fireball-tick;
      onHit=my_fireball-hit_entity;
      onEnd=my_fireball-end}
Key parameters:
  • velocity=64 - Fast projectile speed
  • mr=12 - Max range of 12 blocks
  • hr=0.4;vr=0.4 - Hit radius (horizontal and vertical)
  • onTick - Called every tick while projectile travels
  • onHit - Called when hitting an entity
  • onEnd - Called when projectile reaches max range or hits block
4

Add Visual Effects

Create the tick skill that displays particle effects as the projectile travels:
my_fireball-spell.yml
my_fireball-tick:
  Skills:
  - setvarloc{var=targetloc;
      v=@projectileforward{f=1;
        x="<random.float.-0.25to0.25>*<skill.var.size|1>";
        y="<random.float.-0.25to0.25>*<skill.var.size|1>";
        z="<random.float.-0.25to0.25>*<skill.var.size|1>"}}
  - e:pl{fo=true;origin=@VariableLocation{var=originloc};
      p=small_flame;a=1;db=0.3} @VariableLocation{var=targetloc}
  - e:pl{fo=true;
      origin=@VariableLocation{var=originloc;
        x="<random.float.-0.1to0.1>";
        y="<random.float.-0.1to0.1>";
        z="<random.float.-0.1to0.1>"};
      p=dust_color_transition;size=0.8;a=1;
      color1=#f3420c;color2=#ff0000;} 
    @VariableLocation{var=targetloc;
      x="<random.float.-0.1to0.1>";
      y="<random.float.-0.1to0.1>";
      z="<random.float.-0.1to0.1>"}
  - setvarloc{var=originloc;v=@VariableLocation{var=targetloc}}
  - setprojectiledirection @projectileforward{f=14;
      x="<random.float.-0.25to0.25>";
      y="<random.float.-0.25to0.25>";
      z="<random.float.-0.25to0.25>"}
This creates a flickering flame trail with slight randomization for a more natural look.
5

Add Damage on Hit

Create the hit skill that damages enemies and applies effects:
my_fireball-spell.yml
my_fireball-hit_entity:
  TargetConditions:
  - burning castinstead my_fireball-hit_entity-critical
  Skills:
  - skill:damage-ability{immune=10;
      damageMod=[
        - variableMath{var=damage;equation="x*0.6"}
      ];
      onHit=[
        - ignite{d=60}
      ]}
This deals 60% of base damage and ignites the target for 3 seconds (60 ticks). If the target is already burning, it triggers the critical hit version instead.Now add the critical hit version:
my_fireball-spell.yml
my_fireball-hit_entity-critical:
  Skills:
  - setvar{var=critical;val=true;type=STRING}
  - skill:damage-ability{
      damageMod=[
        - variableMath{var=damage;equation="x*1.5"}
      ];
      onHit=[
        - ignite{d=200}
      ]}
Critical hits deal 150% damage and ignite for 10 seconds (200 ticks).
6

Add End Effects (Optional)

Add visual and sound effects when the projectile expires:
my_fireball-spell.yml
my_fireball-end:
  Skills:
  - sound{s=entity.generic.extinguish_fire;p=1.5;v=0.5}
  - e:p{p=flame;a=8;speed=0.2;hS=0.2;vS=0.2}
7

Test Your Spell

Reload MythicMobs:
/mm reload
Test the spell:
/mm test cast my_fireball-cast
You should see:
  • A fireball projectile launch forward
  • Flame particle effects trailing behind
  • Damage and ignite effects on hit
  • Critical damage on already-burning targets
  • Charge system with 3 charges that regenerate

Complete Code

# Launch a fireball that ignites enemies
my_fireball-cast:
  Skills:
  - skill:Spell{id=my_fireball-exec;
      name=Fireball;
      type=ABILITY,FIRE;
      spellcd=0;
      charges=3;
      chargecd=2;
      charge_delay=1;
      charge_regen=3}
      
my_fireball-exec:
  Skills:
  - skill:my_fireball-fire{origin=@forward{uel=true;f=1;yo=-0.2}} 
    @forward{yo=-0.2;f=12;uel=true}

my_fireball-fire:
  Skills:
  - skill:setRandomID
  - setvarloc{var=originloc;v=@origin}
  - projectile{fo=true;ti=3;syo=0;sfo=0;hnp=true;se=false;ham=true;
      velocity=64;i=1;g=0;mr=12;hr=0.4;vr=0.4;drawhitbox=false;
      onTick=my_fireball-tick;
      onHit=my_fireball-hit_entity;
      onEnd=my_fireball-end}

my_fireball-tick:
  Skills:
  - setvarloc{var=targetloc;
      v=@projectileforward{f=1;
        x="<random.float.-0.25to0.25>*<skill.var.size|1>";
        y="<random.float.-0.25to0.25>*<skill.var.size|1>";
        z="<random.float.-0.25to0.25>*<skill.var.size|1>"}}
  - e:pl{fo=true;origin=@VariableLocation{var=originloc};
      p=small_flame;a=1;db=0.3} @VariableLocation{var=targetloc}
  - e:pl{fo=true;
      origin=@VariableLocation{var=originloc;
        x="<random.float.-0.1to0.1>";
        y="<random.float.-0.1to0.1>";
        z="<random.float.-0.1to0.1>"};
      p=dust_color_transition;size=0.8;a=1;
      color1=#f3420c;color2=#ff0000;} 
    @VariableLocation{var=targetloc;
      x="<random.float.-0.1to0.1>";
      y="<random.float.-0.1to0.1>";
      z="<random.float.-0.1to0.1>"}
  - setvarloc{var=originloc;v=@VariableLocation{var=targetloc}}
  - setprojectiledirection @projectileforward{f=14;
      x="<random.float.-0.25to0.25>";
      y="<random.float.-0.25to0.25>";
      z="<random.float.-0.25to0.25>"}

my_fireball-hit_entity:
  TargetConditions:
  - burning castinstead my_fireball-hit_entity-critical
  Skills:
  - skill:damage-ability{immune=10;
      damageMod=[
        - variableMath{var=damage;equation="x*0.6"}
      ];
      onHit=[
        - ignite{d=60}
      ]}

my_fireball-hit_entity-critical:
  Skills:
  - setvar{var=critical;val=true;type=STRING}
  - skill:damage-ability{
      damageMod=[
        - variableMath{var=damage;equation="x*1.5"}
      ];
      onHit=[
        - ignite{d=200}
      ]}

my_fireball-end:
  Skills:
  - sound{s=entity.generic.extinguish_fire;p=1.5;v=0.5}
  - e:p{p=flame;a=8;speed=0.2;hS=0.2;vS=0.2}

Understanding Spell Parameters

The Spell handler accepts many configuration parameters. Here are the most commonly used:

Basic Parameters

ParameterTypeDefaultDescription
idstringrequiredThe skill to execute when cast
namestringrequiredDisplay name for the spell
typestring”ABILITY”Spell category/tags (comma-separated)
spellcdfloat1Base cooldown in seconds
damagefloatcaster.damageBase damage value

Charge System

ParameterTypeDefaultDescription
chargesint0Max charges (0 disables charge system)
chargecdfloat3Seconds to regenerate one charge
charge_regenint1Charges restored per cycle
charge_delayfloat0Delay before first charge regens

Warmup/Channeling

ParameterTypeDefaultDescription
warmupfloat0Channel time in seconds before cast
onChannelStartskillchannel-start_fxSkill called when channeling starts
onChannelTickskillchannel-tick_fxSkill called each tick while channeling
onInterruptskill[]Skill called when channel is interrupted

Advanced Stats

ParameterTypeDefaultDescription
critical_chancefloat0.01Chance to crit (0-1)
critical_damagefloat0Bonus crit damage multiplier
velocityfloat48Projectile velocity
rangefloat32Max spell range

Next Steps

Now that you’ve created your first spell, you can:
  • Explore the demo spells in skills/Demo Skills/Demo Spells/ for more examples
  • Learn about the damage system and modifiers
  • Create custom visual effects with particles
  • Build spell combos and interactions
  • Implement mana costs and resource management
Check out the burning_blast-spell.yml demo for an advanced example featuring warmup channeling, dynamic retargeting, and explosive area damage.

Build docs developers (and LLMs) love