forked from DFHack/scripts
-
Notifications
You must be signed in to change notification settings - Fork 4
/
exterminate.rb
200 lines (166 loc) · 5.96 KB
/
exterminate.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# exterminate creatures
=begin
exterminate
===========
Kills any unit of a given race.
With no argument, lists the available races and count eligible targets.
With the special argument ``this``, targets only the selected creature.
Alternatively, ``him``, ``her``, ``it``, ``target``, and ``selected``
do the same thing.
With the special argument ``undead``, targets all undeads on the map,
regardless of their race.
When specifying a race, a caste can be specified to further restrict the
targeting. To do that, append and colon and the caste name after the race.
Any non-dead non-caged unit of the specified race gets its ``blood_count``
set to 0, which means immediate death at the next game tick. For creatures
such as vampires, it also sets animal.vanish_countdown to 2.
An alternate mode is selected by adding a 2nd argument to the command,
``magma``. In this case, a column of 7/7 magma is generated on top of the
targets until they die (Warning: do not call on magma-safe creatures. Also,
using this mode on birds is not recommended.) The final alternate mode
is ``butcher``, which marks them for butchering but does not kill.
Will target any unit on a revealed tile of the map, including ambushers,
but ignore caged/chained creatures.
Ex::
exterminate gob
exterminate gob:male
exterminate gob:enemy
To kill a single creature, select the unit with the 'v' cursor and::
exterminate this
To purify all elves on the map with fire (may have side-effects)::
exterminate elve magma
=end
race = $script_args[0]
# if the 2nd parameter is 'magma', magma rain for the targets instead of instant death
# if it is 'butcher' mark all units for butchering (wont work with hostiles)
kill_by = $script_args[1]
case kill_by
when 'magma'
slain = 'burning'
when 'slaughter', 'butcher'
slain = 'marked for butcher'
when nil
slain = 'slain'
else
race = 'help'
end
checkunit = lambda { |u|
(u.body.blood_count != 0 or u.body.blood_max == 0) and
not u.flags1.inactive and
not u.flags1.caged and not u.flags1.chained and
#not u.flags1.hidden_in_ambush and
not df.map_designation_at(u).hidden
}
slayit = lambda { |u|
case kill_by
when 'magma'
# it's getting hot around here
# !!WARNING!! do not call on a magma-safe creature
ouh = df.onupdate_register("exterminate ensure #{u.id}", 1) {
if u.flags2.killed
df.onupdate_unregister(ouh)
else
x, y, z = u.pos.x, u.pos.y, u.pos.z
z += 1 while tile = df.map_tile_at(x, y, z+1) and
tile.shape_passableflow and tile.shape_passablelow
df.map_tile_at(x, y, z).spawn_magma(7)
end
}
when 'butcher', 'slaughter'
# mark for slaughter at butcher's shop
u.flags2.slaughter = true
else
# just make them drop dead
u.body.blood_count = 0
# some races dont mind having no blood, ensure they are still taken care of.
u.animal.vanish_countdown = 2
end
}
all_races = Hash.new(0)
df.world.units.active.map { |u|
if checkunit[u]
if (u.enemy.undead or
(u.curse.add_tags1.OPPOSED_TO_LIFE and not
u.curse.rem_tags1.OPPOSED_TO_LIFE))
all_races['Undead'] += 1
else
all_races[u.race_tg.creature_id] += 1
end
end
}
case race
when nil
all_races.sort_by { |race, cnt| [cnt, race] }.each{ |race, cnt| puts " #{race} #{cnt}" }
when 'help', '?'
puts <<EOS
Kills all creatures of a given race.
You may add a 'caste' to the race to kill all males, females, or a special case: enemy.
With no argument, lists possible targets with their head count.
With the special argument 'this', kill only the currently selected creature.
Alternatively, 'him', 'her', 'it', 'target', and 'selected' do the same thing.
With the special argument 'undead', kill all undead creatures/thralls.
The targets will bleed out on the next game tick, or if they are immune to that, will vanish in a puff of smoke.
The special final argument 'magma' will make magma rain on the targets instead.
The special final argument 'butcher' will mark the targets for butchering instead.
Ex: exterminate gob
exterminate gob:male
exterminate gob:enemy
exterminate elve magma
exterminate him
exterminate pig butcher
EOS
when 'him', 'her', 'it', 'that', 'this', 'selected', 'target'
if him = df.unit_find
slayit[him]
else
puts "Select a target ingame"
end
when /^undead/i
count = 0
df.world.units.active.each { |u|
if (u.enemy.undead or
(u.curse.add_tags1.OPPOSED_TO_LIFE and not
u.curse.rem_tags1.OPPOSED_TO_LIFE)) and
checkunit[u]
slayit[u]
count += 1
end
}
puts "#{slain} #{count} undeads"
else
if race.index(':')
race, caste = race.split(':')
end
raw_race = df.match_rawname(race, all_races.keys)
if not raw_race
puts "Invalid race, use one of #{all_races.keys.sort.join(' ')}"
throw :script_finished
end
race_nr = df.world.raws.creatures.all.index { |cr| cr.creature_id == raw_race }
if caste == "enemy"
caste_nr = true
raw_caste = "enemy"
elsif caste
all_castes = df.world.raws.creatures.all[race_nr].caste.map { |c| c.caste_id }
raw_caste = df.match_rawname(caste, all_castes)
if not raw_caste
puts "Invalid caste, use one of #{all_castes.sort.join(' ')} enemy"
throw :script_finished
end
caste_nr = all_castes.index(raw_caste)
else
caste_nr = false
end
count = 0
df.world.units.active.each do |u|
if u.race == race_nr and checkunit[u]
if caste_nr
next if caste == "enemy" && !df.unit_ishostile(u)
next if caste != "enemy" && u.caste != caste_nr
end
slayit[u]
count += 1
end
end
puts "#{slain} #{count} #{raw_caste} #{raw_race}"
end