Wavelist Editing Guide

Notice: I do not condone cheating in online multiplayer. This guide is for informational and educational purposes only.

This guide will guide you through editing wavelists so you can have multiplayer battles with whatever enemies you choose.

Here are the tools you will need to follow this guide.

You should understand the concepts in the DLC Editing Guide fairly well before attempting this guide.

Table of Contents

How waves work

In multiplayer, waves are defined by the wave budget, the max number of enemies, and the enemies for the wave itself. Each enemy has a wave cost, with the highest cost being boss enemies (Atlas, Banshee, etc) and the lowest being basic enemies (husk, trooper). Each wave has a budget of points, which determines how long a wave will be.

Wave costs are defined defined in BioGame under sfxgamempcontent.sfxwave_horde enemylist in the Coalesced files. Below is a snippet of the basegame BIOGame file's definition - note that some are overriden in later DLCs.

      "enemylist": [
        "(EnemyType=\"WAVE_CER_AssaultTrooper\",\tEnemyArchetypeName = \"Char_Enemies.Archetypes.Cerberus.AssaultTrooper\",\tWaveCost=20)",
        "(EnemyType=\"WAVE_CER_Centurion\",\t\t\tEnemyArchetypeName = \"Char_Enemies.Archetypes.Cerberus.Centurion\",\t\tWaveCost=30)",
        "(EnemyType=\"WAVE_CER_Nemesis\",\t\t\tEnemyArchetypeName = \"Char_Enemies.Archetypes.Cerberus.Nemesis\",\t\tWaveCost=40)",
        "(EnemyType=\"WAVE_CER_Engineer\",\t\t\tEnemyArchetypeName = \"Char_Enemies.Archetypes.Cerberus.Engineer\",\t\tWaveCost=40)",
        "(EnemyType=\"WAVE_CER_Guardian\",\t\t\tEnemyArchetypeName = \"Char_Enemies.Archetypes.Cerberus.Guardian\",\t\tWaveCost=40)",
        ...
        ...

This assigns the names you use in wave definitions to archetypes (think of it as a link to the correct files to load). It also defines the wavecost on the right which you can edit to make them worth more or less to a wave.

Using these archetype assignments is how BioWare updated some enemies like the Phantom's corrupt bubble shield (fixed in Earth) and the Atlas' DoT rocket ("fixed" in Retaliation). In the DLCs if you want to use the old versions of enemies just delete the lines with the new archetypes. They will have the DLC name in them (e.g. Char_Enemies_MP4.Archetypes.Reapers.Marauder).

The default point values for waves and enemies is defined below.

Cerberus
Enemy Wave Cost Defined in
Assault Trooper 20 Basegame
Centurion 30 Basegame
Engineer 40 Basegame
Nemesis 40 Basegame
Guardian 40 Basegame
Phantom 80 MP3
Dragoon 70 MP4
Atlas 100 MP4
Geth
Enemy Wave Cost Defined in
Geth Trooper 25 Basegame
Geth Rocket Trooper 40 Basegame
Geth Hunter 40 Basegame
Geth Pyro 40 MP4
Geth Bomber 30 MP4
Geth Prime 100 MP4
Geth Prime Turret 5 Basegame
Geth Prime Shield Drone 7 Basegame
Reaper
Enemy Wave Cost Defined in
Cannibal 25 MP4
Marauder 35 MP4
Brute 70 Basegame
Husk 10 Basegame
Ravager 60 Basegame
Swarmer 2 Basegame
Banshee 100 MP4
Collector
Enemy Wave Cost Defined in
Collector Trooper 25 MP4
Collector Web 10 MP4
Collector Captain 35 MP4
Seeker Swarm 10 MP4
Abomination 40 MP4
Scion 75 MP4
Praetorian 120 MP4

*Possession does not affect point values

As a wave progresses points are drained (unless you are in an objective wave - then it is infinite until completion). When points are depleted nothing will spawn. You can monitor this in realtime if you do the profile mpgame command from the console during a match.

Wave definition

Waves are defined in multiple locations.

As you can see there is actually 7 factions. MP4 uses a type 1 entry to set the entire object to null, then it writes four type 2's (append or update) that contain the new wavelists with the extra enemies.

Below is the wavelist definition for Cerberus2's 10th wave. It is located in the MP4 Retaliation DLC, so you'll have to extract the coalesced file and decompile it.

"sfxwave_horde_cerberus10 sfxwave_horde_cerberus2": {
      "enemies": [
        {
          "Type": 2,
          "Value": "(Difficulty=DO_Level1,Enemies=((EnemyType=\"WAVE_CER_AssaultTrooper\"),(EnemyType=\"WAVE_CER_Engineer\", MinCount=2, MaxCount=2),(EnemyType=\"WAVE_CER_Phantom\", MinCount=1, MaxCount=1, MaxPerWave=2),(EnemyType=\"WAVE_CER_Atlas\", MinCount=1, MaxCount=1, MaxPerWave=1)))"
        },
        {
          "Type": 2,
          "Value": "(Difficulty=DO_Level2,Enemies=((EnemyType=\"WAVE_CER_Guardian\"),(EnemyType=\"WAVE_CER_Engineer\", MinCount=2, MaxCount=2),(EnemyType=\"WAVE_CER_Phantom\", MinCount=2, MaxCount=2, MaxPerWave=5),(EnemyType=\"WAVE_CER_Atlas\", MinCount=2, MaxCount=2, MaxPerWave=4)))"
        },
        {
          "Type": 2,
          "Value": "(Difficulty=DO_Level3,Enemies=((EnemyType=\"WAVE_CER_Engineer\"),(EnemyType=\"WAVE_CER_Phantom\", MinCount=4, MaxCount=4),(EnemyType=\"WAVE_CER_Atlas\", MinCount=2, MaxCount=2)))"
        },
        {
          "Type": 2,
          "Value": "(Difficulty=DO_Level4,Enemies=((EnemyType=\"WAVE_CER_Phantom\"),(EnemyType=\"WAVE_CER_Atlas\", MinCount=2, MaxCount=2),(EnemyType=\"WAVE_GTH_GethBomber\", MinCount=2, MaxCount=2),(EnemyType=\"WAVE_RPR_Banshee\", MinCount=2, MaxCount=2)))"
        }
      ],
      "waveindex": [
        {
          "Type": 2,
          "Value": "10"
        }
      ]
    },

The name syntax is WAVE_<FAC>_Name, which is defined in the enemylist. If you want a full list of names, look at the Files in Depth guide. Make sure you have the right number of parenthesis, commas between enemies, and escaped strings with \". You should really run the file through JSONLint before you compile and test, it will save you a lot of time.

WAVE_CER_Engineer

The first item in every wave definition is the base enemy. When all other enemy slots are filled the base enemy will fill out of the rest of the spots. The number of spots is the same as maxenemies, set in BioGame (as seen in the Simple Modding Guide).

WAVE_CER_Phantom and WAVE_CER_Atlas

Both of these enemies have additional details about them, MinCount=4 and MaxCount=4/MinCount=2 and MaxCount=2 respectively. These extra details specify that there must be at least 4 phantoms on the field at a time, and no less than 4 phantoms on the field at a time. The same goes for the Atlas.

This is why you nuke the first enemy in an assassination objective - if you kill multiple enemies at once including the target, the next target may become the easier of the replacements of the ones you have killed.

The process for deciding the next enemy to spawn is done as follows:

  1. Check all enemy requirements (must be 4 phantoms, 2 atlases)
  2. If an enemy requirement is not met, spawn an enemy:
    • If enough remaining points - spawn the required enemy
    • If not enough remaining points - spawn the base enemy to exhaust wave pointsIt might spawn anyways and set the remaining points to 0
  3. Spawn a base enemy

I haven't tested if you can use just one of these two operators or if they have to be together. There is one additional operator, WaveMax, where you can set the maximum of an enemy that can spawn. These are typically used in Bronze and Silver to make difficult enemies have a hard cap each wave.

We are going to edit Cerberus2 for gold difficulty. For simplicity's sake we will be doing only the first 3 waves.

Cerberus
Wave Enemies
1 [base]Geth Bomber
2 [base]Dragoon
Abomination Min=2 Max=2
Banshee Max=1 Min=1
3 [base]Centurion
Scion Min=2 Max=2
Geth Prime Max=3 Min=3

You can quickly find the waves you are looking for in the biogame file by searching for enemynamewavenumber, such as cerberus11 or geth3. Sometimes you will get results like cerberus2, which is also the name of a wavelist.

Try this part before reading the code below to make sure you understand the concepts.

The following is what your first 3 gold wave declarations should look like - I've removed the irrelevant waves and difficulty declarations so it is easy to see.

    "sfxwave_horde_cerberus1 sfxwave_horde_cerberus2": {
      "enemies": [
        ...
        {
          "Type": 2,
          "Value": "(Difficulty=DO_Level3,Enemies=((EnemyType=\"Wave_GTH_GethBomber\")))"
        },
        ...
      ]
    },

    "sfxwave_horde_cerberus2 sfxwave_horde_cerberus2": {
      "enemies": [
        ...
        {
          "Type": 2,
          "Value": "(Difficulty=DO_Level3,Enemies=((EnemyType=\"WAVE_CER_Phoenix\"),(EnemyType=\"WAVE_COL_Abomination\", MinCount=2, MaxCount=2),(EnemyType=\"WAVE_RPR_Banshee\", MinCount=2, MaxCount=2)))"
        },
        ...
      ]
    },
    "sfxwave_horde_cerberus3 sfxwave_horde_cerberus2": {
      "enemies": [
        ...
        {
          "Type": 2,
          "Value": "(Difficulty=DO_Level3,Enemies=((EnemyType=\"WAVE_CER_Centurion\"),(EnemyType=\"Wave_COL_Scion\", MinCount=2, MaxCount=2),(EnemyType=\"WAVE_GTH_GethPrime\", MinCount=3, MaxCount=3)))"
        },
        ...
      ]
    },
    ...

If you wish you can continue to make changes to other waves, but it is a good idea to checkpoint at times because it is very easy to make a mistake that is hard to find later. There are other items in the biogame file that might interest you, such as how few enemies there can be before beserk mode kicks in and the master map list. At this point we are done editing the file for this guide.

Some things you need to watch for when modifying wavelists:

  • For some waves clients will not see some enemies depending on the mix of enemies you pick. I have not noticed a pattern, but wave 3 and 4 seem to be the most affected. Clients will report damage and staggering from invisible enemies. This only applies if the clients are not running the mod.
  • You always need a base enemy with no requirements in a wave definition.
  • You should test your mods with the assassination objective for waves 3, 6, and 10: certain enemy choices will make the game not refill the assassination time when the target is killed, leaving you only about 30 seconds to complete the objective. For the most part you should have a difficult enemy included in these waves to avoid it.
  • While I haven't tested it, I've heard that you can only spawn about 5 or 6 different enemies at a time. Loading a lot of different enemies is pretty resource intensive.
  • Modding is a finesse - players don't want to play enemy spam for 11 waves, nor do all people have high end gaming computers that can hold 100 collectors. Keep your clients in mind when you design a mod.

Testing your changes

Once you've got your edits in place, you need to repack your MP4 coalesced, update the PCConsoleTOC.bin, and then inject into the DLC or use Mod Manager to install it. Directions for this are in the DLC Editing Guide. Once this is done, you need to use a DLC authorizer to make the game accept your modifications. Finally, you can start a Gold Cerberus game.

If everything works as planned, you should see the wave edits. If waves don't load, you need to debug your mod.

If all goes well, you should see something like the following.

Wave 1: Geth Bombers

Wave 2: Dragoons, Abominations, Banshees

Wave 3: Centurions, Scions, Geth Primes

Debugging Your Changes

Recently I discovered some useful wavelist commands that would have been a tremendous help in the past. Using the in game console you can use the following commands to quickly test your mod.

Final Product

By following this guide you should have produced the source files located in this mod, which you can download for comparison.