Handrolling an RPG Stat System

A look at the design philosophy behind the Written Realms stats system, tracing its roots to legendary game titles such as World of Warcraft, Diablo and Baldur's gate.
By Pat
Feb 28 2020

So you want to make an RPG stats system. This should be the easy part, right? How many games have there been with players leveling up to engage in strategic combat against ever more powerful foes? Our forerunners in the field of RPG design have ensured that we stand on the shoulders of giants, but with so many giants it can be difficult to know where to begin clambering. And worse, simply picking our favorite giants could lead to an impossible straddle and toppling down into the abyss of needless complexity and shallow play patterns (I’ll stop torturing this metaphor now). This is the situation we found ourselves in early on when developing Written Realms and the goal of this post is to share some of our learnings and contrast the tools available so that you can pick what’s right for your game (or just to nerd out because that’s fun too).

The first thing to consider is, just what is the point of a stats system? First, it adds depth to combat in a game that may otherwise be overly simple. Games like Zelda can work with a very simple health and damage system because the action keeps fights engaging, but applying the same system to a game like Final Fantasy would lead to boring combat with little strategy. Second, stats illustrate character differentiation. By codifying the Strength and Intelligence as discrete numbers, it is now clear just how much harder a Fighter will punch than a Wizard. And if you want to be an armored juggernaut instead of a bloodthirsty berserker, you have a system that enforces that fantasy. Last, and very importantly, it almost always serves as the primary indicator of player progression. Many, many games have demonstrated that there is just something immensely satisfying about succeeding at a task and being rewarded with larger numbers. The fact that a game like Cookie Clicker gained legitimate traction without any sort of endgame or purpose to its progress is testament to this. Although some sectors of the industry have perfected the art of weaponizing this desire for predatory monetization practices, it is an extremely powerful tool that can be used responsibly to craft a compelling, engaging experience. I think of it like sugar, whether it’s used to create an addictive soft drink or a delicious cake is up to the chef.

So let’s go over the basic components. The fundamentals of the standard system will come down to health, damage, and defense, whether represented directly or derived implicitly from other values. Balancing these three components is at the heart of most RPG combat and character building decisions. Often, those broad categories are divided further. The most common example is the split between physical and magical damage and defensive stats that affect each type differently. Health is generally treated as a single number, although some games opt for something more ambitious like a system of different body parts or accrued “wounds”. This can work, but be mindful of how much complexity you are adding to your system and whether it will actually lead to more strategic gameplay. A system that requires the player to maintain a mental map of multiple types of sustained damage for both themselves and the enemy may lead to information overload. It’s easy to make the mistake of assuming that additional complexity will add depth. In practice, too much complexity encourages finding the simplest viable strategy and ignoring most of the design space that the designer wants the player to explore. Playtest early and make sure that whatever you add is helping rather than hindering the gameplay.

Now, even with some division and subtyping, there wouldn’t be a whole lot to play around with using only those 3 concepts, which is why nearly every game spices it up with some secondary stats. Almost every game will have some form of critical hit, so they often include a stat for increasing the chance of that occurring (some also provide ways to increase the damage of criticals, but I would be very careful about doing so since it has the chance to completely overshadow any non-critical damage when stacked, especially if there is any Player vs Player combat where burst damage needs to be carefully balanced). Chance to evade or dodge damage is a good choice, particularly if you want the thief or assassin to be able to be on the frontlines while remaining thematically consistent with their archetype. Beyond that, there are a lot of possibilities depending on your game. Are there types of elemental damage? Bonus damage for an element! Do abilities go on cooldown for a time after use? Cooldown reduction! There are tons of possibilities; the hard part is balancing it so that they are all appealing without being so good that players simply stack one or two of them without considering any alternatives. Optimization should be a continuously interesting challenge as players improve their character. When only a few stats matter, this optimization becomes linear and uninteresting. Diablo 3 initially had this problem where only 4 stats were sought after. When they fixed this with the expansion, it added much more fun and longevity to the item hunt (one could argue that hunting broken set bonuses is still linear, but that’s a topic I won’t get into right now). Also, don’t add something just because other games have it. A well-designed elemental system can create depth and reward strategic thinking, but one that is poorly tacked on can flatten combat to a predetermined Rock-Paper-Scissors dynamic or incentivize mindlessly spamming a single ability instead of making use of all of the tools available.

Now that we have some stats, what do we do with them? Figuring out an appropriate formula is actually no small thing and has a significant impact on your game from the ground up. Let’s look at how some big names handle it.

