Object Animations

This feature has been introduced in version 19.1230a.

Custom object animations allow track makers to script their own animated objects. Animations are defined in a text file named custom_animations.txt placed in the level folder.

  • Custom animations are added through a new object type in Objects edit mode.
  • Each object can consist of multiple models (*.m with optional *.ncp collision) that act as bones. Each bone is animated either freely or relative to a parent.
  • Animation data and keyframes are defined in custom_animations.txt.
  • Use the Custom Animation trigger type to trigger the animation at a specific lap, the first or last lap. Animations can be triggered once or multiple times.
  • You can show or hide body parts per keyframe by setting a visibility flag. This also affects the collision.
  • Each bone can also have a light, sound effect (*.wav) and spark generator attached to it. These attachments can be created, updated or deleted at any keyframe.

Each custom animation object added in Objects edit mode accepts the following flags:

  • Animation ID (the animation slot defined in custom_animations.txt).
  • Trigger ID (optional, if the object uses a trigger).
  • Start time (delay in steps of 0.1 seconds).
  • Whether to show or hide in time trial.

Triggers let you decide when to start the animation. The Custom Animation trigger type supports the following options:

  • Flag low: Object ID (same as Trigger ID above).
  • Flag high: The lap to trigger in (0 = any lap, -1 = last lap, n = nth lap).

Sample Custom Animations File

custom_animations.txt

This file contains a couple of sample animations along with documentation of all used properties and limitations. You can use this to base your custom animations on.

To see the sample animations in action, download the complete sample track below. cstm_anim_ex.zip

Models

Up to 64 custom models can be defined. These models need to be shared by all animations. Each model has an ID and model name.

MODEL   0   "tw_plane"

In this case, the game looks for the files models\tw_plane.m and models\tw_plane.ncp. However, it is possible to override this behavior by placing the files inside the level's custom folder instead (custom\tw_plane.wav).

Sound Effects

Up to 64 sound effects can be defined. These sounds need to be shared by all animations. Each sound effect has an ID and file name.

SFX     0   "gator"

In this case, the game looks for the file wavs\gator.wav. However, it is possible to override this behavior by placing the files inside the level's custom folder instead (custom\gator.wav).

Animations

Up to 256 animations can be defined. To define an animation, add and extend the following block to your custom_animations.txt file:

ANIMATION {
  Slot                      0                         ; Slot ID (0 to 255)
  Name                      "DEFAULT"                 ; Display name (currently unused)
  Mode                      0                         ; 0: loop / 1: animate a single time, stopping after the last frame / 2: back and forth (reverse after last keyframe)
  NeedsTrigger              false                     ; Whether the animation needs to be triggered
  TriggerOnce               false                     ; Whether the animation can be triggered multiple times
  PreCountdown              false                     ; Whether the animation must start before countdown (in multiplayer)

  BONE {
    BoneID                  0                         ; Body part ID (0 to 15); part 0 is the main body part
    ModelID                 -1                        ; Model ID (0 to 63, or -1)
    Parent                  0                         ; Body part parent ID; must be smaller than the bone ID; not present at the main body part
    OffsetTranslation       0.000 0.000 0.000         ; Offset to parent location
    OffsetRotationAxis      0.000 -1.000 0.000        ; Offset rotation axis
    OffsetRotationAmount    0.000                     ; Offset rotation (in degrees)
  }
  ; Add more bones here.

  KEYFRAME {
    FrameNr                 0                         ; Number of the keyframe (0 to 255)
    Time                    1.000                     ; Time (in seconds) since previous keyframe
    Type                    0                         ; Interpolation type. 0 - linear, 1 - smooth start, 2 - smooth end, 3 - both smooth, 4 - overshoot

    BONE {
      BoneID                0                         ; Body part ID
      Visible               true                      ; Toggle body part visibility (for all future keyframes until it is changed again)
      Translation           0.000 0.000 0.000         ; Translation
      RotationAxis          0.000 -1.000 0.000        ; Rotation axis
      RotationAmount        0.000                     ; Rotation (in degrees)

      ; Add properties for light, sound effect and sparks here (optional).
      ; Values are inherited by future keyframes, so only the properties to
      ; be changed need to be specified again.
      SFX {
        SfxID               -1                        ; Sound ID (0 to 63, or -1)
        Range               0                         ; Range multiplier (0 to 100)
        Looping             false                     ; Whether the sound is continuous or one-shot
      }
      SPARK {
        Type                -1                        ; Particle type, defined in properties.txt (0 to 63, or -1)
        AverageSpeed        0                         ; Average speed of particle (0 to 200)
        VariableSpeed       0                         ; Speed variation of particle (0 to 200)
        Frequency           0                         ; Particle generation frequency (1 to 200, or 0 for one-shot)
      }
      LIGHT {
        Type                -1                        ; Light type (0 - omni, 1 - omni normal, 2 - spot, 3 - spot normal, or -1 to disable)
        Color               0 0 0                     ; Light color (RGB values, -1024 to 1024 for each component)
        Reach               0                         ; Light reach distance
        ConeSize            0                         ; Cone size for spot lights (1 to 180)
        FlickerSpeed        0                         ; Flicker speed (1 to 255, 0 to disable)
      }
    }
    ; Update more bones here.
  }

  ; Add more keyframes here.
}

