dfhack/plugins/lua/buildingplan.lua

96 lines
3.4 KiB
Lua

local _ENV = mkmodule('plugins.buildingplan')
2020-08-16 00:03:49 -06:00
--[[
Native functions:
prep buildingplan for core algorithm changes Lots of refactoring and reorganizing, with only cosmetic player-visible changes. - show quickfort mode hotlkey label regardless of whether the current building type has buildingplan enabled. before, it was only shown after the user enabled buildingplan for the current building. this eliminates the extra step when enabling quickfort mode, which force-enables all building types. - changed signature of lua-exported isPlannableBuilding to take subtype and custom type in addition to building type. this is only used by quickfort, and it already sends all three params in preparation for this change - added lua-exported scheduleCycle(), which is like doCycle(), but only takes effect on the next non-paused frame. this lets quickfort run only one buildingplan cycle regardless of how many #build blueprints were run - declared a few dfhack library methods and params const so buildingplan could call them from const methods - converted buildingplan internal debug logging fn to have a printf api - reshaped buildingplan-planner API and refactored implementation in preparation for upcoming core algorithm changes for supporing all building types (no externally-visible functionality changes) - changed df::building_type params to type, subtype, custom tuple keys - introduced capability to return multiple filters per building type (though the current buildings all only have one filter per) - split monolith hook functions in buildingplan.cpp into one per scope. this significantly cleans up the code and preps the hooks to handle iterating through multiple item filters. - got rid of send_key function and replaced with better reporting of whether keys have been handled
2020-10-16 14:52:23 -06:00
* bool isPlannableBuilding(df::building_type type, int16_t subtype, int32_t custom)
2020-08-16 00:03:49 -06:00
* void addPlannedBuilding(df::building *bld)
* void doCycle()
prep buildingplan for core algorithm changes Lots of refactoring and reorganizing, with only cosmetic player-visible changes. - show quickfort mode hotlkey label regardless of whether the current building type has buildingplan enabled. before, it was only shown after the user enabled buildingplan for the current building. this eliminates the extra step when enabling quickfort mode, which force-enables all building types. - changed signature of lua-exported isPlannableBuilding to take subtype and custom type in addition to building type. this is only used by quickfort, and it already sends all three params in preparation for this change - added lua-exported scheduleCycle(), which is like doCycle(), but only takes effect on the next non-paused frame. this lets quickfort run only one buildingplan cycle regardless of how many #build blueprints were run - declared a few dfhack library methods and params const so buildingplan could call them from const methods - converted buildingplan internal debug logging fn to have a printf api - reshaped buildingplan-planner API and refactored implementation in preparation for upcoming core algorithm changes for supporing all building types (no externally-visible functionality changes) - changed df::building_type params to type, subtype, custom tuple keys - introduced capability to return multiple filters per building type (though the current buildings all only have one filter per) - split monolith hook functions in buildingplan.cpp into one per scope. this significantly cleans up the code and preps the hooks to handle iterating through multiple item filters. - got rid of send_key function and replaced with better reporting of whether keys have been handled
2020-10-16 14:52:23 -06:00
* void scheduleCycle()
2020-08-16 00:03:49 -06:00
--]]
local guidm = require('gui.dwarfmode')
require('dfhack.buildings')
-- does not need the core suspended
function get_num_filters(btype, subtype, custom)
local filters = dfhack.buildings.getFiltersByType(
{}, btype, subtype, custom)
if filters then return #filters end
return 0
end
local function to_title_case(str)
str = str:gsub('(%a)([%w_]*)',
function (first, rest) return first:upper()..rest:lower() end)
str = str:gsub('_', ' ')
return str
end
-- returns a reasonable label for the item based on the qualities of the filter
-- does not need the core suspended
-- reverse_idx is 0-based and is expected to be counted from the *last* filter
function get_item_label(btype, subtype, custom, reverse_idx)
local filters = dfhack.buildings.getFiltersByType(
{}, btype, subtype, custom)
if not filters then return 'No item' end
if reverse_idx < 0 or reverse_idx >= #filters then
return 'Invalid index'
end
local filter = filters[#filters-reverse_idx]
if filter.has_tool_use then
return to_title_case(df.tool_uses[filter.has_tool_use])
end
if filter.item_type then
return to_title_case(df.item_type[filter.item_type])
end
if filter.flags2 and filter.flags2.building_material then
if filter.flags2.fire_safe then
return "Fire-safe building material";
end
if filter.flags2.magma_safe then
return "Magma-safe building material";
end
return "Generic building material";
end
if filter.vector_id then
return to_title_case(df.job_item_vector_id[filter.vector_id])
end
return "Unknown";
end
-- needs the core suspended
function construct_building_from_ui_state()
local uibs = df.global.ui_build_selector
local world = df.global.world
local direction = world.selected_direction
local _, width, height = dfhack.buildings.getCorrectSize(
world.building_width, world.building_height, uibs.building_type,
uibs.building_subtype, uibs.custom_type, direction)
-- the cursor is at the center of the building; we need the upper-left
-- corner of the building
local pos = guidm.getCursorPos()
pos.x = pos.x - math.floor(width/2)
pos.y = pos.y - math.floor(height/2)
local bld, err = dfhack.buildings.constructBuilding{
type=uibs.building_type, subtype=uibs.building_subtype,
custom=uibs.custom_type, pos=pos, width=width, height=height,
direction=direction}
if err then error(err) end
-- assign fields for the types that need them. we can't pass them all in to
-- the call to constructBuilding since attempting to assign unrelated
-- fields to building types that don't support them causes errors.
for k,v in pairs(bld) do
if k == 'friction' then bld.friction = uibs.friction end
if k == 'use_dump' then bld.use_dump = uibs.use_dump end
if k == 'dump_x_shift' then bld.dump_x_shift = uibs.dump_x_shift end
if k == 'dump_y_shift' then bld.dump_y_shift = uibs.dump_y_shift end
if k == 'speed' then bld.speed = uibs.speed end
end
return bld
end
return _ENV