Ravenfield

Ravenfield

Damage Core
RadioactiveJellyfish  [developer] 4 Jan, 2024 @ 11:47pm
For Modders
Similar to Movement Core, Damage Core is a solution to allow different mods to modify damage without overlapping with one another. See below for the functions that this mod adds.

Accessing Damage Core
To find Damage Core in the game, just add this snippet of code to your Start function.
local damageSystemObj = self.gameObject.Find("DamageCore") if damageSystemObj then self.damageSystem = damageSystemObj.GetComponent(ScriptedBehaviour) end
DO NOT PUT THIS IN AWAKE! IT HAS TO BE IN START

Modifiers
You can add damage modifiers to actors. There are four types of modifiers.
  • Normal Health Damage
  • Splash Health Damage
  • Normal Balance Damage
  • Splash Balance Damage
Splash damage refers to explosive damage.

Adding Modifiers
To add a modifier, we use Damage Core's AddDamageModifier function.
Declaration
AddDamageModifier(Actor actor, string modifierName, float modifierValue,string damageType, bool splashDamage)
Example
self.damageCore.self:AddDamageModifier(Player.actor,"BodyArmor",0.75,"health",false) self.damageCore.self:AddDamageModifier(Player.actor,"BodyArmor",0.75,"balance",false)

The example above means the player will only take 75% health and balance damage.

Modifiers do not necesarilly mean damage reduction!
When damage is calculated, it just simply multiplies the original damage value by the final damage modifier.
If multiple modifiers exist for one actor, all multipliers are multiplied together.

Removing Modifiers
To remove a modifier we call RemoveDamageModifier.
Declaration
RemoveDamageModifier(Actor actor, string modifierName, string damageType, bool splashDamage)
Example
self.damageCore.self:RemoveDamageModifier(Player.actor,"BodyArmor","health",false) self.damageCore.self:RemoveDamageModifier(Player.actor,"BodyArmor","balance",false)
When modifiers are added/removed the final calculated damage modifier is recalculated. Only add or remove modifiers when necessary. Modifiers are not removed on actor death.

Events
Damage Core's events is essentially RF's OnTakeDamageInfo event split into three. PreCalculation, ModifyCalculation and PostCalculation.

Adding and Removing Events
To add events we call AddListener.
Declaration
AddListener(string eventType, Actor actor, DynValue owner, func)
Example
local function preCalc(actor, source, info) self:MyPreCalculationFunction(actor, source, info) end self.damageSystem.self:AddListener("PreCalculation", Player.actor, self, preCalc)
As with the example above, do not pass your class' function into the AddListener call. Wrap your function call into a local function and pass the local function into the call. Alternatives may exist but this is what I've found to work.

To remove events we call RemoveListener.
Declaration
RemoveListener(string eventType, Actor actor, DynValue owner)
Example
self.damageSystem.self:RemoveListener("PreCalculation", Player.actor, self)
What you pass in Owner can be anything, so long as it is unique. You must pass the same owner in both add and remove in order for things to work properly. Only one event listener can exist per object.

Pre Calculation
These events are invoked before an actor's multipliers modify the damage and before ModifyCalculation events. It does however happen after the mutator's global damage multipliers modify the damage. This is useful for knowing what damage the actor should have taken before any modifiers and events are applied.

Your event functions must follow this signature.
OnPreCalculate(Actor actor, Actor source, DamageInfo info)
Example
function MyClass:OnPreDamageCalculation(actor,source,info) print("Pre Calculation") print(info.healthDamage) end

Modify Calculation
These events are invoked after the above function as well as after an actor's modifiers modify the existing damage. This event allows you to modify damage info however you wish. These changes will then reflect on PostCalculation and the final result of damage taken by the actor. Because of this, it is required that your function return the modified damage info at the end.

Your event functions must follow this signature.
OnModifyCalculation(Actor actor, Actor source, DamageInfo info)
Example
function MyClass:OnModifyCalculation(actor,source,info) print("OnModifyCalculation") info.healthDamage = info.healthDamage * 0.5 end
The above event will modify the damage info's healthDamage variable by 50%. This means in the final calculation the actor will only receive 50% of the intended damage.

Post Calculation
These events are invoked after all of the above. This is useful for knowing what the final damage actually is after all the modifications done by multipliers and events.

Your event functions must follow this signature.
OnPostDamageCalculation(Actor actor, Actor source, DamageInfo info)
Example
function MyClass:OnPostDamageCalculation(actor,source,info) print("OnPostDamageCalculation") print(info.healthDamage) end

The Order of Operations
For clarity's sake, below is the order of things that happen within Damage Core.

  • Global damage multipliers are applied.
  • If both health and balance damage are 0 due to global multipliers, stop here.This also consumes the OnTakeDamage event.
  • Pre Calculation events are called.
  • Actor Modifiers are applied to the damage values.
  • Modify Calculation events are called.
  • Post Calculation events are called.

Take note of the order above when making your modifiers and events.
Last edited by RadioactiveJellyfish; 5 Jan, 2024 @ 1:22am