Files
2025-03-31 13:19:47 +02:00

313 lines
9.2 KiB
Lua

-- Hooks Lua event "changeFallDamage" to cause more damage and NT afflictions like fractures and artery cuts on extremities depending on severity
local limbtypes = {
LimbType.Torso,
LimbType.Head,
LimbType.LeftArm,
LimbType.RightArm,
LimbType.LeftLeg,
LimbType.RightLeg,
}
local function HasLungs(c)
return not HF.HasAffliction(c, "lungremoved")
end
local function getCalculatedReductionSuit(armor, strength, limbtype)
if armor == nil then
return 0
end
local reduction = 0
if armor.HasTag("deepdivinglarge") or armor.HasTag("deepdiving") then
local modifiers = armor.GetComponentString("Wearable").DamageModifiers
for modifier in modifiers do
if string.find(modifier.AfflictionIdentifiers, "blunttrauma") ~= nil then
reduction = strength - strength * modifier.DamageMultiplier
end
end
elseif armor.HasTag("clothing") and armor.HasTag("smallitem") and limbtype == LimbType.Torso then
local modifiers = armor.GetComponentString("Wearable").DamageModifiers
for modifier in modifiers do
if string.find(modifier.AfflictionIdentifiers, "blunttrauma") ~= nil then
reduction = strength - strength * modifier.DamageMultiplier
end
end
end
return reduction
end
local function getCalculatedReductionClothes(armor, strength, limbtype)
if armor == nil then
return 0
end
local reduction = 0
if armor.HasTag("deepdiving") or armor.HasTag("diving") then
local modifiers = armor.GetComponentString("Wearable").DamageModifiers
for modifier in modifiers do
if string.find(modifier.AfflictionIdentifiers, "blunttrauma") ~= nil then
reduction = strength - strength * modifier.DamageMultiplier
end
end
elseif armor.HasTag("clothing") and armor.HasTag("smallitem") then
local modifiers = armor.GetComponentString("Wearable").DamageModifiers
for modifier in modifiers do
if string.find(modifier.AfflictionIdentifiers, "blunttrauma") ~= nil then
reduction = strength - strength * modifier.DamageMultiplier
end
end
end
return reduction
end
local function getCalculatedReductionHelmet(armor, strength)
if armor == nil then
return 0
end
local reduction = 0
if armor.HasTag("smallitem") then
local modifiers = armor.GetComponentString("Wearable").DamageModifiers
for modifier in modifiers do
if string.find(modifier.AfflictionIdentifiers, "blunttrauma") ~= nil then
reduction = strength - strength * modifier.DamageMultiplier
end
end
end
return reduction
end
local function getCalculatedConcussionReduction(armor, strength)
if armor == nil then
return 0
end
local reduction = 0
if armor.HasTag("deepdiving") or armor.HasTag("deepdivinglarge") then
local modifiers = armor.GetComponentString("Wearable").DamageModifiers
for modifier in modifiers do
if string.find(modifier.AfflictionIdentifiers, "concussion") ~= nil then
reduction = strength - strength * modifier.DamageMultiplier
end
end
elseif armor.HasTag("smallitem") then
local modifiers = armor.GetComponentString("Wearable").DamageModifiers
for modifier in modifiers do
if string.find(modifier.AfflictionIdentifiers, "concussion") ~= nil then
reduction = strength - strength * modifier.DamageMultiplier
end
end
end
return reduction
end
Hook.Add("changeFallDamage", "NT.falldamage", function(impactDamage, character, impactPos, velocity)
-- dont bother with creatures
if not character.IsHuman then
return
end
-- dont apply fall damage in water
if character.InWater then
return 0
end
-- dont apply fall damage when dragged by someone
if character.SelectedBy ~= nil then
return 0
end
local velocityMagnitude = HF.Magnitude(velocity)
velocityMagnitude = velocityMagnitude ^ 1.5
-- apply fall damage to all limbs based on fall direction
local mainlimbPos = character.AnimController.MainLimb.WorldPosition
local limbDotResults = {}
local minDotRes = 1000
for limb in character.AnimController.Limbs do
for type in limbtypes do
if limb.type == type then
-- fetch the direction of each limb relative to the torso
local limbPosition = limb.WorldPosition
local posDif = limbPosition - mainlimbPos
posDif.X = posDif.X / 100
posDif.Y = posDif.Y / 100
local posDifMagnitude = HF.Magnitude(posDif)
if posDifMagnitude > 1 then
posDif.Normalize()
end
local normalizedVelocity = Vector2(velocity.X, velocity.Y)
normalizedVelocity.Normalize()
-- compare those directions to the direction we're moving
-- this will later be used to hurt the limbs facing impact more than the others
local limbDot = Vector2.Dot(posDif, normalizedVelocity)
limbDotResults[type] = limbDot
if minDotRes > limbDot then
minDotRes = limbDot
end
break
end
end
end
-- shift all weights out of the negatives
-- increase the weight of all limbs if speed is high
-- the effect of this is that, at higher speeds, all limbs take damage instead of mainly the ones facing the impact site
for type, dotResult in pairs(limbDotResults) do
limbDotResults[type] = dotResult - minDotRes + math.max(0, (velocityMagnitude - 30) / 10)
end
-- count weight so we're able to distribute the damage fractionally
local weightsum = 0
for dotResult in limbDotResults do
weightsum = weightsum + dotResult
end
for type, dotResult in pairs(limbDotResults) do
local relativeWeight = dotResult / weightsum
-- lets limit the numbers to the max value of blunttrauma so that resistances make sense
local damageInflictedToThisLimb = math.min(
relativeWeight * math.max(0, velocityMagnitude - 10) ^ 1.5 * NTConfig.Get("NT_falldamage", 1) * 0.5,
200
)
NT.CauseFallDamage(character, type, damageInflictedToThisLimb)
end
-- make the normal damage not run
return 0
end)
NT.CauseFallDamage = function(character, limbtype, strength)
local armor1 = character.Inventory.GetItemInLimbSlot(InvSlotType.OuterClothes)
local armor2 = character.Inventory.GetItemInLimbSlot(InvSlotType.InnerClothes)
if limbtype ~= LimbType.Head then
strength = math.max(
strength
- getCalculatedReductionSuit(armor1, strength, limbtype)
- getCalculatedReductionClothes(armor2, strength, limbtype),
0
)
else
armor2 = character.Inventory.GetItemInLimbSlot(InvSlotType.Head)
strength = math.max(
strength
- getCalculatedReductionSuit(armor1, strength, limbtype)
- getCalculatedReductionHelmet(armor2, strength, limbtype),
0
)
end
-- additionally calculate the affliction reduced damage
local prefab = AfflictionPrefab.Prefabs["blunttrauma"]
local resistance = character.CharacterHealth.GetResistance(prefab, limbtype)
if resistance >= 1 then
return
end
strength = strength * (1 - resistance)
HF.AddAfflictionLimb(character, "blunttrauma", limbtype, strength)
-- return earlier if the strength value is not high enough for damage checks
if strength < 1 then
return
end
local fractureImmune = false
local injuryChanceMultiplier = NTConfig.Get("NT_falldamageSeriousInjuryChance", 1)
-- torso
if not fractureImmune and strength >= 1 and limbtype == LimbType.Torso then
if
HF.Chance(
(strength - 15)
/ 100
* NTC.GetMultiplier(character, "anyfracturechance")
* NTConfig.Get("NT_fractureChance", 1)
* injuryChanceMultiplier
)
then
NT.BreakLimb(character, limbtype)
if
HasLungs(character)
and strength >= 5
and HF.Chance(
strength
/ 70
* NTC.GetMultiplier(character, "pneumothoraxchance")
* NTConfig.Get("NT_pneumothoraxChance", 1)
)
then
HF.AddAffliction(character, "pneumothorax", 5)
end
end
end
-- head
if not fractureImmune and strength >= 1 and limbtype == LimbType.Head then
if strength >= 15 and HF.Chance(math.min(strength / 100, 0.7)) then
HF.AddAfflictionResisted(
character,
"concussion",
math.max(
10
- getCalculatedConcussionReduction(armor1, 10, limbtype)
- getCalculatedConcussionReduction(armor2, 10, limbtype),
0
)
)
end
if
strength >= 15
and HF.Chance(
math.min((strength - 15) / 100, 0.7)
* NTC.GetMultiplier(character, "anyfracturechance")
* NTConfig.Get("NT_fractureChance", 1)
* injuryChanceMultiplier
)
then
NT.BreakLimb(character, limbtype)
end
if
strength >= 55
and HF.Chance(
math.min((strength - 55) / 100, 0.7)
* NTC.GetMultiplier(character, "anyfracturechance")
* NTConfig.Get("NT_fractureChance", 1)
* injuryChanceMultiplier
)
then
HF.AddAffliction(character, "n_fracture", 5)
end
if strength >= 5 and HF.Chance(0.7) then
HF.AddAffliction(character, "cerebralhypoxia", strength * HF.RandomRange(0.1, 0.4))
end
end
-- extremities
if not fractureImmune and strength >= 1 and HF.LimbIsExtremity(limbtype) then
if
HF.Chance(
(strength - 15)
/ 100
* NTC.GetMultiplier(character, "anyfracturechance")
* NTConfig.Get("NT_fractureChance", 1)
* injuryChanceMultiplier
)
then
NT.BreakLimb(character, limbtype)
if HF.Chance((strength - 2) / 60) then
-- this is here to simulate open fractures
NT.ArteryCutLimb(character, limbtype)
end
end
if
HF.Chance(
HF.Clamp((strength - 5) / 120, 0, 0.5)
* NTC.GetMultiplier(character, "dislocationchance")
* NTConfig.Get("NT_dislocationChance", 1)
* injuryChanceMultiplier
) and not NT.LimbIsAmputated(character, limbtype)
then
NT.DislocateLimb(character, limbtype)
end
end
end