We’ll start with a classic that predates even the earliest JRPGs, Dungeons & Dragons. Due to the game’s tabletop nature, everything is determined by dice rolls that are modified by certain bonuses and penalties. For instance, whenever a character attacks, they make a roll with a 20 sided die, apply a modifier based on their stats and status effects, then compare that to the target’s Armor Class. If the roll is equal or higher, then the attack connects and the damage is determined by another set of dice rolls. In the case that they roll a 20 (5% chance), then it’s a critical hit with bonus damage, a concept that has appeared in just about every RPG since. (I know this is something of an oversimplification, but I think it broadly conveys what’s going on here).

The thing about dice rolls is that they are very high variance, which seems like an obvious thing to point out but bear with me. They make for great dramatic (or hilariously catastrophic) moments when everybody at the table is watching to see what numbers come up. There are successful games that faithfully port systems like this, but one aspect that they lack is a moderator that can smooth out the experience to turn streaks of bad luck into a part of the story rather than a game over screen (although some dungeon masters will opt to do that anyway). Baldur’s Gate is one of my favorite games ever made, but it would be a very frustrating experience if it weren’t for the Quick Save feature to reload when those inevitable cold streaks happen. Emulating a true dice rolling system is a perfectly fine choice, but it should be a decision made recognizing that gameplay consistency will take a hit for the sake of being aesthetically faithful to its tabletop origins and that there will likely be frustrating moments as a result, even more so if there is a PvP element built around it.

On to one of the classics in the digital realm, Final Fantasy. There have been variations on how exactly damage is calculated throughout the series, but we’ll use FF7 as the example. The baseline power of a character is determined through this formula:

P = Attack + (Attack + Level) * Attack * Level / 1024

Interestingly, Level is used directly here rather than just implicitly increasing power by increasing Attack while leveling up. This Power is then used in the following formula, where M is a constant based on the move being used and D is the target defense. For the sake of brevity, we’ll skip the minor variance tacked on afterward.

Damage = M * P * (512 – D) / (16 * 512)

Now, clearly this formula was effective enough to form the backbone of the combat system in one of the most successful and influential RPGs of all time, but do you see any potential issues here that could come up if you tried to simply reuse it?

First, it breaks if any character gets close to or beyond 512 Defense. Defense is no longer a stat that you can increase as a character grows in power, but is more a static representation of their archetype (wizard in a robe has 50 DEF, knight wearing plate has 300 DEF). Also, there is now an unintuitive dynamic where Defense gets better the more of it you have. The value of a +10 DEF item varies wildly (going from 10 to 20 DEF is negligible but going from 490 to 500 cuts damage in half) and a player that doesn’t look these things up will often be making suboptimal choices with no clear feedback. While there is something to be said for rewarding a player that knows the systems well, we should avoid punishing players for doing something that makes intuitive sense, such as shoring up the defenses of a fragile character, wherever possible.

Let’s look at a slightly lesser known JRPG, Star Ocean, for another example. This one also has some fancy tweaks layered on, but the core number is calculated by:

Damage = (Attack * 2 – Defense) / 1.5

This approach can also work, but presents a similarly unintuitive dynamic as the previous formula in that Defense becomes better the more that it is stacked. Even worse, it’s no longer the arbitrary 512 value that you have to design around, but the moving target of the differential between the player and enemy stats. A game using this system will often be very punishing should the player should they attempt to tackle content while underleveled and, conversely, an overstatted character will shrug off so much damage that combat becomes trivial and boring. The only “real” gameplay will exist in a narrow band around the level that the player is “supposed” to be. This isn’t an impossible challenge to tackle as a designer, but it makes life harder than it needs to be, especially given that players have their own preferences as to how much grinding they want to do. And, once again, this is especially problematic in PvP scenarios where a high level ganker is not only advantaged by having higher stats and a wider variety of skills, but is nearly invulnerable to their lower level prey due to how combat math is handled.

Lastly, let’s look at Diablo 3 for both a good and bad example. First, we’ll look at the Do Not.

D3 went through many iterations of their Dodge mechanic, but all that we’re going to evaluate here is their initial formula:

if (Dexterity <= 100)
DodgeChance = Dexterity * 0.001;

else if (Dexterity <= 500)
DodgeChance = (Dexterity – 100) * 0.00025 + 0.1;

else if (Dexterity <= 1000)
DodgeChance = (Dexterity – 500) * 0.0002 + 0.2;

