check items for accessibility for dialogs

before we only checked when doing the cycle, so if an inaccessible item
were manually selected, we'd never be able to build
develop
Myk Taylor 2023-04-26 21:01:21 -07:00
parent ba06a8f2bb
commit 1b8fc20ad5
No known key found for this signature in database
4 changed files with 24 additions and 23 deletions

@ -38,6 +38,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences:
## Fixes
- `autoclothing`: eliminate game lag when there are many inventory items in the fort
- `buildingplan`: fixed size limit calculations for rollers
- `buildingplan`: fixed items not being checked for accessibility in the filter and item selection dialogs
- `dig-now`: properly detect and complete smoothing designations that have been converted into active jobs
## Misc Improvements

@ -704,7 +704,7 @@ static int scanAvailableItems(color_ostream &out, df::building_type type, int16_
filter.setMaterials(set<MaterialInfo>());
special.clear();
}
if (itemPassesScreen(item) && matchesFilters(item, jitem, heat, filter, special)) {
if (itemPassesScreen(out, item) && matchesFilters(item, jitem, heat, filter, special)) {
if (item_ids)
item_ids->emplace_back(item->id);
if (counts) {

@ -54,7 +54,7 @@ void set_config_val(DFHack::PersistentDataItem &c, int index, int value);
void set_config_bool(DFHack::PersistentDataItem &c, int index, bool value);
std::vector<df::job_item_vector_id> getVectorIds(DFHack::color_ostream &out, const df::job_item *job_item, bool ignore_filters);
bool itemPassesScreen(df::item * item);
bool itemPassesScreen(DFHack::color_ostream& out, df::item* item);
df::job_item getJobItemWithHeatSafety(const df::job_item *job_item, HeatSafety heat);
bool matchesFilters(df::item * item, const df::job_item * job_item, HeatSafety heat, const ItemFilter &item_filter, const std::set<std::string> &special);
bool isJobReady(DFHack::color_ostream &out, const std::vector<df::job_item *> &jitems);

@ -43,10 +43,27 @@ struct BadFlags {
}
};
bool itemPassesScreen(df::item * item) {
// This is tricky. we want to choose an item that can be brought to the job site, but that's not
// necessarily the same as job->pos. it could be many tiles off in any direction (e.g. for bridges), or
// up or down (e.g. for stairs). For now, just return if the item is on a walkable tile.
static bool isAccessible(color_ostream& out, df::item* item) {
df::coord item_pos = Items::getPosition(item);
df::map_block* block = Maps::getTileBlock(item_pos);
bool is_walkable = false;
if (block) {
uint16_t walkability_group = index_tile(block->walkable, item_pos);
is_walkable = walkability_group != 0;
TRACE(cycle, out).print("item %d in walkability_group %u at (%d,%d,%d) is %saccessible from job site\n",
item->id, walkability_group, item_pos.x, item_pos.y, item_pos.z, is_walkable ? "(probably) " : "not ");
}
return is_walkable;
}
bool itemPassesScreen(color_ostream& out, df::item* item) {
static const BadFlags bad_flags;
return !(item->flags.whole & bad_flags.whole)
&& !item->isAssignedToStockpile();
&& !item->isAssignedToStockpile()
&& isAccessible(out, item);
}
df::job_item getJobItemWithHeatSafety(const df::job_item *job_item, HeatSafety heat) {
@ -165,22 +182,6 @@ static df::building * popInvalidTasks(color_ostream &out, Bucket &task_queue,
return NULL;
}
// This is tricky. we want to choose an item that can be brought to the job site, but that's not
// necessarily the same as job->pos. it could be many tiles off in any direction (e.g. for bridges), or
// up or down (e.g. for stairs). For now, just return if the item is on a walkable tile.
static bool isAccessibleFrom(color_ostream &out, df::item *item, df::job *job) {
df::coord item_pos = Items::getPosition(item);
df::map_block *block = Maps::getTileBlock(item_pos);
bool is_walkable = false;
if (block) {
uint16_t walkability_group = index_tile(block->walkable, item_pos);
is_walkable = walkability_group != 0;
TRACE(cycle,out).print("item %d in walkability_group %u at (%d,%d,%d) is %saccessible from job site\n",
item->id, walkability_group, item_pos.x, item_pos.y, item_pos.z, is_walkable ? "" : "not ");
}
return is_walkable;
}
static void doVector(color_ostream &out, df::job_item_vector_id vector_id,
map<string, Bucket> &buckets,
unordered_map<int32_t, PlannedBuilding> &planned_buildings,
@ -195,7 +196,7 @@ static void doVector(color_ostream &out, df::job_item_vector_id vector_id,
item_it != item_vector.rend();
++item_it) {
auto item = *item_it;
if (!itemPassesScreen(item))
if (!itemPassesScreen(out, item))
continue;
for (auto bucket_it = buckets.begin(); bucket_it != buckets.end(); ) {
TRACE(cycle,out).print("scanning bucket: %s/%s\n",
@ -218,8 +219,7 @@ static void doVector(color_ostream &out, df::job_item_vector_id vector_id,
auto filter_idx = task.second;
const int rev_filter_idx = num_filters - (filter_idx+1);
auto &pb = planned_buildings.at(id);
if (isAccessibleFrom(out, item, job)
&& matchesFilters(item, jitems[filter_idx], pb.heat_safety,
if (matchesFilters(item, jitems[filter_idx], pb.heat_safety,
pb.item_filters[rev_filter_idx], pb.specials)
&& Job::attachJobItem(job, item,
df::job_item_ref::Hauled, filter_idx))