#include "script_component.hpp" /* * Author: Brandon (TCVM) * Updates camera to be on a fixed point * * Arguments: * 0: Guidance Arg Array * 1: PFID * * Return Value: * None * * Example: * [[], 0] call ace_missileguidance_fnc_guidancePFH; * * Public: No */ params ["_cameraArray", "_projectile", "_deltaTime", "_cameraNamespace"]; _extractedInfo params ["", "", "", "", "", "", "", "_miscManeuvering", "", "_miscSeeker", "", "", "_cameraArray"]; _cameraArray params ["_hasCamera", "", "", "", "", "", "", "", "_viewData", "_gimbalData", "", "_designating", "_canStopDesignating"]; _viewData params ["_lookDir", "_groundPos", "_pointPos", "_movingCameraX", "_movingCameraY"]; _gimbalData params ["_hasGimbal", "_maxGimbalX", "_maxGimbalY", "_gimbalSpeedX", "_gimbalSpeedY", "", "", "_gimbalZoomSpeedModifiers", "_stabilizeWhenMoving", "_designateWhenStationary", "_trackLockedPosition"]; if (!_hasCamera || { _cameraNamespace isEqualTo objNull }) exitWith {}; if ([_cameraNamespace] call FUNC(camera_userInCamera)) then { cameraEffectEnableHUD true; }; private _camera = _cameraNamespace getVariable [QGVAR(camera), nil]; private _logic = _cameraNamespace getVariable [QGVAR(logic), objNull]; private _fovChanged = _cameraNamespace getVariable [QGVAR(fovChanged), false]; private _cameraOffset = _cameraNamespace getVariable [QGVAR(projectileSize), 0]; private _missileDirection = vectorNormalized velocity _projectile; private _cameraPosASL = (getPosASLVisual _projectile) vectorAdd (_missileDirection vectorMultiply _cameraOffset); private _designatedLastFrame = _cameraNamespace getVariable [QGVAR(designatedLastFrame), false]; if (_designatedLastFrame && !_canStopDesignating && { !(_groundPos isEqualTo [0, 0, 0] && _pointPos isEqualTo [0, 0, 0]) }) then { _designating = true; }; if (!_designating && _designatedLastFrame) then { _designatedLastFrame = false; _cameraNamespace setVariable [QGVAR(designatedLastFrame), _designatedLastFrame]; }; if (_fovChanged) then { private _lerpFovEnabled = _cameraNamespace getVariable [QGVAR(lerpFOVChange), false]; private _targetFOV = _cameraNamespace getVariable [QGVAR(targetFOV), 1]; private _currentFOV = _cameraNamespace getVariable [QGVAR(currentFOV), 1]; private _fovChangeStart = _cameraNamespace getVariable [QGVAR(fovChangedTime), 0]; private _startingFOV = _cameraNamespace getVariable [QGVAR(startingFov), 1]; private _fovChangeTime = _cameraNamespace getVariable [QGVAR(fovChangeTime), 0]; private _setFOV = _targetFOV; if (_lerpFovEnabled) then { _setFOV = linearConversion [0, _fovChangeTime, CBA_missionTime - _fovChangeStart, _startingFOV, _targetFOV, true]; } else { _fovChanged = false; }; // if the FOV is near enough to the target FOV stop the lerp if (abs(_setFOV - _targetFOV) == 0 || ((CBA_missionTime - _fovChangeStart) > _fovChangeTime + 2)) then { _setFOV = _targetFOV; _fovChanged = false; }; _camera camSetFOV _setFOV; _cameraNamespace setVariable [QGVAR(fovChanged), _fovChanged]; _cameraNamespace setVariable [QGVAR(currentFOV), _setFOV]; }; _movingCameraX = false; _movingCameraY = false; private _relativePos = _cameraNamespace getVariable [QGVAR(logicPos), _missileDirection vectorMultiply GIMBAL_LOGIC_OFFSET]; private _expectedPos = _relativePos; if (_hasGimbal) then { private _lookInput = _cameraNamespace getVariable [QGVAR(lookInput), [0, 0, 0, 0]]; _lookInput params ["_up", "_down", "_left", "_right"]; _movingCameraX = (_right - _left) != 0; _movingCameraY = (_up - _down) != 0; private _lastGroundPos = _cameraNamespace getVariable [QGVAR(lastMovedGroundPos), [0, 0, 0]]; if !((_movingCameraX || _movingCameraY) || true) then { // If we designate a target set the current tracking point to the current ground point to avoid unwanted behavior from static cameras if (_designating && !_designatedLastFrame) then { _designatedLastFrame = true; _cameraNamespace setVariable [QGVAR(designatedLastFrame), _designatedLastFrame]; _lastGroundPos = _groundPos; _cameraNamespace setVariable [QGVAR(lastMovedGroundPos), _lastGroundPos]; }; if (_trackLockedPosition && { (_seekerTargetPos isNotEqualTo [0, 0, 0]) } && _canStopDesignating) then { _lastGroundPos = _seekerTargetPos; }; // lock the camera and dont gimbal with missile rotation if !(_lastGroundPos isEqualTo [0, 0, 0]) then { #ifdef DEBUG_MODE_FULL drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [1, 1, 1, 1], ASLtoATL (_lastGroundPos), 0.75, 0.75, 0, "Last Camera Ground Position", 1, 0.025, "TahomaB"]; #endif private _directionToGround = _cameraPosASL vectorFromTo _lastGroundPos; (_directionToGround call CBA_fnc_vect2polar) params ["", "_azimuth", "_elevation"]; _expectedPos = _directionToGround vectorMultiply GIMBAL_LOGIC_OFFSET; }; } else { private _speedModifier = 1; if (_gimbalZoomSpeedModifiers isNotEqualTo []) then { _speedModifier = (_gimbalZoomSpeedModifiers select (_cameraNamespace getVariable [QGVAR(currentZoomIndex), 0])); }; private _offsetX = (_speedModifier * _gimbalSpeedX * _deltaTime * (_right - _left)); private _offsetY = (_speedModifier * _gimbalSpeedY * _deltaTime * (_up - _down)); private _directionToLast = _relativePos; if !(_groundPos isEqualTo [0, 0, 0]) then { private _lastLogicPos = getPosASLVisual _logic; _directionToLast = _cameraPosASL vectorFromTo _groundPos; }; (_directionToLast call CBA_fnc_vect2polar) params ["", "_azimuth", "_elevation"]; _expectedPos = [GIMBAL_LOGIC_OFFSET, _azimuth + _offsetX, _elevation + _offsetY] call CBA_fnc_polar2vect; }; }; _relativePos = _expectedPos; (_relativePos call CBA_fnc_vect2polar) params ["", "_azimuth", "_elevation"]; (_missileDirection call CBA_fnc_vect2polar) params ["", "", "_missilePitch"]; private _projectileDir = vectorDirVisual _projectile; _projectileDir set [2, 0]; private _2dRelativePos = [_relativePos#0, _relativePos#1, 0]; private _cameraAzimuth = acos (_projectileDir vectorCos _2dRelativePos); private _cameraElevation = _missilePitch - _elevation; if (_cameraAzimuth > _maxGimbalX) then { private _maxDirection = (direction _projectile) + _maxGimbalX; private _crossProductSign = (_2dRelativePos vectorCrossProduct _projectileDir)#2; if (_crossProductSign < 0) then { _maxDirection = (direction _projectile) - _maxGimbalX; }; if (_maxDirection >= 360) then { _maxDirection = _maxDirection - 360; }; if (_maxDirection < 0) then { _maxDirection = 360 + _maxDirection; }; private _maxVec = [GIMBAL_LOGIC_OFFSET, _maxDirection, _elevation] call CBA_fnc_polar2vect; _relativePos set [0, _maxVec select 0]; _relativePos set [1, _maxVec select 1]; _azimuth = _maxDirection; }; if (abs(_cameraElevation) >= _maxGimbalY) then { private _maxElevation = _missilePitch + _maxGimbalY; if (_cameraElevation > 0) then { _maxElevation = _missilePitch - _maxGimbalY; }; if (_maxElevation >= 360) then { _maxElevation = 360 - _maxElevation; }; if (_maxElevation < 0) then { _maxElevation = 360 + _maxElevation; }; private _maxVec = [GIMBAL_LOGIC_OFFSET, _azimuth, _maxElevation] call CBA_fnc_polar2vect; _relativePos set [2, _maxVec select 2]; }; _designating = (!_canStopDesignating && _designating) || { _cameraNamespace getVariable [QGVAR(alwaysDesignate), false] || { (_cameraNamespace getVariable [QGVAR(designateInput), [0]])#0 == 1 } }; if (_designateWhenStationary && !(_movingCameraX || _movingCameraY)) then { _designating = true; }; _cameraNamespace setVariable [QGVAR(logicPos), _relativePos]; _cameraNamespace setVariable [QGVAR(cameraPos), _cameraPosASL]; private _p = _cameraPosASL vectorAdd _relativePos; _logic setPosASL _p; _camera camSetTarget _logic; _camera setPosASL _cameraPosASL; _lookDir = _cameraPosASL vectorFromTo (getPosASL _logic); private _projectedPos = _cameraPosASL vectorAdd (_lookDir vectorMultiply 10000); private _surfaceIntersections = lineIntersectsSurfaces [_cameraPosASL, _projectedPos, _projectile, _logic]; private _pointPos = [0, 0, 0]; private _groundPos = terrainIntersectAtASL [_cameraPosASL, _projectedPos]; if (count _surfaceIntersections > 0) then { _pointPos = (_surfaceIntersections select 0) select 0; }; if (_movingCameraX) then { _cameraNamespace setVariable [QGVAR(lastMovedGroundPosX), _groundPos]; }; if (_movingCameraY) then { _cameraNamespace setVariable [QGVAR(lastMovedGroundPosY), _groundPos]; }; if (_movingCameraX || _movingCameraY) then { _cameraNamespace setVariable [QGVAR(lastMovedGroundPos), _groundPos]; }; _cameraArray set [11, _designating]; #ifdef DEBUG_MODE_FULL drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [1, 0.5, 1, 1], ASLToAGL _cameraPosASL, 0.75, 0.75, 0, "Camera Pos", 1, 0.025, "TahomaB"]; drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [1, 0.5, 1, 1], getPosATL _logic, 0.75, 0.75, 0, "Logic Pos", 1, 0.025, "TahomaB"]; drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [0, 1, 1, 1], ASLtoAGL (_groundPos), 0.75, 0.75, 0, "Camera Ground Position", 1, 0.025, "TahomaB"]; drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [1, 1, 0, 1], ASLtoAGL (_pointPos), 0.75, 0.75, 0, "Camera Point Position", 1, 0.025, "TahomaB"]; #endif _viewData set [0, _lookDir]; _viewData set [1, _groundPos]; _viewData set [2, _pointPos]; _viewData set [3, _movingCameraX]; _viewData set [4, _movingCameraY]; _cameraArray set [8, _viewData]; _camera camCommit 0; [_cameraNamespace, _cameraArray] call FUNC(camera_updateTargetingGate);