State
Since 1.7 there are reports that ACE Medical's second chance feature can cause characters to end up with 0 resilience health without becoming unconscious. ACE uses HitZone::SetHealthScaled to set the health of resilience to 0 when second chance gets triggered. I managed to trace back the issue to a conflict between HitZone::SetHealthScaled and damage handling, which leads the character to end up in the wrong damage state.
Steps to reproduce:
Open Workbench with no mods
Put the code below in a script file and compile it (It will apply damage to the head, use SetHealthScaled(0.0) on resilience when the damage state of the head changes and log resilience health and state in ShouldBeUnconscious)
//-----------------------------------------------------------------------------------------------------------
modded class SCR_CharacterHeadHitZone
{
//-----------------------------------------------------------------------------------------------------------
//! Set resilience to zero when head hit zone changes state
override protected void OnDamageStateChanged(EDamageState newState, EDamageState previousDamageState, bool isJIP)
{
super.OnDamageStateChanged(newState, previousDamageState, isJIP);
SCR_CharacterDamageManagerComponent damageManager = SCR_CharacterDamageManagerComponent.Cast(GetHitZoneContainer());
if (damageManager)
damageManager.GetResilienceHitZone().SetHealthScaled(0.0);
}
}
//-----------------------------------------------------------------------------------------------------------
modded class SCR_CharacterResilienceHitZone
{
//-----------------------------------------------------------------------------------------------------------
//! Turn off resilience regen to keep the broken state
override float CalculatePassiveRegenDPS(bool considerRegenScale = true)
{
return 0;
}
}
//-----------------------------------------------------------------------------------------------------------
modded class SCR_PlayerController
{
//-----------------------------------------------------------------------------------------------------------
//! Apply damage to head when taking control of a character
override protected void OnControlledEntityChanged(IEntity from, IEntity to)
{
super.OnControlledEntityChanged(from, to);
SCR_ChimeraCharacter char = SCR_ChimeraCharacter.Cast(to);
if (!char)
return;
SCR_CharacterDamageManagerComponent damageManager = SCR_CharacterDamageManagerComponent.Cast(char.GetDamageManager());
if (!damageManager)
return;
vector hitPosDirNorm[3];
SCR_DamageContext damageContext = new SCR_DamageContext(
EDamageType.TRUE,
1.0,
hitPosDirNorm,
char,
damageManager.GetHitZoneByName("Head"),
damageManager.GetInstigator(),
null,
16,
83
);
damageManager.HandleDamage(damageContext);
}
}
//-----------------------------------------------------------------------------------------------------------
modded class SCR_CharacterDamageManagerComponent
{
//-----------------------------------------------------------------------------------------------------------
//! Log resilience state and health when checking consciousness
override bool ShouldBeUnconscious()
{
HitZone resilienceHZ = GetResilienceHitZone();
PrintFormat("|ResilienceDamageState=%1|ResilienceHealth=%2|", SCR_Enum.GetEnumName(ECharacterResilienceState, resilienceHZ.GetDamageState()), resilienceHZ.GetHealth());
return super.ShouldBeUnconscious();
}
}Run MpTest.ent and check console output:
SCRIPT : |ResilienceDamageState=DESTROYED|ResilienceHealth=0|
SCRIPT : |ResilienceDamageState=INTERMEDIARY|ResilienceHealth=0|Indicating that initially we got the correct state (DESTROYED), but then transition to an incorrect one (INTERMEDIARY)
Activity
You are not signed in. Please sign in to see more details and to reply.
State