RMRK is retiring.
Registration is disabled. The site will remain online, but eventually become a read-only archive. More information.

RMRK.net has nothing to do with Blockchains, Cryptocurrency or NFTs. We have been around since the early 2000s, but there is a new group using the RMRK name that deals with those things. We have nothing to do with them.
NFTs are a scam, and if somebody is trying to persuade you to buy or invest in crypto/blockchain/NFT content, please turn them down and save your money. See this video for more information.
Database Extender

0 Members and 1 Guest are viewing this topic.

**
Rep: +0/-0Level 55
RMRK Junior
Hello, I present a Script by my mentor ! Nuki !
---------------------------------------------
Database Extender
Thanks Hiino for the translation
 
I think that the RPG Maker database is a bit of a pain since we cannot extend it. Hence, I am obligated to stay in the quite restrictive base system, and, in order to obtain cooler (and more specific) things I have to abuse of the database's commentary/note fields (and why not complete with the Typed Entities script, which isn't adapted to this kind of things... IN MY OPINION!)
So I plagiarized Avygeil who had already been plagiarized by Grim and recoded a database system for RM.
 
Concept
This system is based on the same idea as the one Grim used in his "Expressive Database", except it's a bit better (and more cleverly) coded. So firstly we are going to create tables in a blank script on top of Main. To achieve this, simply write:
Code: [Select]
class Swords < Database::Table
  # Here we will define our table's fields
end
To add fields that characterize our table, we have to set their type and their name.
The script accepts the following types:
 
  • :string   - Represents text data
  • :integer   - Represents an integer number
  • :float   - Represents a floating point number
  • :boolean   - Represents either true or false (a switch)
  • :polymorphic   - Represents any RM data type
Here is an example with swords and Pokemon:
Code: [Select]
class Swords < Database::Table
  integer :id
  string  :name
  string  :description
  float   :cost
  integer :power
end

class Pokemon < Database::Table
  integer :id
  string  :name
  string  :description
  string  :type
  integer :power
end
The goal is to describe every attribute of our tables. Of course, these exaples are quite naive and not finished.
 
How to fill our database
There are two ways of filling our database.
The first one is the most economic: after having defined our fields, we can use the "insert" command and pass it arguments. If said arguments aren't the right type the script will try to convert them, else it will set them a default value according to their type. Here is an example:
Code: [Select]
class Swords < Database::Table
  # Design of the table
  integer :id
  string  :name
  string  :description
  float   :cost
  integer :power
  # Filling
  insert 0, "Excalibur", "A rare sword", 150.50, 120
  insert 1, "Durendal", "A very rare sword", 200.20, 200
  insert 2, "Dard", "Bilbon's, then Frodon's sword", 30.0, 50
end

class Pokemon < Database::Table
  # Design of the table
  integer :id
  string  :name
  string  :description
  string  :type
  integer :power
  # Filling
  insert 0, "Pikachu", "Ugly green mouse", "Electric", 10
  insert 1, "Pichu", "Same as above", "Electric", 5
  insert 2, "Doraemon", "thing", "Fire", 100
  insert 3, "Sangoku", "Legendary Pokemon", "Rare", 1000
end
Also, it is possible to instantiate objects this way:
Code: [Select]
Pokemon.new(id: 4, name: "Mew", description: "Blue monkey", type: "Plant", power: 999)
Pokemon.new(id: 5, name: "Magicalichigo", description: "Looks like an Evoli", type: "Psy", power: 1)
Personally, I prefer this way of doing, which allows me to separate my "design" and my filling. But it's possible to mix both techniques.
 
 
Access a table
We just have to write:Database.tables[:Table_Name] or Database.Table_Name
For example: Database.Pokemon or Database.tables[:Pokemon]
Then Database.Pokemon[0] will return the first record (Pikachu), but since the fields are stored inside an array, it is possible to use all the methods concerning arrays. However this part only addresses scripters, kind of like this whole script actually
 
Process the initial RPG Maker database
Since this script is modern and cool, it also allows for handling the RPG Maker database with the same primitives.
For example, to access the Actors table of the database, we will write: Database.VXACE_Actors, which returns the array of all the database's actors.
The accessible tables:
 
VXACE_Actors
VXACE_Classes
VXACE_Skills
VXACE_Items
VXACE_Weapons
VXACE_Armors
VXACE_Enemies
VXACE_States
VXACE_Animations
VXACE_Tilesets
VXACE_CommonEvents
VXACE_MapInfos
This append allows us to manipulate the initial database in a transparent manner with the script.
 
