A summon is two things joined by a name: an authored cutscene and a battle skill. When they match, the engine does the rest — the summon appears under the battle Summon command, plays its cinematic, and applies its damage at exactly the frame you choose.
The folder
Each summon lives in its own folder under your project's assets/Cutscenes/Summons/ directory, named by its id:
assets/Cutscenes/Summons/
└── ifrit/
├── ifrit.data.php # identity, transitions, wielder rules
└── ifrit.timeline.php # frame-by-frame animation
Both files return plain PHP arrays. The engine scans this directory at runtime, so dropping a new folder in is all it takes to register a new summon.
The data file
ifrit.data.php describes everything about the summon except its animation:
return [
'id' => 'ifrit',
'name' => 'Ifrit', // shown on the "[ IFRIT ]" title card
'moveName' => 'Hell Fire', // announced when the summon attacks
'description' => 'A fiery inferno tears across the battlefield.',
'linkedActionId' => 'Ifrit', // must match a skill name
'transitionIn' => ['type' => 'fadeToBlack', 'durationMs' => 450, 'color' => 'red'],
'transitionOut' => ['type' => 'fadeFromBlack', 'durationMs' => 300, 'color' => 'red'],
'effectTiming' => ['mode' => 'cue', 'cueId' => 'apply_ifrit_damage'],
'targetPresentation' => ['mode' => 'full_screen', 'showCasterNameBanner' => true],
];
Beyond identity, a summon can carry codex fields — lore that feeds the in-game summon screen, where players open a detail entry for each summon:
'lore' => 'A djinn of living flame, bound to the mortal world by an oath …',
'element' => 'Fire',
'strengths' => ['Ice', 'Flora'],
'weaknesses' => ['Water'],
'attributes' => ['Power' => 'A', 'Speed' => 'C', 'Temperament' => 'Wrathful'],
The lore text answers the question the list alone cannot: who or what is this being? The short description describes the move; the lore describes the creature. Element, strengths, weaknesses, and free-form attributes round out the entry — all optional, all shown only when present.
Two names matter to the player, and they do different jobs:
nameis the summon's identity — it fills the title card before the cinematic.moveNameis the summon's attack — it is what the battle log announces when the summon acts. Ifrit is the creature; Hell Fire is what it does to you. If you omitmoveName, the summon's name is announced instead.
The transitions wrap the cinematic in a colored glyph curtain. Match the color to the element — a red curtain for fire, light_blue for a tidal wave, brown for an earthquake — and the transition itself becomes part of the staging.
The skill
A summon reaches the battle menu through a skill whose name equals the cutscene's linkedActionId. Define it in assets/Data/skills.php like any other battle skill:
new SpecialSkill(
'Ifrit',
'Call forth Ifrit to engulf a foe in roaring flame.',
'',
12, // MP cost
0,
new ItemScope(ItemScopeSide::ENEMY, ItemScopeNumber::ONE, ItemScopeStatus::ALIVE),
Occasion::BATTLE_SCREEN,
new SkillInvocation('$1 summons Ifrit!', 0, 0, 1, 10),
[
new HPDamageSkillEffect(
'$user->stats->magicAttack * 8 - intval($target->stats->magicDefence / 2) + 28',
NULL, 0.15, false
),
],
),
The damage formula, MP cost, and targeting are ordinary skill design — summons simply add a cinematic on top. A useful convention: scale flat damage bonuses with MP cost across your summon roster, so the expensive calls feel expensive.
When the summon acts
The full sequence the player sees:
- The battle log announces the move — "Hell Fire".
- The transition curtain sweeps the field.
- The title card shows the summon's name.
- The timeline plays, frame by frame.
- At the cue frame, damage lands — numbers pop mid-explosion, not after it.
- The curtain sweeps back out and battle resumes.
The damage cue is declared in the timeline and referenced by effectTiming.cueId. Fire it at your animation's visual peak; the next chapter covers how.