A powerful curse is burning through the world's most powerful magic users, escalating their powers to dangerously violent extremes! Hoping Batman can take on the hard work, John Constantine's transported his House of Mystery to overlook Gotham Cemetery, where he and it are now under attack.
Who - or what - is the source of this terrible curse? Is magic itself doomed? Will Constantine’s cheeky imposition land him in hot water with the Caped Crusader? Constantine and Zatanna have personally asked for your help.
In Justice League Dark Cursed, players will join forces with Batman and members of the Justice League Dark to put an end to this threat to all magic.
Release Date: October 5, 2023
This episode required we familiar ourselves with the Justice League and Justice League Dark storylines. We had to be careful in how to extract from these two teams as there has been confusing overlap between the two, most notably Batman's membership in the Justice League, and his indirect involvement with Justice League Dark. Does he believe in magic?
Episode 46 was by far one of my favorite projects! The research phase was thrilling, and the Justice League Dark movie had me súper inspired. This was also a rare opportunity to implement single-player adventure content in a game almost entirely focused on massively-multiplayer experiences.
In the end we decided to develop five instances: a single-player Solo, two four-player Alerts, an eight-player Raid, and a 50-player Open World known as Cursed Gotham City. For purposes of this portfolio, this subpage will focus only on the solo instance and the ways in which I contributed to it.
Roles: Product Owner, Area Designer, Technical NPC Designer
An important factor in our game is replayability, and being able to get through certain pieces of content with relative quickness. Our target audience wants a fun adventure, exciting boss battles, and the freedom to play it over and over without feeling grindy. We wrote the solo with that in mind, making sure to balance the amount of dialogue delivered through scripted sequences and cutscenes.
Episode 45 heavily focused on the boss encounters between Cursed Wonder Girl and Cursed. While a great of material was brainstormed during kickoff, we really wanted to lean into the things the two characters could do. This would not have been successful had we not done our research as some of our concepts contradicted some of their powers, such as Zatanna possibly using fire, which would make no sense.
A major step in my design process is creating a design macro. This spreadsheet pushes me to think wholistically, doing my best to play through my vision in my mind, and itemize what efforts are required to pull it off. Each line item is a moment-to-moment rundown of what events would be taking place through gameplay, and breaks down each beat into objectives, mechanics, assets, etc.
This step went very smoothly thanks to the design macro shown above. The categories the art team needs to see was broken apart into individual columns, and quickly extracted by running through each line item. Every asset request was then used to generate the document the art producer requires.
Once again we were in an all-new map for this level. Art and design collaborated a bit earlier than usual on this map as we had two ridealongs, with each one following at different times.
Tools: Unreal Engine
We made a lot of mistakes with this map. At the start of the instance, Wonder Girl makes a quip, and then runs away through a door, which happened to be the one the player should go through.
What happens if the player follows? Why doesn't Wonder Girl fight the baddies? What happens to the scripted sequence if the player leaves while Zatanna is still talking?
There were many more questions we asked, but these were a few that were difficult to address. Fortunately we found a solution using a specific AI strategy and complicated logic switches, but it was a notable oversight on my part.
A stretch goal of ours was to place promotional posters throughout the theater that would tease Zatanna's attacks. We had the idea that we could allude to her mechanics by presenting it on the poster as if it were one of her magic tricks. Dialogue was actually written and recorded for these moments, but we unfortunately cut due to time.
Part of our area designs needed to consider what characters might say. As we polished the design of our areas, we always wrote hallway banter such as combat chatter, functional VO, and lines for allies.
The first thing we needed to do was implment that baseline data for the area to perform. This included simple data such as waypoints, checkpoints, and triggers, as well as larger systems such as standard enemy encounters that occur during the infiltration phases.
Areas a managed using what we call the arbiter. I'm unsure if this is a proprietary term for our modified version of Unreal, but it's the technical equivalent as the Level Blueprint. Here you can see the outline for the entire instance, which at a high level is handling the flow from enter to exit, as well incoming and outgoing events from the encounters.
Here you can see the general flow for the entire area starting with when the player first enters the region, all the way through every event that can occur.
The first boss fight in this area is with a younger Wonder Girl who has been unexpectedly cursed by Hecate. Her fight required a broad amount of implementation, including scripted dialogue sequences, opening and closing cutscenes, and dynamic allies responsive to players' conditions. To builder her correctly, we used a phase-based setup of three AI strategies.
Use Ball Lightning until the NPC reaches less than 70% health
Use Ground Smash until the NPC reaches less than 30% health
Use Lunge Tackle until the NPC is KOed
Cursed Wonder Girl's three unique abilities are her Ball Lightning, Ground Smash, and Lunge Tackle attacks. Each of these attacks are built from scratch, and were implemented using the Unreal ability editor.
This mechanic makes the NPC vulnerable when the attack is being used. We liked the idea of using this classic attack, and add debuffs for the caster and target. If the ability is used when a player is blocking, the user takes damage on collision rather than applying damage.
If the player was too close when the ability was used, they'd get stunned without notice. To mitigate this, we added a pushback when called to move players away before the projectiles were shot.
We wanted to balance this attack for both difficulty and moving styles. There are a few rules specifying how much damage to be done based on the hardness, but also for players who are blocking or flying.
This fight was handled by referencing the encounter in the area's arbiter. All of the things that occur in the fight are scripted within the encounter itself, but how it affects progression, player messaging, and achievements are all done in the arbiter.
Most of what is written in the encounter editor speaks to the arbiter via its incoming and outgoing events. Many of them go into a variety of switches to control logic, but some (towards the bottom) are used to contribute towards feats and Steam achievements.
Most of the boss encounter script is handling AI events coming from the NPC's strategies, and event nodes to trigger scripted sequences, combat chatter, and VO.
Use Cursed Glitter Balls until NPC reaches less than 30% health
Use Magical Orbital until NPC reaches less than 30% health
Use Aerial Blasters until NPC is KOed
Cursed Zatanna's three unique abilities are her Cursed Glitter Ball, Magical Orbital, and Aerial Blasters attacks. These attacks are a bit different from the others in that they rely on hidden abilities, as well as invisible NPC enemy adds.
This attack was initially overpowered and not realized to be until adequately tested. The attack fires up to six projectiles in an arc motion halfway between the caster and the target, but did not take a stack count into consideration. Until we limited collision to just one, there was a chance players would be insta-killed if hit by all six at once. Brutal!
Although the script makes this ability seem chaotic, it is actually quite simple: target a player to mark an AOD, strike a beam from above for an AOE. We collaborated with our systems team on this mechanic, and added a variety of rules to accommodate the rewards they could earn. For this episode, the augment would reduce a certain amount of damage depending on how many they have equipped.
The main stage where the fight takes place has high ceilings. It's important we avoid players cheesing the game and spamming attacks while flying above, so we created a grounding spell that would check if players were flying, and if so, prevent them from flying for roughly ten seconds.
This attack functioned a bit differently from the others in that it was used by an invisible NPC rather than Zatanna herself. These NPCs would populate in the space above her, and then shoot laser beams at the players from a distance. Depending on the difficulty, up to three could be spawned.
Just like the previous boss, this fight was scripted using the encounter editor, and then referenced and managed in the arbiter. This allowed us to command how the fight could reset, keep track of achievements, and deal with hidden things like enabling triggers and toggling checkpoints.
The second fight was a bit more invloved, especially when it came to enemy adds (for the aerial blasters) and tracking feats/achievements. There were also more events to handle, as this was the final fight and would be followed by a cutscene, scripted outro, enabled portals, and a "post-game" of sorts for players to explore backstage.
The general flow functions similar to Wonder Girl's battle, but this fight calls in low-level enemies for the Aerial Blasters, and also provides some utility to randomize possible lines of combat chatter and functional VO.