header general

Action Script (ACS)

Anatomy of a Cutscene

The screen is dark and all you hear is the crackling static of a radio receiver in its last throes. Slowly the screen brightens in a classic fade-in to reveal a scene of carnage and destruction. Suddenly, a shadow darts across the screen and the camera moves to follow it. Ominous music pipes in, softly at first, but growing to a crescendo as the camera reaches a breach in the wall. A city street stretches out below, buildings along it lying in ruins and utter devastation. The camera slowly drops to street level and pans around. You hear the sound of heavy, belabored breathing, and the camera swings in the direction of the sound. Suddenly a scream rings out, and the camera lens is splattered with drops of crimson as you hear the sound of a body hitting the pavement. The music peaks just in time to show you a vast, indistinct shape shambling away into an adjacent alley. Words and a logo zoom out onto the screen, but you are cringing at the horror of it all, and for a moment you can't make sense of the words. "ATTACK OF THE KILLER FIENDS", they announce. The scene fades to black but the title remains on the screen. You breathe a sigh of relief as you press the 'ESC' button to bring up the menu. All is safe with the world. It's only a game after all.

Anybody who's played a modern computer or console game has seen one - the ubiquitous cutscene. Used for everything, from providing a story's introduction to filling in pieces of the action that cannot be left to the player to control, cutscenes serve a myriad of purposes. As outlined by the fictitious scenario in the paragraph above, it is used as a means to set up the "back story" and to create the appropriate mood. It can be used for mission briefings, where the player can benefit from basic information about the game and its objectives. It can be used to show the player the effect of his/her actions in a distant, remote part of the game. It can be used to advance the plot, provide clues, and promote character development. Finally, it can be used to provide a dramatic conclusion when the player has successfully completed all objectives. Cutscenes are an important tool in a game-developer's kit, and when used skillfully they can create a dynamic environment in the player's sand-box.

There are two key elements in the creation of a cutscene - aesthetics and mechanics. Aesthetics are, largely, subjective and a matter of taste. Therefore, I'll only provide some basic guidelines on what this constitutes. Or, more accurately, I'll provide some guidelines on what I think it constitutes. Mechanics, on the other hand, are more easily established, and I'll provide step-by-step instructions on how to achieve some common cutscene effects.

A. Aesthetics of a Cutscene

The aesthetics aspect of a cutscene revolves around the mood you wish to create, and your desire to hold the player's interest. Here are some pointers, all of which pertain more to cinematography than map-building:

    1. You'll want to make the cut-scene visually appealing, so make sure that the scene is one that is suitably lit. By that I don't necessarily mean "brightly-lit"; lighting should be adequate to illuminate the scene so that the player can obtain whatever visual cues you wish to convey, while creating the proper atmosphere. Use dynamic lighting if your game engine permits (e.g., GZDooM).
    2. Select an area of your game that shows off some interesting architecture or other map feature. While the "action" may be occurring in the foreground, the player's eyes are likely to wander, and there's plenty to gain by showing off maximum eye-candy, especially during an introductory cutscene.
    3. You'll want the cut-scene to be dynamic, so make full use of moving cameras (traveling along all three axes as appropriate) and switching cameras. [More on moving cameras in the section on Mechanics.]
    4. Use close-ups of characters or objects, zooming in or out as appropriate.
    5. Use character or object motion as appropriate, allowing your camera to pan with the motion. GZDooM allows "moving" models, and both GZDooM and ZDooM allow characters (also known as "actors") to walk along a specified path, and pause at specified points; you can even create fight sequences by scripting battles between actors. These all serve to create a visually-arresting scene that is more likely to hold the player's attention.
    6. Use fade-in and fade-out to transition from one camera to the next, as appropriate.
    7. Avoid keeping the camera fixed at one spot for more than a few seconds. My rule of thumb for real-life videography is to record no single shot for more than 10 seconds - I can easily use a video editing program to stitch together various scenes for a longer sequence if necessary, and shorter "shots" tend to be more exciting.
    8. Use sound effects and music to enhance the atmosphere.

B. Mechanics of a Cutscene

