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.

Now I need to just fix the Armor kind issue.

Good day everybody!

I come today to ask what I'm hoping will be a quick question, for the Hash class. What I basically need to do is I'm writting an Equipment Optimization system, which automatically equips each piece of equipment based off the highest stat(s) requested (highest .atk and .str for instance), which I've got semi-covered, but then I realized that I need the information to be stored in the format of a Hash, but I don't know how to automatically generate a hash like I need. It needs to list the Equipments' IDs => Equipments' Stats, like so...

Code:
hash = {1 => 112, 2 => 140, 3 => 175, 4 => 218}

But I need a method similiar to the 'Array.push(object)' method or the 'Array << object' method, so I can do...

Code:
hash = Hash.new
$data_weapons.each do |w|
  hash << {w.id => w.atk}
end

Is there a way to generate information into a Hash in a similiar fashion to this, or would I just be better off just using an Array in a similiar fashion and pretending its a hash?
 
I think your best bet would be to do it like that:
hash[key] = value

in your case
Code:
hash = Hash.new
$data_weapons.each do |w|
  hash[w.id] = w.atk
end
I don't think there's another way of doing it with hashes.
 

Zeriab

Sponsor

I very much dislike the idea of pushing data into a hash.
A Hash in ruby maps one object to another. (You could call it a HashMap, which is also what it is called in many other langauges)
You can create new mappings or change existing ones in the way Dargor showed.

For your problem I would suggest a different approach. I would suggest using arrays instead.
Note that the RPG::Weapon objects has its id as a property. We already have a mapping to it with $data_weapons so why create a new mapping?
If you want to make the player equip the weapon with the highest attack power you can consider this code snippet which does it for the player: (Whoever leads)
Code:
    # The player
    actor = $game_party.actors[0]
    # Get the equippable weapon set
    weapon_set = $data_classes[actor.class_id].weapon_set
    data = []
    # Unequip current weapon
    actor.equip(0, 0)
    # Find all weapons which can be equipped
    for i in 1...$data_weapons.size
      if $game_party.weapon_number(i) > 0 and weapon_set.include?(i)
        data.push($data_weapons[i])
      end
    end
    # Sort the equippable weapons in decreasing attack power order
    sorted_weapons = data.compact.sort {|w1, w2| w2.atk <=> w1.atk}
    # Get the best weapon
    best = sorted_weapons[0]
    # Equip the weapon
    actor.equip(0, best.id)

If the inline comments are not enough just ask which part you want me to explain in more details

*hugs*
- Zeriab
 
I did ultimately wind up doing it as an array built similiar to a hash. Here's what I wound up with, and it appears to be working fine now (I definately had to fix it, considering I submitted it to MACL earlier this year. It only listed the stats previously, now it lists [id, stat])

Here's what I did for weapons

Code:
class Game_Actor < Game_Battler
  #-----------------------------------------------------------------------------
  # * Alias Listings
  #-----------------------------------------------------------------------------
  alias_method :kn_macl_gm_actor_equip, :equip
  #-----------------------------------------------------------------------------
  # * Equip
  #-----------------------------------------------------------------------------
  def equip(equip_type, id)
    unless id < 0
      kn_macl_gm_actor_equip(equip_type, id)
    end
  end
  #-----------------------------------------------------------------------------
  # * Name      : Weapon Set
  #   Info      : Returns all weapon objects for an actor's class
  #   Author    : Kain Nobel
  #   Call Info : None
  #-----------------------------------------------------------------------------
  def weapon_set
    return $data_classes[@class_id].weapon_set
  end
  #-----------------------------------------------------------------------------
  # * Name      : Weapon Stats
  #   Info      : Returns a list of desired stats for the actor's weapon set
  #   Author    : Kain Nobel
  #   Call Info : Parameter is a string representing parameter in question
  #-----------------------------------------------------------------------------
  def weapon_stats(parameter)
    arr, weapons = Array.new, Array.new
    weapon_set.each do |id|
      if $game_party.weapons.has_key?(id)
        if $game_party.weapons[id] > 0
          weapons << id
        end
      end
    end
    weapons.sort!
    weapons.each do |id|
      case parameter
      when 'name' ; arr << [id, $data_weapons[id].name]
      when 'price'; arr << [id, $data_weapons[id].price]
      when 'atk'  ; arr << [id, $data_weapons[id].atk]
      when 'pdef' ; arr << [id, $data_weapons[id].pdef]
      when 'mdef' ; arr << [id, $data_weapons[id].mdef]
      when 'str'  ; arr << [id, $data_weapons[id].str_plus]
      when 'dex'  ; arr << [id, $data_weapons[id].dex_plus]
      when 'agi'  ; arr << [id, $data_weapons[id].agi_plus]
      when 'int'  ; arr << [id, $data_weapons[id].int_plus]
      else ; print(":"+parameter+": is not a valid parameter when\n",
      "checking for $game_actor["+@actor_id.to_s+"].weapon_set()")
      end
    end
    return arr
  end
  #-----------------------------------------------------------------------------
  # * Name      : Strongest Weapon
  #   Info      : Returns the strongest weapon, based on parameter
  #   Author    : Kain Nobel
  #   Call Info : Parameter is a string representing parameter in question
  #-----------------------------------------------------------------------------
  def strongest_weapon(parameter)
    arr, stats = Array.new, Array.new
    weapon_stats(parameter).each do |stat|
      stats << stat[1]
    end
    stats.sort!
    stats.reverse!
    stats.each do |stat|
      weapon_stats(parameter).each do |param|
        if param[1] == stat && stat > 0
          return param[0]
        end
      end
    end
    return -1
  end
  #-----------------------------------------------------------------------------
  # * Name      : Weakest Weapon
  #   Info      : Returns the weakest weapon, based on parameter
  #   Author    : Kain Nobel
  #   Call Info : Parameter is a string representing parameter in question
  #-----------------------------------------------------------------------------
  def weakest_weapon(parameter)
    arr, stats = Array.new, Array.new
    weapon_stats(parameter).each do |stat|
      stats << stat[1]
    end
    stats.sort!
    stats.each do |stat|
      weapon_stats(parameter).each do |param|
        if param[1] == stat && stat > 0
          return param[0]
        end
      end
    end
    return -1
  end
