Making it Rain Round 2 – Missing and Evading

Last week, I posted a little script that you could use for an attack which repeats at the end of each turn. It did what it was supposed to do, but lacked a number of key features. Let’s talk about one today – allowing the enemy to dodge the attack.

Since we’re simulating a lot of battle things now in our script, it’s time to really understand battle flow. Here’s the best chart I’ve found so far, a really good explanation of how battle works in RPG Maker. You’ll see that before we get into damage or anything like that, we need to know if the skill hits. There are two parts to it: does it hit, and did the enemy evade?

Familiarity with last week’s post is assumed – go check it out if you haven’t already!

Does It Hit?

Before we bother with calculating damage or anything like that (or playing the attack animation and sounds), we want to see if the skill hits. We get this with the attacker’s hit rate! This is accessed with a little thing called item_hit, which belongs to an actor. Item_hit works by taking the attacker and the skill, and returning their chance to hit. It calculates everything – whether the item is physical or magic, equipped items that impact the attacker’s chance to hit. It does everything for us. We then just need to generate a random number 0-100, and if that random number is below our chance to hit, we hit. Otherwise we miss. Additions to the meat of our script from last week are bolded and underlined

...
@log_window.add_text("Arrows continued to rain from the sky!") 
show_animation($game_troop.members, 18)
prng = Random.new
$game_troop.members.each { |enemy| 
     hit = prng.rand(100)
     evade = prng.rand(100
     if hit < $game_actors[1].item_hit($game_actors[1], $data_skills[3]) * 100
          low = ((($game_actors[1].atk * 4) - (enemy.def * 2)) * 0.8).floor
          high = ((($game_actors[1].atk * 4) - (enemy.def * 2)) * 1.2).ceil
          damage = (low..high).to_a.sample
          enemy.hp -= damage
          enemy.perform_damage_effect
          @log_window.add_text("#{enemy.name} took #{damage} damage!")
     else
          #handle missing
     end
     wait(60)
}
...

So what did we do? We made a new random number generator, and for each enemy, came up with a random number called “hit.” Then we asked if hit was less than our archer’s chance to hit with Skill # 3 in our database. Skill 3 is, of course, Arrow Rain. We multiply by 100, since item_hit returns a percentage. If that’s not the case, we go to our else branch, which isn’t filled in yet. But will be soon!

Did the Enemy Dodge?

Hit chance isn’t the only way to miss. Remember, an enemy can also evade. So let’s do that too! Recall that we set an enemy’s evade property in the database:

Evasion rate is in addition to the player's chance to hit, so don't set this too high if your player can regularly miss!

Evasion rate is in addition to the player’s chance to hit, so don’t set this too high if your player can regularly miss!

This means that a slime has a 5% chance to evade. We’ll take another random number, 0-100, and if it’s above our slime’s chance to evade (5%) do damage; otherwise, handle an evade. And how do we get the slime’s chance to evade? Item_eva of course! Check it out:

...
@log_window.add_text("Arrows continued to rain from the sky!") 
show_animation($game_troop.members, 18)
prng = Random.new
$game_troop.members.each { |enemy| 
     hit = prng.rand(100)
     evade = prng.rand(100)
     if hit < $game_actors[1].item_hit($game_actors[1], $data_skills[3]) * 100
          if evade > enemy.item_eva(enemy, $data_skills[3]) * 100
               low = ((($game_actors[1].atk * 4) - (enemy.def * 2)) * 0.8).floor
               high = ((($game_actors[1].atk * 4) - (enemy.def * 2)) * 1.2).ceil
               damage = (low..high).to_a.sample
               enemy.hp -= damage
               enemy.perform_damage_effect
               @log_window.add_text("#{enemy.name} took #{damage} damage!")
          else
               #handle evading
          end
     else
          #handle missing
     end
     wait(60)
}
...

Handling Evading and Missing

As it turns out, when we’re not doing damage, life is a lot easier. We only need to play a sound and show a little text. To play the sound, we want to reference whatever you’ve put in your database as the missing or evading sound. You can set that here:

We're using evasion, and not magic evasion, because Arrow Rain is a physical skill.

We’re using evasion, and not magic evasion, because Arrow Rain is a physical skill.

We access these with Sound.play_evasion and Sound.play_miss. Easy!

Similarly easy is the log window. Not only can we .add_text to the log window, we can call function display_evasion and display_miss for easy displays.

So our evading and missing looks just like this:

else
          Sound.play_evasion
          @log_window.display_evasion(enemy, $data_skills[3])
     end
else
     Sound.play_miss
     @log_window.display_miss(enemy, $data_skills[3])
end
...

Putting It All Together

And so, our final, miss-allowing script looks like this:

 

class Scene_Battle
     alias :old_turn_end :turn_end 

     def turn_end
          if (1..3).include?($game_variables[10])
               @log_window.add_text("Arrows continued to rain from the sky!") 
               show_animation($game_troop.members, 18)
               prng = Random.new
               $game_troop.members.each { |enemy| 
                    hit = prng.rand(100)
                    evade = prng.rand(100)

                    #hit
                    if hit < $game_actors[1].item_hit($game_actors[1], $data_skills[3]) * 100
                         if evade > enemy.item_eva(enemy, $data_skills[3]) * 100
                              low = ((($game_actors[1].atk * 4) - (enemy.def * 2)) * 0.8).floor
                              high = ((($game_actors[1].atk * 4) - (enemy.def * 2)) * 1.2).ceil
                              damage = (low..high).to_a.sample
                              enemy.hp -= damage
                              enemy.perform_damage_effect
                              @log_window.add_text("#{enemy.name} took #{damage} damage!")
                         else
                              #evade
                              Sound.play_evasion
                         end
                     else
                     #miss
                         Sound.play_miss
                         @log_window.display_miss(enemy, $data_skills[3])
                     end
                     wait(60)
               }
          $game_variables[10] -= 1
          elsif $game_variables[10] == 4
          $game_variables[10] -= 1
     end
     old_turn_end
 end
end
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s