diff --git a/NEWS b/NEWS index fdde16e77..73c205c18 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,7 @@ DFHack future - superdwarf: work in adventure mode too - tweak stable-cursor: carries cursor location from/to Build menu. - deathcause: allow selection from the unitlist screen + - slayrace: allow targetting undeads New tweaks: - tweak military-training: speed up melee squad training up to 10x (normally 3-5x). New scripts: diff --git a/Readme.rst b/Readme.rst index afad3ef4c..150f0d488 100644 --- a/Readme.rst +++ b/Readme.rst @@ -1850,13 +1850,16 @@ slayrace ======== Kills any unit of a given race. -With no argument, lists the available races. +With no argument, lists the available races and count eligible targets. With the special argument ``him``, targets only the selected creature. +With the special argument ``undead``, targets all undeads on the map, +regardless of their 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, also set animal.vanish_countdown to 2. +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 diff --git a/scripts/slayrace.rb b/scripts/slayrace.rb index ca50020f7..9709b93fa 100644 --- a/scripts/slayrace.rb +++ b/scripts/slayrace.rb @@ -1,14 +1,17 @@ # slay all creatures of a given race # race = name of the race to eradicate, use 'him' to target only the selected creature +# use 'undead' to target all undeads race = $script_args[0] + # if the 2nd parameter is 'magma', magma rain for the targets instead of instant death magma = ($script_args[1] == 'magma') checkunit = lambda { |u| - u.body.blood_count != 0 and + (u.body.blood_count != 0 or u.body.blood_max == 0) and not u.flags1.dead and - not u.flags1.caged 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 } @@ -26,7 +29,8 @@ slayit = lambda { |u| 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 + 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 } @@ -36,17 +40,41 @@ slayit = lambda { |u| all_races = Hash.new(0) df.world.units.active.map { |u| - all_races[u.race_tg.creature_id] += 1 if checkunit[u] + if checkunit[u] + if (u.enemy.undead or + (u.curse.add_tags1.OPPOSED_TO_LIFE and not + u.curse.del_tags1.OPPOSED_TO_LIFE)) + all_races['Undead'] += 1 + else + all_races[u.race_tg.creature_id] += 1 + end + end } -if !race +case race +when nil all_races.sort_by { |race, cnt| [cnt, race] }.each{ |race, cnt| puts " #{race} #{cnt}" } -elsif race == 'him' + +when 'him' if him = df.unit_find slayit[him] else - puts "Choose target" + 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.del_tags1.OPPOSED_TO_LIFE)) and + checkunit[u] + slayit[u] + count += 1 + end + } + puts "slain #{count} undeads" + else raw_race = df.match_rawname(race, all_races.keys) raise 'invalid race' if not raw_race @@ -60,6 +88,6 @@ else count += 1 end } - puts "slain #{count} #{raw_race}" + end