mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
Merge branch 'master' into missile_gbu
This commit is contained in:
commit
0423091ea8
@ -38,9 +38,8 @@ class CfgAmmo {
|
||||
EGVAR(vehicle_damage,incendiary) = 1.0;
|
||||
|
||||
class ace_missileguidance {
|
||||
minDeflection = 0;
|
||||
maxDeflection = 0;
|
||||
incDeflection = 0;
|
||||
pitchRate = 0;
|
||||
yawRate = 0;
|
||||
|
||||
canVanillaLock = 0;
|
||||
|
||||
@ -51,6 +50,9 @@ class CfgAmmo {
|
||||
defaultSeekerLockMode = "LOAL";
|
||||
seekerLockModes[] = { "LOAL", "LOBL" };
|
||||
|
||||
defaultNavigationType = "LineOfSight";
|
||||
navigationTypes[] = { "LineOfSight" };
|
||||
|
||||
seekLastTargetPos = 0;
|
||||
seekerAngle = 30;
|
||||
seekerAccuracy = 1;
|
||||
@ -82,6 +84,9 @@ class CfgAmmo {
|
||||
class ace_missileguidance {
|
||||
enabled = 1;
|
||||
|
||||
pitchRate = 0;
|
||||
yawRate = 0;
|
||||
|
||||
// Guidance type for munitions
|
||||
defaultSeekerType = "SACLOS";
|
||||
seekerTypes[] = { "SACLOS" };
|
||||
|
@ -26,9 +26,8 @@ class CfgAmmo {
|
||||
class ace_missileguidance {
|
||||
enabled = 1;
|
||||
|
||||
minDeflection = 0.0005; // Minium flap deflection for guidance
|
||||
maxDeflection = 0.01; // Maximum flap deflection for guidance
|
||||
incDeflection = 0.0005; // The incrmeent in which deflection adjusts.
|
||||
pitchRate = 30; // degrees per second
|
||||
yawRate = 30;
|
||||
|
||||
canVanillaLock = 0; // Can this default vanilla lock? Only applicable to non-cadet mode
|
||||
|
||||
@ -39,6 +38,9 @@ class CfgAmmo {
|
||||
defaultSeekerLockMode = "LOAL";
|
||||
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]
|
||||
seekerAngle = 70; // Angle in front of the missile which can be searched
|
||||
seekerAccuracy = 1; // seeker accuracy multiplier
|
||||
@ -49,6 +51,19 @@ class CfgAmmo {
|
||||
// Attack profile type selection
|
||||
defaultAttackProfile = "hellfire";
|
||||
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 {
|
||||
@ -75,8 +90,8 @@ class CfgAmmo {
|
||||
canVanillaLock = 1;
|
||||
enabled = 1; // Missile Guidance must be explicitly enabled
|
||||
seekLastTargetPos = 0;
|
||||
defaultSeekerType = "ARH";
|
||||
seekerTypes[] = { "ARH" };
|
||||
defaultSeekerType = "MillimeterWaveRadar";
|
||||
seekerTypes[] = { "MillimeterWaveRadar" };
|
||||
defaultSeekerLockMode = "LOBL";
|
||||
seekerLockModes[] = { "LOBL" };
|
||||
|
||||
|
@ -2,3 +2,4 @@ LOG("prep");
|
||||
PREP(attackProfile);
|
||||
PREP(getAttackProfileSettings);
|
||||
PREP(setupVehicle);
|
||||
PREP(midCourseTransition);
|
||||
|
@ -18,80 +18,99 @@
|
||||
*/
|
||||
|
||||
params ["_seekerTargetPos", "_args", "_attackProfileStateParams"];
|
||||
_args params ["_firedEH", "_launchParams", "", "", "_stateParams"];
|
||||
_args params ["_firedEH", "_launchParams", "_flightParams", "", "_stateParams"];
|
||||
_stateParams params ["", "_seekerStateParams"];
|
||||
_launchParams params ["","_targetLaunchParams","_seekerType"];
|
||||
|
||||
_targetLaunchParams params ["", "", "_launchPos"];
|
||||
_targetLaunchParams params ["", "", "_launchPos", "_launchDir"];
|
||||
_firedEH params ["","","","","","","_projectile"];
|
||||
|
||||
// Get state params:
|
||||
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;
|
||||
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 {
|
||||
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];
|
||||
|
||||
_attackProfileStateParams set [2, [_projectilePos select 2, _seekerTargetPos distance2d _projectilePos]];
|
||||
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
|
||||
_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];
|
||||
|
||||
_attackProfileStateParams set [2, [_projectilePos select 2, _seekerTargetPos distance2d _projectilePos]];
|
||||
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
|
||||
//IGNORE_PRIVATE_WARNING ["_attackProfileName"];
|
||||
_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
|
||||
@ -40,5 +42,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);
|
||||
|
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;
|
||||
|
@ -58,12 +58,13 @@ class CfgAmmo {
|
||||
class ace_missileguidance {
|
||||
enabled = 1;
|
||||
|
||||
minDeflection = 0; // Minium flap deflection for guidance
|
||||
maxDeflection = 0.0030; // Maximum flap deflection for guidance
|
||||
incDeflection = 0.0005; // The incrmeent in which deflection adjusts.
|
||||
pitchRate = 45; // Minium flap deflection for guidance
|
||||
yawRate = 45; // Maximum flap deflection for guidance
|
||||
|
||||
canVanillaLock = 0; // Can this default vanilla lock? Only applicable to non-cadet mode
|
||||
|
||||
showTrail = 1;
|
||||
|
||||
// Guidance type for munitions
|
||||
defaultSeekerType = "SACLOS";
|
||||
seekerTypes[] = { "SACLOS" };
|
||||
@ -71,6 +72,14 @@ class CfgAmmo {
|
||||
defaultSeekerLockMode = "LOAL";
|
||||
seekerLockModes[] = { "LOAL", "LOBL" };
|
||||
|
||||
defaultNavigationType = "Line";
|
||||
navigationTypes[] = { "Line" };
|
||||
|
||||
lineGainP = 7;
|
||||
lineGainD = 6;
|
||||
|
||||
initialPitch = 2;
|
||||
|
||||
seekLastTargetPos = 0; // seek last target position [if seeker loses LOS of target, continue to last known pos]
|
||||
seekerAngle = 30; // Angle from the shooter's view that can track the missile
|
||||
seekerAccuracy = 1; // seeker accuracy multiplier
|
||||
@ -78,7 +87,6 @@ class CfgAmmo {
|
||||
seekerMinRange = 75;
|
||||
seekerMaxRange = 4000; // Range from the missile which the seeker can visually search
|
||||
|
||||
correctionDistance = 8; // distance from center of crosshair where missile slows down
|
||||
offsetFromCrosshair[] = { 0, 0, 0.5 }; // where the missile wants to stay in relation to the center of the crosshair.
|
||||
|
||||
// Attack profile type selection
|
||||
|
@ -4,11 +4,22 @@ class CfgVehicles {
|
||||
class Turrets;
|
||||
};
|
||||
class LT_01_base_F: Tank_F {
|
||||
class AnimationSources;
|
||||
class Turrets: Turrets {
|
||||
class MainTurret;
|
||||
};
|
||||
};
|
||||
class LT_01_AT_base_F: LT_01_base_F {
|
||||
class AnimationSources: AnimationSources {
|
||||
class Missiles_revolving {
|
||||
source = "revolving";
|
||||
weapon = QGVAR(generic_launcher);
|
||||
};
|
||||
class Missiles_reloadMagazine {
|
||||
source = "reloadMagazine";
|
||||
weapon = QGVAR(generic_launcher);
|
||||
};
|
||||
};
|
||||
class Turrets: Turrets {
|
||||
class MainTurret: MainTurret {
|
||||
weapons[] = {"SmokeLauncher","HMG_127",QGVAR(generic_launcher)};
|
||||
|
@ -2,6 +2,6 @@ class EGVAR(missileguidance,AttackProfiles) {
|
||||
class maverick {
|
||||
name = "LOAL-DIR";
|
||||
nameLocked = "LOBL-DIR";
|
||||
functionName = QEFUNC(missileguidance,attackProfile_DIR);
|
||||
functionName = QEFUNC(missileguidance,attackProfile_LIN);
|
||||
};
|
||||
};
|
||||
|
@ -5,6 +5,45 @@ class CfgAmmo {
|
||||
};
|
||||
class Missile_AGM_02_F: MissileBase {};
|
||||
|
||||
class GVAR(D): Missile_AGM_02_F {
|
||||
author = "Dani (TCVM)";
|
||||
missileLockMaxDistance = 14000;
|
||||
maneuvrability = 0;
|
||||
class ace_missileguidance {
|
||||
enabled = 1;
|
||||
|
||||
pitchRate = 15;
|
||||
yawRate = 15;
|
||||
|
||||
canVanillaLock = 1;
|
||||
|
||||
defaultSeekerType = "Optic";
|
||||
seekerTypes[] = {"Optic"};
|
||||
|
||||
defaultSeekerLockMode = "LOBL";
|
||||
seekerLockModes[] = {"LOBL"};
|
||||
|
||||
defaultNavigationType = "AugmentedProportionalNavigation";
|
||||
navigationTypes[] = { "AugmentedProportionalNavigation" };
|
||||
|
||||
seekLastTargetPos = 1;
|
||||
seekerAngle = 60;
|
||||
seekerAccuracy = 1;
|
||||
|
||||
seekerMinRange = 1;
|
||||
seekerMaxRange = 14000;
|
||||
|
||||
defaultAttackProfile = "maverick";
|
||||
attackProfiles[] = {"maverick"};
|
||||
};
|
||||
};
|
||||
|
||||
class GVAR(G): GVAR(D) {
|
||||
class ace_missileguidance: ace_missileguidance {
|
||||
enabled = 1;
|
||||
};
|
||||
};
|
||||
|
||||
class GVAR(L): Missile_AGM_02_F {
|
||||
author = "xrufix";
|
||||
autoSeekTarget = 0;
|
||||
@ -16,9 +55,8 @@ class CfgAmmo {
|
||||
class ace_missileguidance {
|
||||
enabled = 1;
|
||||
|
||||
minDeflection = 0;
|
||||
maxDeflection = 0.002;
|
||||
incDeflection = 0.001;
|
||||
pitchRate = 15;
|
||||
yawRate = 15;
|
||||
|
||||
canVanillaLock = 0;
|
||||
|
||||
@ -28,6 +66,9 @@ class CfgAmmo {
|
||||
defaultSeekerLockMode = "LOAL";
|
||||
seekerLockModes[] = {"LOAL","LOBL"};
|
||||
|
||||
defaultNavigationType = "AugmentedProportionalNavigation";
|
||||
navigationTypes[] = { "AugmentedProportionalNavigation" };
|
||||
|
||||
seekLastTargetPos = 1;
|
||||
seekerAngle = 60;
|
||||
seekerAccuracy = 1;
|
||||
@ -49,9 +90,8 @@ class CfgAmmo {
|
||||
class ace_missileguidance {
|
||||
enabled = 1;
|
||||
|
||||
minDeflection = 0;
|
||||
maxDeflection = 0.002;
|
||||
incDeflection = 0.001;
|
||||
pitchRate = 20;
|
||||
yawRate = 20;
|
||||
|
||||
canVanillaLock = 0;
|
||||
|
||||
@ -61,6 +101,9 @@ class CfgAmmo {
|
||||
defaultSeekerLockMode = "LOAL";
|
||||
seekerLockModes[] = {"LOAL"};
|
||||
|
||||
defaultNavigationType = "AugmentedProportionalNavigation";
|
||||
navigationTypes[] = { "AugmentedProportionalNavigation" };
|
||||
|
||||
seekLastTargetPos = 1;
|
||||
seekerAngle = 40;
|
||||
seekerAccuracy = 1;
|
||||
|
@ -12,7 +12,71 @@ class CfgMagazines {
|
||||
|
||||
class PylonRack_Missile_AGM_02_x1: magazine_Missile_AGM_02_x1 {};
|
||||
class PylonRack_Missile_AGM_02_x2: magazine_Missile_AGM_02_x1 {};
|
||||
|
||||
// Optical Mavericks
|
||||
class GVAR(D_magazine): 6Rnd_Missile_AGM_02_F {
|
||||
ammo = QGVAR(D);
|
||||
author = "Dani (TCVM)";
|
||||
displayName = CSTRING(d_mag_x1);
|
||||
};
|
||||
class GVAR(D_pylonRack_1Rnd): PylonRack_1Rnd_Missile_AGM_02_F {
|
||||
ammo = QGVAR(D);
|
||||
author = "Dani (TCVM)";
|
||||
displayName = CSTRING(d_mag_x1);
|
||||
pylonWeapon = QGVAR(D_Launcher);
|
||||
};
|
||||
class GVAR(D_pylonRack_3Rnd): PylonRack_3Rnd_Missile_AGM_02_F {
|
||||
ammo = QGVAR(D);
|
||||
author = "Dani (TCVM)";
|
||||
displayName = CSTRING(d_mag_x3);
|
||||
pylonWeapon = QGVAR(D_Launcher);
|
||||
};
|
||||
|
||||
class GVAR(G_magazine_x1): magazine_Missile_AGM_02_x1 {
|
||||
ammo = QGVAR(G);
|
||||
author = "Dani (TCVM)";
|
||||
displayName = CSTRING(g_mag_x1);
|
||||
};
|
||||
class GVAR(G_pylonmissile_x1): PylonMissile_Missile_AGM_02_x1 {
|
||||
ammo = QGVAR(G);
|
||||
author = "Dani (TCVM)";
|
||||
displayName = CSTRING(g_mag_x1);
|
||||
pylonWeapon = QGVAR(G_Launcher);
|
||||
};
|
||||
class GVAR(G_pylonmissile_x2): PylonMissile_Missile_AGM_02_x2 {
|
||||
ammo = QGVAR(G);
|
||||
author = "Dani (TCVM)";
|
||||
displayName = CSTRING(g_mag_x2);
|
||||
pylonWeapon = QGVAR(G_Launcher);
|
||||
};
|
||||
|
||||
class GVAR(G_pylonRack_1Rnd): PylonRack_1Rnd_Missile_AGM_02_F {
|
||||
ammo = QGVAR(G);
|
||||
author = "Dani (TCVM)";
|
||||
displayName = CSTRING(g_mag_x1);
|
||||
pylonWeapon = QGVAR(G_Launcher);
|
||||
};
|
||||
class GVAR(G_PylonRack_3Rnd): PylonRack_3Rnd_Missile_AGM_02_F {
|
||||
ammo = QGVAR(G);
|
||||
author = "Dani (TCVM)";
|
||||
displayName = CSTRING(g_mag_x3);
|
||||
pylonWeapon = QGVAR(G_Launcher);
|
||||
};
|
||||
|
||||
class GVAR(G_PylonRack_x1): PylonRack_Missile_AGM_02_x1 {
|
||||
ammo = QGVAR(G);
|
||||
author = "Dani (TCVM)";
|
||||
displayName = CSTRING(g_mag_x1);
|
||||
pylonWeapon = QGVAR(G_Launcher);
|
||||
};
|
||||
class GVAR(G_PylonRack_x2): PylonRack_Missile_AGM_02_x2 {
|
||||
ammo = QGVAR(G);
|
||||
author = "Dani (TCVM)";
|
||||
displayName = CSTRING(g_mag_x2);
|
||||
pylonWeapon = QGVAR(G_Launcher);
|
||||
};
|
||||
|
||||
// Laser Mavericks
|
||||
class GVAR(L_magazine_x1): magazine_Missile_AGM_02_x1 {
|
||||
ammo = QGVAR(L);
|
||||
author = "xrufix";
|
||||
|
@ -6,6 +6,22 @@ class CfgWeapons {
|
||||
class MissileLauncher: LauncherCore {};
|
||||
class Missile_AGM_02_Plane_CAS_01_F: MissileLauncher {};
|
||||
|
||||
class GVAR(D_Launcher): Missile_AGM_02_Plane_CAS_01_F {
|
||||
author = "Dani (TCVM)";
|
||||
displayname = CSTRING(D);
|
||||
magazines[] = {QGVAR(D_magazine), QGVAR(D_pylonRack_1Rnd), QGVAR(D_pylonRack_3Rnd)};
|
||||
weaponLockDelay = 0.1;
|
||||
weaponLockSystem = 2;
|
||||
};
|
||||
|
||||
class GVAR(G_Launcher): weapon_AGM_65Launcher {
|
||||
author = "Dani (TCVM)";
|
||||
displayname = CSTRING(G);
|
||||
magazines[] = {QGVAR(G_magazine_x1), QGVAR(G_pylonmissile_x1), QGVAR(G_pylonmissile_x2), QGVAR(G_pylonRack_1Rnd), QGVAR(G_PylonRack_3Rnd), QGVAR(G_PylonRack_x1), QGVAR(G_PylonRack_x2)};
|
||||
weaponLockDelay = 0.1;
|
||||
weaponLockSystem = 2;
|
||||
};
|
||||
|
||||
class GVAR(L_Launcher): weapon_AGM_65Launcher {
|
||||
author = "xrufix";
|
||||
displayname = CSTRING(L);
|
||||
|
@ -111,6 +111,27 @@
|
||||
<Turkish>1x Kh-25ML [ACE]</Turkish>
|
||||
<Spanish>1x Kh-25ML [ACE]</Spanish>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Maverick_d">
|
||||
<English>AGM-65 Maverick D</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Maverick_g">
|
||||
<English>AGM-65 Maverick G</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Maverick_d_mag_x1">
|
||||
<English>AGM-65 Maverick D [ACE]</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Maverick_d_mag_x3">
|
||||
<English>3x AGM-65 Maverick D [ACE]</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Maverick_g_mag_x1">
|
||||
<English>AGM-65 Maverick G [ACE]</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Maverick_g_mag_x2">
|
||||
<English>2x AGM-65 Maverick G [ACE]</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_Maverick_g_mag_x3">
|
||||
<English>3x AGM-65 Maverick G [ACE]</English>
|
||||
</Key>
|
||||
</Container>
|
||||
<Container name="weapons">
|
||||
<Key ID="STR_ACE_Maverick_l">
|
||||
|
@ -10,12 +10,14 @@ class CfgAmmo {
|
||||
class ace_missileguidance {
|
||||
enabled = 1;
|
||||
|
||||
minDeflection = 0; // Minium flap deflection for guidance
|
||||
maxDeflection = 0.0027; // Maximum flap deflection for guidance
|
||||
incDeflection = 0.0005; // The incrmeent in which deflection adjusts.
|
||||
pitchRate = 50; // Minium flap deflection for guidance
|
||||
yawRate = 50; // Maximum flap deflection for guidance
|
||||
initialPitch = 2;
|
||||
|
||||
canVanillaLock = 0; // Can this default vanilla lock? Only applicable to non-cadet mode
|
||||
|
||||
showTrail = 1;
|
||||
|
||||
// Guidance type for munitions
|
||||
defaultSeekerType = "SACLOS";
|
||||
seekerTypes[] = { "SACLOS" };
|
||||
@ -23,6 +25,12 @@ class CfgAmmo {
|
||||
defaultSeekerLockMode = "LOAL";
|
||||
seekerLockModes[] = { "LOAL", "LOBL" };
|
||||
|
||||
defaultNavigationType = "Line";
|
||||
navigationTypes[] = { "Line" };
|
||||
|
||||
lineGainP = 10;
|
||||
lineGainD = 9;
|
||||
|
||||
seekLastTargetPos = 0; // seek last target position [if seeker loses LOS of target, continue to last known pos]
|
||||
seekerAngle = 15; // Angle from the shooter's view that can track the missile
|
||||
seekerAccuracy = 1; // seeker accuracy multiplier
|
||||
@ -30,7 +38,6 @@ class CfgAmmo {
|
||||
seekerMinRange = 80;
|
||||
seekerMaxRange = 2000; // Range from the missile which the seeker can visually search
|
||||
|
||||
correctionDistance = 3; // distance from center of crosshair where missile slows down
|
||||
offsetFromCrosshair[] = { 0, 0, 0 }; // where the missile wants to stay in relation to the center of the crosshair.
|
||||
|
||||
// Attack profile type selection
|
||||
@ -50,9 +57,8 @@ class CfgAmmo {
|
||||
class ace_missileguidance {
|
||||
enabled = 1;
|
||||
|
||||
minDeflection = 0; // Minium flap deflection for guidance
|
||||
maxDeflection = 0.0027; // Maximum flap deflection for guidance
|
||||
incDeflection = 0.0005; // The incrmeent in which deflection adjusts.
|
||||
pitchRate = 25; // Minium flap deflection for guidance
|
||||
yawRate = 25; // Maximum flap deflection for guidance
|
||||
|
||||
canVanillaLock = 0; // Can this default vanilla lock? Only applicable to non-cadet mode
|
||||
|
||||
@ -63,6 +69,12 @@ class CfgAmmo {
|
||||
defaultSeekerLockMode = "LOAL";
|
||||
seekerLockModes[] = { "LOAL", "LOBL" };
|
||||
|
||||
defaultNavigationType = "Line";
|
||||
navigationTypes[] = { "Line" };
|
||||
|
||||
lineGainP = 21;
|
||||
lineGainD = 18;
|
||||
|
||||
seekLastTargetPos = 0; // seek last target position [if seeker loses LOS of target, continue to last known pos]
|
||||
seekerAngle = 15; // Angle from the shooter's view that can track the missile
|
||||
seekerAccuracy = 1; // seeker accuracy multiplier
|
||||
@ -70,7 +82,7 @@ class CfgAmmo {
|
||||
seekerMinRange = 80;
|
||||
seekerMaxRange = 2000; // Range from the missile which the seeker can visually search
|
||||
|
||||
correctionDistance = 3; // distance from center of crosshair where missile slows down
|
||||
correctionDistance = 1; // distance from center of crosshair where missile slows down
|
||||
offsetFromCrosshair[] = { 0, 0, 0 }; // where the missile wants to stay in relation to the center of the crosshair.
|
||||
|
||||
// Attack profile type selection
|
||||
|
@ -20,19 +20,21 @@ class CfgAmmo {
|
||||
class ADDON {
|
||||
enabled = 1;
|
||||
|
||||
minDeflection = 0.0005; // Minium flap deflection for guidance
|
||||
maxDeflection = 0.0025; // Maximum flap deflection for guidance
|
||||
incDeflection = 0.0005; // The incrmeent in which deflection adjusts.
|
||||
pitchRate = 40; // degrees per second
|
||||
yawRate = 40;
|
||||
|
||||
canVanillaLock = 0; // Can this default vanilla lock? Only applicable to non-cadet mode
|
||||
|
||||
// Guidance type for munitions
|
||||
defaultSeekerType = "SALH";
|
||||
seekerTypes[] = { "SALH", "LIDAR", "SARH", "Optic", "Thermal", "GPS", "SACLOS", "MCLOS" };
|
||||
seekerTypes[] = { "SALH" };
|
||||
|
||||
defaultSeekerLockMode = "LOAL";
|
||||
seekerLockModes[] = { "LOAL", "LOBL" };
|
||||
|
||||
defaultNavigationType = "AugmentedProportionalNavigation";
|
||||
navigationTypes[] = { "AugmentedProportionalNavigation" };
|
||||
|
||||
seekerAngle = 90; // Angle in front of the missile which can be searched
|
||||
seekerAccuracy = 1; // seeker accuracy multiplier
|
||||
|
||||
@ -69,9 +71,10 @@ class CfgAmmo {
|
||||
class ADDON {
|
||||
enabled = 1;
|
||||
|
||||
minDeflection = 0.00005; // Minium flap deflection for guidance
|
||||
maxDeflection = 0.025; // Maximum flap deflection for guidance
|
||||
incDeflection = 0.00005; // The incrmeent in which deflection adjusts.
|
||||
pitchRate = 100; // degrees per second
|
||||
yawRate = 100;
|
||||
stabilityCoefficient = 0.2;
|
||||
bangBangGuidance = 0;
|
||||
|
||||
canVanillaLock = 0;
|
||||
|
||||
@ -82,6 +85,11 @@ class CfgAmmo {
|
||||
defaultSeekerLockMode = "LOBL";
|
||||
seekerLockModes[] = { "LOBL" };
|
||||
|
||||
defaultNavigationType = "Direct";
|
||||
navigationTypes[] = { "Direct", "ZeroEffortMiss" };
|
||||
|
||||
navigationGain = 3;
|
||||
|
||||
seekerAngle = 180; // Angle in front of the missile which can be searched
|
||||
seekerAccuracy = 1; // seeker accuracy multiplier
|
||||
|
||||
@ -94,6 +102,19 @@ class CfgAmmo {
|
||||
defaultAttackProfile = "JAV_TOP";
|
||||
attackProfiles[] = { "JAV_TOP", "JAV_DIR" };
|
||||
useModeForAttackProfile = 1;
|
||||
|
||||
class navigationStates {
|
||||
class initial {
|
||||
transitionCondition = QFUNC(javelin_midCourseTransition);
|
||||
navigationType = "Direct";
|
||||
};
|
||||
class terminal {
|
||||
transitionCondition = "";
|
||||
navigationType = "ZeroEffortMiss";
|
||||
};
|
||||
// transitions from initial -> termimal
|
||||
states[] = {"initial", "terminal"};
|
||||
};
|
||||
};
|
||||
};
|
||||
class ACE_Javelin_FGM148_static: ACE_Javelin_FGM148 {
|
||||
|
@ -4,24 +4,40 @@ class CfgMagazines {
|
||||
class 6Rnd_ACE_Hydra70_DAGR: 12Rnd_PG_missiles {
|
||||
ammo = "ACE_Hydra70_DAGR";
|
||||
count = 12;
|
||||
displayName = "6 Round DAGR";
|
||||
displayNameShort = "6 Round DAGR";
|
||||
descriptionShort = "6 Round DAGR";
|
||||
displayName = CSTRING(Hydra70_DAGR_6x);
|
||||
weight = 36;
|
||||
|
||||
};
|
||||
class 12Rnd_ACE_Hydra70_DAGR: 6Rnd_ACE_Hydra70_DAGR {
|
||||
count = 12;
|
||||
displayName = "16 Round DAGR";
|
||||
displayNameShort = "16 Round DAGR";
|
||||
descriptionShort = "16 Round DAGR";
|
||||
displayName = CSTRING(Hydra70_DAGR_12x);
|
||||
weight = 72;
|
||||
};
|
||||
class 24Rnd_ACE_Hydra70_DAGR: 6Rnd_ACE_Hydra70_DAGR {
|
||||
count = 24;
|
||||
displayName = "24 Round DAGR";
|
||||
displayNameShort = "24 Round DAGR";
|
||||
descriptionShort = "24 Round DAGR";
|
||||
displayName = CSTRING(Hydra70_DAGR_24x);
|
||||
weight = 72;
|
||||
};
|
||||
|
||||
class PylonRack_12Rnd_PG_missiles;
|
||||
class PylonRack_6Rnd_ACE_DAGR: PylonRack_12Rnd_PG_missiles {
|
||||
ammo = "ACE_Hydra70_DAGR";
|
||||
displayName = CSTRING(Hydra70_DAGR_6x);
|
||||
count = 6;
|
||||
pylonWeapon = QGVAR(dagr);
|
||||
};
|
||||
|
||||
class PylonRack_12Rnd_ACE_DAGR: PylonRack_12Rnd_PG_missiles {
|
||||
ammo = "ACE_Hydra70_DAGR";
|
||||
displayName = CSTRING(Hydra70_DAGR_12x);
|
||||
count = 12;
|
||||
pylonWeapon = QGVAR(dagr);
|
||||
};
|
||||
|
||||
class PylonRack_24Rnd_ACE_DAGR: PylonRack_12Rnd_PG_missiles {
|
||||
ammo = "ACE_Hydra70_DAGR";
|
||||
displayName = CSTRING(Hydra70_DAGR_24x);
|
||||
count = 24;
|
||||
pylonWeapon = QGVAR(dagr);
|
||||
};
|
||||
};
|
||||
|
@ -2,8 +2,13 @@ class CfgWeapons {
|
||||
class missiles_DAGR;
|
||||
|
||||
class GVAR(dagr): missiles_DAGR {
|
||||
EGVAR(laser,canSelect) = 1; // can ace_laser lock (allows switching laser code)
|
||||
EGVAR(laser,showHud) = 1; // show attack profile / lock on hud
|
||||
magazines[] = {"6Rnd_ACE_Hydra70_DAGR","12Rnd_ACE_Hydra70_DAGR","24Rnd_ACE_Hydra70_DAGR","PylonRack_6Rnd_ACE_DAGR","PylonRack_12Rnd_ACE_DAGR","PylonRack_24Rnd_ACE_DAGR"};
|
||||
|
||||
autoFire = 0;
|
||||
canLock = 0;
|
||||
magazines[] = {"6Rnd_ACE_Hydra70_DAGR","12Rnd_ACE_Hydra70_DAGR","24Rnd_ACE_Hydra70_DAGR"};
|
||||
weaponLockSystem = 0;
|
||||
lockingTargetSound[] = {"",0,1};
|
||||
lockedTargetSound[] = {"",0,1};
|
||||
};
|
||||
|
@ -32,6 +32,7 @@ PREP(attackProfile_BEAM);
|
||||
// Javelin profiles
|
||||
PREP(attackProfile_JAV_DIR);
|
||||
PREP(attackProfile_JAV_TOP);
|
||||
PREP(javelin_midCourseTransition);
|
||||
|
||||
// Navigation Profiles
|
||||
PREP(navigationType_zeroEffortMiss);
|
||||
|
@ -47,7 +47,7 @@ private _returnTargetPos = _seekerTargetPos;
|
||||
switch (_attackProfileStateParams select 0) do {
|
||||
case STAGE_LAUNCH: {
|
||||
TRACE_1("STAGE_LAUNCH","");
|
||||
if (_distanceToShooter < 10) then {
|
||||
if (_distanceToShooter < 6) then {
|
||||
_returnTargetPos = _seekerTargetPos vectorAdd [0,0,_distanceToTarget*2];
|
||||
} else {
|
||||
_attackProfileStateParams set [0, STAGE_CLIMB];
|
||||
@ -55,7 +55,8 @@ switch (_attackProfileStateParams select 0) do {
|
||||
};
|
||||
case STAGE_CLIMB: {
|
||||
TRACE_1("STAGE_CLIMB","");
|
||||
private _cruisAlt = 60 * (_distanceShooterToTarget/2000);
|
||||
// 65 is min range
|
||||
private _cruisAlt = 60 * ((0 max (_distanceShooterToTarget - 65))/2000);
|
||||
|
||||
if ( ((ASLToAGL _projectilePos) select 2) - ((ASLToAGL _seekerTargetPos) select 2) >= _cruisAlt) then {
|
||||
_attackProfileStateParams set [0, STAGE_TERMINAL];
|
||||
|
@ -57,7 +57,7 @@ switch( (_attackProfileStateParams select 0) ) do {
|
||||
TRACE_1("STAGE_CLIMB","");
|
||||
private _cruisAlt = 140;
|
||||
if (_distanceShooterToTarget < 1250) then {
|
||||
_cruisAlt = 140 * (_distanceShooterToTarget/1250);
|
||||
_cruisAlt = 140 * ((0 max (_distanceShooterToTarget - 150))/1250);
|
||||
TRACE_1("_cruisAlt",_cruisAlt);
|
||||
};
|
||||
if ( ((ASLToAGL _projectilePos) select 2) - ((ASLToAGL _seekerTargetPos) select 2) >= _cruisAlt) then {
|
||||
|
@ -0,0 +1,33 @@
|
||||
#include "..\script_component.hpp"
|
||||
/*
|
||||
* Author: tcvm
|
||||
* Condition to switch to next navigation profile
|
||||
*
|
||||
* Arguments:
|
||||
* Guidance Arg Array <ARRAY>
|
||||
*
|
||||
* Return Value:
|
||||
* None
|
||||
*
|
||||
* Example:
|
||||
* [] call ace_missileguidance_fnc_javelin_midCourseTransition
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#define STAGE_LAUNCH 1
|
||||
#define STAGE_CLIMB 2
|
||||
#define STAGE_COAST 3
|
||||
#define STAGE_TERMINAL 4
|
||||
|
||||
_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_TERMINAL
|
||||
|
@ -205,5 +205,14 @@
|
||||
<Chinese>循環切換開火模式</Chinese>
|
||||
<Turkish>Ateşleme Modunu Değiştir</Turkish>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_MissileGuidance_Hydra70_DAGR_6x">
|
||||
<English>6x DAGR [ACE]</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_MissileGuidance_Hydra70_DAGR_12x">
|
||||
<English>12x DAGR [ACE]</English>
|
||||
</Key>
|
||||
<Key ID="STR_ACE_MissileGuidance_Hydra70_DAGR_24x">
|
||||
<English>24x DAGR [ACE]</English>
|
||||
</Key>
|
||||
</Package>
|
||||
</Project>
|
||||
|
@ -12,3 +12,9 @@ class EGVAR(missileguidance,SeekerTypes) {
|
||||
functionName = QFUNC(seeker);
|
||||
};
|
||||
};
|
||||
class EGVAR(missileguidance,NavigationTypes) {
|
||||
class GVAR(PLOS) {
|
||||
functionName = QFUNC(navigation);
|
||||
onFired = QFUNC(navigation_onFired);
|
||||
};
|
||||
};
|
||||
|
@ -6,9 +6,8 @@ class CfgAmmo {
|
||||
class ace_missileguidance {
|
||||
enabled = 1;
|
||||
|
||||
minDeflection = 0.0005; // Minium flap deflection for guidance
|
||||
maxDeflection = 0.01; // Maximum flap deflection for guidance
|
||||
incDeflection = 0.0005; // The incrmeent in which deflection adjusts.
|
||||
pitchRate = 5; // Minium flap deflection for guidance
|
||||
yawRate = 10; // Maximum flap deflection for guidance
|
||||
|
||||
canVanillaLock = 0; // Can this default vanilla lock? Only applicable to non-cadet mode
|
||||
|
||||
@ -19,6 +18,9 @@ class CfgAmmo {
|
||||
defaultSeekerLockMode = "LOBL";
|
||||
seekerLockModes[] = {"LOBL"};
|
||||
|
||||
defaultNavigationType = QGVAR(PLOS);
|
||||
navigationTypes[] = { QGVAR(PLOS) };
|
||||
|
||||
seekLastTargetPos = 0; // seek last target position [if seeker loses LOS of target, continue to last known pos]
|
||||
seekerAngle = 45; // Angle in front of the missile which can be searched
|
||||
seekerAccuracy = 1; // seeker accuracy multiplier
|
||||
|
@ -4,3 +4,5 @@ PREP(attackProfile);
|
||||
PREP(keyDown);
|
||||
PREP(onFired);
|
||||
PREP(seeker);
|
||||
PREP(navigation);
|
||||
PREP(navigation_onFired);
|
||||
|
@ -22,7 +22,11 @@ GVAR(pitchChange) = 0;
|
||||
|
||||
// Visual debuging, idealy used with a moving vehicle called "testTarget"
|
||||
#ifdef DRAW_NLAW_INFO
|
||||
GVAR(debug_firedPrediction) = [];
|
||||
addMissionEventHandler ["Draw3d", {
|
||||
// BLACK - On fired path prediction
|
||||
{ drawIcon3D _x; } forEach GVAR(debug_firedPrediction);
|
||||
|
||||
// GREEN - Draw an object called "testTarget"'s aim pos and 1 sec aimpos predicted by velocity
|
||||
if ((!isNil "testTarget") && {!isNull testTarget}) then {
|
||||
{
|
||||
|
@ -18,14 +18,13 @@
|
||||
*/
|
||||
|
||||
params ["_seekerTargetPos", "_args", "_attackProfileStateParams"];
|
||||
|
||||
#ifdef DRAW_NLAW_INFO
|
||||
_args params ["_firedEH", "_launchParams"];
|
||||
_launchParams params ["","_targetLaunchParams", "", "_attackProfile"];
|
||||
_targetLaunchParams params ["", "", "_launchPos"];
|
||||
_firedEH params ["","","","","","","_projectile"];
|
||||
|
||||
// Use seeker (if terminal)
|
||||
if (_seekerTargetPos isNotEqualTo [0,0,0]) exitWith {_seekerTargetPos};
|
||||
|
||||
_attackProfileStateParams params ["_startTime", "_startLOS", "_yawChange", "_pitchChange"];
|
||||
(_startLOS call CBA_fnc_vect2Polar) params ["", "_yaw", "_pitch"];
|
||||
|
||||
@ -36,14 +35,6 @@ private _flightTime = CBA_missionTime - _startTime;
|
||||
private _realYaw = _yaw + _yawChange * _flightTime;
|
||||
private _realPitch = _pitch + _pitchChange * _flightTime;
|
||||
|
||||
private _returnTargetPos = _launchPos vectorAdd ([_distanceFromLaunch, _realYaw, _realPitch] call CBA_fnc_polar2vect);
|
||||
|
||||
if (_attackProfile == QGVAR(overflyTopAttack)) then { // Add 2m height in OTA attack mode
|
||||
_returnTargetPos = _returnTargetPos vectorAdd [0,0,2];
|
||||
};
|
||||
|
||||
|
||||
#ifdef DRAW_NLAW_INFO
|
||||
drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [1,0,1,1], ASLtoAGL _launchPos, 0.75, 0.75, 0, "LAUNCH", 1, 0.025, "TahomaB"];
|
||||
drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [0,1,1,1], ASLtoAGL (_launchPos vectorAdd (_startLOS vectorMultiply (_distanceFromLaunch + 50))), 0.75, 0.75, 0, "Original LOS", 1, 0.025, "TahomaB"];
|
||||
drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [1,1,0,1], ASLtoAGL (_launchPos vectorAdd ([_distanceFromLaunch + 50, _realYaw, _realPitch] call CBA_fnc_polar2vect)), 0.75, 0.75, 0, format ["Predicted @%1sec",(floor(_flightTime * 10)/10)], 1, 0.025, "TahomaB"];
|
||||
@ -56,5 +47,4 @@ if ((count _test) > 0) then {
|
||||
};
|
||||
#endif
|
||||
|
||||
// TRACE_1("Adjusted target position",_returnTargetPos);
|
||||
_returnTargetPos;
|
||||
[0, 0, 1]
|
||||
|
@ -74,7 +74,7 @@ playSound "ACE_Sound_Click";
|
||||
_args set [1, _yaw];
|
||||
_args set [2, _pitch];
|
||||
|
||||
#ifdef DEBUG_MODE_FULL
|
||||
#ifdef DRAW_NLAW_INFO
|
||||
hintSilent format ["Instantaneous\nYaw: %1\n Pitch: %2\nGVAR\nYaw: %3\nPitch: %4", _yawChange, _pitchChange, GVAR(yawChange), GVAR(pitchChange)];
|
||||
#endif
|
||||
}, .25, [CBA_missionTime, _yaw, _pitch, true]] call CBA_fnc_addPerFrameHandler;
|
||||
|
78
addons/nlaw/functions/fnc_navigation.sqf
Normal file
78
addons/nlaw/functions/fnc_navigation.sqf
Normal file
@ -0,0 +1,78 @@
|
||||
#include "..\script_component.hpp"
|
||||
/*
|
||||
* Author: tcvm
|
||||
* Attempts to hold angle as fed to by seeker. Does so with a simple proportional controller
|
||||
*
|
||||
* Arguments:
|
||||
* Guidance Arg Array <ARRAY>
|
||||
*
|
||||
* Return Value:
|
||||
* Commanded acceleration normal to LOS in world space <ARRAY>
|
||||
*
|
||||
* Example:
|
||||
* [] call ace_missileguidance_fnc_navigationType_line
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
// arbitrary constant
|
||||
#define PROPORTIONALITY_CONSTANT 20
|
||||
params ["_args", "_timestep", "_seekerTargetPos", "_profileAdjustedTargetPos", "_targetData", "_navigationParams"];
|
||||
_args params ["_firedEH"];
|
||||
_firedEH params ["","","","","","","_projectile"];
|
||||
|
||||
_navigationParams params ["_yawChange", "_pitchChange", "_lastPitch", "_lastYaw", "_initialPitch", "_pitchUp", "_lastYawRateDifference"];
|
||||
|
||||
// for some reason we need to multiply this. I don't know why, but it just works
|
||||
_pitchChange = _pitchChange * 1.5;
|
||||
_yawChange = _yawChange * 1.5;
|
||||
|
||||
((velocity _projectile) call CBA_fnc_vect2polar) params ["", "_currentYaw", "_currentPitch"];
|
||||
|
||||
private _pitchRate = if (_timestep == 0) then {
|
||||
0
|
||||
} else {
|
||||
(_currentPitch - _lastPitch) / _timestep
|
||||
};
|
||||
_navigationParams set [2, _currentPitch];
|
||||
|
||||
private _pitchModifier = if (_pitchChange == 0) then {
|
||||
1
|
||||
} else {
|
||||
abs (_pitchRate / _pitchChange)
|
||||
};
|
||||
private _desiredPitchChange = (_pitchChange - _pitchRate) * PROPORTIONALITY_CONSTANT * _pitchModifier;
|
||||
_desiredPitchChange = _desiredPitchChange + _pitchUp * (_initialPitch - _currentPitch) * PROPORTIONALITY_CONSTANT * _pitchModifier;
|
||||
|
||||
private _yawRate = if (_timestep == 0) then {
|
||||
0
|
||||
} else {
|
||||
(_currentYaw - _lastYaw) / _timestep
|
||||
};
|
||||
_navigationParams set [3, _currentYaw];
|
||||
|
||||
private _yawModifier = if (_yawChange == 0) then {
|
||||
1
|
||||
} else {
|
||||
abs (_yawRate / _yawChange)
|
||||
};
|
||||
|
||||
private _yawRateDifference = _yawChange - _yawRate;
|
||||
private _yawChangeDerivative = if (_timestep == 0) then {
|
||||
0
|
||||
} else {
|
||||
(_yawRateDifference - _lastYawRateDifference) / _timestep
|
||||
};
|
||||
_navigationParams set [6, _yawRateDifference];
|
||||
|
||||
private _desiredYawChange = _yawRateDifference * PROPORTIONALITY_CONSTANT + _yawRateDifference * 2;
|
||||
|
||||
#ifdef DRAW_NLAW_INFO
|
||||
drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [1,0,1,1], ASLtoAGL getPosASLVisual _projectile, 0.75, 0.75, 0, format ["dP [%1] dY: [%2]", _desiredPitchChange, _desiredYawChange], 1, 0.025, "TahomaB"];
|
||||
drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [1,0,1,1], [0, 0, 1] vectorAdd ASLtoAGL getPosASLVisual _projectile, 0.75, 0.75, 0, format ["pitch proportional [%1] yaw proportional [%2]", _pitchModifier, _yawModifier], 1, 0.025, "TahomaB"];
|
||||
#endif
|
||||
|
||||
TRACE_4("nlaw pitch/yaw info",_currentPitch,_lastPitch,_currentYaw,_lastYaw);
|
||||
TRACE_6("nlaw navigation",_yawChange,_desiredYawChange,_pitchChange,_desiredPitchChange,_yawRate,_pitchRate);
|
||||
|
||||
_projectile vectorModelToWorldVisual [_yawChange + _desiredYawChange, 0, _pitchChange + _desiredPitchChange]
|
||||
|
70
addons/nlaw/functions/fnc_navigation_onFired.sqf
Normal file
70
addons/nlaw/functions/fnc_navigation_onFired.sqf
Normal file
@ -0,0 +1,70 @@
|
||||
#include "..\script_component.hpp"
|
||||
/*
|
||||
* Author: PabstMirror
|
||||
* Sets up missile guidance state arrays (called from missileGuidance's onFired).
|
||||
*
|
||||
* Arguments:
|
||||
* Guidance Arg Array <ARRAY>
|
||||
*
|
||||
* Return Value:
|
||||
* Navigation Parameters <ARRAY>
|
||||
*
|
||||
* Example:
|
||||
* [] call ace_nlaw_fnc_onFired
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
|
||||
params ["_firedEH", "_launchParams", "_flightParams", "_seekerParams", "_stateParams"];
|
||||
_firedEH params ["_shooter","","","","","","_projectile"];
|
||||
_launchParams params ["","_targetLaunchParams","","_attackProfile"];
|
||||
_targetLaunchParams params ["_target"];
|
||||
_stateParams params ["", "", "", "", "_navigationParams"];
|
||||
|
||||
// Reset _launchPos origin as projectile's height instead of player's foot
|
||||
_targetLaunchParams set [2, getPosASL _projectile];
|
||||
|
||||
// Get state params:
|
||||
TRACE_3("start of attack profile",_attackProfile,_shooter,vectorDir _projectile);
|
||||
|
||||
private _firedLOS = _shooter weaponDirection (currentWeapon _shooter);
|
||||
private _yawChange = 0;
|
||||
private _pitchChange = 0;
|
||||
|
||||
if (_shooter == ACE_player) then {
|
||||
TRACE_2("isPlayer",GVAR(yawChange),GVAR(pitchChange));
|
||||
_yawChange = GVAR(yawChange);
|
||||
_pitchChange = GVAR(pitchChange);
|
||||
TRACE_1("los check",_firedLOS call CBA_fnc_vect2Polar);
|
||||
} else {
|
||||
if ((!isNil "_target") && {!isNull _target}) then {
|
||||
_firedLOS = (getPosASL _projectile) vectorFromTo (aimPos _target);
|
||||
(((eyePos _shooter) vectorFromTo (aimPos _target)) call CBA_fnc_vect2Polar) params ["", "_startYaw", "_startPitch"];
|
||||
// Add some random error to AI's velocity prediction:
|
||||
private _random = random [(_shooter skillFinal "aimingAccuracy") min 0.9, 1, 2-((_shooter skillFinal "aimingAccuracy") min 0.9)];
|
||||
(((eyePos _shooter) vectorFromTo ((aimPos _target) vectorAdd ((velocity _target) vectorMultiply (_random)))) call CBA_fnc_vect2Polar) params ["", "_predictedYaw", "_predictedPitch"];
|
||||
_yawChange = ([_predictedYaw - _startYaw] call CBA_fnc_simplifyAngle180);
|
||||
_pitchChange = ([_predictedPitch - _startPitch] call CBA_fnc_simplifyAngle180);
|
||||
TRACE_1("AI",_target);
|
||||
} else {
|
||||
TRACE_1("AI - no target",_target);
|
||||
};
|
||||
};
|
||||
|
||||
// Limit Max Deflection
|
||||
//_yawChange = -10 max _yawChange min 10;
|
||||
//_pitchChange = -10 max _pitchChange min 10;
|
||||
|
||||
((velocity _projectile) call CBA_fnc_vect2polar) params ["", "_currentYaw", "_currentPitch"];
|
||||
((ACE_player weaponDirection (currentWeapon ACE_player)) call CBA_fnc_vect2Polar) params ["", "_yaw", "_pitch"];
|
||||
|
||||
TRACE_5("attackProfileStateParams",_firedLOS,_yawChange,_pitchChange,_currentPitch,_currentYaw);
|
||||
_navigationParams set [0, _yawChange];
|
||||
_navigationParams set [1, _pitchChange];
|
||||
_navigationParams set [2, _currentPitch]; // last pitch
|
||||
_navigationParams set [3, _currentYaw]; // last yaw
|
||||
_navigationParams set [4, _pitch]; // initial pitch
|
||||
_navigationParams set [5, 0]; // whether or not to zero out the pitch
|
||||
_navigationParams set [6, 0];
|
||||
_navigationParams
|
||||
|
@ -19,7 +19,7 @@ params ["_firedEH", "_launchParams", "_flightParams", "_seekerParams", "_statePa
|
||||
_firedEH params ["_shooter","","","","","","_projectile"];
|
||||
_launchParams params ["","_targetLaunchParams","","_attackProfile"];
|
||||
_targetLaunchParams params ["_target"];
|
||||
_stateParams params ["", "", "_attackProfileStateParams"];
|
||||
_stateParams params ["", "_seekerStateParams", "_attackProfileStateParams"];
|
||||
|
||||
// Reset _launchPos origin as projectile's height instead of player's foot
|
||||
_targetLaunchParams set [2, getPosASL _projectile];
|
||||
@ -27,7 +27,7 @@ _targetLaunchParams set [2, getPosASL _projectile];
|
||||
// Get state params:
|
||||
TRACE_3("start of attack profile",_attackProfile,_shooter,vectorDir _projectile);
|
||||
|
||||
private _firedLOS = _shooter weaponDirection (currentWeapon _shooter);
|
||||
private _firedLOS = vectorDir _projectile;
|
||||
private _yawChange = 0;
|
||||
private _pitchChange = 0;
|
||||
|
||||
@ -36,6 +36,23 @@ if (_shooter == ACE_player) then {
|
||||
_yawChange = GVAR(yawChange);
|
||||
_pitchChange = GVAR(pitchChange);
|
||||
TRACE_1("los check",_firedLOS call CBA_fnc_vect2Polar);
|
||||
|
||||
#ifdef DRAW_NLAW_INFO
|
||||
systemChat format ["YAW [%1]", _yawChange];
|
||||
systemChat format ["PITCH [%1]", _pitchChange];
|
||||
GVAR(debug_firedPrediction) = [];
|
||||
private _debugPos = getPosASL _projectile;
|
||||
((ACE_player weaponDirection (currentWeapon ACE_player)) call CBA_fnc_vect2Polar) params ["", "_debugYaw", "_debugPitch"];
|
||||
private _distance = 0;
|
||||
for "_x" from 0 to 6 step 0.1 do {
|
||||
private _debugAproxVel = linearConversion [0, 1, 5, 40, 170, true];
|
||||
_distance = _distance + _debugAproxVel * 0.1;
|
||||
private _debugYaw = _debugYaw + _yawChange * _x;
|
||||
private _debugPitch = _debugPitch + _pitchChange * _x;
|
||||
private _debugPos = _debugPos vectorAdd ([_distance, _debugYaw, _debugPitch] call CBA_fnc_polar2vect);
|
||||
GVAR(debug_firedPrediction) pushBack ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [0,0,0,1], ASLtoAGL _debugPos, 0.5, 0.5, 0, format ["%1", _x], 1, 0.025, "TahomaB"];
|
||||
};
|
||||
#endif
|
||||
} else {
|
||||
if ((!isNil "_target") && {!isNull _target}) then {
|
||||
_firedLOS = (getPosASL _projectile) vectorFromTo (aimPos _target);
|
||||
@ -55,6 +72,10 @@ if (_shooter == ACE_player) then {
|
||||
_yawChange = -10 max _yawChange min 10;
|
||||
_pitchChange = -10 max _pitchChange min 10;
|
||||
|
||||
_seekerStateParams set [2, _yawChange];
|
||||
_seekerStateParams set [3, _pitchChange];
|
||||
_seekerStateParams set [4, CBA_missionTime];
|
||||
|
||||
TRACE_3("attackProfileStateParams",_firedLOS,_yawChange,_pitchChange);
|
||||
_attackProfileStateParams set [0, CBA_missionTime];
|
||||
_attackProfileStateParams set [1, _firedLOS];
|
||||
|
@ -16,14 +16,27 @@
|
||||
*
|
||||
* Public: No
|
||||
*/
|
||||
#define PITCH_UP_TIME 1
|
||||
|
||||
params ["", "_args", "_seekerStateParams"];
|
||||
params ["", "_args", "_seekerStateParams", "", "", "_targetData"];
|
||||
_args params ["_firedEH", "_launchParams", "", "_seekerParams", "_stateParams"];
|
||||
_firedEH params ["","","","","","","_projectile"];
|
||||
_launchParams params ["", "_targetLaunchParams", "", "_attackProfile"];
|
||||
_targetLaunchParams params ["", "", "_launchPos"];
|
||||
_stateParams params ["", "", "", "", "_navigationParams"];
|
||||
|
||||
if (_attackProfile == QGVAR(directAttack)) exitWith {[0,0,0]};
|
||||
if (_attackProfile == QGVAR(directAttack)) exitWith {
|
||||
_navigationParams set [5, 1];
|
||||
[0,0,0]
|
||||
};
|
||||
|
||||
_seekerStateParams params ["", "", "", "_originalPitchRate", "_startTime"];
|
||||
_navigationParams params ["", "_pitchRate"];
|
||||
|
||||
// pitch up for the first second of flight to begin an over-fly trajectory
|
||||
private _pitchChange = linearConversion [0, PITCH_UP_TIME, CBA_missionTime - _startTime, 2, 0, true];
|
||||
_navigationParams set [1, _originalPitchRate + _pitchChange];
|
||||
_navigationParams set [5, ((CBA_missionTime - _startTime) min PITCH_UP_TIME) / PITCH_UP_TIME];
|
||||
|
||||
private _projPos = getPosASL _projectile;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user