Bay 12 Games Forum

Please login or register.

Login with username, password and session length
Advanced search  

Author Topic: How butchering results are calculated (with DFHack lua script)  (Read 2436 times)

Urist Da Vinci

  • Bay Watcher
  • [NATURAL_SKILL: ENGINEER:4]
    • View Profile

For each tissue layer in each body part of a creature, the game calculates the volume of the layer and compares it to thresholds. This determines if you get anything from the part/layer, or if you get several items.

This lua script gives the butchering results for a specific living creature:
Code: (butcher.lua) [Select]
--Calculates butchering results. Alpha version. Target a living creature.

unit=dfhack.gui.getSelectedUnit()
if unit==nil then
print ("No unit under cursor!  Aborting!")
return
end

print(unit.name.first_name, df.global.world.raws.creatures.all[unit.race].creature_id)
print("Creature size (base, current): ", unit.body.size_info.size_base, unit.body.size_info.size_cur)
totalvol=0
totalbone=0
missingparts=0
testrecord={}


for partnum,v in pairs(unit.body.body_plan.body_parts) do
for layernum, vv in pairs(v.layers) do
--START MAIN LOOP

partsize = math.floor(unit.body.size_info.size_base * v.relsize / unit.body.body_plan.total_relsize)
modpartfraction= vv.part_fraction
partname = v.name_singular[0].value
layername = vv.layer_name

if layername == "FAT" then
--currently can't link to or check tissue flags, so can't see if custom tissue resizes based on stored energy
modpartfraction = unit.counters2.stored_fat * modpartfraction / 2500 / 100
end

if layername == "MUSCLE" then
--should update to consider strength bonus due to curses etc.
modpartfraction = unit.body.physical_attrs.STRENGTH.value * modpartfraction / 1000
end


volume = math.floor(partsize * modpartfraction / v.fraction_total)
totalvol=totalvol+volume
finalresult = math.floor(volume/2500)

if volume < 26 and (partsize < 26 or vv.flags.CONNECTS==false) then
--this is an approximation of the actual game code
finalresult=0
else
if finalresult < 1 then
finalresult=1
end
end

--is layer or part missing? in actual code this was checked earlier?
if unit.body.components.body_part_status[partnum].missing==true then
finalresult=0
missingparts=1
end
if unit.body.components.layer_status[vv.layer_id].gone==true then
finalresult=0
missingparts=1
end

if layername == "BONE" and v.flags.TOTEMABLE==false then
totalbone=totalbone+finalresult
end

if testrecord[layername]==nil then
if finalresult>0 then
testrecord[layername]=finalresult
end
else
testrecord[layername]=testrecord[layername]+finalresult
end

--END MAIN LOOP
end
end

print(" ")
printall(testrecord)
print("Bone (minus skull):", totalbone)
if missingparts==1 then
print("BODY IS MISSING SOME PARTS OR LAYERS (i.e. combat damage)")
end
print(" ")
I suppose a similar approach could be used to find the min and max amounts for creatures from the species. It depends on a lot of variables, which can be seen if you examine the script, so I am not going to spend time on that.

Feel free to ask questions or suggest improvements.

EDIT: updated script to not show layers with zero butchering results
« Last Edit: March 29, 2014, 01:18:09 pm by Urist Da Vinci »
Logged

Roses

  • Bay Watcher
    • View Profile
Re: How butchering results are calculated (with DFHack lua script)
« Reply #1 on: March 24, 2014, 03:35:00 am »

I didn't see it in my quick look through, but you might want to include an EXTRA_BUTCHER_OBJECTS the creature might have. It really isn't needed in the script, but for completeness sake you may consider doing it.
Logged

Bo-Rufus CMVII

  • Bay Watcher
    • View Profile
Re: How butchering results are calculated (with DFHack lua script)
« Reply #2 on: March 24, 2014, 09:55:45 pm »

Consider adding your script to the list at http://www.bay12forums.com/smf/index.php?topic=135506.0

The first post in the thread tells you how to add it.
Logged

Urist Da Vinci

  • Bay Watcher
  • [NATURAL_SKILL: ENGINEER:4]
    • View Profile
Re: How butchering results are calculated (with DFHack lua script)
« Reply #3 on: March 25, 2014, 12:05:22 am »

I didn't see it in my quick look through, but you might want to include an EXTRA_BUTCHER_OBJECTS the creature might have. It really isn't needed in the script, but for completeness sake you may consider doing it.

Funny, that code is only used at present for giving gizzard stones to birds, yet domestic poultry birds won't drop it because they are too small to even drop the gizzard. Only appears to drop from crocodiles, beak dogs, and the monstrous cavern bird(s).

