Replies: 7 comments
-
I don't plan to keep Dwarf Therapist as an external labor manager. I want to move to work details. It is still using labors right now because of technical limitations. When I use DFHack RPC that will be for editing work details (and other stuff) but not labors directly. I think I would only need from such an API a function that updates the labors from the new work details settings (and notify other plugins if they need it). I don't know how these labor managing plugins work. I'd like a summary. Do they make work details meaningless? All of them or only selected ones? Then I may need to know that and display something to tell the user work details are being overridden. Note that this is my personal plans. Maybe someone won't like it and fork or continue the abandoned Dwarf Therapist. Although I don't see what labors can do that work details cannot. |
Beta Was this translation helpful? Give feedback.
-
There's definitely improvements to be made to the hack I came up with for autofish. we don't know a way to get the game to update the work details just yet, but there has been talks of exposing what is necessary to do this. Once that's figured out, I can amend that logic to help more here, i think? |
Beta Was this translation helpful? Give feedback.
-
Is this the autofish "hack"? -- workaround to actually enable labours
for _,v2 in ipairs(v.assigned_units) do
-- find unit by ID and toggle fishing
local unit = df.unit.find(v2)
unit.status.labors.FISH = state
end Updating the labors should not be too difficult. The real issue I see with autofish logic is if the user has a work detail with FISH and one or more other labors. Then the whole work details is disabled but only FISH is updated, leading to an inconsistent state. When eventually the game update labors, the other labors will also be disabled. If autofish is assuming fishing work details only contain FISH. You should check these preconditions and warn the user if they are not verified. |
Beta Was this translation helpful? Give feedback.
-
Yeah. You're right, i didn't think about that originally when I wrote it. That was just to get it working at the time. There is a function somewhere to update the work details, we just haven't found it yet, which will mean the extra bit won't need to be there any more, and can be reupurposed to defer to other labor managers if required. work details are just a vector with some data in, but changing them doesn't actually update anything except the UI ingame. |
Beta Was this translation helpful? Give feedback.
-
In 50.07-steam win64, at 0x14030E9B7, the function looks like this: sub_14030E9B7(unitst *unit)
{
if (game.external_flag & 1)
return;
if (unit->profession == BABY || unit->is_tamable() || !unit->is_fort_controlled()) {
// 0x14030F334
memset(unit->labors, 0, 94);
return 0;
}
else if (unit->profession == CHILD) {
// 0x14030E9DF
if (!plotinfo.hauling.flags.children_do_chores || binary_search(plotinfo.hauling.chores_exempted_children, unit->id)) {
// goto 0x14030F334
memset(unit->labors, 0, 94);
return;
}
// 0x14030EA4F
return memmove(labors, &plotinfo.hauling.chores, 94);
}
else {
// 0x14030EA6D
old_cutwood = unit->labors[CUTWOOD];
old_hunt = unit->labors[HUNT];
old_mine = unit->labors[MINE];
no_default_labors /*r15*/ = is_menial_work_exempted(unit, plotinfo.group_id) || unit->flags4.only_do_assigned_jobs;
memset(unit->labors, no_default_labors ? 0 : 1, 94);
unit->labors[MINE] = 0;
unit->labors[CUTWOOD] = 0;
unit->labors[HUNT] = 0;
unit->labors[FISH] = 0;
unit->labors[DIAGNOSE] = 0;
unit->labors[SURGERY] = 0;
unit->labors[BONE_SETTING] = 0;
for (work_detail/*r8*/: plotinfo.hauling.work_details) {
if ((work_detail->work_detail_flags & (enabled | limited) == enabled))
continue;
for (l = 0; l < 94; ++l) // unrolled loop on labor
if (work_detail->allowed_labors[l] != 0)
unit->labors[l] = 0;
}
for (work_detail/*rsi*/: plotinfo.hauling.work_details) {
if ((work_detail->work_detail_flags & (enabled | limited) == (enabled | limited))) {
// 0x14030EDC2
if (binary_search(unit->id, work_detail->assigned_units) == -1)
continue;
for (l = 0; l < 94; ++l) // unrolled loop on labor
if (work_detail->allowed_labors[l] != 0)
unit->labors[l] = 1;
}
else if ((work_detail->work_detail_flags & (enabled | limited) != enabled))
continue;
else { // enabled
// 0x14030F013
if (no_default_labors && binary_search(unit->id, work_detail->assigned_units) == -1)
continue;
for (l = 0; l < 94; ++l) // unrolled loop on labor
if (work_detail->allowed_labors[l] != 0)
unit->labors[l] = 1;
}
}
for (occupation/*rdx*/: unit->occupations) {
if (occupation->type == DOCTOR) {
unit->labors[DIAGNOSE] = 1;
unit->labors[SURGERY] = 1;
unit->labors[BONE_SETTING] = 1;
}
if (occupation->type == DIAGNOSTICIAN) {
unit->labors[DIAGNOSE] = 1;
}
if (occupation->type == SURGEON) {
unit->labors[SURGERY] = 1;
}
if (occupation->type == BONE_DOCTOR) {
unit->labors[BONE_SETTING] = 1;
}
}
if (old_mine != unit->labors[MINE] || old_cutwood != unit->labors[CUTWOOD] || old_hunt != unit->labors[HUNT]) {
sub_140EF1F30(unit);
unit->military.pickup_flags |= 1;
}
}
} Nothing surprising. Special case labors were already known. A few notes:
|
Beta Was this translation helpful? Give feedback.
-
I uploaded an experimental plugin with some functions that may be interesting for a labor module: https://github.com/cvuchener/dfhack-plugin-workdetailtest/blob/master/workdetailtest.cpp (I think mostly |
Beta Was this translation helpful? Give feedback.
-
i vtracked the function above forward from v50.07 to v50.13 if i am not mistaken, all of these were "exact instruction" matches so the code hasn't changed since 50.07 unfortunately, none of the no-arg methods in there are 29 call points into this function; i'm currently investigating if any of them can be usefully attached. probably not, but never know, we might get lucky |
Beta Was this translation helpful? Give feedback.
-
Proposal: a core API for managing labors/work details
The api should provides some group of functions to enable/disable labors in some way.
When a labor change is requested, the api will check the df "external labor management" flag. If it's 0, then the game is using vanilla labor management and the code does what is appropriate for when work details are in vanilla mode, basically replicating/extending the logic that @AndrielChaoti came up with for autofish. If the flag is 1 and there is a registered dfhack labor manager, then the labor management change is passed to the registered labor manager which will do whatever is appropriate to accommodate the request. If the flag is 1 and there is not a registered labor manager, then the labor management change either (a) fails or (b) is done in some "default" way that yields the best reasonable result on the assumption that the external labor manager is Dwarf Therapist
Beta Was this translation helpful? Give feedback.
All reactions