Merge remote-tracking branch 'kmartin/master'

develop
Alexander Gavrilov 2012-10-12 16:02:42 +04:00
commit adfb307942
11 changed files with 116 additions and 53 deletions

@ -8,6 +8,7 @@ DFHack future
Misc improvements:
- fastdwarf: new mode using debug flags, and some internal consistency fixes.
- added a small stand-alone utility for applying and removing binary patches.
- removebadthoughts: add --dry-run option
DFHack v0.34.11-r2

@ -1662,16 +1662,18 @@ removebadthoughts
This script remove negative thoughts from your dwarves. Very useful against
tantrum spirals.
With a selected unit in 'v' mode, will clear this unit's mind, otherwise
clear all your fort's units minds.
The script can target a single creature, when used with the ``him`` argument,
or the whole fort population, with ``all``.
To show every bad thought present without actually removing them, run the
script with the ``-n`` or ``--dry-run`` argument. This can give a quick
hint on what bothers your dwarves the most.
Individual dwarf happiness may not increase right after this command is run,
but in the short term your dwarves will get much more joyful.
The thoughts are set to be very old, and the game will remove them soon when
you unpause.
With the optional ``-v`` parameter, the script will dump the negative thoughts
it removed.
Internals: the thoughts are set to be very old, so that the game remove them
quickly after you unpause.
slayrace
@ -1680,7 +1682,7 @@ Kills any unit of a given race.
With no argument, lists the available races.
With the special argument 'him', targets only the selected creature.
With the special argument ``him``, targets only the selected creature.
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

@ -352,23 +352,13 @@ module DFHack
job
end
# check item flags to see if it is suitable for use as a building material
def building_isitemfree(i)
!i.flags.in_job and
!i.flags.in_inventory and
!i.flags.removed and
!i.flags.in_building and
!i.flags.owned and
!i.flags.forbid
end
# exemple usage
def buildbed(pos=cursor)
raise 'where to ?' if pos.x < 0
item = world.items.all.find { |i|
i.kind_of?(ItemBedst) and
building_isitemfree(i)
item_isfree(i)
}
raise 'no free bed, build more !' if not item

@ -6,8 +6,12 @@ module DFHack
if what == :selected
case curview._rtti_classname
when :viewscreen_itemst
ref = curview.entry_ref[curview.cursor_pos]
ref.item_tg if ref.kind_of?(GeneralRefItem)
if ref = curview.entry_ref[curview.cursor_pos]
ref.item_tg if ref.kind_of?(GeneralRefItem)
else
# not a container
curview.item
end
when :viewscreen_storesst # z/stocks
if curview.in_group_mode == 0 and curview.in_right_list == 1
curview.items[curview.item_cursor]
@ -47,5 +51,17 @@ module DFHack
raise "what what?"
end
end
# check item flags to see if it is suitable for use as a job input material
def item_isfree(i)
!i.flags.trader and
!i.flags.in_job and
!i.flags.in_inventory and
!i.flags.removed and
!i.flags.in_building and
!i.flags.owned and
!i.flags.forbid
end
end
end

@ -240,5 +240,35 @@ module DFHack
def spawn_magma(quantity=7)
spawn_liquid(quantity, true)
end
# yield a serie of tiles until the block returns true, returns the matching tile
# the yielded tiles form a (squared) spiral centered here in the current zlevel
# eg for radius 4, yields (-4, -4), (-4, -3), .., (-4, 3),
# (-4, 4), (-3, 4), .., (4, 4), .., (4, -4), .., (-3, -4)
# then move on to radius 5
def spiral_search(maxradius=100, minradius=0, step=1)
if minradius == 0
return self if yield self
minradius += step
end
sides = [[0, 1], [1, 0], [0, -1], [-1, 0]]
(minradius..maxradius).step(step) { |r|
sides.length.times { |s|
dxr, dyr = sides[(s-1) % sides.length]
dx, dy = sides[s]
(-r...r).step(step) { |v|
t = offset(dxr*r + dx*v, dyr*r + dy*v)
return t if t and yield t
}
}
}
nil
end
# returns dx^2+dy^2+dz^2
def distance_to(ot)
(x-ot.x)**2 + (y-ot.y)**2 + (z-ot.z)**2
end
end
end

@ -189,6 +189,10 @@ module DFHack
end
def to_s ; token ; end
def ===(other)
other.mat_index == mat_index and other.mat_type == mat_type
end
end
class << self

@ -785,6 +785,7 @@ module DFHack
def isset(key)
raise unless @_memaddr
key = @_enum.int(key) if _enum
raise "unknown key #{key.inspect}" if key.kind_of?(::Symbol)
DFHack.memory_stlset_isset(@_memaddr, key)
end
alias is_set? isset
@ -792,12 +793,14 @@ module DFHack
def set(key)
raise unless @_memaddr
key = @_enum.int(key) if _enum
raise "unknown key #{key.inspect}" if key.kind_of?(::Symbol)
DFHack.memory_stlset_set(@_memaddr, key)
end
def delete(key)
raise unless @_memaddr
key = @_enum.int(key) if _enum
raise "unknown key #{key.inspect}" if key.kind_of?(::Symbol)
DFHack.memory_stlset_deletekey(@_memaddr, key)
end

