Jump to content
Sign in to follow this  
smacker909

respawn problem

Recommended Posts

Hey guys, I'm having an occasional issue with my respawn script being called multiple times.. trying to keep count for max respawns..etc.

The actual respawn works fine, but sometimes I get 2 counts for 1 respawn. I understand that the handledamage can be called multiple times at once, but I'm unsure how to get my counter working :(

Any help would be much appreciated !

I'm using ;

player addeventhandler ["handledamage",{ player setdamage ((damage player) / 1.001)}];
maxRespawns = 3;
respawns = 0;

and running;

if(isNil "respawning") then {respawning = false};
if (respawning) exitWith {}; 
waitUntil {damage player >= .85};
null = [] execVM "scripts\respawn.sqf";

finally;

respawn.sqf:

respawning = true;
1 fadeSound 0;
2 fadeMusic 1;

_track = [] call randomMusic;
playMusic _track;
titleText ["You are critically wounded. Respawning...","PLAIN DOWN"];
sleep 1;

player setVelocity [0,0,0];
player playMove "AinjPpneMstpSnonWrflDnon_rolltoback";

sleep 2;

titleCut ["", "BLACK OUT", 3];
sleep 3;
titleCut ["", "BLACK FADED", 999];

_dir = [player, getMarkerPos "virtualExtractionMkr"] call BIS_fnc_dirTo;
_pos = [position player, 300, _dir] call BIS_fnc_relPos;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// for ->  BIS_fnc_findSafePos
_mindist = 0;           // minimum distance from the center position
_maxdist = 50;          // maximum distance from the center position
_minFromObj = 2;         // minimum distance from the nearest object
_waterMode = 0;          //  0 = No, 1 = Can, 2 = Must
_terrGrd = .7;            // max terrain grad: Number - average altitude diffrerence in meters
_shore = 0;              // 0 - doesn't have to be shore , 1 - must be shore
/*
optional:
blacklist (optional): Array - nested array of positions to avoid
default positions (optional): Array - nested array of default positions
*/

_finalPos = [_pos, _mindist, _maxdist, _minFromObj, _waterMode, _terrGrd, _shore] call BIS_fnc_findSafePos;


VASBox setPos _finalPos;
_finalPos set[1,(_finalPos select 1) + 5];
player setPos _finalPos;


player setDamage 0;
player setCaptive false;

sleep 5;

player playMove "amovppnemstpsraswrfldnon";
player playMove "";

1 fadeSound 1;
playsound "chopperLeaving";

titleCut ["", "BLACK IN", 3];
titleText ["","PLAIN DOWN"];
execVM "scripts\intel_hud.sqf";
sleep 3;
7 fadeMusic 0;
7 fadeSound 1;

respawns = respawns + 1;
playSound "radioStatic";
hint format ["%1 of %2 respawns used.",respawns, maxRespawns];
sleep 2;

if (respawns < maxRespawns) then 
{	
execVM "scripts\respawnSetup.sqf"
}else{
player removeAllEventHandlers "HandleDamage";
hint "Out of respawns!";
};

respawning = false;

Share this post


Link to post
Share on other sites

handleDamage may at times be called twice, but nothing i can see in your eventhandler is connected to your counter.

sp or mp? and is there a chunk of code missing? where are you running this:

if(isNil "respawning") then {respawning = false}; 
if (respawning) exitWith {};  
waitUntil {damage player >= .85}; 
null = [] execVM "scripts\respawn.sqf";  

A couple things off the top of my head that sound similar:

- respawned player body is colliding with previous body, object or vehicle, killing it quickly, triggering another respawn (a previous personal hair-pulling discovery) (SP)

- respawn.sqf is not starting and setting 'respawning = true' fast enough, which could cause a second iteration to also loop & run. try moving that initial mutex to just after the waitUntil{} line so it is set before respawn is even run; respawn.sqf then takes care of returning it to 'respawning=false'.

- add a timeout condition to your script so it cannot be executed more than once every 5 sec, for example. (allowtime = time + 5; if (time > allowtime)...) - although i encourage discovering the blip rather than just burying it.

Edited by dr_strangepete

Share this post


Link to post
Share on other sites
Your code does not make much sense to me

Same thoughts here, but Kovvalsky is on the right track with onPlayerRespawn.sqf and/or using get/set variable to accomplish what you need to.

I would also recommend just adding a Dammaged or Hit EH to the player instead of a HandleDamage, allowing you to combine your need to check the player damage, instead of using a waitUntil:

I'm using strictly the get/set variable method below:

//init.sqf or initPlayerLocal.sqf
player addEventHandler ["Hit",
{
if ((damage player >= 0.85) && player getVariable ["respawns",0] < player getVariable ["maxRespawns",3] && !(player getVariable ["respawnProcess",false])) then 
{
	null = [] execVM "scripts\respawn.sqf";
	player setVariable ["respawns",1];
	player setVariable ["respawnProcess",true];
};
}];

Changed up your main body as well to reflect the needed changes, and I also took out some other stuff as I wasn't sure why you had them, so if they are still necessary for something else just place them back in:

//respawn.sqf

if (player getVariable ["respawnProcess",false]) exitWith {};

_respawnCount = player getVariable ["respawns",0];
_maxRespawns = player getVariable ["maxRespawns",3];

1 fadeSound 0; 
2 fadeMusic 1; 

_track = [] call randomMusic; 
playMusic _track; 
titleText ["You are critically wounded. Respawning...","PLAIN DOWN"]; 
sleep 1; 

player setVelocity [0,0,0]; 
player playMove "AinjPpneMstpSnonWrflDnon_rolltoback"; 

