Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

[VX] Damage Formulas

Status
Not open for further replies.
I hate big numbers.

My characters start off with 25 HP, and towards the end of the game they'd have 50, maybe a hundred. It'd be a nice clean number like that, up by 5 or so with each level. Similarly, I want their attack powers to be 2, 3, 4, etc. Weapons would add 1, 2, 3 or whatever to that number. Enemies have 5-10 HP early in the game, and they should take damage equal to your character's attack. If they have defense at all (many will have a defense of 0), then it would be subtracted from the damage done.

For example:

Hero has an attack value of three, with a weapon that adds 1, making it 4. The enemy has a defense of 1. When I attack, I should do 3 damage (4-1).

If you're familiar with Paper Mario, it's very similar to that. Bascailly, I'm trying to seriously simplify battle formulas.

I'm totally lost when it comes to scripting, and after digging for fifteen minutes through Scene_Battle, Etheon directed me to Game_Battler, around lines 600+. Cool, we were getting somewhere.

The plan was that I'd be able do figure this out myself. Changing formulas shouldn't be hard, right? But I'm still totally confused.

I'm using VX, by the way.
 

khmp

Sponsor

etheon was right. There's a method called "make_attack_damage_value" inside Game_Battler. Basically when you or an enemy selects attack the one being attacked calls this method to figure out how much they get hurt. Its very important to realize that the one being attacked is the one who decides the damage. All right so it sounds like you want to make the majority of your adjustments here. For starters you might want to remove the multipliers and variance. Try changing the first line to (attacker.atk - self.def) just a straight linear run.

Code:
#==============================================================================
# ** Game_Battler
#------------------------------------------------------------------------------
#  This class deals with battlers. It's used as a superclass of the Game_Actor
# and Game_Enemy classes.
#==============================================================================
class Game_Battler
  #--------------------------------------------------------------------------
  # * Calculation of Damage From Normal Attack
  #     attacker : Attacker
  #    The results are substituted for @hp_damage
  #--------------------------------------------------------------------------
  def make_attack_damage_value(attacker)
    # Base calculation
    damage = attacker.atk - self.def

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

    # Guard adjustment
    damage = apply_guard(damage)

    # If the damage came out to be zero give the chance for making at
    # least 1 damage.
    if damage == 0
      # 0 or 1 damage.
      damage = rand(2)
    else
      # Decide whether or not we have a critical.
      @critical = (rand(100) < attacker.cri)

      # If there was a critical and it is prevented by the battler.
      @critical = false if prevent_critical

      # Double damage if successful critical.
      damage *= 2 if @critical
    end

    # Our final damage value is stored here.
    @hp_damage = damage               
  end
end

Something like that. Its very formulaic. Easy to understand and interpret. I removed the elemental damage and only applied guarding to damage. You might want to throw out criticals if you want to always be able to predict the damage.

Good luck with it Despain! :thumb:
 

e

Sponsor

Methods changed in Game_Battler:
element_rate:
Code:
  #--------------------------------------------------------------------------
  # * Get Element Change Value
  #     element_id : element ID
  #--------------------------------------------------------------------------
  def element_rate(element_id)
    return 1
  end
atk:
Code:
  #--------------------------------------------------------------------------
  # * Get Attack
  #--------------------------------------------------------------------------
  def atk
    n = [base_atk + @atk_plus, 1].max
    
    # Apply states
    self.states.each { |s| n *= s.atk_rate / 100.0 }
    
    # Round and make sure it's not less than 1.
    return [Integer(n), 1].max
  end
def:
Code:
  #--------------------------------------------------------------------------
  # * Get Defense
  #--------------------------------------------------------------------------
  def def
    n = [base_def + @def_plus, 1].max
    
    # Apply states
    self.states.each { |s| n *= s.def_rate / 100.0 }
    
    # Round and make sure it's above 0
    return [Integer(n), 1].max
  end
make_attack_damage_value:
Code:
  #--------------------------------------------------------------------------
  # * Calculation of Damage From Normal Attack
  #     attacker : Attacker
  #    The results are substituted for @hp_damage
  #--------------------------------------------------------------------------
  def make_attack_damage_value(attacker)
    damage = attacker.atk - self.def                  # base calculation
    damage = 0 if damage < 0                          # if negative, make 0
    damage *= elements_max_rate(attacker.element_set) # elemental adjustment
    
    if damage > 0                                     # a positive number?
      @critical = (rand(100) < attacker.cri)          # critical hit?
      @critical = false if prevent_critical           # criticals prevented?
      damage *= 2 if @critical                        # critical adjustment
    end

    @hp_damage = damage                               # damage HP
  end
make_obj_damage_value:
Code:
  #--------------------------------------------------------------------------
  # * Calculation of Damage Caused by Skills or Items
  #     user : User of skill or item
  #     obj  : Skill or item (for normal attacks, this is nil)
  #    The results are substituted for @hp_damage or @mp_damage.
  #--------------------------------------------------------------------------
  def make_obj_damage_value(user, obj)
    damage = obj.base_damage                        # get base damage
    if damage > 0                                   # a positive number?
      damage += user.atk * obj.atk_f                # Attack F of the user
      damage += user.spi * obj.spi_f                # Spirit F of the user
      unless obj.ignore_defense                     # Except for ignore defense
        damage -= self.def * obj.atk_f              # Attack F of the target
        damage -= self.spi * obj.spi_f              # Spirit F of the target
      end
      damage = 0 if damage < 0                      # If negative, make 0
    elsif damage < 0                                # a negative number?
      damage += user.atk * obj.atk_f                # Attack F of the user
      damage += user.spi * obj.spi_f                # Spirit F of the user
    end
    damage *= elements_max_rate(obj.element_set)    # elemental adjustment

    if obj.damage_to_mp  
      @mp_damage = damage                           # damage MP
    else
      @hp_damage = damage                           # damage HP
    end
  end

Game_Enemy:
Code:
  #--------------------------------------------------------------------------
  # * Get Element Change Value
  #     element_id : element ID
  #--------------------------------------------------------------------------
  def element_rate(element_id)
    rank = enemy.element_ranks[element_id]
    result = [0,2,1.5,1,0.5,0,-1].at(rank)
    for state in states
      result /= 2 if state.element_set.include?(element_id)
    end
    return result
  end

Game_Actor:
Code:
  #--------------------------------------------------------------------------
  # * Get Element Change Value
  #     element_id : element ID
  #--------------------------------------------------------------------------
  def element_rate(element_id)
    rank = self.class.element_ranks[element_id]
    result = [0,2,1.5,1,0.5,0,-1].at(rank)
    for armor in armors.compact
      result /= 0.2 if armor.element_set.include?(element_id)
    end
    for state in states
      result /= 0.2 if state.element_set.include?(element_id)
    end
    return result
  end

That is, assuming that you've adjusted the elements settings.

And just because it's a long post, I'll spite khmp.
 
I'm was attempting to accomplish the same.  Etheon's changes worked like a charm, except for enemy's attacks.
If actor's def greater than or equal to monster's attack, it would do 0 damage, as it should.  But if monster's attack is greater than actor's def, the damage dealt is multiplied by 100.
Changing this line:
    return 1 if element_set.empty?
under elements_max_rate in Game_Battler seems to have fixed it.  It's late in the morning, so I'm wondering if this is just a bad fix that will bonk something else.
 
Status
Not open for further replies.

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top