The Music System of Hellgate: London

Building an Adaptive Music System for a Dynamically Generated Game

by David Steinwedel, October 2007

Hellgate: London provides unique opportunities and challenges in implementing a successful, modern, adaptive music system. Below I’ll provide insight on the goals of Hellgate’s system, how a music ‘Set’ is built, how it is altered dynamically, and what we use to change it.

Goals

We set off with three basic but important goals for music in Hellgate: The music should not be repetitive, it should change dynamically with what the player is doing, and the player should not notice any sleight of hand used to achieve the first two goals.

Keeping it Varied—Music Sets from Building Blocks

The basic elements of a Music Set are full length loops called Full Mixes, which are divided into two categories: Action and Ambient. All Mixes in all categories are exactly the same length and tempo (or half/double time). Each Full Mix can have any number of Sub-Mixes (usually one) which are lighter variations of the Full Mix. Only one Mix is playing at any time.

Video Game Dynamic Music Example

We took this approach for a few reasons. First, it allows ambient and action cues to be drastically different from each other. In many adaptive music systems, separate tracks will stack, adding elements as the action changes. Having multiple interchangeable tracks allows more flexibility for the composer to try different things and gives better control over the final Mix (of both full and sub versions). So a typical Set would start off with four tracks:

Tunnel Level Action Full Mix

Tunnel Level Action Sub Mix

Tunnel Level Ambient Full Mix

Tunnel Level Ambient Sub Mix

This provides us lots of variability by allowing a change between any of the Mixes at any musically viable time. To make sure things stay interesting we added another layer of complexity: Stingers.

A stinger is a one-shot sound that combines seamlessly with a playing Mix. Hellgate employs three types of stingers: Overlay, Interrupt, and Breakdown. Overlay Stingers fall transparently on top of the current Mix. Interrupt Stingers mute the current track while playing, effectively replacing a section of music. Breakdown Stingers pause the current Mix and continue it when the Stinger finishes, interjecting a new section of music and lengthening the Mix.

An Overlay Stinger

Video Game Dynamic Music Example Stinger

An Interrupt Stinger

Video Game Dynamic Music Example Stinger

A Breakdown Stinger

Video Game Dynamic Music Example Stinger

Stingers are used to smooth transitions when switching Mixes or to add variety to a Mix. They can be any length and are assignable to certain areas of a Mix. (An Interrupt stinger, for example, can be written for a specific portion of the track, or used for transitions only in certain areas.) This behavior keeps the music feeling natural as it transitions.

Each music Set has up to 25 or 30 stingers. A typical set might look like this (with multiple instances of each type of stinger):

Tunnel Level Overlay Hits (think of cymbal crashes for the start of a phrase or transition).

Tunnel Level Action to Ambient Interrupts

Tunnel Level Ambient to Action Interrupts

Tunnel Level Action Interrupts

Tunnel Level Action Breakdowns

Tunnel Level Ambient Interrupts

Tunnel Level Button Endings

There are an infinite number of stinger opportunities with this system (many of which are not explored for cost, footprint, and data management concerns). With all the pieces listed and a decent amount of data set up we can smoothly move between any of our Mixes and keep any single Mix dynamically changing each time it loops.

Music Controllers

Hellgate has a number of unique design elements that greatly affected how the music control system was built and hooked to the game. First is randomization—the game is completely randomized from top to bottom and, in a sense, we wanted music to follow this tradition. Second is that Hellgate’s fundamental client/server design limited our ability to use Level Zones, the Questing System, or AI as music controllers. We decided to work as best we could with the given design limitations and base our music control strictly on player actions.

To this end, we took whatever game stats we thought were valuable and created a scripting language to direct state changes in the music. Our system uses a series of If, Then, Else statements to ask questions about the game state and then evaluate what the music should do. Some of the most useful stats include:

Monsters_killed(time in seconds); returns the number of monsters killed in the previous N seconds

Meters_moved(time in seconds); returns the number of meters moved by the player in the previous N seconds

Monsters_pct_left(); returns the percent of monsters left in a level from the original spawn population

Monsters_in_Radius(radius in meters); returns the number of monsters within the given radius

Boss_hp_pct(radius in meters); returns percent of hit points left of the nearest boss within the given radius

Hp_cur*100/hp_max; returns percent left of player health

Hp_lost(time in seconds); returns hit points lost by the player in last N seconds

Rand(A,N); returns a random value between A and N.

Using combinations of input values, subroutines are written to handle different music behavior. For example, here’s a statement to turn on the action music when a player is quickly & easily moving through a large field of monsters:

If Music==Ambient && monsters_killed(32) >= 10 && monsters_pct_left() >= 50 && enemies_in_radius(50) >= 20 && ( hp_cur*100/hp_max ) >= 65 && rand(0,100) >= 50; then Music==Action; else …..

There is no game state that directly encapsulates ‘quickly and easily moving through a lot of monsters,’ so we examine what happens while playing the game to determine what combination of state values describes the situation. This script is saying (in order) that if the music is currently playing an ambient Mix, and you’ve been killing a lot of monsters lately, and there are a lot of monsters left both in the level and near you, and you’ve got most of your health left, then, pending a throw of the dice, switch the music to the action Mix. If any of those conditions fails, evaluate the next set of conditions.

We wrote a whole series of subroutines to handle moving in and out of each Mix for generic gameplay. Then we created routines to handle specific events, such as boss fights or special quests. As the game developed we found that each class played at a different pace, requiring subroutines balanced for each class. Failsafe systems were added (such as Max Playtime, so a track can’t stay on forever and Minimum Playtime, so a player can’t somehow trigger a ‘music mini game’).

A typical music script for one character class.

Video Game Dynamic Music Example ScriptDoes it Work?

Yes and no.

In terms of our goals, we met all of them to some degree. The music consistently changes and it does so based on the player. I’ve received comments from both users and developers indicating the sleight of hand works. “I was playing and really into it and all of a sudden I realized the music was blasting away! Where did it come from?”

However, there’s plenty that can be improved.

Since Hellgate can’t be pinned into a certain game category (is it an ARPG, FPS, MMO, or something else altogether?) and has customizable skill trees and over 100 viable weapons, it makes for an infinite number of play styles. Our system, which was scripted and balanced by one person, works well as long as you play the game somewhat like I do (a badass, nonstop killing machine). Stopping to inspect every item, playing tepidly, warping into town to sell loot, and tons of other actions can stop or slow the pace of the game enough to reset the system and keep music from working as intended.

Where our system shines is in micro-managing music. It allows for constant music cue changes according to the scope of a battle and how it’s going for the player. We can write cues and stingers for specific actions and conditions and switch to them instantaneously. As our audio programmer says, “It’s a good reactive music system.” And he’s right in most cases. However there are times when music needs to be proactive, looking ahead at what’s coming.

For the system to completely shine, we need to add a macro-level controller. For example, approaching a known battle in a pre-designed level would turn the music system on and start running a music script, which would then micro-control music for the encounter’s duration.

Such a design is never going to happen because it’s against Hellgate’s core design, so we’re working on other methods and technologies to do the same thing within our available toolset. Fortunately, we can continue to iterate on Hellgate: London and work our way to Music 2.0.