internals:advscript-format

AdvScript Format

Documentation for the file format used for Story scripts.

File Format

Encryption

The usual file encryption is used, get the keys from the adv_script table in the assets database.

The header is 27 bytes long. Integers in little endian.

Address Length Description
0x00 1 Header identifier (0x80)
0x01 1 “Data information byte” (seems to be some kind of bitmask - 0x80 = has data section?, 0x40 = has resource section)
0x02 4 Data section start address
0x06 4 Resource section start address (0 if there is no resource section)
0x0A 4 Data section size after decompression
0x0E 4 Resource section size after decompression (0 if there is no resource section)
0x12 1 “Check byte” (?? seems to be always be 0)
0x13 4 “Nonce” (?? seems to be always be 0)
0x17 4 “Key nonce” (?? seems to be always be 0)

Compression

AdvScript files are compressed by using length-distance pairs (comparable to LZ77).

A copy instruction starts with the identifier byte 0x80. The following byte is the offset, the one after that is the match length. To decompress the data stream, the copy instruction must be replaced by length + 1 bytes read from the data stream rewound by offset + 1 bytes.

Note that length can be greater than offset, in which case a sequence can be repeated several times - for example, the byte sequence 11 22 33 80 02 05 would decompress into 9 bytes: 11 22 33 11 22 33 11 22 33.

One must take care that copy instructions are only handled outside of completed characters - the identifier byte may occur within a multibyte UTF-8 character, especially full width punctuation, but does not represent a copy instruction in that case.

Once the header is removed and the file is decompressed, you have the actual AdvScript script, a text file in UTF-8 encoding.

Structure

Resource Section

A list of resources that is required to execute this AdvScript. Probably seperate so AdvScript players can check for needed data first.

The section begins with a line defining how many resources follow:

resource=A sound=B script=C definition=D

Where A, B, C and D are integers, including 0. This header line defines the amount of each type of resource. Following this line, there are A lines with resource files (classes defining basic objects, so things such as backgrounds, sprites and effects can be loaded and used), B lines with sound files, C files with other AdvScripts and D definition files. The Resource section ends immediately after.

Note that voice lines for dialogue are not listed in the sound files here, as they are not required to execute the AdvScript - they are optional, since the player can choose to play the episode with or without voices. These are handled seperately (somehow, to be researched) by the Text commands.

Definition files are the only location where constants and macros can be defined. The following two commands are used for them.

@const

@<const_name> <value ...>

@ marks a constant, that can be used at any point in the script and seems to be simply evaluated by replacing it in the command string. That means all characters after the constant name, until the end of the line, are part of the replacement, even if seperated by spaces.

This is used for example to define constants of pairs of X and Y coordinates, so that they can be used together in the other commands.

@consts must be defined in a definition file, and then loaded in the Data section with &const.

%macro

%<macro_name>
[command]
[command]
[command]
...

% marks a macro, basically a function. When %<macro_name> is used anywhere else, the list of commands below the definition will be executed. The command list is ended either by the start of a new macro, or the end of the definition file.

%macros must be defined in a definition file, and then loaded in the Data section with &macro.

Data Section

Starting at the data section start address from the header, the actual AdvScript commands are listed to be played back when the player watches the story. It seems to always begin with the Label #main, which is probably an entry point marker. Commands are further detailed below.

Commands

Each command is one line in the script, and arguments are split by half-width spaces (0x20). Leading/trailing spaces must be ignored, multiple consecutive spaces are treated as a single space. Since spaces split arguments, if they're needed for anything (a textbox label, a message, a dialogue option…), surrounding text with pipes like this escapes them: ||I can use spaces||. Escaping includes newlines - if an escaped segment includes an \n, it does not start a new command.

Any command that will pause the script (like Text or fade) can be modified to skip the pause and immediately continue instead by adding + as the final argument. This is usually used if delay commands are used to, for example, run timed animations during a voice line. This is often followed by something like a wait or a waitclick command to still behave like the unmodified command, but with extra command running in parallel.

Many commands deal with “planes”, where backgrounds, characters and effects can be placed on. It's easier to think of them as layers. All planes are shown at once (with some exceptions like phone mode), and elements on them can be shown and hidden on demand. However, only one background/character/effect/… each can exist per plane.

Text

<label> <message> [voice]

label: If the command in the first argument is not known, it is interpreted as a Text command. The message box pops up and displays the given text. The first argument, which would usually be the command name, is used as the label for the box, showing the speaker of the text. [player] is replaced by the player's chosen nickname, - is a special label to indicate the message box label should be hidden. All other unicode strings are displayed as-is.

