smacker909 3 Posted December 3, 2014 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
kovvalsky 13 Posted December 4, 2014 Your code does not have much sense to me, but maybe onPlayerRespawn.sqf or Respawn EventHandler can help you. You can store one variable on player like "RespawnVar" or something with setVariable command, and look at the value anytime. Share this post Link to post Share on other sites
dr_strangepete 6 Posted December 4, 2014 (edited) 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 December 4, 2014 by dr_strangepete Share this post Link to post Share on other sites
jshock 513 Posted December 4, 2014 (edited) 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 December 4, 2014 by JShock Share this post Link to post Share on other sites
dr_strangepete 6 Posted December 4, 2014 (edited) 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 December 4, 2014 by dr_strangepete rewritten Share this post Link to post Share on other sites
smacker909 3 Posted December 4, 2014 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
jshock 513 Posted December 4, 2014 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
fn_Quiksilver 1636 Posted December 4, 2014 (edited) 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 December 4, 2014 by MDCCLXXVI Share this post Link to post Share on other sites
smacker909 3 Posted December 4, 2014 Thanks, I have some work to do :) Share this post Link to post Share on other sites
siuling337 10 Posted December 4, 2014 Thanks for sharing~! Share this post Link to post Share on other sites