ruby: add building creation code
parent
ea6e207290
commit
2629db5ed1
@ -1,70 +0,0 @@
|
||||
module DFHack
|
||||
def self.buildbedhere
|
||||
suspend {
|
||||
raise 'where to ?' if cursor.x < 0
|
||||
|
||||
item = world.items.all.find { |i|
|
||||
i.kind_of?(ItemBedst) and
|
||||
i.itemrefs.empty? and
|
||||
!i.flags.in_job
|
||||
}
|
||||
raise 'no free bed, build more !' if not item
|
||||
|
||||
job = Job.cpp_new
|
||||
jobitemref = JobItemRef.cpp_new
|
||||
refbuildingholder = GeneralRefBuildingHolderst.cpp_new
|
||||
building = BuildingBedst.cpp_new
|
||||
itemjob = SpecificRef.cpp_new
|
||||
|
||||
buildingid = df.building_next_id
|
||||
df.building_next_id += 1
|
||||
|
||||
job.job_type = :ConstructBuilding
|
||||
job.pos = cursor
|
||||
job.mat_type = item.mat_type
|
||||
job.mat_index = item.mat_index
|
||||
job.hist_figure_id = -1
|
||||
job.items << jobitemref
|
||||
job.references << refbuildingholder
|
||||
|
||||
jobitemref.item = item
|
||||
jobitemref.role = :Hauled
|
||||
jobitemref.job_item_idx = -1
|
||||
|
||||
refbuildingholder.building_id = buildingid
|
||||
|
||||
building.x1 = building.x2 = building.centerx = cursor.x
|
||||
building.y1 = building.y2 = building.centery = cursor.y
|
||||
building.z = cursor.z
|
||||
building.mat_type = item.mat_type
|
||||
building.mat_index = item.mat_index
|
||||
building.race = ui.race_id
|
||||
building.id = buildingid
|
||||
building.jobs << job
|
||||
building.specific_squad = -1
|
||||
|
||||
itemjob.type = :JOB
|
||||
itemjob.job = job
|
||||
|
||||
item.flags.in_job = true
|
||||
item.specific_refs << itemjob
|
||||
|
||||
map_block_at(cursor).occupancy[cursor.x%16][cursor.y%16].building = :Planned
|
||||
link_job job
|
||||
world.buildings.all << building
|
||||
building.categorize(true)
|
||||
}
|
||||
end
|
||||
def self.deconstructbldhere
|
||||
suspend {
|
||||
raise "'q'uery a building" if ui.main.mode != :QueryBuilding or not building = world.selected_building
|
||||
job = Job.cpp_new
|
||||
refbuildingholder = GeneralRefBuildingHolderst.cpp_new
|
||||
job.job_type = :DestroyBuilding
|
||||
refbuildingholder.building_id = building.id
|
||||
job.references << refbuildingholder
|
||||
building.jobs << job
|
||||
link_job job
|
||||
}
|
||||
end
|
||||
end
|
@ -0,0 +1,267 @@
|
||||
module DFHack
|
||||
|
||||
# allocate a new building object
|
||||
def self.building_alloc(type, subtype=-1, custom=-1)
|
||||
type = BuildingType.to_sym(type)
|
||||
cls = rtti_n2c[BuildingType::Classname[type].to_sym]
|
||||
raise "invalid building type #{type.inspect}" if not cls
|
||||
bld = cls.cpp_new
|
||||
bld.race = ui.race_id
|
||||
bld.setSubtype(subtype) if subtype != -1
|
||||
bld.setCustomType(custom) if custom != -1
|
||||
case type
|
||||
when :Furnace; bld.melt_remainder[world.raws.inorganics.length] = 0
|
||||
when :Coffin; bld.initBurialFlags
|
||||
when :Trap; bld.unk_cc = 500 if bld.trap_type == :PressurePlate
|
||||
end
|
||||
bld
|
||||
end
|
||||
|
||||
# used by building_setsize
|
||||
def self.building_check_bridge_support(bld)
|
||||
x1 = bld.x1-1
|
||||
x2 = bld.x2+1
|
||||
y1 = bld.y1-1
|
||||
y2 = bld.y2+1
|
||||
z = bld.z
|
||||
(x1..x2).each { |x|
|
||||
(y1..y2).each { |y|
|
||||
next if ((x == x1 or x == x2) and
|
||||
(y == y1 or y == y2))
|
||||
if mb = map_block_at(x, y, z) and tile = mb.tiletype[x%16][y%16] and TiletypeShape::BasicShape[Tiletype::Shape[tile]] == :Open
|
||||
bld.gate_flags.has_support = true
|
||||
return
|
||||
end
|
||||
}
|
||||
}
|
||||
bld.gate_flags.has_support = false
|
||||
end
|
||||
|
||||
# sets x2/centerx/y2/centery from x1/y1/bldtype
|
||||
# x2/y2 preserved for :FarmPlot etc
|
||||
def self.building_setsize(bld)
|
||||
bld.x2 = bld.x1 if bld.x1 > bld.x2
|
||||
bld.y2 = bld.y1 if bld.y1 > bld.y2
|
||||
case bld.getType
|
||||
when :Bridge
|
||||
bld.centerx = bld.x1 + (bld.x2+1-bld.x1)/2
|
||||
bld.centery = bld.y1 + (bld.y2+1-bld.y1)/2
|
||||
building_check_bridge_support(bld)
|
||||
when :FarmPlot, :RoadDirt, :RoadPaved, :Stockpile, :Civzone
|
||||
bld.centerx = bld.x1 + (bld.x2+1-bld.x1)/2
|
||||
bld.centery = bld.y1 + (bld.y2+1-bld.y1)/2
|
||||
when :TradeDepot, :Shop
|
||||
bld.x2 = bld.x1+4
|
||||
bld.y2 = bld.y1+4
|
||||
bld.centerx = bld.x1+2
|
||||
bld.centery = bld.y1+2
|
||||
when :SiegeEngine, :Windmill, :Wagon
|
||||
bld.x2 = bld.x1+2
|
||||
bld.y2 = bld.y1+2
|
||||
bld.centerx = bld.x1+1
|
||||
bld.centery = bld.y1+1
|
||||
when :AxleHorizontal
|
||||
if bld.is_vertical == 1
|
||||
bld.x2 = bld.centerx = bld.x1
|
||||
bld.centery = bld.y1 + (bld.y2+1-bld.y1)/2
|
||||
else
|
||||
bld.centerx = bld.x1 + (bld.x2+1-bld.x1)/2
|
||||
bld.y2 = bld.centery = bld.y1
|
||||
end
|
||||
when :WaterWheel
|
||||
if bld.is_vertical == 1
|
||||
bld.x2 = bld.centerx = bld.x1
|
||||
bld.y2 = bld.y1+2
|
||||
bld.centery = bld.y1+1
|
||||
else
|
||||
bld.x2 = bld.x1+2
|
||||
bld.centerx = bld.x1+1
|
||||
bld.y2 = bld.centery = bld.y1
|
||||
end
|
||||
when :Workshop, :Furnace
|
||||
# Furnace = Custom or default case only
|
||||
case bld.type
|
||||
when :Quern, :Millstone, :Tool
|
||||
bld.x2 = bld.centerx = bld.x1
|
||||
bld.y2 = bld.centery = bld.y1
|
||||
when :Siege, :Kennels
|
||||
bld.x2 = bld.x1+4
|
||||
bld.y2 = bld.y1+4
|
||||
bld.centerx = bld.x1+2
|
||||
bld.centery = bld.y1+2
|
||||
when :Custom
|
||||
if bdef = world.raws.buildings.all.binsearch(bld.getCustomType)
|
||||
bld.x2 = bld.x1 + bdef.dim_x - 1
|
||||
bld.y2 = bld.y1 + bdef.dim_y - 1
|
||||
bld.centerx = bld.x1 + bdef.workloc_x
|
||||
bld.centery = bld.y1 + bdef.workloc_y
|
||||
end
|
||||
else
|
||||
bld.x2 = bld.x1+2
|
||||
bld.y2 = bld.y1+2
|
||||
bld.centerx = bld.x1+1
|
||||
bld.centery = bld.y1+1
|
||||
end
|
||||
when :ScrewPump
|
||||
case bld.direction
|
||||
when :FromEast
|
||||
bld.x2 = bld.centerx = bld.x1+1
|
||||
bld.y2 = bld.centery = bld.y1
|
||||
when :FromSouth
|
||||
bld.x2 = bld.centerx = bld.x1
|
||||
bld.y2 = bld.centery = bld.y1+1
|
||||
when :FromWest
|
||||
bld.x2 = bld.x1+1
|
||||
bld.y2 = bld.centery = bld.y1
|
||||
bld.centerx = bld.x1
|
||||
else
|
||||
bld.x2 = bld.x1+1
|
||||
bld.y2 = bld.centery = bld.y1
|
||||
bld.centerx = bld.x1
|
||||
end
|
||||
when :Well
|
||||
bld.bucket_z = bld.z
|
||||
bld.x2 = bld.centerx = bld.x1
|
||||
bld.y2 = bld.centery = bld.y1
|
||||
when :Construction
|
||||
bld.x2 = bld.centerx = bld.x1
|
||||
bld.y2 = bld.centery = bld.y1
|
||||
bld.setMaterialAmount(1)
|
||||
return
|
||||
else
|
||||
bld.x2 = bld.centerx = bld.x1
|
||||
bld.y2 = bld.centery = bld.y1
|
||||
end
|
||||
bld.setMaterialAmount((bld.x2-bld.x1+1)*(bld.y2-bld.y1+1)/4+1)
|
||||
end
|
||||
|
||||
# set building at position, with optional width/height
|
||||
def self.building_position(bld, pos, w=nil, h=nil)
|
||||
bld.x1 = pos.x
|
||||
bld.y1 = pos.y
|
||||
bld.z = pos.z
|
||||
bld.x2 = bld.x1+w-1 if w
|
||||
bld.y2 = bld.y1+h-1 if h
|
||||
building_setsize(bld)
|
||||
end
|
||||
|
||||
# set map occupancy/stockpile/etc for a building
|
||||
def self.building_setoccupancy(bld)
|
||||
stockpile = (bld.getType == :Stockpile)
|
||||
complete = (bld.getBuildStage >= bld.getMaxBuildStage)
|
||||
extents = (bld.room.extents and bld.isExtentShaped)
|
||||
|
||||
z = bld.z
|
||||
(bld.x1..bld.x2).each { |x|
|
||||
(bld.y1..bld.y2).each { |y|
|
||||
next if !extents or bld.room.extents[bld.room.width*(y-bld.room.y)+(x-bld.room.x)] == 0
|
||||
next if not mb = map_block_at(x, y, z)
|
||||
des = mb.designation[x%16][y%16]
|
||||
des.pile = stockpile
|
||||
des.dig = :No
|
||||
if complete
|
||||
bld.updateOccupancy(x, y)
|
||||
else
|
||||
mb.occupancy[x%16][y%16].building = :Planned
|
||||
end
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
# link bld into other rooms if it is inside their extents
|
||||
def self.building_linkrooms(bld)
|
||||
didstuff = false
|
||||
world.buildings.other[:ANY_FREE].each { |ob|
|
||||
next if !ob.is_room or ob.z != bld.z
|
||||
next if !ob.room.extents or !ob.isExtentShaped or ob.room.extents[ob.room.width*(bld.y1-ob.room.y)+(bld.x1-ob.room.x)] == 0
|
||||
didstuff = true
|
||||
ob.children << bld
|
||||
bld.parents << ob
|
||||
}
|
||||
ui.equipment.update.buildings = true if didstuff
|
||||
end
|
||||
|
||||
# link the building into the world, set map data, link rooms, bld.id
|
||||
def self.building_link(bld)
|
||||
bld.id = df.building_next_id
|
||||
df.building_next_id += 1
|
||||
|
||||
world.buildings.all << bld
|
||||
bld.categorize(true)
|
||||
building_setoccupancy(bld) if bld.isSettingOccupancy
|
||||
building_linkrooms(bld)
|
||||
end
|
||||
|
||||
# set a design for the building
|
||||
def self.building_createdesign(bld, rough=true)
|
||||
job = bld.jobs[0]
|
||||
job.mat_type = bld.mat_type
|
||||
job.mat_index = bld.mat_index
|
||||
if bld.needsDesign
|
||||
bld.design = BuildingDesign.cpp_new
|
||||
bld.design.flags.rough = rough
|
||||
end
|
||||
end
|
||||
|
||||
# creates a job to build bld, return it
|
||||
def self.building_linkforconstruct(bld)
|
||||
building_link bld
|
||||
ref = GeneralRefBuildingHolderst.cpp_new
|
||||
ref.building_id = bld.id
|
||||
job = Job.cpp_new
|
||||
job.job_type = :ConstructBuilding
|
||||
job.pos = [bld.centerx, bld.centery, bld.z]
|
||||
job.references << ref
|
||||
bld.jobs << job
|
||||
job_link job
|
||||
job
|
||||
end
|
||||
|
||||
# construct a building with items or JobItems
|
||||
def self.building_construct(bld, items)
|
||||
job = building_linkforconstruct(bld)
|
||||
rough = false
|
||||
items.each { |item|
|
||||
if items.kind_of?(JobItem)
|
||||
item.quantity = (bld.x2-bld.x1+1)*(bld.y2-bld.y1+1)/4+1 if item.quantity < 0
|
||||
job.job_items << item
|
||||
else
|
||||
job_attachitem(job, item, :Hauled)
|
||||
end
|
||||
rough = true if item.getType == :BOULDER
|
||||
bld.mat_type = item.getMaterial if bld.mat_type == -1
|
||||
bld.mat_index = item.getMaterialIndex if bld.mat_index == -1
|
||||
}
|
||||
building_createdesign(bld, rough)
|
||||
end
|
||||
|
||||
# creates a job to deconstruct the building
|
||||
def self.building_deconstruct(bld)
|
||||
job = Job.cpp_new
|
||||
refbuildingholder = GeneralRefBuildingHolderst.cpp_new
|
||||
job.job_type = :DestroyBuilding
|
||||
refbuildingholder.building_id = building.id
|
||||
job.references << refbuildingholder
|
||||
building.jobs << job
|
||||
job_link job
|
||||
job
|
||||
end
|
||||
|
||||
# exemple usage
|
||||
def self.buildbed(pos=cursor)
|
||||
suspend {
|
||||
raise 'where to ?' if pos.x < 0
|
||||
|
||||
item = world.items.all.find { |i|
|
||||
i.kind_of?(ItemBedst) and
|
||||
i.itemrefs.empty? and
|
||||
!i.flags.in_job
|
||||
}
|
||||
raise 'no free bed, build more !' if not item
|
||||
|
||||
bld = building_alloc(:Bed)
|
||||
building_position(bld, pos)
|
||||
building_construct(bld, [item])
|
||||
}
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue