Skip to content

Commit 42a8ac3

Browse files
chdocmaster-spike
authored andcommitted
new tool: immortal-cravings
1 parent cb03157 commit 42a8ac3

File tree

3 files changed

+29
-36
lines changed

3 files changed

+29
-36
lines changed

changelog.txt

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ Template for new versions:
5858
- `idle-crafting`: allow dwarves to independently satisfy their need to craft objects
5959
- `gui/family-affairs`: (reinstated) inspect or meddle with pregnancies, marriages, or lover relationships
6060
- `notes`: attach notes to locations on a fort map
61+
- `immortal-cravings`: allow immortals to satisfy their cravings for food and drink
6162

6263
## New Features
6364
- `caravan`: DFHack dialogs for trade screens (both ``Bring goods to depot`` and the ``Trade`` barter screen) can now filter by item origins (foreign vs. fort-made) and can filter bins by whether they have a mix of ethically acceptable and unacceptable items in them

docs/immortal-cravings.rst

+2-3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,5 @@ occupied.
1414
Usage
1515
-----
1616

17-
::
18-
19-
enable immortal-cravings
17+
``enable immortal-cravings``
18+
``disable immortal-cravings``

immortal-cravings.lua

+26-33
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ local function findClosest(pos, item_vector, is_good)
2424
local dclosest = -1
2525
for _,item in ipairs(item_vector) do
2626
if not item.flags.in_job and (not is_good or is_good(item)) then
27-
local pitem = xyz2pos(dfhack.items.getPosition(item))
27+
local x, y, z = dfhack.items.getPosition(item)
28+
local pitem = xyz2pos(x, y, z)
2829
local ditem = distance(pos, pitem)
2930
if dfhack.maps.canWalkBetween(pos, pitem) and (not closest or ditem < dclosest) then
3031
closest = item
@@ -37,11 +38,11 @@ end
3738

3839
---find a drink
3940
---@param pos df.coord
40-
---@return df.item_drinkst?
41+
---@return df.item_drinkst|nil
4142
local function get_closest_drink(pos)
4243
local is_good = function (drink)
4344
local container = dfhack.items.getContainer(drink)
44-
return container and container:isFoodStorage()
45+
return container and df.item_barrelst:is_instance(container)
4546
end
4647
return findClosest(pos, df.global.world.items.other.DRINK, is_good)
4748
end
@@ -51,12 +52,7 @@ end
5152
local function get_closest_meal(pos)
5253
---@param meal df.item_foodst
5354
local function is_good(meal)
54-
if meal.flags.rotten then
55-
return false
56-
else
57-
local container = dfhack.items.getContainer(meal)
58-
return not container or container:isFoodStorage()
59-
end
55+
return meal.flags.rotten == false
6056
end
6157
return findClosest(pos, df.global.world.items.other.FOOD, is_good)
6258
end
@@ -127,13 +123,13 @@ local function load_state()
127123
enabled = persisted_data.enabled or false
128124
end
129125

130-
DrinkAlcohol = df.need_type.DrinkAlcohol
131-
EatGoodMeal = df.need_type.EatGoodMeal
126+
DrinkAlcohol = df.need_type['DrinkAlcohol']
127+
EatGoodMeal = df.need_type['EatGoodMeal']
132128

133129
---@type integer[]
134-
watched = watched or {}
130+
watched = {}
135131

136-
local threshold = -9000
132+
threshold = -9000
137133

138134
---unit loop: check for idle watched units and create eat/drink jobs for them
139135
local function unit_loop()
@@ -142,25 +138,23 @@ local function unit_loop()
142138
local kept = {}
143139
for _, unit_id in ipairs(watched) do
144140
local unit = df.unit.find(unit_id)
145-
if
146-
not unit or not dfhack.units.isActive(unit) or
147-
unit.flags1.caged or unit.flags1.chained
148-
then
149-
goto next_unit
150-
end
151-
if not idle.unitIsAvailable(unit) then
152-
table.insert(kept, unit.id)
153-
else
154-
-- unit is available for jobs; satisfy one of its needs
155-
for _, need in ipairs(unit.status.current_soul.personality.needs) do
156-
if need.id == DrinkAlcohol and need.focus_level < threshold then
157-
goDrink(unit)
158-
break
159-
elseif need.id == EatGoodMeal and need.focus_level < threshold then
160-
goEat(unit)
161-
break
141+
if unit and not (unit.flags1.caged or unit.flags1.chained) then
142+
if not idle.unitIsAvailable(unit) then
143+
table.insert(kept, unit.id)
144+
else
145+
--
146+
for _, need in ipairs(unit.status.current_soul.personality.needs) do
147+
if need.id == DrinkAlcohol and need.focus_level < threshold then
148+
goDrink(unit)
149+
goto next_unit
150+
elseif need.id == EatGoodMeal and need.focus_level < threshold then
151+
goEat(unit)
152+
goto next_unit
153+
end
162154
end
163155
end
156+
else
157+
-- print('immortal-cravings: unit gone or caged')
164158
end
165159
::next_unit::
166160
end
@@ -173,7 +167,7 @@ end
173167

174168
---main loop: look for citizens with personality needs for food/drink but w/o physiological need
175169
local function main_loop()
176-
-- print('immortal-cravings watching:')
170+
print('immortal-cravings watching:')
177171
watched = {}
178172
for _, unit in ipairs(dfhack.units.getCitizens()) do
179173
if unit.curse.add_tags1.NO_DRINK or unit.curse.add_tags1.NO_EAT then
@@ -182,7 +176,7 @@ local function main_loop()
182176
need.id == EatGoodMeal and need.focus_level < threshold
183177
then
184178
table.insert(watched, unit.id)
185-
-- print(' '..dfhack.df2console(dfhack.TranslateName(dfhack.units.getVisibleName(unit))))
179+
print(' '..dfhack.df2console(dfhack.TranslateName(dfhack.units.getVisibleName(unit))))
186180
goto next_unit
187181
end
188182
end
@@ -214,7 +208,6 @@ end
214208
dfhack.onStateChange[GLOBAL_KEY] = function(sc)
215209
if sc == SC_MAP_UNLOADED then
216210
enabled = false
217-
-- repeat-util will cancel the loops on unload
218211
return
219212
end
220213

0 commit comments

Comments
 (0)