Scripted Phased Lighting
By Richard Clark

Figure 1: Scripted Lighting

ZDoom's lighting is the best of any port and the phased, or moving lights, is a feature that really adds atmosphere to any map. However, it isn't very customizable. This tutorial shows how to script a lighting effect similar to phased lighting and offers complete control over the lights. The sample wad sectlite.zip has the room pictured in Figure 1.

Figure 2: Map Layout

Figure 2 shows the map layout. The sectors are tagged 1 to 17, in sequential order. Using tags in sequential order makes the scripting much easier.

There are two switches in the room. One switch makes the light go in one direction, the other switch makes the light go in the other direction. You could also do the same with a single switch and a flag in the script to keep track of which state the switch was in at any point in time.

    #include "zcommon.acs"

    #define faderate 24
    #define lowlight 120
    #define highlight 200
    #define lastsector 17
    #define firstsector 1
    #define lightdelay 5

    //The current script running.
    int ldir;

    script 1 (int dir)
    {
    	int i;

    	//Kill the running script.
    	if (ldir > 0) ACS_Terminate (ldir, 0);

    	//Clear all the lights.
    	for (i=firstsector; i<lastsector; i++)
    		Light_ChangeToValue (i, lowlight);

    	if (dir == 0)
    		ACS_Execute (2, 0, 0, 0, 0);
    	else
    		ACS_Execute (3, 0, 0, 0, 0);
    }

    script 2 (void)
    {
    	int i;

    	ldir = 2;

    	//Set the beginning sector tag.
    	if (i==0) i = firstsector;

    	//Dim the current sector.
    	Light_Fade (i, lowlight, faderate);

    	//Get the next sector tag.
    	i++;

    	//Wrap around to beginning sector.
    	if (i>lastsector) i = firstsector;

    	//Set the next sector to bright.
    	Light_ChangeToValue (i, highlight);

    	Delay (lightdelay);
    	Restart;
    }

    script 3 (void)
    {

    	int i;

    	ldir = 3;

    	//Set the beginning sector tag.
    	if (i==0) i = lastsector;

    	//Dim the current sector.
    	Light_Fade (i, lowlight, faderate);

    	//Get the next sector tag.
    	i--;

    	//Wrap around to ending sector.
    	if (i<firstsector) i = lastsector;

    	//Set the next sector to bright.
    	Light_ChangeToValue (i, highlight);

    	Delay (lightdelay);
    	Restart;
    }

Figure 3: Script

Notice the use of defines in the top of the script. Defines can really simplify your scripting and also make the script much more readable. If you need to change a value in your script, it is much easier to just change the value of the define, rather than searching through the whole script for the different values. It is also fairly clear from reading the script and looking at the human-readable defines what the script is doing.

The two light specials being used are specials that have been used in other scripts, so should be familiar.

Script 1 is activated by one of the switches. The parameter value, dir indicates which direction the lights go. The first thing script 1 does is reset all the lights to the current default value (120). It then terminates any running script by using the value stored in ldir. It then executes either script 2 or 3 depending on which direction has been passed in dir.

Script 2 and 3 do exactly the same thing, except in opposite directions. The script simply runs through the sectors, making the current tagged sector (i) fade slowly to the default light value, and then makes the next sector (i--, or i++) the max light value. This gives the effect of a trail of light running through the sectors. Both script 2 and 3 continuously run when they are activated, until terminated by script 1.

Now, why two scripts? So that one script could be terminated and one could be started. I could not terminate and start a script in a single call, although that may be possible using a technique that I don't know. This approach worked quite well, however.

The scripted phased lighting here doesn't look exactly like the built-in phased lighting (although that is possible with a more elaborate script), but it does offer complete control and in my opinion at least. looks good enough to be included in any ZDoom level.

Sources

ZDoom reference by Randy Heit.

Back