Dynamic Lighting for Scripting

By: Brian Green                Date: October 11, 2003

Purpose:

This document details how to work with dynamic lighting from the script point of view.

Basics

Dynamic lighting information is defined in the message SendLightingInformation() in each class.  This message is called in User::ToCliObject() when requesting the "normal" view.  Lighting information works a lot like overlays, in that a 0 is sent if there is no dynamic lighting information, but a non-zero first value indicates that we have other information for the client's use.

Dyanmic lighting consists of 3 parts.  First is the flags for the light, indicating any special conditions or effects for the light.  Next is the intensity, or how bright/large the light is.  Finally, we have the color of the light which is sent in RGB form.  This is all the client needs to render the light.

Details

Data sizes

The three piecess of data sent have specific sizes
Data
Size
Notes
Flags
2 bytes (16 bits)
Flags defined in blakston.khd, detailed below.
Intensity
1 byte (8 bits)
Range from 0-255 in intensity.  Note that only the low-order byte is sent, so a value of 256 will send a value of 0.
Color
2 bytes (16 bits)
Send in RGB format, with each color having 5 bits each (1 bit extra).  Bit format: XRRRRRGGGGGBBBBB, where X represents the "negative" bit.

Lighting flags

The flags defined in blakston.khd are as follows:

LIGHT_FLAG_NONE = 0x0000

This is the default flag for no lighting information.  This should not be used with any other flag.

LIGHT_FLAG_ON   = 0x0001
This is the flag indicating that there is lighting information.  This flag should always be used for dynamic information.

LIGHT_FLAG_DYNAMIC = 0x0002
This flag indicates that the light is "dynamic".  This means the light source could move.  This should be used for monsters, players, or any other object that can move on it's own accord.  Objects that are not flagged as dynamic are cached on the client side for performance.

LIGHT_FLAG_WAVERING = 0x0004
This flag indicates that a light "wavers" like a natural fire source.  Magical light should not have this flag set.

Helper functions

The message GetRGB is defined in the system object.  The prototype looks like this:
GetRGB(iRed = 0, iGreen = 0, iBlue = 0, bPercent = TRUE, bNegative = FALSE)

iRed, iGreen, and iBlue are all values to be converted.  bPercent indicates if the values are percents or raw values.  If bPercent is TRUE, then the values should be from 0-100; if bPercent is FALSE, the values should be from 0-15.  The color values are bound as a sanity check in the message.  Finally, bNegative indicates if this is a "negative" light source (one that takes away color instead of adding to it).

Lighting constants

To aid with lighting, we have defined some lighting constants.  These are stanard RGB values that can be used in other files or in the admin window.

Basic Colors
The basic colors are: red, orange, yellow, green, blue, purple, and white.  Each color comes in three varieties: bright (full saturation), normal (66% saturation), and dark (33% saturation).  The constants for the basic colors are of the format LIGHT_(variety)(color), where bright is "B", dark is "D", and normal color has no letter.

Example: LIGHT_BBLUE is a bright blue color (100% blue saturation).  LIGHT_WHITE is a normal white color (66% saturation).  LIGHT_DRED is a dark red color (33% saturation).

Extra Colors
We define other colors as needed.  Current extra colors, their hex values, and a description are:

Constant
Hex value
Description
LIGHT_LIGHTNING 0x3DFF A bluish white for lightning effects.
LIGHT_BLOOD 0x3C00 A deep (50%) red.
LIGHT_FIRE 0x7F06 A yellow-orange fire color
LIGHT_SPECTRAL 0x0D21 DGREEN with a bit more red.
LIGHT_NEWSGLOBE 0x3DFF Identical to LIGHT_LIGHTNING, but put here in case it needs to be changed later.
LIGHT_FOUNTAIN 0x0C6C A very dim white, with blue tint, primarily for the Tos Fountain.

Example code

This code snippet defines an object with a dynamic flag (object could move around the room), with about 20% intensity of 100% blue color.

   SendLightingInformation()
   {
      AddPacket(2,(LIGHT_FLAG_ON | LIGHT_FLAG_DYNAMIC));
     
% 50 out of 255 intensity of light
      AddPacket(1,50);
     
% Pure blue color
      AddPacket(2,LIGHT_BBLUE);

      return;
   }

This code snippet defines an object with a variable intensity a color that depends on another variable.

   SendLightingInformation()
   {
      AddPacket(2,LIGHT_FLAG_ON);
     
% out of 255 intensity of light
      AddPacket(1,piLightIntensity);
      if bGood
      {
        % A 50% blue color
        AddPacket(2,send(SYS,@GetRGB,#blue=50));
      }
      else
      {
        % A dim white color
        AddPacket(2,LIGHT_DWHITE);
      }

      return;
   }

Future directions

The intention was to use the "negative" color bit for removing color.  So, making a light "negative blue" would remove a certain level of blue from the area.  We could use this to make the Shadowbeasts have a negative white color, making the area around them a darker.

This has not yet been implemented.