Project Roguelite Strategy
Why did I make this?
There were two goals that I wanted to achieve in making this game. The first was understanding what goes into creating video games. The second goal was to create a turn-based RPG that I could share with friends. This game idea was a mashup of deck builder, rogue-lite, and JRPG genres. Thematically, I wanted the player to experiment, push their limits, and learn that failure can inevitably lead to success.
I used RPG Maker MZ (RMMZ) because it was simple to learn, used javascript for the engine, and would provide a good base to build off of. Since RMMZ is written in javascript, it was easy to share the game with friends through itch.io. They could play the game in their browser.
Project Roguelite Strategy (PRLS) was completed over 1 month, April-May 2021.
What I did
- I designed and created 3 worlds for the player to explore. 1 Hub for the party setup. 1 Tutorial dungeon with 1 miniboss and 1 major boss. 1 complete Volcano dungeon with 3 minibosses and 1 major boss.
- I created and balanced 8 classes, 6 base classes, and 2 alternative class. Each class has 5-6 spells that work in a ‘combat rotation’.
- I created a vertical progression system based around pushing the party to exhaustion and rewarding effort. Death is a required mechanic in this gameplay loop.
- I created a horizontal progression system for equipment and alternative classes to allow the player to customize their party based on the situation.
What I built on top of
- All assets such as sounds, UI, character sprites, particle effects, or environment tiles were provided out of the box by RMMZ.
- The combat engine is built on top of the existing RMMZ engine.
- Some community plugins were used to implement spell effects that required hooks at the beginning or end of an actor’s turn.
- Years of RPG, TCG, Roguelite knowledge and experience. Elements of Final Fantasy, World of Warcraft, Bravely Default, Slay the Spire, Magic: The Gathering, and Dragon Quest are baked in here.
Game Design
Gameplay Loop
To understand the core game loop of this game, it would be helpful to explain the core gameplay loop of JRPGs, Deckbuilders, and Roguelites.
The core JRPG loop
The core Rogue-lite loop (roughly)
The core deckbuilder loop
PRLS tries to smush all of these loops into one core gameplay loop
Closing a loop
In the above loop, to keep the gameplay loop closed between runs, gold is lost upon entering a dungeon and consumable items are lost upon leaving a dungeon for any reason. This causes two interesting side effects. The first is that the players are incentivized to use consumables as opposed to hoarding them (this is a big problem in JRPG play patterns) which will typically extend a run farther than the player would expect. The second is that it creates a link between runs, similar to towns, players spend their gold and see how far they can get with this new stash of consumables.
Going Against the Grain
My biggest concern in this game loop was conveying to the player that ‘death is good’ as a mechanic. This concept runs counter to all gaming knowledge a player has built up in their game-playing career. It’s like telling someone to read a book backward. To do this, the first dungeon is designed to kill the party in the first 2 or 3 enemy encounters. Upon death, a player will be at their most frustrated point and then they’re greeted with ‘you have earned N XP.’ This triggers the realization that progression in this game carries over through death. After playtesting the game with friends. The concept of dying never came up as a point of negative feedback as long as it was properly signposted.
Multi-class design
Rogue-lites are known for their systematic design and a large variety of gameplay styles. The biggest variety in PRLS comes from the multi-class design. Each class has a unique combat rotation, an expected order of abilities the players should use for optimal damage, similar to how a WoW or FFXIV class might play. Learning how each class rotation plays out and then applying that knowledge to configure a party to operate as a unit is one of the most engaging loops in multi-class games. Since a player is controlling the entire party, it becomes apparent that classes can interact and play off each other.
For example, the Hunter class builds up resources to unleash a shot that causes the target to take extra damage (1.5x) for 2 turns. If the Swordsman is also in the party, they can hold their resource spender ability, double swing (deals double damage), for this burst window to deal triple damage (2 x 1.5) per hit.
As players get more comfortable with individual class strengths and weaknesses, party composition becomes a class of its own. This means that the party variety can be described in a binomial coefficient n choose k, where n is the total number of classes and k is the party size (initially 2 but then progressed to 3). For 8 classes, there are 56 unique combinations. Adding another class creates 84 unique combinations. At the intended goal of 24 classes, you create 2024 total party compositions without equipment. That leads to a lot of variety and replayability for a player to explore.
Horizontal Progression Through Kiss/Curse Equipment
Equipment is balanced on a kiss/curse system, so all equipment has benefits and drawbacks associated with them. As you get more items, it increases the diversity of strategies that the equipment can provide. For example, the electric sword deals 1.5x damage to water enemies but does .5x damage to ground enemies. In a meta with nothing but ground enemies, a regular sword would be a better pick if it’s the difference between that and the electric sword.
Feedback
Since this was my first game, there was a lot of player feedback. The biggest blind spot I had was around when a class learns new skills. Originally all classes learned skills at the same levels (2,4,7,10,15,21) to ensure all classes were roughly balanced at every level. But this reduced excitement. A player would know if they just learned an ability, they probably weren’t going to get one soon. At the cost of game balance, I shifted the learning levels around. This caused delight and excitement as now, new abilities were a surprise and seemed to occur at every level.
One other piece of feedback is that all enemies have some sort of elemental weakness to them. This is similar to the pokemon system of type weaknesses. The Black Mage class is based around this combat mechanic. However, without watching the numbers, there is no indication that some attacks deal more damage than others. Without knowing the underlying implementation a player may think this because the skill inherently hits harder or because it hit a weakness. I decided to add a spell called ‘analyze’ which would tell the player what weakness an enemy type had. This feeds into the idea that the player is ‘mastering a dungeon’ as they won’t have to waste a turn to analyze the enemies next dungeon run. Currently, this requires the player to remember these weaknesses, but in a future version of the game, I’d like to keep track of that information similarly to Octopath Traveler’s weakness UI.
Level Design
Since the variety of the game comes from diverse party combinations and deckbuilding setup, the level design is responsible for setting up a playground for the player to experiment and be challenged. I went with the decision to use a fixed set of enemies in a dungeon so players can learn the different troop patterns and after dying to one, can change their strategy going in the next time.
To prevent repeating the same encounters over and over again, shortcuts are applied to the dungeons to skip completed sections. For example, the volcano level is set up in a counter-clockwise swirl and a bridge connects the west side of each swirl to create a shortcut after every boss is defeated.
Lastly, I used the camera framing to let players know that certain items existed on the edge of the screen, but they would need to figure out how to get there.
This looks promising!
I have to push farther than I expected…
Gameplay/Tools/QA Programming
Gameplay programming
RMMZ documentation is pretty sparse and requires reading through the engine code to understand how certain functions work. For example, to override the way that speed affects turn order, I had to create a plugin that would override the prototype function. I also had to do things like implement non-damage effects, like ‘analyze’ to display enemy health.
Other gameplay tools that I created involved creating the function to provide partial credit of XP on party death. The function takes the current state of the encounter and tallies how much XP to give the player. This value depends on how close the player was to defeating the enemy troop. A slain enemy gives full credit, but a damaged enemy can only give up to half credit. The half credit is to dissuade a player from just trying to grind bosses and then intentionally die right before they kill the boss.
Tools/QA/Balance Scaling
The most interesting challenge I came across was scaling the game. As a one person team, if I wanted to make a fundamental change I didn’t want to have to replay the game and ensure that every encounter was balanced. In addition, if I wanted to add a new encounter, I wanted to quickly determine the difficulty of the encounter allowing rapid iteration.
I started by creating a mathematical simulation of a theoretical party configuration attempting to fight a single enemy. The main information I wanted to glean was: Who would win first, the player or the enemy? If the player, how many turns would this take? This was done through a spreadsheet for simplicity initially. As long as classes are roughly balanced relative to each other, any configuration will lead to similar outcomes.
After doing this, I realized that a troop of enemies could be modeled as just a single enemy. To do this would require taking a ratio of each troop member’s health and defense and boiling that down to a theoretical single enemy. Since RMMZ keeps all of its data in JSON blobs, it would be fairly challenging to be able to scale this spreadsheet to multiple different enemies and run regression simulations against all enemies at once. I realized it was time to abstract this spreadsheet into a script and inevitably a spec file.
To do so, I pulled out different spell abilities for each class and put them into an exportable javascript file. This had a plethora of benefits. First, it made adding new spells easy because almost all spells rely on the fundamental base physical or base magic damage formula so spells could reference this formula without having to copy-paste it all over the database. Second, editing spell formulas became much easier since it was in text form, as text manipulation is a programmer’s bread and butter (if I was working in a team with other folks that needed to create spell formulas, this might not be the best approach). Lastly, I could reference these abilities in other utility scripts, such as creating test functions to validate edge and base cases for different spell formulas.
Once I had this information pulled out, I created a script that would simulate different combat encounters using values directly from the MZ database. Given this function, I created a new test file that would allow me to quickly simulate new combat encounters given real game data. If I changed an enemy’s power, health, or defense, I would know in seconds if that change would push the enemy’s power level outside of an acceptable balance range.
All this effort allowed me to create combat encounters in minutes instead of hours. Ultimately, it helped me scale 10x moving into the volcano dungeon.
Production
I expected scope creep to hit while working on this game. To combat this, I gave myself a checkpoint every 2 weeks to have a sharable version of the game with a new dungeon and classes. This time crunch helped me focus on what I needed to do to hit that deadline. I leveraged Notion’s notebook system to keep track of ideas and game thoughts so that I could look into them later. This ultimately became my game design document. I kept track of tasks in Todoist to keep things in priority order and cut tasks that wouldn’t make it into the final release.
Final Thoughts
Moving forward
After prototyping in RMMZ, it became clear that this was an idea that would work. But in the investigation period for the 3rd release of the game, I started to notice that working with RMMZ kept becoming more difficult as overriding functions could only go so far. For the next release of the game, I’d like to learn Unity and reach feature parity in each version.
Future Edit: While I did take some courses on Unity, real-life obligations go in the way and I had to put this project on the backburner.
Play It!
If you’d like to play Project Roguelite Strategy, it is playable in the browser here:
For convenience, a skip directly to the second dungeon is available on the item shopkeeper.
If you’d like to view the code it’s available here!