Page MenuHomeFeedback Tracker

inAreaArray variant to return indexes: inAreaArrayIndexes
Closed, ResolvedPublic

Description

I'd like to request a variation of inAreaArray command that returns matching indexes instead of array elements. Non-object entities have to be represented as positions and to determine which non-object entity was matched by the command, you have to resort to hacky approaches like storing indexes as position Z coordinate which creates additional overhead for high-performing scripts, for which inAreaArray command very useful.

Details

Severity
Feature
Resolution
Fixed
Reproducibility
N/A
Operating System
Windows 10 x64
Category
Scripting
Additional Information

Current inAreaArray output:

[
	[0,0,0],
	[100,0,0],
	[200,0,0]
] inAreaArrayIndexes [[0,0,0], 150, 150]

>[[0,0,0],[100,0,0]]

Proposed inAreaArrayIndexes output:

[
	[0,0,0],
	[100,0,0],
	[200,0,0]
] inAreaArrayIndexes [[0,0,0], 150, 150]

>[0,1]

Event Timeline

SaMatra created this task.Feb 19 2023, 2:26 PM
SaMatra renamed this task from inAreaArrayIndexes to inAreaArray variant to return indexes: inAreaArrayIndexes.

rev 150318 https://community.bistudio.com/wiki/inAreaArrayIndexes

Please check every variation thoroughly

BIS_fnc_KK removed BIS_fnc_KK as the assignee of this task.Feb 20 2023, 3:40 PM
BIS_fnc_KK changed the task status from New to Feedback.
BIS_fnc_KK added a subscriber: BIS_fnc_KK.

resort to hacky approaches like storing indexes as position Z coordinate

You can just store them as hashmaps now

dedmen set Ref Ticket to AIII-55567.Mar 1 2023, 1:42 PM

