diff --git a/AUTHORS b/AUTHORS index 1db6ed1c..c71fe135 100644 --- a/AUTHORS +++ b/AUTHORS @@ -17,3 +17,4 @@ Jonpas LorenLuke OverlordZorn Zelik +FailNot diff --git a/addons/backblast/Scripts/Game/ACE_Backblast/ACE_BackblastComponent.c b/addons/backblast/Scripts/Game/ACE_Backblast/ACE_BackblastComponent.c index 84e7d2f5..95a7c94b 100644 --- a/addons/backblast/Scripts/Game/ACE_Backblast/ACE_BackblastComponent.c +++ b/addons/backblast/Scripts/Game/ACE_Backblast/ACE_BackblastComponent.c @@ -81,7 +81,7 @@ class ACE_BackblastComponent : ScriptComponent foreach (SCR_ChimeraCharacter character : affectedEntities) { - SCR_DamageManagerComponent damageManager = character.GetDamageManager(); + SCR_CharacterDamageManagerComponent damageManager = SCR_CharacterDamageManagerComponent.Cast(character.GetDamageManager()); if (!damageManager) continue; @@ -119,8 +119,8 @@ class ACE_BackblastComponent : ScriptComponent if (!charHitZone) continue; - charHitZone.AddBleeding(nodes[0]); - }; + damageManager.AddBleedingEffectOnHitZone(charHitZone, nodes[0]); + } } if (m_bDebugModeEnabled) diff --git a/addons/medical/Prefabs/Items/Medicine/EpinephrineInjection/ACE_Medical_EpinephrineInjection.et b/addons/medical/Prefabs/Items/Medicine/EpinephrineInjection/ACE_Medical_EpinephrineInjection.et index 391153b4..3a94e69a 100755 --- a/addons/medical/Prefabs/Items/Medicine/EpinephrineInjection/ACE_Medical_EpinephrineInjection.et +++ b/addons/medical/Prefabs/Items/Medicine/EpinephrineInjection/ACE_Medical_EpinephrineInjection.et @@ -33,6 +33,12 @@ GenericEntity : "{3238FC0BDB67AA78}Prefabs/Items/Medicine/MorphineInjection_01/M } SCR_ConsumableItemComponent "{59E68C74C5CEE74F}" { m_ConsumableEffect ACE_Medical_ConsumableEpinephrine "{59E68C74C1F3910E}" { + m_fItemRegenerationSpeed 5 + m_fItemRegenerationDuration 30 + m_aDamageEffectsToLoad { + ACE_Medical_EpinephrineDamageEffect "{6122D60861B541E7}" { + } + } m_fItemRegenerationSpeedDPS 5 m_fItemRegenerationDurationS 30 } diff --git a/addons/medical/Prefabs/Items/Medicine/MorphineInjection_01/MorphineInjection_01.et b/addons/medical/Prefabs/Items/Medicine/MorphineInjection_01/MorphineInjection_01.et index 6bee70a2..28867706 100755 --- a/addons/medical/Prefabs/Items/Medicine/MorphineInjection_01/MorphineInjection_01.et +++ b/addons/medical/Prefabs/Items/Medicine/MorphineInjection_01/MorphineInjection_01.et @@ -15,6 +15,12 @@ GenericEntity : "{3238FC0BDB67AA78}Prefabs/Items/Medicine/MorphineInjection_01/M } SCR_ConsumableItemComponent "{59E68C74C5CEE74F}" { m_ConsumableEffect ACE_Medical_ConsumableMorphine "{59E68C74C1F3910E}" { + m_fItemRegenerationSpeed 5 + m_fItemRegenerationDuration 60 + m_aDamageEffectsToLoad { + ACE_Medical_MorphineDamageEffect "{6122D60861B541E7}" { + } + } m_fItemRegenerationSpeedDPS 5 m_fItemRegenerationDurationS 60 } diff --git a/addons/medical/scripts/Game/ACE_Medical/Character/SCR_CharacterControllerComponent.c b/addons/medical/scripts/Game/ACE_Medical/Character/SCR_CharacterControllerComponent.c deleted file mode 100644 index 93dcc098..00000000 --- a/addons/medical/scripts/Game/ACE_Medical/Character/SCR_CharacterControllerComponent.c +++ /dev/null @@ -1,58 +0,0 @@ -//------------------------------------------------------------------------------------------------ -//! Introduce a second chance, which gets triggered when the character would have died without -//! falling unconscious. -modded class SCR_CharacterControllerComponent : CharacterControllerComponent -{ - protected SCR_CharacterDamageManagerComponent m_pACE_Medical_DamageManager; - protected const float ACE_MEDICAL_SECOND_CHANCE_DEACTIVATION_TIMEOUT_MS = 1000; - - //------------------------------------------------------------------------------------------------ - //! Initialize member variables - override void OnInit(IEntity owner) - { - super.OnInit(owner); - m_pACE_Medical_DamageManager = SCR_CharacterDamageManagerComponent.Cast(owner.FindComponent(SCR_CharacterDamageManagerComponent)); - } - - //------------------------------------------------------------------------------------------------ - //! Add/remove second chance when life state changes - override void OnLifeStateChanged(ECharacterLifeState previousLifeState, ECharacterLifeState newLifeState) - { - super.OnLifeStateChanged(previousLifeState, newLifeState); - - // Only run if ACE Medical has been initialized for this character - if (!m_pACE_Medical_DamageManager.ACE_Medical_IsInitialized()) - return; - - // OnLifeStateChanged sometimes gets triggered without a change in state - if (previousLifeState == newLifeState) - return; - - switch (newLifeState) - { - // Add second chance when revived - case ECharacterLifeState.ALIVE: - { - GetGame().GetCallqueue().Remove(m_pACE_Medical_DamageManager.ACE_Medical_EnableSecondChance); - m_pACE_Medical_DamageManager.ACE_Medical_EnableSecondChance(true); - m_pACE_Medical_DamageManager.ACE_Medical_SetSecondChanceTrigged(false); - break; - } - - // Schedule removal of second chance when falling unconscious - case ECharacterLifeState.INCAPACITATED: - { - GetGame().GetCallqueue().CallLater(m_pACE_Medical_DamageManager.ACE_Medical_EnableSecondChance, ACE_MEDICAL_SECOND_CHANCE_DEACTIVATION_TIMEOUT_MS, false, false); - break; - } - - // Remove second chance when dead - case ECharacterLifeState.DEAD: - { - GetGame().GetCallqueue().Remove(m_pACE_Medical_DamageManager.ACE_Medical_EnableSecondChance); - m_pACE_Medical_DamageManager.ACE_Medical_EnableSecondChance(false); - break; - } - } - } -} diff --git a/addons/medical/scripts/Game/ACE_Medical/Components/Damage/SCR_CharacterDamageManagerComponent.c b/addons/medical/scripts/Game/ACE_Medical/Components/Damage/ACE_Medical_SCR_CharacterDamageManagerComponent.c similarity index 77% rename from addons/medical/scripts/Game/ACE_Medical/Components/Damage/SCR_CharacterDamageManagerComponent.c rename to addons/medical/scripts/Game/ACE_Medical/Components/Damage/ACE_Medical_SCR_CharacterDamageManagerComponent.c index 5a4c3954..8536fe99 100644 --- a/addons/medical/scripts/Game/ACE_Medical/Components/Damage/SCR_CharacterDamageManagerComponent.c +++ b/addons/medical/scripts/Game/ACE_Medical/Components/Damage/ACE_Medical_SCR_CharacterDamageManagerComponent.c @@ -2,78 +2,74 @@ //! Introduce a second chance, which gets triggered when the character would have died without //! falling unconscious. //! Add methods for interacting with pain hit zone. -modded class SCR_CharacterDamageManagerComponent : SCR_DamageManagerComponent +modded class SCR_CharacterDamageManagerComponent { - [RplProp(), Attribute(defvalue: "0", desc: "Resilience regeneration scale when second chance was triggered. The default regeneration rate will be multiplied by this factor.", category: "ACE Medical")] - protected float m_fACE_Medical_SecondChanceRegenScale; + private static const float ACE_MEDICAL_SECOND_CHANCE_DEACTIVATION_TIMEOUT_MS = 1000; protected HitZone m_pACE_Medical_HealthHitZone; protected float m_fACE_Medical_CriticalHealth; - protected ref array m_aACE_Medical_PhysicalHitZones = {}; protected ACE_Medical_PainHitZone m_pACE_Medical_PainHitZone; protected float m_fACE_Medical_ModeratePainThreshold; protected float m_fACE_Medical_SeriousPainThreshold; - + // We only notify the replication system about changes of these members on initialization // After init, each proxy is itself responsible for updating these members // Having them as RplProp also ensures that JIPs receive the current state from the server [RplProp()] protected bool m_bACE_Medical_Initialized = false; [RplProp()] + protected float m_fACE_Medical_SecondChanceRegenScale; + [RplProp()] protected bool m_bACE_Medical_HasSecondChance = false; [RplProp()] protected bool m_bACE_Medical_SecondChanceOnHeadEnabled = false; [RplProp()] protected bool m_bACE_Medical_SecondChanceTriggered = false; - + + //----------------------------------------------------------------------------------------------------------- //! Initialize member variables override void OnInit(IEntity owner) { super.OnInit(owner); - + m_pACE_Medical_HealthHitZone = GetHitZoneByName("Health"); if (!m_pACE_Medical_HealthHitZone) return; - + m_fACE_Medical_CriticalHealth = m_pACE_Medical_HealthHitZone.GetDamageStateThreshold(ECharacterHealthState.CRITICAL); - GetPhysicalHitZones(m_aACE_Medical_PhysicalHitZones); } - + //----------------------------------------------------------------------------------------------------------- //! Initialize ACE medical on a character damage manager (Called on the server) void ACE_Medical_Initialize() { if (m_bACE_Medical_Initialized) return; - - ACE_Medical_Settings settings = ACE_SettingsHelperT.GetModSettings(); + + const ACE_Medical_Settings settings = ACE_SettingsHelperT.GetModSettings(); if (settings) { m_bACE_Medical_SecondChanceOnHeadEnabled = settings.m_bSecondChanceOnHeadEnabled; m_fACE_Medical_SecondChanceRegenScale = settings.m_fSecondChanceRegenScale; } - + ACE_Medical_EnableSecondChance(true); // Damage calculations are done on all machines, so we have to broadcast the init m_bACE_Medical_Initialized = true; Replication.BumpMe(); } - + //------------------------------------------------------------------------------------------------ // Reduce regeneration rate when second chance was triggered override float GetResilienceRegenScale() { - float scale = super.GetResilienceRegenScale(); + const float scale = super.GetResilienceRegenScale(); if (m_bACE_Medical_SecondChanceTriggered && scale > 0) - { return m_fACE_Medical_SecondChanceRegenScale; - } else - { return scale; - } } //------------------------------------------------------------------------------------------------ @@ -87,12 +83,15 @@ modded class SCR_CharacterDamageManagerComponent : SCR_DamageManagerComponent //! Returns true if at least one physical hit zone is injured bool ACE_Medical_CanBeHealed() { - foreach (HitZone hitZone : m_aACE_Medical_PhysicalHitZones) + array physicalHitZones = {}; + GetPhysicalHitZones(physicalHitZones); + + foreach (HitZone hitZone : physicalHitZones) { if (hitZone.GetHealthScaled() < 0.999) return true; } - + return false; } @@ -111,21 +110,21 @@ modded class SCR_CharacterDamageManagerComponent : SCR_DamageManagerComponent { return m_pACE_Medical_PainHitZone; } - + //----------------------------------------------------------------------------------------------------------- //! Returns true if pain hit zone is at least moderately damaged bool ACE_Medical_IsInPain() { return m_pACE_Medical_PainHitZone.GetHealthScaled() <= m_fACE_Medical_ModeratePainThreshold; } - + //----------------------------------------------------------------------------------------------------------- //! Returns intensity of pain used for ACE_Medical_PainScreenEffect float ACE_Medical_GetPainIntensity() { // Clamp between serious damage and full health - float scaledHealth = Math.Clamp(m_pACE_Medical_PainHitZone.GetHealthScaled(), m_fACE_Medical_SeriousPainThreshold, 1); - + const float scaledHealth = Math.Clamp(m_pACE_Medical_PainHitZone.GetHealthScaled(), m_fACE_Medical_SeriousPainThreshold, 1); + if (scaledHealth > m_fACE_Medical_ModeratePainThreshold) { // No effect when less than moderate damage @@ -137,13 +136,6 @@ modded class SCR_CharacterDamageManagerComponent : SCR_DamageManagerComponent return Math.InverseLerp(1, m_fACE_Medical_SeriousPainThreshold, scaledHealth); } } - - //------------------------------------------------------------------------------------------------ - //! Returns true if ACE Medical has been initialized - bool ACE_Medical_IsInitialized() - { - return m_bACE_Medical_Initialized; - } //------------------------------------------------------------------------------------------------ //! Enable/disable second chance @@ -151,38 +143,81 @@ modded class SCR_CharacterDamageManagerComponent : SCR_DamageManagerComponent { m_bACE_Medical_HasSecondChance = enable; } - + //------------------------------------------------------------------------------------------------ //! Check if second chance is enabled bool ACE_Medical_HasSecondChance() { return m_bACE_Medical_HasSecondChance; } - + //----------------------------------------------------------------------------------------------------------- //! Returns true if second chance is enabled for the given hit zone bool ACE_Medical_HasSecondChanceOnHitZone(HitZone hitZone) { if (!m_bACE_Medical_HasSecondChance) return false; - + if (m_bACE_Medical_SecondChanceOnHeadEnabled) return true; - + return (hitZone != m_pHeadHitZone); } - + //------------------------------------------------------------------------------------------------ //! To be set true when second chance was used void ACE_Medical_SetSecondChanceTrigged(bool isTriggered) { m_bACE_Medical_SecondChanceTriggered = isTriggered; } - + //------------------------------------------------------------------------------------------------ //! Check if second chance was used bool ACE_Medical_WasSecondChanceTrigged() { return m_bACE_Medical_SecondChanceTriggered; } + + //------------------------------------------------------------------------------------------------ + override void OnLifeStateChanged(ECharacterLifeState previousLifeState, ECharacterLifeState newLifeState) + { + super.OnLifeStateChanged(previousLifeState, newLifeState); + + if (previousLifeState == newLifeState) + return; + + switch (newLifeState) + { + // Add second chance when revived + case ECharacterLifeState.ALIVE: + { + GetGame().GetCallqueue().Remove(ACE_Medical_EnableSecondChance); + ACE_Medical_EnableSecondChance(true); + ACE_Medical_SetSecondChanceTrigged(false); + break; + } + + // Schedule removal of second chance when falling unconscious + case ECharacterLifeState.INCAPACITATED: + { + GetGame().GetCallqueue().Remove(ACE_Medical_EnableSecondChance); + GetGame().GetCallqueue().CallLater(ACE_Medical_EnableSecondChance, ACE_MEDICAL_SECOND_CHANCE_DEACTIVATION_TIMEOUT_MS, false, false); + break; + } + + // Remove second chance when dead + case ECharacterLifeState.DEAD: + { + GetGame().GetCallqueue().Remove(ACE_Medical_EnableSecondChance); + ACE_Medical_EnableSecondChance(false); + break; + } + } + } + + //------------------------------------------------------------------------------------------------ + void ~SCR_CharacterDamageManagerComponent() + { + GetGame().GetCallqueue().Remove(ACE_Medical_EnableSecondChance); + } } diff --git a/addons/medical/scripts/Game/ACE_Medical/Components/Gadgets/SCR_ConsumableEffectBase.c b/addons/medical/scripts/Game/ACE_Medical/Components/Gadgets/ACE_Medical_ConsumableEffectBase.c old mode 100755 new mode 100644 similarity index 100% rename from addons/medical/scripts/Game/ACE_Medical/Components/Gadgets/SCR_ConsumableEffectBase.c rename to addons/medical/scripts/Game/ACE_Medical/Components/Gadgets/ACE_Medical_ConsumableEffectBase.c diff --git a/addons/medical/scripts/Game/ACE_Medical/Components/Gadgets/ACE_Medical_ConsumableEpinephrine.c b/addons/medical/scripts/Game/ACE_Medical/Components/Gadgets/ACE_Medical_ConsumableEpinephrine.c index ed13edc8..05ee301e 100755 --- a/addons/medical/scripts/Game/ACE_Medical/Components/Gadgets/ACE_Medical_ConsumableEpinephrine.c +++ b/addons/medical/scripts/Game/ACE_Medical/Components/Gadgets/ACE_Medical_ConsumableEpinephrine.c @@ -2,63 +2,44 @@ [BaseContainerProps()] class ACE_Medical_ConsumableEpinephrine : SCR_ConsumableEffectHealthItems { - [Attribute(defvalue: "20", desc: "Regeneration speed of related hitzone when consuming this item", category: "Regeneration")] - protected float m_fItemRegenerationSpeedDPS; - - [Attribute(defvalue: "10", desc: "Regeneration duration of related hitzone when consuming this item in seconds", category: "Regeneration")] - protected float m_fItemRegenerationDurationS; - - //------------------------------------------------------------------------------------------------ - //! Heal resilience hit zone - override void ApplyEffect(notnull IEntity target, notnull IEntity user, IEntity item, ItemUseParameters animParams) - { - super.ApplyEffect(target, user, item, animParams); - - ChimeraCharacter char = ChimeraCharacter.Cast(target); - if (!char) - return; - - SCR_CharacterDamageManagerComponent damageManager = SCR_CharacterDamageManagerComponent.Cast(char.GetDamageManager()); - if (!damageManager) - return; - - SCR_HitZone resilienceHZ = SCR_HitZone.Cast(damageManager.GetResilienceHitZone()); - if (!resilienceHZ) - return; - - resilienceHZ.CustomRegeneration(target, m_fItemRegenerationDurationS, m_fItemRegenerationSpeedDPS); - } - //------------------------------------------------------------------------------------------------ //! Can be applied when patient is unconscious and no epinephrine is in the system override bool CanApplyEffect(notnull IEntity target, notnull IEntity user, out SCR_EConsumableFailReason failReason) { - ChimeraCharacter char = ChimeraCharacter.Cast(target); + const ChimeraCharacter char = ChimeraCharacter.Cast(target); if (!char) return false; - SCR_CharacterDamageManagerComponent damageManager = SCR_CharacterDamageManagerComponent.Cast(char.GetDamageManager()); + SCR_CharacterControllerComponent charCtrl = SCR_CharacterControllerComponent.Cast(char.GetCharacterController()); + if (charCtrl.GetLifeState() != ECharacterLifeState.INCAPACITATED) + { + failReason = SCR_EConsumableFailReason.ACE_MEDICAL_NOT_INCAPACITATED; + return false; + } + + const SCR_CharacterDamageManagerComponent damageManager = SCR_CharacterDamageManagerComponent.Cast(char.GetDamageManager()); if (!damageManager) return false; - SCR_HitZone resilienceHZ = SCR_HitZone.Cast(damageManager.GetResilienceHitZone()); + const SCR_HitZone resilienceHZ = SCR_HitZone.Cast(damageManager.GetResilienceHitZone()); if (!resilienceHZ) return false; // Check if epinephrine is in the system already - if (resilienceHZ.GetDamageOverTime(EDamageType.HEALING) < 0) + array effects = damageManager.GetAllPersistentEffectsOfType(ACE_Medical_EpinephrineDamageEffect); + if (!effects.IsEmpty()) { failReason = SCR_EConsumableFailReason.ALREADY_APPLIED; return false; } - + // Cannot be applied while bleeding - if (damageManager.IsDamagedOverTime(EDamageType.BLEEDING)) + if (damageManager.IsBleeding()) { failReason = SCR_EConsumableFailReason.IS_BLEEDING; return false; } - + // Cannot be applied if critically injured // We also have to check if the character is still healable if (damageManager.ACE_Medical_HasCriticalHealth() && damageManager.ACE_Medical_CanBeHealed()) @@ -66,13 +47,8 @@ class ACE_Medical_ConsumableEpinephrine : SCR_ConsumableEffectHealthItems failReason = SCR_EConsumableFailReason.ACE_MEDICAL_TOO_DAMAGED; return false; } - - SCR_CharacterControllerComponent charCtrl = SCR_CharacterControllerComponent.Cast(char.GetCharacterController()); - if (charCtrl.GetLifeState() == ECharacterLifeState.INCAPACITATED) - return true; - failReason = SCR_EConsumableFailReason.ACE_MEDICAL_NOT_INCAPACITATED; - return false; + return true; } //------------------------------------------------------------------------------------------------ diff --git a/addons/medical/scripts/Game/ACE_Medical/Components/Gadgets/ACE_Medical_ConsumableMorphine.c b/addons/medical/scripts/Game/ACE_Medical/Components/Gadgets/ACE_Medical_ConsumableMorphine.c index bb3e1f7e..e49b3131 100755 --- a/addons/medical/scripts/Game/ACE_Medical/Components/Gadgets/ACE_Medical_ConsumableMorphine.c +++ b/addons/medical/scripts/Game/ACE_Medical/Components/Gadgets/ACE_Medical_ConsumableMorphine.c @@ -4,33 +4,6 @@ [BaseContainerProps()] class ACE_Medical_ConsumableMorphine : SCR_ConsumableEffectHealthItems { - [Attribute(defvalue: "10", desc: "Regeneration speed of related hitzone when consuming this item", category: "Regeneration")] - protected float m_fItemRegenerationSpeedDPS; - - [Attribute(defvalue: "10", desc: "Regeneration duration of related hitzone when consuming this item in seconds", category: "Regeneration")] - protected float m_fItemRegenerationDurationS; - - //------------------------------------------------------------------------------------------------ - //! Fully heal pain hit zone - override void ApplyEffect(notnull IEntity target, notnull IEntity user, IEntity item, ItemUseParameters animParams) - { - super.ApplyEffect(target, user, item, animParams); - - ChimeraCharacter char = ChimeraCharacter.Cast(target); - if (!char) - return; - - SCR_CharacterDamageManagerComponent damageManager = SCR_CharacterDamageManagerComponent.Cast(char.GetDamageManager()); - if (!damageManager) - return; - - ACE_Medical_PainHitZone painHZ = damageManager.ACE_Medical_GetPainHitZone(); - if (!painHZ) - return; - - painHZ.CustomRegeneration(target, m_fItemRegenerationDurationS, m_fItemRegenerationSpeedDPS); - } - //------------------------------------------------------------------------------------------------ //! Can be applied when patient is in pain and no morphine is in the system override bool CanApplyEffect(notnull IEntity target, notnull IEntity user, out SCR_EConsumableFailReason failReason) @@ -48,7 +21,8 @@ class ACE_Medical_ConsumableMorphine : SCR_ConsumableEffectHealthItems return false; // Check if morphine is in the system already - if (painHZ.GetDamageOverTime(EDamageType.HEALING) < 0) + array effects = damageManager.GetAllPersistentEffectsOfType(ACE_Medical_MorphineDamageEffect); + if (!effects.IsEmpty()) { failReason = SCR_EConsumableFailReason.ALREADY_APPLIED; return false; diff --git a/addons/medical/scripts/Game/ACE_Medical/Components/SupportStation/SCR_HealSupportStationComponent.c b/addons/medical/scripts/Game/ACE_Medical/Components/SupportStation/ACE_Medical_HealSupportStationComponent.c similarity index 57% rename from addons/medical/scripts/Game/ACE_Medical/Components/SupportStation/SCR_HealSupportStationComponent.c rename to addons/medical/scripts/Game/ACE_Medical/Components/SupportStation/ACE_Medical_HealSupportStationComponent.c index 78869cbe..f14aacb4 100644 --- a/addons/medical/scripts/Game/ACE_Medical/Components/SupportStation/SCR_HealSupportStationComponent.c +++ b/addons/medical/scripts/Game/ACE_Medical/Components/SupportStation/ACE_Medical_HealSupportStationComponent.c @@ -1,5 +1,4 @@ -//------------------------------------------------------------------------------------------------ -modded class SCR_HealSupportStationComponent : SCR_BaseDamageHealSupportStationComponent +modded class SCR_HealSupportStationComponent { //------------------------------------------------------------------------------------------------ //! Apply settings @@ -7,11 +6,11 @@ modded class SCR_HealSupportStationComponent : SCR_BaseDamageHealSupportStationC { super.DelayedInit(owner); - ACE_Medical_Settings settings = ACE_SettingsHelperT.GetModSettings(); + const ACE_Medical_Settings settings = ACE_SettingsHelperT.GetModSettings(); if (!settings) return; - SCR_ResourceComponent resource = SCR_ResourceComponent.Cast(GetOwner().FindComponent(SCR_ResourceComponent)); + const SCR_ResourceComponent resource = SCR_ResourceComponent.Cast(GetOwner().FindComponent(SCR_ResourceComponent)); if (!resource) return; diff --git a/addons/medical/scripts/Game/ACE_Medical/HitZone/ACE_Medical_CharacterResilienceHitZone.c b/addons/medical/scripts/Game/ACE_Medical/HitZone/ACE_Medical_CharacterResilienceHitZone.c new file mode 100644 index 00000000..c0c049af --- /dev/null +++ b/addons/medical/scripts/Game/ACE_Medical/HitZone/ACE_Medical_CharacterResilienceHitZone.c @@ -0,0 +1,16 @@ +//------------------------------------------------------------------------------------------------ +modded class SCR_CharacterResilienceHitZone : SCR_RegeneratingHitZone +{ + //------------------------------------------------------------------------------------------------ + //! Multiply regen DPS by the regen scale + override float CalculatePassiveRegenDPS(bool considerRegenScale = true) + { + float regenDPS = super.CalculatePassiveRegenDPS(considerRegenScale); + + const SCR_CharacterDamageManagerComponent damageManager = SCR_CharacterDamageManagerComponent.Cast(GetHitZoneContainer()); + if (damageManager) + regenDPS *= damageManager.GetResilienceRegenScale(); + + return regenDPS; + } +} diff --git a/addons/medical/scripts/Game/ACE_Medical/HitZone/ACE_Medical_PainHitZone.c b/addons/medical/scripts/Game/ACE_Medical/HitZone/ACE_Medical_PainHitZone.c index 781432ed..c3b69e60 100755 --- a/addons/medical/scripts/Game/ACE_Medical/HitZone/ACE_Medical_PainHitZone.c +++ b/addons/medical/scripts/Game/ACE_Medical/HitZone/ACE_Medical_PainHitZone.c @@ -7,19 +7,19 @@ class ACE_Medical_PainHitZone : SCR_RegeneratingHitZone override void OnInit(IEntity pOwnerEntity, GenericComponent pManagerComponent) { super.OnInit(pOwnerEntity, pManagerComponent); - SCR_CharacterDamageManagerComponent characterDamageManager = SCR_CharacterDamageManagerComponent.Cast(pManagerComponent); + const SCR_CharacterDamageManagerComponent characterDamageManager = SCR_CharacterDamageManagerComponent.Cast(pManagerComponent); if (characterDamageManager) characterDamageManager.ACE_Medical_SetPainHitZone(this); } //----------------------------------------------------------------------------------------------------------- //! Suppress passive regeneration while bleeding - override float CalculatePassiveRegeneration() + override float CalculatePassiveRegenDPS(bool considerRegenScale = true) { - SCR_CharacterDamageManagerComponent manager = SCR_CharacterDamageManagerComponent.Cast(GetHitZoneContainer()); - if (manager && manager.IsDamagedOverTime(EDamageType.BLEEDING)) + const SCR_CharacterDamageManagerComponent damageManager = SCR_CharacterDamageManagerComponent.Cast(GetHitZoneContainer()); + if (damageManager && damageManager.IsBleeding()) return 0; - return super.CalculatePassiveRegeneration(); + return super.CalculatePassiveRegenDPS(considerRegenScale); } } diff --git a/addons/medical/scripts/Game/ACE_Medical/HitZone/SCR_CharacterHealthHitZone.c b/addons/medical/scripts/Game/ACE_Medical/HitZone/ACE_Medical_SCR_CharacterHealthHitZone.c similarity index 85% rename from addons/medical/scripts/Game/ACE_Medical/HitZone/SCR_CharacterHealthHitZone.c rename to addons/medical/scripts/Game/ACE_Medical/HitZone/ACE_Medical_SCR_CharacterHealthHitZone.c index 6616a2f1..1abc1a9d 100644 --- a/addons/medical/scripts/Game/ACE_Medical/HitZone/SCR_CharacterHealthHitZone.c +++ b/addons/medical/scripts/Game/ACE_Medical/HitZone/ACE_Medical_SCR_CharacterHealthHitZone.c @@ -1,6 +1,6 @@ //----------------------------------------------------------------------------------------------------------- //! health hitzone - Receives damage from physical hitzones -modded class SCR_CharacterHealthHitZone : SCR_HitZone +modded class SCR_CharacterHealthHitZone { protected SCR_CharacterDamageManagerComponent m_pACE_Medical_DamageManager; protected bool m_bACE_Medical_HasSecondChanceOnHead; @@ -32,18 +32,16 @@ modded class SCR_CharacterHealthHitZone : SCR_HitZone //! Triggers second chance if damage had to be rescaled protected float ACE_Medical_ComputeSecondChanceEffectiveDamage(notnull BaseDamageContext damageContext, bool isDOT) { - float effectiveDamage = super.ComputeEffectiveDamage(damageContext, isDOT); + const float effectiveDamage = super.ComputeEffectiveDamage(damageContext, isDOT); if (GetHealth() - effectiveDamage >= ACE_MEDICAL_SECOND_CHANCE_MIN_HEALTH) return effectiveDamage; - SCR_CharacterHitZone hitZone = SCR_CharacterHitZone.Cast(damageContext.struckHitZone); + const SCR_CharacterHitZone hitZone = SCR_CharacterHitZone.Cast(damageContext.struckHitZone); if (hitZone && !m_pACE_Medical_DamageManager.ACE_Medical_WasSecondChanceTrigged()) { m_pACE_Medical_DamageManager.ACE_Medical_SetSecondChanceTrigged(true); // Add bleeding to the hit zone that triggered second chance - // Only call AddBleeding on the authority, since it does a broadcast itself - if (!IsProxy()) - hitZone.AddBleeding(damageContext.colliderID); + m_pACE_Medical_DamageManager.AddBleedingEffectOnHitZone(hitZone, damageContext.colliderID); } return GetHealth() - ACE_MEDICAL_SECOND_CHANCE_MIN_HEALTH; diff --git a/addons/medical/scripts/Game/ACE_Medical/UserActions/ACE_Medical_EpinephrineUserAction.c b/addons/medical/scripts/Game/ACE_Medical/UserActions/ACE_Medical_EpinephrineUserAction.c index 7e1f4e12..0ea588a5 100755 --- a/addons/medical/scripts/Game/ACE_Medical/UserActions/ACE_Medical_EpinephrineUserAction.c +++ b/addons/medical/scripts/Game/ACE_Medical/UserActions/ACE_Medical_EpinephrineUserAction.c @@ -15,11 +15,11 @@ class ACE_Medical_EpinephrineUserAction : SCR_MorphineUserAction override bool CanBePerformedScript(IEntity user) { // Medic character - ChimeraCharacter userCharacter = ChimeraCharacter.Cast(user); + const ChimeraCharacter userCharacter = ChimeraCharacter.Cast(user); if (!userCharacter) return false; - SCR_ConsumableItemComponent consumableComponent = GetConsumableComponent(userCharacter); + const SCR_ConsumableItemComponent consumableComponent = GetConsumableComponent(userCharacter); if (!consumableComponent) return false; diff --git a/addons/medical/scripts/Game/Damage/DamageEffects/CharacterDamageEffects/ACE_Medical_EpinephrineDamageEffect.c b/addons/medical/scripts/Game/Damage/DamageEffects/CharacterDamageEffects/ACE_Medical_EpinephrineDamageEffect.c new file mode 100644 index 00000000..ab5a4186 --- /dev/null +++ b/addons/medical/scripts/Game/Damage/DamageEffects/CharacterDamageEffects/ACE_Medical_EpinephrineDamageEffect.c @@ -0,0 +1,19 @@ +//------------------------------------------------------------------------------------------------ +class ACE_Medical_EpinephrineDamageEffect: SCR_DotDamageEffect +{ + //------------------------------------------------------------------------------------------------ + override bool HijackDamageEffect(SCR_ExtendedDamageManagerComponent dmgManager) + { + const SCR_CharacterDamageManagerComponent charDmgManager = SCR_CharacterDamageManagerComponent.Cast(dmgManager); + if (charDmgManager) + SetAffectedHitZone(charDmgManager.GetResilienceHitZone()); + + return false; + } + + //------------------------------------------------------------------------------------------------ + override EDamageType GetDefaultDamageType() + { + return EDamageType.HEALING; + } +} diff --git a/addons/medical/scripts/Game/Damage/DamageEffects/CharacterDamageEffects/ACE_Medical_MorphineDamageEffect.c b/addons/medical/scripts/Game/Damage/DamageEffects/CharacterDamageEffects/ACE_Medical_MorphineDamageEffect.c new file mode 100644 index 00000000..d776ba64 --- /dev/null +++ b/addons/medical/scripts/Game/Damage/DamageEffects/CharacterDamageEffects/ACE_Medical_MorphineDamageEffect.c @@ -0,0 +1,19 @@ +//------------------------------------------------------------------------------------------------ +class ACE_Medical_MorphineDamageEffect: SCR_DotDamageEffect +{ + //------------------------------------------------------------------------------------------------ + override bool HijackDamageEffect(SCR_ExtendedDamageManagerComponent dmgManager) + { + const SCR_CharacterDamageManagerComponent charDmgManager = SCR_CharacterDamageManagerComponent.Cast(dmgManager); + if (charDmgManager) + SetAffectedHitZone(charDmgManager.ACE_Medical_GetPainHitZone()); + + return false; + } + + //------------------------------------------------------------------------------------------------ + override EDamageType GetDefaultDamageType() + { + return EDamageType.HEALING; + } +} diff --git a/addons/medical/scripts/Game/ACE_Medical/Player/SCR_PlayerController.c b/addons/medical/scripts/Game/Player/ACE_Medical_PlayerController.c similarity index 65% rename from addons/medical/scripts/Game/ACE_Medical/Player/SCR_PlayerController.c rename to addons/medical/scripts/Game/Player/ACE_Medical_PlayerController.c index 00ef8ee7..9c3840b4 100644 --- a/addons/medical/scripts/Game/ACE_Medical/Player/SCR_PlayerController.c +++ b/addons/medical/scripts/Game/Player/ACE_Medical_PlayerController.c @@ -1,21 +1,20 @@ -//------------------------------------------------------------------------------------------------ -modded class SCR_PlayerController : PlayerController +modded class SCR_PlayerController { //------------------------------------------------------------------------------------------------ //! Initialize ACE Medical on player controlled characters override void OnControlledEntityChanged(IEntity from, IEntity to) { super.OnControlledEntityChanged(from, to); - + // OnControlledEntityChanged runs on owner too, but we only want to call the init on the server if (Replication.IsRunning() && !Replication.IsServer()) return; - + //! Do not initialize for GM controlled AI if (!to || IsPossessing()) return; - - SCR_CharacterDamageManagerComponent damageManager = SCR_CharacterDamageManagerComponent.Cast(to.FindComponent(SCR_CharacterDamageManagerComponent)); + + const SCR_CharacterDamageManagerComponent damageManager = SCR_CharacterDamageManagerComponent.Cast(to.FindComponent(SCR_CharacterDamageManagerComponent)); if (damageManager) damageManager.ACE_Medical_Initialize(); } diff --git a/addons/medical/scripts/Game/UserActions/SCR_BandageUserAction.c b/addons/medical/scripts/Game/UserActions/SCR_BandageUserAction.c deleted file mode 100644 index 5a8798d4..00000000 --- a/addons/medical/scripts/Game/UserActions/SCR_BandageUserAction.c +++ /dev/null @@ -1,59 +0,0 @@ -//------------------------------------------------------------------------------------------------ -//! Hard-override of SCR_BandageUserAction -class SCR_BandageUserAction : SCR_HealingUserAction -{ - //------------------------------------------------------------------------------------------------ - //! Copy of vanilla method - override void OnActionCanceled(IEntity pOwnerEntity, IEntity pUserEntity) - { - ChimeraCharacter character = ChimeraCharacter.Cast(pUserEntity); - if (!character) - return; - - CharacterControllerComponent controller = character.GetCharacterController(); - if (!controller) - return; - - if (controller.GetLifeState() != ECharacterLifeState.ALIVE) - return; - - SCR_ConsumableItemComponent consumableComponent = GetConsumableComponent(character); - if (consumableComponent) - consumableComponent.SetAlternativeModel(false); - } - - //------------------------------------------------------------------------------------------------ - //! We move the handling from CanBeShownScript to CanBePerformedScript - //! We check the bleeding via the array of all bleeding hit zones, which should be more reliable - //! than the vanilla implementation - override bool CanBePerformedScript(IEntity user) - { - if (!super.CanBePerformedScript(user)) - return false; - - // Target character - ChimeraCharacter char = ChimeraCharacter.Cast(GetOwner()); - if (!char) - return false; - - SCR_CharacterDamageManagerComponent damageManager = SCR_CharacterDamageManagerComponent.Cast(char.GetDamageManager()); - if (!damageManager) - return false; - - array bleedingHitZones = {}; - damageManager.GetBleedingHitZones(bleedingHitZones); - - foreach (HitZone hitZone : bleedingHitZones) - { - SCR_CharacterHitZone charHitZone = SCR_CharacterHitZone.Cast(hitZone); - if (!charHitZone) - continue; - - if (charHitZone.GetHitZoneGroup() == m_eHitZoneGroup) - return true; - } - - SetCannotPerformReason(m_sNotBleeding); - return false; - } -} diff --git a/addons/trenches/scripts/Game/ACE_Trenches/Building/SCR_CampaignBuildingGadgetToolComponent.c b/addons/trenches/scripts/Game/ACE_Trenches/Building/SCR_CampaignBuildingGadgetToolComponent.c index b9e9dcec..fd8b0ca3 100644 --- a/addons/trenches/scripts/Game/ACE_Trenches/Building/SCR_CampaignBuildingGadgetToolComponent.c +++ b/addons/trenches/scripts/Game/ACE_Trenches/Building/SCR_CampaignBuildingGadgetToolComponent.c @@ -38,7 +38,7 @@ modded class SCR_CampaignBuildingGadgetToolComponent : SCR_GadgetComponent return; m_bACE_InHand = false; - ToggleActive(false); + ToggleActive(false, SCR_EUseContext.FROM_INVENTORY); GetGame().GetInputManager().RemoveActionListener("CharacterInspect", EActionTrigger.DOWN, ToogleActiveAction); } @@ -115,7 +115,7 @@ modded class SCR_CampaignBuildingGadgetToolComponent : SCR_GadgetComponent //------------------------------------------------------------------------------------------------ //! Toggles building placement preview - override void ToggleActive(bool state) + override void ToggleActive(bool state, SCR_EUseContext context) { if (m_bActivated == state) return; @@ -150,6 +150,6 @@ modded class SCR_CampaignBuildingGadgetToolComponent : SCR_GadgetComponent //! Callback for CharacterInspect keybind void ToogleActiveAction() { - ToggleActive(!m_bActivated); + ToggleActive(!m_bActivated, SCR_EUseContext.FROM_ACTION); } }