-
Notifications
You must be signed in to change notification settings - Fork 1
Chapter Scripting
Note
Initially, this page will only go over the template.lua file for what the very basics of a chapter script looks like. Later, there will be specific examples of how to do specific things within your custom chapter scripts.
Important
This specific guide will assume you have already dumped your game and have access to the common.txt lua file used for chapter scripting, found in Switch\fe_assets_scripts
So you want to edit a chapter script, or even make your own custom chapter? Then it's important to understand what each function in a chapter script does and how it works. Here, I'll be going step by step into each required function for a chapter script, and what they basically do. Later, there will be more specific and involved examples, but for now we'll just be going over the bare minimum.
Look at this document & the pinned messages of the old server & active server to learn more.
At the start of every chapter script, you'll find a section for includes and shortcuts/variables. Most chapter scripts will also do the same for its chapter specific variables, but this example just has an Include and a PID variable. I'll likely refer to these variables as shortcuts because its good to think of them like that. While you could type out "PID_リュール" each time you want to refer to Alear, it's easier to just shortcut it out to be something like g_pid_alear.
Include("Common") -- Include the common.txt referenced prior
g_pid_alear = "PID_リュール" -- Alear PID variableNote that you do not have to follow the naming scheme of g_pid_unit - you can use whatever you want. I do recommend using something like g_pid_ though, as it helps keep things organized.
Also note the Include("Common") at the start. This includes the common.txt I mentioned earlier, which has a lot of useful functions that you can use in your chapter script. You can also make your own Lua file for your own new functions you want to use across multiple chapters, in which case you'd just do Include("YourFileName"). This is, of course, assuming your file has been added correctly in the scripts folder of your Cobalt mod.
The first thing your script needs is a Startup function. Here's the example we're using in the template file:
function Startup()
Log("Startup");
-- Set Variables/Flags here
-- VariableSet(var, value)
-- WinRule
WinRuleSetDestroyBoss( true ) -- Defeat Boss True/False
WinRuleSetMID("MID_RULE_X000_WIN") -- Message to be displayed as the Win Rule in game (Defeat some boss, etc)
LoseRuleSetMID( "MID_RULE_COMMON_LOSE" ) -- Message to be displayed as the Lose Rule in game (Alear dies, etc)
FlagReg() -- The function where all of your flags/vars will be entered
EventReg() -- The function where all of your events/functions will be entered
endEverything is fairly self explanatory, and if not, the comments in the code should help you understand each part. FlagReg() and EventReg() are both defined below this function, and are the next parts of this guide.
The one thing to note is VariableSet, which I think is mostly used for setting specific chapter rules, like if you can use the convoy or not. These variables are in Japanese, and are undocumented at this time.
The next part of a chapter script registers the flags & variables that will be used in your script, as well setting their initial values.
function FlagReg()
-- VariableEntry(var/flag, value)
-- Below this are examples added from my own custom chapter, and will not be present in the template file provided in this guide
VariableEntry(g_var_bridge_1, 0)
VariableEntry(g_var_bridge_2, 0)
VariableEntry(g_alaina_vil_1, 0)
VariableEntry(g_alaina_vil_2, 0)
VariableEntry(g_key_house1destroy, 0)
VariableEntry(g_key_house2destroy, 0)
endAs you may have noticed, all of my variables/flags here start with g_something, just like the Alear variable defined above. If you want to use new variables/flags just for your chapter, you'd define them underneath the Include, like the Alear one, in the same way. Then, you can use them with VariableEntry to make them work in your chapter. I'm fairly certain it is required you register them with VariableEntry in this function, so make sure you do that!
function EventReg()
-- EventEntryTurn(func, startTurn, endTurn, Force, optionalCondition, ...)
-- Below this are examples added from my own custom chapter, and will not be present in the template file provided in this guide
EventEntryTurn(AlainaJoin, 1, 1, FORCE_PLAYER) -- The function `AlainaJoin` will play from turn 1 to turn 1 (so just turn 1), before the player phase starts. (FORCE_PLAYER)
-- Talks
EventEntryTalk(AlainaAlear, alear, FORCE_PLAYER, alaina, FORCE_PLAYER, true, "VAR_ALAINA_ALEAR") -- The function `AlainaAlear` will play when Alear, who is on the players team, talks to Alaina, who is on the players team. This will not happen if "VAR_ALAINA_ALEAR" is `true.`
EventEntryTalk(JasperAlear, alear, FORCE_PLAYER, jasper, FORCE_PLAYER, true, "VAR_JASPER_ALEAR") -- Same as above
--Reinforcements
EventEntryTurn(Reinforcements, -1, -1, FORCE_PLAYER) -- The function `Reinforcements` will play starting at turn 0 (-1), and go on forever (-1), before player phase starts. `MapGetTurn()` is used in the `Reinforcements` function to do reinforcements spawning based on turn #.
EventEntryDie(AlainaDie, "PID_Alaina", FORCE_PLAYER, condition_true) -- The function `AlainaDie` will play when `"PID_Alaina"`, who is on the player's team, dies. `condition_true` is a function in the `common.txt` that just returns `true`.
EventEntryBattleAfter(FirstDie, cutscene_guy, FORCE_ENEMY, "", FORCE_PLAYER, true, EnemyFirstDeathCondition) -- The function `FirstDie` will play after a battle with `cutscene_guy`, who is on the enemy's team. The next `PID` is left blank, as we still need to get to the condition which always comes after the 2nd `PID` in case you want this post-battle event to only play when specific units fight each other. `EnemyFirstDeathCondition` is a function that returns `true`/`false` depending on certain conditions for if this event should play or not.
endfunction Opening() -- Plays on Chapter Opening
Log("Opening");
-- PuppetDemo("X000, "MID_OP1")
-- Below this are examples added from my own custom chapter, and will not be present in the template file provided in this guide
PuppetDemo("X001", "MID_OP_ALAINA") -- msbt, message id
PuppetDemo("X001", "MID_OP2_ALAINA")
Log("Opening Finished")
endThis function is for playing the opening cutscenes before the map has loaded. For information on how to make custom cutscenes, please see the page for puppet files.
MapOpening() are the events/cutscenes that play on the map itself, before the prep screen or chapter start depending on the type of chapter.
function MapOpening() -- Plays on loading/showing the map prior to chapter start
Log("MapOpening"); -- Will print out to terminal if using Cobalt/Ryujinx
-- Your opening event here...
CursorSetPos(5, 5)
CursorSetDistanceMode(CURSOR_DISTANCE_NEAR)
MapCameraWait()
Dispos("DispoGroup", DISPOS_FLAG_FOCUS) -- `Dispos` is for loading units. This is the same as other FE games, so if you have modded other FE games you should be familiar with it.
Yield()
WaitTime(1.0) -- A function in `common.txt` for waiting. It's not exactly seconds, look at the function if you want more specifics.
CursorAnimeCreate_FromPid("PID_M000_リュール") -- Animates/focuses the cursor on the specified unit.
WinRule() -- Displays the chapters winrule, which is defined in `Startup()`
CursorAnimeDelete()
endEverything above is fairly self explanatory. You can do anything you need to here, whether it's a full cutscene or just preparing/loading the chapter map as you see fit. For now, this just sets the cursor's position, spawns in a dispo group, and displays the chapter's win/loss conditions.
And that's it for all the startup/opening functions! From here, you'd define any new functions your chapter needs that you need for stuff like conditions and events, like what you saw in the EventReg section.
The same as MapOpening(), but after the win condition has been met and the chapter is over.
function MapEnding()
Log("MapEnding")
if VariableGet( g_key_turn2event ) == 0 then
MapHistoryRewindEnable()
end
endThis specific example is from Chapter 4. It's for enabling the Draconic Time Crystal, I believe.
The same as Opening(), but after the chapter is over and MapEnding() has finished. These are the post chapter cutscenes, which are handled by the previously mentioned puppet files.
function Ending()
Log("Ending")
PuppetDemo("M003", "MID_ED1")
Movie("Scene30")
SkipEscape()
FadeInAndWait(FADE_FAST)
Movie("S09")
SkipEscape()
FadeOutAndWait(FADE_FAST)
Movie("Scene06")
SkipEscape()
endThis specific example is from Chapter 3. It plays a cutscene, and then an animated movie/cutscene.
This is the last required function in a chapter script, and plays whatever you want when you gameover. It goes almost entirely unused, except for some specific instances in important story chapters.
function GameOver()
Log("GameOver")
Movie("S21")
SkipEscape()
VariableSet(g_key_M026_gameover, 1)
endThis example is from the final chapter in the game, for playing the bad ending where you lose.
Lythos, the Engage modding Wiki • Resources • Getting Started • Cobalt Wiki * Discord Server