So, you have a script but want to add some functionality to it. The main script for characters is ai_soldier.lua and even I can't understand every bit of it so modifying it is really a pain in the..., so I figured out a neat way to make it work in a bit different way while not actually touching ai_soldier.lua file.
In this example we want a guard which will stand still unless he is being shot at or he sees us with a weapon. Something like this:
Let's create a new file called
guard.lua. Now for him to stay neutral we will need ai_neutral.lua and for him to attack the player we will need ai_soldier.lua, so let's require and initiate them in our new file:
package.path = "scriptbank/?.lua;"
require('ai_neutral')
require('ai_soldier')
function guard_init(e)
ai_neutral_init(e)
ai_soldier_init(e)
end
function guard_main(e)
end
Now we will add a simple code to make it call appropriate script when certain conditions are met. If we don't have a weapon in our hands (key 0) our
g_PlayerGunID variable will be 0, and if we have a weapon it'll be greater than 0. Similarly, if our guard can't see us it'll have
g_Entity[e]['plrvisible'] set to 0 and if he can see us it'll be 1. So let's just check if we have weapon (g_PlayerGunID greater than 0) and if guard can see us carrying the weapon (g_Entity[e]['plrvisible'] equals to 1). Since we are working with "plrvisible", make sure you set "View Cone Angle" and "View Range" on your soldier to some reasonable values (I have used 100 and 1000 respectively)!
function guard_main(e)
if g_PlayerGunID > 0 and g_Entity[e]['plrvisible'] == 1 then
ai_soldier_main(e)
else
ai_neutral_main(e)
end
end
That's basically it! When we get the weapon out and the guard can see us, it will call ai_soldier_main(e) and otherwise it will call ai_neutral_main(e). There's one thing though: If we wave a weapon in front of a guard and then holster it (in real life) I don't believe the guard will forget about it and with this code it will. So we need to set a flag for the guard to remember he has seen a weapon.
Create a global variable
guard_flagged right below our require statements and initialize it to false
require('ai_neutral')
require('ai_soldier')
guard_flagged = {}
function guard_init(e)
ai_neutral_init(e)
ai_soldier_init(e)
guard_flagged[e] = false
end
And then we need to modify our check to include this variable AND set it to "true" if our conditions are met:
function guard_main(e)
if guard_flagged[e] == true or (g_PlayerGunID > 0 and g_Entity[e]['plrvisible'] == 1) then
guard_flagged[e] = true
ai_soldier_main(e)
else
ai_neutral_main(e)
end
end
Note the parenthesis, they are very important here. We want our guard to attack if he is flagged OR both latter checks are true (player is carrying a weapon and is visible). To make him remember, we also set guard_flagged[e] to true.
However, there's still one thing left: If we are behind the guard and he can't see us, and we take out our weapon and shoot at him, he won't respond. To make him respond we will simply place his strength to 100 and when it gets below 100 we will change guard's flag state. This isn't a perfect solution if we have more guards with different strengths, but it'll be fine for the sake of this example:
function guard_main(e)
if guard_flagged[e] == true or (g_PlayerGunID > 0 and g_Entity[e]['plrvisible'] == 1) then
guard_flagged[e] = true
ai_soldier_main(e)
else
ai_neutral_main(e)
end
if g_Entity[e]['health'] < 100 then
guard_flagged[e] = true
end
end
That's it now! So the main idea is to require the scripts we are going to use, initialize them and make our script call those scripts' main functions depending on the conditions we define. Whole script (without debug info) is attached.
Note: Initializing two or more complex ai_ scripts may cause conflict and unpredicted behavior. But you're on your own with that
P.S. For debug info (like in my video above) add this line of code right below the newly added code (health check):
Prompt( (g_PlayerGunID > 0 and "carrying weapon" or "holstered") .. '; ' .. (g_Entity[e]['plrvisible'] == 1 and "visible" or "not visible") .. '; guard ' .. (guard_flagged[e] and "flagged" or "not flagged" ) )