-
Notifications
You must be signed in to change notification settings - Fork 193
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added autowheelbarrow script for stockpile management #1328
Changes from all commits
750440c
b59e84f
4d84620
fa532a7
5fe65dd
bcf1e02
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
local repeatutil = require("repeat-util") | ||
local GLOBAL_KEY = "autowheelbarrow" | ||
enabled = enabled or false | ||
|
||
-- Main function for managing wheelbarrows | ||
local function unassign_wheelbarrows() | ||
local wheelbarrow_count = 0 | ||
for _, item in ipairs(df.global.world.items.other.TOOL) do | ||
if df.item_toolst:is_instance(item) then | ||
local tool_def = dfhack.items.getSubtypeDef(item:getType(), item:getSubtype()) | ||
if tool_def and tool_def.id == "ITEM_TOOL_WHEELBARROW" then | ||
wheelbarrow_count = wheelbarrow_count + 1 -- Count each wheelbarrow | ||
if item.flags.in_job then | ||
-- Skip if in use | ||
elseif item.stockpile then | ||
item.stockpile.id = -1 -- Unassign wheelbarrow from stockpile | ||
end | ||
end | ||
end | ||
end | ||
return wheelbarrow_count -- Return the total count of wheelbarrows processed | ||
end | ||
|
||
local function set_wheelbarrows_for_all_stockpiles() | ||
for _, building in ipairs(df.global.world.buildings.all) do | ||
if building:getType() == df.building_type.Stockpile then | ||
local stockpile_settings = building.settings | ||
local skip_wheelbarrows = false | ||
|
||
-- Check food settings to skip wheelbarrows | ||
if stockpile_settings and stockpile_settings.food then | ||
local food_settings = stockpile_settings.food | ||
skip_wheelbarrows = #food_settings.meat > 0 or #food_settings.fish > 0 or #food_settings.unprepared_fish > 0 or | ||
#food_settings.egg > 0 or #food_settings.plants > 0 or #food_settings.drink_plant > 0 or | ||
#food_settings.drink_animal > 0 or #food_settings.cheese_animal > 0 or #food_settings.cheese_plant > 0 or | ||
#food_settings.seeds > 0 or #food_settings.leaves > 0 or #food_settings.powder_plant > 0 or | ||
#food_settings.powder_creature > 0 or #food_settings.glob > 0 or #food_settings.glob_paste > 0 or | ||
#food_settings.glob_pressed > 0 or #food_settings.liquid_plant > 0 or #food_settings.liquid_animal > 0 or | ||
#food_settings.liquid_misc > 0 | ||
--dfhack.println("Skipping stockpile due to food items" .. tostring(building)) | ||
|
||
end | ||
|
||
-- Check all the flags and skip if any of them are true (for individual stockpiles) | ||
if stockpile_settings and stockpile_settings.flags then | ||
local flags = stockpile_settings.flags | ||
if flags.animals == true or flags.food == true or flags.furniture == true or | ||
flags.corpses == true or flags.refuse == true or flags.ammo == true or flags.coins == true or | ||
flags.bars_blocks == true or flags.gems == true or flags.finished_goods == true or | ||
flags.leather == true or flags.cloth == true or flags.wood == true or | ||
flags.weapons == true or flags.armor == true or flags.sheet == true or | ||
flags[17] == true or flags[18] == true or flags[19] == true or flags[20] == true or | ||
flags[21] == true or flags[22] == true or flags[23] == true or flags[24] == true or | ||
flags[25] == true or flags[26] == true or flags[27] == true or flags[28] == true or | ||
flags[29] == true or flags[30] == true or flags[31] == true then | ||
skip_wheelbarrows = true | ||
--dfhack.println("individual stockpiles Skipping stockpile due to one or more flags being true at " .. tostring(building)) | ||
end | ||
end | ||
|
||
-- Check if all flags are set to false (for the none stockpile) | ||
if stockpile_settings and stockpile_settings.flags then | ||
local flags = stockpile_settings.flags | ||
if flags.animals == false and flags.food == false and flags.furniture == false and | ||
flags.corpses == false and flags.refuse == false and flags.stone == false and flags.ammo == false and | ||
flags.coins == false and flags.bars_blocks == false and flags.gems == false and flags.finished_goods == false and | ||
flags.leather == false and flags.cloth == false and flags.wood == false and flags.weapons == false and | ||
flags.armor == false and flags.sheet == false and | ||
flags[17] == false and flags[18] == false and flags[19] == false and flags[20] == false and | ||
flags[21] == false and flags[22] == false and flags[23] == false and flags[24] == false and | ||
flags[25] == false and flags[26] == false and flags[27] == false and flags[28] == false and | ||
flags[29] == false and flags[30] == false and flags[31] == false then | ||
skip_wheelbarrows = true | ||
--dfhack.println("Skipping NONE stockpile" .. tostring(building)) | ||
end | ||
end | ||
Comment on lines
+61
to
+76
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Checking unnamed flags likely does not make sense at all. If anything, the code should probably check whether the stockpile has any goods enabled that make use of wheelbarrows, instead of checking whether it has (also) some goods enabled that do not make use of them. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You got me there. idk what they are for, but they exist so I added them. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. they only "exist" in the sense that the flag word has 32 bits. they don't have a (known) use and so predicating any behavior on their value will result in unpredictable behavior because their value is unpredictable |
||
|
||
if skip_wheelbarrows then | ||
building.max_wheelbarrows = 0 | ||
else | ||
local count = unassign_wheelbarrows() | ||
building.max_wheelbarrows = count | ||
Comment on lines
+81
to
+82
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doesn't calling There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes you're right I should unassign all wheelbarrows before the loop. |
||
--dfhack.println("Set wheelbarrow limit for stockpile at " .. tostring(building) .. " to " .. count) | ||
end | ||
end | ||
end | ||
end | ||
|
||
local function auto_wheelbarrows() | ||
for _, unit in ipairs(df.global.world.units.active) do | ||
if dfhack.units.isCitizen(unit) and unit.job.current_job and unit.job.current_job.job_type == 38 then | ||
unassign_wheelbarrows() | ||
set_wheelbarrows_for_all_stockpiles() | ||
return | ||
end | ||
end | ||
end | ||
|
||
-- Event loop function to call periodically | ||
local function event_loop() | ||
if enabled then | ||
dfhack.println("Running autowheelbarrow.lua ") | ||
auto_wheelbarrows() | ||
-- Check again in 7 days | ||
repeatutil.scheduleUnlessAlreadyScheduled(GLOBAL_KEY, 7, "days", event_loop) | ||
end | ||
end | ||
Comment on lines
+89
to
+107
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand the rationale for your timing. It looks to me as if you check every 7 days whether there is, at that very moment, a unit that has the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The reason for the timing of seven days is children decide to pick up a wheelbarrow and it can take them quite a bit of time to haul the wheelbarrow meaning if the child is hauling for a while this will cause the program to run again and unassign all of the wheelbarrows in the fort resulting in a loop causing less work to be done. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The 7 days may be fine, even though it may be preferable to make this configurable. My question was more: why should the reassignment only occur if there is an active |
||
|
||
-- Manage on state change | ||
dfhack.onStateChange[GLOBAL_KEY] = function(sc) | ||
if sc == SC_MAP_LOADED and df.global.gamemode == df.game_mode.DWARF then | ||
event_loop() -- Start the event loop when the game map is loaded | ||
elseif sc == SC_MAP_UNLOADED then | ||
repeatutil.cancel(GLOBAL_KEY) -- Stop the event loop when the map is unloaded | ||
end | ||
end | ||
|
||
-- Enable the script and start the event loop | ||
enabled = true | ||
event_loop() | ||
Comment on lines
+109
to
+120
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Have a look at how the |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
autowheelbarrow | ||
=============== | ||
|
||
.. dfhack-tool:: | ||
:summary: Automatically manage wheelbarrows in stockpiles based on conditions. | ||
:tags: fort auto stockpiles | ||
|
||
This script automates the assignment of wheelbarrows to stockpiles based on specific criteria, such as the type of items stored in the stockpile. Stockpiles with food, armor, or all flags set to ``false`` will not have wheelbarrows assigned. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That documentation should clearly identify the problem the script is trying to solve. In particular, it should answer the following questions:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have no idea why stockpiles containing food should not have wheelbarrows. After all, it is quite possible to have a stockpile that has both food and boulders enabled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand what you're saying, but I don't like it. The main purpose of creating this program was to maintain high efficiency in stockpiles containing wheelbarrows and, of course, have wheelbarrows move freely between stockpiles. Having food and stones together sounds insane to me, and this program will instead be a detriment to users, as those stockpiles will not be set to 1 automatically if stone is found or to x (wheelbarrows in the fort) per the program's functionality. Additionally, it will be a problem if 30 wheelbarrows inhabit a food and stone stockpile, as that is a possibility if I remove the conditions, which will cascade into a problem with food. I'm sorry for being stubborn; I think these conditions are essential. If this program is scrapped or repurposed, that's fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you missed the main point of my remark. I wasn't suggesting that this script should fully account for mixed food and stone stockpiles - I agree that those aren't very useful.
My point was that the program logic could be drastically simplified using a positive check for item categories that require wheelbarrows (i.e. boulders). I don't know which other item categories consistently reach the 75Γ threshold for being carried using a wheelbarrow. Platinum and gold bars do, as do filled minecarts.
Another possibility might be to never check the item flags of the stockpile, and instead only modify the number of requested wheelbarrows for stockpiles that request at least one wheelbarrow. By default, that applies only to stone stockpiles, but the user could decide to assign in wheelbarrows to other stockpiles as well.