sleep 2; 

titleCut ["", "BLACK OUT", 3]; 
sleep 3; 
titleCut ["", "BLACK FADED", 999]; 

_dir = [player, getMarkerPos "virtualExtractionMkr"] call BIS_fnc_dirTo; 
_pos = [position player, 300, _dir] call BIS_fnc_relPos; 

///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
// for ->  BIS_fnc_findSafePos 
_mindist = 0;           // minimum distance from the center position 
_maxdist = 50;          // maximum distance from the center position 
_minFromObj = 2;         // minimum distance from the nearest object 
_waterMode = 0;          //  0 = No, 1 = Can, 2 = Must 
_terrGrd = .7;            // max terrain grad: Number - average altitude diffrerence in meters 
_shore = 0;              // 0 - doesn't have to be shore , 1 - must be shore 
/* 
   optional: 
   blacklist (optional): Array - nested array of positions to avoid 
   default positions (optional): Array - nested array of default positions 
*/ 

_finalPos = [_pos, _mindist, _maxdist, _minFromObj, _waterMode, _terrGrd, _shore] call BIS_fnc_findSafePos; 


VASBox setPos _finalPos; 
_finalPos set[1,(_finalPos select 1) + 5]; 
player setPos _finalPos; 


player setDamage 0; 
player setCaptive false; 

sleep 5; 

player playMove "amovppnemstpsraswrfldnon"; 
player playMove ""; 

1 fadeSound 1; 
playsound "chopperLeaving"; 

titleCut ["", "BLACK IN", 3]; 
titleText ["","PLAIN DOWN"]; 
null = [] execVM "scripts\intel_hud.sqf"; 
sleep 3; 
7 fadeMusic 0; 
7 fadeSound 1; 

playSound "radioStatic"; 
hint format ["%1 of %2 respawns used.",_respawnCount,_maxRespawns]; 
sleep 2; 

if (_respawnCount < _maxRespawns) then  
{     
  null = execVM "scripts\respawnSetup.sqf";//I'm not sure you will need to set it up again with my setup 
}else{ 
   player removeAllEventHandlers "Hit"; 
   hint "Out of respawns!"; 
};

player setVariable ["respawnProcess",false];

Edited by JShock

Share this post


Link to post
Share on other sites

I think handleDamage EH is more appropriate, as 'Hit' isn't guaranteed** to be called when killed, so if you get one-shotted, you won't respawn. Aside, looks like the better way to go, with whats given.

depending if single player or mp respawn eh's and scripts wouldn't work, as respawn is manually scripted in sp, and thus the need to intercept the handleDamage, and decide whether to live, or let die.

Edited by dr_strangepete
rewritten

Share this post


Link to post
Share on other sites

Sorry I should have specified this is SP and not true respawn, but rather don't let me truly die, black out my screen and move me :) Funny thing is it's working fine about 90% as much as I have tested.

I will check out the suggestions and post back. Thanks for taking the time!

Share this post


Link to post
Share on other sites
I think handleDamage EH is more appropriate, as 'Hit' isn't guaranteed** to be called when killed, so if you get one-shotted, you won't respawn.

Good point, it's a simple change of the EH name and maybe a condition or two in my example.

Share this post


Link to post
Share on other sites
Sorry I should have specified this is SP and not true respawn, but rather don't let me truly die, black out my screen and move me :) Funny thing is it's working fine about 90% as much as I have tested.

I will check out the suggestions and post back. Thanks for taking the time!

The issue you're having is due to player body parts. There are a few different body parts (legs, hands, head, torso, etc) which can all receive damage. If one body part receives fatal damage the player will die, even though the total average damage returned by (damage player) won't have hit your threshold. Of course once the death event occurs all damage is set to 1.

Here is a Damage EH I have for players, to keep a player alive if they are going to die.

Credit: Celery for his work on HandleDamage, and I think also credit Grimes for elements of his revive system.

This is as lean and mean as I can get it.

playerDamageHandler01 = player addEventHandler [
"HandleDamage",
{
	private ["_selections","_getHit","_i","_olddmg","_curdmg","_newdmg"];
	_selections = player getVariable ["selections",[]];
	_getHit = player getVariable ["getHit",[]];
	_selection = _this select 1;
	_curdmg = _this select 2;
	if (!(_selection isEqualTo [_selections])) then {
		0 = _selections pushBack _selection;
		0 = _getHit pushBack 0;
	};
	_i = _selections find _selection;
	_olddmg = _getHit select _i;
	if (_curdmg >= 0.99) then {
		_newdmg = 0.99;

		//=============================== INSERT YOUR SCRIPT BELOW

		player allowDamage FALSE;				// Reset this to TRUE in your script when appropriate
		[player] spawn QS_fnc_unconsciousM;		// Replace this with your 'death but not quite death' script

		//=============================== INSERT YOUR SCRIPT ABOVE

		_newdmg;
	} else {
		_newdmg = _curdmg;
		_getHit set [_i,_newdmg];
		_newdmg;
	};
}
];

And to remove it:

player removeEventHandler ["HandleDamage",playerDamageHandler01]; 
hint "Out of respawns!"; 

* The weakness of a handledamage system intervening prior to the death event is that we don't get the nice ragdoll physics. There are gimmicky ways to simulate the ragdoll (talk to zooloo75), but I have found after extensive coding attempts that it is aesthetically better just to let the player die to get some nice organic death animation, and then worry about the medical system after the death has occurred. I suppose if it is single player it doesn't matter as the player can't really see himself especially with the "BLACK OUT".

Edited by MDCCLXXVI

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
Sign in to follow this  

×