else if (Dexterity <= 8000)
DodgeChance = (Dexterity – 1000) * 0.0001 + 0.3;

DodgeChance = 1;

Now, this sort of “breakpoint” based calculation isn’t necessarily broken and can be tempting when you want to achieve certain numbers within your existing system for aesthetic reasons (“Warriors will have about 50 DEX and 5% dodge, Thieves should be about 1500 and 35%”), but I’d advise against it because it goes against the intuition that you are training your players to develop and, again, rewards behavior that goes against common sense. There is nothing natural about Dexterity suddenly becoming a worse stat once you get to 100, then 500, then 1000. This should be avoided unless you want to punish players who spend more time playing your game than combing a wiki.

How they chose to handle Armor, on the other hand, is a great example to go by. In this case, damage is calculated as:

Damage = Attack * (1 – 100 * Armor / (Armor + 50 * Attacker Level))

It may not be immediately apparent, but this formula scales very naturally. The way that Armor is used here ensures that mitigation approaches 100% asymptotically and that it would take an absurd amount to reach “gamebreaking” levels. Also, the math works out so that, for a given amount of Health, a point of armor will consistently add the same amount to a character’s “effective health”, meaning how much raw damage the character can take before dying (e.g. if I have 50% armor mitigation and 100 HP, then my EHP is 200). The most generic form of the above equation can be stated as:

Percent = X / (X + L * K)

Where X is the relevant stat, L is a constant based on attacker level, and K is a second constant to tune the numbers to whatever you think is reasonable. Other examples of games that use a variant of this formula for armor include World of Warcraft and DotA 2. If you want there to be a baseline chance C (e.g. Dodge is at least 5%), you would use the following adjustment:

Percent = (X + L * K * C) / (X + L * K)

I strongly recommend this for any case where the game would break if the numbers got too close to 100%. For instance, we use the same formula for dodge, but for critical chance we simply use X / (L * K) + C since a character that crits all the time doesn’t actually break anything and is almost certainly an inefficient use of stat budget, but a character with 100% dodge is functionally immune to physical attacks unless stunned. While some games choose to embrace this sort of RPS dynamic where certain 1v1 matchups are more or less predetermined (if you can’t stun them, then you lose), that should be a deliberate decision that you make because you want to encourage group PvP or emphasize character build choices more than real-time combat decisions rather than an unintended side effect.

One thing to note here is that L should be based off of the Attacker level instead of the Defender if possible. The distinction is subtle, but otherwise a character can actually become less powerful by leveling up since their stats don’t do as much compared to the larger constant. Taken to the most extreme case, one can imagine a low level character stacking so much dodge or armor that they are invincible so long as they never level up. It’s unlikely that this would be possible in a given game, but it’s cleaner if the system itself eliminates any such possibilities altogether, even if most players won’t even notice.

Now you may have some questions about this mysterious “level constant”. While I don’t claim that this is axiom that must be held to, my opinion is that most everything should be built around a number that more or less represents where your player is at unless you want to be handholding your player through whatever playground you have assembled for them. For our system in Written Realms, we decided to pick a constant that generally represented each level and build around it. Specifically, that number is:

C = 1.1 ^ Level * 5.5

The formula is simple, but its implications as far-reaching. The 5.5 is of little importance and was chosen mostly for aesthetics once the rest of the system was determined, what matters is that we decided is that a “level up” should represent a roughly 10% increase in power, for both players and NPCs. Now, we use this number for quite a lot, crit, stat budget, dodge, armor but what really matters is what you want to do. We’ve optimized for allowing users to build a world that has a built-in, scalable system, but you can choose whatever works for you so long as it creates the game that you want. We ourselves deviate from this formula between levels 15 to 20 to taper off the scaling a bit and ensure that a level 17 character can complete with a level 20. What is important is that you think about what does matter when there is a showdown between high and low level character, what that means, and how your system will represent that.

Taking this all together, what did we decide to do for our system? Since our goal is not to make a single game, but a platform through which anybody can create their own world, we wanted to keep the core of it simple and comprehensible. Also, since we want the game to be playable through a purely text interface, we can’t rely on any specialized UI to convey a wall of different stats in a readable format (no Sphere Grid shenanigans for us). Given these constraints, our system comes down to the following:

Health – How much damage you can take before dying (technically, being sent to the infirmary, but you get the idea)

Mana – Used by Mages and Clerics for abilities. Regenerates slowly during combat and more quickly while resting.

