Imperfect Tutorial on NPC Navgoaling

by lassev
Version 4.9.2007



Introduction

The aggravating art of telling NPCs what to do in game is something that has reputedly driven lesser men to insanity or untimely deaths. Or both. However, this doesn't necessarily need to be the case. Through careful manipulation of the temporal matrix and the diverse layers of human consciousness it is perfectly possible to reach a level of understanding needed to achieve the highest of all mortal goals: To successfully instruct the stormtrooper to walk to the other side of the room. This is essentially what this imperfect tutorial is all about. You'll be the judge of whether it succeeds or not.

Compatibility note: The author of this tutorial is a dedicated SP mapper. However, everything in this tutorial has been tested in both SP and MP, and where there are differences to be found, they have been mostly noted in the text.

Technical note: This tutorial assumes the reader to have basic mapping and scripting skills, and have BehavEd successfully configured. If you have never scripted, you'll need to get BehavEd running fully before trying to proceed with these instructions. This tutorial won't explain how to configure it.

Contents:
1. 1st Battle -- The very basic navgoaling scheme.
2. 2nd Battle -- Navgoals and waypoints.
3. 2nd Battle Exception -- The way of the waypoints and doors in SP and MP.
4. 3rd Battle -- Simplifications by universal scripts and parms.
5. 4th Battle -- Extra material.

1st Battle: Basic Principles

Foreword

