diff --git a/docs/plugins/autolabor.rst b/docs/plugins/autolabor.rst index 1fa859987..3ab5c4e09 100644 --- a/docs/plugins/autolabor.rst +++ b/docs/plugins/autolabor.rst @@ -18,8 +18,31 @@ untouched by autolabor. .. warning:: - autolabor will override any manual changes you make to labors while it is - enabled, including through other tools such as Dwarf Therapist. + **This plugin is still being tested. Use at your own risk.** + + The algorithms that autolabor uses to choose labor assignments have *not* been updated for version 50 of + Dwarf Fortress. There is no particular guarantee that the labor assignments autolabor is making are optimal, + and it is entirely possible that the assignments it makes will lead to unforeseen consequences. You should + monitor what your dwarves are doing, and more importantly not doing, when using autolabor. + + At this time there is no way to easily see what labors are being assigned to whom, as there is no longer + any vanilla means for seeing the labor assignment table. Until `manipulator` is once again available, + probably the best way to see what autolabor is doing is to use + `Dwarf Therapist `_. You can also increase autolabor's + logging level using the `debugfilter` command (setting either ``debug`` or ``trace`` level for the + ``cycle`` mode) but be warned that this may generate a large amount of console spam, especially in a large fort. + + When it is enabled, autolabor automatically disables the work detail system. You cannot + use autolabor and work details at the same time. If you attempt to open the work detail screen while + autolabor is active, a warning box should appear advising you that autolabor is managing labors and preventing + you from making any changes on that screen. + + Finally, should you disable autolabor, autolabor will automatically reenable the vanilla work detail system. + However, the work detail system only updates labors when the work detail screen is open and some change is + made on that screen. Therefore, if you choose to disable autolabor, you should probably immediately + thereafter open the work details screen and make some change to force the game to recompute all labor + assignments based on the vanilla algorithm. At this time, it is not possible for autolabor to do this + automatically. Usage ----- diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index d5f35fb21..76c80b156 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -81,7 +81,7 @@ dfhack_plugin(autoclothing autoclothing.cpp) dfhack_plugin(autodump autodump.cpp) dfhack_plugin(autofarm autofarm.cpp) #dfhack_plugin(autogems autogems.cpp LINK_LIBRARIES jsoncpp_static) -#add_subdirectory(autolabor) +add_subdirectory(autolabor) #dfhack_plugin(automaterial automaterial.cpp LINK_LIBRARIES lua) dfhack_plugin(automelt automelt.cpp LINK_LIBRARIES lua) #dfhack_plugin(autonestbox autonestbox.cpp LINK_LIBRARIES lua) diff --git a/plugins/autolabor/CMakeLists.txt b/plugins/autolabor/CMakeLists.txt index 554a02ecf..721654d20 100644 --- a/plugins/autolabor/CMakeLists.txt +++ b/plugins/autolabor/CMakeLists.txt @@ -10,6 +10,6 @@ set_source_files_properties(${COMMON_HDRS} PROPERTIES HEADER_FILE_ONLY TRUE) # mash them together (headers are marked as headers and nothing will try to compile them) list(APPEND COMMON_SRCS ${COMMON_HDRS}) -dfhack_plugin(labormanager labormanager.cpp joblabormapper.cpp ${COMMON_SRCS}) +#dfhack_plugin(labormanager labormanager.cpp joblabormapper.cpp ${COMMON_SRCS}) -dfhack_plugin(autolabor autolabor.cpp ${COMMON_SRCS}) +dfhack_plugin(autolabor autolabor.cpp ${COMMON_SRCS} LINK_LIBRARIES lua) diff --git a/plugins/autolabor/autolabor.cpp b/plugins/autolabor/autolabor.cpp index 0af4be5e2..4eac48ab9 100644 --- a/plugins/autolabor/autolabor.cpp +++ b/plugins/autolabor/autolabor.cpp @@ -34,6 +34,8 @@ #include #include #include +#include +#include #include @@ -49,6 +51,7 @@ using namespace df::enums; DFHACK_PLUGIN("autolabor"); REQUIRE_GLOBAL(plotinfo); REQUIRE_GLOBAL(world); +REQUIRE_GLOBAL(game); #define ARRAY_COUNT(array) (sizeof(array)/sizeof((array)[0])) @@ -172,9 +175,9 @@ static const struct labor_default default_labor_infos[] = { /* CLEAN */ {HAULERS, false, 1, 200, 0}, /* CUTWOOD */ {AUTOMATIC, true, 1, 200, 0}, /* CARPENTER */ {AUTOMATIC, false, 1, 200, 0}, - /* DETAIL */ {AUTOMATIC, false, 1, 200, 0}, + /* STONECUTTER */ {AUTOMATIC, false, 1, 200, 0}, + /* STONE_CARVER */ {AUTOMATIC, false, 1, 200, 0}, /* MASON */ {AUTOMATIC, false, 1, 200, 0}, - /* ARCHITECT */ {AUTOMATIC, false, 1, 200, 0}, /* ANIMALTRAIN */ {AUTOMATIC, false, 1, 200, 0}, /* ANIMALCARE */ {AUTOMATIC, false, 1, 200, 0}, /* DIAGNOSE */ {AUTOMATIC, false, 1, 200, 0}, @@ -242,7 +245,18 @@ static const struct labor_default default_labor_infos[] = { /* BUILD_ROAD */ {AUTOMATIC, false, 1, 200, 0}, /* BUILD_CONSTRUCTION */ {AUTOMATIC, false, 1, 200, 0}, /* PAPERMAKING */ {AUTOMATIC, false, 1, 200, 0}, - /* BOOKBINDING */ {AUTOMATIC, false, 1, 200, 0} + /* BOOKBINDING */ {AUTOMATIC, false, 1, 200, 0}, + /* ANON_LABOR_83 */ {DISABLE, false, 0, 0, 0}, + /* ANON_LABOR_84 */ {DISABLE, false, 0, 0, 0}, + /* ANON_LABOR_85 */ {DISABLE, false, 0, 0, 0}, + /* ANON_LABOR_86 */ {DISABLE, false, 0, 0, 0}, + /* ANON_LABOR_87 */ {DISABLE, false, 0, 0, 0}, + /* ANON_LABOR_88 */ {DISABLE, false, 0, 0, 0}, + /* ANON_LABOR_89 */ {DISABLE, false, 0, 0, 0}, + /* ANON_LABOR_90 */ {DISABLE, false, 0, 0, 0}, + /* ANON_LABOR_91 */ {DISABLE, false, 0, 0, 0}, + /* ANON_LABOR_92 */ {DISABLE, false, 0, 0, 0}, + /* ANON_LABOR_93 */ {DISABLE, false, 0, 0, 0}, }; static const int responsibility_penalties[] = { @@ -399,6 +413,8 @@ static void enable_plugin(color_ostream &out) cleanup_state(); init_state(); + + df::global::game->external_flag |= 1; // shut down DF's work detail system } DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) @@ -711,15 +727,18 @@ DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_chan DFhackCExport command_result plugin_onupdate ( color_ostream &out ) { - static int step_count = 0; + static int last_run = 0; + static const int run_frequency = 60; + if(!world || !world->map.block_index || !enable_autolabor) { return CR_OK; } - if (++step_count < 60) + if (world->frame_counter - last_run <= run_frequency) return CR_OK; - step_count = 0; + + last_run = world->frame_counter; std::vector dwarfs; @@ -1065,6 +1084,8 @@ DFhackCExport command_result plugin_enable ( color_ostream &out, bool enable ) enable_autolabor = false; setOptionEnabled(CF_ENABLED, false); + df::global::game->external_flag &= ~1; // reenable DF's work detail system + out << "Autolabor is disabled." << std::endl; } diff --git a/plugins/autolabor/laborstatemap.h b/plugins/autolabor/laborstatemap.h index 789685930..61cebdd9c 100644 --- a/plugins/autolabor/laborstatemap.h +++ b/plugins/autolabor/laborstatemap.h @@ -42,6 +42,8 @@ char const* state_names[] { const dwarf_state dwarf_states[] = { dwarf_state::BUSY /* CarveFortification */, + dwarf_state::BUSY /* SmoothWall */, + dwarf_state::BUSY /* SmoothFloor */, dwarf_state::BUSY /* DetailWall */, dwarf_state::BUSY /* DetailFloor */, dwarf_state::EXCLUSIVE /* Dig */, @@ -75,21 +77,17 @@ const dwarf_state dwarf_states[] = { dwarf_state::BUSY /* CatchLiveLandAnimal */, dwarf_state::BUSY /* CatchLiveFish */, dwarf_state::BUSY /* ReturnKill */, - dwarf_state::BUSY /* CheckChest */, dwarf_state::BUSY /* StoreOwnedItem */, dwarf_state::BUSY /* PlaceItemInTomb */, dwarf_state::BUSY /* StoreItemInStockpile */, dwarf_state::BUSY /* StoreItemInBag */, - dwarf_state::BUSY /* StoreItemInHospital */, - dwarf_state::BUSY /* StoreItemInChest */, - dwarf_state::BUSY /* StoreItemInCabinet */, + dwarf_state::BUSY /* StoreItemInLocation */, dwarf_state::BUSY /* StoreWeapon */, dwarf_state::BUSY /* StoreArmor */, dwarf_state::BUSY /* StoreItemInBarrel */, dwarf_state::BUSY /* StoreItemInBin */, dwarf_state::BUSY /* SeekArtifact */, dwarf_state::BUSY /* SeekInfant */, - dwarf_state::OTHER /* AttendParty */, dwarf_state::OTHER /* GoShopping */, dwarf_state::OTHER /* GoShopping2 */, dwarf_state::BUSY /* Clean */, @@ -117,6 +115,7 @@ const dwarf_state dwarf_states[] = { dwarf_state::BUSY /* ConstructCoffin */, dwarf_state::BUSY /* ConstructTable */, dwarf_state::BUSY /* ConstructChest */, + dwarf_state::BUSY /* ConstructBag */, dwarf_state::BUSY /* ConstructBin */, dwarf_state::BUSY /* ConstructArmorStand */, dwarf_state::BUSY /* ConstructWeaponRack */, @@ -153,7 +152,7 @@ const dwarf_state dwarf_states[] = { dwarf_state::BUSY /* MilkCreature */, dwarf_state::BUSY /* MakeCheese */, dwarf_state::BUSY /* ProcessPlants */, - dwarf_state::BUSY /* ProcessPlantsBag */, + dwarf_state::BUSY /* PolishStones */, dwarf_state::BUSY /* ProcessPlantsVial */, dwarf_state::BUSY /* ProcessPlantsBarrel */, dwarf_state::BUSY /* PrepareMeal */, @@ -165,7 +164,6 @@ const dwarf_state dwarf_states[] = { dwarf_state::BUSY /* MakeChain */, dwarf_state::BUSY /* MakeFlask */, dwarf_state::BUSY /* MakeGoblet */, - dwarf_state::BUSY /* MakeInstrument */, dwarf_state::BUSY /* MakeToy */, dwarf_state::BUSY /* MakeAnimalTrap */, dwarf_state::BUSY /* MakeBarrel */, @@ -188,10 +186,10 @@ const dwarf_state dwarf_states[] = { dwarf_state::BUSY /* LoadStoneTrap */, dwarf_state::BUSY /* LoadWeaponTrap */, dwarf_state::BUSY /* CleanTrap */, - dwarf_state::BUSY /* CastSpell */, + dwarf_state::BUSY /* EncrustWithStones */, dwarf_state::BUSY /* LinkBuildingToTrigger */, dwarf_state::BUSY /* PullLever */, - dwarf_state::BUSY /* BrewDrink */, + dwarf_state::OTHER /* _unk_0x94*/, dwarf_state::BUSY /* ExtractFromPlants */, dwarf_state::BUSY /* ExtractFromRawFish */, dwarf_state::BUSY /* ExtractFromLandAnimal */, diff --git a/plugins/lua/autolabor.lua b/plugins/lua/autolabor.lua new file mode 100644 index 000000000..b91227650 --- /dev/null +++ b/plugins/lua/autolabor.lua @@ -0,0 +1,47 @@ +local _ENV = mkmodule('plugins.autolabor') + +local gui = require('gui') +local overlay = require('plugins.overlay') +local widgets = require('gui.widgets') + +local function is_labor_panel_visible() + local info = df.global.game.main_interface.info + return info.open and info.current_mode == df.info_interface_mode_type.LABOR +end + +AutolaborOverlay = defclass(AutolaborOverlay, overlay.OverlayWidget) +AutolaborOverlay.ATTRS{ + default_pos={x=7,y=-13}, + default_enabled=true, + viewscreens='dwarfmode', + frame={w=29, h=5}, + frame_style=gui.MEDIUM_FRAME, + frame_background=gui.CLEAR_PEN, +} + +function AutolaborOverlay:init() + self:addviews{ + widgets.Label{ + frame={t=0, l=0}, + text_pen=COLOR_RED, + text={ + 'DFHack autolabor is active!', NEWLINE, + 'Any changes made on this', NEWLINE, + 'screen will have no effect.' + }, + }, + } +end + +function AutolaborOverlay:render(dc) + if not is_labor_panel_visible() or not isEnabled() then + return false + end + AutolaborOverlay.super.render(self, dc) +end + +OVERLAY_WIDGETS = { + overlay=AutolaborOverlay, +} + +return _ENV