Jump to content
Sign in to follow this  
thaFunkster

How to change AI stance? (and other questions)...

Recommended Posts

Hi,

I am currently trying to make a cutscene, there is suprisingly little helpful information on this around the web. I used to make them in OFP, but this seems harder.

Anyway, my first question:

I have a campfire, and I have included "this setBehaviour "CARELESS"" to the soldiers around it. But they still dont sit down. I cant seem to find how to make them sit down in the Comref, I thought there would be a "setStance" command but I cant seem to find it.

Can anyone tell me how to do this please?

(I will probably have a lot more questions later referring to camera setting, but for now this is it).

Thanks.

---

Also, I see there is a person setFaceAnimation blink command. What about the other ones? I want to make a soldier look worried or panicked..

Edited by thaFunkster

Share this post


Link to post
Share on other sites

Sitting down isn't a stance, it's an action. You can set a unit's stance with setUnitPos (standing, kneeling, prone).

To get a unit to sit down, use

_this action ["SitDown", _this];

, where _this is the unit to have sit. However this will probably only work for a short time. You'll probably also want to use _this disableAI "ANIM" to prevent the unit entering animations on its own so you can fully control its behaviour.

Here's the list of Actions in Arma 1. I don't think they've created an updated list for Arma 2, but most of the Arma 1 actions are still present.

You might also want to look at switchMove and playMove. Those entries have a link to an incomplete list of moves in Arma 2.

This is a little script that I have lying around for having people sitting down and chilling out, not sure how well it works though. Might give you something to start from though.

_anims = ["AmovPsitMstpSraSwrflDnon_smoking", "AmovPsitMstpSraSwrflDnon_weaponCheck1"];
doStop _this;
sleep 0.5;
_this disableAI "ANIM";
_this setBehaviour "SAFE";
_this action ["SitDown", _this];

while {behaviour _this == "SAFE"} do
{
 _anim = _anims select (random floor (count _anims));
 _this playMoveNow _anim;
 sleep 60 + (random 30);
};

This was for use in a mission, hence the 'safe' behaviour and falling out of the loop if the unit went into combat mode. You might want to remove that check and set it to careless instead.

Also, a DISMISSED waypoint will result in units wandering off and sometimes sitting down -- but that's very unlikely to be what you want for a cutscene, since it's unpredictable.

Not sure about the setFaceAnimation thing, there's a thread in the beta testing forum about setMimic not working which sounds like it might be what you'd need.

Share this post


Link to post
Share on other sites

Excellent, thanks indeed for that. I will try out your script and post back how it works.

Share this post


Link to post
Share on other sites

Ok,

I tried

_this action ["SitDown", _this];

I had to change "_this" to "this" otherwise it would say "local variable in global space".

