Home » How to develop RPG Damage Formulas?

How to develop RPG Damage Formulas?


Creating formulas like this requires knowledge of elementary mathematical functions – the things you learned about in Algebra and Pre-calculus class.

Once you have those mastered, just ask yourself (replace “value” with “damage,” or “health,” or “speed” or whatever):

  • Do you want the value to grow at a constant rate? Use a linear function.
  • Do you want the value to grow slow at first, but fast later? Use a polynomial or exponential function.
  • Do you want the value to grow fast at first, and slow down later? Use an nth-root or logarithmic function.
  • Do you want the value to grow slowly at the start/end but fast in the middle? Or do you want it to grow quickly but still have an upper-bound? Use a sigmoid curve, such as atan or the logistic function.
  • Do you want the value to oscillate? Use a sin or some other wave.

Then just tweak it (add/multiply stuff, change the base-value, etc) until it feels right. A graphing calculator will help you visualize how changes to the parameters will affect the function.

By the way, the problems you are experiencing are due to integer overflows.

Use variable-types that are large enough to hold the numbers you’re working with. Sizes differ by platform in C++, but using the 32-bit Visual Studio compiler, unsigned int is 32-bit, while unsigned __int64 (MS-specific) is 64-bit. Also consider using a double.

Additionally, try to reorganize your operations so that you don’t encounter such large numbers in the first place (for example, rather than MDef * MDef / 110, do (int)((float)MDef / 110 * MDef)).

My Characters stats are composed of the following:

There’s your real problem: you defined your stats before defining what those stats actually mean. You’re putting the cart before the horse.

Look at how D&D (tabletop) works. “Strength” doesn’t mean anything by itself; it only means something because there’s a rule that says, “Add your strength bonus to your melee attack.” That rule is part of D&D’s combat rules. Without the combat rules, “Strength” is generally a meaningless quantity.

The first question you need to ask yourself is this: how much differentiation do I want between characters? Again, look at D&D. There, they have 6 basic stats. These stats define different dimensions of play for characters. A character with a high Dexterity will have different options from a character with low Dexterity.

But the reason for even that difference all comes back to rules. A high Dexterity means bonuses to ranged attacks; you can hit more often with ranged attacks. So just between Strength and Dexterity, you have two dimensions of play: ranged vs. melee.

Intelligence and Wisdom also form something of a pairing, but these interact more with specific classes. Int makes Wizards and other arcane spellcasters better (or possible under some rulesets), Wisdom is vital for Clerics and other divine spellcasters. Because divine and arcane spells have different spell lists, these two stats are involved in different dimensions of play.

You need to define the basic rules around stats before you can define growth progression functions and the like. You don’t need specifics; you don’t need to say that “each point of strength is added into the random roll to determine if a melee attack hits.” What you need are meta-rules like “dexterity makes ranged attackers better.” You can figure out exactly how it makes them better later on.

There are different ways to progress characters. A common old-school Final Fantasy trick was to simply use the character’s level as part of their damage computations. This could be simply multiplying the level by the appropriate stat, or it could mean applying a function to the character’s level. Say, a quadratic progression, so that the rate of a character’s damage would increase per level.

However you want your combat functions to work, they need to take into account progression. Your functions need hooks for progression.

D&D has a funny way of progression. It is part class-based; every time you go up in level, you get new class features and a flat bonus to your to-hit, based on your character class. However, some class features got better by themselves. Spells in D&D would have progression built into them. A spell might do 1d4 damage per 2 levels of a spellcaster above the first. So every other wizard level makes that spell better.

D&D also used item-based progression heavily. Until 4th edition, item-based progression was mainly for fighting characters, but even in older editions, spellcasters had items that gave them stat buffs or other adjustments (or flat out gave them spells).

So items are another thing your combat functions need to take into account. Do items just buff one or more stats while equipped, or do they do other things as well? D&D was a bit odd, in that stats rarely changed; weapons simply did XdY damage, possibly with a bonus based on one of your stats. And that was that. So your only way to do more damage in battle was to find a better weapon. In many videogame RPGs, they take level into account in addition to a weapon.

Your formulas seem pretty complicated. I’m not sure how professional RPG developers handle this, but I’d recommend on focusing on simplicity. Try to find the simplest possible formula you can that still incorporates the range of stats you want to use. For instance, could you have stats modify each other prior to damage calculation, rather than modifying the damage during the calculation? Once you’ve got a formula in mind, I’d try graphing it for a wide range of possible values to see how it will behave as players level up. Obviously the fewer variables you have, them more feasible this will be.

