summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/landscape.html3
-rw-r--r--openttd.c37
-rw-r--r--rail_cmd.c13
-rw-r--r--saveload.c4
-rw-r--r--waypoint.c68
-rw-r--r--waypoint.h40
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>
diff --git a/openttd.c b/openttd.c
index 97a918a3c..e63685382 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 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 */