Modifying Individual Sounds - XCOM:EU 2012

From Nexus Mods Wiki
Jump to: navigation, search

Overview

It is a fairly simple mod to remove or make minor adjustments to individual sounds in XCOM EU/EW that you may find annoying or distracting. The process is nearly the same for most sounds, although small details might be different depending on the particular sound you want to eliminate.

Some examples of sounds to eliminate are the beeping of proximity mines and the background "hover" sound of the hover SHIV. See the example section below for patch files to remove these sounds.

The basic idea behind this kind of mod is to locate the "Sound Cue" responsible for playing the particular sound and modifying it to remove the reference to the sound file in question. This basically "breaks" the sound, but in a way that is harmless to the game; the only effect is that the game cannot find the sound file to play and plays nothing. Other similar mods may be possible, depending on the sound, such as lowering the volume instead of removing the sound outright.

Programs and Tools

A few basic programs are needed to perform this kind of mod. Several of the steps involve using the command line so some knowledge of how to run commands from the command line is an asset.

Details

There are three main steps to creating a mod of this nature:

  1. Discover the exact name of the sound to modify.
  2. Find the Sound Cue corresponding to this sound in the game's UPK files.
  3. Construct the patch file to eliminate or modify this sound.

Discovering the Name of a Sound

The first step is to find out exactly what the sound you are interested in modding is called. This is easily done in game with the help of the Developer Console.

First launch the game and in the developer console use the "ShowLog" command to open a log window that will display the game log. This will open in a new window, not within the game itself. Once the console has been opened, go back into the game and perform the action(s) needed to get the game to play the sound you want to modify. Once it has played, enter the "ListSounds" command in the developer console. This will print the names of all sounds that are currently loaded by the game into the log window you opened earlier. It will include all recently played sounds, so you will see many sounds here, hopefully including the one you are looking for.

Below is a snippet of the output when looking for the the Proximity Mine beep sound. It was listed after launching a proximity mine in a tactical mission. The list has been trimmed to keep it short, and the bolded line is the interesting one.

 [0189.38] Log: Listing all sounds.
 [0189.38] Log: , Size Kb, NumChannels, SoundName, bAllocationInPermanentPool, SoundClass
 [0189.39] Log: ,   514.17, 2 channel(s), SoundUI.AlienActivity, 0, SoundFX
 [0189.39] Log: ,   342.17, 1 channel(s), soundmutonfx.MutonSignalVictory, 0, SoundFX
 [0189.40] Log: ,   172.35, 1 channel(s), SoundFloaterFX.FloaterMovement04, 0, SoundFX
 ...
 [0189.48] Log: ,    24.50, 1 channel(s), WP_ProximityMine.ProximityMineBeep, 0, SoundFX
 ...
 [0189.52] Log: ,    14.12, 1 channel(s), soundmutonfx.MutonFootDirt05, 0, SoundFX
 [0189.52] Log: ,    13.91, 1 channel(s), SoundDroneFX.DroneArmServo01, 0, SoundFX
 [0189.52] Log: ,    13.73, 1 channel(s), SoundDroneFX.DroneArmServo03, 0, SoundFX
 [0189.52] Log: ,     4.43, 1 channel(s), WP_BPHeavyLaser.LaserHeavyBarrelClick01, 0, SoundFX
 [0189.52] Log:  3004.80 Kb for 43 resident sounds

Recognizing the sound you are looking for in the game may take a little guesswork if the sound is fairly generic. In this case, "ProximityMineBeep" is a clear name that is likely the one we want, compared to others such as "FloaterMovement04" or "LaserHeavyBarrelClick01".

Finding the Sound Cue

After identifying the name of the sound, the next step is to find the package (.UPK file) the sound file resides in. This is not necessarily easy to do: the name of the package may or may not really be related to the name of the sound in question.

One of the simplest approaches is to just search for the name of the sound in all packages. Most packages installed by XCOM EU/EW are compressed, so in order to search them you need to first decompress all the files. You can do this with the DecompressLZO utility included in UPKUtils. Having decompressed copies of the files is also needed to open them in UE Explorer so it's a good practice to copy all the .upk files from the XComGame\CookedPCConsole folder of your installation to another folder and uncompress all of them with DecompressLZO. You can then search for the sound name with the findstr command from a command prompt window. For example, searching for the "ProximityMineBeep" sound located above:

 C:\Tools\unpacked> findstr /M ProximityMineBeep *.upk
 Weapon_MEC_Launcher_SF.upk
 
 C:\Tools\unpacked>

Here we see the file is found in the package Weapon_MEC_Launcher_SF.upk, and nowhere else.

Open up the package in UE Explorer and select the "Objects" tab, then the "Content" tab below this. Find the group name that corresponds to the part of the sound before the dot (in this case, we want WP_ProximityMine because the full sound name is "WP_ProximityMine.ProximityMineBeep"). Expand this tab.

Proxminebeep.png

The above screenshot shows the contents of the WP_ProximityMine group. In this case it contains several items, two of which are interesting: "ProximityMineBeep" and "ProximityMineBeepCue". Clicking on each will show some details about the objects in the package. In this case, "ProximityMineBeep" has class "SoundWaveNode" which means it is an actual sound file. You can extract this object as an .ogg file and play it outside the game. The object "ProximityMineBeepCue" is a "Sound Cue" which is the object we want: we want to modify the sound cue to break the link between this cue and the sound file itself.

