diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 9c3716314..b6e05b749 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -128,7 +128,7 @@ if (BUILD_SUPPORTED) DFHACK_PLUGIN(infiniteSky infiniteSky.cpp) DFHACK_PLUGIN(isoworldremote isoworldremote.cpp PROTOBUFS isoworldremote) DFHACK_PLUGIN(jobutils jobutils.cpp) - DFHACK_PLUGIN(labormanager labormanager.cpp) + add_subdirectory(labormanager) DFHACK_PLUGIN(lair lair.cpp) DFHACK_PLUGIN(liquids liquids.cpp Brushes.h LINK_LIBRARIES lua) DFHACK_PLUGIN(luasocket luasocket.cpp LINK_LIBRARIES clsocket lua dfhack-tinythread) diff --git a/plugins/labormanager/CMakeLists.txt b/plugins/labormanager/CMakeLists.txt new file mode 100644 index 000000000..8e9e28b81 --- /dev/null +++ b/plugins/labormanager/CMakeLists.txt @@ -0,0 +1,34 @@ +PROJECT (labormanager) +# A list of source files +SET(PROJECT_SRCS + labormanager.cpp + joblabormapper.cpp +) +# A list of headers +SET(PROJECT_HDRS + labormanager.h + joblabormapper.h +) +SET_SOURCE_FILES_PROPERTIES( ${PROJECT_HDRS} PROPERTIES HEADER_FILE_ONLY TRUE) + +# mash them together (headers are marked as headers and nothing will try to compile them) +LIST(APPEND PROJECT_SRCS ${PROJECT_HDRS}) + +#linux +IF(UNIX) + add_definitions(-DLINUX_BUILD) + SET(PROJECT_LIBS + # add any extra linux libs here + ${PROJECT_LIBS} + ) +# windows +ELSE(UNIX) + SET(PROJECT_LIBS + # add any extra linux libs here + ${PROJECT_LIBS} + $(NOINHERIT) + ) +ENDIF(UNIX) +# this makes sure all the stuff is put in proper places and linked to dfhack + +DFHACK_PLUGIN(labormanager ${PROJECT_SRCS} LINK_LIBRARIES ${PROJECT_LIBS}) diff --git a/plugins/labormanager/joblabormapper.cpp b/plugins/labormanager/joblabormapper.cpp new file mode 100644 index 000000000..051331137 --- /dev/null +++ b/plugins/labormanager/joblabormapper.cpp @@ -0,0 +1,920 @@ +/*a + * This file contains the logic to attempt to intuit the labor required for + * a given job. This is way more complicated than it should be, but I have + * not figured out how to make it simpler. + * + * Usage: + * Instantiate an instance of the JobLaborMapper class + * Call the find_job_labor method of that class instance, + * passing the job as the only argument, to determine the labor for that job + * When done, destroy the instance + * + * The class should allow you to create multiple instances, although there is + * little benefit to doing so. jlfuncs are not reused across instances. + * + */ + + +#include "DataDefs.h" +#include "MiscUtils.h" +#include "modules/Materials.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include + +#include + +#include + +#include + +#include +#include + +using namespace std; +using std::string; +using std::endl; +using namespace DFHack; +using namespace df::enums; +using df::global::ui; +using df::global::world; + +#include "labormanager.h" +#include "joblabormapper.h" + +static df::unit_labor hauling_labor_map[] = +{ + df::unit_labor::HAUL_ITEM, /* BAR */ + df::unit_labor::HAUL_STONE, /* SMALLGEM */ + df::unit_labor::HAUL_ITEM, /* BLOCKS */ + df::unit_labor::HAUL_STONE, /* ROUGH */ + df::unit_labor::HAUL_STONE, /* BOULDER */ + df::unit_labor::HAUL_WOOD, /* WOOD */ + df::unit_labor::HAUL_FURNITURE, /* DOOR */ + df::unit_labor::HAUL_FURNITURE, /* FLOODGATE */ + df::unit_labor::HAUL_FURNITURE, /* BED */ + df::unit_labor::HAUL_FURNITURE, /* CHAIR */ + df::unit_labor::HAUL_ITEM, /* CHAIN */ + df::unit_labor::HAUL_ITEM, /* FLASK */ + df::unit_labor::HAUL_ITEM, /* GOBLET */ + df::unit_labor::HAUL_ITEM, /* INSTRUMENT */ + df::unit_labor::HAUL_ITEM, /* TOY */ + df::unit_labor::HAUL_FURNITURE, /* WINDOW */ + df::unit_labor::HAUL_ANIMALS, /* CAGE */ + df::unit_labor::HAUL_ITEM, /* BARREL */ + df::unit_labor::HAUL_ITEM, /* BUCKET */ + df::unit_labor::HAUL_ANIMALS, /* ANIMALTRAP */ + df::unit_labor::HAUL_FURNITURE, /* TABLE */ + df::unit_labor::HAUL_FURNITURE, /* COFFIN */ + df::unit_labor::HAUL_FURNITURE, /* STATUE */ + df::unit_labor::HAUL_REFUSE, /* CORPSE */ + df::unit_labor::HAUL_ITEM, /* WEAPON */ + df::unit_labor::HAUL_ITEM, /* ARMOR */ + df::unit_labor::HAUL_ITEM, /* SHOES */ + df::unit_labor::HAUL_ITEM, /* SHIELD */ + df::unit_labor::HAUL_ITEM, /* HELM */ + df::unit_labor::HAUL_ITEM, /* GLOVES */ + df::unit_labor::HAUL_FURNITURE, /* BOX */ + df::unit_labor::HAUL_ITEM, /* BIN */ + df::unit_labor::HAUL_FURNITURE, /* ARMORSTAND */ + df::unit_labor::HAUL_FURNITURE, /* WEAPONRACK */ + df::unit_labor::HAUL_FURNITURE, /* CABINET */ + df::unit_labor::HAUL_ITEM, /* FIGURINE */ + df::unit_labor::HAUL_ITEM, /* AMULET */ + df::unit_labor::HAUL_ITEM, /* SCEPTER */ + df::unit_labor::HAUL_ITEM, /* AMMO */ + df::unit_labor::HAUL_ITEM, /* CROWN */ + df::unit_labor::HAUL_ITEM, /* RING */ + df::unit_labor::HAUL_ITEM, /* EARRING */ + df::unit_labor::HAUL_ITEM, /* BRACELET */ + df::unit_labor::HAUL_ITEM, /* GEM */ + df::unit_labor::HAUL_FURNITURE, /* ANVIL */ + df::unit_labor::HAUL_REFUSE, /* CORPSEPIECE */ + df::unit_labor::HAUL_REFUSE, /* REMAINS */ + df::unit_labor::HAUL_FOOD, /* MEAT */ + df::unit_labor::HAUL_FOOD, /* FISH */ + df::unit_labor::HAUL_FOOD, /* FISH_RAW */ + df::unit_labor::HAUL_REFUSE, /* VERMIN */ + df::unit_labor::HAUL_ITEM, /* PET */ + df::unit_labor::HAUL_ITEM, /* SEEDS */ + df::unit_labor::HAUL_FOOD, /* PLANT */ + df::unit_labor::HAUL_ITEM, /* SKIN_TANNED */ + df::unit_labor::HAUL_FOOD, /* LEAVES */ + df::unit_labor::HAUL_ITEM, /* THREAD */ + df::unit_labor::HAUL_ITEM, /* CLOTH */ + df::unit_labor::HAUL_ITEM, /* TOTEM */ + df::unit_labor::HAUL_ITEM, /* PANTS */ + df::unit_labor::HAUL_ITEM, /* BACKPACK */ + df::unit_labor::HAUL_ITEM, /* QUIVER */ + df::unit_labor::HAUL_FURNITURE, /* CATAPULTPARTS */ + df::unit_labor::HAUL_FURNITURE, /* BALLISTAPARTS */ + df::unit_labor::HAUL_FURNITURE, /* SIEGEAMMO */ + df::unit_labor::HAUL_FURNITURE, /* BALLISTAARROWHEAD */ + df::unit_labor::HAUL_FURNITURE, /* TRAPPARTS */ + df::unit_labor::HAUL_FURNITURE, /* TRAPCOMP */ + df::unit_labor::HAUL_FOOD, /* DRINK */ + df::unit_labor::HAUL_FOOD, /* POWDER_MISC */ + df::unit_labor::HAUL_FOOD, /* CHEESE */ + df::unit_labor::HAUL_FOOD, /* FOOD */ + df::unit_labor::HAUL_FOOD, /* LIQUID_MISC */ + df::unit_labor::HAUL_ITEM, /* COIN */ + df::unit_labor::HAUL_FOOD, /* GLOB */ + df::unit_labor::HAUL_STONE, /* ROCK */ + df::unit_labor::HAUL_FURNITURE, /* PIPE_SECTION */ + df::unit_labor::HAUL_FURNITURE, /* HATCH_COVER */ + df::unit_labor::HAUL_FURNITURE, /* GRATE */ + df::unit_labor::HAUL_FURNITURE, /* QUERN */ + df::unit_labor::HAUL_FURNITURE, /* MILLSTONE */ + df::unit_labor::HAUL_ITEM, /* SPLINT */ + df::unit_labor::HAUL_ITEM, /* CRUTCH */ + df::unit_labor::HAUL_FURNITURE, /* TRACTION_BENCH */ + df::unit_labor::HAUL_ITEM, /* ORTHOPEDIC_CAST */ + df::unit_labor::HAUL_ITEM, /* TOOL */ + df::unit_labor::HAUL_FURNITURE, /* SLAB */ + df::unit_labor::HAUL_FOOD, /* EGG */ + df::unit_labor::HAUL_ITEM, /* BOOK */ +}; + +static df::unit_labor workshop_build_labor[] = +{ + /* Carpenters */ df::unit_labor::CARPENTER, + /* Farmers */ df::unit_labor::PROCESS_PLANT, + /* Masons */ df::unit_labor::MASON, + /* Craftsdwarfs */ df::unit_labor::STONE_CRAFT, + /* Jewelers */ df::unit_labor::CUT_GEM, + /* MetalsmithsForge */ df::unit_labor::METAL_CRAFT, + /* MagmaForge */ df::unit_labor::METAL_CRAFT, + /* Bowyers */ df::unit_labor::BOWYER, + /* Mechanics */ df::unit_labor::MECHANIC, + /* Siege */ df::unit_labor::SIEGECRAFT, + /* Butchers */ df::unit_labor::BUTCHER, + /* Leatherworks */ df::unit_labor::LEATHER, + /* Tanners */ df::unit_labor::TANNER, + /* Clothiers */ df::unit_labor::CLOTHESMAKER, + /* Fishery */ df::unit_labor::CLEAN_FISH, + /* Still */ df::unit_labor::BREWER, + /* Loom */ df::unit_labor::WEAVER, + /* Quern */ df::unit_labor::MILLER, + /* Kennels */ df::unit_labor::ANIMALTRAIN, + /* Kitchen */ df::unit_labor::COOK, + /* Ashery */ df::unit_labor::LYE_MAKING, + /* Dyers */ df::unit_labor::DYER, + /* Millstone */ df::unit_labor::MILLER, + /* Custom */ df::unit_labor::NONE, + /* Tool */ df::unit_labor::NONE +}; + +static df::building* get_building_from_job(df::job* j) +{ + for (auto r = j->general_refs.begin(); r != j->general_refs.end(); r++) + { + if ((*r)->getType() == df::general_ref_type::BUILDING_HOLDER) + { + int32_t id = ((df::general_ref_building_holderst*)(*r))->building_id; + df::building* bld = binsearch_in_vector(world->buildings.all, id); + return bld; + } + } + return 0; +} + +static df::unit_labor construction_build_labor(df::building_actual* b) +{ + if (b->getType() == df::building_type::RoadPaved) + return df::unit_labor::BUILD_ROAD; + // Find last item in building with use mode appropriate to the building's constructions state + // For screw pumps contained_items[0] = pipe, 1 corkscrew, 2 block + // For wells 0 mechanism, 1 rope, 2 bucket, 3 block + // Trade depots and bridges use the last one too + // Must check use mode b/c buildings may have items in them that are not part of the building + + df::item* i = 0; + for (auto p = b->contained_items.begin(); p != b->contained_items.end(); p++) + if (b->construction_stage > 0 && (*p)->use_mode == 2 || + b->construction_stage == 0 && (*p)->use_mode == 0) + i = (*p)->item; + + MaterialInfo matinfo; + if (i && matinfo.decode(i)) + { + if (matinfo.material->flags.is_set(df::material_flags::IS_METAL)) + return df::unit_labor::METAL_CRAFT; + if (matinfo.material->flags.is_set(df::material_flags::WOOD)) + return df::unit_labor::CARPENTER; + } + return df::unit_labor::MASON; +} + + +class jlfunc +{ +public: + virtual df::unit_labor get_labor(df::job* j) = 0; +}; + +class jlfunc_const : public jlfunc +{ +private: + df::unit_labor labor; +public: + df::unit_labor get_labor(df::job* j) + { + return labor; + } + jlfunc_const(df::unit_labor l) : labor(l) {}; +}; + +class jlfunc_hauling : public jlfunc +{ +public: + df::unit_labor get_labor(df::job* j) + { + df::item* item = 0; + if (j->job_type == df::job_type::StoreItemInStockpile && j->item_subtype != -1) + return (df::unit_labor) j->item_subtype; + + for (auto i = j->items.begin(); i != j->items.end(); i++) + { + if ((*i)->role == 7) + { + item = (*i)->item; + break; + } + } + + if (item && item->flags.bits.container) + { + for (auto a = item->general_refs.begin(); a != item->general_refs.end(); a++) + { + if ((*a)->getType() == df::general_ref_type::CONTAINS_ITEM) + { + int item_id = ((df::general_ref_contains_itemst *) (*a))->item_id; + item = binsearch_in_vector(world->items.all, item_id); + break; + } + } + } + + df::unit_labor l = item ? hauling_labor_map[item->getType()] : df::unit_labor::HAUL_ITEM; + if (item && l == df::unit_labor::HAUL_REFUSE && item->flags.bits.dead_dwarf) + l = df::unit_labor::HAUL_BODY; + return l; + } + jlfunc_hauling() {}; +}; + +class jlfunc_construct_bld : public jlfunc +{ +public: + df::unit_labor get_labor(df::job* j) + { + if (j->flags.bits.item_lost) + return df::unit_labor::NONE; + + df::building* bld = get_building_from_job(j); + switch (bld->getType()) + { + case df::building_type::Hive: + return df::unit_labor::BEEKEEPING; + case df::building_type::Workshop: + { + df::building_workshopst* ws = (df::building_workshopst*) bld; + if (ws->design && !ws->design->flags.bits.designed) + return df::unit_labor::ARCHITECT; + if (ws->type == df::workshop_type::Custom) + { + df::building_def* def = df::building_def::find(ws->custom_type); + return def->build_labors[0]; + } + else + return workshop_build_labor[ws->type]; + } + break; + case df::building_type::Construction: + return df::unit_labor::BUILD_CONSTRUCTION; + case df::building_type::Furnace: + case df::building_type::TradeDepot: + case df::building_type::Bridge: + case df::building_type::ArcheryTarget: + case df::building_type::WaterWheel: + case df::building_type::RoadPaved: + case df::building_type::Well: + case df::building_type::ScrewPump: + case df::building_type::Wagon: + case df::building_type::Shop: + case df::building_type::Support: + case df::building_type::Windmill: + { + df::building_actual* b = (df::building_actual*) bld; + if (b->design && !b->design->flags.bits.designed) + return df::unit_labor::ARCHITECT; + return construction_build_labor(b); + } + break; + case df::building_type::FarmPlot: + return df::unit_labor::PLANT; + case df::building_type::Chair: + case df::building_type::Bed: + case df::building_type::Table: + case df::building_type::Coffin: + case df::building_type::Door: + case df::building_type::Floodgate: + case df::building_type::Box: + case df::building_type::Weaponrack: + case df::building_type::Armorstand: + case df::building_type::Cabinet: + case df::building_type::Statue: + case df::building_type::WindowGlass: + case df::building_type::WindowGem: + case df::building_type::Cage: + case df::building_type::NestBox: + case df::building_type::TractionBench: + case df::building_type::Slab: + case df::building_type::Chain: + case df::building_type::GrateFloor: + case df::building_type::Hatch: + case df::building_type::BarsFloor: + case df::building_type::BarsVertical: + case df::building_type::GrateWall: + case df::building_type::Bookcase: + case df::building_type::Instrument: + return df::unit_labor::HAUL_FURNITURE; + case df::building_type::Trap: + case df::building_type::GearAssembly: + case df::building_type::AxleHorizontal: + case df::building_type::AxleVertical: + case df::building_type::Rollers: + return df::unit_labor::MECHANIC; + case df::building_type::AnimalTrap: + return df::unit_labor::TRAPPER; + case df::building_type::Civzone: + case df::building_type::Nest: + case df::building_type::Stockpile: + case df::building_type::Weapon: + return df::unit_labor::NONE; + case df::building_type::SiegeEngine: + return df::unit_labor::SIEGECRAFT; + case df::building_type::RoadDirt: + return df::unit_labor::BUILD_ROAD; + } + + debug("LABORMANAGER: Cannot deduce labor for construct building job of type %s\n", + ENUM_KEY_STR(building_type, bld->getType()).c_str()); + debug_pause(); + + return df::unit_labor::NONE; + } + jlfunc_construct_bld() {} +}; + +class jlfunc_destroy_bld : public jlfunc +{ +public: + df::unit_labor get_labor(df::job* j) + { + df::building* bld = get_building_from_job(j); + df::building_type type = bld->getType(); + + switch (bld->getType()) + { + case df::building_type::Hive: + return df::unit_labor::BEEKEEPING; + case df::building_type::Workshop: + { + df::building_workshopst* ws = (df::building_workshopst*) bld; + if (ws->type == df::workshop_type::Custom) + { + df::building_def* def = df::building_def::find(ws->custom_type); + return def->build_labors[0]; + } + else + return workshop_build_labor[ws->type]; + } + break; + case df::building_type::Construction: + return df::unit_labor::REMOVE_CONSTRUCTION; + case df::building_type::Furnace: + case df::building_type::TradeDepot: + case df::building_type::Wagon: + case df::building_type::Bridge: + case df::building_type::ScrewPump: + case df::building_type::ArcheryTarget: + case df::building_type::RoadPaved: + case df::building_type::Shop: + case df::building_type::Support: + case df::building_type::WaterWheel: + case df::building_type::Well: + case df::building_type::Windmill: + { + auto b = (df::building_actual*) bld; + return construction_build_labor(b); + } + break; + case df::building_type::FarmPlot: + return df::unit_labor::PLANT; + case df::building_type::Trap: + case df::building_type::AxleHorizontal: + case df::building_type::AxleVertical: + case df::building_type::GearAssembly: + case df::building_type::Rollers: + return df::unit_labor::MECHANIC; + case df::building_type::Chair: + case df::building_type::Bed: + case df::building_type::Table: + case df::building_type::Coffin: + case df::building_type::Door: + case df::building_type::Floodgate: + case df::building_type::Box: + case df::building_type::Weaponrack: + case df::building_type::Armorstand: + case df::building_type::Cabinet: + case df::building_type::Statue: + case df::building_type::WindowGlass: + case df::building_type::WindowGem: + case df::building_type::Cage: + case df::building_type::NestBox: + case df::building_type::TractionBench: + case df::building_type::Slab: + case df::building_type::Chain: + case df::building_type::Hatch: + case df::building_type::BarsFloor: + case df::building_type::BarsVertical: + case df::building_type::GrateFloor: + case df::building_type::GrateWall: + case df::building_type::Bookcase: + case df::building_type::Instrument: + return df::unit_labor::HAUL_FURNITURE; + case df::building_type::AnimalTrap: + return df::unit_labor::TRAPPER; + case df::building_type::Civzone: + case df::building_type::Nest: + case df::building_type::RoadDirt: + case df::building_type::Stockpile: + case df::building_type::Weapon: + return df::unit_labor::NONE; + case df::building_type::SiegeEngine: + return df::unit_labor::SIEGECRAFT; + } + + debug("LABORMANAGER: Cannot deduce labor for destroy building job of type %s\n", + ENUM_KEY_STR(building_type, bld->getType()).c_str()); + debug_pause(); + + return df::unit_labor::NONE; + } + jlfunc_destroy_bld() {} +}; + +class jlfunc_make : public jlfunc +{ +private: + df::unit_labor metaltype; +public: + df::unit_labor get_labor(df::job* j) + { + df::building* bld = get_building_from_job(j); + if (bld->getType() == df::building_type::Workshop) + { + df::workshop_type type = ((df::building_workshopst*)(bld))->type; + switch (type) + { + case df::workshop_type::Craftsdwarfs: + { + df::item_type jobitem = j->job_items[0]->item_type; + switch (jobitem) + { + case df::item_type::BOULDER: + return df::unit_labor::STONE_CRAFT; + case df::item_type::NONE: + if (j->material_category.bits.bone || + j->material_category.bits.horn || + j->material_category.bits.tooth || + j->material_category.bits.shell) + return df::unit_labor::BONE_CARVE; + else + { + debug("LABORMANAGER: Cannot deduce labor for make crafts job (not bone)\n"); + debug_pause(); + return df::unit_labor::NONE; + } + case df::item_type::WOOD: + return df::unit_labor::WOOD_CRAFT; + case df::item_type::CLOTH: + return df::unit_labor::CLOTHESMAKER; + case df::item_type::SKIN_TANNED: + return df::unit_labor::LEATHER; + default: + debug("LABORMANAGER: Cannot deduce labor for make crafts job, item type %s\n", + ENUM_KEY_STR(item_type, jobitem).c_str()); + debug_pause(); + return df::unit_labor::NONE; + } + } + case df::workshop_type::Masons: + return df::unit_labor::MASON; + case df::workshop_type::Carpenters: + return df::unit_labor::CARPENTER; + case df::workshop_type::Leatherworks: + return df::unit_labor::LEATHER; + case df::workshop_type::Clothiers: + return df::unit_labor::CLOTHESMAKER; + case df::workshop_type::Bowyers: + return df::unit_labor::BOWYER; + case df::workshop_type::MagmaForge: + case df::workshop_type::MetalsmithsForge: + return metaltype; + default: + debug("LABORMANAGER: Cannot deduce labor for make job, workshop type %s\n", + ENUM_KEY_STR(workshop_type, type).c_str()); + debug_pause(); + return df::unit_labor::NONE; + } + } + else if (bld->getType() == df::building_type::Furnace) + { + df::furnace_type type = ((df::building_furnacest*)(bld))->type; + switch (type) + { + case df::furnace_type::MagmaGlassFurnace: + case df::furnace_type::GlassFurnace: + return df::unit_labor::GLASSMAKER; + default: + debug("LABORMANAGER: Cannot deduce labor for make job, furnace type %s\n", + ENUM_KEY_STR(furnace_type, type).c_str()); + debug_pause(); + return df::unit_labor::NONE; + } + } + + debug("LABORMANAGER: Cannot deduce labor for make job, building type %s\n", + ENUM_KEY_STR(building_type, bld->getType()).c_str()); + debug_pause(); + + return df::unit_labor::NONE; + } + + jlfunc_make(df::unit_labor mt) : metaltype(mt) {} +}; + +class jlfunc_custom : public jlfunc +{ +public: + df::unit_labor get_labor(df::job* j) + { + for (auto r = world->raws.reactions.begin(); r != world->raws.reactions.end(); r++) + { + if ((*r)->code == j->reaction_name) + { + df::job_skill skill = (*r)->skill; + df::unit_labor labor = ENUM_ATTR(job_skill, labor, skill); + return labor; + } + } + return df::unit_labor::NONE; + } + jlfunc_custom() {} +}; + +jlfunc* JobLaborMapper::jlf_const(df::unit_labor l) { + jlfunc* jlf; + if (jlf_cache.count(l) == 0) + { + jlf = new jlfunc_const(l); + jlf_cache[l] = jlf; + } + else + jlf = jlf_cache[l]; + + return jlf; +} + +JobLaborMapper::~JobLaborMapper() +{ + std::set log; + + for (auto i = jlf_cache.begin(); i != jlf_cache.end(); i++) + { + if (!log.count(i->second)) + { + log.insert(i->second); + delete i->second; + } + i->second = 0; + } + + FOR_ENUM_ITEMS(job_type, j) + { + if (j < 0) + continue; + + jlfunc* p = job_to_labor_table[j]; + if (!log.count(p)) + { + log.insert(p); + delete p; + } + job_to_labor_table[j] = 0; + } + +} + +JobLaborMapper::JobLaborMapper() +{ + jlfunc* jlf_hauling = new jlfunc_hauling(); + jlfunc* jlf_make_furniture = new jlfunc_make(df::unit_labor::FORGE_FURNITURE); + jlfunc* jlf_make_object = new jlfunc_make(df::unit_labor::METAL_CRAFT); + jlfunc* jlf_make_armor = new jlfunc_make(df::unit_labor::FORGE_ARMOR); + jlfunc* jlf_make_weapon = new jlfunc_make(df::unit_labor::FORGE_WEAPON); + + jlfunc* jlf_no_labor = jlf_const(df::unit_labor::NONE); + + job_to_labor_table[df::job_type::CarveFortification] = jlf_const(df::unit_labor::DETAIL); + job_to_labor_table[df::job_type::DetailWall] = jlf_const(df::unit_labor::DETAIL); + job_to_labor_table[df::job_type::DetailFloor] = jlf_const(df::unit_labor::DETAIL); + job_to_labor_table[df::job_type::Dig] = jlf_const(df::unit_labor::MINE); + job_to_labor_table[df::job_type::CarveUpwardStaircase] = jlf_const(df::unit_labor::MINE); + job_to_labor_table[df::job_type::CarveDownwardStaircase] = jlf_const(df::unit_labor::MINE); + job_to_labor_table[df::job_type::CarveUpDownStaircase] = jlf_const(df::unit_labor::MINE); + job_to_labor_table[df::job_type::CarveRamp] = jlf_const(df::unit_labor::MINE); + job_to_labor_table[df::job_type::DigChannel] = jlf_const(df::unit_labor::MINE); + job_to_labor_table[df::job_type::FellTree] = jlf_const(df::unit_labor::CUTWOOD); + job_to_labor_table[df::job_type::GatherPlants] = jlf_const(df::unit_labor::HERBALIST); + job_to_labor_table[df::job_type::RemoveConstruction] = jlf_const(df::unit_labor::REMOVE_CONSTRUCTION); + job_to_labor_table[df::job_type::CollectWebs] = jlf_const(df::unit_labor::WEAVER); + job_to_labor_table[df::job_type::BringItemToDepot] = jlf_const(df::unit_labor::HAUL_TRADE); + job_to_labor_table[df::job_type::BringItemToShop] = jlf_no_labor; + job_to_labor_table[df::job_type::Eat] = jlf_no_labor; + job_to_labor_table[df::job_type::GetProvisions] = jlf_no_labor; + job_to_labor_table[df::job_type::Drink] = jlf_no_labor; + job_to_labor_table[df::job_type::Drink2] = jlf_no_labor; + job_to_labor_table[df::job_type::FillWaterskin] = jlf_no_labor; + job_to_labor_table[df::job_type::FillWaterskin2] = jlf_no_labor; + job_to_labor_table[df::job_type::Sleep] = jlf_no_labor; + job_to_labor_table[df::job_type::CollectSand] = jlf_const(df::unit_labor::HAUL_ITEM); + job_to_labor_table[df::job_type::Fish] = jlf_const(df::unit_labor::FISH); + job_to_labor_table[df::job_type::Hunt] = jlf_const(df::unit_labor::HUNT); + job_to_labor_table[df::job_type::HuntVermin] = jlf_no_labor; + job_to_labor_table[df::job_type::Kidnap] = jlf_no_labor; + job_to_labor_table[df::job_type::BeatCriminal] = jlf_no_labor; + job_to_labor_table[df::job_type::StartingFistFight] = jlf_no_labor; + job_to_labor_table[df::job_type::CollectTaxes] = jlf_no_labor; + job_to_labor_table[df::job_type::GuardTaxCollector] = jlf_no_labor; + job_to_labor_table[df::job_type::CatchLiveLandAnimal] = jlf_const(df::unit_labor::HUNT); + job_to_labor_table[df::job_type::CatchLiveFish] = jlf_const(df::unit_labor::FISH); + job_to_labor_table[df::job_type::ReturnKill] = jlf_no_labor; + job_to_labor_table[df::job_type::CheckChest] = jlf_no_labor; + job_to_labor_table[df::job_type::StoreOwnedItem] = jlf_no_labor; + job_to_labor_table[df::job_type::PlaceItemInTomb] = jlf_const(df::unit_labor::HAUL_BODY); + job_to_labor_table[df::job_type::StoreItemInStockpile] = jlf_hauling; + job_to_labor_table[df::job_type::StoreItemInBag] = jlf_hauling; + job_to_labor_table[df::job_type::StoreItemInHospital] = jlf_hauling; + job_to_labor_table[df::job_type::StoreWeapon] = jlf_hauling; + job_to_labor_table[df::job_type::StoreArmor] = jlf_hauling; + job_to_labor_table[df::job_type::StoreItemInBarrel] = jlf_hauling; + job_to_labor_table[df::job_type::StoreItemInBin] = jlf_hauling; + job_to_labor_table[df::job_type::SeekArtifact] = jlf_no_labor; + job_to_labor_table[df::job_type::SeekInfant] = jlf_no_labor; + job_to_labor_table[df::job_type::AttendParty] = jlf_no_labor; + job_to_labor_table[df::job_type::GoShopping] = jlf_no_labor; + job_to_labor_table[df::job_type::GoShopping2] = jlf_no_labor; + job_to_labor_table[df::job_type::Clean] = jlf_const(df::unit_labor::CLEAN); + job_to_labor_table[df::job_type::Rest] = jlf_no_labor; + job_to_labor_table[df::job_type::PickupEquipment] = jlf_no_labor; + job_to_labor_table[df::job_type::DumpItem] = jlf_const(df::unit_labor::HAUL_REFUSE); + job_to_labor_table[df::job_type::StrangeMoodCrafter] = jlf_no_labor; + job_to_labor_table[df::job_type::StrangeMoodJeweller] = jlf_no_labor; + job_to_labor_table[df::job_type::StrangeMoodForge] = jlf_no_labor; + job_to_labor_table[df::job_type::StrangeMoodMagmaForge] = jlf_no_labor; + job_to_labor_table[df::job_type::StrangeMoodBrooding] = jlf_no_labor; + job_to_labor_table[df::job_type::StrangeMoodFell] = jlf_no_labor; + job_to_labor_table[df::job_type::StrangeMoodCarpenter] = jlf_no_labor; + job_to_labor_table[df::job_type::StrangeMoodMason] = jlf_no_labor; + job_to_labor_table[df::job_type::StrangeMoodBowyer] = jlf_no_labor; + job_to_labor_table[df::job_type::StrangeMoodTanner] = jlf_no_labor; + job_to_labor_table[df::job_type::StrangeMoodWeaver] = jlf_no_labor; + job_to_labor_table[df::job_type::StrangeMoodGlassmaker] = jlf_no_labor; + job_to_labor_table[df::job_type::StrangeMoodMechanics] = jlf_no_labor; + job_to_labor_table[df::job_type::ConstructBuilding] = new jlfunc_construct_bld(); + job_to_labor_table[df::job_type::ConstructDoor] = jlf_make_furniture; + job_to_labor_table[df::job_type::ConstructFloodgate] = jlf_make_furniture; + job_to_labor_table[df::job_type::ConstructBed] = jlf_make_furniture; + job_to_labor_table[df::job_type::ConstructThrone] = jlf_make_furniture; + job_to_labor_table[df::job_type::ConstructCoffin] = jlf_make_furniture; + job_to_labor_table[df::job_type::ConstructTable] = jlf_make_furniture; + job_to_labor_table[df::job_type::ConstructChest] = jlf_make_furniture; + job_to_labor_table[df::job_type::ConstructBin] = jlf_make_furniture; + job_to_labor_table[df::job_type::ConstructArmorStand] = jlf_make_furniture; + job_to_labor_table[df::job_type::ConstructWeaponRack] = jlf_make_furniture; + job_to_labor_table[df::job_type::ConstructCabinet] = jlf_make_furniture; + job_to_labor_table[df::job_type::ConstructStatue] = jlf_make_furniture; + job_to_labor_table[df::job_type::ConstructBlocks] = jlf_make_furniture; + job_to_labor_table[df::job_type::MakeRawGlass] = jlf_const(df::unit_labor::GLASSMAKER); + job_to_labor_table[df::job_type::MakeCrafts] = jlf_make_object; job_to_labor_table[df::job_type::MintCoins] = jlf_const(df::unit_labor::METAL_CRAFT); + job_to_labor_table[df::job_type::CutGems] = jlf_const(df::unit_labor::CUT_GEM); + job_to_labor_table[df::job_type::CutGlass] = jlf_const(df::unit_labor::CUT_GEM); + job_to_labor_table[df::job_type::EncrustWithGems] = jlf_const(df::unit_labor::ENCRUST_GEM); + job_to_labor_table[df::job_type::EncrustWithGlass] = jlf_const(df::unit_labor::ENCRUST_GEM); + job_to_labor_table[df::job_type::DestroyBuilding] = new jlfunc_destroy_bld(); + job_to_labor_table[df::job_type::SmeltOre] = jlf_const(df::unit_labor::SMELT); + job_to_labor_table[df::job_type::MeltMetalObject] = jlf_const(df::unit_labor::SMELT); + job_to_labor_table[df::job_type::ExtractMetalStrands] = jlf_const(df::unit_labor::EXTRACT_STRAND); + job_to_labor_table[df::job_type::PlantSeeds] = jlf_const(df::unit_labor::PLANT); + job_to_labor_table[df::job_type::HarvestPlants] = jlf_const(df::unit_labor::PLANT); + job_to_labor_table[df::job_type::TrainHuntingAnimal] = jlf_const(df::unit_labor::ANIMALTRAIN); + job_to_labor_table[df::job_type::TrainWarAnimal] = jlf_const(df::unit_labor::ANIMALTRAIN); + job_to_labor_table[df::job_type::MakeWeapon] = jlf_make_weapon; + job_to_labor_table[df::job_type::ForgeAnvil] = jlf_make_furniture; + job_to_labor_table[df::job_type::ConstructCatapultParts] = jlf_const(df::unit_labor::SIEGECRAFT); + job_to_labor_table[df::job_type::ConstructBallistaParts] = jlf_const(df::unit_labor::SIEGECRAFT); + job_to_labor_table[df::job_type::MakeArmor] = jlf_make_armor; + job_to_labor_table[df::job_type::MakeHelm] = jlf_make_armor; + job_to_labor_table[df::job_type::MakePants] = jlf_make_armor; + job_to_labor_table[df::job_type::StudWith] = jlf_make_object; + job_to_labor_table[df::job_type::ButcherAnimal] = jlf_const(df::unit_labor::BUTCHER); + job_to_labor_table[df::job_type::PrepareRawFish] = jlf_const(df::unit_labor::CLEAN_FISH); + job_to_labor_table[df::job_type::MillPlants] = jlf_const(df::unit_labor::MILLER); + job_to_labor_table[df::job_type::BaitTrap] = jlf_const(df::unit_labor::TRAPPER); + job_to_labor_table[df::job_type::MilkCreature] = jlf_const(df::unit_labor::MILK); + job_to_labor_table[df::job_type::MakeCheese] = jlf_const(df::unit_labor::MAKE_CHEESE); + job_to_labor_table[df::job_type::ProcessPlants] = jlf_const(df::unit_labor::PROCESS_PLANT); + job_to_labor_table[df::job_type::ProcessPlantsVial] = jlf_const(df::unit_labor::PROCESS_PLANT); + job_to_labor_table[df::job_type::ProcessPlantsBarrel] = jlf_const(df::unit_labor::PROCESS_PLANT); + job_to_labor_table[df::job_type::PrepareMeal] = jlf_const(df::unit_labor::COOK); + job_to_labor_table[df::job_type::WeaveCloth] = jlf_const(df::unit_labor::WEAVER); + job_to_labor_table[df::job_type::MakeGloves] = jlf_make_armor; + job_to_labor_table[df::job_type::MakeShoes] = jlf_make_armor; + job_to_labor_table[df::job_type::MakeShield] = jlf_make_armor; + job_to_labor_table[df::job_type::MakeCage] = jlf_make_furniture; + job_to_labor_table[df::job_type::MakeChain] = jlf_make_object; + job_to_labor_table[df::job_type::MakeFlask] = jlf_make_object; + job_to_labor_table[df::job_type::MakeGoblet] = jlf_make_object; + job_to_labor_table[df::job_type::MakeToy] = jlf_make_object; + job_to_labor_table[df::job_type::MakeAnimalTrap] = jlf_const(df::unit_labor::TRAPPER); + job_to_labor_table[df::job_type::MakeBarrel] = jlf_make_furniture; + job_to_labor_table[df::job_type::MakeBucket] = jlf_make_furniture; + job_to_labor_table[df::job_type::MakeWindow] = jlf_make_furniture; + job_to_labor_table[df::job_type::MakeTotem] = jlf_const(df::unit_labor::BONE_CARVE); + job_to_labor_table[df::job_type::MakeAmmo] = jlf_make_weapon; + job_to_labor_table[df::job_type::DecorateWith] = jlf_make_object; + job_to_labor_table[df::job_type::MakeBackpack] = jlf_make_object; + job_to_labor_table[df::job_type::MakeQuiver] = jlf_make_armor; + job_to_labor_table[df::job_type::MakeBallistaArrowHead] = jlf_make_weapon; + job_to_labor_table[df::job_type::AssembleSiegeAmmo] = jlf_const(df::unit_labor::SIEGECRAFT); + job_to_labor_table[df::job_type::LoadCatapult] = jlf_const(df::unit_labor::SIEGEOPERATE); + job_to_labor_table[df::job_type::LoadBallista] = jlf_const(df::unit_labor::SIEGEOPERATE); + job_to_labor_table[df::job_type::FireCatapult] = jlf_const(df::unit_labor::SIEGEOPERATE); + job_to_labor_table[df::job_type::FireBallista] = jlf_const(df::unit_labor::SIEGEOPERATE); + job_to_labor_table[df::job_type::ConstructMechanisms] = jlf_const(df::unit_labor::MECHANIC); + job_to_labor_table[df::job_type::MakeTrapComponent] = jlf_make_weapon; + job_to_labor_table[df::job_type::LoadCageTrap] = jlf_const(df::unit_labor::MECHANIC); + job_to_labor_table[df::job_type::LoadStoneTrap] = jlf_const(df::unit_labor::MECHANIC); + job_to_labor_table[df::job_type::LoadWeaponTrap] = jlf_const(df::unit_labor::MECHANIC); + job_to_labor_table[df::job_type::CleanTrap] = jlf_const(df::unit_labor::MECHANIC); + job_to_labor_table[df::job_type::CastSpell] = jlf_no_labor; + job_to_labor_table[df::job_type::LinkBuildingToTrigger] = jlf_const(df::unit_labor::MECHANIC); + job_to_labor_table[df::job_type::PullLever] = jlf_const(df::unit_labor::PULL_LEVER); + job_to_labor_table[df::job_type::ExtractFromPlants] = jlf_const(df::unit_labor::HERBALIST); + job_to_labor_table[df::job_type::ExtractFromRawFish] = jlf_const(df::unit_labor::DISSECT_FISH); + job_to_labor_table[df::job_type::ExtractFromLandAnimal] = jlf_const(df::unit_labor::DISSECT_VERMIN); + job_to_labor_table[df::job_type::TameVermin] = jlf_const(df::unit_labor::ANIMALTRAIN); + job_to_labor_table[df::job_type::TameAnimal] = jlf_const(df::unit_labor::ANIMALTRAIN); + job_to_labor_table[df::job_type::ChainAnimal] = jlf_const(df::unit_labor::HAUL_ANIMALS); + job_to_labor_table[df::job_type::UnchainAnimal] = jlf_const(df::unit_labor::HAUL_ANIMALS); + job_to_labor_table[df::job_type::UnchainPet] = jlf_no_labor; + job_to_labor_table[df::job_type::ReleaseLargeCreature] = jlf_const(df::unit_labor::HAUL_ANIMALS); + job_to_labor_table[df::job_type::ReleasePet] = jlf_no_labor; + job_to_labor_table[df::job_type::ReleaseSmallCreature] = jlf_no_labor; + job_to_labor_table[df::job_type::HandleSmallCreature] = jlf_no_labor; + job_to_labor_table[df::job_type::HandleLargeCreature] = jlf_const(df::unit_labor::HAUL_ANIMALS); + job_to_labor_table[df::job_type::CageLargeCreature] = jlf_const(df::unit_labor::HAUL_ANIMALS); + job_to_labor_table[df::job_type::CageSmallCreature] = jlf_no_labor; + job_to_labor_table[df::job_type::RecoverWounded] = jlf_const(df::unit_labor::RECOVER_WOUNDED); + job_to_labor_table[df::job_type::DiagnosePatient] = jlf_const(df::unit_labor::DIAGNOSE); + job_to_labor_table[df::job_type::ImmobilizeBreak] = jlf_const(df::unit_labor::BONE_SETTING); + job_to_labor_table[df::job_type::DressWound] = jlf_const(df::unit_labor::DRESSING_WOUNDS); + job_to_labor_table[df::job_type::CleanPatient] = jlf_const(df::unit_labor::DRESSING_WOUNDS); + job_to_labor_table[df::job_type::Surgery] = jlf_const(df::unit_labor::SURGERY); + job_to_labor_table[df::job_type::Suture] = jlf_const(df::unit_labor::SUTURING); + job_to_labor_table[df::job_type::SetBone] = jlf_const(df::unit_labor::BONE_SETTING); + job_to_labor_table[df::job_type::PlaceInTraction] = jlf_const(df::unit_labor::BONE_SETTING); + job_to_labor_table[df::job_type::DrainAquarium] = jlf_no_labor; + job_to_labor_table[df::job_type::FillAquarium] = jlf_no_labor; + job_to_labor_table[df::job_type::FillPond] = jlf_no_labor; + job_to_labor_table[df::job_type::GiveWater] = jlf_const(df::unit_labor::FEED_WATER_CIVILIANS); + job_to_labor_table[df::job_type::GiveFood] = jlf_const(df::unit_labor::FEED_WATER_CIVILIANS); + job_to_labor_table[df::job_type::GiveWater2] = jlf_no_labor; + job_to_labor_table[df::job_type::GiveFood2] = jlf_no_labor; + job_to_labor_table[df::job_type::RecoverPet] = jlf_no_labor; + job_to_labor_table[df::job_type::PitLargeAnimal] = jlf_const(df::unit_labor::HAUL_ANIMALS); + job_to_labor_table[df::job_type::PitSmallAnimal] = jlf_no_labor; + job_to_labor_table[df::job_type::SlaughterAnimal] = jlf_const(df::unit_labor::BUTCHER); + job_to_labor_table[df::job_type::MakeCharcoal] = jlf_const(df::unit_labor::BURN_WOOD); + job_to_labor_table[df::job_type::MakeAsh] = jlf_const(df::unit_labor::BURN_WOOD); + job_to_labor_table[df::job_type::MakeLye] = jlf_const(df::unit_labor::LYE_MAKING); + job_to_labor_table[df::job_type::MakePotashFromLye] = jlf_const(df::unit_labor::POTASH_MAKING); + job_to_labor_table[df::job_type::FertilizeField] = jlf_const(df::unit_labor::PLANT); + job_to_labor_table[df::job_type::MakePotashFromAsh] = jlf_const(df::unit_labor::POTASH_MAKING); + job_to_labor_table[df::job_type::DyeThread] = jlf_const(df::unit_labor::DYER); + job_to_labor_table[df::job_type::DyeCloth] = jlf_const(df::unit_labor::DYER); + job_to_labor_table[df::job_type::SewImage] = jlf_make_object; + job_to_labor_table[df::job_type::MakePipeSection] = jlf_make_furniture; + job_to_labor_table[df::job_type::OperatePump] = jlf_const(df::unit_labor::OPERATE_PUMP); + job_to_labor_table[df::job_type::ManageWorkOrders] = jlf_no_labor; + job_to_labor_table[df::job_type::UpdateStockpileRecords] = jlf_no_labor; + job_to_labor_table[df::job_type::TradeAtDepot] = jlf_no_labor; + job_to_labor_table[df::job_type::ConstructHatchCover] = jlf_make_furniture; + job_to_labor_table[df::job_type::ConstructGrate] = jlf_make_furniture; + job_to_labor_table[df::job_type::RemoveStairs] = jlf_const(df::unit_labor::MINE); + job_to_labor_table[df::job_type::ConstructQuern] = jlf_make_furniture; + job_to_labor_table[df::job_type::ConstructMillstone] = jlf_make_furniture; + job_to_labor_table[df::job_type::ConstructSplint] = jlf_make_furniture; + job_to_labor_table[df::job_type::ConstructCrutch] = jlf_make_furniture; + job_to_labor_table[df::job_type::ConstructTractionBench] = jlf_const(df::unit_labor::MECHANIC); + job_to_labor_table[df::job_type::CleanSelf] = jlf_no_labor; + job_to_labor_table[df::job_type::BringCrutch] = jlf_const(df::unit_labor::BONE_SETTING); + job_to_labor_table[df::job_type::ApplyCast] = jlf_const(df::unit_labor::BONE_SETTING); + job_to_labor_table[df::job_type::CustomReaction] = new jlfunc_custom(); + job_to_labor_table[df::job_type::ConstructSlab] = jlf_make_furniture; + job_to_labor_table[df::job_type::EngraveSlab] = jlf_const(df::unit_labor::DETAIL); + job_to_labor_table[df::job_type::ShearCreature] = jlf_const(df::unit_labor::SHEARER); + job_to_labor_table[df::job_type::SpinThread] = jlf_const(df::unit_labor::SPINNER); + job_to_labor_table[df::job_type::PenLargeAnimal] = jlf_const(df::unit_labor::HAUL_ANIMALS); + job_to_labor_table[df::job_type::PenSmallAnimal] = jlf_no_labor; + job_to_labor_table[df::job_type::MakeTool] = jlf_make_object; + job_to_labor_table[df::job_type::CollectClay] = jlf_const(df::unit_labor::POTTERY); + job_to_labor_table[df::job_type::InstallColonyInHive] = jlf_const(df::unit_labor::BEEKEEPING); + job_to_labor_table[df::job_type::CollectHiveProducts] = jlf_const(df::unit_labor::BEEKEEPING); + job_to_labor_table[df::job_type::CauseTrouble] = jlf_no_labor; + job_to_labor_table[df::job_type::DrinkBlood] = jlf_no_labor; + job_to_labor_table[df::job_type::ReportCrime] = jlf_no_labor; + job_to_labor_table[df::job_type::ExecuteCriminal] = jlf_no_labor; + job_to_labor_table[df::job_type::TrainAnimal] = jlf_const(df::unit_labor::ANIMALTRAIN); + job_to_labor_table[df::job_type::CarveTrack] = jlf_const(df::unit_labor::DETAIL); + job_to_labor_table[df::job_type::PushTrackVehicle] = jlf_const(df::unit_labor::HANDLE_VEHICLES); + job_to_labor_table[df::job_type::PlaceTrackVehicle] = jlf_const(df::unit_labor::HANDLE_VEHICLES); + job_to_labor_table[df::job_type::StoreItemInVehicle] = jlf_hauling; + job_to_labor_table[df::job_type::GeldAnimal] = jlf_const(df::unit_labor::GELD); + job_to_labor_table[df::job_type::MakeFigurine] = jlf_make_object; + job_to_labor_table[df::job_type::MakeAmulet] = jlf_make_object; + job_to_labor_table[df::job_type::MakeScepter] = jlf_make_object; + job_to_labor_table[df::job_type::MakeCrown] = jlf_make_object; + job_to_labor_table[df::job_type::MakeRing] = jlf_make_object; + job_to_labor_table[df::job_type::MakeEarring] = jlf_make_object; + job_to_labor_table[df::job_type::MakeBracelet] = jlf_make_object; + job_to_labor_table[df::job_type::MakeGem] = jlf_make_object; + + job_to_labor_table[df::job_type::StoreItemInLocation] = jlf_no_labor; // StoreItemInLocation +}; + +df::unit_labor JobLaborMapper::find_job_labor(df::job* j) +{ + if (j->job_type == df::job_type::CustomReaction) + { + for (auto r = world->raws.reactions.begin(); r != world->raws.reactions.end(); r++) + { + if ((*r)->code == j->reaction_name) + { + df::job_skill skill = (*r)->skill; + return ENUM_ATTR(job_skill, labor, skill); + } + } + return df::unit_labor::NONE; + } + + + df::unit_labor labor; + if (job_to_labor_table.count(j->job_type) == 0) + { + debug("LABORMANAGER: job has no job to labor table entry: %s (%d)\n", ENUM_KEY_STR(job_type, j->job_type).c_str(), j->job_type); + debug_pause(); + labor = df::unit_labor::NONE; + } + else { + + labor = job_to_labor_table[j->job_type]->get_labor(j); + } + + return labor; +} + +/* End of labor deducer */ \ No newline at end of file diff --git a/plugins/labormanager/joblabormapper.h b/plugins/labormanager/joblabormapper.h new file mode 100644 index 000000000..37d405f54 --- /dev/null +++ b/plugins/labormanager/joblabormapper.h @@ -0,0 +1,32 @@ +#pragma once + +#include + +#include + +using namespace DFHack; +using namespace df::enums; + +#include "df/job.h" +#include "df/job_type.h" +#include "df/unit_labor.h" + + +class jlfunc; + +class JobLaborMapper { + +private: + std::map job_to_labor_table; + std::map jlf_cache; + + jlfunc* jlf_const(df::unit_labor l); + +public: + ~JobLaborMapper(); + JobLaborMapper(); + + df::unit_labor find_job_labor(df::job* j); + + +}; diff --git a/plugins/labormanager.cpp b/plugins/labormanager/labormanager.cpp similarity index 59% rename from plugins/labormanager.cpp rename to plugins/labormanager/labormanager.cpp index cec70ab1e..cefdc90f9 100644 --- a/plugins/labormanager.cpp +++ b/plugins/labormanager/labormanager.cpp @@ -68,6 +68,9 @@ #include #include +#include "labormanager.h" +#include "joblabormapper.h" + using namespace std; using std::string; using std::endl; @@ -96,7 +99,7 @@ enum ConfigFlags { // Here go all the command declarations... // mostly to allow having the mandatory stuff on top of the file and commands on the bottom -command_result labormanager (color_ostream &out, std::vector & parameters); +command_result labormanager(color_ostream &out, std::vector & parameters); // A plugin must be able to return its name and version. // The name string provided must correspond to the filename - labormanager.plug.so or labormanager.plug.dll in this case @@ -393,8 +396,8 @@ struct labor_info return (*df::global::cur_year - config.ival(3)) * 403200 + *df::global::cur_year_tick - config.ival(4); } void mark_assigned() { - config.ival(3) = (* df::global::cur_year); - config.ival(4) = (* df::global::cur_year_tick); + config.ival(3) = (*df::global::cur_year); + config.ival(4) = (*df::global::cur_year_tick); } }; @@ -500,7 +503,7 @@ static const struct labor_default default_labor_infos[] = { /* BOOKBINDING */ {100, 0, TOOL_NONE} }; -void debug (char* fmt, ...); + struct dwarf_info_t { @@ -531,189 +534,20 @@ struct dwarf_info_t }; -/* -* Here starts all the complicated stuff to try to deduce labors from jobs. -* This is all way more complicated than it really ought to be, but I have -* not found a way to make it simpler. -*/ - -static df::unit_labor hauling_labor_map[] = -{ - df::unit_labor::HAUL_ITEM, /* BAR */ - df::unit_labor::HAUL_STONE, /* SMALLGEM */ - df::unit_labor::HAUL_ITEM, /* BLOCKS */ - df::unit_labor::HAUL_STONE, /* ROUGH */ - df::unit_labor::HAUL_STONE, /* BOULDER */ - df::unit_labor::HAUL_WOOD, /* WOOD */ - df::unit_labor::HAUL_FURNITURE, /* DOOR */ - df::unit_labor::HAUL_FURNITURE, /* FLOODGATE */ - df::unit_labor::HAUL_FURNITURE, /* BED */ - df::unit_labor::HAUL_FURNITURE, /* CHAIR */ - df::unit_labor::HAUL_ITEM, /* CHAIN */ - df::unit_labor::HAUL_ITEM, /* FLASK */ - df::unit_labor::HAUL_ITEM, /* GOBLET */ - df::unit_labor::HAUL_ITEM, /* INSTRUMENT */ - df::unit_labor::HAUL_ITEM, /* TOY */ - df::unit_labor::HAUL_FURNITURE, /* WINDOW */ - df::unit_labor::HAUL_ANIMALS, /* CAGE */ - df::unit_labor::HAUL_ITEM, /* BARREL */ - df::unit_labor::HAUL_ITEM, /* BUCKET */ - df::unit_labor::HAUL_ANIMALS, /* ANIMALTRAP */ - df::unit_labor::HAUL_FURNITURE, /* TABLE */ - df::unit_labor::HAUL_FURNITURE, /* COFFIN */ - df::unit_labor::HAUL_FURNITURE, /* STATUE */ - df::unit_labor::HAUL_REFUSE, /* CORPSE */ - df::unit_labor::HAUL_ITEM, /* WEAPON */ - df::unit_labor::HAUL_ITEM, /* ARMOR */ - df::unit_labor::HAUL_ITEM, /* SHOES */ - df::unit_labor::HAUL_ITEM, /* SHIELD */ - df::unit_labor::HAUL_ITEM, /* HELM */ - df::unit_labor::HAUL_ITEM, /* GLOVES */ - df::unit_labor::HAUL_FURNITURE, /* BOX */ - df::unit_labor::HAUL_ITEM, /* BIN */ - df::unit_labor::HAUL_FURNITURE, /* ARMORSTAND */ - df::unit_labor::HAUL_FURNITURE, /* WEAPONRACK */ - df::unit_labor::HAUL_FURNITURE, /* CABINET */ - df::unit_labor::HAUL_ITEM, /* FIGURINE */ - df::unit_labor::HAUL_ITEM, /* AMULET */ - df::unit_labor::HAUL_ITEM, /* SCEPTER */ - df::unit_labor::HAUL_ITEM, /* AMMO */ - df::unit_labor::HAUL_ITEM, /* CROWN */ - df::unit_labor::HAUL_ITEM, /* RING */ - df::unit_labor::HAUL_ITEM, /* EARRING */ - df::unit_labor::HAUL_ITEM, /* BRACELET */ - df::unit_labor::HAUL_ITEM, /* GEM */ - df::unit_labor::HAUL_FURNITURE, /* ANVIL */ - df::unit_labor::HAUL_REFUSE, /* CORPSEPIECE */ - df::unit_labor::HAUL_REFUSE, /* REMAINS */ - df::unit_labor::HAUL_FOOD, /* MEAT */ - df::unit_labor::HAUL_FOOD, /* FISH */ - df::unit_labor::HAUL_FOOD, /* FISH_RAW */ - df::unit_labor::HAUL_REFUSE, /* VERMIN */ - df::unit_labor::HAUL_ITEM, /* PET */ - df::unit_labor::HAUL_ITEM, /* SEEDS */ - df::unit_labor::HAUL_FOOD, /* PLANT */ - df::unit_labor::HAUL_ITEM, /* SKIN_TANNED */ - df::unit_labor::HAUL_FOOD, /* LEAVES */ - df::unit_labor::HAUL_ITEM, /* THREAD */ - df::unit_labor::HAUL_ITEM, /* CLOTH */ - df::unit_labor::HAUL_ITEM, /* TOTEM */ - df::unit_labor::HAUL_ITEM, /* PANTS */ - df::unit_labor::HAUL_ITEM, /* BACKPACK */ - df::unit_labor::HAUL_ITEM, /* QUIVER */ - df::unit_labor::HAUL_FURNITURE, /* CATAPULTPARTS */ - df::unit_labor::HAUL_FURNITURE, /* BALLISTAPARTS */ - df::unit_labor::HAUL_FURNITURE, /* SIEGEAMMO */ - df::unit_labor::HAUL_FURNITURE, /* BALLISTAARROWHEAD */ - df::unit_labor::HAUL_FURNITURE, /* TRAPPARTS */ - df::unit_labor::HAUL_FURNITURE, /* TRAPCOMP */ - df::unit_labor::HAUL_FOOD, /* DRINK */ - df::unit_labor::HAUL_FOOD, /* POWDER_MISC */ - df::unit_labor::HAUL_FOOD, /* CHEESE */ - df::unit_labor::HAUL_FOOD, /* FOOD */ - df::unit_labor::HAUL_FOOD, /* LIQUID_MISC */ - df::unit_labor::HAUL_ITEM, /* COIN */ - df::unit_labor::HAUL_FOOD, /* GLOB */ - df::unit_labor::HAUL_STONE, /* ROCK */ - df::unit_labor::HAUL_FURNITURE, /* PIPE_SECTION */ - df::unit_labor::HAUL_FURNITURE, /* HATCH_COVER */ - df::unit_labor::HAUL_FURNITURE, /* GRATE */ - df::unit_labor::HAUL_FURNITURE, /* QUERN */ - df::unit_labor::HAUL_FURNITURE, /* MILLSTONE */ - df::unit_labor::HAUL_ITEM, /* SPLINT */ - df::unit_labor::HAUL_ITEM, /* CRUTCH */ - df::unit_labor::HAUL_FURNITURE, /* TRACTION_BENCH */ - df::unit_labor::HAUL_ITEM, /* ORTHOPEDIC_CAST */ - df::unit_labor::HAUL_ITEM, /* TOOL */ - df::unit_labor::HAUL_FURNITURE, /* SLAB */ - df::unit_labor::HAUL_FOOD, /* EGG */ - df::unit_labor::HAUL_ITEM, /* BOOK */ -}; - -static df::unit_labor workshop_build_labor[] = -{ - /* Carpenters */ df::unit_labor::CARPENTER, - /* Farmers */ df::unit_labor::PROCESS_PLANT, - /* Masons */ df::unit_labor::MASON, - /* Craftsdwarfs */ df::unit_labor::STONE_CRAFT, - /* Jewelers */ df::unit_labor::CUT_GEM, - /* MetalsmithsForge */ df::unit_labor::METAL_CRAFT, - /* MagmaForge */ df::unit_labor::METAL_CRAFT, - /* Bowyers */ df::unit_labor::BOWYER, - /* Mechanics */ df::unit_labor::MECHANIC, - /* Siege */ df::unit_labor::SIEGECRAFT, - /* Butchers */ df::unit_labor::BUTCHER, - /* Leatherworks */ df::unit_labor::LEATHER, - /* Tanners */ df::unit_labor::TANNER, - /* Clothiers */ df::unit_labor::CLOTHESMAKER, - /* Fishery */ df::unit_labor::CLEAN_FISH, - /* Still */ df::unit_labor::BREWER, - /* Loom */ df::unit_labor::WEAVER, - /* Quern */ df::unit_labor::MILLER, - /* Kennels */ df::unit_labor::ANIMALTRAIN, - /* Kitchen */ df::unit_labor::COOK, - /* Ashery */ df::unit_labor::LYE_MAKING, - /* Dyers */ df::unit_labor::DYER, - /* Millstone */ df::unit_labor::MILLER, - /* Custom */ df::unit_labor::NONE, - /* Tool */ df::unit_labor::NONE -}; - -static df::building* get_building_from_job(df::job* j) -{ - for (auto r = j->general_refs.begin(); r != j->general_refs.end(); r++) - { - if ((*r)->getType() == df::general_ref_type::BUILDING_HOLDER) - { - int32_t id = ((df::general_ref_building_holderst*)(*r))->building_id; - df::building* bld = binsearch_in_vector(world->buildings.all, id); - return bld; - } - } - return 0; -} - -static df::unit_labor construction_build_labor (df::building_actual* b) -{ - if (b->getType() == df::building_type::RoadPaved) - return df::unit_labor::BUILD_ROAD; - // Find last item in building with use mode appropriate to the building's constructions state - // For screw pumps contained_items[0] = pipe, 1 corkscrew, 2 block - // For wells 0 mechanism, 1 rope, 2 bucket, 3 block - // Trade depots and bridges use the last one too - // Must check use mode b/c buildings may have items in them that are not part of the building - - df::item* i = 0; - for (auto p = b->contained_items.begin(); p != b->contained_items.end(); p++) - if (b->construction_stage > 0 && (*p)->use_mode == 2 || - b->construction_stage == 0 && (*p)->use_mode == 0) - i = (*p)->item; - - MaterialInfo matinfo; - if (i && matinfo.decode(i)) - { - if (matinfo.material->flags.is_set(df::material_flags::IS_METAL)) - return df::unit_labor::METAL_CRAFT; - if (matinfo.material->flags.is_set(df::material_flags::WOOD)) - return df::unit_labor::CARPENTER; - } - return df::unit_labor::MASON; -} - color_ostream* debug_stream; -void debug (const char* fmt, ...) +void debug(const char* fmt, ...) { if (debug_stream) { va_list args; - va_start(args,fmt); + va_start(args, fmt); debug_stream->vprint(fmt, args); va_end(args); } } -void debug_pause () +void debug_pause() { if (pause_on_error) { @@ -722,707 +556,6 @@ void debug_pause () } } -class JobLaborMapper { - -private: - class jlfunc - { - public: - virtual df::unit_labor get_labor(df::job* j) = 0; - }; - - class jlfunc_const : public jlfunc - { - private: - df::unit_labor labor; - public: - df::unit_labor get_labor(df::job* j) - { - return labor; - } - jlfunc_const(df::unit_labor l) : labor(l) {}; - }; - - class jlfunc_hauling : public jlfunc - { - public: - df::unit_labor get_labor(df::job* j) - { - df::item* item = 0; - if (j->job_type == df::job_type::StoreItemInStockpile && j->item_subtype != -1) - return (df::unit_labor) j->item_subtype; - - for (auto i = j->items.begin(); i != j->items.end(); i++) - { - if ((*i)->role == 7) - { - item = (*i)->item; - break; - } - } - - if (item && item->flags.bits.container) - { - for (auto a = item->general_refs.begin(); a != item->general_refs.end(); a++) - { - if ((*a)->getType() == df::general_ref_type::CONTAINS_ITEM) - { - int item_id = ((df::general_ref_contains_itemst *) (*a))->item_id; - item = binsearch_in_vector(world->items.all, item_id); - break; - } - } - } - - df::unit_labor l = item ? hauling_labor_map[item->getType()] : df::unit_labor::HAUL_ITEM; - if (item && l == df::unit_labor::HAUL_REFUSE && item->flags.bits.dead_dwarf) - l = df::unit_labor::HAUL_BODY; - return l; - } - jlfunc_hauling() {}; - }; - - class jlfunc_construct_bld : public jlfunc - { - public: - df::unit_labor get_labor(df::job* j) - { - if (j->flags.bits.item_lost) - return df::unit_labor::NONE; - - df::building* bld = get_building_from_job (j); - switch (bld->getType()) - { - case df::building_type::Hive: - return df::unit_labor::BEEKEEPING; - case df::building_type::Workshop: - { - df::building_workshopst* ws = (df::building_workshopst*) bld; - if (ws->design && !ws->design->flags.bits.designed) - return df::unit_labor::ARCHITECT; - if (ws->type == df::workshop_type::Custom) - { - df::building_def* def = df::building_def::find(ws->custom_type); - return def->build_labors[0]; - } - else - return workshop_build_labor[ws->type]; - } - break; - case df::building_type::Construction: - return df::unit_labor::BUILD_CONSTRUCTION; - case df::building_type::Furnace: - case df::building_type::TradeDepot: - case df::building_type::Bridge: - case df::building_type::ArcheryTarget: - case df::building_type::WaterWheel: - case df::building_type::RoadPaved: - case df::building_type::Well: - case df::building_type::ScrewPump: - case df::building_type::Wagon: - case df::building_type::Shop: - case df::building_type::Support: - case df::building_type::Windmill: - { - df::building_actual* b = (df::building_actual*) bld; - if (b->design && !b->design->flags.bits.designed) - return df::unit_labor::ARCHITECT; - return construction_build_labor(b); - } - break; - case df::building_type::FarmPlot: - return df::unit_labor::PLANT; - case df::building_type::Chair: - case df::building_type::Bed: - case df::building_type::Table: - case df::building_type::Coffin: - case df::building_type::Door: - case df::building_type::Floodgate: - case df::building_type::Box: - case df::building_type::Weaponrack: - case df::building_type::Armorstand: - case df::building_type::Cabinet: - case df::building_type::Statue: - case df::building_type::WindowGlass: - case df::building_type::WindowGem: - case df::building_type::Cage: - case df::building_type::NestBox: - case df::building_type::TractionBench: - case df::building_type::Slab: - case df::building_type::Chain: - case df::building_type::GrateFloor: - case df::building_type::Hatch: - case df::building_type::BarsFloor: - case df::building_type::BarsVertical: - case df::building_type::GrateWall: - case df::building_type::Bookcase: - case df::building_type::Instrument: - return df::unit_labor::HAUL_FURNITURE; - case df::building_type::Trap: - case df::building_type::GearAssembly: - case df::building_type::AxleHorizontal: - case df::building_type::AxleVertical: - case df::building_type::Rollers: - return df::unit_labor::MECHANIC; - case df::building_type::AnimalTrap: - return df::unit_labor::TRAPPER; - case df::building_type::Civzone: - case df::building_type::Nest: - case df::building_type::Stockpile: - case df::building_type::Weapon: - return df::unit_labor::NONE; - case df::building_type::SiegeEngine: - return df::unit_labor::SIEGECRAFT; - case df::building_type::RoadDirt: - return df::unit_labor::BUILD_ROAD; - } - - debug ("LABORMANAGER: Cannot deduce labor for construct building job of type %s\n", - ENUM_KEY_STR(building_type, bld->getType()).c_str()); - debug_pause(); - - return df::unit_labor::NONE; - } - jlfunc_construct_bld() {} - }; - - class jlfunc_destroy_bld : public jlfunc - { - public: - df::unit_labor get_labor(df::job* j) - { - df::building* bld = get_building_from_job (j); - df::building_type type = bld->getType(); - - switch (bld->getType()) - { - case df::building_type::Hive: - return df::unit_labor::BEEKEEPING; - case df::building_type::Workshop: - { - df::building_workshopst* ws = (df::building_workshopst*) bld; - if (ws->type == df::workshop_type::Custom) - { - df::building_def* def = df::building_def::find(ws->custom_type); - return def->build_labors[0]; - } - else - return workshop_build_labor[ws->type]; - } - break; - case df::building_type::Construction: - return df::unit_labor::REMOVE_CONSTRUCTION; - case df::building_type::Furnace: - case df::building_type::TradeDepot: - case df::building_type::Wagon: - case df::building_type::Bridge: - case df::building_type::ScrewPump: - case df::building_type::ArcheryTarget: - case df::building_type::RoadPaved: - case df::building_type::Shop: - case df::building_type::Support: - case df::building_type::WaterWheel: - case df::building_type::Well: - case df::building_type::Windmill: - { - auto b = (df::building_actual*) bld; - return construction_build_labor(b); - } - break; - case df::building_type::FarmPlot: - return df::unit_labor::PLANT; - case df::building_type::Trap: - case df::building_type::AxleHorizontal: - case df::building_type::AxleVertical: - case df::building_type::GearAssembly: - case df::building_type::Rollers: - return df::unit_labor::MECHANIC; - case df::building_type::Chair: - case df::building_type::Bed: - case df::building_type::Table: - case df::building_type::Coffin: - case df::building_type::Door: - case df::building_type::Floodgate: - case df::building_type::Box: - case df::building_type::Weaponrack: - case df::building_type::Armorstand: - case df::building_type::Cabinet: - case df::building_type::Statue: - case df::building_type::WindowGlass: - case df::building_type::WindowGem: - case df::building_type::Cage: - case df::building_type::NestBox: - case df::building_type::TractionBench: - case df::building_type::Slab: - case df::building_type::Chain: - case df::building_type::Hatch: - case df::building_type::BarsFloor: - case df::building_type::BarsVertical: - case df::building_type::GrateFloor: - case df::building_type::GrateWall: - case df::building_type::Bookcase: - case df::building_type::Instrument: - return df::unit_labor::HAUL_FURNITURE; - case df::building_type::AnimalTrap: - return df::unit_labor::TRAPPER; - case df::building_type::Civzone: - case df::building_type::Nest: - case df::building_type::RoadDirt: - case df::building_type::Stockpile: - case df::building_type::Weapon: - return df::unit_labor::NONE; - case df::building_type::SiegeEngine: - return df::unit_labor::SIEGECRAFT; - } - - debug ("LABORMANAGER: Cannot deduce labor for destroy building job of type %s\n", - ENUM_KEY_STR(building_type, bld->getType()).c_str()); - debug_pause(); - - return df::unit_labor::NONE; - } - jlfunc_destroy_bld() {} - }; - - class jlfunc_make : public jlfunc - { - private: - df::unit_labor metaltype; - public: - df::unit_labor get_labor(df::job* j) - { - df::building* bld = get_building_from_job(j); - if (bld->getType() == df::building_type::Workshop) - { - df::workshop_type type = ((df::building_workshopst*)(bld))->type; - switch (type) - { - case df::workshop_type::Craftsdwarfs: - { - df::item_type jobitem = j->job_items[0]->item_type; - switch (jobitem) - { - case df::item_type::BOULDER: - return df::unit_labor::STONE_CRAFT; - case df::item_type::NONE: - if (j->material_category.bits.bone || - j->material_category.bits.horn || - j->material_category.bits.tooth || - j->material_category.bits.shell) - return df::unit_labor::BONE_CARVE; - else - { - debug ("LABORMANAGER: Cannot deduce labor for make crafts job (not bone)\n"); - debug_pause(); - return df::unit_labor::NONE; - } - case df::item_type::WOOD: - return df::unit_labor::WOOD_CRAFT; - case df::item_type::CLOTH: - return df::unit_labor::CLOTHESMAKER; - case df::item_type::SKIN_TANNED: - return df::unit_labor::LEATHER; - default: - debug ("LABORMANAGER: Cannot deduce labor for make crafts job, item type %s\n", - ENUM_KEY_STR(item_type, jobitem).c_str()); - debug_pause(); - return df::unit_labor::NONE; - } - } - case df::workshop_type::Masons: - return df::unit_labor::MASON; - case df::workshop_type::Carpenters: - return df::unit_labor::CARPENTER; - case df::workshop_type::Leatherworks: - return df::unit_labor::LEATHER; - case df::workshop_type::Clothiers: - return df::unit_labor::CLOTHESMAKER; - case df::workshop_type::Bowyers: - return df::unit_labor::BOWYER; - case df::workshop_type::MagmaForge: - case df::workshop_type::MetalsmithsForge: - return metaltype; - default: - debug ("LABORMANAGER: Cannot deduce labor for make job, workshop type %s\n", - ENUM_KEY_STR(workshop_type, type).c_str()); - debug_pause(); - return df::unit_labor::NONE; - } - } - else if (bld->getType() == df::building_type::Furnace) - { - df::furnace_type type = ((df::building_furnacest*)(bld))->type; - switch (type) - { - case df::furnace_type::MagmaGlassFurnace: - case df::furnace_type::GlassFurnace: - return df::unit_labor::GLASSMAKER; - default: - debug ("LABORMANAGER: Cannot deduce labor for make job, furnace type %s\n", - ENUM_KEY_STR(furnace_type, type).c_str()); - debug_pause(); - return df::unit_labor::NONE; - } - } - - debug ("LABORMANAGER: Cannot deduce labor for make job, building type %s\n", - ENUM_KEY_STR(building_type, bld->getType()).c_str()); - debug_pause(); - - return df::unit_labor::NONE; - } - - jlfunc_make (df::unit_labor mt) : metaltype(mt) {} - }; - - class jlfunc_custom : public jlfunc - { - public: - df::unit_labor get_labor(df::job* j) - { - for (auto r = world->raws.reactions.begin(); r != world->raws.reactions.end(); r++) - { - if ((*r)->code == j->reaction_name) - { - df::job_skill skill = (*r)->skill; - df::unit_labor labor = ENUM_ATTR(job_skill, labor, skill); - return labor; - } - } - return df::unit_labor::NONE; - } - jlfunc_custom() {} - }; - - map jlf_cache; - - jlfunc* jlf_const(df::unit_labor l) { - jlfunc* jlf; - if (jlf_cache.count(l) == 0) - { - jlf = new jlfunc_const(l); - jlf_cache[l] = jlf; - } - else - jlf = jlf_cache[l]; - - return jlf; - } -private: - std::map job_to_labor_table; - -public: - ~JobLaborMapper() - { - std::set log; - - for (auto i = jlf_cache.begin(); i != jlf_cache.end(); i++) - { - if (!log.count(i->second)) - { - log.insert(i->second); - delete i->second; - } - i->second = 0; - } - - FOR_ENUM_ITEMS (job_type, j) - { - if (j < 0) - continue; - - jlfunc* p = job_to_labor_table[j]; - if (!log.count(p)) - { - log.insert(p); - delete p; - } - job_to_labor_table[j] = 0; - } - } - - JobLaborMapper() - { - jlfunc* jlf_hauling = new jlfunc_hauling(); - jlfunc* jlf_make_furniture = new jlfunc_make(df::unit_labor::FORGE_FURNITURE); - jlfunc* jlf_make_object = new jlfunc_make(df::unit_labor::METAL_CRAFT); - jlfunc* jlf_make_armor = new jlfunc_make(df::unit_labor::FORGE_ARMOR); - jlfunc* jlf_make_weapon = new jlfunc_make(df::unit_labor::FORGE_WEAPON); - - jlfunc* jlf_no_labor = jlf_const(df::unit_labor::NONE); - - job_to_labor_table[df::job_type::CarveFortification] = jlf_const(df::unit_labor::DETAIL); - job_to_labor_table[df::job_type::DetailWall] = jlf_const(df::unit_labor::DETAIL); - job_to_labor_table[df::job_type::DetailFloor] = jlf_const(df::unit_labor::DETAIL); - job_to_labor_table[df::job_type::Dig] = jlf_const(df::unit_labor::MINE); - job_to_labor_table[df::job_type::CarveUpwardStaircase] = jlf_const(df::unit_labor::MINE); - job_to_labor_table[df::job_type::CarveDownwardStaircase] = jlf_const(df::unit_labor::MINE); - job_to_labor_table[df::job_type::CarveUpDownStaircase] = jlf_const(df::unit_labor::MINE); - job_to_labor_table[df::job_type::CarveRamp] = jlf_const(df::unit_labor::MINE); - job_to_labor_table[df::job_type::DigChannel] = jlf_const(df::unit_labor::MINE); - job_to_labor_table[df::job_type::FellTree] = jlf_const(df::unit_labor::CUTWOOD); - job_to_labor_table[df::job_type::GatherPlants] = jlf_const(df::unit_labor::HERBALIST); - job_to_labor_table[df::job_type::RemoveConstruction] = jlf_const(df::unit_labor::REMOVE_CONSTRUCTION); - job_to_labor_table[df::job_type::CollectWebs] = jlf_const(df::unit_labor::WEAVER); - job_to_labor_table[df::job_type::BringItemToDepot] = jlf_const(df::unit_labor::HAUL_TRADE); - job_to_labor_table[df::job_type::BringItemToShop] = jlf_no_labor; - job_to_labor_table[df::job_type::Eat] = jlf_no_labor; - job_to_labor_table[df::job_type::GetProvisions] = jlf_no_labor; - job_to_labor_table[df::job_type::Drink] = jlf_no_labor; - job_to_labor_table[df::job_type::Drink2] = jlf_no_labor; - job_to_labor_table[df::job_type::FillWaterskin] = jlf_no_labor; - job_to_labor_table[df::job_type::FillWaterskin2] = jlf_no_labor; - job_to_labor_table[df::job_type::Sleep] = jlf_no_labor; - job_to_labor_table[df::job_type::CollectSand] = jlf_const(df::unit_labor::HAUL_ITEM); - job_to_labor_table[df::job_type::Fish] = jlf_const(df::unit_labor::FISH); - job_to_labor_table[df::job_type::Hunt] = jlf_const(df::unit_labor::HUNT); - job_to_labor_table[df::job_type::HuntVermin] = jlf_no_labor; - job_to_labor_table[df::job_type::Kidnap] = jlf_no_labor; - job_to_labor_table[df::job_type::BeatCriminal] = jlf_no_labor; - job_to_labor_table[df::job_type::StartingFistFight] = jlf_no_labor; - job_to_labor_table[df::job_type::CollectTaxes] = jlf_no_labor; - job_to_labor_table[df::job_type::GuardTaxCollector] = jlf_no_labor; - job_to_labor_table[df::job_type::CatchLiveLandAnimal] = jlf_const(df::unit_labor::HUNT); - job_to_labor_table[df::job_type::CatchLiveFish] = jlf_const(df::unit_labor::FISH); - job_to_labor_table[df::job_type::ReturnKill] = jlf_no_labor; - job_to_labor_table[df::job_type::CheckChest] = jlf_no_labor; - job_to_labor_table[df::job_type::StoreOwnedItem] = jlf_no_labor; - job_to_labor_table[df::job_type::PlaceItemInTomb] = jlf_const(df::unit_labor::HAUL_BODY); - job_to_labor_table[df::job_type::StoreItemInStockpile] = jlf_hauling; - job_to_labor_table[df::job_type::StoreItemInBag] = jlf_hauling; - job_to_labor_table[df::job_type::StoreItemInHospital] = jlf_hauling; - job_to_labor_table[df::job_type::StoreWeapon] = jlf_hauling; - job_to_labor_table[df::job_type::StoreArmor] = jlf_hauling; - job_to_labor_table[df::job_type::StoreItemInBarrel] = jlf_hauling; - job_to_labor_table[df::job_type::StoreItemInBin] = jlf_hauling; - job_to_labor_table[df::job_type::SeekArtifact] = jlf_no_labor; - job_to_labor_table[df::job_type::SeekInfant] = jlf_no_labor; - job_to_labor_table[df::job_type::AttendParty] = jlf_no_labor; - job_to_labor_table[df::job_type::GoShopping] = jlf_no_labor; - job_to_labor_table[df::job_type::GoShopping2] = jlf_no_labor; - job_to_labor_table[df::job_type::Clean] = jlf_const(df::unit_labor::CLEAN); - job_to_labor_table[df::job_type::Rest] = jlf_no_labor; - job_to_labor_table[df::job_type::PickupEquipment] = jlf_no_labor; - job_to_labor_table[df::job_type::DumpItem] = jlf_const(df::unit_labor::HAUL_REFUSE); - job_to_labor_table[df::job_type::StrangeMoodCrafter] = jlf_no_labor; - job_to_labor_table[df::job_type::StrangeMoodJeweller] = jlf_no_labor; - job_to_labor_table[df::job_type::StrangeMoodForge] = jlf_no_labor; - job_to_labor_table[df::job_type::StrangeMoodMagmaForge] = jlf_no_labor; - job_to_labor_table[df::job_type::StrangeMoodBrooding] = jlf_no_labor; - job_to_labor_table[df::job_type::StrangeMoodFell] = jlf_no_labor; - job_to_labor_table[df::job_type::StrangeMoodCarpenter] = jlf_no_labor; - job_to_labor_table[df::job_type::StrangeMoodMason] = jlf_no_labor; - job_to_labor_table[df::job_type::StrangeMoodBowyer] = jlf_no_labor; - job_to_labor_table[df::job_type::StrangeMoodTanner] = jlf_no_labor; - job_to_labor_table[df::job_type::StrangeMoodWeaver] = jlf_no_labor; - job_to_labor_table[df::job_type::StrangeMoodGlassmaker] = jlf_no_labor; - job_to_labor_table[df::job_type::StrangeMoodMechanics] = jlf_no_labor; - job_to_labor_table[df::job_type::ConstructBuilding] = new jlfunc_construct_bld(); - job_to_labor_table[df::job_type::ConstructDoor] = jlf_make_furniture; - job_to_labor_table[df::job_type::ConstructFloodgate] = jlf_make_furniture; - job_to_labor_table[df::job_type::ConstructBed] = jlf_make_furniture; - job_to_labor_table[df::job_type::ConstructThrone] = jlf_make_furniture; - job_to_labor_table[df::job_type::ConstructCoffin] = jlf_make_furniture; - job_to_labor_table[df::job_type::ConstructTable] = jlf_make_furniture; - job_to_labor_table[df::job_type::ConstructChest] = jlf_make_furniture; - job_to_labor_table[df::job_type::ConstructBin] = jlf_make_furniture; - job_to_labor_table[df::job_type::ConstructArmorStand] = jlf_make_furniture; - job_to_labor_table[df::job_type::ConstructWeaponRack] = jlf_make_furniture; - job_to_labor_table[df::job_type::ConstructCabinet] = jlf_make_furniture; - job_to_labor_table[df::job_type::ConstructStatue] = jlf_make_furniture; - job_to_labor_table[df::job_type::ConstructBlocks] = jlf_make_furniture; - job_to_labor_table[df::job_type::MakeRawGlass] = jlf_const(df::unit_labor::GLASSMAKER); - job_to_labor_table[df::job_type::MakeCrafts] = jlf_make_object; - job_to_labor_table[df::job_type::MintCoins] = jlf_const(df::unit_labor::METAL_CRAFT); - job_to_labor_table[df::job_type::CutGems] = jlf_const(df::unit_labor::CUT_GEM); - job_to_labor_table[df::job_type::CutGlass] = jlf_const(df::unit_labor::CUT_GEM); - job_to_labor_table[df::job_type::EncrustWithGems] = jlf_const(df::unit_labor::ENCRUST_GEM); - job_to_labor_table[df::job_type::EncrustWithGlass] = jlf_const(df::unit_labor::ENCRUST_GEM); - job_to_labor_table[df::job_type::DestroyBuilding] = new jlfunc_destroy_bld(); - job_to_labor_table[df::job_type::SmeltOre] = jlf_const(df::unit_labor::SMELT); - job_to_labor_table[df::job_type::MeltMetalObject] = jlf_const(df::unit_labor::SMELT); - job_to_labor_table[df::job_type::ExtractMetalStrands] = jlf_const(df::unit_labor::EXTRACT_STRAND); - job_to_labor_table[df::job_type::PlantSeeds] = jlf_const(df::unit_labor::PLANT); - job_to_labor_table[df::job_type::HarvestPlants] = jlf_const(df::unit_labor::PLANT); - job_to_labor_table[df::job_type::TrainHuntingAnimal] = jlf_const(df::unit_labor::ANIMALTRAIN); - job_to_labor_table[df::job_type::TrainWarAnimal] = jlf_const(df::unit_labor::ANIMALTRAIN); - job_to_labor_table[df::job_type::MakeWeapon] = jlf_make_weapon; - job_to_labor_table[df::job_type::ForgeAnvil] = jlf_make_furniture; - job_to_labor_table[df::job_type::ConstructCatapultParts] = jlf_const(df::unit_labor::SIEGECRAFT); - job_to_labor_table[df::job_type::ConstructBallistaParts] = jlf_const(df::unit_labor::SIEGECRAFT); - job_to_labor_table[df::job_type::MakeArmor] = jlf_make_armor; - job_to_labor_table[df::job_type::MakeHelm] = jlf_make_armor; - job_to_labor_table[df::job_type::MakePants] = jlf_make_armor; - job_to_labor_table[df::job_type::StudWith] = jlf_make_object; - job_to_labor_table[df::job_type::ButcherAnimal] = jlf_const(df::unit_labor::BUTCHER); - job_to_labor_table[df::job_type::PrepareRawFish] = jlf_const(df::unit_labor::CLEAN_FISH); - job_to_labor_table[df::job_type::MillPlants] = jlf_const(df::unit_labor::MILLER); - job_to_labor_table[df::job_type::BaitTrap] = jlf_const(df::unit_labor::TRAPPER); - job_to_labor_table[df::job_type::MilkCreature] = jlf_const(df::unit_labor::MILK); - job_to_labor_table[df::job_type::MakeCheese] = jlf_const(df::unit_labor::MAKE_CHEESE); - job_to_labor_table[df::job_type::ProcessPlants] = jlf_const(df::unit_labor::PROCESS_PLANT); - job_to_labor_table[df::job_type::ProcessPlantsVial] = jlf_const(df::unit_labor::PROCESS_PLANT); - job_to_labor_table[df::job_type::ProcessPlantsBarrel] = jlf_const(df::unit_labor::PROCESS_PLANT); - job_to_labor_table[df::job_type::PrepareMeal] = jlf_const(df::unit_labor::COOK); - job_to_labor_table[df::job_type::WeaveCloth] = jlf_const(df::unit_labor::WEAVER); - job_to_labor_table[df::job_type::MakeGloves] = jlf_make_armor; - job_to_labor_table[df::job_type::MakeShoes] = jlf_make_armor; - job_to_labor_table[df::job_type::MakeShield] = jlf_make_armor; - job_to_labor_table[df::job_type::MakeCage] = jlf_make_furniture; - job_to_labor_table[df::job_type::MakeChain] = jlf_make_object; - job_to_labor_table[df::job_type::MakeFlask] = jlf_make_object; - job_to_labor_table[df::job_type::MakeGoblet] = jlf_make_object; - job_to_labor_table[df::job_type::MakeToy] = jlf_make_object; - job_to_labor_table[df::job_type::MakeAnimalTrap] = jlf_const(df::unit_labor::TRAPPER); - job_to_labor_table[df::job_type::MakeBarrel] = jlf_make_furniture; - job_to_labor_table[df::job_type::MakeBucket] = jlf_make_furniture; - job_to_labor_table[df::job_type::MakeWindow] = jlf_make_furniture; - job_to_labor_table[df::job_type::MakeTotem] = jlf_const(df::unit_labor::BONE_CARVE); - job_to_labor_table[df::job_type::MakeAmmo] = jlf_make_weapon; - job_to_labor_table[df::job_type::DecorateWith] = jlf_make_object; - job_to_labor_table[df::job_type::MakeBackpack] = jlf_make_object; - job_to_labor_table[df::job_type::MakeQuiver] = jlf_make_armor; - job_to_labor_table[df::job_type::MakeBallistaArrowHead] = jlf_make_weapon; - job_to_labor_table[df::job_type::AssembleSiegeAmmo] = jlf_const(df::unit_labor::SIEGECRAFT); - job_to_labor_table[df::job_type::LoadCatapult] = jlf_const(df::unit_labor::SIEGEOPERATE); - job_to_labor_table[df::job_type::LoadBallista] = jlf_const(df::unit_labor::SIEGEOPERATE); - job_to_labor_table[df::job_type::FireCatapult] = jlf_const(df::unit_labor::SIEGEOPERATE); - job_to_labor_table[df::job_type::FireBallista] = jlf_const(df::unit_labor::SIEGEOPERATE); - job_to_labor_table[df::job_type::ConstructMechanisms] = jlf_const(df::unit_labor::MECHANIC); - job_to_labor_table[df::job_type::MakeTrapComponent] = jlf_make_weapon; - job_to_labor_table[df::job_type::LoadCageTrap] = jlf_const(df::unit_labor::MECHANIC) ; - job_to_labor_table[df::job_type::LoadStoneTrap] = jlf_const(df::unit_labor::MECHANIC) ; - job_to_labor_table[df::job_type::LoadWeaponTrap] = jlf_const(df::unit_labor::MECHANIC) ; - job_to_labor_table[df::job_type::CleanTrap] = jlf_const(df::unit_labor::MECHANIC) ; - job_to_labor_table[df::job_type::CastSpell] = jlf_no_labor; - job_to_labor_table[df::job_type::LinkBuildingToTrigger] = jlf_const(df::unit_labor::MECHANIC) ; - job_to_labor_table[df::job_type::PullLever] = jlf_const(df::unit_labor::PULL_LEVER); - job_to_labor_table[df::job_type::ExtractFromPlants] = jlf_const(df::unit_labor::HERBALIST) ; - job_to_labor_table[df::job_type::ExtractFromRawFish] = jlf_const(df::unit_labor::DISSECT_FISH) ; - job_to_labor_table[df::job_type::ExtractFromLandAnimal] = jlf_const(df::unit_labor::DISSECT_VERMIN) ; - job_to_labor_table[df::job_type::TameVermin] = jlf_const(df::unit_labor::ANIMALTRAIN) ; - job_to_labor_table[df::job_type::TameAnimal] = jlf_const(df::unit_labor::ANIMALTRAIN) ; - job_to_labor_table[df::job_type::ChainAnimal] = jlf_const(df::unit_labor::HAUL_ANIMALS); - job_to_labor_table[df::job_type::UnchainAnimal] = jlf_const(df::unit_labor::HAUL_ANIMALS); - job_to_labor_table[df::job_type::UnchainPet] = jlf_no_labor; - job_to_labor_table[df::job_type::ReleaseLargeCreature] = jlf_const(df::unit_labor::HAUL_ANIMALS); - job_to_labor_table[df::job_type::ReleasePet] = jlf_no_labor; - job_to_labor_table[df::job_type::ReleaseSmallCreature] = jlf_no_labor; - job_to_labor_table[df::job_type::HandleSmallCreature] = jlf_no_labor; - job_to_labor_table[df::job_type::HandleLargeCreature] = jlf_const(df::unit_labor::HAUL_ANIMALS); - job_to_labor_table[df::job_type::CageLargeCreature] = jlf_const(df::unit_labor::HAUL_ANIMALS); - job_to_labor_table[df::job_type::CageSmallCreature] = jlf_no_labor; - job_to_labor_table[df::job_type::RecoverWounded] = jlf_const(df::unit_labor::RECOVER_WOUNDED); - job_to_labor_table[df::job_type::DiagnosePatient] = jlf_const(df::unit_labor::DIAGNOSE) ; - job_to_labor_table[df::job_type::ImmobilizeBreak] = jlf_const(df::unit_labor::BONE_SETTING) ; - job_to_labor_table[df::job_type::DressWound] = jlf_const(df::unit_labor::DRESSING_WOUNDS) ; - job_to_labor_table[df::job_type::CleanPatient] = jlf_const(df::unit_labor::DRESSING_WOUNDS) ; - job_to_labor_table[df::job_type::Surgery] = jlf_const(df::unit_labor::SURGERY) ; - job_to_labor_table[df::job_type::Suture] = jlf_const(df::unit_labor::SUTURING); - job_to_labor_table[df::job_type::SetBone] = jlf_const(df::unit_labor::BONE_SETTING) ; - job_to_labor_table[df::job_type::PlaceInTraction] = jlf_const(df::unit_labor::BONE_SETTING) ; - job_to_labor_table[df::job_type::DrainAquarium] = jlf_no_labor; - job_to_labor_table[df::job_type::FillAquarium] = jlf_no_labor; - job_to_labor_table[df::job_type::FillPond] = jlf_no_labor; - job_to_labor_table[df::job_type::GiveWater] = jlf_const(df::unit_labor::FEED_WATER_CIVILIANS) ; - job_to_labor_table[df::job_type::GiveFood] = jlf_const(df::unit_labor::FEED_WATER_CIVILIANS) ; - job_to_labor_table[df::job_type::GiveWater2] = jlf_no_labor; - job_to_labor_table[df::job_type::GiveFood2] = jlf_no_labor; - job_to_labor_table[df::job_type::RecoverPet] = jlf_no_labor; - job_to_labor_table[df::job_type::PitLargeAnimal] = jlf_const(df::unit_labor::HAUL_ANIMALS); - job_to_labor_table[df::job_type::PitSmallAnimal] = jlf_no_labor; - job_to_labor_table[df::job_type::SlaughterAnimal] = jlf_const(df::unit_labor::BUTCHER); - job_to_labor_table[df::job_type::MakeCharcoal] = jlf_const(df::unit_labor::BURN_WOOD); - job_to_labor_table[df::job_type::MakeAsh] = jlf_const(df::unit_labor::BURN_WOOD); - job_to_labor_table[df::job_type::MakeLye] = jlf_const(df::unit_labor::LYE_MAKING); - job_to_labor_table[df::job_type::MakePotashFromLye] = jlf_const(df::unit_labor::POTASH_MAKING); - job_to_labor_table[df::job_type::FertilizeField] = jlf_const(df::unit_labor::PLANT); - job_to_labor_table[df::job_type::MakePotashFromAsh] = jlf_const(df::unit_labor::POTASH_MAKING); - job_to_labor_table[df::job_type::DyeThread] = jlf_const(df::unit_labor::DYER); - job_to_labor_table[df::job_type::DyeCloth] = jlf_const(df::unit_labor::DYER); - job_to_labor_table[df::job_type::SewImage] = jlf_make_object; - job_to_labor_table[df::job_type::MakePipeSection] = jlf_make_furniture; - job_to_labor_table[df::job_type::OperatePump] = jlf_const(df::unit_labor::OPERATE_PUMP); - job_to_labor_table[df::job_type::ManageWorkOrders] = jlf_no_labor; - job_to_labor_table[df::job_type::UpdateStockpileRecords] = jlf_no_labor; - job_to_labor_table[df::job_type::TradeAtDepot] = jlf_no_labor; - job_to_labor_table[df::job_type::ConstructHatchCover] = jlf_make_furniture; - job_to_labor_table[df::job_type::ConstructGrate] = jlf_make_furniture; - job_to_labor_table[df::job_type::RemoveStairs] = jlf_const(df::unit_labor::MINE); - job_to_labor_table[df::job_type::ConstructQuern] = jlf_make_furniture; - job_to_labor_table[df::job_type::ConstructMillstone] = jlf_make_furniture; - job_to_labor_table[df::job_type::ConstructSplint] = jlf_make_furniture; - job_to_labor_table[df::job_type::ConstructCrutch] = jlf_make_furniture; - job_to_labor_table[df::job_type::ConstructTractionBench] = jlf_const(df::unit_labor::MECHANIC); - job_to_labor_table[df::job_type::CleanSelf] = jlf_no_labor; - job_to_labor_table[df::job_type::BringCrutch] = jlf_const(df::unit_labor::BONE_SETTING); - job_to_labor_table[df::job_type::ApplyCast] = jlf_const(df::unit_labor::BONE_SETTING); - job_to_labor_table[df::job_type::CustomReaction] = new jlfunc_custom(); - job_to_labor_table[df::job_type::ConstructSlab] = jlf_make_furniture; - job_to_labor_table[df::job_type::EngraveSlab] = jlf_const(df::unit_labor::DETAIL); - job_to_labor_table[df::job_type::ShearCreature] = jlf_const(df::unit_labor::SHEARER); - job_to_labor_table[df::job_type::SpinThread] = jlf_const(df::unit_labor::SPINNER); - job_to_labor_table[df::job_type::PenLargeAnimal] = jlf_const(df::unit_labor::HAUL_ANIMALS); - job_to_labor_table[df::job_type::PenSmallAnimal] = jlf_no_labor; - job_to_labor_table[df::job_type::MakeTool] = jlf_make_object; - job_to_labor_table[df::job_type::CollectClay] = jlf_const(df::unit_labor::POTTERY); - job_to_labor_table[df::job_type::InstallColonyInHive] = jlf_const(df::unit_labor::BEEKEEPING); - job_to_labor_table[df::job_type::CollectHiveProducts] = jlf_const(df::unit_labor::BEEKEEPING); - job_to_labor_table[df::job_type::CauseTrouble] = jlf_no_labor; - job_to_labor_table[df::job_type::DrinkBlood] = jlf_no_labor; - job_to_labor_table[df::job_type::ReportCrime] = jlf_no_labor; - job_to_labor_table[df::job_type::ExecuteCriminal] = jlf_no_labor; - job_to_labor_table[df::job_type::TrainAnimal] = jlf_const(df::unit_labor::ANIMALTRAIN); - job_to_labor_table[df::job_type::CarveTrack] = jlf_const(df::unit_labor::DETAIL); - job_to_labor_table[df::job_type::PushTrackVehicle] = jlf_const(df::unit_labor::HANDLE_VEHICLES); - job_to_labor_table[df::job_type::PlaceTrackVehicle] = jlf_const(df::unit_labor::HANDLE_VEHICLES); - job_to_labor_table[df::job_type::StoreItemInVehicle] = jlf_hauling; - job_to_labor_table[df::job_type::GeldAnimal] = jlf_const(df::unit_labor::GELD); - job_to_labor_table[df::job_type::MakeFigurine] = jlf_make_object; - job_to_labor_table[df::job_type::MakeAmulet] = jlf_make_object; - job_to_labor_table[df::job_type::MakeScepter] = jlf_make_object; - job_to_labor_table[df::job_type::MakeCrown] = jlf_make_object; - job_to_labor_table[df::job_type::MakeRing] = jlf_make_object; - job_to_labor_table[df::job_type::MakeEarring] = jlf_make_object; - job_to_labor_table[df::job_type::MakeBracelet] = jlf_make_object; - job_to_labor_table[df::job_type::MakeGem] = jlf_make_object; - - job_to_labor_table[df::job_type::StoreItemInLocation] = jlf_no_labor; // StoreItemInLocation - }; - - df::unit_labor find_job_labor(df::job* j) - { - if (j->job_type == df::job_type::CustomReaction) - { - for (auto r = world->raws.reactions.begin(); r != world->raws.reactions.end(); r++) - { - if ((*r)->code == j->reaction_name) - { - df::job_skill skill = (*r)->skill; - return ENUM_ATTR(job_skill, labor, skill); - } - } - return df::unit_labor::NONE; - } - - - df::unit_labor labor; - if (job_to_labor_table.count(j->job_type) == 0) - { - debug("LABORMANAGER: job has no job to labor table entry: %s (%d)\n", ENUM_KEY_STR(job_type, j->job_type).c_str(), j->job_type); - debug_pause(); - labor = df::unit_labor::NONE; - } else { - - labor = job_to_labor_table[j->job_type]->get_labor(j); - } - - return labor; - } -}; - -/* End of labor deducer */ - static JobLaborMapper* labor_mapper = 0; static bool initialized = false; @@ -1527,8 +660,8 @@ static void generate_labor_to_skill_map() } struct skill_attr_weight { - int phys_attr_weights [6]; - int mental_attr_weights [13]; + int phys_attr_weights[6]; + int mental_attr_weights[13]; }; static struct skill_attr_weight skill_attr_weights[ENUM_LAST_ITEM(job_skill) + 1] = @@ -1687,10 +820,10 @@ static void enable_plugin(color_ostream &out) init_state(); } -DFhackCExport command_result plugin_init ( color_ostream &out, std::vector &commands) +DFhackCExport command_result plugin_init(color_ostream &out, std::vector &commands) { // initialize labor infos table from default table - if(ARRAY_COUNT(default_labor_infos) != ENUM_LAST_ITEM(unit_labor) + 1) + if (ARRAY_COUNT(default_labor_infos) != ENUM_LAST_ITEM(unit_labor) + 1) return CR_FAILURE; // Fill the command list with your commands. @@ -1721,7 +854,7 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector busy_dwarfs; private: - void set_labor (dwarf_info_t* dwarf, df::unit_labor labor, bool value) + void set_labor(dwarf_info_t* dwarf, df::unit_labor labor, bool value) { if (labor >= 0 && labor <= ENUM_LAST_ITEM(unit_labor)) { @@ -1821,7 +954,7 @@ private: } } - void process_job (df::job* j) + void process_job(df::job* j) { if (j->flags.bits.suspend || j->flags.bits.item_lost) return; @@ -1860,7 +993,7 @@ private: } } - df::unit_labor labor = labor_mapper->find_job_labor (j); + df::unit_labor labor = labor_mapper->find_job_labor(j); if (labor != df::unit_labor::NONE) { @@ -1873,7 +1006,8 @@ private: if (d->bits.outside) labor_outside[labor] = true; } - } else { + } + else { labor_infos[labor].mark_assigned(); labor_in_use[labor]++; } @@ -1937,7 +1071,7 @@ private: if (bl->designation[x][y].bits.hidden) { df::coord p = bl->map_pos; - df::coord c(p.x, p.y, p.z-1); + df::coord c(p.x, p.y, p.z - 1); if (Maps::getTileDesignation(c)->bits.hidden) continue; } @@ -2078,15 +1212,28 @@ private: { df::activity_info *act = ui->activities[i]; if (!act) continue; + bool p1 = act->unit_actor == dwarf->dwarf; bool p2 = act->unit_noble == dwarf->dwarf; if (p1 || p2) { - dwarf->clear_all = true; - if (print_debug) - out.print("Dwarf \"%s\" has a meeting, will be cleared of all labors\n", dwarf->dwarf->name.first_name.c_str()); - break; + df::unit* other = p1 ? act->unit_noble : act->unit_actor; + if (other && !(other->flags1.bits.dead || + (other->job.current_job && + (other->job.current_job->job_type == df::job_type::Sleep || + other->job.current_job->job_type == df::job_type::Rest)) || + ENUM_ATTR(profession, military, other->profession))) { + dwarf->clear_all = true; + if (print_debug) + out.print("Dwarf \"%s\" has a meeting, will be cleared of all labors\n", dwarf->dwarf->name.first_name.c_str()); + break; + } + else + { + if (print_debug) + out.print("Dwarf \"%s\" has a meeting, but with someone who can't make the meeting.\n", dwarf->dwarf->name.first_name.c_str()); + } } } @@ -2145,7 +1292,7 @@ private: if (dwarf->dwarf->social_activities.size() > 0) { if (print_debug) - out.print ("Dwarf %s is engaged in a social activity. Info only.\n", dwarf->dwarf->name.first_name.c_str()); + out.print("Dwarf %s is engaged in a social activity. Info only.\n", dwarf->dwarf->name.first_name.c_str()); } if (dwarf->dwarf->profession == profession::BABY || @@ -2173,7 +1320,7 @@ private: state = OTHER; // dwarfs unable to grasp are incapable of nearly all labors dwarf->clear_all = true; if (print_debug) - out.print ("Dwarf %s is disabled, will not be assigned labors\n", dwarf->dwarf->name.first_name.c_str()); + out.print("Dwarf %s is disabled, will not be assigned labors\n", dwarf->dwarf->name.first_name.c_str()); } else { @@ -2260,7 +1407,7 @@ private: int high_skill = 0; - FOR_ENUM_ITEMS (unit_labor, labor) + FOR_ENUM_ITEMS(unit_labor, labor) { if (labor == df::unit_labor::NONE) continue; @@ -2287,7 +1434,8 @@ private: set_labor(dwarf, labor, false); } - } else { + } + else { if (state == IDLE) available_dwarfs.push_back(dwarf); @@ -2310,7 +1458,7 @@ private: busy_dwarfs.clear(); } - int score_labor (dwarf_info_t* d, df::unit_labor labor) + int score_labor(dwarf_info_t* d, df::unit_labor labor) { int skill_level = 0; int xp = 0; @@ -2405,51 +1553,51 @@ public: // add job entries for designation-related jobs - labor_needed[df::unit_labor::MINE] += dig_count; - labor_needed[df::unit_labor::CUTWOOD] += tree_count; - labor_needed[df::unit_labor::DETAIL] += detail_count; + labor_needed[df::unit_labor::MINE] += dig_count; + labor_needed[df::unit_labor::CUTWOOD] += tree_count; + labor_needed[df::unit_labor::DETAIL] += detail_count; labor_needed[df::unit_labor::HERBALIST] += plant_count; // add job entries for health care labor_needed[df::unit_labor::RECOVER_WOUNDED] += cnt_recover_wounded; - labor_needed[df::unit_labor::DIAGNOSE] += cnt_diagnosis; - labor_needed[df::unit_labor::BONE_SETTING] += cnt_immobilize; + labor_needed[df::unit_labor::DIAGNOSE] += cnt_diagnosis; + labor_needed[df::unit_labor::BONE_SETTING] += cnt_immobilize; labor_needed[df::unit_labor::DRESSING_WOUNDS] += cnt_dressing; labor_needed[df::unit_labor::DRESSING_WOUNDS] += cnt_cleaning; - labor_needed[df::unit_labor::SURGERY] += cnt_surgery; - labor_needed[df::unit_labor::SUTURING] += cnt_suture; - labor_needed[df::unit_labor::BONE_SETTING] += cnt_setting; - labor_needed[df::unit_labor::BONE_SETTING] += cnt_traction; - labor_needed[df::unit_labor::BONE_SETTING] += cnt_crutch; + labor_needed[df::unit_labor::SURGERY] += cnt_surgery; + labor_needed[df::unit_labor::SUTURING] += cnt_suture; + labor_needed[df::unit_labor::BONE_SETTING] += cnt_setting; + labor_needed[df::unit_labor::BONE_SETTING] += cnt_traction; + labor_needed[df::unit_labor::BONE_SETTING] += cnt_crutch; labor_needed[df::unit_labor::FEED_WATER_CIVILIANS] += need_food_water; // add entries for hauling jobs - labor_needed[df::unit_labor::HAUL_STONE] += world->stockpile.num_jobs[1]; - labor_needed[df::unit_labor::HAUL_WOOD] += world->stockpile.num_jobs[2]; - labor_needed[df::unit_labor::HAUL_ITEM] += world->stockpile.num_jobs[3]; - labor_needed[df::unit_labor::HAUL_ITEM] += world->stockpile.num_jobs[4]; - labor_needed[df::unit_labor::HAUL_BODY] += world->stockpile.num_jobs[5]; - labor_needed[df::unit_labor::HAUL_FOOD] += world->stockpile.num_jobs[6]; - labor_needed[df::unit_labor::HAUL_REFUSE] += world->stockpile.num_jobs[7]; + labor_needed[df::unit_labor::HAUL_STONE] += world->stockpile.num_jobs[1]; + labor_needed[df::unit_labor::HAUL_WOOD] += world->stockpile.num_jobs[2]; + labor_needed[df::unit_labor::HAUL_ITEM] += world->stockpile.num_jobs[3]; + labor_needed[df::unit_labor::HAUL_ITEM] += world->stockpile.num_jobs[4]; + labor_needed[df::unit_labor::HAUL_BODY] += world->stockpile.num_jobs[5]; + labor_needed[df::unit_labor::HAUL_FOOD] += world->stockpile.num_jobs[6]; + labor_needed[df::unit_labor::HAUL_REFUSE] += world->stockpile.num_jobs[7]; labor_needed[df::unit_labor::HAUL_FURNITURE] += world->stockpile.num_jobs[8]; - labor_needed[df::unit_labor::HAUL_ANIMALS] += world->stockpile.num_jobs[9]; - - labor_needed[df::unit_labor::HAUL_STONE] += (world->stockpile.num_jobs[1] >= world->stockpile.num_haulers[1]) ? 1 : 0; - labor_needed[df::unit_labor::HAUL_WOOD] += (world->stockpile.num_jobs[2] >= world->stockpile.num_haulers[2]) ? 1 : 0; - labor_needed[df::unit_labor::HAUL_ITEM] += (world->stockpile.num_jobs[3] >= world->stockpile.num_haulers[3]) ? 1 : 0; - labor_needed[df::unit_labor::HAUL_BODY] += (world->stockpile.num_jobs[5] >= world->stockpile.num_haulers[5]) ? 1 : 0; - labor_needed[df::unit_labor::HAUL_FOOD] += (world->stockpile.num_jobs[6] >= world->stockpile.num_haulers[6]) ? 1 : 0; - labor_needed[df::unit_labor::HAUL_REFUSE] += (world->stockpile.num_jobs[7] >= world->stockpile.num_haulers[7]) ? 1 : 0; + labor_needed[df::unit_labor::HAUL_ANIMALS] += world->stockpile.num_jobs[9]; + + labor_needed[df::unit_labor::HAUL_STONE] += (world->stockpile.num_jobs[1] >= world->stockpile.num_haulers[1]) ? 1 : 0; + labor_needed[df::unit_labor::HAUL_WOOD] += (world->stockpile.num_jobs[2] >= world->stockpile.num_haulers[2]) ? 1 : 0; + labor_needed[df::unit_labor::HAUL_ITEM] += (world->stockpile.num_jobs[3] >= world->stockpile.num_haulers[3]) ? 1 : 0; + labor_needed[df::unit_labor::HAUL_BODY] += (world->stockpile.num_jobs[5] >= world->stockpile.num_haulers[5]) ? 1 : 0; + labor_needed[df::unit_labor::HAUL_FOOD] += (world->stockpile.num_jobs[6] >= world->stockpile.num_haulers[6]) ? 1 : 0; + labor_needed[df::unit_labor::HAUL_REFUSE] += (world->stockpile.num_jobs[7] >= world->stockpile.num_haulers[7]) ? 1 : 0; labor_needed[df::unit_labor::HAUL_FURNITURE] += (world->stockpile.num_jobs[8] >= world->stockpile.num_haulers[8]) ? 1 : 0; - labor_needed[df::unit_labor::HAUL_ANIMALS] += (world->stockpile.num_jobs[9] >= world->stockpile.num_haulers[9]) ? 1 : 0; + labor_needed[df::unit_labor::HAUL_ANIMALS] += (world->stockpile.num_jobs[9] >= world->stockpile.num_haulers[9]) ? 1 : 0; int binjobs = world->stockpile.num_jobs[4] + ((world->stockpile.num_jobs[4] >= world->stockpile.num_haulers[4]) ? 1 : 0); - labor_needed[df::unit_labor::HAUL_ITEM] += binjobs; - labor_needed[df::unit_labor::HAUL_FOOD] += priority_food; + labor_needed[df::unit_labor::HAUL_ITEM] += binjobs; + labor_needed[df::unit_labor::HAUL_FOOD] += priority_food; // add entries for vehicle hauling @@ -2488,7 +1636,7 @@ public: labor_needed[l] = std::min(labor_needed[l], tool_count[default_labor_infos[l].tool] - tool_in_use[default_labor_infos[l].tool]); if (print_debug && before != labor_needed[l]) - out.print ("labor %s reduced from %d to %d\n", ENUM_KEY_STR(unit_labor, l).c_str(), before, labor_needed[l]); + out.print("labor %s reduced from %d to %d\n", ENUM_KEY_STR(unit_labor, l).c_str(), before, labor_needed[l]); } @@ -2498,7 +1646,7 @@ public: priority_food = 1; if (print_debug) - out.print ("priority food count = %d\n", priority_food); + out.print("priority food count = %d\n", priority_food); while (!available_dwarfs.empty() && priority_food > 0) { @@ -2529,7 +1677,7 @@ public: if (l == df::unit_labor::NONE) continue; - set_labor (*bestdwarf, l, l == df::unit_labor::HAUL_FOOD); + set_labor(*bestdwarf, l, l == df::unit_labor::HAUL_FOOD); } available_dwarfs.erase(bestdwarf); @@ -2544,7 +1692,7 @@ public: { for (auto i = labor_needed.begin(); i != labor_needed.end(); i++) { - out.print ("labor_needed [%s] = %d, busy = %d, outside = %d, idle = %d\n", ENUM_KEY_STR(unit_labor, i->first).c_str(), i->second, + out.print("labor_needed [%s] = %d, busy = %d, outside = %d, idle = %d\n", ENUM_KEY_STR(unit_labor, i->first).c_str(), i->second, labor_infos[i->first].busy_dwarfs, labor_outside[i->first], labor_infos[i->first].idle_dwarfs); } } @@ -2565,7 +1713,7 @@ public: int priority = labor_infos[l].priority(); - priority += labor_infos[l].time_since_last_assigned()/12; + priority += labor_infos[l].time_since_last_assigned() / 12; priority -= labor_infos[l].busy_dwarfs; base_priority[l] = priority; @@ -2583,7 +1731,7 @@ public: to_assign.clear(); - int av = available_dwarfs.size(); + size_t av = available_dwarfs.size(); while (!pq.empty() && av > 0) { @@ -2598,12 +1746,12 @@ public: if (--labor_needed[labor] > 0) { - priority-=10; + priority -= 10; pq2.push(make_pair(priority, labor)); } if (pq.empty()) - while(!pq2.empty()) + while (!pq2.empty()) { pq.push(pq2.top()); pq2.pop(); @@ -2665,7 +1813,7 @@ public: tools_enum t = default_labor_infos[l].tool; - if (l == best_labor && ( t == TOOL_NONE || tool_in_use[t] < tool_count[t]) ) + if (l == best_labor && (t == TOOL_NONE || tool_in_use[t] < tool_count[t])) { set_labor(*bestdwarf, l, true); if (t != TOOL_NONE && !((*bestdwarf)->has_tool[t])) @@ -2707,9 +1855,9 @@ public: for (auto d = busy_dwarfs.begin(); d != busy_dwarfs.end(); d++) { - int current_score = score_labor (*d, (*d)->using_labor); + int current_score = score_labor(*d, (*d)->using_labor); - FOR_ENUM_ITEMS (unit_labor, l) + FOR_ENUM_ITEMS(unit_labor, l) { if (l == df::unit_labor::NONE) continue; @@ -2718,7 +1866,7 @@ public: if (labor_needed[l] <= 0) continue; - int score = score_labor (*d, l); + int score = score_labor(*d, l); if (l == df::unit_labor::HAUL_FOOD && priority_food > 0) score += 1000000; @@ -2751,7 +1899,7 @@ public: if (canary_dwarf) { - FOR_ENUM_ITEMS (unit_labor, l) + FOR_ENUM_ITEMS(unit_labor, l) { if (l >= df::unit_labor::HAUL_STONE && l <= df::unit_labor::HAUL_ANIMALS && canary & (1 << l)) @@ -2763,22 +1911,22 @@ public: set_labor(canary_dwarf, df::unit_labor::REMOVE_CONSTRUCTION, true); if (print_debug) - out.print ("Setting %s as the hauling canary\n", canary_dwarf->dwarf->name.first_name.c_str()); + out.print("Setting %s as the hauling canary\n", canary_dwarf->dwarf->name.first_name.c_str()); } else { if (print_debug) - out.print ("No dwarf available to set as the hauling canary!\n"); + out.print("No dwarf available to set as the hauling canary!\n"); } /* Assign any leftover dwarfs to "standard" labors */ if (print_debug) - out.print ("After assignment, %d dwarfs left over\n", available_dwarfs.size()); + out.print("After assignment, %d dwarfs left over\n", available_dwarfs.size()); for (auto d = available_dwarfs.begin(); d != available_dwarfs.end(); d++) { - FOR_ENUM_ITEMS (unit_labor, l) + FOR_ENUM_ITEMS(unit_labor, l) { if (l == df::unit_labor::NONE) continue; @@ -2789,7 +1937,7 @@ public: l == df::unit_labor::REMOVE_CONSTRUCTION || l == df::unit_labor::PULL_LEVER || l == df::unit_labor::HAUL_TRADE); - } + } } /* check for dwarfs assigned no labors and assign them the bucket list if there are */ @@ -2799,7 +1947,7 @@ public: continue; bool any = false; - FOR_ENUM_ITEMS (unit_labor, l) + FOR_ENUM_ITEMS(unit_labor, l) { if (l == df::unit_labor::NONE) continue; @@ -2810,11 +1958,11 @@ public: } } - set_labor (*d, df::unit_labor::PULL_LEVER, true); + set_labor(*d, df::unit_labor::PULL_LEVER, true); if (any) continue; - FOR_ENUM_ITEMS (unit_labor, l) + FOR_ENUM_ITEMS(unit_labor, l) { if (l == df::unit_labor::NONE) continue; @@ -2835,7 +1983,7 @@ public: if ((*d)->dwarf->military.pickup_flags.bits.update) continue; - FOR_ENUM_ITEMS (unit_labor, l) + FOR_ENUM_ITEMS(unit_labor, l) { if (l == df::unit_labor::NONE) continue; @@ -2903,18 +2051,18 @@ DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_chan return CR_OK; } -DFhackCExport command_result plugin_onupdate ( color_ostream &out ) +DFhackCExport command_result plugin_onupdate(color_ostream &out) { static int step_count = 0; // check run conditions - if(!initialized || !world || !world->map.block_index || !enable_labormanager) + if (!initialized || !world || !world->map.block_index || !enable_labormanager) { // give up if we shouldn't be running' return CR_OK; } -// if (++step_count < 60) -// return CR_OK; + // if (++step_count < 60) + // return CR_OK; if (*df::global::process_jobs) return CR_OK; @@ -2928,7 +2076,7 @@ DFhackCExport command_result plugin_onupdate ( color_ostream &out ) return CR_OK; } -void print_labor (df::unit_labor labor, color_ostream &out) +void print_labor(df::unit_labor labor, color_ostream &out) { string labor_name = ENUM_KEY_STR(unit_labor, labor); out << labor_name << ": "; @@ -2942,7 +2090,7 @@ void print_labor (df::unit_labor labor, color_ostream &out) << endl; } -df::unit_labor lookup_labor_by_name (std::string& name) +df::unit_labor lookup_labor_by_name(std::string& name) { df::unit_labor labor = df::unit_labor::NONE; @@ -2955,7 +2103,7 @@ df::unit_labor lookup_labor_by_name (std::string& name) return labor; } -DFhackCExport command_result plugin_enable ( color_ostream &out, bool enable ) +DFhackCExport command_result plugin_enable(color_ostream &out, bool enable) { if (!Core::getInstance().isWorldLoaded()) { out.printerr("World is not loaded: please load a fort first.\n"); @@ -2966,7 +2114,7 @@ DFhackCExport command_result plugin_enable ( color_ostream &out, bool enable ) { enable_plugin(out); } - else if(!enable && enable_labormanager) + else if (!enable && enable_labormanager) { enable_labormanager = false; setOptionEnabled(CF_ENABLED, false); @@ -2977,7 +2125,7 @@ DFhackCExport command_result plugin_enable ( color_ostream &out, bool enable ) return CR_OK; } -command_result labormanager (color_ostream &out, std::vector & parameters) +command_result labormanager(color_ostream &out, std::vector & parameters) { CoreSuspender suspend; @@ -3014,7 +2162,7 @@ command_result labormanager (color_ostream &out, std::vector & par if (parameters[2] == "none") v = 0; else - v = atoi (parameters[2].c_str()); + v = atoi(parameters[2].c_str()); if (parameters[0] == "max") labor_infos[labor].set_maximum_dwarfs(v); diff --git a/plugins/labormanager/labormanager.h b/plugins/labormanager/labormanager.h new file mode 100644 index 000000000..c958900b1 --- /dev/null +++ b/plugins/labormanager/labormanager.h @@ -0,0 +1,4 @@ +#pragma once + +void debug(const char* fmt, ...); +void debug_pause();