Skip to content

Commit 1ab9c17

Browse files
authored
Merge pull request #1263 from myk002/myk_dangerdanger
use new unit module property functions
2 parents a787a35 + c8bd23f commit 1ab9c17

File tree

7 files changed

+90
-118
lines changed

7 files changed

+90
-118
lines changed

agitation-rebalance.lua

+2-6
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,6 @@ local function persist_state()
106106
dfhack.persistent.saveSiteData(GLOBAL_KEY, state)
107107
end
108108

109-
local function is_agitated(unit)
110-
return unit and unit.flags4.agitated_wilderness_creature
111-
end
112-
113109
local world = df.global.world
114110
local map_features = world.features.map_features
115111
local plotinfo = df.global.plotinfo
@@ -237,7 +233,7 @@ end
237233
local function get_agitated_units()
238234
local agitators = {}
239235
for _, unit in ipairs(world.units.active) do
240-
if is_unkilled(unit) and is_agitated(unit) then
236+
if is_unkilled(unit) and dfhack.units.isAgitated(unit) then
241237
table.insert(agitators, unit)
242238
end
243239
end
@@ -250,7 +246,7 @@ local function check_new_unit(unit_id)
250246
if new_unit_min_frame_counter >= world.frame_counter then return end
251247
local unit = df.unit.find(unit_id)
252248
if not unit or not is_unkilled(unit) then return end
253-
if state.features.surface and is_agitated(unit) then
249+
if state.features.surface and dfhack.units.isAgitated(unit) then
254250
on_surface_attack()
255251
return
256252
end

changelog.txt

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ Template for new versions:
3535
- `timestream`: ensure child growth events (e.g. becoming an adult) are not skipped over
3636

3737
## Misc Improvements
38+
- `gui/sitemap`: show whether a unit is friendly, hostile, or wildlife
39+
- `gui/sitemap`: show whether a unit is caged
3840

3941
## Removed
4042

docs/exterminate.rst

+16-14
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,15 @@ exterminate
55
:summary: Kill things.
66
:tags: fort armok units
77

8-
Kills any unit, or all undead, or all units of a given race. You can target any
9-
unit on a revealed tile of the map, including hidden ambushers, but caged or
10-
chained creatures cannot be killed with this tool.
8+
Kills any individual unit, or all undead, or all units of a given race. Caged
9+
and chained creatures are ignored.
1110

1211
Usage
1312
-----
1413

1514
::
1615

17-
exterminate
16+
exterminate [list]
1817
exterminate this [<options>]
1918
exterminate undead [<options>]
2019
exterminate all[:<caste>] [<options>]
@@ -25,10 +24,10 @@ Race and caste names are case insensitive.
2524
Examples
2625
--------
2726

28-
``exterminate this``
29-
Kill the selected unit.
3027
``exterminate``
3128
List the targets on your map.
29+
``exterminate this``
30+
Kill the selected unit.
3231
``exterminate BIRD_RAVEN:MALE``
3332
Kill the ravens flying around the map (but only the male ones).
3433
``exterminate goblin --method magma --only-visible``
@@ -65,18 +64,21 @@ Methods
6564
:drown: Drown the unit in water.
6665
:magma: Boil the unit in magma (not recommended for magma-safe creatures).
6766
:butcher: Will mark the units for butchering instead of killing them. This is
68-
more useful for pets than armed enemies.
69-
:knockout: Will put units into an unconscious state for 30k ticks (about a month).
70-
:traumatize: Traumatizes all units, forcing them to stare off into space (catatonic state).
67+
useful for pets and not useful for armed enemies.
68+
:knockout: Will put units into an unconscious state for 30k ticks (about a
69+
month in fort mode).
70+
:traumatize: Traumatizes units, forcing them to stare off into space (catatonic
71+
state).
7172

7273
Technical details
7374
-----------------
7475

75-
This tool kills by setting a unit's ``blood_count`` to 0, which means
76-
immediate death at the next game tick. For creatures where this is not enough,
77-
such as vampires, it also sets ``animal.vanish_countdown``, allowing the unit
78-
to vanish in a puff of smoke if the blood loss doesn't kill them.
76+
For the ``instant`` method, this tool kills by setting a unit's ``blood_count``
77+
to 0, which means immediate death at the next game tick. For creatures where
78+
this is not enough, such as vampires, it also sets ``animal.vanish_countdown``,
79+
allowing the unit to vanish in a puff of smoke if the blood loss doesn't kill
80+
them.
7981

