じ☆ve冰风 发表于 2026-8-3 14:43:44

Simple Notetag Config v1.3

Hello,

If you are a scripter in your project and add many attributes in your database but are tired of writing the same stuff many times, this script might help you.
I originally wrote it by adapting an older script from Clarabel from GTBS and realized that it might help others, so I share this here.

It aims to reduce the code needed to add attributes to objects from the database, with this, you can simply add lines of codes like this (either before loading the database or inside method prepare_metadata):
                Ruby:       
nd = Notetag_Data.new(:weight, 0, /^<item_weight\s*=\s*(\d+)\s*>/i, 0)
DATA_ITEMS.concat()

This will create an attribute called weight for all objects in $data_items with default value 0, and that can be modified by putting the corresponding note in the database, for instance if for item number 3 you put <item_weight = 2> in the notes, then:
$data_items.weight will be 2 while $data_items.weight will be the default value.

The syntax is:
                Ruby:       
Notetag_Data.new(:attribute_name, default_value, regexp, assignation_mode_id)

With assignation_mode_id an integer between 0 and 3:
- 0 means that the part inside the parenthesis of the regexp is computed (with eval method) and stored
- 1 means that the string itself is stored (useful for file names or plain text)
- 2 means that when the regexp is found, the value is set to true
- 3 is for hash tables, the first value is the key and the second is the data stored in it, both values are evaluated with eval first

The supported data and notetags are actors, classes, skills, items, weapons, armors,enemies, troops, states, maps and tilesets.
In the case of troops, the notetags are taken from any comment inside the troop's events, regardless of their page conditions.

Note that this script requires an understanding of regular expressions and simple code, therefore if you don't understand how they work, I suggest you don't use this script.
Also, since the script adds attributes 'dynamically', please choose wisely their names to avoid conflict with preexisting attributes and methods. Finally, the script only modifies classes from the RPG module, so you will need to write more code if you plan on using them in your scripts.

Here is the script:
                Ruby:       
#==============================================================================
# Simple Notetag Config v1.3
#------------------------------------------------------------------------------
# Author: Timtrack
# date: 03/03/2026
# inspired by Clarabel's notetags reading in GTBS
#==============================================================================

$imported = {} if $imported.nil?
$imported["TIM-SimpleNotetagConfig"] = true

#==============================================================================
# Version History
#------------------------------------------------------------------------------
# 08/09/2025 - Original release
# 03/11/2025 - v1.1 added tileset notetags support, fixed crash for battle test
# 06/11/2025 - v1.2 added hash support, extended the matching support to cover
#                   more complicated objects
# 03/03/2026 - v1.3 moved the methods creations of the class to be used once
#==============================================================================
# Description: a utility script for those tired of writing the same multiple
# lines of code to setup data from notetags. This script will allow, with a few
# line of code, to create attributes to objects from the database with a default
# value and a basic assignation value through notetag reading.
#
# This script is for advanced users with enough knowledge in notetags setup,
# you must understand basic code and regexp.
#==============================================================================
# Term of use: Free to use in free or commercial games, please give credit.
#==============================================================================
# Installation & Configuration: put the script above main, set your own code in
# method self.prepare_metadata to create attributes to be read in notetags
#
# Add to DATA_ arrays Notetag_Data objects that will be turned into attributes
# inside rpg maker database objects.
# DATA can be DATA_SKILLS, DATA_ITEMS, DATA_WEAPONS, DATA_ARMORS, DATA_TILESETS,
# DATA_STATES, DATA_ENEMIES, DATA_ACTORS, DATA_CLASSES, DATA_MAPS or DATA_TROOPS
#
# For each DATA_X, the attribute will be read from the notetags regexp and will
# be stored inside $data_x at the launch of the game when loading the database.
# There are two exceptions:
# For DATA_MAPS, the data will be stored in $data_mapinfos
# For DATA_TROOPS, the data will be read from comments in every page of the
# troop (regardless of their conditions)
#
# To add an entry, put in the corresponding(s) arrays:
#   Notetag_Data.new(symbol, default, regexp, type)
#
# symb    is the name of the attribute added to the database, it will be set as
#         an accessor, for instance:
#         symb=:range means that obj.range will be accessible from the database
# default is the value set by default when no matching line to the regexp was
#         found
# regexpis a regular expression set to find the value, it will be interpreted
#         with type
# type    is an integer related to AssignationModes indices
#         0/none provided -> the data is read and evaluated (int, bool, float,
#                            symbols, arrays)
#         1               -> the string is stored as is (files, texts)
#         2               -> will replace the default value by true if the
#                            regexp is found
#         3               -> to deal with hash tables, will eval the two values
#                            set ($1,$2) and do hash = eval($2)
#
# You can put a Notetag_Data object x to multiple arrays by calling
#   x.add_to(a1,a2,...)
#
# Example:
#n = Notetag_Data.new(:required_level, 1, /^<min_level\s*=\s*(\d+)\s*>/i, 0)
#n.add_to(DATA_WEAPONS,DATA_ARMORS)
# If the weapon with id 5 has in a notetag <min_level = 3>, then
# $data_weapons.required_level will be 3,
# If no such notetag was given, the default value will be stored instead (ex: 1)
#
# If for some reason you need to perform some specific postprocessing action to
# the added attributes, you can redefine method post_metadata_notetags_reading
# in RPG::BaseItem, RPG::MapInfo, RPG::Tileset, RPG::Troop and their subclasses
#============================================================================

