Basic guide to working with note-tags

With the abundance of note boxes in RPG Maker VX Ace, scripters have turned to note-tagging to add extra data to various objects like actors, skills, or maps. The ability to write scripts that work with notes is a very useful skill to develop as a scripter.

tutorial-notetagging1

This tutorial goes over the very basics of note-tag parsing.

What is a note

A note is a string.
That is all you need to keep in mind.

What is a note-tag

A note-tag is a specific string contained inside the note. It usually conforms to some pattern that is specified by the scripter.

For example, I structure them with opening and closing brackets

<cmd: use_skill 6>

While others may prefer to use a simpler pattern

test: 5

It doesn’t really matter what you prefer as long as you can accurately parse your tags without running into issues with other tags that may potentially contain values that LOOK like your tag.

A working example: overview

Here is the problem I will be using to walk through note-tags.

Suppose we want to add a “gender” property to our actors.
Because there is no gender field in the database editor, I decide to use note tags.
To specify an actor’s gender, I want to tag them with

<gender: male>
<gender: female>

How to load note tags

There are many ways to load them. How you want to do it is up to you.
I would write it like

module RPG
  class Actor < BaseItem

    #-----------------------------------------------------
    # Return the actor's gender. Load it from the notes
    # if necessary
    #-----------------------------------------------------
    def gender
      return @gender unless @gender.nil?
      load_notetag_actor_gender
      return @gender
    end

    def load_notetag_actor_gender
      # do it later
    end
  end
end

Reading the note

Now the question is how to define load_notetag_actor_gender. You can use any string-parsing techniques that you know, but I would prefer to use regular expressions because they provide powerful pattern-matching functionality that is useful for working with unstructured data like a string.

If you don’t know anything about regular expressions (regex), I would suggest doing a couple exercises on them to become familiar with the syntax.

You should also use Rubular for designing and testing your expressions.

Defining the regex

Anyways so we start by defining the regex.

/<gender:s*(male|female)>/i

It is pretty simple, because the format of the tag is basically

  • Begins with open bracket
  • Followed by the string “gender”
  • Followed by a colon
  • Followed by zero or more white-space characters (like spaces)
  • Followed by the string “male” or the string “female”
  • Followed by a close bracket

I have decided it can be case-insensitive because that detail is not important.
I have also grouped on the “male” or “female” string because I want to quickly retrieve that in the code.

You may need more complicated regex, but in general note-tags should be simple for users, and consequently you will find yourself coming up with simple expressions.

Using the regex to read the note

Coming up with the regex is probably the more challenging part of note-tagging because it requires you to actually learn something new.

After you have your regex, you just need to know how to call it.
The load_notetag_actor_gender method that I have left empty earlier can be defined as follows.

def load_notetag_actor_gender
  # my regex
  regex = /<gender:s*(male|female)>/i

  # run my regex over the note looking for matches
  res = self.note.match(regex)

  # assign the result
  if res
    @gender = res[1].downcase
  else
    @gender = ""
  end
end

Or, more compactly, I would just say

def load_notetag_actor_gender
  regex = /<gender:s*(male|female)>/i
  @gender = self.note =~ regex ? $1.downcase : ""
end

Either way, it properly reads the note and grabs the field I want.

Capturing multiple note tags

The above example uses the “match” method to parse the note, which only captures one note-tag. However, there are cases where you can have multiple note-tags that you want to capture. In this case, you want to use the “scan” method, which will return all of the matches as an array.

Here is an example of how it is used:

regex = /<bonus: (\w+) (\d+)>/i
note = "<bonus: atk 10><bonus: def 20>"
results = note.scan(regex)
results.each do |res|
   p res
end

This example involves some sort of bonus for your parameters, possibly multiple different parameters. Using the “match” method would only return the first one, so we use the “scan” method to capture and process all of them.

And that’s it

Now that the @gender instance variable has been populated, I can access that data by simply grabbing a reference of the RPG::Actor object and getting its gender

$data_actors[1].gender

References

http://regex.learncodethehardway.org/book/ – start from the beginning.
http://rubular.com/ – And of course Rubular

You may also like...

58 Responses

  1. lioleus says:

    …I think WordPress needs a preview option for comments. The regex there was slightly mangled, I'm afraid; there should be asterisks following most instances of \s, and all instances of \d

    • Hime says:

      Previews would be nice. Even I sometimes wonder whether what I'm typing will be shown properly. I haven't found a preview plugin that is compatible with this comment system though.

      I’ll disable the fancy comments in favor of comment previews.

  2. lioleus says:

    I've recently gotten into the use of regex for scripting, and have used it in other environments before, but I've run straight into an issue and whilst your guide keeps coming up when I look for answers, the answer isn't here.

    Do you know how to detect multiple instances that match a given pattern? For instance, I'm trying to find instances of something like '<recruit equipment: [slot], [id]>' (with appropriate values filled in), which is picked up with the regex /<recruit\sequipment\s:\s(\d),\s(\d)>/i
    My issues start when I try to pick up more than one copy of that tag. Whilst Rubular says it should pick up multiple copies as multiple match groups, that doesn't work and RPG Maker only ever seems to pick up the first tag. Even when changing the regex to /(<recruit\sequipment\s:\s\d,\s\d>)/i or /(<recruit\sequipment\s:\s\d,\s\d>)+/i it only picks up the first instance of the tag (eg. <recruit equipment: 0, 1>) and not the second (eg. <recruit equipment: 1, 1>)

    Without seeing the code because it wouldn't be very readable, can you make any suggestions as to how to go about detecting multiple copies of a given tag? Or would you need to see the code in question to make any suggestions?

    • Hime says:

      Use the scan method. For example

      str = "<tag: 1><tag: 2><tag: 3>"
      regex = /<tag: (\d+)>/i
      p str.scan(regex)
      

      This returns all of the results and then you can just iterate over them.

Leave a Reply to lioleus Cancel reply

Your email address will not be published. Required fields are marked *