add search support for noble candidates

develop
Myk Taylor 2023-10-13 14:33:22 -07:00
parent 43b0c3e10d
commit d739d9c1ef
No known key found for this signature in database
4 changed files with 90 additions and 5 deletions

@ -57,7 +57,7 @@ Template for new versions:
## New Features ## New Features
- `logistics`: ``automelt`` now optionally supports melting masterworks; click on gear icon on `stockpiles` overlay frame - `logistics`: ``automelt`` now optionally supports melting masterworks; click on gear icon on `stockpiles` overlay frame
- `sort`: new search widgets for Info panel tabs, including all "Creatures" subtabs, all "Objects" subtabs, "Tasks", and the "Work details" subtab under "Labor" - `sort`: new search widgets for Info panel tabs, including all "Creatures" subtabs, all "Objects" subtabs, "Tasks", candidate assignment on the "Noble" subtab, and the "Work details" subtab under "Labor"
- `sort`: new search and filter widgets for the "Interrogate" and "Convict" screens under "Justice" - `sort`: new search and filter widgets for the "Interrogate" and "Convict" screens under "Justice"
- `sort`: new search widgets for location selection screen (when you're choosing what kind of guildhall or temple to dedicate) - `sort`: new search widgets for location selection screen (when you're choosing what kind of guildhall or temple to dedicate)
- `sort`: new search widgets for burrow assignment screen and other unit assignment dialogs - `sort`: new search widgets for burrow assignment screen and other unit assignment dialogs

@ -115,6 +115,15 @@ necromancers, necromancer experiments, and intelligent undead.
On the interrogations screen, you can also filter units by whether they have On the interrogations screen, you can also filter units by whether they have
already been interrogated. already been interrogated.
Candidates overlay
------------------
When you select the button to choose a candidate to assign to a noble role on
the nobles screen, you can search for units by name, profession, or any of the
skills in which they have achieved at least "novice" level. For example, when
assigning a broker, you can search for "appraisal" to find candidates that have
at least some appraisal skill.
Location selection overlay Location selection overlay
-------------------------- --------------------------

