diff --git a/docs/landscape.html b/docs/landscape.html index deea8ab206..1cc907f967 100644 --- a/docs/landscape.html +++ b/docs/landscape.html @@ -146,10 +146,11 @@ m5 bits 7 and 6 set: railway depot / checkpoints

  • m1: owner of the depot / checkpoint
  • +
  • m2: For waypoints, index into the array of waypoints.
  • m3 bits 0..3 = track type
  • m3 bit 4 = use custom sprite (valid only for the checkpoint)
  • m3 bit 6 = track on this tile is reserved by pbs
  • -
  • m4 = custom station id
  • +
  • m4 bits 0..3 = ground type, as per m2 bits 0..3 for railway tiles.
  • diff --git a/openttd.c b/openttd.c index 97a918a3c5..e63685382b 100644 --- a/openttd.c +++ b/openttd.c @@ -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 18e0a7481b..7a7bd68c8a 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 05bfb44753..7b3a00b80d 100644 --- a/saveload.c +++ b/saveload.c @@ -29,8 +29,8 @@ #include 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 60b6c87354..53844a6096 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<