* Train is approaching line end, slow down and possibly reverse * * @param v front train engine * @param signal not line end, just a red signal * @param reverse Set to false to not execute the vehicle reversing. This does not change any other logic. * @return true iff we did NOT have to reverse */
| 3792 | * @return true iff we did NOT have to reverse |
| 3793 | */ |
| 3794 | static bool TrainApproachingLineEnd(Train *v, bool signal, bool reverse) |
| 3795 | { |
| 3796 | /* Calc position within the current tile */ |
| 3797 | uint x = v->x_pos & 0xF; |
| 3798 | uint y = v->y_pos & 0xF; |
| 3799 | |
| 3800 | /* for diagonal directions, 'x' will be 0..15 - |
| 3801 | * for other directions, it will be 1, 3, 5, ..., 15 */ |
| 3802 | switch (v->direction) { |
| 3803 | case DIR_N : x = ~x + ~y + 25; break; |
| 3804 | case DIR_NW: x = y; [[fallthrough]]; |
| 3805 | case DIR_NE: x = ~x + 16; break; |
| 3806 | case DIR_E : x = ~x + y + 9; break; |
| 3807 | case DIR_SE: x = y; break; |
| 3808 | case DIR_S : x = x + y - 7; break; |
| 3809 | case DIR_W : x = ~y + x + 9; break; |
| 3810 | default: break; |
| 3811 | } |
| 3812 | |
| 3813 | /* Do not reverse when approaching red signal. Make sure the vehicle's front |
| 3814 | * does not cross the tile boundary when we do reverse, but as the vehicle's |
| 3815 | * location is based on their center, use half a vehicle's length as offset. |
| 3816 | * Multiply the half-length by two for straight directions to compensate that |
| 3817 | * we only get odd x offsets there. */ |
| 3818 | if (!signal && x + (v->gcache.cached_veh_length + 1) / 2 * (IsDiagonalDirection(v->direction) ? 1 : 2) >= TILE_SIZE) { |
| 3819 | /* we are too near the tile end, reverse now */ |
| 3820 | v->cur_speed = 0; |
| 3821 | if (reverse) ReverseTrainDirection(v); |
| 3822 | return false; |
| 3823 | } |
| 3824 | |
| 3825 | /* slow down */ |
| 3826 | v->vehstatus.Set(VehState::TrainSlowing); |
| 3827 | uint16_t break_speed = _breakdown_speeds[x & 0xF]; |
| 3828 | if (break_speed < v->cur_speed) v->cur_speed = break_speed; |
| 3829 | |
| 3830 | return true; |
| 3831 | } |
| 3832 | |
| 3833 | |
| 3834 | /** |
no test coverage detected