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.

Indirect Editing of a Hash

Hello, all you happy people.

I began an experiment about 2 hours ago, just to see if I could make it work.  The result is the following script:
Code:
#==============================================================================
# ** Game_SelfVariables
#------------------------------------------------------------------------------
#  This class handles self variables. It's a wrapper for the built-in class
#  "Hash." Refer to "$game_self_variables" for the instance of this class.
#==============================================================================

class Game_SelfVariables
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize
    @data = {}
  end
  #--------------------------------------------------------------------------
  # * Get Self Variable
  #     key : key
  #--------------------------------------------------------------------------
  def [](key)
    return @data[key] == nil ? 0 : @data[key]
  end
  #--------------------------------------------------------------------------
  # * Set Self Variable
  #     key   : key
  #     value : The value to which you want to set a variable.
  #--------------------------------------------------------------------------
  def []=(key, value)
    @data[key] = [[value, -99999999].max, 99999999].min
  end
end


#==============================================================================
# ** Interpreter
#==============================================================================
class Interpreter
  
  #--------------------------------------------------------------------------
  # * Set Self Variable to (value)
  #--------------------------------------------------------------------------
  def set_self_variable(variable, value)
    # If event ID is valid
    if @event_id > 0
      # Make a self variable key
      key = [$game_map.map_id, @event_id, variable]
      # Change self variable
      $game_self_variables[key] = value
    end
    # Refresh map
    $game_map.need_refresh = true
    # Continue
    return true
  end

  #--------------------------------------------------------------------------
  # * Add (value) to Self Variable
  #--------------------------------------------------------------------------
  def add_self_variable(variable, value)
    # If event ID is valid
    if @event_id > 0
      # Make a self variable key
      key = [$game_map.map_id, @event_id, variable]
      # Change self variable
      $game_self_variables[key] = ($game_self_variables[key] + value)
    end
    # Refresh map
    $game_map.need_refresh = true
    # Continue
    return true
  end
  
  #--------------------------------------------------------------------------
  # * Subtract (value) from Self Variable
  #--------------------------------------------------------------------------
  def sub_self_variable(variable, value)
    # If event ID is valid
    if @event_id > 0
      # Make a self variable key
      key = [$game_map.map_id, @event_id, variable]
      # Change self variable
      $game_self_variables[key] = ($game_self_variables[key] - value)
    end
    # Refresh map
    $game_map.need_refresh = true
    # Continue
    return true
  end
  
  #--------------------------------------------------------------------------
  # * Multiply Self Variable by (value)
  #--------------------------------------------------------------------------
  def mul_self_variable(variable, value)
    # If event ID is valid
    if @event_id > 0
      # Make a self variable key
      key = [$game_map.map_id, @event_id, variable]
      # Change self variable
      $game_self_variables[key] = ($game_self_variables[key] * value)
    end
    # Refresh map
    $game_map.need_refresh = true
    # Continue
    return true
  end
  
  #--------------------------------------------------------------------------
  # * Divide Self Variable by (value)
  #--------------------------------------------------------------------------
  def sub_self_variable(variable, value)
    # If event ID is valid
    if @event_id > 0
      # Make a self variable key
      key = [$game_map.map_id, @event_id, variable]
      # Change self variable
      if value != 0
        $game_self_variables[key] = ($game_self_variables[key] / value)
      end
    end
    # Refresh map
    $game_map.need_refresh = true
    # Continue
    return true
  end
  
  #--------------------------------------------------------------------------
  # * Set Self Variable to Remainder
  #--------------------------------------------------------------------------
  def rem_self_variable(variable, value)
    # If event ID is valid
    if @event_id > 0
      # Make a self variable key
      key = [$game_map.map_id, @event_id, variable]
      # Change self variable
      if value != 0
        $game_self_variables[key] = ($game_self_variables[key] % value)
      end
    end
    # Refresh map
    $game_map.need_refresh = true
    # Continue
    return true
  end
  
  #--------------------------------------------------------------------------
  # * Get current value of Self Variable
  #--------------------------------------------------------------------------
  def self_variable(variable)
    # If event ID is valid
    if @event_id > 0
      # Make a self variable key
      key = [$game_map.map_id, @event_id, variable]
      # Check self variable
      value = $game_self_variables[key]
    end
    # Refresh map
    $game_map.need_refresh = true
    # Continue
    return value
  end
