ACE3/addons/laser/functions/fnc_seekerFindLaserSpot.sqf
Glowbal b489750d5b Minor optimizations using private, params, and isEqualType (#4323)
* Optimizations with private, params, and isEqualType

* Fixed tab being used instead of space

* Fixed tabs inserted by notepad++

* More usage of new private syntax and params

- changed a few checks for an array being empty to `_arr isEqualTo []`
rather than `count _arr == 0`
- added more uses of `private` on the same line as the variable is
declared
- added more uses of params to assign variables passed as parameters
- removed unnecessary parentheses
- removed several unnecessary variable declarations with private array
syntax

* clean up and formatting
2016-09-04 16:44:22 +02:00

159 lines
5.8 KiB
Plaintext

/*
* Author: Nou
* Turn a laser designator on.
*
* Arguments:
* 0: Position of seeker (ASL) <position>
* 1: Direction vector (will be normalized) <vector>
* 2: Seeker FOV in degrees <number>
* 3: Seeker wavelength sensitivity range, [1550,1550] is common eye safe. <array>
* 4: Seeker laser code. <number>
*
* Return Value:
* Array, [Strongest compatible laser spot ASL pos, owner object] Nil array values if nothing found.
*/
#include "script_component.hpp"
private ["_pos", "_seekerWavelengths", "_seekerCode", "_spots", "_buckets", "_excludes", "_bucketIndex", "_finalPos", "_owner", "_obj", "_x", "_method"];
private ["_emitterWavelength", "_laserCode", "_divergence", "_laser", "_res", "_bucketPos", "_bucketList", "_c", "_forEachIndex", "_index"];
private ["_testPos", "_finalBuckets", "_largest", "_largestIndex", "_finalBucket", "_owners", "_avgX", "_avgY", "_avgZ", "_count", "_maxOwner", "_maxOwnerIndex", "_finalOwner"];
private ["_dir", "_seekerCos", "_seekerFov", "_testDotProduct", "_testPoint", "_testPointVector"];
_pos = _this select 0;
_dir = vectorNormalized (_this select 1);
_seekerFov = _this select 2;
_seekerWavelengths = _this select 3;
_seekerCode = _this select 4;
_seekerCos = cos _seekerFov;
_spots = [];
_buckets = [];
_excludes = [];
_bucketIndex = 0;
_finalPos = nil;
_finalOwner = nil;
{
_obj = _x select 0;
_owner = _x select 1;
_method = _x select 2;
_emitterWavelength = _x select 3;
_laserCode = _x select 4;
_divergence = _x select 5;
if(alive _obj && {_emitterWavelength >= (_seekerWavelengths select 0)} && {_emitterWavelength <= (_seekerWavelengths select 1)} && {_laserCode == _seekerCode}) then {
_laser = [];
if(IS_CODE(_method)) then {
_laser = _x call _method;
} else {
if(IS_STRING(_method)) then {
_laser = _x call (missionNamespace getVariable [_method, {}]);
} else {
if(IS_ARRAY(_method)) then {
if(count _method == 2) then {
_laser = [ATLtoASL (_obj modelToWorldVisual (_method select 0)), _obj weaponDirection (_method select 1)];
} else {
if(count _method == 3) then {
_laser = [ATLtoASL (_obj modelToWorldVisual (_method select 0)), (ATLtoASL (_obj modelToWorldVisual (_method select 1))) vectorFromTo (ATLtoASL (_obj modelToWorldVisual (_method select 2)))];
};
};
};
};
};
//Handle Weird Data Return
if (_laser params [["_laserPos", [], [[]], 3], ["_laserDir", [], [[]], 3]]) then {
_res = [_laserPos, _laserDir, _divergence] call FUNC(shootCone);
{
_testPoint = _x select 0;
_testPointVector = vectorNormalized (_testPoint vectorDiff _pos);
_testDotProduct = _dir vectorDotProduct _testPointVector;
if(_testDotProduct > _seekerCos) then {
_spots pushBack [_testPoint, _owner];
};
} forEach (_res select 2);
};
};
} forEach (GVAR(laserEmitters) select 2);
if((count _spots) > 0) then {
_bucketPos = nil;
_bucketList = nil;
_c = 0;
while { count(_spots) != count(_excludes) && _c < (count _spots) } do {
scopeName "mainSearch";
{
if(!(_forEachIndex in _excludes)) then {
_index = _buckets pushBack [_x, [_x]];
_excludes pushBack _forEachIndex;
_bucketPos = _x select 0;
_bucketList = (_buckets select _index) select 1;
breakTo "mainSearch";
};
} forEach _spots;
{
if(!(_forEachIndex in _excludes)) then {
_testPos = (_x select 0);
if(_testPos vectorDistanceSqr _bucketPos <= 100) then {
_bucketList pushBack _x;
_excludes pushBack _forEachIndex;
};
};
} forEach _spots;
_c = _c + 1;
};
_finalBuckets = [];
_largest = -1;
_largestIndex = 0;
{
_index = _finalBuckets pushBack [];
_bucketList = _finalBuckets select _index;
{
_testPos = (_x select 0);
if(!terrainIntersectASL [_pos, _testPos] && {!lineIntersects [_pos, _testPos]}) then {
_bucketList pushBack _x;
};
} forEach (_x select 1);
if((count _bucketList) > _largest) then {
_largest = (count _bucketList);
_largestIndex = _index;
};
} forEach _buckets;
_finalBucket = _finalBuckets select _largestIndex;
_owners = [] call CBA_fnc_hashCreate;
if(count _finalBucket > 0) then {
_avgX = 0;
_avgY = 0;
_avgZ = 0;
{
//player sideChat format["x: %1", _x];
_avgX = _avgX + ((_x select 0) select 0);
_avgY = _avgY + ((_x select 0) select 1);
_avgZ = _avgZ + ((_x select 0) select 2);
_owner = _x select 1;
if ([_owners, _owner] call CBA_fnc_hashHasKey) then {
private _count = [_owners, _owner] call CBA_fnc_hashGet;
[_owners, _owner, _count + 1] call CBA_fnc_hashSet;
} else {
[_owners, _owner, 1] call CBA_fnc_hashSet;
};
} forEach _finalBucket;
_count = count _finalBucket;
_finalPos = [_avgX/_count, _avgY/_count, _avgZ/_count];
_maxOwner = -1;
_maxOwnerIndex = 0;
{
if((_owners select 1) select _forEachIndex > _maxOwner) then {
_maxOwner = (_owners select 1) select _forEachIndex;
_maxOwnerIndex = _forEachIndex;
};
} forEach (_owners select 0);
_finalOwner = (_owners select 0) select _maxOwnerIndex;
};
};
[_finalPos, _owner];