86 return true; |
86 return true; |
87 } |
87 } |
88 |
88 |
89 |
89 |
90 /** Delete a piece of road. |
90 /** Delete a piece of road. |
91 * @param x,y tile coordinates for road construction |
91 * @param tile tile where to remove road from |
92 * @param p1 road piece flags |
92 * @param p1 road piece flags |
93 * @param p2 unused |
93 * @param p2 unused |
94 */ |
94 */ |
95 int32 CmdRemoveRoad(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
95 int32 CmdRemoveRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
96 { |
96 { |
97 // cost for removing inner/edge -roads |
97 // cost for removing inner/edge -roads |
98 static const uint16 road_remove_cost[2] = {50, 18}; |
98 static const uint16 road_remove_cost[2] = {50, 18}; |
99 |
99 |
100 TileIndex tile; |
|
101 PlayerID owner; |
100 PlayerID owner; |
102 Town *t; |
101 Town *t; |
103 /* true if the roadpiece was always removeable, |
102 /* true if the roadpiece was always removeable, |
104 * false if it was a center piece. Affects town ratings drop */ |
103 * false if it was a center piece. Affects town ratings drop */ |
105 bool edge_road; |
104 bool edge_road; |
108 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
107 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
109 |
108 |
110 /* Road pieces are max 4 bitset values (NE, NW, SE, SW) */ |
109 /* Road pieces are max 4 bitset values (NE, NW, SE, SW) */ |
111 if (p1 >> 4) return CMD_ERROR; |
110 if (p1 >> 4) return CMD_ERROR; |
112 pieces = p1; |
111 pieces = p1; |
113 |
|
114 tile = TileVirtXY(x, y); |
|
115 |
112 |
116 if (!IsTileType(tile, MP_STREET) && !IsTileType(tile, MP_TUNNELBRIDGE)) return CMD_ERROR; |
113 if (!IsTileType(tile, MP_STREET) && !IsTileType(tile, MP_TUNNELBRIDGE)) return CMD_ERROR; |
117 |
114 |
118 owner = IsLevelCrossing(tile) ? GetCrossingRoadOwner(tile) : GetTileOwner(tile); |
115 owner = IsLevelCrossing(tile) ? GetCrossingRoadOwner(tile) : GetTileOwner(tile); |
119 |
116 |
269 } |
266 } |
270 return CMD_ERROR; |
267 return CMD_ERROR; |
271 } |
268 } |
272 |
269 |
273 /** Build a piece of road. |
270 /** Build a piece of road. |
274 * @param x,y tile coordinates for road construction |
271 * @param tile tile where to build road |
275 * @param p1 road piece flags |
272 * @param p1 road piece flags |
276 * @param p2 the town that is building the road (0 if not applicable) |
273 * @param p2 the town that is building the road (0 if not applicable) |
277 */ |
274 */ |
278 int32 CmdBuildRoad(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
275 int32 CmdBuildRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
279 { |
276 { |
280 int32 cost = 0; |
277 int32 cost = 0; |
281 int32 ret; |
278 int32 ret; |
282 RoadBits existing = 0; |
279 RoadBits existing = 0; |
283 RoadBits pieces; |
280 RoadBits pieces; |
284 TileIndex tile; |
|
285 byte tileh; |
281 byte tileh; |
286 |
282 |
287 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
283 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
288 |
284 |
289 /* Road pieces are max 4 bitset values (NE, NW, SE, SW) and town can only be non-zero |
285 /* 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 */ |
286 * if a non-player is building the road */ |
291 if ((p1 >> 4) || (_current_player < MAX_PLAYERS && p2 != 0) || !IsTownIndex(p2)) return CMD_ERROR; |
287 if ((p1 >> 4) || (_current_player < MAX_PLAYERS && p2 != 0) || !IsTownIndex(p2)) return CMD_ERROR; |
292 pieces = p1; |
288 pieces = p1; |
293 |
289 |
294 tile = TileVirtXY(x, y); |
|
295 tileh = GetTileSlope(tile, NULL); |
290 tileh = GetTileSlope(tile, NULL); |
296 |
291 |
297 switch (GetTileType(tile)) { |
292 switch (GetTileType(tile)) { |
298 case MP_STREET: |
293 case MP_STREET: |
299 switch (GetRoadType(tile)) { |
294 switch (GetRoadType(tile)) { |
386 } |
381 } |
387 return _price.build_road * 2; |
382 return _price.build_road * 2; |
388 |
383 |
389 default: |
384 default: |
390 do_clear:; |
385 do_clear:; |
391 ret = DoCommandByTile(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
386 ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
392 if (CmdFailed(ret)) return ret; |
387 if (CmdFailed(ret)) return ret; |
393 cost += ret; |
388 cost += ret; |
394 } |
389 } |
395 |
390 |
396 ret = CheckRoadSlope(tileh, &pieces, existing); |
391 ret = CheckRoadSlope(tileh, &pieces, existing); |
437 return _price.build_rail >> 1; |
432 return _price.build_rail >> 1; |
438 } |
433 } |
439 |
434 |
440 |
435 |
441 /** Build a long piece of road. |
436 /** Build a long piece of road. |
442 * @param x,y end tile of drag |
437 * @param end_tile end tile of drag |
443 * @param p1 start tile of drag |
438 * @param p1 start tile of drag |
444 * @param p2 various bitstuffed elements |
439 * @param p2 various bitstuffed elements |
445 * - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1) |
440 * - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1) |
446 * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2) |
441 * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2) |
447 * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4) |
442 * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4) |
448 */ |
443 */ |
449 int32 CmdBuildLongRoad(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
444 int32 CmdBuildLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2) |
450 { |
445 { |
451 TileIndex start_tile, end_tile, tile; |
446 TileIndex start_tile, tile; |
452 int32 cost, ret; |
447 int32 cost, ret; |
453 |
448 |
454 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
449 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
455 |
450 |
456 if (p1 >= MapSize()) return CMD_ERROR; |
451 if (p1 >= MapSize()) return CMD_ERROR; |
457 |
452 |
458 start_tile = p1; |
453 start_tile = p1; |
459 end_tile = TileVirtXY(x, y); |
|
460 |
454 |
461 /* Only drag in X or Y direction dictated by the direction variable */ |
455 /* Only drag in X or Y direction dictated by the direction variable */ |
462 if (!HASBIT(p2, 2) && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis |
456 if (!HASBIT(p2, 2) && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis |
463 if (HASBIT(p2, 2) && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis |
457 if (HASBIT(p2, 2) && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis |
464 |
458 |
477 RoadBits bits = HASBIT(p2, 2) ? ROAD_Y : ROAD_X; |
471 RoadBits bits = HASBIT(p2, 2) ? ROAD_Y : ROAD_X; |
478 |
472 |
479 if (tile == end_tile && !HASBIT(p2, 1)) bits &= ROAD_NW | ROAD_NE; |
473 if (tile == end_tile && !HASBIT(p2, 1)) bits &= ROAD_NW | ROAD_NE; |
480 if (tile == start_tile && HASBIT(p2, 0)) bits &= ROAD_SE | ROAD_SW; |
474 if (tile == start_tile && HASBIT(p2, 0)) bits &= ROAD_SE | ROAD_SW; |
481 |
475 |
482 ret = DoCommandByTile(tile, bits, 0, flags, CMD_BUILD_ROAD); |
476 ret = DoCommand(tile, bits, 0, flags, CMD_BUILD_ROAD); |
483 if (CmdFailed(ret)) { |
477 if (CmdFailed(ret)) { |
484 if (_error_message != STR_1007_ALREADY_BUILT) return CMD_ERROR; |
478 if (_error_message != STR_1007_ALREADY_BUILT) return CMD_ERROR; |
485 } else { |
479 } else { |
486 cost += ret; |
480 cost += ret; |
487 } |
481 } |
493 |
487 |
494 return (cost == 0) ? CMD_ERROR : cost; |
488 return (cost == 0) ? CMD_ERROR : cost; |
495 } |
489 } |
496 |
490 |
497 /** Remove a long piece of road. |
491 /** Remove a long piece of road. |
498 * @param x,y end tile of drag |
492 * @param end_tile end tile of drag |
499 * @param p1 start tile of drag |
493 * @param p1 start tile of drag |
500 * @param p2 various bitstuffed elements |
494 * @param p2 various bitstuffed elements |
501 * - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1) |
495 * - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1) |
502 * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2) |
496 * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2) |
503 * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4) |
497 * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4) |
504 */ |
498 */ |
505 int32 CmdRemoveLongRoad(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
499 int32 CmdRemoveLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2) |
506 { |
500 { |
507 TileIndex start_tile, end_tile, tile; |
501 TileIndex start_tile, tile; |
508 int32 cost, ret; |
502 int32 cost, ret; |
509 |
503 |
510 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
504 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
511 |
505 |
512 if (p1 >= MapSize()) return CMD_ERROR; |
506 if (p1 >= MapSize()) return CMD_ERROR; |
513 |
507 |
514 start_tile = p1; |
508 start_tile = p1; |
515 end_tile = TileVirtXY(x, y); |
|
516 |
509 |
517 /* Only drag in X or Y direction dictated by the direction variable */ |
510 /* Only drag in X or Y direction dictated by the direction variable */ |
518 if (!HASBIT(p2, 2) && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis |
511 if (!HASBIT(p2, 2) && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis |
519 if (HASBIT(p2, 2) && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis |
512 if (HASBIT(p2, 2) && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis |
520 |
513 |
535 if (tile == end_tile && !HASBIT(p2, 1)) bits &= ROAD_NW | ROAD_NE; |
528 if (tile == end_tile && !HASBIT(p2, 1)) bits &= ROAD_NW | ROAD_NE; |
536 if (tile == start_tile && HASBIT(p2, 0)) bits &= ROAD_SE | ROAD_SW; |
529 if (tile == start_tile && HASBIT(p2, 0)) bits &= ROAD_SE | ROAD_SW; |
537 |
530 |
538 // try to remove the halves. |
531 // try to remove the halves. |
539 if (bits != 0) { |
532 if (bits != 0) { |
540 ret = DoCommandByTile(tile, bits, 0, flags, CMD_REMOVE_ROAD); |
533 ret = DoCommand(tile, bits, 0, flags, CMD_REMOVE_ROAD); |
541 if (!CmdFailed(ret)) cost += ret; |
534 if (!CmdFailed(ret)) cost += ret; |
542 } |
535 } |
543 |
536 |
544 if (tile == end_tile) break; |
537 if (tile == end_tile) break; |
545 |
538 |
548 |
541 |
549 return (cost == 0) ? CMD_ERROR : cost; |
542 return (cost == 0) ? CMD_ERROR : cost; |
550 } |
543 } |
551 |
544 |
552 /** Build a road depot. |
545 /** Build a road depot. |
553 * @param x,y tile coordinates where the depot will be built |
546 * @param tile tile where to build the depot |
554 * @param p1 entrance direction (DiagDirection) |
547 * @param p1 entrance direction (DiagDirection) |
555 * @param p2 unused |
548 * @param p2 unused |
556 * |
549 * |
557 * @todo When checking for the tile slope, |
550 * @todo When checking for the tile slope, |
558 * distingush between "Flat land required" and "land sloped in wrong direction" |
551 * distingush between "Flat land required" and "land sloped in wrong direction" |
559 */ |
552 */ |
560 int32 CmdBuildRoadDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
553 int32 CmdBuildRoadDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
561 { |
554 { |
562 int32 cost; |
555 int32 cost; |
563 Depot *dep; |
556 Depot *dep; |
564 TileIndex tile; |
|
565 uint tileh; |
557 uint tileh; |
566 |
558 |
567 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
559 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
568 |
560 |
569 if (p1 > 3) return CMD_ERROR; // check direction |
561 if (p1 > 3) return CMD_ERROR; // check direction |
570 |
|
571 tile = TileVirtXY(x, y); |
|
572 |
562 |
573 if (!EnsureNoVehicle(tile)) return CMD_ERROR; |
563 if (!EnsureNoVehicle(tile)) return CMD_ERROR; |
574 |
564 |
575 tileh = GetTileSlope(tile, NULL); |
565 tileh = GetTileSlope(tile, NULL); |
576 if (tileh != 0 && ( |
566 if (tileh != 0 && ( |
579 !CanBuildDepotByTileh(p1, tileh) |
569 !CanBuildDepotByTileh(p1, tileh) |
580 )) { |
570 )) { |
581 return_cmd_error(STR_0007_FLAT_LAND_REQUIRED); |
571 return_cmd_error(STR_0007_FLAT_LAND_REQUIRED); |
582 } |
572 } |
583 |
573 |
584 cost = DoCommandByTile(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
574 cost = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
585 if (CmdFailed(cost)) return CMD_ERROR; |
575 if (CmdFailed(cost)) return CMD_ERROR; |
586 |
576 |
587 dep = AllocateDepot(); |
577 dep = AllocateDepot(); |
588 if (dep == NULL) return CMD_ERROR; |
578 if (dep == NULL) return CMD_ERROR; |
589 |
579 |
622 if (!((1 << b) & (M(1)|M(2)|M(4)|M(8))) && |
612 if (!((1 << b) & (M(1)|M(2)|M(4)|M(8))) && |
623 (!(flags & DC_AI_BUILDING) || !IsTileOwner(tile, OWNER_TOWN)) && |
613 (!(flags & DC_AI_BUILDING) || !IsTileOwner(tile, OWNER_TOWN)) && |
624 flags & DC_AUTO) { |
614 flags & DC_AUTO) { |
625 return_cmd_error(STR_1801_MUST_REMOVE_ROAD_FIRST); |
615 return_cmd_error(STR_1801_MUST_REMOVE_ROAD_FIRST); |
626 } |
616 } |
627 return DoCommandByTile(tile, b, 0, flags, CMD_REMOVE_ROAD); |
617 return DoCommand(tile, b, 0, flags, CMD_REMOVE_ROAD); |
628 } |
618 } |
629 |
619 |
630 case ROAD_CROSSING: { |
620 case ROAD_CROSSING: { |
631 int32 ret; |
621 int32 ret; |
632 |
622 |
633 if (flags & DC_AUTO) return_cmd_error(STR_1801_MUST_REMOVE_ROAD_FIRST); |
623 if (flags & DC_AUTO) return_cmd_error(STR_1801_MUST_REMOVE_ROAD_FIRST); |
634 |
624 |
635 ret = DoCommandByTile(tile, GetCrossingRoadBits(tile), 0, flags, CMD_REMOVE_ROAD); |
625 ret = DoCommand(tile, GetCrossingRoadBits(tile), 0, flags, CMD_REMOVE_ROAD); |
636 if (CmdFailed(ret)) return CMD_ERROR; |
626 if (CmdFailed(ret)) return CMD_ERROR; |
637 |
627 |
638 if (flags & DC_EXEC) { |
628 if (flags & DC_EXEC) { |
639 DoCommandByTile(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
629 DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
640 } |
630 } |
641 return ret; |
631 return ret; |
642 } |
632 } |
643 |
633 |
644 default: |
634 default: |
1090 MakeRoadNormal(tile, GetCrossingRoadOwner(tile), GetCrossingRoadBits(tile), GetTownIndex(tile)); |
1080 MakeRoadNormal(tile, GetCrossingRoadOwner(tile), GetCrossingRoadBits(tile), GetTownIndex(tile)); |
1091 break; |
1081 break; |
1092 |
1082 |
1093 default: |
1083 default: |
1094 case ROAD_DEPOT: |
1084 case ROAD_DEPOT: |
1095 DoCommandByTile(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR); |
1085 DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR); |
1096 break; |
1086 break; |
1097 } |
1087 } |
1098 } |
1088 } |
1099 } |
1089 } |
1100 |
1090 |