end

#==============================================================================
# ** Scene_Title
#------------------------------------------------------------------------------
# Aliases are made to properly initialize self variables.
#==============================================================================
class Scene_Title
  alias ds_self_variables_command_new_game command_new_game
  def command_new_game
    $game_self_variables = Game_SelfVariables.new
    ds_self_variables_command_new_game
  end
  
  alias ds_self_variables_battle_test battle_test
  def battle_test
    $game_self_variables = Game_SelfVariables.new
    ds_self_variables_battle_test
  end
end

#==============================================================================
# ** Scene_Save
#------------------------------------------------------------------------------
# Adding $game_self_variables.
#==============================================================================
class Scene_Save
  alias ds_self_variables_write_save_data write_save_data
  def write_save_data(file)
    ds_self_variables_write_save_data(file)
    Marshal.dump($game_self_variables, file)
  end
end

#==============================================================================
# ** Scene_Load
#------------------------------------------------------------------------------
# Adding $game_self_variables.
#==============================================================================
class Scene_Load
  alias ds_self_variables_read_save_data read_save_data
  def read_save_data(file)
    ds_self_variables_read_save_data(file)
    $game_self_variables        = Marshal.load(file)
  end
end
As you can see, it's not the cleanest thing in the world, and I find myself frustrated.  In its current version, the code requires different commands for every operation that could be performed on a self_variable.  Thus, I've ended up with the following command list (all of which are meant to be called from the Interpreter):
Code:
self_variable(variable)     #returns the current value of the variable.
set_self_variable(variable, value)     #Sets variable to value.
add_self_variable(variable, value)     #Adds value to variable.
sub_self_variable(variable, value)     #Subtracts value from variable.
mul_self_variable(variable, value)     #Multiplies variable by value.
div_self_variable(variable, value)     #Divides variable by value (with divide-by-zero protection.)
rem_self_variable(variable, value)     #Get the remainder when the variable is divided by the value.
It's not elegant in the least.  What I wanted to do, and was unable to figure out, was how to translate in the Interpreter so that I could do a call something like this:
Code:
self_variables[variable] += value
In other words, what I'm wanting is for the event to be able to look at its relevant chunk of $game_self_variables as if it were an array, like $game_variables.  I just don't know how to do the definition of the middle-layer in Interpreter so that I can make that kind of call.

Once I get this fixed, I intend to see if I can find a way to comment parse a page so that if a certain comment is on the page, it'll check its self_variables for a page condition, but otherwise it will check $game_variables as normal.

The goal is to produce something that not only works, but is user-friendly within the Call Script command or the Script area of a Conditional Branch.

====================================================
Edit
====================================================

I think I've found a solution.  What I've done is create a class that Interpreter calls as a child that mimics an array just enough for the interaction I need.  I think it does, anyway.  Thus, with a new script version to post, the question becomes thus:  Is there something I've done wrong here that's glaringly obvious to the more experienced?

Code:
#==============================================================================
# ** Game_SelfVariables
#------------------------------------------------------------------------------
#  This class handles self variables. It's a wrapper for the built-in class
#  "Hash." Refer to "$game_self_variables" for the instance of this class.
#==============================================================================

class Game_SelfVariables
  #--------------------------------------------------------------------------
  # * Object Initialization
  #--------------------------------------------------------------------------
  def initialize
    @data = {}
  end
  #--------------------------------------------------------------------------
  # * Get Self Variable
  #     key : key
  #--------------------------------------------------------------------------
  def [](key)
    return @data[key] == nil ? 0 : @data[key]
  end
  #--------------------------------------------------------------------------
  # * Set Self Variable
  #     key   : key
  #     value : the variable's value
  #--------------------------------------------------------------------------
  def []=(key, value)
    @data[key] = [[value, -99999999].max, 99999999].min
  end