Anyway, it didnt work... :(

I also tried your script ( I am putting all this in the initialization feild of the relevant unit) that didnt work either. (Note, no _ seem to work in this case, I had to remove them.)

Edited by thaFunkster

Share this post


Link to post
Share on other sites

It won't work when run from the unit init, since you can't use sleep statements and other pauses within the init. I also have a feeling that first "sleep 0.5" was important, like the unit needs to be allowed to do some initialisation before it will play your own animations.

Put the commands in a plain-text file in your mission directory, and rename it to sitdown.sqf or something similar. Then in the unit init field, put

nul = this execVM 'sitdown.sqf'

This will execute the script, with "this" (the unit) being passed to the script in its _this variable.

Share this post


Link to post
Share on other sites

I did exactly as you said. I tried to save in that directory and it wouldnt let me, saying I didnt have permission (Win 7). So I saved elswhere then pasted it across.

Anyway, went to run it, and I am told 'sitDown.sqf' not found, even though that is the exact name I gave it.

I saved to Program Files/Bohemia Interactive/ArmaII/Missions .....Any idea what is going on?

--------

EDIT: I got it, it's Win 7 creating a folder in My Documents...

It worked!

arma2s.jpg

----

Now, a couple of other questions if I may:

How do I get the two standing guys to look casual and shoulder their rifles?

And on a similar note, I have a patrol out the front, I set them to Careless, but they still walk, then run then walk then run, they dont look careless. I want them to do that casual walk with weapons on backs, any idea how I can do this?

Edited by thaFunkster

Share this post


Link to post
Share on other sites

I read somewhere that the animation for walking with weapons on back no longer exists, so I don't think you can do that. To get them to walk in careless mode, set their movement speed to limited, either on their waypoint or via group setSpeed "LIMITED".

I think there's an animation for standing still with weapons shouldered, but I'm not sure its name. A bit of Googling hasn't turned up anything, so I could be wrong...

If it's okay for the guy to be unarmed, you can playMove "UnaErcPoslechVelitele1" to have him stand with his hands behind his back. Looks kind of idle.

Share this post


Link to post
Share on other sites

What? How can it no longer exist? Where did it go lol....

Once again you have been very helpful, thankses.

Share this post


Link to post
Share on other sites

Ok,

So I have a new question if you will indulge me.

I have a trigger that goes off when Blue detected within a radius. On activation I want all red units to hold fire, not engage.

Then, when a second trigger is set off, I want a specific OPFOR unit to target then shoot a particular blue soldier.

How can I do this please?

Share this post


Link to post
Share on other sites

First you'll need a list of all OPFOR units that you want to have hold fire. You can get this by putting an OPFOR PRESENT trigger around the area you want to have affected, and giving it a name. In code elsewhere, you can then use "list name_of_that_trigger" to get the list of units which is activating it, which in this case will be all the OPFOR units in its area.

Alternatively, you can loop through allUnits and only apply the action to the opfor units. This might be easier and slightly more efficient for a cutscene where there's probably not many units outside of the area of interest, anyway.

Once you've decided on your list of units, you'll need to tell them not to fire. Hmmm. Most probably the best way is to set them to the 'never fire' combat mode. You may also need to set them as careless to prevent them behaving oddly. My only doubt is whether they'll immediately stop firing at their current target when you do this.

So, the code. If you're using allUnits, it'll be something like this:

{
 if (side _x == East) then
 {
   _x setCombatMode "BLUE";
   _x setBehaviour "CARELESS";
   _x doTarget objNull;
 };

} forEach allUnits;

I'm not sure if doTarget objNull will actually cause it to lose interest in its target. The times I've tried to use it, it's appeared to have no effect. A note on that page suggests to use doWatch objNull instead, so you could try that. Neither have been useful for me. You could also try using setCaptive on the blufor unit(s) to make the OPFOR stop shooting them.

Within the forEach loop, _x is the loop variable, so the code in the {}s is run once for each unit that exists in the game, with the value of _x pointing to each unit in succession.

You can then check which side the unit is on, and make the OPFOR units stop fighting with setCombatMode "BLUE" (never fire) and setBehaviour "CARELESS".

If you opt to use a trigger to select the OPFOR units you want to apply the cease-fire to, then the last line will look like:

} forEach list name_of_your_trigger;

For the second bit, when your trigger activates you want to do:

opfor_unit doTarget blufor_unit;
opfor_unit doFire blufor_unit;

That should cause it to target and fire at the blufor unit - use the name field in the unit properties in the editor to give it a name. You might want to add a sleep between the two actions for dramatic effect. If not, then I don't think the doTarget is really required; doFire should cause the unit to target and then shoot at the designated unit.

Share this post


Link to post
Share on other sites

Thank you once again.

Ok, so I have tried it, but it is not working.

My lone American Soldier keeps getting killed by the MGs once he runs up the hill.

Here is a screen of the trigger:

arma2pic.jpg

And here is the Script I am using:

{

if (side _x == East) then

{

_x setCombatMode "BLUE";

_x setBehaviour "CARELESS";

_x doTarget objNull;

};

} forEach list RedHoldFire

This is called "RedHoldFire.sqf".

Any idea what is going wrong?

Share this post


Link to post
Share on other sites

The condition should be left as "this", not set to "true" - it might be activating before the trigger has had time to detect the units inside it.

You could also try adding

_x sideChat 'Holding fire'

