SephirothSpawn
Sponsor
(Very rough draft)
Introduction
This is just a little quick tutorial inspired from seeing support topics. It will explain how to create new data structure classes (such as the Actor/Class/Weapon/Etc. classes from the RPG module in RMXP/VX). This tutorial is for more advanced scripters.
Data structure classes are basically "containers" for all your objects data you set in the database editor. Graphics, names, powers, descriptions, etc. all are stored in Ruby objects. But what if you wanted to add a new data structure class for something new, say a treasure chest? What's the best way to organize and read all this data? Data Structures.
Data Structures in XP/VX
Before we start making our own data structure classes and object, we need to figure out a practical way to store and access this data. RMXP/VX has a effective way of doing this and for purposes of this tutorial, we will follow the way XP/VX stores and accesses this data.
Whenever you create your objects in the database editor and press save, all our data is saved for us into rxdata files. We don't have the ability to be able to do this by ourselves, we have to script the creation of our objects and if we wish, save the .rxdata files ourselves.
When the game is loaded, the objects are loaded into data arrays. You can see this in Scene_Title directly under main:[rgss] Â Â # Load database
  $data_actors     = load_data("Data/Actors.rxdata")
  $data_classes    = load_data("Data/Classes.rxdata")
  $data_skills     = load_data("Data/Skills.rxdata")
  $data_items     = load_data("Data/Items.rxdata")
  $data_weapons    = load_data("Data/Weapons.rxdata")
  $data_armors     = load_data("Data/Armors.rxdata")
  $data_enemies    = load_data("Data/Enemies.rxdata")
  $data_troops     = load_data("Data/Troops.rxdata")
  $data_states     = load_data("Data/States.rxdata")
  $data_animations   = load_data("Data/Animations.rxdata")
  $data_tilesets    = load_data("Data/Tilesets.rxdata")
  $data_common_events = load_data("Data/CommonEvents.rxdata")
  $data_system     = load_data("Data/System.rxdata")
