You are welcome to create new Reflex-compatible scripts. The main use for this for sending and receiving "bang" messages from sensors and to actuators using your own timing and other behavior logic. But you can also create your own reusable sensors, actuators, and logic components for resale, too.

Just keep in mind that the Reflex name and standard are created and maintained by Galen and under the Metaverse Machines brand. You must represent your creations as your own and not explicitly endorsed by me or as part of Metaverse Machines.

Template script

To get started, please get the template script:

Reflex script template 3.3.cs

All Reflex 3 scripts started as a copy of this script. In addition to adding your own settings, you'll also need to modify the .CustomInitialization(), .GetSettings(), .SetSettings(), and .Validate() methods if you are creating a reusable Reflex component script. You can ignore the latter 3 if you are just creating a custom control script for your scene. They implement the "live programming" feature of Reflex.

To detect and respond to specific bang messages, edit the .IncomingReflexMessage() method, which comes with a code stub for doing just that. To send out your own bang messages, invoke one of the various .Bang() methods.

Reflex message structure

The template script above contains code for constructing and parsing bang and other messages, but if you want to craft your own, here is some guidance on how best to do it. Please do consult the library functions in the template script for exacting details.

If you want to see real Reflex messages and try sending some of your own by hand, add the Reflex console to your scene and try the following chat commands:

/reflex showbangs on
/reflex bang DemoBang

Reflex3|1|Bang|demobang|1|1

All Reflex messages are sent out on channel 1000. Older Reflex 2 and 1 scripts share this channel, but they will not interact with Reflex 3 scripts either way. All Reflex 3 messages begin with "Reflex3|", for example, while older Reflex versions use different prefixes.

Each Reflex message is a pipe-delimited list of arguments, as in the above example. These are escaped using a simple set of replacements:

The first argument is always "Reflex3" (exact case), so a validator should filter out other messages using the same channel with a check like the following:

protected void IncomingMessage(int Channel, string Source, 
  SessionId SourceId, ScriptId SourceScriptId, string Message
) {

    if (!Message.StartsWith("Reflex3|")) return;
    ...

}

The second argument is always the ID of the script, collected using the standard Script.ID. This is an ideal way to refer uniquely not only to scripts in objects, but also in effect to the objects themselves. Note that this is not actually an integer. It is typically a hexadecimal number (e.g., "2f"), but it's best to just treat it as an arbitrary string value.

The third argument is always the major operation. For your integration work, this will almost always be "Bang". However, there are other operations used for live programming. And some Reflex scripts have special operations, such as how the lock key script sends out "LockKeyAt" messages frequently so locks can tell when they are in range.

After the third argument, all other arguments are custom to the specific operation. For Bang messages, the fourth argument is the bang name (e.g., "DemoBang"). This is almost always an optionally suffixed version of the Name setting for that script (e.g., "TriggerVolume1:On").

After the bang name, the fifth argument is a "bang entity type" indicator with one of the following values:

For agents, the sixth argument is the SessionId of the agent. For objects, it's the ObjectId value for the object. And for unspecified types, it's "0".

Some reflex scripts will tack on extra arguments after the sixth to give custom applications like yours additional context. For example, the command script will send the full message text that matched its filter. Since standard Reflex scripts are designed to be binary in nature, there's nothing they can really do with this extra data.

Manipulating other Reflex scripts

Remember how you can live-program Reflex scripts using the Reflex console? Your scripts can also alter those same Reflex scripts' settings at run-time. You might want to dynamically adjust the range on a proximity sensor or disable a door from opening. You might want to adjust the volume of background music or environmental sounds for an event.

You would do well to turn on all messages and study the messages the console sends out when you do live-programming stuff. However, here is some insight into how to change the settings on some other Reflex script. You will use the "SetSettings" operation. Here's an example of a message that you'd send out:

Reflex3|1|SetSettings|Teleporter1|TriggerNamesCsv|ToPosition:0,0,2\pTriggerNamesCsv:Lava:On

You'd do better to just use code like the following if you start with the template script:

string NewSettings =
    "ToPosition:"      + Util.Escape(NewPosition) + "|" +
    "TriggerNamesCsv:" + Util.Escape(NewTriggerNamesCsv);

SendReflexMessage("SetSettings", ToReflexName, NewSettings);

You can also send out a "GetSettings" message with the ID (in brackets) or Reflex name of the script as the only other argument. You'll get a "Settings" message in response that has the same pipe-delimited keys/values structure as the kind you send out with "SetSettings".