Hermes is a script for RPG Maker XP that extends the functionality of the built-in message window. It it highly configurable and comes with some enhancement for text display in other windows as well.
The current version is Hermes 0.4. Before you ask, yes, that means it's 40% finished. Yet it is much better than many other scripts that claim to be 100% finished. I can't test everything, and Hermes probably is not bug-free. If you find a bug, please tell me about it! I might not be able to fix it right away, but I will try my best to memorize it until I get to work on Hermes again!
Color.new("#FFFFFF7F")
is now equivalent to
Color.new(255, 255, 255, 127)
Hermes 0.4 is the first version to not ship as a single script. Not even as four single scripts, like the developer version used to. No, it comes in 25 files spread across 6 folders. Why? Because it's easier - easier for me to maintain, easier for you to install.
Inserter is a script that can modify existing RPG Maker scripts on-the-fly: When the game is started, it imports all the scripts (*.rb files) it will find in the Data/Scripts folder or sub folders, sorted by path / file name. If no further instructions are given in a certain script, it will be inserted above Main. However, Inserter scripts also have the ability to alter existing scripts, for example to add features to standard classes. For this to work, however, the scripts it tries to alter must not have been changed manually. Hermes inserts code into Game_Temp, Scene_Map, Scene_Save, Scene_Load and Main, so make sure these scripts have not been altered. Also, insertion might fail if you are not using the scripts from the official English RGSS version.
If your project fulfills these requirements, the only thing you really need to do is to install Inserter. Since Inserter is a previously unreleased script, I have included it with Hermes 0.4. If you haven't downloaded Hermes yet, you can get it from its official website. If you only want to install Inserter for some reason, you can also download it from the Inserter website.
Either way, the archive will contain a text file called plainly inserter.txt. Open it with your favorite text Editor, copy the complete contents to the clipboard, launch RPGXP, open your pet project, open the script editor, insert a new script at the very top of the list (not directly above Main!), select the script and paste from clipboard. Optionally, rename the script into "Inserter". Then hit OK, done!
If you haven't deleted or modified and of RPG Maker's original scripts, Inserter should be able to patch the required files into your project. If you get a message from Inserter that not all Scripts could be modified, Hermes will not work correctly. In this case, make sure all the original scripts in your project are virgin. Having other scripts installed is not a reason why Insertion would fail, only if original scripts have been changed in-place!
There are lots of settings available for Hermes. Some of them can even be changed while the game is running, others are static. To adjust the settings to your liking, please have a look at the config scripts that should be located in Data/Scripts/Hermes/0 - config/*.rb. They are segmented into four parts for convenience. Open the .rb files with your favorite text editor and change the settings to your liking. Their meanings are mostly described in the scripts themselves, however some of the savable settings are only introduced briefly. To see a more detailed description for those, please read on.
Here is a complete list of settings you can change during the game. Most of them are obvious or well enough explained in the config section, so I won't talk about them too much. But I do want to say a few things about the less obvious options; see below this table.
Setting | Default | Expected |
---|---|---|
font_name | Hermes::Message::Text::NAME | String, Array or :default |
font_size | Hermes::Message::Text::SIZE | Positive whole number or :default |
font_bold | Hermes::Message::Text::BOLD | true, false or :default |
font_italic | Hermes::Message::Text::ITALIC | true, false or :default |
font_color | Hermes::Message::Text::COLOR | Color, "#RRGGBB[AA]" or :default |
font_shadow | Hermes::Message::Text::SHADOW | TextEffect, Array or :default |
font_outline | Hermes::Message::Text::OUTLINE | TextEffect, Array or :default |
font_texture | Hermes::Message::Text::TEXTURE | String, :default or :none |
align | Hermes::Message::Text::ALIGN | 0 for left, 1 for center or 2 for right |
valign | Hermes::Message::Text::VALIGN | 0 for top, 1 for middle, 2 for bottom |
sound | Hermes::Message::Text::SOUND | String or :off |
speed | Hermes::Message::Text::SPEED | Non-negative Integer |
prevent_skipping | Hermes::Message::Text::PREVENT_SKIPPING | true or false |
width | Hermes::Message::Box::WIDTH | Positive Integer |
line_max | Hermes::Message::Box::LINE_MAX | Positive Integer |
shrink | Hermes::Message::Box::SHRINK | true / false |
line_height | Hermes::Message::Box::LINE_HEIGHT | Positive Integer |
margin | Hermes::Message::Box::MARGIN | Integer |
event_x | Hermes::Message::Box::EVENT_X | Integer |
event_y | Hermes::Message::Box::EVENT_Y | Integer |
opacity | Hermes::Message::Box::OPACITY | Integer between 0 and 255 |
skin | Hermes::Message::Box::SKIN | String or :default |
name_font_name | Hermes::Name::Text::NAME | String, Array or :default |
name_font_size | Hermes::Name::Text::SIZE | Positive whole number or :default |
name_font_bold | Hermes::Name::Text::BOLD | true, false or :default |
name_font_italic | Hermes::Name::Text::ITALIC | true, false or :default |
name_font_color | Hermes::Name::Text::COLOR | Color, "#RRGGBB[AA]" or :default |
name_font_shadow | Hermes::Name::Text::SHADOW | TextEffect, Array or :default |
name_font_outline | Hermes::Name::Text::OUTLINE | TextEffect, Array or :default |
name_font_texture | Hermes::Name::Text::TEXTURE | String, :default or :none |
name_pos | Hermes::Name::Box::POS | 0, 1, 2 or 3 |
name_overlap | Hermes::Name::Box::OVERLAP | Integer |
name_offset | Hermes::Name::Box::OFFSET | Integer |
name_padding | Hermes::Name::Box::PADDING | Integer |
name_swap | Hermes::Name::Box::SWAP | true of false |
name_opacity | Hermes::Name::Box::OPACITY | Integer between 0 and 255 |
name_skin | Hermes::Name::Box::SKIN | String or :default |
All these settings can be changed at any time during the game and will be
saved to and loaded from game saves. To change e.g. the message font, you can
insert a Script event command into your event body and write something like
Hermes.font_name = "Times New Roman"
. Alternatively, you can use
the (shorter) global variable $msg, e.g., to make the font in the name box
bold, type $msg.name_font_bold = true
. By definition, all the
changeable settings have a default value (which can be changed in the config
section). To reset a setting to its default, you can simply set it to nil. The
default will then be assumed automatically. For example, if you want to reset
the message window's font color to the one specified in the config file, write
Hermes.font_color = nil
.
The value ":default" is something different than the "default value"! Changing a setting to :default will not reset it to the defult specified in the config file. Rather, it will cause this setting to use RGSS' default value.
For fonts, setting Hermes.font_* to :default will result in the value being changed to Font.default_*. Since when Hermes is started, Font.default_* are set to the values font in Hermes::GlobalText::*, you can roughly say the value :default refers to those (which is not entirely true, because Font.default_* can be changed later).
If you set the message or name window skin to :default, it will use the default skin you set in RPG Maker. Even if you change the window skin during the game, it will always use the one currently set. (This behavior was bugged in Hermes <0.4, where setting it to :default only copied the default skin once)
If an unexpected value is tried to be assigned to one of the properties, Hermes will spit out a warning (if the game is run in debug mode; this behavior can be disabled, see DEBUG_WARNINGS in the config section) and then set the setting to a fallback value. It is recommended not to turn off debug warnings during the development and when a warning appears, don't just ignore it but try to fix the issue! While you might be lucky and the Game will continue without crashing, you'll never know what unexpected side results might have arisen.
These settings rely on a common class, TextEffect. When you set either of
them, you have the choice to pass a TextEffect object or an Array. If you
pass an Array, it will be immediately used to create a TextEffect. So consider
the Array option a convenience to take less space. To create a TextEffect, you
can specify either one or two arguments. The first one is the strength of the
effect (offset for shadow, width for outline), the second one a Color. If the
latter is left out, a default color (black, 50% opacity) will be used. So, for
example,
Hermes.name_font_outline = TextEffect.new(2, Color.new(255,255,255))
will create a 2 pixel wide, white outline and make the name box use it.
The following does the same, but is more likely to fit into the short lines of
Call Script event command:
$msg.name_font_outline = [2, "#FFFFFF"]
.
A texture is a small Bitmaps which Hermes will use as a "skin" for your font. It can be of any size, but since Hermes usually draws every letter individually (but at least every line), it will only ever use the upper left part of the image if it's too large. It can't be to small though, as it's automatically repeated in both dimensions. The picture needs to be in the Graphics/Picture folder.
If a texture is set, Hermes will first draw the text as usual including any text effects if set. Then, it tiles the texture over the text. To determine the color to use for each new pixel, Hermes calculates, for each color channel, the square root of the product of this channel's values from the text and the texture bitmap. This causes the effects to stay intact, but is really slow, too! So please use textures carefully.
This is a new feature of Hermes that will, if enabled, change the height of the message window dynamically depending on how many lines are actually in the box compared to the maximum line number. For example, if line_max is 6, shrink is set to true and a message is shown with only 3 lines, the box is shrunk to that height. This setting cooperates nicely with the vertical align setting. E.g., if vertical align it set to bottom, the message window will shrink "towards" the bottom of where it is shown.
Value | Meaning |
---|---|
0 | Position name box in upper left corner of message window |
1 | Position name box in upper right corner of message window |
2 | Position name box in lower right corner of message window |
3 | Position name box in lower left corner of message window |
Setting | Meaning |
---|---|
name_overlap | Number of pixels the name box should be moved in y direction towards the center of the message window. If negative, it will be moved away. A value of 0 means that they are directly on top of each other. |
name_offset | Number of pixels the name box should be moved in x direction towards the center of the message window. If negative, it will be moved away. A value of 0 means that their outer borders line up vertically. |
name_padding | Number of pixels of empty space between the name and the name box borders. |
name_swap | If this is activated, the name box's position will be changed to the opposite to avoid getting pushed out of the screen. |
Hermes can easily be expanded to support more tags. Instead of the full name, you can shorten every tag in your Show Text command, as long as it stays ambiguous. For example, you can safely abbreviate \Sound to \so, but not to \s because then it would conflict with other Hermes tags, for example \Shadow.
In the following, I will use a simple-as-possible Backus-Naur form variant to describe the syntax of the Hermes tags. Here's a quick overview of how it works:
Notation | Meaning | Example |
---|---|---|
green color | Whole, positive number | meaning of life could be 42 but not -1 or 42.5 |
red color | A string of characters | rgss could be completely bugged or well that's it |
blue color | A fixed value | life must be life |
a..b | Numbers between a and b | 2..6 could be 4 or 6 but not 9 |
( a / b ) | Alternate | ( pork / beef ) could be pork or beef but not ham or 5 |
[ a ] | Optional | [ hero ] could be I or you or nothing |
{ a } | None, one or more | { 2 / girls / 1 / cup } could be 21cupcupcup or nothing |
Draws the following text in the specified color, which is either a color code from 0 to 7 (see table below) or a hexadecimal color code which may include an alpha value. The latter should start with a # sign, like in HTML/CSS.
Color code | Color |
---|---|
0 | |
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8-9 |
Color code | Color |
---|---|
#FFFFFF | |
#8080FF | |
#FF8080 | |
#80FF80 | |
#80FF80FF | |
#80FF8080 | (semi-transparent) |
#80FF8000 | (invisible) |
#FF8000 | |
#0080FF | |
#fd6e57 | |
#79e7e6 | |
... | ..... |
For all of the above tags, there is an equivalent one for name boxes (see
\NameBox), by prepending the respective tags with
an underscore character (_). For example, to change the text size in the name
box. You can write \_size[26]
. However, this will only work when
a \NameBox tag has been used before, in the same
message. If you try to set a font property prior to setting a name box text,
it simply won't work.
Displays one of the following things:
First argument | Second argument | Result |
---|---|---|
e | enemy id | Name of the enemy with the given ID |
i | item id | Icon and name of item with the given ID |
w | weapon id | Icon and name of weapon with the given ID |
a | armor id | Icon and name of armor with the given ID |
s | skill id | Icon and name of skill with the given ID |
(none) | variable id | Value of game variable with the given ID |
Shows a single face graphic or a face graphic out of a faceset image. These images need to be present in the Graphics/Pictures folder of your project. If an actor ID is specified, it will look for the file Graphics/Pictures/face_actor id, if a file name is specified, it will naturally look for Graphics/Pictures/file name.
If a face alias was specified, it will translate it into a face ID via the rules specified in config/face.rb. By default, these are:
Alias | Face ID |
---|---|
normal | 1 |
happy | 2 |
sad | 3 |
angry | 4 |
If a face id was specified directly or resolved this way, the picture
file will be considered a faceset, consisting of an arbitrary number of
rows with 4 faces each. The row height is assumed as
Hermes::Face::HEIGHT, the face width is assumed as image width divided by
four, and the face id is counted left-to-right, top-to-bottom. Example:
1 normal | 2 happy |
3 sad | 4 angry |
5 | 6 | 8 | 8 |
9 | 10 | 11 | 12 |
The third part is a string of flags, which will be loaded one after
another. If one property is set more than once, only the last version
will be used. Here is what the flags stand for:
Flag | Meaning | Explanation |
---|---|---|
a | Animate the face | The face will be animated by using the a single column of the graphic as the set of frames. In the above example, 2, 6, and 10 would form the animation frames if we called \f[bla,happy,a]. |
1..9 | Animation speed | Ineffective if a is not set. If it is, the animation speed will be set to the given value (1=fast, 9=slow). |
c | Animation type "cycle" | Ineffective if a is not set. If it is, the animation will be a repeat-from-start type, e.g. the frame sequence would be 2, 6, 10, 2, 6, 10, 2,... if we take the same example as above. |
s | Animation type "seesaw" | Ineffective if a is not set. If it is, the animation will be a inverse-direction type, e.g. the frame sequence would be 2, 6, 10, 6, 2, 6, 10, 6,... if we take the same example again. |
p | Pause animation along with message | Ineffective if a is not set. If it is, the animation will be paused when the message is paused, i.e., when it shows the small blinking arrow and waits for the user to hit a choice key. |
d | Don't pause along with message | Ineffective if a is not set. If it is, the animation will not be paused with the message. |
l | Face position: left | Face graphic will be shown in the left of the message window. |
r | Face position: right | Face graphic will be shown in the right of the message window. |
n | Face orientation: normal | Face graphic will be shown in the same orientation it has in the original graphic. |
m | Face orientation: mirrored | Face graphic will be flipped horizontally. |
The tags in this section are different from all the others in that they aren't defined and parsed as usual. They are "magic" in a way, being executed outside of the normal procedure.
If this tag is specified, the containing message will be opened as a speech-bubble-esque pop-up over a defined character, or in full screen mode with transparent background. The first argument is used as follows:
Value | Meaning |
---|---|
screen, -1 | Full screen message with transparent background |
hero, 0 | Pop-up over the player |
event id | Pop-up over the event with the specified ID |
this, (none) | Pop-up over the event currently being executed |
The full screen text box will display as many lines as fit the screen and
can be used for various overlay text, e.g. game credits. The pop-up
version will be automatically resized to the size of the text it contains
and will be fixed to the event it is attached to. If the event moves,
the box follows. When the second argument is not set, the box will try
everything to stay on screen, while still staying as close to its host as
possible.
But the second parameter (async) is where it gets really interesting. If it is set, the message window will not be controlled by the player. Instead, it will stay by its event until you close it manually. This can either be done with a \Close command inside this message or by opening a new message attached to the same event. If you want to close it with the latter method without opening a new window, simply set an empty message to pop up over the event. Empty messages will not be shown, however the old box will still be closed.
Asynchronous messages (i.e., such with the async flag set) can use all the things normal messages can, except for choices and input numbers. They will move with their events, even outside of the visible area. There's a virtually unlimited number of asynchronous messages possible, but only one per event at a time.
An interesting edge-case is when a synchronous pop-up message is showing, and then, invoked by e.g. a parallel process event, an asynchronous message is shown. The synchronous will then be killed without player interaction. You can see this demonstrated in the Hermes Demo, along with related behaviors when using asynchronous messages.
In battle, pop-up messages can also be used. If the supplied argument is a number less than 4, it will pop up over the party member with the fitting ID. If it is greater than three, it will pop up over the enemies (i.e., if 4, it will appear over the first monster, if 5, over the second etc.). However, battle might be bugged. I haven't properly tested this, in particular not with asynchronous messages.