[/rgss]
Without going into this deeply, the load_data is a special method that reads Ruby objects from rxdata files (works in conjunction with the save_data method that saves Ruby objects into rxdata files). So we setting global arrays (that can be read everywhere in your scripts) that hold our objects data. The first object in these list is always nil, because in our editor, objects start with the ID of 1 (Aluxes' ID is 1, not 0). We use this @id to reference attributes of our objects in the in these $data arrays. For example, to get weapon ID#4's name, we use:
We will continue this practice of making the first object nil and having an @id instance in all our objects we create.
Whenever you create your objects in the database editor and press save, all our data is saved for us into rxdata files. We don't have the ability to be able to do this by ourselves, we have to script the creation of our objects and if we wish, save the .rxdata files ourselves.
When the game is loaded, the objects are loaded into data arrays. You can see this in Scene_Title directly under main:[rgss] Â Â # Load database
  $data_actors     = load_data("Data/Actors.rxdata")
  $data_classes    = load_data("Data/Classes.rxdata")
  $data_skills     = load_data("Data/Skills.rxdata")
  $data_items     = load_data("Data/Items.rxdata")
  $data_weapons    = load_data("Data/Weapons.rxdata")
  $data_armors     = load_data("Data/Armors.rxdata")
  $data_enemies    = load_data("Data/Enemies.rxdata")
  $data_troops     = load_data("Data/Troops.rxdata")
  $data_states     = load_data("Data/States.rxdata")
  $data_animations   = load_data("Data/Animations.rxdata")
  $data_tilesets    = load_data("Data/Tilesets.rxdata")
  $data_common_events = load_data("Data/CommonEvents.rxdata")
  $data_system     = load_data("Data/System.rxdata")
[/rgss]
Without going into this deeply, the load_data is a special method that reads Ruby objects from rxdata files (works in conjunction with the save_data method that saves Ruby objects into rxdata files). So we setting global arrays (that can be read everywhere in your scripts) that hold our objects data. The first object in these list is always nil, because in our editor, objects start with the ID of 1 (Aluxes' ID is 1, not 0). We use this @id to reference attributes of our objects in the in these $data arrays. For example, to get weapon ID#4's name, we use:
Code:
name = $data_weapons[4].name
We will continue this practice of making the first object nil and having an @id instance in all our objects we create.
Making your first data structure class
Whenever you are thinking of this new object you need to think of it as a real world object: What attributes and functions does this object have? Attributes are the easiest to setup: just make a list of possible details about your object. Name, icon, description and other physical traits of the object you will be reading at later times. Functions are slightly harder, and you can add these later. Your object may not need functions at all.
For this tutorial, we will think of a treasure chest. What attributes does a treasure chest have? We will make a simple list for our treasure chest:
Ruby comes with a very cool class called Struct. It allows us to make Data Structure classes more quickly. Lets look at the class RPG::Weapon, how we would make it without the Struct class and with the Struct class.
[rgss]# Without Struct class
module RPG
 class Weapon
  def initialize
   @id = 0
   @name = ""
   @icon_name = ""
   @description = ""
   @animation1_id = 0
   @animation2_id = 0
   @price = 0
   @atk = 0
   @pdef = 0
   @mdef = 0
   @str_plus = 0
   @dex_plus = 0
   @agi_plus = 0
   @int_plus = 0
   @element_set = []
   @plus_state_set = []
   @minus_state_set = []
  end
  attr_accessor :id
  attr_accessor :name
  attr_accessor :icon_name
  attr_accessor :description
  attr_accessor :animation1_id
  attr_accessor :animation2_id
  attr_accessor :price
  attr_accessor :atk
  attr_accessor :pdef
  attr_accessor :mdef
  attr_accessor :str_plus
  attr_accessor :dex_plus
  attr_accessor :agi_plus
  attr_accessor :int_plus
  attr_accessor :element_set
  attr_accessor :plus_state_set
  attr_accessor :minus_state_set
 end
end
Â
# Using Struct Class (I did not include :id and you will see why below)
RPG::Weapon = Struct.newname, :icon_name, :description, :animation1_id,
 :animation2_id, :price, :atk, :pdef , :mdef, :str_plus, :dex_plus, :agi_plus,
 :int_plus, :element_set, :plus_state_set, :minus_state_set)
[/rgss]
In the Struct block, we didn't have to specify attr_accessor for each of our attibutes. The Struct class auto-creates these accessor methods for us. The disadvantage of the Struct class is for each of these attributes, you need to pass what attribute is when creating your object.
[rgss]# So instead of:
weapon = RPG::Weapon.new
weapon.name = 'Iron Sword'
weapon.icon_name = '001-Icon01'
# ...
# We have to pass every attribute when we create our object in the same order the class was created.
weapon = RPG::Weapon.new('Icon Sword', '001-Icon01', ...)
[/rgss]
You cannot rely on the initialize method set defaults for our instances. There are a few ways around this. First way is to only specify unique attributes that every object has, make our own initialize method and calling the Struct initialize method.
[rgss]Â
RPG::Weapon = Struct.newname, :icon_name, :description)
class RPG::Weapon
 attr_accessor :animation1_id
 attr_accessor :animation2_id
 attr_accessor :price
 attr_accessor :atk
 attr_accessor :pdef
 attr_accessor :mdef
 attr_accessor :str_plus
 attr_accessor :dex_plus
 attr_accessor :agi_plus
 attr_accessor :int_plus
 attr_accessor :element_set
 attr_accessor :plus_state_set
 attr_accessor :minus_state_set
 alias_method :weapon_init, :initialize
 def initalize(*struct_args)
  # This sends name, icon name and description back to the Struct initialize method
  weapon_init(*struct_args)
  # Now we can set defaults for our other attributes
  @animation1_id = 0
  @animation2_id = 0
  @price = 0
  @atk = 0
  @pdef = 0
  @mdef = 0
  @str_plus = 0
  @dex_plus = 0
  @agi_plus = 0
  @int_plus = 0
  @element_set = []
  @plus_state_set = []
  @minus_state_set = []
 end
