Jump to content
MANTIA

Have A.I. pull weapon when trigger fired

Recommended Posts

Trying to have an unarmed OPFOR ("BADGUY")a.i. unit pull out a weapon via a trigger. Currently have in trigger "on act" null = execVM "BADCIVI.sqf" and in that sqf [BADGUY, "hgun_Pistol_01_F", 1, 0] call BIS_fnc_addWeapon .

 

This works but I do not wish create a script for each and every bad dude I want pulling this stunt. So I want one script that I can define the badguy in the trigger activation and then run the script giving that guy the weapon. So I can easily set up triggers doing this for each bad dude. Low level of coding other than some QBasic back in high school and having a hard time figuring out how to define a variable in a trigger and then in that simple script.

Share this post


Link to post
Share on other sites

What makes the trigger activate? There maybe a better way to handle the whole thing like an eventHandler or scriptedEventHandler?

Share this post


Link to post
Share on other sites
1 hour ago, Larrow said:

What makes the trigger activate? There maybe a better way to handle the whole thing like an eventHandler or scriptedEventHandler?

Blufor presence

Share this post


Link to post
Share on other sites

So is it an actual set area OR is it more when a West player gets close to a badguy?

If the second then you could make a function that spawns a trigger that is attached to the badguy, so where ever he goes it is an area around him, if a West player gets near him he pulls out a weapon. Is this the kind of thing you are going for?

Try this in a blank mission with just you(west) and an AI(east) and place the following in its init.

