Gunter Severloh 4052 Posted July 28 (edited) -=/Respawn in Singleplayer\=- by Rydygier & Gunter Severloh Description When your playing a mission in single-player, either a subscribed or a mission you created yourself, and when you get killed, did you ever wonder if it were possible if you could just keep playing somehow without relying on saves? If you could just respawn like you can in multiplayer? ... Well now you can! This is a code written by Rydydgier that will allow you to respawn in singelplayer, either through preview in the editor, or in a mission in scenarios. All you need to do is define a marker where you want to respawn, or a vehicle name you want to respawn at for a mobile respawn, and then add the ini.sqf in the scenario folder. See the features below for more details! Features - Respawn anywhere by defining where you want to respawn at via marker like a base respawn. - Make your scenario dynamic and replayable by setting up a random respawn by defining where you want to respawn via multiple markers. - Setup a mobile respawn by giving a vehicle a name and you will respawn wherever that vehicle is. - Use the code from an external script and not directly from the init.sqf if you want too. - Save your loadout on respawn of the placed unit in the editor, or respawn with the added loadout setup through arsenal that was applied to the unit. - Set how many times you want to respawn, either use a set number or set it to -1 for unlimited respawns. - Remove your dead body apon death, automatic corpse removal, every time you die in your mission your player character's body will be deleted by sinking into the ground. - Respawn screen. - Respawn timer. Installation and Setup Setup - Script 1. Create a notepad/notepad++ document and copy and paste the following code into it: 2. Save and name the document: init.sqf and put it into your scenario folder. //single player respawn script RYD_SPR_RespawnPositions = [myCar_1];//one will be chosen at random, markers, objects or arrays including coordintes and direction, for example: RYD_SPR_RespawnPositions = ["marker1","OtherMarker_2",someObject_1,[[100,200,0],120]]; RYD_SPR_Respawns = -1;//amount of respawns. If set with negative value - unlimited respawns RYD_SPR_ChangedLoadout = true;//if true, new unit will get old unit's loadout as it was at death, otherwise new unit will get default loadout. RYD_SPR_DelayParameters = [10,false,true,{}];//[delay in seconds, black courtain, external view, optional code to be executed in the middle of countdown where _this equals new unit] RYD_SPR_TextColor = "3a96d4";//RESPAWN IN: color. //all above arrays can be re-defined on the fly. RYD_SPR_atKilled = { params ["_killed"]; if not (RYD_SPR_Respawns == 0) then { _delay = RYD_SPR_DelayParameters select 0; _blackout = RYD_SPR_DelayParameters select 1; _mode2 = "PLAIN"; _mode3 = "PLAIN"; _mode = if (_blackout) then { _mode2 = "BLACK FADED"; _mode3 = "BLACK IN"; 0.55 fadeSound 0.1; "BLACK OUT" } else { (5 min (_delay + 1)) fadeSound 0.1; "PLAIN" }; "RYD_SPR_RespawnCurtain" cutText ["",_mode,0.55]; enableRadio false; clearRadio; if (RYD_SPR_Respawns > 0) then { RYD_SPR_Respawns = RYD_SPR_Respawns - 1; }; _respawnPos0 = selectRandom RYD_SPR_RespawnPositions; _respawnDir = 0; _respawnPos = switch (typeName _respawnPos0) do { case ("STRING") : { _respawnDir = markerDir _respawnPos0; (getMarkerPos _respawnPos0) }; case ("OBJECT") : { _respawnDir = getDir _respawnPos0; (getPosATL _respawnPos0) }; default { _respawnDir = _respawnPos0 select 1; (_respawnPos0 select 0); }; }; _newUnit = (group _killed) createUnit [(typeOf _killed),_respawnPos,[],0,"NONE"]; _newUnit allowDamage false; _newUnit setCaptive true; _newUnit enableSimulation false; _newUnit hideObject true; _newUnit setDir _respawnDir; //_newUnit setPosATL _respawnPos; _newUnit addEventHandler ["Killed",RYD_SPR_atKilled]; if (RYD_SPR_ChangedLoadout) then { _newUnit setUnitLoadout (missionNameSpace getVariable ["RYD_SPR_customLoadout",(getUnitLoadout _killed)]); }; _killedPos = getPosATL _killed; hideBody _killed; addSwitchableUnit _newUnit; [_newUnit,_mode2,_mode3,_killedPos] spawn { params ["_newUnit","_mode2","_mode3","_killedPos"]; _delay = RYD_SPR_DelayParameters select 0; _blackout = RYD_SPR_DelayParameters select 1; _externalView = RYD_SPR_DelayParameters select 2; _code = RYD_SPR_DelayParameters select 3; _camera = objNull; if (_externalView) then { _camPos = _killedPos getPos [2,(random 360)]; _camPos set [2,6]; _camera = ("camera" camCreate _camPos); camUseNVG (sunOrMoon < 0.5); _camera camSetTarget _killedPos; showCinemaBorder false; _camera cameraEffect ["internal", "BACK"]; _camera camCommit 0; _camPos = _killedPos getPos [((((_delay + 1) max 1)* 2) min 200),(random 360)]; _camPos set [2,((((_delay + 1) max 1) * 6) min 600)]; _camera camSetPos _camPos; _camera camCommit (_delay + 1); }; RYD_SPR_ppChrom = ppEffectCreate ["chromAberration", 1499]; RYD_SPR_ppChrom ppEffectAdjust [0.005,0.005,true]; RYD_SPR_ppCCor = ppEffectCreate ["ColorCorrections",1500]; RYD_SPR_ppCCor ppEffectAdjust [1, 0.4, 0, [0, 0, 0, 0], [1, 1, 1, 0], [1, 1, 1, 0]]; RYD_SPR_ppBlur = ppEffectCreate ["DynamicBlur", 1501]; RYD_SPR_ppBlur ppEffectAdjust [0.08]; RYD_SPR_ppGrain = ppEffectCreate ["FilmGrain", 1502]; RYD_SPR_ppGrain ppEffectAdjust [0.5, 2, 1, 1, 1, 0]; sleep 1; selectPlayer _newUnit; _newUnit call _code; BIS_DeathBlur ppEffectAdjust [0]; BIS_DeathBlur ppEffectCommit 0; RYD_SPR_ppCCor ppEffectEnable true; RYD_SPR_ppCCor ppEffectCommit (5 min (_delay + 1)); RYD_SPR_ppGrain ppEffectEnable true; RYD_SPR_ppGrain ppEffectCommit (5 min (_delay + 1)); RYD_SPR_ppBlur ppEffectEnable true; RYD_SPR_ppBlur ppEffectCommit (5 min (_delay + 1)); RYD_SPR_ppChrom ppEffectEnable true; RYD_SPR_ppChrom ppEffectCommit (5 min (_delay + 1)); _time = time; waitUntil { sleep 0.05; _countdown = ((_delay - (time - _time)) max 0) toFixed 1; "RYD_SPR_RespawnCurtain" cutText [(format ["<t color='#%2' size='1.75' align='left' shadow='1'>RESPAWN IN: %1</t>",_countdown,RYD_SPR_TextColor]),_mode2,0.01,true,true]; ((time - _time) > _delay) }; _camera cameraEffect ["terminate", "BACK"]; camDestroy _camera; camUseNVG false; ppEffectDestroy RYD_SPR_ppGrain; ppEffectDestroy RYD_SPR_ppBlur; ppEffectDestroy RYD_SPR_ppChrom; ppEffectDestroy RYD_SPR_ppCCor; 0.55 fadeSound 1; enableRadio true; _newUnit allowDamage true; _newUnit setCaptive false; _newUnit enableSimulation true; _newUnit hideObject false; "RYD_SPR_RespawnCurtain" cutText ["",_mode3,0.55]; }; } else { enableEndDialog; }; }; waitUntil { sleep 0.1; (alive player) }; missionNameSpace setVariable ["RYD_SPR_customLoadout",(getUnitLoadout player)]; player addEventHandler ["Killed",RYD_SPR_atKilled]; Setup - editor (base respawn) For a normal base respawn, in the editor place a marker and name it what you want and then add the name of the marker in quotes to this parameter like in the code below: RYD_SPR_RespawnPositions = ["m1"]; //one will be chosen at random, markers, objects or arrays including coordinates and direction, for example: RYD_SPR_RespawnPositions = ["marker1","OtherMarker_2",someObject_1,[[100,200,0],120]]; Setup - editor (mobile respawn) To setup a mobile respawn in the editor place a vehicle and name it what you want and then add the name of the vehicle without quotes to this parameter like in the code below: RYD_SPR_RespawnPositions = [myCar_1]; //one will be chosen at random, markers, objects or arrays including coordinates and direction, for example: RYD_SPR_RespawnPositions = ["marker1","OtherMarker_2",someObject_1,[[100,200,0],120]]; Setup - External Script Instead of using the init.sqf for the code, you can setup an external script that can be used: 1. Create a notepad/notepad++ document and copy and paste the code from above into it: 2. Save and name the document: RYD_RSP.sqf and put it into your scenario folder. 3. Create a notepad/notepad++ document and add the following code to it: execVM "RYD_RSP.sqf"; 4. Add both RYD_RSP.sqf and the init.sqf to your scenario folder where the mission.sqm is located. Parameters There are 5 parameters you can adjust based on what you want to do in your scenario: RYD_SPR_RespawnPositions = ["m1"]; "m1" is an example name of a marker, it will be chosen at random, markers, objects or arrays including coordinates and direction, for example: RYD_SPR_RespawnPositions = ["marker1","OtherMarker_2",someObject_1,[[100,200,0],120]]; If only one marker name is defined then you will only respawn at that marker, if more are defined then you will respawn randomly at one of the markers defined in the array. RYD_SPR_Respawns = 3; 3 is the amount of respawns you want, it can be any number. If set with negative value like -1 you will have unlimited respawns. RYD_SPR_ChangedLoadout = true; If set to true, new unit will get old unit's loadout as it was at death, otherwise new unit will get default loadout of placed editor unit. RYD_SPR_DelayParameters = [10,false,true,{}]; //[delay in seconds, black curtain, external view, optional code to be executed in the middle of countdown where _this equals new unit] RYD_SPR_TextColor = "3a96d4"; //RESPAWN IN: color. Credits Rydygier wrote the code. Both Gunter's and Rydygier's ideas. Edited August 4 by Gunter Severloh Updated script and thread 5 1 Share this post Link to post Share on other sites
pierremgi 4851 Posted July 28 Nice work for a true die and respawn in SP! The limitations you mentioned lead me to another way where single player falls unconscious, then be healed by fellow AIs or wake up after a parametered delay. SP, on contrary of MP, doesn't really die but player must wait for being on foot again (see MGI SP Simple Respawn module). 2 Share this post Link to post Share on other sites
Gunter Severloh 4052 Posted August 4 Update Script update, from Rydygier: New parameters: RYD_SPR_DelayParameters = [30,false,true,{}]; //[delay in seconds, black curtain, external view, optional code to be executed in the middle of countdown where _this equals new unit]RYD_SPR_TextColor = "3a96d4"; //RESPAWN IN: color. If you turn black curtain on, you'll see countdown text on the black background. If the curtain is off AND external camera is off, you'll see same countdown from new unit perspective, which may look like this: If curtain is OFF and external view is ON (default), then you'll have custom camera focused on the body position moving upwards, giving kind of top-down panoramic view. It may look like this: In all cases radio is disabled and other sounds except music are silenced down. "Optional code" parameter is a way to inject additional coding, that will be executed at the beginning of the countdown. So mostly for advanced users. Of course, advanced users would rather edit the main code instead, but having such an option does no harm. Example of simple use:RYD_SPR_DelayParameters = [20,false,true,{playMusic "RadioAmbient1"}]; This will play known from default menu radio ambient FX at the countdown. But you can same way execute anything, even whole .sqf files. If both curtain is ON and external view is ON - well, curtain covers any camera actions anyway, so in total you have 3 meaningful modes. Second parameter allows to customize countdown text color in hexadecimal format or change it on the fly, just a gimmick. As you see, applied are also some post process effects. During that delay new player unit is already spawned, but it stays invisible, captive, immune to damage and immobilized. 1 Share this post Link to post Share on other sites
Gunter Severloh 4052 Posted August 4 Thanks! But give the props and credits to Rydygier hes the genius of the code, if it weren't for his creative skills, this wouldn't be possible! Share this post Link to post Share on other sites
major-stiffy 279 Posted August 6 Not seeing how this could be incorporated into Pilgrimage. Thoughts? Something like this would be nice... I use it in MP Pilgrimage. The download link doesn't work but I have the file. Share this post Link to post Share on other sites
Rydygier 1309 Posted August 6 There's large risk, it woulnd't work because reasons, but if you want to try, I recommend to [] spawn {}; whole thing at the very end of JRInit.sqf and add such a line: _newUnit = (group _killed) createUnit [(typeOf _killed),_respawnPos,[],0,"NONE"];RYD_JR_Alex = _newUnit; But then also you need to figure a way to define respawn position/decide, where respawn should occur. At the boat? So initially:RYD_SPR_RespawnPositions = [RYD_JR_boat]; And at the hideout if it is set, so this: case (8) : {_center setVariable ["RYD_JR_Parking",_veh]}; into: case (8) : {_center setVariable ["RYD_JR_Parking",_veh];RYD_SPR_RespawnPositions = [_veh];}; And if you pack the hideout - the boat is set again. But there may be optionally multiple hideouts, so it is more complex - perhaps you should rather add new randomly piced spot to RYD_SPR_RespawnPositions each time new hideout is set, and remove this spot when it is packed, and if after that the array is empty - add the boat to it? Share this post Link to post Share on other sites
Rydygier 1309 Posted August 6 Quote ADV Move Respawn Marker Script This also is a way. So you have some marker in RYD_SPR_RespawnPositions and then in some parallel loop you update it's position to make the player respawn somewhere around last position. Maybe like: [] spawn { _pos = getPosATL RYD_JR_Boat; _i = "respawnMark_" + (str _pos); _i = createMarker [_i,_pos]; _i setMarkerColor "colorBlack"; _i setMarkerShape "ICON"; _i setMarkerType "mil_dot"; _i setMarkerSize [0,0]; RYD_SPR_RespawnPositions = [_i]; while {true} do { sleep 30; _i setMarkerPos (player getPos [(75 + (random 75)),random 360]) }; }; But again, IMO there's serious risk, combining this respawn with Pilgrimage would somehow, at least partially, break Pilgrimage regardless of respawn position method. Share this post Link to post Share on other sites
major-stiffy 279 Posted August 7 Yeah, it looks messy. Not liking boat or hide out option myself. I might mess around with the one I use in MP. Thanks Ryd Share this post Link to post Share on other sites