From 77c2b99ee542e3825c4f25e7b5a399597fd436e2 Mon Sep 17 00:00:00 2001 From: SilentSpike Date: Wed, 9 Sep 2015 23:21:49 +0100 Subject: [PATCH] Change spectator external camera behaviour Using the "external" view is limited by the server difficulty setting. Instead the spectator external camera has been replaced with an oribtal camera as was originally planned to be added alongside the default views. --- addons/spectator/XEH_preInit.sqf | 1 + .../spectator/functions/fnc_handleCamera.sqf | 68 +++++++++++++------ .../spectator/functions/fnc_handleIcons.sqf | 2 +- .../functions/fnc_handleInterface.sqf | 13 ++-- addons/spectator/functions/fnc_handleMap.sqf | 2 +- .../functions/fnc_setCameraAttributes.sqf | 8 +-- .../spectator/functions/fnc_setSpectator.sqf | 20 ++++-- .../functions/fnc_toggleInterface.sqf | 2 +- .../functions/fnc_transitionCamera.sqf | 45 +++++++----- .../functions/fnc_updateCameraModes.sqf | 2 +- .../functions/fnc_updateVisionModes.sqf | 2 +- 11 files changed, 107 insertions(+), 58 deletions(-) diff --git a/addons/spectator/XEH_preInit.sqf b/addons/spectator/XEH_preInit.sqf index d1bf48d106..e26dc27d07 100644 --- a/addons/spectator/XEH_preInit.sqf +++ b/addons/spectator/XEH_preInit.sqf @@ -31,6 +31,7 @@ GVAR(availableSides) = [west,east,resistance,civilian]; GVAR(availableVisions) = [-2,-1,0,1]; GVAR(camAgent) = objNull; +GVAR(camDistance) = 10; GVAR(camMode) = 0; GVAR(camPan) = 0; GVAR(camPos) = ATLtoASL [worldSize * 0.5, worldSize * 0.5, 20]; diff --git a/addons/spectator/functions/fnc_handleCamera.sqf b/addons/spectator/functions/fnc_handleCamera.sqf index db196c8504..000471809e 100644 --- a/addons/spectator/functions/fnc_handleCamera.sqf +++ b/addons/spectator/functions/fnc_handleCamera.sqf @@ -20,29 +20,53 @@ // Kill PFH when not in free cam (or display is closed) if (isNil QGVAR(camHandler)) exitWith { [_this select 1] call CBA_fnc_removePerFrameHandler; }; -private ["_camera","_oldPos","_altMod","_zoomMod","_mX","_mY","_mZ","_pan","_x","_y","_z"]; - -_camera = GVAR(camera); -_oldPos = getPosASL _camera; - -// Dolly/Boom amount should be influnced by zoom level (it should really be exponential) -// Dollying should also slow as the camera gets close to the ground -_zoomMod = (GVAR(camZoom) * 0.8) max 1; -_altMod = ((((getPos _camera) select 2) * 0.05) max 0.1) min 1; - -_mX = (GVAR(camDolly) select 0) * _altMod / _zoomMod; -_mY = (GVAR(camDolly) select 1) * _altMod / _zoomMod; -_mZ = GVAR(camBoom) / _zoomMod; +private ["_camera","_pan","_tilt","_x","_y","_z"]; _pan = (GVAR(camPan) + 360) % 360; -_x = (_oldPos select 0) + (_mX * cos(_pan)) + (_mY * sin(_pan)); -_y = (_oldPos select 1) - (_mX * sin(_pan)) + (_mY * cos(_pan)); -_z = (_oldPos select 2) + _mZ; +_tilt = GVAR(camTilt); -// Prevent camera going under terrain -GVAR(camPos) = [_x,_y,_z max (getTerrainHeightASL [_x,_y])]; +if (GVAR(camMode) == 0) then { + private ["_oldPos","_altMod","_zoomMod","_mX","_mY","_mZ"]; + _camera = GVAR(freeCamera); + _oldPos = GVAR(camPos); -// Update camera position and rotation -_camera setPosASL GVAR(camPos); -_camera setDir GVAR(camPan); -[_camera, GVAR(camTilt), 0] call BIS_fnc_setPitchBank; + // Dolly/Boom amount should be influnced by zoom level (it should really be exponential) + // Dollying should also slow as the camera gets close to the ground + _zoomMod = (GVAR(camZoom) * 0.8) max 1; + _altMod = ((((getPos _camera) select 2) * 0.05) max 0.1) min 1; + + _mX = (GVAR(camDolly) select 0) * _altMod / _zoomMod; + _mY = (GVAR(camDolly) select 1) * _altMod / _zoomMod; + _mZ = GVAR(camBoom) / _zoomMod; + + _x = (_oldPos select 0) + (_mX * cos(_pan)) + (_mY * sin(_pan)); + _y = (_oldPos select 1) - (_mX * sin(_pan)) + (_mY * cos(_pan)); + _z = (_oldPos select 2) + _mZ; + + // Prevent camera going under terrain + GVAR(camPos) = [_x,_y,_z max (getTerrainHeightASL [_x,_y])]; + + // Update camera position and rotation + _camera setPosASL GVAR(camPos); + _camera setDir _pan; + [_camera, _tilt, 0] call BIS_fnc_setPitchBank; +} else { + private ["_unit","_target","_distance"]; + _camera = GVAR(unitCamera); + + _unit = GVAR(camUnit); + _target = GVAR(targetCamera); + _distance = GVAR(camDistance); + + _x = sin(_pan)*_distance*cos(_tilt); + _y = cos(_pan)*_distance*cos(_tilt); + _z = sin(_tilt) * (2 * (0.3 max _distance)); + + // Update the position of the target camera (used for smooth unit tracking) + _target camSetPos ((_unit modelToWorldVisual [0,0,0]) vectorAdd [0,0,1.5]); + _target camCommit 0; + + // Update the relative position of the unit camera + _camera camSetRelPos [_x, _y, _z]; + _camera camCommit 0; +}; diff --git a/addons/spectator/functions/fnc_handleIcons.sqf b/addons/spectator/functions/fnc_handleIcons.sqf index 72c0d7dee6..d1f83690ff 100644 --- a/addons/spectator/functions/fnc_handleIcons.sqf +++ b/addons/spectator/functions/fnc_handleIcons.sqf @@ -21,7 +21,7 @@ if !(GVAR(showIcons)) exitWith {}; private ["_refPoint","_drawVehicles","_leader","_color","_txt","_unit"]; // Draw groups unless leader is within distance -_refPoint = [GVAR(camera),GVAR(camUnit)] select (GVAR(camMode) > 0); +_refPoint = [GVAR(freeCamera),GVAR(camUnit)] select (GVAR(camMode) > 0); _drawVehicles = []; { _leader = leader _x; diff --git a/addons/spectator/functions/fnc_handleInterface.sqf b/addons/spectator/functions/fnc_handleInterface.sqf index 93c6ca3ddd..7c961071c3 100644 --- a/addons/spectator/functions/fnc_handleInterface.sqf +++ b/addons/spectator/functions/fnc_handleInterface.sqf @@ -149,11 +149,16 @@ switch (toLower _mode) do { case "onmousezchanged": { _args params ["_ctrl","_zChange"]; - // Scroll to change speed, modifier for zoom - if (GVAR(ctrlKey)) then { - [nil,nil,nil,nil,nil,nil,nil, GVAR(camSpeed) + _zChange * 0.2] call FUNC(setCameraAttributes); + // Scroll to modify distance value in third person + if (GVAR(camMode) == 0) then { + // Scroll to change speed, modifier for zoom + if (GVAR(ctrlKey)) then { + [nil,nil,nil,nil,nil,nil,nil, GVAR(camSpeed) + _zChange * 0.2] call FUNC(setCameraAttributes); + } else { + [nil,nil,nil,nil,nil,nil, GVAR(camZoom) + _zChange * 0.1] call FUNC(setCameraAttributes); + }; } else { - [nil,nil,nil,nil,nil,nil, GVAR(camZoom) + _zChange * 0.1] call FUNC(setCameraAttributes); + GVAR(camDistance) = ((GVAR(camDistance) - _zChange * 2) max 5) min 50; }; }; case "onmousemoving": { diff --git a/addons/spectator/functions/fnc_handleMap.sqf b/addons/spectator/functions/fnc_handleMap.sqf index 4eeb5fd7e1..fd084f9967 100644 --- a/addons/spectator/functions/fnc_handleMap.sqf +++ b/addons/spectator/functions/fnc_handleMap.sqf @@ -21,7 +21,7 @@ params ["_map"]; private ["_cachedVehicles","_unit","_color","_icon","_txt"]; if (GVAR(camMode) == 0) then { - _map drawIcon ["\A3\UI_F\Data\GUI\Rsc\RscDisplayMissionEditor\iconcamera_ca.paa",[0,0,0,1],GVAR(camera),20,20,GVAR(camPan)]; + _map drawIcon ["\A3\UI_F\Data\GUI\Rsc\RscDisplayMissionEditor\iconcamera_ca.paa",[0,0,0,1],GVAR(freeCamera),20,20,GVAR(camPan)]; }; _cachedVehicles = []; diff --git a/addons/spectator/functions/fnc_setCameraAttributes.sqf b/addons/spectator/functions/fnc_setCameraAttributes.sqf index 8eb6fe51ac..dd8dd3ef6a 100644 --- a/addons/spectator/functions/fnc_setCameraAttributes.sqf +++ b/addons/spectator/functions/fnc_setCameraAttributes.sqf @@ -58,10 +58,10 @@ GVAR(camVision) = _vision; GVAR(camZoom) = (_zoom min 2) max 0.01; // Apply if camera exists -if (isNil QGVAR(camera)) then { +if (GVAR(isSet)) then { + GVAR(freeCamera) setPosATL _position; + [_mode,_unit,_vision] call FUNC(transitionCamera); +} else { GVAR(camMode) = _mode; GVAR(camPos) = (ATLtoASL _position); -} else { - [_mode,_unit,_vision] call FUNC(transitionCamera); - GVAR(camera) setPosATL _position; }; diff --git a/addons/spectator/functions/fnc_setSpectator.sqf b/addons/spectator/functions/fnc_setSpectator.sqf index 621100a5ba..fce2fe829f 100644 --- a/addons/spectator/functions/fnc_setSpectator.sqf +++ b/addons/spectator/functions/fnc_setSpectator.sqf @@ -50,8 +50,14 @@ if (_set) then { // Update units before opening to support pre-set camera unit [] call FUNC(updateUnits); - // Initalize the camera view - GVAR(camera) = "Camera" camCreate (ASLtoATL GVAR(camPos)); + // Initalize the camera objects + GVAR(freeCamera) = "Camera" camCreate (ASLtoATL GVAR(camPos)); + GVAR(unitCamera) = "Camera" camCreate [0,0,0]; + GVAR(targetCamera) = "Camera" camCreate [0,0,0]; + + // Initalize view + GVAR(unitCamera) camSetTarget GVAR(targetCamera); + GVAR(unitCamera) camCommit 0; [] call FUNC(transitionCamera); // Close map and clear radio @@ -85,8 +91,10 @@ if (_set) then { (findDisplay 12249) closeDisplay 0; // Terminate camera - GVAR(camera) cameraEffect ["terminate", "back"]; - camDestroy GVAR(camera); + GVAR(freeCamera) cameraEffect ["terminate", "back"]; + camDestroy GVAR(freeCamera); + camDestroy GVAR(unitCamera); + camDestroy GVAR(targetCamera); clearRadio; @@ -97,10 +105,12 @@ if (_set) then { BIS_fnc_feedback_allowPP = true; // Cleanup camera variables - GVAR(camera) = nil; GVAR(camBoom) = nil; GVAR(camDolly) = nil; GVAR(camGun) = nil; + GVAR(freeCamera) = nil; + GVAR(unitCamera) = nil; + GVAR(targetCamera) = nil; // Cleanup display variables GVAR(ctrlKey) = nil; diff --git a/addons/spectator/functions/fnc_toggleInterface.sqf b/addons/spectator/functions/fnc_toggleInterface.sqf index 4a03de4271..31472702fc 100644 --- a/addons/spectator/functions/fnc_toggleInterface.sqf +++ b/addons/spectator/functions/fnc_toggleInterface.sqf @@ -43,7 +43,7 @@ if (GVAR(showMap)) then { // Centre map on camera/unit upon opening if (_toggleMap) then { - _map ctrlMapAnimAdd [0, 0.5, [GVAR(camUnit),GVAR(camera)] select (GVAR(camMode) == 0)]; + _map ctrlMapAnimAdd [0, 0.5, [GVAR(camUnit),GVAR(freeCamera)] select (GVAR(camMode) == 0)]; ctrlMapAnimCommit _map; }; } else { diff --git a/addons/spectator/functions/fnc_transitionCamera.sqf b/addons/spectator/functions/fnc_transitionCamera.sqf index 72cb9f1a45..edc7fa23a2 100644 --- a/addons/spectator/functions/fnc_transitionCamera.sqf +++ b/addons/spectator/functions/fnc_transitionCamera.sqf @@ -43,15 +43,17 @@ if (_newMode != 1) then { GVAR(camGun) = false; }; +private ["_camera"]; if (_newMode == 0) then { // Free + _camera = GVAR(freeCamera); + // Preserve camUnit value for consistency when manually changing view - GVAR(camera) cameraEffect ["internal", "back"]; + _camera cameraEffect ["internal", "back"]; showCinemaBorder false; - cameraEffectEnableHUD true; // Apply the camera zoom - GVAR(camera) camSetFov -(linearConversion [0.01,2,GVAR(camZoom),-2,-0.01,true]); - GVAR(camera) camCommit 0; + _camera camSetFov -(linearConversion [0.01,2,GVAR(camZoom),-2,-0.01,true]); + _camera camCommit 0; // Agent is switched to in free cam to hide death table and prevent AI chat while allowing icons to draw (also prevents systemChat and unit HUD) // (Why is so much stuff tied into the current camera unit BI?!) @@ -79,20 +81,32 @@ if (_newMode == 0) then { // Free // Handle camera movement if (isNil QGVAR(camHandler)) then { GVAR(camHandler) = [FUNC(handleCamera), 0] call CBA_fnc_addPerFrameHandler; }; } else { + _camera = GVAR(unitCamera); + // When null unit is given choose random if (isNull _newUnit) then { _newUnit = GVAR(unitList) select floor(random(count GVAR(unitList))); }; - if (_newMode == 1) then { // Internal - // Handle gun cam - if (GVAR(camGun)) then { - _newUnit switchCamera "gunner"; - } else { - _newUnit switchCamera "internal"; - }; - } else { // External - _newUnit switchCamera "external"; + // Switch camera view to internal unit view (external uses the camera) + if (GVAR(camGun)) then { + _newUnit switchCamera "gunner"; + } else { + _newUnit switchCamera "internal"; + }; + + // Handle camera differently for internal/external view + if (_newMode == 1) then { + // Terminate camera view + _camera cameraEffect ["terminate", "back"]; + GVAR(camHandler) = nil; + } else { + // Switch to the camera + _camera cameraEffect ["internal", "back"]; + showCinemaBorder false; + + // Handle camera orbit movement + if (isNil QGVAR(camHandler)) then { GVAR(camHandler) = [FUNC(handleCamera), 0] call CBA_fnc_addPerFrameHandler; }; }; // Clear radio if group changed @@ -101,11 +115,6 @@ if (_newMode == 0) then { // Free }; GVAR(camUnit) = _newUnit; - - // Terminate camera view - GVAR(camera) cameraEffect ["terminate", "back"]; - GVAR(camHandler) = nil; - cameraEffectEnableHUD true; }; GVAR(camMode) = _newMode; diff --git a/addons/spectator/functions/fnc_updateCameraModes.sqf b/addons/spectator/functions/fnc_updateCameraModes.sqf index aef51b56c6..de1611823b 100644 --- a/addons/spectator/functions/fnc_updateCameraModes.sqf +++ b/addons/spectator/functions/fnc_updateCameraModes.sqf @@ -41,7 +41,7 @@ if (_newModes isEqualTo []) then { }; // Update camera in case of change -if !(isNil QGVAR(camera)) then { +if (GVAR(isSet)) then { [] call FUNC(transitionCamera); }; diff --git a/addons/spectator/functions/fnc_updateVisionModes.sqf b/addons/spectator/functions/fnc_updateVisionModes.sqf index 2a1e500f3f..c2bbb09167 100644 --- a/addons/spectator/functions/fnc_updateVisionModes.sqf +++ b/addons/spectator/functions/fnc_updateVisionModes.sqf @@ -49,7 +49,7 @@ if (_newModes isEqualTo []) then { }; // Update camera in case of change -if !(isNil QGVAR(camera)) then { +if (GVAR(isSet)) then { [] call FUNC(transitionCamera); };