You're welcome, Gine
Update to v0.34b :
- Fixed the crash that occured sometimes when you are writing texts or when you use incomplete tags,
- Fixed a bug with the .hws saving of item texts, resulting in loss of data inside the .hws,
- Fixed a crash when editing the preferences (they are not useful for the Steam version yet however),
- Fixed various other minor bug,
- You can now add/remove script entries, thus NPC on the field.
When adding/removing entries, the script will be updated so that functions still refer to the right entries. If an entry is deleted but was still used in the script (if it was initialized in the "Main" function, for instance), the reference changes to the "Main" entry and a warning will be prompted.
So, how do you handle NPCs and the PC with this?A model on the field is linked to an entry. I will only discuss of the case when there is only 1 model per entry, but using the UID, one can have several models on the field handled by only one entry.
An entry linked to a model must be of type 2 and initialized with an "InitObject" call in the main function.
To create a new NPC (not for Beatrix, see below), you must create a new entry for it. In the field panel, choose "Edit Entries" and add a new one with the entry type 2. By default, the created entry will have the ID number 1 (and the entries that were already there are displaced except for the Main entry). Its ID is its position in the list.
Then, to create functions for this NPC, choose "Edit Script", right-click on the list in the left, then "Add", then choose the created entry and set the function type to a number depending on the function's purpose (let the mouse on the "Function Type" field to have a list of specially handled function types).
It can have several useful functions.
1) The Init function
This is the one defining the object's 3D model as well as its position on the field, animations and such... A standard Init function looks like this for an object's entry :
Function ManA_Init
set VAR_B10_0 = 58
set VAR_B10_4 = 65163
set VAR_B10_6 = 192
set VAR_B10_2 = 65518
SetModel( 111, 100 )
CreateObject( VAR_B10_0, VAR_B10_4 )
TurnInstant( VAR_B10_6 )
SetStandAnimation( 555 )
SetWalkAnimation( 599 )
SetRunAnimation( 598 )
SetLeftAnimation( 597 )
SetRightAnimation( 601 )
SetObjectLogicalSize( 20, 20, 30 )
SetAnimationStandSpeed( 14, 16, 18, 20 )
SetHeadAngle( 64, 1 )
EnableHeadFocus( 0 )
SetObjectLogicalSize( 1, 40, 150 )
return
The first numbers are the object's initial position (the coordinates X, Y, the facing angle and then the Z coordinate respectively). For the "SetModel" code, a list of known model IDs is available ; note that the model gives its name to the entry, so the model 111 is "ManA".
Unlike the PSX version, the Steam version can use any model any time. The animations, however, must match with the model. As there is no list of animations yet (if you want to help doing one, that would be cool ^^), you'll have to grab the animation ID from other field scripts, where you know that the animations you seek are used.
It seems that there's no need to add the animation in the "Preload" list of the field. I don't actually know that list's purpose then.
2) The SpeakBTN function
This one is executed when the player approches the model and speaks to him. A standard SpeakBTN function looks like this :
Function ManA_SpeakBTN
ifnot ( IsMovementEnabled ) {
return
}
set VAR_A6_158 = 0
if ( VAR_A6_159 == 1 ) {
DisableMove( )
if ( VAR_A6_144 == 0 ) {
DisableMenu( )
} else {
Wait( 1 )
}
}
0x27( 127 )
TurnTowardObject( 250, 32 )
WaitTurn( )
WindowSync( 0, 128, 199 )
set VAR_A6_158 = 1
if ( VAR_A6_159 == 1 ) {
if ( VAR_A6_156 == 0 ) {
EnableMove( )
0x27( 255 )
if ( VAR_A6_144 == 0 ) {
EnableMenu( )
}
}
}
return
If the player is in a cutscene, we don't want him to be able to speak with the NPC that he's facing, thus the "IsMovementEnabled" check. The following 10 lines are standard for everytime the game removes the control from the player, and the last ones are their counterpart to give it back. The "TurnTowardObject( 250, 32 )" forces the NPC to face the player's character, and the "WindowSync" displays a bubble of dialog.
The same kind of function can be made with the CardBTN function but using a "TetraMaster" line of code instead of the "WindowSync" line. For chests, the SpeakBTN function is perfect to allow the player opening the chest and taking the item inside.
3) The other functions
The other functions are used for the rest of the NPC's behavior. The Loop function often ends by the two following lines.
Wait(1)
loop
Which means that the function is executed every frame. There's a Range function that runs when the player's character comes in range of the NPC but don't necessarily speaks to him.
And all other, numbered, functions can be used by the previous ones or by other part of the field's script. They may be used for a tiny part of a cutscene, or a special movement such as a jump, non synchronised dialog (ie. dialog bubbles that are displayed while the player still has the control on his character), or one-time walks...
Note that the cutscene scripts are often writen in a Loop function :
- Either the Main_Loop function is used, manage the cutscene's progression and calls parts of the NPC's script,
- Either the Loop functions of NPC and/or PC are used and comunicate with each other using variables.
NPC models corresponding to a Party's memberThere is a special case of entries that normally are present in all the scripts of the game (even if most of them don't have any function and thus are invisible). Indeed, the last 9 entries are each assigned to a potential member of the party, namelly
Zidane,
Vivi,
Dagger,
Steiner,
Freya,
Quina or Cinna,
Eiko or Marcus,
Amarant or Blank,
Beatrix
These entries have nothing special - you can use any model you want, for instance - but one thing : they can be refered to with special entry IDs and be used if they are in the player's team.
For instance, if the following lines are present in Main_Init function, then up to 3 of these entries will be initialized accordingly to the characters in the player's team :
InitObject( 252, 0 )
InitObject( 253, 0 )
InitObject( 254, 0 )
They can then be refered using the same special entry IDs for cutscenes and such. An example of use can be found in the script of the field "Oeilvert/Planetarium". In the function "Zidane_17" of this field, there's the cutscene when Zidane reads terran letters and the present characters are amazed. The different calls of "RunScriptAsync( ..., 252, ... )" are used to handle the reactions of the 2nd party member, whoever he is, at the different points of the cutscene.
So, in order to implement Beatrix in these cutscene, you need to create functions for her. Add a new function of type 0 chosing the last of the entries, then write the Init function :
Function Beatrix_Init
set VAR_B10_0 = 364
set VAR_B10_4 = 63977
set VAR_B10_6 = 252
set VAR_B10_2 = 65456
SetModel( 204, 100 )
CreateObject( VAR_B10_0, VAR_B10_4 )
TurnInstant( VAR_B10_6 )
SetStandAnimation( 2978 )
SetWalkAnimation( 2975 )
SetRunAnimation( 2981 )
SetLeftAnimation( 2980 )
SetRightAnimation( 2974 )
SetObjectLogicalSize( 20, 20, 30 )
SetHeadAngle( 104, 48 )
return
Replace the first numbers by coordinates (or you can remove those 4 lines and put the coordinates inside the "CreateObject" and "TurnInstant" lines).
With this, Beatrix will be created for this kind of cutscene if and only if she is in your party. You may also need to hide her in the Init function because she shouldn't appear before the cutscene. The line "SetObjectFlags( 14 )" does that.
Then you need to create other functions corresponding to her behavior during the cutscene. Look at the numbered functions for the other characters and create functions for Beatrix with the same ID (type) and with a similar pattern (adapt the dialogs and animations, off course).
By the way, you can add a new text in the corresponding text block beforehand with a right-click on it.
Once everything's done, don't forget to parse your functions and save. Congratulations : you have created cutscene elements for Beatrix !
PS. : contact me if you want to be part of the Github project.