src/tunnelbridge_cmd.cpp
changeset 10207 c291a21b304e
parent 10140 5c9f3aea73a5
child 10208 72c00af5c95d
equal deleted inserted replaced
10206:0050610c0368 10207:c291a21b304e
   220 
   220 
   221 	/* type of bridge */
   221 	/* type of bridge */
   222 	switch (transport_type) {
   222 	switch (transport_type) {
   223 		case TRANSPORT_ROAD:
   223 		case TRANSPORT_ROAD:
   224 			roadtypes = (RoadTypes)GB(p2, 8, 3);
   224 			roadtypes = (RoadTypes)GB(p2, 8, 3);
   225 			if (!AreValidRoadTypes(roadtypes) || !HasRoadTypesAvail(_current_player, roadtypes)) return CMD_ERROR;
   225 			if (!AreValidRoadTypes(roadtypes) || !HasRoadTypesAvail(_current_company, roadtypes)) return CMD_ERROR;
   226 			break;
   226 			break;
   227 
   227 
   228 		case TRANSPORT_RAIL:
   228 		case TRANSPORT_RAIL:
   229 			railtype = (RailType)GB(p2, 8, 7);
   229 			railtype = (RailType)GB(p2, 8, 7);
   230 			if (!ValParamRailtype(railtype)) return CMD_ERROR;
   230 			if (!ValParamRailtype(railtype)) return CMD_ERROR;
   302 		/* Do not replace the bridge with the same bridge type. */
   302 		/* Do not replace the bridge with the same bridge type. */
   303 		if (!(flags & DC_QUERY_COST) && bridge_type == GetBridgeType(tile_start)) {
   303 		if (!(flags & DC_QUERY_COST) && bridge_type == GetBridgeType(tile_start)) {
   304 			return_cmd_error(STR_1007_ALREADY_BUILT);
   304 			return_cmd_error(STR_1007_ALREADY_BUILT);
   305 		}
   305 		}
   306 
   306 
   307 		/* Do not allow replacing another player's bridges. */
   307 		/* Do not allow replacing another company's bridges. */
   308 		if (!IsTileOwner(tile_start, _current_player) && !IsTileOwner(tile_start, OWNER_TOWN)) {
   308 		if (!IsTileOwner(tile_start, _current_company) && !IsTileOwner(tile_start, OWNER_TOWN)) {
   309 			return_cmd_error(STR_1024_AREA_IS_OWNED_BY_ANOTHER);
   309 			return_cmd_error(STR_1024_AREA_IS_OWNED_BY_ANOTHER);
   310 		}
   310 		}
   311 
   311 
   312 		cost.AddCost((bridge_len + 1) * _price.clear_bridge); // The cost of clearing the current bridge.
   312 		cost.AddCost((bridge_len + 1) * _price.clear_bridge); // The cost of clearing the current bridge.
   313 		replace_bridge = true;
   313 		replace_bridge = true;
   316 		/* Do not remove road types when upgrading a bridge */
   316 		/* Do not remove road types when upgrading a bridge */
   317 		roadtypes |= GetRoadTypes(tile_start);
   317 		roadtypes |= GetRoadTypes(tile_start);
   318 	} else {
   318 	} else {
   319 		/* Build a new bridge. */
   319 		/* Build a new bridge. */
   320 
   320 
   321 		bool allow_on_slopes = (!_is_old_ai_player && _settings_game.construction.build_on_slopes && transport_type != TRANSPORT_WATER);
   321 		bool allow_on_slopes = (!_is_old_ai_company && _settings_game.construction.build_on_slopes && transport_type != TRANSPORT_WATER);
   322 
   322 
   323 		/* Try and clear the start landscape */
   323 		/* Try and clear the start landscape */
   324 		ret = DoCommand(tile_start, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   324 		ret = DoCommand(tile_start, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   325 		if (CmdFailed(ret)) return ret;
   325 		if (CmdFailed(ret)) return ret;
   326 		cost = ret;
   326 		cost = ret;
   362 	}
   362 	}
   363 
   363 
   364 	/* do the drill? */
   364 	/* do the drill? */
   365 	if (flags & DC_EXEC) {
   365 	if (flags & DC_EXEC) {
   366 		DiagDirection dir = AxisToDiagDir(direction);
   366 		DiagDirection dir = AxisToDiagDir(direction);
   367 		Owner owner = (replace_bridge && IsTileOwner(tile_start, OWNER_TOWN)) ? OWNER_TOWN : _current_player;
   367 		Owner owner = (replace_bridge && IsTileOwner(tile_start, OWNER_TOWN)) ? OWNER_TOWN : _current_company;
   368 
   368 
   369 		switch (transport_type) {
   369 		switch (transport_type) {
   370 			case TRANSPORT_RAIL:
   370 			case TRANSPORT_RAIL:
   371 				MakeRailBridgeRamp(tile_start, owner, bridge_type, dir,                 railtype);
   371 				MakeRailBridgeRamp(tile_start, owner, bridge_type, dir,                 railtype);
   372 				MakeRailBridgeRamp(tile_end,   owner, bridge_type, ReverseDiagDir(dir), railtype);
   372 				MakeRailBridgeRamp(tile_end,   owner, bridge_type, ReverseDiagDir(dir), railtype);
   441 		}
   441 		}
   442 	}
   442 	}
   443 
   443 
   444 	if (flags & DC_EXEC && transport_type == TRANSPORT_RAIL) {
   444 	if (flags & DC_EXEC && transport_type == TRANSPORT_RAIL) {
   445 		Track track = AxisToTrack(direction);
   445 		Track track = AxisToTrack(direction);
   446 		AddSideToSignalBuffer(tile_start, INVALID_DIAGDIR, _current_player);
   446 		AddSideToSignalBuffer(tile_start, INVALID_DIAGDIR, _current_company);
   447 		YapfNotifyTrackLayoutChange(tile_start, track);
   447 		YapfNotifyTrackLayoutChange(tile_start, track);
   448 	}
   448 	}
   449 
   449 
   450 	/* for human player that builds the bridge he gets a selection to choose from bridges (DC_QUERY_COST)
   450 	/* for human player that builds the bridge he gets a selection to choose from bridges (DC_QUERY_COST)
   451 	 * It's unnecessary to execute this command every time for every bridge. So it is done only
   451 	 * It's unnecessary to execute this command every time for every bridge. So it is done only
   452 	 * and cost is computed in "bridge_gui.c". For AI, Towns this has to be of course calculated
   452 	 * and cost is computed in "bridge_gui.c". For AI, Towns this has to be of course calculated
   453 	 */
   453 	 */
   454 	if (!(flags & DC_QUERY_COST) || (IsValidPlayerID(_current_player) && GetPlayer(_current_player)->is_ai)) {
   454 	if (!(flags & DC_QUERY_COST) || (IsValidCompanyID(_current_company) && GetCompany(_current_company)->is_ai)) {
   455 		bridge_len += 2; // begin and end tiles/ramps
   455 		bridge_len += 2; // begin and end tiles/ramps
   456 
   456 
   457 		if (IsValidPlayerID(_current_player) && !_is_old_ai_player)
   457 		if (IsValidCompanyID(_current_company) && !_is_old_ai_company)
   458 			bridge_len = CalcBridgeLenCostFactor(bridge_len);
   458 			bridge_len = CalcBridgeLenCostFactor(bridge_len);
   459 
   459 
   460 		cost.AddCost((int64)bridge_len * _price.build_bridge * GetBridgeSpec(bridge_type)->price >> 8);
   460 		cost.AddCost((int64)bridge_len * _price.build_bridge * GetBridgeSpec(bridge_type)->price >> 8);
   461 
   461 
   462 		/* Aqueducts are a little more expensive. */
   462 		/* Aqueducts are a little more expensive. */
   489 	_build_tunnel_endtile = 0;
   489 	_build_tunnel_endtile = 0;
   490 	if (transport_type == TRANSPORT_RAIL) {
   490 	if (transport_type == TRANSPORT_RAIL) {
   491 		if (!ValParamRailtype((RailType)p1)) return CMD_ERROR;
   491 		if (!ValParamRailtype((RailType)p1)) return CMD_ERROR;
   492 	} else {
   492 	} else {
   493 		const RoadTypes rts = (RoadTypes)GB(p1, 0, 3);
   493 		const RoadTypes rts = (RoadTypes)GB(p1, 0, 3);
   494 		if (!AreValidRoadTypes(rts) || !HasRoadTypesAvail(_current_player, rts)) return CMD_ERROR;
   494 		if (!AreValidRoadTypes(rts) || !HasRoadTypesAvail(_current_company, rts)) return CMD_ERROR;
   495 	}
   495 	}
   496 
   496 
   497 	start_tileh = GetTileSlope(start_tile, &start_z);
   497 	start_tileh = GetTileSlope(start_tile, &start_z);
   498 	direction = GetInclinedSlopeDirection(start_tileh);
   498 	direction = GetInclinedSlopeDirection(start_tileh);
   499 	if (direction == INVALID_DIAGDIR) return_cmd_error(STR_500B_SITE_UNSUITABLE_FOR_TUNNEL);
   499 	if (direction == INVALID_DIAGDIR) return_cmd_error(STR_500B_SITE_UNSUITABLE_FOR_TUNNEL);
   569 	cost.AddCost(_price.build_tunnel);
   569 	cost.AddCost(_price.build_tunnel);
   570 	cost.AddCost(ret);
   570 	cost.AddCost(ret);
   571 
   571 
   572 	if (flags & DC_EXEC) {
   572 	if (flags & DC_EXEC) {
   573 		if (transport_type == TRANSPORT_RAIL) {
   573 		if (transport_type == TRANSPORT_RAIL) {
   574 			MakeRailTunnel(start_tile, _current_player, direction,                 (RailType)GB(p1, 0, 4));
   574 			MakeRailTunnel(start_tile, _current_company, direction,                 (RailType)GB(p1, 0, 4));
   575 			MakeRailTunnel(end_tile,   _current_player, ReverseDiagDir(direction), (RailType)GB(p1, 0, 4));
   575 			MakeRailTunnel(end_tile,   _current_company, ReverseDiagDir(direction), (RailType)GB(p1, 0, 4));
   576 			AddSideToSignalBuffer(start_tile, INVALID_DIAGDIR, _current_player);
   576 			AddSideToSignalBuffer(start_tile, INVALID_DIAGDIR, _current_company);
   577 			YapfNotifyTrackLayoutChange(start_tile, DiagDirToDiagTrack(direction));
   577 			YapfNotifyTrackLayoutChange(start_tile, DiagDirToDiagTrack(direction));
   578 		} else {
   578 		} else {
   579 			MakeRoadTunnel(start_tile, _current_player, direction,                 (RoadTypes)GB(p1, 0, 3));
   579 			MakeRoadTunnel(start_tile, _current_company, direction,                 (RoadTypes)GB(p1, 0, 3));
   580 			MakeRoadTunnel(end_tile,   _current_player, ReverseDiagDir(direction), (RoadTypes)GB(p1, 0, 3));
   580 			MakeRoadTunnel(end_tile,   _current_company, ReverseDiagDir(direction), (RoadTypes)GB(p1, 0, 3));
   581 		}
   581 		}
   582 	}
   582 	}
   583 
   583 
   584 	return cost;
   584 	return cost;
   585 }
   585 }
   586 
   586 
   587 
   587 
   588 static inline bool CheckAllowRemoveTunnelBridge(TileIndex tile)
   588 static inline bool CheckAllowRemoveTunnelBridge(TileIndex tile)
   589 {
   589 {
   590 	/* Floods can remove anything as well as the scenario editor */
   590 	/* Floods can remove anything as well as the scenario editor */
   591 	if (_current_player == OWNER_WATER || _game_mode == GM_EDITOR) return true;
   591 	if (_current_company == OWNER_WATER || _game_mode == GM_EDITOR) return true;
   592 	/* Obviously if the bridge/tunnel belongs to us, or no-one, we can remove it */
   592 	/* Obviously if the bridge/tunnel belongs to us, or no-one, we can remove it */
   593 	if (CheckTileOwnership(tile) || IsTileOwner(tile, OWNER_NONE)) return true;
   593 	if (CheckTileOwnership(tile) || IsTileOwner(tile, OWNER_NONE)) return true;
   594 	/* Otherwise we can only remove town-owned stuff with extra patch-settings, or cheat */
   594 	/* Otherwise we can only remove town-owned stuff with extra patch-settings, or cheat */
   595 	if (IsTileOwner(tile, OWNER_TOWN) && (_settings_game.construction.extra_dynamite || _cheats.magic_bulldozer.value)) return true;
   595 	if (IsTileOwner(tile, OWNER_TOWN) && (_settings_game.construction.extra_dynamite || _cheats.magic_bulldozer.value)) return true;
   596 	return false;
   596 	return false;
  1293 	DiagDirection dir = GetTunnelBridgeDirection(tile);
  1293 	DiagDirection dir = GetTunnelBridgeDirection(tile);
  1294 	if (side != INVALID_DIAGDIR && side != ReverseDiagDir(dir)) return 0;
  1294 	if (side != INVALID_DIAGDIR && side != ReverseDiagDir(dir)) return 0;
  1295 	return CombineTrackStatus(TrackBitsToTrackdirBits(DiagDirToDiagTrackBits(dir)), TRACKDIR_BIT_NONE);
  1295 	return CombineTrackStatus(TrackBitsToTrackdirBits(DiagDirToDiagTrackBits(dir)), TRACKDIR_BIT_NONE);
  1296 }
  1296 }
  1297 
  1297 
  1298 static void ChangeTileOwner_TunnelBridge(TileIndex tile, PlayerID old_player, PlayerID new_player)
  1298 static void ChangeTileOwner_TunnelBridge(TileIndex tile, Owner old_owner, Owner new_owner)
  1299 {
  1299 {
  1300 	if (!IsTileOwner(tile, old_player)) return;
  1300 	if (!IsTileOwner(tile, old_owner)) return;
  1301 
  1301 
  1302 	if (new_player != PLAYER_SPECTATOR) {
  1302 	if (new_owner != INVALID_OWNER) {
  1303 		SetTileOwner(tile, new_player);
  1303 		SetTileOwner(tile, new_owner);
  1304 	} else {
  1304 	} else {
  1305 		if (CmdFailed(DoCommand(tile, 0, 0, DC_EXEC | DC_BANKRUPT, CMD_LANDSCAPE_CLEAR))) {
  1305 		if (CmdFailed(DoCommand(tile, 0, 0, DC_EXEC | DC_BANKRUPT, CMD_LANDSCAPE_CLEAR))) {
  1306 			/* When clearing the bridge/tunnel failed there are still vehicles on/in
  1306 			/* When clearing the bridge/tunnel failed there are still vehicles on/in
  1307 			 * the bridge/tunnel. As all *our* vehicles are already removed, they
  1307 			 * the bridge/tunnel. As all *our* vehicles are already removed, they
  1308 			 * must be of another owner. Therefore this can't be rail tunnel/bridge.
  1308 			 * must be of another owner. Therefore this can't be rail tunnel/bridge.