mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
remove doppler
This commit is contained in:
parent
46aa1ae70c
commit
87c819f2c3
@ -88,14 +88,6 @@ class GVAR(SeekerTypes) {
|
||||
functionName = QFUNC(seekerType_MWR);
|
||||
onFired = QFUNC(mwr_onFired);
|
||||
};
|
||||
class DopplerRadar {
|
||||
name = "";
|
||||
visualName = "";
|
||||
description = "";
|
||||
|
||||
functionName = QFUNC(seekerType_Doppler);
|
||||
onFired = QFUNC(doppler_onFired);
|
||||
};
|
||||
};
|
||||
|
||||
class GVAR(NavigationTypes) {
|
||||
|
@ -51,7 +51,6 @@ PREP(wire_onFired);
|
||||
|
||||
// Seeker OnFired
|
||||
PREP(SACLOS_onFired);
|
||||
PREP(doppler_onFired);
|
||||
PREP(mwr_onFired);
|
||||
|
||||
// Navigation OnFired
|
||||
|
@ -1,83 +0,0 @@
|
||||
#include "..\script_component.hpp"
|
||||
/*
|
||||
* Author: tcvm
|
||||
* Sets up doppler radar state arrays (called from missileGuidance's onFired).
|
||||
*
|
||||
* Arguments:
|
||||
* Guidance Arg Array <ARRAY>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [] call ace_missileguidance_fnc_mwr_onFired
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
params ["_firedEH", "_launchParams", "", "", "_stateParams"];
|
||||
_firedEH params ["_shooter","","","","","","_projectile"];
|
||||
_stateParams params ["", "_seekerStateParams"];
|
||||
_launchParams params ["","_targetLaunchParams"];
|
||||
_targetLaunchParams params ["_target"];
|
||||
|
||||
if (isNull _target && isVehicleRadarOn vehicle _shooter) then {
|
||||
_target = cursorTarget;
|
||||
};
|
||||
// always allow tracking of projectiles
|
||||
if !(_target isKindOf "AllVehicles" || { (typeOf _target) isKindOf ["Default", configFile >> "CfgAmmo"] }) then {
|
||||
_target = nil;
|
||||
};
|
||||
_launchParams set [0, _target];
|
||||
_projectile setMissileTarget objNull; // to emulate a no launch warning
|
||||
|
||||
private _projectileConfig = configOf _projectile;
|
||||
private _config = _projectileConfig >> "ace_missileguidance";
|
||||
|
||||
private _isActive = false;
|
||||
private _activeRadarDistance = [_config >> "activeRadarEngageDistance", "NUMBER", 500] call CBA_fnc_getConfigEntry;
|
||||
private _projectileThrust = [_projectileConfig >> "thrust", "NUMBER", 0] call CBA_fnc_getConfigEntry;
|
||||
private _projectileThrustTime = [_projectileConfig >> "thrustTime", "NUMBER", 0] call CBA_fnc_getConfigEntry;
|
||||
|
||||
private _lockTypes = [_config >> "lockableTypes", "ARRAY", ["Air", "LandVehicle", "Ship"]] call CBA_fnc_getConfigEntry;
|
||||
|
||||
private _minimumFilterSpeed = [_config >> "minimumSpeedFilter", "NUMBER", 30] call CBA_fnc_getConfigEntry;
|
||||
private _minimumFilterTime = [_config >> "minimumTimeFilter", "NUMBER", 1e-4] call CBA_fnc_getConfigEntry;
|
||||
private _maxTerrainCheck = [_config >> "maxTerrainCheck", "NUMBER", 16000] call CBA_fnc_getConfigEntry;
|
||||
|
||||
private _velocityAtImpact = _projectileThrust * _projectileThrustTime;
|
||||
private _timeToActive = 0;
|
||||
if (!isNil "_target" && _velocityAtImpact > 0) then {
|
||||
private _distanceUntilActive = (((getPosASL _shooter) vectorDistance (getPosASL _target)) - _activeRadarDistance);
|
||||
_timeToActive = 0 max (_distanceUntilActive / _velocityAtImpact);
|
||||
};
|
||||
|
||||
if (isNil "_target") then {
|
||||
_timeToActive = 0;
|
||||
_isActive = true;
|
||||
_target = objNull;
|
||||
};
|
||||
|
||||
private _shooterHasActiveRadar = {
|
||||
if ("ActiveRadarSensorComponent" in _x) exitWith { true };
|
||||
false
|
||||
} forEach listVehicleSensors vehicle _shooter;
|
||||
|
||||
if !(isVehicleRadarOn vehicle _shooter) then {
|
||||
_isActive = true;
|
||||
};
|
||||
|
||||
_seekerStateParams set [0, _isActive];
|
||||
_seekerStateParams set [1, _activeRadarDistance];
|
||||
_seekerStateParams set [2, CBA_missionTime + _timeToActive];
|
||||
_seekerStateParams set [3, getPosASL _target];
|
||||
_seekerStateParams set [4, CBA_missionTime];
|
||||
_seekerStateParams set [5, _shooterHasActiveRadar];
|
||||
_seekerStateParams set [6, false];
|
||||
_seekerStateParams set [7, [0, 0, 0]];
|
||||
_seekerStateParams set [8, CBA_missionTime];
|
||||
_seekerStateParams set [9, isNull _target];
|
||||
_seekerStateParams set [10, _lockTypes];
|
||||
_seekerStateParams set [11, _minimumFilterSpeed];
|
||||
_seekerStateParams set [12, _minimumFilterTime];
|
||||
_seekerStateParams set [13, _maxTerrainCheck];
|
||||
|
@ -1,163 +0,0 @@
|
||||
#include "..\script_component.hpp"
|
||||
/*
|
||||
* Author: tcvm
|
||||
* doppler radar seeker
|
||||
*
|
||||
* Arguments:
|
||||
* 1: Guidance Arg Array <ARRAY>
|
||||
* 2: Seeker State <ARRAY>
|
||||
*
|
||||
* Return Value:
|
||||
* Seeker Pos <ARRAY>
|
||||
*
|
||||
* Example:
|
||||
* [] call call ace_missileguidance_fnc_seekerType_MWR;
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
params ["", "_args", "_seekerStateParams", "", "_timestep"];
|
||||
_args params ["_firedEH", "_launchParams", "", "_seekerParams", "_stateParams", "_targetData"];
|
||||
_firedEH params ["_shooter","","","","","","_projectile"];
|
||||
_launchParams params ["_target","","","",""];
|
||||
_seekerParams params ["_seekerAngle", "", "_seekerMaxRange"];
|
||||
_seekerStateParams params ["_isActive", "_activeRadarEngageDistance", "_timeWhenActive", "_expectedTargetPos", "_lastTargetPollTime", "_shooterHasRadar", "_wasActive", "_lastKnownVelocity", "_lastTimeSeen", "_doesntHaveTarget", "_lockTypes", "_minimumFilterSpeed", "_minimumFilterTime", "_maxTerrainCheck"];
|
||||
|
||||
if (_isActive || { CBA_missionTime >= _timeWhenActive }) then {
|
||||
if !(_isActive) then {
|
||||
_seekerStateParams set [0, true];
|
||||
};
|
||||
if !(_wasActive) then {
|
||||
_seekerStateParams set [6, true];
|
||||
TRACE_1("Missile Pitbull",_seekerStateParams);
|
||||
};
|
||||
|
||||
// if we are tracking a projectile, don't bother with radar crap just fly to it
|
||||
if (!isNil "_target" || { !((typeOf _target) isKindOf ["Default", configFile >> "CfgAmmo"]) }) then {
|
||||
// Internal radar homing
|
||||
// For performance reasons only poll for target every so often instead of each frame
|
||||
if ((_lastTargetPollTime + ACTIVE_RADAR_POLL_FREQUENCY) - CBA_missionTime < 0) then {
|
||||
private _searchPos = _expectedTargetPos;
|
||||
if (_searchPos isEqualTo [0, 0, 0] || { _doesntHaveTarget }) then {
|
||||
_seekerStateParams set [9, true];
|
||||
// no target pos - shot without lock. Have the missile's radar search infront of it on the ground
|
||||
_searchPos = (getPosASL _projectile) vectorAdd (_projectile vectorModelToWorld [0, _seekerMaxRange, -((getPos _projectile)#2)]);
|
||||
};
|
||||
|
||||
_target = objNull;
|
||||
_lastTargetPollTime = CBA_missionTime;
|
||||
_seekerStateParams set [4, _lastTargetPollTime];
|
||||
private _distanceToExpectedTarget = _seekerMaxRange min ((getPosASL _projectile) vectorDistance _searchPos);
|
||||
|
||||
// Simulate how much the seeker can see at the ground
|
||||
private _projDir = vectorDir _projectile;
|
||||
private _projYaw = getDir _projectile;
|
||||
private _rotatedYaw = (+(_projDir select 0) * sin _projYaw) + (+(_projDir select 1) * cos _projYaw);
|
||||
if (_rotatedYaw isEqualTo 0) then { _rotatedYaw = 0.001 };
|
||||
private _projPitch = atan ((_projDir select 2) / _rotatedYaw);
|
||||
private _a1 = abs _projPitch;
|
||||
private _a2 = 180 - ((_seekerAngle / 2) + _a1);
|
||||
private _seekerBaseRadiusAtGround = ACTIVE_RADAR_MINIMUM_SCAN_AREA max (_distanceToExpectedTarget / sin(_a2) * sin(_seekerAngle / 2));
|
||||
|
||||
private _lastKnownSpeed = if (_lastKnownVelocity isEqualTo [0, 0, 0]) then {
|
||||
0
|
||||
} else {
|
||||
vectorMagnitude _lastKnownVelocity;
|
||||
};
|
||||
private _seekerBaseRadiusAdjusted = linearConversion [0, _seekerBaseRadiusAtGround, (CBA_missionTime - _lastTimeSeen) * vectorMagnitude _lastKnownVelocity, ACTIVE_RADAR_MINIMUM_SCAN_AREA, _seekerBaseRadiusAtGround, false];
|
||||
if (_doesntHaveTarget) then {
|
||||
_seekerBaseRadiusAdjusted = _seekerBaseRadiusAtGround;
|
||||
};
|
||||
// Look in front of seeker for any targets
|
||||
private _nearestObjects = nearestObjects [ASLtoAGL _searchPos, _lockTypes, _seekerBaseRadiusAdjusted, false];
|
||||
_nearestObjects = _nearestObjects apply {
|
||||
// I check both Line of Sight versions to make sure that a single bush doesnt make the target lock dissapear but at the same time ensure that this can see through smoke. Should work 80% of the time
|
||||
if ([_projectile, getPosASL _x, _seekerAngle] call FUNC(checkSeekerAngle) && { ([_projectile, _x, true] call FUNC(checkLOS)) || { ([_projectile, _x, false] call FUNC(checkLOS)) } }) then {
|
||||
|
||||
if !([_x, _projectile, _minimumFilterSpeed, _minimumFilterTime, _maxTerrainCheck, _seekerAngle] call FUNC(shouldFilterRadarHit)) exitWith {
|
||||
_x
|
||||
};
|
||||
objNull;
|
||||
} else {
|
||||
objNull
|
||||
};
|
||||
};
|
||||
_nearestObjects = _nearestObjects select { !isNull _x };
|
||||
// Select closest object to the expected position to be the current radar target
|
||||
if ((count _nearestObjects) <= 0) exitWith {
|
||||
_projectile setMissileTarget objNull;
|
||||
_seekerStateParams set [3, _searchPos];
|
||||
_searchPos
|
||||
};
|
||||
private _closestDistance = _seekerBaseRadiusAtGround;
|
||||
{
|
||||
if ((_x distance2d _searchPos) < _closestDistance) then {
|
||||
_closestDistance = _x distance2d _searchPos;
|
||||
_target = _x;
|
||||
};
|
||||
} forEach _nearestObjects;
|
||||
|
||||
_expectedTargetPos = _searchPos;
|
||||
};
|
||||
};
|
||||
} else {
|
||||
if (GVAR(debug_drawGuidanceInfo)) then {
|
||||
_seekerTypeName = "DOPPLER - EXT";
|
||||
};
|
||||
// External radar homing
|
||||
// if the target is in the remote targets for the side, whoever the donor is will "datalink" the target for the hellfire.
|
||||
private _remoteTargets = listRemoteTargets side _shooter;
|
||||
if ((_remoteTargets findIf { (_target in _x) && (_x#1 > 0) }) < 0) then {
|
||||
// I check both Line of Sight versions to make sure that a single bush doesnt make the target lock dissapear but at the same time ensure that this can see through smoke. Should work 80% of the time
|
||||
if (!_shooterHasRadar || { !isVehicleRadarOn vehicle _shooter } || { !alive vehicle _shooter } || { !([vehicle _shooter, _target, true] call FUNC(checkLOS)) && { !([vehicle _shooter, _target, false] call FUNC(checkLOS)) } }) then {
|
||||
_seekerStateParams set [0, true];
|
||||
_target = objNull; // set up state for active guidance
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
if (GVAR(debug_drawGuidanceInfo)) then {
|
||||
drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [1,0,0,1], ASLtoAGL _expectedTargetPos, 0.75, 0.75, 0, "expected target pos", 1, 0.025, "TahomaB"];
|
||||
};
|
||||
|
||||
if !(isNull _target) then {
|
||||
// we check if the target is moving away from us or perpendicular to see if we maintain lock
|
||||
private _centerOfObject = getCenterOfMass _target;
|
||||
private _targetAdjustedPos = _target modelToWorldVisualWorld _centerOfObject;
|
||||
_expectedTargetPos = _targetAdjustedPos;
|
||||
|
||||
private _filterTarget = [_target, _projectile, _minimumFilterSpeed, _minimumFilterTime, _maxTerrainCheck, _seekerAngle] call FUNC(shouldFilterRadarHit);
|
||||
if (_filterTarget) then {
|
||||
// filter out target
|
||||
_target = objNull;
|
||||
_seekerStateParams set [9, true];
|
||||
} else {
|
||||
private _lineOfSight = vectorDirVisual _projectile;
|
||||
private _realTargetVelocity = velocity _target;
|
||||
private _projectedTargetVelocity = _lineOfSight vectorMultiply (_realTargetVelocity vectorDotProduct _lineOfSight);
|
||||
private _relativeTargetVelocity = _realTargetVelocity vectorDiff _projectedTargetVelocity;
|
||||
|
||||
_seekerStateParams set [7, _relativeTargetVelocity];
|
||||
_seekerStateParams set [8, CBA_missionTime];
|
||||
_seekerStateParams set [9, false];
|
||||
|
||||
_targetData set [2, _projectile distance _target];
|
||||
_targetData set [3, _relativeTargetVelocity];
|
||||
|
||||
if (_timestep != 0) then {
|
||||
private _acceleration = (_relativeTargetVelocity vectorDiff _lastKnownVelocity) vectorMultiply (1 / _timestep);
|
||||
_targetData set [4, _acceleration];
|
||||
};
|
||||
};
|
||||
_projectile setMissileTarget _target;
|
||||
};
|
||||
|
||||
if (_expectedTargetPos isEqualTo [0, 0, 0]) then {
|
||||
_expectedTargetPos = (getPosASLVisual _projectile) vectorAdd velocity _projectile;
|
||||
};
|
||||
|
||||
_targetData set [0, (getPosASLVisual _projectile) vectorFromTo _expectedTargetPos];
|
||||
|
||||
_seekerStateParams set [3, _expectedTargetPos];
|
||||
_launchParams set [0, _target];
|
||||
_expectedTargetPos
|
||||
|
@ -1,133 +0,0 @@
|
||||
#include "..\script_component.hpp"
|
||||
/*
|
||||
* Author: tcvm
|
||||
* Whether or not we should filter out this target due to masking. Useful for only doppler radar types
|
||||
*
|
||||
* Arguments:
|
||||
* 0: Target <OBJECT>
|
||||
* 1: Projectile <OBJECT>
|
||||
* 2: Minimum speed for doppler return to filter out <NUMBER>
|
||||
* 3: Minimum time for doppler return to filter out <NUMBER>
|
||||
* 4: Maximum distance to check for terrain <NUMBER>
|
||||
* 5: Radar seeker angle <NUMBER>
|
||||
*
|
||||
* Return Value:
|
||||
* Whether or not to filter out this target <BOOL>
|
||||
*
|
||||
* Example:
|
||||
* [] call call ace_missileguidance_fnc_shouldFilterRadarHit;
|
||||
*
|
||||
* Public: Yes
|
||||
*/
|
||||
// as defined by lineIntersectsSurfaces
|
||||
#define MAX_LINE_DISTANCE 5000
|
||||
|
||||
params ["_target", "_projectile", "_minimumSpeed", "_minimumTime", "_maximumTerrainCheck", "_seekerAngle"];
|
||||
TRACE_5("should filter target",_projectile,_target,_minimumSpeed,_minimumTime,_maximumTerrainCheck);
|
||||
// Theory developed from doppler radar visuals at https://www.mudspike.com/dcs-f-15c-combat-guide-for-beginners/
|
||||
|
||||
// helicopter blades will always produce a doppler shift due to their nature. Don't filter
|
||||
if (_target isKindOf "Helicopter" && isEngineOn _target) exitWith {
|
||||
TRACE_2("dont filter helicopters",_target isKindOf "Helicopter",isEngineOn _target);
|
||||
false
|
||||
};
|
||||
|
||||
private _lineOfSight = (getPosASLVisual _projectile) vectorFromTo (getPosASLVisual _target);
|
||||
private _realTargetVelocity = velocity _target;
|
||||
private _closingVelocity = _lineOfSight vectorMultiply (_realTargetVelocity vectorDotProduct _lineOfSight);
|
||||
private _closingSpeed = vectorMagnitude _closingVelocity;
|
||||
|
||||
// if relative target velocity is greather than threshold, we can easily see it. Don't filter
|
||||
if (_closingSpeed > _minimumSpeed) exitWith {
|
||||
TRACE_2("dont filter fast objects approaching",_closingSpeed,_minimumSpeed);
|
||||
false
|
||||
};
|
||||
|
||||
private _projectilePos = getPosASLVisual _projectile;
|
||||
|
||||
private _stepDistance = _lineOfSight vectorMultiply (MAX_LINE_DISTANCE min _maximumTerrainCheck);
|
||||
|
||||
private _checkPos = _projectilePos;
|
||||
private _maskedByGround = false;
|
||||
|
||||
// Check for all surfaces until we reach our max range
|
||||
for "_i" from 0 to _maximumTerrainCheck step MAX_LINE_DISTANCE do {
|
||||
// determine if target is masked by ground
|
||||
private _endPos = _checkPos vectorAdd _stepDistance;
|
||||
private _groundHit = lineIntersectsSurfaces [_checkPos, _endPos, _projectile, _target];
|
||||
|
||||
_maskedByGround = _groundHit isNotEqualTo [];
|
||||
|
||||
_checkPos = _endPos;
|
||||
|
||||
if (_maskedByGround || (_checkPos select 2) <= 0) then {
|
||||
// for ease assume that we can't check underwater
|
||||
if ((_checkPos select 2) < 0) then {
|
||||
_checkPos set [2, 0];
|
||||
};
|
||||
break
|
||||
};
|
||||
};
|
||||
|
||||
// looking at sky, target is clear as day. Check for chaff before filtering
|
||||
if !(_maskedByGround) exitWith {
|
||||
TRACE_1("dont filter stuff in the sky",_maskedByGround);
|
||||
|
||||
// If there is chaff nearby, check if they will confuse missile
|
||||
private _nearby = _target nearObjects 50;
|
||||
_nearby = _nearby select {
|
||||
// 8 = radar blocking
|
||||
private _blocking = configOf _x >> "weaponLockSystem";
|
||||
private _isChaff = false;
|
||||
if (isNumber _blocking) then {
|
||||
_isChaff = (8 == getNumber _blocking);
|
||||
};
|
||||
|
||||
if (isText _blocking) then {
|
||||
_isChaff = ("8" in getText _blocking);
|
||||
};
|
||||
|
||||
private _withinView = [_projectile, getPosASLVisual _x, _seekerAngle] call FUNC(checkSeekerAngle);
|
||||
private _canSee = [_projectile, _x, false] call FUNC(checkLos);
|
||||
|
||||
(_withinView && _canSee && _isChaff)
|
||||
};
|
||||
|
||||
private _foundDecoy = false;
|
||||
{
|
||||
private _considering = false;
|
||||
if !(_foundDecoy) then {
|
||||
_considering = true;
|
||||
if (0.95 <= random 1) then {
|
||||
_foundDecoy = true;
|
||||
};
|
||||
};
|
||||
|
||||
if (GVAR(debug_drawGuidanceInfo)) then {
|
||||
private _chaffPos = ASLToAGL getPosASLVisual _x;
|
||||
private _colour = [1, 0, 0, 1];
|
||||
if (_considering) then {
|
||||
_colour = [0, 1, 0, 1];
|
||||
};
|
||||
if (_foundDecoy) then {
|
||||
_colour = [0, 0, 1, 1];
|
||||
};
|
||||
drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", _colour, _chaffPos, 0.75, 0.75, 0, "C", 1, 0.025, "TahomaB"];
|
||||
};
|
||||
} forEach _nearby;
|
||||
|
||||
_foundDecoy
|
||||
};
|
||||
|
||||
private _distanceToTerrain = _checkPos vectorDistance _projectilePos;
|
||||
private _checkTime = _distanceToTerrain / 3e8;
|
||||
|
||||
// Time to ground is large enough to know if we are looking at a target, don't filter
|
||||
if (_checkTime > _minimumTime) exitWith {
|
||||
TRACE_2("dont filter targets that we can see in ground clutter",_checkTime,_minimumTime);
|
||||
false
|
||||
};
|
||||
|
||||
// filter out the target since we can't reasonably see it
|
||||
true
|
||||
|
Loading…
Reference in New Issue
Block a user