Jump to content

Recommended Posts

Hi all,

 

I've made a script to check the visibility of positions on the map. 

 

An example mission is here I hope I've done this right.

 

1 min Video

 

And the code is here for those interested.

/* 
	CheckVisibility.sqf
	Author: Atmo
	Date: April 2019
	Version: 1.0
	
	Params : None
	
	Description: Checks the visibility of a 2000m square around the position left clicked on in the map. 
				 It checks a position 2m off the ground to the test position.
				 Checks 30m squares - could change the size if you want but it could get intensive...
	
	Running script toggles activation of the eventHandlers so running once turns it on, running it again stops it.
		
	Use: 	single left click (Default mode): - shows non-visible areas as red
			pressing 'alt' and left clicking: - shows visible areas in green.
	
	Some examples:
		1) From an action in an players init
			
			this addAction ["Check Visibility", "fn_CheckVisibility.sqf"];
			
		2) compile the function from the description.ext and then call it
		
			- I'll let you do that.
	
*/
if (!hasInterface) exitWith {["fn_CheckVisibility only runs on client"] call BIS_fnc_error};

// Every time script runs toggle eventHandlers
private _EHs = missionNamespace getVariable [format["BIS_stackedEventHandlers_%1", "onMapSingleClick"], []];
if (_EHs findIf {(_x select 0) isEqualTo "Atmo_CV_EH"} == -1) then {

	["Atmo_CV_EH", "onMapSingleClick", {
		// _pos, _shift, _alt are parameters of onMapSingleClick EH
		private _positions = []; 	// Array of positions tested
		private _size = 30;			// Size of squares (if you change this also change _size in Draw EH)
		
		// Set the drawing method for the ctrlEventHandler
		missionNamespace setVariable ["Atmo_CV_mode", _alt];
		
		// Convert _pos to ASL + 2m
		private _origin = (ATLToASL _pos) vectorAdd [0,0, 2];
		
		for "_i" from -1000 to 1000 step _size do {
			for "_j" from -1000 to 1000 step _size do {
				_testPos = ATLToASL (_pos VectorAdd [_i, _j, 2]);
				
				_visibility = 0;
				
				// Cast a line to the point
				_intersectPos = lineIntersectsSurfaces [_origin, _testpos, player, objNull, true, 1, "VIEW", "FIRE"] select 0 select 0;
				if (isNil "_intersectPos") then {
					// It didn't intersect anything = it is visible 
					_visibility = 1;
				} else {
					// The line hit something - is thing it hit in the area we are testing?
					if (_intersectPos inArea [_testPos, _size, _size, 0, true, -1]) then {_visibility = 1};
				};
				if (_alt) then {
					if (_visibility == 1) then {
						_positions append [_testPos];
					};
				} else {
					if (_visibility == 0) then {
						_positions append [_testPos];
					};
				};
			};
		};
		missionNamespace setVariable ["Atmo_CV_Positions", _positions];
			
	}] call BIS_fnc_addStackedEventHandler;


	// Add draw EventHandler to the map display - Oooo, er, should I use displayAddEventHandler?
	private _map = findDisplay 12 displayCtrl 51;
	private _id = _map ctrlAddEventHandler ["Draw",
	{
		params ["_control"];
		// Get the mode of drawing - false: 'alt' wasn't pressed show not visible in red, true: show visible in green
		private _mode = missionNamespace getVariable ["Atmo_CV_mode", false];
		private _rgba = [[0.5,0,0,0.8], [0,0.5,0,0.8]] select _mode; 
		private _positions = missionNamespace getVariable ["Atmo_CV_Positions", []]; 
		private _size = 15;
		{
			_control drawRectangle [_x, _size, _size, 0, _rgba, "#(rgb,1,1,1)color(1,1,1,1)"] ;	
		} forEach _positions;
		private _pos = missionNamespace getVariable ["Atmo_CV_cursorPos", [0,0]];
		_control drawIcon ["#(rgb,1,1,1)color(1,1,1,1)", [0,0,1,1], _pos, 0, 0, 0, "Check Visibility (click +/- alt)"];
	}];
	// Save the EH id
	missionNamespace setVariable ["Atmo_CV_DrawEHid", _id];

	_id = _map ctrlAddEventHandler ["MouseMoving",
	{	
		params ["_control", "_xPos", "_yPos", "_mouseOver"];
		_pos = _control posScreenToWorld [_xPos + 0.1, _yPos - 0.1];
		missionNamespace setVariable ["Atmo_CV_cursorPos", _pos];
	}];
	// Save the EH id
	missionNamespace setVariable ["Atmo_CV_MouseMoveEHid", _id];
	
} else {
	// The event handler is already there - delete them all
	
	//remove onMapSingleClick
	private _removed = ["Atmo_CV_EH", "onMapSingleClick"] call BIS_fnc_removeStackedEventHandler;
	
	// remove Draw eventHandler on the map
	private _map = findDisplay 12 displayCtrl 51;
	_map ctrlRemoveEventHandler ["Draw", missionNamespace getVariable "Atmo_CV_DrawEHid"];
	_map ctrlRemoveEventHandler ["MouseMoving", missionNamespace getVariable "Atmo_CV_MouseMoveEHid"];
	
	missionNamespace setVariable ["Atmo_CV_Positions", []];
};

(Nice) Comments appreciated - scripters let me know if you see any glaring errors!

 

Atmo

  • Like 5

Share this post


Link to post
Share on other sites

neat and looks like it could work well.

idk if lineIntersect is faster than checkVisibility. what i know is that checkVisibility is newer. You could test it against each other.

Share this post


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

neat and looks like it could work well.

idk if lineIntersect is faster than checkVisibility. what i know is that checkVisibility is newer. You could test it against each other.

There's not much between them in terms of pure performance.
Lineintersects is limited to 1000m and doesn't work underwater and returns a bool. Checkvisibilty isn't restricted like this but is affected by smoke and rain.

 

At longer ranges and in more complicated scenes, Checkvisibilty is slower, but the difference is around the order of 0.0x milliseconds.
 

  • Like 1

Share this post


Link to post
Share on other sites

I used lineIntersectsSurfaces because it returns a position, so if the ray hits something within the area you are testing you can say it is visible. It seems pretty fast altogether. The frame rate drop comes with more drawRectangles….

 

Atmo

Share this post


Link to post
Share on other sites

I really like it! Reminds me of the line-of-sight checks in sims like Steelbeasts or Steel Armor: Blaze of War.

Share this post


Link to post
Share on other sites

 

On 4/20/2019 at 1:59 PM, atmo said:

let me know if you see any glaring errors!

Just one, couldn’t find checkVisibility command anywhere in code 😉

  • Haha 3

Share this post


Link to post
Share on other sites

Thank you @phronk. I was inspired by the Line of Sight tool in Steel Division. It's very cool. I'll keep tweaking it to see it I can come up with a faster method or visually more appealing. I would like to be able to create 'blobs' with smooth filled curves but I notice you can't fill a drawPolygon so it's triangles or similar it seems. Unless anyone has any ideas how to do that, I would be interested.

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

×