-
Notifications
You must be signed in to change notification settings - Fork 51
Voice acting system
On this page, the name of the voice acting mod is assumed to be VoiceMod
but it can be anything else.
This feature allows to play specific sounds when dialog windows show up.
In order to create a voice acting mod, one must do the followings:
- Export the dialogs. This can be done with Hades Workshop (batch export texts) or by launching the game with the Memoria.ini option
[Export] Enabled=1 Text=1
. - For each line of dialog, export the voice acting as an OGG file.
- Tidy OGG files in subfolders according to the following scheme:
VoiceMod/StreamingAssets/Assets/Resources/Sounds/Voices/[LANG]/[ZONEID]/va_[MESSAGEID].ogg
,- where
[LANG]
is the language code among US, UK, JP, GR, FR, IT, ES, - where
[ZONEID]
is the number related to the dialog zone (in HW exported dialogs, it can be read in lines#HW fileid
; in Memoria exported dialogs, it can be read as the first number after$
in each dialog), - and where
[MESSAGEID]
is the number identifying the message (in HW, it's the number indicated on the line#HW newtext
above the message; in Memoria, it's the last number before the=
sign). -
Example (Memoria):
"$0290_EVT_TERA_BB_CDR_0_0353" = "{W213H1}{UpperRightForce}You’re a bigger fool than I imagined{Speed 2}...{Speed -1}";
- => Have the voice file
VoiceMod/StreamingAssets/Assets/Resources/Sounds/Voices/US/290/VA_353.ogg
saying "You’re a bigger fool than I imagined" (Beatrix).
- where
- For dialogs with multiple choices (they have a
{Choice}
code in Memoria-exported files and a[CHOO]
code in the HW versions), have a voice OGG for each choice with a_[CHOICENUM]
appended to the dialog's file name.-
Example:
VoiceMod/StreamingAssets/Assets/Resources/Sounds/Voices/US/290/VA_373.ogg
=> "Cards!? Right now?" -
VoiceMod/StreamingAssets/Assets/Resources/Sounds/Voices/US/290/VA_373_0.ogg
=> "Yes" -
VoiceMod/StreamingAssets/Assets/Resources/Sounds/Voices/US/290/VA_373_1.ogg
=> "No"
-
Example:
- Move this
VoiceMod
folder in the main directory of Final Fantasy IX and register it inMemoria.ini
([Mod] FolderNames = "VoiceMod", ...
).
.akb.bytes
files next to them (in the subfolder of the mod folder), containing the Final Fantasy IX formatted AKB header. When sharing the mod, share the mod folder with only the .akb.bytes
files for optimizing the hard drive space use and loading time (although I didn't see any noticeable frame drop because of isolated sound loads and conversions).
Most dialogs will also have additional paths available which can be helpful to identify the actor in some cases
- Some dialogs have an object id which will be appended at the end of the filename:
va_[MESSAGEID]_[OBECTID]
- Some dialogs have the name of the actor displayed at the top of the box:
va_[MESSAGEID]_[NAME]
Memoria.ini
of your mod:
[Hacks] Enabled = 1 DisableNameChoice = 1
During the festival of the hunt in Lindblum you will be able to voice each participant taking or holding the lead.
-
va_[MESSAGEID]_taken_[N]
when a participant has taken the lead. N increments each time that same participant takes the lead. It goes back to 0 if the file with the number N is not found. If a different participant takes the lead the current playing file will be interrupted and the new participant file will start playing. -
va_[MESSAGEID]_held_[N]
when a participant is hold the lead. N increments each time that same participant holds the lead. It goes back to 0 if the file with the number N is not found. Note that this will happen every time that the player switches screen. While a message (taken or held) is currently playing, another from the same participant will not go off and N will not increment.
When playing Chocobo Hot & Cold minigame the message for getting points will have a number appended to the end starting at 0 and incrementing with each treasure found: va_[MESSAGEID]_[N]
The number is reset each time a new game of H&C is started.
They work exactly the same as above using the special ZONEID = 68
.
Example: VoiceMod/StreamingAssets/Assets/Resources/Sounds/Voices/US/68/VA_52.ogg
=> "I’m sharpening my knife, kupo."
There are two different kinds of battle dialogs: the message dialogs and the ambiant dialogs.
The message dialogs are tied to written messages, mostly enemy messages (like Masked Man's talk when defeating him) or enemy attacks said at loud (like Masked Man's "Gwahaha!" attack).
The ambiant dialogs are extra voice sounds that can be played in various situations like at the start of the fight or when reacting to something happening (like getting killed), mostly by player characters.
They follow the same pathing structure as field dialogs except that battles do not operate within a zone so we replace the zone with battle/[BATTLEID]
, i.e.
VoiceMod/StreamingAssets/Assets/Resources/Sounds/Voices/[LANG]/battle/[BATTLEID]/VA_[MESSAGEINDEX].ogg
The message index is the position of the text in that battle's texts, taking the enemy names and attack names into account.
Example: the first fight against Beatrix has ID 4. That battle's texts are the followings:
- Beatrix
- Attack
- continuing other attack names...
- You’re no match for me!
- Ignorant fools.
- Stock Break
- Annihilated...
- Back attack!
- Gained more Attack Pwr!
VoiceMod/StreamingAssets/Assets/Resources/Sounds/Voices/US/battle/4/VA_10.ogg
=> "You’re no match for me!"
Ambiant dialogs are setup in a text file BattleVoiceEffects.txt
that must be created in the folder VoiceMod
.
Each different ambiant dialog must be setup with a block of text describing the situation in which it is played. These definition blocks look like this:
>BattleInOut Zidane WhenBattleStart VoicePath:Battle/Zidane/Intro Priority:0 [Condition] IsRandomBattle [/Condition]
The order of the lines doesn't matter, except for the first one. The first line of a block must contain one of the keywords below, followed by a space-separated list of the different characters who speak.
>BattleInOut >Act >Hitted >StatusChange
Also, except for >Hitted
, the defining block should contain a When
keyword.
These two keywords are the outline of the situation in which an ambiant dialog is played.
Type of dialog | Possible moments |
---|---|
>BattleInOut
|
WhenBattleStart : triggers at the start of the battle, right after the fighters are placed
WhenGameOver : triggers at the end of the battle if it is a Game Over
WhenDefeated : triggers at the end of the battle if it is a non-critical defeat
WhenBattleInterrupted : triggers at the end of the battle if it has been interrupted by the script
WhenEnemyEscape : triggers at the end of the battle if all the enemies flew
WhenFlee : triggers at the end of the battle if the party flew
WhenVictory : triggers at the end of the battle if it is a victory without the fanfare
WhenVictoryPose : triggers at the end of the battle if it is victory with the fanfare
|
>Act
|
WhenCommandInput : triggers when the first speaker is issued a command by the player
WhenCommandPerform : triggers when the first speaker starts performing an action
WhenHitEffect : triggers when the first speaker applies the effect of his/her action (eg.: right after the attack's damage is dealt, the attack misses, the spell's status is applied, an item is stolen, etc)
WhenCover : triggers when the first speaker covers an ally against an enemy attack
|
>Hitted
|
There is no different moment: the trigger is when the first speaker gets hitted by any attack or ability (at the same time as WhenHitEffect )
|
>StatusChange
|
WhenAdded : triggers when the first speaker gets affected by a status ailment
WhenRemoved : triggers when the first speaker has a status ailment removed from him/her
WhenUsed : triggers when a status takes effect on the first speaker, which depends on the status:
• For Auto-Life, it triggers when the character revives thanks to it • For Reflect, it triggers when a spell gets reflected • For Silence, it triggers when the character tries to cast but fails because of it • For Venom, Poison and Regen, it triggers on the periodic damage/heal • For Confuse and Berserk, it triggers when the character auto-attacks • For Trouble, it triggers when trouble damage is spread • For Heat, it triggers when the character tries to act and dies because of it • For Freeze, it triggers when the character dies because of it • For Doom and Gradual Petrify, it triggers when the countdown reaches 0 |
When using >StatusChange
, the related status(es) must be specified on a different line in the defining block.
The list of statuses can be found here, eg.:
Status:Death
The line VoicePath
says which audio file(s) should be played.
In the example VoicePath:Battle/Zidane/Intro
, the dialog file is meant to have the path VoiceMod/StreamingAssets/Assets/Resources/Sounds/Voices/US/Battle/Zidane/Intro.ogg
(or Intro.akb.bytes
).
In case of multiple comma-separated files (eg. VoicePath:Battle/Zidane/Intro, IntroAlternate
), a random audio will be played, with the restriction that the same ambient dialog trigger will not pick the same audio twice in a row.
The line Priority
rates the importance of the dialog: a dialog can be interrupted by another dialog that has a strictly higher priority but it cannot be interrupted by one that has the same priority or lower.
Finally, the line that encloses the code tag [Condition][/Condition]
can be used to have precise triggering conditions.
The enclosed code is a NCalc formula which allows very flexible conditions.
It is possible to add voice acting inside cinematic by replacing the whole audio file of that cinematic. For that, extract the audio file corresponding to the cinematic (the list can be found here), then place a modded version of that audio file in your mod folder with the corresponding path. For example:
VoiceMod/Assets/Resources/Sounds/Sounds02/Movie_/FMV001.ogg
The newest audio engine (Backend = 1) is able to handle OGGs of any bit rate, mono or stereo. The output is set to 48,000Hz and uses 32-bit float. This is the backend used by default.
For the best compatibility with the old audio engine (Backend = 0), the software and unity engine are expecting the audio files for voice acting to be OGGs setup with 44,100Hz, Single Channel (Mono), and using 32-bit float.
A voice mod needs to setup a couple of INI options.
Create a file Memoria.ini
in the folder VoiceMod
and add the following lines:
[Hacks] Enabled = 1 DisableNameChoice = 1 ; This option prevents the naming menu to pop, so the player cannot rename the different characters [VoiceActing] Enabled = 1 LogVoiceActing = 1 ; This option writes debugging messages in the log (see below) StopVoiceWhenDialogDismissed = 1 ; When this option is enabled, most of voice sounds get stopped when the related dialog box is skipped by the player AutoDismissDialogAfterCompletion = 1 ; When this option is enabled, dialog boxes are automatically closed once the related voice sound has finished playing Volume = 80; base volume at 800% please lower or rise to be correct for your recording not having balanced audio with this could clipping.
If your having problems with a line and are unable to work out the correct location you can enable VA Support Debugging to do this add the following to your memoria.ini
[VoiceActing] LogVoiceActing = 1
With this enabled your Memoria.log file will start getting entires output all the information you need to create your .ogg file E.G
17.08.2022 10:14:24 |M| [VoiceActing] field:2, msg:44, text:[C8C8C8]Cinna “Ain’t here yet.”, path:Voices/US/2/va_44)
should the File then be missing this will be followed by a not found notice E.G (not found)
A big thanks to barkermn01 for coding this system.