-
Notifications
You must be signed in to change notification settings - Fork 199
/
source.lua
201 lines (168 loc) · 5.75 KB
/
source.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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
--@ module = true
local repeatUtil = require('repeat-util')
local GLOBAL_KEY = 'source' -- used for state change hooks and persistence
g_sources_list = g_sources_list or {}
local function persist_state(liquidSources)
dfhack.persistent.saveSiteData(GLOBAL_KEY, liquidSources)
end
local function formatPos(pos)
return ('[%d, %d, %d]'):format(pos.x, pos.y, pos.z)
end
local function is_flow_passable(pos)
local tiletype = dfhack.maps.getTileType(pos)
local titletypeAttrs = df.tiletype.attrs[tiletype]
local shape = titletypeAttrs.shape
local tiletypeShapeAttrs = df.tiletype_shape.attrs[shape]
return tiletypeShapeAttrs.passable_flow
end
local function load_liquid_source()
repeatUtil.scheduleEvery(GLOBAL_KEY, 12, 'ticks', function()
if #g_sources_list == 0 then
repeatUtil.cancel(GLOBAL_KEY)
else
for _, v in ipairs(g_sources_list) do
local block = dfhack.maps.getTileBlock(v.pos)
if block and is_flow_passable(v.pos) then
local isMagma = v.liquid == 'magma'
local flags = dfhack.maps.getTileFlags(v.pos)
local flow = flags.flow_size
if flow ~= v.amount then
local target = flow + 1
if flow > v.amount then
target = flow - 1
end
flags.liquid_type = isMagma
flags.flow_size = target
flags.flow_forbid = (isMagma or target >= 4)
dfhack.maps.enableBlockUpdates(block, true)
end
end
end
end
end)
end
local function delete_source_at(idx)
local v = g_sources_list[idx]
if v then
local block = dfhack.maps.getTileBlock(v.pos)
if block and is_flow_passable(v.pos) then
local flags = dfhack.maps.getTileFlags(v.pos)
flags.flow_size = 0
dfhack.maps.enableBlockUpdates(block, true)
end
table.remove(g_sources_list, idx)
end
end
local function add_liquid_source(pos, liquid, amount)
local new_source = {liquid = liquid, amount = amount, pos = copyall(pos)}
print(("Adding %d %s to %s"):format(amount, liquid, formatPos(pos)))
for k, v in ipairs(g_sources_list) do
if same_xyz(pos, v.pos) then
delete_source_at(k)
break
end
end
table.insert(g_sources_list, new_source)
load_liquid_source()
end
local function delete_liquid_source(pos)
print(("Deleting Source at %s"):format(formatPos(pos)))
for k, v in ipairs(g_sources_list) do
if same_xyz(pos, v.pos) then
print("Source Found")
delete_source_at(k)
break
end
end
end
local function clear_liquid_sources()
while #g_sources_list > 0 do
delete_source_at(#g_sources_list)
end
end
local function list_liquid_sources()
print('Current Liquid Sources:')
for _,v in ipairs(g_sources_list) do
print(('%s %s %d'):format(formatPos(v.pos), v.liquid, v.amount))
end
end
local function find_liquid_source_at_pos(pos)
print(("Searching for Source at %s"):format(formatPos(pos)))
for k,v in ipairs(g_sources_list) do
if same_xyz(v.pos, pos) then
print("Source Found")
return k
end
end
return nil
end
function main(args)
local command = args[1]
if not command or command == 'list' then
list_liquid_sources()
return
end
if command == 'clear' then
clear_liquid_sources()
print("Cleared sources")
return
end
local targetPos = copyall(df.global.cursor)
local index = find_liquid_source_at_pos(targetPos)
if command == 'delete' then
if targetPos.x < 0 then
qerror("Please place the cursor where there is a source to delete")
end
if index then
delete_liquid_source(targetPos)
print(('Deleted source at %s'):format(formatPos(targetPos)))
else
qerror(('%s Does not contain a liquid source'):format(formatPos(targetPos)))
end
return
end
if command == 'add' then
if targetPos.x < 0 then
qerror('Please place the cursor where you would like a source')
end
local liquidArg = args[2]
if not liquidArg then
qerror('You must specify a liquid to add a source for')
end
liquidArg = liquidArg:lower()
if not (liquidArg == 'magma' or liquidArg == 'water') then
qerror('Liquid must be either "water" or "magma"')
end
if not is_flow_passable(targetPos) then
qerror("Tile not flow passable: I'm afraid I can't let you do that, Dave.")
end
local amountArg = tonumber(args[3]) or 7
add_liquid_source(targetPos, liquidArg, amountArg)
print(('Added %s %d at %s'):format(liquidArg, amountArg, formatPos(targetPos)))
return
end
end
dfhack.onStateChange[GLOBAL_KEY] = function(sc)
if sc == SC_WORLD_UNLOADED then
g_sources_list = {}
end
if sc ~= SC_MAP_LOADED or df.global.gamemode ~= df.game_mode.DWARF then
return
end
local data = dfhack.persistent.getSiteData(GLOBAL_KEY, {})
g_sources_list = {}
-- fix up potential errors in previous versions where the list could be non-contiguous
for _, v in pairs(data) do
table.insert(g_sources_list, v)
end
load_liquid_source()
end
if dfhack_flags.module then
return
end
if df.global.gamemode ~= df.game_mode.DWARF or not dfhack.isMapLoaded() then
dfhack.printerr('source needs a loaded fortress map to work')
return
end
main{...}
persist_state(g_sources_list)