Euphoria 147 Posted May 3, 2014 (edited) So I know that I've seen many scripts put the Regex in a module first like so: module Euphoria module Regex REGEX = /<KillItem = (\w+)>/i #Example from one of my scripts. REGEX2 = /<KillItem = (\w+)>/i #Example 2 (pretend it's different...) REGEX3 = /<KillItem = (\w+)>/i #And so on... end end Then I see them call the notetags like this: module DataManager self << class; end #Why put end here? alias alias_database load_database def self.load_database alias_database load_notetags end def self.load_notetags groups = [$data_skills, $data_items, $data_states] for group in groups # for obj in group #Can someone explain these three lines a bit? next if obj.nil? # obj.load_notetags #Same method as above? Why? end end end end I don't exactly understand all of that part, and I absolutely have no idea what follows this... Can someone explain what to do next, and what it all means? (My questions are listed as comments in the code box above) Is there alternate ways of loading notetags? The tutorials I followed never went into loading notetags outside of the module (using something like "item.note.scan(Regex Here)" ) P.S. Sorry if there are any mistakes, this was mostly off the top of my head. Edited May 3, 2014 by Euphoria Share this post Link to post Share on other sites
Kaelan 25 Posted May 4, 2014 (edited) Breaking it down line by line: groups = [$data_skills, $data_items, $data_states] for group in groups for obj in group next if obj.nil? obj.load_notetags end end 1. Store the skills, items and states from the database in an Array 2. Iterate through that array, calling the current collection a "group" (first all skills, then all items then all states) 3. Iterate through each object in the current group. So when iterating through $data_items, obj is the current item. When iterating through skills, obj is the current skill, etc. 4. Most things in the database are 1-indexed, while Ruby collections are always 0-indexed. This means that the first item in each database collection (i.e. $data_items[0]) is usually nil. This line skips processing those to avoid errors. 5. Call the load_notetag function of the current object (current item, skill or state). I imagine the engine that's in has defined a load_notetag function for RPG::BaseItem, RPG::Skill and RPG::State. It's not calling the same function (DataManager::load_notetags), it's calling a function that has the same name in a different object (i.e. RPG::BaseItem.load_notetags). All that said, this code isn't actually doing any parsing, it's whatever gets called by the obj.load_notetags method that's parsing things. You can parse notetags in anyway you want. How you parse it is part due to preference and part due to how you decide to format the information inside your notetags. For items, for example, item.note returns a string containing whatever is in the note. So you use Ruby's regex functions to find the regex inside that string and store it somewhere. Here's a simple example I use for parsing enemy data in my combat engine: RX_ENEMY_TYPE = /<monster_type:\s*(.+)>/i def note_get_monster_type m_data = RX_ENEMY_TYPE.match(@enemy.note) if m_data.nil? || m_data[1].nil? @monster_type = "(NOT SET)" else @monster_type = m_data[1] end end It's set to match a notetag that looks like this: <monster_type: Hobgoblin Regular> inside my enemy notes.The Regexp.match method returns nil when nothing is found, or a MatchData structure when it is. MatchData[0] returns the entire matched string ("<monster_type: Hobgoblin Regular>"). MatchData[1] returns the equivalent of $1, which is the string matched by the bit in parenthesis inside the regex ("Hobgoblin Regular", in this case).A more complicated example: RX_ENEMY_STATS = /<stat_data>[\r\n]*/i def note_get_base_stats @enemy.note.split(RX_ENEMY_STATS).each do |block| next if block.empty? # Skip the start of the note block (the <stat_data> line) block.split('*').each do |line| # Split each part of the block starting with '*' into a line symbol = line.match(/:[\S]+/) # Find the first symbol in the line (i.e. ":str") next unless symbol # Skip this line if there aren't any symbols on it symbol = symbol[0] # Grab the symbol from MatchData[0] line.sub!(/:[\S]+[\s]+/, "") # Remove the matched symbol from the line line.chop! # Chop the newline character out from the end of the line cmd = "@stats.set(#{symbol}, #{line})" # Call a function that sets the stats using eval(cmd) # the loaded symbols. i.e: # @stats.set(:str, :base, 13) # Repeat for each stat end end end Which runs on a tag with (for example): <stat_data> * :str :base, 13 * :dex :base, 10 * :con :base, 16 * :int :base, 10 * :wis :base, 15 * :cha :base, 12 * :ac :base, 1 * :hp :base, 29 * :mhp :base, 29 * :fort :base, 3 * :reflex :base, 1 * :will :base, 3 * :bab :base, 2 <stat_data> Hope that clarifies things a bit. Edited May 4, 2014 by Kaelan 2 Share this post Link to post Share on other sites
Euphoria 147 Posted May 4, 2014 I'll have to go through it again just to help me memorize it but it was really well explained. Thanks a ton Share this post Link to post Share on other sites
Kaelan 25 Posted May 4, 2014 Oh, right, I almost forgot. If you want to practice formatting regular expressions or forget what all the symbols mean, you can use this website: http://www.rubular.com/. It lets you quickly test whether a regex matches a string and has a quick reference of all the accepted characters in one page. I use it a lot when messing with regex stuff, it's faster than trying to test it in RPG maker and having to run your game every time just to check if your regex is correct. You can also use http://codepad.org/ to run small bits of Ruby code and check quickly whether it's doing the right thing or not. Share this post Link to post Share on other sites
Euphoria 147 Posted May 4, 2014 Thanks I've been using rubular, but codepad should be very useful! Share this post Link to post Share on other sites