develop
commit
df6355a092
@ -1,176 +1,176 @@
|
|||||||
class AutoFarm
|
class AutoFarm
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
@thresholds = Hash.new(50)
|
@thresholds = Hash.new(50)
|
||||||
@lastcounts = Hash.new(0)
|
@lastcounts = Hash.new(0)
|
||||||
end
|
end
|
||||||
|
|
||||||
def setthreshold(id, v)
|
def setthreshold(id, v)
|
||||||
list = df.world.raws.plants.all.find_all { |plt| plt.flags[:SEED] }.map { |plt| plt.id }
|
list = df.world.raws.plants.all.find_all { |plt| plt.flags[:SEED] }.map { |plt| plt.id }
|
||||||
if tok = df.match_rawname(id, list)
|
if tok = df.match_rawname(id, list)
|
||||||
@thresholds[tok] = v.to_i
|
@thresholds[tok] = v.to_i
|
||||||
else
|
else
|
||||||
puts "No plant with id #{id}, try one of " +
|
puts "No plant with id #{id}, try one of " +
|
||||||
list.map { |w| w =~ /[^\w]/ ? w.inspect : w }.sort.join(' ')
|
list.map { |w| w =~ /[^\w]/ ? w.inspect : w }.sort.join(' ')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def setdefault(v)
|
def setdefault(v)
|
||||||
@thresholds.default = v.to_i
|
@thresholds.default = v.to_i
|
||||||
end
|
end
|
||||||
|
|
||||||
def is_plantable(plant)
|
def is_plantable(plant)
|
||||||
has_seed = plant.flags[:SEED]
|
has_seed = plant.flags[:SEED]
|
||||||
season = df.cur_season
|
season = df.cur_season
|
||||||
harvest = df.cur_season_tick + plant.growdur * 10
|
harvest = df.cur_season_tick + plant.growdur * 10
|
||||||
will_finish = harvest < 10080
|
will_finish = harvest < 10080
|
||||||
can_plant = has_seed && plant.flags[season]
|
can_plant = has_seed && plant.flags[season]
|
||||||
can_plant = can_plant && (will_finish || plant.flags[(season+1)%4])
|
can_plant = can_plant && (will_finish || plant.flags[(season+1)%4])
|
||||||
can_plant
|
can_plant
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_plantable_plants
|
def find_plantable_plants
|
||||||
plantable = {}
|
plantable = {}
|
||||||
counts = Hash.new(0)
|
counts = Hash.new(0)
|
||||||
|
|
||||||
df.world.items.other[:SEEDS].each { |i|
|
df.world.items.other[:SEEDS].each { |i|
|
||||||
if (!i.flags.dump && !i.flags.forbid && !i.flags.garbage_collect &&
|
if (!i.flags.dump && !i.flags.forbid && !i.flags.garbage_collect &&
|
||||||
!i.flags.hostile && !i.flags.on_fire && !i.flags.rotten &&
|
!i.flags.hostile && !i.flags.on_fire && !i.flags.rotten &&
|
||||||
!i.flags.trader && !i.flags.in_building && !i.flags.construction &&
|
!i.flags.trader && !i.flags.in_building && !i.flags.construction &&
|
||||||
!i.flags.artifact)
|
!i.flags.artifact)
|
||||||
counts[i.mat_index] += i.stack_size
|
counts[i.mat_index] += i.stack_size
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
counts.keys.each { |i|
|
counts.keys.each { |i|
|
||||||
if df.ui.tasks.known_plants[i]
|
if df.ui.tasks.known_plants[i]
|
||||||
plant = df.world.raws.plants.all[i]
|
plant = df.world.raws.plants.all[i]
|
||||||
if is_plantable(plant)
|
if is_plantable(plant)
|
||||||
plantable[i] = :Surface if (plant.underground_depth_min == 0 || plant.underground_depth_max == 0)
|
plantable[i] = :Surface if (plant.underground_depth_min == 0 || plant.underground_depth_max == 0)
|
||||||
plantable[i] = :Underground if (plant.underground_depth_min > 0 || plant.underground_depth_max > 0)
|
plantable[i] = :Underground if (plant.underground_depth_min > 0 || plant.underground_depth_max > 0)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
return plantable
|
return plantable
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_farms(plants, farms)
|
def set_farms(plants, farms)
|
||||||
return if farms.length == 0
|
return if farms.length == 0
|
||||||
if plants.length == 0
|
if plants.length == 0
|
||||||
plants = [-1]
|
plants = [-1]
|
||||||
end
|
end
|
||||||
|
|
||||||
season = df.cur_season
|
season = df.cur_season
|
||||||
|
|
||||||
farms.each_with_index { |f, idx|
|
farms.each_with_index { |f, idx|
|
||||||
f.plant_id[season] = plants[idx % plants.length]
|
f.plant_id[season] = plants[idx % plants.length]
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def process
|
def process
|
||||||
plantable = find_plantable_plants
|
plantable = find_plantable_plants
|
||||||
@lastcounts = Hash.new(0)
|
@lastcounts = Hash.new(0)
|
||||||
|
|
||||||
df.world.items.other[:PLANT].each { |i|
|
df.world.items.other[:PLANT].each { |i|
|
||||||
if (!i.flags.dump && !i.flags.forbid && !i.flags.garbage_collect &&
|
if (!i.flags.dump && !i.flags.forbid && !i.flags.garbage_collect &&
|
||||||
!i.flags.hostile && !i.flags.on_fire && !i.flags.rotten &&
|
!i.flags.hostile && !i.flags.on_fire && !i.flags.rotten &&
|
||||||
!i.flags.trader && !i.flags.in_building && !i.flags.construction &&
|
!i.flags.trader && !i.flags.in_building && !i.flags.construction &&
|
||||||
!i.flags.artifact && plantable.has_key?(i.mat_index))
|
!i.flags.artifact && plantable.has_key?(i.mat_index))
|
||||||
id = df.world.raws.plants.all[i.mat_index].id
|
id = df.world.raws.plants.all[i.mat_index].id
|
||||||
@lastcounts[id] += i.stack_size
|
@lastcounts[id] += i.stack_size
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
return unless @running
|
return unless @running
|
||||||
|
|
||||||
plants_s = []
|
plants_s = []
|
||||||
plants_u = []
|
plants_u = []
|
||||||
|
|
||||||
plantable.each_key { |k|
|
plantable.each_key { |k|
|
||||||
plant = df.world.raws.plants.all[k]
|
plant = df.world.raws.plants.all[k]
|
||||||
if (@lastcounts[plant.id] < @thresholds[plant.id])
|
if (@lastcounts[plant.id] < @thresholds[plant.id])
|
||||||
plants_s.push(k) if plantable[k] == :Surface
|
plants_s.push(k) if plantable[k] == :Surface
|
||||||
plants_u.push(k) if plantable[k] == :Underground
|
plants_u.push(k) if plantable[k] == :Underground
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
farms_s = []
|
farms_s = []
|
||||||
farms_u = []
|
farms_u = []
|
||||||
df.world.buildings.other[:FARM_PLOT].each { |f|
|
df.world.buildings.other[:FARM_PLOT].each { |f|
|
||||||
if (f.flags.exists)
|
if (f.flags.exists)
|
||||||
underground = df.map_designation_at(f.centerx,f.centery,f.z).subterranean
|
underground = df.map_designation_at(f.centerx,f.centery,f.z).subterranean
|
||||||
farms_s.push(f) unless underground
|
farms_s.push(f) unless underground
|
||||||
farms_u.push(f) if underground
|
farms_u.push(f) if underground
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
set_farms(plants_s, farms_s)
|
set_farms(plants_s, farms_s)
|
||||||
set_farms(plants_u, farms_u)
|
set_farms(plants_u, farms_u)
|
||||||
end
|
end
|
||||||
|
|
||||||
def start
|
def start
|
||||||
return if @running
|
return if @running
|
||||||
@onupdate = df.onupdate_register('autofarm', 1200) { process }
|
@onupdate = df.onupdate_register('autofarm', 1200) { process }
|
||||||
@running = true
|
@running = true
|
||||||
end
|
end
|
||||||
|
|
||||||
def stop
|
def stop
|
||||||
df.onupdate_unregister(@onupdate)
|
df.onupdate_unregister(@onupdate)
|
||||||
@running = false
|
@running = false
|
||||||
end
|
end
|
||||||
|
|
||||||
def status
|
def status
|
||||||
stat = @running ? "Running." : "Stopped."
|
stat = @running ? "Running." : "Stopped."
|
||||||
@lastcounts.each { |k,v|
|
@lastcounts.each { |k,v|
|
||||||
stat << "\n#{k} limit #{@thresholds.fetch(k, 'default')} current #{v}"
|
stat << "\n#{k} limit #{@thresholds.fetch(k, 'default')} current #{v}"
|
||||||
}
|
}
|
||||||
@thresholds.each { |k,v|
|
@thresholds.each { |k,v|
|
||||||
stat << "\n#{k} limit #{v} current 0" unless @lastcounts.has_key?(k)
|
stat << "\n#{k} limit #{v} current 0" unless @lastcounts.has_key?(k)
|
||||||
}
|
}
|
||||||
stat << "\nDefault: #{@thresholds.default}"
|
stat << "\nDefault: #{@thresholds.default}"
|
||||||
stat
|
stat
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
$AutoFarm ||= AutoFarm.new
|
$AutoFarm ||= AutoFarm.new
|
||||||
|
|
||||||
case $script_args[0]
|
case $script_args[0]
|
||||||
when 'start'
|
when 'start', 'enable'
|
||||||
$AutoFarm.start
|
$AutoFarm.start
|
||||||
puts $AutoFarm.status
|
puts $AutoFarm.status
|
||||||
|
|
||||||
when 'end', 'stop', 'disable'
|
when 'end', 'stop', 'disable'
|
||||||
$AutoFarm.stop
|
$AutoFarm.stop
|
||||||
puts 'Stopped.'
|
puts 'Stopped.'
|
||||||
|
|
||||||
when 'default'
|
when 'default'
|
||||||
$AutoFarm.setdefault($script_args[1])
|
$AutoFarm.setdefault($script_args[1])
|
||||||
|
|
||||||
when 'threshold'
|
when 'threshold'
|
||||||
t = $script_args[1]
|
t = $script_args[1]
|
||||||
$script_args[2..-1].each {|i|
|
$script_args[2..-1].each {|i|
|
||||||
$AutoFarm.setthreshold(i, t)
|
$AutoFarm.setthreshold(i, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
when 'delete'
|
when 'delete'
|
||||||
$AutoFarm.stop
|
$AutoFarm.stop
|
||||||
$AutoFarm = nil
|
$AutoFarm = nil
|
||||||
|
|
||||||
when 'help', '?'
|
when 'help', '?'
|
||||||
puts <<EOS
|
puts <<EOS
|
||||||
Automatically handle crop selection in farm plots based on current plant stocks.
|
Automatically handle crop selection in farm plots based on current plant stocks.
|
||||||
Selects a crop for planting if current stock is below a threshold.
|
Selects a crop for planting if current stock is below a threshold.
|
||||||
Selected crops are dispatched on all farmplots.
|
Selected crops are dispatched on all farmplots.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
autofarm start
|
autofarm start
|
||||||
autofarm default 30
|
autofarm default 30
|
||||||
autofarm threshold 150 helmet_plump tail_pig
|
autofarm threshold 150 helmet_plump tail_pig
|
||||||
EOS
|
EOS
|
||||||
|
|
||||||
else
|
else
|
||||||
$AutoFarm.process
|
$AutoFarm.process
|
||||||
puts $AutoFarm.status
|
puts $AutoFarm.status
|
||||||
end
|
end
|
||||||
|
@ -1,58 +1,58 @@
|
|||||||
class AutoUnsuspend
|
class AutoUnsuspend
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
end
|
end
|
||||||
|
|
||||||
def process
|
def process
|
||||||
return false unless @running
|
return false unless @running
|
||||||
joblist = df.world.job_list.next
|
joblist = df.world.job_list.next
|
||||||
count = 0
|
count = 0
|
||||||
|
|
||||||
while joblist
|
while joblist
|
||||||
job = joblist.item
|
job = joblist.item
|
||||||
joblist = joblist.next
|
joblist = joblist.next
|
||||||
|
|
||||||
if job.job_type == :ConstructBuilding
|
if job.job_type == :ConstructBuilding
|
||||||
if (job.flags.suspend)
|
if (job.flags.suspend)
|
||||||
item = job.items[0].item
|
item = job.items[0].item
|
||||||
job.flags.suspend = false
|
job.flags.suspend = false
|
||||||
count += 1
|
count += 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
puts "Unsuspended #{count} job(s)." unless count == 0
|
puts "Unsuspended #{count} job(s)." unless count == 0
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def start
|
def start
|
||||||
@onupdate = df.onupdate_register('autounsuspend', 5) { process }
|
@onupdate = df.onupdate_register('autounsuspend', 5) { process }
|
||||||
@running = true
|
@running = true
|
||||||
end
|
end
|
||||||
|
|
||||||
def stop
|
def stop
|
||||||
df.onupdate_unregister(@onupdate)
|
df.onupdate_unregister(@onupdate)
|
||||||
@running = false
|
@running = false
|
||||||
end
|
end
|
||||||
|
|
||||||
def status
|
def status
|
||||||
@running ? 'Running.' : 'Stopped.'
|
@running ? 'Running.' : 'Stopped.'
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
case $script_args[0]
|
case $script_args[0]
|
||||||
when 'start'
|
when 'start'
|
||||||
$AutoUnsuspend = AutoUnsuspend.new unless $AutoUnsuspend
|
$AutoUnsuspend = AutoUnsuspend.new unless $AutoUnsuspend
|
||||||
$AutoUnsuspend.start
|
$AutoUnsuspend.start
|
||||||
|
|
||||||
when 'end', 'stop'
|
when 'end', 'stop'
|
||||||
$AutoUnsuspend.stop
|
$AutoUnsuspend.stop
|
||||||
|
|
||||||
else
|
else
|
||||||
if $AutoUnsuspend
|
if $AutoUnsuspend
|
||||||
puts $AutoUnsuspend.status
|
puts $AutoUnsuspend.status
|
||||||
else
|
else
|
||||||
puts 'Not loaded.'
|
puts 'Not loaded.'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,177 +1,177 @@
|
|||||||
# create first necessity items under cursor
|
# create first necessity items under cursor
|
||||||
|
|
||||||
category = $script_args[0] || 'help'
|
category = $script_args[0] || 'help'
|
||||||
mat_raw = $script_args[1] || 'list'
|
mat_raw = $script_args[1] || 'list'
|
||||||
count = $script_args[2]
|
count = $script_args[2]
|
||||||
|
|
||||||
|
|
||||||
category = df.match_rawname(category, ['help', 'bars', 'boulders', 'plants', 'logs', 'webs', 'anvils']) || 'help'
|
category = df.match_rawname(category, ['help', 'bars', 'boulders', 'plants', 'logs', 'webs', 'anvils']) || 'help'
|
||||||
|
|
||||||
if category == 'help'
|
if category == 'help'
|
||||||
puts <<EOS
|
puts <<EOS
|
||||||
Create first necessity items under the cursor.
|
Create first necessity items under the cursor.
|
||||||
Usage:
|
Usage:
|
||||||
create-items [category] [raws token] [number]
|
create-items [category] [raws token] [number]
|
||||||
|
|
||||||
Item categories:
|
Item categories:
|
||||||
bars, boulders, plants, logs, webs, anvils
|
bars, boulders, plants, logs, webs, anvils
|
||||||
|
|
||||||
Raw token:
|
Raw token:
|
||||||
Either a full token (PLANT_MAT:ADLER:WOOD) or the middle part only
|
Either a full token (PLANT_MAT:ADLER:WOOD) or the middle part only
|
||||||
(the missing part is autocompleted depending on the item category)
|
(the missing part is autocompleted depending on the item category)
|
||||||
Use 'list' to show all possibilities
|
Use 'list' to show all possibilities
|
||||||
|
|
||||||
Exemples:
|
Exemples:
|
||||||
create-items boulders hematite 30
|
create-items boulders hematite 30
|
||||||
create-items bars CREATURE_MAT:CAT:SOAP 10
|
create-items bars CREATURE_MAT:CAT:SOAP 10
|
||||||
create-items web cave_giant
|
create-items web cave_giant
|
||||||
create-items plants list
|
create-items plants list
|
||||||
|
|
||||||
EOS
|
EOS
|
||||||
throw :script_finished
|
throw :script_finished
|
||||||
|
|
||||||
elsif mat_raw == 'list'
|
elsif mat_raw == 'list'
|
||||||
# allowed with no cursor
|
# allowed with no cursor
|
||||||
|
|
||||||
elsif df.cursor.x == -30000
|
elsif df.cursor.x == -30000
|
||||||
puts "Please place the game cursor somewhere"
|
puts "Please place the game cursor somewhere"
|
||||||
throw :script_finished
|
throw :script_finished
|
||||||
|
|
||||||
elsif !(maptile = df.map_tile_at(df.cursor))
|
elsif !(maptile = df.map_tile_at(df.cursor))
|
||||||
puts "Error: unallocated map block !"
|
puts "Error: unallocated map block !"
|
||||||
throw :script_finished
|
throw :script_finished
|
||||||
|
|
||||||
elsif !maptile.shape_passablehigh
|
elsif !maptile.shape_passablehigh
|
||||||
puts "Error: impassible tile !"
|
puts "Error: impassible tile !"
|
||||||
throw :script_finished
|
throw :script_finished
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def match_list(tok, list)
|
def match_list(tok, list)
|
||||||
if tok != 'list'
|
if tok != 'list'
|
||||||
tok = df.match_rawname(tok, list)
|
tok = df.match_rawname(tok, list)
|
||||||
if not tok
|
if not tok
|
||||||
puts "Invalid raws token, use one in:"
|
puts "Invalid raws token, use one in:"
|
||||||
tok = 'list'
|
tok = 'list'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if tok == 'list'
|
if tok == 'list'
|
||||||
puts list.map { |w| w =~ /[^\w]/ ? w.inspect : w }.join(' ')
|
puts list.map { |w| w =~ /[^\w]/ ? w.inspect : w }.join(' ')
|
||||||
throw :script_finished
|
throw :script_finished
|
||||||
end
|
end
|
||||||
tok
|
tok
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
case category
|
case category
|
||||||
when 'bars'
|
when 'bars'
|
||||||
# create metal bar, eg createbar INORGANIC:IRON
|
# create metal bar, eg createbar INORGANIC:IRON
|
||||||
cls = DFHack::ItemBarst
|
cls = DFHack::ItemBarst
|
||||||
if mat_raw !~ /:/ and !(df.decode_mat(mat_raw) rescue nil)
|
if mat_raw !~ /:/ and !(df.decode_mat(mat_raw) rescue nil)
|
||||||
list = df.world.raws.inorganics.find_all { |ino|
|
list = df.world.raws.inorganics.find_all { |ino|
|
||||||
ino.material.flags[:IS_METAL]
|
ino.material.flags[:IS_METAL]
|
||||||
}.map { |ino| ino.id }
|
}.map { |ino| ino.id }
|
||||||
mat_raw = match_list(mat_raw, list)
|
mat_raw = match_list(mat_raw, list)
|
||||||
mat_raw = "INORGANIC:#{mat_raw}"
|
mat_raw = "INORGANIC:#{mat_raw}"
|
||||||
puts mat_raw
|
puts mat_raw
|
||||||
end
|
end
|
||||||
customize = lambda { |item|
|
customize = lambda { |item|
|
||||||
item.dimension = 150
|
item.dimension = 150
|
||||||
item.subtype = -1
|
item.subtype = -1
|
||||||
}
|
}
|
||||||
|
|
||||||
when 'boulders'
|
when 'boulders'
|
||||||
cls = DFHack::ItemBoulderst
|
cls = DFHack::ItemBoulderst
|
||||||
if mat_raw !~ /:/ and !(df.decode_mat(mat_raw) rescue nil)
|
if mat_raw !~ /:/ and !(df.decode_mat(mat_raw) rescue nil)
|
||||||
list = df.world.raws.inorganics.find_all { |ino|
|
list = df.world.raws.inorganics.find_all { |ino|
|
||||||
ino.material.flags[:IS_STONE]
|
ino.material.flags[:IS_STONE]
|
||||||
}.map { |ino| ino.id }
|
}.map { |ino| ino.id }
|
||||||
mat_raw = match_list(mat_raw, list)
|
mat_raw = match_list(mat_raw, list)
|
||||||
mat_raw = "INORGANIC:#{mat_raw}"
|
mat_raw = "INORGANIC:#{mat_raw}"
|
||||||
puts mat_raw
|
puts mat_raw
|
||||||
end
|
end
|
||||||
|
|
||||||
when 'plants'
|
when 'plants'
|
||||||
cls = DFHack::ItemPlantst
|
cls = DFHack::ItemPlantst
|
||||||
if mat_raw !~ /:/ and !(df.decode_mat(mat_raw) rescue nil)
|
if mat_raw !~ /:/ and !(df.decode_mat(mat_raw) rescue nil)
|
||||||
list = df.world.raws.plants.all.find_all { |plt|
|
list = df.world.raws.plants.all.find_all { |plt|
|
||||||
plt.material.find { |mat| mat.id == 'STRUCTURAL' }
|
plt.material.find { |mat| mat.id == 'STRUCTURAL' }
|
||||||
}.map { |plt| plt.id }
|
}.map { |plt| plt.id }
|
||||||
mat_raw = match_list(mat_raw, list)
|
mat_raw = match_list(mat_raw, list)
|
||||||
mat_raw = "PLANT_MAT:#{mat_raw}:STRUCTURAL"
|
mat_raw = "PLANT_MAT:#{mat_raw}:STRUCTURAL"
|
||||||
puts mat_raw
|
puts mat_raw
|
||||||
end
|
end
|
||||||
|
|
||||||
when 'logs'
|
when 'logs'
|
||||||
cls = DFHack::ItemWoodst
|
cls = DFHack::ItemWoodst
|
||||||
if mat_raw !~ /:/ and !(df.decode_mat(mat_raw) rescue nil)
|
if mat_raw !~ /:/ and !(df.decode_mat(mat_raw) rescue nil)
|
||||||
list = df.world.raws.plants.all.find_all { |plt|
|
list = df.world.raws.plants.all.find_all { |plt|
|
||||||
plt.material.find { |mat| mat.id == 'WOOD' }
|
plt.material.find { |mat| mat.id == 'WOOD' }
|
||||||
}.map { |plt| plt.id }
|
}.map { |plt| plt.id }
|
||||||
mat_raw = match_list(mat_raw, list)
|
mat_raw = match_list(mat_raw, list)
|
||||||
mat_raw = "PLANT_MAT:#{mat_raw}:WOOD"
|
mat_raw = "PLANT_MAT:#{mat_raw}:WOOD"
|
||||||
puts mat_raw
|
puts mat_raw
|
||||||
end
|
end
|
||||||
|
|
||||||
when 'webs'
|
when 'webs'
|
||||||
cls = DFHack::ItemThreadst
|
cls = DFHack::ItemThreadst
|
||||||
if mat_raw !~ /:/ and !(df.decode_mat(mat_raw) rescue nil)
|
if mat_raw !~ /:/ and !(df.decode_mat(mat_raw) rescue nil)
|
||||||
list = df.world.raws.creatures.all.find_all { |cre|
|
list = df.world.raws.creatures.all.find_all { |cre|
|
||||||
cre.material.find { |mat| mat.id == 'SILK' }
|
cre.material.find { |mat| mat.id == 'SILK' }
|
||||||
}.map { |cre| cre.creature_id }
|
}.map { |cre| cre.creature_id }
|
||||||
mat_raw = match_list(mat_raw, list)
|
mat_raw = match_list(mat_raw, list)
|
||||||
mat_raw = "CREATURE_MAT:#{mat_raw}:SILK"
|
mat_raw = "CREATURE_MAT:#{mat_raw}:SILK"
|
||||||
puts mat_raw
|
puts mat_raw
|
||||||
end
|
end
|
||||||
count ||= 1
|
count ||= 1
|
||||||
customize = lambda { |item|
|
customize = lambda { |item|
|
||||||
item.flags.spider_web = true
|
item.flags.spider_web = true
|
||||||
item.dimension = 15000 # XXX may depend on creature (this is for GCS)
|
item.dimension = 15000 # XXX may depend on creature (this is for GCS)
|
||||||
}
|
}
|
||||||
|
|
||||||
when 'anvils'
|
when 'anvils'
|
||||||
cls = DFHack::ItemAnvilst
|
cls = DFHack::ItemAnvilst
|
||||||
if mat_raw !~ /:/ and !(df.decode_mat(mat_raw) rescue nil)
|
if mat_raw !~ /:/ and !(df.decode_mat(mat_raw) rescue nil)
|
||||||
list = df.world.raws.inorganics.find_all { |ino|
|
list = df.world.raws.inorganics.find_all { |ino|
|
||||||
ino.material.flags[:IS_METAL]
|
ino.material.flags[:IS_METAL]
|
||||||
}.map { |ino| ino.id }
|
}.map { |ino| ino.id }
|
||||||
mat_raw = match_list(mat_raw, list)
|
mat_raw = match_list(mat_raw, list)
|
||||||
mat_raw = "INORGANIC:#{mat_raw}"
|
mat_raw = "INORGANIC:#{mat_raw}"
|
||||||
puts mat_raw
|
puts mat_raw
|
||||||
end
|
end
|
||||||
count ||= 1
|
count ||= 1
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
mat = df.decode_mat mat_raw
|
mat = df.decode_mat mat_raw
|
||||||
|
|
||||||
count ||= 20
|
count ||= 20
|
||||||
count.to_i.times {
|
count.to_i.times {
|
||||||
item = cls.cpp_new
|
item = cls.cpp_new
|
||||||
item.id = df.item_next_id
|
item.id = df.item_next_id
|
||||||
item.stack_size = 1
|
item.stack_size = 1
|
||||||
item.mat_type = mat.mat_type
|
item.mat_type = mat.mat_type
|
||||||
item.mat_index = mat.mat_index
|
item.mat_index = mat.mat_index
|
||||||
|
|
||||||
customize[item] if customize
|
customize[item] if customize
|
||||||
|
|
||||||
df.item_next_id += 1
|
df.item_next_id += 1
|
||||||
item.categorize(true)
|
item.categorize(true)
|
||||||
df.world.items.all << item
|
df.world.items.all << item
|
||||||
|
|
||||||
item.pos = df.cursor
|
item.pos = df.cursor
|
||||||
item.flags.on_ground = true
|
item.flags.on_ground = true
|
||||||
df.map_tile_at.mapblock.items << item.id
|
df.map_tile_at.mapblock.items << item.id
|
||||||
df.map_tile_at.occupancy.item = true
|
df.map_tile_at.occupancy.item = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# move game view, so that the ui menu updates
|
# move game view, so that the ui menu updates
|
||||||
if df.cursor.z > 5
|
if df.cursor.z > 5
|
||||||
df.curview.feed_keys(:CURSOR_DOWN_Z)
|
df.curview.feed_keys(:CURSOR_DOWN_Z)
|
||||||
df.curview.feed_keys(:CURSOR_UP_Z)
|
df.curview.feed_keys(:CURSOR_UP_Z)
|
||||||
else
|
else
|
||||||
df.curview.feed_keys(:CURSOR_UP_Z)
|
df.curview.feed_keys(:CURSOR_UP_Z)
|
||||||
df.curview.feed_keys(:CURSOR_DOWN_Z)
|
df.curview.feed_keys(:CURSOR_DOWN_Z)
|
||||||
end
|
end
|
||||||
|
@ -1,67 +1,67 @@
|
|||||||
# show death cause of a creature
|
# show death cause of a creature
|
||||||
|
|
||||||
def display_death_event(e)
|
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 = "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 << " (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 << " 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 << " 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
|
str << ", shot by a #{df.world.raws.itemdefs.weapons[e.weapon.bow_item_subtype].name}" if e.weapon.bow_item_type == :WEAPON
|
||||||
|
|
||||||
puts str.chomp(',') + '.'
|
puts str.chomp(',') + '.'
|
||||||
end
|
end
|
||||||
|
|
||||||
def display_death_unit(u)
|
def display_death_unit(u)
|
||||||
death_info = u.counters.death_tg
|
death_info = u.counters.death_tg
|
||||||
killer = death_info.killer_tg if death_info
|
killer = death_info.killer_tg if death_info
|
||||||
|
|
||||||
str = "The #{u.race_tg.name[0]}"
|
str = "The #{u.race_tg.name[0]}"
|
||||||
str << " #{u.name}" if u.name.has_name
|
str << " #{u.name}" if u.name.has_name
|
||||||
str << " died"
|
str << " died"
|
||||||
str << " in year #{death_info.event_year}" if death_info
|
str << " in year #{death_info.event_year}" if death_info
|
||||||
str << " (cause: #{u.counters.death_cause.to_s.downcase})," if u.counters.death_cause != -1
|
str << " (cause: #{u.counters.death_cause.to_s.downcase})," if u.counters.death_cause != -1
|
||||||
str << " killed by the #{killer.race_tg.name[0]} #{killer.name}" if killer
|
str << " killed by the #{killer.race_tg.name[0]} #{killer.name}" if killer
|
||||||
|
|
||||||
puts str.chomp(',') + '.'
|
puts str.chomp(',') + '.'
|
||||||
end
|
end
|
||||||
|
|
||||||
item = df.item_find(:selected)
|
item = df.item_find(:selected)
|
||||||
unit = df.unit_find(:selected)
|
unit = df.unit_find(:selected)
|
||||||
|
|
||||||
if !item or !item.kind_of?(DFHack::ItemBodyComponent)
|
if !item or !item.kind_of?(DFHack::ItemBodyComponent)
|
||||||
item = df.world.items.other[:ANY_CORPSE].find { |i| df.at_cursor?(i) }
|
item = df.world.items.other[:ANY_CORPSE].find { |i| df.at_cursor?(i) }
|
||||||
end
|
end
|
||||||
|
|
||||||
if item and item.kind_of?(DFHack::ItemBodyComponent)
|
if item and item.kind_of?(DFHack::ItemBodyComponent)
|
||||||
hf = item.hist_figure_id
|
hf = item.hist_figure_id
|
||||||
elsif unit
|
elsif unit
|
||||||
hf = unit.hist_figure_id
|
hf = unit.hist_figure_id
|
||||||
end
|
end
|
||||||
|
|
||||||
if not hf
|
if not hf
|
||||||
puts "Please select a corpse in the loo'k' menu, or an unit in the 'u'nitlist screen"
|
puts "Please select a corpse in the loo'k' menu, or an unit in the 'u'nitlist screen"
|
||||||
|
|
||||||
elsif hf == -1
|
elsif hf == -1
|
||||||
if unit ||= item.unit_tg
|
if unit ||= item.unit_tg
|
||||||
display_death_unit(unit)
|
display_death_unit(unit)
|
||||||
else
|
else
|
||||||
puts "Not a historical figure, cannot death find info"
|
puts "Not a historical figure, cannot death find info"
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
histfig = df.world.history.figures.binsearch(hf)
|
histfig = df.world.history.figures.binsearch(hf)
|
||||||
unit = histfig ? df.unit_find(histfig.unit_id) : nil
|
unit = histfig ? df.unit_find(histfig.unit_id) : nil
|
||||||
if unit and not unit.flags1.dead and not unit.flags3.ghostly
|
if unit and not unit.flags1.dead and not unit.flags3.ghostly
|
||||||
puts "#{unit.name} is not dead yet !"
|
puts "#{unit.name} is not dead yet !"
|
||||||
|
|
||||||
else
|
else
|
||||||
events = df.world.history.events
|
events = df.world.history.events
|
||||||
(0...events.length).reverse_each { |i|
|
(0...events.length).reverse_each { |i|
|
||||||
e = events[i]
|
e = events[i]
|
||||||
if e.kind_of?(DFHack::HistoryEventHistFigureDiedst) and e.victim_hf == hf
|
if e.kind_of?(DFHack::HistoryEventHistFigureDiedst) and e.victim_hf == hf
|
||||||
display_death_event(e)
|
display_death_event(e)
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
# list indexes in world.item.other[] where current selected item appears
|
||||||
|
|
||||||
|
tg = df.item_find
|
||||||
|
raise 'select an item' if not tg
|
||||||
|
|
||||||
|
o = df.world.items.other
|
||||||
|
# discard ANY/BAD
|
||||||
|
o._indexenum::ENUM.sort.transpose[1][1..-2].each { |k|
|
||||||
|
puts k if o[k].find { |i| i == tg }
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
# unforbid all items
|
||||||
|
|
||||||
|
df.world.items.all.each { |i| i.flags.forbid = false }
|
@ -1,38 +1,38 @@
|
|||||||
# designate an area for digging according to a plan in csv format
|
# designate an area for digging according to a plan in csv format
|
||||||
|
|
||||||
raise "usage: digfort <plan filename>" if not $script_args[0]
|
raise "usage: digfort <plan filename>" if not $script_args[0]
|
||||||
planfile = File.read($script_args[0])
|
planfile = File.read($script_args[0])
|
||||||
|
|
||||||
if df.cursor.x == -30000
|
if df.cursor.x == -30000
|
||||||
raise "place the game cursor to the top-left corner of the design"
|
raise "place the game cursor to the top-left corner of the design"
|
||||||
end
|
end
|
||||||
|
|
||||||
tiles = planfile.lines.map { |l|
|
tiles = planfile.lines.map { |l|
|
||||||
l.sub(/#.*/, '').split(';').map { |t| t.strip }
|
l.sub(/#.*/, '').split(';').map { |t| t.strip }
|
||||||
}
|
}
|
||||||
|
|
||||||
x = x0 = df.cursor.x
|
x = x0 = df.cursor.x
|
||||||
y = df.cursor.y
|
y = df.cursor.y
|
||||||
z = df.cursor.z
|
z = df.cursor.z
|
||||||
|
|
||||||
tiles.each { |line|
|
tiles.each { |line|
|
||||||
next if line.empty? or line == ['']
|
next if line.empty? or line == ['']
|
||||||
line.each { |tile|
|
line.each { |tile|
|
||||||
t = df.map_tile_at(x, y, z)
|
t = df.map_tile_at(x, y, z)
|
||||||
s = t.shape_basic
|
s = t.shape_basic
|
||||||
case tile
|
case tile
|
||||||
when 'd'; t.dig(:Default) if s == :Wall
|
when 'd'; t.dig(:Default) if s == :Wall
|
||||||
when 'u'; t.dig(:UpStair) if s == :Wall
|
when 'u'; t.dig(:UpStair) if s == :Wall
|
||||||
when 'j'; t.dig(:DownStair) if s == :Wall or s == :Floor
|
when 'j'; t.dig(:DownStair) if s == :Wall or s == :Floor
|
||||||
when 'i'; t.dig(:UpDownStair) if s == :Wall
|
when 'i'; t.dig(:UpDownStair) if s == :Wall
|
||||||
when 'h'; t.dig(:Channel) if s == :Wall or s == :Floor
|
when 'h'; t.dig(:Channel) if s == :Wall or s == :Floor
|
||||||
when 'r'; t.dig(:Ramp) if s == :Wall
|
when 'r'; t.dig(:Ramp) if s == :Wall
|
||||||
when 'x'; t.dig(:No)
|
when 'x'; t.dig(:No)
|
||||||
end
|
end
|
||||||
x += 1
|
x += 1
|
||||||
}
|
}
|
||||||
x = x0
|
x = x0
|
||||||
y += 1
|
y += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
puts 'done'
|
puts 'done'
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
# remove all aquifers from the map
|
# remove all aquifers from the map
|
||||||
|
|
||||||
count = 0
|
count = 0
|
||||||
df.each_map_block { |b|
|
df.each_map_block { |b|
|
||||||
if b.designation[0][0].water_table or b.designation[15][15].water_table
|
if b.designation[0][0].water_table or b.designation[8][8].water_table
|
||||||
count += 1
|
count += 1
|
||||||
b.designation.each { |dx| dx.each { |dy| dy.water_table = false } }
|
df.each_map_block_z(b.map_pos.z) { |bz|
|
||||||
end
|
bz.designation.each { |dx| dx.each { |dy| dy.water_table = false } }
|
||||||
}
|
}
|
||||||
|
end
|
||||||
puts "cleared #{count} map blocks"
|
}
|
||||||
|
|
||||||
|
puts "cleared #{count} aquifer#{'s' if count > 1}"
|
||||||
|
@ -1,112 +1,135 @@
|
|||||||
# exterminate creatures
|
# exterminate creatures
|
||||||
|
|
||||||
# race = name of the race to eradicate, use 'him' to target only the selected creature
|
# race = name of the race to eradicate, use 'him' to target only the selected creature
|
||||||
# use 'undead' to target all undeads
|
# use 'undead' to target all undeads
|
||||||
race = $script_args[0]
|
race = $script_args[0]
|
||||||
|
|
||||||
# if the 2nd parameter is 'magma', magma rain for the targets instead of instant death
|
# if the 2nd parameter is 'magma', magma rain for the targets instead of instant death
|
||||||
magma = ($script_args[1] == 'magma')
|
# if it is 'butcher' mark all units for butchering (wont work with hostiles)
|
||||||
|
kill_by = $script_args[1]
|
||||||
checkunit = lambda { |u|
|
|
||||||
(u.body.blood_count != 0 or u.body.blood_max == 0) and
|
case kill_by
|
||||||
not u.flags1.dead and
|
when 'magma'
|
||||||
not u.flags1.caged and not u.flags1.chained and
|
slain = 'burning'
|
||||||
#not u.flags1.hidden_in_ambush and
|
when 'slaughter', 'butcher'
|
||||||
not df.map_designation_at(u).hidden
|
slain = 'marked for butcher'
|
||||||
}
|
when nil
|
||||||
|
slain = 'slain'
|
||||||
slayit = lambda { |u|
|
else
|
||||||
if not magma
|
race = 'help'
|
||||||
# just make them drop dead
|
end
|
||||||
u.body.blood_count = 0
|
|
||||||
# some races dont mind having no blood, ensure they are still taken care of.
|
checkunit = lambda { |u|
|
||||||
u.animal.vanish_countdown = 2
|
(u.body.blood_count != 0 or u.body.blood_max == 0) and
|
||||||
else
|
not u.flags1.dead and
|
||||||
# it's getting hot around here
|
not u.flags1.caged and not u.flags1.chained and
|
||||||
# !!WARNING!! do not call on a magma-safe creature
|
#not u.flags1.hidden_in_ambush and
|
||||||
ouh = df.onupdate_register("exterminate ensure #{u.id}", 1) {
|
not df.map_designation_at(u).hidden
|
||||||
if u.flags1.dead
|
}
|
||||||
df.onupdate_unregister(ouh)
|
|
||||||
else
|
slayit = lambda { |u|
|
||||||
x, y, z = u.pos.x, u.pos.y, u.pos.z
|
case kill_by
|
||||||
z += 1 while tile = df.map_tile_at(x, y, z+1) and
|
when 'magma'
|
||||||
tile.shape_passableflow and tile.shape_passablelow
|
# it's getting hot around here
|
||||||
df.map_tile_at(x, y, z).spawn_magma(7)
|
# !!WARNING!! do not call on a magma-safe creature
|
||||||
end
|
ouh = df.onupdate_register("exterminate ensure #{u.id}", 1) {
|
||||||
}
|
if u.flags1.dead
|
||||||
end
|
df.onupdate_unregister(ouh)
|
||||||
}
|
else
|
||||||
|
x, y, z = u.pos.x, u.pos.y, u.pos.z
|
||||||
all_races = Hash.new(0)
|
z += 1 while tile = df.map_tile_at(x, y, z+1) and
|
||||||
|
tile.shape_passableflow and tile.shape_passablelow
|
||||||
df.world.units.active.map { |u|
|
df.map_tile_at(x, y, z).spawn_magma(7)
|
||||||
if checkunit[u]
|
end
|
||||||
if (u.enemy.undead or
|
}
|
||||||
(u.curse.add_tags1.OPPOSED_TO_LIFE and not
|
when 'butcher', 'slaughter'
|
||||||
u.curse.rem_tags1.OPPOSED_TO_LIFE))
|
# mark for slaughter at butcher's shop
|
||||||
all_races['Undead'] += 1
|
u.flags2.slaughter = true
|
||||||
else
|
else
|
||||||
all_races[u.race_tg.creature_id] += 1
|
# just make them drop dead
|
||||||
end
|
u.body.blood_count = 0
|
||||||
end
|
# some races dont mind having no blood, ensure they are still taken care of.
|
||||||
}
|
u.animal.vanish_countdown = 2
|
||||||
|
end
|
||||||
case race
|
}
|
||||||
when nil
|
|
||||||
all_races.sort_by { |race, cnt| [cnt, race] }.each{ |race, cnt| puts " #{race} #{cnt}" }
|
all_races = Hash.new(0)
|
||||||
|
|
||||||
when 'help', '?'
|
df.world.units.active.map { |u|
|
||||||
puts <<EOS
|
if checkunit[u]
|
||||||
Kills all creatures of a given race.
|
if (u.enemy.undead or
|
||||||
With no argument, lists possible targets with their head count.
|
(u.curse.add_tags1.OPPOSED_TO_LIFE and not
|
||||||
With the special argument 'him' or 'her', kill only the currently selected creature.
|
u.curse.rem_tags1.OPPOSED_TO_LIFE))
|
||||||
With the special argument 'undead', kill all undead creatures/thralls.
|
all_races['Undead'] += 1
|
||||||
|
else
|
||||||
The targets will bleed out on the next game tick, or if they are immune to that, will vanish in a puff of smoke.
|
all_races[u.race_tg.creature_id] += 1
|
||||||
|
end
|
||||||
The special final argument 'magma' will make magma rain on the targets instead.
|
end
|
||||||
|
}
|
||||||
Ex: exterminate gob
|
|
||||||
exterminate elve magma
|
case race
|
||||||
exterminate him
|
when nil
|
||||||
EOS
|
all_races.sort_by { |race, cnt| [cnt, race] }.each{ |race, cnt| puts " #{race} #{cnt}" }
|
||||||
|
|
||||||
when 'him', 'her'
|
when 'help', '?'
|
||||||
if him = df.unit_find
|
puts <<EOS
|
||||||
slayit[him]
|
Kills all creatures of a given race.
|
||||||
else
|
With no argument, lists possible targets with their head count.
|
||||||
puts "Select a target ingame"
|
With the special argument 'him' or 'her', kill only the currently selected creature.
|
||||||
end
|
With the special argument 'undead', kill all undead creatures/thralls.
|
||||||
|
|
||||||
when /^undead/i
|
The targets will bleed out on the next game tick, or if they are immune to that, will vanish in a puff of smoke.
|
||||||
count = 0
|
|
||||||
df.world.units.active.each { |u|
|
The special final argument 'magma' will make magma rain on the targets instead.
|
||||||
if (u.enemy.undead or
|
The special final argument 'butcher' will mark the targets for butchering instead.
|
||||||
(u.curse.add_tags1.OPPOSED_TO_LIFE and not
|
|
||||||
u.curse.rem_tags1.OPPOSED_TO_LIFE)) and
|
Ex: exterminate gob
|
||||||
checkunit[u]
|
exterminate elve magma
|
||||||
slayit[u]
|
exterminate him
|
||||||
count += 1
|
exterminate pig butcher
|
||||||
end
|
EOS
|
||||||
}
|
|
||||||
puts "slain #{count} undeads"
|
when 'him', 'her', 'it', 'that'
|
||||||
|
if him = df.unit_find
|
||||||
else
|
case him.race_tg.caste[him.caste].gender
|
||||||
raw_race = df.match_rawname(race, all_races.keys)
|
when 0; puts 'its a she !' if race != 'her'
|
||||||
if not raw_race
|
when 1; puts 'its a he !' if race != 'him'
|
||||||
puts "Invalid race, use one of #{all_races.keys.sort.join(' ')}"
|
else; puts 'its an it !' if race != 'it' and race != 'that'
|
||||||
throw :script_finished
|
end
|
||||||
end
|
slayit[him]
|
||||||
|
else
|
||||||
race_nr = df.world.raws.creatures.all.index { |cr| cr.creature_id == raw_race }
|
puts "Select a target ingame"
|
||||||
|
end
|
||||||
count = 0
|
|
||||||
df.world.units.active.each { |u|
|
when /^undead/i
|
||||||
if u.race == race_nr and checkunit[u]
|
count = 0
|
||||||
slayit[u]
|
df.world.units.active.each { |u|
|
||||||
count += 1
|
if (u.enemy.undead or
|
||||||
end
|
(u.curse.add_tags1.OPPOSED_TO_LIFE and not
|
||||||
}
|
u.curse.rem_tags1.OPPOSED_TO_LIFE)) and
|
||||||
puts "slain #{count} #{raw_race}"
|
checkunit[u]
|
||||||
|
slayit[u]
|
||||||
end
|
count += 1
|
||||||
|
end
|
||||||
|
}
|
||||||
|
puts "#{slain} #{count} undeads"
|
||||||
|
|
||||||
|
else
|
||||||
|
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 }
|
||||||
|
|
||||||
|
count = 0
|
||||||
|
df.world.units.active.each { |u|
|
||||||
|
if u.race == race_nr and checkunit[u]
|
||||||
|
slayit[u]
|
||||||
|
count += 1
|
||||||
|
end
|
||||||
|
}
|
||||||
|
puts "#{slain} #{count} #{raw_race}"
|
||||||
|
|
||||||
|
end
|
||||||
|
@ -1,64 +1,64 @@
|
|||||||
# script to fix loyalty cascade, when you order your militia to kill friendly units
|
# script to fix loyalty cascade, when you order your militia to kill friendly units
|
||||||
|
|
||||||
def fixunit(unit)
|
def fixunit(unit)
|
||||||
return if unit.race != df.ui.race_id or unit.civ_id != df.ui.civ_id
|
return if unit.race != df.ui.race_id or unit.civ_id != df.ui.civ_id
|
||||||
links = unit.hist_figure_tg.entity_links
|
links = unit.hist_figure_tg.entity_links
|
||||||
fixed = false
|
fixed = false
|
||||||
|
|
||||||
# check if the unit is a civ renegade
|
# check if the unit is a civ renegade
|
||||||
if i1 = links.index { |l|
|
if i1 = links.index { |l|
|
||||||
l.kind_of?(DFHack::HistfigEntityLinkFormerMemberst) and
|
l.kind_of?(DFHack::HistfigEntityLinkFormerMemberst) and
|
||||||
l.entity_id == df.ui.civ_id
|
l.entity_id == df.ui.civ_id
|
||||||
} and i2 = links.index { |l|
|
} and i2 = links.index { |l|
|
||||||
l.kind_of?(DFHack::HistfigEntityLinkEnemyst) and
|
l.kind_of?(DFHack::HistfigEntityLinkEnemyst) and
|
||||||
l.entity_id == df.ui.civ_id
|
l.entity_id == df.ui.civ_id
|
||||||
}
|
}
|
||||||
fixed = true
|
fixed = true
|
||||||
i1, i2 = i2, i1 if i1 > i2
|
i1, i2 = i2, i1 if i1 > i2
|
||||||
links.delete_at i2
|
links.delete_at i2
|
||||||
links.delete_at i1
|
links.delete_at i1
|
||||||
links << DFHack::HistfigEntityLinkMemberst.cpp_new(:entity_id => df.ui.civ_id, :link_strength => 100)
|
links << DFHack::HistfigEntityLinkMemberst.cpp_new(:entity_id => df.ui.civ_id, :link_strength => 100)
|
||||||
df.add_announcement "fixloyalty: #{unit.name} is now a member of #{df.ui.civ_tg.name} again"
|
df.add_announcement "fixloyalty: #{unit.name} is now a member of #{df.ui.civ_tg.name} again"
|
||||||
end
|
end
|
||||||
|
|
||||||
# check if the unit is a group renegade
|
# check if the unit is a group renegade
|
||||||
if i1 = links.index { |l|
|
if i1 = links.index { |l|
|
||||||
l.kind_of?(DFHack::HistfigEntityLinkFormerMemberst) and
|
l.kind_of?(DFHack::HistfigEntityLinkFormerMemberst) and
|
||||||
l.entity_id == df.ui.group_id
|
l.entity_id == df.ui.group_id
|
||||||
} and i2 = links.index { |l|
|
} and i2 = links.index { |l|
|
||||||
l.kind_of?(DFHack::HistfigEntityLinkEnemyst) and
|
l.kind_of?(DFHack::HistfigEntityLinkEnemyst) and
|
||||||
l.entity_id == df.ui.group_id
|
l.entity_id == df.ui.group_id
|
||||||
}
|
}
|
||||||
fixed = true
|
fixed = true
|
||||||
i1, i2 = i2, i1 if i1 > i2
|
i1, i2 = i2, i1 if i1 > i2
|
||||||
links.delete_at i2
|
links.delete_at i2
|
||||||
links.delete_at i1
|
links.delete_at i1
|
||||||
links << DFHack::HistfigEntityLinkMemberst.cpp_new(:entity_id => df.ui.group_id, :link_strength => 100)
|
links << DFHack::HistfigEntityLinkMemberst.cpp_new(:entity_id => df.ui.group_id, :link_strength => 100)
|
||||||
df.add_announcement "fixloyalty: #{unit.name} is now a member of #{df.ui.group_tg.name} again"
|
df.add_announcement "fixloyalty: #{unit.name} is now a member of #{df.ui.group_tg.name} again"
|
||||||
end
|
end
|
||||||
|
|
||||||
# fix the 'is an enemy' cache matrix (mark to be recalculated by the game when needed)
|
# fix the 'is an enemy' cache matrix (mark to be recalculated by the game when needed)
|
||||||
if fixed and unit.enemy.enemy_status_slot != -1
|
if fixed and unit.enemy.enemy_status_slot != -1
|
||||||
i = unit.enemy.enemy_status_slot
|
i = unit.enemy.enemy_status_slot
|
||||||
unit.enemy.enemy_status_slot = -1
|
unit.enemy.enemy_status_slot = -1
|
||||||
cache = df.world.enemy_status_cache
|
cache = df.world.enemy_status_cache
|
||||||
cache.slot_used[i] = false
|
cache.slot_used[i] = false
|
||||||
cache.rel_map[i].map! { -1 }
|
cache.rel_map[i].map! { -1 }
|
||||||
cache.rel_map.each { |a| a[i] = -1 }
|
cache.rel_map.each { |a| a[i] = -1 }
|
||||||
cache.next_slot = i if cache.next_slot > i
|
cache.next_slot = i if cache.next_slot > i
|
||||||
end
|
end
|
||||||
|
|
||||||
# return true if we actually fixed the unit
|
# return true if we actually fixed the unit
|
||||||
fixed
|
fixed
|
||||||
end
|
end
|
||||||
|
|
||||||
count = 0
|
count = 0
|
||||||
df.unit_citizens.each { |u|
|
df.unit_citizens.each { |u|
|
||||||
count += 1 if fixunit(u)
|
count += 1 if fixunit(u)
|
||||||
}
|
}
|
||||||
|
|
||||||
if count > 0
|
if count > 0
|
||||||
puts "loyalty cascade fixed (#{count} dwarves)"
|
puts "loyalty cascade fixed (#{count} dwarves)"
|
||||||
else
|
else
|
||||||
puts "no loyalty cascade found"
|
puts "no loyalty cascade found"
|
||||||
end
|
end
|
||||||
|
@ -1,20 +1,25 @@
|
|||||||
# fix doors that are frozen in 'open' state
|
# fix doors that are frozen in 'open' state
|
||||||
|
|
||||||
# door is stuck in open state if the map occupancy flag incorrectly indicates
|
# this may happen after people mess with the game by (incorrectly) teleporting units or items
|
||||||
# that an unit is present (and creatures will prone to pass through)
|
# a door may stick open if the map occupancy flags are wrong
|
||||||
|
|
||||||
count = 0
|
count = 0
|
||||||
df.world.buildings.all.each { |bld|
|
df.world.buildings.all.each { |bld|
|
||||||
# for all doors
|
# for all doors
|
||||||
next if bld._rtti_classname != :building_doorst
|
next if bld._rtti_classname != :building_doorst
|
||||||
# check if it is open
|
# check if it is open
|
||||||
next if bld.close_timer == 0
|
next if bld.close_timer == 0
|
||||||
# check if occupancy is set
|
# check if occupancy is set
|
||||||
occ = df.map_occupancy_at(bld.x1, bld.y1, bld.z)
|
occ = df.map_occupancy_at(bld.x1, bld.y1, bld.z)
|
||||||
next if not occ.unit
|
if (occ.unit or occ.unit_grounded) and not
|
||||||
# check if an unit is present
|
# check if an unit is present
|
||||||
next if df.world.units.active.find { |u| u.pos.x == bld.x1 and u.pos.y == bld.y1 and u.pos.z == bld.z }
|
df.world.units.active.find { |u| u.pos.x == bld.x1 and u.pos.y == bld.y1 and u.pos.z == bld.z }
|
||||||
count += 1
|
count += 1
|
||||||
occ.unit = false
|
occ.unit = occ.unit_grounded = false
|
||||||
}
|
end
|
||||||
puts "unstuck #{count} doors"
|
if occ.item and not df.world.items.all.find { |i| i.pos.x == bld.x1 and i.pos.y == bld.y1 and i.pos.z == bld.z }
|
||||||
|
count += 1
|
||||||
|
occ.item = false
|
||||||
|
end
|
||||||
|
}
|
||||||
|
puts "unstuck #{count} doors"
|
||||||
|
@ -1,49 +1,49 @@
|
|||||||
# grow crops in farm plots. ex: growcrops helmet_plump 20
|
# grow crops in farm plots. ex: growcrops helmet_plump 20
|
||||||
|
|
||||||
material = $script_args[0]
|
material = $script_args[0]
|
||||||
count_max = $script_args[1].to_i
|
count_max = $script_args[1].to_i
|
||||||
count_max = 100 if count_max == 0
|
count_max = 100 if count_max == 0
|
||||||
|
|
||||||
# cache information from the raws
|
# cache information from the raws
|
||||||
@raws_plant_name ||= {}
|
@raws_plant_name ||= {}
|
||||||
@raws_plant_growdur ||= {}
|
@raws_plant_growdur ||= {}
|
||||||
if @raws_plant_name.empty?
|
if @raws_plant_name.empty?
|
||||||
df.world.raws.plants.all.each_with_index { |p, idx|
|
df.world.raws.plants.all.each_with_index { |p, idx|
|
||||||
@raws_plant_name[idx] = p.id
|
@raws_plant_name[idx] = p.id
|
||||||
@raws_plant_growdur[idx] = p.growdur
|
@raws_plant_growdur[idx] = p.growdur
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
inventory = Hash.new(0)
|
inventory = Hash.new(0)
|
||||||
df.world.items.other[:SEEDS].each { |seed|
|
df.world.items.other[:SEEDS].each { |seed|
|
||||||
next if not seed.flags.in_building
|
next if not seed.flags.in_building
|
||||||
next if not seed.general_refs.find { |ref| ref._rtti_classname == :general_ref_building_holderst }
|
next if not seed.general_refs.find { |ref| ref._rtti_classname == :general_ref_building_holderst }
|
||||||
next if seed.grow_counter >= @raws_plant_growdur[seed.mat_index]
|
next if seed.grow_counter >= @raws_plant_growdur[seed.mat_index]
|
||||||
inventory[seed.mat_index] += 1
|
inventory[seed.mat_index] += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if !material or material == 'help' or material == 'list'
|
if !material or material == 'help' or material == 'list'
|
||||||
# show a list of available crop types
|
# show a list of available crop types
|
||||||
inventory.sort_by { |mat, c| c }.each { |mat, c|
|
inventory.sort_by { |mat, c| c }.each { |mat, c|
|
||||||
name = df.world.raws.plants.all[mat].id
|
name = df.world.raws.plants.all[mat].id
|
||||||
puts " #{name} #{c}"
|
puts " #{name} #{c}"
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
mat = df.match_rawname(material, inventory.keys.map { |k| @raws_plant_name[k] })
|
mat = df.match_rawname(material, inventory.keys.map { |k| @raws_plant_name[k] })
|
||||||
unless wantmat = @raws_plant_name.index(mat)
|
unless wantmat = @raws_plant_name.index(mat)
|
||||||
raise "invalid plant material #{material}"
|
raise "invalid plant material #{material}"
|
||||||
end
|
end
|
||||||
|
|
||||||
count = 0
|
count = 0
|
||||||
df.world.items.other[:SEEDS].each { |seed|
|
df.world.items.other[:SEEDS].each { |seed|
|
||||||
next if seed.mat_index != wantmat
|
next if seed.mat_index != wantmat
|
||||||
next if not seed.flags.in_building
|
next if not seed.flags.in_building
|
||||||
next if not seed.general_refs.find { |ref| ref._rtti_classname == :general_ref_building_holderst }
|
next if not seed.general_refs.find { |ref| ref._rtti_classname == :general_ref_building_holderst }
|
||||||
next if seed.grow_counter >= @raws_plant_growdur[seed.mat_index]
|
next if seed.grow_counter >= @raws_plant_growdur[seed.mat_index]
|
||||||
seed.grow_counter = @raws_plant_growdur[seed.mat_index]
|
seed.grow_counter = @raws_plant_growdur[seed.mat_index]
|
||||||
count += 1
|
count += 1
|
||||||
}
|
}
|
||||||
puts "Grown #{count} #{mat}"
|
puts "Grown #{count} #{mat}"
|
||||||
end
|
end
|
||||||
|
@ -1,120 +1,120 @@
|
|||||||
# control your levers from the dfhack console
|
# control your levers from the dfhack console
|
||||||
|
|
||||||
def lever_pull_job(bld)
|
def lever_pull_job(bld)
|
||||||
ref = DFHack::GeneralRefBuildingHolderst.cpp_new
|
ref = DFHack::GeneralRefBuildingHolderst.cpp_new
|
||||||
ref.building_id = bld.id
|
ref.building_id = bld.id
|
||||||
|
|
||||||
job = DFHack::Job.cpp_new
|
job = DFHack::Job.cpp_new
|
||||||
job.job_type = :PullLever
|
job.job_type = :PullLever
|
||||||
job.pos = [bld.centerx, bld.centery, bld.z]
|
job.pos = [bld.centerx, bld.centery, bld.z]
|
||||||
job.general_refs << ref
|
job.general_refs << ref
|
||||||
bld.jobs << job
|
bld.jobs << job
|
||||||
df.job_link job
|
df.job_link job
|
||||||
|
|
||||||
puts lever_descr(bld)
|
puts lever_descr(bld)
|
||||||
end
|
end
|
||||||
|
|
||||||
def lever_pull_cheat(bld)
|
def lever_pull_cheat(bld)
|
||||||
bld.linked_mechanisms.each { |i|
|
bld.linked_mechanisms.each { |i|
|
||||||
i.general_refs.grep(DFHack::GeneralRefBuildingHolderst).each { |r|
|
i.general_refs.grep(DFHack::GeneralRefBuildingHolderst).each { |r|
|
||||||
r.building_tg.setTriggerState(bld.state)
|
r.building_tg.setTriggerState(bld.state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bld.state = (bld.state == 0 ? 1 : 0)
|
bld.state = (bld.state == 0 ? 1 : 0)
|
||||||
|
|
||||||
puts lever_descr(bld)
|
puts lever_descr(bld)
|
||||||
end
|
end
|
||||||
|
|
||||||
def lever_descr(bld, idx=nil)
|
def lever_descr(bld, idx=nil)
|
||||||
ret = []
|
ret = []
|
||||||
|
|
||||||
# lever description
|
# lever description
|
||||||
descr = ''
|
descr = ''
|
||||||
descr << "#{idx}: " if idx
|
descr << "#{idx}: " if idx
|
||||||
descr << "lever ##{bld.id} @[#{bld.centerx}, #{bld.centery}, #{bld.z}] #{bld.state == 0 ? '\\' : '/'}"
|
descr << "lever ##{bld.id} @[#{bld.centerx}, #{bld.centery}, #{bld.z}] #{bld.state == 0 ? '\\' : '/'}"
|
||||||
bld.jobs.each { |j|
|
bld.jobs.each { |j|
|
||||||
if j.job_type == :PullLever
|
if j.job_type == :PullLever
|
||||||
flags = ''
|
flags = ''
|
||||||
flags << ', repeat' if j.flags.repeat
|
flags << ', repeat' if j.flags.repeat
|
||||||
flags << ', suspended' if j.flags.suspend
|
flags << ', suspended' if j.flags.suspend
|
||||||
descr << " (pull order#{flags})"
|
descr << " (pull order#{flags})"
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
bld.linked_mechanisms.map { |i|
|
bld.linked_mechanisms.map { |i|
|
||||||
i.general_refs.grep(DFHack::GeneralRefBuildingHolderst)
|
i.general_refs.grep(DFHack::GeneralRefBuildingHolderst)
|
||||||
}.flatten.each { |r|
|
}.flatten.each { |r|
|
||||||
# linked building description
|
# linked building description
|
||||||
tg = r.building_tg
|
tg = r.building_tg
|
||||||
state = ''
|
state = ''
|
||||||
if tg.respond_to?(:gate_flags)
|
if tg.respond_to?(:gate_flags)
|
||||||
state << (tg.gate_flags.closed ? 'closed' : 'opened')
|
state << (tg.gate_flags.closed ? 'closed' : 'opened')
|
||||||
state << ", closing (#{tg.timer})" if tg.gate_flags.closing
|
state << ", closing (#{tg.timer})" if tg.gate_flags.closing
|
||||||
state << ", opening (#{tg.timer})" if tg.gate_flags.opening
|
state << ", opening (#{tg.timer})" if tg.gate_flags.opening
|
||||||
end
|
end
|
||||||
|
|
||||||
ret << (descr + " linked to #{tg._rtti_classname} ##{tg.id} @[#{tg.centerx}, #{tg.centery}, #{tg.z}] #{state}")
|
ret << (descr + " linked to #{tg._rtti_classname} ##{tg.id} @[#{tg.centerx}, #{tg.centery}, #{tg.z}] #{state}")
|
||||||
|
|
||||||
# indent other links
|
# indent other links
|
||||||
descr = descr.gsub(/./, ' ')
|
descr = descr.gsub(/./, ' ')
|
||||||
}
|
}
|
||||||
|
|
||||||
ret << descr if ret.empty?
|
ret << descr if ret.empty?
|
||||||
|
|
||||||
ret
|
ret
|
||||||
end
|
end
|
||||||
|
|
||||||
def lever_list
|
def lever_list
|
||||||
@lever_list = []
|
@lever_list = []
|
||||||
df.world.buildings.other[:TRAP].find_all { |bld|
|
df.world.buildings.other[:TRAP].find_all { |bld|
|
||||||
bld.trap_type == :Lever
|
bld.trap_type == :Lever
|
||||||
}.sort_by { |bld| bld.id }.each { |bld|
|
}.sort_by { |bld| bld.id }.each { |bld|
|
||||||
puts lever_descr(bld, @lever_list.length)
|
puts lever_descr(bld, @lever_list.length)
|
||||||
@lever_list << bld.id
|
@lever_list << bld.id
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
case $script_args[0]
|
case $script_args[0]
|
||||||
when 'pull'
|
when 'pull'
|
||||||
cheat = $script_args.delete('--cheat') || $script_args.delete('--now')
|
cheat = $script_args.delete('--cheat') || $script_args.delete('--now')
|
||||||
|
|
||||||
id = $script_args[1].to_i
|
id = $script_args[1].to_i
|
||||||
id = @lever_list[id] || id
|
id = @lever_list[id] || id
|
||||||
bld = df.building_find(id)
|
bld = df.building_find(id)
|
||||||
raise 'invalid lever id' if not bld
|
raise 'invalid lever id' if not bld
|
||||||
|
|
||||||
if cheat
|
if cheat
|
||||||
lever_pull_cheat(bld)
|
lever_pull_cheat(bld)
|
||||||
else
|
else
|
||||||
lever_pull_job(bld)
|
lever_pull_job(bld)
|
||||||
end
|
end
|
||||||
|
|
||||||
when 'list'
|
when 'list'
|
||||||
lever_list
|
lever_list
|
||||||
|
|
||||||
when /^\d+$/
|
when /^\d+$/
|
||||||
id = $script_args[0].to_i
|
id = $script_args[0].to_i
|
||||||
id = @lever_list[id] || id
|
id = @lever_list[id] || id
|
||||||
bld = df.building_find(id)
|
bld = df.building_find(id)
|
||||||
raise 'invalid lever id' if not bld
|
raise 'invalid lever id' if not bld
|
||||||
|
|
||||||
puts lever_descr(bld)
|
puts lever_descr(bld)
|
||||||
|
|
||||||
else
|
else
|
||||||
puts <<EOS
|
puts <<EOS
|
||||||
Lever control from the dfhack console
|
Lever control from the dfhack console
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
lever list
|
lever list
|
||||||
shows the list of levers in the fortress, with their id and links
|
shows the list of levers in the fortress, with their id and links
|
||||||
|
|
||||||
lever pull 42
|
lever pull 42
|
||||||
order the dwarves to pull lever 42
|
order the dwarves to pull lever 42
|
||||||
|
|
||||||
lever pull 42 --cheat
|
lever pull 42 --cheat
|
||||||
magically pull lever 42 immediately
|
magically pull lever 42 immediately
|
||||||
EOS
|
EOS
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -0,0 +1,84 @@
|
|||||||
|
# scan the map for ore veins
|
||||||
|
|
||||||
|
target_ore = $script_args[0]
|
||||||
|
|
||||||
|
def find_all_ore_veins
|
||||||
|
puts 'scanning map...'
|
||||||
|
$ore_veins = {}
|
||||||
|
seen_mat = {}
|
||||||
|
df.each_map_block { |block|
|
||||||
|
block.block_events.grep(DFHack::BlockSquareEventMineralst).each { |vein|
|
||||||
|
mat_index = vein.inorganic_mat
|
||||||
|
if not seen_mat[mat_index] or $ore_veins[mat_index]
|
||||||
|
seen_mat[mat_index] = true
|
||||||
|
if df.world.raws.inorganics[mat_index].flags[:METAL_ORE]
|
||||||
|
$ore_veins[mat_index] ||= []
|
||||||
|
$ore_veins[mat_index] << [block.map_pos.x, block.map_pos.y, block.map_pos.z]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
df.onstatechange_register_once { |st|
|
||||||
|
if st == :MAP_LOADED
|
||||||
|
$ore_veins = nil # invalidate veins cache
|
||||||
|
true
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
$ore_veins
|
||||||
|
end
|
||||||
|
|
||||||
|
$ore_veins ||= find_all_ore_veins
|
||||||
|
|
||||||
|
if not target_ore or target_ore == 'help'
|
||||||
|
puts <<EOS
|
||||||
|
Scan the map to find one random tile of unmined ore.
|
||||||
|
It will center the game view on that tile and mark it for digging.
|
||||||
|
Only works with metal ores.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
locate_ore list list all existing vein materials (including mined ones)
|
||||||
|
locate_ore hematite find one tile of unmined hematite ore
|
||||||
|
locate_ore iron find one tile of unmined ore you can smelt into iron
|
||||||
|
EOS
|
||||||
|
|
||||||
|
elsif target_ore and mats = $ore_veins.keys.find_all { |k|
|
||||||
|
ino = df.world.raws.inorganics[k]
|
||||||
|
ino.id =~ /#{target_ore}/i or ino.metal_ore.mat_index.find { |m|
|
||||||
|
df.world.raws.inorganics[m].id =~ /#{target_ore}/i
|
||||||
|
}
|
||||||
|
} and not mats.empty?
|
||||||
|
pos = nil
|
||||||
|
dxs = (0..15).sort_by { rand }
|
||||||
|
dys = (0..15).sort_by { rand }
|
||||||
|
if found_mat = mats.sort_by { rand }.find { |mat|
|
||||||
|
$ore_veins[mat].sort_by { rand }.find { |bx, by, bz|
|
||||||
|
dys.find { |dy|
|
||||||
|
dxs.find { |dx|
|
||||||
|
tile = df.map_tile_at(bx+dx, by+dy, bz)
|
||||||
|
if tile.tilemat == :MINERAL and tile.designation.dig == :No and tile.shape == :WALL and
|
||||||
|
tile.mat_index_vein == mat and
|
||||||
|
# ignore map borders
|
||||||
|
bx+dx > 0 and bx+dx < df.world.map.x_count-1 and by+dy > 0 and by+dy < df.world.map.y_count-1
|
||||||
|
pos = [bx+dx, by+dy, bz]
|
||||||
|
end
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
df.center_viewscreen(*pos)
|
||||||
|
df.map_tile_at(*pos).dig
|
||||||
|
puts "Here is some #{df.world.raws.inorganics[found_mat].id}"
|
||||||
|
else
|
||||||
|
puts "Cannot find unmined #{mats.map { |mat| df.world.raws.inorganics[mat].id }.join(', ')}"
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
puts "Available ores:", $ore_veins.sort_by { |mat, pos| pos.length }.map { |mat, pos|
|
||||||
|
ore = df.world.raws.inorganics[mat]
|
||||||
|
metals = ore.metal_ore.mat_index.map { |m| df.world.raws.inorganics[m] }
|
||||||
|
' ' + ore.id.downcase + ' (' + metals.map { |m| m.id.downcase }.join(', ') + ')'
|
||||||
|
}
|
||||||
|
|
||||||
|
end
|
@ -1,56 +0,0 @@
|
|||||||
# create an infinite magma source at the cursor
|
|
||||||
|
|
||||||
$magma_sources ||= []
|
|
||||||
|
|
||||||
case $script_args[0]
|
|
||||||
when 'here'
|
|
||||||
$magma_onupdate ||= df.onupdate_register('magmasource', 12) {
|
|
||||||
# called every 12 game ticks (100x a dwarf day)
|
|
||||||
if $magma_sources.empty?
|
|
||||||
df.onupdate_unregister($magma_onupdate)
|
|
||||||
$magma_onupdate = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
$magma_sources.each { |x, y, z|
|
|
||||||
if tile = df.map_tile_at(x, y, z) and tile.shape_passableflow
|
|
||||||
des = tile.designation
|
|
||||||
tile.spawn_magma(des.flow_size + 1) if des.flow_size < 7
|
|
||||||
end
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if df.cursor.x != -30000
|
|
||||||
if tile = df.map_tile_at(df.cursor)
|
|
||||||
if tile.shape_passableflow
|
|
||||||
$magma_sources << [df.cursor.x, df.cursor.y, df.cursor.z]
|
|
||||||
else
|
|
||||||
puts "Impassable tile: I'm afraid I can't do that, Dave"
|
|
||||||
end
|
|
||||||
else
|
|
||||||
puts "Unallocated map block - build something here first"
|
|
||||||
end
|
|
||||||
else
|
|
||||||
puts "Please put the game cursor where you want a magma source"
|
|
||||||
end
|
|
||||||
|
|
||||||
when 'delete-here'
|
|
||||||
$magma_sources.delete [df.cursor.x, df.cursor.y, df.cursor.z]
|
|
||||||
|
|
||||||
when 'stop'
|
|
||||||
$magma_sources.clear
|
|
||||||
|
|
||||||
else
|
|
||||||
puts <<EOS
|
|
||||||
Creates a new infinite magma source at the cursor.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
here - create a new source at the current cursor position
|
|
||||||
(call multiple times for higher flow)
|
|
||||||
delete-here - delete the source under the cursor
|
|
||||||
stop - delete all created magma sources
|
|
||||||
EOS
|
|
||||||
|
|
||||||
if $magma_sources.first
|
|
||||||
puts '', 'Current magma sources:', $magma_sources.map { |s| " #{s.inspect}" }
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,40 +1,40 @@
|
|||||||
# pit all caged creatures in a zone
|
# pit all caged creatures in a zone
|
||||||
|
|
||||||
case $script_args[0]
|
case $script_args[0]
|
||||||
when '?', 'help'
|
when '?', 'help'
|
||||||
puts <<EOS
|
puts <<EOS
|
||||||
Run this script with the cursor on top of a pit/pond activity zone, or with a zone identifier as argument.
|
Run this script with the cursor on top of a pit/pond activity zone, or with a zone identifier as argument.
|
||||||
It will mark all caged creatures on tiles covered by the zone to be dumped.
|
It will mark all caged creatures on tiles covered by the zone to be dumped.
|
||||||
Works best with an animal stockpile on top of the pit/pond zone.
|
Works best with an animal stockpile on top of the pit/pond zone.
|
||||||
EOS
|
EOS
|
||||||
throw :script_finished
|
throw :script_finished
|
||||||
|
|
||||||
when /(\d+)/
|
when /(\d+)/
|
||||||
nr = $1.to_i
|
nr = $1.to_i
|
||||||
bld = df.world.buildings.other[:ACTIVITY_ZONE].find { |zone| zone.zone_num == nr }
|
bld = df.world.buildings.other[:ACTIVITY_ZONE].find { |zone| zone.zone_num == nr }
|
||||||
|
|
||||||
else
|
else
|
||||||
bld = df.world.buildings.other[:ACTIVITY_ZONE].find { |zone|
|
bld = df.world.buildings.other[:ACTIVITY_ZONE].find { |zone|
|
||||||
zone.zone_flags.pit_pond and zone.z == df.cursor.z and
|
zone.zone_flags.pit_pond and zone.z == df.cursor.z and
|
||||||
zone.x1 <= df.cursor.x and zone.x2 >= df.cursor.x and zone.y1 <= df.cursor.y and zone.y2 >= df.cursor.y
|
zone.x1 <= df.cursor.x and zone.x2 >= df.cursor.x and zone.y1 <= df.cursor.y and zone.y2 >= df.cursor.y
|
||||||
}
|
}
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if not bld
|
if not bld
|
||||||
puts "Please select a pit/pond zone"
|
puts "Please select a pit/pond zone"
|
||||||
throw :script_finished
|
throw :script_finished
|
||||||
end
|
end
|
||||||
|
|
||||||
found = 0
|
found = 0
|
||||||
df.world.items.other[:CAGE].each { |cg|
|
df.world.items.other[:CAGE].each { |cg|
|
||||||
next if not cg.flags.on_ground
|
next if not cg.flags.on_ground
|
||||||
next if cg.pos.z != bld.z or cg.pos.x < bld.x1 or cg.pos.x > bld.x2 or cg.pos.y < bld.y1 or cg.pos.y > bld.y2
|
next if cg.pos.z != bld.z or cg.pos.x < bld.x1 or cg.pos.x > bld.x2 or cg.pos.y < bld.y1 or cg.pos.y > bld.y2
|
||||||
next if not uref = cg.general_refs.grep(DFHack::GeneralRefContainsUnitst).first
|
next if not uref = cg.general_refs.grep(DFHack::GeneralRefContainsUnitst).first
|
||||||
found += 1
|
found += 1
|
||||||
u = uref.unit_tg
|
u = uref.unit_tg
|
||||||
puts "Pitting #{u.race_tg.name[0]} #{u.id} #{u.name}"
|
puts "Pitting #{u.race_tg.name[0]} #{u.id} #{u.name}"
|
||||||
u.general_refs << DFHack::GeneralRefBuildingCivzoneAssignedst.cpp_new(:building_id => bld.id)
|
u.general_refs << DFHack::GeneralRefBuildingCivzoneAssignedst.cpp_new(:building_id => bld.id)
|
||||||
bld.assigned_creature << u.id
|
bld.assigned_creature << u.id
|
||||||
}
|
}
|
||||||
puts "No creature available for pitting" if found == 0
|
puts "No creature available for pitting" if found == 0
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
# run many dfhack commands separated by ;
|
||||||
|
# ex: multicmd locate-ore IRON ; digv ; digcircle 16
|
||||||
|
|
||||||
|
$script_args.join(' ').split(/\s*;\s*/).each { |cmd| df.dfhack_run cmd }
|
@ -1,43 +1,43 @@
|
|||||||
# remove bad thoughts for the selected unit or the whole fort
|
# remove bad thoughts for the selected unit or the whole fort
|
||||||
|
|
||||||
dry_run = $script_args.delete('--dry-run') || $script_args.delete('-n')
|
dry_run = $script_args.delete('--dry-run') || $script_args.delete('-n')
|
||||||
|
|
||||||
$script_args << 'all' if dry_run and $script_args.empty?
|
$script_args << 'all' if dry_run and $script_args.empty?
|
||||||
|
|
||||||
seenbad = Hash.new(0)
|
seenbad = Hash.new(0)
|
||||||
|
|
||||||
clear_mind = lambda { |u|
|
clear_mind = lambda { |u|
|
||||||
u.status.recent_events.each { |e|
|
u.status.recent_events.each { |e|
|
||||||
next if DFHack::UnitThoughtType::Value[e.type].to_s[0, 1] != '-'
|
next if DFHack::UnitThoughtType::Value[e.type].to_s[0, 1] != '-'
|
||||||
seenbad[e.type] += 1
|
seenbad[e.type] += 1
|
||||||
e.age = 0x1000_0000 unless dry_run
|
e.age = 0x1000_0000 unless dry_run
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
summary = lambda {
|
summary = lambda {
|
||||||
seenbad.sort_by { |thought, cnt| cnt }.each { |thought, cnt|
|
seenbad.sort_by { |thought, cnt| cnt }.each { |thought, cnt|
|
||||||
puts " #{thought} #{cnt}"
|
puts " #{thought} #{cnt}"
|
||||||
}
|
}
|
||||||
count = seenbad.values.inject(0) { |sum, cnt| sum+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
|
puts "Removed #{count} bad thought#{'s' if count != 1}." if count > 0 and not dry_run
|
||||||
}
|
}
|
||||||
|
|
||||||
case $script_args[0]
|
case $script_args[0]
|
||||||
when 'him'
|
when 'him'
|
||||||
if u = df.unit_find
|
if u = df.unit_find
|
||||||
clear_mind[u]
|
clear_mind[u]
|
||||||
summary[]
|
summary[]
|
||||||
else
|
else
|
||||||
puts 'Please select a dwarf ingame'
|
puts 'Please select a dwarf ingame'
|
||||||
end
|
end
|
||||||
|
|
||||||
when 'all'
|
when 'all'
|
||||||
df.unit_citizens.each { |uu|
|
df.unit_citizens.each { |uu|
|
||||||
clear_mind[uu]
|
clear_mind[uu]
|
||||||
}
|
}
|
||||||
summary[]
|
summary[]
|
||||||
|
|
||||||
else
|
else
|
||||||
puts "Usage: removebadthoughts [--dry-run] <him|all>"
|
puts "Usage: removebadthoughts [--dry-run] <him|all>"
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -0,0 +1,83 @@
|
|||||||
|
# create an infinite magma/water source/drain at the cursor
|
||||||
|
|
||||||
|
$sources ||= []
|
||||||
|
|
||||||
|
cur_source = {
|
||||||
|
:liquid => 'water',
|
||||||
|
:amount => 7,
|
||||||
|
:pos => [df.cursor.x, df.cursor.y, df.cursor.z]
|
||||||
|
}
|
||||||
|
cmd = 'help'
|
||||||
|
|
||||||
|
$script_args.each { |a|
|
||||||
|
case a.downcase
|
||||||
|
when 'water', 'magma'
|
||||||
|
cur_source[:liquid] = a.downcase
|
||||||
|
when /^\d+$/
|
||||||
|
cur_source[:amount] = a.to_i
|
||||||
|
when 'add', 'del', 'delete', 'clear', 'help', 'list'
|
||||||
|
cmd = a.downcase
|
||||||
|
else
|
||||||
|
puts "source: unhandled argument #{a}"
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
case cmd
|
||||||
|
when 'add'
|
||||||
|
$sources_onupdate ||= df.onupdate_register('sources', 12) {
|
||||||
|
# called every 12 game ticks (100x a dwarf day)
|
||||||
|
$sources.each { |s|
|
||||||
|
if tile = df.map_tile_at(*s[:pos]) and tile.shape_passableflow
|
||||||
|
# XXX does not check current liquid_type
|
||||||
|
des = tile.designation
|
||||||
|
cur = des.flow_size
|
||||||
|
if cur != s[:amount]
|
||||||
|
tile.spawn_liquid((cur > s[:amount] ? cur-1 : cur+1), s[:liquid] == 'magma')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}
|
||||||
|
if $sources.empty?
|
||||||
|
df.onupdate_unregister($sources_onupdate)
|
||||||
|
$sources_onupdate = nil
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
if cur_source[:pos][0] >= 0
|
||||||
|
if tile = df.map_tile_at(*cur_source[:pos])
|
||||||
|
if tile.shape_passableflow
|
||||||
|
$sources << cur_source
|
||||||
|
else
|
||||||
|
puts "Impassable tile: I'm afraid I can't do that, Dave"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
puts "Unallocated map block - build something here first"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
puts "Please put the game cursor where you want a source"
|
||||||
|
end
|
||||||
|
|
||||||
|
when 'del', 'delete'
|
||||||
|
$sources.delete_if { |s| s[:pos] == cur_source[:pos] }
|
||||||
|
|
||||||
|
when 'clear'
|
||||||
|
$sources.clear
|
||||||
|
|
||||||
|
when 'list'
|
||||||
|
puts "Source list:", $sources.map { |s|
|
||||||
|
" #{s[:pos].inspect} #{s[:liquid]} #{s[:amount]}"
|
||||||
|
}
|
||||||
|
puts "Current cursor pos: #{[df.cursor.x, df.cursor.y, df.cursor.z].inspect}" if df.cursor.x >= 0
|
||||||
|
|
||||||
|
else
|
||||||
|
puts <<EOS
|
||||||
|
Creates a new infinite liquid source at the cursor.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
source add water - create a water source under cursor
|
||||||
|
source add water 0 - create a water drain
|
||||||
|
source add magma 5 - create a magma source, up to 5/7 deep
|
||||||
|
source delete - delete source under cursor
|
||||||
|
source clear - remove all sources
|
||||||
|
source list
|
||||||
|
EOS
|
||||||
|
end
|
@ -1,204 +1,204 @@
|
|||||||
# mark stuff inside of cages for dumping.
|
# mark stuff inside of cages for dumping.
|
||||||
|
|
||||||
def plural(nr, name)
|
def plural(nr, name)
|
||||||
# '1 cage' / '4 cages'
|
# '1 cage' / '4 cages'
|
||||||
"#{nr} #{name}#{'s' if nr > 1}"
|
"#{nr} #{name}#{'s' if nr > 1}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def cage_dump_items(list)
|
def cage_dump_items(list)
|
||||||
count = 0
|
count = 0
|
||||||
count_cage = 0
|
count_cage = 0
|
||||||
list.each { |cage|
|
list.each { |cage|
|
||||||
pre_count = count
|
pre_count = count
|
||||||
cage.general_refs.each { |ref|
|
cage.general_refs.each { |ref|
|
||||||
next unless ref.kind_of?(DFHack::GeneralRefContainsItemst)
|
next unless ref.kind_of?(DFHack::GeneralRefContainsItemst)
|
||||||
next if ref.item_tg.flags.dump
|
next if ref.item_tg.flags.dump
|
||||||
count += 1
|
count += 1
|
||||||
ref.item_tg.flags.dump = true
|
ref.item_tg.flags.dump = true
|
||||||
}
|
}
|
||||||
count_cage += 1 if pre_count != count
|
count_cage += 1 if pre_count != count
|
||||||
}
|
}
|
||||||
|
|
||||||
puts "Dumped #{plural(count, 'item')} in #{plural(count_cage, 'cage')}"
|
puts "Dumped #{plural(count, 'item')} in #{plural(count_cage, 'cage')}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def cage_dump_armor(list)
|
def cage_dump_armor(list)
|
||||||
count = 0
|
count = 0
|
||||||
count_cage = 0
|
count_cage = 0
|
||||||
list.each { |cage|
|
list.each { |cage|
|
||||||
pre_count = count
|
pre_count = count
|
||||||
cage.general_refs.each { |ref|
|
cage.general_refs.each { |ref|
|
||||||
next unless ref.kind_of?(DFHack::GeneralRefContainsUnitst)
|
next unless ref.kind_of?(DFHack::GeneralRefContainsUnitst)
|
||||||
ref.unit_tg.inventory.each { |it|
|
ref.unit_tg.inventory.each { |it|
|
||||||
next if it.mode != :Worn
|
next if it.mode != :Worn
|
||||||
next if it.item.flags.dump
|
next if it.item.flags.dump
|
||||||
count += 1
|
count += 1
|
||||||
it.item.flags.dump = true
|
it.item.flags.dump = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
count_cage += 1 if pre_count != count
|
count_cage += 1 if pre_count != count
|
||||||
}
|
}
|
||||||
|
|
||||||
puts "Dumped #{plural(count, 'armor piece')} in #{plural(count_cage, 'cage')}"
|
puts "Dumped #{plural(count, 'armor piece')} in #{plural(count_cage, 'cage')}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def cage_dump_weapons(list)
|
def cage_dump_weapons(list)
|
||||||
count = 0
|
count = 0
|
||||||
count_cage = 0
|
count_cage = 0
|
||||||
list.each { |cage|
|
list.each { |cage|
|
||||||
pre_count = count
|
pre_count = count
|
||||||
cage.general_refs.each { |ref|
|
cage.general_refs.each { |ref|
|
||||||
next unless ref.kind_of?(DFHack::GeneralRefContainsUnitst)
|
next unless ref.kind_of?(DFHack::GeneralRefContainsUnitst)
|
||||||
ref.unit_tg.inventory.each { |it|
|
ref.unit_tg.inventory.each { |it|
|
||||||
next if it.mode != :Weapon
|
next if it.mode != :Weapon
|
||||||
next if it.item.flags.dump
|
next if it.item.flags.dump
|
||||||
count += 1
|
count += 1
|
||||||
it.item.flags.dump = true
|
it.item.flags.dump = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
count_cage += 1 if pre_count != count
|
count_cage += 1 if pre_count != count
|
||||||
}
|
}
|
||||||
|
|
||||||
puts "Dumped #{plural(count, 'weapon')} in #{plural(count_cage, 'cage')}"
|
puts "Dumped #{plural(count, 'weapon')} in #{plural(count_cage, 'cage')}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def cage_dump_all(list)
|
def cage_dump_all(list)
|
||||||
count = 0
|
count = 0
|
||||||
count_cage = 0
|
count_cage = 0
|
||||||
list.each { |cage|
|
list.each { |cage|
|
||||||
pre_count = count
|
pre_count = count
|
||||||
cage.general_refs.each { |ref|
|
cage.general_refs.each { |ref|
|
||||||
case ref
|
case ref
|
||||||
when DFHack::GeneralRefContainsItemst
|
when DFHack::GeneralRefContainsItemst
|
||||||
next if ref.item_tg.flags.dump
|
next if ref.item_tg.flags.dump
|
||||||
count += 1
|
count += 1
|
||||||
ref.item_tg.flags.dump = true
|
ref.item_tg.flags.dump = true
|
||||||
when DFHack::GeneralRefContainsUnitst
|
when DFHack::GeneralRefContainsUnitst
|
||||||
ref.unit_tg.inventory.each { |it|
|
ref.unit_tg.inventory.each { |it|
|
||||||
next if it.item.flags.dump
|
next if it.item.flags.dump
|
||||||
count += 1
|
count += 1
|
||||||
it.item.flags.dump = true
|
it.item.flags.dump = true
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
count_cage += 1 if pre_count != count
|
count_cage += 1 if pre_count != count
|
||||||
}
|
}
|
||||||
|
|
||||||
puts "Dumped #{plural(count, 'item')} in #{plural(count_cage, 'cage')}"
|
puts "Dumped #{plural(count, 'item')} in #{plural(count_cage, 'cage')}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def cage_dump_list(list)
|
def cage_dump_list(list)
|
||||||
count_total = Hash.new(0)
|
count_total = Hash.new(0)
|
||||||
empty_cages = 0
|
empty_cages = 0
|
||||||
list.each { |cage|
|
list.each { |cage|
|
||||||
count = Hash.new(0)
|
count = Hash.new(0)
|
||||||
|
|
||||||
cage.general_refs.each { |ref|
|
cage.general_refs.each { |ref|
|
||||||
case ref
|
case ref
|
||||||
when DFHack::GeneralRefContainsItemst
|
when DFHack::GeneralRefContainsItemst
|
||||||
count[ref.item_tg._rtti_classname] += 1
|
count[ref.item_tg._rtti_classname] += 1
|
||||||
when DFHack::GeneralRefContainsUnitst
|
when DFHack::GeneralRefContainsUnitst
|
||||||
ref.unit_tg.inventory.each { |it|
|
ref.unit_tg.inventory.each { |it|
|
||||||
count[it.item._rtti_classname] += 1
|
count[it.item._rtti_classname] += 1
|
||||||
}
|
}
|
||||||
# TODO vermin ?
|
# TODO vermin ?
|
||||||
else
|
else
|
||||||
puts "unhandled ref #{ref.inspect}" if $DEBUG
|
puts "unhandled ref #{ref.inspect}" if $DEBUG
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
type = case cage
|
type = case cage
|
||||||
when DFHack::ItemCagest; 'Cage'
|
when DFHack::ItemCagest; 'Cage'
|
||||||
when DFHack::ItemAnimaltrapst; 'Animal trap'
|
when DFHack::ItemAnimaltrapst; 'Animal trap'
|
||||||
else cage._rtti_classname
|
else cage._rtti_classname
|
||||||
end
|
end
|
||||||
|
|
||||||
if count.empty?
|
if count.empty?
|
||||||
empty_cages += 1
|
empty_cages += 1
|
||||||
else
|
else
|
||||||
puts "#{type} ##{cage.id}: ", count.sort_by { |k, v| v }.map { |k, v| " #{v} #{k}" }
|
puts "#{type} ##{cage.id}: ", count.sort_by { |k, v| v }.map { |k, v| " #{v} #{k}" }
|
||||||
end
|
end
|
||||||
|
|
||||||
count.each { |k, v| count_total[k] += v }
|
count.each { |k, v| count_total[k] += v }
|
||||||
}
|
}
|
||||||
|
|
||||||
if list.length > 2
|
if list.length > 2
|
||||||
puts '', "Total: ", count_total.sort_by { |k, v| v }.map { |k, v| " #{v} #{k}" }
|
puts '', "Total: ", count_total.sort_by { |k, v| v }.map { |k, v| " #{v} #{k}" }
|
||||||
puts "with #{plural(empty_cages, 'empty cage')}"
|
puts "with #{plural(empty_cages, 'empty cage')}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
# handle magic script arguments
|
# handle magic script arguments
|
||||||
here_only = $script_args.delete 'here'
|
here_only = $script_args.delete 'here'
|
||||||
if here_only
|
if here_only
|
||||||
it = df.item_find
|
it = df.item_find
|
||||||
list = [it]
|
list = [it]
|
||||||
if not it.kind_of?(DFHack::ItemCagest) and not it.kind_of?(DFHack::ItemAnimaltrapst)
|
if not it.kind_of?(DFHack::ItemCagest) and not it.kind_of?(DFHack::ItemAnimaltrapst)
|
||||||
list = df.world.items.other[:ANY_CAGE_OR_TRAP].find_all { |i| df.at_cursor?(i) }
|
list = df.world.items.other[:ANY_CAGE_OR_TRAP].find_all { |i| df.at_cursor?(i) }
|
||||||
end
|
end
|
||||||
if list.empty?
|
if list.empty?
|
||||||
puts 'Please select a cage'
|
puts 'Please select a cage'
|
||||||
throw :script_finished
|
throw :script_finished
|
||||||
end
|
end
|
||||||
|
|
||||||
elsif ids = $script_args.find_all { |arg| arg =~ /^\d+$/ } and ids.first
|
elsif ids = $script_args.find_all { |arg| arg =~ /^\d+$/ } and ids.first
|
||||||
list = []
|
list = []
|
||||||
ids.each { |id|
|
ids.each { |id|
|
||||||
$script_args.delete id
|
$script_args.delete id
|
||||||
if not it = df.item_find(id.to_i)
|
if not it = df.item_find(id.to_i)
|
||||||
puts "Invalid item id #{id}"
|
puts "Invalid item id #{id}"
|
||||||
elsif not it.kind_of?(DFHack::ItemCagest) and not it.kind_of?(DFHack::ItemAnimaltrapst)
|
elsif not it.kind_of?(DFHack::ItemCagest) and not it.kind_of?(DFHack::ItemAnimaltrapst)
|
||||||
puts "Item ##{id} is not a cage"
|
puts "Item ##{id} is not a cage"
|
||||||
list << it
|
list << it
|
||||||
else
|
else
|
||||||
list << it
|
list << it
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
if list.empty?
|
if list.empty?
|
||||||
puts 'Please use a valid cage id'
|
puts 'Please use a valid cage id'
|
||||||
throw :script_finished
|
throw :script_finished
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
list = df.world.items.other[:ANY_CAGE_OR_TRAP]
|
list = df.world.items.other[:ANY_CAGE_OR_TRAP]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
# act
|
# act
|
||||||
case $script_args[0]
|
case $script_args[0]
|
||||||
when /^it/i
|
when /^it/i
|
||||||
cage_dump_items(list)
|
cage_dump_items(list)
|
||||||
when /^arm/i
|
when /^arm/i
|
||||||
cage_dump_armor(list)
|
cage_dump_armor(list)
|
||||||
when /^wea/i
|
when /^wea/i
|
||||||
cage_dump_weapons(list)
|
cage_dump_weapons(list)
|
||||||
when 'all'
|
when 'all'
|
||||||
cage_dump_all(list)
|
cage_dump_all(list)
|
||||||
when 'list'
|
when 'list'
|
||||||
cage_dump_list(list)
|
cage_dump_list(list)
|
||||||
else
|
else
|
||||||
puts <<EOS
|
puts <<EOS
|
||||||
Marks items inside all cages for dumping.
|
Marks items inside all cages for dumping.
|
||||||
Add 'here' to dump stuff only for selected cage.
|
Add 'here' to dump stuff only for selected cage.
|
||||||
Add a cage id to dump stuff for this cage only.
|
Add a cage id to dump stuff for this cage only.
|
||||||
|
|
||||||
See 'autodump' to actually dump stuff.
|
See 'autodump' to actually dump stuff.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
stripcaged items
|
stripcaged items
|
||||||
dump items directly in cages (eg seeds after training)
|
dump items directly in cages (eg seeds after training)
|
||||||
|
|
||||||
stripcaged [armor|weapons] here
|
stripcaged [armor|weapons] here
|
||||||
dump armor or weapons of caged creatures in selected cage
|
dump armor or weapons of caged creatures in selected cage
|
||||||
|
|
||||||
stripcaged all 28 29
|
stripcaged all 28 29
|
||||||
dump every item in cage id 28 and 29, along with every item worn by creatures in there too
|
dump every item in cage id 28 and 29, along with every item worn by creatures in there too
|
||||||
|
|
||||||
stripcaged list
|
stripcaged list
|
||||||
show content of the cages
|
show content of the cages
|
||||||
|
|
||||||
EOS
|
EOS
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -1,61 +1,61 @@
|
|||||||
# give super-dwarven speed to an unit
|
# give super-dwarven speed to an unit
|
||||||
|
|
||||||
$superdwarf_onupdate ||= nil
|
$superdwarf_onupdate ||= nil
|
||||||
$superdwarf_ids ||= []
|
$superdwarf_ids ||= []
|
||||||
|
|
||||||
case $script_args[0]
|
case $script_args[0]
|
||||||
when 'add'
|
when 'add'
|
||||||
if u = df.unit_find
|
if u = df.unit_find
|
||||||
$superdwarf_ids |= [u.id]
|
$superdwarf_ids |= [u.id]
|
||||||
|
|
||||||
$superdwarf_onupdate ||= df.onupdate_register('superdwarf', 1) {
|
$superdwarf_onupdate ||= df.onupdate_register('superdwarf', 1) {
|
||||||
if $superdwarf_ids.empty?
|
if $superdwarf_ids.empty?
|
||||||
df.onupdate_unregister($superdwarf_onupdate)
|
df.onupdate_unregister($superdwarf_onupdate)
|
||||||
$superdwarf_onupdate = nil
|
$superdwarf_onupdate = nil
|
||||||
else
|
else
|
||||||
$superdwarf_ids.each { |id|
|
$superdwarf_ids.each { |id|
|
||||||
if u = df.unit_find(id) and not u.flags1.dead
|
if u = df.unit_find(id) and not u.flags1.dead
|
||||||
# faster walk/work
|
# faster walk/work
|
||||||
if u.counters.job_counter > 0
|
if u.counters.job_counter > 0
|
||||||
u.counters.job_counter = 0
|
u.counters.job_counter = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
# no sleep
|
# no sleep
|
||||||
if u.counters2.sleepiness_timer > 10000
|
if u.counters2.sleepiness_timer > 10000
|
||||||
u.counters2.sleepiness_timer = 1
|
u.counters2.sleepiness_timer = 1
|
||||||
end
|
end
|
||||||
|
|
||||||
# no break
|
# no break
|
||||||
if b = u.status.misc_traits.find { |t| t.id == :OnBreak }
|
if b = u.status.misc_traits.find { |t| t.id == :OnBreak }
|
||||||
b.value = 500_000
|
b.value = 500_000
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
$superdwarf_ids.delete id
|
$superdwarf_ids.delete id
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
puts "Select a creature using 'v'"
|
puts "Select a creature using 'v'"
|
||||||
end
|
end
|
||||||
|
|
||||||
when 'del'
|
when 'del'
|
||||||
if u = df.unit_find
|
if u = df.unit_find
|
||||||
$superdwarf_ids.delete u.id
|
$superdwarf_ids.delete u.id
|
||||||
else
|
else
|
||||||
puts "Select a creature using 'v'"
|
puts "Select a creature using 'v'"
|
||||||
end
|
end
|
||||||
|
|
||||||
when 'clear'
|
when 'clear'
|
||||||
$superdwarf_ids.clear
|
$superdwarf_ids.clear
|
||||||
|
|
||||||
when 'list'
|
when 'list'
|
||||||
puts "current superdwarves:", $superdwarf_ids.map { |id| df.unit_find(id).name }
|
puts "current superdwarves:", $superdwarf_ids.map { |id| df.unit_find(id).name }
|
||||||
|
|
||||||
else
|
else
|
||||||
puts "Usage:",
|
puts "Usage:",
|
||||||
" - superdwarf add: give superspeed to currently selected creature",
|
" - superdwarf add: give superspeed to currently selected creature",
|
||||||
" - superdwarf del: remove superspeed to current creature",
|
" - superdwarf del: remove superspeed to current creature",
|
||||||
" - superdwarf clear: remove all superpowers",
|
" - superdwarf clear: remove all superpowers",
|
||||||
" - superdwarf list: list super-dwarves"
|
" - superdwarf list: list super-dwarves"
|
||||||
end
|
end
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
joblist = df.world.job_list.next
|
joblist = df.world.job_list.next
|
||||||
count = 0
|
count = 0
|
||||||
|
|
||||||
while joblist
|
while joblist
|
||||||
job = joblist.item
|
job = joblist.item
|
||||||
joblist = joblist.next
|
joblist = joblist.next
|
||||||
|
|
||||||
if job.job_type == :ConstructBuilding
|
if job.job_type == :ConstructBuilding
|
||||||
if (job.flags.suspend && job.items && job.items[0])
|
if (job.flags.suspend && job.items && job.items[0])
|
||||||
item = job.items[0].item
|
item = job.items[0].item
|
||||||
job.flags.suspend = false
|
job.flags.suspend = false
|
||||||
count += 1
|
count += 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
puts "Unsuspended #{count} job(s)."
|
puts "Unsuspended #{count} job(s)."
|
||||||
|
Loading…
Reference in New Issue