Jump to content

Sound replacement possible?


TRekNexus

Recommended Posts

tracktwo, you need to compile scripts in debug mode for `Log() messages to appear:

<Path-To-UDK>\Binaries\Win32\UDK.exe make -DEBUG
You can use Mutator class subclasses to try to play your sound with "Mutate" console command. You'll need to install MutatorEnabler first, though.
Link to comment
Share on other sites

  • Replies 199
  • Created
  • Last Reply

Top Posters In This Topic

Thank you WGhost! Success! I've created a new package and loaded it into XCom and played it through a mutator. With these steps it should be possible to construct packages with many new sounds and play them via scripts.

 

First, create and set up the new package with the sounds.

 

 

 

  • Get a sound you want, in .WAV format. For testing, I generated a sound using audacity again. This time, export it as a WAV (Microsoft) signed 16-bit PCM. UDK only imports sounds in WAV format, but it encodes them as .ogg in the cooked packages.
  • Open up the UDK editor for a sample game.

  • In the content manager, click "import" and select the .WAV file you produced.
  • Set the package name to the name you want. E.g. MyCustomSounds, and name the sound appropriately, e.g. testsound.
  • Click the "Auto create Cue" box and hit OK.
  • Save the project. This will prompt you for a location to place the package. I just put it under "<path to udk>\UDKGame\Content"
  • Edit the UDK project's DefaultEngine.ini and add your package name to the [Engine.PackagesToAlwaysCook] section as "+SeekFreePackage=MyCustomSounds"
  • Open the UDK front-end and cook the project. You should now see a cooked upk with your name and the _SF suffix in "<path-to-udk>\UDKGame\CookedPC\MyCustomSounds_SF.upk"
  • Copy this cooked package to the XCom CookedPCConsole folder

 

 

 

Now, create the mutator script to play the sound. You need to have the enable mutators mod installed from the "Scripting with UDK" thread.

 

 

 

Create the folders UDK\Development\Src\SoundMutator\Classes

In this folder, make a new file "SoundMutator.uc" with the following contents:

class SoundMutator extends Mutator;

function Mutate(string MutateString, PlayerController Sender)
{
    local SoundCue cue;
    cue = SoundCue(XComContentManager(class'Engine'.static.GetEngine().GetContentManager()).LoadObjectFromContentPackage("MyCustomSound.testsound_Cue"));
    PlaySound(cue);
    super.Mutate(MutateString, Sender);
}
 

Note that the package name in the content string here doesn't include the _SF suffix that's appended by cooking, and the sound cue is the name of the sound you set on import with "_Cue" on the end.

 

We also need to create a stub XComContentManager in a dummy XComGame.upk package.

 

Create the folders UDK\Development\Src\XComGame\Classes

In this folder, create a new file XComContentManager.uc with the following contents:

class XComContentManager extends object native notplaceable;

function Object LoadObjectFromContentPackage(string objectname)
{
return none;
}

Compile the scripts. Copy the generated SoundMutator.u package to the CookedPCConsole folder in XCom and add it to the sections as specified in the instructions for adding a mutator in the "Scripting with UDK" thread.

 

 

 

Now launch X-Com, load a saved game, and type "Mutate <whatever>" in the console, and you should hear your new sound. The test mutator just plays the fixed sound regardless of argument, but it could be made smarter to play different sounds on different conditions.

Edited by tracktwo
Link to comment
Share on other sites

tracktwo, great! One more person to write mutators! :smile:

 

You can use <whatever> string parameter to pass sound cue name to script.

 

BTW, stub function body can be entirely empty even if it has return value. Proper return value object will be created and imported anyway.

Edited by wghost81
Link to comment
Share on other sites

Great, and I see your new mutator project too, that will be useful.

 

More poking around that I've done:

 

Voice Banks

 

Character voices should be modifiable by creating/changing voice bank files. These have a pretty straightforward format: XComCharacterVoice. A voice bank file is a package that contains an XComVoiceBank object and a big set of SoundNodeWave and corresponding SoundCue objects for each of the voiced events in the game. The XComVoiceBank type is a class that extends Object and has a default property list of ObjectProperties for each of the sounds. Then, it contains an mapping of object references to the variables defined in XComGame.XComCharacterVoiceBank. Example:

XComCharacterVoiceBank : UObject
  ObjRef
  DefaultProperties:
      HunkerDown = ObjectProperty set to the "hunker down" cue in this package
      Reload = ObjectProperty set to the "reloading" cue in this package
      ...
      Strangled = ObjectProperty set to the "Strangled" cue in this package
  TMap<int32, UObjectReference> CueMap

The CueMap maps indices into the default property list to object references of the variables in XComGame.XComCharacterVoiceBank. Because of the way these are set up, I suspect that neither the names of the properties nor the order of the cues in the default property list actually matter. This makes sense because some sounds are mec-specific and others are human-specific, so this way there is no need to specify e.g. choke sounds for mecs or flamethrower sounds for humans by including "holes" in the sound bank. For example, the first entry maps index "1" (the HunkerDown property) to the object reference XComCharacterVoiceBank.HunkerDown in the import table.

 

Voices

 

A voice pack is a set of voice banks. The standard ones typically have 15 banks, so when you, for example, overwatch, it'll choose one of the available overwatch sounds from the list of banks associated with that voice. A voice package contains an object of type XComCharacterVoice. This object collects all the voice bank packages together into a set. Its structure is fairly simple:

XComCharacterVoice : UObject
  ObjRef
  DefaultProperties:
     VoiceBankNames = ArrayProperty of FStrings
     CharacterCustomizationCue = ObjectProperty

Note: because the size of each FString is dynamic, you can't easily seek within the array elements. E.g. even though the array may say it has 15 elements, you can't compute the start of the 3rd element as 3 * element_size because there isn't any one element size. You need to parse the first two to get their lengths first.

 

Each element of the VoiceBankNames array is a string of the format "Typename" <space> "object name". For example, the first entry in the male italian voice 1 bank 0 is "XComCharacterVoiceBank MaleVoice1_Italian_Bank0.MaleVoice1_Italian_Bank0", indicating that the first entry is of type XComCharacterVoiceBank and can be found by the name MaleVoice1_Italian_Bank0 in the package of the same name.

 

Again looking at the standard files, it looks like adding new voice packs is relatively straightforward. This is exactly what the DLC packs do to add the Zhang and Annette voices: they add the corresponding voice pack and bank files to DefaultEngine.ini as +SeekFreePackage, and then create a VoicePackageInfo line to DefaultContent.ini mapping the voice package to one of the voice enumeration values. E.g. Zhang uses eCharVoice_MaleSoldier1_Brash. There are a few extra, unused ones for each gender already there in the default XGGameData.ECharacterVoice enumeration.

 

 

 

When you get the Zhang character, the reward script simply generates a character with the voice set to eCharVoice_MaleSoldier1_Brash. You can make anyone sound like Zhang by setting their voice to that enum value. You can't choose it from the customization UI in-game, but you can do it with a custom script.

 

 

 

The bad news is, the mapping of voice packs to languages seems to be hardcoded in the executable. I'm still looking into this... more on it later.

Link to comment
Share on other sites

Thanks dubiousintent!

 

I've made some real progress on a little mod to allow .INI customization of voices. Unfortunately it will be probably early next week before I have any more time to continue on it, but progress has been very good so far!

 

My plan, for now, is to have the mod basically have (almost) no effect: the same voices are available as they always were, and selected through the customization screen as they were before. The only difference being that all the available voices and the selection of those voices is handled entirely by the .INI and the scripts instead of the executable. And possibly the addition of the Zhang and Annette voices to the english lists, just to show it's working :smile: I lost my Zhang in my current playthrough, and now I can have his old familiar voice on a new soldier.

 

So far my mod replaces the english voice list with just two voice packs, listed in DefaultGame.ini. These are Zhang and Annette. It doesn't (yet) distinguish based on gender or whether or not the soldier is a mec, but that should pretty straightforward to add. With this mod, opening up the customization screen only lets you select between english voice 1 (Zhang) and 2 (Annette). And in the tactical game, the soldiers speak in the corresponding voice.

 

When this is done, it should be possible to add new voices, remove existing ones, or mix and match voices into different places. It also allows the selection of the DLC voices on regular soldiers, as I mentioned.

 

The mod is based off a mutator, and I had to add a new mutation hook to XComHumanPawn.InHQ.FindPossibleCustomParts to overwrite the available voice list. I'll provide the mutator hook to you, wghost81, if you're interested in it.

Link to comment
Share on other sites

> I'll provide the mutator hook to you, wghost81, if you're interested in it.

 

Yes, I'm very interested in further development of XComMutators project. You can join GitHub and submit your changes to main project to become a contributor. Or I can do it myself if you don't want to/don't have time to join GitHub.

Link to comment
Share on other sites

I am already on GitHub, so I'll fork it and send you a pull request for the changes. I might get a little bit of time tomorrow to do that, otherwise it'll probably be a few days.

 

I don't like the patch for the mutator hook I have right now, because it doesn't use enough BEFORE_CODE to ensure the function isn't already modified. I am still getting used to doing the hex code disassembly in my head to correctly set the BEFORE_CODE to a suitable chunk of the function.

Link to comment
Share on other sites

Ok.. so it turns out that the mutator isn't even necessary. The loading and mapping of language voices is handled by the executable, but that is just setting defaults. It is already further overridden by the VoicePackageInfo settings in DefaultContent.ini. This is great, because it means voice modding is far simpler than I originally thought. I had a little time to experiment and successfully added a new "dlcish" language to the game, selectable by the localized customization UI. It has only a single voice in it, but which will set the character to either Annette's or Zhang's voice depending on their gender. I'll post complete instructions & patch files on how to mod the new language when I have some time, probably on Tuesday. It requires only two small patches to the UPKs to add a new language enum value and to mod the hardcoded max language value in the customization ui, the rest is all done via INI files.

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.

×
×
  • Create New...