AI Scripting Additions

Along with the ability to script the behaviour of entities, other features have been added to the single player game. These include the addition of sound scripts and changes to the structure and behaviour of NPCs. This section will examine these features in more detail.

Sound Scripts

Sound scripts are a way of making the playing of a sound a little more versatile. They allow you to change, externally from the level or program, the sound channel, attenuation and file played for a given sound. Sound scripts should work for any sound whose playing is initiated by the server using a general or global sound event. A sound script is identified in these events by the absense of the .wav extension on the name of the sound file. A sound script also doesn't need the path to the file so instead of providing the event with a file name like sound/crypt/slaughterhouse.wav you could use something like slaughter, where this would be the name of the sound script.

Sound script files are stored in the baseq3/sound/scripts folder and have a .sound extension. You can have multiple script files in the folder and a file named filelist.txt, also in this folder, is used to determine which files should be loaded and processed. The name of each script file you wish to use must be included in this file or they will be ignored. For example, if you want to use the crypt1.sound and escape1.sound script files in your game then filelist.txt must look like :

   crypt1.sound
   escape1.sound

Any other sound script files in the folder will be ignored.

A sound script file can contain multiple sound scripts and each script is defined as follows :

   <script name>
   {
     ... data ...
   }

where <script name> is the sound name we would provide to the sound event. For example, our slaughter sound script would be defined by :

   slaughter
   {
     ... data ...
   }

Inside the curly brackets of the script we place information about the sound we wish to play. This includes the path and name of the sound file, the sound channel to use, the attenuation of the sound and whether we should shake the player's screen while the sound plays. By default the sound channel is set to auto, the attenuation is set to local (sound fades with distance) and no shake occurs.

The sound channel is set by placing one of the following on a line of the script.

  • local
  • announcer
  • body
  • voice
  • weapon
  • item
  • auto

The sound attenuation is changed from local to global (no fading with distance) by including the following on a line of the script.

global

The screen shake is set by placing the following on a line of the script.

shake <scale> <radius> <duration>

where <scale> is the intensity of the shake (usually from 1 to 10), <radius> is the distance from the sound location that the shake effect will be shown and <duration> is the number of milliseconds the shaking will last.

The sound file to play is set by placing the following on a line of the script.

sound <name>

where <name> is the path and name (with extension) of the sound file we wish to play.


Using this information our slaughter sound script can be as simple as :

   slaughter
   {
     sound sound/crypt/slaughterhouse.wav
   }

or as complex as :

   slaughter

   {

     voice

     global

     shake 3 800 1000

     sound sound/crypt/slaughterhouse.wav

   }

NPC Behaviour

NPCs have had their behaviour modified so that, even without any AI scripting, they react to situations in a more intelligent manner. Every NPC can have three behaviour states exclusive of those used to make them walk a predefined path. These states are relaxed, alert and attack. In the relaxed and alert states the NPC is actively scanning the area it can see for an enemy to attack, although in the relaxed state the sight distance is half that of the alert state. Previously, the NPC would attack the first enemy it seen in the entities list, regardless if it was the closest enemy to it or not. This has been altered so the NPC will scan for all enemies in it's area and attack the closest one to it.

An NPC that is in pain will shift it's behaviour state from relaxed to alert, increasing it's sight distance and causing it to move about some while scanning for enemies. It will not automatically attack the inflictor of the pain, as it did before, but will go for the closest enemy it sees.

An NPC that is scanning for, but hasn't found, an enemy will also respond to other events happing in it's area. If a friendly NPC is in it's area and it is attacking an enemy then the NPC will go to that location and investigate. Failing that, if an enemy weapon is fired within it's hearing range it will move towards that location to investigate the sound. Otherwise, if the NPC sees or hears any projectile in it's area it will move towards the origin of the projectile to investigate.

These behaviour changes make the unscripted NPCs more aggressive in seeking out enemies and to act in a more realistic manner. These behaviours can also be modified by AI scripting to customize the NPC's reaction to events.

NPC Structure

In conjunction with the AI scripting and behaviour changes the structure of the NPC's data has also been altered, both in the source code and in the configuration files for the NPC. These changes allow more customization of individual NPCs and provide more power to the scripting system.

1. One of the major changes to the NPC configuration files is the addition of 10 more animations to the animations.txt file. These animations, numbered 15 to 24, are not attached to any particular actions like the first 14 are but are used by the scripting to allow special animations to be played. The new animations are defined exactly like the others, with the start frame, number of frames, looping and fps data being required. These animations do not have to be defined in animations.txt if they are not going to be used, so backward compatibility with older NPC data is maintained.

2. The structure of bg_npclist has also been altered as part of the scripting system. Each NPC definition now contains a group designation and a muzzle offset vector. Each NPC must belong to one of two groups, monsters or neutral. Monsters attack neutrals and the player, while neutrals attack monsters and any other neutrals or the player who happen to attack them first.

Previously, each individual NPC had to be checked in the source code by name to see which group it belonged to. Now an NPC has it's group designation checked to determine if it is a monster or neutral. This makes it much easier to add new types of NPCs as less source code changes are required.

The muzzle offset is used to determine the starting point for launching a projectile during a far attack. This used to be hard coded into the projectile firing routines for each type of NPC allowed to use a far attack. AI scripting allows any NPC to use a far attack so the muzzle offset is now included as part of the NPC's data.

3. An NPC can now use skin files to change the texture used by the models. The name of the skin file can be defined in the entity definition or in the AI script. The actual skin file must reside in the same directory as the NPC model. The definition of a skin file is as follows.

A model is made up of one or more objects, each of which has a unique name. These objects are a portion of the model's mesh that uses a specific shader to texture it. The skin file, which is a text file with the .skin extension, lists each object by name and the shader or texture to use when texturing it. For example, if the model consists of two objects named h_body and h_weapon then the skin file for this model would look like :

h_body,models/npc/ogre/ogrered.tga
h_weapon,models/npc/ogre/weapon.tga

if we wished to use the ogrered texture on the body object and the weapon texture on the weapon object. The use of skin files allows each individual NPC in a level to have a different texture and look, while sharing the same model mesh.

Return to Home Page