Implement Metis SACLOS guidance (#6997)

* abc

* Revert "abc"

This reverts commit bcb4214bd9.

* Update to current commit

* Begin transfer of SACLOS into Missile Guidance

* Allow seeker and attack profiles to have their own "OnFired" functions

* Fix bugs with SACLOS

* Implement Metis wire guidance. Add "Beam" guidance

* add missing parenthesis

* Update how Wire/Beam guidance works. Add compatability for SACLOS planes. Move all base missile changes out of missileguidance and into their own files.

* try to cleanup merge

* minor stuff
This commit is contained in:
Brandon Danyluk 2019-12-16 19:01:30 -07:00 committed by PabstMirror
parent 392a0770b3
commit 316fbfe7b9
25 changed files with 275 additions and 94 deletions

View File

@ -1,21 +0,0 @@
class EGVAR(missileguidance,AttackProfiles) {
class WIRE {
name = CSTRING(missileType);
visualName = CSTRING(missileType);
description = CSTRING(missileType_Description);
functionName = QFUNC(attackProfile_WIRE);
onFired = QFUNC(wire_onFired);
};
};
class EGVAR(missileguidance,SeekerTypes) {
class SACLOS {
name = "SACLOS";
visualName = "SACLOS";
description = CSTRING(SACLOS_Description);
functionName = QFUNC(seekerType_SACLOS);
onFired = QFUNC(SACLOS_onFired);
};
};

View File

@ -77,7 +77,7 @@ class CfgAmmo {
seekerMinRange = 75; seekerMinRange = 75;
seekerMaxRange = 4000; // Range from the missile which the seeker can visually search seekerMaxRange = 4000; // Range from the missile which the seeker can visually search
correctionDistance = 15; // distance from center of crosshair where missile slows down 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. offsetFromCrosshair[] = { 0, 0, 0.5 }; // where the missile wants to stay in relation to the center of the crosshair.
// Attack profile type selection // Attack profile type selection

View File

@ -1,12 +0,0 @@
class Extended_PreStart_EventHandlers {
class ADDON {
init = QUOTE(call COMPILE_FILE(XEH_preStart));
};
};
class Extended_PreInit_EventHandlers {
class ADDON {
init = QUOTE(call COMPILE_FILE(XEH_preInit));
};
};

View File

@ -1,5 +0,0 @@
PREP(seekerType_SACLOS);
PREP(attackProfile_WIRE);
PREP(wire_onFired);
PREP(SACLOS_onFired);

View File

@ -1,10 +0,0 @@
#include "script_component.hpp"
ADDON = false;
PREP_RECOMPILE_START;
#include "XEH_PREP.hpp"
PREP_RECOMPILE_END;
ADDON = true;

View File

@ -1,4 +0,0 @@
#include "script_component.hpp"
#include "XEH_PREP.hpp"

View File

@ -14,8 +14,6 @@ class CfgPatches {
}; };
}; };
#include "ACE_GuidanceConfig.hpp"
#include "CfgEventHandlers.hpp"
#include "CfgAmmo.hpp" #include "CfgAmmo.hpp"
#include "CfgMagazines.hpp" #include "CfgMagazines.hpp"
#include "CfgWeapons.hpp" #include "CfgWeapons.hpp"

View File

@ -1,2 +0,0 @@
#include "\z\ace\addons\hot\script_component.hpp"

View File

@ -16,13 +16,3 @@
#include "\z\ace\addons\main\script_macros.hpp" #include "\z\ace\addons\main\script_macros.hpp"
#define RANDOM_VECTOR_3D (call {\
private _z = random 2 - 1;\
private _r = sqrt (1 - _z^2);\
private _theta = random 360;\
[_r * cos _theta, _r * sin _theta, _z]\
})
#define DEFAULT_CORRECTION_DISTANCE 10
#define DEFAULT_LEAD_DISTANCE 50

View File

