diff --git a/docs/zForceWorkshopJobsNow.rst b/docs/zForceWorkshopJobsNow.rst new file mode 100644 index 000000000..1fbdcf6e4 --- /dev/null +++ b/docs/zForceWorkshopJobsNow.rst @@ -0,0 +1,42 @@ +zForceWorkshopJobsNow +===================== + +A DFHack plugin that force-starts or unforces all jobs in workshops and furnaces across the fortress. + +Overview +-------- + +This plugin provides both an in-game overlay and a command-line interface to control whether queued jobs in workshops and furnaces should be executed immediately (`do_now = true`) or not (`do_now = false`). It is useful for players who want more control over job execution prioritization. + +Features +-------- + +- Force all current jobs in all workshops and furnaces to start immediately. +- Toggle job forcing directly from the workshop task viewscreen using a small overlay panel. +- Simple hotkeys: ``o`` (ON) and ``f`` (OFF). +- Compatible with most standard and custom workshops and furnaces. + +Usage +----- + +**In-Game Overlay** + +Navigate to any workshop or furnace job screen. A small UI will appear with: + +:: + + Prioritize All: + ON OFF + +- Press ``ctrl+o`` to prioritize all jobs on all stations. +- Press ``ctrl+i`` to unprioritize all jobs on all stations. + +**Console Command** + +:: + + zForceWorkshopJobsNow [ON|OFF] + +- Running with no argument is equivalent to ``ON``. +- ``ON``: Set ``do_now = true`` for all applicable jobs. +- ``OFF``: Set ``do_now = false`` for all applicable jobs. diff --git a/zForceWorkshopJobsNow.lua b/zForceWorkshopJobsNow.lua new file mode 100644 index 000000000..59ea730ad --- /dev/null +++ b/zForceWorkshopJobsNow.lua @@ -0,0 +1,157 @@ +--@ module=true + +local overlay = require('plugins.overlay') +local widgets = require('gui.widgets') +local gui = require('gui') + +local ForceJobs = {} + +function ForceJobs.prioritize_all_jobs() + local count, changed = 0, 0 + for _, bld in ipairs(df.global.world.buildings.other.IN_PLAY) do + local t = bld:getType() + if t == df.building_type.Workshop or t == df.building_type.Furnace then + count = count + 1 + for _, job in ipairs(bld.jobs or {}) do + if job and not job.flags.do_now then + job.flags.do_now = true + changed = changed + 1 + end + end + end + end + dfhack.println(('ForceJobsNow: Buildings scanned: %d | Jobs changed: %d'):format(count, changed)) +end + +function ForceJobs.disable_all_jobs() + local count, changed = 0, 0 + for _, bld in ipairs(df.global.world.buildings.other.IN_PLAY) do + local t = bld:getType() + if t == df.building_type.Workshop or t == df.building_type.Furnace then + count = count + 1 + for _, job in ipairs(bld.jobs or {}) do + if job and job.flags.do_now then + job.flags.do_now = false + changed = changed + 1 + end + end + end + end + dfhack.println(('ForceJobsNow: Buildings scanned: %d | Jobs disabled: %d'):format(count, changed)) +end + +local ForceJobsOverlay = defclass(ForceJobsOverlay, overlay.OverlayWidget) +ForceJobsOverlay.ATTRS { + desc = 'Force-start jobs in workshops/furnaces.', + viewscreens = { + + 'dwarfmode/ViewSheets/BUILDING/Workshop/Masons/Tasks', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Masons/Items', + 'dwarfmode/ViewSheets/BUILDING/Furnace/Smelter/Tasks', + 'dwarfmode/ViewSheets/BUILDING/Furnace/Smelter/Items', + 'dwarfmode/ViewSheets/BUILDING/Furnace/WoodFurnace/Tasks', + 'dwarfmode/ViewSheets/BUILDING/Furnace/WoodFurnace/Items', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Bowyers/Tasks', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Bowyers/Items', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Craftsdwarfs/Tasks', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Craftsdwarfs/Items', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Mechanics/Tasks', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Mechanics/Items', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Jewelers/Tasks', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Jewelers/Items', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Ashery/Tasks', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Ashery/Items', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Custom/SOAP_MAKER/Tasks', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Custom/Items', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Siege/Tasks', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Siege/Items', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Loom/Tasks', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Loom/Items', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Clothiers/Tasks', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Clothiers/Items', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Dyers/Tasks', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Dyers/Items', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Leatherworks/Tasks', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Leatherworks/Items', + 'dwarfmode/ViewSheets/BUILDING/Furnace/Kiln/Tasks', + 'dwarfmode/ViewSheets/BUILDING/Furnace/Kiln/Items', + 'dwarfmode/ViewSheets/BUILDING/Furnace/GlassFurnace/Tasks', + 'dwarfmode/ViewSheets/BUILDING/Furnace/GlassFurnace/Items', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Carpenters/Tasks', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Carpenters/Items', + 'dwarfmode/ViewSheets/BUILDING/Workshop/MetalsmithsForge/Tasks', + 'dwarfmode/ViewSheets/BUILDING/Workshop/MetalsmithsForge/Items', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Still/Tasks', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Still/Items', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Farmers/Tasks', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Farmers/Items', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Butchers/Tasks', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Butchers/Items', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Kitchen/Tasks', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Kitchen/Items', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Fishery/Tasks', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Fishery/Items', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Tanners/Tasks', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Tanners/Items', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Custom/SCREW_PRESS/Tasks', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Custom/Items', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Quern/Tasks', + 'dwarfmode/ViewSheets/BUILDING/Workshop/Quern/Items', + }, + default_enabled = true, + default_pos = {x = -39, y = 9}, + frame = {w = 22, h = 3, transparent = true}, +} + +function ForceJobsOverlay:init() + self.toggle_state = true -- default to ON + + self:addviews{ + widgets.Panel{ + frame = {b = 0, r = 0, w = 40, h = 5}, + frame_background = gui.CLEAR_PEN, + subviews = { + widgets.Label{ + frame = {l = 0, t = 0}, + text = 'Prioritize All:', + }, + widgets.HotkeyLabel{ + frame = {l = 0, t = 2}, + label = 'ON', + key = 'CUSTOM_CTRL_O', + auto_width = true, + on_activate = function() + self.toggle_state = true + ForceJobs.prioritize_all_jobs() + end, + }, + widgets.HotkeyLabel{ + frame = {l = 11, t = 2}, + label = 'OFF', + key = 'CUSTOM_CTRL_I', + auto_width = true, + on_activate = function() + self.toggle_state = false + ForceJobs.disable_all_jobs() + end, + }, + }, + }, + } +end + +OVERLAY_WIDGETS = { + force_jobs_overlay = ForceJobsOverlay, +} + +-- Run manually from DFHack console +if not dfhack_flags.module then + local cmd = ... + if cmd == nil or cmd:upper() == 'ON' then + ForceJobs.prioritize_all_jobs() + elseif cmd:upper() == 'OFF' then + ForceJobs.disable_all_jobs() + else + qerror("Usage: zForceWorkshopJobsNow [ON|OFF]") + end +end