if $imported["TIM-SimpleNotetagConfig"]

#============================================================================
# SNC/SimpleNotetagConfig -> module that you must configure
#============================================================================
module SNC
#--------------------------------------------------------------------------
# method: prepare_metadata -> called while loading the database at the start
# of the game, fill the arrays with Notetag_Data objects here
#--------------------------------------------------------------------------
def self.prepare_metadata
    #You modify the arrays like this:
    # DATA_SKILLS.concat([
    #   Notetag_Data.new(:var_symb, default_value, regexp, regexp_read_type_id),
    #   Notetag_Data.new(:v2, default_value2, regexp2, regexp_read_type_id2),
    # ])
    #
    #You can also add the same notetag object to multiple data arrays:
    # obj.add_to(DATA_WEAPONS,DATA_ARMORS,DATA_STATES)
    #
    #example code:
    #n = Notetag_Data.new(:required_level, 1, /^<min_level\s*=\s*(\d+)\s*>/i, 0)
    #n.add_to(DATA_WEAPONS,DATA_ARMORS,DATA_MAPS,DATA_TROOPS)
end

#============================================================================
# Editing anything past this point is not recommended
#============================================================================
#DATA_SKILLS Config (modify RPG::Skill)
DATA_SKILLS = []
#DATA_ITEMS Config (modify RPG::Item)
DATA_ITEMS = []
#DATA_WEAPONS Config (modify RPG::Weapon)
DATA_WEAPONS = []
#DATA_ARMORS Config (modify RPG::Armor)
DATA_ARMORS = []
#DATA_STATES Config (modify RPG::State)
DATA_STATES = []
#DATA_ENEMIES Config (modify RPG::Enemy)
DATA_ENEMIES = []
#DATA_ACTORS Config (modify RPG::Actor)
DATA_ACTORS = []
#DATA_CLASSES Config (modify RPG::Class)
DATA_CLASSES = []
#DATA_MAPS Config (modify RPG::MapInfo)
DATA_MAPS = []
#DATA_TROOPS Config (modify RPG::Troop)
DATA_TROOPS = []
#DATA_TILESETS Config (modify RPG::Tileset)
DATA_TILESETS = []

#--------------------------------------------------------------------------
# create_class_metadata_methods -> creates accessor to the object's class
#--------------------------------------------------------------------------
DATA_META_CLASSES = [] #remembers the classes handled
def self.create_class_metadata_methods(obj_class, data_list)
    return if DATA_META_CLASSES.include?(obj_class)
    data_list.each{|d| obj_class.send(:attr_accessor, d.symbol)}
    DATA_META_CLASSES.push(obj_class)
end

#--------------------------------------------------------------------------
# load_notetags_metadata -> reads notes and creates attributes
# data_list is an array of Notetag_Data
#--------------------------------------------------------------------------
def self.load_notetags_metadata(obj, data_list, note)
    create_class_metadata_methods(obj.class, data_list)
    data_list.each do |d|
      obj.instance_variable_set(d.attribute_name, d.default_value)
    end
    note.split(/[\r\n]+/).each do |line|
      data_list.each do |d|
      matches = line.scan(d.regexp)
      matches.each do |str_values|
          original_v = obj.instance_variable_get(d.attribute_name)
          new_val = d.value(original_v, str_values)
          obj.instance_variable_set(d.attribute_name, new_val)
      end
      end
    end # self.note.split
    obj.post_metadata_notetags_reading
end
end #SNC

#============================================================================
# Notetag_Data -> represents how notetags are read for most items
#============================================================================
class Notetag_Data
#eval: to save int, floats or arrays
#string: to save the evaluated data as a string
#activate: to put a value to true when data matches the regexp
#hash: to put inside the hash the second value with key the first value
AssignationModes = [:eval, :string, :activate, :hash]
#accessors:
attr_accessor :symbol, :default_value, :regexp, :assignation_mode
#--------------------------------------------------------------------------
# method: initialize
#--------------------------------------------------------------------------
def initialize(symb,default,regexp,assign_mode_id=0)
    @symbol = symb
    @default_value = default
    @regexp = regexp
    @assignation_mode = AssignationModes
end

#--------------------------------------------------------------------------
# method: attribute_name -> turns symb :s into @s for instance get/set
#--------------------------------------------------------------------------
def attribute_name
    return "@"+@symbol.id2name
end

#--------------------------------------------------------------------------
# method: value -> returns a value to store into the object
# parameters:
# -original_value : the current object's value
# -str_l a list of string identified by the regexp
#--------------------------------------------------------------------------
def value(original_value, str_l)
    case @assignation_mode
    when :eval then eval(str_l)
    when :string then str_l
    when :activate then true
    when :hash
      key= eval(str_l)
      value = eval(str_l)
      original_value = original_value.dup
      original_value = value
      return original_value
    end
