Skip to content

Commit c74dc5f

Browse files
committed
internal/notify/notifications updating missing nemesis warning
Changes: changed the color of the overlay text "missing # nemesis records": * light red when there are affected units on the map. * yellow otherwise. changed the color of the popup window text "permanently disappear": * red when there are affected units on the map. * white otherwise. added notice (in yellow) when there are no affected units on the map. changed the text "active units" to "units on the map" in three places. don't indent unit names; showing them in light red is enough. if the unit name is length is too long, show it without the english name. (internal) implemented caching of tests. (internal) moved all the cache logic into an object. (internal) note: has some debugging-data printing enabled.
1 parent ff1b95a commit c74dc5f

2 files changed

Lines changed: 71 additions & 30 deletions

File tree

changelog.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ Template for new versions:
3333
## Fixes
3434

3535
## Misc Improvements
36+
- `gui/notify`: reduced severity of the missing nemesis records warning if no units on the map are affected. clarified wording.
3637

3738
## Removed
3839

internal/notify/notifications.lua

Lines changed: 70 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -335,22 +335,22 @@ local function save_popup()
335335
end
336336
end
337337

338-
---@return string[]
339-
local function get_active_units_with_missing_nemesis_records()
340-
local namelist = {}
341-
for _, unit in ipairs(df.global.world.units.active) do
338+
---@return df.unit[]
339+
local function _get_active_units_with_missing_nemesis_records()
340+
local list = {}
341+
for _, unit in ipairs(units.active) do
342342
local ref = dfhack.units.getGeneralRef(unit, df.general_ref_type.IS_NEMESIS)
343343
if ref then
344344
local nrec = ref:getNemesis()
345345
if nrec == nil then
346-
table.insert(namelist, dfhack.units.getReadableName(unit))
346+
table.insert(list, unit)
347347
end
348348
end
349349
end
350-
return namelist
350+
return list
351351
end
352352

353-
---@param vector any[] # a df vector or array, or a Lua list.
353+
---@param vector any[] # a df vector or array, or a Lua list (not tested yet).
354354
---@param field string? # nil, or the field name to sort on.
355355
---@param comparator fun(a:any, b:any):integer|nil
356356
--- # an optional comparator that returns -1,0,1 per utils.compare_* .
@@ -378,17 +378,49 @@ local function verify_vector_is_sorted(vector, field, comparator)
378378
return sorted
379379
end
380380

381-
local cache_nemesis_all_is_sorted = {}
382-
---only verifies if the vector length has changed.
383-
---@return boolean
384-
local function verify_nemesis_all_is_sorted()
385-
local vector = df.global.world.nemesis.all
386-
if #vector == cache_nemesis_all_is_sorted.length then
387-
return cache_nemesis_all_is_sorted.sorted
381+
local Cache_nemesis_all = defclass(Cache_nemesis_all, nil) -- singleton, don't need to instantiate.
382+
Cache_nemesis_all.ATTRS{}
383+
384+
---@param force boolean? # true to force updating the cached data
385+
function Cache_nemesis_all:populate(force)
386+
if not force
387+
and self.ATTRS.cached_on_year == dfhack.world.ReadCurrentYear()
388+
and (self.ATTRS.cached_on_tick or 0) + 600 < dfhack.world.ReadCurrentTick()
389+
and self.ATTRS.nemesis_all_length == #df.global.world.nemesis.all
390+
and self.ATTRS.units_active_length == #df.global.world.units.active
391+
then
392+
return
388393
end
389-
cache_nemesis_all_is_sorted.length = #vector
390-
cache_nemesis_all_is_sorted.sorted = verify_vector_is_sorted(vector, 'id')
391-
return cache_nemesis_all_is_sorted.sorted
394+
print("Cache_nemesis_all:populate", "\n",
395+
"force", force, "\n",
396+
"year", self.ATTRS.cached_on_year, dfhack.world.ReadCurrentYear(), "\n",
397+
"tick", self.ATTRS.cached_on_tick, dfhack.world.ReadCurrentTick(), "\n",
398+
"#nemall", self.ATTRS.nemesis_all_length, #df.global.world.nemesis.all, "\n",
399+
"#active", self.ATTRS.units_active_length, #df.global.world.units.active, "\n",
400+
"")
401+
402+
self.ATTRS.cached_on_year = dfhack.world.ReadCurrentYear()
403+
self.ATTRS.cached_on_tick = dfhack.world.ReadCurrentTick()
404+
self.ATTRS.nemesis_all_length = #df.global.world.nemesis.all
405+
self.ATTRS.units_active_length = #df.global.world.units.active
406+
self.ATTRS.nemesis_all_is_sorted = verify_vector_is_sorted(df.global.world.nemesis.all, 'id')
407+
self.ATTRS.affected_units = _get_active_units_with_missing_nemesis_records()
408+
end
409+
410+
function Cache_nemesis_all:init()
411+
self:populate(true)
412+
end
413+
414+
---@return boolean
415+
function Cache_nemesis_all:is_sorted()
416+
self:populate()
417+
return self.ATTRS.nemesis_all_is_sorted
418+
end
419+
420+
---@return df.unit[]
421+
function Cache_nemesis_all:get_affected_units()
422+
self:populate()
423+
return self.ATTRS.affected_units
392424
end
393425