end
[/rgss]
For some of you this may not be practical for you and you would rather cut out the Struct class. I am simply offering an alternate way that some may want to try.
Another alternate I came up with was a Hash_Struct class that is similar to the Struct class. You use it just like the Struct class, can set defaults but you have to pass a hash with the attribute's name and value instead of just attribute's value. This also makes it so you do not have to pass attributes in a certain order. Feel free to ask me questions about this class as I am not going to get into this now:[rgss]#==============================================================================
# ** Classes.Hash_Struct
#------------------------------------------------------------------------------
# SephirothSpawn
# Version 0.1
# 2008-10-14
#------------------------------------------------------------------------------
# Â This class imitates the Struct class however, it allows you to create a
# Â struct class with defaults so when creating a struct object, all attributes
# Â do not need to be passed.
#------------------------------------------------------------------------------
# Â Examples:
#
# Â This creates a new class "Test_Class" with 2 attributes: test1, test2
# Â - Hash_Struct.new('Test_Class', {'test1' => 'a', 'test2' => 'b'})
#
# Â This creates a Test_Class object, passing no arguments
# Â - object1 = Hash_Struct::Test_Class.new
#
# Â Now lets inspect
# Â Â - p object1 => #<Hash_Struct::TestClass:0x3e7d0e8 @test2="b", @test1="a">
#
# Â This creates a Test_Class object, passing 500 as the test1 value
# Â - object2 = Hash_Struct::Test_Class.new('test1' => 500)
#
# Â Now lets inspect
# Â Â - p object2 => #<Hash_Struct::TestClass:0x3e7d0e8 @test2="b", @test1=500>
#==============================================================================
Â
MACL::Loaded << 'Classes.Hash_Struct'
Â
class Hash_Struct
 #--------------------------------------------------------------------------
 # * Object Initialization
 #--------------------------------------------------------------------------
 def initialize(class_name, defaults_hash = {})
  # Start with class name
  s  = "class #{class_name};"
  # Save defaults hash as class variable
  s += "  @@defaults_hash = #{string(defaults_hash)};"
  # Create accessor methods
  defaults_hash.keys.each do |key|
   s += "  attr_accessor :#{key};"
  end
  # Object Initialization
  s += '  def initialize(hash = {});'
  # Passes through defaults
  s += '   @@defaults_hash.each do |key, value|;'
  # If value is defined
  s += '    if hash.has_key?(key);'
  # Define value
  s += '     eval ("@#{key} = hash[key]");'
  # If value not defined
  s += '    else;'
  # Set to default
  s += '     eval ("@#{key} = value");'
  s += '    end;'
  s += '   end;'
  s += '  end;'
  s += 'end;'
  eval s
 end
 #--------------------------------------------------------------------------
 # * String - Returns object in evaluatable format
 #--------------------------------------------------------------------------
 def string(object)
  case object
  when Array
   object.collect! {|x| string(x)}
   return "[#{object.join(',')}]"
  when Hash
   str = '{'
   object.each do |key, value|
    str += "#{string(key)} => #{string(value)},"
   end
   str += '}'
   return str
  when String
   return "'#{object}'"
  when Symbol
   return ":#{object}"
  else
   return object.to_s
  end
 end
end
[/rgss]
Ok. So now that we know a little about setting up a Struct class, let's do this.
[rgss]RPG::Treasure = Struct.newname, :sound_effect, :items, :weapons, :armors, :battle)
[/rgss]
For this tutorial, we will think of a treasure chest. What attributes does a treasure chest have? We will make a simple list for our treasure chest:
- Name
- Sound effect when opening
- Items
- Weapons
- Armors
- Possible battle of occurring instead when opening
Ruby comes with a very cool class called Struct. It allows us to make Data Structure classes more quickly. Lets look at the class RPG::Weapon, how we would make it without the Struct class and with the Struct class.
[rgss]# Without Struct class
module RPG
 class Weapon
  def initialize
   @id = 0
   @name = ""
   @icon_name = ""
   @description = ""
   @animation1_id = 0
   @animation2_id = 0
   @price = 0
   @atk = 0
   @pdef = 0
   @mdef = 0
   @str_plus = 0
   @dex_plus = 0
   @agi_plus = 0
   @int_plus = 0
   @element_set = []
   @plus_state_set = []
   @minus_state_set = []
  end
  attr_accessor :id
  attr_accessor :name
  attr_accessor :icon_name
  attr_accessor :description
  attr_accessor :animation1_id
  attr_accessor :animation2_id
  attr_accessor :price
  attr_accessor :atk
  attr_accessor :pdef
  attr_accessor :mdef
  attr_accessor :str_plus
  attr_accessor :dex_plus
  attr_accessor :agi_plus
  attr_accessor :int_plus
  attr_accessor :element_set
  attr_accessor :plus_state_set
  attr_accessor :minus_state_set
 end
