Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#5031: Fix accessibility logic for wagons #5053

Merged
merged 25 commits into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
50fe672
#5031: Handle top ramps when pathfinding to depot
dhthwy Nov 29, 2024
7e6ec6f
#5031: Assign RAMP_TOP a walkability group from an adjacent tile
dhthwy Nov 29, 2024
ec83a70
#5031: Remove debug prints
dhthwy Nov 29, 2024
2b76868
#5031: Fix MSVC build. Missing headers?
dhthwy Nov 29, 2024
d6083da
Merge branch 'develop' into wagonpathfix
dhthwy Nov 29, 2024
3c7a3b2
#5031: make wagon_flood() check it reaches an edge tile for correctly…
dhthwy Nov 30, 2024
8ea4f6a
#5031: Make wagon pathability tests more robust
dhthwy Dec 1, 2024
317b87d
Merge branch 'develop' into wagonpathfix
dhthwy Dec 1, 2024
a0a37f3
Correctly handle wagon accessible tiles for passable buildings
dhthwy Dec 1, 2024
2a1a734
#5031: handle tracks, murky pool and river tiles
dhthwy Dec 2, 2024
d11dd6d
Merge branch 'develop' into wagonpathfix
dhthwy Dec 7, 2024
7c384c9
Revert "#5031: Fix MSVC build. Missing headers?"
dhthwy Dec 7, 2024
464ef96
Revert "#5031: Remove debug prints"
dhthwy Dec 7, 2024
47eb2ed
Revert "#5031: Assign RAMP_TOP a walkability group from an adjacent t…
dhthwy Dec 7, 2024
3acd1eb
Revert "#5031: Handle top ramps when pathfinding to depot"
dhthwy Dec 7, 2024
0063cd7
remove invalidated RAMP_TOP comment
dhthwy Dec 7, 2024
67497ed
#5031: update changelog
dhthwy Dec 7, 2024
10dd5d0
#5031: check the center too. maybe fix errant passable trees/boulders.
dhthwy Dec 8, 2024
7e33948
Merge branch 'develop' into wagonpathfix
dhthwy Dec 8, 2024
22c7ebe
Merge branch 'develop' into wagonpathfix
dhthwy Dec 8, 2024
6c5dc47
Merge branch 'develop' into wagonpathfix
myk002 Dec 9, 2024
d5ac7c6
Merge branch 'develop' into wagonpathfix
dhthwy Dec 9, 2024
e926210
#5031: check if path exists for bottom and right edge tiles too, plus…
dhthwy Dec 9, 2024
ef0b0e4
#5031: resolve some other minor issues
dhthwy Dec 9, 2024
5d24e07
#5031: don't add non-edge tiles to entry_tiles
dhthwy Dec 9, 2024
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: 1 addition & 0 deletions docs/changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ Template for new versions:
- `timestream`: improve FPS by a further 10%
- `fix/occupancy`: additionally handle the case where tile building occupancy needs to be set instead of cleared
- `orders`: ``orders sort`` now moves orders that are tied to a specific workshop to the top of the list in the global manager orders screen
- `gui/pathable`: make wagon path to depot representation more robust

## Documentation
- Dreamfort: add link to Dreamfort tutorial youtube series: https://www.youtube.com/playlist?list=PLzXx9JcB9oXxmrtkO1y8ZXzBCFEZrKxve
Expand Down
105 changes: 97 additions & 8 deletions plugins/pathable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
#include "PluginManager.h"
#include "TileTypes.h"

