Skip to content

New tool: Multihaul #1484

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 138 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
138 commits
Select commit Hold shift + click to select a range
0ab4262
Add chronicle script to record fortress events
LoireLab Jul 19, 2025
3657eba
Merge pull request #1 from LoireLab/codex/-chronicle.lua
LoireLab Jul 19, 2025
2e675db
fix chronicle initialization and loading
LoireLab Jul 19, 2025
a508e66
Merge branch 'master' into 8pg7m7-codex/-chronicle.lua
LoireLab Jul 19, 2025
75c597b
Merge pull request #3 from LoireLab/8pg7m7-codex/-chronicle.lua
LoireLab Jul 19, 2025
8da32eb
Fix chronicle artifact log and hook handling
LoireLab Jul 19, 2025
b827167
Merge branch 'master' into cijxz4-codex/-chronicle.lua
LoireLab Jul 19, 2025
3e91375
Merge pull request #4 from LoireLab/cijxz4-codex/-chronicle.lua
LoireLab Jul 19, 2025
4ee1a21
fix chronicle artifact timestamp
LoireLab Jul 19, 2025
d912fc2
Merge pull request #6 from LoireLab/codex/fix-artifact_record.year_ti…
LoireLab Jul 19, 2025
5a4b43a
disable heavy scanning in chronicle
LoireLab Jul 19, 2025
7ae87b0
Merge pull request #7 from LoireLab/62ad62-codex
LoireLab Jul 19, 2025
bcbcc3d
Track artifacts and invasions
LoireLab Jul 19, 2025
c623822
Remove legacy scanning in chronicle
LoireLab Jul 19, 2025
1d72e2a
Merge pull request #8 from LoireLab/dhff81-codex
LoireLab Jul 19, 2025
dba3c1a
Refine holy-war mod with deity spheres
LoireLab Jul 19, 2025
5894d49
Merge pull request #9 from LoireLab/9hdvkm-codex
LoireLab Jul 19, 2025
66bc94e
Enhance chronicle output and item tracking
LoireLab Jul 19, 2025
a381a24
Merge pull request #10 from LoireLab/codex/investigate-chronicle-prin…
LoireLab Jul 19, 2025
55777ed
Ensure holy-war sets war on both sides
LoireLab Jul 19, 2025
0bc3aa2
Merge pull request #11 from LoireLab/codex/-holy-war
LoireLab Jul 19, 2025
f79f046
Refine chronicle output
LoireLab Jul 19, 2025
d5e8333
Merge pull request #12 from LoireLab/codex/fix-incomplete-utf-8-seque…
LoireLab Jul 19, 2025
5839e89
holy-war: display war reason
LoireLab Jul 19, 2025
5a1278e
Merge pull request #13 from LoireLab/uyevve-codex
LoireLab Jul 19, 2025
9a12910
Summarize non-artifact item creation
LoireLab Jul 19, 2025
d7b8668
Improve holy-war output
LoireLab Jul 19, 2025
fc848c8
Merge pull request #14 from LoireLab/3zaa1h-codex
LoireLab Jul 19, 2025
348aa13
Merge pull request #15 from LoireLab/90u9lr-codex/-holy-war
LoireLab Jul 19, 2025
1c8ab86
Need-aquire
LoireLab Jul 19, 2025
b541254
chronicle: capture artifact announcements
LoireLab Jul 19, 2025
c80fd0a
Merge pull request #16 from LoireLab/n6oxr7-codex
LoireLab Jul 19, 2025
27f92b8
Improve need-acquire.lua with documentation and cleanup
LoireLab Jul 19, 2025
e11daff
Merge pull request #17 from LoireLab/codex/-need-acquire.lua
LoireLab Jul 19, 2025
1271e42
chronicle: add export command
LoireLab Jul 19, 2025
aa7ec00
Merge pull request #19 from LoireLab/qgrtgu-codex
LoireLab Jul 19, 2025
a827df4
Sanitize chronicle output
LoireLab Jul 19, 2025
64184e2
Merge pull request #20 from LoireLab/tgeoam-codex
LoireLab Jul 19, 2025
aa46986
sanitize chronicle entries
LoireLab Jul 19, 2025
2a78abc
Merge branch 'master' into 7d9b1y-codex
LoireLab Jul 19, 2025
dd2afe3
Merge pull request #21 from LoireLab/7d9b1y-codex
LoireLab Jul 19, 2025
e187aed
Optimization of chronicle.lua
LoireLab Jul 19, 2025
c6cd65a
Refactor scripts and update docs
LoireLab Jul 19, 2025
f39879f
Merge pull request #22 from LoireLab/codex/-need-acquire,-holy-war,-c…
LoireLab Jul 19, 2025
bcd1d94
Chronicle.lua new events and text changes from notification style
LoireLab Jul 19, 2025
a811f4e
Ignore wildlife deaths in chronicle
LoireLab Jul 20, 2025
3c1113f
Merge pull request #23 from LoireLab/codex/-wildlife-chronicle
LoireLab Jul 20, 2025
5f3bea4
Add scrollable chronicle viewer
LoireLab Jul 20, 2025
a1754c3
Merge pull request #24 from LoireLab/codex/-chronicle
LoireLab Jul 20, 2025
18d804b
Preserve trimmed chronicle entries
LoireLab Jul 20, 2025
ce57986
Add multihaul script
LoireLab Jul 20, 2025
93f002f
Merge pull request #25 from LoireLab/fff979-codex/-chronicle
LoireLab Jul 20, 2025
0828c9f
Merge pull request #26 from LoireLab/codex/-haul
LoireLab Jul 20, 2025
dd177e3
Refine death messages with faction-specific text
LoireLab Jul 20, 2025
27e017f
Merge branch 'master' into arkt0w-codex
LoireLab Jul 20, 2025
9abc0cc
Merge pull request #27 from LoireLab/arkt0w-codex
LoireLab Jul 20, 2025
c61e2c1
Add config options and debugging to multihaul
LoireLab Jul 20, 2025
125b9b1
Merge pull request #28 from LoireLab/codex/-multihaul
LoireLab Jul 20, 2025
969dc3b
chronicle: unified notification capture pattern
LoireLab Jul 20, 2025
bb30c35
Add wheelbarrow-multi script
LoireLab Jul 20, 2025
120714f
Merge pull request #29 from LoireLab/xfayq7-codex
LoireLab Jul 20, 2025
4918c25
fix chronicle typos and update help
LoireLab Jul 20, 2025
f661b82
Merge pull request #30 from LoireLab/codex/-chroncile
LoireLab Jul 20, 2025
dbcfc0a
Delete wheelbarrow-multi.lua
LoireLab Jul 20, 2025
e1d73ab
Delete multihaul.lua
LoireLab Jul 20, 2025
ef86f40
Add stack-bodyparts script
LoireLab Jul 20, 2025
232ab56
Merge pull request #31 from LoireLab/cw2cix-codex
LoireLab Jul 20, 2025
c95408d
Revert "Add stack-bodyparts utility"
LoireLab Jul 20, 2025
6d8f5e3
chronicle.lua: fixed multiple notification logging
LoireLab Jul 20, 2025
3ee0432
chronicle.lua: more lines, separate lines for Bloodsuckers and Great …
LoireLab Jul 20, 2025
f5b19f3
chronicle.lua: ticks to detect events increased
LoireLab Jul 20, 2025
112be4e
Merge pull request #33 from LoireLab/revert-31-cw2cix-codex
LoireLab Jul 20, 2025
d44dcc3
Restored multihaul.lua
LoireLab Jul 20, 2025
996bec8
Fix multihaul unloading and limit by container size
LoireLab Jul 20, 2025
84ad664
Merge pull request #34 from LoireLab/codex/fix-unloading-issue-in-mul…
LoireLab Jul 20, 2025
989ae8d
multihaul.lua: reverted to item count since capacity is calculated by…
LoireLab Jul 20, 2025
2d23d4f
Debugging multihaul.lua
LoireLab Jul 20, 2025
e4f035f
Debug multihaul.lua: I got it called
LoireLab Jul 20, 2025
f1566b2
multihaul.lua: clean version with working multi gathering and not wor…
LoireLab Jul 20, 2025
5d1699e
multihaul.lua: fixed unneeded code copied from emptywheelbarrow
LoireLab Jul 21, 2025
0b31ff1
fix multihaul script
LoireLab Jul 21, 2025
c41e43a
Merge pull request #35 from LoireLab/codex/fix-nil-value-error-in-mul…
LoireLab Jul 21, 2025
fef261b
multihaul.lua: WORKING VERSION HURRAY
LoireLab Jul 21, 2025
37c55c5
Restrict multihaul to wheelbarrow jobs
LoireLab Jul 21, 2025
9ee5928
Merge pull request #36 from LoireLab/codex/-multihaul-wheelbarrow
LoireLab Jul 21, 2025
2572537
multihaul: restrict to identical items and verify wheelbarrow
LoireLab Jul 21, 2025
b84914f
Merge pull request #37 from LoireLab/codex/-wheelbarrow
LoireLab Jul 21, 2025
81f3db2
multihaul: fix wheelbarrow role
LoireLab Jul 21, 2025
cf05936
Merge pull request #38 from LoireLab/codex/-pushhaulvehicle
LoireLab Jul 21, 2025
58b3688
multihaul.lua: removed unnesessary checks and fixes
LoireLab Jul 21, 2025
cfb1e95
multihaul: filter items by stockpile settings
LoireLab Jul 21, 2025
7134d53
Merge pull request #39 from LoireLab/lxvsq8-codex
LoireLab Jul 21, 2025
986eeb5
multihaul: add matching modes
LoireLab Jul 21, 2025
f3e50c6
Merge pull request #40 from LoireLab/codex/-multihaul
LoireLab Jul 21, 2025
c2a4bd1
multihaul.lua: changed default mode and removed isItemAllowedInStockpile
LoireLab Jul 21, 2025
48cd99a
multihaul.lua: splited type and subtype modes
LoireLab Jul 21, 2025
8cbf4b3
refactor multihaul state and update docs
LoireLab Jul 21, 2025
46d0f57
Merge pull request #41 from LoireLab/673mq6-codex/-multihaul
LoireLab Jul 21, 2025
bfa99d6
Delete changelog.txt
LoireLab Jul 21, 2025
20dd70d
multihaul: docs updated
LoireLab Jul 21, 2025
640ca99
multihaul: help updated
LoireLab Jul 21, 2025
347d2a2
Delete gui/chronicle.lua
LoireLab Jul 21, 2025
b187046
Delete chronicle.lua
LoireLab Jul 21, 2025
acaa671
Delete holy-war.lua
LoireLab Jul 21, 2025
a9b48d1
Delete docs/need-acquire.rst
LoireLab Jul 21, 2025
2e45d27
Delete docs/wheelbarrow-multi.rst
LoireLab Jul 21, 2025
830de7a
Delete docs/chronicle.rst
LoireLab Jul 21, 2025
e1e3c65
Delete docs/holy-war.rst
LoireLab Jul 21, 2025
b96a5bf
Add files via upload
LoireLab Jul 21, 2025
a4845fd
Update changelog.txt
LoireLab Jul 21, 2025
e963afe
Delete need-acquire.lua
LoireLab Jul 21, 2025
4b0f187
Update multihaul.lua
LoireLab Jul 21, 2025
bb0d045
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 21, 2025
40cd433
multihaul.lua: protection for already in stockpile items and autobrea…
LoireLab Jul 21, 2025
64ac19e
Update multihaul.lua
LoireLab Jul 21, 2025
d31b536
Update multihaul.rst
LoireLab Jul 21, 2025
8ae5572
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 21, 2025
e94232c
multihaul: assign wheelbarrows to any job!
LoireLab Jul 22, 2025
3ccf8d0
multihaul: optimize wheelbarrow assignment
LoireLab Jul 22, 2025
80501dd
multihaul: optimization
LoireLab Jul 22, 2025
8f4c3e7
Update multihaul.rst
LoireLab Jul 22, 2025
ea5a859
multihaul wheelbarrow assign optimization
LoireLab Jul 22, 2025
759332c
Update multihaul.lua
LoireLab Jul 22, 2025
f2886ae
multihaul: fix grabbing wheelbarrows and minecart logic
LoireLab Jul 22, 2025
f21982f
multihaul: optimizing item search
LoireLab Jul 22, 2025
d8eded8
refactor multihaul item search
LoireLab Jul 22, 2025
ae59c6d
Merge pull request #45 from LoireLab/i8l5e4-codex/standardize-item-se…
LoireLab Jul 22, 2025
2b4f7b9
multihaul: added protection for returning wheelbarrow jobs
LoireLab Jul 23, 2025
a76460f
multihaul: removed magic number on wheelbarrow_search_radius_k
LoireLab Jul 23, 2025
bbead11
wheelbarrow_search_radius_k now is called correctly
LoireLab Jul 26, 2025
9410045
multihaul: clear lost wheelbarrow jobs when emptying
LoireLab Jul 26, 2025
c799c3f
Merge pull request #46 from LoireLab/0aur88-codex/implement-finish_jo…
LoireLab Jul 26, 2025
d910921
fix multihaul forward declaration
LoireLab Jul 26, 2025
3f31da2
Merge pull request #47 from LoireLab/x5agea-codex/fix-nil-value-error…
LoireLab Jul 26, 2025
6049eae
autowheelbarrow option now works correctly
LoireLab Jul 26, 2025
a334119
Removed breaking wheelbarrow.flags.in_job
LoireLab Jul 26, 2025
b976bdf
finish_jobs_without_wheelbarrow function expanded
LoireLab Jul 26, 2025
35f4800
Merge branch 'master' into multihaul
LoireLab Jul 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Template for new versions:
# Future

## New Tools
- `multihaul`: add multiple items to a single haul job with wheelbarrow

## New Features
- `gui/mod-manager`: now supports arena mode
Expand Down
52 changes: 52 additions & 0 deletions docs/multihaul.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
multihaul
=========

.. dfhack-tool::
:summary: Haulers gather multiple nearby items when using wheelbarrows.
:tags: fort productivity items stockpile

This tool allows dwarves to collect several adjacent items at once when
performing hauling jobs with a wheelbarrow. When enabled, new
``StoreItemInStockpile`` jobs with wheelbarrows will automatically attach nearby items so
they can be hauled in a single trip. Jobs without wheelbarrows would try to attach one if autowheelbarrows option is on.
Items claimed by another jobs or already stored in stockpiles would be ignored.
By default, up to ten additional items within 10 tiles of the original item are collected.
Warning: Destination stockpile filters are currently ignored by the job (because of DF logic). Which items qualify can be controlled
with the ``--mode`` option.
Basic usage of wheelbarrows remains the same: dwarfs would use them only if hauling item is heavier than 75

Usage
-----

::

multihaul enable [<options>]
multihaul disable
multihaul status
multihaul config [<options>]
multihaul finish

The script can also be enabled persistently with ``enable multihaul``.

``multihaul finish`` cancels any ``StoreItemInStockpile`` jobs that have lost
their wheelbarrows, freeing attached items.

Options
-------

``--radius <tiles>``
Search this many tiles around the target item for additional items. Default
is ``10``.
``--max-items <count>``
Attach at most this many additional items to each hauling job. Default is
``10``.
``--mode <any|sametype|samesubtype|identical>``
Control which nearby items are attached. ``any`` collects any items nearby, even if they are not related to an original job item,
``sametype`` only matches the item type (like STONE or WOOD), ``samesubtype`` requires type and
subtype to match, and ``identical`` additionally matches material. The
default is ``sametype``.
``--autowheelbarrows <on|off|enable|disable>``
Automatically assign wheelbarrows to jobs that lack them.
``--debug <on|off|enable|disable>``
Show debug messages via ``dfhack.gui.showAnnouncement`` when items are
attached.
329 changes: 329 additions & 0 deletions multihaul.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,329 @@
-- Allow haulers to pick up multiple nearby items when using wheelbarrows
--@module = true
--@enable = true

local eventful = require('plugins.eventful')
local utils = require('utils')
local itemtools = reqscript('item')

local GLOBAL_KEY = 'multihaul'

local finish_jobs_without_wheelbarrow

local function get_default_state()
return {
enabled=false,
debug_enabled=false,
radius=10,
wheelbarrow_search_radius_k=5,
max_items=10,
mode='sametype',
autowheelbarrows=true
}
end

