diff options
-rw-r--r-- | docs/landscape.html | 15 | ||||
-rw-r--r-- | docs/landscape_grid.html | 6 | ||||
-rw-r--r-- | src/ai/api/ai_tile.cpp | 6 | ||||
-rw-r--r-- | src/clear_cmd.cpp | 8 | ||||
-rw-r--r-- | src/clear_map.h | 68 | ||||
-rw-r--r-- | src/saveload/afterload.cpp | 27 | ||||
-rw-r--r-- | src/saveload/saveload.cpp | 2 | ||||
-rw-r--r-- | src/smallmap_gui.cpp | 2 | ||||
-rw-r--r-- | src/tree_cmd.cpp | 40 | ||||
-rw-r--r-- | src/tree_map.h | 11 |
10 files changed, 147 insertions, 38 deletions
diff --git a/docs/landscape.html b/docs/landscape.html index 97b766b46..280005da8 100644 --- a/docs/landscape.html +++ b/docs/landscape.html @@ -11,12 +11,13 @@ <body> <h3><a name="Landscape">Landscape</a></h3> - <p>Seven attributes (counting "<span style="font-weight: bold;">type_height</span>") hold the informations about a tile.<BR> + <p>Eight attributes (counting "<span style="font-weight: bold;">type_height</span>") hold the informations about a tile.<BR> These attributes are referred to as "<span style="font-weight: bold;">type_height</span>", "<span style="font-weight: bold;">m1</span>", "<span style="font-weight: bold;">m2</span>", "<span style="font-weight: bold;">m3</span>", "<span style="font-weight: bold;">m4</span>", - "<span style="font-weight: bold;">m5</span>" and "<span style="font-weight: bold;">m6</span>".<BR> + "<span style="font-weight: bold;">m5</span>", "<span style="font-weight: bold;">m6</span>" + and "<span style="font-weight: bold;">m7</span>".<BR> The most important value is the class of a tile, stored in the upper 4 bits of the <span style="font-weight: bold;">type_height</span> attribute. The lower 4 bits are used to encode the height and slope data. @@ -80,6 +81,7 @@ <li>m1: <a href="#OwnershipInfo">owner</a> of the tile (normally <tt>10</tt>)</li> <li>m2: see fields</li> <li>m3 bits 3..0: see fields</li> + <li>m3 bit 4: set if the tile is covered with snow</li> <li>m4 bits 7..5: type of hedge on the SW border of the tile (1 through 6, or 0=none)</li> <li>m4 bits 4..2: same as 7..5, but for the SE border</li> <li>m5 bits 7..5: update counter, incremented on every periodic processing for tile types, @@ -722,8 +724,7 @@ <td> <ul> <li>m1: <a href="#OwnershipInfo">owner</a> (normally <tt>10</tt>)</li> - <li>m2 bits 7..6: ground density - <li>m2 bits 5..4: ground + <li>m2 bits 8..6: ground <table> <tr> @@ -745,8 +746,14 @@ <td align=left><tt>3</tt> </td> <td>on shore (density must be 3)</td> </tr> + + <tr> + <td align=left><tt>4</tt> </td> + <td>on snow with rough land underneed</td> + </tr> </table> </li> + <li>m2 bits 5..4: ground density</li> <li>m2 bits 3..0: update counter, incremented on every periodic processing.<br> on wraparound the growth status is updated (or, if it's <tt>3</tt>, a random action is taken)</li> <li>m3 bits 7..0: type of trees: diff --git a/docs/landscape_grid.html b/docs/landscape_grid.html index 604f14669..af62d7823 100644 --- a/docs/landscape_grid.html +++ b/docs/landscape_grid.html @@ -68,7 +68,7 @@ the array so you can quickly see what is used and what is not. <td class="bits">XXXX XXXX</td> <td class="bits"><span class="option">~~~~ ~~~~</span></td> <td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td> - <td class="bits"><span class="free">OOOO OOOO</span></td> + <td class="bits"><span class="free">OOO</span>X <span class="free">OOOO</span></td> <td class="bits">XXXX XX<span class="free">OO</span></td> <td class="bits">XXXX XXXX</td> <td class="bits">XX<span class="free">OO OO</span>XX</td> @@ -79,7 +79,7 @@ the array so you can quickly see what is used and what is not. <td class="bits">-inherit-</td> <td class="bits"><span class="option">~~~~ ~~~~</span></td> <td class="bits">XXXX XXXX XXXX XXXX</td> - <td class="bits"><span class="free">OOOO</span> XXXX</td> + <td class="bits"><span class="free">OOO</span>X XXXX</td> <td class="bits">-inherit-</td> <td class="bits">-inherit-</td> <td class="bits">XX<span class="free">OO OO</span>XX</td> @@ -170,7 +170,7 @@ the array so you can quickly see what is used and what is not. <td class="caption">trees</td> <td class="bits">XXXX XXXX</td> <td class="bits"><span class="option">~~~~ ~~~~</span></td> - <td class="bits"><span class="free">OOOO OOOO</span> XXXX XXXX</td> + <td class="bits"><span class="free">OOOO OOO</span>X XXXX XXXX</td> <td class="bits"><span class="option">~~</span>XX XXXX</td> <td class="bits">XXXX XX<span class="free">OO</span></td> <td class="bits">XX<span class="free">OO O</span>XXX</td> diff --git a/src/ai/api/ai_tile.cpp b/src/ai/api/ai_tile.cpp index a1c2f1c5e..aeaba0b06 100644 --- a/src/ai/api/ai_tile.cpp +++ b/src/ai/api/ai_tile.cpp @@ -112,21 +112,21 @@ { if (!::IsValidTile(tile)) return false; - return (::IsTileType(tile, MP_CLEAR) && ::IsClearGround(tile, CLEAR_ROCKS)); + return (::IsTileType(tile, MP_CLEAR) && ::GetRawClearGround(tile) == ::CLEAR_ROCKS); } /* static */ bool AITile::IsRoughTile(TileIndex tile) { if (!::IsValidTile(tile)) return false; - return (::IsTileType(tile, MP_CLEAR) && ::IsClearGround(tile, CLEAR_ROUGH)); + return (::IsTileType(tile, MP_CLEAR) && ::GetRawClearGround(tile) == ::CLEAR_ROUGH); } /* static */ bool AITile::IsSnowTile(TileIndex tile) { if (!::IsValidTile(tile)) return false; - return (::IsTileType(tile, MP_CLEAR) && ::IsClearGround(tile, CLEAR_SNOW)); + return (::IsTileType(tile, MP_CLEAR) && ::IsSnowTile(tile)); } /* static */ bool AITile::IsDesertTile(TileIndex tile) diff --git a/src/clear_cmd.cpp b/src/clear_cmd.cpp index e3d1e3137..2e157ffcf 100644 --- a/src/clear_cmd.cpp +++ b/src/clear_cmd.cpp @@ -158,11 +158,11 @@ static void TileLoopClearAlps(TileIndex tile) if (k < 0) { /* Below the snow line, do nothing if no snow. */ - if (!IsClearGround(tile, CLEAR_SNOW)) return; + if (!IsSnowTile(tile)) return; } else { /* At or above the snow line, make snow tile if needed. */ - if (!IsClearGround(tile, CLEAR_SNOW)) { - SetClearGroundDensity(tile, CLEAR_SNOW, 0); + if (!IsSnowTile(tile)) { + MakeSnow(tile); MarkTileDirtyByTile(tile); return; } @@ -177,7 +177,7 @@ static void TileLoopClearAlps(TileIndex tile) AddClearDensity(tile, -1); } else { /* Density at the required level. */ - if (k < 0) SetClearGroundDensity(tile, CLEAR_GRASS, 3); + if (k < 0) ClearSnow(tile); } MarkTileDirtyByTile(tile); } diff --git a/src/clear_map.h b/src/clear_map.h index c9a74295e..0177e5f7f 100644 --- a/src/clear_map.h +++ b/src/clear_map.h @@ -29,18 +29,42 @@ enum ClearGround { /** - * Get the type of clear tile. + * Test if a tile is covered with snow. + * @param t the tile to check + * @pre IsTileType(t, MP_CLEAR) + * @return whether the tile is covered with snow. + */ +static inline bool IsSnowTile(TileIndex t) +{ + assert(IsTileType(t, MP_CLEAR)); + return HasBit(_m[t].m3, 4); +} + +/** + * Get the type of clear tile but never return CLEAR_SNOW. * @param t the tile to get the clear ground type of * @pre IsTileType(t, MP_CLEAR) * @return the ground type */ -static inline ClearGround GetClearGround(TileIndex t) +static inline ClearGround GetRawClearGround(TileIndex t) { assert(IsTileType(t, MP_CLEAR)); return (ClearGround)GB(_m[t].m5, 2, 3); } /** + * Get the type of clear tile. + * @param t the tile to get the clear ground type of + * @pre IsTileType(t, MP_CLEAR) + * @return the ground type + */ +static inline ClearGround GetClearGround(TileIndex t) +{ + if (IsSnowTile(t)) return CLEAR_SNOW; + return GetRawClearGround(t); +} + +/** * Set the type of clear tile. * @param t the tile to set the clear ground type of * @param ct the ground type @@ -76,6 +100,18 @@ static inline void AddClearDensity(TileIndex t, int d) _m[t].m5 += d; } +/** + * Set the density of a non-field clear tile. + * @param t the tile to set the density of + * @param d the new density + * @pre IsTileType(t, MP_CLEAR) + */ +static inline void SetClearDensity(TileIndex t, uint d) +{ + assert(IsTileType(t, MP_CLEAR)); + SB(_m[t].m5, 0, 2, d); +} + /** * Get the counter used to advance to the next clear density/field type. @@ -269,4 +305,32 @@ static inline void MakeField(TileIndex t, uint field_type, IndustryID industry) _me[t].m7 = 0; } +/** + * Make a snow tile. + * @param t the tile to make snowy + * @pre GetClearGround(t) != CLEAR_SNOW + */ +static inline void MakeSnow(TileIndex t) +{ + assert(GetClearGround(t) != CLEAR_SNOW); + SetBit(_m[t].m3, 4); + if (GetClearGround(t) == CLEAR_FIELDS) { + SetClearGroundDensity(t, CLEAR_GRASS, 0); + } else { + SetClearDensity(t, 0); + } +} + +/** + * Clear the snow from a tile and return it to it's previous type. + * @param t the tile to clear of snow + * @pre GetClearGround(t) == CLEAR_SNOW + */ +static inline void ClearSnow(TileIndex t) +{ + assert(GetClearGround(t) == CLEAR_SNOW); + ClrBit(_m[t].m3, 4); + SetClearDensity(t, 3); +} + #endif /* CLEAR_MAP_H */ diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 8116b6d17..d5eb046bc 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -120,7 +120,7 @@ void SetWaterClassDependingOnSurroundings(TileIndex t, bool include_invalid_wate case MP_TREES: /* trees on shore */ - has_water |= (GetTreeGround(neighbour) == TREE_GROUND_SHORE); + has_water |= (GB(_m[neighbour].m2, 4, 2) == TREE_GROUND_SHORE); break; default: break; @@ -1437,8 +1437,8 @@ bool AfterLoadGame() if (CheckSavegameVersion(81)) { for (TileIndex t = 0; t < map_size; t++) { if (GetTileType(t) == MP_TREES) { - TreeGround groundType = GetTreeGround(t); - if (groundType != TREE_GROUND_SNOW_DESERT) SetTreeGroundDensity(t, groundType, 3); + TreeGround groundType = (TreeGround)GB(_m[t].m2, 4, 2); + if (groundType != TREE_GROUND_SNOW_DESERT) SB(_m[t].m2, 6, 2, 3); } } } @@ -1976,6 +1976,27 @@ bool AfterLoadGame() } } + /* The bits for the tree ground and tree density have + * been swapped (m2 bits 7..6 and 5..4. */ + if (CheckSavegameVersion(135)) { + for (TileIndex t = 0; t < map_size; t++) { + if (IsTileType(t, MP_CLEAR)) { + if (GetRawClearGround(t) == CLEAR_SNOW) { + SetClearGroundDensity(t, CLEAR_GRASS, GetClearDensity(t)); + SetBit(_m[t].m3, 4); + } else { + ClrBit(_m[t].m3, 4); + } + } + if (IsTileType(t, MP_TREES)) { + uint density = GB(_m[t].m2, 6, 2); + uint ground = GB(_m[t].m2, 4, 2); + uint counter = GB(_m[t].m2, 0, 4); + _m[t].m2 = ground << 6 | density << 4 | counter; + } + } + } + /* Road stops is 'only' updating some caches */ AfterLoadRoadStops(); AfterLoadLabelMaps(); diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index e7e40c72d..ed899e550 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -47,7 +47,7 @@ #include "saveload_internal.h" -extern const uint16 SAVEGAME_VERSION = 134; +extern const uint16 SAVEGAME_VERSION = 135; SavegameType _savegame_type; ///< type of savegame we are loading diff --git a/src/smallmap_gui.cpp b/src/smallmap_gui.cpp index b5ebceab5..5956af7f9 100644 --- a/src/smallmap_gui.cpp +++ b/src/smallmap_gui.cpp @@ -374,7 +374,7 @@ static inline uint32 GetSmallMapVegetationPixels(TileIndex tile) return GetIndustrySpec(Industry::GetByTile(tile)->type)->check_proc == CHECK_FOREST ? MKCOLOUR(0xD0D0D0D0) : MKCOLOUR(0xB5B5B5B5); case MP_TREES: - if (GetTreeGround(tile) == TREE_GROUND_SNOW_DESERT) { + if (GetTreeGround(tile) == TREE_GROUND_SNOW_DESERT || GetTreeGround(tile) == TREE_GROUND_ROUGH_SNOW) { return (_settings_game.game_creation.landscape == LT_ARCTIC) ? MKCOLOUR(0x98575798) : MKCOLOUR(0xC25757C2); } return MKCOLOUR(0x54575754); diff --git a/src/tree_cmd.cpp b/src/tree_cmd.cpp index 2cd9c35dc..1754acf14 100644 --- a/src/tree_cmd.cpp +++ b/src/tree_cmd.cpp @@ -68,7 +68,7 @@ static bool CanPlantTreesOnTile(TileIndex tile, bool allow_desert) return !IsBridgeAbove(tile) && IsCoast(tile) && !IsSlopeWithOneCornerRaised(GetTileSlope(tile, NULL)); case MP_CLEAR: - return !IsBridgeAbove(tile) && !IsClearGround(tile, CLEAR_FIELDS) && !IsClearGround(tile, CLEAR_ROCKS) && + return !IsBridgeAbove(tile) && !IsClearGround(tile, CLEAR_FIELDS) && GetRawClearGround(tile) != CLEAR_ROCKS && (allow_desert || !IsClearGround(tile, CLEAR_DESERT)); default: return false; @@ -101,10 +101,12 @@ static void PlantTreesOnTile(TileIndex tile, TreeType treetype, uint count, uint case MP_CLEAR: switch (GetClearGround(tile)) { - case CLEAR_GRASS: ground = TREE_GROUND_GRASS; density = GetClearDensity(tile); break; - case CLEAR_ROUGH: ground = TREE_GROUND_ROUGH; break; - default: ground = TREE_GROUND_SNOW_DESERT; density = GetClearDensity(tile); break; + case CLEAR_GRASS: ground = TREE_GROUND_GRASS; break; + case CLEAR_ROUGH: ground = TREE_GROUND_ROUGH; break; + case CLEAR_SNOW: ground = GetRawClearGround(tile) == CLEAR_ROUGH ? TREE_GROUND_ROUGH_SNOW : TREE_GROUND_SNOW_DESERT; break; + default: ground = TREE_GROUND_SNOW_DESERT; break; } + if (GetClearGround(tile) != CLEAR_ROUGH) density = GetClearDensity(tile); break; default: NOT_REACHED(); @@ -163,7 +165,7 @@ static void PlaceTree(TileIndex tile, uint32 r) /* Rerandomize ground, if neither snow nor shore */ TreeGround ground = GetTreeGround(tile); - if (ground != TREE_GROUND_SNOW_DESERT && ground != TREE_GROUND_SHORE) { + if (ground != TREE_GROUND_SNOW_DESERT && ground != TREE_GROUND_ROUGH_SNOW && ground != TREE_GROUND_SHORE) { SetTreeGroundDensity(tile, (TreeGround)GB(r, 28, 1), 3); } @@ -469,7 +471,7 @@ static void DrawTile_Trees(TileInfo *ti) uint index = GB(tmp, 0, 2) + (GetTreeType(ti->tile) << 2); /* different tree styles above one of the grounds */ - if (GetTreeGround(ti->tile) == TREE_GROUND_SNOW_DESERT && + if ((GetTreeGround(ti->tile) == TREE_GROUND_SNOW_DESERT || GetTreeGround(ti->tile) == TREE_GROUND_ROUGH_SNOW) && GetTreeDensity(ti->tile) >= 2 && IsInsideMM(index, TREE_SUB_ARCTIC << 2, TREE_RAINFOREST << 2)) { index += 164 - (TREE_SUB_ARCTIC << 2); @@ -599,14 +601,19 @@ static void TileLoopTreesAlps(TileIndex tile) int k = GetTileZ(tile) - GetSnowLine() + TILE_HEIGHT; if (k < 0) { - if (GetTreeGround(tile) != TREE_GROUND_SNOW_DESERT) return; - SetTreeGroundDensity(tile, TREE_GROUND_GRASS, 3); + switch (GetTreeGround(tile)) { + case TREE_GROUND_SNOW_DESERT: SetTreeGroundDensity(tile, TREE_GROUND_GRASS, 3); break; + case TREE_GROUND_ROUGH_SNOW: SetTreeGroundDensity(tile, TREE_GROUND_ROUGH, 3); break; + default: return; + } } else { uint density = min((uint)k / TILE_HEIGHT, 3); - if (GetTreeGround(tile) != TREE_GROUND_SNOW_DESERT || - GetTreeDensity(tile) != density) { - SetTreeGroundDensity(tile, TREE_GROUND_SNOW_DESERT, density); + if (GetTreeGround(tile) != TREE_GROUND_SNOW_DESERT && GetTreeGround(tile) != TREE_GROUND_ROUGH_SNOW) { + TreeGround tg = GetTreeGround(tile) == TREE_GROUND_ROUGH ? TREE_GROUND_ROUGH_SNOW : TREE_GROUND_SNOW_DESERT; + SetTreeGroundDensity(tile, tg, density); + } else if (GetTreeDensity(tile) != density) { + SetTreeGroundDensity(tile, GetTreeGround(tile), density); } else { if (GetTreeDensity(tile) == 3) { uint32 r = Random(); @@ -709,8 +716,17 @@ static void TileLoop_Trees(TileIndex tile) case TREE_GROUND_SHORE: MakeShore(tile); break; case TREE_GROUND_GRASS: MakeClear(tile, CLEAR_GRASS, GetTreeDensity(tile)); break; case TREE_GROUND_ROUGH: MakeClear(tile, CLEAR_ROUGH, 3); break; + case TREE_GROUND_ROUGH_SNOW: + MakeClear(tile, CLEAR_ROUGH, 3); + MakeSnow(tile); + break; default: // snow or desert - MakeClear(tile, _settings_game.game_creation.landscape == LT_TROPIC ? CLEAR_DESERT : CLEAR_SNOW, GetTreeDensity(tile)); + if (_settings_game.game_creation.landscape == LT_TROPIC) { + MakeClear(tile, CLEAR_DESERT, GetTreeDensity(tile)); + } else { + MakeClear(tile, CLEAR_GRASS, GetTreeDensity(tile)); + MakeSnow(tile); + } break; } } diff --git a/src/tree_map.h b/src/tree_map.h index 39cbe9e1f..35bab6177 100644 --- a/src/tree_map.h +++ b/src/tree_map.h @@ -58,6 +58,7 @@ enum TreeGround { TREE_GROUND_ROUGH = 1, ///< some rough tile TREE_GROUND_SNOW_DESERT = 2, ///< a desert or snow tile, depend on landscape TREE_GROUND_SHORE = 3, ///< shore + TREE_GROUND_ROUGH_SNOW = 4, ///< a snow tile that is rough underneed }; @@ -91,7 +92,7 @@ static inline TreeType GetTreeType(TileIndex t) static inline TreeGround GetTreeGround(TileIndex t) { assert(IsTileType(t, MP_TREES)); - return (TreeGround)GB(_m[t].m2, 4, 2); + return (TreeGround)GB(_m[t].m2, 6, 3); } /** @@ -116,7 +117,7 @@ static inline TreeGround GetTreeGround(TileIndex t) static inline uint GetTreeDensity(TileIndex t) { assert(IsTileType(t, MP_TREES)); - return GB(_m[t].m2, 6, 2); + return GB(_m[t].m2, 4, 2); } /** @@ -133,8 +134,8 @@ static inline uint GetTreeDensity(TileIndex t) static inline void SetTreeGroundDensity(TileIndex t, TreeGround g, uint d) { assert(IsTileType(t, MP_TREES)); // XXX incomplete - SB(_m[t].m2, 4, 2, g); - SB(_m[t].m2, 6, 2, d); + SB(_m[t].m2, 4, 2, d); + SB(_m[t].m2, 6, 3, g); } /** @@ -277,7 +278,7 @@ static inline void MakeTree(TileIndex t, TreeType type, uint count, uint growth, { SetTileType(t, MP_TREES); SetTileOwner(t, OWNER_NONE); - _m[t].m2 = density << 6 | ground << 4 | 0; + _m[t].m2 = ground << 6 | density << 4 | 0; _m[t].m3 = type; _m[t].m4 = 0 << 5 | 0 << 2; _m[t].m5 = count << 6 | growth; |