caddrel 10 Posted May 21, 2017 (edited) Hello there, Am trying to put together missions where a player group can only be incapacitated, never killed. The mission is only ever failed when all players are incapacitated; so there's always a chance of recovery and "no man is left behind." Have been able to handle most situations using a modified version of the script from this thread: https://forums.bistudio.com/forums/topic/199665-damage-handling-scripts-broken-since-166-update/?do=findComment&comment=3191125 However, when players are shot/injured/exploded while inhabiting a vehicle they're dead dead, they never even enter the incapacitated state. This even applies to relatively innocuous "vehicles" like M2 tripods. Is there a workaround for this that could be used? Am very happy putting together something that ejects players from the vehicle on receiving otherwise lethal damage and incapping them, or having a script monitor vehicles and making sure this happens as well. Just don't know enough about all the event handlers / triggers / functions to make that happen. Looking into it now! Anyone know of a potential solution/workaround? Even if it is just pointing in the right direction to look. Edited May 21, 2017 by caddrel Extra sentence Share this post Link to post Share on other sites
R3vo 2654 Posted May 21, 2017 Perhaps you can check the animation the player is currently using? The animation for incapacitated players inside a vehicle should be different from the normal one. https://community.bistudio.com/wiki/Arma_3:_Event_Handlers#AnimChanged 1 Share this post Link to post Share on other sites
caddrel 10 Posted May 21, 2017 (edited) So have done some looking into this. Was trying to alter the default function BIS_fnc_reviveEhDammaged: #include "defines.inc" /* unit: Object - Object the event handler is assigned to hitSelection: String - Name of the selection where the unit was damaged damage: Number - Resulting level of damage hitPartIndex: Number - hit index of the hit selection hitPoint: String - hit point Cfg name shooter: Object - shooter reference (to get instigator use getShotParents on projectile) projectile: Object - the projectile that caused damage */ params ["_unit", "", "_damage","","_hitPoint","_source"]; if (alive _unit && {_damage >= 1 && {REVIVE_ENABLED(_unit) && {_hitPoint == "Incapacitated" && {IS_ACTIVE(_unit)}}}}) then { //["[i] Incapacitated by dependence: %1",_this] call bis_fnc_logFormat; //award attacker with +1 'infantry kill' point [_source] spawn bis_fnc_reviveAwardKill; //incapacitate unit outside of vehicle if (!IN_VEHICLE(_unit)) then { if (isNull _source || {!bis_revive_killfeedShow}) then { SET_STATE(_unit,STATE_INCAPACITATED); } else { SET_STATE_XTRA(_unit,STATE_INCAPACITATED,_source); }; } //kill unit in vehicle else { _unit setDamage 1; }; }; Removed it from the unit via initPlayerLocal.sqf, and replaced it with this: params ["_unit", "", "_damage","","_hitPoint","_source"]; if ((alive _unit) && ((_damage >= 1) && (_hitPoint == "Incapacitated"))) then { //If unit is inside vehicle, move them out and set unconscious. Otherwise proceed as normal. if (vehicle player != player) then { [_source] spawn bis_fnc_reviveAwardKill; moveOut _unit; _unit setUnconscious true; } else { _this call bis_fnc_reviveEhDammaged; }; } else { diag_log format ["LOG:Conditions not met: Alive is %1, damage is %2, hitpoint is %3",alive _unit,_damage,_hitPoint]; }; This seems to preserve previous behaviour when a player is out of a vehicle; they become incapacitated and (because of my other script) are impossible to damage in that state. However when a player is inside the vehicle, the dammaged handler is only called once for the unit, and by that time "alive == false"; "13:19:31 "CADLOG:Conditions not met: Alive is false, damage is 1, hitpoint is Incapacitated"" I've been testing the different interactions by dropping explosives on units and vehicles. Even if you remove the alive condition from the if statement, but the time the event handler is even called the unit is not alive, and so can't be set to incapacitated/unconscious/etc. Edited May 21, 2017 by caddrel Solution found Share this post Link to post Share on other sites
caddrel 10 Posted May 21, 2017 After further tinkering, have found a solution. Not sure how elegant it is, but it works. If a player is in a vehicle and receives lethal damage (>1), they are forced out of the vehicle. This has been combined with the previous script, that reduces all damage to 0 if a player is incapped. So far in the test environment, dropping a bomb on a vehicle with a player in it leaves the player incapacitated next to the burning wreck. Will do further testing to see if there are unintended consequences. Thanks to r3vo for the potential other answer; unfortunately I'm completely unfamiliar with the animation system/states in Arma 3! //initPlayerLocal.sqf params[ "_unit" ]; //Waituntil REVIVE handleDamage EH has been applied waitUntil{ !isNil { _unit getVariable "bis_revive_ehHandleDamage" } }; //Remove REVIVE HandleDamage EH _unit removeEventHandler[ "HandleDamage", _unit getVariable "bis_revive_ehHandleDamage" ]; //Only damage from last applied handleDamage EH is taken into consideration by the engine //Apply a new EH so as we can override the damage applied _unit addEventHandler [ "HandleDamage", { private[ "_damage","_newDamage" ]; params [ "_unit" ]; //If we are not incapacitated if ( lifeState _unit != "INCAPACITATED" ) then { //Get revives handle damage _newDamage = _this call bis_fnc_reviveEhHandleDamage; } else { //if we are incapacitated _newDamage = 0; }; //if damage is enough to kill the player and they're in a vehicle, force them out of the vehicle. if (((_newDamage + (getDammage _unit)) >= 1) && (vehicle player != player)) then { moveOut _unit; //Recalculate damage now player is out of the vehicle. _newDamage = _this call bis_fnc_reviveEhHandleDamage; }; _newDamage }]; Share this post Link to post Share on other sites
caddrel 10 Posted May 21, 2017 So the above script appears to work, however on testing it runs into issues when "reduced damage" is enabled in the difficulty options. The reduced damage seems to make it eject the player from the vehicle before they take lethal damage (in some fringe cases.) If I can find some way to replicate MAX_SAFE_DAMAGE from the BIS Revive functions this can be fixed. Or I can write the code manually, but I'd need to find out how much the game is reducing the damage to the players by. Anyone know the answer to either of these? Share this post Link to post Share on other sites
fn_Quiksilver 1636 Posted May 21, 2017 I eject the driver allowdamage false isnull objectparent player driver vehicle player moveout player setunconscious looks like this sorta for max safe damage i use 0.89 you can use the min command to good effect here. (damage min 0.89) Share this post Link to post Share on other sites
Jnr4817 215 Posted May 21, 2017 2 hours ago, fn_Quiksilver said: I eject the driver allowdamage false isnull objectparent player driver vehicle player moveout player setunconscious looks like this sorta for max safe damage i use 0.89 you can use the min command to good effect here. (damage min 0.89) If you would be so kind as to share the script you are using for this, i would greatly appreciate it? Reed Share this post Link to post Share on other sites
caddrel 10 Posted May 21, 2017 Originally I was under the impression the damage handler applied additional damage to the unit. However, from what I can tell it only applies total damage. So if the unit is already injured in the hand (0.15) and the hand is hit for an extra (0.5) the amount of damage the handler will apply will be 0.65. This makes everything significantly easier; there's no need to check the health of the unit; the damage in the damage handler will only ever be total amount. We can use the same safe damage value used by BIS Revive (0.95). Have done some testing; the script below should work. Used with the BIS Revive basic damage system, a player can only ever be incapacitated. If they take enough damage in a vehicle to be incapacitated, they are ejected from the vehicle and lay incapacitated on the ground. //initPlayerLocal.sqf params[ "_unit" ]; //Waituntil REVIVE handleDamage EH has been applied waitUntil{ !isNil { _unit getVariable "bis_revive_ehHandleDamage" } }; //Remove REVIVE HandleDamage EH _unit removeEventHandler[ "HandleDamage", _unit getVariable "bis_revive_ehHandleDamage" ]; //Only damage from last applied handleDamage EH is taken into consideration by the engine //Apply a new EH so as we can override the damage applied _unit addEventHandler [ "HandleDamage", { private[ "_damage","_newDamage" ]; params [ "_unit" ]; //If we are not incapacitated if ( lifeState _unit != "INCAPACITATED" ) then { //Get revives handle damage _newDamage = _this call bis_fnc_reviveEhHandleDamage; } else { //if we are incapacitated _newDamage = 0; }; //if damage is enough to kill the player and they're in a vehicle, force them out of the vehicle. if ((_newDamage > 0.95) && (vehicle player != player)) then { moveOut _unit; //Call the BIS revive function again; if the player is in a vehicle it sometimes returns 100 damage. _newDamage = _this call bis_fnc_reviveEhHandleDamage; }; _newDamage }]; Another interesting discovery is the damage handler is now called fifteen times for every bullet or source of damage; once for each hitpoint area of the unit. This is the log for a single bullet hitting the test unit. 0:19:38 "Damage applied to HitHead of testguy is 0" 0:19:38 "Damage applied to of testguy is 0.0865005" 0:19:38 "Damage applied to of testguy is 0.0865005" 0:19:38 "Damage applied to HitFace of testguy is 0" 0:19:38 "Damage applied to HitNeck of testguy is 0" 0:19:38 "Damage applied to HitHead of testguy is 0" 0:19:38 "Damage applied to HitPelvis of testguy is 100" 0:19:38 "Moving testguy out of B Alpha 1-1:1 (Caddrel) (testguy)" 0:19:38 "RECALCULATED damage applied to HitPelvis of testguy is 0.95" 0:19:38 "Damage applied to HitAbdomen of testguy is 0.95" 0:19:38 "Damage applied to HitDiaphragm of testguy is 0" 0:19:38 "Damage applied to HitChest of testguy is 0" 0:19:38 "Damage applied to HitBody of testguy is 0" 0:19:38 "Damage applied to HitArms of testguy is 0" 0:19:38 "Damage applied to HitHands of testguy is 0" 0:19:38 "Damage applied to HitLegs of testguy is 0" 0:19:38 "Damage applied to Incapacitated of testguy is 7.83344e-005" Share this post Link to post Share on other sites
fn_Quiksilver 1636 Posted May 22, 2017 15 hours ago, Jnr4817 said: If you would be so kind as to share the script you are using for this, i would greatly appreciate it? Reed I don't mind guiding but I think you'd get more out of it to design such a system yourself :) you've already made good progress in testing the critical hit parts for a player ingame are ["head","body",""] <--- third is general damage if any of those get above some number (maybe 0.9) it is lethal and the player will die. you can test this yourself <unit> setHit ['head',0.95]; <unit> setHit ['body',1]; <unit> setHit ['legs',1]; <unit> setHit ['arms',1]; more info in "getAllHitPointsDamage" command Share this post Link to post Share on other sites
Jnr4817 215 Posted May 22, 2017 2 hours ago, fn_Quiksilver said: I don't mind guiding but I think you'd get more out of it to design such a system yourself :) you've already made good progress in testing the critical hit parts for a player ingame are ["head","body",""] <--- third is general damage if any of those get above some number (maybe 0.9) it is lethal and the player will die. you can test this yourself <unit> setHit ['head',0.95]; <unit> setHit ['body',1]; <unit> setHit ['legs',1]; <unit> setHit ['arms',1]; more info in "getAllHitPointsDamage" command Thank you Share this post Link to post Share on other sites
Midnighters 152 Posted May 22, 2017 @fn_Quiksilver wheeee! Share this post Link to post Share on other sites