and seeing if the units are actually being processed (change it to globalChat if the player character isn't on the same side as them).

Although for that particular setup, I'd just use the waypoints to set the behaviour I wanted, and

this setCombatMode "BLUE" ; this setBehaviour "CARELESS"

in the init field for the units without any waypoints.

Share this post


Link to post
Share on other sites

OK, you advice about using the init field worked perfectly.

I now have created a trigger at a point where I want the blue soldier to get fired on.

When the trigger activates, I call "Shoot.sqf", I also created a global chat so I know it is activated, and it is.

Here is Shoot.sqf:

BMP1 doTarget Bman

BMP1 setBehaviour "COMBAT"

BMP1 setCombatMode "RED"

~2

BMP1 doFire Bman

The thing is, the guys in the BMP who are turned out all just sit there picking their noses. Any idea what is going wrong?

Also, I want the BMP to fire a shell rather than MG rounds at the soldier, so I can script the camera to do some really neat slow mo canon firing stuff.... How can I do that please?

Thanks again in advance....

Share this post


Link to post
Share on other sites

How are you running "shoot.sqf"? That script is in SQS syntax (the old style), so it needs to be run with "exec" rather than "execVM". And you should probably rename it to shoot.sqs to avoid confusion, although I'm pretty certain the game couldn't care less what file extension you use.

What is "BMP1"? There's some oddities with respect to issuing commands to vehicles vs. the people in them. Some things, like flyInHeight, you need to use the vehicle. Other things will work okay if you order the soldier. I think if you set the name in the unit properties for a unit that's on a particular side (i.e. not an empty vehicle) it'll actually refer to the commander or driver of the vehicle (depending on who's in charge of that particular vehicle type).

So... you could try issuing the commands to the vehicle rather than the commander ("vehicle BMP1 doTarget Bman") and see if that makes any difference. You could also try issuing the setBehaviour and setCombatMode commands to the group rather than an individual soldier ("group BMP1 setBehaviour ...").

To get it fire a particular weapon, you can try using the fire command. You can find a list of the vehicle weapons here. You'll probably want to avoid setting fire-at-will mode if you want to control which weapon they use.

Share this post


Link to post
Share on other sites

I am back trying to get this mission working again.

Can I ask for clarification about your point above? If I use old OFP style syntax then I use "exec" rather than execVM? What does the VM refer to ?

And with my script, can I use ~2 rather than "sleep 2"...?

Thanks.

Share this post


Link to post
Share on other sites

Ok,

Well, I have changed the script to "fire.sqs", and made it as follows:

vehicle BMP1 GlobalChat "Activated"

vehicle BMP1 doTarget Bman

sleep 2

vehicle BMP1 doFire Bman

Note, that the trigger that calls the script originally had that chat line, and it worked, so I know the trigger is being activated. However, for some reason the script is not, as the chat message know never comes up, and the BMP never fires...

Any ideas?

Share this post


Link to post
Share on other sites

Whats in your condition and actiation fields of the trigger mate?

Share this post


Link to post
Share on other sites

arma22009123114511875.jpg

I know the tigger is activating every time, because I had the global chat in the "on activation" feild initially.

However, now it is in the script itself, it is not showing...

Edited by thaFunkster

Share this post


Link to post
Share on other sites

Shouldn't you use a tilde as delay in .sqs (never used the format myself)? As has already been said, the 'VM' is for .sqf. It should read

nul = exec "script.sqs"

Share this post


Link to post
Share on other sites

Yes Reimann is correct. Note that SQS and SQF use two different syntaxes. SQF scripts can be run using "execVM", while SQS scripts are run using "exec". I pretty much exclusively use SQF since the syntax is more comfortable to me, but you will see some examples in SQS format so it's good to know both. SQS seems preferred for cutscenes, since camera.sqs provides its output in SQS syntax.

The main differences which I need to keep in mind when using SQS are:

  • SQS has one command per line, i.e. the new line indicates the start of a new statement. SQF needs a semi-colon at the end of statements.
  • In SQS, use ~5 for a 5 second sleep. Use sleep 5; in SQF.
  • In SQS, @condition stops the script until the condition is true. In SQF, use waitUntil { condition }; instead.
  • IF statements are completely different, can't remember SQS syntax since I've never used it. But it's probably ugly, IMO. :)

Otherwise, they're quite similar.

Now, with your example:

vehicle BMP1 GlobalChat "Activated"
vehicle BMP1 doTarget Bman
sleep 2
vehicle BMP1 doFire Bman

which you're invoking with

nul = this execVM "shoot.sqs"

it won't work, because you're using execVM (which tells Arma to expect the "SQF" syntax) but the statements aren't terminated with ;'s so it won't parse it properly.

Change your init trigger to use

this exec "shoot.sqs"

