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.
This commit is contained in:
SilentSpike 2015-09-09 23:21:49 +01:00
parent 17f9eab03a
commit 77c2b99ee5
11 changed files with 107 additions and 58 deletions

View File

@ -31,6 +31,7 @@ GVAR(availableSides) = [west,east,resistance,civilian];
GVAR(availableVisions) = [-2,-1,0,1]; GVAR(availableVisions) = [-2,-1,0,1];
GVAR(camAgent) = objNull; GVAR(camAgent) = objNull;
GVAR(camDistance) = 10;
GVAR(camMode) = 0; GVAR(camMode) = 0;
GVAR(camPan) = 0; GVAR(camPan) = 0;
GVAR(camPos) = ATLtoASL [worldSize * 0.5, worldSize * 0.5, 20]; GVAR(camPos) = ATLtoASL [worldSize * 0.5, worldSize * 0.5, 20];

View File

@ -20,29 +20,53 @@
// Kill PFH when not in free cam (or display is closed) // Kill PFH when not in free cam (or display is closed)
if (isNil QGVAR(camHandler)) exitWith { [_this select 1] call CBA_fnc_removePerFrameHandler; }; if (isNil QGVAR(camHandler)) exitWith { [_this select 1] call CBA_fnc_removePerFrameHandler; };
private ["_camera","_oldPos","_altMod","_zoomMod","_mX","_mY","_mZ","_pan","_x","_y","_z"]; private ["_camera","_pan","_tilt","_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;
_pan = (GVAR(camPan) + 360) % 360; _pan = (GVAR(camPan) + 360) % 360;
_x = (_oldPos select 0) + (_mX * cos(_pan)) + (_mY * sin(_pan)); _tilt = GVAR(camTilt);
_y = (_oldPos select 1) - (_mX * sin(_pan)) + (_mY * cos(_pan));
_z = (_oldPos select 2) + _mZ;
// Prevent camera going under terrain if (GVAR(camMode) == 0) then {
GVAR(camPos) = [_x,_y,_z max (getTerrainHeightASL [_x,_y])]; private ["_oldPos","_altMod","_zoomMod","_mX","_mY","_mZ"];
_camera = GVAR(freeCamera);
_oldPos = GVAR(camPos);
// Update camera position and rotation // Dolly/Boom amount should be influnced by zoom level (it should really be exponential)
_camera setPosASL GVAR(camPos); // Dollying should also slow as the camera gets close to the ground
_camera setDir GVAR(camPan); _zoomMod = (GVAR(camZoom) * 0.8) max 1;
[_camera, GVAR(camTilt), 0] call BIS_fnc_setPitchBank; _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;
};

View File