Up to 16 bones (a main body part and up to 15 child bones) and 256 keyframes can be defined for each animation. The game then interpolates the animation between those keyframes. The type of interpolation can be one of the following:

  1. Linear: Constant velocity and angular velocity.
  2. Smooth start, sudden end: Like an object starting to fall, then hitting the ground.
  3. Sudden start, smooth end.
  4. Smooth start and smooth end.
  5. Exaggerating or overshooting: First moving a bit in the opposite direction, then over the target amount, then again backwards. Gives a robotic look.

Animation Properties

PropertyDescription
SlotUnique ID number of the animation.
NameDisplay name, not used by the game.
Mode0: loop / 1: animate a single time, stopping after the last frame / 2: back and forth (reverse after last keyframe).
NeedsTriggerWhether the animation needs to be triggered.
TriggerOnceWhether the animation can be triggered multiple times. Only applicable when Mode is 1.
PreCountdownWhether the animation must start before countdown (in multiplayer).
BONEOne or more of these blocks to define each body part.
KEYFRAMEOne or more of these blocks to define each keyframe.

Bone Properties

PropertyDescription
BoneIDBody part ID; part 0 is the main body part.
ModelIDModel ID for this body part; can be -1.
ParentBody part parent ID; must be smaller than the bone ID; not present at the main body part.
OffsetTranslationOffset to parent location.
OffsetRotationAxisOffset rotation axis; must be a valid non-zero axis.
OffsetRotationAmountOffset rotation (in degrees).

Keyframe Properties

PropertyDescription
FrameNrNumber of the keyframe.
TimeTime (in seconds) since previous keyframe; animation must have at least one keyframe with non-zero time.
TypeInterpolation type. 0 - linear, 1 - smooth start, 2 - smooth end, 3 - both smooth, 4 - overshoot.
BONEOne or more of these blocks for each body part that should be moved this keyframe.

Keyframe Bone Properties

PropertyDescription
BoneIDBody part ID.
VisibleToggle body part visibility for this keyframe and all future keyframes until this is changed again.
TranslationTranslation.
RotationAxisRotation axis; must be a valid non-zero axis.
RotationAmountRotation (in degrees).
SFXSound effect properties for this keyframe.
SPARKSpark generation properties for this keyframe.
LIGHTLight properties for this keyframe.

Keyframe Sound Properties

PropertyDescription
SfxIDSound effect ID for this body part; can be -1.
RangeRange multiplier (0 to 100). This value is interpolated between frames.
LoopingWhether the sound is looping continuously or plays once.

Keyframe Spark Properties

PropertyDescription
TypeParticle type as it is defined in properties.txt. -1 disables spark generation.
AverageSpeedAverage speed of particle (0 to 200). This value is interpolated between frames.
VariableSpeedRandomized speed variation of particle (0 to 200).
FrequencyParticle generation frequency (1 to 200). 0 generates a single spark instead of continous generation. This value is interpolated between frames.

Keyframe Light Properties

PropertyDescription
TypeLight type. 0 - omni, 1 - omni normal, 2 - spot, 3 - spot normal. -1 removes the light.
ColorLight color. 3 values for RGB, each value ranges from -1024 to 1024. The values are interpolated between frames.
ReachDistance of light's reach. This value is interpolated between frames.
ConeSizeCone size for spot lights (1 to 180). This value is interpolated between frames.
FlickerSpeedFlicker speed (1 to 255). 0 disables flicker.