Toribash
Original Post
Making your own tutorials with Toribash 5.4+
Starting with version 5.4, Toribash features a new way to create and run tutorials which doesn't require extensive Lua scripting knowledge.
This guide expands on how to create your own tutorials, what they can be used for and how to run them afterwards.

This guide has been updated as per Toribash 5.60 (build 230522) which brought several changes to how custom tutorials testing works compared to method described in the original guide.





New tutorial system basics

New system allows (relatively) simple creation of new tutorials / events which may feature replay cutscenes, load various mods, display messages and so on. You can see it in action by loading any tutorial or in-game event (e.g. Hole in the Wall).

Any tutorial consists of minimum 2 data files, one of which contains tutorial instructions and the other is a localization file for messages. Instructions are then loaded by tutorials manager class and run as an actual tutorial. This means that for simpler tutorials you won't need any Lua coding knowledge.

Tutorials consist of steps and use a specific set of instructions which are similar to Toribash chat commands or Toribash-specific Lua functions. All instructions can be roughly divided into two groups: those that act as conditions to pass to next step and those which don't (this is also expanded upon below). Once all requirements to end the step are met, current step is finished and the next one begins automatically.



Creating your first tutorial

Let's say we want to make a simple tutorial that plays 150 frames of a replay, then shows a message and then asks the player to move one of Tori's bodyparts.
To do that, we first create two data files which will be used for the tutorial. Say the tutorial is going to be called mytutorial1, this means we make two files named the following way:
  • mytutorial1.dat - this file will contain all tutorial instructions.
  • mytutorial1_english.txt - this file will contain all tutorial messages in English
One thing to keep in mind - your tutorial must have an English localization. You can add other localization files (and may define all the messages there), but tutorialname_english.txt file has to exist.

After these files are created, open .dat file with any text editor.

With the first step, we want to load a replay. We'll also hide hud and make sure current player's character is displayed on Tori spot:
STEP;
OPT hud 0;
LOADREPLAY mytutorial_replay.rpl;
LOADPLAYER 0 PLAYER;
Every step has to begin with STEP; instruction. After that, we use OPT instruction to set hud to 0, load our replay and load PLAYER (current user) on spot 0 (Tori). Note that LOADREPLAY doesn't automatically start the replay - it will be paused instantly after loading.

For second step, we play 150 frames of the replay:
STEP;
PLAYFRAMES 150;
This one is pretty obvious, PLAYFRAMES 150; instruction plays 150 frames and then pauses the replay.

Third step we display our message. There are two ways of showing messages to user: we can show a general "hint" message or make it look like that's some tutorial character speaking. For this one, we'll go with a character line:
STEP;
SHOWSAYMESSAGE;
SAY mtCharacter;
MESSAGE INTROMSG;
WAITBUTTON;
SHOWSAYMESSAGE; command triggers message box. You only need to run this before showing your first message to user - if we wanted to display another message instantly after this one, having this command among step instructions won't do anything.
SAY [characterName]; commands sets message author to display their name and head texture (if found in customs folder). Here's an example of how it looks.
After that, we set the message that's going to be shown to the user: MESSAGE [messageStringName];. Message string name should correspond to one of text strings from tutorial localization file - see more below.
Last command we add is WAITBUTTON; which pauses tutorial execution until user presses enter or clicks "Continue" button. This is optional, but giving user some time to make sure they've read the message is usually the way to go.

After the message is shown, we need to hide message box and enter edit mode to later wait for user to move a bodypart on their character's body:
STEP;
HIDESAYMESSAGE;

STEP;
EDITGAME;
OPT tooltip 1;
MOVEJOINT R_KNEE FORWARD;
With the first step, we hide say message box, simple.
After that, we enter edit game mode (as we previously were in replay mode), enable tooltip (optional) and set joint movement requirement with MOVEJOINT [jointName] [jointState]; command. This one specifically, would require the user to change their right knee's joint state to "Extending".

That's it, now we're finished with the .dat file. The only thing that remains now is to set the intro message in localization file. To do that, we put the following line in mytutorial_english.txt file:
INTROMSG	Hi, this is my first tutorial!
Pay attention to the fact that string name and the message must be separated by tab and not just any whitespace character.

And now the tutorial is ready to be run! You can read on how to run it below.



Data file syntax

Below you can see a complete list of all currently available commands as of Toribash 5.60.

Notice: all commands must be followed by semicolon (;)

Command arguments preceded with ? are optional.
Commands marked with * act as conditions to pass to next step.
Commands marked with * are optional conditions and require a proper condition to pass to next step to work correctly.


List of available commands






Using custom Lua functions

As the title suggests, you can use custom Lua code within your tutorials.
To do that, you first need to create a [mytutorialname].lua file in same location as other tutorial data files.
This file is loaded on tutorial launch; any functions you want to run with .dat file should be returned at the end of the file or put in a global functions table (legacy method):
lua code:
local function myFunction(viewElement, reqTable)
echo("Hello world")
end

return {
MyFunc = myFunction
}


