Jump to content
Sign in to follow this  
Vertigas

Enemy Detection

Recommended Posts

I'm having some issues with over-sensitive detection of other units. I'm setting up a scenario where the initial task is to meet with an undercover agent, but once the player gets close to the meeting area they discover that the agent has been found out and captured, which should result in changing the "meet with" task to a "rescue" task. The problem I'm having is that the detection triggers fire off way before the player should actually be able to lay eyes on the hostage or any of the enemy units.

I've tried the things outlined here: http://forums.bistudio.com/showthread.php?152042-Simple-detection-trigger-help-requested&highlight=detection

And with enough tweaks to the trigger area and and such I can get it to an almost acceptable level, but still in too many cases the units are detected when not actually visible. What I really want is the ability to only make the task switch when the player has actually laid eyes on the captured agent. I see there are some BIS_fnc* functions that deal with vectors and object intersections, but I've not been able to get those to work.

So how is fine scale detection like this normally handled?

Share this post


Link to post
Share on other sites

You could use these:

http://community.bistudio.com/wiki/lineIntersects

http://community.bistudio.com/wiki/terrainIntersect

Here is an example, using generic Unit1 and Unit2, to determine if Unit1 can see Unit2:

if (!(terrainIntersect [(eyePos Unit2), (eyePos Unit1)]) && {!(lineIntersects [(eyePos Unit1), (eyePos Unit2), Unit1, Unit2])}) then {
   // Unit1 can see Unit2...
};

Just put that condition in a trigger, but you might also want to test if Unit1 is facing Unit2 (that requires some math).

Share this post


Link to post
Share on other sites
Just put that condition in a trigger, but you might also want to test if Unit1 is facing Unit2 (that requires some math).

Theres a function that takes care of it for you BIS_fnc_inAngleSector

//view angle is 30*2=60 degrees
[getposatl unit1,getdir unit1,30,getposatl unit2] call BIS_fnc_inAngleSector

Share this post


Link to post
Share on other sites

The inAngleSector function looks promising (combined with Zonophon's sample). I was trying to do that sort of thing with vectors and lineIntersectsWith before. I'll give it a go and report back. Thank you both.

Share this post


Link to post
Share on other sites

Ugh, posted a nice long response, said it saved, but it never showed up. So let's try this again I guess...

I found variations of this in a couple of threads. If you go into 3rd person you can see that it draws a line from the player's eye position out 5 meters. It mostly follows the eye direction when using free look, but eyeDirection has some issues when turning the head past 60 degrees or so - it stops reporting angles past that. Also some issues when aiming up or down, rather than free look.

[] spawn {
 while {true} do {
   sleep 0.03;
   _start = eyepos player;
   _direction = [(eyeDirection player), 5] call BIS_fnc_vectorMultiply;
   _end = [_start, _direction] call BIS_fnc_vectorAdd;
   drawLine3D [ ASLtoATL _start, ASLtoATL _end, [1,0,0,1]];
   hint str (lineIntersectsWith [_start, _end]);
 };
};

The more important problem is that lineIntersectsWith doesn't detect infantry units. So even though we can do a raycast, we can't see when it's hitting infantry. There is a bug report for this, but I lost the link since it was in my last post that didn't post. If that issue were fixed, and eyeDirection were fixed, we'd be in business, but alas.

The problem with using the inAngleSector thing is that it is only really doing things in 2D - it disregards whether or not the player is looking up or down. But it seems to be the best workable option. So this is what I came up with based on the things you guys suggested...

/*
 Purpose: Returns true if target is in viewer's line of sight.
 Parameters: <viewer object>, <target object>, <minimum distance>, [<knows about value>]
 Result: boolean
*/

WRS_IsLineOfSight = 
{
 private ["_result", "_sectorAngle", "_targetAdjustment", "_parameterCount", "_viewer", 
          "_target", "_minimumDistance", "_knowsAboutLevel", "_eyePosition", "_targetPosition", 
          "_distance2", "_eyeVector", "_eyeDirection"];

 _result = false;
 _sectorAngle = 10;
 _targetAdjustment = -1.5;

 _parameterCount = count _this;
 _viewer = _this select 0;
 _target = _this select 1;
 _minimumDistance = _this select 2;

 _knowsAboutLevel = 0;
 if (_parameterCount > 3) then { _knowsAboutLevel = _this select 3 };


 // calculate squared distance between viewer and target
 _eyePosition = eyePos _viewer;
 _targetPosition = eyePos _target;
 _distance2 = _eyePosition distanceSqr _targetPosition;


 // adjust the target position down a bit, so we have to see a bit more of the body before a hit
 _targetPosition set [2, (_targetPosition select 2) + _targetAdjustment];


 // check for line of sight if within minimum distance
 if (_distance2 < _minimumDistance * _minimumDistance) then
 {
   // get viewer look vector, and convert to degrees
   _eyeVector = eyeDirection _viewer;
   _eyeDirection = ((_eyeVector select 0) atan2 (_eyeVector select 1));

   if ([_eyePosition, _eyeDirection, _sectorAngle, _targetPosition] call BIS_fnc_inAngleSector) then
   {
     if ((_viewer knowsAbout _target) >= _knowsAboutLevel) then
     {
       if (!lineIntersects[_eyePosition, _targetPosition, _viewer, _target]) then
       {
         if (!terrainIntersectASL[_eyePosition, _targetPosition]) then
         {
           _result = true;
         };
       };
     };
   };
 };

 _result
};

And to use it...

[] spawn 
{
 while {true} do 
 {
   if ([player, testGuy, 30, 4] call WRS_IsLineOfSight) then
   {
     hintSilent "In Line of Sight";
   }
   else
   {
     hintSilent "";
   };

   sleep 0.1;
 };
};

It works fairly well - better than just using knowsAbout anyway. It sometimes has an issue with tall grass, where it still gives a detection even though you can't see the unit, but it's working well enough for my purposes. You can adjust the _targetAdjustment value to move the line intersect position close to the feet, so more of the body must be visible before it's in line of sight.

I'll likely create another function that uses this to detect line of sight, and then requires the player to look at the target for a couple of seconds before considering it a detection. Basically creating a custom "knows about" system I guess.

Thanks to you guys for pointing me in the right direction.

Edited by Vertigas
typos and grammar

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  

×