-
Notifications
You must be signed in to change notification settings - Fork 193
/
instruments.lua
162 lines (139 loc) · 4.92 KB
/
instruments.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
local argparse = require('argparse')
local workorder = reqscript('workorder')
-- civilization ID of the player civilization
local civ_id = df.global.plotinfo.civ_id
local raws = df.global.world.raws
---@type instrument itemdef_instrumentst
---@return reaction|nil
function getAssemblyReaction(instrument_id)
for _, reaction in ipairs(raws.reactions.reactions) do
if reaction.source_enid == civ_id and
reaction.category == 'INSTRUMENT' and
reaction.code:find(instrument_id, 1, true)
then
return reaction
end
end
return nil
end
-- patch in thread type
---@type reagent reaction_reagent_itemst
---@return string
function reagentString(reagent)
if reagent.code == 'thread' then
local silk = reagent.flags2.silk and "silk " or ""
local yarn = reagent.flags2.yarn and "yarn " or ""
local plant = reagent.flags2.plant and "plant " or ""
return silk .. yarn .. plant .. "thread"
else
return reagent.code
end
end
---@type reaction reaction
---@return string
function describeReaction(reaction)
local skill = df.job_skill[reaction.skill]
local reagents = {}
for _, reagent in ipairs(reaction.reagents) do
table.insert(reagents, reagentString(reagent))
end
return skill .. ": " .. table.concat(reagents, ", ")
end
local function print_list()
-- gather instrument piece reactions and index them by the instrument they are part of
local instruments = {}
for _, reaction in ipairs(raws.reactions.reactions) do
if reaction.source_enid == civ_id and reaction.category == 'INSTRUMENT_PIECE' then
local iname = reaction.name:match("[^ ]+ ([^ ]+)")
table.insert(ensure_key(instruments, iname),
reaction.name .. " (" .. describeReaction(reaction) .. ")")
end
end
-- go over instruments
for _, instrument in ipairs(raws.itemdefs.instruments) do
if not (instrument.source_enid == civ_id) then goto continue end
local building_tag = instrument.flags.PLACED_AS_BUILDING and " (building, " or " (handheld, "
local reaction = getAssemblyReaction(instrument.id)
dfhack.print(dfhack.df2console(instrument.name .. building_tag))
if #instrument.pieces == 0 then
print(dfhack.df2console(describeReaction(reaction) .. ")"))
else
print(dfhack.df2console(df.job_skill[reaction.skill] .. "/assemble)"))
for _, str in pairs(instruments[instrument.name]) do
print(dfhack.df2console(" " .. str))
end
end
print()
::continue::
end
end
local function order_instrument(name, amount, quiet)
local instrument = nil
for _, instr in ipairs(raws.itemdefs.instruments) do
if dfhack.toSearchNormalized(instr.name) == name and instr.source_enid == civ_id then
instrument = instr
end
end
if not instrument then
qerror("Could not find instrument " .. name)
end
local orders = {}
for i, reaction in ipairs(raws.reactions.reactions) do
if reaction.source_enid == civ_id and reaction.category == 'INSTRUMENT_PIECE' and reaction.code:find(instrument.id, 1, true) then
local part_order = {
id=i,
amount_total=amount,
reaction=reaction.code,
job="CustomReaction",
}
table.insert(orders, part_order)
end
end
if #orders < #instrument.pieces then
print("Warning: Could not find reactions for all instrument pieces")
end
local assembly_reaction = getAssemblyReaction(instrument.id)
local assembly_order = {
id=-1,
amount_total=amount,
reaction=assembly_reaction.code,
job="CustomReaction",
order_conditions={}
}
for _, order in ipairs(orders) do
table.insert(
assembly_order.order_conditions,
{
condition="Completed",
order=order.id
}
)
end
table.insert(orders, assembly_order)
orders = workorder.preprocess_orders(orders)
workorder.fillin_defaults(orders)
workorder.create_orders(orders, quiet)
if not quiet then
print("\nCreated " .. #orders .. " work orders")
end
end
local help = false
local quiet = false
local positionals = argparse.processArgsGetopt({...}, {
{'h', 'help', handler=function() help = true end},
{'q', 'quiet', handler=function() quiet = true end},
})
if help or positionals[1] == 'help' then
print(dfhack.script_help())
return
end
if #positionals == 0 or positionals[1] == "list" then
print_list()
elseif positionals[1] == "order" then
local instrument_name = positionals[2]
if not instrument_name then
qerror("Usage: instruments order <instrument_name> [<amount>]")
end
local amount = positionals[3] or 1
order_instrument(instrument_name, amount, quiet)
end