Jump to content
🛡️FORUMS ARE IN READ-ONLY MODE Read more... ×
iSassafras

[Solved] Locality Problems with HandleDamage

Recommended Posts

Hi guys!

 

I started scripting a few months ago (what else to do in quarantine, right?), so I'm still quite new at this. I already understand a lot of Arma stuff, been scripting quite a bit, but I can't really get the hang of locality. I hope you can help me!

 

Recently, I started using Grimes' Simple Revive Script for my mission. This script basically uses a HandleDamage Event Handler to set a unit unconscious and makes it invulnerable once it reached fatal damage. Other players and AI will then be able to approach the unit and either help or kill it via action menu. I changed some of the scripted AI behaviour and now I started messing with the Event Handler itself because I didn't really like the way you had to deal with every single AI unit once you shot them.

My goal is to make it impossible for players to die by any source except when their bleed out time is exceeded. They should always drop unconscious first after which they can decide to respawn or to wait for help.

In contrast, I want AI to drop unconscious by the first shot that would've been fatal (excluding headshots) and then be killable by any further damage.

 

I came up with some lines of code that, in theory, do exactly what I want. The Event Handler gets added to every player by onPlayerRespawn. I attach a variable to the player to make sure they will only get the Event Handler the first time they respawn. As far as I know, onPlayerRespawn is executed locally, so this means that the Event Handler should be running on the player's machine, right?
Anyway, this is the code that my "HandleDamage" Event Handler is executing:
 

params ["_unit", "_selection", "_damage", "_source", "_projectile", "_hitIndex", "_instigator", "_hitPoint"];

		if (_selection in ["arms", "hands", "legs"]) then // Make units sustain more damage to their extremities
		{
			private _oldExtremities = _unit getHit _selection;
			private _newExtremities = _damage - _oldExtremities;
			_damage = ((_newExtremities * 0.3) + _oldExtremities);
		};

		if ((_damage >= 1) or (damage _unit >= 1)) then // Unit received fatal damage, determine what to do next 
		{
			if (isPlayer _unit) then // In case of player, limit the damage so he/she doesn't die.
			{
				_damage = 0.9;
				_unit setDamage 0.9;
				_unit allowDamage false;
			};

			// If the unit hasn't been unconscious already, make it unconscious.
			// Exception: The unit is NOT a player and received fatal damage to it's head or face. In this case, the unit should die right away.
			if (!(_unit getVariable ["G_Incapacitated",false]) and ((isPlayer _unit) or (!(isPlayer _unit) and (_selection != "head") and (_selection != "face_hub")))) then
			{
				_damage = 0.9;
				_unit setDamage 0.9;
				if (isPlayer _unit) then {_unit allowDamage false};

				[_unit,_instigator] spawn G_fnc_enterIncapacitatedState;
				[_unit, side _unit, _instigator] spawn G_fnc_onKill; // Announces that a unit has been incapacitated
			};
		}
		else
		{ // Damage wasn't fatal, so check how much the unit is damaged. If damage reached the threshold, make the unit heal itself or make medics help them.
			if ((local _unit) and (damage _unit >= 0.4) and (damage _unit < 0.9) and !(_unit getVariable ["OS_healingActive",false])) then {[_unit] spawn _startHealing};
		};


		// Helper for debugging, to track where and how damage was received:
		// [format ["OS_Debug: %1, dmg %2/%3: %4 | overall dmg: %5",name _unit, _selection, _hitPoint, _damage toFixed 2, damage _unit toFixed 2]] remoteExec ["systemChat", _unit, false];
		
		_damage

It may be worth noting that G_fnc_enterIncapacitatedState does a isDamageAllowed check within it's first lines. If it returns 'true' and the unit is a player, it will set allowDamage to 'false'.

Now, this seems to be working perfectly every time I host the mission out of the Eden Editor for testing. I ran over mines and grenades, used Zeus to drop lightning, bombs, rockets and what not on my poor character. I will always drop unconscious and won't die.
However, when I upload the mission to my dedicaded server for testing with a friend, it doesn't work as inteded anymore. It seems I still can't kill myself with anything the Zeus menu has to offer, but my friend or enemy AI units still can, under some circumstances. For instance, I will just die right away without even entering the scripted incapacitated state when being shot by a .50 cal or if he drops Zeus lightning on me. On the other hand, if he is shooting me "carefully" with a handgun or a M4, I will drop unconscious and be invulnerable as intended.
So this left me with the thought that the EH doesn't execute properly when a unit receives damage from a source which is not local to the unit's machine. I just don't understand it because the wiki says that "HandleDamage" gets executed globally.

What am I missing? Any advice? 😞

Share this post


Link to post
Share on other sites

First of all I'd add the event handler in the  initPlayerLocal.sqf. (you don't need a extra variable to check whether the unit allready respawned or not)

 

To your question: Maybe you made a mistake in some function? 

Is the incapacitated state local or global?

 

It`s really hard to tell without all the mission files.

  • Thanks 1

Share this post


Link to post
Share on other sites

Hey man, thanks for the reply!

You're right, adding the Event Handler in initPlayerLocal is definitely the more elegant way to do it. I don't know why I didn't come up with it myself, haha. Thanks for the tip!

Anyways, I was actually able to solve my problem. It seems it wasn't a locality problem at all, I was just messing with the damage values to much or in a wrong order.
In case you're interested, this is my new code:

params ["_unit", "_selection", "_damage", "_source", "_projectile", "_hitIndex", "_instigator", "_hitPoint"];

if ((_damage >= 1) or (damage _unit >= 1)) then // Unit received fatal damage, determine what to do next 
{
	if ((isPlayer _unit) and (_unit getVariable ["G_Incapacitated",false])) then // In case of already incapacitated player, limit the damage so he/she doesn't die.
	{
		_damage = 0.9;
		_unit setDamage 0.9;
	};

	// If the unit hasn't been unconscious already, make it unconscious.
	// Exception: The unit is NOT a player and received fatal damage to it's head or face. In this case, the unit should die right away.
	if ((local _unit) and !(_unit getVariable ["G_Incapacitated",false]) and ((isPlayer _unit) or (!(isPlayer _unit) and (_selection != "head") and (_selection != "face_hub")))) then
	{
		_damage = 0.9;
		_unit setDamage 0.9;

		[_unit,_instigator] spawn G_fnc_enterIncapacitatedState; // Make unit incapacitated. This will trigger near AI to help.
		[_unit, side _unit, _instigator] spawn G_fnc_onKill; // Announces that a unit has been incapacitated
	};
}
else
{
	if (_selection in ["arms", "hands", "legs"]) then // Make units sustain more damage to their extremities
	{
		private _oldExtremities = _unit getHit _selection;
		private _newExtremities = _damage - _oldExtremities;
		_damage = ((_newExtremities * 0.3) + _oldExtremities);
	};			
	
	// Damage wasn't fatal, so check how much the unit is damaged in general. If damage reached the threshold, make the unit heal itself (AI only) or make medics help them.
	if ((local _unit) and (damage _unit >= 0.4) and (damage _unit < 0.9) and !(_unit getVariable ["OS_healingActive",false])) then {[_unit] spawn _startHealing};
};

// Helper for debugging, to track where and how damage was received:
// [format ["OS_Debug: %1, dmg %2/%3: %4 | overall dmg: %5",name _unit, _selection, _hitPoint, _damage toFixed 2, damage _unit toFixed 2]] remoteExec ["systemChat", _unit, false];

_damage

 

  • Like 1

Share this post


Link to post
Share on other sites

×