There are seven common tools you can use in a cutscene, and each of these is already built into ZDooM. As such, you won't need to insert your own resources into your game if you so choose. These tools are:

The first three items all pertain to "cinematography" - types of cameras, switching cameras, and causing cameras to "travel". The fourth item is required if you want actor movement where the actor needs to be animated. The fifth allows you to move an actor (such as an enemy or model) along a path. [Enemies become dormant when propelled by an Actor Mover.] The sixth is useful for mission briefings and other instances when messages need to be conveyed to the player. Action Code Script, or ACS, is the language that ZDooM (and each of its derivatives) uses to create various effects. Please read the articles to which those items have been linked, and become familiar with them.

There are four steps to developing your cutscene [which I have cheesily named the "4P Method"]: Planning, Placement, Programming, Playing. Let me first outline what these steps are and their importance in creating the right effect. After that I'll illustrate with some examples.

    1. Planning:The more complex you want your cutscene to be, the more important it is to plan the sequence of events you'll be recording. Even simple cutscenes require basic decisions. Where should the camera face? Should the camera be stationary or moving? Will it be necessary or desirable to use more than one camera? At what height should the camera be placed for optimal viewing of the scene? Will the actors be stationary of moving? What sound effects should you use? When should message text be displayed, and for low long should it be displayed? The answers to these questions will depend on what the purpose of the cutscene is, and how dynamic you want it to be. Mission briefings will typically involve keeping one or more cameras on a single actor, and will involve fewer "maneuvers". A battle scene will be considerably more complex, involving several actors that will need to perform specific actions. An introductory camera "fly-by" could be equally involved, with a lot of "background action". Therefore, it will probably benefit you to plan each "shot".

    2. Placement: Once you've planned out your scene you'll need to begin putting your "pieces on the board". The four main types of pieces are actors, cameras, interpolation points, and patrol points. Use your plan to place your various pieces into the appropriate positions. Keep in mind that you have three dimensions to work with, so make sure you take advantage of height variations, especially for your cameras. For example, during a mission briefing you can start your camera near the ceiling as it faces the principal actor. As the briefing begins the camera could slide down to a few feet above the ground before moving forward to zoom in on the actor. If there are actors that need to be moving (e.g., an enemy or a model) you'll need to position your Patrol Points and Actor Movers.

    3. Programming (scripting & specials): If your "pieces" are the automobile, your scripting is the driver of the automobile. It tells the pieces when to start, when and where to move, when to turn, and when to stop. The specific lines of code you use will depend on the nature of the cutscene. In most instances you'll need to "freeze" the player so that s/he is unable to move independently and interfere with the action. Accordingly, you'll need the SetPlayerProperty function. You can "unfreeze" the player later, as appropriate. But until then you will need to begin the process of letting the dominoes fall. The first step in that process is "changing" your camera and activating it using the Thing Activate function. [Optionally, you can fade into the scene using the FadeTo function before you activate the camera.] Finally, you fade back into the scene.

    So far, all you've done is changed the scene to a remote camera and activated it. Now you need to trigger the events of your cutscene. If you've set up your first camera to be a moving camera, you'll have also set up your sequence of interpolation points. This, then, becomes a "fire-and-forget" device that proceeds automatically, and does not require further manipulation. Keep in mind that setting up your interpolation points is not a trivial task; distance between points, height of points, angle the point faces, and speed between points [travel time] will all determine how smooth and dynamic your camera movement will be. If you're doing a mission briefing you'll begin displaying the heads up display (HUD) text or begin a sound recording, or both. [You can use ThingSound to start the audio portion of the briefing.] If all you're doing is a "static" mission briefing, where the briefer is stationary, beyond this point you'll simply need to change cameras as appropriate, fade out when the briefing is complete, change cameras back to the player, and unfreeze her/him.

    If you are doing a more complex cutscene, such as a battle scene or a fly-by, you'll need to activate your actors in addition to your cameras. Much of the actor behavior will already have been determined in the Planning, and Placement stages of setting up your scene. To move and animate actors, you'll need to use patrol points to designate the path your actors will take. This method is ideal for enemies, non-combatant actors (e.g., scientists), and other things that have animated frames and behavior. If you just want to move an actor without animating it (e.g., a model of a tram that runs on an electrified rails and without wheels) use an actor mover. You can use this method for any type of actor, but if it's not a model the actor will be moved without any of the inherent animation that is part of its normal behavior; use the patrol point method if you need the sprite animations. If it's a model, the actor mover will move it along the path and all the associated animations will work. For example, if your actor is a model of a helicopter, and the model definition includes turning rotor blades, the helicopter will appear to move forward (or backward/upward/downward as you define) while its blades rotate. Finally, if you want events to happen after the cutscene begins, you can script them using ACS. If you want these events to be triggered when the camera reaches a specific point, use Interpolation Specials. For example, you may want music to begin when the camera has reached a specific point. Set up an interpolation special at that point, then use it to trigger a script that starts the music.

    4. Playing (testing): Once you've implemented the first three of the 4P steps, you'll need to test your work. In reality, however, you'll probably test the various pieces of your cutscene more-or-less continuously during the development phase. The key things you'll want to make sure of are the following:

    1. Cameras are activated at the right moment.
    2. Cameras are facing the correct direction.
    3. Moving cameras are traveling along the proper path.
    4. If both audio and HUD text are used for mission briefings, the two are properly synchronized.
    5. Actors begin moving when they are supposed to, and not before or after.
    6. Actors properly follow their paths or the actor movers.
    7. Other effects (e.g., sounds, music, lighting) are appropriately activated.