end


#==============================================================================
# ** Self Variable Interpreter
#------------------------------------------------------------------------------
# This class handles the translation of $game_self_variables into an array
# so that any individual event can treat its own self_variables as such.  It's
# pretends to be an Array, so far as the interaction requires.
#==============================================================================

class SelfVarInterpreter
  attr_accessor :key
  #---------------------------------------------------------------------------
  # * Object Initialization
  #     key = [$game_map.map_id, @event_id]
  #---------------------------------------------------------------------------
  def initialize
    @key = [0, 0]
  end
  #---------------------------------------------------------------------------
  # * Get Self Variable
  #     variable_id : variable's ID
  #---------------------------------------------------------------------------
  def [](variable_id)
    key = [@key[0], @key[1], variable_id]
    return $game_self_variables[key]
  end
  #---------------------------------------------------------------------------
  # * Set Self Variable
  #     variable_id : variable's ID
  #     value       : the variable's value
  #---------------------------------------------------------------------------
  def []=(variable_id, value)
    key = [@key[0], @key[1], variable_id]
    $game_self_variables[key] = value
  end
end


#==============================================================================
# ** Interpreter
#==============================================================================

class Interpreter
  #---------------------------------------------------------------------------
  # * Initialize
  #---------------------------------------------------------------------------
  alias ds_self_variables_initialize initialize
  def initialize(depth = 0, main = false)
    @self_variables = SelfVarInterpreter.new
    ds_self_variables_initialize(depth, main)
  end
  #---------------------------------------------------------------------------
  # * Setup
  #---------------------------------------------------------------------------
  alias ds_self_variables_setup setup
  def setup(list, event_id)
    ds_self_variables_setup(list, event_id)
    @self_variables.key = [@map_id, @event_id]
  end
end

#==============================================================================
# ** Scene_Title
#------------------------------------------------------------------------------
# Aliases are made to properly initialize self variables.
#==============================================================================
class Scene_Title
  alias ds_self_variables_command_new_game command_new_game
  def command_new_game
    $game_self_variables = Game_SelfVariables.new
    ds_self_variables_command_new_game
  end
  
  alias ds_self_variables_battle_test battle_test
  def battle_test
    $game_self_variables = Game_SelfVariables.new
    ds_self_variables_battle_test
  end
end

#==============================================================================
# ** Scene_Save
#------------------------------------------------------------------------------
# Adding $game_self_variables.
#==============================================================================
class Scene_Save
  alias ds_self_variables_write_save_data write_save_data
  def write_save_data(file)
    ds_self_variables_write_save_data(file)
    Marshal.dump($game_self_variables, file)
  end
end

#==============================================================================
# ** Scene_Load
#------------------------------------------------------------------------------
# Adding $game_self_variables.
#==============================================================================
class Scene_Load
  alias ds_self_variables_read_save_data read_save_data
  def read_save_data(file)
    ds_self_variables_read_save_data(file)
    $game_self_variables        = Marshal.load(file)
  end
end
 
I have a simpler suggestion:

Code:
class Interpreter
  def set_self_variable(variable, value)
    #same as yours so no need to redo it
  end

  def generate_self_variable_key(variable)
    [$game_map.map_id, @event_id, variable]
  end

  def [](variable) 
    if !(ret = $game_self_variables[generate_self_variable_key(variable)])
      set_self_variable(variable)
    end
    return ret
  end

  def []=(variable, value)    
    key = generate_self_variable_key(variable)
    ret = 0
    if @event_id > 0
      ret = ($game_self_variables[key] = value) 
      set_self_variable(variable) if !ret   
      $game_map.need_refresh = true 
    end    
    return ret
  end

end
This way you´ll be able to do things like that:
Code:
self[variable] += value
in the Scripts Call. Haven´t checked,but it should work. And if anything is wrong, please forgive me there has been quite some time since i don´t mess with RMXP and Ruby :)
 

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