Skip to content

Commit 6f180e4

Browse files
committed
add eggwatch first version
1 parent a6cdf8c commit 6f180e4

File tree

1 file changed

+299
-0
lines changed

1 file changed

+299
-0
lines changed

eggwatch.lua

Lines changed: 299 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,299 @@
1+
local argparse = require("argparse")
2+
local eventful = require("plugins.eventful")
3+
4+
local GLOBAL_KEY = "eggwatch"
5+
local EVENT_FREQ = 5
6+
local print_prefix = "eggwatch: "
7+
8+
enabled = enabled or false
9+
default_table = {}
10+
default_table.DEFAULT = 10
11+
function isEnabled()
12+
return enabled
13+
end
14+
15+
local function persist_state()
16+
dfhack.persistent.saveSiteData(
17+
GLOBAL_KEY,
18+
{
19+
enabled = enabled,
20+
verbose = verbose,
21+
target_eggs_count_per_race = target_eggs_count_per_race
22+
}
23+
)
24+
end
25+
26+
--- Load the saved state of the script
27+
local function load_state()
28+
-- load persistent data
29+
local persisted_data = dfhack.persistent.getSiteData(GLOBAL_KEY, {})
30+
enabled = persisted_data.enabled or false
31+
verbose = persisted_data.verbose or false
32+
target_eggs_count_per_race = persisted_data.target_eggs_count_per_race or default_table
33+
end
34+
35+
if dfhack_flags.module then
36+
return
37+
end
38+
local function print_local(text)
39+
print(print_prefix .. text)
40+
end
41+
local function handle_error(text)
42+
qerror(text)
43+
end
44+
local function print_status()
45+
print_local(("eggwatch is currently %s."):format(enabled and "enabled" or "disabled"))
46+
if verbose then
47+
print_local("eggwatch is in verbose mode")
48+
end
49+
end
50+
51+
local function print_detalis(details)
52+
if verbose then
53+
print_local(details)
54+
end
55+
end
56+
57+
local function is_egg(item)
58+
return df.item_type.EGG == item:getType()
59+
end
60+
61+
-- local function find_current_nestbox (current_eggs)
62+
-- for _, nestbox in ipairs (df.global.world.buildings.other.NEST_BOX) do
63+
-- if nestbox.pos == current_eggs.pos then
64+
-- return nestbox
65+
-- end
66+
-- end
67+
-- end
68+
69+
-- local function create_new_egg_stack (original_eggs, remaining_eggs, creature, caste)
70+
71+
-- print('about to split create new egg stack')
72+
-- print(('type= %s'):format(original_eggs:getType()))
73+
-- print(('creature= %s'):format( creature.creature_id))
74+
-- print(('caste= %s '):format(caste.caste_id))
75+
76+
-- --local created_items = dfhack.items.createItem(creator, original_eggs:getType(), -1, creature.creature_id, caste.caste_id)
77+
78+
-- print('created item')
79+
-- local created_egg_stack = created_items[1]
80+
-- print('about to copy fields from orginal eggs')
81+
-- created_egg_stack.incumabtion_counter = original_eggs.incumabtion_counter
82+
-- created_egg_stack.flags = original_eggs.flags
83+
-- created_egg_stack.flags2 = original_eggs.flags2
84+
-- created_egg_stack.egg_flags = original_eggs.egg_flags
85+
-- created_egg_stack.pos = original_eggs.pos
86+
-- created_egg_stack.hatchling_civ_id = original_eggs.hatchling_civ_id
87+
-- created_egg_stack.mothers_genes = original_eggs.mothers_genes
88+
-- created_egg_stack.mothers_caste = original_eggs.mothers_caste
89+
-- created_egg_stack.mother_hf = original_eggs.mother_hf
90+
-- created_egg_stack.fathers_genes = original_eggs.fathers_genes
91+
-- created_egg_stack.fathers_caste = original_eggs.fathers_caste
92+
-- created_egg_stack.father_hf = original_eggs.father_hf
93+
-- created_egg_stack.hatchling_flags1 = original_eggs.hatchling_flags1
94+
-- created_egg_stack.hatchling_flags2 = original_eggs.hatchling_flags2
95+
-- created_egg_stack.hatchling_flags3 = original_eggs.hatchling_flags3
96+
-- created_egg_stack.hatchling_flags4 = original_eggs.hatchling_flags4
97+
-- created_egg_stack.hatchling_training_level = original_eggs.hatchling_training_level
98+
-- created_egg_stack.hatchling_animal_population = original_eggs.hatchling_animal_population
99+
-- created_egg_stack.mother_id = original_eggs.mother_id
100+
101+
-- print('about to move new stack to nestbox')
102+
-- dfhack.items.moveToContainer(created_egg_stack, find_current_nestbox(original_eggs))
103+
-- end
104+
105+
local function count_forbidden_eggs_for_race_in_claimed_nestobxes(race_creature_id)
106+
print_detalis(("start count_forbidden_eggs_for_race_in_claimed_nestobxes"))
107+
local eggs_count = 0
108+
for _, nestbox in ipairs(df.global.world.buildings.other.NEST_BOX) do
109+
if nestbox.claimed_by ~= -1 then
110+
print_detalis(("Found claimed nextbox"))
111+
for _, nestbox_contained_item in ipairs(nestbox.contained_items) do
112+
if nestbox_contained_item.use_mode == df.building_item_role_type.TEMP then
113+
print_detalis(("Found claimed nextbox containing items"))
114+
if df.item_type.EGG == nestbox_contained_item.item:getType() then
115+
print_detalis(("Found claimed nextbox containing items that are eggs"))
116+
if nestbox_contained_item.item.egg_flags.fertile and nestbox_contained_item.item.flags.forbid then
117+
print_detalis(("Eggs are fertile and forbidden"))
118+
if df.creature_raw.find(nestbox_contained_item.item.race).creature_id == race_creature_id then
119+
print_detalis(("Eggs belong to %s"):format(race_creature_id))
120+
print_detalis(
121+
("eggs_count %s + new %s"):format(
122+
eggs_count,
123+
nestbox_contained_item.item.stack_size
124+
)
125+
)
126+
eggs_count = eggs_count + nestbox_contained_item.item.stack_size
127+
print_detalis(("eggs_count after adding current nestbox %s "):format(eggs_count))
128+
end
129+
end
130+
end
131+
end
132+
end
133+
end
134+
end
135+
print_detalis(("end count_forbidden_eggs_for_race_in_claimed_nestobxes"))
136+
return eggs_count
137+
end
138+
local function get_max_eggs_for_race(race_creature_id)
139+
for k, v in pairs(target_eggs_count_per_race) do
140+
if k == race_creature_id then
141+
return v
142+
end
143+
end
144+
target_eggs_count_per_race[race_creature_id] = target_eggs_count_per_race.DEFAULT
145+
persist_state()
146+
return target_eggs_count_per_race[race_creature_id]
147+
end
148+
local function handle_eggs(eggs)
149+
print_detalis(("start handle_eggs"))
150+
if not eggs.egg_flags.fertile then
151+
print_local("Newly laid eggs are not fertile, do nothing")
152+
return
153+
end
154+
155+
local race_creature_id = df.creature_raw.find(eggs.race).creature_id
156+
local max_eggs = get_max_eggs_for_race(race_creature_id)
157+
local current_eggs = eggs.stack_size
158+
159+
local total_count = current_eggs
160+
total_count = total_count + count_forbidden_eggs_for_race_in_claimed_nestobxes(race_creature_id)
161+
162+
print_detalis(("Total count for %s eggs is %s"):format(race_creature_id, total_count))
163+
164+
if total_count - current_eggs < max_eggs then
165+
-- ###if possible split egg stack to forbid only part below max change previous condition to total_count < max_eggs
166+
-- elseif total_count - current_eggs < max_eggs and total_count > max_eggs then
167+
-- local forbid_eggs = max_eggs - total_count + current_eggs
168+
-- local remaining_eggs = current_eggs - forbid_eggs
169+
-- print('about to split eggs stack')
170+
-- create_new_egg_stack(eggs, remaining_eggs, df.creature_raw.find(eggs.race), race_creature.caste[eggs.caste])
171+
-- eggs.stack_size = forbid_eggs
172+
-- eggs.flags.forbid = true
173+
-- print(('Total count for %s eggs is %s over maximum %s , forbidden %s eggs out of clutch of %s.'):format(race_creature_id, total_count, max_eggs, forbid_eggs, current_eggs))
174+
eggs.flags.forbid = true
175+
print_local(
176+
("Previously existing %s eggs is %s lower than maximum %s , forbidden %s new eggs."):format(
177+
race_creature_id,
178+
total_count - current_eggs,
179+
max_eggs,
180+
current_eggs
181+
)
182+
)
183+
else
184+
print_local(
185+
("Total count for %s eggs is %s over maximum %s, newly laid eggs %s , no action taken."):format(
186+
race_creature_id,
187+
total_count,
188+
max_eggs,
189+
current_eggs
190+
)
191+
)
192+
end
193+
194+
print_detalis(("end handle_eggs"))
195+
end
196+
197+
local function check_item_created(item_id)
198+
local item = df.item.find(item_id)
199+
if not item or not is_egg(item) then
200+
return
201+
end
202+
handle_eggs(item)
203+
end
204+
local function do_enable()
205+
enabled = true
206+
eventful.enableEvent(eventful.eventType.ITEM_CREATED, EVENT_FREQ)
207+
eventful.onItemCreated[GLOBAL_KEY] = check_item_created
208+
end
209+
210+
local function do_disable()
211+
enabled = false
212+
eventful.onItemCreated[GLOBAL_KEY] = nil
213+
end
214+
215+
local function validate_creature_id(creature_id)
216+
for i, c in ipairs(df.global.world.raws.creatures.all) do
217+
if c.creature_id == creature_id then
218+
return true
219+
end
220+
end
221+
return false
222+
end
223+
224+
local function set_target(target_race, target_count)
225+
if target_race == nil or target_race == "" then
226+
handle_error('must specify "DEFAULT" or valid creature_id')
227+
end
228+
local target_race_upper = string.upper(target_race)
229+
if tonumber(target_count) == nil or tonumber(target_count) < 0 then
230+
handle_error("No valid target count specified")
231+
end
232+
if target_race_upper == "DEFAULT" or validate_creature_id(target_race_upper) then
233+
target_eggs_count_per_race[target_race_upper] = tonumber(target_count)
234+
else
235+
handle_error('must specify "DEFAULT" or valid creature_id')
236+
end
237+
238+
print_local(dump(target_eggs_count_per_race))
239+
end
240+
function dump(o)
241+
if type(o) == "table" then
242+
local s = "{ "
243+
for k, v in pairs(o) do
244+
if type(k) ~= "number" then
245+
k = '"' .. k .. '"'
246+
end
247+
s = s .. "[" .. k .. "] = " .. dump(v) .. ","
248+
end
249+
return s .. "} "
250+
else
251+
return tostring(o)
252+
end
253+
end
254+
255+
if df.global.gamemode ~= df.game_mode.DWARF or not dfhack.isMapLoaded() then
256+
dfhack.printerr("eggwatch needs a loaded fortress to work")
257+
return
258+
end
259+
260+
local args, opts = {...}, {}
261+
if dfhack_flags and dfhack_flags.enable then
262+
args = {dfhack_flags.enable_state and "enable" or "disable"}
263+
end
264+
265+
local positionals =
266+
argparse.processArgsGetopt(
267+
args,
268+
{
269+
{"h", "help", handler = function()
270+
opts.help = true
271+
end}
272+
}
273+
)
274+
275+
load_state()
276+
local command = positionals[1]
277+
278+
if command == "help" or opts.help then
279+
print(dfhack.script_help())
280+
elseif command == "enable" then
281+
do_enable()
282+
print_status()
283+
elseif command == "disable" then
284+
do_disable()
285+
print_status()
286+
elseif command == "target" then
287+
set_target(positionals[2], positionals[3])
288+
print_status()
289+
elseif command == "verbose" then
290+
verbose = not verbose
291+
print_status()
292+
elseif command == 'clear' then
293+
target_eggs_count_per_race = default_table
294+
295+
elseif not command or command == "status" then
296+
print_status()
297+
print_local(dump(target_eggs_count_per_race))
298+
end
299+
persist_state()

0 commit comments

Comments
 (0)