Jump to content
barccy

knowsAbout value display

Recommended Posts

Rozek Poland showed me a way to display the knowsAbout value an AI has of the player, but it only works in OFPR / ARMA CWA.
ARMA 3 says the On Activation field line contains an invalid number in the expression. Can someone alter the grammar so that it works in A3? 

Units: 
west init : t1=true

east name : e1


trigger:

Condition : t1
On Activation : player globalChat format [{knowsAbout:   %1},e1 knowsAbout vehicle player]; t1=false
On Deactivation : t1=true

Share this post


Link to post
Share on other sites
8 minutes ago, barccy said:

On Activation : player globalChat format [{knowsAbout:   %1},e1 knowsAbout vehicle player]; t1=false

 

player globalChat format ["knowsAbout:   %1",e1 knowsAbout vehicle player]; t1=false

  • Like 2
  • Thanks 1

Share this post


Link to post
Share on other sites

Is this in single player? Because this might not work on a server.

 

Share this post


Link to post
Share on other sites
3 hours ago, Tankbuster said:

Is this in single player? Because this might not work on a server.

 

1 thing I wanted to check was testable in single player: how the AI detects people between games. ex. : ARMA 3 , ARMA CWA .
The 2nd thing was to see if radio voice volume in TFAR and ACRE had any or significant effects on how the AI could detect players by hearing them. That needs it to work in MP. I haven't personally tried it, but can in the future or ask if others have. 
Do you know a different way that would work in MP?

Share this post


Link to post
Share on other sites

The 2 videos you post show expected behaviour of AI as documented on the Biki.

The reason it might get complicated in multiplayer is that  where _who knowsAbout _target , who (the AI) must be local, so in your example, you must run where the AI is local and if that is on a dedicated server, the command player cannot work, as player doesn't exist there.

I don't use TFAR or ACRE, others might have more information than me.

  • Like 3

Share this post


Link to post
Share on other sites

To be honest, I haven't used it before so I can't really know anything about possible limitations, but from the BIKI it seems that you could possibly use targetKnowledge or even nearTargets. I don't have the ability to test the commands now so I can't really provide too much help here except some speculative implemetations. I don't have too much time at the moment so I'll try to fix something with those commands when I find some time.

 

Please let us know if any of those worked out for you and if possible provide your solution for other people who might have the same or similar issues.

  • Like 2

Share this post


Link to post
Share on other sites

EDIT: I apologise in advance for the long post. It contains many examples which could possibly be shortened but I decided to leave them as is.

 

Hey, I found some time to improvise on a possible solution with the commands mentioned above. I want to stress again the fact that I haven't used any of the commands I suggest here, so all code presented is based on the BIKI pages and the intended use of the commands, as they are presented in their explanation/example pages. So, please treat the code with caution and if unsure assume it is not working as intended (this means... test, test and test again).

 

Before starting, I would like to mention a couple of things about the code. I will use some variables which I assume you will have available in your code. Such variables are the soldier whose knowledge about other units you want to check.

 

So, starting with targetKnowledge, a possible solution to your problem would be

// private _soldier: The unit whose knowledge to check

// Get the _soldier's side to use below (to avoid constantly calling the command)
private _soldSide = side _soldier;

// Run forever... for testing only
while{true} do {
	{
		private _trgInfo = _soldier targetKnowledge _x; // Get the knowledge of the target

		if(!((_trgInfo select 4) isEqualTo _soldSide)) then { // Check if the unit is NOT in the same faction with the _soldier
			systemChat (str (_trgInfo select 1)); // Print whether the unit is known to the _soldier
		};
	} forEach (allUnits - _soldier); // Check against all units but the _soldier

	// Sleep a bit to save some CPU
	sleep 5;
};

Of course, you can refrain from using forEach (which can be quite CPU intensive) if you know exactly against who you would like to check. For example, if you have the _soldier mentioned above and you also have the name of the unit to check against you could do something like

// private _soldier: The unit whose knowledge to check
// private _unit: The unit to check against

// Run forever... For testing only
while{true} do {
	private _trgInfo = _soldier targetKnowledge _unit; // Get the knowledge of the target
	systemChat (str (_trgInfo select 1)); // Print whether the _unit is known to the _soldier

	// Sleep to save some CPU
	sleep 5;
};

 

Next command is nearTargets. You could possibly use it to get whether one unit is recognised by the enemy or not. I am not sure how this is calculated so it may or may not be useful to you. An example could look like

// private _soldier: The unit whose knowledge to check

// Get the _soldier's side to use below (to avoid constantly calling the command)
private _soldSide = side _soldier;

// Run forever... for testing only
while{true} do {
	private _targets = _soldier nearTargets viewDistance; // Get all targets that are up to the view distance

	{
		// Check the subjective cost which is positive for enemies
		if((_x select 3) > 0} then {
			systemChat format["Enemy soldier found at coordinates: %1", _targets select 0]; // Inform of enemy's location
		};
	} forEach _targets;

	// Sleep a bit to save some CPU
	sleep 5;
};

