313 lines
9.2 KiB
Lua
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
|