All custom functions will always receive two arguments by default, viewElement and reqTable. You can safely ignore them in some cases, but they'll be of great use if you want to expand your tutorial gui or add custom step completion conditions.
  • First argument passed to the function is a UIElement object that exists while current step is active and is destroyed once it's over. You'd typically want to attach any custom UI elements to this object as it ensures they'll only exist during current step.
  • Second argument is a list of current step requirements (serialized as TutorialStepRequirement[] with EmmyLua annotations) to move on to the next step (or fall back). By adding elements to this list, you can add your own custom requirements or modify existing requirements and/or their completion states.

There are also two hook namespaces that may come in handy: tbTutorialsCustom and tbTutorialsCustomStatic.
First one is used for hooks that you only want to run while current step is active, second one will keep hooks running until tutorial ends.
Here's an example of tbTutorialsCustom usage to wait for player to press a specific key as it's used in Punching Tutorial:



Tutorials, UIElement, UIElement3D, Files, MoveMemory and Tooltip classes will be always available for your custom Lua code, but if you want to use functions from other Toribash classes or other Lua files make sure to include them separately to be sure they're available.

Tutorials class itself is defined in data/script/system/tutorial_manager.lua.
If you're looking for more examples of how custom Lua code can be used for tutorials or events, feel free to check existing game tutorials (data files are located in data/tutorials and custom Lua code for them is located in data/script/tutorial/data) or events (all files located in data/script/event/).



Running your tutorial

Alright, so you got your files in one place, now you only need to run it as an actual whole thing.
Your whole tutorial can be loaded with a single Lua call:
lua code:
Tutorials:loadTutorial(tutorialName, tutorialPath)


You can also download this script that will allow you to launch the tutorial with a custom name / path: runTutorial.lua
To use it, run /ls runTutorial.lua test mytutorials to load "test" tutorial from data/script/mytutorials folder. Alternatively, you can load the same tutorial by its absolute path by adding the ../ prefix to the path: /ls runTutorial.lua test ../data/script/mytutorials.
Last edited by sir; May 23, 2023 at 09:36 AM.
Sounds like a very cool feature, however I wonder if it will actually be used considering all the steps involved in creating one tutorial. Hopefully in the future we can have more automated and easier system.
Originally Posted by Smaguris View Post
Sounds like a very cool feature, however I wonder if it will actually be used considering all the steps involved in creating one tutorial. Hopefully in the future we can have more automated and easier system.

Next step is AI writing code on its own.

...but seriously, how can it get easier than this? In past you had to write a complete lua script on your own, now you can make a completely operational tutorial with cutscenes and other stuff without writing any single line of actual code.
I feel like the players that do not use forums will most likely stay unaware or uninterested in such feature. It also requires quite a few steps that I believe could be avoided.

Ideally it would be awesome to see this somehow integrated into the game itself, even if it's still just a text editor. For example, you go into "create tutorial" section, there you can "create new" (or "edit existing tutorial") and have an in-game text editor with all of the available commands displayed on the side or something.

artist's rendition



Then clicking a "create tutorial" button would automatically create the two required files, as well as import all the text into them. It could also give a shortcut to importing by suggesting to download the runTutorial.lua for easy import, or if the script is already available then simply import it straight away for a preview of the creation.

As a cherry on the top, a tutorial hub, kinda like replay sharing, would be amazing addition as that would actually make for great sharing platform, which would incentivise users to create tutorials in the first place.

Just to be clear: in no way am I saying that this new feature is bad or useless, I'm simply suggesting how to make it even more accessible and user-friendly.
Last edited by Smaguris; Jun 17, 2019 at 03:40 PM.
a GUI would be the way to go to make creating in-game tutorials a lot easier, i can't imagine there would be demand for it though

and if it is accessible to make it'll probably just be a lot of opener tutorials
If no one has done this. I will be the first.
-----
I'm not sure if I'm missing something obvious but how would you have a replay play endlessly until the user is ready to enter the edit mode.
-----
What do i do for grips?
MOVEJOINT R_GRIP Forward?
What do i do for chest as well?
MOVEJOINT CHEST Right/Left?
Last edited by footlox; Aug 21, 2019 at 03:52 PM. Reason: <24 hour edit/bump
Leader of the Spyder House
Toribash Martial Artists
See the OP for joint states, there's no right / left state (instead use FORWARD / BACK)
Grip requirements aren't present in current version of tutorials manager, but you can write a custom lua function to handle that and then call it when needed with CUSTOMFUNC.

I'm not sure if I'm missing something obvious but how would you have a replay play endlessly until the user is ready to enter the edit mode.

You'll also need a custom lua function for that. Quick example of what can be used:
lua code:
add_hook("draw2d", "tbTutorialsCustom", function()
local ws = get_world_state()
if (ws.match_frame >= ws.game_frame) then
-- TUTORIAL_LEAVEGAME controls leave_game hook behavior which is triggered on replay/fight end but is also used to exit tutorial ui on ESC press
TUTORIAL_LEAVEGAME = true
rewind_replay()
TUTORIAL_LEAVEGAME = false
return
end
end)
As a programmer, I can see how much work was involved into creating this.
Congratulations and hope many people will use this feature.
I will. I have a partial tutorial written but I broke my laptop so I can't really it test it until i get my new one.
Leader of the Spyder House
Toribash Martial Artists