In this tutorial I will show you how to initiate an extra scene for your player to do off the main story path.
First things first, you need find a location in the game you want to have your scene initiated. While you can virtually initiate a scene at nearly any point,
it's wise to be caution as adding scenes during the middle of the main story can cause bugs and glitches if not carefully applied and tested.
In this scene, we will initiate our scene during Disc 4. Since most of the main storyline is completed, we'll have less road blocks and limitations at this time in the game.
Next is selecting a theme for the scene; some dialogue, a scenario to take place, any battles to initiate and rewards (if any) to be received par completing the quest.
You will be using a series of General Variables unused by the game. These variables are the base foundation of all your scenes as these are and can be used to determine your scene as
active,
inactive, or
conditional.
(Conditional: having the player needed do one task to the next in order to unlock a part or whole of your extra scene/quest).
In this example we'll use the extra scene from Final Fantasy IX-2 ~ Lavos Hunt. It's a intermediate scene not too complex but not too simple either.
I. Getting StartedIn field:
Alexandria/Dock (Field ID: 2458), we need to firstly initiate some character that will pose as our scene starter (in this case, it will be
Steiner):
- 1. In Hades Workshop, navigate to the Fields Tab and scroll down to Field Alexandria/Dock (Field ID: 2458)
- 1a. Select "Edit Entries"
- 1b. In the Entries Menu, scroll down and select "Steiner" and "Freya". *Because this field does not natively have Steiner or Freya initiated (par vanilla), we need to add them in manually)
- 1c. Select "Edit Script"
- 1d. In the Edit Script Window, under the "Functions" section, right-click and select "Add"
- 1e. In the Properties Menu, for "Entry" select "Steiner"
- 1f. For Entry Type, set the value "2". "2" means "object with model", standard for all 3D models initiated
- 1g. For "Function Type" set the value "0". "0" means "main function". Every 3d model has an _Init function, which is used to create the 3D model in scene
- 1h. Select "Parse", then "Ok".
*Note: When building scripts ALWAYS select "Parse" then "Ok". You will get a warning for any non-parsed scripts after select Ok.Now we have a
"Steiner_Init" function.
Add the following in the script space:
Function Steiner_Init
SetModel( 5489, 104 )
CreateObject( -222, -2015 )
TurnInstant( 152 )
SetStandAnimation( 2001 )
SetWalkAnimation( 1996 )
SetRunAnimation( 2005 )
SetLeftAnimation( 1986 )
SetRightAnimation( 2010 )
SetObjectLogicalSize( 30, 35, 50 )
SetAnimationStandSpeed( 14, 16, 18, 20 )
SetHeadAngle( 97, 32 )
EnableHeadFocus( 0 )
return
The following arguments are described in the
yellow help box to in right corner of the Edit Script Window provided by Tirlititi.Now with this Function, Steiner is ready to be initiated in game.
Let's do the same for Freya:
(Repeat steps 1d. through 1h.)Function Freya_Init
SetModel( 192, 94 )
CreateObject( 186, -2179 )
TurnInstant( 160 )
SetStandAnimation( 2556 )
SetWalkAnimation( 2553 )
SetRunAnimation( 2558 )
SetLeftAnimation( 2555 )
SetRightAnimation( 2551 )
SetObjectLogicalSize( 26, 34, 48 )
SetAnimationStandSpeed( 14, 16, 18, 20 )
SetHeadAngle( 105, 53 )
SetPathing( 1 )
EnableHeadFocus( 0 )
return
Now we are ready to initiate Steiner in scene.
II. Function Main_InitAt the bottom of the script of
Function Main_Init add the following:
if ( VARL_GenBool_8038 == 1 ) {
InitObject( 20, 0 )
}
if ( VARL_GenBool_8040 == 1 ) {
TerminateEntry( 20 )
}
if ( VARL_GenBool_8041 == 1 ) {
InitObject( 21, 0 )
}
if ( VARL_GenBool_8043 == 1 ) {
TerminateEntry( 21 )
}
return
The following functions are conditional for how this scene will play out for the player.
The first function: if ( VARL_GenBool_8038 == 1 ) {
InitObject( 20, 0 )
}
Will initiate Steiner when the player reaches Alexandria/Dock.Second function: if ( VARL_GenBool_8040 == 1 ) {
TerminateEntry( 20 )
}
Once the player speaks with Steiner, the script will set the Variable above with value "1", indicating the extra scene has begun, Steiner has left the Dock, and upon returning to the Dock, Steiner will be gone.Third function: if ( VARL_GenBool_8041 == 1 ) {
InitObject( 21, 0 )
}
Once the extra scene's hunt battle is completed, the variable above is set to value
"1", to indicate scene completed and upon the player's return to Alexandria/Dock, Freya will be initiated in scene to give the player their reward and end the scene.
Last function: if ( VARL_GenBool_8043 == 1 ) {
TerminateEntry( 21 )
}
return
Terminates the entry of Freya's model once the player as obtained their reward, the variable value is set to
"1" indicating the scene is now completed, no other actions needed.
Script should end with a
return.
III. Building the heart of the SceneNow they we've initiated Steiner and Freya in the field, we can proceed building the heart of scene with dialogues, actions and battles.
- 3a. Navigate to Function Steiner_Init, right-click and click "Add"
- 3b. For "Entry" select "Steiner", "Entry Type", enter value "2", "Function Type", enter value "3". "3" means "running on speak button". This will give the function: "Function Steiner_SpeakBTN" Which is used for the player to speak to main characters and NPCs. Select Ok
- 3c. Navigate to Environment --> Texts. Scroll down to "Alexandria (Ruin)"
- 3d. In the text box, right-click and select "Add". This adds a new text space for entry. *Note, if you're building straight from vanilla files, or Alternate Fantasy, these new text ids should be the same for you
- 3e. Double click the newly created text space and enter the following in the "Edit Text" window
[STRT=15,4][STNR]
"Someone named [68C0D8][HSHD]Viera[C8C8C8][HSHD] was attacked in
[68C0D8][HSHD]Burmecia[C8C8C8][HSHD], yet their belongings forfeit.
I would have them returned."
*For each new text, add a new line.[STRT=140,4][PCHC=2,1][IMME][STNR]
"The creature was [68C0D8][HSHD]Lavos[C8C8C8][HSHD]. Will you slay it?"
[CHOO][MOVE=18,0]Accept
[MOVE=18,0]Decline
*Functions [CHOO][MOVE=0,0] allows the player to select an optional decision for the dialogue. (This setting within the field script functions).[STRT=0,0] Sets the length of the dialogue window. The first value sets the width of the dialogue window, (since the game calculates this on the float, you can set it as low as 15 or 10).
The second value sets the height of the dialogue window. This value is critical as the game does not set this on the float, and needs to be set accordingly or the dialogue window will not be long enough to fit all text in.
To determine the height of a dialogue window, count the number of lines of the entered text.e.g.[STRT=140,4][PCHC=2,1][IMME][STNR]
"The creature was [68C0D8][HSHD]Lavos[C8C8C8][HSHD]. Will you slay it?"
[CHOO][MOVE=18,0]Accept
[MOVE=18,0]Decline
This text is 4 lines long, so you enter
[STRT=140,4] second value is
"4".
*Function "[STNR]" is a character naming opcode which is used to enter the character's name in the dialogue set from the Naming Screen. If you enter in the character's vanilla names without the opcode, the character's name entered from the Naming Screen will not show.Here's all the 8 main character's opcodes:
[ZDNE] "Set for Zidane"
[DGGR] "Set for Dagger"
[VIVI] "Set for Vivi"
{STNR] "Set for Steiner"
[FRYA] 'Set for Freya"
[QUIN] "Set for Quina"
[EIKO] "Set for Eiko"
[AMRT] "Set for Amarant"
*Code: [68C0D8][HSHD][C8C8C8][HSHD] sets a text color. There are a few other codes for this within the game.Add the text for Alexandria (Ruin):[STRT=15,4][STNR]
"Someone named [68C0D8][HSHD]Viera[C8C8C8][HSHD] was attacked in
[68C0D8][HSHD]Burmecia[C8C8C8][HSHD], yet their belongings forfeit.
I would have them returned."
[STRT=140,4][PCHC=2,1][IMME][STNR]
"The creature was [68C0D8][HSHD]Lavos[C8C8C8][HSHD]. Will you slay it?"
[CHOO][MOVE=18,0]Accept
[MOVE=18,0]Decline
[STRT=15,5][STNR]
"I am glad to know there is
strength and honor even among
you. I will lend my arm in the hunt
of [68C0D8][HSHD]Lavos[C8C8C8][HSHD]."
[STRT=15,4][STNR]
"I shall await you in [68C0D8][HSHD]Burmecia[C8C8C8][HSHD] with
[68C0D8][HSHD][FRYA][C8C8C8][HSHD]. I do not think the creature
will have left."
[STRT=15,3]
[68C0D8][HSHD]Lavos[C8C8C8][HSHD][SPED=2]...[SPED=-1]
[C8B040][HSHD]The hunt begins![C8C8C8][HSHD]
[STRT=15,3][STNR]
"We are victorious. No more
shall that beast roam freely."
[STRT=15,6][FRYA]
"Thank you. I could not have
recovered past Viera's belongings
without your help. I was fortunate
to find such worthy aid. You have
my gratitude."
[STRT=15,5][FRYA]
"The world is a wonderful place,
filled with ideas as diverse as its
people. Such individuality was not
to be found on that steppe."
[STRT=15,2][STNR]
"I understand[SPED=2]...[SPED=-1]"
3. In function:
"Function Steiner_SpeakBTN" enter the following:
*Mind not my description messages after the "\\" while pasting in your scripts, Hades Workshop will ignore the trailing.Function Steiner_SpeakBTN
DisableMove( ) \\ Disables player movement.
DisableMenu( ) \\ Disable player accessing menus.
if ( VARL_GenBool_8039 == 0 ) {
TurnTowardObject( 19, 32 ) \\Turns the model to an object.
WindowSync( 1, 128, 277 ) \\ Function for adding dialogue.
set VARL_GenBool_8039 = 1
}
DisableMove( )
DisableMenu( )
WindowSync( 1, 128, 278 )
if ( GetDialogChoice == 0 ) {
set VARL_GenBool_8040 = 1 \\ set the variable with value "1" (to keep Steiner removed after accepting the hunt & initiating the follow up scene in Burmecia).
WindowSync( 1, 128, 279 )
WindowSync( 1, 128, 280 )
FadeFilter( 6, 16, 0, 74, 74, 74 ) \\ Set a fade effect.
RaiseWindows( ) \\ Used for showing text on screen without a diagloue bubble.
WindowAsync( 1, 16, 281 )
RunSoundCode3( 53248, 1350, 0, -128, 125 ) \\ Run a sound effect.
Wait( 70 ) \\ Wait some time (calculated in frames)
RunSoundCode3( 53248, 789, 0, -128, 125 )
Wait( 40 )
CloseWindow( 1 )
FadeFilter( 6, 16, VAR_GlobUInt8_17, 255, 255, 255 )
EnableMove( )
EnableMenu( )
Wait( 16 )
FadeFilter( 7, 16, VAR_GlobUInt8_17, 0, 0, 0 )
TerminateEntry( 255 ) \\ Terimante the current function entry.
} else {
WindowSync( 1, 128, 295 ) \\ Steiner's text: "I understand..."
TurnTowardObject( 10, 32 )
EnableMove( )
EnableMenu( )
Wait( 16 )
}
if ( GetDialogChoice == 0 ) {
FadeFilter( 7, 16, VAR_GlobUInt8_17, 0, 0, 0 )
} else {
TimedTurn( VAR_GlobUInt8_16, 16 )
WaitTurn( )
EnableMove( )
0x27( 255 )
EnableMenu( )
}
return
The } else { function is used in dialogue cases like these; when the player select yes - do one action, else do another action.IV. Adding Dialogue4. In function:
"Freya_SpeakBTN" enter the following:
Function Freya_SpeakBTN
DisableMove( )
DisableMenu( )
TurnTowardObject( 19, 32 )
WindowSync( 1, 128, 283 )
AddGil( 7000 )
RunSoundCode3( 53248, 108, 0, -128, 125 )
WindowSync( 1, 128, 284 )
AddItem( 38, 1 )
RunSoundCode3( 53248, 108, 0, -128, 125 )
WindowSync( 1, 128, 285 )
AddItem( 167, 1 )
RunSoundCode3( 53248, 108, 0, -128, 125 )
WindowSync( 1, 128, 286 )
AddItem( 225, 15 )
RunSoundCode3( 53248, 108, 0, -128, 125 )
WindowSync( 1, 128, 287 )
AddItem( 226, 7 )
RunSoundCode3( 53248, 108, 0, -128, 125 )
WindowSync( 1, 128, 288 )
AddItem( 227, 4 )
RunSoundCode3( 53248, 108, 0, -128, 125 )
WindowSync( 1, 128, 289 )
AddItem( 228, 2 )
RunSoundCode3( 53248, 108, 0, -128, 125 )
WindowSync( 1, 128, 290 )
AddItem( 229, 1 )
RunSoundCode3( 53248, 108, 0, -128, 125 )
WindowSync( 1, 128, 291 )
AddItem( 204, 1 )
RunSoundCode3( 53248, 108, 0, -128, 125 )
WindowSync( 1, 128, 292 )
AddItem( 222, 2 )
RunSoundCode3( 53248, 108, 0, -128, 125 )
WindowSync( 1, 128, 293 )
AddItem( 300, 1 )
RunSoundCode3( 53248, 3096, 0, -128, 125 )
WindowSync( 1, 128, 296 )
set VARL_GenBool_8043 = 1
WindowSync( 1, 128, 294 )
FadeFilter( 2, 12, 0, 255, 255, 255 )
EnableMove( )
EnableMenu( )
Wait( 16 )
FadeFilter( 2, 36, 0, 0, 0, 0 )
TerminateEntry( 255 )
return
Now we have our dialogue set and done for these field.
V. Executing the hunt5. Navigate to field:
"Burmecia/Suburb" (Field ID: 751)*repeat steps (Repeat steps 1b. through 1h.)5a. In the Edit Script Window,
Function Main_Init add the following at the end of the script:
if ( ( VARL_GenBool_8040 == 1 ) && ( IsInParty(3) && IsInParty(4) ) ) {
InitObject( 17, 0 )
InitObject( 18, 0 )
RunSoundCode( 0, 105 )
}
if ( VARL_GenBool_8042 == 1 ) {
TerminateEntry( 17 )
TerminateEntry( 18 )
}
if ( VARL_GenBool_8040 == 1 ) {
FadeFilter( 2, 24, 0, 2, 181, 225 )
}
if ( VARL_GenBool_8041 == 1 ) {
FadeFilter( 2, 24, 0, 0, 0, 0 )
RunSoundCode( 0, 68 )
}
Since our hunt requires Steiner and Freya to be in our party to proceed we need a conditional that reads:
If the hunt has been activated + Steiner and Freya is currently in the player's party; continue the quest hunt.Once these conditions lye true, Steiner and Freya will be initiated into the field scene.
if ( VARL_GenBool_8042 == 1 ) {
TerminateEntry( 17 )
TerminateEntry( 18 )
}
This condition is activated once the hunt battle is complete, to prevent Steiner and Freya from appear after the completed scene. if ( VARL_GenBool_8040 == 1 ) {
FadeFilter( 2, 24, 0, 2, 181, 225 )
}
This function enabled a fade effect for the presence of Lavos in the area. (It can be removed for preference). if ( VARL_GenBool_8041 == 1 ) {
FadeFilter( 2, 24, 0, 0, 0, 0 )
RunSoundCode( 0, 68 )
}
This function is conditional to remove the above fade effect once Lavos is defeated.5b. Navigate back to
Environments --> Text, scroll to
Burmecia and add the following text:
[STRT=15,2][STNR]
"Good. You are come."
[STRT=15,3][FRYA]
"[68C0D8][HSHD]Lavos[C8C8C8][HSHD] is a great creature
with massive scales. It will not be far. Come!"
[STRT=15,4][FRYA]
"We are victorious. I would reward
you for your courage. Visit me back
at Alexandria. I shall wait for you there."
5c. Add a
"SpeakBTN" function to
Freya_Init and add the following:
Function Freya_SpeakBTN
DisableMove( )
DisableMenu( )
TurnTowardObject( 16, 32 )
WindowSyncEx( 18, 1, 128, 338 )
WindowSync( 1, 128, 339 )
EnableMove( )
EnableMenu( )
RunScriptSync( 2, 17, 30 )
RunScriptSync( 2, 18, 31 )
return
5d. Navigate to field:
"Burmecia/Palace" (Field ID: 766)Under
Function Main_Init, add the follow at the end of the script:
if ( ( VARL_GenBool_8040 == 1 ) && ( IsInParty(3) && IsInParty(4) ) ) {
InitObject( 16, 0 )
InitObject( 18, 0 )
}
if ( VARL_GenBool_8042 == 1 ) {
TerminateEntry( 16 )
TerminateEntry( 18 )
}
if ( VARL_GenBool_8040 == 1 ) {
FadeFilter( 2, 24, 0, 2, 181, 225 )
}
if ( VARL_GenBool_8041 == 1 ) {
FadeFilter( 2, 24, 0, 0, 0, 0 )
}
The same functions as before.After adding Steiner & Freya Init functions, add a
SpeakBTN function to
Freya_Init and add the following:
Function Freya_SpeakBTN
DisableMove( )
DisableMenu( )
WindowSync( 1, 128, 339 )
Wait( 20 )
RunSoundCode3( 53248, 789, 0, -128, 125 )
Wait( 40 )
RunSoundCode( 0, 77 ) \\ Run a BGM code.
Battle( 1, 210 ) \\ Start a battle. (Battle ID: 210)
DisableMove( )
DisableMenu( )
set VARL_GenBool_8041 = 1
set VARL_GenBool_8042 = 1
RunSoundCode( 256, 77 )
WindowSync( 1, 128, 340 )
FadeFilter( 2, 12, 0, 255, 255, 255 )
Wait( 16 )
EnableMove( )
EnableMenu( )
RunSoundCode( 0, 68 )
FadeFilter( 2, 36, 0, 0, 0, 0 )
TerminateEntry( 18 )
TerminateEntry( 255 )
return
Upon initiating a battle in this field, we need to add Function Main_Reinit. This function is required for all battles in fields, without it, the player will be frozen in place and unable to move afterwards.Function Main_Reinit
set VAR_GlobBool_159 = 0
RunScriptAsync( 0, 250, 11 )
if ( VAR_GlobBool_155 == 1 ) {
ATE( 1 )
}
if ( VAR_GlobBool_158 == 0 ) {
0x27( 127 )
} else {
0x27( 255 )
}
Wait( 2 )
ShowTile( 5, 0 )
ShowTile( 6, 0 )
ShowTile( 7, 0 )
ShowTile( 8, 0 )
ShowTile( 9, 0 )
ShowTile( 10, 0 )
Wait( 2 )
if ( VAR_GenUInt8_13 == 9 ) {
SetTextVariable( 2, 0 )
WindowAsync( 6, 0, 62 )
RaiseWindows( )
WaitWindow( 6 )
set VAR_GenUInt8_13 = 0
}
if ( VAR_GenUInt8_14 == 9 ) {
SetTextVariable( 2, 1 )
WindowAsync( 6, 0, 62 )
RaiseWindows( )
WaitWindow( 6 )
set VAR_GenUInt8_14 = 0
}
set VAR_GlobBool_159 = 1
if ( VAR_GlobBool_158 == 1 ) {
set VAR_GlobBool_158 = 1
if ( VAR_GlobBool_159 == 1 ) {
if ( VAR_GlobBool_156 == 0 ) {
EnableMove( )
0x27( 255 )
if ( VAR_GlobBool_144 == 0 ) {
EnableMenu( )
}
}
}
}
set VAR_GlobUInt8_30 = 127
SetWeather( 24, 56 )
if ( VAR_GlobUInt8_17 == 255 ) {
set Op66(( GetData_12 - 160 ), ( GetData_13 - 112 ))
}
0xA9( 250 )
FadeFilter( 7, 16, VAR_GlobUInt8_17, 0, 0, 0 )
return
5f. Navigate back to field
Alexandria/Dock (Field ID: 2458)VI. Finalizing your Scene6. Add a
SpeakBTN function to
Freya_Init and add the following:
Function Freya_SpeakBTN
DisableMove( )
DisableMenu( )
TurnTowardObject( 19, 32 )
WindowSync( 1, 128, 283 )
AddGil( 7000 )
RunSoundCode3( 53248, 108, 0, -128, 125 )
WindowSync( 1, 128, 284 )
AddItem( 38, 1 )
RunSoundCode3( 53248, 108, 0, -128, 125 )
WindowSync( 1, 128, 285 )
AddItem( 167, 1 )
RunSoundCode3( 53248, 108, 0, -128, 125 )
WindowSync( 1, 128, 286 )
AddItem( 225, 15 )
RunSoundCode3( 53248, 108, 0, -128, 125 )
WindowSync( 1, 128, 287 )
AddItem( 226, 7 )
RunSoundCode3( 53248, 108, 0, -128, 125 )
WindowSync( 1, 128, 288 )
AddItem( 227, 4 )
RunSoundCode3( 53248, 108, 0, -128, 125 )
WindowSync( 1, 128, 289 )
AddItem( 228, 2 )
RunSoundCode3( 53248, 108, 0, -128, 125 )
WindowSync( 1, 128, 290 )
AddItem( 229, 1 )
RunSoundCode3( 53248, 108, 0, -128, 125 )
WindowSync( 1, 128, 291 )
AddItem( 204, 1 )
RunSoundCode3( 53248, 108, 0, -128, 125 )
WindowSync( 1, 128, 292 )
AddItem( 222, 2 )
RunSoundCode3( 53248, 108, 0, -128, 125 )
WindowSync( 1, 128, 293 )
AddItem( 300, 1 )
RunSoundCode3( 53248, 3096, 0, -128, 125 )
WindowSync( 1, 128, 296 )
set VARL_GenBool_8043 = 1
WindowSync( 1, 128, 294 )
FadeFilter( 2, 12, 0, 255, 255, 255 )
EnableMove( )
EnableMenu( )
Wait( 16 )
FadeFilter( 2, 36, 0, 0, 0, 0 )
TerminateEntry( 255 )
return
And that marks the end of your extra scene!
*If you want your scene to be repeatable, you can set your variable conditions back to value "0" somewhere and the process will begin again.You can see another example of extra scenes in action
here.