275 * @param p1 road piece flags |
275 * @param p1 road piece flags |
276 * @param p2 the town that is building the road (0 if not applicable) |
276 * @param p2 the town that is building the road (0 if not applicable) |
277 */ |
277 */ |
278 int32 CmdBuildRoad(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
278 int32 CmdBuildRoad(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
279 { |
279 { |
280 TileInfo ti; |
|
281 int32 cost = 0; |
280 int32 cost = 0; |
282 int32 ret; |
281 int32 ret; |
283 RoadBits existing = 0; |
282 RoadBits existing = 0; |
284 RoadBits pieces; |
283 RoadBits pieces; |
285 TileIndex tile; |
284 TileIndex tile; |
|
285 byte tileh; |
286 |
286 |
287 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
287 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
288 |
288 |
289 /* Road pieces are max 4 bitset values (NE, NW, SE, SW) and town can only be non-zero |
289 /* Road pieces are max 4 bitset values (NE, NW, SE, SW) and town can only be non-zero |
290 * if a non-player is building the road */ |
290 * if a non-player is building the road */ |
291 if ((p1 >> 4) || (_current_player < MAX_PLAYERS && p2 != 0) || !IsTownIndex(p2)) return CMD_ERROR; |
291 if ((p1 >> 4) || (_current_player < MAX_PLAYERS && p2 != 0) || !IsTownIndex(p2)) return CMD_ERROR; |
292 pieces = p1; |
292 pieces = p1; |
293 |
293 |
294 FindLandscapeHeight(&ti, x, y); |
294 tile = TileVirtXY(x, y); |
295 tile = ti.tile; |
295 tileh = GetTileSlope(tile, NULL); |
296 |
296 |
297 switch (ti.type) { |
297 switch (GetTileType(tile)) { |
298 case MP_STREET: |
298 case MP_STREET: |
299 switch (GetRoadType(tile)) { |
299 switch (GetRoadType(tile)) { |
300 case ROAD_NORMAL: |
300 case ROAD_NORMAL: |
301 existing = GetRoadBits(tile); |
301 existing = GetRoadBits(tile); |
302 if ((existing & pieces) == pieces) { |
302 if ((existing & pieces) == pieces) { |
318 break; |
318 break; |
319 |
319 |
320 case MP_RAILWAY: { |
320 case MP_RAILWAY: { |
321 Axis roaddir; |
321 Axis roaddir; |
322 |
322 |
323 if (IsSteepTileh(ti.tileh)) { // very steep tile |
323 if (IsSteepTileh(tileh)) { // very steep tile |
324 return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
324 return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
325 } |
325 } |
326 |
326 |
327 #define M(x) (1 << (x)) |
327 #define M(x) (1 << (x)) |
328 /* Level crossings may only be built on these slopes */ |
328 /* Level crossings may only be built on these slopes */ |
329 if (!HASBIT(M(14) | M(13) | M(11) | M(10) | M(7) | M(5) | M(0), ti.tileh)) { |
329 if (!HASBIT(M(14) | M(13) | M(11) | M(10) | M(7) | M(5) | M(0), tileh)) { |
330 return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
330 return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
331 } |
331 } |
332 #undef M |
332 #undef M |
333 |
333 |
334 if (GetRailTileType(tile) != RAIL_TYPE_NORMAL) goto do_clear; |
334 if (GetRailTileType(tile) != RAIL_TYPE_NORMAL) goto do_clear; |
355 return _price.build_road * 2; |
355 return _price.build_road * 2; |
356 } |
356 } |
357 |
357 |
358 case MP_TUNNELBRIDGE: |
358 case MP_TUNNELBRIDGE: |
359 /* check for flat land */ |
359 /* check for flat land */ |
360 if (IsSteepTileh(ti.tileh)) { // very steep tile |
360 if (IsSteepTileh(tileh)) { // very steep tile |
361 return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
361 return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
362 } |
362 } |
363 |
363 |
364 if (!IsBridge(tile) || !IsBridgeMiddle(tile)) goto do_clear; |
364 if (!IsBridge(tile) || !IsBridgeMiddle(tile)) goto do_clear; |
365 |
365 |
391 ret = DoCommandByTile(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
391 ret = DoCommandByTile(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
392 if (CmdFailed(ret)) return ret; |
392 if (CmdFailed(ret)) return ret; |
393 cost += ret; |
393 cost += ret; |
394 } |
394 } |
395 |
395 |
396 ret = CheckRoadSlope(ti.tileh, &pieces, existing); |
396 ret = CheckRoadSlope(tileh, &pieces, existing); |
397 if (CmdFailed(ret)) return_cmd_error(STR_1800_LAND_SLOPED_IN_WRONG_DIRECTION); |
397 if (CmdFailed(ret)) return_cmd_error(STR_1800_LAND_SLOPED_IN_WRONG_DIRECTION); |
398 if (ret != 0 && (!_patches.build_on_slopes || _is_old_ai_player)) { |
398 if (ret != 0 && (!_patches.build_on_slopes || _is_old_ai_player)) { |
399 return CMD_ERROR; |
399 return CMD_ERROR; |
400 } |
400 } |
401 cost += ret; |
401 cost += ret; |
402 |
402 |
403 if (ti.type == MP_STREET) { |
403 if (IsTileType(tile, MP_STREET)) { |
404 // Don't put the pieces that already exist |
404 // Don't put the pieces that already exist |
405 pieces &= ComplementRoadBits(existing); |
405 pieces &= ComplementRoadBits(existing); |
406 } |
406 } |
407 |
407 |
408 cost += CountRoadBits(pieces) * _price.build_road; |
408 cost += CountRoadBits(pieces) * _price.build_road; |
409 |
409 |
410 if (flags & DC_EXEC) { |
410 if (flags & DC_EXEC) { |
411 if (ti.type == MP_STREET) { |
411 if (IsTileType(tile, MP_STREET)) { |
412 SetRoadBits(tile, existing | pieces); |
412 SetRoadBits(tile, existing | pieces); |
413 } else { |
413 } else { |
414 MakeRoadNormal(tile, _current_player, pieces, p2); |
414 MakeRoadNormal(tile, _current_player, pieces, p2); |
415 } |
415 } |
416 |
416 |