NPC navgoaling, or controlling the NPC movement via scripting and navgoals, is a basic technique expanding the rather nonexistent AI found inside the JA engine (if you look hard enough the AI's right there, in theory). In short it's just telling, via a script, to proceed to the next navgoal. Waypoint_navgoals are entities placed in Radiant in the desired places in the map. A technical definition of immense importance here is to separate waypoints and waypoint_navgoals from each other. Waypoints are entities placed in the map for the engine to use them automatically, whereas navgoals are entities used solely by scripting. However, the game engine can use a pathway of waypoints to guide the NPC to a navgoal not immediately visible, like in a neighbouring room. Moreover, waypoints can be used to create a network the NPCs can follow in a random manner under a special behavior_state.

During this 1st Chapter of the tutorial, a very simple case of NPC navgoaling will be presented: How to make a couple of stormtroopers walk back and forth in front of a door. As if guarding it. Moreover, when these hapless fellows spot an enemy, they will stop their mindless patrolling and start shooting.

A Map of Great Simplicity

Let's start the tutorial by creating a very simple room, like the one shown in the shot below:


Fig 1. The room layout.

The room consist of the info_playerstart (on the left), two stormtroopers (red squares on the right) and four waypoint_navgoals (green). The STs will spawn where they stand, gather their instructions from the spawnscripts and proceed to walk to the navgoal on the other side of the room. There they will turn and walk back. And turn and walk again, and again, endlessly. In any case, enter keys and values for the entities as shown in the Fig 2 below.


Fig 2. The entity properties.

The waypoint_navgoals only need the individual targetnames, the stormtroopers only need the individual spawnscripts. One you have them in place, you should have ended up with something like this:

First Stromtrooper:
classname NPC_Stormtrooper
spawnscript navgoaler/st1_simple

Second Stromtrooper:
classname NPC_Stormtrooper
spawnscript navgoaler/st2_simple

Navgoals:
classname waypoint_navgoal
targetname st1_nav1

classname waypoint_navgoal
targetname st1_nav2

classname waypoint_navgoal
targetname st2_nav2

classname waypoint_navgoal
targetname st2_nav1

Save the map as "navgoaler". Next we will proceed to create the two spawnscripts for the STs as well as the alert script that will make the dudes stop their endless walking back and forth once they spot an enemy (the player, that is). Both tasks are very simple scripting.

Scripts of Great Lucidity

Launch your BehavEd. The two spanwscripts will be written first. The scripts consist of three parts: Setting the STs to walk instead of running, setting the alert script, and then finally the loop that will make them to walk back and forth as long as they are undisturbed. This script could be constructed as well without the first and second parts, but that could result in the STs running instead of walking all the time, and furthermore they would still run back and forth shooting once they notice the enemy, unless wounded, which sometimes makes them stop.


Fig 3. The ST spawnscript.

The set_navgoal commands are inside Tasks. Tasks are a method of grouping and organizing script commands. Furthermore, a Task can be Waited. This means the game will monitor when the Task is finished. So, in this script the other Task, for the ST to turn around and to go back to the starting point, won't be executed before the ST has reached the first navgoal first. This is exceedingly convenient. When writing this script, pay extra attention to the indention and that you don't by accident place the loop inside the second task or anything like that. Following good programming conventions, nothing extra should be inside the loop, so in this case only the two dowaits are located there. DOWAIT is a combination of DO and WAIT. DO("task") executes a task and WAIT("task") waits until the task is finished before letting the script to proceed.

Save this script as "st1_simple" in a subfolder "navgoaler" under your script folder. And compile it. Then adjust it for the other ST by changing the SET_NAVGOALs to st2_ instead of st1_s. Save As as "st2_simple" in the same subfolder. Then start a new script and make it look like Fig 4 below:


Fig 4. The Alert spawnscript.

This one script will work for both of the STs, so no need to make them individual ones. It does nothing but Flush the NPC entities (that is, remove all pending script commands they might be running, in this case the loop), and then sets them to run instead of walk. They will still most likely run to the ends of their paths, but that hardly matters. Save and compile it as "alert" in the same "navgoaler" subfolder under scripts.

Afterword

Compile the map and have a look at it in game (if you run MP, remember to set sv_pure 0). The STs will walk back and forth happily, yet when they spot the player, they will stop their movement shortly and just start shooting like there's no tomorrow.

2nd Battle: Waypoints And Navgoals

Foreword

Like was mentioned in the previous Foreword, waypoint_navgoals and waypoints are two different things. This second battle will demonstrate the practical differences by showing how to make an NPC to walk from one room to another via a winding corridor, relying on the waypoint network. The mapper can't really do more with the waypoints than try to place and connect them in a semi-intelligent manner throughout the map in all the places where NPCs possibly need to travel. Point_combats are other entities that are only used by the engine in an automatic manner. They are closely connected to the waypoints in the sense that the NPCs will use waypoint networks to get to the point_combats. Point_combats themselves are like preferred places for the NPCs to be when they are fighting. If the NPC can't see the player from one combat_point, it'll run to another (if they are present) to get a better aim. All in all, they are essential for any intelligent NPC fighting in JA.

A Map of Twisted Simplicity

Let's build just a bit more complicated map by cloning the first room and connecting them with a corridor, like in Fig 5 below.


Fig 5. Rooms of cloned delight.

As you can see, it's basically the same room as in the first map, just cloned and connected by a corridor. For simplicity's sake no doors are present, only empty doorways. Also, for this version delete the stormtrooper number 2, leaving only st1 behind. Also remove the st2 navgoals. Then move the st1_nav1 to the new room. Then, build the waypoint chain. Place the first waypoint to overlap the navgoal, the second into the corridor so that a line of sight (los) remains between the two. And so forth like in the pic. After that, target the first waypoint to the second, the second to the third, and the third to the fourth. The waypoint network is now finished. The important fact to keep in mind is that los must be present from one waypoint to the next at all times.

There's not actually anything else to be done for this particular experiment. The st will use the script from the first experiment to head to the navgoal in the other room, and then head back. Just like it was doing in front of the door. Now it's only a longer path, following the waypoints. So, compile the map and have a look in game. No extra scripting is necessary.


Fig 6. A screenshot of the second experiment. The ST is walking back from the other room.

Afterword

You can also test out of academic interest what would happen without the waypoints: The ST would only stand there never moving anywhere, because there is no los between its spawning point and the navgoal. A line of sight is necessary for the pathfinding algorithm of JA to work. However, if you force push the ST all the way down the corridor to the other doorway, it will suddenly move to the navgoal, because los was established.

2nd Battle Exception: SP and MP Differences

Technical Information

This chapter deals with a fundamental difference between the SP and MP engines regarding waypoints and doors. In short, the MP engine disregards doors, thus making the pathfinding algorithm behave as if the doors weren't there, whereas the SP engine handles doors as absolute blocks of the line of sight general requirement for waypoint networks (that was mentioned earlier in the tutorial).

Fig 7 below demonstrates the requirement differences in practice when a door is installed in the previous test map. The SP engine won't be able to handle the situation without the additional waypoints on both sides of the door, whereas the MP engine makes no difference of whether those waypoints are there or not (or rather, the MP engine pays no attention to the door).


Fig 7. The door related waypoint requirement differences in SP and MP.

If other types of doors are used, like doors requiring the use button or toggled doors, then fancier solutions must be implemented, but that's not really within the realms of this tutorial and will be left for the imagination of the individual mappers.

3rd Battle: Universal Scripts

Foreword

Universal scripts are scripts that can be called by many entities to execute commands still relevant for the individual calling entity. Thus in practice it allows to reduce the total number of scripts. Of course it's not all away from the workload, because often some of it is just shifted to Radiant entity properties or variables, not to mention the universal scripts are a bit more complicated than the purely entity specific scripts. However, once they are established, they will make things easier. This chapter will present the most typical kind of a universal script used for controlling NPC navgoaling by fetching the navgoal names from the entity params. This way the NPC movement can be totally plotted in Radiant without having to edit the script at all for every NPC.

The Fig 8 below shows the test map for this configuration. There are four stormtroopers in total, with three original routes. So, the two STs in the corridor share the same navgoals. They all will use the same "st_uni" script for their movements. Their navgoals are defined by Parm1 and Parm2 attributes in their Radiant entity properties. In the picture are marked the targetnames for the various navgoals and the parm values of the STs. In addition to this, the same spawnscript must be entered for all the NPCs.


Fig 8. The basic plan of the universal script based patrolling of various NPCs.

Note, however, that it may be necessary to add waypoints into the corridor for this example to work in SP, depending on the length of the corridor. See Fig 9 for an example. In MP this is generally not necessary due to seemingly lower thresholds.


Fig 9. In SP it might be needed to have waypoints in a long corridor.

So, the entities needed for this test map are:

First Stromtrooper (lower room):
classname NPC_Stormtrooper
spawnscript navgoaler/st_uni
Parm1 nav1a
Parm2 nav1b

Second Stromtrooper (upper room):
classname NPC_Stormtrooper
spawnscript navgoaler/st_uni
Parm1 nav2a
Parm2 nav2b

Third Stromtrooper (corridor upper):
classname NPC_Stormtrooper
spawnscript navgoaler/st_uni
Parm1 nav3b
Parm2 nav3a

Fourth Stromtrooper (corridor lower):
classname NPC_Stormtrooper
spawnscript navgoaler/st_uni
Parm1 nav3a
Parm2 nav3b

Navgoals:
Lower Room:
Upper navgoal: targetname nav1a
Lower navgoal: targetname nav1b

Upper Room:
Upper navgoal: targetname nav2a
Lower navgoal: targetname nav2b

Corridor:
Upper navgoal: targetname nav3a
Lower navgoal: targetname nav3b

The universal script for this example is not much more complicated than those of the first examples. The whole script is in Fig 10, with some explanations below. It's advisable to just open the old st1_simple script, edit it and Save As it with a new name.


Fig 10. The complete universal script for Parm based navgoaling.

The whole difference between this script and the previous NPC specific scripts lies in the set_navgoal commands. In the universal script the commands fetch STRING type variable values from the entity Param keys. In practice it's no different than typing the navgoal targetname straight into the commands, except that this same script can be used with any NPC having valid Params stored in Radiant. Fig 11 below shows how to change the set_navgoal command to this form.


Fig 11. In the event editor first press Helper, then Get.

Once you have the script finished, save it as "st_uni" in the same subdirectory as the ones before, compile the map and you are ready to go.

Afterword

There can be more than two Parms as well saved in the entity properties, and nothing prevents from building more elaborate patrol routes for NPCs. Waypoints will be necessary in both SP and MP, like the second test map showed, if fancier routes are built. However, if the NPC is able to establish a los with the next navgoal, it will not follow a waypoint pathway even if one existed. So, an NPC will rather choose the direct path even if it means falling into a chasm than follow waypoints circumventing the chasm.

4th Battle: Extra Material

Foreword

As an extra material this last chapter will have a brief glance at the possibilities of the waypoints as automatic entities. Navgoals are of no use without scripting, but as has been previously stated, waypoints are autonomous and there's no direct control over how they will be used by the engine. The closest thing to using them purposefully is by telling an NPC to use them, though in a rather random manner. But if it's not the purpose of the level maker to specifically march a detachment of troops to harass the player(s) or patrol a strict route, then a random manner could suffice.

Aside of waypoints, this test map will also have point_combats, which are designated places for shooters NPCs to occupy while they are engaging the enemy. They are linked to the waypoint network not physically but in a manner similar to navgoals: The NPCs can use the waypoint network to find their way from one point_combat to the next. However, waypoints are not targeted at point_combats. Waypoints are never targeted at anything else than other waypoints nor do any other entities target waypoints. To read more about various pathfinding entities, check out Ford "Raven" Dye's tutorial on the subject.

Map of Much Wandering

Fig 12 below will present the simple test map for this chapter.


Fig 12. The layout of the waypoint wander test map. The brown arrow is a "target2" arrow not drawn by Radiant.


Fig 13. A radiant 3D shot of the map. The purple entities are point_combats.

A good thing to remember when laying out waypoints is that there should be no obstacles between consequtive ones, and no waypoints should share targetnames. However, multiple targets can be designated by target, target2, target3, and target4 keys. Although GtkRadiant might not necessarily recognize and draw arrows for targeting that goes above the normal target. In the test map of this chapter the brown arrow (in the 2D shot) shows a target2 targeting.

The spawnscript to make the two stormtroopers wander around aimlessly is very simple. The other script needed is an alert script again, but it's also going to be a bit different, so make a new one with a new name, alert2.


Fig 14. St_wander spawnscript for aimless wandering along the waypoint network.


Fig 15. Alert2 script which defaults the bahaviorstate from bs_wander.

To make an NPC wander aimlessly following the waypoint network, it's simply enough to change the behavior_state (BS) to bs_wander, as shown in Fig 14. This causes the NPC to wander here and there. To remove this behavior, the BS can be changed back to bs_default, which happens in the alert2 script, shown in Fig 15. The set_behavior_state command is a special table command found among the multitude of set_ commands.


Fig 16. Stormtroopers patrolling the room.




Conclusion

This concludes the tutorial. The basics of navgoaling were incompletely explained, like the tutorial name promises. With some trial and error great deeds can be accomplished once a mapper with keen interest forgets everything said in this tutorial and researches the issue by himself in his own august company.