@ -4,7 +4,7 @@ class CfgAmmo {
class Components; class Components;
}; };
class Missile_AGM_02_F : MissileBase {}; class Missile_AGM_02_F : MissileBase {};
class GVAR(L) : Missile_AGM_02_F { class GVAR(L) : Missile_AGM_02_F {
author = "xrufix"; author = "xrufix";
autoSeekTarget = 0; autoSeekTarget = 0;

1
addons/metis/$PBOPREFIX$ Normal file
View File

@ -0,0 +1 @@
z\ace\addons\metis

81
addons/metis/CfgAmmo.hpp Normal file
View File

@ -0,0 +1,81 @@
class CfgAmmo {
class M_Vorona_HEAT;
class GVAR(HEAT): M_Vorona_HEAT {
manualControl = 0;
irLock = 0;
laserLock = 0;
airLock = 0;
lockType = 0;
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.
canVanillaLock = 0; // Can this default vanilla lock? Only applicable to non-cadet mode
// Guidance type for munitions
defaultSeekerType = "SACLOS";
seekerTypes[] = { "SACLOS" };
defaultSeekerLockMode = "LOAL";
seekerLockModes[] = { "LOAL", "LOBL" };
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
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
defaultAttackProfile = "WIRE";
attackProfiles[] = {"WIRE"};
};
};
class M_Vorona_HE;
class GVAR(HE): M_Vorona_HE {
manualControl = 0;
irLock = 0;
laserLock = 0;
airLock = 0;
lockType = 0;
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.
canVanillaLock = 0; // Can this default vanilla lock? Only applicable to non-cadet mode
// Guidance type for munitions
defaultSeekerType = "SACLOS";
seekerTypes[] = { "SACLOS" };
defaultSeekerLockMode = "LOAL";
seekerLockModes[] = { "LOAL", "LOBL" };
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
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
defaultAttackProfile = "WIRE";
attackProfiles[] = {"WIRE"};
};
};
};

View File

@ -0,0 +1,10 @@
class CfgMagazines {
class CA_LauncherMagazine;
class Vorona_HEAT : CA_LauncherMagazine {
ammo = QGVAR(HEAT);
};
class Vorona_HE : Vorona_HEAT {
ammo = QGVAR(HE);
};
};

12
addons/metis/README.md Normal file
View File

@ -0,0 +1,12 @@
ace_metis
===================
Converts vanilla "Vorona" Missile Guidance into ACE SACLOS Guidance
## Maintainers
The people responsible for merging changes to this component or answering potential questions.
- [Brandon-TCVM](https://github.com/TheCandianVendingMachine)

19
addons/metis/config.cpp Normal file
View File

@ -0,0 +1,19 @@
#include "script_component.hpp"
class CfgPatches {
class ADDON {
name = COMPONENT_NAME;
units[] = {};
weapons[] = {};
requiredVersion = REQUIRED_VERSION;
requiredAddons[] = {"ace_missileguidance"};
author = ECSTRING(common,ACETeam);
authors[] = {"Brandon (TCVM)"};
url = ECSTRING(main,URL);
VERSION_CONFIG;
};
};
#include "CfgAmmo.hpp"
#include "CfgMagazines.hpp"

View File

@ -0,0 +1,18 @@
#define COMPONENT metis
#define COMPONENT_BEAUTIFIED Metis
#include "\z\ace\addons\main\script_mod.hpp"
// #define DEBUG_MODE_FULL
// #define DISABLE_COMPILE_CACHE
// #define ENABLE_PERFORMANCE_COUNTERS
#ifdef DEBUG_ENABLED_METIS
#define DEBUG_MODE_FULL
#endif
#ifdef DEBUG_SETTINGS_METIS
#define DEBUG_SETTINGS DEBUG_SETTINGS_METIS
#endif
#include "\z\ace\addons\main\script_macros.hpp"

View File

@ -41,6 +41,22 @@ class GVAR(AttackProfiles) {
functionName = QFUNC(attackProfile_JAV_TOP); functionName = QFUNC(attackProfile_JAV_TOP);
}; };
class WIRE {
name = "";
visualName = "";
description = "";
functionName = QFUNC(attackProfile_WIRE);
onFired = QFUNC(wire_onFired);
};
class BEAM {
name = "";
visualName = "";
description = "";
functionName = QFUNC(attackProfile_BEAM);
onFired = QFUNC(wire_onFired); // since Beam guidance is pretty much the same as Wire guidance, we can reuse this
};
}; };
class GVAR(SeekerTypes) { class GVAR(SeekerTypes) {
@ -58,4 +74,12 @@ class GVAR(SeekerTypes) {
functionName = QFUNC(seekerType_Optic); functionName = QFUNC(seekerType_Optic);
}; };
class SACLOS {
name = "";
visualName = "";
description = "";
functionName = QFUNC(seekerType_SACLOS);
onFired = QFUNC(SACLOS_onFired);
};
}; };

View File

@ -10,7 +10,7 @@ PREP(onFired);
PREP(onIncomingMissile); PREP(onIncomingMissile);
PREP(guidancePFH); PREP(guidancePFH);
PREP(doAttackProfile); PREP(doAttackProfile);
PREP(doSeekerSearch); PREP(doSeekerSearch);
PREP(doHandoff); PREP(doHandoff);
@ -22,6 +22,8 @@ PREP(attackProfile_DIR);
PREP(attackProfile_HI); PREP(attackProfile_HI);
PREP(attackProfile_LIN); PREP(attackProfile_LIN);
PREP(attackProfile_MID); PREP(attackProfile_MID);
PREP(attackProfile_WIRE);
PREP(attackProfile_BEAM);
// Javelin profiles // Javelin profiles
PREP(attackProfile_JAV_DIR); PREP(attackProfile_JAV_DIR);
@ -30,3 +32,10 @@ PREP(attackProfile_JAV_TOP);
// Seeker search functions // Seeker search functions
PREP(seekerType_SALH); PREP(seekerType_SALH);
PREP(seekerType_Optic); PREP(seekerType_Optic);
PREP(seekerType_SACLOS);
// Attack Profiles OnFired
PREP(wire_onFired);
// Seeker OnFired
PREP(SACLOS_onFired);

View File

@ -10,7 +10,7 @@
* None * None
* *
* Example: * Example:
* [] call ace_hot_fnc_SACLOS_onFired * [] call ace_missileguidance_fnc_SACLOS_onFired
* *
* Public: No * Public: No
*/ */
@ -19,9 +19,8 @@ _firedEH params ["_shooter","_weapon","","","","","_projectile"];
_stateParams params ["", "_seekerStateParams"]; _stateParams params ["", "_seekerStateParams"];
private _config = ([_projectile] call CBA_fnc_getObjectConfig) >> "ace_missileguidance"; private _config = ([_projectile] call CBA_fnc_getObjectConfig) >> "ace_missileguidance";
private _distanceAheadOfMissile = [_config >> "missileLeadDistance", "NUMBER", DEFAULT_LEAD_DISTANCE] call CBA_fnc_getConfigEntry;
if (_shooter isKindOf "Plane") then { WARNING("SACLOS fired from planes unsupported"); }; if (_shooter isKindOf "Plane" && { !hasPilotCamera _shooter }) exitWith { WARNING("SACLOS fired from planes without camera unsupported"); };
private _turretPath = [_shooter, _weapon] call CBA_fnc_turretPathWeapon; private _turretPath = [_shooter, _weapon] call CBA_fnc_turretPathWeapon;
private _turretConfig = [_shooter, _turretPath] call CBA_fnc_getTurret; private _turretConfig = [_shooter, _turretPath] call CBA_fnc_getTurret;
@ -31,5 +30,4 @@ private _animationSourceGun = getText(_turretConfig >> "animationSourceGun");
_seekerStateParams set [0, _memoryPointGunnerOptics]; _seekerStateParams set [0, _memoryPointGunnerOptics];
_seekerStateParams set [1, _animationSourceBody]; _seekerStateParams set [1, _animationSourceBody];
_seekerStateParams set [2, _animationSourceGun]; _seekerStateParams set [2, _animationSourceGun];
_seekerStateParams set [3, _distanceAheadOfMissile];

View File

