diff --git a/docs/landscape.html b/docs/landscape.html --- a/docs/landscape.html +++ b/docs/landscape.html @@ -106,6 +106,7 @@ @@ -816,8 +818,6 @@ Note: the actually displayed set of trees depends on both type and number of trees -
  • m4 bits 7..5: type of hedge on the SW border of the tile (1 through 6, or 0=none)
  • -
  • m4 bits 4..2: type of hedge on the SE border of the tile (1 through 6, or 0=none)
  • m5 bits 7..6: number of trees minus one
  • m5 bits 2..0: growth status: diff --git a/docs/landscape_grid.html b/docs/landscape_grid.html --- a/docs/landscape_grid.html +++ b/docs/landscape_grid.html @@ -68,10 +68,10 @@ the array so you can quickly see what is - + - + @@ -79,10 +79,10 @@ the array so you can quickly see what is - + - + @@ -172,7 +172,7 @@ the array so you can quickly see what is - + diff --git a/src/clear_cmd.cpp b/src/clear_cmd.cpp --- a/src/clear_cmd.cpp +++ b/src/clear_cmd.cpp @@ -61,22 +61,44 @@ void DrawHillyLandTile(const TileInfo *t } } -void DrawClearLandFence(const TileInfo *ti) +static void DrawClearLandFence(const TileInfo *ti) { + /* combine fences into one sprite object */ + StartSpriteCombine(); + + int maxz = GetSlopeMaxPixelZ(ti->tileh); + + bool fence_nw = GetFenceNW(ti->tile) != 0; + if (fence_nw) { + int z = GetSlopePixelZInCorner(ti->tileh, CORNER_W); + SpriteID sprite = _clear_land_fence_sprites[GetFenceNW(ti->tile) - 1] + _fence_mod_by_tileh_nw[ti->tileh]; + AddSortableSpriteToDraw(sprite, PAL_NONE, ti->x, ti->y - 15, 16, 31, maxz - z + 4, ti->z + z, false, 0, 15, -z); + } + + bool fence_ne = GetFenceNE(ti->tile) != 0; + if (fence_ne) { + int z = GetSlopePixelZInCorner(ti->tileh, CORNER_E); + SpriteID sprite = _clear_land_fence_sprites[GetFenceNE(ti->tile) - 1] + _fence_mod_by_tileh_ne[ti->tileh]; + AddSortableSpriteToDraw(sprite, PAL_NONE, ti->x - 15, ti->y, 31, 16, maxz - z + 4, ti->z + z, false, 15, 0, -z); + } + bool fence_sw = GetFenceSW(ti->tile) != 0; bool fence_se = GetFenceSE(ti->tile) != 0; - if (!fence_sw && !fence_se) return; - - int z = GetSlopePixelZInCorner(ti->tileh, CORNER_S); + if (fence_sw || fence_se) { + int z = GetSlopePixelZInCorner(ti->tileh, CORNER_S); - if (fence_sw) { - DrawGroundSpriteAt(_clear_land_fence_sprites[GetFenceSW(ti->tile) - 1] + _fence_mod_by_tileh_sw[ti->tileh], PAL_NONE, 0, 0, z); - } + if (fence_sw) { + SpriteID sprite = _clear_land_fence_sprites[GetFenceSW(ti->tile) - 1] + _fence_mod_by_tileh_sw[ti->tileh]; + AddSortableSpriteToDraw(sprite, PAL_NONE, ti->x, ti->y, 16, 16, maxz - z + 4, ti->z + z, false, 0, 0, -z); + } - if (fence_se) { - DrawGroundSpriteAt(_clear_land_fence_sprites[GetFenceSE(ti->tile) - 1] + _fence_mod_by_tileh_se[ti->tileh], PAL_NONE, 0, 0, z); + if (fence_se) { + SpriteID sprite = _clear_land_fence_sprites[GetFenceSE(ti->tile) - 1] + _fence_mod_by_tileh_se[ti->tileh]; + AddSortableSpriteToDraw(sprite, PAL_NONE, ti->x, ti->y, 16, 16, maxz - z + 4, ti->z + z, false, 0, 0, -z); + } } + EndSpriteCombine(); } static void DrawTile_Clear(TileInfo *ti) @@ -96,6 +118,7 @@ static void DrawTile_Clear(TileInfo *ti) case CLEAR_FIELDS: DrawGroundSprite(_clear_land_sprites_farmland[GetFieldType(ti->tile)] + SlopeToSpriteOffset(ti->tileh), PAL_NONE); + DrawClearLandFence(ti); break; case CLEAR_SNOW: @@ -104,7 +127,6 @@ static void DrawTile_Clear(TileInfo *ti) break; } - DrawClearLandFence(ti); DrawBridgeMiddle(ti); } @@ -121,35 +143,33 @@ static Foundation GetFoundation_Clear(Ti return FOUNDATION_NONE; } -void TileLoopClearHelper(TileIndex tile) +static void UpdateFences(TileIndex tile) { - bool self = (IsTileType(tile, MP_CLEAR) && IsClearGround(tile, CLEAR_FIELDS)); + assert(IsTileType(tile, MP_CLEAR) && IsClearGround(tile, CLEAR_FIELDS)); bool dirty = false; bool neighbour = (IsTileType(TILE_ADDXY(tile, 1, 0), MP_CLEAR) && IsClearGround(TILE_ADDXY(tile, 1, 0), CLEAR_FIELDS)); - if (GetFenceSW(tile) == 0) { - if (self != neighbour) { - SetFenceSW(tile, 3); - dirty = true; - } - } else { - if (self == 0 && neighbour == 0) { - SetFenceSW(tile, 0); - dirty = true; - } + if (!neighbour && GetFenceSW(tile) == 0) { + SetFenceSW(tile, 3); + dirty = true; } neighbour = (IsTileType(TILE_ADDXY(tile, 0, 1), MP_CLEAR) && IsClearGround(TILE_ADDXY(tile, 0, 1), CLEAR_FIELDS)); - if (GetFenceSE(tile) == 0) { - if (self != neighbour) { - SetFenceSE(tile, 3); - dirty = true; - } - } else { - if (self == 0 && neighbour == 0) { - SetFenceSE(tile, 0); - dirty = true; - } + if (!neighbour && GetFenceSE(tile) == 0) { + SetFenceSE(tile, 3); + dirty = true; + } + + neighbour = (IsTileType(TILE_ADDXY(tile, -1, 0), MP_CLEAR) && IsClearGround(TILE_ADDXY(tile, -1, 0), CLEAR_FIELDS)); + if (!neighbour && GetFenceNE(tile) == 0) { + SetFenceNE(tile, 3); + dirty = true; + } + + neighbour = (IsTileType(TILE_ADDXY(tile, 0, -1), MP_CLEAR) && IsClearGround(TILE_ADDXY(tile, 0, -1), CLEAR_FIELDS)); + if (!neighbour && GetFenceNW(tile) == 0) { + SetFenceNW(tile, 3); + dirty = true; } if (dirty) MarkTileDirtyByTile(tile); @@ -239,7 +259,6 @@ static void TileLoop_Clear(TileIndex til return; } } - TileLoopClearHelper(tile); AmbientSoundEffectCallback(tile); switch (_settings_game.game_creation.landscape) { @@ -264,8 +283,8 @@ static void TileLoop_Clear(TileIndex til } break; - case CLEAR_FIELDS: { - uint field_type; + case CLEAR_FIELDS: + UpdateFences(tile); if (_game_mode == GM_EDITOR) return; @@ -280,12 +299,11 @@ static void TileLoop_Clear(TileIndex til /* This farmfield is no longer farmfield, so make it grass again */ MakeClear(tile, CLEAR_GRASS, 2); } else { - field_type = GetFieldType(tile); + uint field_type = GetFieldType(tile); field_type = (field_type < 8) ? field_type + 1 : 0; SetFieldType(tile, field_type); } break; - } default: return; diff --git a/src/clear_func.h b/src/clear_func.h --- a/src/clear_func.h +++ b/src/clear_func.h @@ -16,7 +16,5 @@ void DrawHillyLandTile(const TileInfo *ti); void DrawClearLandTile(const TileInfo *ti, byte set); -void DrawClearLandFence(const TileInfo *ti); -void TileLoopClearHelper(TileIndex tile); #endif /* CLEAR_FUNC_H */ diff --git a/src/clear_map.h b/src/clear_map.h --- a/src/clear_map.h +++ b/src/clear_map.h @@ -216,12 +216,12 @@ static inline void SetIndustryIndexOfFie /** * Is there a fence at the south eastern border? * @param t the tile to check for fences - * @pre IsTileType(t, MP_CLEAR) || IsTileType(t, MP_TREES) + * @pre IsClearGround(t, CLEAR_FIELDS) * @return 0 if there is no fence, otherwise the fence type */ static inline uint GetFenceSE(TileIndex t) { - assert(IsTileType(t, MP_CLEAR) || IsTileType(t, MP_TREES)); + assert(IsClearGround(t, CLEAR_FIELDS)); return GB(_m[t].m4, 2, 3); } @@ -230,23 +230,23 @@ static inline uint GetFenceSE(TileIndex * eastern border. * @param t the tile to check for fences * @param h 0 if there is no fence, otherwise the fence type - * @pre IsTileType(t, MP_CLEAR) || IsTileType(t, MP_TREES) + * @pre IsClearGround(t, CLEAR_FIELDS) */ static inline void SetFenceSE(TileIndex t, uint h) { - assert(IsTileType(t, MP_CLEAR) || IsTileType(t, MP_TREES)); // XXX incomplete + assert(IsClearGround(t, CLEAR_FIELDS)); SB(_m[t].m4, 2, 3, h); } /** * Is there a fence at the south western border? * @param t the tile to check for fences - * @pre IsTileType(t, MP_CLEAR) || IsTileType(t, MP_TREES) + * @pre IsClearGround(t, CLEAR_FIELDS) * @return 0 if there is no fence, otherwise the fence type */ static inline uint GetFenceSW(TileIndex t) { - assert(IsTileType(t, MP_CLEAR) || IsTileType(t, MP_TREES)); + assert(IsClearGround(t, CLEAR_FIELDS)); return GB(_m[t].m4, 5, 3); } @@ -255,14 +255,64 @@ static inline uint GetFenceSW(TileIndex * western border. * @param t the tile to check for fences * @param h 0 if there is no fence, otherwise the fence type - * @pre IsTileType(t, MP_CLEAR) || IsTileType(t, MP_TREES) + * @pre IsClearGround(t, CLEAR_FIELDS) */ static inline void SetFenceSW(TileIndex t, uint h) { - assert(IsTileType(t, MP_CLEAR) || IsTileType(t, MP_TREES)); // XXX incomplete + assert(IsClearGround(t, CLEAR_FIELDS)); SB(_m[t].m4, 5, 3, h); } +/** + * Is there a fence at the north eastern border? + * @param t the tile to check for fences + * @pre IsClearGround(t, CLEAR_FIELDS) + * @return 0 if there is no fence, otherwise the fence type + */ +static inline uint GetFenceNE(TileIndex t) +{ + assert(IsClearGround(t, CLEAR_FIELDS)); + return GB(_m[t].m3, 5, 3); +} + +/** + * Sets the type of fence (and whether there is one) for the north + * eastern border. + * @param t the tile to check for fences + * @param h 0 if there is no fence, otherwise the fence type + * @pre IsClearGround(t, CLEAR_FIELDS) + */ +static inline void SetFenceNE(TileIndex t, uint h) +{ + assert(IsClearGround(t, CLEAR_FIELDS)); + SB(_m[t].m3, 5, 3, h); +} + +/** + * Is there a fence at the north western border? + * @param t the tile to check for fences + * @pre IsClearGround(t, CLEAR_FIELDS) + * @return 0 if there is no fence, otherwise the fence type + */ +static inline uint GetFenceNW(TileIndex t) +{ + assert(IsClearGround(t, CLEAR_FIELDS)); + return GB(_m[t].m6, 2, 3); +} + +/** + * Sets the type of fence (and whether there is one) for the north + * western border. + * @param t the tile to check for fences + * @param h 0 if there is no fence, otherwise the fence type + * @pre IsClearGround(t, CLEAR_FIELDS) + */ +static inline void SetFenceNW(TileIndex t, uint h) +{ + assert(IsClearGround(t, CLEAR_FIELDS)); + SB(_m[t].m6, 2, 3, h); +} + /** * Make a clear tile. diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp --- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -955,20 +955,28 @@ static bool IsBadFarmFieldTile2(TileInde } } -static void SetupFarmFieldFence(TileIndex tile, int size, byte type, Axis direction) +static void SetupFarmFieldFence(TileIndex tile, int size, byte type, Axis direction, bool north) { do { tile = TILE_MASK(tile); - if (IsTileType(tile, MP_CLEAR) || IsTileType(tile, MP_TREES)) { + if (IsTileType(tile, MP_CLEAR) && IsClearGround(tile, CLEAR_FIELDS)) { byte or_ = type; if (or_ == 1 && Chance16(1, 7)) or_ = 2; if (direction == AXIS_X) { - SetFenceSE(tile, or_); + if (north) { + SetFenceNW(tile, or_); + } else { + SetFenceSE(tile, or_); + } } else { - SetFenceSW(tile, or_); + if (north) { + SetFenceNE(tile, or_); + } else { + SetFenceSW(tile, or_); + } } } @@ -1021,10 +1029,10 @@ static void PlantFarmField(TileIndex til type = _plantfarmfield_type[Random() & 0xF]; } - SetupFarmFieldFence(ta.tile - TileDiffXY(1, 0), ta.h, type, AXIS_Y); - SetupFarmFieldFence(ta.tile - TileDiffXY(0, 1), ta.w, type, AXIS_X); - SetupFarmFieldFence(ta.tile + TileDiffXY(ta.w - 1, 0), ta.h, type, AXIS_Y); - SetupFarmFieldFence(ta.tile + TileDiffXY(0, ta.h - 1), ta.w, type, AXIS_X); + SetupFarmFieldFence(ta.tile, ta.h, type, AXIS_Y, true); + SetupFarmFieldFence(ta.tile, ta.w, type, AXIS_X, true); + SetupFarmFieldFence(ta.tile + TileDiffXY(ta.w - 1, 0), ta.h, type, AXIS_Y, false); + SetupFarmFieldFence(ta.tile + TileDiffXY(0, ta.h - 1), ta.w, type, AXIS_X, false); } void PlantRandomFarmField(const Industry *i) diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -1267,10 +1267,6 @@ bool AfterLoadGame() if (IsTileType(t, MP_CLEAR) && IsClearGround(t, CLEAR_FIELDS)) { /* remove fields */ MakeClear(t, CLEAR_GRASS, 3); - } else if (IsTileType(t, MP_CLEAR) || IsTileType(t, MP_TREES)) { - /* remove fences around fields */ - SetFenceSE(t, 0); - SetFenceSW(t, 0); } } @@ -2653,6 +2649,24 @@ bool AfterLoadGame() _settings_game.game_creation.snow_line_height /= TILE_HEIGHT; } + if (IsSavegameVersionBefore(164) && !IsSavegameVersionBefore(32)) { + /* We store 4 fences in the field tiles instead of only SE and SW. */ + for (TileIndex t = 0; t < map_size; t++) { + if (!IsTileType(t, MP_CLEAR) && !IsTileType(t, MP_TREES)) continue; + if (IsTileType(t, MP_CLEAR) && IsClearGround(t, CLEAR_FIELDS)) continue; + uint fence = GB(_m[t].m4, 5, 3); + if (fence != 0 && IsTileType(TILE_ADDXY(t, 1, 0), MP_CLEAR) && IsClearGround(TILE_ADDXY(t, 1, 0), CLEAR_FIELDS)) { + SetFenceNE(TILE_ADDXY(t, 1, 0), fence); + } + fence = GB(_m[t].m4, 2, 3); + if (fence != 0 && IsTileType(TILE_ADDXY(t, 0, 1), MP_CLEAR) && IsClearGround(TILE_ADDXY(t, 0, 1), CLEAR_FIELDS)) { + SetFenceNW(TILE_ADDXY(t, 0, 1), fence); + } + SB(_m[t].m4, 2, 3, 0); + SB(_m[t].m4, 5, 3, 0); + } + } + /* When any NewGRF has been changed the availability of some vehicles might * have been changed too. e->company_avail must be set to 0 in that case * which is done by StartupEngines(). */ diff --git a/src/table/clear_land.h b/src/table/clear_land.h --- a/src/table/clear_land.h +++ b/src/table/clear_land.h @@ -34,6 +34,20 @@ static const byte _fence_mod_by_tileh_se 1, 1, 5, 5, 3, 3, 3, 1, }; +static const byte _fence_mod_by_tileh_ne[32] = { + 0, 0, 0, 0, 4, 4, 4, 4, + 2, 2, 2, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 4, 4, 4, 4, + 2, 2, 2, 2, 0, 0, 0, 0, +}; + +static const byte _fence_mod_by_tileh_nw[32] = { + 1, 5, 1, 5, 1, 5, 1, 5, + 3, 1, 3, 1, 3, 1, 3, 1, + 1, 5, 1, 5, 1, 5, 1, 5, + 3, 1, 3, 1, 3, 1, 3, 1, +}; + static const SpriteID _clear_land_fence_sprites[7] = { SPR_HEDGE_BUSHES, diff --git a/src/tree_cmd.cpp b/src/tree_cmd.cpp --- a/src/tree_cmd.cpp +++ b/src/tree_cmd.cpp @@ -453,8 +453,6 @@ static void DrawTile_Trees(TileInfo *ti) default: DrawGroundSprite(_clear_land_sprites_snow_desert[GetTreeDensity(ti->tile)] + SlopeToSpriteOffset(ti->tileh), PAL_NONE); break; } - DrawClearLandFence(ti); - /* Do not draw trees when the invisible trees setting is set */ if (IsInvisibilitySet(TO_TREES)) return; @@ -630,7 +628,6 @@ static void TileLoop_Trees(TileIndex til } AmbientSoundEffectCallback(tile); - TileLoopClearHelper(tile); uint treeCounter = GetTreeCounter(tile);
    XXXX XXXX OOO~ ~~~~ OOOO OOOO OOOO OOOOOOOX OOOOXXXX OOOO XXXX XXOO XXXX XXXXXXOO OOXXXXOX XXXX OOOO OOOO
    -inherit- -inherit- XXXX XXXX XXXX XXXXOOOX XXXXXXXX XXXX -inherit- -inherit-XXOO OOXXXXOX XXXX OOOO OOOO
    OOO~ ~~~~ OOOO OOOX XXXX XXXX ~~XX XXXXXXXX XXOOOOOO OOOO XXOO OXXX OOOO OOXX OOOO OOOO