Just for hypothesis here's my ideas how the AI could be improved. It's a bit of a long post but I put a lot of thought in it and this would solve almost every issue with NPC behavior. Whether it's really possible I don't know but most of these things are already in Deus Ex and just need some modification of it.
There's already a state called "alarmed" for the NPC's. When they are in this state they search for the player. But they can also do some special things, for instance raisealarm_beforefleeing in the AI properties, which can also be set to raisealarm_beforeattacking. Now let's say there were three new navigationpoints: "combatnode" "defensepoint" and "assaultpoint" And when NPC's are alarmed they ignore the regular pathnodes and patrolpoints and only use these three new navigationpoints. This would greatly improve the behavior of NPC's during battles. The new navigationpoints are visible to the NPC when he's not alarmed so combatnodes can be placed as normal pathnodes too. That way there's no need to double place pathnodes (which would clog up the engine)
First the function of the combatnode. The combatnode needs to have a property called "combatgroup" And then there needs to be a new NPC class that also has the property "combatgroup". Assign the new NPC's to certain combatgroups and they will never use others. That way the NPC's will never leave a certain area during a battle but they run around randomly inside the area, only sticking to the combatnodes they are assigned to. Assign a NPC to a single combatnode and he will never leave that single spot. Assign a NPC to no combatnodes and he will treat all combatnodes like they are the same, even if the combatnode has a group. These "combatgroups" seem like the hardest to code since navigationgroups don't seem to be in Deus Ex at all. The rest should be easier to code since it's variations of what already exists in Deus Ex combined with this new function.
The combatnode is meant for random movement during battles. But the mapbuilder might want the NPC's to do something specific when they are alarmed. Let's say the NPC is at point A and the mapbuilder wants the NPC to run to point B and then point C when he becomes alarmed. This is what a defensepoint would be used for. It's sort of the same as the patrolpoint, except that when the NPC becomes alarmed he receives an ordertrigger to run to that point. For that reason the custom NPC has another new property under Orders called "defense/assaultpoint" to specify that point.
The defensepoint has the same properties as a normal patrolpoint, most notably Nextpatrol and pausetime. It's possible to link defensepoints together the same way as patrolpoints but instead of walking the NPC runs. Furthermore you can also use a normal ordertrigger (RunTo defensepointA) to make NPC's run around in a map without alarming them. With an ordertrigger they can only run to one spot but making them run to a defensepoint would make them run to the next one.
The assaultpoint works the same as the defensepoint with one big difference: it makes the NPC become unalarmed. With defensepoints the NPC still shoots back, so when confronted with the player they would still attack him instead of run to the defensepoint. Assaultpoints make the NPC become unalarmed even if the player is shooting at them while they are running. They completely ignore the player and any other threats. This way the mapmaker can make groups of NPC's split up and use tactics when they are attacked. NPC's would only become alarmed again once they reached a defensepoint, so the mapbuilder would always have to use a defensepoint as the last point.
Defensepoints and assaultpoints also have these properties: "combatgroup" and "nextcombatgroup" That way they can be used to switch combat groups, something that is needed to make an NPC run behind a cover and stay there. If nextcombatgroup is set to none the NPC will treat all combatnodes like they are the same again.
Here's three examples of how to use combatnodes, defensepoints and assaultpoints.
- Example 1: one NPC hiding behind cover
To make an NPC seek cover and stay under this cover the mapmaker needs to set the custom NPC to defense/assaultpoint=defend_here. Then the mapmaker places a defensepoint somewhere and names it “defend_here” in the tag properties. Then he sets the path to the defensepoint with combatnodes. He sets the combatnodes to be “groupA” in their properties and in the NPC’s properties he sets the combatgroup to “groupA” too. However in the defensepoint he sets the nextgroup to be “groupB” while there is no group B. That way the NPC will never leave that spot and not attempt to run back to the combatnodes again. If the mapbuilder wants the NPC to ignore the player until the NPC has reached the defensepoint he should make the NPC start with an assaultpoint.
Example 2: one or more NPC’s guarding an area
To make one or multiple NPC’s guard an area simply use combatnodes and make them have combatgroups. Set the NPC’s to the same combatgroups. This way for instance a group of enemies will stop chasing the player once he leaves a certain area.
Example 3: making the NPC's try to surround the player
The player encounters a large group of NPC's. A firefight breaks out. Most of the NPC's are set to combatgroups and will stay to defend the area, they will not run towards the player. In this scenario both the player and the NPC's are hiding behind cover and shooting at each other. Some of the NPC's are set to assaultpoints so they ignore the firefight. The assaultpoints lead around the buildings and to the player's flank. If the player stays where he is he will be surrounded.
Now there's just one last little thing that's needed: a combattrigger. Usually the player has several ways to approach a group of NPC's. The combattrigger would work like this: it sends the commands for "defense/assaultpoint" and "combatgroup" to the NPC it is attached to. But the NPC will only respond to them when he becomes alarmed. The combattrigger works as "bWhileStandingByOnly" in a flagtrigger and their radius would typically be big. That way if the player encounters a scenario like in example 3 the NPC's will be able to respond with different counter attacks. Since there are usually different ways to approach enemies there should be different defensepoints or assaultpoints the NPC runs to when he is alarmed. For instance an NPC might have a long patrolpoint, so if the NPC is set to "defense/assaultpoint=assault_here" he might run away from the player while the mapmaker doesn't want that. For those reasons there needs to be a combattrigger to tell the NPC to go to a specific defense/assaultpoint and use a specific group of combatnodes when the player is in a certain location. The combattrigger should have up to eight "outevents" and "outtags" that can be set so that multiple NPC's can be attached to the same combattrigger, a bit like the dispatcher has eight outevents and outdelays. Combattriggers can also be attached to each other for even bigger groups of NPC's.
The radius of a combattrigger could be set smaller by the mapbuilder. That way NPC's react more precise to what the player is doing. If the player is hiding behind a wall they'd have a tactic for that, but if he switches to hiding behind a tree they'd have a tactic for that too. Still not exciting enough? Well, I suppose seeing the AI respond the same way gets kinda boring during replays. So let's include a "random combattrigger" This trigger is the same as the normal combattrigger except that instead of having eight outevents and outtags it only has eight "randomtags" and it can only be attached to one NPC. Once the NPC becomes alarmed he randomly picks one of the points in "randomtags" That way the NPC won't always use the same tactic and games don't become predictable. Just like the normal combattrigger randomcombattriggers can be attached to each other for bigger groups of NPC's.
Oh, and the new NPC's could really use a new property called "bCrouch" under Combat. Otherwise NPC's will attempt to crouch and fire while standing behind cover. And a property that could be added to the defensepoints and assaultpoints is "wait for" with a class and a "waitfor time" specified there. That way the NPC's would wait for a certain class to arrive before running to the next point and the NPC's will act more like a team. Since the mapbuilder doesn't want the NPC's to wait forever for dead NPC's there should be a waiting time which is the maximum time the NPC will wait before running to the next point. Add options to fill in up to eight class types to wait for and the mapbuilder can set up teams by creating separate classes for all the team members and make them spread out through a city and meet up again before spreading out again. Set the class type to the player's class to make them wait for the player.
Taa-daah! Now the NPC's can do almost everything the mapbuilder wants during a battle. So who's gonna code this and release it as a new mod?