SephirothSpawn
Sponsor
By SephirothSpawn
Introduction
Ever want to give your objects attributes? Giving an actor a new stat like luck that grows as your actor does?
This script was designed to allow you to give any object (usually data structure objects) stats, either with a set stat or a stat that grows (stat is a hash, with "level" as the key and stat value as the "value") via the Curve Generator module. If you wish to use this for a object class, there must be an instance @id specified to read the stats.
Script
Copy and paste the code anywhere but it must be above any scripts that use this
Adding Attributes:
[rgss]#==============================================================================
# ** Adding Attributes Easy
#------------------------------------------------------------------------------
# SephirothSpawn
# Version 1.11
# 2009-02-02 (Year-Month-Day)
#------------------------------------------------------------------------------
# * Version History:
#
# Â Version 1.0 -------------------------------------------------- (2009-01-21)
# Â Â Version 1.1 ------------------------------------------------- (2009-02-02)
# Â Â - Fix: Fixed add_stat default hash setup. Changed to object_to_string.
#------------------------------------------------------------------------------
# * Description:
#
# Â This script was designed to allow you to give any object (usually data
# Â structure objects) stats, either with a set stat or a stat that grows
# Â (stat is a hash, with "level" as the key and stat value as the "value")
# Â via the Curve Generator module. If you wish to use this for a object class,
# Â there must be an instance @id specified to read the stats.
#------------------------------------------------------------------------------
# * Instructions:
#
# Â Place the script anywhere above Main and any scripts that use it.
#------------------------------------------------------------------------------
# * Terms & Conditions:
#
# Â Copyright (C) 2009 SephirothSpawn (Timothy Hoffman)
# Â Free for non-commercial & commercial use.
# Â Any modifications to the system are not to be re-distributed without my
# Â consent.
#==============================================================================
Â
#==============================================================================
# ** Module
#==============================================================================
Â
class Module
 #--------------------------------------------------------------------------
 # * Add Stat
 #--------------------------------------------------------------------------
 private
 def add_stat(stat_name, hash_settings)
  # Create method
  s  = "def #{stat_name};"
  s += "  settings = #{object_to_string(hash_settings)};"
  s += "  settings.default = #{object_to_string(hash_settings.default)};"
  s += "  return settings[@id];"
  s += "end;"
  # Eval method
  module_eval (s)
 end
 #--------------------------------------------------------------------------
 # * Add Stat Curve
 #--------------------------------------------------------------------------
 private
 def add_stat_curve(stat_name, hash_settings)
  # Create method
  s  = "def #{stat_name};"
  s += '  @gen_stats = {} if @gen_stats == nil;'
  s += "  if @gen_stats['#{stat_name}'] == nil;"
  s += "   @gen_stats['#{stat_name}'] = {};"
  s += "  end;"
  s += "  if @gen_stats['#{stat_name}'].has_key?(@id);"
  s += "   return @gen_stats['#{stat_name}'][@id];"
  s += "  end;"
  s += "  settings = #{object_to_string(hash_settings)};"
  s += "  settings.default = #{object_to_string(hash_settings.default)};"
  s += "  curve = Curve_Generator.generate_curve(*settings[@id]);"
  s += "  @gen_stats['#{stat_name}'][@id] = curve;"
  s += "  return @gen_stats['#{stat_name}'][@id];"
  s += "end;"
  # Eval method
  module_eval (s)
 end
 #--------------------------------------------------------------------------
 # * Object to String
 #--------------------------------------------------------------------------
 def object_to_string(object)
  case object
  when Array
   object.collect! {|value| object_to_string(value)}
   return "[#{object.join(',')}]"
  when Hash
   s = '{'
   object.each do |key, value|
    s += "#{object_to_string(key)}=>#{object_to_string(value)},"
   end
   s += '}'
   return s
  else
   return object.to_s
  end
 end