Note that in this case the cue has a little expand handle (+) next to it indicating it has its own child nodes. Expanding this you see a node "SoundNodeAttenuation". Sound cues can contain a number of sub-objects to modify the sound in various ways. In this case a attenuation node is used. Attenuation nodes are typically used in Unreal to lower the volume of a sound as you get further away from it. It's important in this case because we need to find the reference to the sound file itself somewhere in this cue. It might be directly in the cue, or it might be in a sub-object of the cue. It depends on the sound in question and takes a little bit of detective work to locate. UE Explorer often does a poor job at displaying the contents of these nodes in the window, but fortunately you can "teach" it how to display things better in most cases. For example, here's the output in the Window with "ProximityMineBeepCue" selected:

 begin object name=ProximityMineBeepCue class=SoundCue
   SoundClass=SoundFX
   SoundClassName=ESoundClassName.None
   begin object name=SoundNodeAttenuation class=SoundNodeAttenuation
       ChildNodes=/* Array type was not detected. */
   object end
   // Reference: SoundNodeAttenuation'WP_ProximityMine.ProximityMineBeepCue.SoundNodeAttenuation'
   FirstNode=SoundNodeAttenuation
   VolumeMultiplier=1.0
   Duration=0.28446710
 object end
 // Reference: SoundCue'WP_ProximityMine.ProximityMineBeepCue'

The bolded line for ChildNodes indicates UE Explorer failed to decode the list of child nodes because UE Explorer doesn't know what the array type is in this case. I know it's an array of objects, so click the "Options" menu and under "Array Type Definitions" click "Add" then enter "SoundNodeAttenuation.ChildNodes" in the "Group" box and choose "ObjectProperty" from the "Type" list and click save. You'll only need to do this once to set up UE Explorer and then it will work for all attenuation nodes. But if the cue in question has some other sub-node type you may need to repeat this process for the new sub-node kind.

Now select the cue again (you may need to click off and back on again to get the screen to refresh) and you should see this:

 begin object name=ProximityMineBeepCue class=SoundCue
   SoundClass=SoundFX
   SoundClassName=ESoundClassName.None
   begin object name=SoundNodeAttenuation class=SoundNodeAttenuation
       ChildNodes(0)=SoundNodeWave'WP_ProximityMine.ProximityMineBeep'
   object end
   // Reference: SoundNodeAttenuation'WP_ProximityMine.ProximityMineBeepCue.SoundNodeAttenuation'
   FirstNode=SoundNodeAttenuation
   VolumeMultiplier=1.0
   Duration=0.28446710
 object end
 // Reference: SoundCue'WP_ProximityMine.ProximityMineBeepCue'

Much better! Now we see the SoundNodeWave named "WP_ProximityMineBeep.ProximityMineBeep" is a child of the SoundNodeAttenuation node in the ProximityMineBeepCue. Now that we've located the object, we can construct the patch file.

Constructing the Patch File

The basic idea of the patch file is to replace the reference to the SoundNodeWave object in the cue with a null reference. Then when the cue plays, it finds no sound file to play and you will get only silence.

There's still one more step involved in getting the correct object name, though. UPKUtils generally appends a number on the end of cue sub-nodes, so if the sound you're working with is actually in a sub node, as in this case (inside the attenuator) you need to determine the name of the object as known by UPKUtils. The easiest way to do this is to use the "DeserealizeAll" command in UPKUtils and then search for the string you want.

 C:\Tools\unpacked>DeserealizeAll.exe Weapon_MEC_Launcher_SF.upk | findstr ProximityMineBeepCue
 WP_ProximityMine.ProximityMineBeepCue
 WP_ProximityMine.ProximityMineBeepCue.SoundNodeAttenuation_0
 
 C:\Tools\unpacked>

In this case we can see the name of the attenutator node is "WP_ProximityMine.ProximityMineBeepCue.SoundNodeAttenutation_0". Knowing the name of the object to modify and the name of the sound node to remove, we can now create a basic patch file:

 UPK_FILE=Weapon_MEC_Launcher_SF.upk
 OBJECT=WP_ProximityMine.ProximityMineBeepCue.SoundNodeAttenuation_0
 [BEFORE_CODE]
  <WP_ProximityMine.ProximityMineBeep>
 [AFTER_CODE]
 <NullRef>

Use the name of the cue or sub-object in the cue that refers to the sound in the OBJECT line and use the full name of the sound as was listed way back in the sound list from the dev console in the BEFORE_CODE section. The AFTER_CODE set to <NullRef> replaces the sound with a null reference, and no sounds will play.

This patch file can now be applied with PatcherGUI and distributed.

Changing the Volume

Instead of outright removing the sound, another option would be to modify the sound somewhat. One example would be to reduce or increase the volume of that sound. Most sound cues have a VolumeMultiplier property, which is a floating point value. Changing this to a bigger or smaller number in your patch file should produce the desired results in game.

Examples

Remove Proximity Mine Beeping

  UPK_FILE=Weapon_MEC_Launcher_SF.upk
  OBJECT=WP_ProximityMine.ProximityMineBeepCue.SoundNodeAttenuation_0
  [BEFORE_CODE]
  <WP_ProximityMine.ProximityMineBeep>
  [AFTER_CODE]
  <NullRef>


Remove Hover SHIV Idle Hover Sound

 

 UPK_FILE=Unit_XComTank3_SF.upk
 OBJECT=SoundSHIVFX.HoverIdleOnAlertCue
 [BEFORE_CODE]
 <SoundSHIVFX.HoverIdleOnAlertCue.SoundNodeAttenuation_0>
 [AFTER_CODE]
 <NullRef>