#include "df/building_type.h"
#include "df/building_hatchst.h"
#include "df/building_bars_floorst.h"
#include "df/building_grate_floorst.h"
#include "df/tile_building_occ.h"
#include "modules/Buildings.h"
#include "modules/Gui.h"
#include "modules/Maps.h"
Expand Down Expand Up @@ -168,11 +173,14 @@ static bool get_pathability_groups(color_ostream &out, unordered_set<uint16_t> *
static bool get_entry_tiles(unordered_set<df::coord> * entry_tiles, const unordered_set<uint16_t> & depot_pathability_groups) {
auto & edge = plotinfo->map_edge;
size_t num_edge_tiles = edge.surface_x.size();
uint32_t max_x, max_y, max_z;
Maps::getTileSize(max_x, max_y, max_z);
bool found = false;
for (size_t idx = 0; idx < num_edge_tiles; ++idx) {
df::coord pos(edge.surface_x[idx], edge.surface_y[idx], edge.surface_z[idx]);
auto wgroup = Maps::getWalkableGroup(pos);
if (depot_pathability_groups.contains(wgroup)) {
if (depot_pathability_groups.contains(wgroup) &&
(pos.x == 0 || pos.y == 0 || pos.x == (int16_t)max_x || pos.y == (int16_t)max_y)) {
found = true;
if (!entry_tiles)
break;
Expand Down Expand Up @@ -203,20 +211,99 @@ struct FloodCtx {
: wgroup(wgroup), wagon_path(wagon_path), entry_tiles(entry_tiles) {}
};

static bool is_wagon_traversible(FloodCtx & ctx, const df::coord & pos, const df::coord & prev_pos) {
if (auto bld = Buildings::findAtTile(pos)) {
auto btype = bld->getType();
if (btype == df::building_type::Trap || btype == df::building_type::Door)
static bool is_wagon_dynamic_traversible(df::tiletype_shape shape, const df::coord & pos) {
auto bld = Buildings::findAtTile(pos);
if (!bld) return false;

auto btype = bld->getType();
// open hatch should be inaccessible regardless of the tile it sits on
if (btype == df::building_type::Hatch) {
if (shape == df::tiletype_shape::RAMP_TOP)
return false;

auto& hatch = *static_cast<df::building_hatchst*>(bld);
if (hatch.door_flags.bits.closed)
return true;
// open floor grate/bar should be inaccessible regardless of the tile it sits on
} else if (btype == df::building_type::GrateFloor) {
auto& b = *static_cast<df::building_grate_floorst*>(bld);
if (b.gate_flags.bits.closed)
return true;
} else if (btype == df::building_type::BarsFloor) {
auto& b = *static_cast<df::building_bars_floorst*>(bld);
if (b.gate_flags.bits.closed)
return true;
}
// Doors, traps..etc
return false;
}

// NOTE: When i.e. tracks, stairs have a bridge over them, the tile will have
// an occupancy of floored.
static bool is_wagon_tile_traversible(df::tiletype tt) {
auto shape = tileShape(tt);
auto special = tileSpecial(tt);
auto material = tileMaterial(tt);

// Allow ramps (murky pool and river tiles are blocked except for ramps)
if (shape == df::tiletype_shape::RAMP_TOP)
return true;
// NOTE: smoothing a boulder turns it into a smoothed floor
else if (shape == df::tiletype_shape::STAIR_UP || shape == df::tiletype_shape::STAIR_DOWN ||
shape == df::tiletype_shape::STAIR_UPDOWN || shape == df::tiletype_shape::BOULDER ||
shape == df::tiletype_shape::EMPTY || shape == df::tiletype_shape::NONE)
return false;
else if (special == df::tiletype_special::TRACK)
return false;
// Fires seem to have their own path group, and group for lava is 0
// According to wiki, the wagon won't path thru pool and river tiles, but ramps are ok
else if (material == df::tiletype_material::POOL || material == df::tiletype_material::RIVER)
return false;

return true;
}

static bool is_wagon_traversible(FloodCtx & ctx, const df::coord & pos, const df::coord & prev_pos) {
auto tt = Maps::getTileType(pos);
if (!tt)
return false;

auto shape = tileShape(*tt);
if (shape == df::tiletype_shape::STAIR_UP || shape == df::tiletype_shape::STAIR_UPDOWN)
auto occp = Maps::getTileOccupancy(pos);
if (!occp)
return false;
auto & occ = *occp;
switch (occ.bits.building) {
case tile_building_occ::Obstacle: // Statues, windmills (middle tile)
//FALLTHROUGH
case tile_building_occ::Well:
//FALLTHROUGH
case tile_building_occ::Impassable: // Raised bridges
return false;

case tile_building_occ::Dynamic:
// doors(block), levers (block), traps (block), hatches (OK, but block on down ramp)
// closed floor grates (OK), closed floor bars (OK)
if (is_wagon_dynamic_traversible(shape, pos) == false)
return false;
break;

case tile_building_occ::None: // Not occupied by a building
//FALLTHROUGH
case tile_building_occ::Planned:
//FALLTHROUGH
case tile_building_occ::Passable:
// Any tile with no building or a passable building including
// beds, supports, rollers, armor/weapon stands, cages (not traps),
// open wall grate/vertical bars, retracted bridges, open floodgates,
// workshops (tiles with open space are handled by the tile check)
if (is_wagon_tile_traversible(*tt) == false)
return false;
break;
case tile_building_occ::Floored:
// depot, lowered bridges or retractable bridges, forbidden hatches
break;
}

if (ctx.wgroup == Maps::getWalkableGroup(pos))
return true;
Expand Down Expand Up @@ -248,12 +335,13 @@ static void check_wagon_tile(FloodCtx & ctx, const df::coord & pos) {
ctx.seen.emplace(pos);

if (ctx.entry_tiles.contains(pos)) {
ctx.wagon_path.emplace(pos);
ctx.wagon_path.emplace(pos); // Is this needed?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably not since the rendering of the edge tile will overwrite the rendering of the wagon path

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually, keep this in, since we might want to highlight the overlap (by coloring it green?)

ctx.search_edge.emplace(pos);
return;
}

if (is_wagon_traversible(ctx, pos+df::coord(-1, -1, 0), pos) &&
if (is_wagon_traversible(ctx, pos, pos) &&
is_wagon_traversible(ctx, pos+df::coord(-1, -1, 0), pos) &&
is_wagon_traversible(ctx, pos+df::coord( 0, -1, 0), pos) &&
is_wagon_traversible(ctx, pos+df::coord( 1, -1, 0), pos) &&
is_wagon_traversible(ctx, pos+df::coord(-1, 0, 0), pos) &&
Expand Down Expand Up @@ -286,6 +374,7 @@ static bool wagon_flood(color_ostream &out, unordered_set<df::coord> * wagon_pat
ctx.wagon_path.emplace(depot_pos);
ctx.seen.emplace(depot_pos);
ctx.search_edge.emplace(depot_pos);

while (!ctx.search_edge.empty()) {
df::coord pos = ctx.search_edge.top();
ctx.search_edge.pop();
Expand Down
Loading