8082
If the method of choice involves liquids, the tile is filled with a liquid
8183
level of 7 every tick. If the target unit moves, the liquid moves along with
82-
it, leaving the vacated tiles clean.
84+
it, leaving the vacated tiles clean (though possibly scorched).

emigration.lua

+7-10
Original file line numberDiff line numberDiff line change
@@ -153,16 +153,13 @@ function canLeave(unit)
153153
return false
154154
end
155155

156-
return dfhack.units.isCitizen(unit) and
157-
dfhack.units.isActive(unit) and
158-
not dfhack.units.isOpposedToLife(unit) and
159-
not unit.flags1.merchant and
160-
not unit.flags1.diplomat and
161-
not unit.flags1.chained and
162-
dfhack.units.getNoblePositions(unit) == nil and
163-
unit.military.squad_id == -1 and
164-
not dfhack.units.isBaby(unit) and
165-
not dfhack.units.isChild(unit)
156+
return dfhack.units.isActive(unit) and
157+
dfhack.units.isCitizen(unit) and
158+
not dfhack.units.getNoblePositions(unit) and
159+
not unit.flags1.chained and
160+
unit.military.squad_id == -1 and
161+
not dfhack.units.isBaby(unit) and
162+
not dfhack.units.isChild(unit)
166163
end
167164

168165
function checkForDeserters(method,civ_id)

exterminate.lua

+30-64
Original file line numberDiff line numberDiff line change
@@ -14,32 +14,24 @@ local function spawnLiquid(position, liquid_level, liquid_type, update_liquids)
1414
map_block.flags.update_liquid_twice = update_liquids
1515
end
1616

17-
local function checkUnit(unit)
18-
return (unit.body.blood_count ~= 0 or unit.body.blood_max == 0) and
19-
not unit.flags1.inactive and
20-
not unit.flags1.caged and
21-
not unit.flags1.chained
22-
end
23-
24-
local function isUnitFriendly(unit)
25-
if dfhack.units.isDanger(unit) then
17+
local function checkUnit(opts, unit)
18+
if not dfhack.units.isActive(unit) or
19+
(unit.body.blood_max ~= 0 and unit.body.blood_count == 0) or
20+
unit.flags1.caged or
21+
unit.flags1.chained
22+
then
2623
return false
2724
end
28-
local adv = dfhack.world.getAdventurer()
29-
if adv then
30-
if adv == unit or
31-
unit.relationship_ids.GroupLeader == adv.id or
32-
unit.relationship_ids.PetOwner == adv.id
33-
then
34-
return true
35-
end
25+
if opts.only_visible and not dfhack.units.isVisible(unit) then
26+
return false
3627
end
37-
38-
return dfhack.units.isOwnCiv(unit) or
39-
dfhack.units.isOwnGroup(unit) or
40-
dfhack.units.isVisiting(unit) or
41-
dfhack.units.isTame(unit) or
42-
dfhack.units.isDomesticated(unit)
28+
if not opts.include_friendly and not dfhack.units.isDanger(unit) and not dfhack.units.isWildlife(unit) then
29+
return false
30+
end
31+
if opts.selected_caste and opts.selected_caste ~= df.creature_raw.find(unit.race).caste[unit.caste].caste_id then
32+
return false
33+
end
34+
return true
4335
end
4436

