-- Assign creatures to restraints
-- Jailer 1.1
-- Attempts to create job to assign creature to cage/chain
-- Fortress mode script called from DFHack, can use either the command line or a popup gui to select participants
-- LNP: [04410r03-x64]
-- GUI courtesy of scripts from warmist and Putnam
--
http://www.bay12forums.com/smf/index.php?topic=91166.msg4149991#msg4149991--
http://www.bay12forums.com/smf/index.php?topic=139553.msg5858508#msg5858508-- Many thanks to the inhabitants of Erithkosh, who suffered much during testing
local utils=require('utils')
local script=require('gui.script')
validArgs = utils.invert({
'help',
'nogui',
'victim',
'jailer',
'restraint'
})
local args = utils.processArgs({...}, validArgs)
local cmdVictim = {}
local userVictim = {}
local cmdJailer = {}
local userJailer = {}
local cmdJail = {}
local userJail = {}
local helpme = [===[
jailer.lua
=========
This script should create a job to assign a creature to a cage/restraint. Creature IDs can be found with
cprobe, building IDs can be found with bprobe. The script can operate in two modes. When called without
arguments, it presents a gui allowing selection of the victim, jailer, and restraint. Called with arguments,
allows you directly specify targets. Note that non-citizens can only be targeted by the non-gui approach.
Note1: Restraints must be rooms, set to justice
Note2: Cages must be metal. At this time, it appears chains can be any material.
Caution! Assigning jobs to active military units occasionally causes crashes.
arguments:
-help
print this help message
-nogui
Do not use the gui for target selection. You must provide victim and aggressors arguments
-victim
Unit ID of the target (unit to be restrained)
-jailer
Unit ID of the dwarf that you want to chain up the victim.
-restraint
Building ID of the restraint/cage where the creature should be jailed
Examples
jailer
Launches gui
jailer -nogui -victim 76 -jailer 79 -restraint 210
Launches the script. Unit 79 gets a job aimed at restraining unit 76 on building id 210
]===]
-- Handle help requests
if args.help then
print(helpme)
return
end
-- Handle user input
if ( args.nogui and args.victim and args.jailer and args.restraint ) then
table.insert(cmdVictim, args.victim)
table.insert(cmdJailer, args.jailer)
table.insert(cmdJail, args.restraint)
else
print("Launching Cage gui. You might review -help")
end
function getLastJobLink()
-- v43.03: Preserved for legacy uses
-- local st=df.global.world.job_list
-- v44.10
local st=df.global.world.jobs.list
while st.next~=nil do
st=st.next
end
return st
end
function addNewJob(job)
local nn=getLastJobLink()
local nl=df.job_list_link:new()
nl.prev=nn
nn.next=nl
nl.item=job
job.list_link=nl
end
function jailUnit(unit1,unit2,restraint,jtype)
local nj=df.job:new()
nj.id=df.global.job_next_id
df.global.job_next_id=df.global.job_next_id+1
nj.flags.special=true
-- jtype: 1-cage, 2-chain
if jtype == 1 then
nj.job_type=df.job_type.CageLargeCreature
elseif jtype == 2 then
nj.job_type=df.job_type.ChainAnimal
else
print("Bad jtype. Neither chain nor cage")
qerror('Error: Bad jail type for job!. Neither chain nor cage?')
end
nj.completion_timer=-1
nj.general_refs:insert("#",{new=df.general_ref_building_holderst,building_id=restraint.id})
nj.general_refs:insert("#",{new=df.general_ref_unit_cageest,unit_id=unit2.id})
nj.general_refs:insert("#",{new=df.general_ref_unit_workerst,unit_id=unit1.id})
addNewJob(nj)
unit1.job.current_job=nj
end
function assignJail(unit2,jail,jtype)
-- jtype: 1-cage, 2-chain
if jtype == 1 then
jail.assigned_units:insert("#",unit2.id)
elseif jtype == 2 then
jail.assigned = unit2
else
print("Bad jtype. Neither chain nor cage")
qerror('Error: Bad jail for assignment!. Neither chain nor cage?')
end
end
local function getCitizenList()
local citizenTable={}
for k,u in ipairs(df.global.world.units.active) do
if dfhack.units.isCitizen(u) then
table.insert(citizenTable,{dfhack.TranslateName(dfhack.units.getVisibleName(u)),nil,u})
end
end
return citizenTable
end
local function getJailerList()
local citizenTable={}
for k,u in ipairs(df.global.world.units.active) do
if dfhack.units.isCitizen(u) and u.military.squad_id < 0 then
table.insert(citizenTable,{dfhack.TranslateName(dfhack.units.getVisibleName(u)),nil,u})
end
end
return citizenTable
end
local function getJailList()
local jailTable={}
for k,u in ipairs(df.global.world.buildings.all) do
if u.flags.justice == true then
-- print("Jailer:Jail: ",k,utils.getBuildingName(u))
if string.match(utils.getBuildingName(u), "Chain") and u.assigned == nil then
table.insert(jailTable,{utils.getBuildingName(u),nil,u})
elseif string.match(utils.getBuildingName(u), "Rope") and u.assigned == nil then
table.insert(jailTable,{utils.getBuildingName(u),nil,u})
elseif string.match(utils.getBuildingName(u), "Cage") then
table.insert(jailTable,{utils.getBuildingName(u),nil,u})
end
end
end
return jailTable
end
local function jail(userVictim, userJailer, userJail)
local unit1,unit2,jail = {}
local jtype = 0
for k, v in pairs(userVictim) do
--print("Jailer:Victim: ",dfhack.units.getVisibleName(v))
unit2 = v
end
for k, v in pairs(userJailer) do
--print("Jailer:Jailer: ",dfhack.units.getVisibleName(v))
unit1 = v
end
for k, v in pairs(userJail) do
--print("Jailer:Jail: ",utils.getBuildingName(v))
jail = v
local jtest = utils.getBuildingName(v)
if string.match(jtest, "Cage") then
jtype = 1
elseif string.match(jtest, "Rope") then
jtype = 2
elseif string.match(jtest, "Chain") then
jtype = 2
end
end
assignJail(unit2,jail,jtype)
jailUnit(unit1,unit2,jail,jtype)
end
-- Let's do this
script.start(function()
-- Get list of valid targets(citizens)
local citizens=getCitizenList()
-- Get list of valid aggressors(the mob)
local jailers=getJailerList()
local jails=getJailList()
if #citizens==0 then
script.showMessage('Jailer',"No citizens! Something is broken.",COLOR_WHITE)
qerror('Error: No citizens! Something is broken.')
return
end
if #jailers==0 then
script.showMessage('Jailer',"No one can be the jailer!",COLOR_WHITE)
qerror('Error: No jailer! Something is broken.')
return
end
if #jails==0 then
script.showMessage('Jailer',"No empty rooms for justice!",COLOR_WHITE)
qerror('Error: No jails! No empty rooms for justice?')
return
end
-- Gui in use
if not args.nogui then
-- Gui is in use, overwrite command line options specified
userVictim = {}
userJailer = {}
userJail = {}
-- Prompt for victim
local ok2,name2,victim = script.showListPrompt("Jailer","Choose the victim",COLOR_WHITE,citizens)
local isVictim = victim[3]
table.insert(userVictim, victim[3])
-- Prompt for jailer
userAggressors = {}
local ok2,name2,jailer = script.showListPrompt("Jailer","Choose the jailer",COLOR_WHITE,citizens)
table.insert(userJailer, jailer[3])
-- Prompt for jail
local ok2,name2,jail = script.showListPrompt("Jailer","Choose the jail",COLOR_WHITE,jails)
table.insert(userJail, jail[3])
-- Gui not in use
else
for k, v in pairs(cmdVictim) do
table.insert(userVictim, df.unit.find(v))
end
for k, v in pairs(cmdJailer) do
table.insert(userJailer, df.unit.find(v))
end
for k, v in pairs(cmdJail) do
table.insert(userJail, df.building.find(v))
end
end
print("Victim: " .. #userVictim .. " Jailer: " .. #userJailer .. " Jail: " .. #userJail)
-- Restrain some folks!
jail(userVictim, userJailer, userJail)
end)