-
Notifications
You must be signed in to change notification settings - Fork 481
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
Changes from 21 commits
50fe672
7e6ec6f
ec83a70
2b76868
d6083da
3c7a3b2
8ea4f6a
317b87d
a0a37f3
2a1a734
d11dd6d
7c384c9
464ef96
47eb2ed
3acd1eb
0063cd7
67497ed
10dd5d0
7e33948
22c7ebe
6c5dc47
d5ac7c6
e926210
ef0b0e4
5d24e07
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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" | ||
|
@@ -203,20 +208,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 murky pool ramps | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe explain why you're calling out murky pools in particular |
||
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) | ||
return false; | ||
auto& occ = *Maps::getTileOccupancy(pos); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. while the return value should never ever be NULL if |
||
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; | ||
default: | ||
//NOTREACHED | ||
break; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can remove the default case so the compiler complains if another case ever appears |
||
} | ||
|
||
if (ctx.wgroup == Maps::getWalkableGroup(pos)) | ||
return true; | ||
|
@@ -248,12 +332,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? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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) && | ||
|
@@ -293,7 +378,10 @@ static bool wagon_flood(color_ostream &out, unordered_set<df::coord> * wagon_pat | |
TRACE(log,out).print("checking tile: (%d, %d, %d); pathability group: %d\n", pos.x, pos.y, pos.z, | ||
Maps::getWalkableGroup(pos)); | ||
|
||
if (entry_tiles.contains(pos)) { | ||
// Ensure our wagon flood end points lands on an edge tile. | ||
// When there is no path to the depot entry_tiles will not | ||
// contain any edge tiles. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this statement is not quite correct. when there is no path to the depot, then the search_edge will never contain any edge tiles. |
||
if ((pos.x == 0 || pos.y == 0) && entry_tiles.contains(pos)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why are we restricting the entry edge match to the top or left of the map? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Huge oversight. Thanks for pointing that out. |
||
found = true; | ||
if (!wagon_path) | ||
break; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
df::tiletype
is just an int (an enum), so no need to take a reference