Skip to content

Voice acting system

Tirlititi edited this page Jul 23, 2023 · 12 revisions

On this page, the name of the voice acting mod is assumed to be VoiceMod but it can be anything else.

Table of Contents

In-Field dialogs

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:

  1. 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.
  2. For each line of dialog, export the voice acting as an OGG file.
  3. 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).
  4. 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"
  5. Move this VoiceMod folder in the main directory of Final Fantasy IX and register it in Memoria.ini ([Mod] FolderNames = "VoiceMod", ...).
When voice files are played in-game, Memoria generates .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).

In-World dialogs

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."

In-Battle dialogs

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.

Message dialogs

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:

  1. Beatrix
  2. Attack
  3. continuing other attack names...
  4. You’re no match for me!
  5. Ignorant fools.
  6. Stock Break
  7. Annihilated...
  8. Back attack!
  9. Gained more Attack Pwr!
Thus: VoiceMod/StreamingAssets/Assets/Resources/Sounds/Voices/US/battle/4/VA_10.ogg => "You’re no match for me!"

Ambiant dialogs

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.

In-Cinematic dialogs

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

Audio Format

For the best compatibility, the software and unity engine are expecting the audio files for voice acting to be OGGs setup with 44100Hz, Single Channel (Mono), and using 32-bit float.

INI options

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.

Debugging

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.