Update doppler seeker to allow the tracking and killing of projectiles

This commit is contained in:
Brandon Danyluk 2021-05-18 03:44:05 -06:00
parent 36d75765c6
commit f7bd523221
2 changed files with 62 additions and 59 deletions

View File

@ -20,7 +20,6 @@ _stateParams params ["", "_seekerStateParams"];
_launchParams params ["","_targetLaunchParams"];
_targetLaunchParams params ["_target"];
_target = missileTarget _projectile;
if (isNull _target && isVehicleRadarOn vehicle _shooter) then {
_target = cursorTarget;
};

View File

@ -31,70 +31,73 @@ if (_isActive || { CBA_missionTime >= _timeWhenActive }) then {
TRACE_1("Missile Pitbull",_seekerStateParams);
};
// 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)]);
};
// 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);
_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));
// 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;
private _lastKnownSpeed = if (_lastKnownVelocity isEqualTo [0, 0, 0]) then {
0
} else {
objNull
vectorMagnitude _lastKnownVelocity;
};
};
_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;
private _seekerBaseRadiusAdjusted = linearConversion [0, _seekerBaseRadiusAtGround, (CBA_missionTime - _lastTimeSeen) * vectorMagnitude _lastKnownVelocity, ACTIVE_RADAR_MINIMUM_SCAN_AREA, _seekerBaseRadiusAtGround, false];
if (_doesntHaveTarget) then {
_seekerBaseRadiusAdjusted = _seekerBaseRadiusAtGround;
};
} forEach _nearestObjects;
_expectedTargetPos = _searchPos;
// 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 {
@ -125,6 +128,7 @@ if !(isNull _target) then {
private _filterTarget = [_target, _projectile, _minimumFilterSpeed, _minimumFilterTime, _maxTerrainCheck, _seekerAngle] call FUNC(shouldFilterRadarHit);
if (_filterTarget) then {
// filter out target
systemChat "filter";
_target = objNull;
_seekerStateParams set [9, true];
} else {