Hi everyone, I’m going to present some basic information about editing the battle formulas in RMVX. For the most part, this information is semi-documented in the RGSS2 help file included with RMVX but is pretty incomplete. Anyway, let’s get started.

 

Step 1: Open the Script Editor and scroll down to where it says “Game_Battler.” This is the script for the engine that handles battle calculations. Left-click on the script to open it, and scroll all the way down to line 637. You’ll notice green text (green text is a comment or series of comments that are not compiled by the engine) that says the following:

 Calculation of Damage From Normal Attack

  #     attacker : Attacker

  #    The results are substituted for @hp_damage

 Here’s the whole chunk of code you’ll be working with and a screenshot:

Game_Battler script section

Game_Battler script section

 

 #————————————————————————–

  # * Calculation of Damage From Normal Attack

  #     attacker : Attacker

  #    The results are substituted for @hp_damage

  #————————————————————————–

  def make_attack_damage_value(attacker)

    damage = attacker.atk * 4 – self.def * 2        # base calculation

    damage = 1 if damage < 0                        # if negative, make 1

    damage *= elements_max_rate(attacker.element_set)   # elemental adjustment

    damage /= 100

    if damage == 0                                  # if damage is 0,

      damage = rand(2)                              # half of the time, 1 dmg

    elsif damage > 0                                # a positive number?

      @critical = (rand(100) < attacker.cri)        # critical hit?

      @critical = false if prevent_critical         # criticals prevented?

      damage *= 3 if @critical                      # critical adjustment

    end

    damage = apply_variance(damage, 20)             # variance

    damage = apply_guard(damage)                    # guard adjustment

    @hp_damage = damage                             # damage HP

  end

 Right below that text on line 642 is where the code that calculates damage from normal attacks in the game begins.

Step 2: The next two lines of code are the ones you can change without dramatically affecting how the editor works or needing to know how to code in Ruby.

 damage = attacker.atk * 4 – self.def * 2        # base calculation

    damage = 1 if damage < 0   

So, that first line (line 643) is the basic damage calculation for normal damage. It means that the attacker’s damage is first multiplied by 4. Next, the defender’s defense is multiplied by 2. Lastly, the final defense value is subtracted from the final attack value. Here’s an example:

Player 1: Attack value = 2.

Enemy Defense value = 2.

The math would look like this: (2 x 4) – (2 x 2). This works out to 8 – 4, or a base damage of 4.

The “atk” value calculation is determined on line 156, and the “def” value is determined on line 166. I’ve pasted the code below.

# * Get Attack

  #————————————————————————–

  def atk

    n = [[base_atk + @atk_plus, 1].max, 999].min

    for state in states do n *= state.atk_rate / 100.0 end

    n = [[Integer(n), 1].max, 999].min

    return n

  end

  #————————————————————————–

  # * Get Defense

  #————————————————————————–

  def def

    n = [[base_def + @def_plus, 1].max, 999].min

    for state in states do n *= state.def_rate / 100.0 end

    n = [[Integer(n), 1].max, 999].min

    return n

  end

Note that in both of the code chunks above, base_atk and base_def are actually calculated in the Game_Actor script, not in the Game_Battler script that we’re currently looking at. If you’re inclined to take a look, check out line 226 for the beginning of the base_atk calculation and line 234 for base_def. They are calculated by a combination of your character’s stats, level and weapon and armor values. 

Next is line 644. This line of code represents the minimum damage a normal attack can inflict. Here, I’ve already set this value to 1. I decided that in my game, if you get hit, even if you fully defend, you still take 1 point of damage. The math for that code works as follows: if the damage is less than 0 (notice the < symbol), set the damage value to 0. I changed it to say “if the damage value is less than 0, set the minimum damage to 1.”

The only problem you can run into here, though, is that in lines 647 and 648, i.e. the following two lines of code:

if damage == 0                                 

      damage = rand(2)

…you can end up with a situation where when the damage is calculated as less than 0, your minimum damage is 1, but when your damage is actually equal to 0, the minimum damage is 1 only half the time. Pretty weird. If you want to set the minimum damage to 1 all the time, just change line 648 to this:

damage = 1

So what is “rand(2)” ? That’s a method that creates a random number between 0 and 1. Normally in Ruby, the “rand” method only creates a random number between 0 and 1. If you check the RGSS2 documentation in RMVX, you can see how the rand() method works. Look in Standard Library then Built-in Functions. Basically, rand() returns (i.e. gives you) an integer greater than or equal to 0 but less than the maximum. The number in the parentheses is the max. So if your max is 2, as it is in this case, you’ll end up with a number greater than or equal to 0 but less than 2. The only possible value here is 1.