@ -1286,6 +1286,7 @@ OVERLAY_WIDGETS = {
squad_assignment=SquadAssignmentOverlay, squad_assignment=SquadAssignmentOverlay,
squad_annotation=SquadAnnotationOverlay, squad_annotation=SquadAnnotationOverlay,
info=require('plugins.sort.info').InfoOverlay, info=require('plugins.sort.info').InfoOverlay,
candidates=require('plugins.sort.info').CandidatesOverlay,
interrogation=require('plugins.sort.info').InterrogationOverlay, interrogation=require('plugins.sort.info').InterrogationOverlay,
location_selector=require('plugins.sort.locationselector').LocationSelectorOverlay, location_selector=require('plugins.sort.locationselector').LocationSelectorOverlay,
unit_selector=require('plugins.sort.unitselector').UnitSelectorOverlay, unit_selector=require('plugins.sort.unitselector').UnitSelectorOverlay,

@ -6,6 +6,7 @@ local widgets = require('gui.widgets')
local utils = require('utils') local utils = require('utils')
local info = df.global.game.main_interface.info local info = df.global.game.main_interface.info
local administrators = info.administrators
local creatures = info.creatures local creatures = info.creatures
local justice = info.justice local justice = info.justice
local objects = info.artifacts local objects = info.artifacts
@ -135,7 +136,7 @@ local function work_details_search(vec, data, text, incremental)
vec, data, text, incremental) vec, data, text, incremental)
end end
local function cleanup_cri_unit(vec, data) local function restore_allocated_data(vec, data)
if not data.saved_visible or not data.saved_original then return end if not data.saved_visible or not data.saved_original then return end
for _,elem in ipairs(data.saved_original) do for _,elem in ipairs(data.saved_original) do
if not utils.linear_index(data.saved_visible, elem) then if not utils.linear_index(data.saved_visible, elem) then
@ -144,6 +145,26 @@ local function cleanup_cri_unit(vec, data)
end end
end end
local function serialize_skills(unit)
if not unit or not unit.status or not unit.status.current_soul then
return ''
end
local skills = {}
for _, skill in ipairs(unit.status.current_soul.skills) do
if skill.rating > 0 then -- ignore dabbling
table.insert(skills, df.job_skill[skill.id])
end
end
return table.concat(skills, ' ')
end
local function get_candidate_search_key(cand)
if not cand.un then return end
return ('%s %s'):format(
get_unit_search_key(cand.un),
serialize_skills(cand.un))
end
-- ---------------------- -- ----------------------
-- InfoOverlay -- InfoOverlay
-- --
@ -186,12 +207,12 @@ function InfoOverlay:init()
get_search_key_fn=get_cri_unit_search_key, get_search_key_fn=get_cri_unit_search_key,
get_sort_fn=get_sort get_sort_fn=get_sort
}), }),
curry(cleanup_cri_unit, vec)) curry(restore_allocated_data, vec))
end end
self:register_handler('JOBS', tasks.cri_job, self:register_handler('JOBS', tasks.cri_job,
curry(sortoverlay.single_vector_search, {get_search_key_fn=get_cri_unit_search_key}), curry(sortoverlay.single_vector_search, {get_search_key_fn=get_cri_unit_search_key}),
curry(cleanup_cri_unit, vec)) curry(restore_allocated_data, tasks.cri_job))
self:register_handler('PET_OT', creatures.atk_index, self:register_handler('PET_OT', creatures.atk_index,
curry(sortoverlay.single_vector_search, {get_search_key_fn=get_race_name})) curry(sortoverlay.single_vector_search, {get_search_key_fn=get_race_name}))
self:register_handler('PET_AT', creatures.trainer, self:register_handler('PET_AT', creatures.trainer,
@ -259,7 +280,7 @@ function InfoOverlay:updateFrames()
local ret = resize_overlay(self) local ret = resize_overlay(self)
local l, t = get_panel_offsets() local l, t = get_panel_offsets()
local frame = self.subviews.panel.frame local frame = self.subviews.panel.frame
if (frame.l == l and frame.t == t) then return ret end if frame.l == l and frame.t == t then return ret end
frame.l, frame.t = l, t frame.l, frame.t = l, t
return true return true
end end
@ -282,6 +303,60 @@ function InfoOverlay:onInput(keys)
return InfoOverlay.super.onInput(self, keys) return InfoOverlay.super.onInput(self, keys)
end end
-- ----------------------
-- CandidatesOverlay
--
CandidatesOverlay = defclass(CandidatesOverlay, sortoverlay.SortOverlay)
CandidatesOverlay.ATTRS{
default_pos={x=54, y=8},
viewscreens='dwarfmode/Info/ADMINISTRATORS/Candidates',
frame={w=27, h=3},
}
function CandidatesOverlay:init()
self:addviews{
widgets.BannerPanel{
view_id='panel',
frame={l=0, t=0, r=0, h=1},
subviews={
widgets.EditField{
view_id='search',
frame={l=1, t=0, r=1},
label_text="Search: ",
key='CUSTOM_ALT_S',
on_change=function(text) self:do_search(text) end,
},
},
},
}
self:register_handler('CANDIDATE', administrators.candidate,
curry(sortoverlay.single_vector_search, {get_search_key_fn=get_candidate_search_key}),
curry(restore_allocated_data, administrators.candidate))
end
function CandidatesOverlay:get_key()
if administrators.choosing_candidate then
return 'CANDIDATE'
end
end
function CandidatesOverlay:updateFrames()
local t = is_tabs_in_two_rows() and 2 or 0
local frame = self.subviews.panel.frame
if frame.t == t then return end
frame.t = t
return true
end
function CandidatesOverlay:onRenderBody(dc)
CandidatesOverlay.super.onRenderBody(self, dc)
if self:updateFrames() then
self:updateLayout()
end
end
-- ---------------------- -- ----------------------
-- InterrogationOverlay -- InterrogationOverlay
-- --