@ -21,7 +21,7 @@ if !(GVAR(showIcons)) exitWith {};
private ["_refPoint","_drawVehicles","_leader","_color","_txt","_unit"]; private ["_refPoint","_drawVehicles","_leader","_color","_txt","_unit"];
// Draw groups unless leader is within distance // 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 = []; _drawVehicles = [];
{ {
_leader = leader _x; _leader = leader _x;

View File

@ -149,12 +149,17 @@ switch (toLower _mode) do {
case "onmousezchanged": { case "onmousezchanged": {
_args params ["_ctrl","_zChange"]; _args params ["_ctrl","_zChange"];
// Scroll to modify distance value in third person
if (GVAR(camMode) == 0) then {
// Scroll to change speed, modifier for zoom // Scroll to change speed, modifier for zoom
if (GVAR(ctrlKey)) then { if (GVAR(ctrlKey)) then {
[nil,nil,nil,nil,nil,nil,nil, GVAR(camSpeed) + _zChange * 0.2] call FUNC(setCameraAttributes); [nil,nil,nil,nil,nil,nil,nil, GVAR(camSpeed) + _zChange * 0.2] call FUNC(setCameraAttributes);
} else { } else {
[nil,nil,nil,nil,nil,nil, GVAR(camZoom) + _zChange * 0.1] call FUNC(setCameraAttributes); [nil,nil,nil,nil,nil,nil, GVAR(camZoom) + _zChange * 0.1] call FUNC(setCameraAttributes);
}; };
} else {
GVAR(camDistance) = ((GVAR(camDistance) - _zChange * 2) max 5) min 50;
};
}; };
case "onmousemoving": { case "onmousemoving": {
_args params ["_ctrl","_x","_y"]; _args params ["_ctrl","_x","_y"];

View File

@ -21,7 +21,7 @@ params ["_map"];
private ["_cachedVehicles","_unit","_color","_icon","_txt"]; private ["_cachedVehicles","_unit","_color","_icon","_txt"];
if (GVAR(camMode) == 0) then { 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 = []; _cachedVehicles = [];

View File

@ -58,10 +58,10 @@ GVAR(camVision) = _vision;
GVAR(camZoom) = (_zoom min 2) max 0.01; GVAR(camZoom) = (_zoom min 2) max 0.01;
// Apply if camera exists // 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(camMode) = _mode;
GVAR(camPos) = (ATLtoASL _position); GVAR(camPos) = (ATLtoASL _position);
} else {
[_mode,_unit,_vision] call FUNC(transitionCamera);
GVAR(camera) setPosATL _position;
}; };

View File

@ -50,8 +50,14 @@ if (_set) then {
// Update units before opening to support pre-set camera unit // Update units before opening to support pre-set camera unit
[] call FUNC(updateUnits); [] call FUNC(updateUnits);
// Initalize the camera view // Initalize the camera objects
GVAR(camera) = "Camera" camCreate (ASLtoATL GVAR(camPos)); 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); [] call FUNC(transitionCamera);
// Close map and clear radio // Close map and clear radio
@ -85,8 +91,10 @@ if (_set) then {
(findDisplay 12249) closeDisplay 0; (findDisplay 12249) closeDisplay 0;
// Terminate camera // Terminate camera
GVAR(camera) cameraEffect ["terminate", "back"]; GVAR(freeCamera) cameraEffect ["terminate", "back"];
camDestroy GVAR(camera); camDestroy GVAR(freeCamera);
camDestroy GVAR(unitCamera);
camDestroy GVAR(targetCamera);
clearRadio; clearRadio;
@ -97,10 +105,12 @@ if (_set) then {
BIS_fnc_feedback_allowPP = true; BIS_fnc_feedback_allowPP = true;
// Cleanup camera variables // Cleanup camera variables
GVAR(camera) = nil;
GVAR(camBoom) = nil; GVAR(camBoom) = nil;
GVAR(camDolly) = nil; GVAR(camDolly) = nil;
GVAR(camGun) = nil; GVAR(camGun) = nil;
GVAR(freeCamera) = nil;
GVAR(unitCamera) = nil;
GVAR(targetCamera) = nil;
// Cleanup display variables // Cleanup display variables
GVAR(ctrlKey) = nil; GVAR(ctrlKey) = nil;

View File

@ -43,7 +43,7 @@ if (GVAR(showMap)) then {
// Centre map on camera/unit upon opening // Centre map on camera/unit upon opening
if (_toggleMap) then { 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; ctrlMapAnimCommit _map;
}; };
} else { } else {

View File

@ -43,15 +43,17 @@ if (_newMode != 1) then {
GVAR(camGun) = false; GVAR(camGun) = false;
}; };
private ["_camera"];
if (_newMode == 0) then { // Free if (_newMode == 0) then { // Free
_camera = GVAR(freeCamera);
// Preserve camUnit value for consistency when manually changing view // Preserve camUnit value for consistency when manually changing view
GVAR(camera) cameraEffect ["internal", "back"]; _camera cameraEffect ["internal", "back"];
showCinemaBorder false; showCinemaBorder false;
cameraEffectEnableHUD true;
// Apply the camera zoom // Apply the camera zoom
GVAR(camera) camSetFov -(linearConversion [0.01,2,GVAR(camZoom),-2,-0.01,true]); _camera camSetFov -(linearConversion [0.01,2,GVAR(camZoom),-2,-0.01,true]);
GVAR(camera) camCommit 0; _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) // 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?!) // (Why is so much stuff tied into the current camera unit BI?!)
@ -79,20 +81,32 @@ if (_newMode == 0) then { // Free
// Handle camera movement // Handle camera movement
if (isNil QGVAR(camHandler)) then { GVAR(camHandler) = [FUNC(handleCamera), 0] call CBA_fnc_addPerFrameHandler; }; if (isNil QGVAR(camHandler)) then { GVAR(camHandler) = [FUNC(handleCamera), 0] call CBA_fnc_addPerFrameHandler; };
} else { } else {
_camera = GVAR(unitCamera);
// When null unit is given choose random // When null unit is given choose random
if (isNull _newUnit) then { if (isNull _newUnit) then {
_newUnit = GVAR(unitList) select floor(random(count GVAR(unitList))); _newUnit = GVAR(unitList) select floor(random(count GVAR(unitList)));
}; };
if (_newMode == 1) then { // Internal // Switch camera view to internal unit view (external uses the camera)
// Handle gun cam
if (GVAR(camGun)) then { if (GVAR(camGun)) then {
_newUnit switchCamera "gunner"; _newUnit switchCamera "gunner";
} else { } else {
_newUnit switchCamera "internal"; _newUnit switchCamera "internal";
}; };
} else { // External
_newUnit switchCamera "external"; // 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 // Clear radio if group changed
@ -101,11 +115,6 @@ if (_newMode == 0) then { // Free
}; };
GVAR(camUnit) = _newUnit; GVAR(camUnit) = _newUnit;
// Terminate camera view
GVAR(camera) cameraEffect ["terminate", "back"];
GVAR(camHandler) = nil;
cameraEffectEnableHUD true;
}; };
GVAR(camMode) = _newMode; GVAR(camMode) = _newMode;

View File

@ -41,7 +41,7 @@ if (_newModes isEqualTo []) then {
}; };
// Update camera in case of change // Update camera in case of change
if !(isNil QGVAR(camera)) then { if (GVAR(isSet)) then {
[] call FUNC(transitionCamera); [] call FUNC(transitionCamera);
}; };

View File

@ -49,7 +49,7 @@ if (_newModes isEqualTo []) then {
}; };
// Update camera in case of change // Update camera in case of change
if !(isNil QGVAR(camera)) then { if (GVAR(isSet)) then {
[] call FUNC(transitionCamera); [] call FUNC(transitionCamera);
}; };