Immortal: Gates of Pyre

Immortal: Gates of Pyre is the first large project i’ve worked on. Thanks to my experience in RTS level design and the more recent creation of my rogue-like RTS, Tainted Radiance, Sunspear Games entrusted me to create the Missions game mode.

This game mode is strongly inspired by Starcraft 2’s Co-op game mode which was the biggest innovation in the genre. It allows for the creation of a highly-replayable experience dedicated to PvE players that cost significantly less than a full campaign.

On a personal level, i love games with long-term progression and customization so I was super excited to be able to create a successor to Starcraft 2’s Co-op.

Humble beginnings

When I joined the project, the Missions game mode was is a blank state. Everything was yet to be done.

The first task was to setup the vision that would help me draft the version version of the player’s progression and the structure of missions.

While figuring out the first version of game design document, I had to get used to Unreal Engine. I previously used Starcraft 2’s Galaxy editor which was tailor-made for RTS. Back then, I didn’t realize how spoiled I was to be able to create and iterate on maps super fast. It was tough to get used to slow creation speed with Unreal Engine’s terrain tools.

Progression

Metaprogression systems are not public so this section will be developed at a later date. What I can say is that these systems support long-term player progression because of the live-service game context.

There is still some player progression available in the game with the difficulty settings. On lower difficulty, the enemy is only able to train lower tech units and large parts of the map are blocked-off. So when the player decides to increase the difficulty, they get the satisfaction of playing in a larger playground and discover new enemy threats.

This mostly works on less experienced players that start playing on lower difficulties. Players experienced in RTS games tend to play right away on higher difficulties so they will miss this progression. There are more details about this in the Difficulty Parameters section.

Missions have a score system that is shown to the player when the mission is completed or failed. When the player has the skill, knowledge and the will to complete more objectives and with greater efficiency, they are rewarded by a score. This score will be used in the future for the player’s progression.

The score screen at the end of a mission

Missions

The structure of missions have been standardized in a way where they all work with the scoring and metaprogression systems. This is a process that took multiple iterations.

Missions can be played with a flexible amount of players. Those who want to play alone and not be bothered by anyone can do so. And at the same time, they can bring a friend to play with if they wish so.

Because of the live-service game structure, the priority was to create highly replayable missions with diverse objectives that reward different playstyles and strategies.

Each mission has its own identity based on the deep lore of the game. The objectives helps to keep the mission different from the others.

The mission objectives have characteristics that have an impact on how efficient the various Immortals are. For example, Orzum, the defensive Immortal, is more powerful on Holdout, the Nexus defense mission. It is important to create a set of missions that favors each Immortal.

A mission has a main objective, one static bonus objective and between 1 and 3 random bonus objectives depending on the difficulty. The static bonus objective always has a reward that is visible for the player.

Here is how the randomization of missions work:

  • At the start, a seed is generated
  • The terrain is semi-produrally generated. There is a handmade map layout and on top of it, there are spawning locations for pathing blockers. This cuts or open paths so the points to defend and enemy attacks paths aren’t always the same
  • The player’s starting and second resource locations are fixed. The other ones are randomized homogenously depending on the distance from the player’s starting location. Sometimes, these additional resource locations are inside enemy bases, sometimes not.
  • The Pyre Camps, which are creep camps that give the Pyre resource spawn randomly on preset points.
  • The enemy faction is decided randomly between Qrath and Aru. And for higher difficulties, it selects a random enemy Immortal.
  • The enemy bases are spawned. Some locations always contain an enemy base, others spawn randomly a base.
  • 2 enemy unit compositions made of 3 unit classes are selected and are randomly attributed to each base. This creates variety in the strength and weaknesses in the enemy unit compositions. With more experience and knowledge, players are able to adapt their own unit composition which leads to more variety for them.
  • And to finish, between 1 and 3 random bonus objectives are added. These objectives create points of interest that alter the player’s game plan for the mission. Some bonus objectives can add more power to the enemy, others can give benefits to the player.

3 different seeds of the Golem Factory mission. You can see resource locations, Pyre camps and some enemy bases in different locations. 3 enemy base locations are permanent.

For the map layout of missions, players always start next to each other because it is more comfortable for them to play this way. It also increases the feeling of playing together. There can be missions where players start far from other other but they would be exceptions, twists on the established formula.

Difficulty parameters

The difficulty parameters of missions are divided in 2 categories: the usual numerical parameters but also complexity parameters that are critical to not overwhelm new players.

The difficulty selection on Holdout

The numerical difficulty parameters are the following:

  • The quantity of enemy bases
  • Enemy bases contain more units
  • Larger enemy attacks
  • More frequent enemy attacks
  • The quantity of bonus objectives
  • Higher objective values
    • It leads to a longer mission duration which requires a better economy management from the player

These are the mission complexity parameters:

  • Large parts of the map are blocked off on lower difficulties
    • The player only needs to focus on a smaller area
  • The enemy doesn’t have access to higher tech units on lower difficulties
    • Lower tech units are simpler to understand for new players
  • Some bonus objectives are available only from a specific difficulty
The south-east corner of Golem Factory is blocked off with a thick fog on Hard difficulty and below.

Because missions are playable alone and in a team of 2 players, it was tricky to find the right way to balance the difficulty. I ended up going for the following solution:

  • Increase the quantity of enemy units in attacks
  • Launch two attacks on different player-controlled locations instead of one.

Blueprint scripting

When I joined the project, my experience with Unreal Engine was minimal so I had everything to learn. Thanks to my programming background, I was already comfortable with the logic of programming so it was mostly about getting used to the server-client architecture, the giant library of functions and to the Blueprint UI.

There were just a few custom functions useful for missions so my programming speed was very slow. At first, it took me a few weeks to setup a single mission. Over the years, as I built functions and blueprint objects specific for missions, I was able to produce a mission prototype in just a day.

My major struggle was to understand how the server-client works. To prevent hacks, the games were fully run on a server . I was very often confused why some client-side or server-side code wasn’t executed. It took me years to get comfortable with that.