forked from DFHack/scripts
-
Notifications
You must be signed in to change notification settings - Fork 0
/
combine-plants.lua
118 lines (97 loc) · 3.97 KB
/
combine-plants.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
-- Merge plant stacks in the selected container or stockpile
--[====[
combine-plants
==============
Merge stacks of plants or plant growths in the selected container or stockpile.
]====]
local utils = require 'utils'
local validArgs = utils.invert({ 'max', 'stockpile', 'container' })
local args = utils.processArgs({...}, validArgs)
local max = 12
if args.max then max = tonumber(args.max) end
local stockpile = nil
if args.stockpile then stockpile = df.building.find(tonumber(args.stockpile)) end
local container = nil
if args.container then container = df.item.find(tonumber(args.container)) end
function itemsCompatible(item0, item1)
return item0:getType() == item1:getType()
and item0.mat_type == item1.mat_type --hint:df.item_plantst
and item0.mat_index == item1.mat_index --hint:df.item_plantst
end
function getPlants(items, plants, index)
repeat
local nextBatch = {}
for _,v in pairs(items) do
-- Skip items currently tasked
if #v.specific_refs == 0 then
if v:getType() == df.item_type.PLANT or v:getType() == df.item_type.PLANT_GROWTH or v:getType() == df.item_type.CHEESE then
plants[index] = v
index = index + 1
else
local containedItems = dfhack.items.getContainedItems(v)
if #containedItems > 0 then
for _,w in pairs(containedItems) do
table.insert(nextBatch, w)
end
end
end
end
end
items = nextBatch
until #items == 0
return index
end
local item = container or dfhack.gui.getSelectedItem(true)
local building = stockpile or dfhack.gui.getSelectedBuilding(true)
if building ~= nil and building:getType() ~= 29 then building = nil end
if item == nil and building == nil then
qerror("Select an item or building")
else
local rootItems
if building then
rootItems = dfhack.buildings.getStockpileContents(building)
else
rootItems = dfhack.items.getContainedItems(item)
end
if #rootItems == 0 then
qerror("Select a non-empty container")
else
local plants = { } --as:df.item_actual[]
local plantCount = getPlants(rootItems, plants, 0)
print("found " .. plantCount .. " plants")
local removedPlants = { } --as:bool[]
for i=0,(plantCount-2) do
local currentPlant = plants[i] --as:df.item_plantst
local itemsNeeded = max - currentPlant.stack_size
if removedPlants[currentPlant.id] == nil and itemsNeeded > 0 then
local j = i+1
local last = plantCount
repeat
local sourcePlant = plants[j]
if removedPlants[sourcePlant.id] == nil and itemsCompatible(currentPlant, sourcePlant) then
local amountToMove = math.min(itemsNeeded, sourcePlant.stack_size)
itemsNeeded = itemsNeeded - amountToMove
currentPlant.stack_size = currentPlant.stack_size + amountToMove
if sourcePlant.stack_size == amountToMove then
removedPlants[sourcePlant.id] = true
sourcePlant.stack_size = 1
else
sourcePlant.stack_size = sourcePlant.stack_size - amountToMove
end
-- else print("failed")
end
j = j + 1
until j == plantCount or itemsNeeded == 0
end
end
local removedCount = 0
for id,removed in pairs(removedPlants) do
if removed then
removedCount = removedCount + 1
local removedPlant = df.item.find(id)
dfhack.items.remove(removedPlant)
end
end
print("removed " .. removedCount .. " plants")
end
end