diff --git a/addons/spectator/XEH_postInit.sqf b/addons/spectator/XEH_postInit.sqf index 45ac78e89c..35b463837f 100644 --- a/addons/spectator/XEH_postInit.sqf +++ b/addons/spectator/XEH_postInit.sqf @@ -7,11 +7,4 @@ ["SettingsInitialized", { GVAR(availableModes) = [[0,1,2], [1,2], [0], [1], [2]] select GVAR(restrictModes); GVAR(availableVisions) = [[-2,-1,0,1], [-2,-1], [-2,0,1], [-2]] select GVAR(restrictVisions); - - if !(hasInterface) exitWith {}; - - if (GVAR(onDeath)) then { - player addEventHandler ["Killed",FUNC(handleKilled)]; - player addEventHandler ["Respawn",FUNC(handleRespawn)]; - }; }] call EFUNC(common,addEventHandler); diff --git a/addons/spectator/XEH_preInit.sqf b/addons/spectator/XEH_preInit.sqf index 3b317ba904..73c629a0ce 100644 --- a/addons/spectator/XEH_preInit.sqf +++ b/addons/spectator/XEH_preInit.sqf @@ -2,15 +2,21 @@ ADDON = false; +PREP(bi_respawnBase); +PREP(bi_respawnCounter); +PREP(bi_respawnEndMission); +PREP(bi_respawnInstant); +PREP(bi_respawnNone); +PREP(bi_respawnSeagull); +PREP(bi_respawnSpectator); +PREP(bi_respawnWave); PREP(cacheUnitInfo); PREP(cycleCamera); PREP(handleCamera); PREP(handleCompass); PREP(handleIcons); PREP(handleInterface); -PREP(handleKilled); PREP(handleMouse); -PREP(handleRespawn); PREP(handleToolbar); PREP(handleUnits); PREP(moduleSpectatorSettings); @@ -38,7 +44,7 @@ GVAR(camUnit) = objNull; GVAR(camVision) = -2; GVAR(camZoom) = 1.25; -GVAR(open) = false; +GVAR(isSet) = false; GVAR(showComp) = true; GVAR(showHelp) = true; diff --git a/addons/spectator/config.cpp b/addons/spectator/config.cpp index e686c75294..eb73761e5f 100644 --- a/addons/spectator/config.cpp +++ b/addons/spectator/config.cpp @@ -16,3 +16,38 @@ class CfgPatches { #include "CfgEventHandlers.hpp" #include "CfgVehicles.hpp" #include "ui\interface.hpp" + +class CfgRespawnTemplates { + class None { + onPlayerKilled = QFUNC(bi_respawnNone); + }; + class Spectator { + onPlayerKilled = QFUNC(bi_respawnSpectator); + onPlayerRespawn = QFUNC(bi_respawnSpectator); + }; + class Instant { + onPlayerKilled = QFUNC(bi_respawnInstant); + onPlayerRespawn = QFUNC(bi_respawnInstant); + }; + class Base { + onPlayerKilled = QFUNC(bi_respawnBase); + onPlayerRespawn = QFUNC(bi_respawnBase); + }; + class EndMission + { + onPlayerKilled = QFUNC(bi_respawnEndMission); + onPlayerRespawn = QFUNC(bi_respawnEndMission); + }; + class Seagull { + onPlayerRespawn = QFUNC(bi_respawnSeagull); + }; + class Wave + { + onPlayerKilled = QFUNC(bi_respawnWave); + onPlayerRespawn = QFUNC(bi_respawnWave); + }; + class Counter { + onPlayerKilled = QFUNC(bi_respawnCounter); + onPlayerRespawn = QFUNC(bi_respawnCounter); + }; +}; diff --git a/addons/spectator/functions/fnc_bi_respawnBase.sqf b/addons/spectator/functions/fnc_bi_respawnBase.sqf new file mode 100644 index 0000000000..7ea5b0c745 --- /dev/null +++ b/addons/spectator/functions/fnc_bi_respawnBase.sqf @@ -0,0 +1,35 @@ +/* + * Author: Bohemia Interactive + * Part of the BI respawn framework + * Handles base respawn type (respawn on marker) + * Edited to support ace_spectator integration + * + * Arguments: + * 0: Corpse/New Unit + * 1: Killer/Old Unit + * 2: Respawn Type + * 3: Respawn Delay + * + * Return Value: + * None + * + * Public: No + */ + +#include "script_component.hpp" + +if !(GVAR(onDeath)) exitWith {}; + +params [["_unit",objNull,[objNull]], ["_killer",objNull,[objNull]]]; + +if (alive _unit) then { + [_unit,false] call FUNC(setSpectator); +} else { + private ["_vision","_pos"]; + if (isNull _killer) then {_killer = _unit}; + _vision = [-2,-1] select (sunOrMoon < 1); + _pos = (getPosATL _unit) vectorAdd [0,0,5]; + + [2,_killer,_vision,_pos,getDir _unit] call FUNC(setCameraAttributes); + [_unit] call FUNC(setSpectator); +}; diff --git a/addons/spectator/functions/fnc_bi_respawnCounter.sqf b/addons/spectator/functions/fnc_bi_respawnCounter.sqf new file mode 100644 index 0000000000..0bee90ec61 --- /dev/null +++ b/addons/spectator/functions/fnc_bi_respawnCounter.sqf @@ -0,0 +1,35 @@ +/* + * Author: Bohemia Interactive (Karel Moricky) + * Part of the BI respawn framework + * Handles the respawn timer display + * Edited to disable counter when spectator is opened + * + * Arguments: + * 0: Corpse/New Unit + * 1: Killer/Old Unit + * 2: Respawn Type + * 3: Respawn Delay + * + * Return Value: + * None + * + * Public: No + */ + +#include "script_component.hpp" + +_player = [_this,0,objNull,[objnull]] call bis_fnc_param; + +_respawnDelay = [_this,3,0,[0]] call bis_fnc_param; + +if (!isplayer _player && !isnull _player && _respawnDelay > 0) exitwith {["Attempting to use the function on AI unit %1, can be used only on players."] call bis_fnc_error;}; + +//--- Engine-triggered respawn +_layer = "BIS_fnc_respawnCounter" call bis_fnc_rscLayer; + +if (!alive _player) then { + if (GVAR(onDeath) || (playerrespawntime < 1)) exitwith {}; + _layer cutrsc ["RscRespawnCounter","plain"]; +} else { + _layer cuttext ["","plain"]; +}; diff --git a/addons/spectator/functions/fnc_bi_respawnEndMission.sqf b/addons/spectator/functions/fnc_bi_respawnEndMission.sqf new file mode 100644 index 0000000000..23b8dacc17 --- /dev/null +++ b/addons/spectator/functions/fnc_bi_respawnEndMission.sqf @@ -0,0 +1,62 @@ +/* + * Author: Bohemia Interactive (Karel Moricky) + * Part of the BI respawn framework + * Ends the mission when all players are dead + * Edited to support ace_spectator integration + * + * Arguments: + * 0: Corpse/New Unit + * 1: Killer/Old Unit + * 2: Respawn Type + * 3: Respawn Delay + * + * Return Value: + * None + * + * Public: No + */ + +#include "script_component.hpp" + +params [["_unit",objNull,[objNull]], ["_killer",objNull,[objNull]]]; +private ["_vision","_pos"]; + +if (isNull _killer) then {_killer = _unit}; +_vision = [-2,-1] select (sunOrMoon < 1); +_pos = (getPosATL _unit) vectorAdd [0,0,5]; + +if (ismultiplayer) then { + + _respawnType = 0 call bis_fnc_missionRespawnType; + if (_respawnType in [0,1,4,5]) then { + + //--- No more respawn slots + if ({isplayer _x && alive _x} count playableunits == 0) then { + [["endDeath",false],"bis_fnc_endmission"] call bis_fnc_mp; + } else { + if (GVAR(onDeath) && (_respawnType in [0,1])) then { + [2,_killer,_vision,_pos,getDir _unit] call FUNC(setCameraAttributes); + [_unit] call FUNC(setSpectator); + }; + }; + + //--- Don't end the script to prevent premature mission end + waituntil {false}; + } else { + + if (!alive _unit) then { + + //--- No more respawn tickets + if ([] call bis_fnc_respawntickets == 0 && {isplayer _x} count playableunits == 0) then { + [["endDeath",false],"bis_fnc_endmission"] call bis_fnc_mp; + } else { + if (GVAR(onDeath)) then { + [2,_killer,_vision,_pos,getDir _unit] call FUNC(setCameraAttributes); + [_unit] call FUNC(setSpectator); + }; + }; + } else { + [_unit,false] call FUNC(setSpectator); + }; + }; +}; diff --git a/addons/spectator/functions/fnc_bi_respawnInstant.sqf b/addons/spectator/functions/fnc_bi_respawnInstant.sqf new file mode 100644 index 0000000000..fd1d255cf9 --- /dev/null +++ b/addons/spectator/functions/fnc_bi_respawnInstant.sqf @@ -0,0 +1,35 @@ +/* + * Author: Bohemia Interactive + * Part of the BI respawn framework + * Handles instant respawn type (respawn at position of death) + * Edited to support ace_spectator integration + * + * Arguments: + * 0: Corpse/New Unit + * 1: Killer/Old Unit + * 2: Respawn Type + * 3: Respawn Delay + * + * Return Value: + * None + * + * Public: No + */ + +#include "script_component.hpp" + +if !(GVAR(onDeath)) exitWith {}; + +params [["_unit",objNull,[objNull]], ["_killer",objNull,[objNull]]]; + +if (alive _unit) then { + [_unit,false] call FUNC(setSpectator); +} else { + private ["_vision","_pos"]; + if (isNull _killer) then {_killer = _unit}; + _vision = [-2,-1] select (sunOrMoon < 1); + _pos = (getPosATL _unit) vectorAdd [0,0,5]; + + [2,_killer,_vision,_pos,getDir _unit] call FUNC(setCameraAttributes); + [_unit] call FUNC(setSpectator); +}; diff --git a/addons/spectator/functions/fnc_bi_respawnNone.sqf b/addons/spectator/functions/fnc_bi_respawnNone.sqf new file mode 100644 index 0000000000..a5031a8fd9 --- /dev/null +++ b/addons/spectator/functions/fnc_bi_respawnNone.sqf @@ -0,0 +1,293 @@ +/* + * Author: Bohemia Interactive (Karel Moricky) + * Part of the BI respawn framework + * Shows death screen for respawn type "None" + * Edited to support ace_spectator integration + * + * Arguments: + * 0: Corpse + * 1: Killer + * 2: Respawn Type + * 3: Respawn Delay + * + * Return Value: + * None + * + * Public: No + */ +private ["_soundvolume","_musicvolume"]; + +#define BI_CONTROL (_display displayctrl _n) + +#include "script_component.hpp" + +disableserialization; +_player = _this select 0; +_killer = _this select 1; +if (isnull _killer) then {_killer = _player}; + +_musicvolume = musicvolume; +_soundvolume = soundvolume; //MUF-TODO: check if this is done before sound is faded in fn_feedbackMain.fsm + +_start = isnil "bis_fnc_respawnNone_start"; +if (_start) then { + bis_fnc_respawnNone_start = [daytime,time / 3600]; + + //3.5 fadesound 0; //MUF-commented + + sleep 2; + if (alive player) exitwith {}; + cutText ["","BLACK OUT",1]; + sleep 1.5; + BIS_fnc_feedback_allowPP = false; //MUF-switch health PP off + //(["HealthPP_black"] call bis_fnc_rscLayer) cutText ["","BLACK IN",1];//MUF-black in (remove black screen that was launched in FSM PP) + + if (ismultiplayer) then { + if (GVAR(onDeath)) then { + private ["_vision","_pos"]; + _vision = [-2,-1] select (sunOrMoon < 1); + _pos = (getPosATL _player) vectorAdd [0,0,5]; + + [2,_killer,_vision,_pos,getDir _player] call FUNC(setCameraAttributes); + [_player] call FUNC(setSpectator); + } else { + (finddisplay 46) createdisplay "RscDisplayMissionEnd"; + }; + } else {enableenddialog}; +}; +if (alive player) exitwith { + [player,false] call FUNC(setSpectator); + cuttext ["","plain"]; +}; //--- Terminate when player manages to switch do different unit already + +if (GVAR(onDeath)) exitWith {}; + +waituntil {!isnull (finddisplay 58)}; +_display = finddisplay 58; + +//--- Black fade in +_n = 1060; +BI_CONTROL ctrlsetfade 1; +if (_start) then { + + //--- Play ambient radio + setacctime 1; + 0 fademusic 0; + 4 fademusic 0.8; + playmusic format ['RadioAmbient%1',ceil random 1/*30*/]; + _musicEH = addMusicEventHandler ["MusicStop",{[] spawn {playmusic format ['RadioAmbient%1',ceil random 1/*30*/];};}]; + uinamespace setvariable ["bis_fnc_respawnNone_musicEH",_musicEH]; + _display displayaddeventhandler ["unload","removeMusicEventHandler ['MusicStop',uinamespace getvariable ['bis_fnc_respawnNone_musicEH',-1]];"]; + + BI_CONTROL ctrlcommit 4; +} else { + BI_CONTROL ctrlcommit 0; +}; +cuttext ["","plain"]; + +//--- HUD +_n = 5800; +BI_CONTROL ctrlsettext gettext (configfile >> "cfgingameui" >> "cursor" >> "select"); +BI_CONTROL ctrlsetposition [-10,-10,safezoneH * 0.07 * 3/4,safezoneH * 0.07]; +BI_CONTROL ctrlsettextcolor [1,1,1,1]; +BI_CONTROL ctrlcommit 0; + +//--- SITREP (ToDO: Localize) +_sitrep = "SITREP||"; +if (name _player != "Error: No unit") then { + _sitrep = _sitrep + "KIA: %4. %5|"; +}; +_sitrep = _sitrep + "TOD: %2 [%3]|LOC: %6 \ %7"; +if (_killer != _player) then { + _sitrep = _sitrep + "||ENY: %8"; + if (currentweapon _killer != "") then { + _sitrep = _sitrep + "|ENW: %9" + }; +}; +_sitrep = format [ + _sitrep, + 1 * safezoneH, + [bis_fnc_respawnNone_start select 0,"HH:MM:SS"] call bis_fnc_timetostring, + [bis_fnc_respawnNone_start select 1,"HH:MM:SS"] call bis_fnc_timetostring, + toupper localize format ["STR_SHORT_%1",rank _player], + toupper name _player, + mapGridPosition _player, + toupper worldname, + toupper ((configfile >> "cfgvehicles" >> typeof _killer) call bis_fnc_displayname), + toupper ((configfile >> "cfgweapons" >> currentweapon _killer) call bis_fnc_displayname) + +]; + +_n = 11000; +_bcgPos = ctrlposition BI_CONTROL; +_n = 5858; +//BI_CONTROL ctrlsetposition [_bcgPos select 0,safezoneY + ((_bcgPos select 0) - safezoneX) * 4/3,safezoneW - 2 * (_bcgPos select 2),safezoneH / 2]; +BI_CONTROL ctrlsetposition [(((safezoneW / safezoneH) min 1.2) / 40) + (safezoneX), + ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) + (safezoneY), + safezoneW - 2 * (_bcgPos select 2), + safezoneH / 2]; +BI_CONTROL ctrlcommit 0; +[BI_CONTROL,_sitrep] spawn { + scriptname "bis_fnc_respawnNone: SITREP"; + disableserialization; + _control = _this select 0; + _sitrepArray = toarray (_this select 1); + {_sitrepArray set [_foreachindex,tostring [_x]]} foreach _sitrepArray; + _sitrep = ""; + //_sitrepFormat = "%1"; + _sitrepFormat = "%1"; + + sleep 1; + for "_i" from 0 to (count _sitrepArray - 1) do { + _letter = _sitrepArray select _i; + _delay = if (_letter == "|") then {_letter = "
"; 1} else {0.01}; + _sitrep = _sitrep + _letter; + _control ctrlsetstructuredtext parsetext format [_sitrepFormat,_sitrep + "_"]; + //playsound ["IncomingChallenge",true]; + sleep _delay; + if (isnull _control) exitwith {}; + }; + _control ctrlsetstructuredtext parsetext format [_sitrepFormat,_sitrep]; +}; + + +//--- Create UAV camera +_camera = "camera" camcreate position player; +_camera cameraeffect ["internal","back"]; +_camera campreparefov 0.4; +_camera campreparetarget _killer; +showcinemaborder false; + +//--- Set PP effects +_saturation = 0.0 + random 0.3; +_ppColor = ppEffectCreate ["ColorCorrections", 1999]; +_ppColor ppEffectEnable true; +_ppColor ppEffectAdjust [1, 1, 0, [1, 1, 1, 0], [1 - _saturation, 1 - _saturation, 1 - _saturation, _saturation], [1, 0.25, 0, 1.0]]; +_ppColor ppEffectCommit 0; + +_ppGrain = ppEffectCreate ["filmGrain", 2012]; +_ppGrain ppEffectEnable true; +_ppGrain ppEffectAdjust [random 0.2, 1, 1, 0, 1]; +_ppGrain ppEffectCommit 0; + +//--- Camera update executed every frame +bis_fnc_respawnNone_player = _player; +bis_fnc_respawnNone_killer = _killer; +bis_fnc_respawnNone_camera = _camera; +bis_fnc_respawnNone_loop = { + scriptname "bis_fnc_respawnNone: camera"; + _display = _this select 0; + _player = bis_fnc_respawnNone_player; + _killer = bis_fnc_respawnNone_killer; + _camera = bis_fnc_respawnNone_camera; + + _sin = 20 * sin (time * 7); + _killerPos = [ + (visiblepositionasl _killer select 0), + (visiblepositionasl _killer select 1) + (_sin), + (visiblepositionasl _killer select 2) + (_sin) + ]; + + _dirToKiller = if (_killer == _player) then { + direction _player; + } else { + ([_player,_killerPos] call bis_fnc_dirto) + _sin; + }; + _pos = [ + visiblepositionasl _player, + -20, + _dirToKiller + ] call bis_fnc_relpos; + _pos set [2,((_pos select 2) + 7) max (getterrainheightasl _pos + 7)]; + + //--- Pitch + _heightCamera = getterrainheightasl _pos; + _heightKiller = getterrainheightasl _killerPos; + _height = _heightCamera - _heightKiller; + _dis = _killerPos distance _pos; + _angle = (asin (_height/_dis)); + + _camera setdir _dirtokiller; + [_camera,-_angle,_sin] call bis_fnc_setpitchbank; + _camera setposasl _pos; + + //--- HUD + _n = 5800; + _hudPos = (worldtoscreen position _player); + if (count _hudPos > 0) then { + _hudPosW = ctrlposition BI_CONTROL select 2; + _hudPosH = ctrlposition BI_CONTROL select 3; + _hudPos = [ + (_hudPos select 0) - _hudPosW / 2, + (_hudPos select 1) - _hudPosH / 2, + _hudPosW, + _hudPosH + ]; + BI_CONTROL ctrlsetposition _hudPos; + BI_CONTROL ctrlcommit 0; + }; +}; + +bis_fnc_respawnNone_keydown = { + _key = _this select 1; + + if (_key in (actionkeys 'nightvision') || _key < 0) then { + bis_fnc_respawnNone_vision = bis_fnc_respawnNone_vision + 1; + _vision = bis_fnc_respawnNone_vision % 4; + switch (_vision) do { + case 0: { + camusenvg false; + call compile 'false SetCamUseTi 0'; + }; + case 1: { + camusenvg true; + call compile 'false SetCamUseTi 0'; + }; + case 2: { + camusenvg false; + call compile 'true SetCamUseTi 0'; + }; + case 3: { + camusenvg false; + call compile 'true SetCamUseTi 1'; + }; + }; + }; +}; +//bis_fnc_respawnNone_vision = (1 + floor random 3) % 4; //--- Random vision (not NVG) +bis_fnc_respawnNone_vision = -1; +if (sunormoon < 1) then {bis_fnc_respawnNone_vision = 0;}; +[-1,-1] call bis_fnc_respawnNone_keydown; + +_display displayaddeventhandler ["mousemoving","_this call bis_fnc_respawnNone_loop"]; +_display displayaddeventhandler ["mouseholding","_this call bis_fnc_respawnNone_loop"]; +_display displayaddeventhandler ["keydown","_this call bis_fnc_respawnNone_keydown"]; + + +//--- Team Switch display opened +waituntil {isnull _display}; +_displayTeamSwitch = finddisplay 632; + +//--- Team Switch display closed - cleanup and restart the view +waituntil {isnull _displayTeamSwitch}; + +_camera cameraeffect ["terminate","back"]; +camdestroy _camera; + +bis_fnc_respawnNone_player = nil; +bis_fnc_respawnNone_killer = nil; +bis_fnc_respawnNone_camera = nil; +bis_fnc_respawnNone_loop = nil; + +ppeffectdestroy _ppColor; +ppeffectdestroy _ppGrain; + +if (!alive player) exitwith {_this call bis_fnc_respawnNone;}; + + +//--- Resurrection! +BIS_fnc_feedback_allowPP = true; +0 fadesound _soundvolume; +0 fademusic _musicvolume; +playmusic ""; +bis_fnc_respawnNone_start = nil; diff --git a/addons/spectator/functions/fnc_bi_respawnSeagull.sqf b/addons/spectator/functions/fnc_bi_respawnSeagull.sqf new file mode 100644 index 0000000000..2e01ffa6ea --- /dev/null +++ b/addons/spectator/functions/fnc_bi_respawnSeagull.sqf @@ -0,0 +1,101 @@ +/* + * Author: Bohemia Interactive + * Part of the BI respawn framework + * Correctly handles seagull respawn (not used by default) + * Edited to support ace_spectator integration + * + * Arguments: + * 0: Corpse/New Unit + * 1: Killer/Old Unit + * 2: Respawn Type + * 3: Respawn Delay + * + * Return Value: + * None + * + * Public: No + */ + +#include "script_component.hpp" + +_seagull = _this select 0; +_player = _this select 1; +_this call bis_fnc_log; + +if (!isplayer _player && !isplayer _seagull) exitwith {["Attempting to use the function on AI unit %1, can be used only on players."] call bis_fnc_error;}; + +waituntil {missionnamespace getvariable ["BIS_fnc_feedback_allowDeathScreen",true]}; +BIS_fnc_feedback_allowPP = false; +//(["HealthPP_black"] call bis_fnc_rscLayer) cutText ["","BLACK IN",8]; + +if (GVAR(onDeath)) exitWith { + private ["_vision","_pos"]; + + if (isNull _player) then {_player = _seagull}; + _vision = [-2,-1] select (sunOrMoon < 1); + _pos = (getPosATL _player) vectorAdd [0,0,5]; + + [_seagull,QGVAR(isSeagull)] call EFUNC(common,hideUnit); + [2,_player,_vision,_pos,getDir _seagull] call FUNC(setCameraAttributes); + [_seagull] call FUNC(setSpectator); +}; + +_camera = "camera" camCreate [(position _player select 0)-0.75, (position _player select 1)-0.75,(position _player select 2) + 0.5]; +_camera cameraEffect ["internal","back"]; +_camera camSetFOV 0.800; +_camera camCommit 0; +waituntil {camCommitted _camera}; + +0 fadeMusic 0.5; +playMusic "Track06_Abandoned_Battlespace"; + +_camera camSetTarget vehicle _player; +_camera camSetRelPos [-0.82,-3.12,3.38]; +_camera camSetFOV 0.800; +_camera camCommit 7; + +sleep 1; +_preload = _player spawn {waitUntil {(preloadCamera getPos _this) && (2 preloadObject _this)}}; +sleep 5; +waituntil {camCommitted _camera}; + +_camera camSetRelPos [1.17,-21.71,2.07]; +_camera camSetFOV 0.400; +_camera camCommit 10; +sleep 2; +terminate _preload; +sleep 3; +_preload = _player spawn {waitUntil {(preloadCamera getPos _this) && (3 preloadObject _this)}}; +waituntil {camCommitted _camera}; + +_camera camSetTarget vehicle _player; +_camera camSetRelPos [5.80,1.29,5.07]; +_camera camSetFOV 0.300; +_camera camCommit 7; +sleep 2; +terminate _preload; +_preload = _seagull spawn {waitUntil {(preloadCamera getPos _this) && (4 preloadObject _this)}}; +waituntil {camCommitted _camera}; + +_camera camSetRelPos [2.71,19.55,12.94]; +_camera camSetFOV 0.700; +_camera camCommit 2; +waituntil {camCommitted _camera}; + +_camera camSetTarget _seagull; +_camera camSetRelPos [-6.66,18.99,2.59]; +_camera camSetFOV 0.700; +_camera camCommit 3; +waituntil {camCommitted _camera}; + +3 fadeMusic 0; + +_camera camSetRelPos [1.17,-21.71,-1.07]; +_camera camSetFOV 0.300; +_camera camCommit 3; +waituntil {camCommitted _camera}; +terminate _preload; + +_seagull switchCamera "EXTERNAL"; +_seagull cameraEffect ["terminate","back"]; +camDestroy _camera; diff --git a/addons/spectator/functions/fnc_bi_respawnSpectator.sqf b/addons/spectator/functions/fnc_bi_respawnSpectator.sqf new file mode 100644 index 0000000000..5097b61ab2 --- /dev/null +++ b/addons/spectator/functions/fnc_bi_respawnSpectator.sqf @@ -0,0 +1,59 @@ +/* + * Author: Bohemia Interactive + * Part of the BI respawn framework + * Opens BI spectator interface (default used by seagull respawn) + * Edited to support ace_spectator integration + * + * Arguments: + * 0: Corpse/New Unit + * 1: Killer/Old Unit + * 2: Respawn Type + * 3: Respawn Delay + * + * Return Value: + * None + * + * Public: No + */ + +#include "script_component.hpp" + +params [["_unit",objNull,[objNull]], ["_killer",objNull,[objNull]], ["_respawn",-1,[0]]]; +private ["_vision","_pos"]; + +if (isNull _killer) then {_killer = _unit}; +_vision = [-2,-1] select (sunOrMoon < 1); +_pos = (getPosATL _unit) vectorAdd [0,0,5]; + +_layer = "BIS_fnc_respawnSpectator" call bis_fnc_rscLayer; + +if (!alive _unit) then { + if (GVAR(onDeath)) then { + [2,_killer,_vision,_pos,getDir _unit] call FUNC(setCameraAttributes); + [_unit] call FUNC(setSpectator); + } else { + _layer cutrsc ["RscSpectator","plain"]; + }; +} else { + if (_respawn == 1) then { + + //--- Open + waituntil {missionnamespace getvariable ["BIS_fnc_feedback_allowDeathScreen",true]}; + BIS_fnc_feedback_allowPP = false; + //(["HealthPP_black"] call bis_fnc_rscLayer) cutText ["","BLACK IN",1]; + if (GVAR(onDeath)) then { + [_unit,QGVAR(isSeagull)] call EFUNC(common,hideUnit); + [2,_killer,_vision,_pos,getDir _unit] call FUNC(setCameraAttributes); + [_unit] call FUNC(setSpectator); + } else { + _layer cutrsc ["RscSpectator","plain"]; + }; + } else { + if (GVAR(onDeath)) then { + [_unit,false] call FUNC(setSpectator); + }; + + //--- Close + _layer cuttext ["","plain"]; + }; +}; diff --git a/addons/spectator/functions/fnc_bi_respawnWave.sqf b/addons/spectator/functions/fnc_bi_respawnWave.sqf new file mode 100644 index 0000000000..371a8edcdc --- /dev/null +++ b/addons/spectator/functions/fnc_bi_respawnWave.sqf @@ -0,0 +1,43 @@ +/* + * Author: Bohemia Interactive + * Part of the BI respawn framework + * Handles wave respawning system + * Edited to support ace_spectator integration + * + * Arguments: + * 0: Corpse/New Unit + * 1: Killer/Old Unit + * 2: Respawn Type + * 3: Respawn Delay + * + * Return Value: + * None + * + * Public: No + */ + +#include "script_component.hpp" + +params [["_unit",objNull,[objNull]], ["_killer",objNull,[objNull]], ["_respawn",0,[0]], ["_respawnDelay",0,[0]]]; + +if (!isplayer _unit && !isnull _unit) exitwith {["Attempting to use the function on AI unit %1, can be used only on players."] call bis_fnc_error;}; + +if (!alive _unit) then { + //--- Set the time only when it was not modified already + if (_respawnDelay != 0 && _respawnDelay == playerrespawntime) then { + setplayerrespawntime (_respawnDelay + _respawnDelay - (servertime % _respawnDelay)); + + if !(GVAR(onDeath)) exitWith {}; + private ["_vision","_pos"]; + + if (isNull _killer) then {_killer = _unit}; + _vision = [-2,-1] select (sunOrMoon < 1); + _pos = (getPosATL _unit) vectorAdd [0,0,5]; + + [2,_killer,_vision,_pos,getDir _unit] call FUNC(setCameraAttributes); + [_unit] call FUNC(setSpectator); + }; +} else { + setplayerrespawntime _respawndelay; + [_unit,false] call FUNC(setSpectator); +}; diff --git a/addons/spectator/functions/fnc_handleInterface.sqf b/addons/spectator/functions/fnc_handleInterface.sqf index 315398ab0c..5c8c958451 100644 --- a/addons/spectator/functions/fnc_handleInterface.sqf +++ b/addons/spectator/functions/fnc_handleInterface.sqf @@ -23,8 +23,7 @@ switch (toLower _mode) do { // Safely open/close the interface case "open": { // Prevent reopening - if (GVAR(open)) exitWith {}; - GVAR(open) = true; + if (GVAR(isSet)) exitWith {}; // Initalize camera variables GVAR(camBoom) = 0; @@ -37,15 +36,17 @@ switch (toLower _mode) do { GVAR(mouse) = [false,false]; GVAR(mousePos) = [0.5,0.5]; - // Camera starts with night vision if it's dark - if (sunOrMoon < 1) then { - [nil,nil,-1] call FUNC(setCameraAttributes); - }; - // Initalize the camera view GVAR(camera) = "Camera" camCreate (ASLtoATL GVAR(camPos)); [] call FUNC(transitionCamera); + // Close map + openMap [false,false]; + + // Close any BI layers/effects + BIS_fnc_feedback_allowPP = false; + ("BIS_fnc_respawnCounter" call BIS_fnc_rscLayer) cutText ["","plain"]; + // Close all existing dialogs while {dialog} do { closeDialog 0; @@ -65,8 +66,7 @@ switch (toLower _mode) do { _args params ["_unit"]; // Can't close a second time - if !(GVAR(open)) exitWith {}; - GVAR(open) = false; + if !(GVAR(isSet)) exitWith {}; // Terminate interface while {dialog} do { @@ -80,6 +80,10 @@ switch (toLower _mode) do { // Return to player view _unit switchCamera "internal"; + // Re-enable any BI effects + BIS_fnc_feedback_allowPP = true; + BIS_fnc_respawnNone_start = nil; + // Cleanup camera variables GVAR(camera) = nil; GVAR(camBoom) = nil; diff --git a/addons/spectator/functions/fnc_handleKilled.sqf b/addons/spectator/functions/fnc_handleKilled.sqf deleted file mode 100644 index 05671ed749..0000000000 --- a/addons/spectator/functions/fnc_handleKilled.sqf +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Author: SilentSpike - * Set inital camera attributes and set as spectator on death - * Part of the spectator during death system - * - * Arguments: - * 0: Corpse - * 1: Killer - * - * Return Value: - * None - * - * Public: No - */ - -#include "script_component.hpp" - -params ["_unit","_killer"]; - -if (isNull _killer) then { - [2,_unit] call FUNC(setCameraAttributes); -} else { - [2,_killer] call FUNC(setCameraAttributes); -}; - -[_unit] call FUNC(setSpectator); diff --git a/addons/spectator/functions/fnc_handleRespawn.sqf b/addons/spectator/functions/fnc_handleRespawn.sqf deleted file mode 100644 index aa695dd553..0000000000 --- a/addons/spectator/functions/fnc_handleRespawn.sqf +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Author: SilentSpike - * Un-set as spectator on respawn - * Part of the spectator during death system - * - * Arguments: - * 0: New unit - * 1: Old unit - * - * Return Value: - * None - * - * Public: No - */ - -#include "script_component.hpp" - -params ["_unit","_oldUnit"]; - -[_unit,false] call FUNC(setSpectator); diff --git a/addons/spectator/functions/fnc_setCameraAttributes.sqf b/addons/spectator/functions/fnc_setCameraAttributes.sqf index da2373318d..278a8c4758 100644 --- a/addons/spectator/functions/fnc_setCameraAttributes.sqf +++ b/addons/spectator/functions/fnc_setCameraAttributes.sqf @@ -51,7 +51,7 @@ if !(_vision in GVAR(availableVisions)) then { }; GVAR(camPan) = _heading % 360; -GVAR(camPosition) = (ATLtoASL _position); +GVAR(camPos) = (ATLtoASL _position); GVAR(camSpeed) = (_speed max 0.05) min 10; GVAR(camTilt) = (_tilt max -89) min 89; GVAR(camUnit) = _unit; diff --git a/addons/spectator/functions/fnc_setSpectator.sqf b/addons/spectator/functions/fnc_setSpectator.sqf index b6e85926c5..2d5ada415c 100644 --- a/addons/spectator/functions/fnc_setSpectator.sqf +++ b/addons/spectator/functions/fnc_setSpectator.sqf @@ -1,9 +1,9 @@ /* * Author: SilentSpike - * Sets target unit to the given spectator state (virtually) + * Sets target player to the given spectator state (virtually) * To physically handle a spectator see ace_spectator_fnc_stageSpectator * - * Units will be able to communicate in ACRE/TFAR as appropriate + * Player will be able to communicate in ACRE/TFAR as appropriate * The spectator interface will be opened/closed * * Arguments: @@ -23,20 +23,11 @@ params ["_unit", ["_set",true,[true]]]; -// No change, no service (but allow spectators to be reset) -if !(_set || (GETVAR(_unit,GVAR(isSet),false))) exitWith {}; - // Only run for player units if !(isPlayer _unit) exitWith {}; if !(local _unit) exitwith { - [[_unit, _set, _target], QFUNC(setSpectator), _unit] call EFUNC(common,execRemoteFnc); -}; - -if (_set) then { - ["open"] call FUNC(handleInterface); -} else { - ["close",_unit] call FUNC(handleInterface); + [[_unit, _set], QFUNC(setSpectator), _unit] call EFUNC(common,execRemoteFnc); }; // Handle common addon audio @@ -44,10 +35,14 @@ if (["ace_hearing"] call EFUNC(common,isModLoaded)) then {EGVAR(hearing,disableV if (["acre_sys_radio"] call EFUNC(common,isModLoaded)) then {[_set] call acre_api_fnc_setSpectator}; if (["task_force_radio"] call EFUNC(common,isModLoaded)) then {[_unit, _set] call TFAR_fnc_forceSpectator}; -// No theoretical change if an existing spectator was reset -if !(_set isEqualTo (GETVAR(_unit,GVAR(isSet),false))) then { - // Mark spectator state for reference - _unit setVariable [QGVAR(isSet), _set, true]; - - ["spectatorSet",[_set]] call EFUNC(common,localEvent); +if (_set) then { + ["open"] call FUNC(handleInterface); +} else { + ["close",_unit] call FUNC(handleInterface); }; + +// Mark spectator state for reference +_unit setVariable [QGVAR(isSet), _set, true]; +GVAR(isSet) = _set; + +["spectatorSet",[_set,_unit]] call EFUNC(common,localEvent); diff --git a/addons/spectator/functions/fnc_stageSpectator.sqf b/addons/spectator/functions/fnc_stageSpectator.sqf index bac5174601..3e17235e3e 100644 --- a/addons/spectator/functions/fnc_stageSpectator.sqf +++ b/addons/spectator/functions/fnc_stageSpectator.sqf @@ -30,7 +30,7 @@ if !(_set || (GETVAR(_unit,GVAR(isStaged),false))) exitWith {}; if !(isPlayer _unit) exitWith {}; if !(local _unit) exitwith { - [[_unit, _set, _target], QFUNC(stageSpectator), _unit] call EFUNC(common,execRemoteFnc); + [[_unit, _set], QFUNC(stageSpectator), _unit] call EFUNC(common,execRemoteFnc); }; // Prevent player falling into water @@ -49,7 +49,7 @@ if (_set) then { [_unit, QGVAR(isStaged)] call EFUNC(common,hideUnit); [_unit, QGVAR(isStaged)] call EFUNC(common,muteUnit); - _unit setPos (getMarkerPos QGVAR(respawn)); + _unit setPos (markerPos QGVAR(respawn)); } else { // Physical beings can talk [_unit, QGVAR(isStaged)] call EFUNC(common,unhideUnit);