Skip to content

Locations and languages

Use localization files to translate your mod’s text. Register a locale only when adding a language choice to the game. A location is the arena background and fighter placement used by a fight.

Recovered location compatibility: the legacy bridge name uses the installed night_bridge artwork and layout because the original Bridge images are missing. Its runtime name stays bridge. A registered custom location uses its own supplied layout and artwork. A location without a music setting can still be previewed; its encounter supplies the battle track.

Signature: sf2.locales.register(definition)

Returns: The qualified locale ID as a string.

When: During mod loading.

Requires: content.register.

Field Meaning
id Required local identifier.
name Required display name.
locale Required locale code.
alias Optional legacy identifier, default empty.
is_asian Optional boolean, default false; selects the corresponding text layout behavior.
file_icon, file_icon_selected Optional existing icon names, default empty.
loader_image, preloader_image Optional existing image names, default empty.
fonts Optional font configuration described below.

If fonts is supplied, content, title, and button are required font-name strings. size_scale, line_spacing, and custom_line_spacing_scale default to 1 and must be positive finite numbers. Font and image names must resolve to supported game resources; this function does not import a font file.

local language_id = sf2.locales.register {
id = "custom_english",
name = "Custom English",
locale = "eng",
}

This registers the language option. Put translated strings in localization files separately; see Localization.

For procedural warnings and pose-based hazard sensors, see Arena regions and markers. Lua owns their timing and damage policy.

Signature: sf2.locations.register(definition)

Returns: A location handle.

When: During mod loading.

Requires: content.register; declare dependencies for external assets.

Field Default and meaning
id Required local identifier.
color "0x000000"; background color string.
width, height 1936, 512; positive arena dimensions.
min_width Same as width; positive minimum width.
wall, floor 200, 80; arena boundaries.
position_y 0; vertical offset.
friction_force, grid_size 0; physics/layout settings. Grid size cannot be negative.
dojo false; opt this location into saved dojo selection . At most 256 choices across active mods.
music Optional single audio handle; cannot be combined with nonempty music_choices.
music_choices Optional dense array of up to 16 distinct audio handles. Empty/omitted means no choices.
layers Required, nonempty array of layer tables.
tags Optional array of up to 16 stage tags, such as { "night", "lamps" }, so effects that pick stages by tag include yours. Needs presentation.visuals.

Each layer has type (integer, default 1), factor (number, default 1), and scaling (boolean, default false). It needs images or fighter placements. Use type = 2 for a layer with fighters.

An image requires a sprite handle. x and y default to 0; positive width and height default to 1. opaque, flip_x, flip_y, and mask are booleans defaulting to false. A fighter placement requires all four numbers: player_x, player_y, enemy_x, enemy_y. Coordinates and numeric settings must be finite.

local arena = sf2.locations.register {
id = "training_arena",
width = 1936, height = 512, floor = 80, wall = 200,
layers = {
{
type = 1,
images = { {
sprite = sf2.assets.sprite(
"core:textures/locations/battlefield/battlefield_bg1.back_1"),
width = 1936, height = 1024,
} },
},
{
type = 2,
fighters = {
player_x = 868, player_y = -94,
enemy_x = 1068, enemy_y = -94,
},
},
},
}

These dimensions are a starting point for this particular background. Check both fighter positions and camera framing in game when changing the art.

Signature: sf2.locations.name(location)

Returns: The location’s qualified ID as a string.

When: During mod loading, after obtaining the location handle.

Requires: A valid location handle belonging to the current scripting context; no additional capability.

Converts a location handle to the name expected by a fight’s location field. Passing a plain string or a handle of another kind is an error.

local arena_name = sf2.locations.name(arena)
-- Use location = arena_name inside sf2.fights.register { ... }.

Stage tags say what a stage looks like: its light, its weather and what is in it. Visual effects pick their stages by tag (tags and exclude_tags), so an effect written for fire runs on every burning stage, including stages from other mods, without listing their names. Tags are presentation only: they are never saved and do not change which mods can play together online.

Every stage has exactly one light tag. The others are optional.

Tag Meaning
day Open daylight, or daylight through windows.
dusk Low sun: sunset, sunrise or golden haze.
night A night sky or moonlight.
dark Little natural light at all: caves, voids, deep rooms.
indoor Under a roof or inside a cave.
raid A raid boss arena.
fire Open flames, lava or something burning.
lamps Lanterns, candles or lit windows.
otherworld An unnatural glow: magic, machines, portals.
rain Rain.
snow Snow or ice.
mist Fog, haze or drifting dust.
heat Shimmering hot air.
foliage Trees, leaves or grass.
petals Blossoms or flowers.
water A lake, river, sea or waterfall.