end
Â
# Using Struct Class (I did not include :id and you will see why below)
RPG::Weapon = Struct.newname, :icon_name, :description, :animation1_id,
 :animation2_id, :price, :atk, :pdef , :mdef, :str_plus, :dex_plus, :agi_plus,
 :int_plus, :element_set, :plus_state_set, :minus_state_set)
[/rgss]
In the Struct block, we didn't have to specify attr_accessor for each of our attibutes. The Struct class auto-creates these accessor methods for us. The disadvantage of the Struct class is for each of these attributes, you need to pass what attribute is when creating your object.
[rgss]# So instead of:
weapon = RPG::Weapon.new
weapon.name = 'Iron Sword'
weapon.icon_name = '001-Icon01'
# ...
# We have to pass every attribute when we create our object in the same order the class was created.
weapon = RPG::Weapon.new('Icon Sword', '001-Icon01', ...)
[/rgss]
You cannot rely on the initialize method set defaults for our instances. There are a few ways around this. First way is to only specify unique attributes that every object has, make our own initialize method and calling the Struct initialize method.
[rgss]Â
RPG::Weapon = Struct.newname, :icon_name, :description)
class RPG::Weapon
 attr_accessor :animation1_id
 attr_accessor :animation2_id
 attr_accessor :price
 attr_accessor :atk
 attr_accessor :pdef
 attr_accessor :mdef
 attr_accessor :str_plus
 attr_accessor :dex_plus
 attr_accessor :agi_plus
 attr_accessor :int_plus
 attr_accessor :element_set
 attr_accessor :plus_state_set
 attr_accessor :minus_state_set
 alias_method :weapon_init, :initialize
 def initalize(*struct_args)
  # This sends name, icon name and description back to the Struct initialize method
  weapon_init(*struct_args)
  # Now we can set defaults for our other attributes
  @animation1_id = 0
  @animation2_id = 0
  @price = 0
  @atk = 0
  @pdef = 0
  @mdef = 0
  @str_plus = 0
  @dex_plus = 0
  @agi_plus = 0
  @int_plus = 0
  @element_set = []
  @plus_state_set = []
  @minus_state_set = []
 end
