2023-09-12 18:58:10 +00:00
|
|
|
#include "..\script_component.hpp"
|
2016-11-15 18:15:25 +00:00
|
|
|
/*
|
|
|
|
* Author: jaynus, PabstMirror
|
|
|
|
* Main loop, handles scaning for targets and drawing the javelin optic
|
|
|
|
*
|
|
|
|
* Arguments:
|
|
|
|
* 0: Last run frame <NUMBER>
|
|
|
|
* 0: Current target (what we locked last run) <OBJECT>
|
|
|
|
* 0: Lock start time (cba mission time) <NUMBER>
|
|
|
|
* 0: Next sound play time (ticktime) <NUMBER>
|
|
|
|
* 0: Next target scan (ticktime) <NUMBER>
|
|
|
|
*
|
|
|
|
* Return Value:
|
|
|
|
* None
|
|
|
|
*
|
|
|
|
* Example:
|
2020-04-25 06:41:45 +00:00
|
|
|
* [] call ace_javelin_fnc_onOpticDraw
|
2016-11-15 18:15:25 +00:00
|
|
|
*
|
|
|
|
* Public: No
|
|
|
|
*/
|
2016-05-30 16:37:03 +00:00
|
|
|
|
2016-11-15 18:15:25 +00:00
|
|
|
// TRACE_1("onOpticDraw",diag_frameno);
|
2016-05-30 16:37:03 +00:00
|
|
|
|
2016-11-15 18:15:25 +00:00
|
|
|
#define __TRACKINTERVAL 0 // how frequent the ui update should be.
|
|
|
|
#define __SCANNTERVAL 0.05 // how frequent the target scan check should be.
|
|
|
|
#define __LOCKONTIME 3 // Lock on won't occur sooner
|
2016-05-30 16:37:03 +00:00
|
|
|
|
|
|
|
// Pull the arguments
|
2016-11-15 18:15:25 +00:00
|
|
|
params ["_lastRunFrame", "_currentTarget", "_lockStartTime", "_soundNextPlayTime", "_fireDisabledEH", "_nextTargetScan"];
|
|
|
|
|
|
|
|
// Get shooter info
|
|
|
|
private _currentShooter = if (ACE_player call CBA_fnc_canUseWeapon) then {ACE_player} else {vehicle ACE_player};
|
|
|
|
private _currentWeapon = currentWeapon _currentShooter;
|
|
|
|
private _currentMagazine = currentMagazine _currentShooter;
|
|
|
|
|
|
|
|
// Get weapon / ammo configs
|
|
|
|
private _ammoCount = _currentShooter ammo _currentWeapon;
|
|
|
|
private _weaponConfig = configProperties [configFile >> "CfgWeapons" >> _currentWeapon, QUOTE(configName _x == QUOTE(QGVAR(enabled))), false];
|
|
|
|
private _ammoConfig = if (_currentMagazine != "") then {
|
|
|
|
private _ammoType = getText (configFile >> "CfgMagazines" >> _currentMagazine >> "ammo");
|
|
|
|
configProperties [(configFile >> "CfgAmmo" >> _ammoType), "(configName _x) == 'ace_missileguidance'", false];
|
2016-05-30 16:37:03 +00:00
|
|
|
} else {
|
|
|
|
[]
|
|
|
|
};
|
|
|
|
|
2016-11-15 18:15:25 +00:00
|
|
|
// Check if loaded and javelin enabled for wepaon and missile guidance enabled for loaded ammo
|
|
|
|
if ((_ammoCount == 0) || // No ammo loaded
|
|
|
|
{(count _weaponConfig) < 1} || {(getNumber (_weaponConfig select 0)) != 1} || // Not enabled for weapon
|
|
|
|
{(count _ammoConfig) < 1} || {(getNumber ((_ammoConfig select 0) >> "enabled")) != 1} // Not enabled for ammo
|
|
|
|
) exitWith {
|
2016-05-30 16:37:03 +00:00
|
|
|
|
2016-11-15 18:15:25 +00:00
|
|
|
__JavelinIGUITargeting ctrlShow false;
|
|
|
|
__JavelinIGUISeek ctrlSetTextColor __ColorGray;
|
2016-05-30 16:37:03 +00:00
|
|
|
|
2016-11-15 18:15:25 +00:00
|
|
|
_fireDisabledEH = [_fireDisabledEH] call FUNC(enableFire);
|
|
|
|
_this set [0, diag_frameno];
|
|
|
|
_this set [4, _fireDisabledEH];
|
2023-06-28 10:55:45 +00:00
|
|
|
|
|
|
|
// Fix weapon being in top-attack when loading AP magazine (https://feedback.bistudio.com/T171012)
|
|
|
|
if ((_currentShooter == ACE_player) && {_currentMagazine == "Titan_AP"} && {currentWeaponMode ACE_player == "TopDown"}) then {
|
|
|
|
{
|
|
|
|
_x params ["_xIndex", "", "", "", "_xMode"];
|
|
|
|
if (_xMode == "Single") exitWith {
|
|
|
|
ACE_player action ["SwitchWeapon", _currentShooter, ACE_player, _xIndex];
|
|
|
|
__JavelinIGUITop ctrlSetTextColor __ColorGray;
|
|
|
|
__JavelinIGUIDir ctrlSetTextColor __ColorGreen;
|
|
|
|
TRACE_2("fix top-attack for AP",weaponState _currentShooter,_x);
|
|
|
|
};
|
|
|
|
} forEach (ACE_player weaponsInfo [_currentWeapon, true]);
|
|
|
|
};
|
2016-05-30 16:37:03 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2016-11-15 18:15:25 +00:00
|
|
|
// Bail on fast movement (keep it steady)
|
|
|
|
if ((velocity ACE_player) distance [0,0,0] > 0.75 && {cameraView == "GUNNER"} && {cameraOn == ACE_player}) exitWith {
|
|
|
|
TRACE_1("exiting gunner because movement",velocity ACE_player);
|
2016-05-30 16:37:03 +00:00
|
|
|
ACE_player switchCamera "INTERNAL";
|
|
|
|
if (player != ACE_player) then {
|
|
|
|
TRACE_2("Zeus, manually reseting RC after switchCamera",player,ACE_player);
|
|
|
|
player remoteControl ACE_player;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2016-11-15 18:15:25 +00:00
|
|
|
// Refresh the firemode (top/dir)
|
2016-05-30 16:37:03 +00:00
|
|
|
[] call FUNC(showFireMode);
|
|
|
|
|
2016-11-15 18:15:25 +00:00
|
|
|
// Get UI constants
|
|
|
|
private _offsetX = 0.5 * safeZoneW - safeZoneX - 0.5;
|
|
|
|
private _offsetY = 0.5 * safeZoneH - safeZoneY - 0.5;
|
|
|
|
|
|
|
|
private _newTarget = objNull;
|
2018-11-26 23:09:45 +00:00
|
|
|
if (GVAR(isLockKeyDown) && {cameraView == "GUNNER"} && {((currentVisionMode ACE_player) == 2) || {missionNamespace getVariable [QGVAR(ignoreVisionMode), false]}}) then {
|
2016-11-15 18:15:25 +00:00
|
|
|
// Attempting to lock; getTarget can be expensive so it's rate is limited
|
|
|
|
if (diag_tickTime > _nextTargetScan) then {
|
|
|
|
BEGIN_COUNTER(getTarget);
|
|
|
|
_newTarget = [_currentTarget, 2500, 0.6] call FUNC(getTarget);
|
|
|
|
END_COUNTER(getTarget);
|
|
|
|
_nextTargetScan = diag_tickTime + __SCANNTERVAL;
|
|
|
|
} else {
|
|
|
|
_newTarget = _currentTarget;
|
2016-05-30 16:37:03 +00:00
|
|
|
};
|
|
|
|
|
2016-11-15 18:15:25 +00:00
|
|
|
// Show gate box
|
|
|
|
private _boundsInput = if (_currentTarget isKindOf "CAManBase") then {
|
|
|
|
[_currentTarget,[-0.5,-0.5,-0.25],[0,0,0]];
|
|
|
|
} else {
|
2021-10-30 21:42:03 +00:00
|
|
|
[_currentTarget,[-1,-1,-1],_currentTarget selectionPosition "zamerny"];
|
2016-05-30 16:37:03 +00:00
|
|
|
};
|
|
|
|
|
2016-11-15 18:15:25 +00:00
|
|
|
private _bpos = _boundsInput call EFUNC(common,worldToScreenBounds);
|
2021-10-30 21:42:03 +00:00
|
|
|
|
2016-11-15 18:15:25 +00:00
|
|
|
private _lockTime = if (isNull _currentTarget) then {0} else {CBA_missionTime - _lockStartTime};
|
|
|
|
private _minX = ((linearConversion [1, (__LOCKONTIME - 0.5), _lockTime, 0.5 - 0.075*safeZoneW, (_bpos select 0), true]) + _offsetX) max __ConstraintLeft;
|
|
|
|
private _minY = ((linearConversion [1, (__LOCKONTIME - 0.5), _lockTime, 0.5 - 0.075*safeZoneH, (_bpos select 1), true]) + _offsetY) max __ConstraintTop;
|
|
|
|
private _maxX = (((linearConversion [1, (__LOCKONTIME - 0.5), _lockTime, 0.5 + 0.075*safeZoneW, (_bpos select 2), true]) + _offsetX) min __ConstraintRight) - (0.025 * (3 / 4) * safeZoneH);
|
|
|
|
private _maxY = (((linearConversion [1, (__LOCKONTIME - 0.5), _lockTime, 0.5 + 0.075*safeZoneH, (_bpos select 3), true]) + _offsetY) min __ConstraintBottom) - (0.025 * safeZoneH);
|
|
|
|
|
|
|
|
// TRACE_3("",_boundsInput,_bpos,_lockTime);
|
|
|
|
// TRACE_4("",_minX,_maxX,_minY,_maxY);
|
|
|
|
|
|
|
|
__JavelinIGUITargetingGateTL ctrlSetPosition [_minX, _minY];
|
|
|
|
__JavelinIGUITargetingGateTR ctrlSetPosition [_maxX, _minY];
|
|
|
|
__JavelinIGUITargetingGateBL ctrlSetPosition [_minX, _maxY];
|
|
|
|
__JavelinIGUITargetingGateBR ctrlSetPosition [_maxX, _maxY];
|
|
|
|
{_x ctrlCommit __TRACKINTERVAL} forEach [__JavelinIGUITargetingGateTL, __JavelinIGUITargetingGateTR, __JavelinIGUITargetingGateBL, __JavelinIGUITargetingGateBR];
|
|
|
|
|
|
|
|
__JavelinIGUITargeting ctrlShow true;
|
|
|
|
__JavelinIGUITargetingGate ctrlShow true;
|
2016-05-30 16:37:03 +00:00
|
|
|
} else {
|
2016-11-15 18:15:25 +00:00
|
|
|
// Not trying to lock
|
|
|
|
__JavelinIGUITargeting ctrlShow false;
|
|
|
|
__JavelinIGUITargetingGate ctrlShow false;
|
|
|
|
__JavelinIGUITargetingLines ctrlShow false;
|
2016-05-30 16:37:03 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
if (isNull _newTarget) then {
|
2016-11-15 18:15:25 +00:00
|
|
|
// No target found
|
2016-05-30 16:37:03 +00:00
|
|
|
_currentTarget = objNull;
|
2016-11-15 18:15:25 +00:00
|
|
|
_lockStartTime = 0;
|
2016-05-30 16:37:03 +00:00
|
|
|
__JavelinIGUISeek ctrlSetTextColor __ColorGray;
|
2016-11-15 18:15:25 +00:00
|
|
|
_currentShooter setVariable ["ace_missileguidance_target", nil, false];
|
2016-05-30 16:37:03 +00:00
|
|
|
|
2016-11-15 18:15:25 +00:00
|
|
|
__JavelinIGUITargetingLines ctrlShow false;
|
2021-10-30 21:42:03 +00:00
|
|
|
|
2016-05-30 16:37:03 +00:00
|
|
|
// Disallow fire
|
|
|
|
_fireDisabledEH = [_fireDisabledEH] call FUNC(disableFire);
|
|
|
|
} else {
|
2016-11-15 18:15:25 +00:00
|
|
|
if ((!isNull _newTarget) && {_currentTarget != _newTarget}) then {
|
|
|
|
TRACE_1("New Target, reseting locking", _newTarget);
|
|
|
|
_lockStartTime = CBA_missionTime;
|
|
|
|
_currentTarget = _newTarget;
|
|
|
|
};
|
2016-05-30 16:37:03 +00:00
|
|
|
|
2016-11-15 18:15:25 +00:00
|
|
|
if ((CBA_missionTime - _lockStartTime) > __LOCKONTIME) then { // Lock on after 3 seconds
|
|
|
|
TRACE_2("LOCKED!", _currentTarget, _lockStartTime);
|
|
|
|
__JavelinIGUISeek ctrlSetTextColor __ColorGreen;
|
|
|
|
__JavelinIGUITargetingLines ctrlShow true;
|
|
|
|
|
|
|
|
// Move target marker (the crosshair) to aimpoint on the target
|
|
|
|
private _aimPointOnTarget = _currentTarget selectionPosition (["zamerny", "body"] select (_currentTarget isKindOf "CAManBase"));
|
|
|
|
(worldToScreen (_currentTarget modelToWorld _aimPointOnTarget)) params [["_aposX", 0.5], ["_aposY", 0.5]];
|
|
|
|
private _ctrlPos = ctrlPosition __JavelinIGUITargetingLineV;
|
|
|
|
_ctrlPos set [0, _aposX + _offsetX];
|
|
|
|
__JavelinIGUITargetingLineV ctrlSetPosition _ctrlPos;
|
|
|
|
__JavelinIGUITargetingLineV ctrlCommit __TRACKINTERVAL;
|
|
|
|
_ctrlPos = ctrlPosition __JavelinIGUITargetingLineH;
|
|
|
|
_ctrlPos set [1, _aposY + _offsetY];
|
|
|
|
__JavelinIGUITargetingLineH ctrlSetPosition _ctrlPos;
|
|
|
|
__JavelinIGUITargetingLineH ctrlCommit __TRACKINTERVAL;
|
|
|
|
|
|
|
|
_currentShooter setVariable ["ace_missileguidance_target", _currentTarget, false];
|
|
|
|
|
|
|
|
// Allow fire
|
|
|
|
_fireDisabledEH = [_fireDisabledEH] call FUNC(enableFire);
|
2016-05-30 16:37:03 +00:00
|
|
|
|
2016-11-15 18:15:25 +00:00
|
|
|
if (diag_tickTime > _soundNextPlayTime) then {
|
|
|
|
playSound "ACE_Javelin_Locked";
|
|
|
|
_soundNextPlayTime = diag_tickTime + 0.25;
|
2016-05-30 16:37:03 +00:00
|
|
|
};
|
|
|
|
} else {
|
2016-11-15 18:15:25 +00:00
|
|
|
// Lock in progress
|
2016-05-30 16:37:03 +00:00
|
|
|
__JavelinIGUISeek ctrlSetTextColor __ColorGray;
|
|
|
|
__JavelinIGUITargetingLines ctrlShow false;
|
|
|
|
|
2016-09-04 14:44:22 +00:00
|
|
|
_currentShooter setVariable ["ace_missileguidance_target", nil, false];
|
2016-05-30 16:37:03 +00:00
|
|
|
|
2016-11-15 18:15:25 +00:00
|
|
|
if (diag_tickTime > _soundNextPlayTime) then {
|
|
|
|
playSound "ACE_Javelin_Locking";
|
|
|
|
_soundNextPlayTime = diag_tickTime + 0.25;
|
|
|
|
};
|
2016-05-30 16:37:03 +00:00
|
|
|
// Disallow fire
|
|
|
|
_fireDisabledEH = [_fireDisabledEH] call FUNC(disableFire);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
// Save arguments for next run
|
2016-11-15 18:15:25 +00:00
|
|
|
_this set [0, diag_frameno];
|
|
|
|
_this set [1, _currentTarget];
|
|
|
|
_this set [2, _lockStartTime];
|
|
|
|
_this set [3, _soundNextPlayTime];
|
|
|
|
_this set [4, _fireDisabledEH];
|
|
|
|
_this set [5, _nextTargetScan];
|