Jump to content
caddrel

Request: BIS Revive - Workaround for no incapacitated state in vehicles

Recommended Posts

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 by caddrel
Extra sentence

Share this post


Link to post
Share on other sites

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 by caddrel
Solution found

Share this post


Link to post
Share on other sites


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

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

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
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

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
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
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

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×