AI behaviour depending on player actions: Difference between revisions
No edit summary |
|||
Line 1: | Line 1: | ||
I am going to describe the setup of a mission, in which the AI is neutral to the player as default. | I am going to describe the setup of a mission, in which the AI is neutral to the player as default. The AI only gets hostile to the player, if the player is seen performing an illegal action. Such actions include: Being seen in an area where the player isn't supposed to be, stealing loot, or carrying a weapon. | ||
The first thing you have to do is to put all AI | The first thing you have to do is to put all affected AI on one team. Let's just take team 1. So set the spawnarg "team" "1" on all affected AI and make sure non-affected AI are on a different team. Create a ''target_setrelation'' entity and set the following spawnarg on it: "rel 1,0" "0". This will cause the AI on team 1 to see the player (team 0) as neutral (0). Target this entity from a worldspawn brush or trigger it via the command | ||
sys.trigger($nameof_target_setrelation); | sys.trigger($nameof_target_setrelation); | ||
included in your main function. | included in your main() script function. | ||
== Being seen in an area where you aren't supposed to be == | == Being seen in an area where you aren't supposed to be == | ||
The first thing you need to do is to make use of the zone system. This approach is described [http://wiki.thedarkmod.com/index.php?title=Ambient_Sounds,_a_zone_approach, here]. This system allows you to call functions when the player | The first thing you need to do is to make use of the zone system. This approach is described [http://wiki.thedarkmod.com/index.php?title=Ambient_Sounds,_a_zone_approach, here]. This system allows you to call functions when the player passes from one zone to another. Here we'll make use of the ''call_on_entry'' script function. The following has to be applied to all allowed/disallowed zones neighboring each other. On the ''info_location'' entities belonging to the zones set the spawnarg "call_on_entry" "''functionname''", where ''functionname'' is: | ||
''setNeutralZone'' on allowed zones | ''setNeutralZone'' on allowed zones | ||
''setHostileZone'' on disallowed zones | ''setHostileZone'' on disallowed zones | ||
The functions used here have to have the form '''void''' ''functionname''('''entity''' ''entityname''). The ''entity'' is the zone | The functions used here have to have the form '''void''' ''functionname''('''entity''' ''entityname''). The ''entity'' is the zone the player enters. As we don't need it here, but need the basic behavior for the weapon-based AI-player relation discussed below, they just call other functions with the same names without ''Zone'' at the end and no arguments passed. What they do is trigger the ''target_setrelation'' entities from the next section named ... | ||
== | == Caught stealing == | ||
This | This makes use of some triggers. You'll need two ''target_setrelation'' entities and one ''trigger_relay'' entity. | ||
On the first ''target_setrelation'' entity set the spawnarg "rel 1,0" "-1" | On the first ''target_setrelation'' entity set the spawnarg "rel 1,0" "-1". On the second, set "rel 1,0" "0". Let the ''trigger_relay'' target the second ''target_setrelation'' entity and set the spawnarg "delay" "T" on the ''trigger_relay'', where T specifies the timespan in which the player is detected as hostile after stealing something (see description below). | ||
Now let '''every''' item that the player is not allowed to take target both the first ''target_setrelation'' and the ''trigger_relay'' entity. The next thing you need to do is to set up a hidden objective with the content "If one AI of team 1 goes to alert state 5". In the '''success script''' field enter ''isHostile''. This function will then destroy the second ''target_setrelation'' entity, so the AI stays hostile to the player. | Now let '''every''' item that the player is not allowed to take target both the first ''target_setrelation'' and the ''trigger_relay'' entity. The next thing you need to do is to set up a hidden objective with the content "If one AI of team 1 goes to alert state 5". In the '''success script''' field enter ''isHostile''. This function will then destroy the second ''target_setrelation'' entity, so the AI stays hostile to the player. | ||
''Note: alert state 5 is the highest alert state and means | ''Note: alert state 5 is the highest alert state and means that the player was seen by an AI.'' | ||
What does the setup do? | What does the setup do? | ||
Every time you steal something the AI from team 1 will be set hostile to you for a certain amount of time. After that period they will become neutral to you again, unless they see you within this amount of time. If so, they'll stay hostile. As you can see the amount of time (called T above) has an impact on how difficult it is for the player to get away with disallowed actions. Setting it to a higher value makes it more difficult and vice versa. | |||
== Being seen carrying a weapon == | == Being seen carrying a weapon == | ||
You'll need the following script: | |||
void CheckWeapon() | void CheckWeapon() | ||
Line 52: | Line 52: | ||
This function is started from the ''main'' method via | This function is started from the ''main'' method via | ||
thread | thread CheckWeapon(); | ||
The functions ''setNeutral'' and ''setHostile'' are the same as above. The script | The functions ''setNeutral'' and ''setHostile'' are the same as above. The script sets the AI to hostile as long as you carry a weapon. Again, being seen by any hostile AI will cause the hostility to be permanent. | ||
== What is missing == | == What is missing == | ||
There are | There are other situations in which the player could be seen as a threat. For example if he is seen attempting to pick a door or opening one that is normally locked by a key the player isn't suppose to have. Also, the player could be seen as a threat when discovered carrying a body. | ||
In addition, it is also not very realistic that '''all''' the AI in Team 1 will become your enemies once '''one''' AI has seen you doing something | In addition, it is also not very realistic that '''all''' the AI in Team 1 will become your enemies once '''one''' AI has seen you doing something you're not allowed to do, especially since you have the possibility of killing him and hiding him without being seen. | ||
Another point is that there is a delay on how long you can be detected after stealing something. Applying such a | Another point is that there is a delay on how long you can be detected after stealing something. Applying such a behavior to the other '''DONT'S''' may be useful. | ||
This needs fixing and I will add solutions once I have them. | This needs fixing and I will add solutions once I have them. | ||
Line 68: | Line 68: | ||
== Summary == | == Summary == | ||
Now that we have all the pieces together, let's sum up | Now that we have all the pieces together, let's sum up how to set up the complete behavior. (We are starting from zero here; nothing has been done so far). | ||
We need: | We need: | ||
Line 76: | Line 76: | ||
One ''trigger_relay'' entity called '''relay''' | One ''trigger_relay'' entity called '''relay''' | ||
A script file called ''mymapname''.script, where ''mymapname'' | A script file called ''mymapname''.script, where ''mymapname'' is the name of your map. | ||
An invisible objective "If one AI of team 1 get to alert level 5". | |||
---- | ---- | ||
On all affected AI set "team" "1". Non-affected AI go to another team. | |||
On '''makeHostile''' set "rel 1,0" "-1". | |||
On '''makeHostile''' set "rel 1,0" "-1" | |||
On ''' | On '''makeNeutral''' set "rel 1,0" "0". | ||
On | On '''relay''' set "target" "makeNeutral" and "delay" "1". | ||
On ''' | On the objective put ''stayHostile'' in the '''success script''' field. | ||
On '''all''' | On '''all''' objects that are not allowed to be taken by the player set "target" "makeHostile" and "target0" "relay". | ||
On '''all''' ''info_location'' entities belonging to zones where the player is not allowed to be, set "call_on_entry" "setHostileZone". | |||
'' | Do the same for '''all''' other ''info_location'' entities but use the method "setNeutralZone". | ||
''Hint: The last two steps can be restricted to zones neighboring zones of the other kind''. | |||
On '''any''' worldspawn set "target" "makeNeutral". | |||
---- | ---- | ||
In the script file include | In the script file include | ||
Line 126: | Line 122: | ||
$makeNeutral.remove(); | $makeNeutral.remove(); | ||
} | } | ||
void | void CheckWeapon() { | ||
do { | do { | ||
if ($player1.getCurrentWeapon()=="atdm:weapon_unarmed") { | if ($player1.getCurrentWeapon() == "atdm:weapon_unarmed") { | ||
setNeutral(); | setNeutral(); | ||
} | } | ||
Line 138: | Line 134: | ||
} | } | ||
void main() { | void main() { | ||
thread | thread CheckWeapon(); | ||
} | } | ||
That's it. If you want to make the detection time for stealing things difficulty dependent, add the following spawnargs on '''relay''': | That's it. If you want to make the detection time for stealing things difficulty-dependent, add the following spawnargs on '''relay''': | ||
"diff_1_change_0" "delay" | "diff_1_change_0" "delay" | ||
Line 148: | Line 144: | ||
"diff_2_arg_0" "2.0" | "diff_2_arg_0" "2.0" | ||
Of course you can use other times | Of course, you can use other times than mentioned here. | ||
--[[User:Obsttorte|Obsttorte]] ([[User talk:Obsttorte|talk]]) 11:18, 2 January 2013 (EST) | --[[User:Obsttorte|Obsttorte]] ([[User talk:Obsttorte|talk]]) 11:18, 2 January 2013 (EST) |
Revision as of 19:41, 2 January 2013
I am going to describe the setup of a mission, in which the AI is neutral to the player as default. The AI only gets hostile to the player, if the player is seen performing an illegal action. Such actions include: Being seen in an area where the player isn't supposed to be, stealing loot, or carrying a weapon.
The first thing you have to do is to put all affected AI on one team. Let's just take team 1. So set the spawnarg "team" "1" on all affected AI and make sure non-affected AI are on a different team. Create a target_setrelation entity and set the following spawnarg on it: "rel 1,0" "0". This will cause the AI on team 1 to see the player (team 0) as neutral (0). Target this entity from a worldspawn brush or trigger it via the command
sys.trigger($nameof_target_setrelation);
included in your main() script function.
Being seen in an area where you aren't supposed to be
The first thing you need to do is to make use of the zone system. This approach is described here. This system allows you to call functions when the player passes from one zone to another. Here we'll make use of the call_on_entry script function. The following has to be applied to all allowed/disallowed zones neighboring each other. On the info_location entities belonging to the zones set the spawnarg "call_on_entry" "functionname", where functionname is:
setNeutralZone on allowed zones setHostileZone on disallowed zones
The functions used here have to have the form void functionname(entity entityname). The entity is the zone the player enters. As we don't need it here, but need the basic behavior for the weapon-based AI-player relation discussed below, they just call other functions with the same names without Zone at the end and no arguments passed. What they do is trigger the target_setrelation entities from the next section named ...
Caught stealing
This makes use of some triggers. You'll need two target_setrelation entities and one trigger_relay entity.
On the first target_setrelation entity set the spawnarg "rel 1,0" "-1". On the second, set "rel 1,0" "0". Let the trigger_relay target the second target_setrelation entity and set the spawnarg "delay" "T" on the trigger_relay, where T specifies the timespan in which the player is detected as hostile after stealing something (see description below).
Now let every item that the player is not allowed to take target both the first target_setrelation and the trigger_relay entity. The next thing you need to do is to set up a hidden objective with the content "If one AI of team 1 goes to alert state 5". In the success script field enter isHostile. This function will then destroy the second target_setrelation entity, so the AI stays hostile to the player.
Note: alert state 5 is the highest alert state and means that the player was seen by an AI.
What does the setup do?
Every time you steal something the AI from team 1 will be set hostile to you for a certain amount of time. After that period they will become neutral to you again, unless they see you within this amount of time. If so, they'll stay hostile. As you can see the amount of time (called T above) has an impact on how difficult it is for the player to get away with disallowed actions. Setting it to a higher value makes it more difficult and vice versa.
Being seen carrying a weapon
You'll need the following script:
void CheckWeapon() { do { if ($player1.getCurrentWeapon() == 'atdm:weapon_unarmed') { setNeutral(); } else { setHostile(); } sys.wait(1); } while(true); }
This function is started from the main method via
thread CheckWeapon();
The functions setNeutral and setHostile are the same as above. The script sets the AI to hostile as long as you carry a weapon. Again, being seen by any hostile AI will cause the hostility to be permanent.
What is missing
There are other situations in which the player could be seen as a threat. For example if he is seen attempting to pick a door or opening one that is normally locked by a key the player isn't suppose to have. Also, the player could be seen as a threat when discovered carrying a body.
In addition, it is also not very realistic that all the AI in Team 1 will become your enemies once one AI has seen you doing something you're not allowed to do, especially since you have the possibility of killing him and hiding him without being seen.
Another point is that there is a delay on how long you can be detected after stealing something. Applying such a behavior to the other DONT'S may be useful.
This needs fixing and I will add solutions once I have them.
Summary
Now that we have all the pieces together, let's sum up how to set up the complete behavior. (We are starting from zero here; nothing has been done so far).
We need:
Two target_setrelation entities called makeHostile and makeNeutral
One trigger_relay entity called relay
A script file called mymapname.script, where mymapname is the name of your map.
An invisible objective "If one AI of team 1 get to alert level 5".
On all affected AI set "team" "1". Non-affected AI go to another team.
On makeHostile set "rel 1,0" "-1".
On makeNeutral set "rel 1,0" "0".
On relay set "target" "makeNeutral" and "delay" "1".
On the objective put stayHostile in the success script field.
On all objects that are not allowed to be taken by the player set "target" "makeHostile" and "target0" "relay".
On all info_location entities belonging to zones where the player is not allowed to be, set "call_on_entry" "setHostileZone".
Do the same for all other info_location entities but use the method "setNeutralZone".
Hint: The last two steps can be restricted to zones neighboring zones of the other kind.
On any worldspawn set "target" "makeNeutral".
In the script file include
void setHostileZone(entity zone) { setHostile(); } void setNeutralZone(entity zone) { setNeutral(); } void setHostile() { sys.trigger($makeHostile); } void setNeutral() { sys.trigger($makeNeutral); } void stayHostile() { setHostile(); $makeNeutral.remove(); } void CheckWeapon() { do { if ($player1.getCurrentWeapon() == "atdm:weapon_unarmed") { setNeutral(); } else { setHostile(); } sys.wait(1); } while(true); } void main() { thread CheckWeapon(); }
That's it. If you want to make the detection time for stealing things difficulty-dependent, add the following spawnargs on relay:
"diff_1_change_0" "delay" "diff_1_arg_0" "1.5" "diff_2_change_0" "delay" "diff_2_arg_0" "2.0"
Of course, you can use other times than mentioned here.