mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
adjust hellfire attack profile to work with pro-nav
This commit is contained in:
parent
5cd61d1301
commit
4d5d395f61
@ -18,7 +18,7 @@
|
||||
*/
|
||||
|
||||
params ["_seekerTargetPos", "_args", "_attackProfileStateParams"];
|
||||
_args params ["_firedEH", "_launchParams", "", "", "_stateParams"];
|
||||
_args params ["_firedEH", "_launchParams", "_flightParams", "", "_stateParams"];
|
||||
_stateParams params ["", "_seekerStateParams"];
|
||||
_launchParams params ["","_targetLaunchParams","_seekerType"];
|
||||
|
||||
@ -29,69 +29,72 @@ _firedEH params ["","","","","","","_projectile"];
|
||||
if (_attackProfileStateParams isEqualTo []) then {
|
||||
_this call FUNC(getAttackProfileSettings);
|
||||
};
|
||||
_attackProfileStateParams params ["_attackStage", "_configLaunchHeightClear"];
|
||||
|
||||
_attackProfileStateParams params ["_attackStage", "_configLaunchHeightClear", "_missileStateData"];
|
||||
|
||||
private _projectilePos = getPosASL _projectile;
|
||||
private _distanceFromLaunch2d = _launchPos distance2d _projectilePos;
|
||||
private _heightAboveLaunch = (_projectilePos select 2) - (_launchPos select 2);
|
||||
|
||||
// Add height depending on distance for compensate
|
||||
private _returnTargetPos = nil;
|
||||
private _returnTargetPos = _seekerTargetPos;
|
||||
|
||||
private _closingRate = vectorMagnitude velocity _projectile;
|
||||
private _timeToGo = (_projectilePos distance2d _seekerTargetPos) / _closingRate;
|
||||
|
||||
private _los = vectorNormalized (_seekerTargetPos vectorDiff _projectilePos);
|
||||
|
||||
_flightParams params ["_pitchRate", "_yawRate"];
|
||||
|
||||
private _angleToTarget = acos ((vectorDir _projectile) vectorCos _los);
|
||||
private _atMinRotationAngle = _angleToTarget >= (0.5 * _pitchRate * _timeToGo);
|
||||
|
||||
switch (_attackStage) do {
|
||||
case STAGE_LAUNCH: { // Gain height quickly to pass terrain mask
|
||||
_returnTargetPos = _projectilePos getPos [100, getDir _projectile];
|
||||
_returnTargetPos set [2, (_projectilePos select 2) + 36.4]; // 100 and 36.4 gives a 20 deg angle
|
||||
_missileStateData params ["_heightBeforeStateSwitch", "_initialDistanceToTarget"];
|
||||
_returnTargetPos set [2, _heightBeforeStateSwitch + (_initialDistanceToTarget * sin 20)]; // 100 and 36.4 gives a 20 deg angle
|
||||
|
||||
if (_heightAboveLaunch > _configLaunchHeightClear) then {
|
||||
_attackProfileStateParams set [0, STAGE_SEEK_CRUISE];
|
||||
TRACE_2("New Stage: STAGE_SEEK_CRUISE",_distanceFromLaunch2d,_heightAboveLaunch);
|
||||
};
|
||||
|
||||
if (_atMinRotationAngle) then {
|
||||
_attackProfileStateParams set [0, STAGE_ATTACK_TERMINAL];
|
||||
TRACE_2("New Stage: STAGE_ATTACK_TERMINAL",_distanceToTarget2d,_currentHeightOverTarget);
|
||||
};
|
||||
};
|
||||
case STAGE_SEEK_CRUISE: { // Slowly gain altitude while searching for target
|
||||
_missileStateData params ["_heightBeforeStateSwitch", "_initialDistanceToTarget"];
|
||||
// Before 4000 cruise at 5.7 degrees up, then level out
|
||||
private _cruiseHeight = linearConversion [3000, 5000, _distanceFromLaunch2d, 10, 0, true];
|
||||
|
||||
_returnTargetPos = _projectilePos getPos [100, getDir _projectile];
|
||||
_returnTargetPos set [2, (_projectilePos select 2) + _cruiseHeight];
|
||||
|
||||
_returnTargetPos set [2, _heightBeforeStateSwitch + (_initialDistanceToTarget * sin 5.7)];
|
||||
|
||||
if (_seekerTargetPos isNotEqualTo [0,0,0]) then {
|
||||
_attackProfileStateParams set [0, STAGE_ATTACK_CRUISE];
|
||||
|
||||
_attackProfileStateParams set [2, [_projectilePos select 2, _seekerTargetPos distance2d _projectilePos]];
|
||||
TRACE_1("New Stage: STAGE_ATTACK_CRUISE",_distanceFromLaunch2d);
|
||||
};
|
||||
};
|
||||
case STAGE_ATTACK_CRUISE: {
|
||||
_missileStateData params ["_heightBeforeStateSwitch", "_initialDistanceToTarget"];
|
||||
|
||||
private _currentHeightOverTarget = (_projectilePos select 2) - (_seekerTargetPos select 2);
|
||||
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
|
||||
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)];
|
||||
_returnTargetPos set [2, _heightBeforeStateSwitch + (_initialDistanceToTarget * sin 7)];
|
||||
|
||||
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];
|
||||
TRACE_2("New Stage: STAGE_ATTACK_TERMINAL",_distanceToTarget2d,_currentHeightOverTarget);
|
||||
};
|
||||
};
|
||||
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
|
||||
if (_attackStage >= 3 && { _seekerType isEqualTo "ARH" }) then {
|
||||
_seekerStateParams params ["", "", "", "", "", "", "", "_lastKnownVelocity"];
|
||||
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);
|
||||
};
|
||||
};
|
||||
// missile guidance defines this variable in doAttackProfile
|
||||
_attackProfileName = ["na", "hellfire - LAUNCH", "hellfire - SEEK CRUISE", "hellfire - ATTACK CRUISE", "hellfire - TERMINAL"] select _attackStage;
|
||||
|
||||
// TRACE_1("Adjusted target position", _returnTargetPos);
|
||||
TRACE_1("Adjusted target position", _returnTargetPos);
|
||||
_returnTargetPos;
|
||||
|
@ -27,6 +27,8 @@ private _attackConfig = configFile >> QEGVAR(missileguidance,AttackProfiles) >>
|
||||
// Launch (clearing terrain mask for LO/HI):
|
||||
private _configLaunchHeightClear = getNumber (_attackConfig >> QGVAR(launchHeightClear));
|
||||
|
||||
private _projectilePos = getPosASL _projectile;
|
||||
|
||||
// Get starting stage
|
||||
private _startingStage = if (_configLaunchHeightClear > 0) then {
|
||||
STAGE_LAUNCH; // LOAL-HI / LO
|
||||
@ -41,5 +43,9 @@ private _startingStage = if (_configLaunchHeightClear > 0) then {
|
||||
// Set data in param array
|
||||
_attackProfileStateParams set [0, _startingStage];
|
||||
_attackProfileStateParams set [1, _configLaunchHeightClear];
|
||||
_attackProfileStateParams set [2, [
|
||||
_projectilePos select 2,
|
||||
_seekerTargetPos distance2d _projectilePos
|
||||
]];
|
||||
|
||||
TRACE_1("new shot settings",_attackProfileStateParams);
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include "\z\ace\addons\main\script_mod.hpp"
|
||||
|
||||
// #define DEBUG_MODE_FULL
|
||||
// #define DISABLE_COMPILE_CACHE
|
||||
#define DISABLE_COMPILE_CACHE
|
||||
// #define ENABLE_PERFORMANCE_COUNTERS
|
||||
|
||||
#ifdef DEBUG_ENABLED_HELLFIRE
|
||||
|
@ -22,7 +22,6 @@ _args params ["", "_launchParams"];
|
||||
_launchParams params ["", "", "", "_attackProfileName"];
|
||||
|
||||
private _attackProfileFunction = getText (configFile >> QGVAR(AttackProfiles) >> _attackProfileName >> "functionName");
|
||||
|
||||
private _attackProfilePos = _this call (missionNamespace getVariable _attackProfileFunction);
|
||||
|
||||
if ((isNil "_attackProfilePos") || {_attackProfilePos isEqualTo [0,0,0]}) exitWith {
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
BEGIN_COUNTER(guidancePFH);
|
||||
|
||||
#define TIMESTEP_FACTOR 0.01
|
||||
#define TIMESTEP_FACTOR diag_deltaTime
|
||||
|
||||
params ["_args", "_pfID"];
|
||||
_args params ["_firedEH", "_launchParams", "_flightParams", "_seekerParams", "_stateParams"];
|
||||
@ -31,24 +31,12 @@ if (!alive _projectile || isNull _projectile || isNull _shooter) exitWith {
|
||||
END_COUNTER(guidancePFH);
|
||||
};
|
||||
|
||||
private _runtimeDelta = diag_tickTime - _lastRunTime;
|
||||
private _adjustTime = 1;
|
||||
|
||||
if (accTime > 0) then {
|
||||
_adjustTime = 1/accTime;
|
||||
_adjustTime = _adjustTime * (_runtimeDelta / TIMESTEP_FACTOR);
|
||||
TRACE_4("Adjust timing", 1/accTime, _adjustTime, _runtimeDelta, (_runtimeDelta / TIMESTEP_FACTOR) );
|
||||
} else {
|
||||
_adjustTime = 0;
|
||||
};
|
||||
|
||||
private _pitchRate = _flightParams select 0;
|
||||
private _yawRate = _flightParams select 1;
|
||||
_flightParams params ["_pitchRate", "_yawRate"];
|
||||
|
||||
// Run seeker function:
|
||||
private _seekerTargetPos = [[0,0,0], _args, _seekerStateParams, _lastKnownPosState] call FUNC(doSeekerSearch);
|
||||
|
||||
// Run attack profile function:
|
||||
_seekerTargetPos = AGLtoASL ASLToAGL _seekerTargetPos;
|
||||
private _profileAdjustedTargetPos = [_seekerTargetPos, _args, _attackProfileStateParams] call FUNC(doAttackProfile);
|
||||
|
||||
private _projectilePos = getPosASLVisual _projectile;
|
||||
|
@ -70,7 +70,7 @@ if (isNil "_navigationType" || {!(_navigationType in (getArray (_config >> "navi
|
||||
_navigationType = getText (_config >> "defaultNavigationType");
|
||||
};
|
||||
|
||||
if (isNil "_navigationType") then {
|
||||
if (isNil "_navigationType" || _navigationType isEqualTo "") then {
|
||||
// most missiles use ProNav by default
|
||||
_navigationType = "ProportionalNavigation";
|
||||
};
|
||||
@ -108,6 +108,14 @@ private _navigationParameters = [
|
||||
// set up in navigation type onFired function
|
||||
];
|
||||
|
||||
// default config values to make sure there is backwards compat
|
||||
private _pitchRate = 30;
|
||||
private _yawRate = 30;
|
||||
if (isNumber (_config >> "pitchRate")) then {
|
||||
_pitchRate = getNumber ( _config >> "pitchRate" );
|
||||
_yawRate = getNumber ( _config >> "yawRate" );
|
||||
};
|
||||
|
||||
TRACE_5("Beginning ACE guidance system",_target,_ammo,_seekerType,_attackProfile,_navigationType);
|
||||
private _args = [_this,
|
||||
[ _shooter,
|
||||
@ -119,8 +127,8 @@ private _args = [_this,
|
||||
_navigationType
|
||||
],
|
||||
[
|
||||
getNumber ( _config >> "pitchRate" ),
|
||||
getNumber ( _config >> "yawRate" )
|
||||
_pitchRate,
|
||||
_yawRate
|
||||
],
|
||||
[
|
||||
getNumber ( _config >> "seekerAngle" ),
|
||||
|
@ -23,12 +23,14 @@ _seekerParams params ["_seekerAngle", "_seekerAccuracy", "_seekerMaxRange", "_se
|
||||
|
||||
private _ammoConfig = configOf _projectile;
|
||||
private _navigationGain = getNumber (_ammoConfig >> QUOTE(ADDON) >> "navigationGain");
|
||||
if (_navigationGain == 0) then {
|
||||
_navigationGain = 3;
|
||||
};
|
||||
|
||||
private _pitchYaw = (vectorDir _projectile) call CBA_fnc_vect2Polar;
|
||||
|
||||
_navigationParams = [
|
||||
[ // Last Missile Frame
|
||||
[0, 0, 0], // Last target position
|
||||
[0, 0, 0], // Last target position array
|
||||
[0, 0, 0], // Last target velocity
|
||||
[0, 0, 0] // Last line of sight
|
||||
],
|
||||
|
@ -61,7 +61,6 @@ if (_isActive || { CBA_missionTime >= _timeWhenActive }) then {
|
||||
};
|
||||
// Look in front of seeker for any targets
|
||||
private _nearestObjects = nearestObjects [ASLtoAGL _searchPos, ["Air", "LandVehicle", "Ship"], _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 {
|
||||
@ -74,6 +73,7 @@ if (_isActive || { CBA_missionTime >= _timeWhenActive }) then {
|
||||
// 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;
|
||||
@ -104,17 +104,21 @@ if (_isActive || { CBA_missionTime >= _timeWhenActive }) then {
|
||||
};
|
||||
};
|
||||
|
||||
#ifdef DRAW_GUIDANCE_INFO
|
||||
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"];
|
||||
#endif
|
||||
|
||||
if !(isNull _target) then {
|
||||
private _centerOfObject = getCenterOfMass _target;
|
||||
private _targetAdjustedPos = _target modelToWorldWorld _centerOfObject;
|
||||
private _targetAdjustedPos = _target modelToWorldVisualWorld _centerOfObject;
|
||||
_expectedTargetPos = _targetAdjustedPos;
|
||||
|
||||
_seekerStateParams set [3, _expectedTargetPos];
|
||||
_seekerStateParams set [7, velocity _target];
|
||||
_seekerStateParams set [8, CBA_missionTime];
|
||||
_seekerStateParams set [9, false];
|
||||
};
|
||||
|
||||
_seekerStateParams set [3, _expectedTargetPos];
|
||||
_launchParams set [0, _target];
|
||||
_expectedTargetPos
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user