In general, each creature starts off asleep/idle and does nothing but wait for stimuli or scripting commands. While in this condition the level designers can do all the scripting they want to the creature because no AI is currently running (it is basically off). Now, for the AI to actually turn on, the creature must receive some type of stimuli to activate it. Right now these include sight (of an enemy), sounds (weapons, pain, footsteps, etc.), and pain. If any of these stimuli are received, then the AI will turn on and scripting will no longer be run. At this point, the state machine will now be processed each frame and scripting will be ignored until such time that the AI is finished. The AI can finish if it resolves the stimuli (enemy is killed, checks out the sound and finds nothing, etc.) or it fails to resolve the stimuli (it loses the enemy and can’t find him). This would put the creature back to the asleep/idle condition again and everything starts over.
· Conditionals are usually just short C procedures that determine if a specific condition is true or false. These are used by the state machine to determine which state to go to next. They process the actor’s information (or global information) to determine if the condition is true or false.
· Format: (in actor.cpp)
bool <conditional procedure name>( Conditional &condition, Entity &ent )
{
Actor *act = (Actor *)&ent;
…
conditional code
…
return boolean value;
}
Conditional <conditional name>(“<string used from statemaps>”, <procedure name>);
· This is where the AI actually does the real work (walk, attack, fire, etc.).
· Each behavior must have at least a Begin, Evaluate, and End procedure and optionally can have a ShowInfo, Archive, and Unarchive procedure (and any others that are necessary). The Begin procedure is called once when the behavior is first setup, the End procedure is called once when the behavior is finished, and the Evaluate procedure is processed every frame that the behavior is running. As for the optional ones, Showinfo is used to print useful information, Archive is used in save games, and Unarchive is used in loading save games.
· Special note: returning false in the Evaluate procedure ends the behavior. So if the state machine does not handle this then no behavior will be running until the state changes. This might be changed in the future.
· This is what defines how a creature transitions between all of its states (determines what to do). It uses the conditionals to determine which state to go to and when and what to actually do when in that state (which behavior). Each state machine is defined in a .st file and all of them are located in the fakk/ai directory.
· Basically how the state machine works is as follows: every game frame the state machine for each actor is processed if the actor is awake. It starts with the first potential next state and works its way down the list of potential next states. The first state to have all of its conditions to evaluate to true is the state chosen to be next. Once the state for this game frame is chosen, then the animation is chosen in a similar manner (tests until ones conditions all evaluate to true). Also, if this is a new state (changed since last frame) we setup the new behavior (set by the behavior command).
· Format (just one state, see fakk/ai directory for full state machines):
state <state name>
{
legs
{
<animation name> : default
}
behavior <behavior name> <arguments>
time <minimum time> <maximum time> (optional command)
states
{
<state 1 name> : <conditional 1 name> <arguments> <conditional 2 name> …
<state 2 name> …
}
}
· All arguments must be in quotes (might change in future).
· The behavior command sets which behavior will be processed while in this state.
· The time command (optional) specifies the minimum and maximum time to spend in this state (if nothing else changes the state first). This is used with the TIME_DONE or DONE conditional.
· This is where the level designers can make the creatures do very specific things (walk on a patrol route, set an alarm off, etc.).
· Events that occur that basically turns on the AI. These include sight, sound, pain, and script (attack and attackplayer commands). If left alone all of these will turn the AI on. There are some commands to help manage which stimuli any individual creature will respond to and some for the entire class of creature.
· ai_on – turns on response to all stimuli
· ai_off – turns off response to all stimuli (ai will never turn on with this command on)
· ai_deaf – creature will ignore sounds
· ai_dumb – creature will ignore sight and sounds
· deaf – makes all creatures of this type ignore sounds (in tiki file)
There are two main ways to extend the AI from code. You can add new conditionals and you can add new behaviors. You should add new conditionals if you want the AI to make better decisions on what to do. You should add new behaviors if you want the creatures to be able to do new things. See the previous section to see what the format is to add new conditionals and behaviors.
You can also extend the AI by adding commands to the level script for any individual creature to make it do very specific things (walk a certain patrol route, type on the computer, etc.). You can add these commands basically in two different places, directly in the level script (which is normally probably not a good idea) and inside of an actor thread. The reason why directly inside the level script is probably not normally good is because these commands will always get run regardless if the AI is running or not. The commands in the actor threads on the other hand will be ignored until the AI is back in an idle state (this is much safer in general).
· Thread format:
$<actor name> thread <label name> (starts the actor thread at this label)
<label name>: (actual thread, this will be in the level script somewhere)
…
script commands
…
end
· Some available script commands are : lookat, turnto, walkto, jumpto, runto, anim, attack, attackplayer, ifenemyvisible, ifnear, ifcanhideat, and ifenemywithin. See game for current documentation on these commands.
· The path finding routine in FAKK is just your typical A* search.
· Can place pathnodes in the editor with info/pathnodes.
· The maximum distance between any path nodes that wants to be a connected directly is 128 units.
· Can mark nodes as special types in editor (AI_FLEE, AI_DUCK, and AI_COVER).
· AI_DOOR, AI_JUMP, AI_LADDER, and AI_ACTION aren’t used right now.
· Use the command ai_showroutes in the game to see the paths.
· In general, use as few path nodes as possible while still below the maximum length of 128.
· See the map arena for a good example of a map with path nodes in it.
· Seek – just steers directly towards the destination
· FollowPath – follows along the path nodes to the destination
· Chase – tries to get to the destination however possible. First sees if it can walk directly to destination (does this check in code doesn’t actually try to move there). If this can’t be done then it uses the path nodes to go where it needs to. If for some reason the actor gets stuck while trying to use the path nodes it will wander a little bit to get unstuck.
· actorinfo <actor number> - shows lots of useful info on the specified actor
· ai_showroutes – shows the path routes
· ai_shownodenums – shows the path routes with the node numbers
· ai_timepaths <minimum number> - displays path finding time if greater than or equal to the minimum number (in milliseconds)
These are the current behaviors that are in the game as of 1/12/2000. The following format is the behavior name, what parameters (through setargs) it can receive if any, and a short description.
· Idle – does nothing but twitch every once in a while
· Watch – tries to always look towards the enemy
· Turn <turnspeed> – constantly turns at the specified speed
· TurnTo – turns toward the specified entity or direction
· GotoPathNode <anim name> <vector or path node name> - actor goes to the specified location
· Flee <anim name> - actor runs towards a random path node
· PlayAnim <anim name> - plays the specified animation
· FindCover <anim name> <crouch anim name> - actor moves to nearest path node mark as either AI_DUCK or AI_COVER that cannot be seen by the enemy. If marked as AI_DUCK then the actor will crouch when it gets to the node.
· FindFlee <anim name> - actor moves to the nearest path node marked as AI_FLEE
· FindEnemy <anim name> - actor moves to the nearest path node where it can see the enemy
· AimAndShoot <fire anim> <max shots> <aim anim> - actor aims and then shoots at the enemy
· AimAndMelee <anim name> <max shots> - actor aims and then melees enemy
· Jump <anim name> <path node or entity> <speed> - actor jumps to specified spot
· FlyToPoint – flys to specified point (internal use by code only)
· FlyCloseToEnemy <anim name> <turnspeed> - tries to fly to enemy
· FlyWander <anim name> <turnspeed> <change course time> - flies around randomly
· FlyCircle <anim name> - flies in circles around enemy
· FlyDive <anim name> <speed> - dives towards enemy
· FlyClimb <anim name> <height> - climbs up to specified height relative to current position
· Land <anim name> - lands on ground directly beneath actor
· GetCloseToEnemy <anim name> - actor moves towards enemy
· Investigate <anim name> - actor investigates noise heard
· Aim – aims toward the specified target (internal use by code only)
Utility behaviors are those that are designed only to do something in their begin function. Thus they only do something when first called.
· GetNearestEnemy – sets the actor’s currentEnemy to the nearest enemy
· Suicide – kills the actor
· TurnTowardsEnemy – turns directly towards the enemy
· DamageEnemy <damage> - damages the enemy
· CircleEnemy <anim name> - circles around the enemy, used by shkynerpad_bigarm
· ShockWater – shocks the water with electricity, used by shkynerpad_bigarm
· Shock <tag name> <damage> <attack pitch> <random angle> – shock the water with elec., use by shkynerpad_smallarm
· CircleAttack <command> <direction> - makes all small arms do a circle attack, used by shkynerpad_body
· DragEnemy <tag name> <damage> - binds the enemy to the specified tag and then drags him along, used by tr_vine
· Spin <speed> - spins the actor at the specified speed, used by spinning_plant
· Digest – digests any nearby entities, used by sucknblaugh
· Might change the format of passing arguments to everything in the state machine from the quoted method to a more normal method :) from “arg1” “arg2” to ( arg1 , arg2 )
· Need to add code for actor’s to open doors and to use jump nodes
· Need to fix obstacle avoidance code