Skip to content

Commit f05291d

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

File tree

1 file changed

+135
-0
lines changed

1 file changed

+135
-0
lines changed

Diff for: husbandry.lua

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

0 commit comments

Comments
 (0)