Additionally, BlueRaja provided an important explanation of why you might be seeing unexpected values at higher stat levels. Using unsigned types and checking for overflows will be important.

Related Solutions

Custom query with Castle ActiveRecord

In this case what you want is HqlBasedQuery. Your query will be a projection, so what you'll get back will be an ArrayList of tuples containing the results (the content of each element of the ArrayList will depend on the query, but for more than one value will...

What is the “You have new mail” message in Linux/UNIX?

Where is this mail? It's likely to be in the spool file: /var/mail/$USER or /var/spool/mail/$USER are the most common locations on Linux and BSD. (Other locations are possible – check if $MAIL is set – but by default, the system only informs you about...

How can I find the implementations of Linux kernel system calls?

System calls aren't handled like regular function calls. It takes special code to make the transition from user space to kernel space, basically a bit of inline assembly code injected into your program at the call site. The kernel side code that "catches" the...

Is a composite index also good for queries on the first field?

It certainly is. We discussed that in great detail under this related question: Working of indexes in PostgreSQL Space is allocated in multiples of MAXALIGN, which is typically 8 bytes on a 64-bit OS or (much less common) 4 bytes on a 32-bit OS. If you are not...

Explaining computational complexity theory

Hoooo, doctoral comp flashback. Okay, here goes. We start with the idea of a decision problem, a problem for which an algorithm can always answer "yes" or "no." We also need the idea of two models of computer (Turing machine, really): deterministic and...

Building a multi-level menu for umbraco

First off, no need pass the a parent parameter around. The context will transport this information. Here is the XSL stylesheet that should solve your problem: <!-- update this variable on how deep your menu should be --> <xsl:variable...

How to generate a random string?

My favorite way to do it is by using /dev/urandom together with tr to delete unwanted characters. For instance, to get only digits and letters: tr -dc A-Za-z0-9 </dev/urandom | head -c 13 ; echo '' Alternatively, to include more characters from the OWASP...

How to copy a file from a remote server to a local machine?

The syntax for scp is: If you are on the computer from which you want to send file to a remote computer: scp /file/to/send username@remote:/where/to/put Here the remote can be a FQDN or an IP address. On the other hand if you are on the computer wanting to...

What is the difference between curl and wget?

The main differences are: wget's major strong side compared to curl is its ability to download recursively. wget is command line only. There's no lib or anything, but curl's features are powered by libcurl. curl supports FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP,...

Using ‘sed’ to find and replace [duplicate]

sed is the stream editor, in that you can use | (pipe) to send standard streams (STDIN and STDOUT specifically) through sed and alter them programmatically on the fly, making it a handy tool in the Unix philosophy tradition; but can edit files directly, too,...

How do I loop through only directories in bash?

You can specify a slash at the end to match only directories: for d in */ ; do echo "$d" done If you want to exclude symlinks, use a test to continue the loop if the current entry is a link. You need to remove the trailing slash from the name in order for -L to...

How to clear journalctl

The self maintenance method is to vacuum the logs by size or time. Retain only the past two days: journalctl --vacuum-time=2d Retain only the past 500 MB: journalctl --vacuum-size=500M man journalctl for more information. You don't typically clear the journal...

How can I run a command which will survive terminal close?

One of the following 2 should work: $ nohup redshift & or $ redshift & $ disown See the following for a bit more information on how this works: man nohup help disown Difference between nohup, disown and & (be sure to read the comments too) If your...

Get exit status of process that’s piped to another

bash and zsh have an array variable that holds the exit status of each element (command) of the last pipeline executed by the shell. If you are using bash, the array is called PIPESTATUS (case matters!) and the array indicies start at zero: $ false | true $...

Execute vs Read bit. How do directory permissions in Linux work?

When applying permissions to directories on Linux, the permission bits have different meanings than on regular files. The read bit (r) allows the affected user to list the files within the directory The write bit (w) allows the affected user to create, rename,...

What are the pros and cons of Vim and Emacs? [closed]

I use both, although if I had to choose one, I know which one I would pick. Still, I'll try to make an objective comparison on a few issues. Available everywhere? If you're a professional system administrator who works with Unix systems, or a power user on...