end
[/rgss]
This script requires the Curve Generator Module (4.01)
[rgss]#==============================================================================
# ** Modules.Curve Generator Module (4.01) Â Â Â Â By Trickster & SephirothSpawn
#------------------------------------------------------------------------------
# * Description :
#
# Â This script was designed to generate a curve of numbers given certain
# Â values. As of now, their are 3 formulas for you to choose from : Point-
# Â slope; Early & Late; Early / Steady / Late + Curves.
#------------------------------------------------------------------------------
# * Syntax :
#
# Â Generating Curve :
# Â Â - curve = Curve_Generator.generate_curve(type, <args>)
#
# Â Type : 0 - Point Slope
# Â Â Â Â Â 1 - Early / Late
# Â Â Â Â Â 2 - Early / Steady / Late + Curves
#
# Â Args :
#
# Â Â Type 0 : min_level, max_level, start value, inflation
# Â Â Type 1 : min_level, max_level, min_value, max_value, early, late
# Â Â Type 2 : min level, mid_level, max level, min value, mid_value,
# Â Â Â Â Â Â max value, early, late, steady, curve 1, curve 2, integer
#
# Â This will return a hash : { level => value, ... }
#==============================================================================
Â
#==============================================================================
# ** Curve_Generator
#==============================================================================
Â
module Curve_Generator
 #--------------------------------------------------------------------------
 # * Generate Curve
 #
 #  Type : 0 - Point Slope
 #      1 - Early / Late
 #      2 - Early / Steady / Late + Curves
 #
 #  Args :
 #
 #   Type 0 : min_level, max_level, start value, inflation
 #   Type 1 : min_level, max_level, min_value, max_value, early, late
 #   Type 2 : min level, mid_level, max level, min value, mid_value,
 #       max value, early, late, steady, curve 1, curve 2, integer
 #--------------------------------------------------------------------------
 def self.generate_curve(type, *args)
  # Collects Saved Tables
  tables = self.load_tables
  # Check for Previously Generated Table
  if tables.has_key?(type) && tables[type].has_key?(args)
   # Return Previously Generated Table
   return tables[type][args]
  end
  # Branch Point By Type
  case type
  when 0 # Point Slope
   table = Point_Slope.generate_curve(*args)
  when 1 # Early / Late
   table = Early_Late.generate_curve(*args)
  when 2 # Early / Stead / Late + Curves
   table = ESL_Curves.generate_curve(*args)
  end
  # Set 0 Defaults
  table.default = 0
  # Saves Table Information
  self.save_table(type, args, table)
  # Return Curve Information
  return table
 end
 #-------------------------------------------------------------------------
 # * Save Table
 #-------------------------------------------------------------------------
 def self.save_table(type, args, table)
  # Collects Saved Tables
  tables = self.load_tables
  # Creates Hash of Type (If non present)
  tables[type] = {} unless tables.has_key?(type)
  # Saves Table Data
  tables[type][args] = table
  # Resaves Tables to File
  save_data(tables, 'Data/Curve Generator.rxdata')  Â
 end
 #-------------------------------------------------------------------------
 # * Load Tables
 #-------------------------------------------------------------------------
 def self.load_tables
  # Test For Saved Table File
  unless FileTest.exist?('Data/Curve Generator.rxdata')
   # Creates Curve Generator Rxdata File
   save_data({}, 'Data/Curve Generator.rxdata')
  end
  # Returns Saved Tables
  return load_data('Data/Curve Generator.rxdata')
 end Â
Â
 #============================================================================
 # ** Point Slope
 #============================================================================
Â
 module Point_Slope
  #------------------------------------------------------------------------
  # * Generate Curve
  #
  #  Args : min_level, max_level, start value, inflation
  #------------------------------------------------------------------------
  def self.generate_curve(min_l, max_l, start_value, inflation)
   # Creates Table
   table = {}
   # Fills Table
   for level in min_l..max_l
    table[level] = start_value + inflation * level
   end
   # Return Table
   return table
  end
 end
Â
 #============================================================================
 # ** Early Late
 #============================================================================
