mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
Merge pull request #501 from acemod/network_lasers
Break all the lasers. Continuing expansion work is in #535
This commit is contained in:
commit
0c3caffe89
@ -2,8 +2,32 @@ class CfgVehicles {
|
||||
class All;
|
||||
|
||||
class LaserTarget: All {
|
||||
// @TODO: Changing the model and simulation hides it, but THEN IT DOESNT SPAWN WTF!?
|
||||
model = "\A3\Weapons_F\empty.p3d";
|
||||
simulation = "nvmarker";
|
||||
nvTarget = 1;
|
||||
//simulation = "laserTarget";
|
||||
//threat[] = {0,0,0};
|
||||
class EventHandlers {
|
||||
init = QUOTE(_this call FUNC(laser_init));
|
||||
};
|
||||
|
||||
diffuse[] = {0,0,0};
|
||||
ambient[] = {0,0,0};
|
||||
brightness = 0;
|
||||
name = "pozicni blik";
|
||||
drawLight = 0;
|
||||
drawLightSize = 0;
|
||||
drawLightCenterSize = 0;
|
||||
activeLight = 0;
|
||||
blinking = 0;
|
||||
dayLight = 0;
|
||||
onlyInNvg = 0;
|
||||
useFlare = 0;
|
||||
};
|
||||
|
||||
// Visual laserTarget override
|
||||
class ACE_LaserTarget_Visual : LaserTarget {
|
||||
//model = "\A3\Weapons_f\laserTgt.p3d";
|
||||
};
|
||||
};
|
8
addons/laser/CfgWeapons.hpp
Normal file
8
addons/laser/CfgWeapons.hpp
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
class CfgWeapons {
|
||||
class Binocular;
|
||||
|
||||
class Laserdesignator : Binocular {
|
||||
visionMode[] = {"Normal","NVG"};
|
||||
};
|
||||
};
|
1
addons/laser/RscInGameUI.hpp
Normal file
1
addons/laser/RscInGameUI.hpp
Normal file
@ -0,0 +1 @@
|
||||
// TODO: RscOptics_LaserDesignator for laser code designation
|
@ -1,3 +1,4 @@
|
||||
#include "script_component.hpp"
|
||||
NO_DEDICATED;
|
||||
|
||||
["laser_laserOn", {_this call DFUNC(handleLaserOn)}] call EFUNC(common,addEventHandler);
|
||||
["laser_laserOff", {_this call DFUNC(handleLaserOff)}] call EFUNC(common,addEventHandler);
|
||||
|
@ -6,15 +6,28 @@ PREP(shootRay);
|
||||
PREP(shootCone);
|
||||
PREP(checkLos);
|
||||
|
||||
PREP(findLaserDesignator);
|
||||
PREP(findStrongestRay);
|
||||
|
||||
PREP(translateToModelSpace);
|
||||
PREP(translateToWeaponSpace);
|
||||
|
||||
PREP(laser_init);
|
||||
PREP(seekerFindLaserSpot);
|
||||
PREP(laserOn);
|
||||
PREP(laserOff);
|
||||
PREP(handleLaserOn);
|
||||
PREP(handleLaserOff);
|
||||
|
||||
PREP(drawVisibleLaserTargets);
|
||||
|
||||
PREP(laser_init);
|
||||
PREP(vanillaLaserSeekerHandler);
|
||||
PREP(laserTargetPFH);
|
||||
|
||||
ACE_LASERS = [];
|
||||
ACE_DEFAULT_LASER_CODE = 1001;
|
||||
GVAR(VanillaLasers) = [];
|
||||
|
||||
// Laser default variables
|
||||
ACE_DEFAULT_LASER_CODE = 1001;
|
||||
ACE_DEFAULT_LASER_WAVELENGTH = 1550;
|
||||
ACE_DEFAULT_LASER_BEAMSPREAD = 1;
|
||||
|
||||
GVAR(laserEmitters) = HASH_CREATE;
|
@ -11,4 +11,5 @@ class CfgPatches {
|
||||
};
|
||||
|
||||
#include "CfgEventhandlers.hpp"
|
||||
#include "CfgVehicles.hpp"
|
||||
#include "CfgVehicles.hpp"
|
||||
#include "CfgWeapons.hpp"
|
1
addons/laser/functions/fnc_drawVisibleLaserTargets.sqf
Normal file
1
addons/laser/functions/fnc_drawVisibleLaserTargets.sqf
Normal file
@ -0,0 +1 @@
|
||||
// @TODO: This is to draw the actual LaserTarget positions to utilize for laser shooting.
|
@ -1,74 +0,0 @@
|
||||
//#define DEBUG_MODE_FULL
|
||||
#include "script_component.hpp"
|
||||
|
||||
private ["_seeker", "_headingPitch", "_found", "_vectorTo", "_polarTo", "_dir", "_vertOk", "_horzOk", "_fov",
|
||||
"_closestDistance", "_pos1", "_pos2", "_disCheck", "_currentTarget", "_potentialTargets", "_offset", "_vector"];
|
||||
|
||||
_seeker = _this select 0;
|
||||
_laserCode = _this select 1;
|
||||
_fov = if (count _this > 2) then {_this select 2} else {75};
|
||||
_vector = if (count _this > 3) then {_this select 3} else {vectorDir _seeker};
|
||||
_offset = if (count _this > 4) then {_this select 4} else {[0,0,0]};
|
||||
|
||||
_headingPitch = _vector call CBA_fnc_vect2polar;
|
||||
_currentTarget = nil;
|
||||
_found = false;
|
||||
|
||||
_getPosASL = {visiblePositionASL (_this select 0)};
|
||||
|
||||
LOG("Searching lasers");
|
||||
if(!(isNil "ACE_LASERS")) then {
|
||||
_potentialTargets = [];
|
||||
TRACE_1("", ACE_LASERS);
|
||||
|
||||
{
|
||||
if(!(isNull _x)) then {
|
||||
_sensorPos = ATLtoASL(_seeker modelToWorldVisual _offset);
|
||||
_vectorTo = [_sensorPos, ([_x] call _getPosASL)] call BIS_fnc_vectorFromXToY;
|
||||
_polarTo = _vectorTo call CBA_fnc_vect2polar;
|
||||
_dir = _polarTo select 1;
|
||||
_dir = _dir - (_headingPitch select 1);
|
||||
|
||||
TRACE_4("Calc", _sensorPos, _vectorTo, _polarTo, _dir);
|
||||
|
||||
if (_dir < 0) then {_dir = _dir + 360};
|
||||
if (_dir > 360) then {_dir = _dir - 360};
|
||||
_vertOk = false;
|
||||
_horzOk = false;
|
||||
if(_dir < _fov || {_dir > (360-_fov)}) then {
|
||||
_horzOk = true;
|
||||
};
|
||||
if(abs((abs(_polarTo select 2))-(abs(_headingPitch select 2))) < _fov) then {
|
||||
_vertOk = true;
|
||||
};
|
||||
|
||||
TRACE_2("Results", _vertOk, _horzOk);
|
||||
|
||||
if(_vertOk && {_horzOk}) then {
|
||||
// Does the laser currently have our current code, if we have one?
|
||||
_targetCode = _x getVariable ["ACE_LASER_CODE", ACE_DEFAULT_LASER_CODE];
|
||||
TRACE_1("Target in sight, checking code", _targetCode, _laserCode);
|
||||
if(_targetCode == _laserCode) then {
|
||||
_potentialTargets set[(count _potentialTargets), _x];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
} forEach ACE_LASERS;
|
||||
|
||||
TRACE_1("", _potentialTargets);
|
||||
|
||||
_closestDistance = 100000;
|
||||
{
|
||||
_pos1 = (getPosASL _seeker);
|
||||
_pos2 = ([_x] call _getPosASL);
|
||||
_disCheck = _pos1 distance _pos2;
|
||||
// shouldn't this bail out when a valid target is found instead of iterating over all potential targets ?
|
||||
if(_disCheck < _closestDistance && {[_pos1, _pos2, _x, _seeker] call FUNC(checkLos)}) then {
|
||||
_found = true;
|
||||
_currentTarget = _x;
|
||||
_closestDistance = _disCheck;
|
||||
};
|
||||
} forEach _potentialTargets;
|
||||
};
|
||||
[_found, _currentTarget]
|
8
addons/laser/functions/fnc_handleLaserOff.sqf
Normal file
8
addons/laser/functions/fnc_handleLaserOff.sqf
Normal file
@ -0,0 +1,8 @@
|
||||
//fnc_handleLaserOff.sqf
|
||||
#include "script_component.hpp"
|
||||
|
||||
private ["_uuid"];
|
||||
_uuid = _this select 0;
|
||||
if(HASH_HASKEY(GVAR(laserEmitters), _uuid)) then {
|
||||
HASH_REM(GVAR(laserEmitters), _uuid);
|
||||
};
|
7
addons/laser/functions/fnc_handleLaserOn.sqf
Normal file
7
addons/laser/functions/fnc_handleLaserOn.sqf
Normal file
@ -0,0 +1,7 @@
|
||||
//fnc_handleLaserOn.sqf
|
||||
#include "script_component.hpp"
|
||||
|
||||
private ["_uuid", "_args"];
|
||||
_uuid = _this select 0;
|
||||
_args = _this select 1;
|
||||
HASH_SET(GVAR(laserEmitters), _uuid, _args);
|
16
addons/laser/functions/fnc_laserOff.sqf
Normal file
16
addons/laser/functions/fnc_laserOff.sqf
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Author: Nou
|
||||
* Turn a laser designator off.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: UUID (from laserOn) <string>
|
||||
*
|
||||
* Return value:
|
||||
* None
|
||||
*/
|
||||
|
||||
#include "script_component.hpp"
|
||||
|
||||
private ["_uuid"];
|
||||
_uuid = _this select 0;
|
||||
["laser_laserOff", [_uuid]] call EFUNC(common,globalEvent);
|
23
addons/laser/functions/fnc_laserOn.sqf
Normal file
23
addons/laser/functions/fnc_laserOn.sqf
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Author: Nou
|
||||
* Turn a laser designator on.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Emitter <object>
|
||||
* 1: Owner <object>
|
||||
* 2: Method, can be code, which emitter and owner are passed to, a string function name, an array with a position memory point and weapon name, or an array with a position memory point, a vector begining memory point, and vector ending memory point.
|
||||
* 3: Wavelength (1550nm is common eye safe) <number>
|
||||
* 4: Laser code <number>
|
||||
* 5: Beam divergence (in mils off beam center).
|
||||
*
|
||||
* Return value:
|
||||
* String, UUID for sending to laserOff function.
|
||||
*/
|
||||
|
||||
#include "script_component.hpp"
|
||||
|
||||
private ["_uuid", "_args"];
|
||||
_uuid = format["%1%2%3", floor diag_tickTime, floor random 1000, floor random 10000];
|
||||
_args = [_uuid, _this];
|
||||
["laser_laserOn", _args] call EFUNC(common,globalEvent);
|
||||
_uuid;
|
@ -1,20 +1,25 @@
|
||||
//#define DEBUG_MODE_FULL
|
||||
#include "script_component.hpp"
|
||||
TRACE_1("enter", _this);
|
||||
|
||||
private["_args", "_laserTarget"];
|
||||
//TRACE_1("enter", _this);
|
||||
_args = _this select 0;
|
||||
_laserTarget = _args select 0;
|
||||
_shooter = _args select 1;
|
||||
_uuid = _args select 2;
|
||||
|
||||
if(isNull _laserTarget || !alive player) exitWith {
|
||||
if(isNull _laserTarget || !alive _shooter) exitWith {
|
||||
[(_this select 1)] call cba_fnc_removePerFrameHandler;
|
||||
REM(ACE_LASERS, _laserTarget);
|
||||
REM(GVAR(VanillaLasers), _laserTarget);
|
||||
|
||||
// Remove laseron
|
||||
[_uuid] call FUNC(laserOff);
|
||||
};
|
||||
|
||||
_end = diag_tickTime;
|
||||
|
||||
#ifdef DEBUG_MODE_FULL
|
||||
// Iconize the location of the actual laserTarget
|
||||
_pos = [_laserTarget] call FUNC(getPosASL);
|
||||
_pos = getPosASL _laserTarget;
|
||||
drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\select_target_ca.paa", [1,0,0,1], (ASLtoATL _pos), 0.75, 0.75, 0, "", 0.5, 0.025, "TahomaB"];
|
||||
|
||||
{
|
||||
|
@ -1,25 +1,32 @@
|
||||
//#define DEBUG_MODE_FULL
|
||||
#include "script_component.hpp"
|
||||
PARAMS_1(_laserTarget);
|
||||
|
||||
TRACE_1("enter", _this);
|
||||
|
||||
PARAMS_1(_laserTarget);
|
||||
|
||||
// Add the target to the global targets array
|
||||
// Everyone tracks them
|
||||
|
||||
// Add the laser localized to the laser array, and give it the default localized code
|
||||
PUSH(ACE_LASERS, _laserTarget);
|
||||
PUSH(GVAR(VanillaLasers), _laserTarget);
|
||||
|
||||
// Check the vehicle, otherwise use the default
|
||||
_laserTarget setVariable ["ACE_LASER_CODE", ACE_DEFAULT_LASER_CODE, false];
|
||||
_laserTarget setVariable [QGVAR(code), ACE_DEFAULT_LASER_CODE, false];
|
||||
_laserTarget setVariable [QGVAR(beamSpread), ACE_DEFAULT_LASER_BEAMSPREAD, false];
|
||||
_laserTarget setVariable [QGVAR(waveLength), ACE_DEFAULT_LASER_WAVELENGTH, false];
|
||||
|
||||
// Clean the lasers of any null objects while we are here
|
||||
REM(ACE_LASERS, objNull);
|
||||
REM(GVAR(VanillaLasers), objNull);
|
||||
|
||||
if(!(local _laserTarget)) exitWith { };
|
||||
|
||||
// The target is local, so its on this client
|
||||
if(!isDedicated) then {
|
||||
_laserTarget setVariable ["ACE_LASERTARGET_SHOOTER", ACE_player, true];
|
||||
|
||||
[FUNC(laserTargetPFH), 0, [_laserTarget, ACE_player]] call cba_fnc_addPerFrameHandler;
|
||||
// @TODO: Get ownership variables and set them on the vehicle
|
||||
|
||||
_uuid = [(vehicle ACE_player), ACE_player, QFUNC(vanillaLaserSeekerHandler), ACE_DEFAULT_LASER_WAVELENGTH, ACE_DEFAULT_LASER_CODE, ACE_DEFAULT_LASER_BEAMSPREAD] call FUNC(laserOn);
|
||||
_laserTarget setVariable [QGVAR(uuid), _uuid, false];
|
||||
[FUNC(laserTargetPFH), 0, [_laserTarget, ACE_player, _uuid]] call cba_fnc_addPerFrameHandler;
|
||||
} else {
|
||||
// server side ownership of laser
|
||||
//_laserTarget setVariable ["ACE_LASERTARGET_SHOOTER", nil, false];
|
||||
_laserTarget setVariable [QGVAR(owner), nil, true];
|
||||
};
|
||||
|
@ -32,7 +32,5 @@ if (_d != 0) then {
|
||||
};
|
||||
|
||||
/* Inverse of step 1 */
|
||||
_q1 set[0, (_q2 select 0) + (_p1 select 0)];
|
||||
_q1 set[1, (_q2 select 1) + (_p1 select 1)];
|
||||
_q1 set[2, (_q2 select 2) + (_p1 select 2)];
|
||||
_q1 = _q2 vectorAdd _p1;
|
||||
_q1;
|
@ -5,19 +5,12 @@ _p = _this select 0;
|
||||
_p1 = _this select 1;
|
||||
_p2 = _this select 2;
|
||||
|
||||
_q1 = [];
|
||||
_q2 = [];
|
||||
_u = [];
|
||||
|
||||
/* Step 1 */
|
||||
_q1 set[0, (_p select 0) - (_p1 select 0)];
|
||||
_q1 set[1, (_p select 1) - (_p1 select 1)];
|
||||
_q1 set[2, (_p select 2) - (_p1 select 2)];
|
||||
|
||||
_u set[0, (_p2 select 0) - (_p1 select 0)];
|
||||
_u set[1, (_p2 select 1) - (_p1 select 1)];
|
||||
_u set[2, (_p2 select 2) - (_p1 select 2)];
|
||||
_u = _u call BIS_fnc_unitVector;
|
||||
_q1 = _p vectorDiff _p1;
|
||||
_u = _p2 vectorDiff _p1;
|
||||
_u = vectorNormalized _u;
|
||||
_d = sqrt((_u select 1)*(_u select 1) + (_u select 2)*(_u select 2));
|
||||
|
||||
/* Step 2 */
|
||||
|
143
addons/laser/functions/fnc_seekerFindLaserSpot.sqf
Normal file
143
addons/laser/functions/fnc_seekerFindLaserSpot.sqf
Normal file
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Author: Nou
|
||||
* Turn a laser designator on.
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Position of seeker (ASL) <position>
|
||||
* 1: Seeker wavelength sensitivity range, [1550,1550] is common eye safe. <array>
|
||||
* 2: 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",
|
||||
"_emitterWavelength", "_laserCode", "_divergence", "_laser", "_laserPos", "_laserDir", "_res", "_bucketPos", "_bucketList", "_c", "_forEachIndex", "_index",
|
||||
"_testPos", "_finalBuckets", "_largest", "_largestIndex", "_finalBucket", "_owners", "_avgX", "_avgY", "_avgZ", "_count", "_maxOwner", "_maxOwnerIndex", "_finalOwner"];
|
||||
|
||||
_pos = _this select 0;
|
||||
_seekerWavelengths = _this select 1;
|
||||
_seekerCode = _this select 2;
|
||||
|
||||
_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)))];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
_laserPos = _laser select 0;
|
||||
_laserDir = _laser select 1;
|
||||
_res = [_laserPos, _laserDir, _divergence] call FUNC(shootCone);
|
||||
{
|
||||
_spots pushBack [_x select 0, _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];
|
@ -1,8 +1,17 @@
|
||||
#include "script_component.hpp"
|
||||
|
||||
//#define DEBUG_MODE_FULL
|
||||
private ["_divergence","_pos","_vec","_longestReturn","_shortestReturn","_resultPositions","_p1","_p2","_p","_v","_cp","_vecRotateMap","_result",
|
||||
"_resultPos","_distance","_count","_pos2","_radOffset","_offset","_offsetPos","_offsetVector"];
|
||||
_divergence = 0.3;
|
||||
_pos = _this select 0;
|
||||
_vec = _this select 1;
|
||||
if(count _this > 2) then {
|
||||
_divergence = _this select 2;
|
||||
};
|
||||
_count = 3;
|
||||
if(count _this > 3) then {
|
||||
_count = _this select 3;
|
||||
};
|
||||
_longestReturn = -1000000000;
|
||||
_shortestReturn = 1000000000;
|
||||
_resultPositions = [];
|
||||
@ -10,7 +19,7 @@ _p1 = [0,0,0];
|
||||
_p2 = +_vec;
|
||||
_p = (_vec call CBA_fnc_vect2polar);
|
||||
_v = [(_p select 0), (_p select 1), (_p select 2)+90] call CBA_fnc_polar2vect;
|
||||
_cp = [_vec, _v] call BIS_fnc_crossProduct;
|
||||
_cp = _vec vectorCrossProduct _v;
|
||||
|
||||
_vecRotateMap = [_cp, _p1, _p2] call FUNC(rotateVectLineGetMap);
|
||||
|
||||
@ -24,28 +33,21 @@ if(!isNil "_resultPos") then {
|
||||
if(_distance > _longestReturn) then {
|
||||
_longestReturn = _distance;
|
||||
};
|
||||
_resultPositions set[(count _resultPositions), _result];
|
||||
_resultPositions pushBack _result;
|
||||
#ifdef DEBUG_MODE_FULL
|
||||
DRAW_LINES set[(count DRAW_LINES), [_pos, _resultPos, [0, 1, 0, 1]]];
|
||||
// DRAW_LINES set[(count DRAW_LINES), [_pos, _resultPos, [0, 1, 0, 1]]];
|
||||
drawLine3D [ASLtoATL _pos, ASLtoATL _resultPos, [1,0,0,1]];
|
||||
#endif
|
||||
};
|
||||
_count = 8;
|
||||
|
||||
_pos2 = [
|
||||
(_pos select 0)+((_vec select 0)*1000),
|
||||
(_pos select 1)+((_vec select 1)*1000),
|
||||
(_pos select 2)+((_vec select 2)*1000)
|
||||
];
|
||||
|
||||
_pos2 = _pos vectorAdd (_vec vectorMultiply 1000);
|
||||
{
|
||||
for "_i" from 0 to ceil(_count*_x) do {
|
||||
_radOffset = random 360;
|
||||
_offset = [_vecRotateMap, (((360/_count)*_i)+_radOffset) mod 360] call FUNC(rotateVectLine);
|
||||
_offsetPos = [
|
||||
(_pos2 select 0)+((_offset select 0)*(_divergence*_x)),
|
||||
(_pos2 select 1)+((_offset select 1)*(_divergence*_x)),
|
||||
(_pos2 select 2)+((_offset select 2)*(_divergence*_x))
|
||||
];
|
||||
_offsetVector = [_pos, _offsetPos] call BIS_fnc_vectorFromXtoY;
|
||||
_offsetPos = _pos2 vectorAdd (_offset vectorMultiply (_divergence*_x));
|
||||
_offsetVector = _pos vectorFromTo _offsetPos;
|
||||
_result = [_pos, _offsetVector] call FUNC(shootRay);
|
||||
_resultPos = _result select 0;
|
||||
if(!isNil "_resultPos") then {
|
||||
@ -56,9 +58,10 @@ _pos2 = [
|
||||
if(_distance > _longestReturn) then {
|
||||
_longestReturn = _distance;
|
||||
};
|
||||
_resultPositions set[(count _resultPositions), _result];
|
||||
_resultPositions pushBack _result;
|
||||
#ifdef DEBUG_MODE_FULL
|
||||
DRAW_LINES set[(count DRAW_LINES), [_pos, _resultPos, [0, 1, 0, 1]]];
|
||||
// DRAW_LINES set[(count DRAW_LINES), [_pos, _resultPos, [0, 1, 0, 1]]];
|
||||
drawLine3D [ASLtoATL _pos, ASLtoATL _resultPos, [1,0,0,1]];
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
@ -11,13 +11,8 @@ _lastPos = +_pos;
|
||||
{
|
||||
scopeName "mainSearch";
|
||||
for "_i" from 1 to 10 do {
|
||||
_nextPos = [
|
||||
(_lastPos select 0)+((_vec select 0)*_x),
|
||||
(_lastPos select 1)+((_vec select 1)*_x),
|
||||
(_lastPos select 2)+((_vec select 2)*_x)
|
||||
];
|
||||
|
||||
if(lineIntersects [_lastPos, _nextPos] || terrainIntersectASL [_lastPos, _nextPos]) then {
|
||||
_nextPos = _lastPos vectorAdd (_vec vectorMultiply _x);
|
||||
if(terrainIntersectASL [_lastPos, _nextPos] || {lineIntersects [_lastPos, _nextPos]}) then {
|
||||
_resultPos = _lastPos;
|
||||
breakTo "mainSearch";
|
||||
} else {
|
||||
@ -25,6 +20,5 @@ _lastPos = +_pos;
|
||||
_lastPos = _nextPos;
|
||||
};
|
||||
};
|
||||
|
||||
} forEach _fidelity;
|
||||
[_resultPos, _distance];
|
26
addons/laser/functions/fnc_vanillaLaserSeekerHandler.sqf
Normal file
26
addons/laser/functions/fnc_vanillaLaserSeekerHandler.sqf
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Author: jaynus
|
||||
* Handler function for laser network code.
|
||||
*
|
||||
* Argument:
|
||||
* 0: Emitter
|
||||
* 1: Owner
|
||||
*
|
||||
* Return value:
|
||||
* [position, direction]
|
||||
*/
|
||||
//#define DEBUG_MODE_FULL
|
||||
#include "script_component.hpp"
|
||||
|
||||
private["_emitter", "_owner", "_gunnerInfo", "_turretInfo", "_povPos", "_povDir"];
|
||||
|
||||
_emmiter = _this select 0;
|
||||
_owner = _this select 1;
|
||||
|
||||
// Not in a vehicle....
|
||||
// @TODO: handle lasering from turrets
|
||||
if( (vehicle _emmiter) == _emmiter && alive _emmiter && (currentWeapon _emmiter) == "LaserDesignator") exitWith {
|
||||
[(eyePos _emmiter), (eyeDirection _emmiter)]
|
||||
};
|
||||
|
||||
[-1,-1]
|
@ -1,32 +0,0 @@
|
||||
class RscPicture;
|
||||
class RscText;
|
||||
class RscControlsGroupNoScrollbars;
|
||||
/* This disables air radar. We need to make this a seperate HUD addon
|
||||
class RscInGameUI
|
||||
{
|
||||
class RscUnitInfo
|
||||
{
|
||||
class CA_Radar: RscControlsGroupNoScrollbars
|
||||
{
|
||||
class controls
|
||||
{
|
||||
class CA_RadarBackground: RscPicture {
|
||||
colorText[] = {0,0,0,0};
|
||||
text = "";
|
||||
};
|
||||
class CA_RadarIcon: RscPicture {
|
||||
colorText[] = {0,0,0,0};
|
||||
};
|
||||
class CA_Heading: RscText {
|
||||
colorText[] = {0,0,0,0};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
class CfgInGameUI
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
*/
|
@ -8,12 +8,6 @@ class CfgVehicles {
|
||||
class Turrets {
|
||||
class MainTurret;
|
||||
};
|
||||
|
||||
// TODO: move these to a different HUD addon
|
||||
// commanderCanSee = 2+32;
|
||||
// gunnerCanSee = 2+32;
|
||||
// driverCanSee = 2+32;
|
||||
|
||||
};
|
||||
|
||||
class Helicopter_Base_F: Helicopter {};
|
||||
|
@ -5,7 +5,8 @@ PREP(laserHudDesignateOn);
|
||||
PREP(laserHudDesignateOff);
|
||||
PREP(unitTurretHasDesignator);
|
||||
|
||||
GVAR(laser) = nil;
|
||||
PREP(findLaserSource);
|
||||
|
||||
GVAR(active) = false;
|
||||
|
||||
FUNC(getPosASL) = {visiblePositionASL (_this select 0)};
|
||||
|
@ -10,8 +10,6 @@ class CfgPatches {
|
||||
};
|
||||
};
|
||||
|
||||
#include "CfgUI.hpp"
|
||||
|
||||
#include "CfgEventhandlers.hpp"
|
||||
#include "CfgWeapons.hpp"
|
||||
#include "CfgVehicles.hpp"
|
||||
|
30
addons/laser_selfdesignate/functions/fnc_findLaserSource.sqf
Normal file
30
addons/laser_selfdesignate/functions/fnc_findLaserSource.sqf
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Author: jaynus
|
||||
* Handler function for laser network code.
|
||||
*
|
||||
* Argument:
|
||||
* 0: Emitter
|
||||
* 1: Owner
|
||||
*
|
||||
* Return value:
|
||||
* [position, direction]
|
||||
*/
|
||||
//findLaserSource.sqf
|
||||
//#define DEBUG_MODE_FULL
|
||||
#include "script_component.hpp"
|
||||
|
||||
private["_emitter", "_owner", "_gunnerInfo", "_turretInfo", "_povPos", "_povDir"];
|
||||
|
||||
_emmiter = _this select 0;
|
||||
_owner = _this select 1;
|
||||
|
||||
_gunnerInfo = [_emmiter, (currentWeapon _emmiter)] call CBA_fnc_getFirer;
|
||||
_turretInfo = [_emmiter, _gunnerInfo select 1] call EFUNC(common,getTurretDirection);
|
||||
_povPos = _turretInfo select 0;
|
||||
_povDir = _turretInfo select 1;
|
||||
|
||||
if(!isNil "_povPos" && !isNil "_povDir") exitWith {
|
||||
[_povPos, _povDir]
|
||||
};
|
||||
|
||||
[-1,-1]
|
@ -1,28 +1,25 @@
|
||||
/*
|
||||
* Author: jaynus
|
||||
* Turns off passed laser self designation.
|
||||
*
|
||||
* Argument:
|
||||
* 0: Shooter, player shooting the laser
|
||||
* 1: LaserUUID, the UUID of the laser returned by EFUNC(laser,laserOn)
|
||||
* 2: Local laser target, unused.
|
||||
*
|
||||
* Return value:
|
||||
* true
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
|
||||
if( (count _this) > 2) then {
|
||||
EXPLODE_3_PVT(_this,_vehicle,_shooter,_laserTarget);
|
||||
// We got the optional vehicle list, clear the parameters
|
||||
_vehicle setVariable[QGVAR(currentTarget), [], true];
|
||||
EXPLODE_3_PVT(_this,_shooter,_laserUuid, _localLaserTarget);
|
||||
|
||||
[_laserUuid] call EFUNC(laser,laserOff);
|
||||
// @TODO: Nou gets to field all tickets about missing lasers.
|
||||
//deleteVehicle _localLaserTarget;
|
||||
};
|
||||
|
||||
if(isNil QGVAR(laser)) exitWith {
|
||||
false
|
||||
};
|
||||
if(!local GVAR(laser)) then {
|
||||
false
|
||||
};
|
||||
|
||||
_handle = GVAR(laser) getVariable ["ACE_PFH_HANDLE", nil];
|
||||
if(!isNil "_handle") then {
|
||||
[_handle] call cba_fnc_removePerFrameHandler;
|
||||
};
|
||||
|
||||
REM(ACE_LASERS, GVAR(laser));
|
||||
deleteVehicle GVAR(laser);
|
||||
GVAR(laser) = nil;
|
||||
GVAR(active) = false;
|
||||
|
||||
|
||||
|
||||
true
|
@ -1,4 +1,14 @@
|
||||
//#define DEBUG_MODE_FULL
|
||||
/*
|
||||
* Author: jaynus
|
||||
* Turns on laser self designation from this vehicle based on the turret.
|
||||
* There are no arguments, because it is all strictly based on the users vehicle.
|
||||
*
|
||||
* Argument:
|
||||
*
|
||||
* Return value:
|
||||
* N/A
|
||||
*/
|
||||
//#define DEBUG_MODE_FULL
|
||||
#include "script_component.hpp"
|
||||
|
||||
TRACE_1("enter", _this);
|
||||
@ -6,102 +16,74 @@ TRACE_1("enter", _this);
|
||||
#define FCS_UPDATE_DELAY 1
|
||||
|
||||
FUNC(laserHudDesignatePFH) = {
|
||||
private["_strongestResultPos", "_args", "_laserTarget", "_shooter", "_vehicle", "_weapon", "_gunnerInfo", "_turret", "_pov", "_gunBeg", "_gunEnd", "_povPos", "_povDir", "_result", "_resultPositions", "_firstResult", "_forceUpdateTime"];
|
||||
private["_strongestResultPos", "_args", "_localLaserTarget", "_laserResultPosition", "_laserResult", "_shooter", "_vehicle", "_weapon", "_gunnerInfo", "_turretInfo", "_pov", "_gunBeg", "_gunEnd", "_povPos", "_povDir", "_result", "_resultPositions", "_firstResult", "_forceUpdateTime"];
|
||||
_args = _this select 0;
|
||||
_laserTarget = _args select 0;
|
||||
_shooter = _args select 1;
|
||||
|
||||
TRACE_1("", _args, (_laserTarget getVariable["ACE_LASER_CODE"]));
|
||||
|
||||
if((vehicle ACE_player) != _shooter || !alive _shooter || isNull _vehicle || isNull _laserTarget || !GVAR(active) ) exitWith {
|
||||
[_vehicle, _shooter, _laserTarget] call FUNC(laserHudDesignateOff);
|
||||
_shooter = _args select 0;
|
||||
_localLaserTarget = _args select 2;
|
||||
_vehicle = vehicle _shooter;
|
||||
TRACE_1("", _args);
|
||||
|
||||
if((vehicle _shooter) == _shooter || {!alive _shooter} || {isNull _vehicle} || {!GVAR(active)} ) exitWith {
|
||||
_args call FUNC(laserHudDesignateOff);
|
||||
};
|
||||
if(!([_shooter] call FUNC(unitTurretHasDesignator)) ) exitWith {
|
||||
[_vehicle, _shooter, _laserTarget] call FUNC(laserHudDesignateOff);
|
||||
_args call FUNC(laserHudDesignateOff);
|
||||
};
|
||||
|
||||
if( (count _args) < 3) then {
|
||||
_args set[2, diag_tickTime + FCS_UPDATE_DELAY];
|
||||
if( (count _args) < 4) then {
|
||||
_args set[3, diag_tickTime + FCS_UPDATE_DELAY];
|
||||
};
|
||||
_forceUpdateTime = _args select 2;
|
||||
_forceUpdateTime = _args select 3;
|
||||
|
||||
// @TODO: We don't have anything here we need to do the calculations for right now
|
||||
/*
|
||||
|
||||
_vehicle = vehicle _shooter;
|
||||
_weapon = currentWeapon _vehicle;
|
||||
|
||||
// Retrieve the gunner and turret memory point information
|
||||
_gunnerInfo = [_vehicle, _weapon] call CBA_fnc_getFirer;
|
||||
_gunnerInfo = [_vehicle, (currentWeapon _vehicle)] call CBA_fnc_getFirer;
|
||||
_turretInfo = [_vehicle, _gunnerInfo select 1] call EFUNC(common,getTurretDirection);
|
||||
_povPos = _turretInfo select 0;
|
||||
_povDir = _turretInfo select 1;
|
||||
|
||||
_targetInfo = _vehicle getVariable[QGVAR(currentTarget), [] ];
|
||||
if( (count _targetInfo) > 0) then {
|
||||
if(_laserTarget != (_targetInfo select 0) ) then {
|
||||
_targetInfo = []
|
||||
};
|
||||
};
|
||||
if( (count _targetInfo) < 1) then {
|
||||
_targetInfo = [_laserTarget, 1001]; // TODO: set laser code
|
||||
_vehicle setVariable[QGVAR(currentTarget), _targetInfo, true];
|
||||
_laserTarget setVariable[QGVAR(owner), _vehicle, true];
|
||||
};
|
||||
_laserCode = (vehicle ACE_player) getVariable[QGVAR(currentCode), ACE_DEFAULT_LASER_CODE];
|
||||
_waveLength = (vehicle ACE_player) getVariable[QGVAR(currentWaveLength), ACE_DEFAULT_LASER_WAVELENGTH];
|
||||
|
||||
|
||||
_result = [_povPos, _povDir] call EFUNC(laser,shootCone);
|
||||
if((count _result) > 0) then {
|
||||
_resultPositions = _result select 2;
|
||||
_laserResult = [_povPos, [_waveLength,_waveLength], _laserCode] call EFUNC(laser,seekerFindLaserSpot);
|
||||
_laserResultPosition = _laserResult select 0;
|
||||
TRACE_1("Search", _laserResult);
|
||||
|
||||
if((count _resultPositions) > 0) then {
|
||||
_strongestResultPos = [_resultPositions, _povPos] call EFUNC(laser,findStrongestRay);
|
||||
|
||||
// If the laser has moved less than a half meter, then dont move it.
|
||||
// Just regular use of lasers will commonly make them move this much,
|
||||
// but not across multiple close frames.
|
||||
// This loses accuracy a little, but saves position updates per frame.
|
||||
TRACE_5("", diag_tickTime, _forceUpdateTime, getPosASL _laserTarget, _strongestResultPos, ((getPosASL _laserTarget) distance _pos));
|
||||
if((count _laserResult) > 0) then {
|
||||
// @TODO: Nou gets to field all tickets about missing lasers.
|
||||
//_localLaserTarget setPosASL _laserResultPosition;
|
||||
};
|
||||
*/
|
||||
|
||||
if(diag_tickTime > _forceUpdateTime) then {
|
||||
TRACE_1("FCS Update", "");
|
||||
["ace_fcs_forceUpdate", []] call ace_common_fnc_localEvent;
|
||||
};
|
||||
|
||||
//if( (_laserTarget distance _strongestResultPos) > 0.1) then {
|
||||
TRACE_1("LaserPos Update", "");
|
||||
_laserTarget setPosATL (ASLToATL _strongestResultPos);
|
||||
//};
|
||||
|
||||
if(diag_tickTime > _forceUpdateTime) then {
|
||||
_args set[2, diag_tickTime + FCS_UPDATE_DELAY];
|
||||
};
|
||||
#ifdef DEBUG_MODE_FULL
|
||||
drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [1,0,0,1], (getPosATL _laserTarget), 0.75, 0.75, 0, "", 0.5, 0.025, "TahomaB"];
|
||||
|
||||
{
|
||||
private["_position"];
|
||||
_position = _x select 0;
|
||||
drawLine3d [ASLToATL _povPos, ASLToATL _position, [0,0,1,1] ];
|
||||
} forEach _resultPositions;
|
||||
#endif
|
||||
};
|
||||
if(diag_tickTime > _forceUpdateTime) then {
|
||||
["ace_fcs_forceUpdate", []] call ace_common_fnc_localEvent;
|
||||
_args set[3, diag_tickTime + FCS_UPDATE_DELAY];
|
||||
};
|
||||
|
||||
_this set[0, _args];
|
||||
};
|
||||
|
||||
private ["_laserTarget", "_handle", "_vehicle"];
|
||||
private ["_laserTarget", "_handle", "_vehicle", "_laserUuid", "_waveLength", "_beamSpread", "_laserCode"];
|
||||
|
||||
if(isNil QGVAR(laser)) then {
|
||||
_laserTarget = "LaserTargetW" createVehicle (getpos ACE_player);
|
||||
|
||||
if(!GVAR(active)) then {
|
||||
GVAR(active) = true;
|
||||
|
||||
_handle = [FUNC(laserHudDesignatePFH), 0.1, [_laserTarget, ACE_player]] call cba_fnc_addPerFrameHandler;
|
||||
_laserTarget setVariable ["ACE_PFH_HANDLE", _handle, false];
|
||||
TRACE_1("Activating laser", "");
|
||||
|
||||
// Clear the vehicle parameters
|
||||
_vehicle setVariable[QGVAR(currentTarget), [], true];
|
||||
// Get the self-designation variables, or use defaults
|
||||
_laserCode = (vehicle ACE_player) getVariable[QGVAR(currentCode), ACE_DEFAULT_LASER_CODE];
|
||||
_waveLength = (vehicle ACE_player) getVariable[QGVAR(currentWaveLength), ACE_DEFAULT_LASER_WAVELENGTH];
|
||||
_beamSpread = (vehicle ACE_player) getVariable[QGVAR(currentBeamSpread), ACE_DEFAULT_LASER_BEAMSPREAD];
|
||||
|
||||
GVAR(laser) = _laserTarget;
|
||||
_laserUuid = [(vehicle ACE_player), ACE_player, QFUNC(findLaserSource), _waveLength, _laserCode, _beamSpread] call EFUNC(laser,laserOn);
|
||||
|
||||
// @TODO: Create the local target for the players side
|
||||
// @TODO: Nou gets to field all tickets about missing lasers.
|
||||
//_localLaserTarget = "LaserTargetW" createVehicleLocal (getpos ACE_player);
|
||||
|
||||
_handle = [FUNC(laserHudDesignatePFH), 0.1, [ACE_player, _laserUuid, nil]] call cba_fnc_addPerFrameHandler;
|
||||
} else {
|
||||
[] call FUNC(laserHudDesignateOff);
|
||||
[] call FUNC(laserHudDesignateOn);
|
||||
|
@ -3,6 +3,9 @@
|
||||
PREP(rotateVectLineGetMap);
|
||||
PREP(rotateVectLine);
|
||||
|
||||
PREP(checkSeekerAngle);
|
||||
PREP(checkLos);
|
||||
|
||||
PREP(fired);
|
||||
|
||||
PREP(guidancePFH);
|
||||
|
29
addons/missileguidance/functions/fnc_checkLos.sqf
Normal file
29
addons/missileguidance/functions/fnc_checkLos.sqf
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Author: jaynus
|
||||
* Returns whether the seeker object can see the target position with lineIntersect
|
||||
*
|
||||
* Argument:
|
||||
* 0: Seeker [Object]
|
||||
* 1: Target [Object]
|
||||
*
|
||||
* Return value:
|
||||
* Boolean
|
||||
*/
|
||||
#include "script_component.hpp"
|
||||
private["_seeker", "_seekerPos", "_target", "_targetPos", "_return", "_vectorTo", "_searchPos"];
|
||||
_seeker = _this select 0;
|
||||
_target = _this select 1;
|
||||
|
||||
_targetPos = getPosASL _target;
|
||||
_seekerPos = getPosASL _seeker;
|
||||
_return = true;
|
||||
|
||||
if(!(terrainIntersectASL [ _seekerPos, _targetPos])) then {
|
||||
if(lineIntersects [_seekerPos, _targetPos, _seeker, _target]) then {
|
||||
_return = false;
|
||||
};
|
||||
} else {
|
||||
_return = false;
|
||||
};
|
||||
|
||||
_return;
|
50
addons/missileguidance/functions/fnc_checkSeekerAngle.sqf
Normal file
50
addons/missileguidance/functions/fnc_checkSeekerAngle.sqf
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Author: jaynus
|
||||
* Returns whether the target position is within the maximum angle FOV of the provided seeker
|
||||
* objects current direction.
|
||||
*
|
||||
* Argument:
|
||||
* 0: Seeker [Object]
|
||||
* 1: Target [Position]
|
||||
* 2: Max Angle [Degrees]
|
||||
*
|
||||
* Return value:
|
||||
* Boolean
|
||||
*/
|
||||
|
||||
#define DEBUG_MODE_FULL
|
||||
#include "script_component.hpp"
|
||||
private["_seeker", "_targetPos", "_seekerMaxAngle", "_vectorTo", "_sensorPos", "_vertOk", "_horzOk", "_dir", "_headingPitch"];
|
||||
|
||||
_seeker = _this select 0;
|
||||
_targetPos = _this select 1;
|
||||
_seekerMaxAngle = _this select 2;
|
||||
|
||||
_vertOk = false;
|
||||
_horzOk = false;
|
||||
|
||||
_sensorPos = getPosASL _seeker;
|
||||
_vectorTo = _sensorPos vectorFromTo _targetPos;
|
||||
|
||||
_headingPitch = (vectorDir _seeker) call CBA_fnc_vect2polar;
|
||||
_polarTo = _vectorTo call CBA_fnc_vect2polar;
|
||||
|
||||
_dir = _polarTo select 1;
|
||||
_dir = _dir - (_headingPitch select 1);
|
||||
|
||||
if (_dir < 0) then {_dir = _dir + 360};
|
||||
if (_dir > 360) then {_dir = _dir - 360};
|
||||
_vertOk = false;
|
||||
_horzOk = false;
|
||||
if(_dir < _angleFov || {_dir > (360-_angleFov)}) then {
|
||||
_horzOk = true;
|
||||
};
|
||||
if(abs((abs(_polarTo select 2))-(abs(_headingPitch select 2))) < _angleFov) then {
|
||||
_vertOk = true;
|
||||
};
|
||||
|
||||
if(!_vertOk || !_horzOk ) exitWith {
|
||||
false
|
||||
};
|
||||
|
||||
true
|
@ -19,14 +19,31 @@ if(!isNil "_target") then {
|
||||
_foundTargetPos = getPosASL _target;
|
||||
};
|
||||
|
||||
TRACE_2("", _target, _foundTargetPos);
|
||||
/* @TODO: This is seeker LOS and angle checks for LOAL only; LOBL does not need visual
|
||||
_angleFov = _seekerParams select 0;
|
||||
_angleOkay = [_projectile, _foundTargetPos, _angleFov] call FUNC(checkSeekerAngle);
|
||||
|
||||
_projectileSpeed = (vectorMagnitude velocity _projectile);
|
||||
_distanceToTarget = (getPosASL _projectile) vectorDistance _foundTargetPos;
|
||||
_losOkay = false;
|
||||
if(_angleOkay) then {
|
||||
_losOkay = [_projectile, _target] call FUNC(checkSeekerLos);
|
||||
};
|
||||
TRACE_2("", _angleOkay, _losOkay);
|
||||
|
||||
_eta = _distanceToTarget / _projectileSpeed;
|
||||
// If we got here, it was an invalid target, just return a spot 5m in front of the missile
|
||||
if(!_angleOkay || !_losOkay) then {
|
||||
_foundTargetPos = _sensorPos vectorAdd ((velocity _projectile) vectorMultiply 5);
|
||||
} else {
|
||||
TRACE_2("", _target, _foundTargetPos);
|
||||
|
||||
_adjustVelocity = (velocity _target) vectorMultiply _eta;
|
||||
_foundTargetPos = _foundTargetPos vectorAdd _adjustVelocity;
|
||||
// @TODO: Configurable lead for seekers
|
||||
_projectileSpeed = (vectorMagnitude velocity _projectile);
|
||||
_distanceToTarget = (getPosASL _projectile) vectorDistance _foundTargetPos;
|
||||
|
||||
_eta = _distanceToTarget / _projectileSpeed;
|
||||
|
||||
_adjustVelocity = (velocity _target) vectorMultiply _eta;
|
||||
_foundTargetPos = _foundTargetPos vectorAdd _adjustVelocity;
|
||||
};
|
||||
|
||||
*/
|
||||
_foundTargetPos;
|
@ -2,16 +2,25 @@
|
||||
#include "script_component.hpp"
|
||||
|
||||
EXPLODE_7_PVT(((_this select 1) select 0),_shooter,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile);
|
||||
private["_targets", "_foundTargetPos", "_launchParams", "_seekerParams", "_targetLaunchParams"];
|
||||
|
||||
_seekerTargetPos = _this select 0;
|
||||
|
||||
_launchParams = _this select 1;
|
||||
_seekerParams = _launchParams select 3;
|
||||
|
||||
// TODO: this needs to be shootCone/findStrongestRay after testing
|
||||
_targets = [_projectile, ACE_DEFAULT_LASER_CODE, (_seekerParams select 0)] call ace_laser_fnc_findLaserDesignator;
|
||||
_foundTargetPos = getPosASL (_targets select 1);
|
||||
_laserResult = [(getPosASL _projectile), [ACE_DEFAULT_LASER_WAVELENGTH,ACE_DEFAULT_LASER_WAVELENGTH], ACE_DEFAULT_LASER_CODE] call EFUNC(laser,seekerFindLaserSpot);
|
||||
_foundTargetPos = _laserResult select 0;
|
||||
TRACE_1("Search", _laserResult);
|
||||
|
||||
|
||||
if(!isNil "_foundTargetPos") then {
|
||||
_angleFov = _seekerParams select 0;
|
||||
_canSeeTarget = [_projectile, _foundTargetPos, _angleFov] call FUNC(checkSeekerAngle);
|
||||
|
||||
// If we got here, it was an invalid target, just return a spot 5m in front of the missile
|
||||
if(!_canSeeTarget) then {
|
||||
_foundTargetPos = _sensorPos vectorAdd ((velocity _projectile) vectorMultiply 5);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
TRACE_1("Seeker return target pos", _foundTargetPos);
|
||||
_foundTargetPos;
|
Loading…
Reference in New Issue
Block a user