Skip to content

Commit 269eef8

Browse files
Bring back zones in gui/blueprint (WIP) (DFHack#5222)
* Restore zones to blueprints * Begin refactor of get_zone_keys * more refactor * Make zones almost completely work * Update the zone keys * Update blueprint.cpp
1 parent 6ad91b6 commit 269eef8

3 files changed

Lines changed: 66 additions & 172 deletions

File tree

docs/plugins/blueprint.rst

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,6 @@ selected interactively with the `gui/blueprint` command or, if the GUI is not
1515
used, starts at the active cursor location and extends right and down for the
1616
requested width and height.
1717

18-
.. admonition:: Note
19-
20-
blueprint is still in the process of being updated for the new version of
21-
DF. Stockpiles (the "place" phase), zones (the "zone" phase), building
22-
configuration (the "query" phase), and game configuration (the "config"
23-
phase) are not yet supported.
24-
2518
Usage
2619
-----
2720

@@ -83,11 +76,6 @@ phases; just separate them with a space.
8376
Generate quickfort ``#place`` blueprints for placing stockpiles.
8477
``zone``
8578
Generate quickfort ``#zone`` blueprints for designating zones.
86-
``query``
87-
Generate quickfort ``#query`` blueprints for configuring stockpiles and
88-
naming buildings.
89-
``rooms``
90-
Generate quickfort ``#query`` blueprints for defining rooms.
9179

9280
If no phases are specified, phases are autodetected. For example, a ``#place``
9381
blueprint will be created only if there are stockpiles in the blueprint area.

plugins/blueprint.cpp

Lines changed: 64 additions & 155 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,8 @@ struct blueprint_options {
106106
bool construct = false;
107107
bool build = false;
108108
bool place = false;
109-
// bool zone = false;
110-
// bool query = false;
111-
// bool rooms = false;
109+
bool zone = false;
110+
112111

113112
static struct_identity _identity;
114113
};
@@ -132,9 +131,7 @@ static const struct_field_info blueprint_options_fields[] = {
132131
{ struct_field_info::PRIMITIVE, "construct", offsetof(blueprint_options, construct), &df::identity_traits<bool>::identity, 0, 0 },
133132
{ struct_field_info::PRIMITIVE, "build", offsetof(blueprint_options, build), &df::identity_traits<bool>::identity, 0, 0 },
134133
{ struct_field_info::PRIMITIVE, "place", offsetof(blueprint_options, place), &df::identity_traits<bool>::identity, 0, 0 },
135-
// { struct_field_info::PRIMITIVE, "zone", offsetof(blueprint_options, zone), &df::identity_traits<bool>::identity, 0, 0 },
136-
// { struct_field_info::PRIMITIVE, "query", offsetof(blueprint_options, query), &df::identity_traits<bool>::identity, 0, 0 },
137-
// { struct_field_info::PRIMITIVE, "rooms", offsetof(blueprint_options, rooms), &df::identity_traits<bool>::identity, 0, 0 },
134+
{ struct_field_info::PRIMITIVE, "zone", offsetof(blueprint_options, zone), &df::identity_traits<bool>::identity, 0, 0 },
138135
{ struct_field_info::END }
139136
};
140137
struct_identity blueprint_options::_identity(sizeof(blueprint_options), &df::allocator_fn<blueprint_options>, NULL, "blueprint_options", NULL, blueprint_options_fields);
@@ -1107,78 +1104,70 @@ static const char * get_tile_place(const df::coord &pos,
11071104
return add_expansion_syntax(ctx, get_place_keys(ctx));
11081105
}
11091106

1110-
/* TODO: understand how this changes for v50
1111-
static bool hospital_maximums_eq(const df::hospital_supplies &a,
1112-
const df::hospital_supplies &b) {
1113-
return a.max_thread == b.max_thread &&
1114-
a.max_cloth == b.max_cloth &&
1115-
a.max_splints == b.max_splints &&
1116-
a.max_crutches == b.max_crutches &&
1117-
a.max_plaster == b.max_plaster &&
1118-
a.max_buckets == b.max_buckets &&
1119-
a.max_soap == b.max_soap;
1120-
}
1121-
11221107
static const char * get_zone_keys(const df::building_civzonest *zone) {
11231108
static const uint32_t DEFAULT_GATHER_FLAGS =
1124-
df::building_civzonest::T_gather_flags::mask_pick_trees |
1125-
df::building_civzonest::T_gather_flags::mask_pick_shrubs |
1126-
df::building_civzonest::T_gather_flags::mask_gather_fallen;
1127-
static const df::hospital_supplies DEFAULT_HOSPITAL;
1109+
df::civzone_gather_flag::mask_pick_trees |
1110+
df::civzone_gather_flag::mask_pick_shrubs |
1111+
df::civzone_gather_flag::mask_gather_fallen;
11281112

11291113
ostringstream keys;
1130-
const df::building_civzonest::T_zone_flags &flags = zone->zone_flags;
1131-
1132-
// inverted logic for Active since it's on by default
1133-
if (!flags.bits.active) keys << 'a';
1134-
1135-
// in UI order
1136-
if (flags.bits.water_source) keys << 'w';
1137-
if (flags.bits.fishing) keys << 'f';
1138-
if (flags.bits.gather) {
1139-
keys << 'g';
1140-
if (zone->gather_flags.whole != DEFAULT_GATHER_FLAGS) {
1141-
keys << 'G';
1142-
// logic is inverted since they're all on by default
1143-
if (!zone->gather_flags.bits.pick_trees) keys << 't';
1144-
if (!zone->gather_flags.bits.pick_shrubs) keys << 's';
1145-
if (!zone->gather_flags.bits.gather_fallen) keys << 'f';
1146-
keys << '^';
1147-
}
1114+
const df::civzone_type type = zone->type;
1115+
1116+
// in DFHack docs order
1117+
if (type == df::civzone_type::MeetingHall) keys << 'm';
1118+
if (type == df::civzone_type::Bedroom) keys << 'b';
1119+
if (type == df::civzone_type::DiningHall) keys << 'h';
1120+
if (type == df::civzone_type::Pen) keys << 'n';
1121+
if (type == df::civzone_type::Pond) keys << 'p';
1122+
if (type == df::civzone_type::WaterSource) keys << 'w';
1123+
if (type == df::civzone_type::Dungeon) keys << 'j';
1124+
if (type == df::civzone_type::FishingArea) keys << 'f';
1125+
if (type == df::civzone_type::SandCollection) keys << 's';
1126+
if (type == df::civzone_type::Office) keys << 'o';
1127+
if (type == df::civzone_type::Dormitory) keys << 'D';
1128+
if (type == df::civzone_type::Barracks) keys << 'B';
1129+
if (type == df::civzone_type::ArcheryRange) keys << 'a';
1130+
if (type == df::civzone_type::Dump) keys << 'd';
1131+
if (type == df::civzone_type::AnimalTraining) keys << 't';
1132+
if (type == df::civzone_type::Tomb) keys << 'T';
1133+
if (type == df::civzone_type::PlantGathering) keys << 'g';
1134+
if (type == df::civzone_type::ClayCollection) keys << 'c';
1135+
1136+
keys << '{';
1137+
if (!zone->name.empty()) {
1138+
keys << "name=" << zone->name << ' ';
11481139
}
1149-
if (flags.bits.garbage_dump) keys << 'd';
1150-
if (flags.bits.pen_pasture) keys << 'n';
1151-
if (flags.bits.pit_pond) {
1152-
keys << 'p';
1153-
if (zone->pit_flags.bits.is_pond)
1154-
keys << "Pf^";
1140+
if (!zone->spec_sub_flag.bits.active) {
1141+
keys << "active=false ";
11551142
}
1156-
if (flags.bits.sand) keys << 's';
1157-
if (flags.bits.clay) keys << 'c';
1158-
if (flags.bits.meeting_area) keys << 'm';
1159-
if (flags.bits.hospital) {
1160-
keys << 'h';
1161-
const df::hospital_supplies &hospital = zone->hospital;
1162-
if (!hospital_maximums_eq(hospital, DEFAULT_HOSPITAL)) {
1163-
keys << "H{hospital";
1164-
if (hospital.max_thread != DEFAULT_HOSPITAL.max_thread)
1165-
keys << " thread=" << hospital.max_thread;
1166-
if (hospital.max_cloth != DEFAULT_HOSPITAL.max_cloth)
1167-
keys << " cloth=" << hospital.max_cloth;
1168-
if (hospital.max_splints != DEFAULT_HOSPITAL.max_splints)
1169-
keys << " splints=" << hospital.max_splints;
1170-
if (hospital.max_crutches != DEFAULT_HOSPITAL.max_crutches)
1171-
keys << " crutches=" << hospital.max_crutches;
1172-
if (hospital.max_plaster != DEFAULT_HOSPITAL.max_plaster)
1173-
keys << " plaster=" << hospital.max_plaster;
1174-
if (hospital.max_buckets != DEFAULT_HOSPITAL.max_buckets)
1175-
keys << " buckets=" << hospital.max_buckets;
1176-
if (hospital.max_soap != DEFAULT_HOSPITAL.max_soap)
1177-
keys << " soap=" << hospital.max_soap;
1178-
keys << "}^";
1179-
}
1143+
if (zone->assigned_unit) {
1144+
keys << "assigned_unit=" << zone->assigned_unit << ' ';
1145+
}
1146+
if (!zone->zone_settings.pond.flag.bits.keep_filled) {
1147+
keys << "pond=false ";
1148+
}
1149+
auto archery_settings = zone->zone_settings.archery; // need this to get the `shoot_from` direction
1150+
if (archery_settings.dir_y == 0) {
1151+
if (archery_settings.dir_x == 1) keys << "shoot_from=west ";
1152+
if (archery_settings.dir_x == -1) keys << "shoot_from=east ";
1153+
}
1154+
if (archery_settings.dir_x == 0) {
1155+
if (archery_settings.dir_y == 1) keys << "shoot_from=north ";
1156+
if (archery_settings.dir_y == -1) keys << "shoot_from=south ";
1157+
}
1158+
//FIXEME (Squid): Need to know how to get the location data here
1159+
if (!zone->zone_settings.tomb.flags.bits.no_pets) {
1160+
keys << "pets=true ";
1161+
}
1162+
if (zone->zone_settings.tomb.flags.bits.no_citizens) {
1163+
keys << "citizens=false ";
1164+
}
1165+
if (zone->zone_settings.gather.flags.whole != DEFAULT_GATHER_FLAGS) {
1166+
// logic is inverted since they're all on by default
1167+
if (!zone->zone_settings.gather.flags.bits.pick_trees) keys << "pick_trees=false ";
1168+
if (!zone->zone_settings.gather.flags.bits.pick_shrubs) keys << "pick_shrubs=false ";
1169+
if (!zone->zone_settings.gather.flags.bits.gather_fallen) keys << "gather_fallen=false ";
11801170
}
1181-
if (flags.bits.animal_training) keys << 't';
11821171

11831172
string keys_str = keys.str();
11841173

@@ -1187,8 +1176,11 @@ static const char * get_zone_keys(const df::building_civzonest *zone) {
11871176
return NULL;
11881177

11891178
// remove final '^' character if there is one
1190-
if (keys_str.back() == '^')
1179+
if (keys_str.back() == '{') {
11911180
keys_str.pop_back();
1181+
} else {
1182+
keys << '}';
1183+
}
11921184

11931185
return cache(keys_str);
11941186
}
@@ -1215,84 +1207,7 @@ static const char * get_tile_zone(const df::coord &pos,
12151207
return add_expansion_syntax(zone, get_zone_keys(zone));
12161208
}
12171209

1218-
// surrounds the given string in quotes and replaces internal double quotes (")
1219-
// with double double quotes ("") (as per the csv spec)
1220-
static string csv_quote(const string &str) {
1221-
ostringstream outstr;
1222-
outstr << "\"";
1223-
1224-
size_t start = 0;
1225-
auto end = str.find('"');
1226-
while (end != string::npos) {
1227-
outstr << str.substr(start, end - start);
1228-
outstr << "\"\"";
1229-
start = end + 1;
1230-
end = str.find('"', start);
1231-
}
1232-
outstr << str.substr(start, end) << "\"";
1233-
1234-
return outstr.str();
1235-
}
1236-
1237-
static const char * get_tile_query(const df::coord &pos,
1238-
const tile_context &ctx) {
1239-
string bld_name, zone_name;
1240-
auto & seen = ctx.processor->seen;
1241-
1242-
if (ctx.b && !seen.count(ctx.b)) {
1243-
bld_name = ctx.b->name;
1244-
seen.emplace(ctx.b);
1245-
}
1246-
1247-
vector<df::building_civzonest*> civzones;
1248-
if (Buildings::findCivzonesAt(&civzones, pos)) {
1249-
auto civzone = civzones.back();
1250-
if (!seen.count(civzone)) {
1251-
zone_name = civzone->name;
1252-
seen.emplace(civzone);
1253-
}
1254-
}
1255-
1256-
if (!bld_name.size() && !zone_name.size())
1257-
return NULL;
1258-
1259-
ostringstream str;
1260-
if (bld_name.size())
1261-
str << "{givename name=" + csv_quote(bld_name) + "}";
1262-
if (zone_name.size())
1263-
str << "{namezone name=" + csv_quote(zone_name) + "}";
1264-
1265-
return cache(csv_quote(str.str()));
1266-
}
1267-
1268-
static const char * get_tile_rooms(const df::coord &, const tile_context &ctx) {
1269-
if (!ctx.b || !ctx.b->is_room)
1270-
return NULL;
12711210

1272-
// get the maximum distance from the center of the building
1273-
df::building_extents &room = ctx.b->room;
1274-
int32_t x1 = room.x;
1275-
int32_t x2 = room.x + room.width - 1;
1276-
int32_t y1 = room.y;
1277-
int32_t y2 = room.y + room.height - 1;
1278-
1279-
int32_t dimx = std::max(ctx.b->centerx - x1, x2 - ctx.b->centerx);
1280-
int32_t dimy = std::max(ctx.b->centery - y1, y2 - ctx.b->centery);
1281-
int32_t max_dim = std::max(dimx, dimy);
1282-
1283-
switch (max_dim) {
1284-
case 0: return "r---&";
1285-
case 1: return "r--&";
1286-
case 2: return "r-&";
1287-
case 3: return "r&";
1288-
case 4: return "r+&";
1289-
}
1290-
1291-
ostringstream str;
1292-
str << "r{+ " << (max_dim - 3) << "}&";
1293-
return cache(str);
1294-
}
1295-
*/
12961211

12971212
static bool create_output_dir(color_ostream &out,
12981213
const blueprint_options &opts) {
@@ -1503,13 +1418,7 @@ static bool do_transform(color_ostream &out,
15031418
get_tile_build, ensure_building);
15041419
add_processor(processors, opts, "place", "place", opts.place,
15051420
get_tile_place, ensure_building);
1506-
/* TODO: understand how this changes for v50
15071421
add_processor(processors, opts, "zone", "zone", opts.zone, get_tile_zone);
1508-
add_processor(processors, opts, "query", "query", opts.query,
1509-
get_tile_query, ensure_building);
1510-
add_processor(processors, opts, "query", "rooms", opts.rooms,
1511-
get_tile_rooms, ensure_building);
1512-
*/
15131422
if (processors.empty()) {
15141423
out.printerr("no phases requested! nothing to do!\n");
15151424
return false;

plugins/lua/blueprint.lua

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,14 @@ local valid_phase_list = {
99
'construct',
1010
'build',
1111
'place',
12-
-- 'zone',
13-
-- 'query',
14-
-- 'rooms',
12+
'zone',
1513
}
1614
valid_phases = utils.invert(valid_phase_list)
1715

1816
local meta_phase_list = {
1917
'build',
2018
'place',
21-
-- 'zone',
22-
-- 'query',
19+
'zone',
2320
}
2421
meta_phases = utils.invert(meta_phase_list)
2522

0 commit comments

Comments
 (0)