int GetClosestSide(IN RECT *rect, IN POINT pt, OUT int * distance) { int sides[] = { LEFT, RIGHT, TOP, BOTTOM }; int side = LEFT; int i; *distance = INT_MAX; for(i = 0; i < 4; i++) { int d = DistanceFromEdge(rect, pt, sides[i]); if(d < *distance) { *distance = d; side = sides[i]; } } return side; }
/** * Converts a given grayscale map to something that fits in OTTD map system * and create a map of that data. * @param img_width the with of the image in pixels/tiles * @param img_height the height of the image in pixels/tiles * @param map the input map */ static void GrayscaleToMapHeights(uint img_width, uint img_height, byte *map) { /* Defines the detail of the aspect ratio (to avoid doubles) */ const uint num_div = 16384; uint width, height; uint row, col; uint row_pad = 0, col_pad = 0; uint img_scale; uint img_row, img_col; TileIndex tile; /* Get map size and calculate scale and padding values */ switch (_settings_game.game_creation.heightmap_rotation) { default: NOT_REACHED(); case HM_COUNTER_CLOCKWISE: width = MapSizeX(); height = MapSizeY(); break; case HM_CLOCKWISE: width = MapSizeY(); height = MapSizeX(); break; } if ((img_width * num_div) / img_height > ((width * num_div) / height)) { /* Image is wider than map - center vertically */ img_scale = (width * num_div) / img_width; row_pad = (1 + height - ((img_height * img_scale) / num_div)) / 2; } else { /* Image is taller than map - center horizontally */ img_scale = (height * num_div) / img_height; col_pad = (1 + width - ((img_width * img_scale) / num_div)) / 2; } if (_settings_game.construction.freeform_edges) { for (uint x = 0; x < MapSizeX(); x++) MakeVoid(TileXY(x, 0)); for (uint y = 0; y < MapSizeY(); y++) MakeVoid(TileXY(0, y)); } /* Form the landscape */ for (row = 0; row < height; row++) { for (col = 0; col < width; col++) { switch (_settings_game.game_creation.heightmap_rotation) { default: NOT_REACHED(); case HM_COUNTER_CLOCKWISE: tile = TileXY(col, row); break; case HM_CLOCKWISE: tile = TileXY(row, col); break; } /* Check if current tile is within the 1-pixel map edge or padding regions */ if ((!_settings_game.construction.freeform_edges && DistanceFromEdge(tile) <= 1) || (row < row_pad) || (row >= (height - row_pad - (_settings_game.construction.freeform_edges ? 0 : 1))) || (col < col_pad) || (col >= (width - col_pad - (_settings_game.construction.freeform_edges ? 0 : 1)))) { SetTileHeight(tile, 0); } else { /* Use nearest neighbor resizing to scale map data. * We rotate the map 45 degrees (counter)clockwise */ img_row = (((row - row_pad) * num_div) / img_scale); switch (_settings_game.game_creation.heightmap_rotation) { default: NOT_REACHED(); case HM_COUNTER_CLOCKWISE: img_col = (((width - 1 - col - col_pad) * num_div) / img_scale); break; case HM_CLOCKWISE: img_col = (((col - col_pad) * num_div) / img_scale); break; } assert(img_row < img_height); assert(img_col < img_width); /* Colour scales from 0 to 255, OpenTTD height scales from 0 to 15 */ SetTileHeight(tile, map[img_row * img_width + img_col] / 16); } /* Only clear the tiles within the map area. */ if (TileX(tile) != MapMaxX() && TileY(tile) != MapMaxY() && (!_settings_game.construction.freeform_edges || (TileX(tile) != 0 && TileY(tile) != 0))) { MakeClear(tile, CLEAR_GRASS, 3); } } } }
static void TileLoop_Clear(TileIndex tile) { /* If the tile is at any edge flood it to prevent maps without water. */ if (_settings_game.construction.freeform_edges && DistanceFromEdge(tile) == 1) { int z; if (IsTileFlat(tile, &z) && z == 0) { DoFloodTile(tile); MarkTileDirtyByTile(tile); return; } } AmbientSoundEffect(tile); switch (_settings_game.game_creation.landscape) { case LT_TROPIC: TileLoopClearDesert(tile); break; case LT_ARCTIC: TileLoopClearAlps(tile); break; } switch (GetClearGround(tile)) { case CLEAR_GRASS: if (GetClearDensity(tile) == 3) return; if (_game_mode != GM_EDITOR) { if (GetClearCounter(tile) < 7) { AddClearCounter(tile, 1); return; } else { SetClearCounter(tile, 0); AddClearDensity(tile, 1); } } else { SetClearGroundDensity(tile, GB(Random(), 0, 8) > 21 ? CLEAR_GRASS : CLEAR_ROUGH, 3); } break; case CLEAR_FIELDS: UpdateFences(tile); if (_game_mode == GM_EDITOR) return; if (GetClearCounter(tile) < 7) { AddClearCounter(tile, 1); return; } else { SetClearCounter(tile, 0); } if (GetIndustryIndexOfField(tile) == INVALID_INDUSTRY && GetFieldType(tile) >= 7) { /* This farmfield is no longer farmfield, so make it grass again */ MakeClear(tile, CLEAR_GRASS, 2); } else { uint field_type = GetFieldType(tile); field_type = (field_type < 8) ? field_type + 1 : 0; SetFieldType(tile, field_type); } break; default: return; } MarkTileDirtyByTile(tile); }