Description
The NPC Behaviour system allows NPCs to be created, and their subsequent behaviour controlled, by instructions contained within notecards.
Construction
A prim in a linkset - not necessarily the root prim - contains:
the NPC Behaviour script
one or more behaviour notecards
one or more NPC appearance notecards (compatible with osNpcCreate(), etc)
optional "speech center" prim (see Sound section)
optional sound files (see Sound section)
There may be more than one such prim in a linkset (untested), although there is no need for this.
NPC appearance notecards may be created using osNpcSaveAppearance().
Behaviour notecards
Each behaviour notecard is used to control one NPC only. It is comprised of three sections:
the first line contains the text "NPCBE,<n>" where <n> is a version number (currently 1)
a section of INI-style declarations which define certain values
a section of procedural code which defines the behaviour of the NPC
Comments may be preceded by "//", and blank lines are permitted.
Declarations section
The following values should be in the declarations section:
Parameters
Code section
Each line contains a command followed by parameters where necessary. Commands and parameters are separated by whitespace. Text parameters should be enclosed in double quotes.
Commands
On reaching the end of the instructions, execution loops back to the Start line.
Positions/waypoints
Positions can be either the name of a waypoint or a literal vector (enclosed in <>) for a local position.
Waypoints are linked prims that have the prim name "Waypoint" and the waypoint name in the prim description. They can be any type of prim.
Named prims
Prims specified in the Sit and Click commands can be any prim in the linkset with the name specified. If there are multiple prims with the same name, the one nearest to the NPC is used.
Movement
When a Walk, Run or Fly command is executed, the following command is executed only when the NPC arrives at the waypoint. The arrival is detected by comparing the NPC's position with the destination - if within a radius of 1m, execution continues.
Animations
There is an assumption that only one animation will be active at any time - the "Animation" command stops previous animations. Any NPC movement will continue while the animation is in effect - to prevent this, use the Wait command to halt the avatar for the duration of the animation.
Sound
The Sound command causes an invisible, phantom prim called "Speech center" to be rezzed and moved next to the NPC, where it follows the NPC if it is moving. This prim contains the "Speech center" script, which receives instructions from the main script as to which NPC to target and the UUID of the sound to play. Communication is entirely by osMessageObject() in both directions.
The sound parameter may be the name of a sound file in the same prim as the main script, or may be an asset UUID.
Errors
Any syntax errors in the notecard are reported to the owner in chat, and the notecard is ignored.
Miscellaneous points
Standing up
There are long-standing issues in OpenSim with avatar behaviour after standing from a seated position. In particular, this can cause a subsequent osNpcMoveToTarget() command to only execute partially, leaving the NPC standing a long distance short of the target.
To circumvent this, the script issues the command repeatedly, once every 0.5s timer event.
Inaccuracies in NPC movement
Unfortunately, the OSSL command osNpcMoveToTarget() does not position the NPC avatar very accurately, meaning that NPCs could originally be up to 2m away from their assigned positions after a movement command like Walk.
However, the repeated osNpcMoveToTarget() calls (see "Standing up" above) have the effect that the NPC will at some point (perhaps after an incorrect "arrival") arrive close enough to the target for the script to recognise it as arrival. Due to this technique, the detection radius could be reduced from 2m to 1m, making NPC movement effectively much more accurate than it really is.
Compilation/interpretation
The NPC Behaviour script reads all the notecards first, selecting those with the appropriate header as NPC behaviour cards, and reads each one, converting the instructions into an internal format in memory, which is then executed. Doing this rather than interpreting the code directly has several advantages: for example, the syntax of the internal code format can be optimised for quick and cheap interpretation, that the one-to-one relationship of notecard instructions to executed instructions is removed, and that the process of parsing (and syntax error detection/reporting) is separated from the process of execution, making the code cleaner.