Page MenuHomeFeedback Tracker

After Headshot - PlayerBase always reports true for IsDamageDestroyed even if health is restored server side.
New, NormalPublic

Description

If an entity, specifically a PlayerBase or Man is shot at but in the EEHit method you restore the entities health from the TotalDamageResult to each health zone, the player stays alive and receives no damage. Once you headshot the player, even if you restore the brain health the object always returns true for IsDamageDestroyed() - It seems that once a fatal wound is received the entity is marked as damage destroyed but it no longer honors health system values.

I imagine this is the intended functionality but it does not work out if you are trying to make unkillable NPCs or safezone type mods.

After restoring the entity health even after a fatal injury the player visually is alive and can still interact in the world. However since IsDamageDestroyed is always true now, IsAlive is false and this causes issues like being able to loot the player, player character data destroyed if the player logs out or server restarts.

In addition, the SetAllowDamage() in Object class does not appear to have any effect.

Maybe I am approaching this wrong, and if so maybe you can advise on a better way to keep a player/npc alive in game even if hit.

See steps to reproduce for some code you can try out to see what I mean

Details

Severity
None
Resolution
Open
Reproducibility
Always
Operating System
Windows 10 x64
Category
Engine
Steps To Reproduce
  1. Modify PlayerBase with the code below
  2. In game, spawn a PlayerBase object
  3. In game, shoot the target in the body - he stays alive and IsDamageDestroyed() is false (good)
  4. Head shot the object and get a fatal injury on them
  5. EEKilled is called but even if we override, from this point on IsDamageDestroyed() is always true even if health is restored
  6. Player is still able to interact and is not in fact dead but IsAlive is false.
modded class PlayerBase
{
	bool m_ConditionIsMet = true;

	override void EEKilled( Object killer )
	{
		Print( string.Format( "EEKilled - Killer: %1 Is Alive: %2 Is Damage Destroyed: %3", killer.GetType(), IsAlive(), IsDamageDestroyed() )  );
		
		if ( m_ConditionIsMet )
		{
			return;
		}

		super.EEKilled( killer );
	}

	override void EEHitBy( TotalDamageResult damageResult, int damageType, EntityAI source, int component, string dmgZone, string ammo, vector modelPos )
	{
		Print( string.Format( "EEHitBy - Source: %1 Zone: %2 Is Alive: %3 Is Damage Destroyed: %4", source.GetType(), dmgZone, IsAlive(), IsDamageDestroyed() )  );

		if ( m_ConditionIsMet )
		{
			RestoreFromTotalDamageResult( damageResult );
			return;
		}

		super.EEHitBy( damageResult, damageType, source, component, dmgZone, ammo, modelPos );
	}

	void RestoreFromTotalDamageResult( notnull TotalDamageResult damageResult )
	{
		ref array<string> zones = new array<string>;

		GetDamageZones( zones );
		
		AddHealth( "GlobalHealth", "Health", damageResult.GetDamage( "GlobalHealth", "Health" ) );

		if ( IsMan() )
		{
			if ( GetMaxHealth( "GlobalHealth", "Blood" ) > 0 )
			{
				AddHealth( "GlobalHealth", "Blood", damageResult.GetDamage( "GlobalHealth", "Blood" ) );
			}

			if ( GetMaxHealth( "GlobalHealth", "Shock" ) > 0 )
			{
				AddHealth( "GlobalHealth", "Shock", damageResult.GetDamage( "GlobalHealth", "Shock" ) );
			}
		}
		
		foreach ( string zone : zones )
		{
			AddHealth( zone, "Health", damageResult.GetDamage( zone, "Health" ) );
			
			if ( IsMan() )
			{
				if ( GetMaxHealth( zone, "Blood" ) > 0 )
				{
					AddHealth( zone, "Blood", damageResult.GetDamage( zone, "Blood" ) );
				}

				if ( GetMaxHealth( zone, "Shock" ) > 0 )
				{
					AddHealth( zone, "Shock", damageResult.GetDamage( zone, "Shock" ) );
				}
			}
		}
	}
}

Event Timeline

ghassani created this task.Feb 7 2019, 8:10 PM
Borland_vit added a subscriber: Borland_vit.EditedFeb 15 2019, 7:40 AM

I have the same issue =(
Very interesting to solve it...

I have found a solve of this problem:
IsDamageDestroyed() returns value from engine, but you can use method
SetCanBeDestroyed( false ) for your object, and it will not be destroyed untill you send SetCanBeDestroyed( true) to engine.

I saw this option added in 1.1. I will play with it tonight and see if it fixes my use case and report back. Thanks

Yup, works great. Thank you very much kind sir

Borland_vit added a comment.EditedFeb 19 2019, 7:49 AM

You're welcome! I myself have spent a lot of time to solve this))