diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -454,7 +454,15 @@ CommandCost CmdBuildSingleRail(TileIndex default: break; case ROADTYPES_TRAM: /* Tram crossings must always have road. */ - if (flags & DC_EXEC) SetRoadOwner(tile, ROADTYPE_ROAD, _current_company); + if (flags & DC_EXEC) { + SetRoadOwner(tile, ROADTYPE_ROAD, _current_company); + Company *c = Company::GetIfValid(_current_company); + if (c != NULL) { + /* A full diagonal tile has two road bits. */ + c->infrastructure.road[ROADTYPE_ROAD] += 2; + DirtyCompanyInfrastructureWindows(c->index); + } + } roadtypes |= ROADTYPES_ROAD; break; diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -35,6 +35,7 @@ #include "newgrf_railtype.h" #include "date_func.h" #include "genworld.h" +#include "company_gui.h" #include "table/strings.h" @@ -218,8 +219,16 @@ static CommandCost RemoveRoad(TileIndex if (IsTileType(tile, MP_TUNNELBRIDGE)) { TileIndex other_end = GetOtherTunnelBridgeEnd(tile); /* Pay for *every* tile of the bridge or tunnel */ - cost.AddCost((GetTunnelBridgeLength(other_end, tile) + 2) * _price[PR_CLEAR_ROAD]); + uint len = GetTunnelBridgeLength(other_end, tile) + 2; + cost.AddCost(len * _price[PR_CLEAR_ROAD]); if (flags & DC_EXEC) { + Company *c = Company::GetIfValid(GetRoadOwner(tile, rt)); + if (c != NULL) { + /* A full diagonal road tile has two road bits. */ + c->infrastructure.road[rt] -= len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR; + DirtyCompanyInfrastructureWindows(c->index); + } + SetRoadTypes(other_end, GetRoadTypes(other_end) & ~RoadTypeToRoadTypes(rt)); SetRoadTypes(tile, GetRoadTypes(tile) & ~RoadTypeToRoadTypes(rt)); @@ -245,6 +254,12 @@ static CommandCost RemoveRoad(TileIndex assert(IsDriveThroughStopTile(tile)); cost.AddCost(_price[PR_CLEAR_ROAD] * 2); if (flags & DC_EXEC) { + Company *c = Company::GetIfValid(GetTileOwner(tile)); + if (c != NULL) { + /* A full diagonal road tile has two road bits. */ + c->infrastructure.road[rt] -= 2; + DirtyCompanyInfrastructureWindows(c->index); + } SetRoadTypes(tile, GetRoadTypes(tile) & ~RoadTypeToRoadTypes(rt)); MarkTileDirtyByTile(tile); } @@ -299,6 +314,13 @@ static CommandCost RemoveRoad(TileIndex } } } + + Company *c = Company::GetIfValid(GetRoadOwner(tile, rt)); + if (c != NULL) { + c->infrastructure.road[rt] -= CountBits(pieces); + DirtyCompanyInfrastructureWindows(c->index); + } + if (present == ROAD_NONE) { RoadTypes rts = GetRoadTypes(tile) & ComplementRoadTypes(RoadTypeToRoadTypes(rt)); if (rts == ROADTYPES_NONE) { @@ -341,6 +363,13 @@ static CommandCost RemoveRoad(TileIndex if (rt == ROADTYPE_ROAD && HasTileRoadType(tile, ROADTYPE_TRAM) && (flags & DC_EXEC || crossing_check)) return CMD_ERROR; if (flags & DC_EXEC) { + Company *c = Company::GetIfValid(GetRoadOwner(tile, rt)); + if (c != NULL) { + /* A full diagonal road tile has two road bits. */ + c->infrastructure.road[rt] -= 2; + DirtyCompanyInfrastructureWindows(c->index); + } + Track railtrack = GetCrossingRailTrack(tile); RoadTypes rts = GetRoadTypes(tile) & ComplementRoadTypes(RoadTypeToRoadTypes(rt)); if (rts == ROADTYPES_NONE) { @@ -573,6 +602,13 @@ CommandCost CmdBuildRoad(TileIndex tile, if (flags & DC_EXEC) { Track railtrack = AxisToTrack(OtherAxis(roaddir)); YapfNotifyTrackLayoutChange(tile, railtrack); + /* Update company infrastructure counts. A level crossing has two road bits. */ + Company *c = Company::GetIfValid(_current_company); + if (c != NULL) { + c->infrastructure.road[rt] += 2; + if (rt != ROADTYPE_ROAD) c->infrastructure.road[ROADTYPE_ROAD] += 2; + DirtyCompanyInfrastructureWindows(_current_company); + } /* Always add road to the roadtypes (can't draw without it) */ bool reserved = HasBit(GetRailReservationTrackBits(tile), railtrack); MakeRoadCrossing(tile, _current_company, _current_company, GetTileOwner(tile), roaddir, GetRailType(tile), RoadTypeToRoadTypes(rt) | ROADTYPES_ROAD, p2); @@ -708,6 +744,14 @@ do_clear:; break; } + /* Update company infrastructure count. */ + Company *c = Company::GetIfValid(GetRoadOwner(tile, rt)); + if (c != NULL) { + if (IsTileType(tile, MP_TUNNELBRIDGE)) num_pieces *= TUNNELBRIDGE_TRACKBIT_FACTOR; + c->infrastructure.road[rt] += num_pieces; + DirtyCompanyInfrastructureWindows(c->index); + } + if (rt != ROADTYPE_TRAM && IsNormalRoadTile(tile)) { existing |= pieces; SetDisallowedRoadDirections(tile, IsStraightRoad(existing) ? @@ -928,6 +972,10 @@ CommandCost CmdBuildRoadDepot(TileIndex Depot *dep = new Depot(tile); dep->build_date = _date; + /* A road depot has two road bits. */ + Company::Get(_current_company)->infrastructure.road[rt] += 2; + DirtyCompanyInfrastructureWindows(_current_company); + MakeRoadDepot(tile, _current_company, dep->index, dir, rt); MarkTileDirtyByTile(tile); MakeDefaultName(dep); @@ -947,6 +995,13 @@ static CommandCost RemoveRoadDepot(TileI if (ret.Failed()) return ret; if (flags & DC_EXEC) { + Company *c = Company::GetIfValid(GetTileOwner(tile)); + if (c != NULL) { + /* A road depot has two road bits. */ + c->infrastructure.road[FIND_FIRST_BIT(GetRoadTypes(tile))] -= 2; + DirtyCompanyInfrastructureWindows(c->index); + } + delete Depot::GetByTile(tile); DoClearSquare(tile); } @@ -1653,6 +1708,11 @@ static void ChangeTileOwner_Road(TileInd if (new_owner == INVALID_OWNER) { DoCommand(tile, 0, 0, DC_EXEC | DC_BANKRUPT, CMD_LANDSCAPE_CLEAR); } else { + /* A road depot has two road bits. No need to dirty windows here, we'll redraw the whole screen anyway. */ + RoadType rt = (RoadType)FIND_FIRST_BIT(GetRoadTypes(tile)); + Company::Get(old_owner)->infrastructure.road[rt] -= 2; + Company::Get(new_owner)->infrastructure.road[rt] += 2; + SetTileOwner(tile, new_owner); } } @@ -1662,6 +1722,13 @@ static void ChangeTileOwner_Road(TileInd for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) { /* Update all roadtypes, no matter if they are present */ if (GetRoadOwner(tile, rt) == old_owner) { + if (HasTileRoadType(tile, rt)) { + /* A level crossing has two road bits. No need to dirty windows here, we'll redraw the whole screen anyway. */ + uint num_bits = IsLevelCrossing(tile) ? 2 : CountBits(GetRoadBits(tile, rt)); + Company::Get(old_owner)->infrastructure.road[rt] -= num_bits; + if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.road[rt] += num_bits; + } + SetRoadOwner(tile, rt, new_owner == INVALID_OWNER ? OWNER_NONE : new_owner); } } diff --git a/src/saveload/company_sl.cpp b/src/saveload/company_sl.cpp --- a/src/saveload/company_sl.cpp +++ b/src/saveload/company_sl.cpp @@ -115,12 +115,21 @@ void AfterLoadCompanyStats() } break; - case MP_ROAD: + case MP_ROAD: { if (IsLevelCrossing(tile)) { c = Company::GetIfValid(GetTileOwner(tile)); if (c != NULL) c->infrastructure.rail[GetRailType(tile)] += LEVELCROSSING_TRACKBIT_FACTOR; } + + /* Iterate all present road types as each can have a different owner. */ + RoadType rt; + FOR_EACH_SET_ROADTYPE(rt, GetRoadTypes(tile)) { + c = Company::GetIfValid(IsRoadDepot(tile) ? GetTileOwner(tile) : GetRoadOwner(tile, rt)); + /* A level crossings and depots have two road bits. */ + if (c != NULL) c->infrastructure.road[rt] += IsNormalRoad(tile) ? CountBits(GetRoadBits(tile, rt)) : 2; + } break; + } case MP_STATION: c = Company::GetIfValid(GetTileOwner(tile)); @@ -131,6 +140,17 @@ void AfterLoadCompanyStats() if (c != NULL && !IsStationTileBlocked(tile)) c->infrastructure.rail[GetRailType(tile)]++; break; + case STATION_BUS: + case STATION_TRUCK: { + /* Iterate all present road types as each can have a different owner. */ + RoadType rt; + FOR_EACH_SET_ROADTYPE(rt, GetRoadTypes(tile)) { + c = Company::GetIfValid(GetRoadOwner(tile, rt)); + if (c != NULL) c->infrastructure.road[rt] += 2; // A road stop has two road bits. + } + break; + } + default: break; } @@ -150,6 +170,16 @@ void AfterLoadCompanyStats() if (c != NULL) c->infrastructure.rail[GetRailType(tile)] += len; break; + case TRANSPORT_ROAD: { + /* Iterate all present road types as each can have a different owner. */ + RoadType rt; + FOR_EACH_SET_ROADTYPE(rt, GetRoadTypes(tile)) { + c = Company::GetIfValid(GetRoadOwner(tile, rt)); + if (c != NULL) c->infrastructure.road[rt] += len * 2; // A full diagonal road has two road bits. + } + break; + } + default: break; } diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -1791,9 +1791,23 @@ CommandCost CmdBuildRoadStop(TileIndex t RoadStopType rs_type = type ? ROADSTOP_TRUCK : ROADSTOP_BUS; if (is_drive_through) { + /* Update company infrastructure counts. If the current tile is a normal + * road tile, count only the new road bits needed to get a full diagonal road. */ + RoadType rt; + FOR_EACH_SET_ROADTYPE(rt, cur_rts | rts) { + Company *c = Company::GetIfValid(IsNormalRoadTile(cur_tile) && HasBit(cur_rts, rt) ? GetRoadOwner(cur_tile, rt) : _current_company); + if (c != NULL) { + c->infrastructure.road[rt] += 2 - (IsNormalRoadTile(cur_tile) ? CountBits(GetRoadBits(cur_tile, rt)) : 0); + DirtyCompanyInfrastructureWindows(c->index); + } + } + MakeDriveThroughRoadStop(cur_tile, st->owner, road_owner, tram_owner, st->index, rs_type, rts | cur_rts, DiagDirToAxis(ddir)); road_stop->MakeDriveThrough(); } else { + /* Non-drive-through stop never overbuild and always count as two road bits. */ + Company::Get(st->owner)->infrastructure.road[FIND_FIRST_BIT(rts)] += 2; + DirtyCompanyInfrastructureWindows(st->owner); MakeRoadStop(cur_tile, st->owner, st->index, rs_type, rts, ddir); } @@ -1883,6 +1897,16 @@ static CommandCost RemoveRoadStop(TileIn pred->next = cur_stop->next; } + /* Update company infrastructure counts. */ + RoadType rt; + FOR_EACH_SET_ROADTYPE(rt, GetRoadTypes(tile)) { + Company *c = Company::GetIfValid(GetRoadOwner(tile, rt)); + if (c != NULL) { + c->infrastructure.road[rt] -= 2; + DirtyCompanyInfrastructureWindows(c->index); + } + } + if (IsDriveThroughStopTile(tile)) { /* Clears the tile for us */ cur_stop->ClearDriveThrough(); @@ -1967,6 +1991,16 @@ CommandCost CmdRemoveRoadStop(TileIndex if ((flags & DC_EXEC) && is_drive_through) { MakeRoadNormal(cur_tile, road_bits, rts, ClosestTownFromTile(cur_tile, UINT_MAX)->index, road_owner, tram_owner); + + /* Update company infrastructure counts. */ + RoadType rt; + FOR_EACH_SET_ROADTYPE(rt, rts) { + Company *c = Company::GetIfValid(GetRoadOwner(tile, rt)); + if (c != NULL) { + c->infrastructure.road[rt] += CountBits(road_bits); + DirtyCompanyInfrastructureWindows(c->index); + } + } } } @@ -3504,6 +3538,11 @@ static void ChangeTileOwner_Station(Tile for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) { /* Update all roadtypes, no matter if they are present */ if (GetRoadOwner(tile, rt) == old_owner) { + if (HasTileRoadType(tile, rt)) { + /* A drive-through road-stop has always two road bits. No need to dirty windows here, we'll redraw the whole screen anyway. */ + Company::Get(old_owner)->infrastructure.road[rt] -= 2; + if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.road[rt] += 2; + } SetRoadOwner(tile, rt, new_owner == INVALID_OWNER ? OWNER_NONE : new_owner); } } @@ -3523,6 +3562,13 @@ static void ChangeTileOwner_Station(Tile old_company->infrastructure.rail[GetRailType(tile)]--; new_company->infrastructure.rail[GetRailType(tile)]++; } + if (IsRoadStop(tile) && !IsDriveThroughStopTile(tile)) { + RoadType rt; + FOR_EACH_SET_ROADTYPE(rt, GetRoadTypes(tile)) { + old_company->infrastructure.road[rt] -= 2; + new_company->infrastructure.road[rt] += 2; + } + } /* for buoys, owner of tile is owner of water, st->owner == OWNER_NONE */ SetTileOwner(tile, new_owner); diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -443,6 +443,14 @@ CommandCost CmdBuildBridge(TileIndex end break; case TRANSPORT_ROAD: + if (c != NULL) { + /* Add all new road types to the company infrastructure counter. */ + RoadType new_rt; + FOR_EACH_SET_ROADTYPE(new_rt, roadtypes ^ (IsBridgeTile(tile_start) ? GetRoadTypes(tile_start) : ROADTYPES_NONE)) { + /* A full diagonal road tile has two road bits. */ + Company::Get(owner)->infrastructure.road[new_rt] += (bridge_len + 2) * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR; + } + } MakeRoadBridgeRamp(tile_start, owner, bridge_type, dir, roadtypes); MakeRoadBridgeRamp(tile_end, owner, bridge_type, ReverseDiagDir(dir), roadtypes); break; @@ -640,6 +648,12 @@ CommandCost CmdBuildTunnel(TileIndex sta AddSideToSignalBuffer(start_tile, INVALID_DIAGDIR, _current_company); YapfNotifyTrackLayoutChange(start_tile, DiagDirToDiagTrack(direction)); } else { + if (c != NULL) { + RoadType rt; + FOR_EACH_SET_ROADTYPE(rt, rts ^ (IsTunnelTile(start_tile) ? GetRoadTypes(start_tile) : ROADTYPES_NONE)) { + c->infrastructure.road[rt] += num_pieces * 2; // A full diagonal road has two road bits. + } + } MakeRoadTunnel(start_tile, _current_company, direction, rts); MakeRoadTunnel(end_tile, _current_company, ReverseDiagDir(direction), rts); } @@ -761,6 +775,16 @@ static CommandCost DoClearTunnel(TileInd if (v != NULL) TryPathReserve(v); } else { + RoadType rt; + FOR_EACH_SET_ROADTYPE(rt, GetRoadTypes(tile)) { + /* A full diagonal road tile has two road bits. */ + Company *c = Company::GetIfValid(GetRoadOwner(tile, rt)); + if (c != NULL) { + c->infrastructure.road[rt] -= len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR; + DirtyCompanyInfrastructureWindows(c->index); + } + } + DoClearSquare(tile); DoClearSquare(endtile); } @@ -822,6 +846,16 @@ static CommandCost DoClearBridge(TileInd /* Update company infrastructure counts. */ if (rail) { if (Company::IsValidID(owner)) Company::Get(owner)->infrastructure.rail[GetRailType(tile)] -= len * TUNNELBRIDGE_TRACKBIT_FACTOR; + } else if (GetTunnelBridgeTransportType(tile) == TRANSPORT_ROAD) { + RoadType rt; + FOR_EACH_SET_ROADTYPE(rt, GetRoadTypes(tile)) { + Company *c = Company::GetIfValid(GetRoadOwner(tile, rt)); + if (c != NULL) { + /* A full diagonal road tile has two road bits. */ + c->infrastructure.road[rt] -= len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR; + DirtyCompanyInfrastructureWindows(c->index); + } + } } DirtyCompanyInfrastructureWindows(owner); @@ -1520,6 +1554,13 @@ static void ChangeTileOwner_TunnelBridge for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) { /* Update all roadtypes, no matter if they are present */ if (GetRoadOwner(tile, rt) == old_owner) { + if (HasBit(GetRoadTypes(tile), rt)) { + /* Update company infrastructure counts. A full diagonal road tile has two road bits. + * No need to dirty windows here, we'll redraw the whole screen anyway. */ + Company::Get(old_owner)->infrastructure.road[rt] -= num_pieces * 2; + if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.road[rt] += num_pieces * 2; + } + SetRoadOwner(tile, rt, new_owner == INVALID_OWNER ? OWNER_NONE : new_owner); } }