Cutscenes
Cutscenes will be a range of no interaction to very limited interaction. E.g. walking to move the plot forward.
For now, there is only one "placeholder" generic cutscene scene so that I could implement Quest 005 that required it. It plays a simple "loading bar" animation and then, if the current active quest is completed, it will call its respective Quest Announcement.
As a generic placeholder, it should work with whatever is the current active quest.
Goals
The goal of the Cutscenes in this game are primarily used for storytelling and narrative progression. They provide a cinematic means to convey the game's plot, introduce new characters, and establish the setting and context of the game's world. Through cutscenes, we can create emotional impact and deepen the player's immersion in the story. They also serve to reward players, marking the completion of key objectives or levels. Additionally, cutscenes can be used to provide necessary exposition or tutorial information in a more engaging way than simple text or dialogue boxes.
How it works
The placeholder scene
You can find the placeholder scene at res://src/Part_PlaceholderQuestCutscene.tscn
. It's script is right beside it and will work automatically doing the following steps:
- It will connect to the Event
screen_change_fade_out_finished
, and play themain
animation on its callback. - The
AnimationPlayer
is configured to automatically transition from itsmain
animation tofade_out
animation. - The
animation_finished
signal from theAnimationPlayer
node is connected to the script and oncefade_out
finishes, it will try to complete the current active quest, which should show its quest announcement, or an error if there is no active quest- In the case that there was an error, it will stop here and be locked on a black screen
- Once you "accept" the quest completed announcement, it will proceed to the "Next Day"
How the Quest cutscene is triggered
Quest 005 is the only one we have a cutscene so far, so understanding what it asked will help to understand the choices made for this implementation. On Quest 005 description, once we return to Campsite, we should find it empty and a cutscene should start.
But LinearWorld only cares about moving the player between pre-existing levels, so it would just move the player to normal Campsite. From there we would either have to have custom logic on the Campsite scene, to identify that this is Quest 005 final step and change itself, or have some way for Quest 005 to trigger changes on it.
If we start to have more cutscene and Level0_0 scene has to know about all of them, things could get messy. So it would be easier to transition to another "Part_" scene entirely, where we can have a customized Level0_0 and just animate or script the cutscene there the way we want it, but then how do we make LinearWorld understand that this particular transition to Level0_0 should be different?
For that 3 new FuncRef
properties were added to RuntimeData.tres
(FuncRef
are objects that hold a reference to another object and a function name so that it makes it easier to call "remote" functions):
funcref_custom_game_screen_condition
-LinearWorld
will use it when changing levels/locations to check if there is a special condition activatedfuncref_custom_game_screen_play
- if there is any special condition and it returns true,LinearWorld
will use thisFuncRef
instead of its normal logic.funcref_custom_game_screen_finished
- This can be called by the cutscene or custom screen when it finished what it needs to do.
This way, the logic for the custom screen/cutscene/special circumstance can stay encapsulated wherever it makes more sense and in whatever script should be responsible for it. In Quest 005 case, it's in res://src/Quests/Resources/Torion/custom_step_logic/005_step_02_trigger_cutscene.gd
. This step will be responsible for injecting the relevant funcrefs in RuntimeData.tres
and once the player triggers the condition by trying to go back to Campsite, its funcrefs will take over and control the game to go to the correct cutscene.
This approach allows for the "entity" that is responsible for the "cutscene" to handle everything related to it directly, with a "simple" and expect api. Not all of the funcrefs are needed, and outside of triggers that are "enter level/location X" we can just directly trigger a screen change with Events, but for anything that needs to be triggered on level/location changes, these three properties can be used to highjack control from it.
There are also two helper methods on RuntimeData
:
should_use_custom_game_screen_transition()
- will do all the relevant checks to see if funcrefs are valid and special condition is passed.custom_game_screen_completed()
- will check iffuncref_custom_game_screen_finished
is valid and if it is, call it.
With what script it communicates
RuntimeData.gd
- So that it can inject funcrefs in it where LinearWorld can access themLinearWorld.gd
- Since it's responsible for navigating between levels/locations and the trigger for the cutscene is "navigating to level/location X"- Specific Quest and/or Cutscene scripts, as needed.