394426
-- the order of this list controls the order the notifications will appear in the overlay
@@ -398,7 +430,7 @@ NOTIFICATIONS_BY_IDX = {
398430
desc='Reports missing nemesis records, indicating savegame corruption.',
399431
default=true,
400432
fn = function()
401-
if not verify_nemesis_all_is_sorted() then
433+
if not Cache_nemesis_all:is_sorted() then
402434
return { {
403435
pen = COLOR_LIGHTRED,
404436
text = 'nemesis vector not sorted'
@@ -407,12 +439,13 @@ NOTIFICATIONS_BY_IDX = {
407439
local count = df.global.nemesis_next_id - #df.global.world.nemesis.all
408440
if count == 0 then return end
409441
return { {
410-
pen = COLOR_LIGHTRED,
442+
pen = #Cache_nemesis_all:get_affected_units() > 0
443+
and COLOR_LIGHTRED or COLOR_YELLOW,
411444
text = ('missing %d nemesis record%s'):format(count, count == 1 and '' or 's')
412445
} }
413446
end,
414447
on_click=function()
415-
if not verify_nemesis_all_is_sorted() then
448+
if not Cache_nemesis_all:is_sorted() then
416449
local message =
417450
'This save game is corrupt.\n\nThe world.nemesis.global vector\n' ..
418451
'of this savegame is not sorted.\n\nSome attempts to lookup the\n' ..
@@ -421,6 +454,7 @@ NOTIFICATIONS_BY_IDX = {
421454
dlg.showMessage('nemesis vector not sorted', message, COLOR_RED)
422455
return
423456
end
457+
local list = Cache_nemesis_all:get_affected_units()
424458
local message = {
425459
{ pen = COLOR_RED, text = 'This save game may be corrupt.' }, NEWLINE,
426460
NEWLINE,
@@ -431,23 +465,29 @@ NOTIFICATIONS_BY_IDX = {
431465
{ pen = COLOR_WHITE, text = 'crashes during game save and when retiring forts.' }, NEWLINE,
432466
NEWLINE,
433467
{ pen = COLOR_WHITE, text = 'Units with missing nemesis records will' }, NEWLINE,
434-
{ pen = COLOR_RED, text = 'permanently disappear' },
468+
{ pen = #list > 0 and COLOR_RED or COLOR_WHITE,
469+
text = 'permanently disappear' },
435470
{ pen = COLOR_WHITE, text = ' if they leave the map or' }, NEWLINE,
436471
{ pen = COLOR_WHITE, text = 'if the fort is retired.' }, NEWLINE,
437472
NEWLINE,
438473
}
439-
local redtext = get_active_units_with_missing_nemesis_records()
440-
if #redtext > 0 then
474+
if #list > 0 then
441475
table.insert(message, { pen = COLOR_RED,
442-
text = 'These active units are missing their nemesis records:' })
476+
text = 'These units on the map are missing their nemesis records:' })
443477
table.insert(message, NEWLINE)
444-
for _, line in ipairs(redtext) do
445-
table.insert(message, { pen = COLOR_LIGHTRED, text = ' ' .. line })
478+
for _, unit in ipairs(list) do
479+
local text = dfhack.units.getReadableName(unit)
480+
if #text > 55 then text = dfhack.units.getReadableName(unit, true); end
481+
table.insert(message, { pen = COLOR_LIGHTRED, text = text })
446482
table.insert(message, NEWLINE)
447483
end
484+
else
485+
table.insert(message, { pen = COLOR_YELLOW,
486+
text = 'No units on the map are missing their nemesis records.' })
487+
table.insert(message, NEWLINE)
448488
end
449-
dlg.showMessage((#redtext > 0 and 'Active units are' or 'This world is')
450-
.. ' missing nemesis records',message, COLOR_WHITE)
489+
dlg.showMessage((#list > 0 and 'Units on the map are' or 'This world is')
490+
.. ' missing nemesis records', message, COLOR_WHITE)
451491
end,
452492
},
453493
{
@@ -728,7 +768,7 @@ end
728768
config = get_config()
729769

730770
dfhack.onStateChange['internal/notify/notifications'] = function(event)
731-
if event == SC_WORLD_LOADED or event == SC_WORLD_UNLOADED then
732-
cache_nemesis_all_is_sorted = {}
771+
if event == SC_WORLD_LOADED or SC_WORLD_UNLOADED or SC_MAP_LOADED or SC_MAP_UNLOADED then
772+
Cache_nemesis_all:populate(true)
733773
end
734774
end

0 commit comments

Comments
 (0)