dfhack/scripts/emigration.lua

133 lines
4.0 KiB
Lua

--Allow stressed dwarves to emigrate from the fortress
-- For 34.11 by IndigoFenix; update and cleanup by PeridexisErrant
-- old version: http://dffd.bay12games.com/file.php?id=8404
--[[=begin
emigration
==========
Allows dwarves to emigrate from the fortress when stressed,
in proportion to how badly stressed they are and adjusted
for who they would have to leave with - a dwarven merchant
being more attractive than leaving alone (or with an elf).
The check is made monthly.
A happy dwarf (ie with negative stress) will never emigrate.
Usage: ``emigration enable|disable``
=end]]
local args = {...}
if args[1] == "enable" then
enabled = true
elseif args[1] == "disable" then
enabled = false
end
function desireToStay(unit,method,civ_id)
-- on a percentage scale
local value = 100 - unit.status.current_soul.personality.stress_level / 5000
if method == 'merchant' or method == 'diplomat' then
if civ_id ~= unit.civ_id then value = value*2 end end
if method == 'wild' then
value = value*5 end
return value
end
function desert(u,method,civ)
u.relations.following = nil
local line = dfhack.TranslateName(dfhack.units.getVisibleName(u)) .. " has "
if method == 'merchant' then
line = line.."joined the merchants"
u.flags1.merchant = true
u.civ_id = civ
elseif method == 'diplomat' then
line = line.."followed the diplomat"
u.flags1.diplomat = true
u.civ_id = civ
else
line = line.."abandoned the settlement in search of a better life."
u.civ_id = -1
u.flags1.forest = true
u.animal.leave_countdown = 2
end
print(line)
dfhack.gui.showAnnouncement(line, COLOR_WHITE)
end
function canLeave(unit)
for _, skill in pairs(unit.status.current_soul.skills) do
if skill.rating > 14 then return false end
end
if unit.flags1.caged
or unit.race ~= df.global.ui.race_id
or unit.civ_id ~= df.global.ui.civ_id
or dfhack.units.isDead(unit)
or dfhack.units.isOpposedToLife(unit)
or unit.flags1.merchant
or unit.flags1.diplomat
or unit.flags1.chained
or dfhack.units.getNoblePositions(unit) ~= nil
or unit.military.squad_id ~= -1
or dfhack.units.isCitizen(unit)
or dfhack.units.isSane(unit)
or unit.profession ~= 103
or not dfhack.units.isDead(unit)
then return false end
return true
end
function checkForDeserters(method,civ_id)
local allUnits = df.global.world.units.active
for i=#allUnits-1,0,-1 do -- search list in reverse
local u = allUnits[i]
if canLeave(u) and math.random(100) < desireToStay(u,method,civ_id) then
desert(u,method,civ_id)
end
end
end
function checkmigrationnow()
local merchant_civ_ids = {}
local diplomat_civ_ids = {}
local allUnits = df.global.world.units.active
for i=0, #allUnits-1 do
local unit = allUnits[i]
if dfhack.units.isSane(unit)
and not dfhack.units.isDead(unit)
and not dfhack.units.isOpposedToLife(unit)
and not unit.flags1.tame
then
if unit.flags1.merchant then table.insert(merchant_civ_ids, unit.civ_id) end
if unit.flags1.diplomat then table.insert(diplomat_civ_ids, unit.civ_id) end
end
end
for _, civ_id in pairs(merchant_civ_ids) do checkForDeserters('merchant', civ_id) end
for _, civ_id in pairs(diplomat_civ_ids) do checkForDeserters('diplomat', civ_id) end
checkForDeserters('wild', -1)
end
local function event_loop()
if enabled then
checkmigrationnow()
dfhack.timeout(1, 'months', event_loop)
end
end
dfhack.onStateChange.loadEmigration = function(code)
if code==SC_MAP_LOADED then
if enabled then
print("Emigration enabled.")
event_loop()
else
print("Emigration disabled.")
end
end
end
if dfhack.isMapLoaded() then
dfhack.onStateChange.loadEmigration(SC_MAP_LOADED)
end