road_cmd.c
changeset 3491 35d747bb5e82
parent 3435 dfba5b1c7c2d
child 3560 b2fcf1898eec
equal deleted inserted replaced
3490:d53bc3e794bd 3491:35d747bb5e82
    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