diff --git a/chronicle.lua b/chronicle.lua index 446b3fd6c..c247180ed 100644 --- a/chronicle.lua +++ b/chronicle.lua @@ -1,4 +1,4 @@ --- Chronicles fortress events (currently only unit deaths) +-- Chronicles fortress events: unit deaths, artifact creation, and invasions --@module = true --@enable = true @@ -40,48 +40,47 @@ local function on_unit_death(unit_id) local date = format_date(df.global.cur_year, df.global.cur_year_tick) add_entry(string.format('Death of %s on %s', name, date)) end -local function check_artifacts() - local last_id = state.last_artifact_id - for _, rec in ipairs(df.global.world.artifacts.all) do - if rec.id > last_id then - local name = dfhack.translation.translateName(rec.name) - -- artifact_record stores the creation tick in `season_tick` - local date = format_date(rec.year, rec.season_tick or 0) - add_entry(string.format('Artifact "%s" created on %s', name, date)) - last_id = rec.id - end - end - state.last_artifact_id = last_id -end -local function check_invasions() - for _, inv in ipairs(df.global.plotinfo.invasions.list) do - if inv.flags.active and not state.known_invasions[inv.id] then - state.known_invasions[inv.id] = true - local date = format_date(df.global.cur_year, df.global.cur_year_tick) - add_entry(string.format('Invasion started on %s', date)) - end +local function on_item_created(item_id) + local item = df.item.find(item_id) + if not item or not item.flags.artifact then return end + + local gref = dfhack.items.getGeneralRef(item, df.general_ref_type.IS_ARTIFACT) + local rec = gref and df.artifact_record.find(gref.artifact_id) or nil + if not rec then return end + + local name = dfhack.translation.translateName(rec.name) + local date = format_date(rec.year, rec.season_tick or 0) + if rec.id > state.last_artifact_id then + state.last_artifact_id = rec.id end + add_entry(string.format('Artifact "%s" created on %s', name, date)) end --- main loop; artifact and invasion tracking disabled to avoid scanning large --- data structures, which was causing hangs on some forts -local function event_loop() - if not state.enabled then return end - dfhack.timeout(1200, 'ticks', event_loop) +local function on_invasion(invasion_id) + if state.known_invasions[invasion_id] then return end + state.known_invasions[invasion_id] = true + local date = format_date(df.global.cur_year, df.global.cur_year_tick) + add_entry(string.format('Invasion started on %s', date)) end +-- legacy scanning functions for artifacts and invasions have been removed in +-- favor of event-based tracking. the main loop is no longer needed. local function do_enable() state.enabled = true + eventful.enableEvent(eventful.eventType.ITEM_CREATED, 1) + eventful.enableEvent(eventful.eventType.INVASION, 1) eventful.onUnitDeath[GLOBAL_KEY] = on_unit_death + eventful.onItemCreated[GLOBAL_KEY] = on_item_created + eventful.onInvasion[GLOBAL_KEY] = on_invasion persist_state() - - event_loop() end local function do_disable() state.enabled = false eventful.onUnitDeath[GLOBAL_KEY] = nil + eventful.onItemCreated[GLOBAL_KEY] = nil + eventful.onInvasion[GLOBAL_KEY] = nil persist_state() end @@ -95,6 +94,8 @@ end dfhack.onStateChange[GLOBAL_KEY] = function(sc) if sc == SC_MAP_UNLOADED then eventful.onUnitDeath[GLOBAL_KEY] = nil + eventful.onItemCreated[GLOBAL_KEY] = nil + eventful.onInvasion[GLOBAL_KEY] = nil state.enabled = false return end diff --git a/docs/chronicle.rst b/docs/chronicle.rst index 7943ee30a..e573d967b 100644 --- a/docs/chronicle.rst +++ b/docs/chronicle.rst @@ -2,12 +2,11 @@ chronicle ========= .. dfhack-tool:: - :summary: Record fortress events like deaths. Artifact and invasion tracking disabled. + :summary: Record fortress events like deaths, artifacts, and invasions. :tags: fort gameplay This tool automatically records notable events in a chronicle that is stored -with your save. Currently only unit deaths are recorded since artifact and -invasion tracking has been disabled due to performance issues. +with your save. Unit deaths, artifact creation, and invasions are recorded. Usage -----