4537
killMethod = {
@@ -138,26 +130,17 @@ local function getRaceCastes(race_id)
138130
return unit_castes
139131
end
140132

141-
local function getMapRaces(only_visible, include_friendly)
133+
local function getMapRaces(opts)
142134
local map_races = {}
143135
for _, unit in pairs(df.global.world.units.active) do
144-
if only_visible and not dfhack.units.isVisible(unit) then
145-
goto skipunit
146-
end
147-
if not include_friendly and isUnitFriendly(unit) then
148-
goto skipunit
149-
end
150-
if dfhack.units.isActive(unit) and checkUnit(unit) then
151-
local unit_race_name = dfhack.units.isUndead(unit) and "UNDEAD" or df.creature_raw.find(unit.race).creature_id
152-
153-
local race = ensure_key(map_races, unit_race_name)
154-
race.id = unit.race
155-
race.name = unit_race_name
156-
race.count = (race.count or 0) + 1
157-
end
158-
:: skipunit ::
136+
if not checkUnit(opts, unit) then goto continue end
137+
local unit_race_name = dfhack.units.isUndead(unit) and "UNDEAD" or df.creature_raw.find(unit.race).creature_id
138+
local race = ensure_key(map_races, unit_race_name)
139+
race.id = unit.race
140+
race.name = unit_race_name
141+
race.count = (race.count or 0) + 1
142+
::continue::
159143
end
160-
161144
return map_races
162145
end
163146

@@ -200,9 +183,9 @@ if positionals[1] == "this" then
200183
return
201184
end
202185

203-
local map_races = getMapRaces(options.only_visible, options.include_friendly)
186+
local map_races = getMapRaces(options)
204187

205-
if not positionals[1] then
188+
if not positionals[1] or positionals[1] == 'list' then
206189
local sorted_races = {}
207190
for race, value in pairs(map_races) do
208191
table.insert(sorted_races, { name = race, count = value.count })
@@ -224,28 +207,19 @@ if race_name:lower() == 'undead' then
224207
qerror("No undead found on the map.")
225208
end
226209
for _, unit in pairs(df.global.world.units.active) do
227-
if dfhack.units.isUndead(unit) and checkUnit(unit) then
210+
if dfhack.units.isUndead(unit) and checkUnit(options, unit) then
228211
killUnit(unit, options.method)
229212
count = count + 1
230213
end
231214
end
232215
elseif positionals[1]:split(':')[1] == "all" then
233-
local selected_caste = positionals[1]:split(':')[2]
216+
options.selected_caste = positionals[1]:split(':')[2]
234217

235218
for _, unit in ipairs(df.global.world.units.active) do
236219
if options.limit > 0 and count >= options.limit then
237220
break
238221
end
239-
if not checkUnit(unit) then
240-
goto skipunit
241-
end
242-
if options.only_visible and not dfhack.units.isVisible(unit) then
243-
goto skipunit
244-
end
245-
if not options.include_friendly and isUnitFriendly(unit) then
246-
goto skipunit
247-
end
248-
if selected_caste and selected_caste ~= df.creature_raw.find(unit.race).caste[unit.caste].caste_id then
222+
if not checkUnit(options, unit) then
249223
goto skipunit
250224
end
251225

@@ -285,21 +259,13 @@ else
285259
end
286260

287261
target = selected_race
262+
options.selected_caste = selected_caste
288263

289264
for _, unit in pairs(df.global.world.units.active) do
290265
if options.limit > 0 and count >= options.limit then
291266
break
292267
end
293-
if not checkUnit(unit) then
294-
goto skipunit
295-
end
296-
if options.only_visible and not dfhack.units.isVisible(unit) then
297-
goto skipunit
298-
end
299-
if not options.include_friendly and isUnitFriendly(unit) then
300-
goto skipunit
301-
end
302-
if selected_caste and selected_caste ~= df.creature_raw.find(unit.race).caste[unit.caste].caste_id then
268+
if not checkUnit(options, unit) then
303269
goto skipunit
304270
end
305271

gui/sitemap.lua

+22-1
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,27 @@ local function zoom_to_next_zone(_, choice)
9999
data.next_idx = data.next_idx % #data.zones + 1
100100
end
101101

102+
local function get_unit_disposition_and_pen(unit)
103+
local prefix = unit.flags1.caged and 'caged ' or ''
104+
if dfhack.units.isDanger(unit) then
105+
return prefix..'hostile', COLOR_LIGHTRED
106+
end
107+
if not dfhack.units.isFortControlled(unit) and dfhack.units.isWildlife(unit) then
108+
return prefix..'wildlife', COLOR_GREEN
109+
end
110+
return prefix..'friendly', COLOR_LIGHTGREEN
111+
end
112+
113+
local function get_unit_choice_text(unit)
114+
local disposition, disposition_pen = get_unit_disposition_and_pen(unit)
115+
return {
116+
dfhack.units.getReadableName(unit),
117+
' (',
118+
{text=disposition, pen=disposition_pen},
119+
')',
120+
}
121+
end
122+
102123
local function get_unit_choices()
103124
local is_fort = dfhack.world.isFortressMode()
104125
local choices = {}
@@ -110,7 +131,7 @@ local function get_unit_choices()
110131
goto continue
111132
end
112133
table.insert(choices, {
113-
text=dfhack.units.getReadableName(unit),
134+
text=get_unit_choice_text(unit),
114135
data={
115136
unit_id=unit.id,
116137
},

0 commit comments

Comments
 (0)