From ee0d9f662e49055b290240f3933220853d2d803f Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Sun, 31 May 2026 08:16:26 +0100 Subject: [PATCH] Codechange: rework definition of ship and train tile entrance coordinates (#15650) --- src/ship_cmd.cpp | 58 +++------------------------------------------ src/train_cmd.cpp | 20 +--------------- src/vehicle.cpp | 59 ++++++++++++++++++++++++++++++++++++++++++++++ src/vehicle_func.h | 1 + 4 files changed, 64 insertions(+), 74 deletions(-) diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp index dc8707bd51..35a8635951 100644 --- a/src/ship_cmd.cpp +++ b/src/ship_cmd.cpp @@ -509,56 +509,6 @@ static inline TrackBits GetAvailShipTracks(TileIndex tile, DiagDirection dir) return tracks; } -/** Structure for ship sub-coordinate data for moving into a new tile via a Diagdir onto a Track. */ -struct ShipSubcoordData { - uint8_t x_subcoord; ///< New X sub-coordinate on the new tile - uint8_t y_subcoord; ///< New Y sub-coordinate on the new tile - Direction dir; ///< New Direction to move in on the new track -}; -/** Ship sub-coordinate data for moving into a new tile via a Diagdir onto a Track. - * Array indexes are Diagdir, Track. - * There will always be three possible tracks going into an adjacent tile via a Diagdir, - * so each Diagdir sub-array will have three valid and three invalid structures per Track. - */ -static constexpr DiagDirectionIndexArray> _ship_subcoord{{{ - /* DIAGDIR_NE */ - {{{ - {15, 8, DIR_NE}, // TRACK_X - { 0, 0, INVALID_DIR}, // TRACK_Y - { 0, 0, INVALID_DIR}, // TRACK_UPPER - {15, 8, DIR_E}, // TRACK_LOWER - {15, 7, DIR_N}, // TRACK_LEFT - { 0, 0, INVALID_DIR}, // TRACK_RIGHT - }}}, - /* DIAGDIR_SE */ - {{{ - { 0, 0, INVALID_DIR}, // TRACK_X - { 8, 0, DIR_SE}, // TRACK_Y - { 7, 0, DIR_E}, // TRACK_UPPER - { 0, 0, INVALID_DIR}, // TRACK_LOWER - { 8, 0, DIR_S}, // TRACK_LEFT - { 0, 0, INVALID_DIR}, // TRACK_RIGHT - }}}, - /* DIAGDIR_SW */ - {{{ - { 0, 8, DIR_SW}, // TRACK_X - { 0, 0, INVALID_DIR}, // TRACK_Y - { 0, 7, DIR_W}, // TRACK_UPPER - { 0, 0, INVALID_DIR}, // TRACK_LOWER - { 0, 0, INVALID_DIR}, // TRACK_LEFT - { 0, 8, DIR_S}, // TRACK_RIGHT - }}}, - /* DIAGDIR_NW */ - {{{ - { 0, 0, INVALID_DIR}, // TRACK_X - { 8, 15, DIR_NW}, // TRACK_Y - { 0, 0, INVALID_DIR}, // TRACK_UPPER - { 8, 15, DIR_W}, // TRACK_LOWER - { 0, 0, INVALID_DIR}, // TRACK_LEFT - { 7, 15, DIR_N}, // TRACK_RIGHT - }}}, -}}}; - /** * Test if a ship is in the centre of a lock and should move up or down. * @param v Ship being tested. @@ -776,10 +726,8 @@ static void ShipController(Ship *v) const Track track = ChooseShipTrack(v, gp.new_tile, tracks); if (track == INVALID_TRACK) return ReverseShip(v); - const ShipSubcoordData &b = _ship_subcoord[diagdir][track]; - - gp.x = (gp.x & ~0xF) | b.x_subcoord; - gp.y = (gp.y & ~0xF) | b.y_subcoord; + /* Update XY to reflect the entrance to the new tile, and select the direction to use */ + Direction chosen_dir = VehicleEnterTileCoordinates(gp, diagdir, track); /* Call the landscape function and tell it that the vehicle entered the tile */ auto vets = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y); @@ -793,7 +741,7 @@ static void ShipController(Ship *v) if (GetEffectiveWaterClass(gp.old_tile) != GetEffectiveWaterClass(gp.new_tile)) v->UpdateCache(); } - const Direction new_direction = b.dir; + const Direction new_direction = chosen_dir; const DirDiff diff = DirDifference(new_direction, v->direction); switch (diff) { case DirDiff::Same: diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index ae02b312e5..a5b8fd30b7 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -2524,15 +2524,6 @@ void FreeTrainTrackReservation(const Train *consist) UpdateSignalsInBuffer(); } -static const uint8_t _initial_tile_subcoord[6][4][3] = { -{{ 15, 8, 1 }, { 0, 0, 0 }, { 0, 8, 5 }, { 0, 0, 0 }}, -{{ 0, 0, 0 }, { 8, 0, 3 }, { 0, 0, 0 }, { 8, 15, 7 }}, -{{ 0, 0, 0 }, { 7, 0, 2 }, { 0, 7, 6 }, { 0, 0, 0 }}, -{{ 15, 8, 2 }, { 0, 0, 0 }, { 0, 0, 0 }, { 8, 15, 6 }}, -{{ 15, 7, 0 }, { 8, 0, 4 }, { 0, 0, 0 }, { 0, 0, 0 }}, -{{ 0, 0, 0 }, { 0, 0, 0 }, { 0, 8, 4 }, { 7, 15, 0 }}, -}; - /** * Perform pathfinding for a train. * @@ -3524,17 +3515,8 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse) chosen_track &= bits; } - /* Make sure chosen track is a valid track */ - assert( - chosen_track == TRACK_BIT_X || chosen_track == TRACK_BIT_Y || - chosen_track == TRACK_BIT_UPPER || chosen_track == TRACK_BIT_LOWER || - chosen_track == TRACK_BIT_LEFT || chosen_track == TRACK_BIT_RIGHT); - /* Update XY to reflect the entrance to the new tile, and select the direction to use */ - const uint8_t *b = _initial_tile_subcoord[FindFirstBit(chosen_track)][enterdir]; - gp.x = (gp.x & ~0xF) | b[0]; - gp.y = (gp.y & ~0xF) | b[1]; - Direction chosen_dir = (Direction)b[2]; + Direction chosen_dir = VehicleEnterTileCoordinates(gp, enterdir, TrackBitsToTrack(chosen_track)); /* Call the landscape function and tell it that the vehicle entered the tile */ auto vets = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y); diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 3023807d11..5b1ce12a1e 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -3339,3 +3339,62 @@ bool VehiclesHaveSameOrderList(const Vehicle *v1, const Vehicle *v2) { return std::ranges::equal(v1->Orders(), v2->Orders(), [](const Order &o1, const Order &o2) { return o1.Equals(o2); }); } + +/** Vehicle sub-coordinate data for moving into a new tile. */ +struct VehicleSubcoordData : Coord2D { + Direction dir = INVALID_DIR; ///< new direction. +}; + +/** + * Table of subtile coordinates and direction for each combination of chosen track and tile enter direction. + * Combinations that are not possible result in INVALID_DIR. + */ +static constexpr DiagDirectionIndexArray> _vehicle_subcoord{{{ + {{{ // NE + {{15, 8}, DIR_NE}, // TRACK_X + {}, // TRACK_Y + {}, // TRACK_UPPER + {{15, 8}, DIR_E}, // TRACK_LOWER + {{15, 7}, DIR_N}, // TRACK_LEFT + {}, // TRACK_RIGHT + }}}, + {{{ // SE + {}, // TRACK_X + {{8, 0}, DIR_SE}, // TRACK_Y + {{7, 0}, DIR_E}, // TRACK_UPPER + {}, // TRACK_LOWER + {{8, 0}, DIR_S}, // TRACK_LEFT + {}, // TRACK_RIGHT + }}}, + {{{ // SW + {{0, 8}, DIR_SW}, // TRACK_X + {}, // TRACK_Y + {{0, 7}, DIR_W}, // TRACK_UPPER + {}, // TRACK_LOWER + {}, // TRACK_LEFT + {{0, 8}, DIR_S}, // TRACK_RIGHT + }}}, + {{{ // NW + {}, // TRACK_X + {{8, 15}, DIR_NW}, // TRACK_Y + {}, // TRACK_UPPER + {{8, 15}, DIR_W}, // TRACK_LOWER + {}, // TRACK_LEFT + {{7, 15}, DIR_N}, // TRACK_RIGHT + }}}, +}}}; + +/** + * Lookup new subposition coordinates and direction to use when entering a new tile, applying the subcoordinates to the vehicle position result. + * @param gp new vehicle position result to apply subcoordinates to. + * @param enterdir the enter direction for the tile. + * @param track The chosen track for the tile. + * @return the new vehicle direction. + */ +Direction VehicleEnterTileCoordinates(GetNewVehiclePosResult &gp, DiagDirection enterdir, Track track) +{ + const VehicleSubcoordData &b = _vehicle_subcoord[enterdir][track]; + gp.x = (gp.x & ~TILE_UNIT_MASK) | b.x; + gp.y = (gp.y & ~TILE_UNIT_MASK) | b.y; + return b.dir; +} diff --git a/src/vehicle_func.h b/src/vehicle_func.h index 422537bdec..f9ceeaf1b4 100644 --- a/src/vehicle_func.h +++ b/src/vehicle_func.h @@ -330,5 +330,6 @@ bool VehiclesHaveSameEngineList(const Vehicle *v1, const Vehicle *v2); bool VehiclesHaveSameOrderList(const Vehicle *v1, const Vehicle *v2); bool IsUniqueVehicleName(const std::string &name); +Direction VehicleEnterTileCoordinates(GetNewVehiclePosResult &gp, DiagDirection enterdir, Track track); #endif /* VEHICLE_FUNC_H */