累计送礼: 0 个 累计收礼: 1 个 TA的每日心情 开心 2026-7-12 04:10
签到天数: 209 天
连续签到: 2 天
[LV.7]常住居民III
管理员
VIP
7
卡币
58751
OK点
16
推广点
0
同能卷
50
积分 68660
This sole-created script adds no game-performing features, only to add a "Note" field support for XP database, which is a later-generation feature starting from RGSS2.
The Note support will open a new horizon for game scripting, save numerous efforts on tampering with massive configurations before a customized script, and make it simpler and neater to create your own functions.
Special: The WILD MODE (default on) support allows you to override database values, so you can have weapons attack > 1000, attack < 0, or skills with atk_f, dex_f... over 200, or create potions that recovers 999999 HP.
For more help, just read the text before the script.
Ruby:
#============================================================================== # ■ [Data Note] General Note Field for XP by SailCat #------------------------------------------------------------------------------ # Introduction: # This script "adds" a general Note field support for RPG Maker XP # database, which is a later-generation feature starting from VX. # The Note field is parsed automatically as Ruby Hash objects for easier # use in scripting. # # Installation Guide: # Insert this script before the "Main" section, preferably right after # Scene_Debug, or before as many custom scripts as possible. # # Date of release: # Sep. 1, 2024 # # Effects: # 1. Splits "Name" (Actors, Classes, Enemies, States, Animations, Tileset) # field as a place where you write notes. (max = 40 chars) # 2. Splits "Description" (Items, Skills, Weapons, Armors) field as a place # where you write notes. (max = 100 chars) # 3. Splits "Name" of Events and Maps as a place for notes. (max = 100 chars) # 4. In case you need longer notes, use labels to link to a storage common # event, or a file. # 5. For event pages. Write notes in the "comment" command consecutively in # the beginning of the command list w/o limitations. # This applys to map event pages, troop event pages, and common events. # # How to use: # # 1. Default Notes: # 1) Use "#" char (default as configurated) to split the regular name or # description with your notes. (as if writing comments for ruby) # Ex: an item with a description "Recovers HP." and note "concoct=12" # is written as "Recovers HP.#concoct=12" # 2) Use ";" char (default as configurated) to split note sections. # Ex: a note split as "concoct=12" and "wearout=60" is written as # "#concoct=12;wearout=60" # # 2. Extra Notes, choose either: # 1) Use "#>" + label name to refer to a label in the common event. # 2) Use "#<" + label name to refer to a label in a INI file. # # 3. Note Value-Pairs: # Write as standard: key=value, such as "concoct=12" # the key must be a valid ruby identifier # the value must be a valid ruby expression # or simplify as: # key or key+ for key=true # key- for key=false # key:string for key="string" # key.label for key=(refer to a label section in common event) # key=v[1] for key=$game_variables[1] # Why simplify? You have 40 or 100 chars only for a standard note. # In case a semi-colon ";" char is used in value, use "\;" to escape. # # 4. Using Notes in your own script: # In RGSS, use object._key(default_value) to get the value. # Ex: Your character 1 is NAMED as "Alexus#a;b=4;c=5" # $data_actors[1].name # => "Alexus" # $data_actors[1]._a # => true # $data_actors[1]._b # => 4 # $data_actors[1]._c # => 5 # $data_actors[1]._d # => nil --unused key returns nil # $data_actors[1]._d(2) # => 2 --unused key returns default # Ex: Your skill 1 is DESCRIBED as # "Recovers HP for an ally.#f:a.atk - b.def / 2;cd=1.5;no_ref-" # $data_skills[1]._f # => "a.atk - b.def / 2" # $data_skills[1]._cd # => 1.5 # $data_skills[1]._no_ref # => false # Mind that setting a note for one entry will not add it to other entries # $data_skills[2]._f # => nil # unless you set note f=xx or f:xx for it as well. # # 5. For neater scripting and to save the trouble of setting a note for # every entry, we strongly recommend to encapsulate the note fields in # your own script, and assign default values. For example: # # module RPG # class Actor # def gender; _a(false); end # def age; _b(0); end # def skill_per_level; _c(1); end # def perk_count; _d(2); end # end # class Skill # def formula; _f(""); end # def cooldown; _cd(1.0); end # def reflectable; !_no_ref; end # end # end # # Then you can use: # $data_actors[1].gender # => true # $data_actors[1].age # => 4 # $data_actors[1].skill_per_level # => 5 # $data_actors[1].perk_count # => 2 # $data_skills[1].formula # => "a.atk - b.def / 2" # $data_skills[1].cooldown # => 1.5 # $data_skills[1].reflectable # => true # $data_skills[2].formula # => "" # $data_skills[2].cooldown # => 1.0 # $data_skills[2].reflectable # => true # For any entry with or without notes. # # 6. WILD MODE: you can use note to override database default values. # When WILD MODE is activated (by default), you can override default # values by writing a note whose key corresponds to an existing field. # Ex: Your Weapon 1 is DESCRIBED as "An sword made of iron.#atk=1016" # $data_skills[1].atk # => 1016 # This is useful when you need a value that is beyond database limits. # (Only number fields is allowed in this case) # # 7. This script offers an easy interface for Note only, and without any # functions or features that deal with the notes. We leave them to your # own innovations and imaginations. # # 8. Writing Extra Notes in common events. # 1) Always use an EEP command before the common event you referred to. # 2) Use a unique Label command to mark a label section for reference. # 3) Use "Show Text", "Comment" "Script" or "Conditional Branch: Script" # to write the note text. # * Conditional Branch: Script allows 10000 characters maximum, which # will more than suffice. # 4) Refer to this label as either #key.label or #>label # Ex: Common Event 1 # - End Event Processing # - Label: Alexus_pro # - Comment: A warrior that excels at swordfighting, born in # 190 here. # - Label: Alexus # - Comment: age=16; sex:M; profile.Alexus_pro # - Label: Basil # - ...... # Actor 1 Name: Alexus #>Alexus # $data_actors[1]._age # => 16 # $data_actors[1]._profile # => # "A warrior that excels at swordfighting, born in\n190 here." # You can simply write "#>" without a label name, when the label name is # the entry name itself. # # 9. Writing Extra Notes in INI files. # 1) Follow the standard INI file format: # Ex: [Dorothy] # profile=Dorothy, a thief # age=28 # gender=F # height=175 # weight=60 # is_dual_wield=false # 2) Refer to this label using "#<" # Ex: Actor 4 Name: Dorothy #< # $data_actors[4]._profile # => "Dorothy, a thief" # $data_actors[4]._age # => 28 #============================================================================== #============================================================================== # ■ SailCat's XP Plugins #============================================================================== module SailCat #-------------------------------------------------------------------------- # ● Configurations #-------------------------------------------------------------------------- module DataNoteCore_Config SEPARATOR = "#" # Separator before Note DELIMITER = ";" # Separator between note sections (K/V pairs) NOTE_LABEL_CHAR = ?> # Marker for extra long notes in common event NOTE_FILE_CHAR = ?< # Marker for extra long notes in INI file NOTE_FILE = "Data/Note.ini" # File name for the INI file ACTOR_COMMON_EVENT_ID = 1 # Common event ID for Notes for Actors CLASS_COMMON_EVENT_ID = 2 # Common event ID for Notes for Classes SKILL_COMMON_EVENT_ID = 3 # Common event ID for Notes for Skills ITEM_COMMON_EVENT_ID = 4 # Common event ID for Notes for Items WEAPON_COMMON_EVENT_ID = 5 # Common event ID for Notes for Weapons ARMOR_COMMON_EVENT_ID = 6 # Common event ID for Notes for Armors ENEMY_COMMON_EVENT_ID = 7 # Common event ID for Notes for Enemies STATE_COMMON_EVENT_ID = 8 # Common event ID for Notes for States ANIMATION_COMMON_EVENT_ID = 9 # Common event ID for Notes for Animations TILESET_COMMON_EVENT_ID = 10 # Common event ID for Notes for Tilesets MAPINFO_COMMON_EVENT_ID = 11 # Common event ID for Notes for Maps EVENT_COMMON_EVENT_ID = 12 # Common event ID for Notes for Events NOTE_STRING_LF = "\n" # Line feed char for extra long signle note NOTE_DATA_LF = DELIMITER # Line feed char for extra long note data USE_WILD_MODE = true # Allow WILD MODE to override values #-------------------------------------------------------------------------- # ● Don't change this part #-------------------------------------------------------------------------- raise "Separator before and between Notes must be different" if SEPARATOR == DELIMITER raise "Extra long note markers must tell common event and file apart" if NOTE_LABEL_CHAR == NOTE_FILE_CHAR end end #============================================================================== # ■ DataNoteCore #------------------------------------------------------------------------------ # Core Engine for Note Field Support. #============================================================================== module DataNoteCore include SailCat::DataNoteCore_Config #-------------------------------------------------------------------------- # ● Constants #-------------------------------------------------------------------------- SEP_REGEX = /#{SEPARATOR}.+$/ # Don't change this #-------------------------------------------------------------------------- # ● Cache for flat arrays #-------------------------------------------------------------------------- $flat_array_cache = {} #-------------------------------------------------------------------------- # ● Retrive note values #-------------------------------------------------------------------------- def note # If not initialized if @note.nil? # For common events, use command list @note = split(get_command_note(list)) if self.is_a?(RPG::CommonEvent) # For map events, use command list @note = split(get_command_note(list)) if self.is_a?(Game_Event) # For troop, use command list in first page @note = split(get_command_note(pages[0].list)) if self.is_a?(RPG::Troop) # For others, use description, in case of no description, use name @note ||= has_description? ? split(@description) : split(@name) # Analyze analyze end # Retrieve the value return @note end #-------------------------------------------------------------------------- # ● Set note (Runtime support) # note: New note #-------------------------------------------------------------------------- def note=(note) # Set new note @note = note # Reanalyze analyze end #-------------------------------------------------------------------------- # ● Get/set the note value in general #-------------------------------------------------------------------------- def method_missing(param_name, *args, &block) return super unless respond_to?(param_name) param_str = param_name.to_s.sub!(/^_/, "") # Set if param_str[-1] == 61 param_key = param_str.chop self.class.send :define_method, param_name do |value| set_note(param_key, value) end set_note(param_key, *args) # Get else self.class.send :define_method, param_name do |value| get_note(param_str, value) end return get_note(param_str, *args) end end #-------------------------------------------------------------------------- # ● Method name validating #-------------------------------------------------------------------------- def respond_to?(method_name, *) method_name.to_s[/^_.+/].nil? ? super : true end #-------------------------------------------------------------------------- # ● Override in WILD MODE #-------------------------------------------------------------------------- def define_wild_methods return unless USE_WILD_MODE v = instance_variables.select {|i| instance_variable_get(i).is_a?(Numeric)} v.each do |i| next if i == "@id" var = i[1..-1] get_method = var; wild_get = "_#{var}" set_method = "#{var}="; wild_set = "_#{var}=" self.class.send :define_method, get_method do send wild_get, instance_variable_get(i) end self.class.send :define_method, set_method do |value| send wild_set, value instance_variable_set(i, value) end end end #-------------------------------------------------------------------------- # ● Flat array #-------------------------------------------------------------------------- def flat_array(param) case param when [] [] when Array $flat_array_cache[param] ||= param.inject([]) {|a, e| a.concat(flat_array(e))} when Hash flat_array(param.values) when Range param.entries else [param] end end #-------------------------------------------------------------------------- # ● Check description (Private method) #-------------------------------------------------------------------------- private def has_description? instance_variables.include?("@description") end #-------------------------------------------------------------------------- # ● Cut note from commands (Private method) #-------------------------------------------------------------------------- def get_command_note(list) for index in 0...list.length break if list[index].code != 108 and list[index].code != 408 end join_command_note(list[0...index], DELIMITER) end #-------------------------------------------------------------------------- # ● Join notes from commands (Private method) #-------------------------------------------------------------------------- def join_command_note(list, linefeed) (list.collect do |x| case x.code when 111 x.parameters[0] == 12 ? x.parameters[1] : "" when 209 ((x.parameters[1].list.select do |c| c.code == 45 end).map do |c| c.parameters[0] end).join(linefeed) else x.parameters[0] end end).join(linefeed) end #-------------------------------------------------------------------------- # ● Split key/value pairs (Private method) #-------------------------------------------------------------------------- def split(text) text.slice(SEP_REGEX).to_s end #-------------------------------------------------------------------------- # ● Get note value (Private method) #-------------------------------------------------------------------------- def get_note(param_name, default = nil) return default if self.note.empty? or not @note_set.include?(param_name) value = @note_set[param_name].nil? ? default : @note_set[param_name] value.is_a?(Proc) ? value.call($game_variables) : value end #-------------------------------------------------------------------------- # ● Set note value (Private method) #-------------------------------------------------------------------------- def set_note(param_name, value) @note_set ||= {} @note_set[param_name] = value end #-------------------------------------------------------------------------- # ● Get value from label (Private method) #-------------------------------------------------------------------------- def get_label(label, identifier, linefeed) # Retrieve from cache if any event_id = label.sub!(/^([0-9]+),/, "") ? $1.to_i : note_event_id label = default_label(identifier) if label.empty? $data_notes ||= {} if $data_notes.has_key?([event_id, label]) return $data_notes[[event_id, label]] end # Initialize common event $data_common_events ||= load_data("Data/CommonEvents.rxdata") event = $data_common_events[event_id] return "" if event.nil? or event.list.length == 1 # Find label list = event.list start_index = 0 end_index = list.length for index in 0...list.length next if list[index].code != 118 if list[index].parameters[0] == label start_index = index + 1 elsif start_index > 0 break end_index = index end end # Find note in commands if start_index == 0 result = "" else cmds = list[start_index...end_index] cmds.reject! do |x| not [101, 401, 108, 408, 111, 209, 355, 655].include?(x.code) end result = join_command_note(cmds, linefeed) end $data_notes[[event_id, label]] = result end #-------------------------------------------------------------------------- # ● Get value from INI file (Private method) #-------------------------------------------------------------------------- def read_ini_file(label) return unless FileTest.exist?(NOTE_FILE) # Initialize label label = default_label(nil) if label.empty? # Open INI file File.open(NOTE_FILE, "r") do |f| label_key = "[#{label}]\n" found = false # Loop for each line f.each_line do |l| # Continue for remarks next if l[0] == ?; or l[0] == ?# # Continue for wrong labels next unless l == label_key or found # Continue for the next line (found = true; next) unless found # Find Labels break if l[0] == ?[ # Find key/value pair pair = l.split("=", 2) next if pair.size < 2 key = pair[0].strip value = pair[1].strip # Try parse value as number, if failed, as string result = lambda{|v| eval(value) rescue value} result = result.call($game_variables) unless value =~ /v\[|\$/ # Set the value @note_set[key] = result end end end #-------------------------------------------------------------------------- # ● Get extra long notes' Event ID(Private method) #-------------------------------------------------------------------------- def note_event_id class_name = self.class.to_s[5..-1] eval(class_name.upcase + "_COMMON_EVENT_ID") rescue 0 end #-------------------------------------------------------------------------- # ● Get extra long notes' Label name(Private method) #-------------------------------------------------------------------------- def default_label(id) if self.is_a?(RPG::Event) sprintf("%03d#%s%s", $game_map.map_id, self.name, id ? "_#{id}" : "") else self.name + (id ? "_#{id}" : "") end end #-------------------------------------------------------------------------- # ● Analyze the note string (Single run for every object) #-------------------------------------------------------------------------- def analyze @note_set = {} # When empty, returns nil return if @note.nil? or @note.empty? # When label, read from reference if @note[1] == NOTE_LABEL_CHAR @note = SEPARATOR + get_label(@note[2..-1], nil, NOTE_DATA_LF) elsif @note[1] == NOTE_FILE_CHAR read_ini_file(@note[2..-1]) return end # Split strings param_regex = /^ *([A-Za-z0-9_]+)\b([+:=.\-]?(.*?))$/ # Delimit sections note_array = @note[1..-1].gsub(/\\#{DELIMITER}/, "\001").split(DELIMITER) note_array.each do |x| result = nil if x[param_regex] param_name = $1 param_value = $2 param_exp = $3.gsub(/\001/, DELIMITER) # Boolean (+) if param_value.strip.empty? or param_value[0] == ?+ result = true # Boolean (-) elsif param_value[0] == ?- result = false # Numeric elsif param_value[0] == ?= result = lambda{|v| eval(param_exp) rescue nil} result = result.call($game_variables) unless param_exp =~ /v\[|\$/ # String elsif param_value[0] == ?: result = param_exp # Label elsif param_value[0] == ?. result = get_label(param_exp, param_name, NOTE_STRING_LF) end @note_set[param_name] = result end end end end #============================================================================== # ■ RPG Module Inclusions #------------------------------------------------------------------------------ # Include this function for 14 RPG modules. #============================================================================== module RPG [Actor, Class, Enemy, State, Animation, Tileset, MapInfo, Event].each do |c| c.send :include, DataNoteCore c.send :define_method, :name do @name1 ||= (@name.sub(DataNoteCore::SEP_REGEX) {|s| ""}).strip end c.send :define_method, :name= do |value| @name1 = value.strip @name = @name1 + DataNoteCore::SEPARATOR + note end c.new.define_wild_methods unless c == RPG::Event end [Item, Skill, Weapon, Armor].each do |c| c.send :include, DataNoteCore c.send :define_method, :description do @description1 ||= (@description.sub(DataNoteCore::SEP_REGEX) {|s| ""}).strip end c.send :define_method, :description= do |value| @description1 = value.strip @description = @description1 + DataNoteCore::SEPARATOR + note end c.new.define_wild_methods end [Troop, CommonEvent].each do |c| c.send :include, DataNoteCore end end #============================================================================== # ■ Game_Event #------------------------------------------------------------------------------ # Include this function for Game Events (runtime map events). #============================================================================== class Game_Event include DataNoteCore end 复制代码
本贴来自国际rpgmaker官方论坛作者:SailCat处,因国际论坛即将永久关站,为了存档多年珍贵资料,署名转载到本论坛存档,由于官方帖子为英文原帖,需要中文翻译请点击论坛顶部切换语言为中文就可以将帖子翻译成中文浏览,方便大家随时查看,原文地址:
https://forums.rpgmakerweb.com/threads/add-note-support-for-xp-database.171601/