Files
BarotraumaModServer/LocalMods/Neurotrauma/Lua/Scripts/Server/multiscalpel.lua
2026-06-09 00:42:10 +03:00

279 lines
9.3 KiBLFS
Lua
Executable File

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