Table of Contents
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.
Header
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.
@const
s 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.
%macro
s must be defined in a definition file, and then loaded in the Data section with ¯o.
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
$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).
¯o
¯o <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
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 $variable
s, @const
ants 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
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 preload
s 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: