Skip to content

Add z_instrument_all script and documentation #1468

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 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
27 changes: 27 additions & 0 deletions docs/z_instrument_all.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
z_instrument_all.lua
=====================

**Automatically queue work orders for all discovered instruments in Dwarf Fortress using DFHack.**

Features
--------

- Detects all valid, craftable instruments via `instruments` command
- Normalizes and filters instrument names for compatibility
- Automatically places a work order for each instrument without having to manually input order and name

Usage
-----

Run with a number to place **that many** orders per instrument (defaults to 1 if omitted):

::

z_instrument_all 5

This example queues 5 of each discovered instrument.

Acknowledgments
---------------

This script utilizes the DFHack `instruments` command to retrieve and process instrument definitions.
92 changes: 92 additions & 0 deletions z_instrument_all.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
-- z_instrument_all.lua
-- Automatically places work orders for all discovered instruments using: 'instruments order <name> <count>'
-- Optionally accepts a numeric argument to specify the number of each instrument to order (default is 1)

local function collect_unique_instrument_names()
local success, raw_output = pcall(function()
return dfhack.run_command_silent("instruments")
end)

if not success or not raw_output then
qerror("Failed to run 'instruments': " .. tostring(raw_output))
end

local instrument_names = {}
local seen_names = {}

for line in raw_output:gmatch("[^\r\n]+") do
local normalized = dfhack.toSearchNormalized(line)
if not normalized:match("^%s*make") and not normalized:match("^%s*forge") then
local raw_name = line:gsub("%s*%b()", ""):gsub("^%s+", ""):gsub("%s+$", "")
local normalized_name = dfhack.toSearchNormalized(raw_name)
if raw_name ~= "" and not seen_names[normalized_name] then
seen_names[normalized_name] = true
table.insert(instrument_names, { name = raw_name, original_line = line })
end
end
end

return instrument_names
end

local function place_instrument_work_orders(order_count)
local instruments = collect_unique_instrument_names()
local counts = { building = 0, handheld = 0, total = 0 }

for _, instrument in ipairs(instruments) do
local name = instrument.name
local type = "unknown"

-- Determine type based on line description
local line_lower = instrument.original_line:lower()
if line_lower:find("building") then
type = "building"
elseif line_lower:find("handheld") then
type = "handheld"
end

print("------------------------------")
print("Placed order for: " .. name .. " (x" .. order_count .. ") [" .. type .. "]")
print("------------------------------")

local success, err = pcall(function()
dfhack.run_command("instruments", "order", name, tostring(order_count))
end)

if not success then
dfhack.printerr("Failed to place order for '" .. name .. "': " .. tostring(err))
else
counts[type] = counts[type] + order_count
counts.total = counts.total + order_count
end
end

-- Summary
print("\n==== Instrument Order Summary ====")
print("Total instruments ordered: " .. counts.total)
print(" Handheld: " .. counts.handheld)
print(" Building: " .. counts.building)
print("==================================\n")
end

-- Main execution
local args = {...}
local quantity = 1

if #args == 1 then
local parsed = tonumber(args[1])
if parsed and parsed > 0 then
quantity = math.floor(parsed)
else
qerror("Invalid argument. Usage: z_instrument_all [number_of_orders_per_instrument]")
end
elseif #args > 1 then
qerror("Too many arguments. Usage: z_instrument_all [number_of_orders_per_instrument]")
end

local ok, err = pcall(function()
place_instrument_work_orders(quantity)
end)
if not ok then
qerror("Script failed: " .. tostring(err))
end