end
[/rgss]
For some of you this may not be practical for you and you would rather cut out the Struct class. I am simply offering an alternate way that some may want to try.
Another alternate I came up with was a Hash_Struct class that is similar to the Struct class. You use it just like the Struct class, can set defaults but you have to pass a hash with the attribute's name and value instead of just attribute's value. This also makes it so you do not have to pass attributes in a certain order. Feel free to ask me questions about this class as I am not going to get into this now:[rgss]#==============================================================================
# ** Classes.Hash_Struct
#------------------------------------------------------------------------------
# SephirothSpawn
# Version 0.1
# 2008-10-14
#------------------------------------------------------------------------------
# Â This class imitates the Struct class however, it allows you to create a
# Â struct class with defaults so when creating a struct object, all attributes
# Â do not need to be passed.
#------------------------------------------------------------------------------
# Â Examples:
#
# Â This creates a new class "Test_Class" with 2 attributes: test1, test2
# Â - Hash_Struct.new('Test_Class', {'test1' => 'a', 'test2' => 'b'})
#
# Â This creates a Test_Class object, passing no arguments
# Â - object1 = Hash_Struct::Test_Class.new
#
# Â Now lets inspect
# Â Â - p object1 => #<Hash_Struct::TestClass:0x3e7d0e8 @test2="b", @test1="a">
#
# Â This creates a Test_Class object, passing 500 as the test1 value
# Â - object2 = Hash_Struct::Test_Class.new('test1' => 500)
#
# Â Now lets inspect
# Â Â - p object2 => #<Hash_Struct::TestClass:0x3e7d0e8 @test2="b", @test1=500>
#==============================================================================
Â
MACL::Loaded << 'Classes.Hash_Struct'
Â
class Hash_Struct
 #--------------------------------------------------------------------------
 # * Object Initialization
 #--------------------------------------------------------------------------
 def initialize(class_name, defaults_hash = {})
  # Start with class name
  s  = "class #{class_name};"
  # Save defaults hash as class variable
  s += "  @@defaults_hash = #{string(defaults_hash)};"
  # Create accessor methods
  defaults_hash.keys.each do |key|
   s += "  attr_accessor :#{key};"
  end
  # Object Initialization
  s += '  def initialize(hash = {});'
  # Passes through defaults
  s += '   @@defaults_hash.each do |key, value|;'
  # If value is defined
  s += '    if hash.has_key?(key);'
  # Define value
  s += '     eval ("@#{key} = hash[key]");'
  # If value not defined
  s += '    else;'
  # Set to default
  s += '     eval ("@#{key} = value");'
  s += '    end;'
  s += '   end;'
  s += '  end;'
  s += 'end;'
  eval s
 end
 #--------------------------------------------------------------------------
 # * String - Returns object in evaluatable format
 #--------------------------------------------------------------------------
 def string(object)
  case object
  when Array
   object.collect! {|x| string(x)}
   return "[#{object.join(',')}]"
  when Hash
   str = '{'
   object.each do |key, value|
    str += "#{string(key)} => #{string(value)},"
   end
   str += '}'
   return str
  when String
   return "'#{object}'"
  when Symbol
   return ":#{object}"
  else
   return object.to_s
  end
 end
end
[/rgss]
Ok. So now that we know a little about setting up a Struct class, let's do this.
[rgss]RPG::Treasure = Struct.newname, :sound_effect, :items, :weapons, :armors, :battle)
[/rgss]
Making objects with our Data Structure
Ok. We have a class that is going to be used to hold our objects data. Now what? Well as we learned, RM uses $data arrays that hold all this data. Truthfully, we don't need to even load these arrays within main in Scene_Title, so create a new section above Main. First thing you should do is paste the line from above at the top.
Now we create our data array with nil as the first object. You code should now look like this:
[rgss]RPG::Treasure = Struct.newname, :sound_effect, :items, :weapons, :armors, :battle)
Â
$data_treasures = [nil]
[/rgss]
Special trick for setting ID: Since our @id is always increasing by 1 with every object we are creating, we can set this instance for us automatically in the initialize method as well as adding it directly to our $data array. We can only do this because we are creating our objects after the $data_treasures list is created.[rgss]RPG::Treasure = Struct.newname, :sound_effect, :items, :weapons, :armors, :battle)
Â
class RPG::Treasure
 attr_accessor :id
 alias_method :treasure_init, :initialize
 def initialize(*struct_args)
  # Calls our struct initialize method
  treasure_init(*struct_args)
  # Set @id to be the size of our $data_treasures list
  @id = $data_treasures.size
  # Put our object automatically into the list
  $data_treasures[@id] = self
 end
