tunnelbridge_cmd.c
changeset 3063 61a07ec0d09e
parent 3056 44eedffdb485
child 3064 960264bcce6f
equal deleted inserted replaced
3062:2c96a73da934 3063:61a07ec0d09e
   452 		DoCheckTunnelInWay(tile,z,1) &&
   452 		DoCheckTunnelInWay(tile,z,1) &&
   453 		DoCheckTunnelInWay(tile,z,2) &&
   453 		DoCheckTunnelInWay(tile,z,2) &&
   454 		DoCheckTunnelInWay(tile,z,3);
   454 		DoCheckTunnelInWay(tile,z,3);
   455 }
   455 }
   456 
   456 
   457 static byte _build_tunnel_bh;
       
   458 static byte _build_tunnel_railtype;
       
   459 
       
   460 static int32 DoBuildTunnel(int x, int y, int x2, int y2, uint32 flags, uint exc_tile)
       
   461 {
       
   462 	TileIndex end_tile;
       
   463 	int direction;
       
   464 	int32 cost, ret;
       
   465 	TileInfo ti;
       
   466 	uint z;
       
   467 
       
   468 	if ((uint)x > MapMaxX() * 16 - 1 || (uint)y > MapMaxY() * 16 - 1)
       
   469 		return CMD_ERROR;
       
   470 
       
   471 	/* check if valid, and make sure that (x,y) is smaller than (x2,y2) */
       
   472 	direction = 0;
       
   473 	if (x == x2) {
       
   474 		if (y == y2) return_cmd_error(STR_5008_CANNOT_START_AND_END_ON);
       
   475 		direction++;
       
   476 		if (y > y2) {
       
   477 			intswap(y,y2);
       
   478 			intswap(x,x2);
       
   479 			exc_tile |= 2;
       
   480 		}
       
   481 	} else if (y == y2) {
       
   482 		if (x > x2) {
       
   483 			intswap(y,y2);
       
   484 			intswap(x,x2);
       
   485 			exc_tile |= 2;
       
   486 		}
       
   487 	} else {
       
   488 		return_cmd_error(STR_500A_START_AND_END_MUST_BE_IN);
       
   489 	}
       
   490 
       
   491 	cost = 0;
       
   492 
       
   493 	FindLandscapeHeight(&ti, x2, y2);
       
   494 	end_tile = ti.tile;
       
   495 	z = ti.z;
       
   496 
       
   497 	if (exc_tile != 3) {
       
   498 		if ((direction ? 9U : 12U) != ti.tileh)
       
   499 			return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
       
   500 		ret = DoCommandByTile(ti.tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
       
   501 		if (CmdFailed(ret)) return CMD_ERROR;
       
   502 		cost += ret;
       
   503 	}
       
   504 	cost += _price.build_tunnel;
       
   505 
       
   506 	for (;;) {
       
   507 		if (direction) y2-=16; else x2-=16;
       
   508 
       
   509 		if (x2 == x && y2 == y) break;
       
   510 
       
   511 		FindLandscapeHeight(&ti, x2, y2);
       
   512 		if (ti.z <= z) return CMD_ERROR;
       
   513 
       
   514 		if (!_cheats.crossing_tunnels.value && !CheckTunnelInWay(ti.tile, z))
       
   515 			return CMD_ERROR;
       
   516 
       
   517 		cost += _price.build_tunnel;
       
   518 		cost += (cost >> 3);
       
   519 
       
   520 		if (cost >= 400000000) cost = 400000000;
       
   521 	}
       
   522 
       
   523 	FindLandscapeHeight(&ti, x2, y2);
       
   524 	if (ti.z != z) return CMD_ERROR;
       
   525 
       
   526 	if (exc_tile != 1) {
       
   527 		if ((direction ? 6U : 3U) != ti.tileh)
       
   528 			return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
       
   529 
       
   530 		ret = DoCommandByTile(ti.tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
       
   531 		if (CmdFailed(ret)) return CMD_ERROR;
       
   532 		cost += ret;
       
   533 	}
       
   534 
       
   535 	if (flags & DC_EXEC) {
       
   536 		ModifyTile(ti.tile,
       
   537 			MP_SETTYPE(MP_TUNNELBRIDGE) |
       
   538 			MP_MAP3LO | MP_MAPOWNER_CURRENT | MP_MAP5,
       
   539 			_build_tunnel_railtype, /* map3lo */
       
   540 			((_build_tunnel_bh << 1) | 2) - direction /* map5 */
       
   541 		);
       
   542 
       
   543 		ModifyTile(end_tile,
       
   544 			MP_SETTYPE(MP_TUNNELBRIDGE) |
       
   545 			MP_MAP3LO | MP_MAPOWNER_CURRENT | MP_MAP5,
       
   546 			_build_tunnel_railtype, /* map3lo */
       
   547 			(_build_tunnel_bh << 1) | (direction ? 3:0)/* map5 */
       
   548 		);
       
   549 
       
   550 		UpdateSignalsOnSegment(end_tile, direction?7:1);
       
   551 	}
       
   552 
       
   553 	return cost + _price.build_tunnel;
       
   554 }
       
   555 
   457 
   556 /** Build Tunnel.
   458 /** Build Tunnel.
   557  * @param x,y start tile coord of tunnel
   459  * @param x,y start tile coord of tunnel
   558  * @param p1 railtype, 0x200 for road tunnel
   460  * @param p1 railtype, 0x200 for road tunnel
   559  * @param p2 unused
   461  * @param p2 unused
   560  */
   462  */
   561 int32 CmdBuildTunnel(int x, int y, uint32 flags, uint32 p1, uint32 p2)
   463 int32 CmdBuildTunnel(int x, int y, uint32 flags, uint32 p1, uint32 p2)
   562 {
   464 {
   563 	TileInfo ti, tiorg;
   465 	TileIndexDiff delta;
   564 	int direction;
   466 	TileIndex start_tile;
   565 	uint z;
   467 	TileIndex end_tile;
   566 	static const int8 _build_tunnel_coord_mod[4+1] = { -16, 0, 16, 0, -16 };
   468 	DiagDirection direction;
   567 	static const byte _build_tunnel_tileh[4] = {3, 9, 12, 6};
   469 	uint start_tileh;
   568 	TileIndex excavated_tile;
   470 	uint end_tileh;
   569 
   471 	uint start_z;
   570 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   472 	uint end_z;
       
   473 	int32 cost;
       
   474 	int32 ret;
       
   475 
       
   476 	_build_tunnel_endtile = 0;
   571 
   477 
   572 	if (p1 != 0x200 && !ValParamRailtype(p1)) return CMD_ERROR;
   478 	if (p1 != 0x200 && !ValParamRailtype(p1)) return CMD_ERROR;
   573 
   479 
   574 	_build_tunnel_railtype = GB(p1, 0, 8);
   480 	start_tile = TileVirtXY(x, y);
   575 	_build_tunnel_bh       = GB(p1, 8, 8);
   481 	start_tileh = GetTileSlope(start_tile, &start_z);
   576 
   482 
   577 	_build_tunnel_endtile = 0;
   483 	switch (start_tileh) {
   578 	excavated_tile = 0;
   484 		case  3: direction = DIAGDIR_SW; break;
   579 
   485 		case  6: direction = DIAGDIR_SE; break;
   580 	FindLandscapeHeight(&tiorg, x, y);
   486 		case  9: direction = DIAGDIR_NW; break;
   581 
   487 		case 12: direction = DIAGDIR_NE; break;
   582 	if (!EnsureNoVehicle(tiorg.tile))
   488 		default: return_cmd_error(STR_500B_SITE_UNSUITABLE_FOR_TUNNEL);
   583 		return CMD_ERROR;
   489 	}
   584 
   490 
   585 	if (!(direction=0, tiorg.tileh == 12) &&
   491 	ret = DoCommandByTile(start_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   586 			!(direction++, tiorg.tileh ==  6) &&
   492 	if (CmdFailed(ret)) return ret;
   587 			!(direction++, tiorg.tileh ==  3) &&
   493 	cost = _price.build_tunnel + ret;
   588 			!(direction++, tiorg.tileh ==  9)) {
   494 
   589 		return_cmd_error(STR_500B_SITE_UNSUITABLE_FOR_TUNNEL);
   495 	delta = TileOffsByDir(direction);
   590 	}
   496 	end_tile = start_tile;
   591 
   497 	for (;;) {
   592 	z = tiorg.z;
   498 		end_tile += delta;
   593 	do {
   499 		end_tileh = GetTileSlope(end_tile, &end_z);
   594 		x += _build_tunnel_coord_mod[direction];
   500 
   595 		y += _build_tunnel_coord_mod[direction+1];
   501 		if (start_z == end_z) break;
   596 		FindLandscapeHeight(&ti, x, y);
   502 
   597 	} while (z != ti.z);
   503 		if (!_cheats.crossing_tunnels.value && !CheckTunnelInWay(end_tile, start_z)) {
   598 	_build_tunnel_endtile = ti.tile;
   504 			return CMD_ERROR;
   599 
   505 		}
   600 
   506 
   601 	if (!EnsureNoVehicle(ti.tile)) return CMD_ERROR;
   507 		cost += _price.build_tunnel;
   602 
   508 		cost += cost >> 3;
   603 	if (ti.tileh != _build_tunnel_tileh[direction]) {
   509 		if (cost >= 400000000) cost = 400000000;
   604 		if (CmdFailed(DoCommandByTile(ti.tile, ti.tileh & ~_build_tunnel_tileh[direction], 0, flags, CMD_TERRAFORM_LAND)))
   510 	}
   605 			return_cmd_error(STR_5005_UNABLE_TO_EXCAVATE_LAND);
   511 
   606 		excavated_tile = 1;
   512 	// if the command fails from here on we want the end tile to be highlighted
   607 	}
   513 	_build_tunnel_endtile = end_tile;
   608 
   514 
   609 	return DoBuildTunnel(x, y, tiorg.x, tiorg.y, flags, excavated_tile);
   515 	// slope of end tile must be complementary to the slope of the start tile
       
   516 	if (end_tileh != (15 ^ start_tileh)) {
       
   517 		ret = DoCommandByTile(end_tile, end_tileh & start_tileh, 0, flags, CMD_TERRAFORM_LAND);
       
   518 		if (CmdFailed(ret)) return_cmd_error(STR_5005_UNABLE_TO_EXCAVATE_LAND);
       
   519 	} else {
       
   520 		ret = DoCommandByTile(end_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
       
   521 		if (CmdFailed(ret)) return ret;
       
   522 		cost += ret;
       
   523 	}
       
   524 	cost += _price.build_tunnel;
       
   525 
       
   526 	if (flags & DC_EXEC) {
       
   527 		SetTileType(start_tile, MP_TUNNELBRIDGE);
       
   528 		SetTileOwner(start_tile, _current_player);
       
   529 		_m[start_tile].m3 = GB(p1, 0, 4); // rail type (if any)
       
   530 		_m[start_tile].m5 = (GB(p1, 9, 1) << 2) | direction; // transport type and entrance direction
       
   531 
       
   532 		SetTileType(end_tile, MP_TUNNELBRIDGE);
       
   533 		SetTileOwner(end_tile, _current_player);
       
   534 		_m[end_tile].m3 = GB(p1, 0, 4); // rail type (if any)
       
   535 		_m[end_tile].m5 = (GB(p1, 9, 1) << 2) | (direction ^ 2); // transport type and entrance direction
       
   536 
       
   537 		if (GB(p1, 9, 1) == 0) UpdateSignalsOnSegment(start_tile, direction << 1);
       
   538 	}
       
   539 
       
   540 	return cost;
   610 }
   541 }
   611 
   542 
   612 TileIndex CheckTunnelBusy(TileIndex tile, uint *length)
   543 TileIndex CheckTunnelBusy(TileIndex tile, uint *length)
   613 {
   544 {
   614 	uint z = GetTileZ(tile);
   545 	uint z = GetTileZ(tile);