SubItem API

SubItem is the visual and animation layer used by every active object. Players, enemies, characters, and items all inherit these fields through flattening.

Free item/subitem slots can be initialized with initialize(pack_name, entity_name, animation_id, mode = 2). Player/enemy slots and occupied slots are rejected. Helpers created during a cinematic are removed when it ends; see Script-owned cinematics.

Identity And Visual State

Property Type Read/Write Detail
name string read Internal entity name. Exact bridge name is Name.
classic_name string read Name of the Classic entity this one behaves as, followed through its logic references: "Pipe" for a mod's bat that references Classic Pipe. nil when it has no Classic base. Use it to tell weapon kinds apart.
is_throw_only_weapon bool read The item's own logic.json sets throwOnlyWeapon: a weapon that is only thrown, never swung or stabbed.
is_melee_only_weapon bool read The item's own logic.json sets meleeOnlyWeapon: a weapon that is never thrown.
is_breakable_weapon bool read The item's own logic.json names a brokenWeapon: it breaks into that entity on its first hit.
thrown_damage int read Damage the item deals when it hits as a projectile: its logic projectileDamage, followed through logic references.
pack_name string read Content pack name resolved from the pack hash.
pack_hash int read Runtime hash for the current pack. Exact bridge name is PackHash.
is_enabled bool read True when the slot exists. Exact bridge name is IsEnabled.
object_index int read Global object ID for this object. Exact bridge name is ObjectIndex.
entity_type int read/write Runtime hash or type ID for the entity.
palette_pack int read/write Pack hash for palette lookup.
palette_line int read/write Palette row/index.
ignore_rendering bool read/write When true, the animation updater does not advance frame progress through the normal rendered path.
custom_z_order int read/write Manual render depth in raw engine 16.16 units. Unlike Lua position/screen-position fields, this field does not divide by PositionMultiplier (1000). For a Lua ground coordinate, assign ground * 1000.

Animation And Facing

Property Type Read/Write Detail
is_facing_right bool read/write Main facing flag. Changes hitbox orientation, forward/backward input interpretation, and spawn direction.
direction_signal int read 1 when facing right, -1 when facing left.
object_mode int read/write Behaviour mode used by original and reference controllers. For many player standing states, 2 returns to active standing logic.
current_animation_id int read/write Editor-facing animation ID. Internally stored doubled. Prefer set_animation for transitions.
current_animation_frame int read/write Current animation logic frame. Advanced after movement scripts run.
next_animation_id int read/write Queued animation ID. The animation controller copies it into current animation later.
next_animation_frame int read/write Start frame used when the animation ID changes, or when the current animation loops. Setting this alone does not seek an animation already playing.
is_animation_over bool read/write Read checks whether the current frame has reached the animation duration. Writing true finishes the animation. Writing false has no effect.
referenced_object_id int read/write Generic linked object ID used by some behaviours.

Screen Position

Property Type Read/Write Detail
screen_position_x int read/write Screen X in script units. Internally scaled by 1000.
screen_position_y int read/write Screen Y in script units. Internally scaled by 1000.

Generic Script State

Property Type Read/Write Detail
custom_value_1 through custom_value_10 int read/write Per-object script storage. Use for timers, mode selectors, one-shot flags, and stored object IDs.

Read and write these through named properties, such as e.custom_value_1. Bracket access such as e["custom_value_1"] uses the native entity indexer and does not read that property. For indexed storage helpers, use a table of functions that access the named properties explicitly.

Position changes after physics

A scene post-update script runs after character physics has cached screen_position_x/y for rendering. When it makes an instantaneous pose-position change, update those screen coordinates in the same tick as the position/offset and has_just_teleported. Otherwise the new pose is rendered at the previous origin for one frame. For a world-positioned character, use screen_position_x = position_x + position_offset_x and the corresponding Y expression.

Internal Buffers

These are exposed because several original behaviours use them. Prefer custom_value_* unless you are matching or extending an original behaviour that already depends on these buffers.