end

#--------------------------------------------------------------------------
# method: add_to -> add itself to each given arrays
#--------------------------------------------------------------------------
def add_to(*args)
    args.each{|a| a.push(self)}
end
end #Notetag_Data

#============================================================================
# DataManager
#============================================================================
module DataManager
class << self
    alias load_database_metadata load_database
    alias load_battle_test_database_metadata load_battle_test_database
end
#--------------------------------------------------------------------------
# alias method: load_database
#--------------------------------------------------------------------------
def self.load_database
    load_database_metadata
    load_notetags_metadata
end

#--------------------------------------------------------------------------
# alias method: load_battle_test_database -> loads map data
#--------------------------------------------------------------------------
def self.load_battle_test_database
    load_battle_test_database_metadata
    $data_mapinfos = load_data("Data/MapInfos.rvdata2")
end

#--------------------------------------------------------------------------
# new method: load_notetags_metadata
#--------------------------------------------------------------------------
def self.load_notetags_metadata
    SNC.prepare_metadata
    pairs = [
      [$data_actors,SNC::DATA_ACTORS],
      [$data_classes, SNC::DATA_CLASSES],
      [$data_weapons, SNC::DATA_WEAPONS],
      [$data_armors,SNC::DATA_ARMORS],
      [$data_enemies, SNC::DATA_ENEMIES],
      [$data_states,SNC::DATA_STATES],
      [$data_items,   SNC::DATA_ITEMS],
      [$data_skills,SNC::DATA_SKILLS],
      [$data_troops,SNC::DATA_TROOPS],
      [$data_tilesets,SNC::DATA_TILESETS],
    ]
    #for any RPG::BaseItem or RPG::Troop
    pairs.each do |group,data_l|
      group.each do |obj|
      SNC.load_notetags_metadata(obj,data_l,obj.note) if obj
      end
    end
    #load map data, mapinfo will read RPG::Map notetags:
    $data_mapinfos.each_pair do |key,mapinfo|
      next unless mapinfo
      filename = sprintf("Data/Map%03d.rvdata2", key)
      #next unless File.exist?(filename)
      note = load_data(filename).note
      SNC.load_notetags_metadata(mapinfo, SNC::DATA_MAPS,note)
    end
end
end # DataManager

#============================================================================
# RPG::BaseItem -> parent class of actor, class, skill, item, weapon, armor,
# enemy, and state.
#============================================================================
class RPG::BaseItem
#--------------------------------------------------------------------------
# new method: post_metadata_notetags_reading -> postprocessing
#--------------------------------------------------------------------------
def post_metadata_notetags_reading
end
end #RPG::BaseItem

#============================================================================
# RPG::MapInfo -> The data class for map information
#============================================================================
class RPG::MapInfo
#--------------------------------------------------------------------------
# new method: post_metadata_notetags_reading -> postprocessing
#--------------------------------------------------------------------------
def post_metadata_notetags_reading
end
end #RPG::MapInfo

#============================================================================
# RPG::Tileset -> The data class for tilesets
#============================================================================
class RPG::Tileset
#--------------------------------------------------------------------------
# new method: post_metadata_notetags_reading -> postprocessing
#--------------------------------------------------------------------------
def post_metadata_notetags_reading
end
end #RPG::Tileset

#============================================================================
# RPG::Troop -> The data class for enemy troop
#============================================================================
class RPG::Troop
#--------------------------------------------------------------------------
# new method: note -> reads all comments in all pages and returns them as
# notes (from Victor Core Engine)
#--------------------------------------------------------------------------
def note
    comment_list = []
    return @notes if @notes
    @pages.each do |page|
      next unless (page && page.list && page.list.size > 0)
      note_page = page.list.dup
      note_page.each do |item|
      next unless item && (item.code == 108 || item.code == 408)
      comment_list.push(item.parameters)
      end
    end
    @notes = comment_list.join("\r\n")
    return @notes
end

#--------------------------------------------------------------------------
# new method: post_metadata_notetags_reading -> postprocessing
#--------------------------------------------------------------------------
def post_metadata_notetags_reading
end
end #RPG::Troop

end #$imported["TIM-SimpleNotetagConfig"]


Terms and Credits
Free for commercial and non-commercial projects as long as you credit me.

Edit: updated to version 1.1, fixing test battle crash and handling tileset notetags.
Edit: updated to version 1.2, bringing hash table storage.
Edit: updated to version 1.3, the methods created by notetags should now be set once per class, this does not change anything aside from maybe performances at launch.


本贴来自国际rpgmaker官方论坛作者:Timtrack处,因国际论坛即将永久关站,为了存档多年珍贵资料,署名转载到本论坛存档,由于官方帖子为英文原帖,需要中文翻译请点击论坛顶部切换语言为中文就可以将帖子翻译成中文浏览,方便大家随时查看,原文地址:https://forums.rpgmakerweb.com/threads/simple-notetag-config-v1-3.179996/
页: [1]
查看完整版本: Simple Notetag Config v1.3