/* * Author: Nou * Turn a laser designator on. * * Arguments: * 0: Position of seeker (ASL) * 1: Direction vector (will be normalized) * 2: Seeker FOV in degrees * 3: Seeker wavelength sensitivity range, [1550,1550] is common eye safe. * 4: Seeker laser code. * * 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 1); 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 = HASH_CREATE; 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(HASH_HASKEY(_owners, _owner)) then { _count = HASH_GET(_owners, _owner); HASH_SET(_owners, _owner, _count+1); } else { HASH_SET(_owners, _owner, 1); }; } 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];