Property Type Read/Write Detail
customVelocity_DecBuffer_0_4_X int read/write Original decimal/fixed buffer X. Use exact spelling.
customVelocity_DecBuffer_0_4_Y int read/write Original decimal/fixed buffer Y. Use exact spelling.
customVelocity2_DecBuffer_8_C_X int read/write Secondary original buffer X. Use exact spelling.
customVelocity2_DecBuffer_8_C_Y int read/write Secondary original buffer Y. Use exact spelling.
customDecBuffer_10 int read/write Original behaviour scratch field. Use exact spelling.
customDecBuffer_14 int read/write Original behaviour scratch field. Use exact spelling.
customBulletLifetimeDecBuffer_18 int read/write Original projectile lifetime/scratch field. Use exact spelling.
has_just_teleported bool read/write Set for an authored instantaneous position/pose change to skip sprite and position smoothing that tick. Also set by the engine for throw anchors and nonzero animation entries. Clears residual grab glide, except on the newly entered grab itself.

Grab Offsets

Property Type Read/Write Detail
front_grab_offset int read Front grab offset from logic data converted to script units.
back_grab_offset int read Back grab offset from logic data converted to script units.
held_front_grab_offset int read Distance this entity is held at when grabbed from the front (logic heldFrontGrabOffset), in script units; 0 when unset (the grabber's front_grab_offset applies).
held_back_grab_offset int read Same for a hold from behind (logic heldBackGrabOffset); 0 when unset (the grabber's back_grab_offset applies). Native grab strikes on an entity held at its own distance are tested as if it stood at the holder's own grab offset, so they reach it.

Methods

set_animation(animation_id, start_frame = 0)

Queues an animation change. The argument is the editor-facing ID. Internally the engine stores animation IDs doubled, and the bridge performs that conversion.

The change is fully applied by the animation update step. Return false after decisive animation changes if you need to stop the old controller from continuing during the current frame.

start_frame is used on an ID transition (and as the loop restart frame), not as an immediate seek of an unchanged animation. An already-playing animation normally increments current_animation_frame later in this same frame. A script-owned pose clock must account for that increment when positioning linked actors. Shared throw controllers also read the thrower's current progress before the animation update: a queued throw ID can otherwise be paired with the old hold's progress. Test delayed throws and the rendered frame after the animation pass, not just the queued ID and start frame.

character.set_animation(0)
character.object_mode = 2
return false

play_sound(pack_name, sound_name, channel_id = 0, pitch_percentage = 100)

Schedules an audio effect on the object's audio index.

Only loaded sounds play. Sounds are loaded with the entities that reference them (default sounds, hitbox and sound-event sounds, dependencies.json); a sound that only a script plays must be listed in the sounds of some loaded entity's dependencies.json, or it stays silent.

character.play_sound("My Pack", "guard-impact", 1, 100)

show_hit_effect(offset_x, offset_y, big = true, target_id = -1)

Shows the hit sparkle a hitbox contact shows (the big or small Classic spark, drawn in front of every entity), for hits a script applies itself, such as damage written directly to a held actor. offset_x and offset_y are Lua position units from this object: offset_x ahead along its facing, offset_y up. With target_id (an object index) the target also gets the hit vibration a hitbox contact gives it. It only schedules the visual; it does not apply damage or hit pause.

-- a knee halfway to the held enemy, 40 px up
local ahead = victim.position_x - character.position_x
if ahead < 0 then ahead = -ahead end
character.show_hit_effect(ahead / 2, 40 * 65536 / 1000, true, victim.object_index)

start_palette_fade(frames)

Fades the entity's sprite in from black over frames simulation frames, starting this frame: it is drawn fully dark at the start and at its normal palette when the fade ends. 0 (or a negative value) cancels a fade in progress. The fade start and duration are saved in the entity's state, so it is replay, rollback and netplay safe; the darkening itself is view-only.

-- an entity appearing out of the dark over one second
entity.start_palette_fade(60)

clear_referenced_items()

Clears linked/referenced items through the controller. Use when a move owns spawned helper objects and must clean them up.

Example: One-Time Sound

return function()
    local item = game.this_item

    if item == nil then
        return true
    end

    if item.custom_value_1 == 0 then
        item.custom_value_1 = 1
        item.play_sound("My Pack", "spawn", 0)
    end

    return true
end