Alternatively, you could one-line the forEach command like (not a big fan of it but it's up to you to decide)

// private _soldier: The unit whose knowledge to check

// Get the _soldier's side to use below (to avoid constantly calling the command)
private _soldSide = side _soldier;

// Run forever... for testing only
while{true} do {
	{
		// Check the subjective cost which is positive for enemies
		if((_x select 3) > 0} then {
			systemChat format["Enemy soldier found at coordinates: %1", _targets select 0]; // Inform of enemy's location
		};
	} forEach (_soldier nearTargets viewDistance); // Go through all targets that are up to the view distance

	// Sleep a bit to save some CPU
	sleep 5;
};

From what I found on BIKI, the big drawback with this command is that you may get inaccurate information, as what is returned is what the unit knows. Now, this may be closer to what you want since you say that you would like to understand how and/or when an AI unit gets knowledge of other units. Additionally, this command does not allow to check only one unit so you'll have to do something like the following if you want to check only one unit

// private _soldier: The unit whose knowledge to check
// private _unit: The unit to check against

// Run forever... For testing only
while{true} do {
	private _targets = _soldier nearTargets viewDistance; // Get the targets up to the view distance
	private _unitIdx = _targets findIf{(_x select 0) inArea [getPos _unit, 2.5, 2.5, 0, false]}; // Find the unit you are interested in
                                                                                                     // Check if perceived position is in area
                                                                                                     // of a circle with 5 metres diameter around
                                                                                                     // the actual position of the unit. If this is
                                                                                                     // true then this is the unit you want
	if(_unitIdx != -1) then {
		systemChat "Unit found!";
	};

	// Sleep to save some CPU
	sleep 5;
};

Now, at least to my eyes, this is "not very nice" (awful is the right word to use here). I am not sure whether this check is more efficient than going through all the targets. Alternatively, you could filter out the enemies first and then perform this test (omitting the comments to make it more readable)

// private _soldier: The unit whose knowledge to check
// private _unit: The unit to check against

// Run forever... For testing only
while{true} do {
	private _enemies = _soldier nearTargets viewDistance; // Get the targets up to the view distance
	_enemies = _enemies select {(_x select 3) > 0}; // Use the same array for convenience and get the enemies only

	private _unitIdx = _enemies findIf{(_x select 0) inArea [getPos _unit, 2.5, 2.5, 0, false]}; // Find the unit you are interested in

	if(_unitIdx != -1) then {
		systemChat "Unit found!";
	};

	// Sleep to save some CPU
	sleep 5;
};

===================================================================

EDIT: After having another look, this second implementation, most probably, is slower than the first since you have to traverse the array twice. Haven't checked so I can't really say, but it seems like that to me.

===================================================================

Or, in the two solutions above you could possibly get the index of the unit and use it to extract more information about the unit (from the _enemies array).

 

Finally, I found another command, targetsQuery, which could possibly be of help here. The advantage of this command is that it also returns the units as objects which you could possibly use somehow. So a solution with this command could look like

// private _soldier: The unit whose knowledge to check

// Get the side of the unit to avoid constantly calling the command
private _soldSide = side _soldier;

// Run forever... for testing only
while{true} do {
	private _knownUnits = _soldier targetsQuery[objNull, sideUnknown, "", [], 0]; // Get all known units

	{
		if(!((_x select 2) isEqualTo _soldSide)) then {
			systemChat format["Enemy soldier is found at coordinates (2D): %1, _x select 4];
		};
	} forEach _knownUnits; // Go through all the known units

	// Sleep a bit to save some CPU
	sleep 5;
};

As before, you could possibly one-line the array in forEach command like

// private _soldier: The unit whose knowledge to check

// Get the side of the unit to avoid constantly calling the command
private _soldSide = side _soldier;

// Run forever... for testing only
while{true} do {
	{
		if(!((_x select 2) isEqualTo _soldSide)) then {
			systemChat format["Enemy soldier is found at coordinates (2D): %1, _x select 4];
		};
	} forEach (_soldier targetsQuery[objNull, sideUnknown, "", [], 0]); // Go through all the known units

	// Sleep a bit to save some CPU
	sleep 5;
};

Alternatively (and possibly a bit more efficiently), you could filter the units returned by the command if you know the side you are interested in. This would look like (with the one-lined example)

// private _soldier: The unit whose knowledge to check

// Run forever... for testing only
while{true} do {
	{
		systemChat format["Enemy soldier is found at coordinates (2D): %1, _x select 4];
	} forEach (_soldier targetsQuery[objNull, west, "", [], 0]); // Go through all known units of west (BLUFOR) side

	// Sleep a bit to save some CPU
	sleep 5;
};

Of course, if you want exactly one unit you could go by (again with the one-lined example)

// private _soldier: The unit whose knowledge to check
// private _unit: The unit to check against

// Run forever... for testing only
while{true} do {
	private _knownUnits = _soldier targetsQuery[objNull, west, "", getPos _unit, 0]; // Get west units 200m around the _unit
	private _unitIdx = _knownUnits findIf{_x isEqualTo _unit};
	
	if(_unitIdx != -1) then {
		systemChat "Unit found!";
	};

	// Sleep a bit to save some CPU
	sleep 5;
};

I just ran out of examples here 😂. Nevertheless, please note again that those snippets may produce a whole bunch of errors, may not work as intended, may not be useful to you and may have a whole lot more of issues (if, for example, I misunderstood their use or even the locality of theri arguments etc.). So, go ahead and test, test and test some more.

 

Hopefully, you will be able to see in advance which commands and which examples may be useful to you and in what way. This will save a lot of time from testing and trying out commands. If you manage to find a good solution to your problem, please take some time to post it here for the benefit of other users.

 

Finally, if you find yourself in need of more help do not hesitate to post here again with your problem.

 

Have fun, stay safe and ArmA a lot.

Edited by ZaellixA
Added comment about one of the solutions
  • Like 1

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

×