From fa662cafbcf85ff7b935fce2c175ebf8e267686d Mon Sep 17 00:00:00 2001 From: myk002 Date: Tue, 2 Feb 2021 08:28:48 -0800 Subject: [PATCH 1/5] allow alchemist skill to be toggled in manipulator since autohauler uses it as a flag --- docs/changelog.txt | 3 +++ plugins/manipulator.cpp | 14 +++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/docs/changelog.txt b/docs/changelog.txt index 989a9c558..7fc2f7276 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -33,6 +33,9 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: # Future +## Misc Improvements +- `manipulator`: allow Alchemist skill to be toggled since `autohauler` uses it as a flag. + # 0.47.04-r5 ## Fixes diff --git a/plugins/manipulator.cpp b/plugins/manipulator.cpp index b333afae5..9ba18266b 100644 --- a/plugins/manipulator.cpp +++ b/plugins/manipulator.cpp @@ -1700,7 +1700,9 @@ void viewscreen_unitlaborsst::feed(set *events) UnitInfo *cur = units[input_row]; df::unit *unit = cur->unit; df::unit_labor cur_labor = columns[input_column].labor; - if (events->count(interface_key::SELECT) && (cur->allowEdit) && Units::isValidLabor(unit, cur_labor)) + // Allow Alchemist for individual selection since autohauler uses it as a flag. + if (events->count(interface_key::SELECT) && (cur->allowEdit) && + (cur_labor == df::unit_labor::ALCHEMIST || Units::isValidLabor(unit, cur_labor))) { const SkillColumn &col = columns[input_column]; bool newstatus = !unit->status.labors[col.labor]; @@ -1718,6 +1720,7 @@ void viewscreen_unitlaborsst::feed(set *events) } unit->status.labors[col.labor] = newstatus; } + // Don't autoselect Alchemist when selecting all if (events->count(interface_key::SELECT_ALL) && (cur->allowEdit) && Units::isValidLabor(unit, cur_labor)) { const SkillColumn &col = columns[input_column]; @@ -2089,6 +2092,7 @@ void viewscreen_unitlaborsst::render() UnitInfo *cur = units[sel_row]; bool canToggle = false; + bool canToggleAll = false; if (cur != NULL) { df::unit *unit = cur->unit; @@ -2158,7 +2162,11 @@ void viewscreen_unitlaborsst::render() } - canToggle = (cur->allowEdit) && Units::isValidLabor(unit, columns[sel_column].labor); + if (cur->allowEdit) { + df::unit_labor sel_labor = columns[sel_column].labor; + canToggleAll = Units::isValidLabor(unit, sel_labor); + canToggle = canToggleAll || sel_labor == df::unit_labor::ALCHEMIST; + } } int x = 2, y = dim.y - 4; @@ -2166,7 +2174,7 @@ void viewscreen_unitlaborsst::render() OutputString(canToggle ? 15 : 8, x, y, ": Toggle labor, "); OutputString(10, x, y, Screen::getKeyDisplay(interface_key::SELECT_ALL)); - OutputString(canToggle ? 15 : 8, x, y, ": Toggle Group, "); + OutputString(canToggleAll ? 15 : 8, x, y, ": Toggle Group, "); OutputString(10, x, y, Screen::getKeyDisplay(interface_key::UNITJOB_VIEW_UNIT)); OutputString(15, x, y, ": ViewCre, "); From 4d57d27d4d003988ceeaa1f33999f224079f33ed Mon Sep 17 00:00:00 2001 From: myk002 Date: Fri, 5 Feb 2021 16:10:36 -0800 Subject: [PATCH 2/5] Revert "allow alchemist skill to be toggled in manipulator" This reverts commit fa662cafbcf85ff7b935fce2c175ebf8e267686d. --- docs/changelog.txt | 3 --- plugins/manipulator.cpp | 14 +++----------- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/docs/changelog.txt b/docs/changelog.txt index 7fc2f7276..989a9c558 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -33,9 +33,6 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: # Future -## Misc Improvements -- `manipulator`: allow Alchemist skill to be toggled since `autohauler` uses it as a flag. - # 0.47.04-r5 ## Fixes diff --git a/plugins/manipulator.cpp b/plugins/manipulator.cpp index 9ba18266b..b333afae5 100644 --- a/plugins/manipulator.cpp +++ b/plugins/manipulator.cpp @@ -1700,9 +1700,7 @@ void viewscreen_unitlaborsst::feed(set *events) UnitInfo *cur = units[input_row]; df::unit *unit = cur->unit; df::unit_labor cur_labor = columns[input_column].labor; - // Allow Alchemist for individual selection since autohauler uses it as a flag. - if (events->count(interface_key::SELECT) && (cur->allowEdit) && - (cur_labor == df::unit_labor::ALCHEMIST || Units::isValidLabor(unit, cur_labor))) + if (events->count(interface_key::SELECT) && (cur->allowEdit) && Units::isValidLabor(unit, cur_labor)) { const SkillColumn &col = columns[input_column]; bool newstatus = !unit->status.labors[col.labor]; @@ -1720,7 +1718,6 @@ void viewscreen_unitlaborsst::feed(set *events) } unit->status.labors[col.labor] = newstatus; } - // Don't autoselect Alchemist when selecting all if (events->count(interface_key::SELECT_ALL) && (cur->allowEdit) && Units::isValidLabor(unit, cur_labor)) { const SkillColumn &col = columns[input_column]; @@ -2092,7 +2089,6 @@ void viewscreen_unitlaborsst::render() UnitInfo *cur = units[sel_row]; bool canToggle = false; - bool canToggleAll = false; if (cur != NULL) { df::unit *unit = cur->unit; @@ -2162,11 +2158,7 @@ void viewscreen_unitlaborsst::render() } - if (cur->allowEdit) { - df::unit_labor sel_labor = columns[sel_column].labor; - canToggleAll = Units::isValidLabor(unit, sel_labor); - canToggle = canToggleAll || sel_labor == df::unit_labor::ALCHEMIST; - } + canToggle = (cur->allowEdit) && Units::isValidLabor(unit, columns[sel_column].labor); } int x = 2, y = dim.y - 4; @@ -2174,7 +2166,7 @@ void viewscreen_unitlaborsst::render() OutputString(canToggle ? 15 : 8, x, y, ": Toggle labor, "); OutputString(10, x, y, Screen::getKeyDisplay(interface_key::SELECT_ALL)); - OutputString(canToggleAll ? 15 : 8, x, y, ": Toggle Group, "); + OutputString(canToggle ? 15 : 8, x, y, ": Toggle Group, "); OutputString(10, x, y, Screen::getKeyDisplay(interface_key::UNITJOB_VIEW_UNIT)); OutputString(15, x, y, ": ViewCre, "); From 6819ee9928006f90cefa238a1d2bb85e6cfb44bd Mon Sep 17 00:00:00 2001 From: myk002 Date: Fri, 5 Feb 2021 16:45:39 -0800 Subject: [PATCH 3/5] make alchemist flag valid for controllable civs --- docs/Lua API.rst | 9 +++++++++ docs/changelog.txt | 3 +++ library/LuaApi.cpp | 1 + library/include/modules/Units.h | 1 + library/modules/Units.cpp | 22 ++++++++++++++++++++++ plugins/manipulator.cpp | 27 +++++++++++++++++++++++++++ 6 files changed, 63 insertions(+) diff --git a/docs/Lua API.rst b/docs/Lua API.rst index 81c662728..da5ac206b 100644 --- a/docs/Lua API.rst +++ b/docs/Lua API.rst @@ -1270,6 +1270,15 @@ Units module Returns the age of the unit in years as a floating-point value. If ``true_age`` is true, ignores false identities. +* ``dfhack.units.isValidLabor(unit, unit_labor)`` + + Returns whether the indicated labor is settable for the given unit. + +* ``dfhack.units.setLaborValidity(unit_labor)`` + + Sets the given labor as valid for all playable units in the game (that is, for + all civilizations whose members can be residents of your fort). + * ``dfhack.units.getNominalSkill(unit, skill[, use_rust])`` Retrieves the nominal skill level for the given unit. If ``use_rust`` diff --git a/docs/changelog.txt b/docs/changelog.txt index 989a9c558..3f36239ec 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -33,6 +33,9 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: # Future +## Misc Improvements +- `autohauler`: allow the ``Alchemist`` labor to be enabled in `manipulator` and other labor screens so it can be used for its intended purpose of flagging that no hauling labors should be assigned to a dwarf. Before, the only way to set the flag was to use an external program like Dwarf Therapist. + # 0.47.04-r5 ## Fixes diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index d7f3b269f..1c115471a 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -1600,6 +1600,7 @@ static const LuaWrapper::FunctionReg dfhack_units_module[] = { WRAPM(Units, getEffectiveSkill), WRAPM(Units, getExperience), WRAPM(Units, isValidLabor), + WRAPM(Units, setLaborValidity), WRAPM(Units, computeMovementSpeed), WRAPM(Units, computeSlowdownFactor), WRAPM(Units, getProfessionName), diff --git a/library/include/modules/Units.h b/library/include/modules/Units.h index e2d34254d..4a8452203 100644 --- a/library/include/modules/Units.h +++ b/library/include/modules/Units.h @@ -163,6 +163,7 @@ DFHACK_EXPORT int getEffectiveSkill(df::unit *unit, df::job_skill skill_id); DFHACK_EXPORT int getExperience(df::unit *unit, df::job_skill skill_id, bool total = false); DFHACK_EXPORT bool isValidLabor(df::unit *unit, df::unit_labor labor); +DFHACK_EXPORT bool setLaborValidity(df::unit_labor labor, bool isValid); DFHACK_EXPORT int computeMovementSpeed(df::unit *unit); DFHACK_EXPORT float computeSlowdownFactor(df::unit *unit); diff --git a/library/modules/Units.cpp b/library/modules/Units.cpp index a8f96b29f..6ca2e852a 100644 --- a/library/modules/Units.cpp +++ b/library/modules/Units.cpp @@ -893,6 +893,28 @@ bool Units::isValidLabor(df::unit *unit, df::unit_labor labor) return true; } +bool Units::setLaborValidity(df::unit_labor labor, bool isValid) +{ + if (!is_valid_enum_item(labor)) + return false; + if (labor == df::unit_labor::NONE) + return false; + for (size_t i = 0; i < world->raws.entities.size(); ++i) + { + if (!world->raws.entities[i] || + world->raws.entities[i]->flags.is_set(df::entity_raw_flags::LAYER_LINKED) || // Animal people + world->raws.entities[i]->flags.is_set(df::entity_raw_flags::GENERATED) || // Vault guardians + !world->raws.entities[i]->flags.is_set(df::entity_raw_flags::CIV_CONTROLLABLE) || // non-controllable civs + world->raws.entities[i]->translation == "") // Kobolds + { + continue; + } + + world->raws.entities[i]->jobs.permitted_labor[labor] = isValid; + } + return true; +} + inline void adjust_speed_rating(int &rating, bool is_adventure, int value, int dwarf100, int dwarf200, int adv50, int adv75, int adv100, int adv200) { if (is_adventure) diff --git a/plugins/manipulator.cpp b/plugins/manipulator.cpp index b333afae5..ad067276e 100644 --- a/plugins/manipulator.cpp +++ b/plugins/manipulator.cpp @@ -2279,6 +2279,16 @@ struct unitlist_hook : df::viewscreen_unitlistst IMPLEMENT_VMETHOD_INTERPOSE(unitlist_hook, feed); IMPLEMENT_VMETHOD_INTERPOSE(unitlist_hook, render); +static void enable_alchemist(color_ostream &out) +{ + if (!Units::setLaborValidity(unit_labor::ALCHEMIST, true)) + { + // informational only; this is a non-fatal error + out.printerr("manipulator: Could not flag Alchemist as a valid skill; Alchemist will not" + " be settable from DF or DFHack labor management screens.\n"); + } +} + DFhackCExport command_result plugin_enable(color_ostream &out, bool enable) { if (!gps) @@ -2291,6 +2301,9 @@ DFhackCExport command_result plugin_enable(color_ostream &out, bool enable) return CR_FAILURE; is_enabled = enable; + + if (is_enabled) + enable_alchemist(out); } return CR_OK; @@ -2306,6 +2319,20 @@ DFhackCExport command_result plugin_init ( color_ostream &out, vector Date: Sat, 6 Feb 2021 14:14:08 -0800 Subject: [PATCH 4/5] move alchemist-enabling logic to autohauler --- docs/Lua API.rst | 7 ++++--- plugins/autohauler.cpp | 21 +++++++++++++++++---- plugins/manipulator.cpp | 27 --------------------------- 3 files changed, 21 insertions(+), 34 deletions(-) diff --git a/docs/Lua API.rst b/docs/Lua API.rst index da5ac206b..928b3874e 100644 --- a/docs/Lua API.rst +++ b/docs/Lua API.rst @@ -1274,10 +1274,11 @@ Units module Returns whether the indicated labor is settable for the given unit. -* ``dfhack.units.setLaborValidity(unit_labor)`` +* ``dfhack.units.setLaborValidity(unit_labor, isValid)`` - Sets the given labor as valid for all playable units in the game (that is, for - all civilizations whose members can be residents of your fort). + Sets the given labor to the given (boolean) validity for all playable units in + the game (that is, for all civilizations whose members can be residents of + your fort). * ``dfhack.units.getNominalSkill(unit, skill[, use_rust])`` diff --git a/plugins/autohauler.cpp b/plugins/autohauler.cpp index 40d7452c7..7dd574f5f 100644 --- a/plugins/autohauler.cpp +++ b/plugins/autohauler.cpp @@ -565,10 +565,20 @@ static void cleanup_state() labor_infos.clear(); } +static void enable_alchemist(color_ostream &out) +{ + if (!Units::setLaborValidity(unit_labor::ALCHEMIST, true)) + { + // informational only; this is a non-fatal error + out.printerr("manipulator: Could not flag Alchemist as a valid skill; Alchemist will not" + " be settable from DF or DFHack labor management screens.\n"); + } +} + /** * Initialize the plugin labor lists */ -static void init_state() +static void init_state(color_ostream &out) { // This obtains the persistent data from the world save file config = World::GetPersistentData("autohauler/config"); @@ -656,6 +666,9 @@ static void init_state() reset_labor((df::unit_labor) i); } + // Allow Alchemist to be set in the labor-related UI screens so the player + // can actually use it as a flag without having to run Dwarf Therapist + enable_alchemist(out); } /** @@ -681,7 +694,7 @@ static void enable_plugin(color_ostream &out) cleanup_state(); // Initialize the plugin - init_state(); + init_state(out); } /** @@ -740,7 +753,7 @@ DFhackCExport command_result plugin_init ( color_ostream &out, std::vector Date: Wed, 17 Feb 2021 09:16:49 -0800 Subject: [PATCH 5/5] only set labor validity for the player civ --- docs/Lua API.rst | 7 ++++--- library/modules/Units.cpp | 17 ++++------------- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/docs/Lua API.rst b/docs/Lua API.rst index 928b3874e..0f949a397 100644 --- a/docs/Lua API.rst +++ b/docs/Lua API.rst @@ -1276,9 +1276,10 @@ Units module * ``dfhack.units.setLaborValidity(unit_labor, isValid)`` - Sets the given labor to the given (boolean) validity for all playable units in - the game (that is, for all civilizations whose members can be residents of - your fort). + Sets the given labor to the given (boolean) validity for all units that are + part of your fortress civilization. Valid labors are allowed to be toggled + in the in-game labor management screens (including DFHack's labor manipulator + screen). * ``dfhack.units.getNominalSkill(unit, skill[, use_rust])`` diff --git a/library/modules/Units.cpp b/library/modules/Units.cpp index 6ca2e852a..7edf90817 100644 --- a/library/modules/Units.cpp +++ b/library/modules/Units.cpp @@ -899,19 +899,10 @@ bool Units::setLaborValidity(df::unit_labor labor, bool isValid) return false; if (labor == df::unit_labor::NONE) return false; - for (size_t i = 0; i < world->raws.entities.size(); ++i) - { - if (!world->raws.entities[i] || - world->raws.entities[i]->flags.is_set(df::entity_raw_flags::LAYER_LINKED) || // Animal people - world->raws.entities[i]->flags.is_set(df::entity_raw_flags::GENERATED) || // Vault guardians - !world->raws.entities[i]->flags.is_set(df::entity_raw_flags::CIV_CONTROLLABLE) || // non-controllable civs - world->raws.entities[i]->translation == "") // Kobolds - { - continue; - } - - world->raws.entities[i]->jobs.permitted_labor[labor] = isValid; - } + df::historical_entity *entity = df::historical_entity::find(ui->civ_id); + if (!entity || !entity->entity_raw) + return false; + entity->entity_raw->jobs.permitted_labor[labor] = isValid; return true; }