Associating with the Event Extender
If the Event Extender is already appended to your project, you have to place this script below it, so that its database overrides the Event Extender's.
The Design/Filling works the ame way as detailed above.
To access the database, it works as usual or as documented in the Event Extender (for example T[:Pokemon] or T[:VXACE_Actors]).
Thanks to Hiino for his proofreading and translation!

Code: [Select]
# Extend Database ~ Der Botaniker (Nuki)
# http://www.biloucorp.com

# Idea : Avygeil, Grim
# Thanks to Hiino, Zangther (sexual motivation)
# And special thanks to larabdubled


#==============================================================================
# ** Object
#------------------------------------------------------------------------------
#  Generic behaviour
#==============================================================================

class Object
  #--------------------------------------------------------------------------
  # * Bool casting
  #--------------------------------------------------------------------------
  if defined?(Command)
    remove_const(:Database)
    def to_bool; (self != nil || self != false) end
  end
  #--------------------------------------------------------------------------
  # * Polymorphic casting
  #--------------------------------------------------------------------------
  def nothing; self; end
  #--------------------------------------------------------------------------
  # * Get Instance values
  #--------------------------------------------------------------------------
  def instance_values
    instances = Array.new
    instance_variables.each do |i|
      instances << instance_variable_get(i)
    end
    instances
  end
end

#==============================================================================
# ** Database
#------------------------------------------------------------------------------
# Representation of an Abstract Database
#==============================================================================

module Database
 
  #==============================================================================
  # ** Types
  #------------------------------------------------------------------------------
  # Implements the Type System
  #==============================================================================
 
  RPGDatas = [
    "Actors",
    "Classes",
    "Skills",
    "Items",
    "Weapons",
    "Armors",
    "Enemies",
    "States",
    "Animations",
    "Tilesets",
    "CommonEvents",
    "MapInfos"
  ]
 
  module Type
    #--------------------------------------------------------------------------
    # * Type Enum
    #--------------------------------------------------------------------------
    Types = {
      string:       [:to_s, ""],
      integer:      [:to_i, 0],
      float:        [:to_f, 0.0],
      boolean:      [:to_bool, true],
      polymorphic:  [:nothing, ""]
    }
    #--------------------------------------------------------------------------
    # * String representation
    #--------------------------------------------------------------------------
    def string(field_name)
      handle_field(:string, field_name.to_sym)
    end
    alias :text :string
    #--------------------------------------------------------------------------
    # * Integer representation
    #--------------------------------------------------------------------------
    def integer(field_name)
      handle_field(:integer, field_name.to_sym)
    end
    alias :int :integer
    #--------------------------------------------------------------------------
    # * Floating point number representation
    #--------------------------------------------------------------------------
    def float(field_name)
      handle_field(:float, field_name.to_sym)
    end
    #--------------------------------------------------------------------------
    # * Boolean representation
    #--------------------------------------------------------------------------
    def boolean(field_name)
      handle_field(:boolean, field_name.to_sym)
    end
    alias :bool :boolean
    #--------------------------------------------------------------------------
    # * Polymorphic type representation
    #--------------------------------------------------------------------------
    def polymorphic(field_name)
      handle_field(:polymorphic, field_name.to_sym)
    end
    alias :free :polymorphic
    #--------------------------------------------------------------------------
    # * Type Coercion
    #--------------------------------------------------------------------------
    def self.coercion(className)
      return :integer if className == Fixnum
      return :string if className == String
      return :float if className == Float
      return :boolean if className == TrueClass || className == FalseClass
      :polymorphic
    end
  end
 
  #==============================================================================
  # ** Table
  #------------------------------------------------------------------------------
  # Representation of an Abstract Table
  #============================================================================== 
 
  class Table
    #--------------------------------------------------------------------------
    # * Appends Type handler
    #--------------------------------------------------------------------------
    extend Type
    Types = Type::Types
    #--------------------------------------------------------------------------
    # * Singleton of Table
    #--------------------------------------------------------------------------
    class << self
      #--------------------------------------------------------------------------
      # * Public instance variables
      #--------------------------------------------------------------------------
      attr_accessor :fields
      attr_accessor :classname
      #--------------------------------------------------------------------------
      # * Field handling
      #--------------------------------------------------------------------------
      def handle_field(type, name)
        @classname ||= self.to_s.to_sym
        @fields ||= Hash.new
        @fields[name] = type
        instance_variable_set("@#{name}".to_sym, Types[type][1])
        send(:attr_accessor, name)
      end
      #--------------------------------------------------------------------------
      # * Inline insertion
      #--------------------------------------------------------------------------
      def insert(*args)
        keys = @fields.keys
        hash = Hash[keys.zip(args)]
        self.new(hash)
      end
    end
    #--------------------------------------------------------------------------
    # * Object initialization
    #--------------------------------------------------------------------------
    def initialize(hash)
      hash.each do |key, value|
        type = self.class.fields[key]
        insertion = Types[type][1]
        insertion = value.send(Types[type][0]) if value.respond_to?(Types[type][0])
        instance_variable_set("@#{key}".to_sym, insertion)
      end
      Database.tables[self.class.classname] ||= Array.new
      Database.tables[self.class.classname] << self
    end
  end
  #--------------------------------------------------------------------------
  # * Singleton of Database
  #--------------------------------------------------------------------------
  class << self
    #--------------------------------------------------------------------------
    # * Public instance variables
    #--------------------------------------------------------------------------
    attr_accessor :tables
    #--------------------------------------------------------------------------
    # * API for tables
    #--------------------------------------------------------------------------
    Database.tables = Hash.new
    #--------------------------------------------------------------------------
    # * Method Missing
    #--------------------------------------------------------------------------
    def method_missing(method, *args)
      tables[method] || (raise(NoMethodError))
    end
  end