end
Â
$data_treasures = [nil]
Â
RPG::Treasure.new('name', ...)
Â
Â
[/rgss]
The alternate to this is more simple, but requires more coding:
[rgss]RPG::Treasure = Struct.newid, :name, :sound_effect, :items, :weapons, :armors, :battle)
Â
$data_treasures = [nil]
$data_treasures << RPG::Treasure.new(1, 'name', ...)
$data_treasures << RPG::Treasure.new(2, 'name', ...)
[/rgss]
Use whatever method is more practical for you.
In either case, after the line $data_treasures = [nil], you can start creating your objects. Remember, if you are making RPG::Treasure from the Struct class, you must pass the same number of attributes on the RPG::Treasure line as there are symbols passed in the Struct creation.
I am not going to get into the complete setup of our treasure chest attributes, how you plan on using them, etc. as this tutorial is more designed into setting up the Data Structure class and creating your object. If someone would like to me to finish this and show in more depth, let me know.
Now we can also add functions in this class as well. We can make these functions outside of this class and let other classes take care of them, but it's good use of a class to put them in here. Let's make a function called open, for when a player opens a chest.[rgss]RPG::Treasure = Struct.newname, :sound_effect, :items, :weapons, :armors, :battle)
Â
class RPG::Treasure
 attr_accessor :id
 alias_method :treasure_init, :initialize
 def initialize(*struct_args)
  # Calls our struct initialize method
  treasure_init(*struct_args)
  # Set @id to be the size of our $data_treasures list
  @id = $data_treasures.size
  # Put our object automatically into the list
  $data_treasures[@id] = self
 end
 def open
  # play sound effect
  # If battle is true
   # start battle
   # return
  # end
  # gain items
  # gain weapons
  # gain armors
 end
end
[/rgss]
Â
Once again, I did not go into the actual starting battle or gaining items/equipment here because of the number of ways you can set the items/equipment instances. To now perform this function, you would use:
Now we create our data array with nil as the first object. You code should now look like this:
[rgss]RPG::Treasure = Struct.newname, :sound_effect, :items, :weapons, :armors, :battle)
Â
$data_treasures = [nil]
[/rgss]
Special trick for setting ID: Since our @id is always increasing by 1 with every object we are creating, we can set this instance for us automatically in the initialize method as well as adding it directly to our $data array. We can only do this because we are creating our objects after the $data_treasures list is created.[rgss]RPG::Treasure = Struct.newname, :sound_effect, :items, :weapons, :armors, :battle)
Â
class RPG::Treasure
 attr_accessor :id
 alias_method :treasure_init, :initialize
 def initialize(*struct_args)
  # Calls our struct initialize method
  treasure_init(*struct_args)
  # Set @id to be the size of our $data_treasures list
  @id = $data_treasures.size
  # Put our object automatically into the list
  $data_treasures[@id] = self
 end
end
Â
$data_treasures = [nil]
Â
RPG::Treasure.new('name', ...)
Â
Â
[/rgss]
The alternate to this is more simple, but requires more coding:
[rgss]RPG::Treasure = Struct.newid, :name, :sound_effect, :items, :weapons, :armors, :battle)
Â
$data_treasures = [nil]
$data_treasures << RPG::Treasure.new(1, 'name', ...)
$data_treasures << RPG::Treasure.new(2, 'name', ...)
[/rgss]
Use whatever method is more practical for you.
In either case, after the line $data_treasures = [nil], you can start creating your objects. Remember, if you are making RPG::Treasure from the Struct class, you must pass the same number of attributes on the RPG::Treasure line as there are symbols passed in the Struct creation.
I am not going to get into the complete setup of our treasure chest attributes, how you plan on using them, etc. as this tutorial is more designed into setting up the Data Structure class and creating your object. If someone would like to me to finish this and show in more depth, let me know.
Now we can also add functions in this class as well. We can make these functions outside of this class and let other classes take care of them, but it's good use of a class to put them in here. Let's make a function called open, for when a player opens a chest.[rgss]RPG::Treasure = Struct.newname, :sound_effect, :items, :weapons, :armors, :battle)
Â
class RPG::Treasure
 attr_accessor :id
 alias_method :treasure_init, :initialize
 def initialize(*struct_args)
  # Calls our struct initialize method
  treasure_init(*struct_args)
  # Set @id to be the size of our $data_treasures list
  @id = $data_treasures.size
  # Put our object automatically into the list
  $data_treasures[@id] = self
 end
 def open
  # play sound effect
  # If battle is true
   # start battle
   # return
  # end
  # gain items
  # gain weapons
  # gain armors
 end
