-- 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