Â
 module Early_Late
  #------------------------------------------------------------------------
  # * Generate Curve
  #------------------------------------------------------------------------
  def self.generate_curve(min_l, max_l, min_v, max_v, e = 1.0, l = 1.0)
   # Creates Table
   table = {}
   # Fills Table
   for i in min_l..max_l
    # Assigns Value
    table = self.calculate_value(i, min_l.to_f, max_l.to_f,
          min_v.to_f, max_v.to_f, e.to_f, l.to_f)
   end
   # Return Table
   return table
  end
  #------------------------------------------------------------------------
  # * Late Curve
  #------------------------------------------------------------------------
  def self.late_curve(level, min_level, max_level, min, max)
   diff = min_level - max_level
   stat = min - max
   num = stat * level ** 2 - 2 * min_level * stat * level + min_level ** 2 *
      max - 2 * min_level * max_level * min + min * min_level ** 2
   denom = diff ** 2
   return num / denom
  end
  #------------------------------------------------------------------------
  # * Early Curve
  #------------------------------------------------------------------------
  def self.early_curve(level, min_level, max_level, min, max)
   diff = max_level - min_level
   stat = max - @min
   num = -stat * level ** 2 + 2 * max_level * stat * level + min_level **
      2 * max - 2 * min_level * max_level * max + min * max_level ** 2
   denom = diff ** 2
   return num / denom  Â
  end
  #------------------------------------------------------------------------
  # * Steady Curve
  #------------------------------------------------------------------------
  def self.steady_curve(level, min_level, max_level, min, max)
   ch_level = max_level - min_level
   ch_stat = max - min
   base = ch_stat / ch_level * level
   mod = max * min_level - min * max_level
   base2 = mod / ch_level
   return base - base2
  end
  #------------------------------------------------------------------------
  # * Calculate Value
  #------------------------------------------------------------------------
  def self.calculate_value(level, min_level, max_level, min, max, e, l)
   return min if level < min_level
   return max if max_level < level
   if e == l
    stat = self.steady_curve(level, min_level, max_level, min, max)
   else
    early_ = self.early_curve(level, min_level, max_level, min, max)
    late_ = self.late_curve(level, min_level, max_level, min, max)
    stat = (e * early_ + l * late_) / (e + l)
   end
   stat = Integer([[stat, min].max, max].min)
   return stat
  end
 end
  Â
 #============================================================================
 # ** ESL_Curves
 #============================================================================