Attack Power – Increases attack damage (Attack Damage = Weapon Damage + Attack Power / 16). Most physical abilities use some multiplier on the normal attack damage, although a few use attack power directly to encourage a 1H / Shield build.

Spell Power – Increases damage / healing from spells. We toyed with using a fancy formula, but settled a simple relationship where a standard nuke will deal damage equal to 10% SP

Armor – Mitigates physical damage using the formula with K = 60. Armor is not a stat that can be rolled on gear, but is deterministic based on an item’s level and whether it is “light” or “heavy”. This distinction means that a character’s armor level is more a part of their class’s identity than a stackable stat.

Resilience – Now we break from tradition a little bit. Resilience is similar to armor, but applies to all damage types, although K is 120 for this formula so you need to have a decently large health pool before it makes sense to stack this. The primary purpose is to give “tanks” a mitigation stat to build toward rather than just increasing their health pool. An alternative would have been to simply make Armor affect all damage taken and allow that to be a stackable stat, but for our game we wanted to keep a level of counterplay where magic and physical damage can be more or less effective depending on the situation as well as enforcing some more concrete delineation between classes.

Dodge Rating – Increases chance to dodge physical attacks. Unless you’re stunned, in which case you’re SOL. K = 60, C = .02

Critical Rating – Increases the chance of scoring a 50% critical bonus Who doesn’t love bonus damage? As mentioned previously, there is no need to do any fancy downward scaling here since a build that stacks this toward 100% doesn’t break combat in any way and is almost certainly inefficient. K = 120, C = .04

Beyond these fundamental stats, each class has a “primary stat” that essentially functions as a discounted stat bundle.

Strength – 1 Health, 1 Attack Power. Warriors get 1 Critical Rating

Dexterity – 1 Dodge Rating, 1 Critical Rating. Assassins get 1 Attack Power (at least they will when they are added to the game)

Intelligence – 2 Spell Power, 1 Mana

Lastly, there’s the general “survivability” stat bundle that is useful for everybody.

Constitution – 2 Health, 1 Resilience

Under our system, every item has a budget that gets randomly allocated between the different stats and all of the fundamental stats cost 4 “points”. These stats cost 10, so stacking your class’s primary stat is efficient, but you won’t feel too bad if STR or DEX pops up on your gear. The exception to this is that INT is useless for non-casters, but the alternatives that we’ve explored mess with player expectations and intuition to the point that I don’t think it’s worth the trade-off. (Maybe a more intelligent warrior can score more critical hits due to superior tactics, but then why wouldn’t mages get the same benefit?)

The final stats are Health Regen and Mana Regen, which each restore 1 of their respective stat every 2 seconds and cost a hefty 40 points each. It seems pricey, but they can go a long way to cutting downtime and keeping you going in a long fight (specifically, anything longer than 20 seconds).

Finally, what to do about one-handed vs. two-handed weapons? Ever since I found a “Lidless Wall” bone shield on my Sorceress in Diablo 2, I have been fascinated with the idea of being able to not only choose how to optimize my damage output, but being given the tools to make significant adjustments to my survivability even when playing the traditional “glass cannon” class. While developing the system we use in Written Realms, we decided that weapon choice would be a single decision point that could open up a lot of interesting build options. This tradeoff between offense and defense is defined as follows:

  • Attack Power and Spell Power is increased by 50% while wielding a two-handed weapon.
  • Resilience has a base mitigation of 25% while wielding a shield. Additionally, all shields provide a significant amount of armor and are classified as “light” or “heavy” the same way that other armor pieces are.

By implementing this, every character can explore a wide variety of build options suited to different playstyles and situations. Is your Cleric being focus fired down in a group PvP engagement? Pop on a shield so you can take the hits. Is your sword-and-board warrior getting chipped to death by that mage before you can take him out? Bust out that meaty 2H axe and cleave him in two before he can get a cast off!

Well, that’s the rundown of what we decided to do. The goal here isn’t necessarily to outline the “one true stat system”, but to go over the strengths and pitfalls of some possible approaches. What rules there are here can be broken, but should be done so consciously and with purpose. Above all, envision what your decisions mean for the player and what you incentivize, because that is exactly what they will do. Do you want every player to be able to participate from level 1? Then build around that! Do you want there to be a necessary grind before players have earned their place at the table? Go for it! An arcane system of 30 runes that must be hunted down so that they can be woven into a near infinite amount of spells and wards? Sounds hard, but sure! Just know that, ultimately, your intent and ambitions won’t be what gives your players a deep, compelling game; only the system that you create can do that.