@ -3498,11 +3498,11 @@ command_result start_autonestbox(color_ostream &out)
{
enable_autonestbox = true;
if (!config_autobutcher.isValid())
if (!config_autonestbox.isValid())
{
config_autonestbox = World::AddPersistentData("autonestbox/config");
if (!config_autobutcher.isValid())
if (!config_autonestbox.isValid())
{
out << "Cannot enable autonestbox without a world!" << endl;
return CR_OK;

@ -1,15 +1,13 @@
# show death cause of a creature
def display_event(e)
p e if $DEBUG
str = "#{e.victim_tg.name} died in year #{e.year}"
str << " of #{e.death_cause}" if false
str << " killed by the #{e.slayer_race_tg.name[0]} #{e.slayer_tg.name}" if e.slayer != -1
def display_death_event(e)
str = "The #{e.victim_hf_tg.race_tg.name[0]} #{e.victim_hf_tg.name} died in year #{e.year}"
str << " (cause: #{e.death_cause.to_s.downcase}),"
str << " killed by the #{e.slayer_race_tg.name[0]} #{e.slayer_hf_tg.name}" if e.slayer_hf != -1
str << " using a #{df.world.raws.itemdefs.weapons[e.weapon.item_subtype].name}" if e.weapon.item_type == :WEAPON
str << ", shot by a #{df.world.raws.itemdefs.weapons[e.weapon.bow_item_subtype].name}" if e.weapon.bow_item_type == :WEAPON
puts str + '.'
puts str.chomp(',') + '.'
end
item = df.item_find(:selected)
@ -21,14 +19,15 @@ end
if !item or !item.kind_of?(DFHack::ItemBodyComponent)
puts "Please select a corpse in the loo'k' menu"
else
hfig = item.hist_figure_id
if hfig == -1
puts "Not a historical figure, cannot find info"
hf = item.hist_figure_id
if hf == -1
# TODO try to retrieve info from the unit (u = item.unit_tg)
puts "Not a historical figure, cannot death find info"
else
events = df.world.history.events
(0...events.length).reverse_each { |i|
if events[i].kind_of?(DFHack::HistoryEventHistFigureDiedst) and events[i].victim == hfig
display_event(events[i])
if events[i].kind_of?(DFHack::HistoryEventHistFigureDiedst) and events[i].victim_hf == hf
display_death_event(events[i])
break
end
}

@ -1,27 +1,43 @@
# remove bad thoughts for the selected unit or the whole fort
# with removebadthoughts -v, dump the bad thoughts types we removed
verbose = $script_args.delete('-v')
dry_run = $script_args.delete('--dry-run') || $script_args.delete('-n')
if u = df.unit_find(:selected)
targets = [u]
else
targets = df.unit_citizens
end
$script_args << 'all' if dry_run and $script_args.empty?
seenbad = Hash.new(0)
targets.each { |u|
clear_mind = lambda { |u|
u.status.recent_events.each { |e|
next if DFHack::UnitThoughtType::Value[e.type].to_s[0, 1] != '-'
seenbad[e.type] += 1
e.age = 0x1000_0000
e.age = 0x1000_0000 unless dry_run
}
}
if verbose
seenbad.sort_by { |k, v| v }.each { |k, v| puts " #{v} #{k}" }
end
summary = lambda {
seenbad.sort_by { |thought, cnt| cnt }.each { |thought, cnt|
puts " #{thought} #{cnt}"
}
count = seenbad.values.inject(0) { |sum, cnt| sum+cnt }
puts "Removed #{count} bad thought#{'s' if count != 1}." if count > 0 and not dry_run
}
count = seenbad.values.inject(0) { |s, v| s+v }
puts "removed #{count} bad thought#{'s' if count != 1}"
case $script_args[0]
when 'him'
if u = df.unit_find
clear_mind[u]
summary[]
else
puts 'Please select a dwarf ingame'
end
when 'all'
df.unit_citizens.each { |uu|
clear_mind[uu]
}
summary[]
else
puts "Usage: removebadthoughts [--dry-run] <him|all>"
end

@ -33,12 +33,14 @@ slayit = lambda { |u|
end
}
all_races = df.world.units.active.map { |u|
u.race_tg.creature_id if checkunit[u]
}.compact.uniq.sort
all_races = Hash.new(0)
df.world.units.active.map { |u|
all_races[u.race_tg.creature_id] += 1 if checkunit[u]
}
if !race
puts all_races
all_races.sort_by { |race, cnt| [cnt, race] }.each{ |race, cnt| puts " #{race} #{cnt}" }
elsif race == 'him'
if him = df.unit_find
slayit[him]
@ -46,7 +48,7 @@ elsif race == 'him'
puts "Choose target"
end
else
raw_race = df.match_rawname(race, all_races)
raw_race = df.match_rawname(race, all_races.keys)
raise 'invalid race' if not raw_race
race_nr = df.world.raws.creatures.all.index { |cr| cr.creature_id == raw_race }