Most of the problems a beginner has when thinking of creating a good fight scene rely on his conviction that the AI is good enough by itself. I saw a lot of people simply put some soldiers here and there and start their mod, which fails badly in offering a good fighting experience.
So, how are we going to handle this?
First of all, we must understand that the Half Life 2 AI cant see anything by itself. Soldiers and monsters dont have any data about the environment around them, so we need to provide them those data.
The only thing they're good at when compiling a map without providing them data is chasing the player wherever he is regardless of the consequences.
To help them out, there are some special entities, such as:
and so on. Those entities can be found in Hammer and have their unique propieties. I'm not going to explain what each of them does, but I'll do suggest some of them and their use.
PART 1 - Navigation
The first thing a monster needs is knowing what is going on around them. Barrels, crates, walls, everything. With those information, he will follow a path "thinking" where he's going.
For this, we will use info_nodes. An info_node is a special entity used for local navigation that tells the NPCs where they can go.
So, assuming that you have something simple, like this:
You'll start placing info_nodes around to help soldiers and monsters find their way through the level. Another common error I saw often was this:
Now, you may think "Wooah, now they are super smart and can go everywhere!" wrong. Placing a lot of info_nodes around the area with no logic will make your soldiers even more stupid than before!
To check this in game, simply compile your map. Then enter into the console (if you dont know how to do it, create a desktop shortcut to your game and type -toconsole at the end of the "path" field) and use the command: ai_show_connect.
With this command, you can see directly into the game how things are going.
See the green lines? Those areas the NPC can travel to with no problems. The red lines indicates that the area is unreachable and something bad has occurred. Examine the image and you'll find out that:
1 - the green lines are placed in total disorder
2 - some of the info_nodes lead to dead areas because of bad placement
This means that the NPC will follow a strange route, and where he wont find nodes any more, he'll just try to reach the player. So, you have to think before placing info_nodes. Use them carefully, only place them in groups where a NPC must do a choice between two or more paths, and make sure they're always connected to each other.
An example of good node placement on a corner. Notice that, info_nodes can be also info_node_climb and info_node_air. There's no difference between these classes, except that the first is for climbing NPCs and the second is for flying NPCs. Just place the air nodes above the ground where you want your NPC to fly to, with the same method as the ground nodes.
PART II - HINTS
Hints are the essentials of the NPC AI. They provide extra data on the environment and can help them perform a lot of tasks.
Examine the Hint node.
As you can see, Hints work a little differently from info_nodes. There are two types of hints:
- info_node_hint (and info_node_air_hint - which is the same thing)
The info_hint entity only provides information on what's going on around the NPC, and wont serve as node for local navigation. An inf_node_hint instead will do both: will provide useful informations, and serve as a node for the NPC to walk to.
Is up to you to set the first or the second, I generally prefer to have info_node_hints only for basic actions such as cover and entrance\exit pinch.
The Hint propieties are:
Hint Activity - an activity associated with this hint
Target node - this hint can be linked to another node
Maximum and Minimum state - the NPC wont use this hint if he's not in the specified state
Hint - what information this hint will provide to the NPC
There are a variety of actions the NPC can perform with this entity, but the most common are crouch cover medium \ low, entrance \ exit pinch, and enemy disadvantage point.
Remember that certain hints wont work if the player can see the enemy and \ or is behind the NPC.
As for normal nodes, place hint nodes carefully: its no use having a "enemy disadvantage point" in the middle of an open area with no cover: the enemy will try to kill the player directly, becoming cannon fodder for his shotgun. Always try to flank the player or push him into a corner.
Another interesting and very useful aspect of hint nodes is that you can give them a name and divide them in groups, then assign a certain group to your desired NPCs. Even if this wont affect local navigation, they will try to follow the specified route you gave them via hints, so you can create realistic tactics that will make the goal more interesting to reach.
PART III - Brushwork!
Even with those informations and hints, NPCs still needs something that can help them out.
For example, a good map should always have NPC CLIPs around. The npc clip is not an entity, is just a texture with some special proprieties that will block the NPC anywhere you want. Select the npc clip texture, and make a block covered with that. In game this texture will be invisible, and the player wont be affected by it. Try to build boxes and shapes with this texture to prevent NPCs to fall \ get stuck in a corner \ try to reach the player from an unreachable position. With this and the data from nodes and hints, your soldiers and monsters will be real war machines. But there's still a problem to be solved: physics! Yes, physics are the real threat to NPCs, because:
1 - NPCs wont bump into physics even if they're small and easily pushable, instead, they'll avoid them like normal geometry
2 - info_nodes and hint nodes wont be blocked by physics objects, so the NPCs wont know how to reach a certain place if there's a physic object in the middle of the path
To avoid this (very annoying indeed) problem, you must use another entity: logic_navigation.
The logic_navigation entity will tell a desired NPC to push certain physics objects instead of avoiding them. Unfortunately, it appears that you cant use classnames to use this entity, so you'll be forced to do this trick only with certain NPCs with the same name. Physics objects affected by this entity have the same problem, so you'll want to build your levels around this issue when thinking of fighting soldiers.
PART IV - Code
The most important aspect of AI is, of course, the code.
Now I'm going to be a little more specific, just to give you a general idea.
NOTE: I assume you know the basics of C++
Go into your mod foldier\ src \ game \ server \ hl2 \ npc_combine.cpp (if you have Orange Box) and take a look at this line, under the Spawn function:
This defines what the NPC can do. He can turn his head, move on the ground, and jump.
// Innate range attack for grenade CapabilitiesAdd(bits_CAP_INNATE_RANGE_ATTACK2 );
// Innate range attack for kicking CapabilitiesAdd(bits_CAP_INNATE_MELEE_ATTACK1 );
// Can be in a squad
CapabilitiesAdd( bits_CAP_USE_WEAPONS );
CapabilitiesAdd( bits_CAP_DUCK );
// In reloading and cover
CapabilitiesAdd( bits_CAP_NO_HIT_SQUADMATES );
This defines that the NPC can have a squad, he cant hit squadmates, can duck etc etc. Adding things an NPC is capable of can improve very quickly his reactions and give him new abilities. Just experiment it. Removing CapabilitiesADD ( bits_CAP_MOVE_SHOOT ), from npc_combine_s for example, will result in taking away the possibility to shoot and move at the same time, so they'll be moving a lot more to avoid the player, but will shoot less, like HL1 grunts. Also, adding CapabilitiesADD( bits_CAP_MOVE_CLIMB ) with the proper animations from your modeler, will let the NPC climb ladders and other objects via info_node_climb. There's a lot that can be done to make your NPCs the best ever.
Now, you'll be asking "ok, this covers the moves he can perform, but what about the actual "thinking" ?" You're right, I almost forgot. NPCs think about what they'll have to do next with a combination of TASKS, CONDITIONS and SCHEDULES. To make it simple, a series of Tasks (such as wait_for_movement, get_path_to_target, and so on) are performed if certain conditions are met.
If the enemy (the player) is facing me (NPC), then do the following tasks, otherwise, do another one
A series of tasks compose a schedule. Schedules are marked as valid only if every task within the specified schedule is done. If only a single task is not done due to its conditions to be valid, then the schedule is immediately discarded. Lets have a look at the schedules that the Combine soldiers use in battle:
Search for int CNPC_Combine::SelectCombatSchedule()
if ( IRelationType( GetEnemy() ) == D_FR )
if (HasCondition( COND_SEE_ENEMY ) ||
HasCondition( COND_SEE_FEAR ) ||
HasCondition( COND_LIGHT_DAMAGE ) ||
HasCondition( COND_HEAVY_DAMAGE ))
Ok, this is a simple one. Basically it checks if the NPC sees an enemy, and if this enemy is someone he fears (relationship is equal to D_FR - FR stands for Fear), has taken light or heavy damage, then it starts the schedule run_away_from_enemy. Pretty simple huh? Knowing this and the specific tasks \ schedules \ conditions of each monster (usually stored in the Header file) and shared ones, you'll be able to modify their behaviour and make your NPCs true beasts in battle.
Have fun and experiment with your NPCs!