end
[/rgss]
Â
Once again, I did not go into the actual starting battle or gaining items/equipment here because of the number of ways you can set the items/equipment instances. To now perform this function, you would use:
Code:
$data_treasures[id].open
Using save_data/load_data methods
If you have a lot of objects (several treasure chest), you aren't going to want to re-create these objects every time your game is run. We can instead save the objects into Treasures.rxdata file and load them after all the objects are created. This is a very simple process.
Â
To make this happen, we are going to make a flag to either create and save the data or just load the data. You will want to make sure this flag is true every time you modify any of the objects or it will just load your old objects. So you can have something like this:
[rgss]RPG::Treasure = Struct.newname, :sound_effect, :items, :weapons, :armors, :battle)
Â
class RPG::Treasure
  attr_accessor :id
  alias_method :treasure_init, :initialize
  def initialize(*struct_args)
   # Calls our struct initialize method
   treasure_init(*struct_args)
   # Set @id to be the size of our $data_treasures list
   @id = $data_treasures.size
   # Put our object automatically into the list
   $data_treasures[@id] = self
  end
  def open
   # play sound effect
   # If battle is true
    # start battle
    # return
   # end
   # gain items
   # gain weapons
   # gain armors
  end
end
Â
# Make this true if no rxdata file exist or if you have changed anything between
# this line and the save_data line
if true
Â
  $data_treasures = [nil]
  RPG::Treasure.new('name', ...)
  RPG::Treasure.new('name', ...)
  RPG::Treasure.new('name', ...)
  RPG::Treasure.new('name', ...)
  RPG::Treasure.new('name', ...)
Â
  # This saves our data into a rxdata file called "Treasures.rxdata"
  save_data($data_treasures, "Treasures.rxdata")
Â
# If we have not modified the list above and Treasures.rxdata exist
else
Â
  # Load our data like our default data objects in Scene_Title
$data_treasures = [nil]
  $data_treasures = load_data("Treasures.rxdata")
end
[/rgss]
A simple format: If needed, create our objects and save them. If not needed, just load them.
Â
To make this happen, we are going to make a flag to either create and save the data or just load the data. You will want to make sure this flag is true every time you modify any of the objects or it will just load your old objects. So you can have something like this:
[rgss]RPG::Treasure = Struct.newname, :sound_effect, :items, :weapons, :armors, :battle)
Â
class RPG::Treasure
  attr_accessor :id
  alias_method :treasure_init, :initialize
  def initialize(*struct_args)
   # Calls our struct initialize method
   treasure_init(*struct_args)
   # Set @id to be the size of our $data_treasures list
   @id = $data_treasures.size
   # Put our object automatically into the list
   $data_treasures[@id] = self
  end
  def open
   # play sound effect
   # If battle is true
    # start battle
    # return
   # end
   # gain items
   # gain weapons
   # gain armors
  end
end
Â
# Make this true if no rxdata file exist or if you have changed anything between
# this line and the save_data line
if true
Â
  $data_treasures = [nil]
  RPG::Treasure.new('name', ...)
  RPG::Treasure.new('name', ...)
  RPG::Treasure.new('name', ...)
  RPG::Treasure.new('name', ...)
  RPG::Treasure.new('name', ...)
Â
  # This saves our data into a rxdata file called "Treasures.rxdata"
  save_data($data_treasures, "Treasures.rxdata")
Â
# If we have not modified the list above and Treasures.rxdata exist
else
Â
  # Load our data like our default data objects in Scene_Title
$data_treasures = [nil]
  $data_treasures = load_data("Treasures.rxdata")
end
[/rgss]
A simple format: If needed, create our objects and save them. If not needed, just load them.
Review
In closing, I hope you have learned something about making Data Structure classes and objects. Remember the Struct class (or Hash_Struct class) when creating classes. I hope this taught you a few tricks to making this process a little easier. If you have any questions, please do ask in this thread so others may benefit from them. Happy scripting!