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.
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
…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
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.
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?
Use the
scan
method. For exampleThis returns all of the results and then you can just iterate over them.
That did the trick. Thank you very much.