mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
Hellfire - Update to new framework (#10028)
This commit is contained in:
parent
4d088fd828
commit
fad9244104
@ -26,9 +26,8 @@ class CfgAmmo {
|
|||||||
class ace_missileguidance {
|
class ace_missileguidance {
|
||||||
enabled = 1;
|
enabled = 1;
|
||||||
|
|
||||||
minDeflection = 0.0005; // Minium flap deflection for guidance
|
pitchRate = 30; // degrees per second
|
||||||
maxDeflection = 0.01; // Maximum flap deflection for guidance
|
yawRate = 30;
|
||||||
incDeflection = 0.0005; // The incrmeent in which deflection adjusts.
|
|
||||||
|
|
||||||
canVanillaLock = 0; // Can this default vanilla lock? Only applicable to non-cadet mode
|
canVanillaLock = 0; // Can this default vanilla lock? Only applicable to non-cadet mode
|
||||||
|
|
||||||
@ -39,6 +38,9 @@ class CfgAmmo {
|
|||||||
defaultSeekerLockMode = "LOAL";
|
defaultSeekerLockMode = "LOAL";
|
||||||
seekerLockModes[] = { "LOAL", "LOBL" };
|
seekerLockModes[] = { "LOAL", "LOBL" };
|
||||||
|
|
||||||
|
defaultNavigationType = "Direct";
|
||||||
|
navigationTypes[] = { "Direct", "ZeroEffortMiss" };
|
||||||
|
|
||||||
seekLastTargetPos = 1; // seek last target position [if seeker loses LOS of target, continue to last known pos]
|
seekLastTargetPos = 1; // seek last target position [if seeker loses LOS of target, continue to last known pos]
|
||||||
seekerAngle = 70; // Angle in front of the missile which can be searched
|
seekerAngle = 70; // Angle in front of the missile which can be searched
|
||||||
seekerAccuracy = 1; // seeker accuracy multiplier
|
seekerAccuracy = 1; // seeker accuracy multiplier
|
||||||
@ -49,6 +51,19 @@ class CfgAmmo {
|
|||||||
// Attack profile type selection
|
// Attack profile type selection
|
||||||
defaultAttackProfile = "hellfire";
|
defaultAttackProfile = "hellfire";
|
||||||
attackProfiles[] = {"hellfire", "hellfire_hi", "hellfire_lo"};
|
attackProfiles[] = {"hellfire", "hellfire_hi", "hellfire_lo"};
|
||||||
|
|
||||||
|
class navigationStates {
|
||||||
|
class initial {
|
||||||
|
transitionCondition = QFUNC(midCourseTransition);
|
||||||
|
navigationType = "Direct";
|
||||||
|
};
|
||||||
|
class terminal {
|
||||||
|
transitionCondition = "";
|
||||||
|
navigationType = "ZeroEffortMiss";
|
||||||
|
};
|
||||||
|
// transitions from initial -> termimal
|
||||||
|
states[] = {"initial", "terminal"};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
class ACE_Hellfire_AGM114N: ACE_Hellfire_AGM114K {
|
class ACE_Hellfire_AGM114N: ACE_Hellfire_AGM114K {
|
||||||
@ -75,8 +90,8 @@ class CfgAmmo {
|
|||||||
canVanillaLock = 1;
|
canVanillaLock = 1;
|
||||||
enabled = 1; // Missile Guidance must be explicitly enabled
|
enabled = 1; // Missile Guidance must be explicitly enabled
|
||||||
seekLastTargetPos = 0;
|
seekLastTargetPos = 0;
|
||||||
defaultSeekerType = "ARH";
|
defaultSeekerType = "MillimeterWaveRadar";
|
||||||
seekerTypes[] = { "ARH" };
|
seekerTypes[] = { "MillimeterWaveRadar" };
|
||||||
defaultSeekerLockMode = "LOBL";
|
defaultSeekerLockMode = "LOBL";
|
||||||
seekerLockModes[] = { "LOBL" };
|
seekerLockModes[] = { "LOBL" };
|
||||||
|
|
||||||
|
@ -2,3 +2,4 @@ LOG("prep");
|
|||||||
PREP(attackProfile);
|
PREP(attackProfile);
|
||||||
PREP(getAttackProfileSettings);
|
PREP(getAttackProfileSettings);
|
||||||
PREP(setupVehicle);
|
PREP(setupVehicle);
|
||||||
|
PREP(midCourseTransition);
|
||||||
|
@ -18,80 +18,99 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
params ["_seekerTargetPos", "_args", "_attackProfileStateParams"];
|
params ["_seekerTargetPos", "_args", "_attackProfileStateParams"];
|
||||||
_args params ["_firedEH", "_launchParams", "", "", "_stateParams"];
|
_args params ["_firedEH", "_launchParams", "_flightParams", "", "_stateParams"];
|
||||||
_stateParams params ["", "_seekerStateParams"];
|
_stateParams params ["", "_seekerStateParams"];
|
||||||
_launchParams params ["","_targetLaunchParams","_seekerType"];
|
_launchParams params ["","_targetLaunchParams","_seekerType"];
|
||||||
|
|
||||||
_targetLaunchParams params ["", "", "_launchPos"];
|
_targetLaunchParams params ["", "", "_launchPos", "_launchDir"];
|
||||||
_firedEH params ["","","","","","","_projectile"];
|
_firedEH params ["","","","","","","_projectile"];
|
||||||
|
|
||||||
// Get state params:
|
// Get state params:
|
||||||
if (_attackProfileStateParams isEqualTo []) then {
|
if (_attackProfileStateParams isEqualTo []) then {
|
||||||
_this call FUNC(getAttackProfileSettings);
|
_this call FUNC(getAttackProfileSettings);
|
||||||
};
|
};
|
||||||
_attackProfileStateParams params ["_attackStage", "_configLaunchHeightClear"];
|
_attackProfileStateParams params ["_attackStage", "_configLaunchHeightClear", "_missileStateData"];
|
||||||
|
|
||||||
|
|
||||||
private _projectilePos = getPosASL _projectile;
|
private _projectilePos = getPosASL _projectile;
|
||||||
private _distanceFromLaunch2d = _launchPos distance2d _projectilePos;
|
private _distanceFromLaunch2d = _launchPos distance2d _projectilePos;
|
||||||
private _heightAboveLaunch = (_projectilePos select 2) - (_launchPos select 2);
|
private _heightAboveLaunch = (_projectilePos select 2) - (_launchPos select 2);
|
||||||
|
|
||||||
// Add height depending on distance for compensate
|
// Add height depending on distance for compensate
|
||||||
private _returnTargetPos = nil;
|
private _returnTargetPos = _seekerTargetPos;
|
||||||
|
if (_returnTargetPos isEqualTo [0, 0, 0]) then {
|
||||||
|
private _initialDistanceToTarget = 8000;
|
||||||
|
_returnTargetPos = _launchPos vectorAdd (_launchDir vectorMultiply _initialDistanceToTarget);
|
||||||
|
};
|
||||||
|
|
||||||
|
private _closingRate = vectorMagnitude velocity _projectile;
|
||||||
|
// subtract 500 meters to account for the fact that we don't want to be at the perfect pitch exactly when we cross the target
|
||||||
|
// 500 seemed good in testing
|
||||||
|
private _timeToGo = ((_projectilePos distance2d _seekerTargetPos) - 500) / _closingRate;
|
||||||
|
|
||||||
|
// we could do stuff like desired attack angle, but I'm not going that far today
|
||||||
|
private _los = _projectilePos vectorFromTo _seekerTargetPos;
|
||||||
|
|
||||||
|
_flightParams params ["_pitchRate", "_yawRate"];
|
||||||
|
|
||||||
|
private _angleToTarget = acos ((vectorDir _projectile) vectorCos _los);
|
||||||
|
private _atMinRotationAngle = _angleToTarget >= (_pitchRate * _timeToGo);
|
||||||
|
|
||||||
switch (_attackStage) do {
|
switch (_attackStage) do {
|
||||||
case STAGE_LAUNCH: { // Gain height quickly to pass terrain mask
|
case STAGE_LAUNCH: { // Gain height quickly to pass terrain mask
|
||||||
_returnTargetPos = _projectilePos getPos [100, getDir _projectile];
|
_missileStateData params ["_heightBeforeStateSwitch", "_initialDistanceToTarget"];
|
||||||
_returnTargetPos set [2, (_projectilePos select 2) + 36.4]; // 100 and 36.4 gives a 20 deg angle
|
|
||||||
|
_returnTargetPos set [2, _heightBeforeStateSwitch + (_initialDistanceToTarget * sin 20)]; // 100 and 36.4 gives a 20 deg angle
|
||||||
|
|
||||||
if (_heightAboveLaunch > _configLaunchHeightClear) then {
|
if (_heightAboveLaunch > _configLaunchHeightClear) then {
|
||||||
_attackProfileStateParams set [0, STAGE_SEEK_CRUISE];
|
_attackProfileStateParams set [0, STAGE_SEEK_CRUISE];
|
||||||
|
|
||||||
|
_attackProfileStateParams set [2, [_projectilePos select 2, _seekerTargetPos distance2d _projectilePos]];
|
||||||
TRACE_2("New Stage: STAGE_SEEK_CRUISE",_distanceFromLaunch2d,_heightAboveLaunch);
|
TRACE_2("New Stage: STAGE_SEEK_CRUISE",_distanceFromLaunch2d,_heightAboveLaunch);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (_atMinRotationAngle) then {
|
||||||
|
_attackProfileStateParams set [0, STAGE_ATTACK_TERMINAL];
|
||||||
|
|
||||||
|
_attackProfileStateParams set [2, [_projectilePos select 2, _seekerTargetPos distance2d _projectilePos]];
|
||||||
|
TRACE_2("New Stage: STAGE_ATTACK_TERMINAL",_distanceToTarget2d,_currentHeightOverTarget);
|
||||||
|
};
|
||||||
};
|
};
|
||||||
case STAGE_SEEK_CRUISE: { // Slowly gain altitude while searching for target
|
case STAGE_SEEK_CRUISE: { // Slowly gain altitude while searching for target
|
||||||
// Before 4000 cruise at 5.7 degrees up, then level out
|
_missileStateData params ["_heightBeforeStateSwitch", "_initialDistanceToTarget"];
|
||||||
private _cruiseHeight = linearConversion [3000, 5000, _distanceFromLaunch2d, 10, 0, true];
|
|
||||||
|
|
||||||
_returnTargetPos = _projectilePos getPos [100, getDir _projectile];
|
// Before 4000 cruise at 5.7 degrees up, then level out
|
||||||
_returnTargetPos set [2, (_projectilePos select 2) + _cruiseHeight];
|
_returnTargetPos set [2, _heightBeforeStateSwitch + (_initialDistanceToTarget * sin 5.7)];
|
||||||
|
|
||||||
if (_seekerTargetPos isNotEqualTo [0,0,0]) then {
|
if (_seekerTargetPos isNotEqualTo [0,0,0]) then {
|
||||||
_attackProfileStateParams set [0, STAGE_ATTACK_CRUISE];
|
_attackProfileStateParams set [0, STAGE_ATTACK_CRUISE];
|
||||||
|
|
||||||
|
_attackProfileStateParams set [2, [_projectilePos select 2, _seekerTargetPos distance2d _projectilePos]];
|
||||||
TRACE_1("New Stage: STAGE_ATTACK_CRUISE",_distanceFromLaunch2d);
|
TRACE_1("New Stage: STAGE_ATTACK_CRUISE",_distanceFromLaunch2d);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
case STAGE_ATTACK_CRUISE: {
|
case STAGE_ATTACK_CRUISE: {
|
||||||
|
_missileStateData params ["_heightBeforeStateSwitch", "_initialDistanceToTarget"];
|
||||||
|
|
||||||
private _currentHeightOverTarget = (_projectilePos select 2) - (_seekerTargetPos select 2);
|
private _currentHeightOverTarget = (_projectilePos select 2) - (_seekerTargetPos select 2);
|
||||||
private _distanceToTarget2d = _seekerTargetPos distance2d _projectilePos;
|
private _distanceToTarget2d = _seekerTargetPos distance2d _projectilePos;
|
||||||
private _distToGoRatio = _distanceToTarget2d / (_launchPos distance2d _seekerTargetPos);
|
|
||||||
|
|
||||||
// arcing up at 7 degrees to start until 50% left, then smooth curve to a downward attack
|
_returnTargetPos set [2, _heightBeforeStateSwitch + (_initialDistanceToTarget * sin 7)];
|
||||||
private _gainSlope = linearConversion [0.5, 0.1, _distToGoRatio, 7, -7, true];
|
|
||||||
_returnTargetPos = +_seekerTargetPos;
|
|
||||||
_returnTargetPos set [2, ((_projectilePos select 2) + (_distanceToTarget2d * sin _gainSlope)) max (_seekerTargetPos select 2)];
|
|
||||||
|
|
||||||
if ((_distanceToTarget2d < 500) || {(_currentHeightOverTarget atan2 _distanceToTarget2d) > 15}) then { // Wait until we can come down at a sharp angle
|
// if we are at the rotation limit, rotate to target
|
||||||
|
if (_atMinRotationAngle || {(_currentHeightOverTarget atan2 _distanceToTarget2d) > 15}) then { // Wait until we can come down at a sharp angle
|
||||||
_attackProfileStateParams set [0, STAGE_ATTACK_TERMINAL];
|
_attackProfileStateParams set [0, STAGE_ATTACK_TERMINAL];
|
||||||
|
|
||||||
|
_attackProfileStateParams set [2, [_projectilePos select 2, _seekerTargetPos distance2d _projectilePos]];
|
||||||
TRACE_2("New Stage: STAGE_ATTACK_TERMINAL",_distanceToTarget2d,_currentHeightOverTarget);
|
TRACE_2("New Stage: STAGE_ATTACK_TERMINAL",_distanceToTarget2d,_currentHeightOverTarget);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
case STAGE_ATTACK_TERMINAL: {
|
case STAGE_ATTACK_TERMINAL: {
|
||||||
private _distanceToTarget2d = _seekerTargetPos distance2d _projectilePos;
|
|
||||||
_returnTargetPos = _seekerTargetPos vectorAdd [0, 0, _distanceToTarget2d * 0.02];
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Special radar case. Adjust target position such that we are leading it
|
// missile guidance defines this variable in doAttackProfile
|
||||||
if (_attackStage >= 3 && { _seekerType isEqualTo "ARH" }) then {
|
//IGNORE_PRIVATE_WARNING ["_attackProfileName"];
|
||||||
_seekerStateParams params ["", "", "", "", "", "", "", "_lastKnownVelocity"];
|
_attackProfileName = ["na", "hellfire - LAUNCH", "hellfire - SEEK CRUISE", "hellfire - ATTACK CRUISE", "hellfire - TERMINAL"] select _attackStage;
|
||||||
private _projectileVelocity = velocity _projectile;
|
|
||||||
if (_projectileVelocity#2 < 0) then {
|
|
||||||
private _projectileSpeed = vectorMagnitude _projectileVelocity; // this gives a precise impact time versus using speed _projectile. Dont change
|
|
||||||
private _timeUntilImpact = (_seekerTargetPos distance _projectilePos) / _projectileSpeed;
|
|
||||||
_returnTargetPos = _returnTargetPos vectorAdd (_lastKnownVelocity vectorMultiply _timeUntilImpact);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// TRACE_1("Adjusted target position",_returnTargetPos);
|
TRACE_1("Adjusted target position",_returnTargetPos);
|
||||||
_returnTargetPos;
|
_returnTargetPos;
|
||||||
|
@ -27,6 +27,8 @@ private _attackConfig = configFile >> QEGVAR(missileguidance,AttackProfiles) >>
|
|||||||
// Launch (clearing terrain mask for LO/HI):
|
// Launch (clearing terrain mask for LO/HI):
|
||||||
private _configLaunchHeightClear = getNumber (_attackConfig >> QGVAR(launchHeightClear));
|
private _configLaunchHeightClear = getNumber (_attackConfig >> QGVAR(launchHeightClear));
|
||||||
|
|
||||||
|
private _projectilePos = getPosASL _projectile;
|
||||||
|
|
||||||
// Get starting stage
|
// Get starting stage
|
||||||
private _startingStage = if (_configLaunchHeightClear > 0) then {
|
private _startingStage = if (_configLaunchHeightClear > 0) then {
|
||||||
STAGE_LAUNCH; // LOAL-HI / LO
|
STAGE_LAUNCH; // LOAL-HI / LO
|
||||||
@ -40,5 +42,9 @@ private _startingStage = if (_configLaunchHeightClear > 0) then {
|
|||||||
// Set data in param array
|
// Set data in param array
|
||||||
_attackProfileStateParams set [0, _startingStage];
|
_attackProfileStateParams set [0, _startingStage];
|
||||||
_attackProfileStateParams set [1, _configLaunchHeightClear];
|
_attackProfileStateParams set [1, _configLaunchHeightClear];
|
||||||
|
_attackProfileStateParams set [2, [
|
||||||
|
_projectilePos select 2,
|
||||||
|
_seekerTargetPos distance2d _projectilePos
|
||||||
|
]];
|
||||||
|
|
||||||
TRACE_1("new shot settings",_attackProfileStateParams);
|
TRACE_1("new shot settings",_attackProfileStateParams);
|
||||||
|
29
addons/hellfire/functions/fnc_midCourseTransition.sqf
Normal file
29
addons/hellfire/functions/fnc_midCourseTransition.sqf
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#include "..\script_component.hpp"
|
||||||
|
/*
|
||||||
|
* Author: tcvm
|
||||||
|
* Condition to switch to next navigation profile
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* Guidance Arg Array <ARRAY>
|
||||||
|
*
|
||||||
|
* Return Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* [] call ace_hellfire_fnc_midCourseTransition
|
||||||
|
*
|
||||||
|
* Public: No
|
||||||
|
*/
|
||||||
|
|
||||||
|
_args params ["_firedEH", "_launchParams", "_flightParams", "_seekerParams", "_stateParams", "_targetData", "_navigationStateData"];
|
||||||
|
_firedEH params ["_shooter","","","","_ammo","","_projectile"];
|
||||||
|
_launchParams params ["_shooter","_targetLaunchParams","_seekerType","_attackProfile","_lockMode","_laserInfo","_navigationType"];
|
||||||
|
_targetLaunchParams params ["_target", "_targetPos", "_launchPos", "_launchDir", "_launchTime"];
|
||||||
|
_flightParams params ["_pitchRate", "_yawRate", "_isBangBangGuidance"];
|
||||||
|
_stateParams params ["_lastRunTime", "_seekerStateParams", "_attackProfileStateParams", "_lastKnownPosState","_navigationParams", "_guidanceParameters"];
|
||||||
|
_seekerParams params ["_seekerAngle", "_seekerAccuracy", "_seekerMaxRange", "_seekerMinRange"];
|
||||||
|
_targetData params ["_targetDirection", "_attackProfileDirection", "_targetRange", "_targetVelocity", "_targetAcceleration"];
|
||||||
|
|
||||||
|
_attackProfileStateParams params ["_state"];
|
||||||
|
_state isEqualTo STAGE_ATTACK_TERMINAL;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user