end

I had prettymuch done the same thing for armors, but threw armor_kind in as an argument, and everything works pretty decent now. I placed an Optimize option in my Equip Menu, and I optimize equipment like...

Code:
class Scene_Equip < SDK::Scene_Base
  #-----------------------------------------------------------------------------
  # * Optimize Equipment
  #-----------------------------------------------------------------------------
  def optimize_equip(stat)
    case stat
    when 0 ; @actor.equip(0, @actor.strongest_weapon('atk'))
    when 1 ; @actor.equip(0, @actor.strongest_weapon('pdef'))
    when 2 ; @actor.equip(0, @actor.strongest_weapon('mdef'))
    when 3 ; @actor.equip(0, @actor.strongest_weapon('agi'))
    end
    [1,2,3,4].each do |i|
      case stat
      when 0 ; @actor.equip(i, @actor.strongest_armor('str', i))
      when 1 ; @actor.equip(i, @actor.strongest_armor('pdef', i))
      when 2 ; @actor.equip(i, @actor.strongest_armor('mdef', i))
      when 3 ; @actor.equip(i, @actor.strongest_armor('agi', i))
      end
    end
  end

But I notice that the armor being equipped is the wrong kind, and in the default terms of...

Sheild : Equips Helmet
Helmet : Equips Armor
Armor : Equips Accessory
Accessory : Nothing

Thats how its equipping armors, did I do something wrong here? I'm sure its something simple, but how do I fix the armor_kind issue?

Code:
class Game_Actor < Game_Battler
  #-----------------------------------------------------------------------------
  # * Name      : Armor Set
  #   Info      : Returns all armor objects for an actor's class
  #   Author    : Kain Nobel
  #   Call Info : Kind ID for the Armors to check
  #-----------------------------------------------------------------------------
  def armor_set(kind = nil)
    if kind.nil?
      return $data_classes[@class_id].armor_set
    end
    armors = []
    ($data_classes[@class_id].armor_set).each do |armor|
      armors.push(armor) if $data_armors[armor].kind == kind
    end
    return armors
  end
  #-----------------------------------------------------------------------------
  # * Name      : Armor Stats
  #   Info      : Returns a list of desired stats for an actor's armor set
  #   Author    : Kain Nobel
  #   Call Info : Parameter is a string representing parameter in question
  #               Kind refers to the kind of amror it is
  #-----------------------------------------------------------------------------
  def armor_stats(parameter, kind = 0)
    arr, armors = Array.new, Array.new
    armor_set.each do |id|
      if $data_armors[id].kind == kind && $game_party.armors.has_key?(id)
        if $game_party.armors[id] > 0
          armors << id
        end
      end
    end
    armors.sort!
    armors.each do |id|
      case parameter
      when 'name' ; arr << [id, $data_armors[id].name]
      when 'price'; arr << [id, $data_armors[id].price]
      when 'atk'  ; arr << [id, $data_armors[id].atk]
      when 'pdef' ; arr << [id, $data_armors[id].pdef]
      when 'mdef' ; arr << [id, $data_armors[id].mdef]
      when 'str'  ; arr << [id, $data_armors[id].str_plus]
      when 'dex'  ; arr << [id, $data_armors[id].dex_plus]
      when 'agi'  ; arr << [id, $data_armors[id].agi_plus]
      when 'int'  ; arr << [id, $data_armors[id].int_plus]
      else ; print(":"+parameter+": is not a valid parameter when\n",
      "checking for $game_actor["+@actor_id.to_s+"].armor_set()")
      end
    end
    return arr
  end
  #-----------------------------------------------------------------------------
  # * Name      : Strongest Armor
  #   Info      : Returns the strongest armor, based on parameter and kind
  #   Author    : Kain Nobel
  #   Call Info : Parameter is a string representing parameter in question
  #               Kind is what kind of armor it is (shield, helmet, etc.)
  #-----------------------------------------------------------------------------
  def strongest_armor(parameter, kind = 0)
    arr, stats = Array.new, Array.new
    armor_stats(parameter, kind).each do |stat|
      stats << stat[1]
    end
    stats.sort!
    stats.reverse!
    stats.each do |stat|
      armor_stats(parameter, kind).each do |param|
        if param[1] == stat && stat > 0
          return param[0]
        end
      end
    end
    return -1
  end
end

BTW thank you both for your help so far, this should be the only thing I need to fix now.
 

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