So, I wrote lua script for making natural/smooth walls/floors/fortifications/ramps/stairs/holes. It works in a similar way to Tiletypes plugin, except it has a gui for settings and allows mass selection of tiles. I'm not a coder, so I'm also looking for a feedback, 'cause I probably messed something up.
. Without argument command used to select an area by using it twice in two corners, and argument -s used for settings gui. It also includes paint mode, which can be used to change material of existing tile. It doesn't change materials of soil floors, soil walls, trees. But changes natural/smooth walls, floors etc. and constructed walls, floors etc. (Construction item material currently doesn't change, so if deconstructed it will return original item). More information can be found using 'builder ?'.
local help=[====[
Builder
=======
Builds natural and smooth walls, floors, stairs, ramps, channels
Can be used to change materials of natural and constructed walls.
Usage:
-s, s, -setting, setting
Opens settings gui, where you can specify building mode,
brush type, materials and additional flags.
-r, r, -reset, reset
Resets all setting to default. (building mode - smooth walls,
material - none, change underground/above ground - false,
reveal - true, brush - square)
?, -h, h, -help, help
Shows this help.
(nothing)
Selection mode. Select first tile, use script (easier with
keybindings 'keybinding add Ctrl-Z builder') then select
second tile and watch tiles between them being painted.
Available building modes:
Smooth wall, natural wall, smooth floor, natural floor, stairs,
ramp, channel and paint only.
Example:
To create 4x4 smooth wall, first, use 'builder -s'. In
menu choose building mode - smooth walls, alternatively
choose other settings and hit 'Done'. Then select first
corner where walls should be and enter 'builder' without
arguments, select second corner and enter 'builder' again.
You can build over constructions, but avoid building over buildings.
Wouldn't work at map edges. For big selection may be really slow,
so use with caution. Also this script alters memory and may cause
problems and probably even crashes and save corruption so use at
your own risk.
]====]
local gui=require 'gui'
local dlg=require 'gui.dialogs'
function getTileRealPos(pos)
local block=dfhack.maps.getTileBlock(pos)
local x, y = pos.x-block.map_pos.x, pos.y-block.map_pos.y
--returns map block and tile position in this block
return x, y, block
end
function getWall(pos)
local tt=dfhack.maps.getTileType(pos)
local tile=df.tiletype.attrs[tt]
if tile.shape==4 and ( tile.special==0 or tile.special==7 or tile.special==8 or tile.special==9 or tile.material==22 or tile.material==1 ) then
return 2 --natural wall
elseif tile.shape==5 or (tile.shape==4 and tile.special==3 and tile.material~=23) then
return 1 --artificial wall
else
return 0 --everything else (treated as a floor)
end
end
function getNeighbours(pos)
local north = {x=pos.x,y=pos.y-1,z=pos.z}
local east = {x=pos.x+1,y=pos.y,z=pos.z}
local south = {x=pos.x,y=pos.y+1,z=pos.z}
local west = {x=pos.x-1,y=pos.y,z=pos.z}
return getWall(north), getWall(east), getWall(south), getWall(west)
end
function binary(n)
local bits={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
for i=1, n do
bits[1]=bits[1]+1
for i=1, 16 do
if bits[i]>1 then
bits[i]=0
bits[i+1]=bits[i+1]+1
end
end
end
--returns 16 bits which corespond to x positions in every y row
return bits
end
function getLowestHighest(tbl)
--[[ was used to change indexation for tables that started from 0
if tbl[0] then
local newtbl ={}
for i=0, #tbl-1 do
table.insert(newtbl, tbl[i])
end
tbl = newtbl
end
]]
local h = tbl[1]
local l = tbl[1]
for i=1, #tbl do
if tbl[i] > h then
h=tbl[i]
elseif tbl[i] < l then
l=tbl[i]
end
end
return l,h
end
function capitalize(text)
text=string.upper(string.sub(text,1,1))..string.sub(text,2)
return text
end
function isRoofed(pos)
pos={x=pos.x, y=pos.y, z=pos.z+1}
local x, y, block = getTileRealPos(pos)
local tt=dfhack.maps.getTileType(pos)
local tile=df.tiletype.attrs[tt]
--checks if there is roof above
if tile.shape==-1 or tile.shape==0 or tile.shape==10 or tile.shape==13 or tile.shape==14 or tile.shape==15 then
return false
else
return true
end
end
function isAboveInside(pos)
pos={x=pos.x, y=pos.y, z=pos.z+1}
local x, y, block = getTileRealPos(pos)
if block.designation[x][y].outside == false then
return true
else
return false
end
end
function isRamp(pos)
local tt=dfhack.maps.getTileType(pos)
local tile=df.tiletype.attrs[tt]
if tile.shape==9 then
return true
else
return false
end
end
function isConstruction(pos)
local tt=dfhack.maps.getTileType(pos)
local tile=df.tiletype.attrs[tt]
if tile.material==7 then
return true
else
return false
end
end
function removeConstruction(pos)
for i,v in ipairs(df.global.world.constructions) do
if v.pos.x == pos.x and v.pos.y == pos.y and v.pos.z == pos.z then
df.global.world.constructions:erase(i)
--Todo: remove item in construction
end
end
end
function updateBelowLight(pos)
local x, y, block= getTileRealPos({x=pos.x,y=pos.y,z=pos.z-1})
block.designation[x][y].outside=false
end
function updateOpenBelow(pos)
local x, y, block= getTileRealPos({x=pos.x,y=pos.y,z=pos.z-1})
local flags=dfhack.maps.getTileFlags(pos)
block.designation[x][y].light=flags.light
block.designation[x][y].subterranean=flags.subterranean
block.designation[x][y].outside=flags.outside
end
function updateAbovegroundStatus(pos, wall)
local x, y, block= getTileRealPos(pos)
if isRoofed(pos) or isAboveInside(pos) or wall then
--checking if inside, underground and light
block.designation[x][y].outside=false
if builderSettings.above_ground then
block.designation[x][y].subterranean=false
block.designation[x][y].light=true
end
if builderSettings.underground then
block.designation[x][y].subterranean=true
block.designation[x][y].light=false
end
else
block.designation[x][y].outside=true
block.designation[x][y].subterranean=false
block.designation[x][y].light=true
end
end
function clearDirt(pos)
local x, y, block= getTileRealPos(pos)
for i,v in ipairs(block.block_events) do
if v._type==df.block_square_event_material_spatterst or v._type==df.block_square_event_item_spatterst then
v.amount[x][y]=0
end
end
end
function revealHide(pos)
local x, y, block= getTileRealPos(pos)
if builderSettings.reveal then
block.designation[x][y].hidden=false
end
if builderSettings.hide then
block.designation[x][y].hidden=true
end
end
function channelBelow(pos)
local tt=dfhack.maps.getTileType(pos)
local tile=df.tiletype.attrs[tt]
local rng=dfhack.random.new()
if tile.material==1 or tile.material==22 then
makeFloor(pos, 348+rng:random(4)) --soil floor
elseif tile.material==2 or tile.material==3 or tile.material==5 then
makeNaturalFloor(pos) --natural floor
elseif tile.material==4 then
makeFloor(pos, 336+rng:random(4)) --obsidian floor
elseif tile.material==6 then
makeFloor(pos, 254+rng:random(3)) --ice floor
elseif tile.material==7 then
makeFloor(pos, 489) --construction floor
end
end
function updateWall(pos)
--reconnects wall with surrounding walls
local n, e, s, w = getNeighbours(pos)
local x, y, block = getTileRealPos(pos)
local mat
local dirType
local tt=dfhack.maps.getTileType(pos)
local tile=df.tiletype.attrs[tt]
if tile.shape==4 then --only for walls
if tile.material==2 then
mat=302 --stone
elseif tile.material==3 then
mat=283 --feature
elseif tile.material==4 then
mat=264 --lava
elseif tile.material==5 then
mat=412 --mineral
elseif tile.material==6 then
mat=445 --frozen
elseif tile.material==7 then
mat=491 --construction
end
--direction of connections, not the most elegant solution. Todo: find a better way to choose wall type
if s==1 and e==2 and n~=1 and w~=1 then
dirType=1
elseif s==2 and e==1 and n~=1 and w~=1 then
dirType=2
elseif n==2 and e==1 and s~=1 and w~=1 then
dirType=3
elseif n==1 and e==2 and s~=1 and w~=1 then
dirType=4
elseif n==2 and w==1 and s~=1 and e~=1 then
dirType=5
elseif n==1 and w==2 and s~=1 and e~=1 then
dirType=6
elseif s==2 and w==1 and n~=1 and e~=1 then
dirType=7
elseif s==1 and w==2 and n~=1 and e~=1 then
dirType=8
elseif n==1 and e==1 and s==1 and w==1 then
dirType=9
elseif n==1 and e==1 and s==1 and w~=1 then
dirType=10
elseif n~=1 and e==1 and s==1 and w==1 then
dirType=11
elseif n==1 and e==1 and s~=1 and w==1 then
dirType=12
elseif n==1 and e~=1 and s==1 and w==1 then
dirType=13
elseif n~=1 and e==1 and s==1 and w~=1 then
dirType=14
elseif n==1 and e==1 and s~=1 and w~=1 then
dirType=15
elseif n==1 and e~=1 and s~=1 and w==1 then
dirType=16
elseif n~=1 and e~=1 and s==1 and w==1 then
dirType=17
elseif n==1 and e~=1 and s==1 and w~=1 then
dirType=18
elseif n~=1 and e==1 and s~=1 and w==1 then
dirType=19
else
dirType=0 --pillar
end
if dirType==0 then
--change to pillars depending on material
if mat==302 then
block.tiletype[x][y]=79
elseif mat==283 then
block.tiletype[x][y]=81
elseif mat==264 then
block.tiletype[x][y]=80
elseif mat==491 then
block.tiletype[x][y]=491
elseif mat==445 then
block.tiletype[x][y]=83
elseif mat==412 then
block.tiletype[x][y]=82
end
else
--make connections
block.tiletype[x][y]=mat+dirType
end
end
end
function makeWall(pos, wallType)
--create wall depending on wallType
--it is probably possible to merge makeWall, makeFloor and makeChannel into single function
local x, y, block = getTileRealPos(pos)
local n, e, s, w = getNeighbours(pos)
local north = {x=pos.x,y=pos.y-1,z=pos.z}
local east = {x=pos.x+1,y=pos.y,z=pos.z}
local south = {x=pos.x,y=pos.y+1,z=pos.z}
local west = {x=pos.x-1,y=pos.y,z=pos.z}
block.tiletype[x][y]=wallType
block.path_cost[x][y]=0
block.path_tag[x][y]=0
block.walkable[x][y]=0
updateBelowLight(pos)
if getWall(pos)==1 then
updateWall(pos)
end
updateAbovegroundStatus(pos, true)
revealHide(pos)
clearDirt(pos)
if isConstruction(pos) then
removeConstruction(pos)
end
if builderSettings.material then
paintTile(pos, builderSettings.material)
end
if n==1 then
updateWall(north)
end
if e==1 then
updateWall(east)
end
if s==1 then
updateWall(south)
end
if w==1 then
updateWall(west)
end
end
function makeFloor(pos, floorType)
--creates walkable tile (floors, ramps, stairs etc.)
local x, y, block = getTileRealPos(pos)
local n, e, s, w = getNeighbours(pos)
local north = {x=pos.x,y=pos.y-1,z=pos.z}
local east = {x=pos.x+1,y=pos.y,z=pos.z}
local south = {x=pos.x,y=pos.y+1,z=pos.z}
local west = {x=pos.x-1,y=pos.y,z=pos.z}
block.tiletype[x][y]=floorType
block.path_cost[x][y]=100000000 --? have no clue ho it's calculated
block.path_tag[x][y]=14000 --? same here
block.walkable[x][y]=27
updateBelowLight(pos)
updateAbovegroundStatus(pos, false)
clearDirt(pos)
for i=(pos.x-1), pos.x+1 do
for j=(pos.y-1), pos.y+1 do
revealHide({x=i, y=j, z=pos.z})
end
end
if isConstruction(pos) then
removeConstruction(pos)
end
if builderSettings.material then
paintTile(pos, builderSettings.material)
end
if n==1 then
updateWall(north)
end
if e==1 then
updateWall(east)
end
if s==1 then
updateWall(south)
end
if w==1 then
updateWall(west)
end
end
function makeChannel(pos)
--makes empty tile and converts below tile into walkable tile
local x, y, block = getTileRealPos(pos)
local n, e, s, w = getNeighbours(pos)
local north = {x=pos.x,y=pos.y-1,z=pos.z}
local east = {x=pos.x+1,y=pos.y,z=pos.z}
local south = {x=pos.x,y=pos.y+1,z=pos.z}
local west = {x=pos.x-1,y=pos.y,z=pos.z}
if isRamp({x=pos.x,y=pos.y,z=pos.z-1}) then
block.tiletype[x][y]=1
else
block.tiletype[x][y]=32
end
block.path_cost[x][y]=0
block.path_tag[x][y]=0
block.walkable[x][y]=0
if getWall({x=pos.x,y=pos.y,z=pos.z-1})~=0 then
channelBelow({x=pos.x,y=pos.y,z=pos.z-1})
end
updateAbovegroundStatus(pos, false)
clearDirt(pos)
updateOpenBelow(pos)
if isConstruction(pos) then
removeConstruction(pos)
end
for i=(pos.x-1), pos.x+1 do
for j=(pos.y-1), pos.y+1 do
revealHide({x=i, y=j, z=pos.z})
end
end
revealHide({x=pos.x,y=pos.y,z=pos.z-1})
if n==1 then
updateWall(north)
end
if e==1 then
updateWall(east)
end
if s==1 then
updateWall(south)
end
if w==1 then
updateWall(west)
end
end
function paintTile(pos, mat)
--adds mineral to a tile
local x,y,block=getTileRealPos(pos)
local mineral
for i,v in ipairs(block.block_events) do
if v._type==df.block_square_event_mineralst and v.inorganic_mat==mat then
mineral=v --find mineral if it exists for map block
end
end
if not mineral then
--create new mineral for map block
mineral=df.block_square_event_mineralst:new()
mineral.inorganic_mat=mat
mineral.flags.cluster=true
mineral.flags.discovered=true
block.block_events:insert("#", mineral)
end
local bits=binary(mineral.tile_bitmask.bits[y])
if bits[x+1] ~=1 then
--change mineral of the tile
mineral.tile_bitmask.bits[y]=mineral.tile_bitmask.bits[y]+2^x
end
end
function paintConstruction(pos, mat)
--changes material of construction
--Todo: change construction item material if it exists
for i,v in ipairs(df.global.world.constructions) do
if v.pos.x==pos.x and v.pos.y==pos.y and v.pos.z==pos.z then
v.mat_type=0 --inorganic only. todo: accept other materials
v.mat_index=mat
end
end
end
function paintMode(pos)
--paint mode function to keep original tile type but change color/material
local tt=dfhack.maps.getTileType(pos)
local tile=df.tiletype.attrs[tt]
local rng=dfhack.random.new()
if builderSettings.material then
if tile.material==7 then
paintConstruction(pos, builderSettings.material)
else
if tile.shape==4 and ( tile.special==0 or tile.special==7 or tile.special==8 or tile.special==9) and tile.material~=22 and tile.material~=1 then
makeWall(pos, 436) --natural wall
paintTile(pos, builderSettings.material)
elseif tile.shape==4 and tile.special==3 and tile.material~=23 then
makeWall(pos, 82) --smooth wall
paintTile(pos, builderSettings.material)
elseif tile.shape==1 and tile.special==0 and tile.material~=1 then
makeFloor(pos, 437+rng:random(4)) --natural floor
paintTile(pos, builderSettings.material)
elseif tile.shape==1 and tile.special==3 and tile.material~=1 and tile.material~=23 then
makeFloor(pos, 46) --smooth floor
paintTile(pos, builderSettings.material)
elseif tile.shape==5 then
makeFloor(pos, 432) --fortification
paintTile(pos, builderSettings.material)
elseif tile.shape==6 and tile.material~=1 then
makeFloor(pos, 60) --stairs up
paintTile(pos, builderSettings.material)
elseif tile.shape==7 and tile.material~=1 then
makeFloor(pos, 59) --stairs down
paintTile(pos, builderSettings.material)
elseif tile.shape==8 and tile.material~=1 then
makeFloor(pos, 58) --stairs up/down
paintTile(pos, builderSettings.material)
elseif tile.shape==9 and tile.material~=1 then
makeFloor(pos, 236) --ramp
paintTile(pos, builderSettings.material)
else
end
end
end
updateAbovegroundStatus(pos, false)
revealHide(pos)
end
function makeSmoothWall(pos)
if not builderSettings.material then
makeWall(pos, 79)
else
makeWall(pos, 82)
end
if not isRoofed(pos) then
makeSmoothFloor({x=pos.x,y=pos.y,z=pos.z+1})
end
end
function makeNaturalWall(pos)
if not builderSettings.material then
makeWall(pos, 215)
else
makeWall(pos, 436)
end
if not isRoofed(pos) then
makeNaturalFloor({x=pos.x,y=pos.y,z=pos.z+1})
end
end
function makeSmoothFloor(pos)
if not builderSettings.material then
makeFloor(pos, 43)
else
makeFloor(pos, 46)
end
end
function makeNaturalFloor(pos)
local rng=dfhack.random.new()
local floorType
if not builderSettings.material then
floorType=332+rng:random(4)
else
floorType=437+rng:random(4)
end
makeFloor(pos, floorType)
end
function makeStairsU(pos)
if not builderSettings.material then
makeFloor(pos, 57)
else
makeFloor(pos, 60)
end
end
function makeStairsD(pos)
if not builderSettings.material then
makeFloor(pos, 56)
else
makeFloor(pos, 59)
end
end
function makeStairsUD(pos)
if not builderSettings.material then
makeFloor(pos, 55)
else
makeFloor(pos, 58)
end
end
function makeRamp(pos)
if not builderSettings.material then
makeFloor(pos, 233)
else
makeFloor(pos, 236)
end
if not isConstruction({x=pos.x,y=pos.y,z=pos.z+1}) then
makeFloor({x=pos.x,y=pos.y,z=pos.z+1}, 1)
end
end
function makeFortification(pos)
if not builderSettings.material then
makeFloor(pos, 65)
else
makeFloor(pos, 432)
end
local x, y, block = getTileRealPos(pos)
block.walkable[x][y]=0
end
function selectArea()
if df.global.cursor.x==-30000 or df.global.cursor.y==-30000 or df.global.cursor.z==-30000 then
--if there is no cursor. should probably also check for curent ui
dlg.showMessage("Builder", "No cursor found! Place cursor on a tile from where you want to start.", COLOR_RED)
qerror("No cursor")
else
if df.global.cursor.x > 1 and df.global.cursor.x < df.global.world.map.x_count-2 --cursor at least 2 tiles away from every edge
and df.global.cursor.y > 1 and df.global.cursor.y < df.global.world.map.y_count-2
and df.global.cursor.z > 1 and df.global.cursor.z < df.global.world.map.z_count-2 then
if builderSettings.pos1.x==-1 or builderSettings.pos1.y==-1 or builderSettings.pos1.z==-1 then
--if pos1 hasn't been selected yet
builderSettings.pos1.x=df.global.cursor.x
builderSettings.pos1.y=df.global.cursor.y
builderSettings.pos1.z=df.global.cursor.z
else
--selecting pos2, filling area and then reseting pos1 and pos2
builderSettings.pos2.x=df.global.cursor.x
builderSettings.pos2.y=df.global.cursor.y
builderSettings.pos2.z=df.global.cursor.z
fillArea(builderSettings.pos1, builderSettings.pos2)
builderSettings.pos1={x=-1,y=-1,z=-1}
builderSettings.pos2={x=-1,y=-1,z=-1}
end
else
--if at map edge
dlg.showMessage("Builder", "Map edge selected. Currently Builder does not support changing map edges.", COLOR_RED)
qerror("Map edge")
end
end
end
function fillArea(pos1, pos2)
--fills in block of tiles between selected pos1 and pos2
local x1,x2 = getLowestHighest({pos1.x,pos2.x})
local y1,y2 = getLowestHighest({pos1.y,pos2.y})
local z1,z2 = getLowestHighest({pos1.z,pos2.z})
if builderSettings.brush=="Square" then
for i=z1, z2 do
for j=y1, y2 do
for v=x1, x2 do
builderSettings.mode({x=v,y=j,z=i})
end
end
end
elseif builderSettings.brush=="Circle" then
--Todo: make proper circle
local xc=(x2+x1)/2
local yc=(y2+y1)/2
local rx=xc-x1
local ry=yc-y1
for i=z1, z2 do
for j=y1, y2 do
for v=x1, x2 do
--my circle math is just bad, I haven't really bothered with it
if (math.abs(xc-v))^2+(math.abs(yc-j))^2 <= ((rx*(math.abs(xc-v))+ry*(math.abs(yc-j)))/((math.abs(xc-v))+(math.abs(yc-j))))^2 then
builderSettings.mode({x=v,y=j,z=i})
end
end
end
end
end
end
---------v----Gui for settings----v-----------
--==========================================--
function mainSettings()
--main setting menu
local choice={}
table.insert(choice, "Building mode: "..builderSettings.modeTitle)
if not builderSettings.material then
table.insert(choice, "Material: None")
else
table.insert(choice, "Material: "..capitalize(df.global.world.raws.inorganics[builderSettings.material].material.state_name.Solid))
end
if not builderSettings.above_ground and not builderSettings.underground then
table.insert(choice, "Underground status: Keep as it is")
elseif builderSettings.above_ground then
table.insert(choice, "Underground status: Change to 'Above ground'")
elseif builderSettings.underground then
table.insert(choice, "Underground status: Change to 'Underground'")
end
if not builderSettings.reveal and not builderSettings.hide then
table.insert(choice, "Revealed status: Keep as it is")
elseif builderSettings.reveal then
table.insert(choice, "Revealed status: Change to 'Revealed'")
elseif builderSettings.hide then
table.insert(choice, "Revealed status: Change to 'Hidden'")
end
table.insert(choice, "Brush type: "..builderSettings.brush)
table.insert(choice, "Done!")
dlg.showListPrompt("Builder",
"Settings:",
COLOR_WHITE,
choice,
function(a)
if a==1 then
buildingModeSelection()
elseif a==2 then
materialSelection()
elseif a==3 then
undergroundSelection()
elseif a==4 then
revealSelection()
elseif a==5 then
brushSelection()
end
end,
function()
end
)
end
function buildingModeSelection()
--building mode selection menu
local choice={list={"Paint only", "Smooth wall", "Natural wall", "Smooth floor", "Natural floor",
"Channel", "Stairs Up", "Stairs Down", "Stairs Up/Down", "Ramp", "Fortification"},
title={"Paint only", "Smooth wall", "Natural wall", "Smooth floor", "Natural floor", --had to make a copy of a list
"Channel", "Stairs Up", "Stairs Down", "Stairs Up/Down", "Ramp", "Fortification"}, --cause it messes up list on selection
tbl={paintMode, makeSmoothWall, makeNaturalWall, makeSmoothFloor, makeNaturalFloor,
makeChannel, makeStairsU, makeStairsD, makeStairsUD, makeRamp, makeFortification}
}
dlg.showListPrompt("Builder",
"Building modes:",
COLOR_WHITE,
choice.list,
function(a)
--builderSettings.modeTitle=choice.list[a] --returns table not a string
builderSettings.modeTitle=choice.title[a]
builderSettings.mode=choice.tbl[a]
mainSettings()
end,
function()
mainSettings()
end,nil,true
)
end
function materialSelection()
--material selection menu
local choice={list={},index={}}
table.insert(choice.list, "None")
table.insert(choice.index, -1)
for i,v in ipairs(df.global.world.raws.inorganics) do
if (not v.flags.SOIL_ANY and not v.flags.SOIL and not v.flags.GENERATED and
not v.flags.SPECIAL and not v.material.flags.ITEMS_QUERN and not v.material.flags.NO_STONE_STOCKPILE) or
(not v.material.flags.NO_STONE_STOCKPILE and v.material.flags.IS_STONE)
or v.material.flags.IS_GEM or (not v.material.flags.ITEMS_SOFT and v.flags.DIVINE) or v.flags.DEEP_SPECIAL or v.flags.DEEP_SURFACE then
table.insert(choice.list, v.material.state_name.Solid)
table.insert(choice.index, i)
end
end
dlg.showListPrompt("Builder",
"Materials:",
COLOR_WHITE,
choice.list,
function(a)
if a==1 then
builderSettings.material=nil
else
builderSettings.material=choice.index[a]
end
mainSettings()
end,
function()
mainSettings()
end,nil,true
)
end
function undergroundSelection()
--underground/above ground selection menu
local choice={list={"Keep as it is", "Change to 'Above ground'", "Change to 'Underground'"},
tbl={{false, false}, {true, false}, {false, true}}
}
dlg.showListPrompt("Builder",
"Underground status:",
COLOR_WHITE,
choice.list,
function(a)
builderSettings.above_ground=choice.tbl[a][1]
builderSettings.underground=choice.tbl[a][2]
mainSettings()
end,
function()
mainSettings()
end
)
end
function revealSelection()
--reveal flags selection menu
local choice={list={"Keep as it is", "Change to 'Revealed'", "Change to 'Hidden'"},
tbl={{false, false}, {true, false}, {false, true}}
}
dlg.showListPrompt("Builder",
"Revealed status:",
COLOR_WHITE,
choice.list,
function(a)
builderSettings.reveal=choice.tbl[a][1]
builderSettings.hide=choice.tbl[a][2]
mainSettings()
end,
function()
mainSettings()
end
)
end
function brushSelection()
--brush selection menu
local choice={list={"Square", "Circle (Work in progress)"},
tbl={"Square", "Circle"}
}
dlg.showListPrompt("Builder",
"Brush type:",
COLOR_WHITE,
choice.list,
function(a)
builderSettings.brush=choice.tbl[a]
mainSettings()
end,
function()
mainSettings()
end
)
end
builderSettings=builderSettings or {above_ground=false,
underground=false,
reveal=true,
hide=false,
material=nil,
pos1={x=-1,y=-1,z=-1},
pos2={x=-1,y=-1,z=-1},
mode=makeSmoothWall,
modeTitle="Smooth wall",
brush="Square"
}
local args={...}
if not args[1] then
selectArea()
elseif args[1]=="-r" or args[1]=="-reset" or args[1]=="r" or args[1]=="reset" then
builderSettings={above_ground=false,
underground=false,
reveal=true,
hide=false,
material=nil,
pos1={x=-1,y=-1,z=-1},
pos2={x=-1,y=-1,z=-1},
mode=makeSmoothWall,
modeTitle="Smooth wall",
brush="Square"
}
elseif args[1]=="?" or args[1]=="-help" or args[1]=="-h" or args[1]=="help" or args[1]=="h" then
print(help)
elseif args[1]=="-s" or args[1]=="s" or args[1]=="setting" or args[1]=="-setting" then
mainSettings()
else
qerror("Wrong argument entered! Use 'builder ?' for help")
end
I also have a few questions. I would love to include ability to create constructions. And while I can change tiletype to constructed wall, and I can add new construction in df.global.world.constructions, but they do not 'connect'. Constructed wall on a map will be without material and upon deconstruction my added construction entry will remain in df.global.world.constructions. I assume that there is some other thing in the memory that connects constructions to map tiles. Same question for buildings: how can I connect buildings from df.global.world.buildings to map tile?
For building creation I could also use dfhack.buildings.constructWithItems(), but it creates designation for building. I can change building stage for it to 1, and it would appear as fully constructed building, but there still will be a job associated with it. Moving item to this building using moveToBuilding() doesn't work, and deleting job may cause crash. So is there a way to make fully constructed building using this function?
And another question, which I probably could figure out by myself, but to make things easier I decided to ask here. Currently my script will not work for map edges, and will require -reset to work properly after. That's because it will check adjusting tiles in cardinal directions and above tile. I want some simple solution to prevent its usage at the top and bottom of the map, and at all four edges.