state = state or get_default_state()

function isEnabled()
return state.enabled
end

local function persist_state()
dfhack.persistent.saveSiteData(GLOBAL_KEY, state)
end

local function load_state()
state = get_default_state()
utils.assign(state, dfhack.persistent.getSiteData(GLOBAL_KEY, state))
end

local function for_each_item_in_radius(x, y, z, radius, fn)
local xmin = math.max(0, x - radius)
local xmax = math.min(df.global.world.map.x_count - 1, x + radius)
local ymin = math.max(0, y - radius)
local ymax = math.min(df.global.world.map.y_count - 1, y + radius)
local bxmin, bxmax = math.floor(xmin/16), math.floor(xmax/16)
local bymin, bymax = math.floor(ymin/16), math.floor(ymax/16)
for by = bymin, bymax do
for bx = bxmin, bxmax do
local block = dfhack.maps.getTileBlock(bx*16, by*16, z)
if block then
for _, id in ipairs(block.items) do
local item = df.item.find(id)
if item and fn(item) then return end
end
end
end
end
end

local function get_job_stockpile(job)
local ref = dfhack.job.getGeneralRef(job, df.general_ref_type.BUILDING_HOLDER)
return ref and df.building.find(ref.building_id) or nil
end

local function items_identical(a, b)
return a:getType() == b:getType() and a:getSubtype() == b:getSubtype() and
a.mat_type == b.mat_type and a.mat_index == b.mat_index
end

local function items_sametype(a, b)
return a:getType() == b:getType()
end

local function items_samesubtype(a, b)
return a:getType() == b:getType() and a:getSubtype() == b:getSubtype()
end

local match_fns = {
any = function() return true end,
identical = items_identical,
sametype = items_sametype,
samesubtype = items_samesubtype,
}

local function items_match(a, b)
local fn = match_fns[state.mode] or match_fns.sametype
return fn(a, b)
end

local function emptyContainedItems(wheelbarrow)
local items = dfhack.items.getContainedItems(wheelbarrow)
if #items == 0 then return end

if state.debug_enabled then
dfhack.gui.showAnnouncement('multihaul: emptying wheelbarrow', COLOR_CYAN)
end

for _, item in ipairs(items) do
if item.flags.in_job then
local job_ref = dfhack.items.getSpecificRef(item, df.specific_ref_type.JOB)
if job_ref then
dfhack.job.removeJob(job_ref.data.job)
end
end
dfhack.items.moveToGround(item, wheelbarrow.pos)
end
finish_jobs_without_wheelbarrow()
end

local function add_nearby_items(job)
if #job.items == 0 then return end

local target = job.items[0].item
if not target then return end
local stockpile = get_job_stockpile(job)
if not stockpile then return end
local x,y,z = dfhack.items.getPosition(target)
if not x then return end

local cond = {}
itemtools.condition_stockpiled(cond)
local is_stockpiled = cond[1]

local function matches(it)
return items_match(it, target)
end

local count = 0
for_each_item_in_radius(x, y, z, state.radius, function(it)
if it ~= target and not it.flags.in_job and it.flags.on_ground and
not it:isWheelbarrow() and not dfhack.items.isRouteVehicle(it) and
not is_stockpiled(it) and matches(it) then
dfhack.job.attachJobItem(job, it, df.job_role_type.Hauled, -1, -1)
count = count + 1
if state.debug_enabled then
dfhack.gui.showAnnouncement(
('multihaul: added %s to hauling job of %s'):format(
dfhack.items.getDescription(it, 0), dfhack.items.getDescription(target, 0)),
COLOR_CYAN)
end
if count >= state.max_items then return true end
end
end)
end

local function find_attached_wheelbarrow(job)
for _, jitem in ipairs(job.items) do
local item = jitem.item
if item and item:isWheelbarrow() then
if jitem.role ~= df.job_role_type.PushHaulVehicle then
return 'badrole'
end
local ref = dfhack.items.getSpecificRef(item, df.specific_ref_type.JOB)
if ref and ref.data.job == job then
return item
end
end
end
return nil
end

local function find_free_wheelbarrow(stockpile)
if not df.building_stockpilest:is_instance(stockpile) then return nil end
local sx, sy, sz = stockpile.centerx, stockpile.centery, stockpile.z
local found
for_each_item_in_radius(sx, sy, sz, state.radius*state.wheelbarrow_search_radius_k or 10*state.wheelbarrow_search_radius_k, function(it)
if it:isWheelbarrow() and not it.flags.in_job then
found = it
return true
end
end)
return found
end


local function attach_free_wheelbarrow(job)
local stockpile = get_job_stockpile(job)
if not stockpile then return nil end
local wheelbarrow = find_free_wheelbarrow(stockpile)
if not wheelbarrow then return nil end
if dfhack.job.attachJobItem(job, wheelbarrow,
df.job_role_type.PushHaulVehicle, -1, -1) then
if state.debug_enabled then
dfhack.gui.showAnnouncement('multihaul: adding wheelbarrow to a job', COLOR_CYAN)
end
return wheelbarrow
end
end

