Logic Events

Logic events are frame-bound actions stored inside an animation's events array in logic.json. They are useful when you want deterministic animation behaviour without writing Lua.

Event Shape

Every event includes a $type field:

{
  "$type": "Sor2NewEra.Gameplay.SoundEvent, Sor2NewEra",
  "frame": 4,
  "packName": "My Pack",
  "soundName": "punch-heavy"
}

Most events also include frame. Events that operate across a frame window use afterFrame and beforeFrame instead.

Editor Name to JSON Type

The Character Editor shows events under short display names, while the saved JSON uses class names. They do not always match in an obvious way — Set Anim is JumpToAnimationEvent, and Set Value is SetCustomValueEvent. Use this table to move between the editor and hand-edited JSON.

Editor name JSON $type
Set Velocity VelocityEvent
Set Acceleration AccelerationEvent
Input -> Velocity InputVelocityEvent
Input -> Acceleration InputAccelerationEvent
Set Pos Offset PositionOffsetEvent
Stop StopEvent
AccX(0) -> Stop StopOnHorizontalStop
Set Anim JumpToAnimationEvent
Input Button -> Set Anim JumpToAnimationOnInputButton
Input Combo -> Set Anim JumpToAnimationOnInputCombo
Hit -> Set Anim JumpToAnimationOnHit
Land -> Set Anim JumpToAnimationOnLanding
Land -> Set Frame JumpToFrameOnLanding
AccX(0) -> Set Frame JumpToFrameOnHorizontalStop
Spawn Enemy SpawnEnemyEvent
Spawn Item SpawnItemEvent
Grab GrabEvent
Flip FlipEvent
Destroy DestroyEvent
Set Invincibility InvincibilityEvent
Add Health HealthEvent
Set Value SetCustomValueEvent
Play Sound SoundEvent
Play Music MusicEvent

Event List

Event Main fields Use
AccelerationEvent frame, acceleration, useAxisFlags, affectX, affectY, affectZ Set acceleration. Axis flags enable each component input and let zero values affect one component without resetting the others.
VelocityEvent frame, velocity, useAxisFlags, affectX, affectY, affectZ Set velocity. Axis flags enable each component input and let zero values affect one component without resetting the others.
InputAccelerationEvent strength Apply input-driven acceleration on every frame of the animation.
InputVelocityEvent afterFrame, beforeFrame, strength Apply input-driven velocity during a frame window.
StopEvent frame Stop movement.
StopOnHorizontalStop none Stop when horizontal motion stops.
FlipEvent frame Flip facing direction.
PositionOffsetEvent frame, offset fields Move the object by an offset.
InvincibilityEvent frame, invincible Enable or disable invincibility.
HealthEvent frame, health Add health. Use a negative value for a cost or damage.
DestroyEvent frame Destroy or deactivate the object.
GrabEvent frame Attempt grab behaviour.
JumpToAnimationEvent frame, animationId, animationFrame Change animation at a fixed frame.
JumpToAnimationOnHit afterFrame, beforeFrame, animationId Change animation if hit during a window.
JumpToAnimationOnInputButton afterFrame, beforeFrame, animationId Change animation on button input.
JumpToAnimationOnInputCombo afterFrame, beforeFrame, input, animationId, ignoreDuringSlowMotion Change animation on input sequence. The optional slow-motion guard skips activation without clearing input history.
JumpToAnimationOnLanding initialFrame, animationId, animationFrame Change animation when landing.
JumpToFrameOnLanding initialFrame, jumpFrame Jump to a frame when landing.
JumpToFrameOnHorizontalStop initialFrame, jumpFrame Jump to a frame when horizontal motion stops.
SoundEvent frame, packName, soundName or soundNames Play a sound.
MusicEvent frame, packName, musicName Schedule or play music.
SpawnEnemyEvent frame, packName, entityName, animationId, mode Spawn an enemy.
SpawnItemEvent frame, packName, entityName, animationId, mode, positionOffset, velocity Spawn an item or projectile.
SetCustomValueEvent frame, valueId, value Set one custom value slot.

Spawn Item Event

SpawnItemEvent can also include projectile metadata:

{
  "$type": "Sor2NewEra.Gameplay.SpawnItemEvent, Sor2NewEra",
  "frame": 12,
  "packName": "My Pack",
  "entityName": "Fireball",
  "animationId": 0,
  "mode": -1,
  "lifetime": 60,
  "positionOffset": { "x": 12, "y": 0 },
  "velocity": { "x": 520, "y": 0 },
  "isProjectile": true,
  "damage": 8,
  "hitPause": 4,
  "hitSoundName": "fireball-hit",
  "hitSoundPack": "My Pack",
  "hitSoundChannel": 1
}

Events And Animation Behaviour

If an animation defines events, the animation does not run the default referenced Classic move controller for that animation. This protects custom event-based animations from original mode side effects. Movement, branching, spawning, and other default behaviour must then be provided by events, Lua, or the local default physics step.

If you want the original behaviour to run, keep the animation's events array empty and use referenceBehaviour.

When To Use Lua Instead

Use Lua when event data would need branching:

  • if target distance is less than a threshold
  • if the player pressed a custom sequence
  • if health is below a value
  • if a target exists and is on the same line

See Lua Scripting.

Full field reference

For the complete field list of every event, the axis and window semantics, and worked examples, see Entity Files.