EXTRA_BUTCHER_OBJECT appears to drop items in a 1:1 relationship with the number of host organ parts dropped. However there appears to be a bug that only the first item has a material.

Roses

  • Bay Watcher
    • View Profile
Re: How butchering results are calculated (with DFHack lua script)
« Reply #4 on: March 25, 2014, 03:17:03 am »

I know some mods use it heavily (mine for one), it is interesting to know.

EXTRA_BUTCHER_OBJECT appears to drop items in a 1:1 relationship with the number of host organ parts dropped. However there appears to be a bug that only the first item has a material.

What do you mean that only the first item as a material?
Logged

Urist Da Vinci

  • Bay Watcher
  • [NATURAL_SKILL: ENGINEER:4]
    • View Profile
Re: How butchering results are calculated (with DFHack lua script)
« Reply #5 on: March 25, 2014, 08:46:49 pm »

I know some mods use it heavily (mine for one), it is interesting to know.

EXTRA_BUTCHER_OBJECT appears to drop items in a 1:1 relationship with the number of host organ parts dropped. However there appears to be a bug that only the first item has a material.

What do you mean that only the first item as a material?

When I made lungs drop stones instead of gizzards, then I got 2 lungs in the butchering results rather than 1 gizzard. There was also a "conglomerate gizzard stone" and a "  gizzard stone".

Urist Da Vinci

  • Bay Watcher
  • [NATURAL_SKILL: ENGINEER:4]
    • View Profile
Re: How butchering results are calculated (with DFHack lua script)
« Reply #6 on: March 29, 2014, 01:25:33 pm »

Updated the OP script to not show layers if there was a zero quantity of that item in the butchering results. This makes some of the lists easier to read.

Here is a modified version of the script that only works on corpse or body part items.

Code: (butcherItem.lua) [Select]
--Calculates butchering results. Alpha version. Target a dead corpse item or body part item.

item=dfhack.gui.getSelectedItem()
if item==nil then
print ("No item under cursor!  Aborting!")
return
end

itemtype=-1
if item:getType()==23 then
itemtype=23
itemname="CORPSE"
end
if item:getType()==45 then
itemtype=45
itemname="CORPSEPIECE"
end
if itemtype==-1 then
print ("Not a valid item!  Aborting!")
return
end

print(itemname, df.global.world.raws.creatures.all[item.race].creature_id, df.unit.find(item.unit_id).name.first_name)
print("Creature size (base, current): ", item.body.size_info.size_base, item.body.size_info.size_cur)
totalvol=0
totalbone=0
missingparts=0
testrecord={}

bodyinfo=df.global.world.raws.creatures.all[item.race].caste[item.caste].body_info

for partnum,v in pairs(bodyinfo.body_parts) do
for layernum, vv in pairs(v.layers) do
--START MAIN LOOP

partsize = math.floor(item.body.size_info.size_base * v.relsize / bodyinfo.total_relsize)
modpartfraction= vv.part_fraction
partname = v.name_singular[0].value
layername = vv.layer_name

if layername == "FAT" then
--currently can't link to or check tissue flags, so can't see if custom tissue resizes based on stored energy
modpartfraction = item.stored_fat * modpartfraction / 2500 / 100
end

if layername == "MUSCLE" then
--should update to consider strength bonus due to curses etc.
modpartfraction = item.body.physical_attr_value.STRENGTH * modpartfraction / 1000
end


volume = math.floor(partsize * modpartfraction / v.fraction_total)
totalvol=totalvol+volume
finalresult = math.floor(volume/2500)

if volume < 26 and (partsize < 26 or vv.flags.CONNECTS==false) then
--this is an approximation of the actual game code
finalresult=0
else
if finalresult < 1 then
finalresult=1
end
end

--is layer or part missing? in actual code this was checked earlier?
if item.body.components.body_part_status[partnum].missing==true then
finalresult=0
missingparts=1
end
if item.body.components.layer_status[vv.layer_id].gone==true then
finalresult=0
missingparts=1
end

if layername == "BONE" and v.flags.TOTEMABLE==false then
totalbone=totalbone+finalresult
end

if testrecord[layername]==nil then
if finalresult>0 then
testrecord[layername]=finalresult
end
else
testrecord[layername]=testrecord[layername]+finalresult
end

--END MAIN LOOP
end
end

print(" ")
printall(testrecord)
print("Bone (minus skull):", totalbone)
if missingparts==1 then
print("BODY IS MISSING SOME PARTS OR LAYERS (i.e. combat damage)")
end
print(" ")

I am not quite sure what people would use this for. Prioritizing recovery of slain enemy war animals for butchering?