Damage System – Arma Reforger

From Bohemia Interactive Community
Jump to navigation Jump to search
(Page creation)
 
m (Fix image size)
Line 6: Line 6:




[[File:armar-damage_system_flowchart.png|thumb]]
[[File:armar-damage_system_flowchart.png|thumb|600px]]
== Logic Flow ==
== Logic Flow ==



Revision as of 14:07, 21 May 2024

The Damage System is the system that handle entity damage.


The Damage System explained in this document targets the armareforger-symbol black.png1.2.0 version.


armar-damage system flowchart.png

Logic Flow

The workflows goes as follows (see the attached image):

  • damage is received
  • the DamageManagerComponent checks that:
    • damage handling is enabled
    • damage handling is not hijacked
    • received damage should count as a hit
    • check if the entity is dead
    • check if actual damage shalt be dealt
  • it then
    • sends damage to the hit zone which calculates the effective damage
    • replicate the hit over the network for clients to calculate damage locally and display damage effects
    • deals damage
    • sends damage to the hit zone again for it to
      • deal damage
      • trigger OnDamage()
      • pass damage to the parent hit zones and do the same process for themselves
    • triggers DamageManager's OnDamage()
    • if the DamageStates did not change, exits
    • if they did, trigger the hit zone's OnDamageStateChanged() then its own OnDamageStateChanged()


Classes

Class hierarchy goes as follows:

HitZoneContainerComponent // engine-side - itself inheriting from GameComponent, irrelevant here DamageManagerComponent // engine-side SCR_DamageManagerComponent // script-side ExtendedDamageManagerComponent // engine-side SCR_ExtendedDamageManagerComponent // script-side - be sure to read its comments and the warning below SCR_CharacterDamageManagerComponent // script-side


ExtendedDamageManagerComponent Changes

The following API will not be useful for damageManagers inheriting from ExtendedDamageManagerComponent:

void OnDamageOverTimeAdded(EDamageType dType, float dps, HitZone hz); void OnDamageOverTimeRemoved(EDamageType dType, HitZone hz); bool IsDamagedOverTime(EDamageType dType); float GetDamageOverTime(EDamageType dType); void RemoveDamageOverTime(EDamageType dType);

DamageEffects logic replaces the conventional damageOverTime, and has its own API.

OnDamageOverTimeAdded()
OnDamageEffectAdded()
OnDamageOverTimeRemoved()
OnDamageEffectRemoved()
IsDamagedOverTime()

SCR_CharacterDamageManagerComponent.IsBleeding() GetPersistentEffects() GetAllPersistentEffectsOnHitZone() GetAllPersistentEffectsOfType()

GetDamageOverTime()

SCR_RegeneratingHitZone.GetHitZoneDamageOverTime() SCR_CharacterBloodHitZone.GetTotalBleedingAmount()


SetHealth()

The HitZone.SetHealth() method "magically" changes the amount of HP a hit zone has.

This means that the flowchart above will not take place since damage is not actually being dealt - this also means there is no instigator. Instead, only OnHealthSet() and OnDamageStateChanged() are called.

SetHealth() should be used very sparingly, for example in cases where one wants to force a character death, even when damage handling is disabled for that manager (remember, this method is not dealing damage, the health is magically changing).

An alternative to SetHealth() is to call HandleDamage and deal the entity's max health as true damage. By doing it this way, the entity is guaranteed to take enough damage to be destroyed, and the callback structure of a more "natural" cause of death above is maintained.

Bad Usage Example

Keep in mind that doing HandleDamage with true damage max health is not always the best way to destroy an entity. For example, killing a player inside a vehicle.

At first glance, killing the player by dealing damage equal to their max hp sounds like a good idea (and it would work fine on vanilla). However, now think of the (non-existent) Terminator mod.

If the Terminator is inside of a vehicle and the vehicle explodes, it should survive it (because of small damage multipliers, a large health pool, etc.), but since the applied damage is equal to max health, it would die.

This is why the best way to destroy entities is by dealing a "realistic" amount of damage that achieves the wanted goal, but that could technically be survivable by a modded entity.

When writing damage code, try to think of this fictional Terminator mod to ensure as much compatibility as possible.