message: The message to display. Some simple HTML-like styling is supported, check the Markup section below.

voice (optional): The ID of the voice clip to play when this message box appears.

#label

#<label_name>

# marks a label that can be jumped to (see goto and select).

$variable

$<variable_name> [value]

$ declares or sets variables that can be used for flow control. If value is omitted, the variable is simply declared. Nothing happens if the variable already has a value set.

&const

&const <definition_file>

Imports a list of constants from the given file (see @const).

&macro

&macro <definition_file>

Imports a list of macros from the given file (see %macro).

aisac

aisac <aisac_name> <control_name> <value>

Commands that are sent to an Advanced Interactive Sound and Active Controller (AISAC). The only AISAC that seems to be used right now is the voice controller. It has the following known controls. Changes will only apply to the next voice line played, and then reset to the default.

  • AisacC10_BUS_REV
  • AisacC11_Echo
  • AisacC12_Stage
  • AisacC13_LowPass
  • AisacC15_Telephone
  • AisacC16_Megaphone

backeffection

backeffection <enable/disable>

bg

bgm

bgmfade

cg

ch

chat

chat <open/close>

changewindow

changewindow <window_type>

1: Regular bottom message box.

2: Full-screen message box without speaker label.

3: Message bubbles for chat mode.

clear

clear

Hides the message box after it was displayed by a Text command.

click

click <enable/disable>

Whether to allow the user to click the screen to move forward in the script. Can be used with delays or waittext to avoid the user accidentally breaking animations and such.

delay

delay <duration>
[command]
[command]
[command]
...
enddelay

Opens a block in which all commands will only be executed after a certain wait time. The script is not paused, a timer is set instead. The block is closed by an enddelay instruction. If waits or pauses following this command are interrupted by the player, any unfinished delay blocks are immediately executed.

This is usually used to have character sprites animate at certain points during a voice line. A non-pausing Text command is used, followed by one or more delay blocks for each animation, and finished with a waitclick command.

duration: In seconds, can be a decimal.

command: A list of any number of commands to be executed once the timer finishes.

ef

ef <slot> load <effect_name> [arguments...]

Loads an effect from a prefab defined in the Resource Section. Known effect names are:

intensive: Speed lines. Takes desired alpha (0-1) as optional argument, seems to default to 0.5-ish?

particle

place: Single line text label with background

sakura

text: Free-floating tex label

ef <slot> play [arguments...]

place: Takes the text to display as argument

ef <slot> text <text> <size>

text effect only?

ef <slot> color <color>
ef <slot> gradation <color> <color>
ef <slot> shadow <x offset> <y offset> <color>
ef <slot> outline <width> <color>
ef <slot> pos <x> <y>
ef <slot> plane <plane>
ef <slot> scale <x factor> <y factor>
ef <slot> delete

effection

effection <enable/disable>

else

See if.

em

enddelay

See delay.

endif

See if.

eyeblink <enable/disable>

fade

fade <in/out> <layer?> <duration> [color]

If color is not set, it will default to black.

fadesetting

fadesetting type <fade_type>

AlternateStripeHorizontal: horizontally striped, each stripe wiping alternating between wiping left to right and right to left

Circle

Default: uniform fade

Horizontal: horizontal wipe left to right

Round: rotating wipe from top, going clockwise (the “time passing” fade)

Slanting: diagonal wipe, top left to bottom right

SlimStripeHorizontal: like StripeHorizontal but thinner

StripeHorizontal: vertically striped, each stripe wiping horizontally left to right

StripeVertical: horizontally striped, each stripe wiping vertically top to bottom (“blinds transition”)

Vertical: vertical wipe top to bottom

fadesetting flip <enable/disable>

Whether to rotate the fade animation 180 degrees.

finalistselect

finalistselect

A command used exclusively in Chapter 2, Story 10a. Displays a selection dialog for the first nine Nijigaku members. In this story, this will decide who the player character sends a message to, resulting in branching dialogue and changing the following Super Stage.

For the AdvScript execution, this command will store the chosen member in variables. $finalist_id will be set to the chosen member's ID (the same as the ones defined in the Scenarios/ConstantValues/llas_character_constants definition file), and $school_grade will contain the chosen member's year (1/2/3) as a helper variable for handling sprites and honorifics. These variables are used in if commands to set up the planes and run the correct dialogue.

