- Notifications
You must be signed in to change notification settings - Fork201
/
Copy pathautofish.lua
257 lines (216 loc) · 7.42 KB
/
autofish.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
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
-- handles automatic fishing jobs to limit the number of fish the fortress keeps on hand
-- autofish [enable | disable] <max> [min] [<options>]
--@ enable=true
--@ module=true
localargparse=require("argparse")
localrepeatutil=require("repeat-util")
localGLOBAL_KEY="autofish"
-- set default enabled state
enabled=enabledorfalse
s_maxFish=s_maxFishor100
s_minFish=s_minFishor75
s_useRaw=s_useRawortrue
isFishing=isFishingortrue
--- Check if the script is enabled.
-- @return true if the script is enabled, otherwise false.
functionisEnabled()
returnenabled
end
--- Save the current state of the script
localfunctionpersist_state()
dfhack.persistent.saveSiteData(GLOBAL_KEY, {
enabled=enabled,
s_maxFish=s_maxFish,
s_minFish=s_minFish,
s_useRaw=s_useRaw,
isFishing=isFishing,
})
end
--- Load the saved state of the script
localfunctionload_state()
-- load persistent data
localpersisted_data=dfhack.persistent.getSiteData(GLOBAL_KEY, {})
enabled=persisted_data.enabledorfalse
s_maxFish=persisted_data.s_maxFishor100
s_minFish=persisted_data.s_minFishor75
s_useRaw=persisted_data.s_useRawor (persisted_data.s_useRaw==nil)
isFishing=persisted_data.isFishingor (persisted_data.isFishing==nil)
end
--- Set the maximum fish threshold.
-- @param val The value to set s_maxFish to. (number)
functionset_minFish(val)
s_minFish=val
-- min fish cannot exceed max fish
ifs_minFish>=s_maxFishthens_minFish=s_maxFishend
persist_state()
end
--- Set the minimum fish threshold.
-- @param val The value to set s_minFish to. (number)
functionset_maxFish(val)
s_maxFish=val
-- max fish cannot be lower than min fish
ifs_maxFish<=s_minFishthens_minFish=s_maxFishend
persist_state()
end
--- Set the raw fish toggle
-- @param val The value to set s_useRaw to. (boolean)
functionset_useRaw(val)
s_useRaw=val
persist_state()
end
--- Toggle all work details (and fishing labours)
-- @param state What state to toggle the labours to.
functiontoggle_fishing_labour(state)
-- pass true to state to turn on, otherwise disable
-- find all work details that have fishing enabled:
localwork_details=df.global.plotinfo.labor_info.work_details
for_,vinpairs(work_details)do
ifv.allowed_labors.FISHthen
v.flags.mode=stateand
df.work_detail_mode.OnlySelectedDoesThisordf.work_detail_mode.NobodyDoesThis
-- since the work details are not actually applied unless a button
-- is clicked on the work details screen, we have to manually set
-- unit labours
for_,v2inipairs(v.assigned_units)do
-- find unit by ID and toggle fishing
localunit=df.unit.find(v2)
ifunitthen
unit.status.labors.FISH=state
end
end
end
end
isFishing=state-- save current state
-- let the user know we've got enough, or run out of fish
ifisFishingthen
print("autofish: Re-enabling fishing, fallen below minimum.")
else
print("autofish: Disabling fishing, reached desired quota.")
end
end
--- Checks several item flags to see if a given item should be considered good
-- @param item: a valid dwarf fortress item.
functionisValidItem(item)
localflags=item.flags
ifflags.rottenorflags.traderorflags.hostileorflags.forbid
orflags.dumporflags.on_fireorflags.garbage_collectorflags.owned
orflags.removedorflags.encasedorflags.spider_webthen
returnfalse
end
returntrue
end
--- Counts the number of available fish in a fortress
-- @return prepared (number): count of prepared fish available.
-- @return raw (number): count of raw fish available.
functioncount_fish()
localworld=df.global.world
-- count the number of valid fish we have. (not rotten, forbidden, on fire, dumping...)
localprepared,raw=0,0
fork,vinpairs(world.items.other[df.items_other_id.IN_PLAY])do
ifv:getType()==df.item_type.FISHandisValidItem(v)then
prepared=prepared+v:getStackSize()
end
if (v:getType()==df.item_type.FISH_RAWandisValidItem(v))ands_useRawthen
raw=raw+v:getStackSize()
end
end
returnprepared,raw
end
--- The main event loop of the script.
functionevent_loop()
ifnotenabledthenreturnend
localprepared,raw=count_fish()
-- handle pausing/resuming labour
localnumFish=s_useRawand (prepared+raw)orprepared
ifisFishingand (numFish>=s_maxFish)then
toggle_fishing_labour(false)
elseifnotisFishingand (numFish<s_minFish)then
toggle_fishing_labour(true)
end
persist_state()
-- check weekly
repeatutil.scheduleUnlessAlreadyScheduled(GLOBAL_KEY,7,"days",event_loop)
end
--- Print a status output, showing the current state of the script and options.
localfunctionprint_status()
print(string.format("autofish is currently %s.\n", (enabledand"enabled"or"disabled")))
ifenabledthen
localrfs
rfs=s_useRawand"raw & prepared"or"prepared"
print(string.format("Stopping at %s %s fish.",s_maxFish,rfs))
print(string.format("Restarting at %s %s fish.",s_minFish,rfs))
ifisFishingthen
print("\nCurrently allowing fishing.")
else
print("\nCurrently not allowing fishing.")
end
end
end
--- Handles automatic loading
dfhack.onStateChange[GLOBAL_KEY]=function(sc)
-- unload with game
ifsc==SC_MAP_UNLOADEDthen
enabled=false
return
end
ifsc~=SC_MAP_LOADEDordf.global.gamemode~=df.game_mode.DWARFthen
return
end
load_state()
-- run the main code
event_loop()
end
-- sanity checks?
ifdfhack_flags.modulethen
return
end
ifdf.global.gamemode~=df.game_mode.DWARFornotdfhack.isMapLoaded()then
dfhack.printerr("autofish needs a loaded fortress to work")
return
end
-- argument handling
localargs= {...}
ifdfhack_flagsanddfhack_flags.enablethen
args= {dfhack_flags.enable_stateand"enable"or"disable"}
end
-- handle options flags
localpositionals=argparse.processArgsGetopt(args,
{{"r","raw",hasArg=true,
handler=function(optArg)
localval=argparse.boolean(optArg,"raw")
set_useRaw(val)
end}
})
load_state()
-- handle the rest of the arguments
ifpositionals[1]=="enable"then
enabled=true
elseifpositionals[1]=="disable"then
enabled=false
persist_state()
repeatutil.cancel(GLOBAL_KEY)
return
elseifpositionals[1]=="status"then
print_status()
return
-- positionals is an empty table if no positional arguments are set
elseifpositionals~=nilthen
-- check to see if passed args are numbers
ifpositionals[1]andtonumber(positionals[1])then
-- assume we're changing setting:
localnewval=tonumber(positionals[1])
set_maxFish(newval)
ifnotpositionals[2]then
set_minFish(math.floor(newval*0.75))
end
end
ifpositionals[2]andtonumber(positionals[2])then
set_minFish(tonumber(positionals[2]))
end
-- a setting probably changed, save & show the updated settings.
persist_state()
print_status()
return
end
event_loop()
persist_state()