_nul = [ this, 5 ] spawn {
	params[ "_badGuy", "_distance" ];
	
	removeAllWeapons _badGuy;
	{
		_badGuy removeMagazine _x
	}forEach magazines _badGuy;
	_badGuy allowFleeing 0;
	
	_trg = createTrigger[ "EmptyDetector", getPos _badGuy, false ];
	_trg setTriggerArea[ _distance, _distance, 0, false, 100 ];
	_trg setTriggerActivation [ "WEST", "PRESENT", true ];
	_trg setTriggerStatements [
		"this",
		format[ "
			_badGuy = '%1' call BIS_fnc_objectFromNetId;
			 [ _badGuy, 'hgun_Pistol_01_F', 1, '10Rnd_9x21_Mag' ] call BIS_fnc_addWeapon;
		", _badguy call BIS_fnc_netId ],
		format[ "
			_badGuy = '%1' call BIS_fnc_objectFromNetId;
			_badGuy removeWeapon 'hgun_Pistol_01_F';
			_badGuy removeMagazine '10Rnd_9x21_Mag';
		", _badguy call BIS_fnc_netId ]
	];
	_trg attachTo [ _badGuy ];
};

When ever you get near him he will pull out the pistol, when you move out of the trigger the gun is removed.

If this is the kind of thing you are going for you then need to make this into a function OR split into a separate file, that you either call/exevm from each badGuy. Means there is no need to place triggers as the code automatically creates one for each badGuy when called from their init.

  • Like 3

Share this post


Link to post
Share on other sites
8 hours ago, Larrow said:

So is it an actual set area OR is it more when a West player gets close to a badguy?

If the second then you could make a function that spawns a trigger that is attached to the badguy, so where ever he goes it is an area around him, if a West player gets near him he pulls out a weapon. Is this the kind of thing you are going for?

Try this in a blank mission with just you(west) and an AI(east) and place the following in its init.


_nul = [ this, 5 ] spawn {
	params[ "_badGuy", "_distance" ];
	
	removeAllWeapons _badGuy;
	{
		_badGuy removeMagazine _x
	}forEach magazines _badGuy;
	_badGuy allowFleeing 0;
	
	_trg = createTrigger[ "EmptyDetector", getPos _badGuy, false ];
	_trg setTriggerArea[ _distance, _distance, 0, false, 100 ];
	_trg setTriggerActivation [ "WEST", "PRESENT", true ];
	_trg setTriggerStatements [
		"this",
		format[ "
			_badGuy = '%1' call BIS_fnc_objectFromNetId;
			 [ _badGuy, 'hgun_Pistol_01_F', 1, '10Rnd_9x21_Mag' ] call BIS_fnc_addWeapon;
		", _badguy call BIS_fnc_netId ],
		format[ "
			_badGuy = '%1' call BIS_fnc_objectFromNetId;
			_badGuy removeWeapon 'hgun_Pistol_01_F';
			_badGuy removeMagazine '10Rnd_9x21_Mag';
		", _badguy call BIS_fnc_netId ]
	];
	_trg attachTo [ _badGuy ];
};

When ever you get near him he will pull out the pistol, when you move out of the trigger the gun is removed.

If this is the kind of thing you are going for you then need to make this into a function OR split into a separate file, that you either call/exevm from each badGuy. Means there is no need to place triggers as the code automatically creates one for each badGuy when called from their init.

 

Yes, I want blufor to walk into a room with multiple targets and have to PID enemy from civilian. Adding a twist I want a badguy to appear as civilian at first glance but then pull out a weapon. 

I'll give this a try and report back!

 

Thanks

Share this post


Link to post
Share on other sites

Works perfectly!  

 

Thanks so much!

 

Is there a way to make it random? So sometimes the "badguy" doesn't even attempt to pull out a weapon?  I'm trying to make the mission as dynamic, random, and replayble as possible so trying to mix things up whenever and wherever possible. 

Share this post


Link to post
Share on other sites

@Larrow I'm not familiar with bis_fnc_netId and objectFromNetId. Why and how are you using them here? On my mind, _badGuy comes from <this> in init field of the unit, so, should be enough for adding or removing a weapon. On the other hand, I'd write the trigger (so, all the code) for server only. BLUFOR PRESENT will work anyway. Thanks.

  • Like 1

Share this post


Link to post
Share on other sites
1 hour ago, pierremgi said:

I'm not familiar with bis_fnc_netId and objectFromNetId. Why and how are you using them here?

BI's NetID functions are compatible with SP the command equivalents are not.

1 hour ago, pierremgi said:

On my mind, _badGuy comes from <this> in init field of the unit, so, should be enough for adding or removing a weapon.

Trigger statements are STRING. Formatting an OBJECT into a STRING does not work, so instead format in the NetID(which is a STRING) then inside the statement turn it back into an OBJECT.

2 hours ago, pierremgi said:

I'd write the trigger (so, all the code) for server only

For testing it was good enough, but yes the code should be server only.

3 hours ago, MANTIA said:

Is there a way to make it random?

Sure, just change the trigger condition to

_trg setTriggerStatements [
		"this && random 1 >= 0.5",

so 50% of the time, for example.

  • Like 2

Share this post


Link to post
Share on other sites
25 minutes ago, Larrow said:

BI's NetID functions are compatible with SP the command equivalents are not.

Trigger statements are STRING. Formatting an OBJECT into a STRING does not work, so instead format in the NetID(which is a STRING) then inside the statement turn it back into an OBJECT.

For testing it was good enough, but yes the code should be server only.

Sure, just change the trigger condition to


_trg setTriggerStatements [
		"this && random 1 >= 0.5",

 

 

so 50% of the time, for example.

Tried implementing this, and also lowering down to 0.1 but it seems to still happen 100% of the time.  Also I changed the trigger activation repeating to false to make sure it just wasn't firing over and over until he did pull out the weapon .

 

Also how would I make this server only?

Share this post


Link to post
Share on other sites

OK, tks. I discover the netId. Usually, I skipped this kind of tool with global variable (here I'd name and play with a badGuy instead of _badGuy). Interesting anyway.

Share this post


Link to post
Share on other sites
On 12/25/2017 at 9:49 PM, pierremgi said:

Usually, I skipped this kind of tool with global variable (here I'd name and play with a badGuy instead of _badGuy)

And then you would be stuck with the exact problem @MANTIA came here to resolve...

On 12/25/2017 at 2:14 AM, MANTIA said:

but I do not wish create a script for each and every bad dude I want pulling this stunt. So I want one script that I can define the badguy in the trigger activation and then run the script giving that guy the weapon. So I can easily set up triggers doing this for each bad dude.

...having a global variable for each and every bad guy would make having a script that could be reusable for # bad guys problematic (or at least leave you having to upkeep an array of all possible units ). Plus its always a good idea to try and code with as few global variables as possible.

 

On 12/25/2017 at 9:25 PM, MANTIA said:

make sure it just wasn't firing over and over

Your right that will just cause the trigger to keep toggling. Hoping to throw a quick fix never works well :smile_o:

Anyway separated it back out from a test init and added server only (changed to badGuy locality as removeWeapon/Magazine are AL, just incase) check.

BADCIVI.sqf

//BADCIVI.sqf
params[ "_badGuy", "_distance", "_percentChance" ];

if !( local _badGuy ) exitWith {};

_percentChance = _percentChance / 100;

removeAllWeapons _badGuy;
{
	_badGuy removeMagazine _x
}forEach magazines _badGuy;
_badGuy allowFleeing 0;

_trg = createTrigger[ "EmptyDetector", getPos _badGuy, false ];
_trg setTriggerArea[ _distance, _distance, 0, false, 100 ];
_trg setTriggerActivation [ "WEST", "PRESENT", true ];
_trg setTriggerStatements [
	"this",
	format[ "
		_badGuy = '%1' call BIS_fnc_objectFromNetId;
		if ( !isnull _badGuy && { alive _badGuy && { random 1 < %2 }} ) then {			
			[ _badGuy, 'hgun_Pistol_01_F', 1, '10Rnd_9x21_Mag' ] call BIS_fnc_addWeapon;
		};
	", _badguy call BIS_fnc_netId, _percentChance ],
	format[ "
		_badGuy = '%1' call BIS_fnc_objectFromNetId;
		if ( !isnull _badGuy && { alive _badGuy && { _badGuy hasWeapon 'hgun_Pistol_01_F' }} ) then {
			_badGuy removeWeapon 'hgun_Pistol_01_F';
			_badGuy removeMagazine '10Rnd_9x21_Mag';
		};
	", _badguy call BIS_fnc_netId ]
];
_trg attachTo [ _badGuy ];

Then in each units init that you want to be a possible badGuy

//[ unit, detection distance, percent chance to pull weapon ]
_nul = [ this, 5, 50 ] execVM "BADCIVI.sqf";

 

  • Like 1

Share this post


Link to post
Share on other sites
6 hours ago, Larrow said:

And then you would be stuck with the exact problem @MANTIA came here to resolve...

Sorry for my bad reading. You can also add a variable to the trigger, then:

Spoiler

0 = [this, 10] call {
    params["_unit","_distance"];
    if !( local _unit) exitWith {};
    removeAllWeapons _unit;
   {
      _unit removeMagazine _x
   } forEach magazines _unit;
   _unit allowFleeing 0;
   _trg = createTrigger [ "EmptyDetector", getPos _unit, false ];
   _trg setTriggerArea[ _distance, _distance, 0, false, 100 ];
   _trg setTriggerActivation [ "WEST", "PRESENT", true ];
   _trg attachTo [ _unit ];
   _trg setVariable ["badGuy",_unit];
   _trg setTriggerStatements [
      "this",
      " _unit = thisTrigger getVariable 'badGuy';
        if ( !isnull _unit && alive _unit) then {      
          [ _unit, 'hgun_Pistol_01_F', 1, '10Rnd_9x21_Mag' ] call BIS_fnc_addWeapon;
       };
     ",
     " _unit = thisTrigger getVariable 'badGuy'; if ( !isnull _unit &&  alive _unit &&  _unit hasWeapon 'hgun_Pistol_01_F' ) then {
         _unit removeWeapon 'hgun_Pistol_01_F';
         _unit removeMagazine '10Rnd_9x21_Mag';
      };
    "
  ];
};

 

  • Like 2

Share this post


Link to post
Share on other sites
13 hours ago, Larrow said:

And then you would be stuck with the exact problem @MANTIA came here to resolve...

...having a global variable for each and every bad guy would make having a script that could be reusable for # bad guys problematic (or at least leave you having to upkeep an array of all possible units ). Plus its always a good idea to try and code with as few global variables as possible.

 

Your right that will just cause the trigger to keep toggling. Hoping to throw a quick fix never works well :smile_o:

Anyway separated it back out from a test init and added server only (changed to badGuy locality as removeWeapon/Magazine are AL, just incase) check.

BADCIVI.sqf


//BADCIVI.sqf
params[ "_badGuy", "_distance", "_percentChance" ];

if !( local _badGuy ) exitWith {};

_percentChance = _percentChance / 100;

removeAllWeapons _badGuy;
{
	_badGuy removeMagazine _x
}forEach magazines _badGuy;
_badGuy allowFleeing 0;

_trg = createTrigger[ "EmptyDetector", getPos _badGuy, false ];
_trg setTriggerArea[ _distance, _distance, 0, false, 100 ];
_trg setTriggerActivation [ "WEST", "PRESENT", true ];
_trg setTriggerStatements [
	"this",
	format[ "
		_badGuy = '%1' call BIS_fnc_objectFromNetId;
		if ( !isnull _badGuy && { alive _badGuy && { random 1 >= %2 }} ) then {			
			[ _badGuy, 'hgun_Pistol_01_F', 1, '10Rnd_9x21_Mag' ] call BIS_fnc_addWeapon;
		};
	", _badguy call BIS_fnc_netId, _percentChance ],
	format[ "
		_badGuy = '%1' call BIS_fnc_objectFromNetId;
		if ( !isnull _badGuy && { alive _badGuy && { _badGuy hasWeapon 'hgun_Pistol_01_F' }} ) then {
			_badGuy removeWeapon 'hgun_Pistol_01_F';
			_badGuy removeMagazine '10Rnd_9x21_Mag';
		};
	", _badguy call BIS_fnc_netId ]
];
_trg attachTo [ _badGuy ];

Then in each units init that you want to be a possible badGuy


//[ unit, detection distance, percent chance to pull weapon ]
_nul = [ this, 5, 50 ] execVM "BADCIVI.sqf";

Can't thank you enough for the help!  I'll be contributing to your beer fund!

 

Share this post


Link to post
Share on other sites

This doesn't appear to be working on a dedicated server.  I've spent the last few days trying to troubleshoot myself but with no luck.  Any ideas?

Share this post


Link to post
Share on other sites

Should work fine. I even tested on a dedicated before posting my previous reply and is what made me change the code to test the units locality rather than isServer.

Are you sure your units are not changing locality, e.g being put in a players group or handed off to a headless client?

The commands used in BIS_fnc_addWeapon (addWeapon/Magazine) and the trigger deactivation statement (removeWeapon/Magazine) are AL (Argument Local - argument is the unit the commands are being run on ). If the script is running on a different machine to where the unit is local then nothing will seem to happen.

 

Share this post


Link to post
Share on other sites

This function is very interesting for a hostage mission with an enemy infiltrated in the middle of the hostages, but in this case the weapon would not be hidden.


I used the script posted here by Larrow, but I made a modification and it worked here the way I wanted it.

 

So I did so, put three suspects and each of them gave the name of "badguy1", "badguy2" and "badguy3".

 

file init.sqf, here will make the script run on one of the suspect randomly.

 

private _bad = selectRandom [badguy1, badguy2, badguy3];

_null = [ _bad, 10, 0 ] execVM "BadGuy.sqf";

 


Inside the file "badguy.sqf"

//I used the script posted by Larrow, but I made a modification not to hide the weapon. Link of the forum with the script posted by him. Every merit by Larrow.   >> https://forums.bistudio.com/forums/topic/212617-have-ai-pull-weapon-when-trigger-fired/?do=findComment&comment=3258848
//BADGUY.sqf 

params[ "_badGuy", "_distance", "_percentChance" ];

if !( local _badGuy ) exitWith {};

_percentChance = _percentChance / 100;

removeAllWeapons _badGuy;
{
	_badGuy removeMagazine _x
}forEach magazines _badGuy;
_badGuy allowFleeing 0;

_trg = createTrigger[ "EmptyDetector", getPos _badGuy, false ];
_trg setTriggerArea[ _distance, _distance, 0, false, 100 ];
_trg setTriggerActivation [ "WEST", "PRESENT", true ];
_trg setTriggerStatements [
	"this",
	format[ "
		_badGuy = '%1' call BIS_fnc_objectFromNetId;
		if ( !isnull _badGuy && { alive _badGuy && { random 1 >= %2 }} ) then {			
			[ _badGuy, 'hgun_Rook40_F', 2, '16Rnd_9x21_Mag' ] call BIS_fnc_addWeapon;
		};
	", _badguy call BIS_fnc_netId, _percentChance ],
	format[ "
		_badGuy = '%1' call BIS_fnc_objectFromNetId;
		if ( !isnull _badGuy && { alive _badGuy && { _badGuy hasWeapon 'hgun_Rook40_F' }} );
	", _badguy call BIS_fnc_netId ]
];
_trg attachTo [ _badGuy ];


*

Just to clarify, I do not understand anything of script, so I me fun for Dr. Frankstein with script that I find, I get a line here and another line there and see if it works and I get what I look for, sometimes it works, sometimes it's not. I come here to ask how it is done.

 

And in this case I got what I was looking for, but it might have a simpler shape that I still do not know.

 

Neither English I understand, I use the Chrome browser to understand English a little.

This automatic translator has helped me very.

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

×