GameOver¶
This is a terminal coroutine that will present the player with the game over screen and a prompt to reload, return to main menu or if allowed, retry or retry with the ability to manipulate the standard items and medals using a mini PauseMenu.
private IEnumerator GameOver(bool skipsetup)
Parameters¶
skipsetup: If true, it will skip some setup logic at the start and only show the prompt immediately. This is meant only to be used recursively in an edge case where reloading the save file failed which lets the player remedy the problem before letting GameOver try again, but with less setups. This should NEVER be called with the value true for the first time because it will prevent to change to a terminal flow
Procedure¶
alreadyendingis set to true. This prevents AddExperience or EventDialogue 19 (ThePitcherenemy spit out event) from switching to a terminal flow- ItemList's
listredirectis set to -1 (this workarounds a potential inlist issue that can happen as a result of the SetText call later) - The SetText string is prepared and it starts with
|boxstyle,-1|which renders without a dialogue box. This string will get appended when needed later
Setup¶
This entire section is skipped if skipsetup is true.
- All
smallexporbsandbigexporbsare destroyed actionandcancelupdateare set to true changing to a terminal flow- RefreshEnemyHP is called
- SetFlags is called which sets all flags and flagvar to the ones from the StartupData of the
sdata - instance.
hudcooldownis set to -1 which hides the HP HUD elements - FadeMusic is called with a speed of 0.035
- A RoundTransition is played via PlayTransition to pure black with a speed of 0.05 and a data of -10 (which is the sortingOrder)
- A frame is yielded
- instance.
transitionobj[0]z local position is set to 15.0 and its SpriteRenderer's sortingOrder is set to -100 - 2.0 seconds are yielded
- The
cursoris destroyed if it existed - If the
GameOversound isn't playing, it is played (asGameover, but it works still) and the audiosource's volume is set to MainManager.musicvolumewhich is needed because it is considered a sound instead of a music - The SetText string gets the following ammended to it:
|boxstyle,-1||center||line||line||line||line||line||halfline||spd,0||color,4||sort,10||fadeletter|followed bymenutext[146](the game over text shown at the top) followed by|fwait,4.5|. This is basically the game over text positioned a bit down using empty lines and fading in for 4.5 seconds
SetText call¶
The following and any further section happens regardless of skipsetup.
actiontextandhexpcounterare destroyed if they exist- The SetText string gets its final append and it depends on the value of
canflee(meaning the battle was escapable). To note,menutext[78]only contains|end|because these prompt options are blanks: they don't cause SetText to continue since they will be handled after the call: - The SetText call happens in dialogue mode using the final string generated and the following properties:
- fonttype of
BubblegumSans - linebreak of
messagebreak - No tidimensional
- position of MainManager.
bubblepos(normally (0.0, 4.15.0, 10.0)) - No cameraoffset
- size of Vector2.one
- No parent
- No caller
- fonttype of
Broken failsafe logic¶
This is where a very broken failsafe logic occurs. See the note block below for details on why this logic should never happen.
From there, GameOver will yield all frames for a maximum of 330.0 frames until instance.promptbox exists which is when the prompt appears. This is tracked with a local frame countdown decremented by MainManager.framestep followed by a frame yield on each iteration. If the countdown reaches 0.0 before promptbox exists:
gameoveris set to a new GameOver call with skipsetup- A yield break happens which abruply stops this coroutine
NOTE: This failsafe was supposed to be a workaround to a previous inlist issue, but this did not worked because crucically, it breaks the dialogue mode rule since the message lock will still be grabbed if this failsafe triggers. This means the second GameOver call will allow SetText to process a dialogue mode call WHILE ONE IS ONGOING! This is extremely dangerous because it will lead to 2 SetText calls fighting for each other or even allow player control during a dialogue mode call because one of the prompt option reloads a save. This logic should NEVER trigger under any circumstances otherwise, it will break SetText and general game flow! The original inlist issue has been sucessfully workarounded by setting MainManager.
listredirectto -1 earlier so it provides no benefit.
Proper message lock wait¶
After avoiding the broken failsafe (which happens due to instance.promptbox existing after 4.5 seconds instead of 5.5 seconds) instance.promptbox local z position is set to 10.0.
This is followed by all frames being yielded until the message lock gets released. This is a proper and safe wait for the dialogue mode call to finish unlike the broken failsafe above.
Prompt option handling¶
The GameOver (as Gameover but it works anyway) sound is stopped with a speed of 0.002.
From there, the specific prompt options are handled by checking canflee and instance.option.
If you can flee, there's 2 prompt options:
- 0: Reload save
- 1: Return to main menu (this will reset the whole game and go back to the main menu)
If you can't flee, there's 4 prompt options (2 are common with the can flee case):
- 0: Retry
- 1: Change loadout and retry (opens a pause menu allowing to manipulate standard items and medals before retrying)
- 2: Reload save
- 3: Return to main menu (this will reset the whole game and go back to the main menu)
The following details what each option's handling does. No matter which one is handled, a frame is yielded at the very end after the option handler is done.
Retry¶
This only calls Retry without skipdata.
Change loadout and retry¶
- ReloadInitialData is called which does the following (mostly loads from the StartUpData):
- ApplyBadges is called
- ApplyStatBonus is called
- instance.
maxtpis set tosdata.maxtp - instance.
tpis set tosdata.tpclamped from 0 to instance.maxtp - For each player party member:
atkis set to the matchingsdata.atkdefis set to the matchingsdata.defhpis set to the matchingsdata.hpclamped from 0 to the player party member'smaxhplockitemsis set to the matchingsdata.partyitemuse
- instance.
items[0](standard items) is set tosdata.items - instance.
items[1](key items) is set tosdata.keyitem
- instance.
inbattleis set to false (this is only temporary, but needed to have the correct UI naviguation logic to use the PauseMenu) - MainManager.
pausemenuis set to a new GameObject namedPauseMenuwith a PauseMenu component added to it - A frame is yielded
- ApplyBadges is called
- All frames are yielded while
pausemenuexists - Retry with skipdata is called
Reload save¶
There is a special failsafe that occurs if the existing save file no longer exists for some reasons. Here is what happens in that case:
- A frame is yielded
- A new SetText call happens in dialogue mode with the text being
|boxstyle,4||center||halfline||spd,0|followed bymenutext[145]which is an error message informing the player of the problem. The call also has these properties:- fonttype of
BubblegumSans - linebreak of
messagebreak - No tidimensional
- position of Vector3.zero
- No cameraoffset
- size of Vector2.one
- No parent
- No caller
- fonttype of
- All frames are yielded while the message lock is grabbed. This allows the player to possibly remedy the problem by moving the save file at the correct location or to load the backup one. Since no end commands was processed here, there will be a
waitinputat the end allowing this failsafe to be remediable gameoveris set to a new GameOver call with skipsetup. This is safe unlike the failsafe because in this case, there are no SetText call running anymore so this will simply present the same prompt and the player is able to try the reload option again. Since this GameOver call finishes shortly after, it essentially transferts complete control to the new one and it allows this cycle to repeat over and over
If the save does exist, the following is done instead:
- 0.5 seconds are yielded
- MainManager.ReloadSave is called which does the following:
- The
CrowdChattersound is stopped - FadeMusic is called with a speed of 0.1
- All coroutines belonging to MainManager.
battleare stopped andbattlemapis destroyed - All coroutines belonging to MainManager.
events(the EventControl) are stopped - All player party member's
entityare destroyed - RenderSettings.skybox is set to null
- MainManager.
mapis destroyed - Event 22 is started via
eventswithout a caller (this is the save loading event)
- The
- instance.
inbattleis set to false - We enter a
minipause pauseis set to false- This BattleControl is destroyed
Return to main menu¶
- The
CrowdChattersound is stopped - 0.5 seconds are yielded
- SceneManager.LoadScene(0) is called which resets the entire game