Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion internal/quickfort/aliases.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ local log = quickfort_common.log
-- special keycode shortcuts inherited from python quickfort.
local special_keys = {
['&']='Enter',
['+']='{Shift}',
['!']='{Ctrl}',
['~']='{Alt}',
['@']={'{Shift}','Enter'},
Expand Down
142 changes: 84 additions & 58 deletions internal/quickfort/build.lua
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ local utils = require('utils')
local buildingplan = require('plugins.buildingplan')
local quickfort_common = reqscript('internal/quickfort/common')
local quickfort_building = reqscript('internal/quickfort/building')
local quickfort_orders = reqscript('internal/quickfort/orders')
local log = quickfort_common.log

--
Expand Down Expand Up @@ -158,6 +159,27 @@ end
-- ************ the database ************ --
--

local screw_pump_data = {
[df.screw_pump_direction.FromNorth]={label='North', vertical=true},
[df.screw_pump_direction.FromEast]={label='East'},
[df.screw_pump_direction.FromSouth]={label='South', vertical=true},
[df.screw_pump_direction.FromWest]={label='West'}
}
local function make_screw_pump_entry(direction)
local width, height = 1, 1
if screw_pump_data[direction].vertical then
height = 2
else
width = 2
end
return {label=string.format('Screw Pump (Pump From %s)',
screw_pump_data[direction].label),
type=df.building_type.ScrewPump,
min_width=width, max_width=width,
min_height=height, max_height=height,
direction=direction, is_valid_tile_fn=is_valid_tile_has_space}
end

local roller_data = {
[df.screw_pump_direction.FromNorth]={label='Rollers (N->S)', vertical=true},
[df.screw_pump_direction.FromEast]={label='Rollers (E->W)'},
Expand Down Expand Up @@ -199,7 +221,8 @@ local function make_trackstop_entry(direction, friction)
label=label,
type=df.building_type.Trap,
subtype=df.trap_type.TrackStop,
fields=fields
fields=fields,
additional_orders={'wooden minecart'}
}
end

Expand Down Expand Up @@ -243,26 +266,11 @@ local building_db = {
Y={label='Gem Window', type=df.building_type.WindowGem},
D={label='Trade Depot', type=df.building_type.TradeDepot,
min_width=5, max_width=5, min_height=5, max_height=5},
Ms={label='Screw Pump (Pump From North)', type=df.building_type.ScrewPump,
min_width=1, max_width=1, min_height=2, max_height=2,
direction=df.screw_pump_direction.FromNorth,
is_valid_tile_fn=is_valid_tile_has_space},
Msu={label='Screw Pump (Pump From North)', type=df.building_type.ScrewPump,
min_width=1, max_width=1, min_height=2, max_height=2,
direction=df.screw_pump_direction.FromNorth,
is_valid_tile_fn=is_valid_tile_has_space},
Msk={label='Screw Pump (Pump From East)', type=df.building_type.ScrewPump,
min_width=2, max_width=2, min_height=1, max_height=1,
direction=df.screw_pump_direction.FromEast,
is_valid_tile_fn=is_valid_tile_has_space},
Msm={label='Screw Pump (Pump From South)', type=df.building_type.ScrewPump,
min_width=1, max_width=1, min_height=2, max_height=2,
direction=df.screw_pump_direction.FromSouth,
is_valid_tile_fn=is_valid_tile_has_space},
Msh={label='Screw Pump (Pump From West)', type=df.building_type.ScrewPump,
min_width=2, max_width=2, min_height=1, max_height=1,
direction=df.screw_pump_direction.FromWest,
is_valid_tile_fn=is_valid_tile_has_space},
Ms=make_screw_pump_entry(df.screw_pump_direction.FromNorth),
Msu=make_screw_pump_entry(df.screw_pump_direction.FromNorth),
Msk=make_screw_pump_entry(df.screw_pump_direction.FromEast),
Msm=make_screw_pump_entry(df.screw_pump_direction.FromSouth),
Msh=make_screw_pump_entry(df.screw_pump_direction.FromWest),
-- there is no enum for water wheel and horiz axle directions, we just have
-- to pass a non-zero integer (but not a boolean)
Mw={label='Water Wheel (N/S)', type=df.building_type.WaterWheel,
Expand Down Expand Up @@ -309,7 +317,8 @@ local building_db = {
v={label='Restraint', type=df.building_type.Chain},
j={label='Cage', type=df.building_type.Cage},
A={label='Archery Target', type=df.building_type.ArcheryTarget},
R={label='Traction Bench', type=df.building_type.TractionBench},
R={label='Traction Bench', type=df.building_type.TractionBench,
additional_orders={'table', 'mechanisms', 'cloth rope'}},
N={label='Nest Box', type=df.building_type.NestBox},
['{Alt}h']={label='Hive', type=df.building_type.Hive},
-- Offering Places, Bookcases, and Display Furniture are not yet supported
Expand Down Expand Up @@ -469,13 +478,15 @@ local building_db = {
Tw={label='Weapon Trap',
type=df.building_type.Trap, subtype=df.trap_type.WeaponTrap},
Tl={label='Lever',
type=df.building_type.Trap, subtype=df.trap_type.Lever},
type=df.building_type.Trap, subtype=df.trap_type.Lever,
additional_orders={'mechanisms', 'mechanisms'}},
-- TODO: lots of configuration here with no natural order. may need
-- special-case logic when we read the keys.
Tp={label='Pressure Plate',
type=df.building_type.Trap, subtype=df.trap_type.PressurePlate},
Tc={label='Cage Trap',
type=df.building_type.Trap, subtype=df.trap_type.CageTrap},
type=df.building_type.Trap, subtype=df.trap_type.CageTrap,
additional_orders={'wooden cage'}},
-- TODO: Same as weapon trap above
TS={label='Upright Spear/Spike',
type=df.building_type.Weapon, subtype=df.trap_type.StoneFallTrap},
Expand Down Expand Up @@ -590,7 +601,8 @@ for _, v in pairs(building_db) do
v.min_width, v.max_width, v.min_height, v.max_height = 1, 1, 1, 1
end
end
if v.type == df.building_type.Workshop then
if v.type == df.building_type.Workshop or
v.type == df.building_type.Furnace then
v.post_construction_fn = post_construction_init_workshop
end
if v.type == df.building_type.Bridge then
Expand Down Expand Up @@ -724,18 +736,26 @@ local function create_building(b)
if use_extents then
fields.room = {x=b.pos.x, y=b.pos.y, width=b.width, height=b.height}
end
local filters = nil
if quickfort_common.settings['buildings_use_blocks'].value then
-- don't set the vector_id since that breaks custom buildings: it sets
-- all their building materials to use that vector id
local filter_mod = { material={item_type=df.item_type.BLOCKS} }
filters = dfhack.buildings.getFiltersByType(
filter_mod, db_entry.type, db_entry.subtype, db_entry.custom)
end
local bld, err = dfhack.buildings.constructBuilding{
type=db_entry.type, subtype=db_entry.subtype, custom=db_entry.custom,
pos=b.pos, width=b.width, height=b.height, direction=db_entry.direction,
fields=fields}
filters=filters, fields=fields}
if not bld then
-- this is an error instead of a qerror since our validity checking
-- is supposed to prevent this from ever happening
error(string.format('unable to place %s: %s', db_entry.label, err))
end
-- constructBuilding deallocates extents, so we have to assign it after
if use_extents then
bld.room.extents = quickfort_building.make_extents(b, building_db)
quickfort_building.assign_extents(
bld, quickfort_building.make_extents(b, building_db))
end
if buildingplan.isPlannableBuilding(db_entry.type) then
log('registering with buildingplan')
Expand All @@ -744,37 +764,42 @@ local function create_building(b)
if db_entry.post_construction_fn then db_entry.post_construction_fn(bld) end
end

function do_run(zlevel, grid)
local stats = {
designated={label='Buildings designated', value=0, always=true},
unsuitable={label='Unsuitable tiles', value=0},
out_of_bounds={label='Tiles outside map boundary', value=0},
invalid_keys={label='Invalid key sequences', value=0},
}
function do_run(zlevel, grid, ctx)
local stats = ctx.stats
stats.build_designated = stats.build_designated or
{label='Buildings designated', value=0, always=true}
stats.build_unsuitable = stats.build_unsuitable or
{label='Unsuitable tiles for building', value=0}

local buildings = {}
stats.invalid_keys.value = quickfort_building.init_buildings(
zlevel, grid, buildings, building_db, building_aliases)
stats.out_of_bounds.value = quickfort_building.crop_to_bounds(
buildings, building_db)
stats.unsuitable.value = quickfort_building.check_tiles_and_extents(
buildings, building_db)
stats.invalid_keys.value =
stats.invalid_keys.value + quickfort_building.init_buildings(
zlevel, grid, buildings, building_db, building_aliases)
stats.out_of_bounds.value =
stats.out_of_bounds.value + quickfort_building.crop_to_bounds(
buildings, building_db)
stats.build_unsuitable.value =
stats.build_unsuitable.value +
quickfort_building.check_tiles_and_extents(
buildings, building_db)

for _, b in ipairs(buildings) do
if b.pos then
create_building(b)
stats.designated.value = stats.designated.value + 1
stats.build_designated.value = stats.build_designated.value + 1
end
end
buildingplan.doCycle()
dfhack.job.checkBuildingsNow()
return stats
end

function do_orders(zlevel, grid)
local stats = nil
print('"quickfort orders" not yet implemented for mode: build')
return stats
function do_orders(zlevel, grid, ctx)
local stats = ctx.stats
local buildings = {}
stats.invalid_keys.value =
stats.invalid_keys.value + quickfort_building.init_buildings(
zlevel, grid, buildings, building_db, building_aliases)
quickfort_orders.enqueue_orders(stats, buildings, building_db, ctx)
end

local function is_queued_for_destruction(bld)
Expand All @@ -786,16 +811,17 @@ local function is_queued_for_destruction(bld)
return false
end

function do_undo(zlevel, grid)
local stats = {
removed={label='Buildings removed', value=0, always=true},
marked={label='Buildings marked for removal', value=0},
invalid_keys={label='Invalid key sequences', value=0},
}
function do_undo(zlevel, grid, ctx)
local stats = ctx.stats
stats.build_undesignated = stats.build_undesignated or
{label='Buildings undesignated', value=0, always=true}
stats.build_marked = stats.build_marked or
{label='Buildings marked for removal', value=0}

local buildings = {}
stats.invalid_keys.value = quickfort_building.init_buildings(
zlevel, grid, buildings, building_db, building_aliases)
stats.invalid_keys.value =
stats.invalid_keys.value + quickfort_building.init_buildings(
zlevel, grid, buildings, building_db, building_aliases)

for _, s in ipairs(buildings) do
for extent_x, col in ipairs(s.extent_grid) do
Expand All @@ -807,14 +833,14 @@ function do_undo(zlevel, grid)
if bld and bld:getType() ~= df.building_type.Stockpile and
not is_queued_for_destruction(bld) then
if dfhack.buildings.deconstruct(bld) then
stats.removed.value = stats.removed.value + 1
stats.build_undesignated.value =
stats.build_undesignated.value + 1
else
stats.marked.value = stats.marked.value + 1
stats.build_marked.value = stats.build_marked.value + 1
end
end
::continue::
end
end
end
return stats
end
10 changes: 9 additions & 1 deletion internal/quickfort/building.lua
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ local function flood_fill(grid, x, y, seen_grid, data, db, aliases)
if aliases[string.lower(keys)] then keys = aliases[string.lower(keys)] end
if not db[keys] then
if not seen_grid[x] then seen_grid[x] = {} end
seen_grid[x][y] = true -- seen, but not part of any stockpile
seen_grid[x][y] = true -- seen, but not part of any building
print(string.format('invalid key sequence in cell %s: "%s"',
cell, text))
return 1
Expand Down Expand Up @@ -371,3 +371,11 @@ function make_extents(b, db)
end
return extents, num_tiles
end

-- ensures we don't leak memory by overwriting extents
-- constructBuilding deallocates any extents we pass in, so we have to assign it
-- after the building is created
function assign_extents(bld, extents)
if bld.room.extents then df.delete(bld.room.extents) end
bld.room.extents = extents
end
Loading