11-- Allow stressed dwarves to emigrate from the fortress
22-- For 34.11 by IndigoFenix; update and cleanup by PeridexisErrant
33-- old version: http://dffd.bay12games.com/file.php?id=8404
4- --[====[
5- emigration
6- ==========
7- Allows dwarves to emigrate from the fortress when stressed,
8- in proportion to how badly stressed they are and adjusted
9- for who they would have to leave with - a dwarven merchant
10- being more attractive than leaving alone (or with an elf).
11- The check is made monthly.
4+ -- @module = true
5+ -- @enable = true
126
13- A happy dwarf (ie with negative stress) will never emigrate.
7+ local json = require (' json' )
8+ local persist = require (' persist-table' )
149
15- Usage::
16-
17- emigration enable|disable
18- ]====]
10+ local GLOBAL_KEY = ' emigration' -- used for state change hooks and persistence
1911
2012enabled = enabled or false
2113
22- local args = {... }
23- if args [1 ] == " enable" then
24- enabled = true
25- elseif args [1 ] == " disable" then
26- enabled = false
14+ function isEnabled ()
15+ return enabled
16+ end
17+
18+ local function persist_state ()
19+ persist .GlobalTable [GLOBAL_KEY ] = json .encode ({enabled = enabled })
2720end
2821
2922function desireToStay (unit ,method ,civ_id )
3023 -- on a percentage scale
3124 local value = 100 - unit .status .current_soul .personality .stress / 5000
32- if method == ' merchant' or method == ' diplomat ' then
25+ if method == ' merchant' then
3326 if civ_id ~= unit .civ_id then value = value * 2 end end
3427 if method == ' wild' then
3528 value = value * 5 end
@@ -50,42 +43,40 @@ function desert(u,method,civ)
5043 u .flags2 .visitor = true
5144 u .animal .leave_countdown = 2
5245 end
53-
5446 local hf_id = u .hist_figure_id
5547 local hf = df .historical_figure .find (u .hist_figure_id )
56- local fort_ent = df .global .plotinfo .main .fortress_entity
48+ local fort_ent = df .global .ui .main .fortress_entity
5749 local civ_ent = df .historical_entity .find (hf .civ_id )
58-
5950 local newent_id = - 1
6051 local newsite_id = - 1
61-
52+
6253 -- free owned rooms
6354 for i = # u .owned_buildings - 1 , 0 , - 1 do
6455 local temp_bld = df .building .find (u .owned_buildings [i ].id )
6556 dfhack .buildings .setOwner (temp_bld , nil )
6657 end
67-
58+
6859 -- erase the unit from the fortress entity
6960 for k ,v in ipairs (fort_ent .histfig_ids ) do
7061 if v == hf_id then
71- df .global .plotinfo .main .fortress_entity .histfig_ids :erase (k )
62+ df .global .ui .main .fortress_entity .histfig_ids :erase (k )
7263 break
7364 end
7465 end
7566 for k ,v in ipairs (fort_ent .hist_figures ) do
7667 if v .id == hf_id then
77- df .global .plotinfo .main .fortress_entity .hist_figures :erase (k )
68+ df .global .ui .main .fortress_entity .hist_figures :erase (k )
7869 break
7970 end
8071 end
8172 for k ,v in ipairs (fort_ent .nemesis ) do
8273 if v .figure .id == hf_id then
83- df .global .plotinfo .main .fortress_entity .nemesis :erase (k )
84- df .global .plotinfo .main .fortress_entity .nemesis_ids :erase (k )
74+ df .global .ui .main .fortress_entity .nemesis :erase (k )
75+ df .global .ui .main .fortress_entity .nemesis_ids :erase (k )
8576 break
8677 end
8778 end
88-
79+
8980 -- remove the old entity link and create new one to indicate former membership
9081 hf .entity_links :insert (" #" , {new = df .histfig_entity_link_former_memberst , entity_id = fort_ent .id , link_strength = 100 })
9182 for k ,v in ipairs (hf .entity_links ) do
@@ -94,15 +85,15 @@ function desert(u,method,civ)
9485 break
9586 end
9687 end
97-
88+
9889 -- try to find a new entity for the unit to join
9990 for k ,v in ipairs (civ_ent .entity_links ) do
10091 if v .type == df .entity_entity_link_type .CHILD and v .target ~= fort_ent .id then
10192 newent_id = v .target
10293 break
10394 end
10495 end
105-
96+
10697 if newent_id > - 1 then
10798 hf .entity_links :insert (" #" , {new = df .histfig_entity_link_memberst , entity_id = newent_id , link_strength = 100 })
10899
@@ -113,11 +104,9 @@ function desert(u,method,civ)
113104 break
114105 end
115106 end
116-
117107 local newent = df .historical_entity .find (newent_id )
118108 newent .histfig_ids :insert (' #' , hf_id )
119109 newent .hist_figures :insert (' #' , hf )
120-
121110 local hf_event_id = df .global .hist_event_next_id
122111 df .global .hist_event_next_id = df .global .hist_event_next_id + 1
123112 df .global .world .history .events :insert (" #" , {new = df .history_event_add_hf_entity_linkst , year = df .global .cur_year , seconds = df .global .cur_year_tick , id = hf_event_id , civ = newent_id , histfig = hf_id , link_type = 0 })
@@ -127,7 +116,6 @@ function desert(u,method,civ)
127116 df .global .world .history .events :insert (" #" , {new = df .history_event_change_hf_statest , year = df .global .cur_year , seconds = df .global .cur_year_tick , id = hf_event_id , hfid = hf_id , state = 1 , reason = - 1 , site = newsite_id })
128117 end
129118 end
130-
131119 print (line )
132120 dfhack .gui .showAnnouncement (line , COLOR_WHITE )
133121end
@@ -175,9 +163,10 @@ function checkmigrationnow()
175163 end
176164
177165 if # merchant_civ_ids == 0 then
178- checkForDeserters (' wild' , df .global .plotinfo .main .fortress_entity .entity_links [0 ].target )
166+ checkForDeserters (' wild' , df .global .ui .main .fortress_entity .entity_links [0 ].target )
167+ else
168+ for _ , civ_id in pairs (merchant_civ_ids ) do checkForDeserters (' merchant' , civ_id ) end
179169 end
180- for _ , civ_id in pairs (merchant_civ_ids ) do checkForDeserters (' merchant' , civ_id ) end
181170end
182171
183172local function event_loop ()
@@ -187,17 +176,42 @@ local function event_loop()
187176 end
188177end
189178
190- dfhack .onStateChange . loadEmigration = function (code )
191- if code == SC_MAP_LOADED then
192- if enabled then
193- print ( " Emigration enabled. " )
194- event_loop ()
195- else
196- print ( " Emigration disabled. " )
197- end
179+ dfhack .onStateChange [ GLOBAL_KEY ] = function (sc )
180+ if sc == SC_MAP_UNLOADED then
181+ enabled = false
182+ return
183+ end
184+
185+ if sc ~= SC_MAP_LOADED or df . global . gamemode ~= df . game_mode . DWARF then
186+ return
198187 end
188+
189+ local persisted_data = json .decode (persist .GlobalTable [GLOBAL_KEY ] or ' ' )
190+ enabled = (persisted_data or {enabled = false })[' enabled' ]
191+ event_loop ()
192+ end
193+
194+ if dfhack_flags .module then
195+ return
196+ end
197+
198+ if df .global .gamemode ~= df .game_mode .DWARF or not dfhack .isMapLoaded () then
199+ dfhack .printerr (' emigration needs a loaded fortress map to work' )
200+ return
199201end
200202
201- if dfhack .isMapLoaded () then
202- dfhack .onStateChange .loadEmigration (SC_MAP_LOADED )
203+ local args = {... }
204+ if dfhack_flags and dfhack_flags .enable then
205+ args = {dfhack_flags .enable_state and ' enable' or ' disable' }
203206end
207+
208+ if args [1 ] == " enable" then
209+ enabled = true
210+ elseif args [1 ] == " disable" then
211+ enabled = false
212+ else
213+ return
214+ end
215+
216+ event_loop ()
217+ persist_state ()
0 commit comments