If you look at line 649, the formula there checks to see whether your character has scored a critical hit (or whether an enemy has scored one on you). Here’s how that line works. The @critical is a variable. The after the = sign generates a random number between 0 and 99 (again, the “rand” method, explained above) and checks to see if it’s less than the attacker’s “crit” value, which is basically the critical hit chance for a given character or enemy. The next line checks to see if there’s a condition called “prevent_critical” active. If it is, it cancels the effect of the critical hit. If this condition isn’t present, it multiplies the damage calculated up to this point by 3. In our example, if our base damage was 4, the critical hit adjustment would multiply that by 3 and make it equal to 12.

Next on line 654, where it says “apply_variance” you have the amount that is automatically calculated and added to the basic damage calculation entered above. The actual method that determines the variance starts on line 732. I’ve pasted it below:

 

#————————————————————————–

  # * Applying Variance

  #     damage   : Damage

  #     variance : Degree of variance

  #————————————————————————–

  def apply_variance(damage, variance)

    if damage != 0                                  # If damage is not 0

      amp = [damage.abs * variance / 100, 0].max    # Calculate range

      damage += rand(amp+1) + rand(amp+1) – amp     # Execute variance

    end

    return damage

  end

Basically, the calculation for the variance begins by finding the damage.abs value multiplied by the variance amount stated after the word “damage” in the parentheses on line 654 (the default value listed is 20), divided by 100. Then the word “max” means ”take the maximum value from this calculation.” FYI, “damage.abs” is Ruby-speak for ”get the absolute value of the damage value calculated on line 643.” So, all of that determines the range for the variance, and that range is stored in an array variable called “amp.”  The next line (line number 740) actually determines the amount of damage variance that will be applied to the damage calculated on line 643 of the code. That line takes the variable “amp” and says, “get me a random number between the value of amp+1 and 0, then add that to the same value minus the value of ‘amp’ determined above, and then add this amount to the damage calculated on line 643.”

Whew…confused yet? If you plug some numbers into all that math it becomes a lot clearer. Let’ s use a base damage of 10 as an example:

amp = (10 x 20)/100, which equals 2.

The damage would be equal to a random number between 0 and 2,+1. This sets the minimum range for the random number to 1 and the maximum range to 2 . That gets added to another randomly generated number between 1 and and 2. Then the value of “amp” (2 in this case) is subtracted from that amount. Let’s say we ended up with 2 + 2 – 2. The amount added to the damage would end up being 2 points. 

Frankly, changing the variance a lot doesn’t actually change the amount your damage varies by much. Because on line 740 the value of “amp” is subtracted after adding two random numbers together (with the possible maximumvalue for each random number being equal to “amp”), the highest damage variance you can end up with is equal to “amp” itself. If “amp” is 5, your max damage variance will be 5. If you want large swings, you could make the variance a huge number (like 100 or 500 or something). I wouldn’t alter the equation on line 740, though, because you could end up with really massive variances in damage.

The “apply_guard” method used on line 655 only applies if your character has the “super guard” ability. Line 656 actually applies that final damage value (with variance and everything) to the hit points of the character (enemy or actor) being affected.

Now that I’ve explained what all that code means, the most important line to change, if you want to dramatically alter how damage works, is line 643. Here are some examples:

Here’s normal line 643: damage = attacker.atk * 4 – self.def * 2

Let’s make it so that the attacker has a huge advantage over the defender, i.e. attacks are very lethal.

Alt 643: damage = attacker.atk * 5 – self.def * 1

If the base “attacker.atk” is equal to 5, and “self.def” is equal to 5, then the base damage for the attack, even though the attacker’s attack value and enemy’s defense values are the same, would be (5 x 5) – (5 x 1), or 20. 

So, after going through all of that, I hope you get an idea as to how you can alter how damage is calculated. As you can see, even changing some basic things via scripting requires a solid understanding of the code you’re changing. What most scripters actually do is use bits and pieces from the base scripts and override them with entirely new scripts that provide the type of gameplay systems they’re looking for.

I’m still learning Ruby, so for now the next few posts, this is as much scripting as I’m going to talk about, though I do plan to tackle this topic again in the next couple of weeks. If you have any questions about what I’ve written, please send me a comment. Also, if you’re an experienced scripter and you noticed any flaws in my explanation, feel free to point them out. I have no problem admitting mistakes at this stage, and I want to provide correct info to any readers here. 

Next up, back to somewhat simpler things: mapping and eventing.