diff options
-rw-r--r-- | docs/landscape.html | 3 | ||||
-rw-r--r-- | openttd.c | 37 | ||||
-rw-r--r-- | rail_cmd.c | 13 | ||||
-rw-r--r-- | saveload.c | 4 | ||||
-rw-r--r-- | waypoint.c | 68 | ||||
-rw-r--r-- | waypoint.h | 40 |
6 files changed, 123 insertions, 42 deletions
diff --git a/docs/landscape.html b/docs/landscape.html index deea8ab20..1cc907f96 100644 --- a/docs/landscape.html +++ b/docs/landscape.html @@ -146,10 +146,11 @@ m5 bits 7 and 6 set: railway depot / checkpoints <br> <br> <li>m1: <a href="#OwnershipInfo">owner</a> of the depot / checkpoint</li> +<li>m2: For waypoints, index into the array of waypoints.</li> <li>m3 bits 0..3 = <a href="#TrackType">track type</a></li> <li>m3 bit 4 = use custom sprite (valid only for the checkpoint)</li> <li>m3 bit 6 = track on this tile is reserved by pbs</li> -<li>m4 = custom station id</li> +<li>m4 bits 0..3 = ground type, as per m2 bits 0..3 for railway tiles.</li> </ul> </td></tr> @@ -1287,6 +1287,43 @@ bool AfterLoadGame(uint version) } } + /* In version 17, ground type is moved from m2 to m4 for depots and + * waypoints to make way for storing the index in m2. The custom graphics + * id which was stored in m4 is now saved as a grf/id reference in the + * waypoint struct. */ + if (version < 0x1100) { + Waypoint *wp; + + FOR_ALL_WAYPOINTS(wp) { + if (wp->xy != 0 && wp->deleted == 0) { + const StationSpec *spec = NULL; + + if (HASBIT(_m[wp->xy].m3, 4)) + spec = GetCustomStation(STAT_CLASS_WAYP, _m[wp->xy].m4 + 1); + + if (spec != NULL) { + wp->stat_id = _m[wp->xy].m4 + 1; + wp->grfid = spec->grfid; + wp->localidx = spec->localidx; + } else { + // No custom graphics set, so set to default. + wp->stat_id = 0; + wp->grfid = 0; + wp->localidx = 0; + } + + // Move ground type bits from m2 to m4. + _m[wp->xy].m4 = GB(_m[wp->xy].m2, 0, 4); + // Store waypoint index in the tile. + _m[wp->xy].m2 = wp->index; + } + } + } else { + /* As of version 17, we recalculate the custom graphic ID of waypoints + * from the GRF ID / station index. */ + UpdateAllWaypointCustomGraphics(); + } + FOR_ALL_PLAYERS(p) p->avail_railtypes = GetPlayerRailtypes(p->index); return true; diff --git a/rail_cmd.c b/rail_cmd.c index 18e0a7481..7a7bd68c8 100644 --- a/rail_cmd.c +++ b/rail_cmd.c @@ -1493,7 +1493,8 @@ static void DrawTile_Track(TileInfo *ti) if (IsRailWaypoint(ti->tile) && HASBIT(_m[ti->tile].m3, 4)) { // look for customization - const StationSpec *stat = GetCustomStation(STAT_CLASS_WAYP, _m[ti->tile].m4 + 1); + byte stat_id = GetWaypointByTile(ti->tile)->stat_id; + const StationSpec *stat = GetCustomStation(STAT_CLASS_WAYP, stat_id); if (stat != NULL) { DrawTileSeqStruct const *seq; @@ -1535,7 +1536,7 @@ static void DrawTile_Track(TileInfo *ti) // adjust ground tile for desert // (don't adjust for arctic depots, because snow in depots looks weird) // type >= 4 means waypoints - if ((_m[ti->tile].m2 & RAIL_MAP2LO_GROUND_MASK) == RAIL_GROUND_ICE_DESERT && (_opt.landscape == LT_DESERT || type >= 4)) { + if ((_m[ti->tile].m4 & RAIL_MAP2LO_GROUND_MASK) == RAIL_GROUND_ICE_DESERT && (_opt.landscape == LT_DESERT || type >= 4)) { if (image != SPR_FLAT_GRASS_TILE) { image += rti->snow_offset; // tile with tracks } else { @@ -1974,7 +1975,7 @@ static void TileLoop_Track(TileIndex tile) byte new_ground; TrackBits rail; - old_ground = GB(_m[tile].m2, 0, 4); + old_ground = _m[tile].m5 & RAIL_TYPE_SPECIAL ? GB(_m[tile].m4, 0, 4) : GB(_m[tile].m2, 0, 4); switch (_opt.landscape) { case LT_HILLY: @@ -2045,7 +2046,11 @@ static void TileLoop_Track(TileIndex tile) modify_me:; /* tile changed? */ if (old_ground != new_ground) { - SB(_m[tile].m2, 0, 4, new_ground); + if (_m[tile].m5 & RAIL_TYPE_SPECIAL) { + SB(_m[tile].m4, 0, 4, new_ground); + } else { + SB(_m[tile].m2, 0, 4, new_ground); + } MarkTileDirtyByTile(tile); } } diff --git a/saveload.c b/saveload.c index 05bfb4475..7b3a00b80 100644 --- a/saveload.c +++ b/saveload.c @@ -29,8 +29,8 @@ #include <setjmp.h> enum { - SAVEGAME_MAJOR_VERSION = 16, - SAVEGAME_MINOR_VERSION = 1, + SAVEGAME_MAJOR_VERSION = 17, + SAVEGAME_MINOR_VERSION = 0, SAVEGAME_LOADABLE_VERSION = (SAVEGAME_MAJOR_VERSION << 8) + SAVEGAME_MINOR_VERSION }; diff --git a/waypoint.c b/waypoint.c index 60b6c8735..53844a609 100644 --- a/waypoint.c +++ b/waypoint.c @@ -63,19 +63,6 @@ Waypoint *AllocateWaypoint(void) return NULL; } -/* Fetch a waypoint by tile */ -Waypoint *GetWaypointByTile(TileIndex tile) -{ - Waypoint *wp; - - FOR_ALL_WAYPOINTS(wp) { - if (wp->xy == tile) - return wp; - } - - return NULL; -} - /* Update the sign for the waypoint */ void UpdateWaypointSign(Waypoint *wp) { @@ -151,6 +138,29 @@ static Waypoint *FindDeletedWaypointCloseTo(TileIndex tile) return best; } +/** + * Update waypoint graphics id against saved GRFID/localidx. + * This is to ensure the chosen graphics are correct if GRF files are changed. + */ +void UpdateAllWaypointCustomGraphics(void) +{ + Waypoint *wp; + + FOR_ALL_WAYPOINTS(wp) { + uint i; + + if (wp->grfid == 0) continue; + + for (i = 0; i < GetNumCustomStations(STAT_CLASS_WAYP); i++) { + const StationSpec *spec = GetCustomStation(STAT_CLASS_WAYP, i); + if (spec != NULL && spec->grfid == wp->grfid && spec->localidx == wp->localidx) { + wp->stat_id = i; + break; + } + } + } +} + /** Convert existing rail to waypoint. Eg build a waypoint station over * piece of rail * @param x,y coordinates where waypoint will be built @@ -198,13 +208,26 @@ int32 CmdBuildTrainWaypoint(int x, int y, uint32 flags, uint32 p1, uint32 p2) } if (flags & DC_EXEC) { + const StationSpec *spec = NULL; bool reserved = PBSTileReserved(tile) != 0; - ModifyTile(tile, MP_MAP5, RAIL_TYPE_WAYPOINT | dir); - if (p1 > 0) { // waypoint type 0 uses default graphics - // custom graphics - _m[tile].m3 |= 16; - _m[tile].m4 = (p1 - 1) & 0xff; + ModifyTile(tile, MP_MAP2 | MP_MAP5, wp->index, RAIL_TYPE_WAYPOINT | dir); + + if (GB(p1, 0, 8) < GetNumCustomStations(STAT_CLASS_WAYP)) + spec = GetCustomStation(STAT_CLASS_WAYP, GB(p1, 0, 8)); + + if (spec != NULL) { + SETBIT(_m[tile].m3, 4); + wp->stat_id = GB(p1, 0, 8); + wp->grfid = spec->grfid; + wp->localidx = spec->localidx; + } else { + // Specified custom graphics do not exist, so use default. + CLRBIT(_m[tile].m3, 4); + wp->stat_id = 0; + wp->grfid = 0; + wp->localidx = 0; } + if (reserved) { PBSReserveTrack(tile, dir); } else { @@ -280,8 +303,8 @@ int32 RemoveTrainWaypoint(TileIndex tile, uint32 flags, bool justremove) if (justremove) { bool reserved = PBSTileReserved(tile) != 0; - ModifyTile(tile, MP_MAP5, 1<<direction); - _m[tile].m3 &= ~16; + ModifyTile(tile, MP_MAP2_CLEAR | MP_MAP5, 1<<direction); + CLRBIT(_m[tile].m3, 4); _m[tile].m4 = 0; if (reserved) { PBSReserveTrack(tile, direction); @@ -446,8 +469,9 @@ static const SaveLoad _waypoint_desc[] = { SLE_VAR(Waypoint, string, SLE_UINT16), SLE_VAR(Waypoint, deleted, SLE_UINT8), - SLE_CONDVAR(Waypoint, build_date, SLE_UINT16, 3, 255), - SLE_CONDVAR(Waypoint, stat_id, SLE_UINT8, 3, 255), + SLE_CONDVAR(Waypoint, build_date, SLE_UINT16, 3, 255), + SLE_CONDVAR(Waypoint, localidx, SLE_UINT8, 3, 255), + SLE_CONDVAR(Waypoint, grfid, SLE_UINT32, 17, 255), SLE_END() }; diff --git a/waypoint.h b/waypoint.h index a9c3432ea..427fd9d79 100644 --- a/waypoint.h +++ b/waypoint.h @@ -6,18 +6,21 @@ #include "pool.h" struct Waypoint { - TileIndex xy; - uint16 index; - - uint16 town_index; - byte town_cn; // The Nth waypoint for this town (consecutive number) - StringID string; // If this is zero, town + town_cn is used for naming - - ViewportSign sign; - uint16 build_date; - byte stat_id; - uint32 grfid; - byte deleted; // this is a delete counter. when it reaches 0, the waypoint struct is deleted. + TileIndex xy; ///< Tile of waypoint + uint16 index; ///< Index of waypoint + + uint16 town_index; ///< Town associated with the waypoint + byte town_cn; ///< The Nth waypoint for this town (consecutive number) + StringID string; ///< If this is zero (i.e. no custom name), town + town_cn is used for naming + + ViewportSign sign; ///< Dimensions of sign (not saved) + uint16 build_date; ///< Date of construction + + byte stat_id; ///< ID of waypoint within the waypoint class (not saved) + uint32 grfid; ///< ID of GRF file + byte localidx; ///< Index of station within GRF file + + byte deleted; ///< Delete counter. If greater than 0 then it is decremented until it reaches 0; the waypoint is then is deleted. }; enum { @@ -56,13 +59,24 @@ static inline bool IsRailWaypoint(TileIndex tile) return (_m[tile].m5 & 0xFC) == 0xC4; } +/** + * Fetch a waypoint by tile + * @param tile Tile of waypoint + * @return Waypoint + */ +static inline Waypoint *GetWaypointByTile(TileIndex tile) +{ + assert(IsTileType(tile, MP_RAILWAY) && IsRailWaypoint(tile)); + return GetWaypoint(_m[tile].m2); +} + int32 RemoveTrainWaypoint(TileIndex tile, uint32 flags, bool justremove); Station *ComposeWaypointStation(TileIndex tile); -Waypoint *GetWaypointByTile(TileIndex tile); void ShowRenameWaypointWindow(const Waypoint *cp); void DrawWaypointSprite(int x, int y, int image, RailType railtype); void UpdateWaypointSign(Waypoint *cp); void FixOldWaypoints(void); void UpdateAllWaypointSigns(void); +void UpdateAllWaypointCustomGraphics(void); #endif /* WAYPOINT_H */ |