Tag the stages you register with tags in sf2.locations.register. To add tags to a stage that already exists, use sf2.locations.tag.

Stage Tags
american_event_24 day, snow
arena dusk, mist
arkhos_raid raid, dark, fire
autumn day, foliage
bamboo_grove day, foliage, mist
battlefield dusk, mist
blackness_raid raid, dark, otherworld, water
bridge day, petals, water, mist
burning_town night, fire, heat
capsules dark, otherworld, mist
castle_and_bridge day, foliage, water, mist
cave dusk, indoor, mist
chess_yard day, mist
dark_room day, indoor
dock day, water, mist
dojo day, indoor, petals
dojo_8_march day, indoor, petals
dojo_american_event day, indoor
dojo_american_event_22 day, indoor
dojo_american_event_26 day, indoor
dojo_cny25 dusk, lamps
dojo_hw21 dusk, indoor
dojo_hw22 night, indoor, lamps, otherworld
dojo_hw24 dusk, indoor, lamps
dojo_india24 dusk, indoor, lamps
dojo_india25 dusk, indoor, lamps
dojo_indian_event day, indoor, petals
dojo_indian_event_22 dusk, indoor, petals
dojo_new_year_22 night, indoor, snow
eggs dark, otherworld, mist
emerald_forest day, foliage, mist
factory day, otherworld, mist
fall_event_24 night, foliage, mist
fatum_raid raid, dark, fire, mist
fear_raid raid, dark, otherworld
flooded_village day, rain, water, mist
flowers_field day, foliage, petals
flying_rocks dusk, mist
flying_rocks_small dusk, mist
fuji day, snow
fungus_raid raid, dark, otherworld, mist
gatekeeper_raid raid, dark, indoor, lamps, otherworld
graveyard_ships day, heat
haloween_dojo night, indoor
haloween_dojo_2019 night, indoor
heaven day
hoaxen_raid raid, day, otherworld, mist
hunger_raid raid, dark, fire
hunter_raid raid, day, otherworld
hw24_ancient_temple night, lamps, foliage, otherworld
hw24_village_night night, lamps
hw24_waterfall_night night, lamps, water, mist
ice_cave day, indoor, snow
lamps_on_water night, lamps, water, mist
magic_rocks dusk, fire, heat
megalith_raid raid, day, indoor
moon night, mist
mountain dusk, foliage, mist
mountains_ny_25 day, snow, foliage
neural_network dusk, otherworld
new_year_china_dojo day, indoor, lamps, petals
night_bridge night, lamps, foliage, water, mist
pink_lake dusk, water, mist
ritual_battle_raid raid, day, indoor
ritual_fungus_raid raid, dark, otherworld, mist
ritual_hunger_raid raid, dark, fire
ritual_vulcan_raid raid, dark, fire, heat
road day, foliage, petals
ruins_village dusk, mist
ruins_village_small dusk, mist
sakura dusk, petals, mist
saturn_raid raid, night, otherworld
shadow_gate dusk, mist
ships dusk, water
skyport dark, indoor, lamps, otherworld
snowy_peak day, snow
spaceship dusk, otherworld, mist
spaceship_thorny dusk, otherworld, mist
statue dusk, lamps, foliage, mist
stone_dragon day, mist
stone_forest day, water, mist
stone_forest_thorny day, mist
swamp day, rain, foliage, water, mist
two_faced_city night, lamps
village day, foliage
volcano dusk, fire, heat
vortex_raid raid, day, indoor, otherworld, water, mist
vulcan_raid raid, dark, fire, heat
war_raid raid, dusk, fire, heat
waterfall dusk, water, mist
waterfall_small dusk, water, mist
whisper_raid raid, night, indoor, lamps

Signature: sf2.locations.tag(stage, tags)

Returns: Nothing.

When: During mod loading.

Requires: presentation.visuals.

Adds stage tags to a stage. stage is a game stage’s name, such as "dock", or a location handle from sf2.locations.register. tags is an array of 1–16 tags from the list above. Tags only add: a stage keeps its own tags and every other mod’s. An unknown tag is an error.

-- The dock is lit by harbour lanterns in this mod's art.
sf2.locations.tag("dock", { "lamps" })
-- Tag a stage this mod registers after the fact.
local arena = sf2.locations.register { id = "ash_arena", layers = { ... } }
sf2.locations.tag(arena, { "dusk", "fire", "heat" })