function finish_jobs_without_wheelbarrow()
local count = 0
for _, job in utils.listpairs(df.global.world.jobs.list) do
if job.job_type == df.job_type.StoreItemInStockpile and #job.items > 1 and not find_attached_wheelbarrow(job) then
for _, jobitem in ipairs(job.items) do
local item = jobitem.item
if item and item.flags.in_job then
local ref = dfhack.items.getSpecificRef(item, df.specific_ref_type.JOB)
if ref and ref.data.job == job then
dfhack.job.removeJob(job)
end
end
end
job.items:resize(0)
job.completion_timer = 0
count = count + 1
end
end
if count > 0 then
dfhack.gui.showAnnouncement('multihaul: clearing stuck hauling job', COLOR_CYAN)
end
end

local function on_new_job(job)
if job.job_type ~= df.job_type.StoreItemInStockpile then return end
local wheelbarrow = find_attached_wheelbarrow(job)
if wheelbarrow == 'badrole' then return
end
if not wheelbarrow and state.autowheelbarrows then
wheelbarrow = attach_free_wheelbarrow(job)
end
if not wheelbarrow then return end
add_nearby_items(job)
emptyContainedItems(wheelbarrow)
end

local function enable(val)
state.enabled = val
if state.enabled then
eventful.onJobInitiated[GLOBAL_KEY] = on_new_job
else
eventful.onJobInitiated[GLOBAL_KEY] = nil
end
persist_state()
end

if dfhack.internal.IN_TEST then
unit_test_hooks = {on_new_job=on_new_job, enable=enable,
load_state=load_state}
end

-- state change handler

dfhack.onStateChange[GLOBAL_KEY] = function(sc)
if sc == SC_MAP_UNLOADED then
state.enabled = false
eventful.onJobInitiated[GLOBAL_KEY] = nil
return
end
if sc == SC_MAP_LOADED then
load_state()
end
end

if dfhack_flags.module then
return
end

local args = {...}
if dfhack_flags.enable then
if dfhack_flags.enable_state then
enable(true)
else
enable(false)
end
return
end

local function parse_options(start_idx)
local i = start_idx
while i <= #args do
local a = args[i]
if a == '--debug' then
local m = args[i + 1]
if m == 'off' or m == 'disable' then
state.debug_enabled = false
i = i + 1
else
state.debug_enabled = true
end
elseif a == '--autowheelbarrows' then
local m = args[i + 1]
if m == 'on' or m == 'enable' then
state.autowheelbarrows = true
i = i + 1
elseif m == 'off' or m == 'disable' then
state.autowheelbarrows = false
i = i + 1
else
qerror('invalid autowheelbarrows option: ' .. tostring(m))
end
elseif a == '--radius' then
i = i + 1
state.radius = tonumber(args[i]) or state.radius
elseif a == '--max-items' then
i = i + 1
state.max_items = tonumber(args[i]) or state.max_items
elseif a == '--mode' then
i = i + 1
local m = args[i]
if m == 'any' or m == 'sametype' or m == 'samesubtype' or m == 'identical' then
state.mode = m
else
qerror('invalid mode: ' .. tostring(m))
end
end
i = i + 1
end
end

local cmd = args[1]
if cmd == 'enable' then
parse_options(2)
enable(true)
elseif cmd == 'disable' then
enable(false)
elseif cmd == 'status' or not cmd then
print((state.enabled and 'multihaul is enabled' or 'multihaul is disabled'))
print(('radius=%d max-items=%d mode=%s autowheelbarrows=%s debug=%s')
:format(state.radius, state.max_items, state.mode, state.autowheelbarrows and 'on' or 'off', state.debug_enabled and 'on' or 'off'))
elseif cmd == 'config' then
parse_options(2)
persist_state()
print(('multihaul config: radius=%d max-items=%d mode=%s autowheelbarrows=%s debug=%s')
:format(state.radius, state.max_items, state.mode, state.autowheelbarrows and 'on' or 'off', state.debug_enabled and 'on' or 'off'))
elseif cmd == 'unstuckjobs' then
finish_jobs_without_wheelbarrow()
else
qerror('Usage: multihaul [enable|disable|status|config|unstuckjobs] [--radius N] [--max-items N] [--mode MODE] [--autowheelbarrows on|off] [--debug on|off]')
end