diff --git a/src/openttd.cpp b/src/openttd.cpp --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -1458,7 +1458,7 @@ bool AfterLoadGame(void) if (v->type == VEH_Train) { v->u.rail.track = TRACK_BIT_WORMHOLE; } else { - v->u.road.state = 0xFF; + v->u.road.state = RVSB_WORMHOLE; } } } diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -74,6 +74,23 @@ static const TrackdirBits _road_exit_dir TRACKDIR_BIT_RIGHT_S | TRACKDIR_BIT_LOWER_E | TRACKDIR_BIT_Y_SE }; +/** Converts the exit direction of a depot to trackdir the vehicle is going to drive to */ +static const Trackdir _roadveh_depot_exit_trackdir[DIAGDIR_END] = { + TRACKDIR_X_NE, TRACKDIR_Y_SE, TRACKDIR_X_SW, TRACKDIR_Y_NW +}; + +/** Checks whether the trackdir means that we are reversing */ +static bool IsReversingRoadTrackdir(Trackdir dir) +{ + return (dir & 0x07) >= 6; +} + +/** Checks whether the given trackdir is a straight road */ +static bool IsStraightRoadTrackdir(Trackdir dir) +{ + return (dir & 0x06) == 0; +} + int GetRoadVehImage(const Vehicle* v, Direction direction) { int img = v->spritenum; @@ -161,7 +178,7 @@ int32 CmdBuildRoadVeh(TileIndex tile, ui v->z_pos = GetSlopeZ(x,y); v->z_height = 6; - v->u.road.state = 254; + v->u.road.state = RVSB_IN_DEPOT; v->vehstatus = VS_HIDDEN|VS_STOPPED|VS_DEFPAL; v->spritenum = rvi->image_index; @@ -452,7 +469,7 @@ int32 CmdTurnRoadVeh(TileIndex tile, uin v->u.road.crashed_ctr != 0 || v->breakdown_ctr != 0 || v->u.road.overtaking != 0 || - v->u.road.state == 255 || + v->u.road.state == RVSB_WORMHOLE || IsRoadVehInDepot(v) || v->cur_speed < 5) { return CMD_ERROR; @@ -502,7 +519,7 @@ static void ClearCrashedStation(Vehicle rs->SetEntranceBusy(false); /* Free the parking bay */ - rs->FreeBay(HASBIT(v->u.road.state, 1) ? 1 : 0); + rs->FreeBay(HASBIT(v->u.road.state, RVS_USING_SECOND_BAY) ? 1 : 0); } static void RoadVehDelete(Vehicle *v) @@ -607,7 +624,7 @@ static void RoadVehCheckTrainCrash(Vehic { TileIndex tile; - if (v->u.road.state == 255) return; + if (v->u.road.state == RVSB_WORMHOLE) return; tile = v->tile; @@ -875,7 +892,7 @@ static bool RoadVehAccelerate(Vehicle *v // Clamp spd = min(spd, v->max_speed); - if (v->u.road.state == 255) spd = min(spd, SetSpeedLimitOnBridge(v)); + if (v->u.road.state == RVSB_WORMHOLE) spd = min(spd, SetSpeedLimitOnBridge(v)); //updates statusbar only if speed have changed to save CPU time if (spd != v->cur_speed) { @@ -966,7 +983,8 @@ static void RoadVehCheckOvertake(Vehicle if (v->direction != u->direction || !(v->direction & 1)) return; - if (v->u.road.state >= 32 || (v->u.road.state & 7) > 1) return; + /* Check if vehicle is in a road stop, depot, tunnel or bridge or not on a straight road */ + if (v->u.road.state >= RVS_IN_ROAD_STOP || !IsStraightRoadTrackdir((Trackdir)(v->u.road.state & RVSB_TRACKDIR_MASK))) return; tt = GetTileTrackStatus(v->tile, TRANSPORT_ROAD) & 0x3F; if ((tt & 3) == 0) return; @@ -1242,11 +1260,6 @@ static const byte _road_veh_data_1[] = { 15, 15, 11, 11 }; -/** Converts the exit direction of a depot to trackdir the vehicle is going to drive to */ -static const Trackdir _roadveh_depot_exit_trackdir[DIAGDIR_END] = { - TRACKDIR_X_NE, TRACKDIR_Y_SE, TRACKDIR_X_SW, TRACKDIR_Y_NW -}; - static void RoadVehController(Vehicle *v) { Direction new_dir; @@ -1327,11 +1340,8 @@ static void RoadVehController(Vehicle *v if (++v->u.road.overtaking_ctr >= 35) /* If overtaking just aborts at a random moment, we can have a out-of-bound problem, * if the vehicle started a corner. To protect that, only allow an abort of - * overtake if we are on straight road, which are the 8 states below */ - if (v->u.road.state == 0 || v->u.road.state == 1 || - v->u.road.state == 8 || v->u.road.state == 9 || - v->u.road.state == 16 || v->u.road.state == 17 || - v->u.road.state == 24 || v->u.road.state == 25) { + * overtake if we are on straight roads */ + if (v->u.road.state < RVSB_IN_ROAD_STOP && IsStraightRoadTrackdir((Trackdir)v->u.road.state)) { v->u.road.overtaking = 0; } } @@ -1339,7 +1349,7 @@ static void RoadVehController(Vehicle *v /* Save old vehicle position to use at end of move to set viewport area dirty */ BeginVehicleMove(v); - if (v->u.road.state == 255) { + if (v->u.road.state == RVSB_WORMHOLE) { /* Vehicle is on a bridge or in a tunnel */ GetNewVehiclePosResult gp; @@ -1367,7 +1377,7 @@ static void RoadVehController(Vehicle *v } /* Get move position data for next frame */ - rd = _road_drive_data[(v->u.road.state + (_opt.road_side << 4)) ^ v->u.road.overtaking][v->u.road.frame + 1]; + rd = _road_drive_data[(v->u.road.state + (_opt.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking][v->u.road.frame + 1]; if (rd.x & 0x80) { /* Vehicle is moving to the next tile */ @@ -1384,7 +1394,7 @@ static void RoadVehController(Vehicle *v } again: - if ((dir & 7) >= 6) { + if (IsReversingRoadTrackdir(dir)) { /* Turning around */ tile = v->tile; } @@ -1406,12 +1416,12 @@ again: return; } /* Try an about turn to re-enter the previous tile */ - dir = _road_reverse_table[rd.x&3]; + dir = _road_reverse_table[rd.x & 3]; goto again; } - if (IS_BYTE_INSIDE(v->u.road.state, 0x20, 0x30) && IsTileType(v->tile, MP_STATION)) { - if ((dir & 7) >= 6) { + if (IS_BYTE_INSIDE(v->u.road.state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END) && IsTileType(v->tile, MP_STATION)) { + if (IsReversingRoadTrackdir(dir)) { /* New direction is trying to turn vehicle around. * We can't turn at the exit of a road stop so wait.*/ v->cur_speed = 0; @@ -1422,7 +1432,7 @@ again: RoadStop *rs = GetRoadStopByTile(v->tile, GetRoadStopType(v->tile)); /* Vehicle is leaving a road stop tile, mark bay as free and clear the usage bit */ - rs->FreeBay(HASBIT(v->u.road.state, 1) ? 1 : 0); + rs->FreeBay(HASBIT(v->u.road.state, RVS_USING_SECOND_BAY) ? 1 : 0); rs->SetEntranceBusy(false); } } @@ -1475,7 +1485,7 @@ again: } /* Set vehicle to second frame on the tile */ - v->u.road.state = tmp & ~16; + CLRBIT(v->u.road.state, RVS_DRIVE_SIDE); v->u.road.frame = 1; if (newdir != v->direction) { @@ -1495,7 +1505,7 @@ again: new_dir = RoadVehGetSlidingDirection(v, x, y); - if (!IS_BYTE_INSIDE(v->u.road.state, 0x20, 0x30)) { + if (!IS_BYTE_INSIDE(v->u.road.state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END)) { /* Vehicle is not in a road stop. * Check for another vehicle to overtake */ Vehicle* u = RoadVehFindCloseTo(v, x, y, new_dir); @@ -1524,8 +1534,8 @@ again: } } - if (v->u.road.state >= 0x20 && - _road_veh_data_1[v->u.road.state - 0x20 + (_opt.road_side<<4)] == v->u.road.frame) { + if (v->u.road.state >= RVSB_IN_ROAD_STOP && + _road_veh_data_1[v->u.road.state - RVSB_IN_ROAD_STOP + (_opt.road_side << RVS_DRIVE_SIDE)] == v->u.road.frame) { RoadStop *rs = GetRoadStopByTile(v->tile, GetRoadStopType(v->tile)); Station* st = GetStationByTile(v->tile); diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -2222,7 +2222,7 @@ static uint32 VehicleEnter_Station(Vehic } } } else if (v->type == VEH_Road) { - if (v->u.road.state < 16 && !HASBIT(v->u.road.state, 2) && v->u.road.frame == 0) { + if (v->u.road.state < RVSB_IN_ROAD_STOP && v->u.road.frame == 0) { if (IsRoadStop(tile)) { /* Attempt to allocate a parking bay in a road stop */ RoadStop *rs = GetRoadStopByTile(tile, GetRoadStopType(tile)); @@ -2230,11 +2230,11 @@ static uint32 VehicleEnter_Station(Vehic /* Check if station is busy or if there are no free bays. */ if (rs->IsEntranceBusy() || !rs->HasFreeBay()) return VETSB_CANNOT_ENTER; - v->u.road.state += 32; + SETBIT(v->u.road.state, RVS_IN_ROAD_STOP); /* Allocate a bay and update the road state */ uint bay_nr = rs->AllocateBay(); - SB(v->u.road.state, 1, 1, bay_nr); + SB(v->u.road.state, RVS_USING_SECOND_BAY, 1, bay_nr); /* Mark the station entrace as busy */ rs->SetEntranceBusy(true); diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -1250,7 +1250,10 @@ static const byte _tunnel_fractcoord_2[4 static const byte _tunnel_fractcoord_3[4] = {0x82, 0x88, 0x86, 0x48}; static const byte _exit_tunnel_track[4] = {1, 2, 1, 2}; -static const byte _road_exit_tunnel_state[4] = {8, 9, 0, 1}; +/** Get the trackdir of the exit of a tunnel */ +static const Trackdir _road_exit_tunnel_state[DIAGDIR_END] = { + TRACKDIR_X_SW, TRACKDIR_Y_NW, TRACKDIR_X_NE, TRACKDIR_Y_SE +}; static const byte _road_exit_tunnel_frame[4] = {2, 7, 9, 4}; static const byte _tunnel_fractcoord_4[4] = {0x52, 0x85, 0x98, 0x29}; @@ -1304,11 +1307,11 @@ static uint32 VehicleEnter_TunnelBridge( vdir = DirToDiagDir(v->direction); // Enter tunnel? - if (v->u.road.state != 0xFF && dir == vdir) { + if (v->u.road.state != RVSB_WORMHOLE && dir == vdir) { if (fc == _tunnel_fractcoord_4[dir] || fc == _tunnel_fractcoord_5[dir]) { v->tile = tile; - v->u.road.state = 0xFF; + v->u.road.state = RVSB_WORMHOLE; v->vehstatus |= VS_HIDDEN; return VETSB_ENTERED_WORMHOLE; } else { @@ -1354,7 +1357,7 @@ static uint32 VehicleEnter_TunnelBridge( CLRBIT(v->u.rail.flags, VRF_GOINGUP); CLRBIT(v->u.rail.flags, VRF_GOINGDOWN); } else { - v->u.road.state = 0xFF; + v->u.road.state = RVSB_WORMHOLE; } return VETSB_ENTERED_WORMHOLE; } else if (DirToDiagDir(v->direction) == ReverseDiagDir(dir)) { @@ -1365,7 +1368,7 @@ static uint32 VehicleEnter_TunnelBridge( return VETSB_ENTERED_WORMHOLE; } } else { - if (v->u.road.state == 0xFF) { + if (v->u.road.state == RVSB_WORMHOLE) { v->u.road.state = _road_exit_tunnel_state[dir]; v->u.road.frame = 0; return VETSB_ENTERED_WORMHOLE; diff --git a/src/vehicle.cpp b/src/vehicle.cpp --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -2524,7 +2524,7 @@ void VehicleEnterDepot(Vehicle *v) case VEH_Road: InvalidateWindowClasses(WC_ROADVEH_LIST); - v->u.road.state = 254; + v->u.road.state = RVSB_IN_DEPOT; break; case VEH_Ship: diff --git a/src/vehicle.h b/src/vehicle.h --- a/src/vehicle.h +++ b/src/vehicle.h @@ -27,6 +27,37 @@ enum VehicleEnterTileStatus { VETSB_CANNOT_ENTER = 1 << VETS_CANNOT_ENTER, ///< The vehicle cannot enter the tile }; +/** Road vehicle states */ +enum RoadVehicleStates { + /* + * Lower 4 bits are used for vehicle track direction. (Trackdirs) + * When in a road stop (bit 5 set) these bits give the + * track direction of the entry to the road stop. + * As the entry direction will always be a diagonal + * direction (X_NE, Y_SE, X_SW or Y_NW) only bits 0 and 3 + * are needed to hold this direction. Bit 1 is then used to show + * that the vehicle is using the second road stop bay. + */ + + /* Numeric values */ + RVSB_IN_DEPOT = 0xFE, ///< The vehicle is in a depot + RVSB_WORMHOLE = 0xFF, ///< The vehicle is in a tunnel and/or bridge + + /* Bit numbers */ + RVS_USING_SECOND_BAY = 1, ///< Only used while in a road stop + RVS_DRIVE_SIDE = 4, ///< Only used when retrieving move data and for turning vehicles + RVS_IN_ROAD_STOP = 5, ///< The vehicle is in a road stop + + /* Bit sets of the above specified bits */ + RVSB_USING_SECOND_BAY = 1 << RVS_USING_SECOND_BAY, ///< Only used while in a road stop + RVSB_DRIVE_SIDE = 1 << RVS_DRIVE_SIDE, ///< Only used when retrieving move data and for turning vehicles + RVSB_IN_ROAD_STOP = 1 << RVS_IN_ROAD_STOP, ///< The vehicle is in a road stop + RVSB_IN_ROAD_STOP_END = RVSB_IN_ROAD_STOP + TRACKDIR_END, + + RVSB_TRACKDIR_MASK = 0x0F, ///< The mask used to extract track dirs + RVSB_ROAD_STOP_TRACKDIR_MASK = 0x09 ///< Only bits 0 and 3 are used to encode the trackdir for road stops +}; + enum { VEH_Train, VEH_Road, @@ -136,7 +167,7 @@ typedef struct VehicleAir { } VehicleAir; typedef struct VehicleRoad { - byte state; + byte state; /// @see RoadVehicleStates byte frame; uint16 blocked_ctr; byte overtaking;