Cutscenes - KristalTeam/Kristal GitHub Wiki
Relevant files: cutscene.lua, worldcutscene.lua, battlecutscene.lua, text.lua, dialoguetext.lua
Making a Cutscene
Cutscenes are ways to make scripted events play out in a controlled manner. They can be used in either battles or the overworld. Battle cutscenes go in scripts/battle/cutscenes
, and overworld cutscenes go in scripts/world/cutscenes
.
Cutscene files can be made one of 2 ways. The first is to return a function that takes cutscene
as an argument. The cutscene
variable refers to the current Cutscene instance for the function, and is what would be used to execute actions. An example of this type of cutscene would be:
return function(cutscene)
cutscene:wait(1) -- waits 1 second
-- cutscene ends
end
The second way to make a cutscene is to return a table, with indexes referring to cutscene IDs (elaborated on later), and the values each being a function similar to the one above. This is useful for defining many cutscenes within one file, so you don't have to make a new file for each one. An example of this type would be:
return {
id_a = function(cutscene)
cutscene:wait() -- waits 1 frame
cutscene:endCutscene() -- ends the cutscene manually
end,
id_b = function(cutscene, var) -- cutscenes can have arguments passed into them
cutscene:wait(var)
end
}
Cutscenes have several variables and functions available to them, as well as special functions depending on whether the cutscene is an overworld cutscene or a battle cutscene.
Common
finished_callback
: A function that, if defined, will be called when the cutscene ends.
wait(seconds)
: If seconds
is a number, pause the cutscene for the specified amount of seconds. If seconds
is a function, then the cutscene will wait until the function returns true. Some cutscene functions will return functions to define how long they last; passing these functions into wait()
will pause the cutscene until the cutscene function is done. For example, calling cutscene:wait(cutscene:shakeCamera(2))
will shake the camera and wait until the camera is done shaking to resume the cutscene. Additionally, some functions return both a wait function and other values; for these, you'll need to save the returned values to variables, and pass in the wait variable to cutscene:wait()
.
pause()
: Pauses the cutscene indefinitely.
resume()
: Resumes the cutscene if it was paused.
after(func, replace)
: Defines a callback to be called when the cutscene ends, adding onto previously defined callbacks. If replace
is true, however, it will remove all previously defined callbacks.
endCutscene()
: Ends the cutscene.
gotoCutscene(group, id, ...)
: Ends the current cutscene and starts a new one. See [Starting Cutscenes[(Cutscenes#starting-cutscenes) below for how to provide the arguments.
Overworld
textbox
: Refers to the current Textbox instance if there is one.
choicebox
: Refers to the current Choicebox instance if there is one.
choice
: Refers to the number of the last choice made in a Choicebox.
camera_target
: A table of 2 values, referring to the position the camera should be panning to. Should not be set directly, see panTo()
below.
getCharacter(id, index)
: Returns a Character that has an actor with the specified ID. id
is a string referring to an actor ID that the character uses, and index
is an optional number that will specify which instance of the character to return (eg. if there are 3 Ralseis in the room and you call cutscene:getCharacter("ralsei", 2)
, it will return the second Ralsei).
getEvent(id)
, getEvents(id)
: See Map:getEvent()
and Map:getEvents()
.
getMarker(name)
: Returns the position of the marker with the specified name. See Overworld for more details.
detachFollowers()
: Makes followers stop following the party leader.
attachFollowers(return_speed)
: Makes followers start following the party leader. return_speed
is a number defining how fast the followers should walk to their intended position. Returns a function to wait until the followers reach their intended positions.
attachFollowersImmediate()
: Immediately makes all followers start following the party leader and move to their intended position.
alignFollowers(facing, x, y, dist)
: Makes the followers' intended positions be behind the party leader, in a line. facing
is what direction the line should consider the party leader to be facing (eg. right
will make the followers line up to the left of the party leader), x
and y
will offset the line by the specified values, and dist
is how far behind the line should be behind the party leader.
interpolateFollowers()
: Adds the followers' current position to their movement history. If followers are moved by a cutscene, remember to call this at the end, otherwise they will warp back to their old position when the party leader walks.
resetSprites()
: Resets the sprites of all party members.
resetSprite(chara)
: Resets the sprite of the specified character, where chara
is either a string referring to the actor ID of a character, or a Character instance.
look(chara, dir)
: Makes the character face in the direction specified. chara
is either a string referring to the actor ID of a character or a Character instance, and dir
is a string defining the direction to face.
walkTo(chara, x, y, time, facing, keep_facing)
, walkTo(chara, marker, time, facing, keep_facing)
: Makes the character walk towards the specified coordinates. chara
is either a string referring to the actor ID of a character or a Character instance, x
and y
or marker
define the intended position to approach, time
is the amount of seconds it should take for the character to reach the specified position, facing
is an optional string defining the direction they should face when they reach the destination, and keep_facing
is an optional boolean determining whether the character should maintain their current facing direction while walking. Returns a function that waits until the character reaches its destination.
walkToSpeed(chara, x, y, speed, facing, keep_facing)
, walkToSpeed(chara, marker, speed, facing, keep_facing)
: Makes the character walk to the specified position at a specific speed. chara
is either a string referring to the actor ID of a character or a Character instance, x
and y
or marker
define the intended position to approach, speed
is the speed in pixels per frame at 30fps the character should walk, facing
is an optional string defining the direction they should face when they reach the destination, and keep_facing
is an optional boolean determining whether the character should maintain their current facing direction while walking. Returns a function that waits until the character reaches its destination.
setSprite(chara, sprite, speed)
: Sets the character's sprite to the specified path. chara
is either a string referring to the actor ID of a character or a Character instance, sprite
is the sprite path to set the sprite to (relative to the character's actor's path
), and speed
is an optional number that, if defined, will play the sprite at the specified speed (automatically looping).
setAnimation(chara, anim)
: Sets the character's sprite to the specified animation (see setAnimation()
for sprites for detail about the animation argument). Returns a function that waits until the animation is finished, if it doesn't loop.
spin(chara, speed)
: Spins the character.
slideTo(obj, x, y, time, ease)
, slideTo(obj, marker, time, ease)
: Moves an object to the specified position over a period of time. time
is a number defining the amount of time the movement will take, and ease
is an optional string defining the ease type to use for the movement. Returns a function that waits until the object reaches its destination.
slideToSpeed(obj, x, y, speed)
, slideToSpeed(obj, marker, speed)
: Moves an object to the specified position at a specific speed. speed
is a number referring to how fast the object will approach its destination in pixels per frame at 30fps. Returns a function that waits until the object reaches its destination.
jumpTo(chara, ...)
: Makes a character jump. chara
is either a string referring to the actor ID of a character or a Character instance, and ...
correlates to the arguments for the Character's jumpTo()
function (see Characters for more detail). Returns a function that waits until the character finishes jumping.
shakeCharacter(chara, x, y)
: Shakes the character. Returns a function that waits until the character stops shaking.
shakeCamera(x, y)
: Shakes the camera. Returns a function that waits until the camera stops shaking.
detachCamera()
: Makes the camera stop following the party leader.
attachCamera(time)
: Makes the camera reattach to the party leader, panning to them. time
is the number of seconds it will take for the camera to pan. Returns a function that waits until the camera finishes panning.
attachCameraImmediate()
: Immediately attaches the camera to follow the party leader.
panTo(...)
: Pans the camera. The function takes multiple possible kinds of arguments:
- If the first two arguments are numbers, it will pan to the specified coordinates.
- If the first argument is a string, it will pan to a marker with that name.
- If the first argument is a Character instance, it will pan to that character.
The argument after the previously used arguments refers to the time it will take for the camera to pan to its target, and the argument after that will be a function that gets called when the camera reaches its destination. Returns a function that will wait until the camera reaches its destination.
setSpeaker(actor)
: Sets the specified actor to be the current speaker, used for textboxes. actor
can refer to either an actor ID, a Character instance, or an actor's data.
setTextboxTop(top)
: Sets whether textboxes should appear at the top of the screen or not, overriding the default behavior.
text(text, portrait, actor, options)
: Creates a textbox, and automatically pauses the cutscene until the textbox has been advanced. portrait
is an optional string referring to the face sprite used for the textbox, relative to either the current speaker's portrait path (if it has one defined in its actor) or assets/sprites/face
, actor
defines the actor that is speaking (overriding setSpeaker()
if defined), and options
is a table of extra information the textbox uses. options
can contain the following fields:
top
: If true, makes the textbox spawn at the top of the screen.x
,y
: If there's a portrait,x
andy
will offset the portrait's coordinates.wait
: If false, the cutscene will not automatically wait, and instead return both a function that waits until the textbox is advanced, and the Textbox instance used.advance
: If false, the player will be unable to advance the textbox themself.auto
: If true, the textbox will automatically advance when it finishes.skip
: If false, the player will be unable to skip the textbox.reactions
: A table of tables, each containing data to spawn a smaller dialogue within the current one. Each table defines the actor and face sprite used, the x and y positions of the face, and the dialogue, in that order. x and y can be strings as well, referring to existing positions; x can beleft
,leftmid
,mid
,middle
,rightmid
, orright
, and y can betop
,mid
,middle
,bottommid
, andbottom
. Must be used in combination with areact
text command (see In-text Modifiers below for more detail).functions
: A table defining functions that can be called with thefunc
text command (see In-text Modifiers below for more detail). Each index defines the ID of a function, and the value for each index is a function that will receive arguments specified by the modifier.
choicer(choices, options)
: Creates a textbox with choices, and automatically waits until the player chooses. choices
is a table of strings, referring to each option available, and options
is a table of extra information, similar to text()
. Returns the numerical index of the choice that was chosen.
closeText()
: Closes the current textbox if one exists.
startEncounter(encounter, transition, enemy)
: Starts an encounter, and automatically pauses the cutscene until the encounter is finished. encounter
can be either the ID of an encounter or an existing Encounter instance, transition
is an optional boolean determining whether the game should transition into the encounter or start it immediately (defaulting to true), and enemy
is an optional ChaserEnemy instance that will be moved to its starting position in the specified encounter.
mapTransition(...)
: Calls World:mapTransition()
with the provided arguments. Returns a function that waits for the transition to finish.
loadMap(...)
: Calls World:loadMap()
with the provided arguments.
fadeOut(speed, options)
: Makes the screen fade out to black. speed
is the time it will take to fade, and options
is a table of extra information for the fade. options
can define the following fields:
color
: A table of RGB of the color to fade to. Defaults to black.alpha
: The alpha to fade to. Defaults to 1 (full opacity).music
: If defined, the current music will fade out. If defined as true, it will make the music fade out at the same speed as the screen; if defined as a number, it will make the music fade out over the time specified by the number.global
: Whether the function should use the globalGame.fader
object or the map'sGame.world.fader
object. Defaults to true, usingGame.fader
.
fadeIn(speed, options)
: Makes the screen fade back in if it was faded out previously. Takes the same arguments as fadeOut()
.
showShop()
: Shows a miniature shop UI saying how much money and space you have.
hideShop()
: Hides the shop UI if it was shown previously.
Battle
getCharacter(id)
: Returns either a PartyBattler or an EnemyBattler with the specified ID.
getEnemies(id)
: Returns a table of all EnemyBattlers that match the specified ID.
getUser()
: Returns the user of the current action, if one is being performed.
getTarget()
: Returns the target of the current action, if one is being performed.
resetSprites()
: Resets the sprites of all party members and enemies.
setSprite(chara, sprite, speed)
: Sets the character's sprite to the specified path. chara
is either a string referring to a party member or enemy ID, or a PartyBattler or EnemyBattler instance.
setAnimation(chara, anim)
: Sets the battler's sprite to the specified animation (see setAnimation()
for sprites for detail about the animation argument). Returns a function that waits until the animation is finished, if it doesn't loop.
moveTo(battler, x, y, speed)
: Moves the battler to the specified position at a specific speed. chara
is either a string referring to a party member or enemy ID, or a Battler instance, x
and y
are coordinates relative to the topleft of the screen, and speed
is how fast the battler should move. Returns a function that waits until the battler reaches their intended position.
slideTo(obj, x, y, time, ease)
: Moves the object to the specified position over a period of time. x
and y
are coordinates relative to the topleft of the screen, time
is a number defining the amount of time the movement will take, and ease
is an optional string defining the ease type to use for the movement. Returns a function that waits until the object reaches its intended position.
shakeCharacter(chara, x, y)
: Shakes the battler. Returns a function that waits until the character stops shaking.
shakeCamera(shake)
: Shakes the camera. Returns a function that waits until the camera stops shaking.
setSpeaker(actor)
: Sets the specified actor to be the current speaker, used for textboxes (not for enemy dialogue).
text(text, portrait, actor, options)
: Creates a textbox, and automatically pauses the cutscene until the text is advanced. Optionally, portrait
refers to the sprite used for the textbox, actor
refers to the actor that is speaking, and options
is a table of extra information the textbox uses. options
can contain the following fields:
wait
: If false, the cutscene will not automatically wait, and instead return both a function that waits until the textbox is advanced, and the Textbox instance used.advance
: If false, the player will be unable to advance the textbox themself.auto
: If true, the textbox will automatically advance when it finishes.skip
: If false, the player will be unable to skip the textbox.font
: The font for the text to use.reactions
: A table of tables, each containing data to spawn a smaller dialogue within the current one. Each table defines the actor and face sprite used, the x and y positions of the face, and the dialogue, in that order. x and y can be strings as well, referring to existing positions; x can beleft
,leftmid
,mid
,middle
,rightmid
, orright
, and y can betop
,mid
,middle
,bottommid
, andbottom
. Must be used in combination with areact
text command (see In-text Modifiers below for more detail).functions
: A table defining functions that can be called with thefunc
text command (see In-text Modifiers below for more detail). Each index defines the ID of a function, and the value for each index is a function that will receive arguments specified by the modifier.
choicer(choices, options)
: Creates a textbox with choices, and automatically waits until the player chooses. choices
is a table of strings, referring to each option available, and options
is a table of extra information, similar to text()
. Returns the numerical index of the choice that was chosen.
enemyText(enemies, text, options)
: Creates enemy dialogue, and automatically waits until the dialogue is advanced. enemies
is either a string referring to the ID of the EnemyBattlers to use, or an EnemyBattler instance or a table of instances referring to the enemies that should say the dialogue; text
is a string defining what should be said, and options
is a table of extra information the dialogue uses. options
can define the following fields:
x
,y
: The position of the textbox, relative to the enemy's position.right
: A boolean determining whether the textbox should appear to the right of the enemy, and have its point facing to the left.x
andy
will override the position, but not the point change.wait
: If false, the cutscene will not automatically wait, and instead return both a function that waits until the textbox is advanced, and the Textbox instance used.advance
: If false, the player will be unable to advance the textbox themself.auto
: If true, the textbox will automatically advance when it finishes.
fadeOut(speed, options)
: Makes the screen fade out to black. speed
is the time it will take to fade, and options
is a table of extra information for the fade. options
can define the following fields:
color
: A table of RGB of the color to fade to. Defaults to black.alpha
: The alpha to fade to. Defaults to 1 (full opacity).music
: If defined, the current music will fade out. If defined as true, it will make the music fade out at the same speed as the screen; if defined as a number, it will make the music fade out over the time specified by the number.
fadeIn(speed, options)
: Makes the screen fade back in if it was faded out previously. Takes the same arguments as fadeOut()
.
Starting Cutscenes
Cutscenes are started by calling specific functions from either Game.world
or Game.battle
, depending on the type of cutscene. The majority of the functions that start cutscenes will take the arguments group
, id
, and any number of arbitrary arguments after that (referred to as ...
). These arguments can be used in 3 different ways:
- If
group
refers to the file path of a file returning a single function, it will start that cutscene, andid
will be considered part of...
. - If
group
refers to the file path of a file returning a table of multiple functions, andid
refers to the ID of one of those functions, it will start the cutscene with that ID. - If
group
is a string containing the file path of a file and the ID of a function within that file, separated by a period (eg.cutscene_file.cutscene_id
), it will start the cutscene with that ID, andid
will be considered part of...
.
When starting a cutscene function, ...
will be passed into the function as extra arguments.
The following is a list of functions that will start cutscenes:
World:startCutscene(group, id, ...)
: Starts a cutscene relative to scripts/world/cutscenes
.
World:showText(text, after)
: Starts a cutscene that spawns textboxes. text
is either a string, or a table of strings, of the dialogue to show, and after
is an optional function that will be run after the cutscene if defined.
Battle:startCutscene(group, id, ...)
: Starts a cutscene relative to scripts/battle/cutscenes
.
Battle:startActCutscene(group, id, dont_finish)
: Starts a cutscene that will set the state to the next action when finished, passing in the current action user and target into the cutscene function. By default, dont_finish
is false, which will cause the current action to finish properly when the cutscene ends as well.
When starting a Battle cutscene, it will automatically call Battle:setState("CUTSCENE")
upon starting, and when the cutscene ends it will set the state to the correct next state or what the state was before, via cutscene:after()
. This causes the battle to temporarily pause the current state until the cutscene is finished. If you need to set the battle to a specific state once the cutscene is done, you'll need to call cutscene:after()
with a function that sets the battle state, and with replace
being true as to override the automatic state setting.
The Text Object
The global Text
object is used to render most text in Kristal, such as in dialogue or in menus. Text
can be created by calling Text(text, x, y, w, h, font, style)
, where text
is the string that the text should use, x
and y
are the coordinates of the topleft of the text, w
and h
are the width and height of the canvas the text is rendered to, font
is an optional string defining the path to the font, defaulting to main
if undefined, and style
is an optional string defining the starting style of the text, defaulting to none
if undefined (see In-text commands below for a list of styles available).
DialogueText
is a global extension of the Text object, used for dialogue boxes. It can be created with the same arguments as Text
. The main difference between DialogeText and Text is that Text displays the whole string immediately, while DialogueText types each character at a time.
When defining a string for text, you can add modifiers in the string to change aspects of the text partway through it. Commands are made with the format of [command:argument]
, where command
is the name of the modifier being used, and argument
can be data provided to the modifier. For example, the string "This text [color:red]is red"
will change the color of the text "is red". argument
can be either a single string, or a comma separated list of strings, eg. [command:arg1,arg2]
. For a list of all available modifiers, see In-text modifiers below.
Text is processed using something called "nodes" internally. Nodes are tables containing data about the text string. A node is made for each character in the string, defining type
as "character"
, and character
as whatever the character is. Additionally, a node is made for each command used in text, defining type
as "modifier"
, command
as the command used, and arguments
as a table of the arguments applied. This is helpful to know when overriding Mod:onTextSound()
, as that function is called for each node with the character
type, and it passes the node in as an argument.
When creating a Text or DialogueText object, there are many variables and functions available. All variables and functions available for Text are also available for DialogueText.
Text
font
: A string referring to the file path of the font being used.
font_size
: A number determining how large the text should be. nil
by default.
style
: A string referring to the current style being used.
canvas
: The canvas being used to draw the text.
timer
: A number that increases by 1 every frame at 30fps.
text
: The string that the text was given.
sprites
: A table of sprites spawned by the image
modifier (see Text modifiers below for more detail).
autowrap
: Whether the text should automatically create newlines for the provided string. Defaults to true.
draw_every_frame
: Whether the text should be drawn every frame, or if its canvas should be used instead. True if the text has a modifier that updates over time (such as when the text is shaking), but false otherwise for optimization purposes.
state
: A table of values that the text uses to determine what the text should look like at each character. Commands usually function by changing a variable in state
. The following is a list of values defined in state
:
color
: A table of 4 values representing RGBA.font
: A string referring to the file path of the font being used.font_size
: A number determining how large the text should be.nil
by default.style
: A string referring to the current style being used.current_x
,current_y
: Numbers referring to the position of the current character being rendered.typed_characters
: A number representing how many characters have been typed so far.typed_string
: A string representing the current string that has been typed so far.progress
: A number representing how many characters have been processed.current_node
: A number representing the index of the current node being processed.asterisk_mode
: Whether the text should automatically indent. Set to true if an asterisk is used as the first character in the text string.spacing
: A number representing the horizontal space between characters.shake
: Whether the text should be shaking.
resetState()
: Resets the text's state
to its default values.
setText(text)
: Calls resetState()
and sets the text's text
to the provided string.
getFont()
: Returns the Font used for the text, accounting for font_size
.
registerCommand(name, func)
: Creates a custom modifier that the text can use. name
is the name of the modifier, and func
is a function that takes the current Text object and the modifier node as arguments.
isTrue(text)
: Returns whether the specified string would be considered a true value. "true"
, "1"
, "yes"
, and "on"
(and uppercase varieties thereof) are all considered true values; everything else is false.
DialogueText
skip_speed
: Whether the text should be skipping.
state
: DialogueText's state
table, in addition to having all values defined in Text's state
, has some extra values defined:
typing
: Whether the text is currently typing characters.speed
: The speed at which characters type.waiting
: A number representing how long the text is waiting until it types the next character.skipping
: Whether the text should be skipping.typing_sound
: A string referring to the current sound being played for each character.noskip
: Whether the player should not be allowed to skip the text.
In-text modifiers
The following is a list of all modifiers available when defining text. Some of these commands function anywhere, while others only function within DialogueText.
Text
color
: Changes the color of the text. Accepts 3 types of arguments:
- A string representing a color name. Valid color names are
red
,blue
,yellow
,green
,white
,black
,purple
,maroon
,pink
, andlime
. reset
, which resets text color back to normal.#ffffff
or any hex code. The#
is optional.
style
: Changes the style of the text. The available styles are:
none
: Text with no special effects.menu
: Text with a black shadow effect.dark
: Text with a gradient shadow effect, and a gradient for its color if color is not white. Used for all cutscene text by default.dark_menu
: Text with a dark purple shadow effect.GONER
: Text with a glowy outline.
font
: The name of the font for the text to use, relative to assets/fonts
. Kristal implements the fonts main
, main_mono
, main_mono_big
, main_mono_small
, plain
, small
, smallnumbers
, bignumbers
, console
, and goldnumbers
. See [Fonts](Asset-Management#custom fonts) for more detail. If a second argument is defined, it will define the font size of the text.
shake
: Makes the text shake. The argument is the intensity of the shaking.
image
: Spawns a sprite at the position of the modifier. Takes up to 6 arguments: the sprite path of the image, relative to assets/sprites
; the x and y offset of the image in pixels (defaulting to 0); the x and y scale of the image (defaulting to 1); and the speed the sprite should play at if it's a series of images (defaulting to 1/15).
DialogueText
speed
: Affects how fast the text progresses. The argument is a multiplier to default speed ([speed:1]
resets the dialog's speed to normal).
instant
: Makes the textbox advance immediately. Takes no arguments.
stopinstant
: Stops the textbox from advancing immediately if instant
was called earlier. Takes no arguments.
wait
: Pauses the text progressing. The argument is the number of characters to wait; in other words, it pauses for as long as it would take to type x characters at the current speed.
voice
: Changes the voice sound used for the text. Accepts 3 types of arguments:
- A string representing the path to a sound effect.
none
, which makes the text not play any sound.reset
, which makes the text play the sound associated with its character.
react
: Adds a mini dialogue to the textbox. The argument is the index of which face to use when reactions
is defined for the text.
noskip
: Determines whether the player is allowed to skip the text. The argument refers to whether to enable or disable the command.
spacing
: Determines the spacing between letters for the text. The argument is the number of pixels between characters.
face
: Changes the current portrait sprite. Takes multiple arguments: the first argument is a string referring to the path to the new sprite, relative to the current folder being used, and the second and third arguments are optional numbers defining the pixel offset of the new sprite.
facec
: Same as face
, but the sprite path argument is relative to assets/sprites/face
instead of the current portrait folder.
func
: Calls a function. The first argument is the index of which function to call when functions
is defined for the text, and all arguments after that are strings that will be passed into the function.
emote
: Calls onEmote()
for the current shop. The argument is the string to pass into the function. Currently only available in shop dialogue.