Optional motion_x, motion_y, rotation and opacity tables apply to location images. Each is { offset = 0, points = { ... } }. Points require period (seconds) and value; ease defaults to zero. Curves loop from the last point back to the first. Each period is the time from that point to the next. Offset advances the initial phase in seconds.

Position values are displacements in native arena units; positive Y motion uses the native effect’s upward axis (the image’s base y coordinate is inverted by the location loader). Rotation uses native degrees. Opacity values are percentages from 0 to 100. ease = 0 gives linear interpolation. Other values use the native quadratic curvature coefficient, not a named easing preset, and can overshoot.

local drift = {
offset = 0.25,
points = { { period = 1, value = -8 }, { period = 1, value = 8 } },
}
-- Inside a location layer's images array:
local image = {
sprite = sf2.assets.sprite("my.mod:sprites/scenery/banner"),
width = 128, height = 256,
motion_y = drift,
rotation = { points = { { period = 1, value = -2 }, { period = 1, value = 2 } } },
}

Each curve requires 2–64 points. Periods must be between 1/60 and 120 seconds, and offsets between zero and the sum of periods. Values must be finite and in -10000..10000; opacity narrows this to 0..100. Ease must be zero or have magnitude 0.0001..1000 to avoid unstable native coefficients. Zero-duration segments are rejected because the native loop cannot safely advance an all-zero curve. Animated images cannot be masks or marked opaque; flipping remains supported.

These are decorative picture effects using the native scenery clock. They do not grant collision, damage, hazard timing, atlas animation or particle control. Pause behavior must be tested in the intended scene; scenery timing is not the combat callback clock. Curves participate in content fingerprints. Existing static images keep their original projection. Numerical and Lua/projection tests pass; full-game visual, pause and lifetime acceptance remains outstanding.

Set music_choices on a location to let the native game choose one track at fight entry. Each entry has equal probability; a track may repeat on the next entry. The chosen track loops. This is not a sequential playlist, and selection is not tied to a mode’s saved random stream.

-- Add this field to your location definition alongside its id and layers.
music_choices = {
sf2.assets.audio("core:gamedata/music/fight1_samurai_spirit"),
sf2.assets.audio("core:gamedata/music/fight2_blade_dance"),
},

Use audio handles, not filenames or pipe-separated strings. Declare dependencies for tracks from another mod. Duplicate assets, sparse arrays, more than 16 entries, wrong handle kinds and combining a nonempty array with music are rejected. Both a location’s single track and its choices take priority over the fight’s music setting. Omitting both retains the existing fight/default fallback.

The ordered choices are part of the content fingerprint. They do not save a live playback position. Apply & Restart is required after changing the definition. Native selection/projection tests pass; audible playback, volume/mute behavior and scene transitions still need a game test. See the Animated Arena example.

Signature: sf2.locations.dojo_picker { id = "...", button = sprite, button_pressed = sprite, title = key, choices = { { location = ..., name = key, preview = sprite }, ... } }

Returns: The qualified name of the picker’s dojo-menu button, <mod-id>.<id>.

When: During loading (at the top level of your scripts). It is a registration, not something to call from a callback.

Requires: content.register and presentation.dojo. No ui.create is needed: Eclipse draws the picker itself.

Declares a ready-made dojo picker. Eclipse adds your button to the dojo’s side menu (below the disciple toggle, like sf2.ui.dojo_button) and opens the picker when it is pressed. You only describe the choices; no Lua runs while the picker is open.

The picker shows a large medallion of the focused dojo with its name, over a dimmed scene tinted by a soft, slowly turning copy of the same art. A strip of all the medallions sits underneath and glides with the focus; the focused one is enlarged and the others shrink and fade with distance. Changing the focus slides the new medallion in from that side. The dojo the player is using now is tinted gold and labelled CURRENT DOJO.

