2015-01-07 14:27:48 -07:00
//Blueprint
//By cdombroski
//Translates a region of tiles specified by the cursor and arguments/prompts into a series of blueprint files suitable for digfort/buildingplan/quickfort
2016-01-05 17:03:19 -07:00
# include <algorithm>
2020-07-15 17:57:14 -06:00
# include <sstream>
2016-01-05 17:03:19 -07:00
2015-01-07 14:27:48 -07:00
# include <Console.h>
# include <PluginManager.h>
2018-05-08 12:42:41 -06:00
# include "LuaTools.h"
2015-01-07 14:27:48 -07:00
2015-01-12 09:52:46 -07:00
# include "modules/Buildings.h"
2020-07-15 22:35:21 -06:00
# include "modules/Filesystem.h"
2015-01-12 09:52:46 -07:00
# include "modules/Gui.h"
# include "modules/MapCache.h"
2015-01-09 14:00:47 -07:00
# include "df/building_axle_horizontalst.h"
# include "df/building_bridgest.h"
# include "df/building_constructionst.h"
# include "df/building_furnacest.h"
# include "df/building_rollersst.h"
# include "df/building_screw_pumpst.h"
# include "df/building_siegeenginest.h"
# include "df/building_trapst.h"
# include "df/building_water_wheelst.h"
# include "df/building_workshopst.h"
2015-01-07 14:27:48 -07:00
using std : : string ;
using std : : endl ;
using std : : vector ;
using std : : ofstream ;
2015-01-09 14:00:47 -07:00
using std : : swap ;
2015-01-14 12:58:15 -07:00
using std : : find ;
2015-01-14 12:08:54 -07:00
using std : : pair ;
2015-01-07 14:27:48 -07:00
using namespace DFHack ;
2015-01-09 14:00:47 -07:00
using namespace df : : enums ;
2015-01-07 14:27:48 -07:00
DFHACK_PLUGIN ( " blueprint " ) ;
2015-01-14 12:58:15 -07:00
enum phase { DIG = 1 , BUILD = 2 , PLACE = 4 , QUERY = 8 } ;
2015-01-07 14:27:48 -07:00
command_result blueprint ( color_ostream & out , vector < string > & parameters ) ;
DFhackCExport command_result plugin_init ( color_ostream & out , vector < PluginCommand > & commands )
{
commands . push_back ( PluginCommand ( " blueprint " , " Convert map tiles into a blueprint " , blueprint , false ) ) ;
return CR_OK ;
}
DFhackCExport command_result plugin_shutdown ( color_ostream & out )
{
return CR_OK ;
}
command_result help ( color_ostream & out )
{
2015-01-14 12:58:15 -07:00
out < < " blueprint width height depth name [dig] [build] [place] [query] " < < endl
2015-01-07 14:27:48 -07:00
< < " width, height, depth: area to translate in tiles " < < endl
< < " name: base name for blueprint files " < < endl
< < " dig: generate blueprints for digging " < < endl
< < " build: generate blueprints for building " < < endl
< < " place: generate blueprints for stockpiles " < < endl
< < " query: generate blueprints for querying (room designations) " < < endl
< < " defaults to generating all blueprints " < < endl
< < endl
< < " blueprint translates a portion of your fortress into blueprints suitable for " < < endl
2020-07-15 17:57:14 -06:00
< < " digfort/fortplan/quickfort. Blueprints are created in the \" blueprints \" " < < endl
< < " subdirectory of the DF folder with names following a \" name-phase.csv \" pattern. " < < endl
< < " Translation starts at the current cursor location and includes all tiles in the " < < endl
< < " range specified. " < < endl ;
2015-01-07 14:27:48 -07:00
return CR_OK ;
}
2015-01-14 12:08:54 -07:00
pair < uint32_t , uint32_t > get_building_size ( df : : building * b )
{
return pair < uint32_t , uint32_t > ( b - > x2 - b - > x1 + 1 , b - > y2 - b - > y1 + 1 ) ;
}
2015-01-08 10:17:18 -07:00
char get_tile_dig ( MapExtras : : MapCache mc , int32_t x , int32_t y , int32_t z )
{
2015-02-14 20:53:06 -07:00
df : : tiletype tt = mc . tiletypeAt ( DFCoord ( x , y , z ) ) ;
2015-01-09 14:00:47 -07:00
df : : tiletype_shape ts = tileShape ( tt ) ;
2015-01-08 10:17:18 -07:00
switch ( ts )
{
2015-01-09 14:00:47 -07:00
case tiletype_shape : : EMPTY :
2015-02-14 20:53:06 -07:00
case tiletype_shape : : RAMP_TOP :
2015-01-08 10:17:18 -07:00
return ' h ' ;
2015-01-09 14:00:47 -07:00
case tiletype_shape : : FLOOR :
case tiletype_shape : : BOULDER :
case tiletype_shape : : PEBBLES :
case tiletype_shape : : BROOK_TOP :
2015-01-08 10:17:18 -07:00
return ' d ' ;
2015-01-09 14:00:47 -07:00
case tiletype_shape : : FORTIFICATION :
return ' F ' ;
case tiletype_shape : : STAIR_UP :
2015-01-08 10:17:18 -07:00
return ' u ' ;
2015-01-09 14:00:47 -07:00
case tiletype_shape : : STAIR_DOWN :
2015-01-08 10:17:18 -07:00
return ' j ' ;
2015-01-09 14:00:47 -07:00
case tiletype_shape : : STAIR_UPDOWN :
2015-01-08 10:17:18 -07:00
return ' i ' ;
2015-01-09 14:00:47 -07:00
case tiletype_shape : : RAMP :
2015-01-08 10:17:18 -07:00
return ' r ' ;
default :
return ' ' ;
2015-01-09 14:00:47 -07:00
2015-01-08 10:17:18 -07:00
}
}
2015-01-07 14:27:48 -07:00
2015-01-14 12:08:54 -07:00
string get_tile_build ( uint32_t x , uint32_t y , df : : building * b )
2015-01-09 14:00:47 -07:00
{
2015-02-14 20:53:06 -07:00
if ( ! b )
2015-01-12 09:52:46 -07:00
return " " ;
2018-04-06 00:18:15 -06:00
bool at_nw_corner = int32_t ( x ) = = b - > x1 & & int32_t ( y ) = = b - > y1 ;
bool at_se_corner = int32_t ( x ) = = b - > x2 & & int32_t ( y ) = = b - > y2 ;
bool at_center = int32_t ( x ) = = b - > centerx & & int32_t ( y ) = = b - > centery ;
2015-01-14 12:08:54 -07:00
pair < uint32_t , uint32_t > size = get_building_size ( b ) ;
2015-01-16 01:27:14 -07:00
stringstream out ; // = stringstream();
2015-01-09 14:00:47 -07:00
switch ( b - > getType ( ) )
{
case building_type : : Armorstand :
return " a " ;
case building_type : : Bed :
return " b " ;
case building_type : : Chair :
return " c " ;
case building_type : : Door :
return " d " ;
case building_type : : Floodgate :
return " x " ;
case building_type : : Cabinet :
return " f " ;
case building_type : : Box :
return " h " ;
//case building_type::Kennel is missing
case building_type : : FarmPlot :
2015-01-14 12:08:54 -07:00
if ( ! at_nw_corner )
return " ` " ;
out < < " p( " < < size . first < < " x " < < size . second < < " ) " ;
return out . str ( ) ;
2015-01-09 14:00:47 -07:00
case building_type : : Weaponrack :
return " r " ;
case building_type : : Statue :
return " s " ;
case building_type : : Table :
return " t " ;
case building_type : : RoadPaved :
2015-01-14 12:08:54 -07:00
if ( ! at_nw_corner )
return " ` " ;
out < < " o( " < < size . first < < " x " < < size . second < < " ) " ;
return out . str ( ) ;
2015-01-09 14:00:47 -07:00
case building_type : : RoadDirt :
2015-01-14 12:08:54 -07:00
if ( ! at_nw_corner )
return " ` " ;
out < < " O( " < < size . first < < " x " < < size . second < < " ) " ;
return out . str ( ) ;
2015-01-09 14:00:47 -07:00
case building_type : : Bridge :
2015-01-14 12:08:54 -07:00
if ( ! at_nw_corner )
return " ` " ;
2015-01-09 14:00:47 -07:00
switch ( ( ( df : : building_bridgest * ) b ) - > direction )
{
case df : : building_bridgest : : T_direction : : Down :
2015-01-14 12:08:54 -07:00
out < < " gx " ;
break ;
2015-01-09 14:00:47 -07:00
case df : : building_bridgest : : T_direction : : Left :
2015-01-14 12:08:54 -07:00
out < < " ga " ;
break ;
2015-01-09 14:00:47 -07:00
case df : : building_bridgest : : T_direction : : Up :
2015-01-14 12:08:54 -07:00
out < < " gw " ;
break ;
2015-01-09 14:00:47 -07:00
case df : : building_bridgest : : T_direction : : Right :
2015-01-14 12:08:54 -07:00
out < < " gd " ;
break ;
2015-01-09 14:00:47 -07:00
case df : : building_bridgest : : T_direction : : Retracting :
2015-01-14 12:08:54 -07:00
out < < " gs " ;
break ;
2015-01-09 14:00:47 -07:00
}
2015-01-14 12:08:54 -07:00
out < < " ( " < < size . first < < " x " < < size . second < < " ) " ;
return out . str ( ) ;
2015-01-09 14:00:47 -07:00
case building_type : : Well :
return " l " ;
case building_type : : SiegeEngine :
2015-01-14 12:08:54 -07:00
if ( ! at_center )
return " ` " ;
2015-01-12 09:52:46 -07:00
return ( ( df : : building_siegeenginest * ) b ) - > type = = df : : siegeengine_type : : Ballista ? " ib " : " ic " ;
2015-01-09 14:00:47 -07:00
case building_type : : Workshop :
2015-01-14 12:08:54 -07:00
if ( ! at_center )
return " ` " ;
2015-01-09 14:00:47 -07:00
switch ( ( ( df : : building_workshopst * ) b ) - > type )
{
case workshop_type : : Leatherworks :
return " we " ;
case workshop_type : : Quern :
return " wq " ;
case workshop_type : : Millstone :
return " wM " ;
case workshop_type : : Loom :
return " wo " ;
case workshop_type : : Clothiers :
return " wk " ;
case workshop_type : : Bowyers :
return " wb " ;
case workshop_type : : Carpenters :
return " wc " ;
case workshop_type : : MetalsmithsForge :
return " wf " ;
case workshop_type : : MagmaForge :
return " wv " ;
case workshop_type : : Jewelers :
return " wj " ;
case workshop_type : : Masons :
return " wm " ;
case workshop_type : : Butchers :
return " wu " ;
case workshop_type : : Tanners :
return " wn " ;
case workshop_type : : Craftsdwarfs :
return " wr " ;
case workshop_type : : Siege :
return " ws " ;
case workshop_type : : Mechanics :
return " wt " ;
case workshop_type : : Still :
return " wl " ;
case workshop_type : : Farmers :
return " ww " ;
case workshop_type : : Kitchen :
return " wz " ;
case workshop_type : : Fishery :
return " wh " ;
case workshop_type : : Ashery :
return " wy " ;
case workshop_type : : Dyers :
return " wd " ;
2018-04-06 00:18:15 -06:00
case workshop_type : : Kennels :
return " k " ;
2015-01-09 14:00:47 -07:00
case workshop_type : : Custom :
2018-04-06 00:18:15 -06:00
case workshop_type : : Tool :
2015-01-09 14:00:47 -07:00
//can't do anything with custom workshop
2015-01-14 12:08:54 -07:00
return " ` " ;
2015-01-09 14:00:47 -07:00
}
case building_type : : Furnace :
2015-01-14 12:08:54 -07:00
if ( ! at_center )
return " ` " ;
2015-01-09 14:00:47 -07:00
switch ( ( ( df : : building_furnacest * ) b ) - > type )
{
case furnace_type : : WoodFurnace :
return " ew " ;
case furnace_type : : Smelter :
return " es " ;
case furnace_type : : GlassFurnace :
return " eg " ;
case furnace_type : : Kiln :
return " ek " ;
case furnace_type : : MagmaSmelter :
return " el " ;
case furnace_type : : MagmaGlassFurnace :
return " ea " ;
case furnace_type : : MagmaKiln :
return " en " ;
case furnace_type : : Custom :
//can't do anything with custom furnace
2015-01-14 12:08:54 -07:00
return " ` " ;
2015-01-09 14:00:47 -07:00
}
case building_type : : WindowGlass :
return " y " ;
case building_type : : WindowGem :
return " Y " ;
case building_type : : Construction :
switch ( ( ( df : : building_constructionst * ) b ) - > type )
{
2018-04-06 00:18:15 -06:00
case construction_type : : NONE :
return " ` " ;
2015-01-09 14:00:47 -07:00
case construction_type : : Fortification :
return " CF " ;
case construction_type : : Wall :
return " CW " ;
case construction_type : : Floor :
return " Cf " ;
case construction_type : : UpStair :
return " Cu " ;
case construction_type : : DownStair :
return " Cj " ;
case construction_type : : UpDownStair :
return " Cx " ;
case construction_type : : Ramp :
return " Cr " ;
case construction_type : : TrackN :
return " trackN " ;
case construction_type : : TrackS :
return " trackS " ;
case construction_type : : TrackE :
return " trackE " ;
case construction_type : : TrackW :
return " trackW " ;
case construction_type : : TrackNS :
return " trackNS " ;
case construction_type : : TrackNE :
return " trackNE " ;
case construction_type : : TrackNW :
return " trackNW " ;
case construction_type : : TrackSE :
return " trackSE " ;
case construction_type : : TrackSW :
return " trackSW " ;
case construction_type : : TrackEW :
return " trackEW " ;
case construction_type : : TrackNSE :
return " trackNSE " ;
case construction_type : : TrackNSW :
return " trackNSW " ;
case construction_type : : TrackNEW :
return " trackNEW " ;
case construction_type : : TrackSEW :
return " trackSEW " ;
case construction_type : : TrackNSEW :
return " trackNSEW " ;
case construction_type : : TrackRampN :
return " trackrampN " ;
case construction_type : : TrackRampS :
return " trackrampS " ;
case construction_type : : TrackRampE :
return " trackrampE " ;
case construction_type : : TrackRampW :
return " trackrampW " ;
case construction_type : : TrackRampNS :
return " trackrampNS " ;
case construction_type : : TrackRampNE :
return " trackrampNE " ;
case construction_type : : TrackRampNW :
return " trackrampNW " ;
case construction_type : : TrackRampSE :
return " trackrampSE " ;
case construction_type : : TrackRampSW :
return " trackrampSW " ;
case construction_type : : TrackRampEW :
return " trackrampEW " ;
case construction_type : : TrackRampNSE :
return " trackrampNSE " ;
case construction_type : : TrackRampNSW :
return " trackrampNSW " ;
case construction_type : : TrackRampNEW :
return " trackrampNEW " ;
case construction_type : : TrackRampSEW :
return " trackrampSEW " ;
case construction_type : : TrackRampNSEW :
return " trackrampNSEW " ;
}
case building_type : : Shop :
2015-01-14 12:08:54 -07:00
if ( ! at_center )
return " ` " ;
2015-01-09 14:00:47 -07:00
return " z " ;
case building_type : : AnimalTrap :
return " m " ;
case building_type : : Chain :
return " v " ;
case building_type : : Cage :
return " j " ;
case building_type : : TradeDepot :
2015-01-14 12:08:54 -07:00
if ( ! at_center )
return " ` " ;
2015-01-09 14:00:47 -07:00
return " D " ;
case building_type : : Trap :
switch ( ( ( df : : building_trapst * ) b ) - > trap_type )
{
case trap_type : : StoneFallTrap :
return " Ts " ;
case trap_type : : WeaponTrap :
return " Tw " ;
case trap_type : : Lever :
return " Tl " ;
case trap_type : : PressurePlate :
return " Tp " ;
case trap_type : : CageTrap :
return " Tc " ;
case trap_type : : TrackStop :
df : : building_trapst * ts = ( df : : building_trapst * ) b ;
2015-01-14 12:08:54 -07:00
out < < " CS " ;
2015-01-09 14:00:47 -07:00
if ( ts - > use_dump )
{
2015-02-14 20:53:06 -07:00
if ( ts - > dump_x_shift = = 0 )
2015-01-09 14:00:47 -07:00
{
if ( ts - > dump_y_shift > 0 )
2015-01-14 12:08:54 -07:00
out < < " dd " ;
2015-01-09 14:00:47 -07:00
else
2015-01-14 12:08:54 -07:00
out < < " d " ;
2015-01-09 14:00:47 -07:00
}
else
{
if ( ts - > dump_x_shift > 0 )
2015-01-14 12:08:54 -07:00
out < < " ddd " ;
2015-01-09 14:00:47 -07:00
else
2015-01-14 12:08:54 -07:00
out < < " dddd " ;
2015-01-09 14:00:47 -07:00
}
}
switch ( ts - > friction )
{
case 10 :
2015-01-14 12:08:54 -07:00
out < < " a " ;
2015-01-09 14:00:47 -07:00
case 50 :
2015-01-14 12:08:54 -07:00
out < < " a " ;
2015-01-09 14:00:47 -07:00
case 500 :
2015-01-14 12:08:54 -07:00
out < < " a " ;
2015-01-09 14:00:47 -07:00
case 10000 :
2015-01-14 12:08:54 -07:00
out < < " a " ;
2015-01-09 14:00:47 -07:00
}
2015-01-14 12:08:54 -07:00
return out . str ( ) ;
2015-01-09 14:00:47 -07:00
}
case building_type : : ScrewPump :
2015-01-14 12:08:54 -07:00
if ( ! at_se_corner ) //screw pumps anchor at bottom/right
return " ` " ;
2015-01-09 14:00:47 -07:00
switch ( ( ( df : : building_screw_pumpst * ) b ) - > direction )
{
case screw_pump_direction : : FromNorth :
return " Msu " ;
case screw_pump_direction : : FromEast :
return " Msk " ;
case screw_pump_direction : : FromSouth :
return " Msm " ;
case screw_pump_direction : : FromWest :
return " Msh " ;
}
case building_type : : WaterWheel :
2015-01-14 12:08:54 -07:00
if ( ! at_center )
return " ` " ;
2015-01-09 14:00:47 -07:00
//s swaps orientation which defaults to vertical
2015-01-14 12:08:54 -07:00
return ( ( df : : building_water_wheelst * ) b ) - > is_vertical ? " Mw " : " Mws " ;
2015-01-09 14:00:47 -07:00
case building_type : : Windmill :
2015-01-14 12:08:54 -07:00
if ( ! at_center )
return " ` " ;
2015-01-09 14:00:47 -07:00
return " Mm " ;
case building_type : : GearAssembly :
return " Mg " ;
case building_type : : AxleHorizontal :
2015-01-14 12:08:54 -07:00
if ( ! at_nw_corner ) //a guess based on how constructions work
return " ` " ;
2015-01-09 14:00:47 -07:00
//same as water wheel but reversed
2015-01-14 12:08:54 -07:00
out < < " Mh " < < ( ( ( df : : building_axle_horizontalst * ) b ) - > is_vertical ? " s " : " " )
< < " ( " < < size . first < < " x " < < size . second < < " ) " ;
return out . str ( ) ;
2015-01-09 14:00:47 -07:00
case building_type : : AxleVertical :
return " Mv " ;
case building_type : : Rollers :
2015-02-14 20:53:06 -07:00
if ( ! at_nw_corner )
2015-01-14 12:08:54 -07:00
return " ` " ;
out < < " Mr " ;
2015-01-09 14:00:47 -07:00
switch ( ( ( df : : building_rollersst * ) b ) - > direction )
{
case screw_pump_direction : : FromNorth :
break ;
case screw_pump_direction : : FromEast :
2015-01-14 12:08:54 -07:00
out < < " s " ;
2015-01-09 14:00:47 -07:00
case screw_pump_direction : : FromSouth :
2015-01-14 12:08:54 -07:00
out < < " s " ;
2015-02-14 20:53:06 -07:00
case screw_pump_direction : : FromWest :
2015-01-14 12:08:54 -07:00
out < < " s " ;
2015-01-09 14:00:47 -07:00
}
2015-01-14 12:08:54 -07:00
out < < " ( " < < size . first < < " x " < < size . second < < " ) " ;
return out . str ( ) ;
2015-01-09 14:00:47 -07:00
case building_type : : Support :
return " S " ;
case building_type : : ArcheryTarget :
return " A " ;
case building_type : : TractionBench :
return " R " ;
case building_type : : Hatch :
return " H " ;
case building_type : : Slab :
//how to mine alt key?!?
//alt+s
return " " ;
case building_type : : NestBox :
return " N " ;
case building_type : : Hive :
//alt+h
return " " ;
case building_type : : GrateWall :
return " W " ;
case building_type : : GrateFloor :
return " G " ;
case building_type : : BarsVertical :
return " B " ;
case building_type : : BarsFloor :
//alt+b
return " " ;
default :
return " " ;
}
}
2015-01-08 10:17:18 -07:00
2015-01-14 12:08:54 -07:00
string get_tile_place ( uint32_t x , uint32_t y , df : : building * b )
2015-01-13 12:28:28 -07:00
{
if ( ! b | | b - > getType ( ) ! = building_type : : Stockpile )
2015-01-14 12:08:54 -07:00
return " " ;
2018-04-06 00:18:15 -06:00
if ( b - > x1 ! = int32_t ( x ) | | b - > y1 ! = int32_t ( y ) )
2015-01-14 12:08:54 -07:00
return " ` " ;
pair < uint32_t , uint32_t > size = get_building_size ( b ) ;
2015-01-13 12:28:28 -07:00
df : : building_stockpilest * sp = ( df : : building_stockpilest * ) b ;
2015-01-16 01:27:14 -07:00
stringstream out ; // = stringstream();
2015-01-13 12:28:28 -07:00
switch ( sp - > settings . flags . whole )
{
case df : : stockpile_group_set : : mask_animals :
2015-01-14 12:08:54 -07:00
out < < " a " ;
break ;
2015-01-13 12:28:28 -07:00
case df : : stockpile_group_set : : mask_food :
2015-01-14 12:08:54 -07:00
out < < " f " ;
break ;
2015-01-13 12:28:28 -07:00
case df : : stockpile_group_set : : mask_furniture :
2015-01-14 12:08:54 -07:00
out < < " u " ;
break ;
2015-01-13 12:28:28 -07:00
case df : : stockpile_group_set : : mask_corpses :
2015-01-14 12:08:54 -07:00
out < < " y " ;
break ;
2015-01-13 12:28:28 -07:00
case df : : stockpile_group_set : : mask_refuse :
2015-01-14 12:08:54 -07:00
out < < " r " ;
break ;
2015-01-13 12:28:28 -07:00
case df : : stockpile_group_set : : mask_wood :
2015-01-14 12:08:54 -07:00
out < < " w " ;
break ;
2015-01-13 12:28:28 -07:00
case df : : stockpile_group_set : : mask_stone :
2015-01-14 12:08:54 -07:00
out < < " s " ;
break ;
2015-01-13 12:28:28 -07:00
case df : : stockpile_group_set : : mask_gems :
2015-01-14 12:08:54 -07:00
out < < " e " ;
break ;
2015-01-13 12:28:28 -07:00
case df : : stockpile_group_set : : mask_bars_blocks :
2015-01-14 12:08:54 -07:00
out < < " b " ;
break ;
2015-01-13 12:28:28 -07:00
case df : : stockpile_group_set : : mask_cloth :
2015-01-14 12:08:54 -07:00
out < < " h " ;
break ;
2015-01-13 12:28:28 -07:00
case df : : stockpile_group_set : : mask_leather :
2015-01-14 12:08:54 -07:00
out < < " l " ;
break ;
2015-01-13 12:28:28 -07:00
case df : : stockpile_group_set : : mask_ammo :
2015-01-14 12:08:54 -07:00
out < < " z " ;
break ;
2015-01-13 12:28:28 -07:00
case df : : stockpile_group_set : : mask_coins :
2015-01-14 12:08:54 -07:00
out < < " n " ;
break ;
2015-01-13 12:28:28 -07:00
case df : : stockpile_group_set : : mask_finished_goods :
2015-01-14 12:08:54 -07:00
out < < " g " ;
break ;
2015-01-13 12:28:28 -07:00
case df : : stockpile_group_set : : mask_weapons :
2015-01-14 12:08:54 -07:00
out < < " p " ;
break ;
2015-01-13 12:28:28 -07:00
case df : : stockpile_group_set : : mask_armor :
2015-02-14 20:53:06 -07:00
out < < " d " ;
2015-01-14 12:08:54 -07:00
break ;
2015-01-13 12:28:28 -07:00
default : //multiple stockpile type
2015-01-14 12:08:54 -07:00
return " ` " ;
2015-01-13 12:28:28 -07:00
}
2015-01-14 12:08:54 -07:00
out < < " ( " < < size . first < < " x " < < size . second < < " ) " ;
return out . str ( ) ;
2015-01-13 12:28:28 -07:00
}
2015-01-13 14:15:54 -07:00
string get_tile_query ( df : : building * b )
{
if ( b & & b - > is_room )
return " r+ " ;
return " " ;
}
2020-07-15 22:35:21 -06:00
void init_stream ( ofstream & out , std : : string basename , std : : string target )
2020-07-15 17:57:14 -06:00
{
2020-07-15 22:35:21 -06:00
std : : ostringstream out_path ;
out_path < < basename < < " - " < < target < < " .csv " ;
out . open ( out_path . str ( ) , ofstream : : trunc ) ;
2020-07-15 17:57:14 -06:00
out < < " # " < < target < < endl ;
}
command_result do_transform ( DFCoord start , DFCoord end , string name , uint32_t phases , std : : ostringstream & err )
2015-01-07 14:27:48 -07:00
{
ofstream dig , build , place , query ;
2020-07-15 17:57:14 -06:00
2020-07-15 22:35:21 -06:00
std : : string basename = " blueprints/ " + name ;
# ifdef _WIN32
// normalize to forward slashes
std : : replace ( basename . begin ( ) , basename . end ( ) , ' \\ ' , ' / ' ) ;
# endif
size_t last_slash = basename . find_last_of ( " / " ) ;
std : : string parent_path = basename . substr ( 0 , last_slash ) ;
2020-07-15 17:57:14 -06:00
// create output directory if it doesn't already exist
std : : error_code ec ;
2020-07-15 22:35:21 -06:00
if ( ! Filesystem : : mkdir_recursive ( parent_path ) )
2020-07-15 17:57:14 -06:00
{
2020-07-15 22:35:21 -06:00
err < < " could not create output directory: ' " < < parent_path < < " ' " ;
2020-07-15 17:57:14 -06:00
return CR_FAILURE ;
}
2015-01-14 12:58:15 -07:00
if ( phases & QUERY )
2015-01-07 14:27:48 -07:00
{
2015-01-16 01:27:14 -07:00
//query = ofstream((name + "-query.csv").c_str(), ofstream::trunc);
2020-07-15 17:57:14 -06:00
init_stream ( query , basename , " query " ) ;
2015-01-14 12:58:15 -07:00
}
if ( phases & PLACE )
{
2015-01-16 01:27:14 -07:00
//place = ofstream(name + "-place.csv", ofstream::trunc);
2020-07-15 17:57:14 -06:00
init_stream ( place , basename , " place " ) ;
2015-01-14 12:58:15 -07:00
}
if ( phases & BUILD )
{
2015-01-16 01:27:14 -07:00
//build = ofstream(name + "-build.csv", ofstream::trunc);
2020-07-15 17:57:14 -06:00
init_stream ( build , basename , " build " ) ;
2015-01-14 12:58:15 -07:00
}
if ( phases & DIG )
{
2015-01-16 01:27:14 -07:00
//dig = ofstream(name + "-dig.csv", ofstream::trunc);
2020-07-15 17:57:14 -06:00
init_stream ( dig , basename , " dig " ) ;
2015-01-07 14:27:48 -07:00
}
if ( start . x > end . x )
{
swap ( start . x , end . x ) ;
2015-01-08 10:17:18 -07:00
start . x + + ;
end . x + + ;
2015-01-07 14:27:48 -07:00
}
if ( start . y > end . y )
{
swap ( start . y , end . y ) ;
2015-01-08 10:17:18 -07:00
start . y + + ;
end . y + + ;
2015-01-07 14:27:48 -07:00
}
if ( start . z > end . z )
{
swap ( start . z , end . z ) ;
2015-01-08 10:17:18 -07:00
start . z + + ;
end . z + + ;
2015-01-07 14:27:48 -07:00
}
MapExtras : : MapCache mc ;
2015-01-08 10:17:18 -07:00
for ( int32_t z = start . z ; z < end . z ; z + + )
2015-01-07 14:27:48 -07:00
{
2015-01-08 10:17:18 -07:00
for ( int32_t y = start . y ; y < end . y ; y + + )
2015-01-07 14:27:48 -07:00
{
2015-01-08 10:17:18 -07:00
for ( int32_t x = start . x ; x < end . x ; x + + )
2015-01-07 14:27:48 -07:00
{
2015-01-09 14:00:47 -07:00
df : : building * b = DFHack : : Buildings : : findAtTile ( DFCoord ( x , y , z ) ) ;
2015-01-14 12:58:15 -07:00
if ( phases & QUERY )
2015-01-13 14:15:54 -07:00
query < < get_tile_query ( b ) < < ' , ' ;
2015-01-14 12:58:15 -07:00
if ( phases & PLACE )
2015-01-14 12:08:54 -07:00
place < < get_tile_place ( x , y , b ) < < ' , ' ;
2015-01-14 12:58:15 -07:00
if ( phases & BUILD )
2015-01-14 12:08:54 -07:00
build < < get_tile_build ( x , y , b ) < < ' , ' ;
2015-01-14 12:58:15 -07:00
if ( phases & DIG )
2015-01-08 10:17:18 -07:00
dig < < get_tile_dig ( mc , x , y , z ) < < ' , ' ;
2015-01-07 14:27:48 -07:00
}
2015-01-14 12:58:15 -07:00
if ( phases & QUERY )
2015-01-07 14:27:48 -07:00
query < < " # " < < endl ;
2015-01-14 12:58:15 -07:00
if ( phases & PLACE )
2015-01-07 14:27:48 -07:00
place < < " # " < < endl ;
2015-01-14 12:58:15 -07:00
if ( phases & BUILD )
2015-01-08 10:17:18 -07:00
build < < " # " < < endl ;
2015-01-14 12:58:15 -07:00
if ( phases & DIG )
2015-01-07 14:27:48 -07:00
dig < < " # " < < endl ;
}
if ( z < end . z - 1 )
2015-01-14 12:58:15 -07:00
{
if ( phases & QUERY )
2015-01-08 10:17:18 -07:00
query < < " #< " < < endl ;
2015-01-14 12:58:15 -07:00
if ( phases & PLACE )
2015-01-08 10:17:18 -07:00
place < < " #< " < < endl ;
2015-01-14 12:58:15 -07:00
if ( phases & BUILD )
2015-01-08 10:17:18 -07:00
build < < " #< " < < endl ;
2015-01-14 12:58:15 -07:00
if ( phases & DIG )
2015-01-08 10:17:18 -07:00
dig < < " #< " < < endl ;
2015-01-09 14:00:47 -07:00
}
2015-01-07 14:27:48 -07:00
}
2015-01-14 12:58:15 -07:00
if ( phases & QUERY )
2015-01-07 14:27:48 -07:00
query . close ( ) ;
2015-01-14 12:58:15 -07:00
if ( phases & PLACE )
2015-01-07 14:27:48 -07:00
place . close ( ) ;
2015-01-14 12:58:15 -07:00
if ( phases & BUILD )
2015-01-08 10:17:18 -07:00
build . close ( ) ;
2015-01-14 12:58:15 -07:00
if ( phases & DIG )
2015-01-07 14:27:48 -07:00
dig . close ( ) ;
return CR_OK ;
}
2015-01-14 12:58:15 -07:00
bool cmd_option_exists ( vector < string > & parameters , const string & option )
{
return find ( parameters . begin ( ) , parameters . end ( ) , option ) ! = parameters . end ( ) ;
}
command_result blueprint ( color_ostream & out , vector < string > & parameters )
2015-01-07 14:27:48 -07:00
{
if ( parameters . size ( ) < 4 | | parameters . size ( ) > 8 )
return help ( out ) ;
CoreSuspender suspend ;
if ( ! Maps : : IsValid ( ) )
{
out . printerr ( " Map is not available! \n " ) ;
return CR_FAILURE ;
}
int32_t x , y , z ;
if ( ! Gui : : getCursorCoords ( x , y , z ) )
{
out . printerr ( " Can't get cursor coords! Make sure you have an active cursor in DF. \n " ) ;
return CR_FAILURE ;
}
DFCoord start ( x , y , z ) ;
2015-01-08 10:17:18 -07:00
DFCoord end ( x + stoi ( parameters [ 0 ] ) , y + stoi ( parameters [ 1 ] ) , z + stoi ( parameters [ 2 ] ) ) ;
2015-01-14 12:58:15 -07:00
uint32_t option = 0 ;
2020-07-15 17:57:14 -06:00
if ( parameters . size ( ) = = 4 )
{
option = DIG | BUILD | PLACE | QUERY ;
}
else
{
if ( cmd_option_exists ( parameters , " dig " ) )
option | = DIG ;
if ( cmd_option_exists ( parameters , " build " ) )
option | = BUILD ;
if ( cmd_option_exists ( parameters , " place " ) )
option | = PLACE ;
if ( cmd_option_exists ( parameters , " query " ) )
option | = QUERY ;
}
std : : ostringstream err ;
DFHack : : command_result result = do_transform ( start , end , parameters [ 3 ] , option , err ) ;
if ( result ! = CR_OK )
out . printerr ( " %s \n " , err . str ( ) . c_str ( ) ) ;
return result ;
2015-01-16 01:27:14 -07:00
}
2018-05-08 12:42:41 -06:00
static int create ( lua_State * L , uint32_t options ) {
df : : coord start , end ;
lua_settop ( L , 3 ) ;
Lua : : CheckDFAssign ( L , & start , 1 ) ;
if ( ! start . isValid ( ) )
luaL_argerror ( L , 1 , " invalid start position " ) ;
Lua : : CheckDFAssign ( L , & end , 2 ) ;
if ( ! end . isValid ( ) )
luaL_argerror ( L , 2 , " invalid end position " ) ;
string filename ( lua_tostring ( L , 3 ) ) ;
2020-07-15 17:57:14 -06:00
std : : ostringstream err ;
DFHack : : command_result result = do_transform ( start , end , filename , options , err ) ;
if ( result ! = CR_OK )
luaL_error ( L , " %s " , err . str ( ) . c_str ( ) ) ;
lua_pushboolean ( L , result ) ;
2018-05-08 12:42:41 -06:00
return 1 ;
}
static int dig ( lua_State * L ) {
return create ( L , DIG ) ;
}
static int build ( lua_State * L ) {
return create ( L , BUILD ) ;
}
static int place ( lua_State * L ) {
return create ( L , PLACE ) ;
}
static int query ( lua_State * L ) {
return create ( L , QUERY ) ;
}
DFHACK_PLUGIN_LUA_COMMANDS {
DFHACK_LUA_COMMAND ( dig ) ,
DFHACK_LUA_COMMAND ( build ) ,
DFHACK_LUA_COMMAND ( place ) ,
DFHACK_LUA_COMMAND ( query ) ,
DFHACK_LUA_END
} ;