@ -0,0 +1,47 @@
#include "script_component.hpp"
/*
* Author: Brandon (TCVM)
* Attack profile: Beam guided. Exact same as wire-guided, except no wire cutting
*
* Arguments:
* 0: Seeker Target PosASL <ARRAY>
* 1: Guidance Arg Array <ARRAY>
* 2: Attack Profile State <ARRAY>
*
* Return Value:
* Missile Aim PosASL <ARRAY>
*
* Example:
* [[1,2,3], [], []] call ace_missileguidance_fnc_attackProfile_BEAM;
*
* Public: No
*/
params ["_seekerTargetPos", "_args", "_attackProfileStateParams"];
_args params ["_firedEH"];
_firedEH params ["_shooter","","","","","","_projectile"];
_attackProfileStateParams params["_maxCorrectableDistance", "_wireCut", "_randomVector", "_crosshairOffset", "_seekerMaxRangeSqr", "_seekerMinRangeSqr", "_wireCutSource", "_distanceAheadOfMissile"];
private _projectilePos = getPosASL _projectile;
private _shooterPos = getPosASL _shooter;
private _shooterDir = vectorNormalized(_seekerTargetPos vectorDiff _shooterPos);
private _distanceToProjectile = _shooterPos vectorDistanceSqr _projectilePos;
if (_distanceToProjectile > _seekerMaxRangeSqr || { _seekerTargetPos isEqualTo [0, 0, 0] } || { _distanceToProjectile < _seekerMinRangeSqr }) exitWith {
// return position 50m infront of projectile
_projectilePos vectorAdd (_projectile vectorModelToWorld [0, 50, 0])
};
private _relativeCorrection = _projectile vectorWorldToModel (_projectilePos vectorDiff _seekerTargetPos);
_relativeCorrection = _relativeCorrection vectorDiff _crosshairOffset;
private _magnitude = vectorMagnitude [_relativeCorrection select 0, 0, _relativeCorrection select 2];
private _fovImpulse = 1 min (_magnitude / _maxCorrectableDistance); // the simulated impulse for the missile being close to the center of the crosshair
// Adjust the impulse due to near-zero values creating wobbly missiles?
private _correction = _fovImpulse;
_relativeCorrection = (vectorNormalized _relativeCorrection) vectorMultiply _correction;
private _returnPos = _projectilePos vectorDiff (_projectile vectorModelToWorld _relativeCorrection);
_returnPos vectorAdd (_shooterDir vectorMultiply _distanceAheadOfMissile)

View File

