Handle pre-tracking

This commit is contained in:
Brandon Danyluk 2021-12-12 01:26:40 -07:00
parent 7460bb335e
commit 8da028b626
15 changed files with 349 additions and 91 deletions

View File

@ -1,7 +1,7 @@
class CfgAmmo {
class MissileBase;
class M_Titan_AT: MissileBase {};
class GVAR(at): M_Titan_AT {
class GVAR(lr): M_Titan_AT {
timeToLive = 120;
manualControl = 0;

View File

@ -1,8 +1,8 @@
class CfgMagazines {
class Titan_AT;
class GVAR(at): Titan_AT {
class GVAR(lr): Titan_AT {
author = "Brandon (TCVM)";
ammo = QGVAR(at);
ammo = QGVAR(lr);
displayName = "Spike AT";
displayNameShort = "foo";

View File

@ -10,7 +10,7 @@ class CfgWeapons {
class GVAR(launcher): GVAR(base) {
scope = 2;
GVAR(enabled) = 1;
//weaponInfoType = "ACE_RscOptics_javelin";
weaponInfoType = "ACE_RscOptics_spike";
//modelOptics = QPATHTOF(data\reticle_titan.p3d);
canLock = 0;
@ -21,7 +21,7 @@ class CfgWeapons {
displayName = "Spike AT";
displayNameShort = "Spike AT";
magazines[] = {QGVAR(at)};
magazines[] = {QGVAR(lr)};
};
};

View File

@ -0,0 +1,118 @@
// Taken from AGM for optics management.
class RscInGameUI {
class ACE_RscOptics_spike {
idd = 141000;
controls[] = { reticle, GVAR(mapHelper) };
onLoad = QUOTE(with uiNamespace do {ACE_RscOptics_spike = _this select 0;};);
class GVAR(mapHelper): RscMapControl {
onDraw = QUOTE(_this call FUNC(mapHelperDraw););
x = 0;
y = 0;
w = 0;
h = 0;
};
class reticle: RscControlsGroupNoScrollbars {
idc = 242000;
x = "safeZoneX";
y = "safeZoneY";
w = "safeZoneW-safeZoneX";
h = "safeZoneH-safeZoneY";
enabled = 1;
show = 0;
class controls {
class lineV: RscControlsGroupNoScrollbars {
idc = 243100;
enabled = 1;
show = 1;
class Controls {
class lineBlack: RscText {
x = "safeZoneX + (SafeZoneW * 0.501)";
y = "safeZoneY + (SafeZoneH * 0.53)";
w = "safeZoneW * 0.0025";
h = "safeZoneH * 0.1";
colorBackground[] = COLOR_BLACK;
};
class lineWhite: RscText {
x = "safeZoneX + (SafeZoneW * 0.504)";
y = "safeZoneY + (SafeZoneH * 0.53)";
w = "safeZoneW * 0.0025";
h = "safeZoneH * 0.1";
colorBackground[] = COLOR_WHITE;
};
class squareB: RscText {
idc = 243101;
x = "safeZoneX + safeZoneW * 0.499";
y = "safeZoneY + safeZoneH * 0.52";
w = "safeZoneH * 0.006";
h = "safeZoneW * 0.006";
colorBackground[] = COLOR_BLACK;
};
};
};
class lineHL: RscControlsGroupNoScrollbars {
idc = 243200;
enabled = 1;
show = 1;
class Controls {
class lineBlack: RscText {
x = "safeZoneY + (SafeZoneH * 0.37)";
y = "safeZoneX + (SafeZoneW * 0.5)";
w = "safeZoneH * 0.1";
h = "safeZoneW * 0.003";
colorBackground[] = COLOR_BLACK;
};
class lineWhite: RscText {
x = "safeZoneY + (SafeZoneH * 0.37)";
y = "safeZoneX + (SafeZoneW * 0.504)";
w = "safeZoneH * 0.1";
h = "safeZoneW * 0.0023";
colorBackground[] = COLOR_WHITE;
};
class squareL: RscText {
idc = 243201;
x = "safeZoneX + (SafeZoneW * 0.485)";
y = "safeZoneY + safeZoneH * 0.5";
w = "safeZoneH * 0.006";
h = "safeZoneW * 0.006";
colorBackground[] = COLOR_BLACK;
};
};
};
class lineHR: RscControlsGroupNoScrollbars {
idc = 243300;
enabled = 1;
show = 1;
class Controls {
class lineBlack: RscText {
x = "safeZoneY + (SafeZoneH * 0.53)";
y = "safeZoneX + (SafeZoneW * 0.5)";
w = "safeZoneH * 0.1";
h = "safeZoneW * 0.003";
colorBackground[] = COLOR_BLACK;
};
class lineWhite: RscText {
x = "safeZoneY + (SafeZoneH * 0.53)";
y = "safeZoneX + (SafeZoneW * 0.504)";
w = "safeZoneH * 0.1";
h = "safeZoneW * 0.0023";
colorBackground[] = COLOR_WHITE;
};
class squareR: RscText {
idc = 243301;
x = "safeZoneX + (SafeZoneW * 0.515)";
y = "safeZoneY + safeZoneH * 0.5";
w = "safeZoneH * 0.006";
h = "safeZoneW * 0.006";
colorBackground[] = COLOR_BLACK;
};
};
};
};
};
};
};

View File

@ -1,12 +1,3 @@
class RscOpticsValue;
class RscControlsGroupNoScrollbars;
class RscPicture;
class RscLine;
class RscMapControl;
class RscText;
#define COLOR_WHITE {0.8745,0.8745,0.8745,1}
#define COLOR_BLACK {0,0,0,1}
class RscTitles {
class ACE_guidance_spike {

View File

@ -3,7 +3,6 @@ PREP(camera_cycleViewMode);
PREP(camera_destroy);
PREP(camera_handleKeyPress);
PREP(camera_init);
PREP(camera_preTrack);
PREP(camera_setViewMode);
PREP(camera_setZoom);
PREP(camera_switchAway);
@ -16,4 +15,6 @@ PREP(onFired);
PREP(seeker);
PREP(navigation);
PREP(midCourseTransition);
PREP(mapHelperDraw);
PREP(getTargetPosition);

View File

@ -14,8 +14,19 @@ class CfgPatches {
};
};
class RscOpticsValue;
class RscControlsGroupNoScrollbars;
class RscPicture;
class RscLine;
class RscMapControl;
class RscText;
#define COLOR_WHITE {0.8745,0.8745,0.8745,1}
#define COLOR_BLACK {0,0,0,1}
#include "ACE_GuidanceConfig.hpp"
#include "RscTitles.hpp"
#include "RscInGameUI.hpp"
#include "CfgEventhandlers.hpp"
#include "CfgAmmo.hpp"
#include "CfgMagazines.hpp"

View File

@ -19,8 +19,6 @@ params ["_key", "_down"];
if !([objNull] call FUNC(camera_userInCamera)) exitWith {};
playSound "ACE_Sound_Click";
private _return = false;
private _lookInput = GVAR(activeCamera) getVariable [QGVAR(lookInput), [0, 0, 0, 0]];
private _designateInput = GVAR(activeCamera) getVariable [QGVAR(designateInput), [0]];

View File

@ -15,7 +15,7 @@
*
* Public: No
*/
params ["_projectile", "_cameraArray", "_shooter"];
params ["_projectile", "_cameraArray", "_shooter", "_switchOnFireInit"];
_cameraArray params ["_enabled", "_fovLevels", "_initialFOV", "_thermalTypes", "_initialThermalType", "_switchOnFire", "_lerpFOV", "_fovChangeTime", "", "_gimbalData", "_reticleData", "_designating"];
_gimbalData params ["_hasGimbal", "_maxGimbalX", "_maxGimbalY", "_gimbalSpeedX", "_gimbalSpeedY", "_initGimbalAngleX", "_initGimbalAngleY", "_gimbalZoomSpeedModifiers"];
@ -78,7 +78,7 @@ _activeCameraNamespace setVariable [QGVAR(logic), _logic];
_activeCameraNamespace setVariable [QGVAR(missile), _projectile];
_activeCameraNamespace setVariable [QGVAR(logicPos), _projectile vectorModelToWorldVisual _logicPosition];
if (_switchOnFire) then {
if (_switchOnFire && _switchOnFireInit) then {
[_activeCameraNamespace] call FUNC(camera_switchTo);
};

View File

@ -0,0 +1,92 @@
#include "script_component.hpp"
/*
* Author: Brandon (TCVM)
* Return the position of a potential EO target via a "edge detection" algorithm. Compares object bounding boxes to see what we are most likely hitting
*
* Arguments:
* 1: Origin <ARRAY>
* 2: Direction <ARRAY>
* 3: If we are designating <NUMBER>
*
* Return Value:
* Missile Aim PosASL <ARRAY>
*
* Example:
* [[], [], []] call ace_spike_fnc_getTargetPosition;
*
* Public: No
*/
params ["_origin", "_direction", "_designateInput", "_seekerTargetPos", ["_ignoreObject", objNull]];
private _nearObjects = [];
private _intersections = lineIntersectsSurfaces [_origin, _origin vectorAdd (_direction vectorMultiply 5000), _ignoreObject, objNull, true, 1, "FIRE", "VIEW", true];
if (_intersections isNotEqualTo []) then {
(_intersections#0) params ["_intersectPos", "", "_object"];
if (_designateInput == 1) then {
_seekerTargetPos = _intersectPos;
};
_nearObjects = (ASLtoAGL _seekerTargetPos) nearObjects ["AllVehicles", 5];
if (_designateInput == 1 && { !isNull _object }) then {
_nearObjects pushBack _object;
};
};
if (_nearObjects isNotEqualTo []) then {
// I want to prefer the designated position on the object moreso than the bounds of the object
private _averagePosition = _seekerTargetPos vectorMultiply 15;
private _averagePositionCounter = 15;
private _closestObject = objNull;
private _closestDistance = 1e10;
{
if ((getPosASLVisual _x) vectorDistanceSqr _seekerTargetPos < _closestDistance) then {
_closestDistance = (getPosASLVisual _x) vectorDistanceSqr _seekerTargetPos;
_closestObject = _x;
};
} forEach _nearObjects;
private _boundingBox = 0 boundingBoxReal _closestObject;
// Project target bounding box onto screen and do a real bad edge detection check
_boundingBox params ["_min", "_max"];
_min params ["_x0", "_y0", "_z0"];
_max params ["_x1", "_y1", "_z1"];
private _utl = _closestObject modelToWorldVisualWorld [_x0, _y0, _z0];
private _utr = _closestObject modelToWorldVisualWorld [_x1, _y0, _z0];
private _ubr = _closestObject modelToWorldVisualWorld [_x1, _y1, _z0];
private _ubl = _closestObject modelToWorldVisualWorld [_x0, _y1, _z0];
private _dtl = _closestObject modelToWorldVisualWorld [_x0, _y0, _z1];
private _dtr = _closestObject modelToWorldVisualWorld [_x1, _y0, _z1];
private _dbr = _closestObject modelToWorldVisualWorld [_x1, _y1, _z1];
private _dbl = _closestObject modelToWorldVisualWorld [_x0, _y1, _z1];
{
private _intersections = lineIntersectsSurfaces [_origin, _x, _ignoreObject, objNull, false, 16];
if (_intersections isEqualTo []) then {
_averagePosition = _averagePosition vectorAdd _x;
_averagePositionCounter = _averagePositionCounter + 1;
} else {
{
_x params ["_surfacePosition"];
_averagePosition = _averagePosition vectorAdd _surfacePosition;
_averagePositionCounter = _averagePositionCounter + 1;
} forEach _intersections;
}
} forEach [_utl, _utr, _ubr, _ubl, _dtl, _dtr, _dbr, _dbl];
_seekerTargetPos = _averagePosition vectorMultiply (1 / _averagePositionCounter);
} else {
if (_designateInput == 1) then {
_seekerTargetPos = [0, 0, 0];
};
};
_seekerTargetPos

View File

@ -17,4 +17,17 @@
*/
params ["_key", "_down"];
if (_key == SPIKE_KEY_DESIGNATE) then {
if (cameraView == "GUNNER") then {
playSound "ACE_Sound_Click";
};
private _designateInput = 0;
if (_down) then {
_designateInput = 1;
} else {
_designateInput = 0;
};
(uiNamespace getVariable "ACE_RscOptics_spike") setVariable [QGVAR(designate), _designateInput];
};
_this call FUNC(camera_handleKeyPress);

View File

@ -0,0 +1,94 @@
#include "script_component.hpp"
/*
* Author: Brandon (TCVM)
* Handles the map helper's draw event
* Resets arguments if not run recently
* And starts a watchdog to detect when weapon display unloaded
*
* Arguments:
* None
*
* Return Value:
* None
*
* Example:
* [] call ace_spike_fnc_mapHelperDraw
*
* Public: No
*/
#define __SPIKE_DISPLAY (uinamespace getVariable "ACE_RscOptics_spike")
#define __SPIKE_RETICLE (__SPIKE_DISPLAY displayCtrl 242000)
private _currentShooter = if (ACE_player call CBA_fnc_canUseWeapon) then {ACE_player} else {vehicle ACE_player};
if (isNil QGVAR(arguments)) then {
TRACE_1("Starting optic draw", _this);
// reset shooter var:
_currentShooter setVariable ["ace_missileguidance_target", nil, false];
GVAR(arguments) = [
diag_frameno, // Last run frame
[0, 0, 0] // currentTargetObject
];
// Start up a watchdog for when the display is no longer shown (but might not be unloaded or null)
[{
if (isNull (uiNamespace getVariable ["ACE_RscOptics_spike", displayNull])) exitWith {true};
GVAR(arguments) params ["_lastRunFrame"];
(diag_frameno < _lastRunFrame) || {diag_frameno > (_lastRunFrame + 1)}
}, {
TRACE_1("old/null display - ending optic draw",_this);
GVAR(arguments) = nil;
}, []] call CBA_fnc_waitUntilAndExecute;
};
if (cameraView isEqualTo "GUNNER") then {
GVAR(arguments) set [0, diag_frameNo];
__SPIKE_RETICLE ctrlShow true;
GVAR(arguments) params ["", "_targetPosition"];
private _currentAmmo = _currentShooter ammo currentWeapon _currentShooter;
private _designating = __SPIKE_DISPLAY getVariable [QGVAR(designate), 0];
if (_currentAmmo != 0 && { _designating == 1 || _targetPosition isNotEqualTo [0, 0, 0] }) then {
_targetPosition = [eyePos _currentShooter, getCameraViewDirection _currentShooter, _designating, _targetPosition, _currentShooter] call FUNC(getTargetPosition);
GVAR(arguments) set [1, _targetPosition];
};
if (_currentAmmo == 0) then {
__SPIKE_RETICLE ctrlShow false;
} else {
if (_targetPosition isEqualTo [0, 0, 0]) then {
__SPIKE_RETICLE ctrlSetPosition [0, 0];
(__SPIKE_DISPLAY displayCtrl 243101) ctrlShow false;
(__SPIKE_DISPLAY displayCtrl 243201) ctrlShow false;
(__SPIKE_DISPLAY displayCtrl 243301) ctrlShow false;
} else {
(__SPIKE_DISPLAY displayCtrl 243101) ctrlShow true;
(__SPIKE_DISPLAY displayCtrl 243201) ctrlShow true;
(__SPIKE_DISPLAY displayCtrl 243301) ctrlShow true;
_seekerPositionScreen = worldToScreen ASLtoAGL _targetPosition;
if (_seekerPositionScreen isEqualTo []) then {
_seekerPositionScreen = [0, 0];
};
_seekerPositionScreen set [0, _seekerPositionScreen#0 - 0.5];
_seekerPositionScreen set [1, _seekerPositionScreen#1 - 0.5];
__SPIKE_RETICLE ctrlSetPosition _seekerPositionScreen;
if (abs (_seekerPositionScreen#0) > 0.2 || abs (_seekerPositionScreen#1) > 0.2) then {
GVAR(arguments) set [1, [0, 0, 0]];
};
};
_currentShooter setVariable [QGVAR(target), _targetPosition];
};
__SPIKE_RETICLE ctrlCommit 0;
} else {
__SPIKE_RETICLE ctrlShow false;
};

View File

@ -67,8 +67,9 @@ if (!(_cameraConfig isEqualTo configNull) && { (getNumber (_cameraConfig >> "ena
_cameraArray set [12, (getNumber (_cameraConfig >> "canStopDesignating")) == 1];
};
private _camera = [_projectile, _cameraArray, _shooter] call FUNC(camera_init);
GVAR(projectileHashMap) set [hashValue _projectile, _camera];
private _preTarget = +(ACE_PLAYER getVariable [QGVAR(target), [0, 0, 0]]);
private _camera = [_projectile, _cameraArray, _shooter, _preTarget isEqualTo [0, 0, 0]] call FUNC(camera_init);
GVAR(projectileHashMap) set [hashValue _projectile, [_camera, _preTarget]];
[{
params ["_args", "_pfID"];
_args params ["_firedEH", "_cameraArray", "_lastUpdate", "_camera", "_projectileHash"];

View File

@ -17,13 +17,11 @@
*/
params ["", "_args", "_seekerStateParams", "", "_timestep"];
_args params ["_firedEH", "_launchParams", "", "_seekerParams", "_stateParams", "_targetData"];
_args params ["_firedEH", "", "", "", "", "_targetData"];
_firedEH params ["","","","","","","_projectile"];
_launchParams params ["", "_targetParams"];
_targetParams params ["_target"];
_seekerParams params ["_seekerAngle", "", "_seekerMaxRange"];
private _cameraNamespace = GVAR(projectileHashMap) get hashValue _projectile;
(GVAR(projectileHashMap) get hashValue _projectile) params ["_cameraNamespace", "_preTarget"];
private _seekerTargetPos = _cameraNamespace getVariable [QGVAR(seekerTargetPos), [0, 0, 0]];
private _cameraPos = _cameraNamespace getVariable [QGVAR(cameraPos), [0, 0, 0]];
private _logicPos = _cameraNamespace getVariable [QGVAR(logicPos), [0, 0, 0]];
@ -33,71 +31,12 @@ private _seekerTargetInfo = _cameraNamespace getVariable [QGVAR(seekerTargetInfo
private _intersectObject = objNull;
private _designateInput = (_cameraNamespace getVariable [QGVAR(designateInput), [0]]) select 0;
if (_seekerTargetPos isEqualTo [0, 0, 0]) then {
_seekerTargetPos = _preTarget;
};
if ((_seekerTargetPos isNotEqualTo [0, 0, 0]) || { (_designateInput == 1) }) then {
private _nearObjects = [];
private _intersections = lineIntersectsSurfaces [_cameraPos, _cameraPos vectorAdd ((vectorNormalized _logicPos) vectorMultiply 5000), objNull, objNull, true, 1, "FIRE", "VIEW", true];
if (_intersections isNotEqualTo []) then {
(_intersections#0) params ["_intersectPos", "", "_object"];
if (_designateInput == 1) then {
_seekerTargetPos = _intersectPos;
};
_nearObjects = (ASLtoAGL _seekerTargetPos) nearObjects ["AllVehicles", 5];
if (_designateInput == 1 && { !isNull _object }) then {
_nearObjects pushBack _object;
};
};
if (_nearObjects isNotEqualTo []) then {
// I want to prefer the designated position on the object moreso than the bounds of the object
private _averagePosition = _seekerTargetPos vectorMultiply 15;
private _averagePositionCounter = 15;
private _closestObject = objNull;
private _closestDistance = 1e10;
{
if ((getPosASLVisual _x) vectorDistanceSqr _seekerTargetPos < _closestDistance) then {
_closestDistance = (getPosASLVisual _x) vectorDistanceSqr _seekerTargetPos;
_closestObject = _x;
};
} forEach _nearObjects;
private _boundingBox = 0 boundingBoxReal _closestObject;
// Project target bounding box onto screen and do a real bad edge detection check
_boundingBox params ["_min", "_max"];
_min params ["_x0", "_y0", "_z0"];
_max params ["_x1", "_y1", "_z1"];
private _utl = _closestObject modelToWorldVisualWorld [_x0, _y0, _z0];
private _utr = _closestObject modelToWorldVisualWorld [_x1, _y0, _z0];
private _ubr = _closestObject modelToWorldVisualWorld [_x1, _y1, _z0];
private _ubl = _closestObject modelToWorldVisualWorld [_x0, _y1, _z0];
private _dtl = _closestObject modelToWorldVisualWorld [_x0, _y0, _z1];
private _dtr = _closestObject modelToWorldVisualWorld [_x1, _y0, _z1];
private _dbr = _closestObject modelToWorldVisualWorld [_x1, _y1, _z1];
private _dbl = _closestObject modelToWorldVisualWorld [_x0, _y1, _z1];
{
private _intersections = lineIntersectsSurfaces [_cameraPos, _x, objNull, objNull, false, 16];
if (_intersections isEqualTo []) then {
_averagePosition = _averagePosition vectorAdd _x;
_averagePositionCounter = _averagePositionCounter + 1;
} else {
{
_x params ["_surfacePosition"];
_averagePosition = _averagePosition vectorAdd _surfacePosition;
_averagePositionCounter = _averagePositionCounter + 1;
} forEach _intersections;
}
} forEach [_utl, _utr, _ubr, _ubl, _dtl, _dtr, _dbr, _dbl];
_seekerTargetPos = _averagePosition vectorMultiply (1 / _averagePositionCounter);
};
_seekerTargetPos = [_cameraPos, vectorNormalized _logicPos, _designateInput, _seekerTargetPos] call FUNC(getTargetPosition);
};
_cameraNamespace setVariable [QGVAR(seekerTargetPos), _seekerTargetPos];

View File

@ -40,6 +40,6 @@
#define CRUISE_PRO_GAIN 0.3
#define CRUISE_DER_GAIN 3
#define BATTERY_LIFE 30
#define BATTERY_LIFE (43 + random 10)
#define GIMBAL_LOGIC_OFFSET 10