diff --git a/changelog.txt b/changelog.txt index ac0ad32eca..9dd52fe75a 100644 --- a/changelog.txt +++ b/changelog.txt @@ -29,6 +29,7 @@ Template for new versions: ## New Tools - `fix/wildlife`: prevent wildlife from getting stuck when trying to exit the map. This fix needs to be enabled manually in `gui/control-panel` on the Bug Fixes tab since not all players want this bug to be fixed. - `immortal-cravings`: allow immortals to satisfy their cravings for food and drink +- `justice`: various functions pertaining to the justice system, currently with a command to pardon a unit's prison sentence ## New Features - `force`: support the ``Wildlife`` event to allow additional wildlife to enter the map diff --git a/docs/justice.rst b/docs/justice.rst new file mode 100644 index 0000000000..ea65a668d2 --- /dev/null +++ b/docs/justice.rst @@ -0,0 +1,34 @@ +justice +======= + +.. dfhack-tool:: + :summary: Mess with the justice system. + :tags: fort armok units + +This tool allows control over aspects of the justice system, such as the +ability to pardon criminals. + +Usage +----- + +:: + justice [list] + justice pardon [--unit ] + +Pardon the selected unit or the one specified by unit id (if provided). +Currently only applies to prison time and doesn't cancel beatings or +hammerings. + +Examples +-------- + +``justice`` + List the convicts currently serving sentences. +``justice pardon`` + Commutes the sentence of the currently selected convict. + +Options +------- + +``-u``, ``--unit `` + Specifies a specific unit instead of using a selected unit. diff --git a/justice.lua b/justice.lua new file mode 100644 index 0000000000..489618e49d --- /dev/null +++ b/justice.lua @@ -0,0 +1,61 @@ +local argparse = require('argparse') + +local TICKS_PER_SEASON_TICK = 10 +local TICKS_PER_DAY = 1200 + +local function list_convicts() + local found = false + for _,punishment in ipairs(df.global.plotinfo.punishments) do + local unit = df.unit.find(punishment.criminal) + if unit and punishment.prison_counter > 0 then + found = true + local days = math.ceil((punishment.prison_counter * TICKS_PER_SEASON_TICK) / TICKS_PER_DAY) + print(('%s (id: %d): serving a sentence of %d day(s)'):format( + dfhack.units.getReadableName(unit), unit.id, days)) + end + end + if not found then + print('No criminals currently serving sentences.') + end +end + +local function pardon_unit(unit) + for _,punishment in ipairs(df.global.plotinfo.punishments) do + if punishment.criminal == unit.id then + punishment.prison_counter = 0 + return + end + end + qerror('Unit is not currently serving a sentence!') +end + +local function command_pardon(unit_id) + local unit = nil + if not unit_id then + unit = dfhack.gui.getSelectedUnit(true) + if not unit then qerror('No unit selected!') end + else + unit = df.unit.find(unit_id) + if not unit then qerror(('No unit with id %d'):format(unit_id)) end + end + pardon_unit(unit) +end + +local unit_id = nil + +local positionals = argparse.processArgsGetopt({...}, + { + {'u', 'unit', hasArg=true, + handler=function(optarg) unit_id = argparse.nonnegativeInt(optarg, 'unit') end}, + } +) + +local command = positionals[1] + +if command == 'pardon' then + command_pardon(unit_id) +elseif not command or command == 'list' then + list_convicts() +else + qerror(('Unrecognised command: %s'):format(command)) +end