Track LocalMods as part of monolith
This commit is contained in:
+174
@@ -0,0 +1,174 @@
|
||||
-- Neurotrauma blood types functions
|
||||
-- Hooks Lua event "characterCreated" to create a randomized blood type for spawned character and sets their immunity to 100
|
||||
---@diagnostic disable: lowercase-global, undefined-global
|
||||
NT.BLOODTYPE = { -- blood types and chance in percent
|
||||
{ "ominus", 7 },
|
||||
{ "oplus", 37 },
|
||||
{ "aminus", 6 },
|
||||
{ "aplus", 36 },
|
||||
{ "bminus", 2 },
|
||||
{ "bplus", 8 },
|
||||
{ "abminus", 1 },
|
||||
{ "abplus", 3 },
|
||||
}
|
||||
NT.setBlood = {}
|
||||
NT.foundAny = false
|
||||
|
||||
-- Insert all blood types in one table for RandomizeBlood()
|
||||
for index, value in ipairs(NT.BLOODTYPE) do
|
||||
-- print(index," : ",value[1],", ",value[2],"%")
|
||||
table.insert(NT.setBlood, index, { value[2], value[1] })
|
||||
end
|
||||
|
||||
-- Applies math.random() blood type.
|
||||
-- returns the applied bloodtype as an affliction identifier
|
||||
function NT.RandomizeBlood(character)
|
||||
rand = math.random(0, 99)
|
||||
local i = 0
|
||||
for index, value in ipairs(NT.setBlood) do
|
||||
i = i + value[1]
|
||||
if i > rand then
|
||||
HF.SetAffliction(character, value[2], 100)
|
||||
return value[2]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Hook.Add("characterCreated", "NT.BloodAndImmunity", function(createdCharacter)
|
||||
Timer.Wait(function()
|
||||
if createdCharacter.IsHuman and not createdCharacter.IsDead then
|
||||
NT.TryRandomizeBlood(createdCharacter)
|
||||
|
||||
-- add immunity
|
||||
local conditional2 = createdCharacter.CharacterHealth.GetAffliction("immunity")
|
||||
if conditional2 == nil then HF.SetAffliction(createdCharacter, "immunity", 100) end
|
||||
end
|
||||
end, 1000)
|
||||
end)
|
||||
|
||||
-- applies a new bloodtype only if the character doesnt already have one
|
||||
function NT.TryRandomizeBlood(character)
|
||||
NT.GetBloodtype(character)
|
||||
end
|
||||
|
||||
-- returns the bloodtype of the character as an affliction identifier string
|
||||
-- generates blood type if none present
|
||||
function NT.GetBloodtype(character)
|
||||
for index, affliction in ipairs(NT.BLOODTYPE) do
|
||||
local conditional = character.CharacterHealth.GetAffliction(affliction[1])
|
||||
|
||||
if conditional ~= nil and conditional.Strength > 0 then
|
||||
return affliction[1] -- TODO: give out abplus (AB+) to enemy team for blood infusions
|
||||
end
|
||||
end
|
||||
|
||||
return NT.RandomizeBlood(character)
|
||||
end
|
||||
|
||||
function NT.HasBloodtype(character)
|
||||
for index, affliction in ipairs(NT.BLOODTYPE) do
|
||||
local conditional = character.CharacterHealth.GetAffliction(affliction[1])
|
||||
|
||||
if conditional ~= nil and conditional.Strength > 0 then return true end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
Hook.Add("OnInsertedIntoBloodAnalyzer", "NT.BloodAnalyzer", function(effect, deltaTime, item, targets, position)
|
||||
-- Hematology Analyzer (bloodanalyzer) can scan inserted blood bags
|
||||
local owner = item.GetRootInventoryOwner()
|
||||
if owner == nil then return end
|
||||
if not LuaUserData.IsTargetType(owner, "Barotrauma.Character") then return end
|
||||
if not owner.IsPlayer then return end
|
||||
|
||||
local character = owner
|
||||
local contained = item.OwnInventory.GetItemAt(0)
|
||||
|
||||
local BaseColor = "127,255,255"
|
||||
local NameColor = "127,255,255"
|
||||
local LowColor = "127,255,255"
|
||||
local HighColor = "127,255,255"
|
||||
local VitalColor = "127,255,255"
|
||||
|
||||
if NTConfig.Get("NTSCAN_enablecoloredscanner", 1) then
|
||||
BaseColor = table.concat(NTConfig.Get("NTSCAN_basecolor", 1), ",")
|
||||
NameColor = table.concat(NTConfig.Get("NTSCAN_namecolor", 1), ",")
|
||||
LowColor = table.concat(NTConfig.Get("NTSCAN_lowcolor", 1), ",")
|
||||
HighColor = table.concat(NTConfig.Get("NTSCAN_highcolor", 1), ",")
|
||||
VitalColor = table.concat(NTConfig.Get("NTSCAN_vitalcolor", 1), ",")
|
||||
end
|
||||
|
||||
-- NT adds bloodbag; NT Blood Work or 'Real Sonar Medical Item Recipes Patch for Neurotrauma' add allblood, lets check for either
|
||||
if contained ~= nil and (contained.HasTag("bloodbag") or contained.HasTag("allblood")) then
|
||||
HF.GiveItem(character, "ntsfx_syringe")
|
||||
Timer.Wait(function()
|
||||
if item == nil or character == nil or item.OwnInventory.GetItemAt(0) ~= contained then return end
|
||||
|
||||
local identifier = contained.Prefab.Identifier.Value
|
||||
local packtype = "o-"
|
||||
if identifier ~= "antibloodloss2" then packtype = string.sub(identifier, string.len("bloodpack") + 1) end
|
||||
local bloodTypeDisplay = string.gsub(packtype, "abc", "c")
|
||||
bloodTypeDisplay = string.gsub(bloodTypeDisplay, "plus", "+")
|
||||
bloodTypeDisplay = string.gsub(bloodTypeDisplay, "minus", "-")
|
||||
bloodTypeDisplay = string.upper(bloodTypeDisplay)
|
||||
|
||||
local readoutString = "‖color:"
|
||||
.. BaseColor
|
||||
.. "‖"
|
||||
.. "Bloodpack: "
|
||||
.. "‖color:end‖"
|
||||
.. "‖color:"
|
||||
.. NameColor
|
||||
.. "‖"
|
||||
.. bloodTypeDisplay
|
||||
.. "‖color:end‖"
|
||||
-- check if acidosis, alkalosis or sepsis
|
||||
local tags = HF.SplitString(contained.Tags, ",")
|
||||
local defects = ""
|
||||
for tag in tags do
|
||||
if tag == "sepsis" then
|
||||
defects = defects .. "‖color:" .. VitalColor .. "‖" .. "\nSepsis detected" .. "‖color:end‖"
|
||||
end
|
||||
|
||||
if HF.StartsWith(tag, "acid") then
|
||||
local split = HF.SplitString(tag, ":")
|
||||
if split[2] ~= nil then
|
||||
defects = defects
|
||||
.. "‖color:"
|
||||
.. HighColor
|
||||
.. "‖"
|
||||
.. "\nAcidosis: "
|
||||
.. tonumber(split[2])
|
||||
.. "%"
|
||||
.. "‖color:end‖"
|
||||
end
|
||||
elseif HF.StartsWith(tag, "alkal") then
|
||||
local split = HF.SplitString(tag, ":")
|
||||
if split[2] ~= nil then
|
||||
defects = defects
|
||||
.. "‖color:"
|
||||
.. HighColor
|
||||
.. "‖"
|
||||
.. "\nAlkalosis: "
|
||||
.. tonumber(split[2])
|
||||
.. "%"
|
||||
.. "‖color:end‖"
|
||||
end
|
||||
end
|
||||
end
|
||||
if defects ~= "" then
|
||||
readoutString = readoutString .. defects
|
||||
else
|
||||
readoutString = readoutString
|
||||
.. "‖color:"
|
||||
.. LowColor
|
||||
.. "‖"
|
||||
.. "\nNo blood defects"
|
||||
.. "‖color:end‖"
|
||||
end
|
||||
|
||||
HF.DMClient(HF.CharacterToClient(character), readoutString, Color(127, 255, 255, 255))
|
||||
end, 1500)
|
||||
end
|
||||
end)
|
||||
@@ -0,0 +1,32 @@
|
||||
-- Hooks CalculateMovementPenalty method of Barotrauma.Character
|
||||
-- when painless enough, disable weapon sway / movement hindrance limb penalties
|
||||
-- !!! Lags the game, though GetAimWobble seems to be ok to patch
|
||||
|
||||
-- Disable movement penalties for painless characters
|
||||
-- Has about 2 ms performance drop on a many character save
|
||||
--Hook.Patch("Barotrauma.Character", "CalculateMovementPenalty", function(instance, ptable)
|
||||
-- if HF.HasAffliction(instance, "analgesia", 20) then
|
||||
-- ptable.PreventExecution = true
|
||||
-- return 0
|
||||
-- end
|
||||
--end, Hook.HookMethodType.Before)
|
||||
|
||||
-- Disable aim penalties for painless characters
|
||||
Hook.Patch("Barotrauma.AnimController", "GetAimWobble", function(instance, ptable)
|
||||
if HF.HasAffliction(instance.Character, "analgesia", 20) then
|
||||
ptable.PreventExecution = true
|
||||
return 0
|
||||
end
|
||||
end, Hook.HookMethodType.Before)
|
||||
|
||||
-- Patch to cause unconscious from the game rather than stun
|
||||
-- Lags the game by 6 times (on the same save)
|
||||
--Hook.Patch("Barotrauma.CharacterHealth", "get_IsUnconscious", function(instance, ptable)
|
||||
-- local isUnconscious = HF.HasAffliction(instance.Character, "sym_unconsciousness")
|
||||
-- ptable.PreventExecution = true
|
||||
-- return instance.Character.IsDead
|
||||
-- or (
|
||||
-- (instance.Character.Vitality <= 0.0 or isUnconscious)
|
||||
-- and not instance.Character.HasAbilityFlag(AbilityFlags.AlwaysStayConscious)
|
||||
-- )
|
||||
--end, Hook.HookMethodType.After)
|
||||
@@ -0,0 +1,108 @@
|
||||
-- THIS FILE IS NO LONGER IN USE
|
||||
-- the defunct item in question has been removed from the mod
|
||||
-- i'm keeping it here for...safekeeping i guess
|
||||
|
||||
LuaUserData.RegisterTypeBarotrauma("PurchasedItem")
|
||||
LuaUserData.RegisterType("System.Xml.Linq.XElement")
|
||||
|
||||
local VANILLA_PREFAB_ID = "antibloodloss2"
|
||||
local DEFUNCT_PREFAB_ID = "bloodpackominus"
|
||||
|
||||
-- Removes vanilla bloodpacks from cached stores in case the user installed
|
||||
-- this mod mid-campaign.
|
||||
-- NOTE: stores that had their stocks generated before installing this mod
|
||||
-- won't have any new medical items added.
|
||||
Hook.HookMethod("Barotrauma.Location", "LoadStores", function(instance, ptable)
|
||||
if instance.Stores == nil then return end
|
||||
|
||||
for storeId, store in pairs(instance.Stores) do
|
||||
for _, purchasedItem in pairs(store.Stock) do
|
||||
local itemId = purchasedItem.ItemPrefabIdentifier
|
||||
if itemId == DEFUNCT_PREFAB_ID then
|
||||
-- print("Removing defunct bloodpack (qty " .. purchasedItem.Quantity .. ") from " .. tostring(storeId))
|
||||
store.RemoveStock({ purchasedItem })
|
||||
end
|
||||
end
|
||||
end
|
||||
end, Hook.HookMethodType.After)
|
||||
|
||||
-- Replaces all vanilla bloodpack items with O- blood
|
||||
local function replaceItems()
|
||||
local ntBloodPrefab = ItemPrefab.Prefabs[DEFUNCT_PREFAB_ID]
|
||||
local vanillaBloodPrefab = ItemPrefab.Prefabs[VANILLA_PREFAB_ID]
|
||||
if ntBloodPrefab == nil then
|
||||
print("ERROR: couldn't find " .. DEFUNCT_PREFAB_ID)
|
||||
return
|
||||
end
|
||||
|
||||
for _, item in pairs(Item.ItemList) do
|
||||
local id = tostring(item.Prefab.Identifier)
|
||||
if id == DEFUNCT_PREFAB_ID then
|
||||
-- Don't replace decorative blood packs
|
||||
if item.NonInteractable then return end
|
||||
|
||||
local pos = item.WorldPosition
|
||||
local inv = item.ParentInventory
|
||||
local condition = item.ConditionPercentage
|
||||
local quality = item.Quality
|
||||
-- print("replacing blood pack (pos=" .. tostring(pos) .. ", inv=" .. tostring(inv) .. ")")
|
||||
|
||||
local slotIdx = -1
|
||||
if inv ~= nil then
|
||||
slotIdx = inv.FindIndex(item)
|
||||
if slotIdx < 0 then
|
||||
print(
|
||||
"ERROR: couldn't find item ("
|
||||
.. tostring(item)
|
||||
.. ", pos "
|
||||
.. tostring(pos)
|
||||
.. ") in inventory ("
|
||||
.. tostring(inv)
|
||||
.. ")"
|
||||
)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- We call `Drop()` first in case the inventory is full because
|
||||
-- `AddEntityToRemoveQueue` may not remove the item before we
|
||||
-- insert the new one, causing the inventory to overflow.
|
||||
item.Drop()
|
||||
Entity.Spawner.AddEntityToRemoveQueue(item)
|
||||
|
||||
Entity.Spawner.AddItemToSpawnQueue(vanillaBloodPrefab, pos, condition, quality, function(newItem)
|
||||
newItem.Rotation = item.Rotation
|
||||
-- Stolen items stay stolen
|
||||
newItem.AllowStealing = item.AllowStealing
|
||||
newItem.OriginalOutpost = item.OriginalOutpost
|
||||
|
||||
if inv ~= nil then
|
||||
if not inv.TryPutItem(newItem, slotIdx, false, true, nil) then
|
||||
print(
|
||||
"ERROR: failed to replace neurotrauma bloodpack ("
|
||||
.. tostring(item)
|
||||
.. ", pos "
|
||||
.. tostring(pos)
|
||||
.. ", slotIdx "
|
||||
.. tostring(slotIdx)
|
||||
.. ", inv "
|
||||
.. tostring(inv)
|
||||
.. ") with new item: "
|
||||
.. tostring(newItem)
|
||||
)
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Hook.Add("roundStart", "NT.ConvertBloodPacks", function()
|
||||
replaceItems()
|
||||
end)
|
||||
|
||||
-- Hook.Add("chatMessage", "NT.BloodPackTesting", function(msg, client)
|
||||
-- if (msg == "convertblood") then
|
||||
-- replaceItems()
|
||||
-- end
|
||||
-- end)
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
-- Hooks Lua event "human.CPRSuccess" to prevent fractures from ragdoll jank, and
|
||||
-- apply NT affliction cpr_buff or cause rib fractures in Hooked Lua event "human.CPRFailed"
|
||||
-- human.CPRSuccess was changed to character.CPRSuccess? Way above my paygrade - Lukako
|
||||
|
||||
Hook.Add("character.CPRSuccess", "NT.CPRSuccess", function(animcontroller)
|
||||
if
|
||||
animcontroller == nil
|
||||
or animcontroller.Character == nil
|
||||
or animcontroller.Character.SelectedCharacter == nil
|
||||
then
|
||||
return
|
||||
end
|
||||
|
||||
local character = animcontroller.Character.SelectedCharacter
|
||||
|
||||
if not HF.HasAffliction(character, "luabotomy") then HF.SetAffliction(character, "luabotomy", 1) end
|
||||
|
||||
if not HF.HasAffliction(character, "cpr_buff_auto") then HF.AddAffliction(character, "cpr_buff", 2) end
|
||||
|
||||
HF.AddAffliction(character, "cpr_fracturebuff", 2) -- prevent fractures during CPR (fuck baro physics)
|
||||
end)
|
||||
|
||||
Hook.Add("character.CPRFailed", "NT.CPRFailed", function(animcontroller)
|
||||
if
|
||||
animcontroller == nil
|
||||
or animcontroller.Character == nil
|
||||
or animcontroller.Character.SelectedCharacter == nil
|
||||
then
|
||||
return
|
||||
end
|
||||
|
||||
local character = animcontroller.Character.SelectedCharacter
|
||||
|
||||
if not HF.HasAffliction(character, "luabotomy") then HF.SetAffliction(character, "luabotomy", 1) end
|
||||
|
||||
HF.AddAffliction(character, "cpr_fracturebuff", 2) -- prevent fractures during CPR (fuck baro physics)
|
||||
HF.AddAfflictionLimb(character, "blunttrauma", LimbType.Torso, 0.3)
|
||||
|
||||
if
|
||||
HF.Chance(
|
||||
NTConfig.Get("NT_fractureChance", 1)
|
||||
* NTConfig.Get("NT_CPRFractureChance", 1)
|
||||
* 0.2
|
||||
/ HF.GetSkillLevel(animcontroller.Character, "medical")
|
||||
)
|
||||
then
|
||||
HF.AddAffliction(character, "t_fracture", 1)
|
||||
end
|
||||
end)
|
||||
@@ -0,0 +1,25 @@
|
||||
-- Based on config settings, which items ought to be destroyed
|
||||
local function DynamicRemoveItems()
|
||||
local blockedItems = HF.DynamicUnavailableItems()
|
||||
|
||||
for _, item in pairs(Item.ItemList) do
|
||||
local id = item.Prefab.Identifier.Value
|
||||
if blockedItems[id] then item.Remove() end
|
||||
end
|
||||
end
|
||||
|
||||
-- On level swap, remove any items that shouldn't be there
|
||||
Hook.Add("roundEnd", "nt_dynamicremoveitems", function()
|
||||
DynamicRemoveItems()
|
||||
end)
|
||||
|
||||
-- Recreate stores command to make sure newly added items are actually in stores
|
||||
Game.AddCommand("nt_recreatestores", "Recreate all stores.", function()
|
||||
if Game.GameSession.Map ~= nil then
|
||||
for location in Game.GameSession.Map.Locations do
|
||||
location.CreateStores(true)
|
||||
end
|
||||
else
|
||||
print("nt_recreatestores: Tried to recreate stores in the campaign map, but there is none!")
|
||||
end
|
||||
end)
|
||||
+300
@@ -0,0 +1,300 @@
|
||||
-- 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)
|
||||
-- don't run the code if we ignore the code
|
||||
if not NTConfig.Get("NT_Calculations", true) then return 0 end
|
||||
|
||||
-- dont bother with creatures
|
||||
if not character.IsHuman then return 0 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
|
||||
|
||||
-- don't apply fall damage if were specifically immune to it
|
||||
if HF.HasAffliction(character, "cpr_fracturebuff") or HF.HasAffliction(character, "stopcreatureabuse") then
|
||||
return 0
|
||||
end
|
||||
|
||||
if not HF.HasAffliction(character, "luabotomy") then HF.SetAffliction(character, "luabotomy", 1) end
|
||||
|
||||
local velocityMagnitude = HF.Magnitude(velocity)
|
||||
velocityMagnitude = velocityMagnitude ^ 1.3
|
||||
|
||||
-- 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,
|
||||
NTConfig.Get("NT_falldamageCeiling", 1) * 60
|
||||
)
|
||||
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 - 15) / 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
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
LuaUserData.MakeMethodAccessible(Descriptors["Barotrauma.HumanAIController"], "SpeakAboutIssues")
|
||||
|
||||
-- hopefully this stops bots from doing any rescuing at all.
|
||||
-- and also hopefully my assumption that this very specific thing
|
||||
-- about bots is what is causing them to eat frames is correct.
|
||||
|
||||
if NTConfig.Get("NT_disableBotAlgorithms", true) then
|
||||
Hook.Patch("Barotrauma.AIObjectiveRescueAll", "IsValidTarget", {
|
||||
"Barotrauma.Character",
|
||||
"Barotrauma.Character",
|
||||
"out System.Boolean",
|
||||
}, function(instance, ptable)
|
||||
-- TODO: some bot behavior
|
||||
-- make it hostile act if:
|
||||
-- surgery without corresponding ailments
|
||||
-- treatment without ailments
|
||||
|
||||
-- basic self treatments:
|
||||
-- find items to treat each other for blood loss or bleeding or suturable damage or fractures and dislocations
|
||||
-- ^ would possibly need items to have proper suitable treatments too, and yk bots dont spawn with enough meds...
|
||||
|
||||
ptable.PreventExecution = true
|
||||
return false
|
||||
end, Hook.HookMethodType.Before)
|
||||
end
|
||||
|
||||
local afflictions = {
|
||||
"n_fracture", -- urgent perceivable afflictions
|
||||
"h_arterialcut",
|
||||
"ll_arterialcut",
|
||||
"rl_arterialcut",
|
||||
"ra_arterialcut",
|
||||
"la_arterialcut",
|
||||
"sym_hematemesis", -- urgent causes
|
||||
"sym_paleskin",
|
||||
"sym_confusion",
|
||||
"sym_lightheadedness",
|
||||
"pain_abdominal",
|
||||
"inflammation",
|
||||
"gangrene",
|
||||
"fever",
|
||||
"sym_headache",
|
||||
"sym_blurredvision",
|
||||
"t_fracture", -- not urgent afflictions
|
||||
"h_fracture",
|
||||
"ra_fracture",
|
||||
"la_fracture",
|
||||
"rl_fracture",
|
||||
"ll_fracture",
|
||||
"dislocation1",
|
||||
"dislocation2",
|
||||
"dislocation3",
|
||||
"dislocation4",
|
||||
"pain_chest", -- not urgent causes
|
||||
"sym_weakness",
|
||||
"sym_sweating",
|
||||
"dyspnea",
|
||||
"sym_bloating",
|
||||
"sym_legswelling",
|
||||
"sym_craving",
|
||||
"sym_palpitations",
|
||||
}
|
||||
NT.SymsForNPC = { ntaffs = afflictions }
|
||||
|
||||
-- How to add own symptoms example:
|
||||
--local goobertable = { "goober", "gooberer" }
|
||||
--table.insert(NT.SymsForNPC, goobertable)
|
||||
|
||||
-- allows npcs to talk about their neuro afflictions
|
||||
|
||||
Hook.Patch("Barotrauma.HumanAIController", "SpeakAboutIssues", function(instance)
|
||||
local character = instance.Character
|
||||
|
||||
if not HF.HasAffliction(character, "luabotomy", 1) then return end
|
||||
|
||||
local message = ""
|
||||
local chatType = ChatMessageType.Default
|
||||
|
||||
if ChatMessage.CanUseRadio(character) then chatType = ChatMessageType.Radio end
|
||||
|
||||
for identifier in NT.SymsForNPC.ntaffs do
|
||||
if HF.HasAffliction(character, identifier, 1) then
|
||||
message = TextManager.Get("npcdialogsym." .. identifier)
|
||||
character.Speak(message, chatType, math.random(0, 5), Identifier(identifier .. "DialogSym"), 600.0)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
for table in NT.SymsForNPC do
|
||||
for identifier in table do
|
||||
if HF.HasAffliction(character, identifier, 1) then
|
||||
message = TextManager.Get("npcdialogsym." .. identifier)
|
||||
character.Speak(message, chatType, math.random(0, 5), Identifier(identifier .. "DialogSym"), 600.0)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end, Hook.HookMethodType.After)
|
||||
+2096
File diff suppressed because it is too large
Load Diff
+2784
File diff suppressed because it is too large
Load Diff
+90
@@ -0,0 +1,90 @@
|
||||
-- Spawns items inside medstartercrate
|
||||
-- Hooks XML Lua event "NT.medstartercrate.spawn" to create medstartercrate items and put them inside it
|
||||
Hook.Add(
|
||||
"NT.medstartercrate.spawn",
|
||||
"NT.medstartercrate.spawn",
|
||||
function(effect, deltaTime, item, targets, worldPosition)
|
||||
Timer.Wait(function()
|
||||
if item == nil then return end
|
||||
|
||||
-- check if the item already got populated before
|
||||
-- got broken somehow and is no longer needed, handled with oneshot="true" for the StatusEffect inside the medstartercrate item that calls this hook on spawn
|
||||
|
||||
-- local populated = item.HasTag("used")
|
||||
-- if populated then return end
|
||||
|
||||
-- add used tag
|
||||
|
||||
-- local tags = HF.SplitString(item.Tags,",")
|
||||
-- table.insert(tags,"used")
|
||||
-- local tagstring = ""
|
||||
-- for index, value in ipairs(tags) do
|
||||
-- tagstring = tagstring..value
|
||||
-- if index < #tags then tagstring=tagstring.."," end
|
||||
-- end
|
||||
-- item.Tags = tagstring
|
||||
|
||||
-- populate with goodies!!
|
||||
|
||||
if item.Scale == 0.5 then return end
|
||||
item.Scale = 0.5
|
||||
HF.SpawnItemPlusFunction("medtoolbox", function(params)
|
||||
HF.SpawnItemPlusFunction("defibrillator", nil, nil, params.item.OwnInventory, 0)
|
||||
HF.SpawnItemPlusFunction("autocpr", nil, nil, params.item.OwnInventory, 1)
|
||||
for i = 1, 2, 1 do
|
||||
HF.SpawnItemPlusFunction("tourniquet", nil, nil, params.item.OwnInventory, 2)
|
||||
end
|
||||
for i = 1, 2, 1 do
|
||||
HF.SpawnItemPlusFunction("ringerssolution", nil, nil, params.item.OwnInventory, 3)
|
||||
end
|
||||
HF.SpawnItemPlusFunction("surgicaldrill", nil, nil, params.item.OwnInventory, 4)
|
||||
HF.SpawnItemPlusFunction("surgerysaw", nil, nil, params.item.OwnInventory, 5)
|
||||
end, nil, item.OwnInventory, 0)
|
||||
|
||||
HF.SpawnItemPlusFunction("medtoolbox", function(params)
|
||||
HF.SpawnItemPlusFunction("antibleeding1", nil, nil, params.item.OwnInventory, 0)
|
||||
HF.SpawnItemPlusFunction("gypsum", nil, nil, params.item.OwnInventory, 1)
|
||||
HF.SpawnItemPlusFunction("opium", nil, nil, params.item.OwnInventory, 2)
|
||||
HF.SpawnItemPlusFunction("antibiotics", nil, nil, params.item.OwnInventory, 3)
|
||||
HF.SpawnItemPlusFunction("ointment", nil, nil, params.item.OwnInventory, 4)
|
||||
end, nil, item.OwnInventory, 1)
|
||||
|
||||
HF.SpawnItemPlusFunction("surgerytoolbox", function(params)
|
||||
HF.SpawnItemPlusFunction("advscalpel", nil, nil, params.item.OwnInventory, 0)
|
||||
HF.SpawnItemPlusFunction("advhemostat", nil, nil, params.item.OwnInventory, 1)
|
||||
HF.SpawnItemPlusFunction("advretractors", nil, nil, params.item.OwnInventory, 2)
|
||||
for i = 1, 16, 1 do
|
||||
HF.SpawnItemPlusFunction("suture", nil, nil, params.item.OwnInventory, 3)
|
||||
end
|
||||
HF.SpawnItemPlusFunction("tweezers", nil, nil, params.item.OwnInventory, 4)
|
||||
HF.SpawnItemPlusFunction("traumashears", nil, nil, params.item.OwnInventory, 5)
|
||||
HF.SpawnItemPlusFunction("drainage", nil, nil, params.item.OwnInventory, 6)
|
||||
HF.SpawnItemPlusFunction("needle", nil, nil, params.item.OwnInventory, 7)
|
||||
end, nil, item.OwnInventory, 3)
|
||||
|
||||
HF.SpawnItemPlusFunction("bloodanalyzer", nil, nil, item.OwnInventory, 6)
|
||||
HF.SpawnItemPlusFunction("healthscanner", function(params)
|
||||
local prefab = ItemPrefab.GetItemPrefab("batterycell")
|
||||
Entity.Spawner.AddItemToSpawnQueue(prefab, params["item"].WorldPosition, nil, nil, function(batteryItem)
|
||||
params["item"].OwnInventory.TryPutItem(batteryItem)
|
||||
end)
|
||||
end, nil, item.OwnInventory, 7)
|
||||
end, 35)
|
||||
end
|
||||
)
|
||||
|
||||
Hook.Add("character.giveJobItems", "NT.giveHealthScannersBatteries", function(character)
|
||||
Timer.Wait(function()
|
||||
for item in character.Inventory.AllItems do
|
||||
local thisIdentifier = item.Prefab.Identifier.Value
|
||||
if thisIdentifier == "healthscanner" then
|
||||
if item.OwnInventory ~= nil and item.OwnInventory.GetItemAt(0) == nil then
|
||||
local prefab = ItemPrefab.GetItemPrefab("batterycell")
|
||||
Entity.Spawner.AddItemToSpawnQueue(prefab, character.WorldPosition, nil, nil, function(batteryItem)
|
||||
item.OwnInventory.TryPutItem(batteryItem, character)
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
end, 1000)
|
||||
end)
|
||||
@@ -0,0 +1,34 @@
|
||||
-- Modders, please use ModDir:Neurotrauma when taking dependencies, and
|
||||
-- name your patches with the word "neurotrauma" (letter case doesnt matter)
|
||||
|
||||
-- sets NT.modconflict to true if incompatible mod detected
|
||||
-- this applies meta affliction "modconflict" every round
|
||||
-- prints out the warning and incompatible mod on server startup
|
||||
-- Hooks Lua event "roundStart" to do the above each round
|
||||
NT.modconflict = false
|
||||
function NT.CheckModConflicts()
|
||||
NT.modconflict = false
|
||||
if NTConfig.Get("NT_ignoreModConflicts", false) then return end
|
||||
|
||||
local itemsToCheck = { "antidama2", "opdeco_hospitalbed" }
|
||||
|
||||
for prefab in ItemPrefab.Prefabs do
|
||||
if HF.TableContains(itemsToCheck, prefab.Identifier.Value) then
|
||||
local mod = prefab.ConfigElement.ContentPackage.Name
|
||||
if not string.find(string.lower(mod), "neurotrauma") then
|
||||
NT.modconflict = true
|
||||
print("Found Neurotrauma incompatibility with mod: ", mod)
|
||||
print("WARNING! mod conflict detected! Neurotrauma may not function correctly and requires a patch!")
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Timer.Wait(function()
|
||||
NT.CheckModConflicts()
|
||||
end, 1000)
|
||||
Hook.Add("roundStart", "NT.RoundStart.modconflicts", function()
|
||||
Timer.Wait(function()
|
||||
NT.CheckModConflicts()
|
||||
end, 10000)
|
||||
end)
|
||||
+278
@@ -0,0 +1,278 @@
|
||||
-- NT functions for multiscalpel mode setting
|
||||
-- Hooks XML Lua events defined in the multiscalpel item.xml
|
||||
-- Hooks Lua event "roundStart" to RefreshAllMultiscalpels descriptions
|
||||
function NT.SetMultiscalpelFunction(item, func)
|
||||
if func ~= "" then
|
||||
item.Tags = "multiscalpel_" .. func
|
||||
else
|
||||
item.Tags = ""
|
||||
end
|
||||
NT.RefreshScalpelDescription(item)
|
||||
end
|
||||
|
||||
local function GetMultiscalpelMode(item)
|
||||
local functiontag = ""
|
||||
local tags = HF.SplitString(item.Tags, ",")
|
||||
for tag in tags do
|
||||
if HF.StartsWith(tag, "multiscalpel_") then
|
||||
functiontag = HF.SplitString(tag, "_")[2]
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
return functiontag
|
||||
end
|
||||
|
||||
function NT.RefreshScalpelDescription(item)
|
||||
-- if not HF.ItemHasTag(item,"init") then return end
|
||||
-- hostside only
|
||||
if Game.IsMultiplayer and CLIENT then return end
|
||||
|
||||
if not Entity.Spawner then
|
||||
Timer.Wait(function()
|
||||
NT.RefreshScalpelDescription(item)
|
||||
end, 35)
|
||||
return
|
||||
end
|
||||
|
||||
local functiontag = GetMultiscalpelMode(item)
|
||||
|
||||
if functiontag == "" then return end
|
||||
|
||||
local targetinventory = item.ParentInventory
|
||||
local targetslot = 0
|
||||
if targetinventory ~= nil then targetslot = targetinventory.FindIndex(item) end
|
||||
|
||||
local function SpawnFunc(newscalpelitem, targetinventory)
|
||||
if targetinventory ~= nil then targetinventory.TryPutItem(newscalpelitem, targetslot, true, true, nil) end
|
||||
newscalpelitem.DescriptionTag = "multiscalpel." .. functiontag
|
||||
newscalpelitem.Tags = "multiscalpel_" .. functiontag
|
||||
end
|
||||
HF.RemoveItem(item)
|
||||
Timer.Wait(function()
|
||||
local prefab = item.Prefab
|
||||
Entity.Spawner.AddItemToSpawnQueue(prefab, item.WorldPosition, nil, nil, function(newscalpelitem)
|
||||
SpawnFunc(newscalpelitem, targetinventory)
|
||||
end)
|
||||
end, 35)
|
||||
end
|
||||
|
||||
-- Let's faithfully believe Ydrec that said the item descriptions are already serialized by base game
|
||||
--Hook.Add("roundStart", "NT.RoundStart.Multiscalpels", function()
|
||||
-- Timer.Wait(function()
|
||||
-- NT.RefreshAllMultiscalpels()
|
||||
-- end, 10000) -- maybe 10 seconds is enough?
|
||||
--end)
|
||||
|
||||
function NT.RefreshAllMultiscalpels()
|
||||
-- descriptions dont get serialized, so i have to respawn
|
||||
-- every scalpel every round to keep their descriptions (big oof)
|
||||
|
||||
-- fetch scalpel items
|
||||
local scalpelItems = {}
|
||||
for item in Item.ItemList do
|
||||
if item.Prefab.Identifier.Value == "multiscalpel" then table.insert(scalpelItems, item) end
|
||||
end
|
||||
-- refresh items
|
||||
for scalpel in scalpelItems do
|
||||
NT.RefreshScalpelDescription(scalpel)
|
||||
end
|
||||
end
|
||||
--Timer.Wait(function()
|
||||
-- NT.RefreshAllMultiscalpels()
|
||||
--end, 50)
|
||||
|
||||
Hook.Add(
|
||||
"NT.multiscalpel.incision",
|
||||
"NT.multiscalpel.incision",
|
||||
function(effect, deltaTime, item, targets, worldPosition)
|
||||
NT.SetMultiscalpelFunction(item, "incision")
|
||||
end
|
||||
)
|
||||
Hook.Add("NT.multiscalpel.kidneys", "NT.multiscalpel.kidneys", function(effect, deltaTime, item, targets, worldPosition)
|
||||
NT.SetMultiscalpelFunction(item, "kidneys")
|
||||
end)
|
||||
Hook.Add("NT.multiscalpel.liver", "NT.multiscalpel.liver", function(effect, deltaTime, item, targets, worldPosition)
|
||||
NT.SetMultiscalpelFunction(item, "liver")
|
||||
end)
|
||||
Hook.Add("NT.multiscalpel.lungs", "NT.multiscalpel.lungs", function(effect, deltaTime, item, targets, worldPosition)
|
||||
NT.SetMultiscalpelFunction(item, "lungs")
|
||||
end)
|
||||
Hook.Add("NT.multiscalpel.heart", "NT.multiscalpel.heart", function(effect, deltaTime, item, targets, worldPosition)
|
||||
NT.SetMultiscalpelFunction(item, "heart")
|
||||
end)
|
||||
Hook.Add("NT.multiscalpel.brain", "NT.multiscalpel.brain", function(effect, deltaTime, item, targets, worldPosition)
|
||||
NT.SetMultiscalpelFunction(item, "brain")
|
||||
end)
|
||||
Hook.Add("NT.multiscalpel.bandage", "NT.multiscalpel.bandage", function(effect, deltaTime, item, targets, worldPosition)
|
||||
NT.SetMultiscalpelFunction(item, "bandage")
|
||||
end)
|
||||
Hook.Add(
|
||||
"NT.multiscalpel.speedflex",
|
||||
"NT.multiscalpel.speedflex",
|
||||
function(effect, deltaTime, item, targets, worldPosition)
|
||||
NT.SetMultiscalpelFunction(item, "speedflex")
|
||||
end
|
||||
)
|
||||
|
||||
NT.ItemMethods.multiscalpel = function(item, usingCharacter, targetCharacter, limb)
|
||||
local limbtype = HF.NormalizeLimbType(limb.type)
|
||||
|
||||
local mode = GetMultiscalpelMode(item)
|
||||
if mode == "" then mode = "none" end
|
||||
|
||||
local modeFunctions = {
|
||||
none = function(item, usingCharacter, targetCharacter, limb) end,
|
||||
incision = NT.ItemMethods.advscalpel,
|
||||
kidneys = NT.ItemMethods.organscalpel_kidneys,
|
||||
liver = NT.ItemMethods.organscalpel_liver,
|
||||
lungs = NT.ItemMethods.organscalpel_lungs,
|
||||
heart = NT.ItemMethods.organscalpel_heart,
|
||||
brain = NT.ItemMethods.organscalpel_brain,
|
||||
bandage = function(item, usingCharacter, targetCharacter, limb)
|
||||
-- remove casts, bandages, and if none of those apply, cause some damage
|
||||
|
||||
-- code snippet taken from NT.ItemMethods.traumashears
|
||||
-- does the target have any cuttable afflictions?
|
||||
local cuttables = HF.CombineArrays(NT.CuttableAfflictions, NT.TraumashearsAfflictions)
|
||||
local canCut = false
|
||||
for val in cuttables do
|
||||
local prefab = AfflictionPrefab.Prefabs[val]
|
||||
if prefab ~= nil then
|
||||
if prefab.LimbSpecific then
|
||||
if HF.HasAfflictionLimb(targetCharacter, val, limbtype, 0.1) then
|
||||
canCut = true
|
||||
break
|
||||
end
|
||||
elseif limbtype == prefab.IndicatorLimb then
|
||||
if HF.HasAffliction(targetCharacter, val, 0.1) then
|
||||
canCut = true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if canCut then
|
||||
NT.ItemMethods.traumashears(item, usingCharacter, targetCharacter, limb)
|
||||
else
|
||||
-- malpractice time!!!!
|
||||
local open = HF.HasAfflictionLimb(targetCharacter, "retractedskin", limbtype, 1)
|
||||
local istorso = limbtype == LimbType.Torso
|
||||
local ishead = limbtype == LimbType.Head
|
||||
|
||||
if not open then
|
||||
HF.AddAfflictionLimb(targetCharacter, "bleeding", limbtype, 6 + math.random() * 4, usingCharacter)
|
||||
HF.AddAfflictionLimb(
|
||||
targetCharacter,
|
||||
"lacerations",
|
||||
limbtype,
|
||||
2.5 + math.random() * 5,
|
||||
usingCharacter
|
||||
)
|
||||
HF.GiveItem(targetCharacter, "ntsfx_slash")
|
||||
else
|
||||
if istorso then
|
||||
-- stabbing an open torso (not good for the organs therein!)
|
||||
|
||||
HF.AddAffliction(targetCharacter, "internalbleeding", 6 + math.random() * 12, usingCharacter)
|
||||
HF.AddAfflictionLimb(
|
||||
targetCharacter,
|
||||
"lacerations",
|
||||
limbtype,
|
||||
4 + math.random() * 6,
|
||||
usingCharacter
|
||||
)
|
||||
HF.AddAfflictionLimb(
|
||||
targetCharacter,
|
||||
"internaldamage",
|
||||
limbtype,
|
||||
4 + math.random() * 6,
|
||||
usingCharacter
|
||||
)
|
||||
|
||||
local case = math.random()
|
||||
local casecount = 4
|
||||
if case < 1 / casecount then
|
||||
HF.AddAffliction(targetCharacter, "kidneydamage", 10 + math.random() * 10, usingCharacter)
|
||||
elseif case < 2 / casecount then
|
||||
HF.AddAffliction(targetCharacter, "liverdamage", 10 + math.random() * 10, usingCharacter)
|
||||
elseif case < 3 / casecount then
|
||||
HF.AddAffliction(targetCharacter, "lungdamage", 10 + math.random() * 10, usingCharacter)
|
||||
elseif case < 4 / casecount then
|
||||
HF.AddAffliction(targetCharacter, "heartdamage", 10 + math.random() * 10, usingCharacter)
|
||||
end
|
||||
elseif ishead then
|
||||
-- stabbing an open head (brain surgery done right!)
|
||||
|
||||
HF.AddAffliction(targetCharacter, "cerebralhypoxia", 15 + math.random() * 15, usingCharacter)
|
||||
HF.AddAfflictionLimb(
|
||||
targetCharacter,
|
||||
"internaldamage",
|
||||
limbtype,
|
||||
10 + math.random() * 10,
|
||||
usingCharacter
|
||||
)
|
||||
HF.AddAfflictionLimb(
|
||||
targetCharacter,
|
||||
"bleeding",
|
||||
limbtype,
|
||||
6 + math.random() * 12,
|
||||
usingCharacter
|
||||
)
|
||||
else
|
||||
-- stabbing an open arm or leg (how to cause fractures)
|
||||
|
||||
HF.AddAfflictionLimb(
|
||||
targetCharacter,
|
||||
"bleeding",
|
||||
limbtype,
|
||||
6 + math.random() * 6,
|
||||
usingCharacter
|
||||
)
|
||||
HF.AddAfflictionLimb(
|
||||
targetCharacter,
|
||||
"lacerations",
|
||||
limbtype,
|
||||
4 + math.random() * 6,
|
||||
usingCharacter
|
||||
)
|
||||
HF.AddAfflictionLimb(
|
||||
targetCharacter,
|
||||
"internaldamage",
|
||||
limbtype,
|
||||
4 + math.random() * 6,
|
||||
usingCharacter
|
||||
)
|
||||
if HF.Chance(0.1) then NT.BreakLimb(targetCharacter, limbtype) end
|
||||
end
|
||||
|
||||
HF.GiveItem(targetCharacter, "ntsfx_slash")
|
||||
end
|
||||
end
|
||||
end,
|
||||
speedflex = function(item, usingCharacter, targetCharacter, limb)
|
||||
local animcontroller = targetCharacter.AnimController
|
||||
local torsoLimb = limb
|
||||
if animcontroller ~= nil then torsoLimb = animcontroller.MainLimb end
|
||||
|
||||
if limbtype == LimbType.Head then
|
||||
NT.ItemMethods.organscalpel_brain(item, usingCharacter, targetCharacter, limb)
|
||||
elseif limbtype == LimbType.LeftArm then
|
||||
NT.ItemMethods.organscalpel_kidneys(item, usingCharacter, targetCharacter, torsoLimb)
|
||||
elseif limbtype == LimbType.Torso then
|
||||
NT.ItemMethods.organscalpel_liver(item, usingCharacter, targetCharacter, torsoLimb)
|
||||
elseif limbtype == LimbType.RightArm then
|
||||
NT.ItemMethods.organscalpel_heart(item, usingCharacter, targetCharacter, torsoLimb)
|
||||
elseif limbtype == LimbType.LeftLeg then
|
||||
NT.ItemMethods.organscalpel_lungs(item, usingCharacter, targetCharacter, torsoLimb)
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
if modeFunctions[mode] ~= nil then modeFunctions[mode](item, usingCharacter, targetCharacter, limb) end
|
||||
|
||||
if mode ~= "none" then Timer.Wait(function()
|
||||
item.Tags = "multiscalpel_" .. mode
|
||||
end, 50) end
|
||||
end
|
||||
+334
@@ -0,0 +1,334 @@
|
||||
NTC = {} -- a class containing compatibility functions for other mods to make use of neurotraumas symptom system
|
||||
|
||||
-- use this function to register your expansion mod to be displayed by the
|
||||
-- console lua startup readout of neurotrauma expansions
|
||||
|
||||
-- check surgery plus or cybernetics for an example
|
||||
-- example of code for registering your expansion in init.lua:
|
||||
|
||||
-- MyExp = {} -- Example Expansions
|
||||
-- MyExp.Name="My Expansion"
|
||||
-- MyExp.Version = "A1.0"
|
||||
-- MyExp.VersionNum = 01000000 -- split into two digits (01->1.; 00->0.; 00->0h; 00->0) -> 1.0.0h0
|
||||
-- MyExp.MinNTVersion = "A1.7.1"
|
||||
-- MyExp.MinNTVersionNum = 01070100 -- 01.07.01.00 -> A1.7.1h0
|
||||
-- Timer.Wait(function() if NT ~= nil then NTC.RegisterExpansion(MyExp) end end,1)
|
||||
|
||||
NTC.RegisteredExpansions = {}
|
||||
-- The function to add your addon to NT, see above for more info.
|
||||
---@param expansionMainObject table The table of the addon.
|
||||
function NTC.RegisterExpansion(expansionMainObject)
|
||||
table.insert(NTC.RegisteredExpansions, expansionMainObject)
|
||||
end
|
||||
|
||||
-- a table of tables, each character that has some custom data has an entry
|
||||
NTC.CharacterData = {}
|
||||
|
||||
-- use this function to induce symptoms temporarily
|
||||
-- duration is in humanupdates (~2 seconds), should at least be 2 to prevent symptom flickering
|
||||
---@param character Character The character to set the symptom on.
|
||||
---@param symptomidentifer string The identifier of the symptom.
|
||||
---@param duration integer The number of human updates it lasts for.
|
||||
function NTC.SetSymptomTrue(character, symptomidentifer, duration)
|
||||
if duration == nil then duration = 2 end
|
||||
|
||||
NTC.AddEmptyCharacterData(character)
|
||||
local data = NTC.GetCharacterData(character)
|
||||
data[symptomidentifer] = duration
|
||||
|
||||
NTC.CharacterData[character.ID] = data
|
||||
end
|
||||
|
||||
-- use this function to suppress symptoms temporarily. this takes precedence over NTC.SetSymptomTrue.
|
||||
-- duration is in humanupdates (~2 seconds), should at least be 2 to prevent symptom flickering
|
||||
---@param character Character The character to set the symptom on.
|
||||
---@param symptomidentifer string The identifier of the symptom.
|
||||
---@param duration integer The number of human updates it lasts for.
|
||||
function NTC.SetSymptomFalse(character, symptomidentifer, duration)
|
||||
if duration == nil then duration = 2 end
|
||||
|
||||
NTC.AddEmptyCharacterData(character)
|
||||
local data = NTC.GetCharacterData(character)
|
||||
data["!" .. symptomidentifer] = duration
|
||||
|
||||
NTC.CharacterData[character.ID] = data
|
||||
end
|
||||
|
||||
-- usage example: anywhere in your lua code, cause 4 seconds (2 humanupdates) of pale skin with this:
|
||||
-- NTC.SetSymptomTrue(targetCharacter,"sym_paleskin",2)
|
||||
|
||||
-- a list of possible symptom identifiers:
|
||||
|
||||
-- sym_unconsciousness
|
||||
-- tachycardia
|
||||
-- hyperventilation
|
||||
-- hypoventilation
|
||||
-- dyspnea
|
||||
-- sym_cough
|
||||
-- sym_paleskin
|
||||
-- sym_lightheadedness
|
||||
-- sym_blurredvision
|
||||
-- sym_confusion
|
||||
-- sym_headache
|
||||
-- sym_legswelling
|
||||
-- sym_weakness
|
||||
-- sym_wheezing
|
||||
-- sym_vomiting
|
||||
-- sym_nausea
|
||||
-- sym_hematemesis
|
||||
-- sym_fever
|
||||
-- sym_abdomdiscomfort
|
||||
-- sym_bloating
|
||||
-- sym_jaundice
|
||||
-- sym_sweating
|
||||
-- sym_palpitations
|
||||
-- sym_craving
|
||||
-- pain_abdominal
|
||||
-- pain_chest
|
||||
-- lockleftarm
|
||||
-- lockrightarm
|
||||
-- lockleftleg
|
||||
-- lockrightleg
|
||||
|
||||
-- with the following identifiers you can either cause things or prevent them.
|
||||
-- i recommend setting the duration when using these to cause things to 1.
|
||||
|
||||
-- triggersym_seizure
|
||||
-- triggersym_coma
|
||||
-- triggersym_stroke
|
||||
-- triggersym_heartattack
|
||||
-- triggersym_cardiacarrest
|
||||
-- triggersym_respiratoryarrest
|
||||
|
||||
-- prints all of the current compatibility data in the chat
|
||||
-- might be useful for debugging
|
||||
function NTC.DebugPrintAllData()
|
||||
local res = "neurotrauma compatibility data:\n"
|
||||
for key, value in pairs(NTC.CharacterData) do
|
||||
res = res .. "\n" .. value["character"].Name
|
||||
for key2, value2 in pairs(value) do
|
||||
res = res .. "\n " .. tostring(key2) .. " : " .. tostring(value2)
|
||||
end
|
||||
end
|
||||
|
||||
PrintChat(res)
|
||||
end
|
||||
|
||||
NTC.PreHumanUpdateHooks = {}
|
||||
-- use this function to add a function to be executed before humanupdate with a character parameter
|
||||
---@param func function The actual function to be called before a human update.
|
||||
function NTC.AddPreHumanUpdateHook(func)
|
||||
NTC.PreHumanUpdateHooks[#NTC.PreHumanUpdateHooks + 1] = func
|
||||
end
|
||||
|
||||
NTC.HumanUpdateHooks = {}
|
||||
-- use this function to add a function to be executed after humanupdate with a character parameter
|
||||
---@param func function The actual function to be called after a human update.
|
||||
function NTC.AddHumanUpdateHook(func)
|
||||
NTC.HumanUpdateHooks[#NTC.HumanUpdateHooks + 1] = func
|
||||
end
|
||||
|
||||
NTC.OnDamagedHooks = {}
|
||||
-- use this function to add a function to be executed after ondamaged
|
||||
-- with a characterhealth, attack result and limb parameter
|
||||
---@param func function The actual function to be called on damaged.
|
||||
function NTC.AddOnDamagedHook(func)
|
||||
NTC.OnDamagedHooks[#NTC.OnDamagedHooks + 1] = func
|
||||
end
|
||||
|
||||
NTC.ModifyingOnDamagedHooks = {}
|
||||
-- use this function to add a function to be executed before ondamaged
|
||||
-- with a characterhealth, afflictions and limb parameter, and afflictions return type
|
||||
---@param func function The actual function to be called on damaged. Modifying.
|
||||
function NTC.AddModifyingOnDamagedHook(func)
|
||||
NTC.ModifyingOnDamagedHooks[#NTC.ModifyingOnDamagedHooks + 1] = func
|
||||
end
|
||||
|
||||
NTC.CharacterSpeedMultipliers = {}
|
||||
-- use this function to multiply a characters speed for one human update.
|
||||
-- should always be called from within a prehumanupdate hook
|
||||
---@param character Character The character to set the speed multiplier to.
|
||||
---@param multiplier number The value of the multiplier.
|
||||
function NTC.MultiplySpeed(character, multiplier)
|
||||
if NTC.CharacterSpeedMultipliers[character] == nil then
|
||||
NTC.CharacterSpeedMultipliers[character] = multiplier
|
||||
else
|
||||
NTC.CharacterSpeedMultipliers[character] = NTC.CharacterSpeedMultipliers[character] * multiplier
|
||||
end
|
||||
end
|
||||
|
||||
-- use this function to register an affliction to be detected by the hematology analyzer
|
||||
---@param identifier string The identifier of the affliction to be visible on hematology.
|
||||
function NTC.AddHematologyAffliction(identifier)
|
||||
Timer.Wait(function()
|
||||
if not HF.TableContains(NT.HematologyDetectable, identifier) then
|
||||
table.insert(NT.HematologyDetectable, identifier)
|
||||
end
|
||||
end, 1)
|
||||
end
|
||||
|
||||
-- use this function to register an affliction to be healed by sutures
|
||||
-- identifier: the identifier of the affliction to be healed
|
||||
-- surgeryskillgain: how much surgery skill is gained by healing this affliction (optional, default: 0)
|
||||
-- requiredaffliction: what affliction has to be present alongside the healed affliction for it to get healed (optional, default: none)
|
||||
-- func: a function that gets run if the affliction is present. if provided, doesnt heal the affliction automatically (optional, default: none)
|
||||
-- func(item, usingCharacter, targetCharacter, limb)
|
||||
---@param identifier string The identifier of the affliction to be cured by sutures.
|
||||
---@param surgeryskillgain number The surgeryskill increase from sutured affliction.
|
||||
---@param requiredaffliction string The identifier of the requiredaffliction (Might need more documentation!)
|
||||
---@param func function The function to be called when the affliction is cured with sutures.
|
||||
function NTC.AddSuturedAffliction(identifier, surgeryskillgain, requiredaffliction, func)
|
||||
Timer.Wait(function()
|
||||
if not HF.TableContains(NT.SutureAfflictions, identifier) then
|
||||
NT.SutureAfflictions[identifier] = {
|
||||
xpgain = surgeryskillgain,
|
||||
case = requiredaffliction,
|
||||
func = func,
|
||||
}
|
||||
end
|
||||
end, 1)
|
||||
end
|
||||
|
||||
-- use this function to register an affliction to be healed by drainage
|
||||
---@param identifier string The identifier of the affliction to be healed.
|
||||
function NTC.AddDrainageAffliction(identifier)
|
||||
Timer.Wait(function()
|
||||
if not HF.TableContains(NT.DrainageAfflictions, identifier) then
|
||||
table.insert(NT.DrainageAfflictions, identifier)
|
||||
end
|
||||
end, 1)
|
||||
end
|
||||
|
||||
NTC.AfflictionsAffectingVitality = {
|
||||
bleeding = true,
|
||||
bleedingnonstop = true,
|
||||
burn = true,
|
||||
acidburn = true,
|
||||
lacerations = true,
|
||||
gunshotwound = true,
|
||||
bitewounds = true,
|
||||
explosiondamage = true,
|
||||
blunttrauma = true,
|
||||
internaldamage = true,
|
||||
organdamage = true,
|
||||
cerebralhypoxia = true,
|
||||
gangrene = true,
|
||||
th_amputation = true,
|
||||
sh_amputation = true,
|
||||
suturedw = true,
|
||||
alcoholaddiction = true,
|
||||
opiateaddiction = true,
|
||||
}
|
||||
-- use this function to register an affliction that will cause vitality damage. (Might need more documentation!)
|
||||
---@param identifier string The identifier of the affliction to cause damage.
|
||||
function NTC.AddAfflictionAffectingVitality(identifier)
|
||||
NTC.AfflictionsAffectingVitality[identifier] = true
|
||||
end
|
||||
|
||||
-- these functions are used by neurotrauma to check for symptom overrides
|
||||
---@param character Character The character to check the symptom on.
|
||||
---@param symptomidentifer string The identifier of the symptom.
|
||||
---@return boolean
|
||||
function NTC.GetSymptom(character, symptomidentifer)
|
||||
local chardata = NTC.GetCharacterData(character)
|
||||
if chardata == nil then return false end
|
||||
|
||||
local durationleft = chardata[symptomidentifer]
|
||||
|
||||
if durationleft == nil then return false end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
---@param character Character The character to check the symptom false on.
|
||||
---@param symptomidentifer string The identifier of the symptom false.
|
||||
---@return boolean
|
||||
function NTC.GetSymptomFalse(character, symptomidentifer)
|
||||
local chardata = NTC.GetCharacterData(character)
|
||||
if chardata == nil then return false end
|
||||
|
||||
local durationleft = chardata["!" .. symptomidentifer]
|
||||
|
||||
if durationleft == nil then return false end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-- sets multiplier data for one humanupdate, should be called from within a humanupdate hook
|
||||
---@param character Character The character to set the multiplier on.
|
||||
---@param multiplieridentifier string The identifier of the multiplier.
|
||||
---@param multiplier number The multiplier number.
|
||||
function NTC.SetMultiplier(character, multiplieridentifier, multiplier)
|
||||
NTC.AddEmptyCharacterData(character)
|
||||
local data = NTC.GetCharacterData(character)
|
||||
data["mult_" .. multiplieridentifier] = NTC.GetMultiplier(character, multiplieridentifier) * multiplier
|
||||
NTC.CharacterData[character.ID] = data
|
||||
end
|
||||
|
||||
---@param character Character The character to set the multiplier on.
|
||||
---@param multiplieridentifier string The identifier of the multiplier.
|
||||
function NTC.GetMultiplier(character, multiplieridentifier)
|
||||
local data = NTC.GetCharacterData(character)
|
||||
if data == nil or data["mult_" .. multiplieridentifier] == nil then return 1 end
|
||||
return data["mult_" .. multiplieridentifier]
|
||||
end
|
||||
|
||||
-- sets tag data for one humanupdate, should be called from within a humanupdate hook
|
||||
---@param character Character The character to set the tag on.
|
||||
---@param multiplieridentifier string The identifier of the tag.
|
||||
function NTC.SetTag(character, tagidentifier)
|
||||
NTC.AddEmptyCharacterData(character)
|
||||
local data = NTC.GetCharacterData(character)
|
||||
data["tag_" .. tagidentifier] = 1
|
||||
end
|
||||
function NTC.HasTag(character, tagidentifier)
|
||||
local data = NTC.GetCharacterData(character)
|
||||
if data == nil or data["tag_" .. tagidentifier] == nil then return false end
|
||||
return true
|
||||
end
|
||||
|
||||
-- // Utility functions //
|
||||
-- don't concern yourself with these
|
||||
function NTC.AddEmptyCharacterData(character)
|
||||
if NTC.GetCharacterData(character) ~= nil then return end
|
||||
local newdat = {}
|
||||
newdat["character"] = character
|
||||
NTC.CharacterData[character.ID] = newdat
|
||||
end
|
||||
function NTC.CheckChardataEmpty(character)
|
||||
local chardat = NTC.GetCharacterData(character)
|
||||
if chardat == nil or HF.TableSize(chardat) > 1 then return end
|
||||
|
||||
-- remove entry from data
|
||||
NTC.CharacterData[character.ID] = nil
|
||||
end
|
||||
function NTC.GetCharacterData(character)
|
||||
return NTC.CharacterData[character.ID]
|
||||
end
|
||||
function NTC.TickCharacter(character)
|
||||
local chardata = NTC.GetCharacterData(character)
|
||||
if chardata == nil then return end
|
||||
|
||||
for key, value in pairs(chardata) do
|
||||
if key ~= "character" then
|
||||
if HF.StartsWith(key, "mult_") then -- multipliers
|
||||
chardata[key] = nil
|
||||
NTC.CheckChardataEmpty(character)
|
||||
else -- symptoms
|
||||
local durationleft = value
|
||||
if durationleft ~= nil and durationleft > 1 then
|
||||
chardata[key] = durationleft - 1
|
||||
else
|
||||
chardata[key] = nil
|
||||
NTC.CheckChardataEmpty(character)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
NTC.CharacterData[character.ID] = chardata
|
||||
end
|
||||
function NTC.GetSpeedMultiplier(character)
|
||||
if NTC.CharacterSpeedMultipliers[character] ~= nil then return NTC.CharacterSpeedMultipliers[character] end
|
||||
return 1
|
||||
end
|
||||
+733
@@ -0,0 +1,733 @@
|
||||
-- Hooks Lua event "character.applyDamage" to cause NT afflictions after attacks depending on the damaging affliction defined here in NT.OnDamagedMethods
|
||||
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(
|
||||
"character.damageLimb",
|
||||
"NT.ondamagedby",
|
||||
function(
|
||||
character,
|
||||
worldPosition,
|
||||
hitLimb,
|
||||
afflictions,
|
||||
stun,
|
||||
playSound,
|
||||
attackImpulse,
|
||||
attacker,
|
||||
damageMultiplier,
|
||||
allowStacking,
|
||||
penetration,
|
||||
shouldImplode
|
||||
)
|
||||
if -- invalid attack data, don't do anything
|
||||
character == nil
|
||||
or character.IsDead
|
||||
or not character.IsHuman
|
||||
or afflictions == nil
|
||||
or hitLimb == nil
|
||||
or hitLimb.IsSevered
|
||||
or attacker == nil
|
||||
or not NTConfig.Get("NT_Calculations", true)
|
||||
then
|
||||
return
|
||||
end
|
||||
local creatureCategory = NTConfig.Get("NT_creatureNoFallDamage", 1)
|
||||
-- they make the game miserable with falldamage on
|
||||
for val in creatureCategory do
|
||||
if attacker.SpeciesName == val then
|
||||
HF.AddAffliction(character, "stopcreatureabuse", 2)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
)
|
||||
Hook.Add("character.applyDamage", "NT.ondamaged", function(characterHealth, attackResult, hitLimb)
|
||||
--print(hitLimb.HealthIndex or hitLimb ~= nil)
|
||||
|
||||
if -- invalid attack data, don't do anything
|
||||
characterHealth == nil
|
||||
or characterHealth.Character == nil
|
||||
or characterHealth.Character.IsDead
|
||||
or not characterHealth.Character.IsHuman
|
||||
or attackResult == nil
|
||||
or attackResult.Afflictions == nil
|
||||
or #attackResult.Afflictions <= 0
|
||||
or hitLimb == nil
|
||||
or hitLimb.IsSevered
|
||||
or not NTConfig.Get("NT_Calculations", true)
|
||||
then
|
||||
return
|
||||
end
|
||||
|
||||
if not HF.HasAffliction(characterHealth.Character, "luabotomy") then
|
||||
HF.SetAffliction(characterHealth.Character, "luabotomy", 1)
|
||||
end
|
||||
|
||||
local afflictions = attackResult.Afflictions
|
||||
|
||||
-- ntc
|
||||
-- modifying ondamaged hooks
|
||||
for key, val in pairs(NTC.ModifyingOnDamagedHooks) do
|
||||
afflictions = val(characterHealth, afflictions, hitLimb)
|
||||
end
|
||||
|
||||
local identifier = ""
|
||||
local methodtorun = nil
|
||||
for value in afflictions do
|
||||
-- execute fitting method, if available
|
||||
identifier = value.Prefab.Identifier.Value
|
||||
methodtorun = NT.OnDamagedMethods[identifier]
|
||||
if methodtorun ~= nil then
|
||||
-- make resistance from afflictions apply
|
||||
local resistance = HF.GetResistance(characterHealth.Character, identifier, hitLimb.type)
|
||||
local strength = value.Strength * (1 - resistance)
|
||||
|
||||
methodtorun(characterHealth.Character, strength, hitLimb.type)
|
||||
end
|
||||
end
|
||||
|
||||
-- ntc
|
||||
-- ondamaged hooks
|
||||
for key, val in pairs(NTC.OnDamagedHooks) do
|
||||
val(characterHealth, attackResult, hitLimb)
|
||||
end
|
||||
end)
|
||||
|
||||
NT.OnDamagedMethods = {}
|
||||
|
||||
local function HasLungs(c)
|
||||
return not HF.HasAffliction(c, "lungremoved")
|
||||
end
|
||||
local function HasHeart(c)
|
||||
return not HF.HasAffliction(c, "heartremoved")
|
||||
end
|
||||
|
||||
-- cause foreign bodies, rib fractures, pneumothorax, tamponade, internal bleeding, fractures, neurotrauma
|
||||
NT.OnDamagedMethods.gunshotwound = function(character, strength, limbtype)
|
||||
limbtype = HF.NormalizeLimbType(limbtype)
|
||||
|
||||
local causeFullForeignBody = false
|
||||
|
||||
-- torso specific
|
||||
if strength >= 1 and limbtype == LimbType.Torso then
|
||||
local hitOrgan = false
|
||||
if
|
||||
HF.Chance(
|
||||
HF.Clamp(strength * 0.02, 0, 0.3)
|
||||
* NTC.GetMultiplier(character, "anyfracturechance")
|
||||
* NTConfig.Get("NT_fractureChance", 1)
|
||||
)
|
||||
then
|
||||
NT.BreakLimb(character, limbtype)
|
||||
causeFullForeignBody = true
|
||||
end
|
||||
if
|
||||
HasLungs(character)
|
||||
and HF.Chance(
|
||||
0.3 * NTC.GetMultiplier(character, "pneumothoraxchance") * NTConfig.Get("NT_pneumothoraxChance", 1)
|
||||
)
|
||||
then
|
||||
HF.AddAffliction(character, "pneumothorax", 5)
|
||||
HF.AddAffliction(character, "lungdamage", strength)
|
||||
HF.AddAffliction(character, "organdamage", strength / 4)
|
||||
hitOrgan = true
|
||||
end
|
||||
if
|
||||
HasHeart(character)
|
||||
and hitOrgan == false
|
||||
and strength >= 5
|
||||
and HF.Chance(
|
||||
strength / 50 * NTC.GetMultiplier(character, "tamponadechance") * NTConfig.Get("NT_tamponadeChance", 1)
|
||||
)
|
||||
then
|
||||
HF.AddAffliction(character, "tamponade", 5)
|
||||
HF.AddAffliction(character, "heartdamage", strength)
|
||||
HF.AddAffliction(character, "organdamage", strength / 4)
|
||||
hitOrgan = true
|
||||
end
|
||||
if strength >= 5 then HF.AddAffliction(character, "internalbleeding", strength * HF.RandomRange(0.3, 0.6)) end
|
||||
|
||||
-- liver and kidney damage
|
||||
if hitOrgan == false and strength >= 2 and HF.Chance(0.5) then
|
||||
HF.AddAfflictionLimb(character, "organdamage", limbtype, strength / 4)
|
||||
if HF.Chance(0.5) then
|
||||
HF.AddAffliction(character, "liverdamage", strength)
|
||||
else
|
||||
HF.AddAffliction(character, "kidneydamage", strength)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- head
|
||||
if strength >= 1 and limbtype == LimbType.Head then
|
||||
if
|
||||
HF.Chance(
|
||||
strength / 90 * NTC.GetMultiplier(character, "anyfracturechance") * NTConfig.Get("NT_fractureChance", 1)
|
||||
)
|
||||
then
|
||||
NT.BreakLimb(character, limbtype)
|
||||
causeFullForeignBody = true
|
||||
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 strength >= 1 and HF.LimbIsExtremity(limbtype) then
|
||||
if
|
||||
NT.LimbIsBroken(character, limbtype)
|
||||
and not NT.LimbIsAmputated(character, limbtype)
|
||||
and HF.Chance(
|
||||
strength
|
||||
/ 60
|
||||
* NTC.GetMultiplier(character, "traumamputatechance")
|
||||
* NTConfig.Get("NT_traumaticAmputationChance", 1)
|
||||
)
|
||||
then
|
||||
NT.TraumamputateLimb(character, limbtype)
|
||||
end
|
||||
if
|
||||
HF.Chance(
|
||||
strength / 60 * NTC.GetMultiplier(character, "anyfracturechance") * NTConfig.Get("NT_fractureChance", 1)
|
||||
)
|
||||
then
|
||||
NT.BreakLimb(character, limbtype)
|
||||
causeFullForeignBody = true
|
||||
end
|
||||
end
|
||||
|
||||
-- foreign bodies
|
||||
if causeFullForeignBody then
|
||||
HF.AddAfflictionLimb(
|
||||
character,
|
||||
"foreignbody",
|
||||
limbtype,
|
||||
HF.Clamp(strength, 0, 30) * NTC.GetMultiplier(character, "foreignbodymultiplier")
|
||||
)
|
||||
else
|
||||
if HF.Chance(0.75) then
|
||||
HF.AddAfflictionLimb(
|
||||
character,
|
||||
"foreignbody",
|
||||
limbtype,
|
||||
HF.Clamp(strength / 4, 0, 20) * NTC.GetMultiplier(character, "foreignbodymultiplier")
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- cause foreign bodies, rib fractures, pneumothorax, internal bleeding, concussion, fractures
|
||||
NT.OnDamagedMethods.explosiondamage = function(character, strength, limbtype)
|
||||
limbtype = HF.NormalizeLimbType(limbtype)
|
||||
|
||||
if HF.Chance(0.75) then
|
||||
HF.AddAfflictionLimb(
|
||||
character,
|
||||
"foreignbody",
|
||||
limbtype,
|
||||
strength / 2 * NTC.GetMultiplier(character, "foreignbodymultiplier")
|
||||
)
|
||||
end
|
||||
|
||||
-- torso specific
|
||||
if strength >= 1 and limbtype == LimbType.Torso then
|
||||
if
|
||||
strength >= 10
|
||||
and HF.Chance(
|
||||
strength / 50 * NTC.GetMultiplier(character, "anyfracturechance") * NTConfig.Get("NT_fractureChance", 1)
|
||||
)
|
||||
then
|
||||
NT.BreakLimb(character, limbtype)
|
||||
end
|
||||
if
|
||||
HasLungs(character)
|
||||
and strength >= 5
|
||||
and HF.Chance(
|
||||
strength
|
||||
/ 50
|
||||
* NTC.GetMultiplier(character, "pneumothoraxchance")
|
||||
* NTConfig.Get("NT_pneumothoraxChance", 1)
|
||||
)
|
||||
then
|
||||
HF.AddAffliction(character, "pneumothorax", 5)
|
||||
end
|
||||
if strength >= 5 then HF.AddAffliction(character, "internalbleeding", strength * HF.RandomRange(0.2, 0.5)) end
|
||||
end
|
||||
|
||||
-- head
|
||||
if strength >= 1 and limbtype == LimbType.Head then
|
||||
if strength >= 15 and HF.Chance(math.min(strength / 60, 0.7)) then
|
||||
local armor1 = character.Inventory.GetItemInLimbSlot(InvSlotType.OuterClothes)
|
||||
local armor2 = character.Inventory.GetItemInLimbSlot(InvSlotType.Head)
|
||||
local reduceddmg = math.max(
|
||||
10
|
||||
- getCalculatedConcussionReduction(armor1, 10, limbtype)
|
||||
- getCalculatedConcussionReduction(armor2, 10, limbtype),
|
||||
0
|
||||
)
|
||||
HF.AddAfflictionResisted(character, "concussion", reduceddmg)
|
||||
end
|
||||
if
|
||||
strength >= 15
|
||||
and HF.Chance(
|
||||
math.min(strength / 60, 0.7)
|
||||
* NTC.GetMultiplier(character, "anyfracturechance")
|
||||
* NTConfig.Get("NT_fractureChance", 1)
|
||||
)
|
||||
then
|
||||
NT.BreakLimb(character, limbtype)
|
||||
end
|
||||
if
|
||||
strength >= 15
|
||||
and HF.Chance(
|
||||
math.min(strength / 60, 0.7)
|
||||
* NTC.GetMultiplier(character, "anyfracturechance")
|
||||
* NTConfig.Get("NT_fractureChance", 1)
|
||||
)
|
||||
then
|
||||
HF.AddAffliction(character, "n_fracture", 5)
|
||||
end
|
||||
if strength >= 75 and HF.Chance(0.25) then
|
||||
-- drop previously held item
|
||||
local previtem = HF.GetHeadWear(character)
|
||||
if previtem ~= nil then previtem.Drop(character, true) end
|
||||
NT.TraumamputateLimb(character, limbtype)
|
||||
end
|
||||
end
|
||||
|
||||
-- extremities
|
||||
if strength >= 1 and HF.LimbIsExtremity(limbtype) then
|
||||
if
|
||||
NT.LimbIsBroken(character, limbtype)
|
||||
and not NT.LimbIsAmputated(character, limbtype)
|
||||
and HF.Chance(
|
||||
strength
|
||||
/ 60
|
||||
* NTC.GetMultiplier(character, "traumamputatechance")
|
||||
* NTConfig.Get("NT_traumaticAmputationChance", 1)
|
||||
)
|
||||
then
|
||||
NT.TraumamputateLimb(character, limbtype)
|
||||
end
|
||||
if
|
||||
HF.Chance(
|
||||
strength / 60 * NTC.GetMultiplier(character, "anyfracturechance") * NTConfig.Get("NT_fractureChance", 1)
|
||||
)
|
||||
then
|
||||
NT.BreakLimb(character, limbtype)
|
||||
end
|
||||
if
|
||||
HF.Chance(
|
||||
0.35 * NTC.GetMultiplier(character, "dislocationchance") * NTConfig.Get("NT_dislocationChance", 1)
|
||||
) and not NT.LimbIsAmputated(character, limbtype)
|
||||
then
|
||||
NT.DislocateLimb(character, limbtype)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- cause rib fractures, pneumothorax, internal bleeding, concussion, fractures
|
||||
NT.OnDamagedMethods.bitewounds = function(character, strength, limbtype)
|
||||
limbtype = HF.NormalizeLimbType(limbtype)
|
||||
|
||||
-- torso specific
|
||||
if strength >= 1 and limbtype == LimbType.Torso then
|
||||
if
|
||||
strength >= 10
|
||||
and HF.Chance(
|
||||
(strength - 10)
|
||||
/ 50
|
||||
* NTC.GetMultiplier(character, "anyfracturechance")
|
||||
* NTConfig.Get("NT_fractureChance", 1)
|
||||
)
|
||||
then
|
||||
NT.BreakLimb(character, limbtype)
|
||||
end
|
||||
if
|
||||
HasLungs(character)
|
||||
and strength >= 5
|
||||
and HF.Chance(
|
||||
(strength - 5)
|
||||
/ 50
|
||||
* NTC.GetMultiplier(character, "pneumothoraxchance")
|
||||
* NTConfig.Get("NT_pneumothoraxChance", 1)
|
||||
)
|
||||
then
|
||||
HF.AddAffliction(character, "pneumothorax", 5)
|
||||
end
|
||||
if strength >= 5 then HF.AddAffliction(character, "internalbleeding", strength * HF.RandomRange(0.2, 0.5)) end
|
||||
end
|
||||
|
||||
-- head
|
||||
if strength >= 1 and limbtype == LimbType.Head then
|
||||
if strength >= 15 and HF.Chance(math.min(strength / 60, 0.7)) then
|
||||
local armor1 = character.Inventory.GetItemInLimbSlot(InvSlotType.OuterClothes)
|
||||
local armor2 = character.Inventory.GetItemInLimbSlot(InvSlotType.Head)
|
||||
local reduceddmg = math.max(
|
||||
10
|
||||
- getCalculatedConcussionReduction(armor1, 10, limbtype)
|
||||
- getCalculatedConcussionReduction(armor2, 10, limbtype),
|
||||
0
|
||||
)
|
||||
HF.AddAfflictionResisted(character, "concussion", reduceddmg)
|
||||
end
|
||||
if
|
||||
strength >= 15
|
||||
and HF.Chance(
|
||||
math.min((strength - 10) / 60, 0.7)
|
||||
* NTC.GetMultiplier(character, "anyfracturechance")
|
||||
* NTConfig.Get("NT_fractureChance", 1)
|
||||
)
|
||||
then
|
||||
NT.BreakLimb(character, limbtype)
|
||||
end
|
||||
end
|
||||
|
||||
-- extremities
|
||||
if strength >= 1 and HF.LimbIsExtremity(limbtype) then
|
||||
if
|
||||
NT.LimbIsBroken(character, limbtype)
|
||||
and not NT.LimbIsAmputated(character, limbtype)
|
||||
and HF.Chance(
|
||||
(strength - 5)
|
||||
/ 60
|
||||
* NTC.GetMultiplier(character, "traumamputatechance")
|
||||
* NTConfig.Get("NT_traumaticAmputationChance", 1)
|
||||
)
|
||||
then
|
||||
NT.TraumamputateLimb(character, limbtype, character.LastAttacker)
|
||||
end
|
||||
if
|
||||
HF.Chance(
|
||||
(strength - 5)
|
||||
/ 60
|
||||
* NTC.GetMultiplier(character, "anyfracturechance")
|
||||
* NTConfig.Get("NT_fractureChance", 1)
|
||||
)
|
||||
then
|
||||
NT.BreakLimb(character, limbtype)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- cause rib fractures, pneumothorax, tamponade, internal bleeding, fractures
|
||||
NT.OnDamagedMethods.lacerations = function(character, strength, limbtype)
|
||||
limbtype = HF.NormalizeLimbType(limbtype)
|
||||
|
||||
-- torso specific
|
||||
if strength >= 1 and limbtype == LimbType.Torso then
|
||||
if
|
||||
strength >= 10
|
||||
and HF.Chance(
|
||||
(strength - 10)
|
||||
/ 50
|
||||
* NTC.GetMultiplier(character, "anyfracturechance")
|
||||
* NTConfig.Get("NT_fractureChance", 1)
|
||||
)
|
||||
then
|
||||
NT.BreakLimb(character, limbtype)
|
||||
end
|
||||
if
|
||||
HasLungs(character)
|
||||
and strength >= 5
|
||||
and HF.Chance(
|
||||
(strength - 5)
|
||||
/ 50
|
||||
* NTC.GetMultiplier(character, "pneumothoraxchance")
|
||||
* NTConfig.Get("NT_pneumothoraxChance", 1)
|
||||
)
|
||||
then
|
||||
HF.AddAffliction(character, "pneumothorax", 5)
|
||||
end
|
||||
if
|
||||
HasHeart(character)
|
||||
and strength >= 5
|
||||
and HF.Chance(
|
||||
(strength - 5)
|
||||
/ 50
|
||||
* NTC.GetMultiplier(character, "tamponadechance")
|
||||
* NTConfig.Get("NT_tamponadeChance", 1)
|
||||
)
|
||||
then
|
||||
HF.AddAffliction(character, "tamponade", 5)
|
||||
end
|
||||
if strength >= 5 then HF.AddAffliction(character, "internalbleeding", strength * HF.RandomRange(0.2, 0.5)) end
|
||||
end
|
||||
|
||||
-- head
|
||||
if strength >= 1 and limbtype == LimbType.Head then
|
||||
if
|
||||
strength >= 15
|
||||
and HF.Chance(
|
||||
math.min((strength - 15) / 60, 0.7)
|
||||
* NTC.GetMultiplier(character, "anyfracturechance")
|
||||
* NTConfig.Get("NT_fractureChance", 1)
|
||||
)
|
||||
then
|
||||
NT.BreakLimb(character, limbtype)
|
||||
end
|
||||
end
|
||||
|
||||
-- extremities
|
||||
if strength >= 1 and HF.LimbIsExtremity(limbtype) then
|
||||
if
|
||||
NT.LimbIsBroken(character, limbtype)
|
||||
and not NT.LimbIsAmputated(character, limbtype)
|
||||
and HF.Chance(
|
||||
strength
|
||||
/ 60
|
||||
* NTC.GetMultiplier(character, "traumamputatechance")
|
||||
* NTConfig.Get("NT_traumaticAmputationChance", 1)
|
||||
)
|
||||
then
|
||||
NT.TraumamputateLimb(character, limbtype)
|
||||
end
|
||||
if
|
||||
HF.Chance(
|
||||
(strength - 5)
|
||||
/ 60
|
||||
* NTC.GetMultiplier(character, "anyfracturechance")
|
||||
* NTConfig.Get("NT_fractureChance", 1)
|
||||
)
|
||||
then
|
||||
NT.BreakLimb(character, limbtype)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- cause rib fractures, organ damage, pneumothorax, concussion, fractures, neurotrauma
|
||||
NT.OnDamagedMethods.blunttrauma = function(character, strength, limbtype)
|
||||
limbtype = HF.NormalizeLimbType(limbtype)
|
||||
|
||||
local fractureImmune = HF.HasAffliction(character, "cpr_fracturebuff")
|
||||
|
||||
-- torso
|
||||
if not fractureImmune and strength >= 1 and limbtype == LimbType.Torso then
|
||||
if
|
||||
HF.Chance(
|
||||
strength / 50 * NTC.GetMultiplier(character, "anyfracturechance") * NTConfig.Get("NT_fractureChance", 1)
|
||||
)
|
||||
then
|
||||
NT.BreakLimb(character, limbtype)
|
||||
end
|
||||
|
||||
HF.AddAffliction(character, "lungdamage", strength * HF.RandomRange(0, 1))
|
||||
HF.AddAffliction(character, "heartdamage", strength * HF.RandomRange(0, 1))
|
||||
HF.AddAffliction(character, "liverdamage", strength * HF.RandomRange(0, 1))
|
||||
HF.AddAffliction(character, "kidneydamage", strength * HF.RandomRange(0, 1))
|
||||
HF.AddAffliction(character, "organdamage", strength * HF.RandomRange(0, 1))
|
||||
|
||||
if
|
||||
HasLungs(character)
|
||||
and strength >= 5
|
||||
and HF.Chance(
|
||||
strength
|
||||
/ 50
|
||||
* NTC.GetMultiplier(character, "pneumothoraxchance")
|
||||
* NTConfig.Get("NT_pneumothoraxChance", 1)
|
||||
)
|
||||
then
|
||||
HF.AddAffliction(character, "pneumothorax", 5)
|
||||
end
|
||||
end
|
||||
|
||||
-- head
|
||||
if not fractureImmune and strength >= 1 and limbtype == LimbType.Head then
|
||||
if strength >= 15 and HF.Chance(math.min(strength / 60, 0.7)) then
|
||||
local armor1 = character.Inventory.GetItemInLimbSlot(InvSlotType.OuterClothes)
|
||||
local armor2 = character.Inventory.GetItemInLimbSlot(InvSlotType.Head)
|
||||
local reduceddmg = math.max(
|
||||
10
|
||||
- getCalculatedConcussionReduction(armor1, 10, limbtype)
|
||||
- getCalculatedConcussionReduction(armor2, 10, limbtype),
|
||||
0
|
||||
)
|
||||
HF.AddAfflictionResisted(character, "concussion", reduceddmg)
|
||||
end
|
||||
if
|
||||
strength >= 15
|
||||
and HF.Chance(
|
||||
math.min((strength - 10) / 60, 0.7)
|
||||
* NTC.GetMultiplier(character, "anyfracturechance")
|
||||
* NTConfig.Get("NT_fractureChance", 1)
|
||||
)
|
||||
then
|
||||
NT.BreakLimb(character, limbtype)
|
||||
end
|
||||
if
|
||||
strength >= 15
|
||||
and HF.Chance(
|
||||
math.min((strength - 10) / 60, 0.7)
|
||||
* NTC.GetMultiplier(character, "anyfracturechance")
|
||||
* NTConfig.Get("NT_fractureChance", 1)
|
||||
)
|
||||
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
|
||||
strength > 15
|
||||
and NT.LimbIsBroken(character, limbtype)
|
||||
and not NT.LimbIsAmputated(character, limbtype)
|
||||
and HF.Chance(
|
||||
strength
|
||||
/ 100
|
||||
* NTC.GetMultiplier(character, "traumamputatechance")
|
||||
* NTConfig.Get("NT_traumaticAmputationChance", 1)
|
||||
)
|
||||
then
|
||||
NT.TraumamputateLimb(character, limbtype)
|
||||
end
|
||||
if
|
||||
HF.Chance(
|
||||
(strength - 2)
|
||||
/ 60
|
||||
* NTC.GetMultiplier(character, "anyfracturechance")
|
||||
* NTConfig.Get("NT_fractureChance", 1)
|
||||
)
|
||||
then
|
||||
NT.BreakLimb(character, limbtype)
|
||||
end
|
||||
if
|
||||
HF.Chance(
|
||||
HF.Clamp((strength - 2) / 80, 0, 0.5)
|
||||
* NTC.GetMultiplier(character, "dislocationchance")
|
||||
* NTConfig.Get("NT_dislocationChance", 1)
|
||||
) and not NT.LimbIsAmputated(character, limbtype)
|
||||
then
|
||||
NT.DislocateLimb(character, limbtype)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- cause rib fractures, organ damage, pneumothorax, concussion, fractures
|
||||
NT.OnDamagedMethods.internaldamage = function(character, strength, limbtype)
|
||||
limbtype = HF.NormalizeLimbType(limbtype)
|
||||
|
||||
-- torso
|
||||
if strength >= 1 and limbtype == LimbType.Torso then
|
||||
if
|
||||
HF.Chance(
|
||||
(strength - 5)
|
||||
/ 50
|
||||
* NTC.GetMultiplier(character, "anyfracturechance")
|
||||
* NTConfig.Get("NT_fractureChance", 1)
|
||||
)
|
||||
then
|
||||
NT.BreakLimb(character, limbtype)
|
||||
end
|
||||
|
||||
HF.AddAffliction(character, "lungdamage", strength * HF.RandomRange(0, 1))
|
||||
HF.AddAffliction(character, "heartdamage", strength * HF.RandomRange(0, 1))
|
||||
HF.AddAffliction(character, "liverdamage", strength * HF.RandomRange(0, 1))
|
||||
HF.AddAffliction(character, "kidneydamage", strength * HF.RandomRange(0, 1))
|
||||
HF.AddAffliction(character, "organdamage", strength * HF.RandomRange(0, 1))
|
||||
|
||||
if
|
||||
HasLungs(character)
|
||||
and strength >= 5
|
||||
and HF.Chance(
|
||||
(strength - 5)
|
||||
/ 50
|
||||
* NTC.GetMultiplier(character, "pneumothoraxchance")
|
||||
* NTConfig.Get("NT_pneumothoraxChance", 1)
|
||||
)
|
||||
then
|
||||
HF.AddAffliction(character, "pneumothorax", 5)
|
||||
end
|
||||
end
|
||||
|
||||
-- head
|
||||
if strength >= 1 and limbtype == LimbType.Head then
|
||||
if strength >= 15 and HF.Chance(math.min(strength / 60, 0.7)) then
|
||||
local armor1 = character.Inventory.GetItemInLimbSlot(InvSlotType.OuterClothes)
|
||||
local armor2 = character.Inventory.GetItemInLimbSlot(InvSlotType.Head)
|
||||
local reduceddmg = math.max(
|
||||
10
|
||||
- getCalculatedConcussionReduction(armor1, 10, limbtype)
|
||||
- getCalculatedConcussionReduction(armor2, 10, limbtype),
|
||||
0
|
||||
)
|
||||
HF.AddAfflictionResisted(character, "concussion", reduceddmg)
|
||||
end
|
||||
if
|
||||
strength >= 15
|
||||
and HF.Chance(
|
||||
math.min((strength - 5) / 60, 0.7)
|
||||
* NTC.GetMultiplier(character, "anyfracturechance")
|
||||
* NTConfig.Get("NT_fractureChance", 1)
|
||||
)
|
||||
then
|
||||
NT.BreakLimb(character, limbtype)
|
||||
end
|
||||
if
|
||||
strength >= 15
|
||||
and HF.Chance(
|
||||
math.min((strength - 5) / 60, 0.7)
|
||||
* NTC.GetMultiplier(character, "anyfracturechance")
|
||||
* NTConfig.Get("NT_fractureChance", 1)
|
||||
)
|
||||
then
|
||||
HF.AddAffliction(character, "n_fracture", 5)
|
||||
end
|
||||
end
|
||||
|
||||
-- extremities
|
||||
if strength >= 1 and HF.LimbIsExtremity(limbtype) then
|
||||
if
|
||||
strength > 10
|
||||
and NT.LimbIsBroken(character, limbtype)
|
||||
and not NT.LimbIsAmputated(character, limbtype)
|
||||
and HF.Chance(
|
||||
(strength - 10)
|
||||
/ 60
|
||||
* NTC.GetMultiplier(character, "traumamputatechance")
|
||||
* NTConfig.Get("NT_traumaticAmputationChance", 1)
|
||||
)
|
||||
then
|
||||
NT.TraumamputateLimb(character, limbtype)
|
||||
end
|
||||
if
|
||||
HF.Chance(
|
||||
(strength - 5)
|
||||
/ 60
|
||||
* NTC.GetMultiplier(character, "anyfracturechance")
|
||||
* NTConfig.Get("NT_fractureChance", 1)
|
||||
)
|
||||
then
|
||||
NT.BreakLimb(character, limbtype)
|
||||
end
|
||||
if
|
||||
HF.Chance(
|
||||
0.25 * NTC.GetMultiplier(character, "dislocationchance") * NTConfig.Get("NT_dislocationChance", 1)
|
||||
) and not NT.LimbIsAmputated(character, limbtype)
|
||||
then
|
||||
NT.DislocateLimb(character, limbtype)
|
||||
end
|
||||
end
|
||||
end
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
-- Hooks Lua event "Barotrauma.Character" to apply vanilla burning (formerly NT onfire) affliction and set a human on fire
|
||||
Hook.HookMethod("Barotrauma.Character", "ApplyStatusEffects", function(instance, ptable)
|
||||
if ptable.actionType == ActionType.OnFire then
|
||||
local function ApplyBurn(character, limbtype)
|
||||
HF.AddAfflictionLimb(character, "burning", limbtype, ptable.deltaTime * 3)
|
||||
end
|
||||
|
||||
if instance.IsHuman then
|
||||
if not HF.HasAffliction(instance, "luabotomy") then HF.SetAffliction(instance, "luabotomy", 1) end
|
||||
ApplyBurn(instance, LimbType.Torso)
|
||||
ApplyBurn(instance, LimbType.Head)
|
||||
ApplyBurn(instance, LimbType.LeftArm)
|
||||
ApplyBurn(instance, LimbType.RightArm)
|
||||
ApplyBurn(instance, LimbType.LeftLeg)
|
||||
ApplyBurn(instance, LimbType.RightLeg)
|
||||
else
|
||||
HF.AddAfflictionLimb(instance, "burning", instance.AnimController.MainLimb.type, ptable.deltaTime * 5)
|
||||
end
|
||||
end
|
||||
end, Hook.HookMethodType.After)
|
||||
@@ -0,0 +1,7 @@
|
||||
-- Hooks XML Lua event "NT.causeScreams" to cause character to scream if config has enabled screaming
|
||||
Hook.Add("NT.causeScreams", "NT.causeScreams", function(...)
|
||||
if not NTConfig.Get("NT_screams", true) then return end
|
||||
|
||||
local character = table.pack(...)[3]
|
||||
HF.SetAffliction(character, "screaming", 10)
|
||||
end)
|
||||
Reference in New Issue
Block a user