Additionally, the command (somehow) adds member_id to the payload for the story/finishUserStoryMain API call at the end of the story to notify the server about which Super Stage to display. (It might be that this is not something the command itself does, but that the AdvScript runtime exports set variables at the end, and other code actually checks for whether the variable was declared so it can be added to the payload.)

The command will still be executed if the player skips the story before this command.

fronteffection

fronteffection <enable/disable>

goto

goto <label>

Jumps to the given label and executes commands from there.

if

if <condition>
[command]
[command]
...
[else]
[command]
[command]
...
endif

Opens a block in which all commands will only be executed if the condition evaluates to true. The block is ended either by the start of an optional else block for commands to be executed if the condition evaluates to false, or the endif command.

The condition can use $variables, @constants and the usual operators for testing equality and comparing numbers (for example: if $school_grade <= 2).

label

letterbox

letterbox <show/hide> [duration] [size]% [plane]

duration: Duration of the animation that both moves and fades the borders, in seconds

size: Size of the borders relative to the screen, in percent. This is per border, not in total - so 50% will cover the entire screen.

plane: Which plane to show the borders on.

lipsync

lipsync <sync/normal>

messagefrom

When chat is open and the window type is 3 (message bubbles), this adds the member avatar next to the message bubble created by the following Text commands (until messagefrom is used again.). A Text command from [player] will override this setting, but keep the value set for the messages following the player character message.

TODO: does this also apply to label?

movement

ot

ot <plane?> <"material"/"blur"> <arguments?>

Special effects for all items on the given plane?

material takes Sepia, NegativePosition or default as argument. blur takes two numbers (blur radius and alpha?)

phone

phone set <plane>

Sets up the phone module, using plane as the displayed plane number for commands such as bg and ch.

phone open

Plays the phone opening animation (sliding up from the center of the bottom edge)

phone close

Plays the phone opening animation (sliding down)

phonepos

phonepos /<x> /<y>

The / is required (?). Can be used to place the phone off-center.

pillerbox

sic

pillerbox <show/hide> [duration] [size]% [plane]

See letterbox.

plane

For cutins

preload

recollect

recollect <enable/disable>

release

release <"cg"/"ch"/"se"...>

Destroy all resources of the given type. Can define multiple types as seperate arguments. Not required at the end of the script, just as a mid-script cleanup if neccessary.

select

select <text> <label>

Shows dialogue options for the player character. If a select command is read, all following select commands are also processed. The script is then paused and all selections are shown as an option list for the player, with the given display text on the buttons. If a button is pressed, the script jumps to the given label and resumes.

silentborder

silentborder <"default"/number>

singletext

singletext <enable/disable>

sound

soundstop

sp

talkstop

textmode

textmode <textmode_type>

Normal: The default mode, where each Text command clears the message box and only displays the text from that one command.

Additive: Will not automatically clear the message box for each Text command, and allows appending text to an existing one. The clear command can still be used to manually empty message boxes. Note that text will be appended directly without line breaks, so if you want them you must add a <br/> tag at the end of the previous message or at the start of the new message.

AdditiveNewLine: Will not automatically clear message boxes like Additive, but will add a double new line for each new Text command automatically (so that there is a blank line in-between).

textspeed

textspeed <number or "default"> ["auto"]

If the second argument is auto, set the text speed for autoplaying mode, if not, for normal mode? (These always appear in pairs, one with and one without auto, with the same number)

viewing

viewing <enable/disable>

Show or hide the top right menu buttons.

volume

wait

wait <duration>

Pauses the script for a certain amount of time. Cannot be skipped by the player.

duration: In seconds, can be a decimal.

waitclick

waitclick

Pauses the script until the user clicks the screen. Usually used after a non-pausing Text command once the delay commands after it were executed.

waittext

waittext

Pauses the script until the text typing animation finishes for the previous Text command. Usually used after a non-pausing Text command, combined with textmode set to Additive and some delay commands, this allows delaying parts of a message box.

waitload

waitload

Pauses the script until all preloads started before this command finish.

window

window <"show"/"hide"> ["animation"]

Shows or hides the text window, instantly if the second argument is missing or with an animation if it is set to animation.

Markup

In the message of Text commands, AdvScript supports some HTML-like markup to style the text. While some name and attributes might be different, it generally works just like HTML.

<br/>

<br/>

A linebreak.

<span>

<span size="number" spacing="number">...</span>

Apply a style to the text between the tags. All attributes are optional.

size: Text size. Default text size seems to be about 28?

spacing: Distance between characters, can be set to “0” to remove any spacing.


Contributors to this page:
internals/advscript-format.txt · Last modified: 2022/09/16 16:24 by Suyooo