I actually did have a chance to fix the severed issue. This will now properly sever everything connected to a severed body part.
local utils = require 'utils'
function checkconnectedparts(unit,parts)
for i,x in pairs(parts) do
for j,y in pairs(unit.body.body_plan.body_parts) do
if y.con_part_id == x then
table.insert(parts,j)
end
end
end
return parts
end
function checkbodycategory(unit,bp)
local parts = {}
local body = unit.body.body_plan.body_parts
for i,x in ipairs(bp) do
local a = 1
for j,y in ipairs(body) do
if y.category == x and not unit.body.components.body_part_status[j].missing then
parts[a] = j
a = a + 1
end
end
end
return parts
end
function checkbodytoken(unit,bp)
local parts = {}
local body = unit.body.body_plan.body_parts
for i,x in ipairs(bp) do
local a = 1
for j,y in ipairs(body) do
if y.token == x and not unit.body.components.body_part_status[j].missing then
parts[a] = j
a = a + 1
end
end
end
return parts
end
function checkbodyflag(unit,bp)
local parts = {}
local body = unit.body.body_plan.body_parts
for i,x in ipairs(bp) do
local a = 1
for j,y in ipairs(body) do
if y.flags[x] and not unit.body.components.body_part_status[j].missing then
parts[a] = j
a = a + 1
end
end
end
return parts
end
function checkbodylayer(unit,parts,layers)
local a = 1
local array = {}
for i,x in pairs(parts) do
local part = unit.body.body_plan.body_parts[x]
for j,y in pairs(layers) do
for k,z in pairs(part.layers) do
if z.layer_name == y or y == 'ALL' then
array[a] = {x,k,z.layer_id}
a = a+1
end
end
end
end
return array
end
function addwound(unit,array,numbers,effect,flags,attacker,args)
local body = unit.body
local wound = df.unit_wound:new()
wound.id = body.wound_next_id
body.wound_next_id = body.wound_next_id + 1
if attacker and tonumber(attacker) then wound.attacker_unit_id = tonumber(attacker) end
if args.severed then -- For applying wounds that remove body parts (doesn't produce severed body part)
wound.flags.severed_part = true
for i,x in pairs(array) do
part = df.unit_wound.T_parts:new()
part.global_layer_idx = x[3]
part.layer_idx = x[2]
part.body_part_id = x[1]
for j,y in pairs(numbers) do
if y and tonumber(y) then part[j] = tonumber(y) end
end
part.contact_area = 1
part.surface_perc = 0
part.strain = 0
part.cur_penetration_perc = 0
part.max_penetration_perc = 0
wound.parts:insert('#',part)
body.components.body_part_status[x[1]].missing = true
body.components.body_part_status[x[1]].muscle_damage = true
body.components.body_part_status[x[1]].muscle_loss = true
body.components.body_part_status[x[1]].bone_damage = true
body.components.body_part_status[x[1]].bone_loss = true
body.components.body_part_status[x[1]].skin_damage = true
body.components.body_part_status[x[1]].severed_or_jammed = true
body.components.layer_status[x[3]].gone = true
body.components.layer_cut_fraction[x[3]] = 10000
body.components.layer_dent_fraction[x[3]] = 10000
end
elseif args.mortal then -- For applying wounds that kill unit (not really useful, mortal wounds are all so different)
wound.flags.mortal_wound = true
body.blood_count = 0
else -- For applying all other types of wounds
for i,x in pairs(array) do
part = df.unit_wound.T_parts:new()
part.global_layer_idx = x[3]
part.layer_idx = x[2]
part.body_part_id = x[1]
for j,y in pairs(numbers) do
if y and tonumber(y) then part[j] = tonumber(y) end
end
if effect then
part.effect_type:insert('#',tonumber(df.wound_effect_type[effect[1]]))
part.effect_perc1:insert('#',tonumber(effect[2]))
part.effect_perc2:insert('#',tonumber(effect[3]))
end
if args.surface_perc >= 100 then part.flags2.entire_surface = true end
for j,y in pairs(flags) do
part.flags1[y] = true
end
wound.parts:insert('#',part)
if part.strain >= 50000 then
body.components.layer_dent_fraction[x[3]] = body.components.layer_dent_fraction[x[3]] + part.aurface_perc*part.cur_penetration_perc
body.components.layer_cut_fraction[x[3]] = body.components.layer_cut_fraction[x[3]] + part.aurface_perc*part.cur_penetration_per
elseif part.strain > 0 then
body.components.layer_cut_fraction[x[3]] = body.components.layer_cut_fraction[x[3]] + part.aurface_perc*part.cur_penetration_perc
elseif part.strain == 0 and effect then
body.components.layer_effect_fraction[x[3]] = body.components.layer_effect_fraction[x[3]] + part.aurface_perc*part.effect_perc1[0]
end
if part.strain >= 50000 and part.cur_penetration_per >= 100 then
body.components.layer_wound_area[x[3]] = body.components.layer_wound_area[x[3]] + part.contact_area
end
end
body.wounds:insert('#',wound)
end
end
validArgs = validArgs or utils.invert({
'help',
'category',
'token',
'flag',
'all',
'layer',
'unit',
'bleeding',
'pain',
'nausea',
'dizziness',
'paralysis',
'numbness',
'swelling',
'impaired',
'strain',
'contact_area',
'surface_perc',
'penetration',
'effect',
'attacker',
'flags',
'mortal',
'severed',
'infection',
})
local args = utils.processArgs({...}, validArgs)
if args.help then -- Help declaration
print([[wound-add.lua
Assign a wound to a specific body part and layer of a unit
arguments:
-help
print this help message
-unit id
REQUIRED
id of the target unit
-attacker id
-all \
target all body parts |
-category TYPE |
examples: |
TENTACLE |
HOOF_REAR |
HEAD |
-token TYPE | Must have at least one of these
examples: |
UB |
LB |
REYE |
-flag FLAG |
examples: |
SIGHT |
LIMB |
SMALL /
-layer TYPE
examples:
SKIN
FAT
MUSCLE
ALL
-bleeding #
set bleeding amount for all layers
-pain #
set pain amount for all layers
-nausea #
set nausea amount for all layers
-dizziness #
set dizziness amount for all layers
-paralysis #
set paralysis amount for all layers
-numbness #
set numbness amount for all layers
-swelling #
set swelling amount for all layers
-impaired #
set impaired amount for all layers
-strain #
set strain level for all layers
-contact_area #
set contact area of wound for all layers
-surface_perc #
set surface area affected percentage for all layers
-penetration #
set penetration depth percentage for all layers
-effect [ type # # ]
set what type of wound it is, numbers are percentages, unknown their exact affect
valid types
Bruise
Burn
Frostbite
Melting
Boiling
Freezing
Condensation
Necrosis
Blister
-flags [ flags ]
set which flags are toggled for the wound
valid flags
cut
smashed
scar_cut
scar_smashed
tendon_bruised
tendon_strained
tendon_torn
ligament_bruised
ligament_sprained
ligament_torn
motor_nerve_severed
sensory_nerve_severed
edged_damage
smashed_apart
major_artery
guts_spilled
edged_shake1
scar_edged_shake1
edged_shake2
broken
scar_broken
gouged
blunt_shake1
scar_blunt_shake1
blunt_shake2
joint_bend1
scar_joint_bend1
joint_bend2
compound_fracture
overlapping_fracture
artery
-mortal
sets the wound as a mortal wound (kills the unit by lack of blood)
-severed
sets the body part as severed and removes it (severed body part is not created)
examples:
unit/wound-add -unit \\UNIT_ID -all -layer SKIN -pain 20 -surface_perc 100 -effect [ Burn 100 100 ]
unit/wound-add -unit \\UNIT_ID -token UB -layer ALL -bleeding 10 -penetration 100 -contact_area 25 -surface_perc 30 -flags [ cut edged_damage ]
]])
return
end
if args.unit and tonumber(args.unit) then -- Check for unit declaration !REQUIRED
unit = df.unit.find(tonumber(args.unit))
else
print('No unit selected')
return
end
dur = tonumber(args.dur) or 0 -- Check if there is a duration (default 0)
parts = {}
recall = ''
tokens = args.all or args.category or args.token or args.flag
layers = args.layer or ''
if type(layers) == 'string' then layers = {layers} end
if type(tokens) == 'string' then tokens = {tokens} end
if args.all then -- Check for the all body parts flag. !!RUN EFFECT!!
body = unit.body.body_plan.body_parts
for k,v in ipairs(body) do
parts[k] = k
end
recall = 'all'
elseif args.category then -- Check for category body parts. !!RUN CHECKBODYCATEGORY!!. !!RUN EFFECT!!
parts = checkbodycategory(unit,tokens)
recall = 'category'
elseif args.token then -- Check for token body parts. !!RUN CHECKBODYTOKEN!!. !!RUN EFFECT!!
parts = checkbodytoken(unit,tokens)
recall = 'token'
elseif args.flag then -- Check for flag body parts. !!RUN CHECKBODYFLAG!!. !!RUN EFFECT!!
parts = checkbodyflag(unit,tokens)
recall = 'flag'
end
local numbers = {}
numbers.bleeding = args.bleeding
numbers.pain = args.pain
numbers.nausea = args.nausea
numbers.dizziness = args.dizziness
numbers.paralysis = args.paralysis
numbers.numbness = args.numbness
numbers.swelling = args.swelling
numbers.impaired = args.impaired
numbers.strain = args.strain
numbers.contact_area = args.contact_area
numbers.surface_perc = args.surface_perc
numbers.cur_penetration_perc = args.penetration
numbers.max_penetration_perc = args.penetration
if args.severed then parts = checkconnectedparts(unit,parts) end
if args.severed then layers = {'ALL'} end
parts_and_layers = checkbodylayer(unit,parts,layers)
if #parts_and_layers >= 1 then
addwound(unit,parts_and_layers,numbers,args.effect,args.flags,args.attacker,args)
end