Control Action
Left/Right arrows, A/D, mouse wheel, D-pad or left stick, the < > arrows, clicking a medallion in the strip Move the focus (holding repeats).
Enter, Space, gamepad A, clicking the large medallion or the focused strip medallion Enter that dojo: the medallion pulses, the choice is saved as with sf2.locations.select_dojo and the dojo reloads through the usual scene fade. Choosing the current dojo just closes the picker.
Esc, Backspace, gamepad B Close without changing anything.
Field Required/default Meaning
id Required 1–64 lowercase ASCII letters, digits, _ or -. The button is named <mod-id>.<id> and counts toward your mod’s four dojo buttons.
button Required Sprite handle for the dojo-menu button.
button_pressed The button sprite, darkened Sprite handle shown while the dojo-menu button is held down. Same size as button.
title "CHOOSE YOUR DOJO" Localization handle for the heading (shown in capitals).
choices Required 1–64 choices, in display order, without duplicate locations.
choices[i].location Required A core:locations/<name> string or a location handle this mod registered with dojo = true.
choices[i].name Required Localization handle shown under the large medallion (in capitals).
choices[i].preview Required Sprite handle for the medallion. Square art with a transparent surround works best; it is drawn at up to 330 × 330 units.

A mod may declare one picker. Choices whose native location is not installed, or whose preview fails to load, are left out when the picker opens; if none remain the button does nothing and a warning is logged. The button does not send a dojo_button story event; plain sf2.ui.dojo_button buttons still do.

local sf2 = require("sf2")
local choices = {}
for _, name in ipairs({ "dojo", "dojo_india24", "haloween_dojo_2019" }) do
choices[#choices + 1] = {
location = "core:locations/" .. name,
name = sf2.localization.key("dojo_name." .. name),
preview = sf2.assets.sprite("sprites/dojos/" .. name),
}
end
sf2.locations.dojo_picker {
id = "dojo_picker",
button = sf2.assets.sprite("sprites/dojos/button"),
button_pressed = sf2.assets.sprite("sprites/dojos/button_pressed"),
title = sf2.localization.key("dojo_picker.title"),
choices = choices,
}

Signature: sf2.locations.select_dojo(location_or_core_id)

Returns: nil.

When: After a game profile has loaded, normally from a selector’s UI callback. The new backdrop applies on the next dojo or shop entry; it does not refresh an already open scene. The shop renders the selected dojo’s native layers and ambient effects behind its fighter preview and controls, including registered mod locations.

Requires: presentation.dojo and either this mod’s registered location handle with dojo = true, or a core:locations/name string for an installed native location with gamedata/locations/name/params.xml. UI creation separately requires ui.create.

-- arena is a location handle registered earlier with dojo = true.
-- Call inside your selector's on_click callback.
sf2.locations.select_dojo(arena)
sf2.ui.close(view)
-- Select an installed native dojo without copying its location definition.
sf2.locations.select_dojo("core:locations/dojo_india24")

The host writes the preference into the current profile’s existing save DOM and requests the normal profile save. The call does not synchronously flush to disk. The preference takes priority over the native quest-selected dojo, and never changes ordinary battle locations. No fighter or inventory definition is changed.

The latest explicit selection replaces the previous preference. A mod can select its own registered choices or an installed native location. No selection is made automatically when a mod loads. Invalid handles or core IDs, missing native params, non-dojo mod locations, unavailable profiles and missing capability raise an error before changing the preference. If a selected core location becomes unavailable on a later run, the host temporarily uses the native dojo and preserves the saved choice until its params return.

Signature: sf2.locations.selected_dojo()

Returns: Saved qualified location ID string, or nil for the native default.

When: After a game profile has loaded.

Requires: presentation.dojo.

local selected = sf2.locations.selected_dojo()
local using_this_arena = selected == sf2.locations.name(arena)

This reports the saved preference, including a currently unavailable location. It does not report the temporary fallback or the currently rendered scene. When its provider mod is absent, the game uses the native dojo and preserves the preference. Reenabling the provider restores it at the next dojo entry.

Signature: sf2.locations.reset_dojo()

Returns: nil.

When: After a game profile has loaded, normally from a reset button.

Requires: presentation.dojo. The saved choice must belong to this mod, be a core location, or already be empty; another mod’s preference cannot be cleared by this function.

local selected = sf2.locations.selected_dojo()
if selected == nil or selected == sf2.locations.name(arena) then
sf2.locations.reset_dojo()
end

Reset explicitly clears the preference and requests a profile save; it preserves unrelated save data. The native/default dojo returns on the next entry. Switching profiles and shutting down unload the active binding. Unknown or malformed preference data is retained and selection operations remain unavailable for that profile.

The Dojo Selector example opens a game-themed chooser from a custom map entry using deferred mode preparation. Closing it cancels preparation without entering a fight. Native menu insertion and automatic scene navigation are not supplied by these functions. Registration, Lua UI callbacks and save-store tests pass; full-game persistence, art rendering and scene transitions still need acceptance.