Loading

Paste #pb70f60wf

  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.             /* A lock was built on the last iteration, which means
  48.              * this iteration's tile belongs to the lock. */
  49.             built_lock = false;
  50.             continue;
  51.         }
  52.         Slope slope = GetTileSlope(tile);
  53.  
  54.         if (slope != SLOPE_FLAT && !IsInclinedSlope(slope)) {
  55.             return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED);
  56.         }
  57.         /* From here on, slope is either flat or inclined. */
  58.  
  59.         /* Can't make water of water! */
  60.         if (IsTileType(tile, MP_WATER) && (!IsTileOwner(tile, OWNER_WATER) || wc == WATER_CLASS_SEA)) continue;
  61.  
  62.         CommandCost ret;
  63.         bool river = HasTileWaterClass(tile) && GetWaterClass(tile) == WATER_CLASS_RIVER;
  64.  
  65.         Slope slope_next = GetTileSlope(tile_next);
  66.         if (rem > 0 && wc == WATER_CLASS_CANAL && slope == SLOPE_FLAT && IsInclinedSlope(slope_next) && DiagDirToAxis(GetInclinedSlopeDirection(slope_next)) == axis) {
  67.             /* The conditions indicate a lock might be built on next iteration.
  68.              * Don't clear this tile and skip to the next iteration now. */
  69.             continue;
  70.         } else {
  71.             bool water = IsWaterTile(tile);
  72.             if (rem >= 0) { // Single-line or single-clicking.
  73.                 if (wc == WATER_CLASS_CANAL && IsInclinedSlope(slope)) {
  74.                     /* Try to build a lock on inclined tile. */
  75.                     if ((axis == INVALID_AXIS || DiagDirToAxis(GetInclinedSlopeDirection(slope)) == axis)) {
  76.                         int tile_delta = TileOffsByDiagDir(GetInclinedSlopeDirection(slope));
  77.                         if (rem == 0 && axis == INVALID_AXIS || IsTileFlat(tile + tile_delta) && IsTileFlat(tile - tile_delta)) {
  78.                             ret = DoCommand(tile, 0, 0, flags, CMD_BUILD_LOCK);
  79.                             if (ret.Failed()) return ret;
  80.                             cost.AddCost(ret);
  81.                             built_lock = true;
  82.                         } else {
  83.                             return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
  84.                         }
  85.                     } else {
  86.                         if (DiagDirToAxis(GetInclinedSlopeDirection(slope)) == OtherAxis(axis)) {
  87.                             return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
  88.                         }
  89.                     }
  90.                 } else {
  91.                     ret = DoCommand(tile, 0, 0, flags | DC_FORCE_CLEAR_TILE, CMD_LANDSCAPE_CLEAR);
  92.                     if (ret.Failed()) return ret;
  93.                     if (!water) cost.AddCost(ret);
  94.                 }
  95.             } else { // Area-dragging mode.
  96.                 if (wc == WATER_CLASS_CANAL && IsInclinedSlope(slope)) {
  97.                     return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED);
  98.                 } else {
  99.                     ret = DoCommand(tile, 0, 0, flags | DC_FORCE_CLEAR_TILE, CMD_LANDSCAPE_CLEAR);
  100.                     if (ret.Failed()) return ret;
  101.                     if (!water) cost.AddCost(ret);
  102.                 }
  103.             }
  104.         }
  105.  
  106.         if (flags & DC_EXEC) {
  107.             switch (wc) {
  108.                 case WATER_CLASS_RIVER:
  109.                     MakeRiver(tile, Random());
  110.                     if (_game_mode == GM_EDITOR) {
  111.                         TileIndex tile2 = tile;
  112.                         CircularTileSearch(&tile2, 5, RiverModifyDesertZone, NULL);
  113.                     }
  114.                     break;
  115.  
  116.                 case WATER_CLASS_SEA:
  117.                     if (TileHeight(tile) == 0) {
  118.                         MakeSea(tile);
  119.                         break;
  120.                     }
  121.                     /* FALL THROUGH */
  122.  
  123.                 default:
  124.                     if (!built_lock) {
  125.                         MakeCanal(tile, _current_company, Random());
  126.                         if (river) SetCanalOnRiver(tile);
  127.                         if (Company::IsValidID(_current_company)) {
  128.                             Company::Get(_current_company)->infrastructure.water++;
  129.                             DirtyCompanyInfrastructureWindows(_current_company);
  130.                         }
  131.                     }
  132.                     break;
  133.             }
  134.             MarkTileDirtyByTile(tile);
  135.             MarkCanalsAndRiversAroundDirty(tile);
  136.         }
  137.  
  138.         if (!built_lock) cost.AddCost(_price[PR_BUILD_CANAL]);
  139.     }
  140.  
  141.     if (cost.GetCost() == 0) {
  142.         return_cmd_error(STR_ERROR_ALREADY_BUILT);
  143.     } else {
  144.         return cost;
  145.     }
  146. }

Version history

Revision # Author Created at
pjtgnjoan Anonymous 26 Sep 2016, 15:53:31 UTC Diff

Comments