instead ("exec" doesn't return anything so you don't need that nul = in front of it, and you'll probably get an error if you try to use it).

You'll also need to change the "sleep 2" in the script to "~2" since there's no "sleep" command in SQS scripts.

Also, you should locate your ArmA2.RPT file, which is a logfile Arma generates when it runs. Script errors and such will be logged to this file, which will help tremendously when things don't work.

On Vista/Win7 it'll be in C:\Users\yourusername\AppData\Local\ArmA 2\ArmA2.RPT

Not sure on XP. But if all else fails, do a search of the whole drive for *.rpt. It can be opened with any text editor, e.g. notepad. I actually use tail on my second display to keep an eye on it, unfortunately it's not flushed all that often but it does still keep me from having to close and re-open it all the time.

You can also add the -showScriptErrors parameter to your ArmA2 command line and it'll show errors in-game, but only for a short while.

Edited by some kind of guy
De-Googlified link to tail

Share this post


Link to post
Share on other sites
Yes Reimann is correct. Note that SQS and SQF use two different syntaxes. SQF scripts can be run using "execVM", while SQS scripts are run using "exec". I pretty much exclusively use SQF since the syntax is more comfortable to me, but you will see some examples in SQS format so it's good to know both. SQS seems preferred for cutscenes, since camera.sqs provides its output in SQS syntax.

The main differences which I need to keep in mind when using SQS are:

  • SQS has one command per line, i.e. the new line indicates the start of a new statement. SQF needs a semi-colon at the end of statements.
  • In SQS, use ~5 for a 5 second sleep. Use sleep 5; in SQF.
  • In SQS, @condition stops the script until the condition is true. In SQF, use waitUntil { condition }; instead.
  • IF statements are completely different, can't remember SQS syntax since I've never used it. But it's probably ugly, IMO. :)

Otherwise, they're quite similar.

Now, with your example:

vehicle BMP1 GlobalChat "Activated"
vehicle BMP1 doTarget Bman
sleep 2
vehicle BMP1 doFire Bman

which you're invoking with

nul = this execVM "shoot.sqs"

it won't work, because you're using execVM (which tells Arma to expect the "SQF" syntax) but the statements aren't terminated with ;'s so it won't parse it properly.

Change your init trigger to use

this exec "shoot.sqs"

instead ("exec" doesn't return anything so you don't need that nul = in front of it, and you'll probably get an error if you try to use it).

You'll also need to change the "sleep 2" in the script to "~2" since there's no "sleep" command in SQS scripts.

Also, you should locate your ArmA2.RPT file, which is a logfile Arma generates when it runs. Script errors and such will be logged to this file, which will help tremendously when things don't work.

On Vista/Win7 it'll be in C:\Users\yourusername\AppData\Local\ArmA 2\ArmA2.RPT

Not sure on XP. But if all else fails, do a search of the whole drive for *.rpt. It can be opened with any text editor, e.g. notepad. I actually use tail on my second display to keep an eye on it, unfortunately it's not flushed all that often but it does still keep me from having to close and re-open it all the time.

You can also add the -showScriptErrors parameter to your ArmA2 command line and it'll show errors in-game, but only for a short while.

sorry for getting a little off subject, but I have to say thank you. I am a newbie when it comes to scripting and I have started recently using .sqf instead of .sqs. In this post you described it quite eloquently!:yay:

I may send you a few pm's sometime to get more understanding about script writing:D

Share this post


Link to post
Share on other sites

Great thanks to you both, that clears up a lot of confusion for me as well...

I will try out the fixes and see how I go.

Share this post


Link to post
Share on other sites

Great thanks to you both, that clears up a lot of confusion for me as well...

I will try out the fixes and see how I go.

------------

Ok:

I have changed my script to "Shoot.sqf" with the following in it:

sleep 0.5;

vehicle BMP1 GlobalChat "Activated";

vehicle BMP1 doTarget Bman;

sleep 2;

vehicle BMP1 doFire Bman;

It is being called in the trigger's on Activation field by this:

nul = this execVM "Shoot.sqf"

But still, nothing is happening, it is not running for some reason...

???

Share this post


Link to post
Share on other sites

Okay, standard troubleshooting:

  • The trigger is definitely being activated? Either put something in front of the execVM, or use the "effects" option to make something happen so you know the trigger definitely ran.
  • First line of your script, add
    player globalChat "Activated";

    This will let you see if the script itself is running but it's having problems with one or more of the commands.

---------- Post added at 03:11 PM ---------- Previous post was at 02:50 PM ----------

Additional troubleshooting ... it seems doFire isn't enough to get it to fire if the vehicle is in "hold fire" or "never fire" mode. That's a bit annoying...

If he's the only enemy around, you can add a

BMP1 setCombatMode "YELLOW";

to tell it to open fire. If it's targeting the enemy soldier the "doFire" would then be somewhat optional, but probably good to keep all the same.

The other option is to use fire to force it to immediately fire a particular weapon. However, it won't aim and then fire, so it needs to be pointing right at the moment first.

You can also use "fire" if you want to make the BMP fire its cannon instead of the PKT machine gun.

Additionally, if your BMP is set to CARELESS mode then it won't be able to turn its turret and will fail to properly target the soldier.

---------- Post added at 04:06 PM ---------- Previous post was at 03:11 PM ----------

A-ha! Welcome to the wonderful world of Arma scripting, where things that sound simple in theory turn out to have all sorts of complications.

You can use fire to force the BMP to fire its weapon, unless it's in CARELESS mode. Which is a bit annoying, however since it can't turn its turret in careless mode anyway, it probably doesn't really matter. So either start the unit in SAFE or AWARE, or have your script run:

BMP1 setBehaviour "AWARE";

This will get the crew to turn in and they'll start the engine so they can move the turret.

If you do this though, you'll find a bit of an issue: you can fire all you like, but they'll never actually hit the guy. This seems to be because doTarget only tracks the target on the horizontal plane, but doesn't angle the gun downwards. So all the shots will go right over your Bguy.

However! doFire will cause them to aim the gun properly. If their combat mode is set to "BLUE" (Never fire) or "GREEN" (Hold fire) or, presumably, "WHITE" (hold fire, engage at will) then they won't actually fire the gun. But they will aim it properly.

So, you can either:

  • use doTarget to get the BMP to track the bad guy, then when you want it to attack, use setCombatMode "YELLOW" to make it open fire with the AI handling weapon selection and fire rate; or
  • use doTarget to get the BMP to track the bad guy (if you want), doFire to get it to aim at him properly, and finally BMP1 fire "PKT" to get it to fire the machinegun or BMP1 fire "2A72"; to get it to fire the cannon (assuming it's a BMP-3, other vehicles will have different weapons).

You might want to put the firing into a loop that only stops when the guy is dead, just in case the first shot misses and your cutscene starts getting confusing for the viewer.

Here's a full script I'm using to test this, which is probably overly complex for your cutscene, but might be fun to understand all the same:

BMP1 GlobalChat "Activated";
sleep 0.5;
BMP1 setBehaviour "SAFE";
BMP1 setCombatMode "BLUE";
BMP1 doTarget Bman;
sleep 4;
while { damage Bman < 1.0 && time < 60 } do
{
 BMP1 fire (currentWeapon BMP1);
 if (currentWeapon BMP1 == "PKT") then
 {
   sleep 0.1 + random 0.1;
   if (random 1 < 0.05) then { BMP1 selectWeapon "2A72"; };
 }
 else
 {
   sleep 0.3 + random 0.3;
   if (random 1 < 0.2) then { BMP1 selectWeapon "PKT"; };
 };
}
if (damage Bman < 1.0) then
{
 BMP1 globalChat "Going weapons hot!";
 BMP1 setCombatMode "YELLOW";
};

Okay so the first few lines you're probably quite familiar with. The next big block makes the BMP continue to fire at the Bman until either he's dead (damage unit == 1 means he's dead/destroyed), or 60 seconds have passed since the mission started.

Once that loop ends, if the Bman is still alive, we change the BMP's combat mode to "Open fire" and let the AI finish the job. Note that the above script is using doTarget, which means the "forced firing" won't ever kill the man (unless he happens to be on a hill at the right elevation...). If you change that to doFire, then the first shot will almost certainly kill him, provided your initial sleep is long enough for them to get the gun aligned.

Inside the "forced firing" loop, we get the BMP to fire its currently selected weapon, then pause a bit and randomly decide if we want to switch weapon. It starts out using the PKT (because it's targeting a soldier), but you could force that before the loop starts with BMP1 selectWeapon "PKT"; if you wanted to be certain. I then use different random percentages and sleep values to make it more likely to use the PKT, and fire more rapidly with the PKT. If you only want to use the cannon, you could replace that whole section with

while { damage Bman < 1.0 && time < 60 } do
{
 BMP1 fire "2A72";
 sleep 0.5;
};

and if you trust the AI to hit it (which it will do if you use doFire instead of doTarget) then you could remove the loop and just make it fire once or twice.

In case you're still having problems, here's a very simple mission with the above script in place, set on Utes. A blufor guy will walk out from behind the control tower, into a trigger which will execute the script and cause a parked BMP to target him and then kill him.

ShootTest.utes.7z

Just extract it to your missions directory and it should create a new folder ShootTest.utes, and then load it in the mission editor and hit preview.

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
Sign in to follow this  

×