end



#==============================================================================
# ** Junction with the Event Extender 4
#==============================================================================
if defined?(Command)
  #==============================================================================
  # ** T
  #------------------------------------------------------------------------------
  #  Database handling API
  #==============================================================================
 
  module T
    #--------------------------------------------------------------------------
    # * Get a table
    #--------------------------------------------------------------------------
    def [](name); Database.tables[name.to_sym]; end
  end
end

#==============================================================================
# ** RPG::Module Mapping
#------------------------------------------------------------------------------
#  Initial Database Mapping
#==============================================================================

Database::RPGDatas.each do |data|
  rpgStruct = load_data("Data/#{data}.rvdata2")
  instance = rpgStruct.find{|i| !i.nil?}
  instance = instance[1] if instance.is_a?(Array)
  Object.const_set(
    "VXACE_#{data}".to_sym,
    Class.new(Database::Table) do
      self.classname = "VXACE_#{data}".to_sym
      instance.instance_variables.each do |attr|
        classData = instance.send(:instance_variable_get, attr).class
        type = Database::Type.coercion(classData)
        self.send(type, attr.to_s[1..-1].to_sym)
      end
      rpgStruct.each do |rpgData|
        rpgData = rpgData[1] if rpgData.is_a?(Hash)
        self.insert(*rpgData.instance_values)
      end
    end
  )
end

If I update the script, it will usually be on this page: https://github.com/Funkywork/Scripts-rm/blob/master/VXAce/Extend-Database.rb
And the official Page : http://www.biloucorp.com/index.php?page=article&id_article=4

*
Rep:
Level 82
There's a concern here:

Quote
So I plagiarized Avygeil who had already been plagiarized by Grim and recoded a database system for RM.

Now, what I do notice, is that this thread is a pretty close translation of the official web page here: http://www.biloucorp.com/index.php?page=article&id_article=4

In fact, I get my translation straight from Google Translate, and aside from a few changes, it's almost identical.

Now, I'm assuming that you've simply translated the page (via whatever means) seeing as it is written by someone else, but the fact that there's a mention of plagiarism and nothing to say how lightly that term is being used (it's a serious thing to do) is a big concern. I'm pretty sure RMRK does not condone plagiarism, and without knowledge on how serious that is, I don't think this script will be here for too long.

Also, as a side: I have no need to know in the credits of the script, that someone was involved in the "sexual motivation" behind the script. It's completely irrelevant and more than is needed to be done, let alone preserved for eternity in writing.
(Why do I always feel like it's the end of the world and I'm the last man standing?)

**
Rep: +0/-0Level 55
RMRK Junior
I transmitted your post to Nuki (whom I had mentioned at the beginning of my topic as the author of this script) and he said:
Quote
ahahahahah, okay delete the script then.

From my point of view, I am sorry that this script is being that controversial, I didn't realize what it could beget.
I can assure you that Avygeil knows of the existence of that script (which was, in fact, implemented in a completely different way) and that the commentary about plagiarism was only a light joke. Besides, the "sexual motivation" part was also a joke, in case you didn't get it.
I find it sad to deprive the community of a useful script, but the author doesn't want his script edited in the least.
« Last Edit: March 28, 2013, 06:45:23 PM by Grimimi »