Skip to content

Commit f1201e6

Browse files
committed
automatic milking/shearing at closest workshop (WIP)
1 parent 5898e83 commit f1201e6

File tree

1 file changed

+128
-0
lines changed

1 file changed

+128
-0
lines changed

husbandry.lua

+128
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
2+
-- From workorder.lua
3+
---------------------------8<-----------------------------
4+
5+
-- local utils = require 'utils'
6+
7+
local world = df.global.world
8+
local uu = dfhack.units
9+
10+
local function isValidAnimal(u)
11+
-- this should also check for the absence of misc trait 55 (as of 50.09), but we don't
12+
-- currently have an enum definition for that value yet
13+
return uu.isOwnCiv(u)
14+
and uu.isAlive(u)
15+
and uu.isAdult(u)
16+
and uu.isActive(u)
17+
and uu.isFortControlled(u)
18+
and uu.isTame(u)
19+
and not uu.isMarkedForSlaughter(u)
20+
and not uu.getMiscTrait(u, df.misc_trait_type.Migrant, false)
21+
end
22+
23+
-- true/false or nil if no shearable_tissue_layer with length > 0.
24+
local function canShearCreature(u)
25+
local stls = world.raws.creatures
26+
.all[u.race]
27+
.caste[u.caste]
28+
.shearable_tissue_layer
29+
30+
local any
31+
for _, stl in ipairs(stls) do
32+
if stl.length > 0 then
33+
for _, bpi in ipairs(stl.bp_modifiers_idx) do
34+
any = { u.appearance.bp_modifiers[bpi], stl.length }
35+
if u.appearance.bp_modifiers[bpi] >= stl.length then
36+
return true, any
37+
end
38+
end
39+
end
40+
end
41+
42+
if any then return false, any end
43+
-- otherwise: nil
44+
end
45+
46+
---------------------------8<-----------------------------
47+
48+
local function canMilkCreature(u)
49+
if uu.isMilkable(u) and not uu.isPet(u) then
50+
local mt_milk = uu.getMiscTrait(u, df.misc_trait_type.MilkCounter, false)
51+
if not mt_milk then return true else return false end
52+
else
53+
return nil
54+
end
55+
end
56+
57+
function hasJobType(workshop, jobtype)
58+
for _, job in ipairs(workshop.jobs) do
59+
if job.job_type == jobtype then return true end
60+
end
61+
return false
62+
end
63+
64+
65+
function addWorkshopJob(workshop, job_type, rep, priority)
66+
local ref = df.general_ref_building_holderst:new()
67+
ref.building_id = workshop.id
68+
69+
local job = df.job:new()
70+
job.job_type = job_type
71+
job.pos = {
72+
x = workshop.centerx,
73+
y = workshop.centery,
74+
z = workshop.z
75+
}
76+
job.flags['repeat'] = rep
77+
job.flags.do_now = priority
78+
job.general_refs:insert("#", ref)
79+
workshop.jobs:insert("#", job)
80+
81+
dfhack.job.linkIntoWorld(job, true)
82+
dfhack.job.checkBuildingsNow()
83+
end
84+
85+
-- squared distance is enough for ordering by distance
86+
local function distance2 (x1,y1,x2,y2)
87+
return (math.abs(x1-x2)^2 + math.abs(y1-y2)^2)
88+
end
89+
90+
-- organize workshops by z-level
91+
local workshops_by_z = {}
92+
for _, workshop in ipairs(df.global.world.buildings.other.WORKSHOP_FARMER) do
93+
table.insert(ensure_key(workshops_by_z, workshop.z), workshop)
94+
end
95+
96+
for _, unit in ipairs(world.units.active) do
97+
if not isValidAnimal(unit) then goto skip end
98+
99+
local shear = canShearCreature(unit)
100+
local milk = canMilkCreature(unit)
101+
102+
if not shear and not milk then goto skip end
103+
104+
-- print(dfhack.units.getReadableName(unit),'shear:', shear, 'milk:', milk)
105+
106+
-- locate closest farmers workshop (on same z level)
107+
local closest = nil
108+
local distance = nil
109+
for _, workshop in pairs(workshops_by_z[unit.pos.z] or {}) do
110+
local d = distance2(unit.pos.x, unit.pos.y, workshop.centerx, workshop.centery)
111+
if not closest or d < distance then
112+
closest = workshop
113+
distance = d
114+
end
115+
end
116+
117+
-- enure that closest workshop has the appropriate jobs
118+
if closest and #closest.jobs < 5 then
119+
if milk and not hasJobType(closest, df.job_type.MilkCreature) then
120+
addWorkshopJob(closest, df.job_type.MilkCreature, false, false)
121+
end
122+
if shear and not hasJobType(closest, df.job_type.ShearCreature) then
123+
addWorkshopJob(closest, df.job_type.ShearCreature, false, false)
124+
end
125+
end
126+
127+
::skip::
128+
end

0 commit comments

Comments
 (0)