C. Making a Cutscene Optional

Whenever possible, especially whenever the viewing of the the cut-scene is not necessary for the player's advancement within the game, provide the player a means to skip the cut-scene. Watching a cut-scene may be enjoyable the first time, but if a player goes back and plays the map again s/he may not be interested in sitting through it again. There are several ways by which you can allow a player to skip a cutscene. [However, keep in mind that some cutscenes may be required in order to move the action or story along, and it may not be desirable (or even possible) to make these portions skippable.] The method you use to allow players to skip cutscenes will, to some extent, depend on the type of cutscene:

    1. Introductions: You've seen the clever cinematics at the beginning of games where the camera swoops down from the sky and circles around a gothic-looking castle, skimming the surface of a moat under a curved bridge, before soaring heavenward again as the music thunders to its conclusion. This type of scene is an effective way to advertise your game, essentially by showing cool stuff right off the bat. In (G)ZDooM you can achieve this effect by creating a TITLEMAP. A TITLEMAP has the advantage of being skippable at any point - the MENU is pulled up as soon as the player presses any key - but also allows the cutscene to be as long or as short as the game author wishes it to be.

    2. Mission Briefings: Mission briefings pose a problem of being (generally) required the first time a game is played, but not necessary after that. One way to give the player the option of accepting the briefing or skipping it, is to create two "paths" before that point. The first path will go to the briefing, while the second path will by-pass it. If the briefing is at the beginning of the game, you can simply present the player with two switches - one for the briefing, one to skip it. If you wanted to make the choice more "realistic", you could have a corridor at the game start that leads to the briefing room (and a sign that says "Briefing Room" could be posted outside). The corridor could branch off at the door, continuing to the rest of the game, thereby not requiring the player to enter the briefing room.

    Alternatively, if you wanted the mission briefing to begin automatically, you can silently teleport the player to a remote 64x64 sector after the camera has been activated. The wall that the player faces has an ACS trigger that, when "used", ends the briefing, teleports the player back to her/his original location, and changes the camera back to the players point of view (POV). In this way, the player can exit the briefing at will. [This same effect can be achieved by having the ACS trigger at the player's original location, but the risk is that the player may not activate the trigger during the briefing, but may inadvertently do so afterwards, resulting in unintended consequences. It is possible to nullify the trigger using ACS, and if you are comfortable enough with the use of variables, this method will work just as well for you.]

    3. Other Cutscenes: The same method that works for skipping mission briefings after they have started will also work for other types of cutscenes. Simply provide the player with an ACS trigger that will terminate the cutscene and return the player to the game. (G)ZDooM allows even a totally frozen player to "use" switches, etc.

D. An Example of a Mission Briefing

Mission briefings are generally the simplest types of cutscenes to develop. Let's look at the key blocks of code in an example. [Incidentally, this example is from Paranoid, a Half-Life mod for GZDooM.] The first picture below is the scene where the mission briefing occurs. You see the model of the briefer, the desk and other office accoutrements, and the two cameras. The second picture is from the map editor, and it shows the layout of the scene; the notes indicate what each thing is.

cutscene1 cutscene2

Now let's look at the scripting that went into creating the mission briefing:

// Script 11: Mission Briefing & begin game

script 11 (void)

    SetPlayerProperty(1, 1, PROP_TOTALLYFROZEN);
    FadeTo (0, 0, 0, 1.0, 3.0);
    ChangeCamera (255, 0, 0);
    fadeto (0, 0, 0, 0.0, 3.0);
    [Remainder of script, see below]

This triggers the following sequence: the player freezes, the screen fades to black in 3 seconds, the players point of view changes from the normal in-game mode to the particular camera for the cutscene (tag ID = 255), the camera is activated, and the scene being captured by the camera fades into view in 3 seconds.

Meanwhile, camera with thing identification (TID) of 255 has been set up as a moving camera at zheight = 152, is bilinear (camera will adjust its angle to match those of the points it passes), and will move to interpolation point with TID = 254. Interpolation point (IP) with TID = 254 has the same x, y, and z coordinates as the camera, is pointing to IP with TID = 253, and has a travel time of 64 tics to that IP, which is at zheight = 128 and slightly forward of the camera start point. This means that, upon being activated, the camera will slowly float down towards the floor before moving forward to the next IP.

    [Continued from script, see above]
    ambientsound ("radiostatic", 127);
    ThingSound (19, "BRIEF01", 127);

    SetHUDSize (640, 480, 1);
    SetFont ("confont");
    HUDMessage (s:"Dr. Bellmer, this mission briefing will serve to instruct you\non your primary and secondary objectives.";
    HUDMSG_TYPEON | HUDMSG_LOG, 2, CR_GOLD, 30.1, 200.1, 0.5, 0.07, 1.0);
    [Remainder of script, see below]

This section begins with a sound being triggered, signalling that the briefing is about to begin. This is a useful device that adds a touch of realism, but is entirely optional. Following that, the audio portion of the briefing starts. You'll need to include a sound file in your game and set up the sound definitions, but that's the subject of a different discussion. In this example, the mission briefing also includes a HUDMessage that simply transcribes the audio portion. You can choose to use only the audio, or only the HUDMessage, or both.

Meanwhile, the camera has moved to its "destination" IP. In this example, the IP is positioned at an actual camera model that the player can see as the POV approaches it. Again, this is simply a device to provide some realism, and is not required.

    [Continued from script (some lines omitted), see above]
    ChangeCamera (249, 0, 0);
    ThingSound (19, "BRIEF02", 127);
    HUDMessage (s:"Your primary objective is to damage their information systems so that data\nrecovery is difficult and time-consuming.";
    HUDMSG_TYPEON | HUDMSG_LOG, 2, CR_GOLD, 30.1, 200.1, 0.8, 0.08, 1.0);
    [Remainder of script, see below]

After the briefing has gone on for a little while, you should consider changing cameras to lend a touch of dynamism to the proceedings. In this example, the camera changes to a fixed cameraoff to the side, and which is pointing at the briefer. The second audio section of the briefing then begins, and the transcribed test is displayed. The reason to split the audio file into two or more files is that it allows better control of the synchronization of audio, HUDMessages, and camera movement.

    [Continued from script (some lines omitted), see above]
    ChangeCamera (255, 0, 0);
    ThingSound (19, "BRIEF04", 127);
    HUDMessage (s:"Periodically, during your mission, you will receive transmissions from me.";
    HUDMSG_TYPEON | HUDMSG_LOG, 2, CR_GOLD, 30.1, 200.1, 0.4, 0.05, 1.0);
    [Some lines omitted]
    ambientsound ("radiostatic", 127);
    fadeto (0, 0, 0, 1.0, 3.0);
    ChangeCamera (0, 0, 0);
    SetPlayerProperty (1, 0, PROP_TOTALLYFROZEN);
    fadeto (0, 0, 0, 0.0, 3.0);

As before, after some more of the briefing, you should change the camera again. In this instance, the camera has been changed back to the original moving camera while the last audio and HUDMessage portion of the briefing is delivered. Finally, the radiostatic sound is played to signify the end of the briefing, and the scene fades to black. The camera is changed back to the player's POV, the player is unfrozen, and the scene fades back in.

Admittedly, this is a rather involved mission briefing, and you can achieve the same result without the manipulations described here. However, this example illustrates the richness and diversity of effects that you can employ to create an attractive cutscene. The principles used in this example are virtually the same as those for other, more complex cutscenes. Even though you may use more actors, have more frequent camera changes, or implement more sound & light effects, the toolbox defined in the discussion above will allow you to execute a slick and professional-looking cutscene.

Using LoadACS

Loading ACS for all maps, rather than loading it in each map itself, is often referred to as global ACS. It's one of the trickier things for new modders to get a hold of, and since Realm667 only uses this form of ACS in submissions, I figured it would be best to post a tutorial to show how to do this.

Firstly, the related wiki articles and a helpful link:

To start, we write a script. We'll keep this simple. This is a LoadACS tutorial, not an ACS tutorial, so if you don't understand how to work ACS to begin with, start here: http://zdoom.org/wiki/A_quick_beginner's_guide_to_ACS and work your way up.

#Library SOMEACS //The library name. This should be limited to eight characters
#Include "zcommon.acs" //ACS needs this, generally

Script 600 ENTER //Use a number you're reasonable sure won't be used in a map
    Print(s:"Hello World!");

Generally, you would want to write this in a map editor like Doom Builder, in a quick test map, to weed out any scripting errors before you try to compile it for real.

Next, after you have the script written into a normal .txt (We'll say SOMEACS.txt), drag and drop it into ACC.exe, which can usually be found in your Doom Builder directory. If it compiled successfully (and this is why you try it in Doom Builder first, so you can see the errors), then you should have SOMEACS.o. Import this file into your wad between A_START and A_END markers, or into a pk3 in the ACS folder. Next, create a lump called LOADACS, and add the filename (minus the file extension), such as "SOMEACS" on its own line. If you wanted multiple entries, they each have to go in their own lines, such as:


It should be that simple. That script should print "Hello World!" on map start, even on stock Doom 2 maps. There are some things to note, however.

  • The library name has to be eight characters or less, and each library name must be unique.
  • Keep the filename for the ACS and the library name the same. Certain things take filename and certain things like the library name. If both names are the same, there's no problem.
  • This only works if the script number isn't already taken. If LoadACS loads a script 100, and the map already has a script 100, it usually uses the map's script, but you shouldn't rely on that.
  • "Open-source" ACS is a copy of the ACS scripts that are uncompiled. Even if you think you're done with these scripts, it's helpful to keep around in case you need to edit it later on, or if someone else wants to see how you did things, and it's always helpful to keep in the wad itself.
  • If a mod is very ACS-heavy, it's a good idea to keep scripts relatively compartmentalized into different entries in LoadACS. One file for monsters and one file for weapons, for example, can help keep things easy if you want to make a change to one without having to recompile the whole thing.
  • If a file called acs.err is created by ACC.exe instead of what you were expecting, there was an error in compiling, and acs.err should help with finding what it is. It opens like a standard .txt. However, it's a lot faster to write and test in Doom Builder, where you would get an error immediately, and compiles with a single button, before you finally compile it with ACC.exe.
We use cookies

We use cookies on our website. Some of them are essential for the operation of the site, while others help us to improve this site and the user experience (tracking cookies). You can decide for yourself whether you want to allow cookies or not. Please note that if you reject them, you may not be able to use all the functionalities of the site.