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
- `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 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

@ -115,6 +115,15 @@ necromancers, necromancer experiments, and intelligent undead.
On the interrogations screen, you can also filter units by whether they have
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
--------------------------

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

@ -6,6 +6,7 @@ local widgets = require('gui.widgets')
local utils = require('utils')
local info = df.global.game.main_interface.info
local administrators = info.administrators
local creatures = info.creatures
local justice = info.justice
local objects = info.artifacts
@ -135,7 +136,7 @@ local function work_details_search(vec, data, text, incremental)
vec, data, text, incremental)
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
for _,elem in ipairs(data.saved_original) do
if not utils.linear_index(data.saved_visible, elem) then
@ -144,6 +145,26 @@ local function cleanup_cri_unit(vec, data)
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
--
@ -186,12 +207,12 @@ function InfoOverlay:init()
get_search_key_fn=get_cri_unit_search_key,
get_sort_fn=get_sort
}),
curry(cleanup_cri_unit, vec))
curry(restore_allocated_data, vec))
end
self:register_handler('JOBS', tasks.cri_job,
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,
curry(sortoverlay.single_vector_search, {get_search_key_fn=get_race_name}))
self:register_handler('PET_AT', creatures.trainer,
@ -259,7 +280,7 @@ function InfoOverlay:updateFrames()
local ret = resize_overlay(self)
local l, t = get_panel_offsets()
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
return true
end
@ -282,6 +303,60 @@ function InfoOverlay:onInput(keys)
return InfoOverlay.super.onInput(self, keys)
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
--