Loading

Paste #py1q66axy

  1. /**
  2.  * Build a single piece of rail
  3.  * @param tile tile  to build on
  4.  * @param flags operation to perform
  5.  * @param p1 railtype of being built piece (normal, mono, maglev)
  6.  * @param p2 rail track to build
  7.  * @param text unused
  8.  * @return the cost of this operation or an error
  9.  */
  10. CommandCost CmdBuildSingleRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
  11. {
  12.     RailType railtype = Extract<RailType, 0, 4>(p1);
  13.     Track track = Extract<Track, 0, 3>(p2);
  14.     CommandCost cost(EXPENSES_CONSTRUCTION);
  15.  
  16.     if (!ValParamRailtype(railtype) || !ValParamTrackOrientation(track)) return CMD_ERROR;
  17.  
  18.     Slope tileh = GetTileSlope(tile);
  19.     TrackBits trackbit = TrackToTrackBits(track);
  20.  
  21.     switch (GetTileType(tile)) {
  22.         case MP_RAILWAY: {
  23.             CommandCost ret = CheckTileOwnership(tile);
  24.             if (ret.Failed()) return ret;
  25.  
  26.             if (!IsPlainRail(tile)) return CMD_ERROR;
  27.  
  28.             if (!IsCompatibleRail(GetRailType(tile), railtype)) return_cmd_error(STR_ERROR_IMPOSSIBLE_TRACK_COMBINATION);
  29.  
  30.             ret = CheckTrackCombination(tile, trackbit, flags);
  31.             if (ret.Succeeded()) ret = EnsureNoTrainOnTrack(tile, track);
  32.             if (ret.Failed()) return ret;
  33.  
  34.             ret = CheckRailSlope(tileh, trackbit, GetTrackBits(tile), tile);
  35.             if (ret.Failed()) return ret;
  36.             cost.AddCost(ret);
  37.  
  38.             /* If the rail types don't match, try to convert only if engines of
  39.              * the new rail type are not powered on the present rail type and engines of
  40.              * the present rail type are powered on the new rail type. */
  41.             if (GetRailType(tile) != railtype && !HasPowerOnRail(railtype, GetRailType(tile))) {
  42.                 if (HasPowerOnRail(GetRailType(tile), railtype)) {
  43.                     ret = DoCommand(tile, tile, railtype, flags, CMD_CONVERT_RAIL);
  44.                     if (ret.Failed()) return ret;
  45.                     cost.AddCost(ret);
  46.                 } else {
  47.                     return CMD_ERROR;
  48.                 }
  49.             }
  50.  
  51.             if (flags & DC_EXEC) {
  52.                 SetRailGroundType(tile, RAIL_GROUND_BARREN);
  53.                 TrackBits bits = GetTrackBits(tile);
  54.                 SetTrackBits(tile, bits | trackbit);
  55.                 /* Subtract old infrastructure count. */
  56.                 uint pieces = CountBits(bits);
  57.                 if (TracksOverlap(bits)) pieces *= pieces;
  58.                 Company::Get(GetTileOwner(tile))->infrastructure.rail[GetRailType(tile)] -= pieces;
  59.                 /* Add new infrastructure count. */
  60.                 pieces = CountBits(bits | trackbit);
  61.                 if (TracksOverlap(bits | trackbit)) pieces *= pieces;
  62.                 Company::Get(GetTileOwner(tile))->infrastructure.rail[GetRailType(tile)] += pieces;
  63.                 DirtyCompanyInfrastructureWindows(GetTileOwner(tile));
  64.             }
  65.             break;
  66.         }
  67.  
  68.         case MP_ROAD: {
  69.             /* Level crossings may only be built on these slopes */
  70.             if (!HasBit(VALID_LEVEL_CROSSING_SLOPES, tileh)) return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
  71.  
  72.             CommandCost ret = EnsureNoVehicleOnGround(tile);
  73.             if (ret.Failed()) return ret;
  74.  
  75.             if (IsNormalRoad(tile)) {
  76.                 if (HasRoadWorks(tile)) return_cmd_error(STR_ERROR_ROAD_WORKS_IN_PROGRESS);
  77.  
  78.                 if (GetDisallowedRoadDirections(tile) != DRD_NONE) return_cmd_error(STR_ERROR_CROSSING_ON_ONEWAY_ROAD);
  79.  
  80.                 if (RailNoLevelCrossings(railtype)) return_cmd_error(STR_ERROR_CROSSING_DISALLOWED);
  81.  
  82.                 RoadTypes roadtypes = GetRoadTypes(tile);
  83.                 RoadBits road = GetRoadBits(tile, ROADTYPE_ROAD);
  84.                 RoadBits tram = GetRoadBits(tile, ROADTYPE_TRAM);
  85.                 if ((track == TRACK_X && ((road | tram) & ROAD_X) == 0) ||
  86.                         (track == TRACK_Y && ((road | tram) & ROAD_Y) == 0)) {
  87.                     Owner road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
  88.                     Owner tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM);
  89.                     /* Disallow breaking end-of-line of someone else
  90.                      * so trams can still reverse on this tile. */
  91.                     if (Company::IsValidID(tram_owner) && HasExactlyOneBit(tram)) {
  92.                         CommandCost ret = CheckOwnership(tram_owner);
  93.                         if (ret.Failed()) return ret;
  94.                     }
  95.                     /* Crossings must always have a road... */
  96.                     uint num_new_road_pieces = 2 - CountBits(road);
  97.                     if (road == ROAD_NONE) road_owner = _current_company;
  98.                     roadtypes |= ROADTYPES_ROAD;
  99.                     /* ...but tram is not required. */
  100.                     uint num_new_tram_pieces = (tram != ROAD_NONE) ? 2 - CountBits(tram) : 0;
  101.  
  102.                     cost.AddCost((num_new_road_pieces + num_new_tram_pieces) * _price[PR_BUILD_ROAD]);
  103.  
  104.                     if (flags & DC_EXEC) {
  105.                         MakeRoadCrossing(tile, road_owner, tram_owner, _current_company, (track == TRACK_X ? AXIS_Y : AXIS_X), railtype, roadtypes, GetTownIndex(tile));
  106.                         UpdateLevelCrossing(tile, false);
  107.                         Company::Get(_current_company)->infrastructure.rail[railtype] += LEVELCROSSING_TRACKBIT_FACTOR;
  108.                         DirtyCompanyInfrastructureWindows(_current_company);
  109.                         if (num_new_road_pieces > 0 && Company::IsValidID(road_owner)) {
  110.                             Company::Get(road_owner)->infrastructure.road[ROADTYPE_ROAD] += num_new_road_pieces;
  111.                             DirtyCompanyInfrastructureWindows(road_owner);
  112.                         }
  113.                         if (num_new_tram_pieces > 0 && Company::IsValidID(tram_owner)) {
  114.                             Company::Get(tram_owner)->infrastructure.road[ROADTYPE_TRAM] += num_new_tram_pieces;
  115.                             DirtyCompanyInfrastructureWindows(tram_owner);
  116.                         }
  117.                     }
  118.                     break;
  119.                 }
  120.             }
  121.  
  122.             if (IsLevelCrossing(tile) && GetCrossingRailBits(tile) == trackbit) {
  123.                 return_cmd_error(STR_ERROR_ALREADY_BUILT);
  124.             }
  125.             /* FALL THROUGH */
  126.         }
  127.  
  128.         default: {
  129.             /* Will there be flat water on the lower halftile? */
  130.             bool water_ground = IsTileType(tile, MP_WATER) && IsSlopeWithOneCornerRaised(tileh);
  131.  
  132.             CommandCost ret = CheckRailSlope(tileh, trackbit, TRACK_BIT_NONE, tile);
  133.             if (ret.Failed()) return ret;
  134.             cost.AddCost(ret);
  135.  
  136.             if (!water_ground) {
  137.                 ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
  138.                 if (ret.Failed()) return ret;
  139.                 cost.AddCost(ret);
  140.             } else {
  141.                 cost.AddCost(_price[PR_CLEAR_ROUGH]);
  142.             }
  143.  
  144.             if (flags & DC_EXEC) {
  145.                 MakeRailNormal(tile, _current_company, trackbit, railtype);
  146.                 if (water_ground) SetRailGroundType(tile, RAIL_GROUND_WATER);
  147.                 Company::Get(_current_company)->infrastructure.rail[railtype]++;
  148.                 DirtyCompanyInfrastructureWindows(_current_company);
  149.             }
  150.             break;
  151.         }
  152.     }
  153.  
  154.     if (flags & DC_EXEC) {
  155.         MarkTileDirtyByTile(tile);
  156.         AddTrackToSignalBuffer(tile, track, _current_company);
  157.         YapfNotifyTrackLayoutChange(tile, track);
  158.     }
  159.  
  160.     cost.AddCost(RailBuildCost(railtype));
  161.     return cost;
  162. }

Comments