@ -12,18 +12,22 @@
* Missile Aim PosASL <ARRAY> * Missile Aim PosASL <ARRAY>
* *
* Example: * Example:
* [[1,2,3], [], []] call ace_hot_fnc_attackProfile_WIRE; * [[1,2,3], [], []] call ace_missileguidance_fnc_attackProfile_WIRE;
* *
* Public: No * Public: No
*/ */
params ["_seekerTargetPos", "_args", "_attackProfileStateParams"]; params ["_seekerTargetPos", "_args", "_attackProfileStateParams"];
_args params ["_firedEH"]; _args params ["_firedEH"];
_firedEH params ["_shooter","","","","","","_projectile"]; _firedEH params ["_shooter","","","","","","_projectile"];
_attackProfileStateParams params["_maxCorrectableDistance", "_wireCut", "_randomVector", "_crosshairOffset", "_seekerMaxRangeSqr", "", "_wireCutSource"]; _attackProfileStateParams params["_maxCorrectableDistance", "_wireCut", "_randomVector", "_crosshairOffset", "_seekerMaxRangeSqr", "_seekerMinRangeSqr", "_wireCutSource", "_distanceAheadOfMissile"];
private _projectilePos = getPosASL _projectile; private _projectilePos = getPosASL _projectile;
private _shooterPos = getPosASL _shooter;
if ((((getPosASL _shooter) vectorDistanceSqr _projectilePos) > _seekerMaxRangeSqr) || { _wireCut }) exitWith { private _shooterDir = vectorNormalized(_seekerTargetPos vectorDiff _shooterPos);
private _distanceToProjectile = _shooterPos vectorDistanceSqr _projectilePos;
if ((_distanceToProjectile > _seekerMaxRangeSqr) || { _wireCut }) exitWith {
// wire snap, random direction // wire snap, random direction
if (_randomVector isEqualTo [0, 0, 0]) then { if (_randomVector isEqualTo [0, 0, 0]) then {
_randomVector = RANDOM_VECTOR_3D vectorMultiply 300; _randomVector = RANDOM_VECTOR_3D vectorMultiply 300;
@ -35,7 +39,7 @@ if ((((getPosASL _shooter) vectorDistanceSqr _projectilePos) > _seekerMaxRangeSq
_projectilePos vectorAdd _randomVector _projectilePos vectorAdd _randomVector
}; };
if (_seekerTargetPos isEqualTo [0, 0, 0]) exitWith { if (_seekerTargetPos isEqualTo [0, 0, 0] || { _distanceToProjectile < _seekerMinRangeSqr }) exitWith {
// cut wire if its caught on terrain // cut wire if its caught on terrain
/*if !(lineIntersectsSurfaces [getPosASL _shooter, _projectilePos, _shooter] isEqualTo []) then { /*if !(lineIntersectsSurfaces [getPosASL _shooter, _projectilePos, _shooter] isEqualTo []) then {
_attackProfileStateParams set [1, true]; _attackProfileStateParams set [1, true];
@ -48,13 +52,12 @@ private _relativeCorrection = _projectile vectorWorldToModel (_projectilePos vec
_relativeCorrection = _relativeCorrection vectorDiff _crosshairOffset; _relativeCorrection = _relativeCorrection vectorDiff _crosshairOffset;
private _magnitude = vectorMagnitude [_relativeCorrection select 0, 0, _relativeCorrection select 2]; private _magnitude = vectorMagnitude [_relativeCorrection select 0, 0, _relativeCorrection select 2];
private _fovImpulse = 1 min (_magnitude / _maxCorrectableDistance); // the simulated impulse for the missile being close to the center of the crosshair private _fovImpulse = 1 min (_magnitude / _maxCorrectableDistance); // the simulated impulse for the missile being close to the center of the crosshair
// Adjust the impulse due to near-zero values creating wobbly missiles? // Adjust the impulse due to near-zero values creating wobbly missiles?
private _correction = _fovImpulse; private _correction = _fovImpulse;
_relativeCorrection = (vectorNormalized _relativeCorrection) vectorMultiply _correction; _relativeCorrection = (vectorNormalized _relativeCorrection) vectorMultiply _correction;
private _returnPos = _projectilePos vectorDiff (_projectile vectorModelToWorld _relativeCorrection);
_projectilePos vectorDiff (_projectile vectorModelToWorld _relativeCorrection); _returnPos vectorAdd (_shooterDir vectorMultiply _distanceAheadOfMissile)

View File

@ -123,27 +123,27 @@ TRACE_1("",_onFiredFunc);
if (_onFiredFunc != "") then { if (_onFiredFunc != "") then {
_args call (missionNamespace getVariable _onFiredFunc); _args call (missionNamespace getVariable _onFiredFunc);
}; };
_onFiredFunc = getText (configFile >> QGVAR(AttackProfiles) >> _attackProfile >> "onFired"); _onFiredFunc = getText (configFile >> QGVAR(AttackProfiles) >> _attackProfile >> "onFired");
TRACE_1("",_onFiredFunc); TRACE_1("",_onFiredFunc);
if (_onFiredFunc != "") then { if (_onFiredFunc != "") then {
_args call (missionNamespace getVariable _onFiredFunc); _args call (missionNamespace getVariable _onFiredFunc);
}; };
// Run the "onFired" function passing the full guidance args array // Run the "onFired" function passing the full guidance args array
_onFiredFunc = getText (_config >> "onFired"); _onFiredFunc = getText (_config >> "onFired");
TRACE_1("",_onFiredFunc); TRACE_1("",_onFiredFunc);
if (_onFiredFunc != "") then { if (_onFiredFunc != "") then {
_args call (missionNamespace getVariable _onFiredFunc); _args call (missionNamespace getVariable _onFiredFunc);
}; };
// Reverse: // Reverse:
// _args params ["_firedEH", "_launchParams", "_flightParams", "_seekerParams", "_stateParams"]; // _args params ["_firedEH", "_launchParams", "_flightParams", "_seekerParams", "_stateParams"];
// _firedEH params ["_shooter","","","","_ammo","","_projectile"]; // _firedEH params ["_shooter","","","","_ammo","","_projectile"];
// _launchParams params ["_shooter","_targetLaunchParams","_seekerType","_attackProfile","_lockMode","_laserInfo"]; // _launchParams params ["_shooter","_targetLaunchParams","_seekerType","_attackProfile","_lockMode","_laserInfo"];
// _targetLaunchParams params ["_target", "_targetPos", "_launchPos"]; // _targetLaunchParams params ["_target", "_targetPos", "_launchPos"];
// _stateParams params ["_lastRunTime", "_seekerStateParams", "_attackProfileStateParams", "_lastKnownPosState"]; // _stateParams params ["_lastRunTime", "_seekerStateParams", "_attackProfileStateParams", "_lastKnownPosState"];
// _seekerParams params ["_seekerAngle", "_seekerAccuracy", "_seekerMaxRange"]; // _seekerParams params ["_seekerAngle", "_seekerAccuracy", "_seekerMaxRange", "_seekerMinRange"];
[FUNC(guidancePFH), 0, _args ] call CBA_fnc_addPerFrameHandler; [FUNC(guidancePFH), 0, _args ] call CBA_fnc_addPerFrameHandler;

View File

@ -11,7 +11,7 @@
* Position of wanted missile pos relative to the camera direction <ARRAY> * Position of wanted missile pos relative to the camera direction <ARRAY>
* *
* Example: * Example:
* [] call ace_hot_fnc_seekerType_SACLOS * [] call ace_missileguidance_fnc_seekerType_SACLOS
* *
* Public: No * Public: No
*/ */
@ -20,16 +20,28 @@ _args params ["_firedEH", "", "", "_seekerParams", "_stateParams"];
_firedEH params ["_shooter","_weapon","","","","","_projectile"]; _firedEH params ["_shooter","_weapon","","","","","_projectile"];
_seekerParams params ["_seekerAngle"]; _seekerParams params ["_seekerAngle"];
_stateParams params ["", "_seekerStateParams"]; _stateParams params ["", "_seekerStateParams"];
_seekerStateParams params ["_memoryPointGunnerOptics", "_animationSourceBody", "_animationSourceGun", "_distanceAheadOfMissile"]; _seekerStateParams params ["_memoryPointGunnerOptics", "_animationSourceBody", "_animationSourceGun"];
private _shooterPos = AGLToASL (_shooter modelToWorld(_shooter selectionPosition _memoryPointGunnerOptics)); private _shooterPos = AGLToASL (_shooter modelToWorld(_shooter selectionPosition _memoryPointGunnerOptics));
private _projPos = getPosASL _projectile; private _projPos = getPosASL _projectile;
private _lookDirection = if !(_shooter isKindOf "CAManBase" || {_shooter isKindOf "StaticWeapon"}) then { private _lookDirection = if !(_shooter isKindOf "CAManBase" || {_shooter isKindOf "StaticWeapon"}) then {
private _gBody = -deg(_shooter animationPhase _animationSourceBody); private _finalLookDirection = if (_shooter isKindOf "Plane") then {
private _gGun = deg(_shooter animationPhase _animationSourceGun); _shooterPos = _shooter modelToWorldVisualWorld getPilotCameraPosition _shooter;
private _trackingTarget = getPilotCameraTarget _shooter;
_shooter vectorModelToWorld ([1, _gBody, _gGun] call CBA_fnc_polar2vect); _trackingTarget params ["_isTracking", "_trackingPos"];
// Because ARMA doesnt update the camera rotation if you are locked on immediatly, we have to calculate the look direction manually or else the SACLOS target will be wrong, especially if shooter is moving
if (_isTracking) then {
vectorNormalized (_trackingPos vectorDiff _shooterPos);
} else {
_shooter vectorModelToWorldVisual getPilotCameraDirection _shooter;
};
} else {
private _gBody = -deg(_shooter animationPhase _animationSourceBody);
private _gGun = deg(_shooter animationPhase _animationSourceGun);
_shooter vectorModelToWorldVisual ([1, _gBody, _gGun] call CBA_fnc_polar2vect);
};
_finalLookDirection
} else { } else {
_shooterPos = eyePos _shooter; _shooterPos = eyePos _shooter;
_shooter weaponDirection _weapon _shooter weaponDirection _weapon
@ -46,5 +58,5 @@ if ((_testDotProduct < (cos _seekerAngle)) || { !(_testIntersections isEqualTo [
[0, 0, 0] [0, 0, 0]
}; };
_shooterPos vectorAdd (_lookDirection vectorMultiply (_distanceToProj + _distanceAheadOfMissile)); _shooterPos vectorAdd (_lookDirection vectorMultiply _distanceToProj);

View File

@ -10,7 +10,7 @@
* None * None
* *
* Example: * Example:
* [] call ace_hot_fnc_wire_onFired * [] call ace_missileguidance_fnc_wire_onFired
* *
* Public: No * Public: No
*/ */
@ -21,11 +21,12 @@ _seekerParams params ["", "", "_seekerMaxRange", "_seekerMinRange"];
private _config = ([_projectile] call CBA_fnc_getObjectConfig) >> "ace_missileguidance"; private _config = ([_projectile] call CBA_fnc_getObjectConfig) >> "ace_missileguidance";
private _maxCorrectableDistance = [_config >> "correctionDistance", "NUMBER", DEFAULT_CORRECTION_DISTANCE] call CBA_fnc_getConfigEntry; private _maxCorrectableDistance = [_config >> "correctionDistance", "NUMBER", DEFAULT_CORRECTION_DISTANCE] call CBA_fnc_getConfigEntry;
private _distanceAheadOfMissile = [_config >> "missileLeadDistance", "NUMBER", DEFAULT_LEAD_DISTANCE] call CBA_fnc_getConfigEntry;
private _maxDistanceSqr = _seekerMaxRange * _seekerMaxRange; private _maxDistanceSqr = _seekerMaxRange * _seekerMaxRange;
private _minDistanceSqr = _seekerMinRange * _seekerMinRange; private _minDistanceSqr = _seekerMinRange * _seekerMinRange;
// AI don't know how to use the crosshair offset becauze they dum dum // AI don't know how to use the crosshair offset becauze they dum dum
_crosshairOffset = if ((_gunner != ACE_PLAYER) && {_gunner != (ACE_controlledUAV select 1)}) then { private _crosshairOffset = if ((_gunner != ACE_PLAYER) && {_gunner != (ACE_controlledUAV select 1)}) then {
[0, 0, 0]; [0, 0, 0];
} else { } else {
[_config >> "offsetFromCrosshair", "ARRAY", [0, 0, 0]] call CBA_fnc_getConfigEntry [_config >> "offsetFromCrosshair", "ARRAY", [0, 0, 0]] call CBA_fnc_getConfigEntry
@ -43,4 +44,5 @@ _attackProfileStateParams set [3, _crosshairOffset]; // crosshair offset
_attackProfileStateParams set [4, _maxDistanceSqr]; // max distance squared used for wire cut _attackProfileStateParams set [4, _maxDistanceSqr]; // max distance squared used for wire cut
_attackProfileStateParams set [5, _minDistanceSqr]; _attackProfileStateParams set [5, _minDistanceSqr];
_attackProfileStateParams set [6, _wireCutSource]; _attackProfileStateParams set [6, _wireCutSource];
_attackProfileStateParams set [7, _distanceAheadOfMissile];

View File

@ -16,3 +16,14 @@
#endif #endif
#include "\z\ace\addons\main\script_macros.hpp" #include "\z\ace\addons\main\script_macros.hpp"
#define RANDOM_VECTOR_3D (call {\
private _z = random 2 - 1;\
private _r = sqrt (1 - _z^2);\
private _theta = random 360;\
[_r * cos _theta, _r * sin _theta, _z]\
})
#define DEFAULT_CORRECTION_DISTANCE 2
#define DEFAULT_LEAD_DISTANCE 5