Loading

Paste #pjtgnjoan

  1. /**
  2.  * Build a piece of canal.
  3.  * @param tile end tile of stretch-dragging
  4.  * @param flags type of operation
  5.  * @param p1 start tile of stretch-dragging
  6.  * @param p2 waterclass to build. sea and river can only be built in scenario editor
  7.  * @param text unused
  8.  * @return the cost of this operation or an error
  9.  */
  10. CommandCost CmdBuildCanal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
  11. {
  12.     WaterClass wc = Extract<WaterClass, 0, 2>(p2);
  13.     if (p1 >= MapSize() || wc == WATER_CLASS_INVALID) return CMD_ERROR;
  14.  
  15.     /* Outside of the editor you can only build canals, not oceans */
  16.     if (wc != WATER_CLASS_CANAL && _game_mode != GM_EDITOR) return CMD_ERROR;
  17.  
  18.     TileArea ta(tile, p1);
  19.  
  20.     /* Outside the editor you can only drag canals, and not areas */
  21.     if (_game_mode != GM_EDITOR && ta.w != 1 && ta.h != 1) return CMD_ERROR;
  22.  
  23.     Axis axis = INVALID_AXIS;
  24.     int delta = 0;
  25.     TileIndex tile_next = min(tile, p1);
  26.     int rem = 1; // Single-click mode.
  27.  
  28.     /* Maybe change to Single-line mode. */
  29.     if (ta.w == 1 && ta.h > 1) {
  30.         rem = ta.h;
  31.         axis = AXIS_Y;
  32.     }
  33.     if (ta.w > 1 && ta.h == 1) {
  34.         rem = ta.w;
  35.         axis = AXIS_X;
  36.     }
  37.     /* Maybe change to Area-dragging mode. */
  38.     if (ta.w > 1 && ta.h > 1) rem = -1;
  39.     if (axis != INVALID_AXIS) delta = TileOffsByDiagDir(AxisToDiagDir(axis));
  40.  
  41.     bool built_lock = false;
  42.     CommandCost cost(EXPENSES_CONSTRUCTION);
  43.     TILE_AREA_LOOP(tile, ta) {
  44.         if (rem > 0) rem--;
  45.         tile_next += delta;
  46.         if (built_lock) {
  47.             built_lock = false;
  48.             continue;
  49.         }
  50.         Slope slope = GetTileSlope(tile);
  51.         Slope slope_next = GetTileSlope(tile_next);
  52.  
  53.         if (slope != SLOPE_FLAT && !IsInclinedSlope(slope)) {
  54.             return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED);
  55.         }
  56.  
  57.         /* Can't make water of water! */
  58.         if (IsTileType(tile, MP_WATER) && (!IsTileOwner(tile, OWNER_WATER) || wc == WATER_CLASS_SEA)) continue;
  59.  
  60.         CommandCost ret;
  61.         bool river = HasTileWaterClass(tile) && GetWaterClass(tile) == WATER_CLASS_RIVER;
  62.  
  63.         if (rem > 0 && wc == WATER_CLASS_CANAL && slope == SLOPE_FLAT && IsInclinedSlope(slope_next) && DiagDirToAxis(GetInclinedSlopeDirection(slope_next)) == axis) {
  64.             /* The conditions indicate a lock might be built on next iteration. Don't clear this tile and skip to the next iteration now. */
  65.             continue;
  66.         } else {
  67.             /* From here on, slope is either flat or inclined. */
  68.             if (rem >= 0) { // Single-line or single-clicking.
  69.                 if (wc == WATER_CLASS_CANAL && IsInclinedSlope(slope)) {
  70.                     /* Try to build a lock on inclined tile. */
  71.                     if ((axis == INVALID_AXIS || DiagDirToAxis(GetInclinedSlopeDirection(slope)) == axis)) {
  72.                         if (rem == 0 && axis == INVALID_AXIS || IsTileFlat(tile + TileOffsByDiagDir(GetInclinedSlopeDirection(slope))) && IsTileFlat(tile - TileOffsByDiagDir(GetInclinedSlopeDirection(slope)))) {
  73.                             ret = DoCommand(tile, 0, 0, flags, CMD_BUILD_LOCK);
  74.                             if (ret.Failed()) return ret;
  75.                             cost.AddCost(ret);
  76.                             built_lock = true;
  77.                         } else {
  78.                             return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
  79.                         }
  80.                     } else {
  81.                         if (DiagDirToAxis(GetInclinedSlopeDirection(slope)) == OtherAxis(axis)) {
  82.                             return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
  83.                         }
  84.                     }
  85.                 } else {
  86.                     bool water = IsWaterTile(tile);
  87.                     ret = DoCommand(tile, 0, 0, flags | DC_FORCE_CLEAR_TILE, CMD_LANDSCAPE_CLEAR);
  88.                     if (ret.Failed()) return ret;
  89.                     if (!water) cost.AddCost(ret);
  90.                 }
  91.             } else { // Area-dragging mode.
  92.                 if (wc == WATER_CLASS_CANAL && IsInclinedSlope(slope)) {
  93.                     return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED);
  94.                 } else {
  95.                     bool water = IsWaterTile(tile);
  96.                     ret = DoCommand(tile, 0, 0, flags | DC_FORCE_CLEAR_TILE, CMD_LANDSCAPE_CLEAR);
  97.                     if (ret.Failed()) return ret;
  98.                     if (!water) cost.AddCost(ret);
  99.                 }
  100.             }
  101.         }
  102.  
  103.         if (flags & DC_EXEC) {
  104.             switch (wc) {
  105.                 case WATER_CLASS_RIVER:
  106.                     MakeRiver(tile, Random());
  107.                     if (_game_mode == GM_EDITOR) {
  108.                         TileIndex tile2 = tile;
  109.                         CircularTileSearch(&tile2, 5, RiverModifyDesertZone, NULL);
  110.                     }
  111.                     break;
  112.  
  113.                 case WATER_CLASS_SEA:
  114.                     if (TileHeight(tile) == 0) {
  115.                         MakeSea(tile);
  116.                         break;
  117.                     }
  118.                     /* FALL THROUGH */
  119.  
  120.                 default:
  121.                     if (!built_lock) {
  122.                         MakeCanal(tile, _current_company, Random());
  123.                         if (river) SetCanalOnRiver(tile);
  124.                         if (Company::IsValidID(_current_company)) {
  125.                             Company::Get(_current_company)->infrastructure.water++;
  126.                             DirtyCompanyInfrastructureWindows(_current_company);
  127.                         }
  128.                     }
  129.                     break;
  130.             }
  131.             MarkTileDirtyByTile(tile);
  132.             MarkCanalsAndRiversAroundDirty(tile);
  133.         }
  134.  
  135.         if (!built_lock) cost.AddCost(_price[PR_BUILD_CANAL]);
  136.     }
  137.  
  138.     if (cost.GetCost() == 0) {
  139.         return_cmd_error(STR_ERROR_ALREADY_BUILT);
  140.     } else {
  141.         return cost;
  142.     }
  143. }

Comments