Â
 module ESL_Curves
  #------------------------------------------------------------------------
  # * Generate Curve
  #------------------------------------------------------------------------
  def self.generate_curve(mn_v, md_v, mx_v, mn_l, md_l, mx_l, e = 0, l = 0,
              s = 0, c1 = 0, c2 = 0, i = true)
   # Saves Values
   @min_value, @mid_value, @max_value = mn_v, md_v, mx_v
   @min_level, @mid_level, @max_level = mn_l, md_l, mx_l
   @early   , @late   , @steady   = e  , l  , s
   @curve1  , @curve2  , @integer  = c1  , c2  , i
   # Error Checking
   self.error_checking
   # Calculate constants
   self.calculate_constants
   # Returns Table
   return self.generate_table
  end
  #-----------------------------------------------------------------------
  # * Error Checking
  #-----------------------------------------------------------------------
  def self.error_checking
   if @late + @early + @steady + @curve1 + @curve2 == 0
    raise(StandardError, "No Influences Have Been Defined")
   elsif @min_level == @mid_level || @min_level == @max_level ||
      @mid_level == @max_level
    raise(StandardError, "Can't Use Same Level for Min, Mid, or Max Level")
   end
  end
  #-----------------------------------------------------------------------
  # * Calculate Constants
  #-----------------------------------------------------------------------
  def self.calculate_constants
   # Calculate "infi" and "inmi"
   @inmi = (@mid_value - @min_value) / (@mid_level - @min_level)
   @infi = (@max_value - @min_value) / (@max_level - @min_level)
   # Calculate "infimi"
   @infimi = (@infi - @inmi) / (@max_level - @mid_level)
  end
  #-----------------------------------------------------------------------
  # * Generate Table
  #-----------------------------------------------------------------------
  def self.generate_table
   # Create Hash table
   table = {}
   # Run Through Each Level
   self.each {|level, value| table[level] = value}
   # Return Created Table
   return table
  end
  #-----------------------------------------------------------------------
  # * Each Interator
  #-----------------------------------------------------------------------
  def self.each
   # Get Minimum level and Maximum Level
   minimum, maximum = @min_level.to_i, @max_level.to_i
   # Run Through Minimum and Maximum and Yield Level and Value
   (minimum..maximum).each {|level| yield(level, self.get_stat(level))}
  end
  #-----------------------------------------------------------------------
  # * Get Stat
  #-----------------------------------------------------------------------
  def self.get_stat(level)
   return @integer ? @min_value.to_i : @min_value if level <= @min_level
   return @integer ? @max_value.to_i : @max_value if level >= @max_level
   # Setup Total
   total = 0
   # Get Values for Every Stat if greater than 0
   total += @early  * self.early_curve(level)    if @early > 0
   total += @late  * self.late_curve(level)    if @late > 0
   total += @steady * self.steady_curve(level)   if @steady > 0
   total += @curve1 * self.early_late_curve(level) if @curve1 > 0
   total += @curve2 * self.late_early_curve(level) if @curve2 > 0
   # Get Average
   total /= @late + @early + @steady + @curve1 + @curve2
   # Limit Value
   total = level < @mid_level ?
    [total, @mid_value].min : [total, @mid_value].max
   # Further Limit Value
   total = [[total, @min_value].max, @max_value].min
   # Return Value
   return @integer ? total.to_i : total
  end
  #-----------------------------------------------------------------------
  # * Late Curve
  #-----------------------------------------------------------------------
  def self.late_curve(level)
   # Calculate "A"
   a_num = @infimi * (3 * @min_level + @mid_level) + @inmi
   a_den = (@max_level - @min_level) * (@mid_level - @min_level)
   a = - a_num / a_den
   # Return Value
   return curve(a, level)
  end
  #-----------------------------------------------------------------------
  # * Early Curve
  #-----------------------------------------------------------------------
  def self.early_curve(level)
   # Calculate "A"
   a_num = @infimi * (2 * @max_level + @min_level + @mid_level) + @inmi
   a_den = (@max_level - @mid_level) * (@max_level - @min_level)
   a = - a_num / a_den
   # Return Value
   return curve(a, level)
  end
  #-----------------------------------------------------------------------
  # * Early Late Curve
  #-----------------------------------------------------------------------
  def self.early_late_curve(level)
   # Calculate "A"
   a = @infimi / (@max_level + @min_level - 2 * @mid_level)
   # Return Value
   return curve(a, level)
  end
  #-----------------------------------------------------------------------
  # * Late Early Curve
  #-----------------------------------------------------------------------
  def self.late_early_curve(level)
   # If Less than Mid Level
   if level < @mid_level
    # Return Late Curve for level
    return late_curve(level)
   # If Greater than Mid Level
   elsif level > @mid_level
    # Return Early Curve for Level
    return early_curve(level)
   # If at Mid Level
   elsif level == @mid_level
    # Return Mid Value
    return @mid_value
   end
  end
  #-----------------------------------------------------------------------
  # * Steady Curve
  #-----------------------------------------------------------------------
  def self.steady_curve(level)
   ch_level = @max_level - @min_level
   ch_stat = @max_value - @min_value
   base = ch_stat / ch_level * level
   mod = @max_value * @min_level - @min_level * @max_level
   base2 = mod / ch_level
   return base - base2
  end
  #-----------------------------------------------------------------------
  # * Curve
  #-----------------------------------------------------------------------
  def self.curve(a, level)
   # Calculate "B"
   b = @infimi - a * (@min_level + @mid_level + @max_level)
   # Calculate "C"
   c = @inmi - a * (@mid_level ** 2 + @min_level * @mid_level +
     @min_level ** 2) - b * (@mid_level + @min_level)
   # Calculate "D"
   d = @min_value - (a * @min_level ** 3 + b * @min_level ** 2 + c *
     @min_level)
   # Calculate Stat
   stat = a * level ** 3 + b * level ** 2 + c * level + d
   # Return Stat
   return stat
  end
 end