Did tests for all possible combination, works properly. Shitty test code:

	if(!isNil"markers") then {{deleteMarker _x} forEach markers;}; markers = [];
	if(!isNil"objects") then {{deleteVehicle _x} forEach objects}; objects = [];
	if(!isNil"locations") then {{deleteLocation _x} forEach locations}; locations = [];
	positions = [];
	if(isNil"testgroups") then {{{deleteVehicle _x} forEach units _x; deleteGroup _x} forEach testgroups};
	testgroups = [];

	private _marker_types = "true" configClasses (configFile >> "CfgMarkers") apply {configName _x};
	testalpha = 0.3;

	for "_i" from 1 to 50 do {
		for "_j" from 1 to 10 do {
			private _pos = getPosWorld player vectorAdd [_i * 100, _j * 100, 0];

			switch(true) do {
				case (_i <= 10): {
					private _m = createMarker [str round random 1e10, _pos];
					_m setMarkerShape selectRandom ["RECTANGLE", "ELLIPSE", "ICON", "ICON"];
					if(markerShape _m == "ICON") then {
						_m setMarkerType selectRandom _marker_types;
						_m setMarkerSize [1, 1];
					} else {
						_m setMarkerSize [50, 50];
					};
					_m setMarkerDir random 360;
					_m setMarkerColor "ColorRed";
					markers pushBack _m;
				};
				case (_i <= 20): {
					private _obj = "Logic" createVehicleLocal _pos;
					objects pushBack _obj;
				};
				case (_i <= 30): {
					private _loc = createLocation ["o_inf", _pos, 50, 50];
					locations pushBack _loc;
				};
				case (_i <= 40): {
					positions pushBack _pos;
				};
				case (_i <= 50): {
					private _group = createGroup blufor;
					_group createUnit ["Logic", _pos, [], 0, "CAN_COLLIDE"];
					testgroups pushBack _group;
				};
			};
		};
	};

	if(isNil"draweh") then {draweh = findDisplay 12 displayCtrl 51 ctrlAddEventHandler ["Draw", {call mapdraw}];};
	if(!isNil"trig") then {deleteVehicle trig};
	trig = createTrigger ["EmptyDetector", getPosWorld objNull, false];

	if(!isNil"loc") then {deleteLocation loc};
	loc = createLocation ["Name", getPosWorld objNull, 0, 0];

	if(!isNil"mark") then {deleteMarker mark};
	mark = createMarker [str random 1e10, getPosWorld objNull];
	mark setMarkerColor "ColorWhite";
	mark setMarkerAlpha testalpha;
	mark setMarkerType selectRandom _marker_types;
	mark setMarkerBrush "SolidFull";

	mapdraw = {
		params ["_map"];
		private _scale = ctrlMapScale _map;
		private _rev_time = 5;
		private _rect = (diag_tickTime % (_rev_time * 2) > _rev_time);
		private _dir = diag_tickTime % _rev_time / _rev_time * 360;
		private _width = 5000 * _scale;
		private _height = 2000 * _scale;
		private _array_check = [_map ctrlMapScreenToWorld getMousePosition, _width, _height, _dir, _rect, -1];
		private _ui_offset_y = SafeZOneH / 3;
		private _ui_offset_x = _ui_offset_y * 3/4;

		trig setTriggerArea [_width, _height, _dir, _rect, -1];
		trig setPos (_map ctrlMapScreenToWorld (getMousePosition vectorAdd [-_ui_offset_x,0]));

		loc setDirection _dir;
		loc setRectangular _rect;
		loc setSize [_width, _height];
		loc setPosition (_map ctrlMapScreenToWorld (getMousePosition vectorAdd [_ui_offset_x,0]));

		mark setMarkerPos (_map ctrlMapScreenToWorld (getMousePosition vectorAdd [0,_ui_offset_y]));
		mark setMarkerDir _dir;
		mark setMarkerShape (if(_rect) then {
			mark setMarkerShape "RECTANGLE";
			mark setMarkerSize [_width, _height];
		} else {
			mark setMarkerShape "ELLIPSE";
			mark setMarkerSize [_width, _height];
		});

		private _matched_positions_indexes = [];
		{
			private _indexes =
				   (_x inAreaArrayIndexes _array_check)
				 + (_x inAreaArrayIndexes trig)
				 + (_x inAreaArrayIndexes loc)
				 + (_x inAreaArrayIndexes mark);

			switch(true) do {
				case(_x isEqualRef markers): {
					{
						if(_forEachIndex in _indexes) then {
							_x setMarkerColor "ColorGreen";
						} else {
							_x setMarkerColor "ColorRed";
						};
					} forEach markers;
				};
				case(_x isEqualRef positions): {
					_matched_positions_indexes = _indexes;
				};
				case(_x isEqualRef locations): {
					{
						if(_forEachIndex in _indexes) then {
							_x setType "b_inf";
						} else {
							_x setType "o_inf";
						};
					} forEach locations;
				};
				default {
					{
						_x setVariable ["matched", _forEachIndex in _indexes];
					} forEach _x;
				};
			};
		} forEach [markers, objects, locations, positions, testgroups];

		{
			_map drawIcon [
				 getText(configFile >> "CfgVehicles" >> typeOf _x >> "icon")
				,if(_x getVariable ["matched", false]) then {[0,1,0,1]} else {[1,0,0,1]}
				,getPosWorld _x
				,20
				,20
				,getDir _x
				,""
				,2
			];
		} forEach objects;

		{
			_map drawIcon [
				 "iconExplosiveAT"
				,if(_forEachIndex in _matched_positions_indexes) then {[0,1,0,1]} else {[1,0,0,1]}
				,_x
				,30
				,30
				,0
				,"Pos"
				,2
			];
		} forEach positions;

		{
			_map drawIcon [
				 "iconExplosiveGP"
				,if(_x getVariable ["matched", false]) then {[0,1,0,1]} else {[1,0,0,1]}
				,getPosWorld leader _x
				,30
				,30
				,0
				,"Grp"
				,2
			];
		} forEach testgroups;

		if(_rect) then {
			_map drawRectangle [_array_check select 0, _width, _height, _dir, [1,1,1,testalpha], "#(rgb,8,8,3)color(1,1,1,1)"];
			_map drawRectangle [locationPosition loc, size loc select 0, size loc select 1, direction loc, [1,1,1,testalpha], "#(rgb,8,8,3)color(1,1,1,1)"];
			_map drawRectangle [getPosWorld trig, triggerArea trig select 0, triggerArea trig select 1, triggerArea trig select 2, [1,1,1,testalpha], "#(rgb,8,8,3)color(1,1,1,1)"];
		} else {
			_map drawEllipse [_array_check select 0, _width, _height, _dir, [1,1,1,testalpha], "#(rgb,8,8,3)color(1,1,1,1)"];
			_map drawEllipse [locationPosition loc, size loc select 0, size loc select 1, direction loc, [1,1,1,testalpha], "#(rgb,8,8,3)color(1,1,1,1)"];
			_map drawEllipse [getPosWorld trig, triggerArea trig select 0, triggerArea trig select 1, triggerArea trig select 2, [1,1,1,testalpha], "#(rgb,8,8,3)color(1,1,1,1)"];
		};

		private _text_offset = [0,1000*_scale,0];
		_map drawIcon ["iconExplosiveAT", [1,1,1,1], _array_check select 0 vectorAdd _text_offset, 1e-6, 1e-6, 0, "Array check", 2];
		_map drawIcon ["iconExplosiveAT", [1,1,1,1], locationPosition loc vectorAdd _text_offset, 1e-6, 1e-6, 0, "Location check", 2];
		_map drawIcon ["iconExplosiveAT", [1,1,1,1], getPosWorld trig vectorAdd _text_offset, 1e-6, 1e-6, 0, "Trigger check", 2];
		_map drawIcon ["iconExplosiveAT", [1,1,1,1], markerPos mark vectorAdd _text_offset, 1e-6, 1e-6, 0, "Marker check", 2];
	};
	0
BIS_fnc_KK closed this task as Resolved.Mar 31 2023, 3:36 PM
BIS_fnc_KK changed Resolution from Open to Fixed.

New command is great, but I'd also like to request tweaks to existing commands, here are the tickets:
T171744 - Have inAreaArray and inAreaArrayIndexes take ENTITY as argument like inArea does
T171699 - Have inPolygon take ENTITY as argument
T171524 - inAreaArray variant that takes both list of areas and list of positions to check

Bug found in inAreaArrayIndexes, it ignores c for height:

private _area = [positionCameraToWorld [0,0,0], 20, 20, 0, true, 20];
[
     [player] inAreaArrayIndexes _area
    ,[player] inAreaArray _area
]

> [[],[B Alpha 1-2:1 (Sa-Matra)]]

BIS_fnc_KK added a comment.EditedMay 14 2024, 1:16 PM

Bug found in inAreaArrayIndexes, it ignores c for height:

private _area = [positionCameraToWorld [0,0,0], 20, 20, 0, true, 20];
[
     [player] inAreaArrayIndexes _area
    ,[player] inAreaArray _area
]

=> [[],[B Alpha 1-2:1 (Sa-Matra)]]

as designed please see wiki