end
[/rgss]
Instructions
Basic Stats (That do not increase)
In your object class, add:
[rgss]class Your_Class
 hash_settings = {object_id => value, object_id => value, ...}
 hash_settings.default = default_for_non_specified_objects
 add_stat('your_stat_name', hash_settings)
end
Â
Â
[/rgss]
Now you will just need to call your_object.your_stat_name and it will return the value for that object.
[rgss]class Your_Class
 hash_settings = {object_id => value, object_id => value, ...}
 hash_settings.default = default_for_non_specified_objects
 add_stat('your_stat_name', hash_settings)
end
Â
Â
[/rgss]
Now you will just need to call your_object.your_stat_name and it will return the value for that object.
In your object class, add:
[rgss]class Your_Class
 hash_settings = {object_id => [curve_type, curve_argument, ...], object_id => [curve_type, curve_argument, ...], ...}
 hash_settings.default = [curve_type, curve_argument, ...]
 add_stat_curve('your_stat_name', hash_settings)
end
Â
Â
[/rgss]
Curve type and curve_arguments are listing in the curve generator module heading. If you need help, just ask.
Now you will just need to call your_object.your_stat_name and it will return a hash with your curve specified. (Key as "level" and value of stat at that level as the value)
[rgss]class Your_Class
 hash_settings = {object_id => [curve_type, curve_argument, ...], object_id => [curve_type, curve_argument, ...], ...}
 hash_settings.default = [curve_type, curve_argument, ...]
 add_stat_curve('your_stat_name', hash_settings)
end
Â
Â
[/rgss]
Curve type and curve_arguments are listing in the curve generator module heading. If you need help, just ask.
Now you will just need to call your_object.your_stat_name and it will return a hash with your curve specified. (Key as "level" and value of stat at that level as the value)
Examples:
[rgss]class RPG::Actor
 luck = {
  1 => [0, 1, 99, 5, 1],
  2 => [0, 1, 99, 4, 2],
  7 => [0, 1, 99, 2, 4],
  8 => [0, 1, 99, 1, 5],
 }
 luck.default = [0, 1, 99, 3, 3]
 add_stat_curve('luck', luck)
 rating = {
  1=>1,
  2=>2,
  7=>2,
  8=>1
 }
 rating.default = 3
 add_stat('rating', rating)
end
Â
class Game_Actor
 def luck
  return $data_actors[@actor_id].luck[@level]
 end
 def rating
  return $data_actors[@actor_id].rating
 end
end
[/rgss]
 luck = {
  1 => [0, 1, 99, 5, 1],
  2 => [0, 1, 99, 4, 2],
  7 => [0, 1, 99, 2, 4],
  8 => [0, 1, 99, 1, 5],
 }
 luck.default = [0, 1, 99, 3, 3]
 add_stat_curve('luck', luck)
 rating = {
  1=>1,
  2=>2,
  7=>2,
  8=>1
 }
 rating.default = 3
 add_stat('rating', rating)
end
Â
class Game_Actor
 def luck
  return $data_actors[@actor_id].luck[@level]
 end
 def rating
  return $data_actors[@actor_id].rating
 end
end
[/rgss]
Shouldn't cause any incompatibility or issues anywhere.
Credits and Thanks
jjangjae for motivating me to finally do this.
Terms and Conditions
Free for any use or redistribution, just credit me.
Author's Notes
If anyone has any questions setting this up, please specify what you are trying to accomplish, and I can guide you through it.
As always, Enjoy :thumb: