summaryrefslogtreecommitdiff
path: root/station_cmd.c
diff options
context:
space:
mode:
authorcelestar <celestar@openttd.org>2005-01-29 19:41:44 +0000
committercelestar <celestar@openttd.org>2005-01-29 19:41:44 +0000
commit752b3f0dd614217d68f361e2d0b2cc599a37c860 (patch)
treefcefcecfa2ec7dd8e9178d5206788bd62dcf3c53 /station_cmd.c
parent885fd2b15c1ae9a1422f82b8bcdd9d1a287c3aa6 (diff)
downloadopenttd-752b3f0dd614217d68f361e2d0b2cc599a37c860.tar.xz
(svn r1721) -Feature: It is now possible to build multiple road stations (up to 8) on
a single station. Thanks to: Truelight for the saveload code, Darkvater and Hackykid for network testing and Tron for proof-reading 1500 lines of diff.
Diffstat (limited to 'station_cmd.c')
-rw-r--r--station_cmd.c456
1 files changed, 292 insertions, 164 deletions
diff --git a/station_cmd.c b/station_cmd.c
index ebf77d903..d8cc5800b 100644
--- a/station_cmd.c
+++ b/station_cmd.c
@@ -43,14 +43,79 @@ static void MarkStationDirty(Station *st)
}
}
+static void InitializeRoadStop(RoadStop *road_stop, RoadStop *previous, TileIndex tile, uint index)
+{
+ road_stop->xy = tile;
+ road_stop->used = true;
+ road_stop->status = 3; //stop is free
+ road_stop->slot[0] = road_stop->slot[1] = INVALID_SLOT;
+ road_stop->next = NULL;
+ road_stop->prev = previous;
+ road_stop->station = index;
+}
+
+inline int GetRoadStopType(TileIndex tile)
+{
+ return (_map5[tile] < 0x47) ? RS_TRUCK : RS_BUS;
+}
+
+RoadStop * GetPrimaryRoadStop(const Station *st, RoadStopType type)
+{
+ switch (type) {
+ case RS_BUS: return st->bus_stops;
+ case RS_TRUCK: return st->truck_stops;
+ default:
+ NOT_REACHED();
+ }
+
+ return NULL;
+}
+
+RoadStop * GetRoadStopByTile(TileIndex tile, RoadStopType type)
+{
+ const Station *st = GetStation(_map2[tile]);
+ RoadStop *rs;
+
+ for ( rs = GetPrimaryRoadStop(st, type); rs->xy != tile; rs = rs->next)
+ assert(rs->next != NULL);
+
+ return rs;
+}
+
+uint GetNumRoadStops(const Station *st, RoadStopType type)
+{
+ int num = 0;
+ const RoadStop *rs;
+
+ assert(st != NULL);
+ for ( rs = GetPrimaryRoadStop(st, type); rs != NULL; num++, rs = rs->next);
+
+ return num;
+}
+
+RoadStop * GetFirstFreeRoadStop( void )
+{
+ RoadStop *rs = _roadstops;
+ int i = 0;
+
+ for ( i = 0; i < NUM_ROAD_STOPS; i++, rs++) {
+ if (!rs->used) {
+ rs->index = i;
+ return rs;
+ }
+ }
+
+ return NULL;
+}
+
/* Calculate the radius of the station. Basicly it is the biggest
radius that is available within the station */
static byte FindCatchmentRadius(Station *st)
{
byte ret = 0;
- if (st->bus_tile) ret = max(ret, CA_BUS);
- if (st->lorry_tile) ret = max(ret, CA_TRUCK);
+ if (st->bus_stops != NULL) ret = max(ret, CA_BUS);
+ if (st->truck_stops != NULL) ret = max(ret, CA_TRUCK);
if (st->train_tile) ret = max(ret, CA_TRAIN);
if (st->dock_tile) ret = max(ret, CA_DOCK);
@@ -101,7 +166,7 @@ TileIndex GetStationTileForVehicle(const Vehicle *v, const Station *st)
case VEH_Train: return st->train_tile;
case VEH_Aircraft: return st->airport_tile;
case VEH_Ship: return st->dock_tile;
- case VEH_Road: return (v->cargo_type == CT_PASSENGERS) ? st->bus_tile : st->lorry_tile;
+ case VEH_Road: return (v->cargo_type == CT_PASSENGERS) ? st->bus_stops->xy : st->truck_stops->xy;
default:
assert(false);
return 0;
@@ -326,7 +391,8 @@ static void StationInitialize(Station *st, TileIndex tile)
GoodsEntry *ge;
st->xy = tile;
- st->bus_tile = st->lorry_tile = st->airport_tile = st->dock_tile = st->train_tile = 0;
+ st->airport_tile = st->dock_tile = st->train_tile = 0;
+ st->bus_stops = st->truck_stops = NULL;
st->had_vehicle_of_type = 0;
st->time_since_load = 255;
st->time_since_unload = 255;
@@ -352,8 +418,9 @@ static void StationInitialize(Station *st, TileIndex tile)
static void UpdateStationVirtCoord(Station *st)
{
Point pt = RemapCoords2(TileX(st->xy) * 16, TileY(st->xy) * 16);
+
pt.y -= 32;
- if (st->facilities&FACIL_AIRPORT && st->airport_type==AT_OILRIG) pt.y -= 16;
+ if (st->facilities & FACIL_AIRPORT && st->airport_type == AT_OILRIG) pt.y -= 16;
SetDParam(0, st->index);
SetDParam(1, st->facilities);
@@ -498,10 +565,13 @@ void GetAcceptanceAroundTiles(uint *accepts, uint tile, int w, int h, int rad)
static void UpdateStationAcceptance(Station *st, bool show_msg)
{
uint old_acc, new_acc;
- TileIndex span[1+1+2+2+1];
+ TileIndex *span;
+ RoadStop *cur_rs;
int i;
int min_x, min_y, max_x, max_y;
int rad = 4; //Put this to surpress a compiler warning
+ int num = 0;
+ int num_bus, num_truck;
uint accepts[NUM_CARGO];
// Don't update acceptance for a buoy
@@ -511,33 +581,62 @@ static void UpdateStationAcceptance(Station *st, bool show_msg)
/* old accepted goods types */
old_acc = GetAcceptanceMask(st);
+ if (st->train_tile != 0) num += 2;
+ if (st->airport_tile != 0) num += 2;
+ if (st->dock_tile != 0) num++;
+
+ num_bus = GetNumRoadStops(st, RS_BUS);
+ num_truck = GetNumRoadStops(st, RS_TRUCK);
+
+ num += (num_bus + num_truck);
+
+ span = malloc(num * sizeof(*span));
+ if (span == NULL)
+ error("UpdateStationAcceptance: Could not allocate memory");
+
// Put all the tiles that span an area in the table.
- span[3] = span[5] = 0;
- span[0] = st->bus_tile;
- span[1] = st->lorry_tile;
- span[2] = st->train_tile;
if (st->train_tile != 0) {
- span[3] = st->train_tile + TILE_XY(st->trainst_w-1, st->trainst_h-1);
+ *span++ = st->train_tile;
+ *span++ = st->train_tile + TILE_XY(st->trainst_w-1, st->trainst_h-1);
}
- span[4] = st->airport_tile;
+
if (st->airport_tile != 0) {
- span[5] = st->airport_tile + TILE_XY(_airport_size_x[st->airport_type]-1, _airport_size_y[st->airport_type]-1);
+ *span++ = st->airport_tile;
+ *span++ = st->airport_tile + TILE_XY(_airport_size_x[st->airport_type]-1, _airport_size_y[st->airport_type]-1);
+ }
+
+ if (st->dock_tile != 0)
+ *span++ = st->dock_tile;
+
+ cur_rs = st->bus_stops;
+ for (i = 0; i < num_bus; i++) {
+ *span++ = cur_rs->xy;
+ cur_rs = cur_rs->next;
+ }
+
+ cur_rs = st->truck_stops;
+ for (i = 0; i < num_truck; i++) {
+ *span++ = cur_rs->xy;
+ cur_rs = cur_rs->next;
}
- span[6] = st->dock_tile;
// Construct a rectangle from those points
min_x = min_y = 0x7FFFFFFF;
max_x = max_y = 0;
- for(i=0; i!=7; i++) {
- uint tile = span[i];
- if (tile) {
+ for(; num != 0; num--) {
+ TileIndex tile = *(--span);
+ if (tile != 0) { //assume there is no station at (0, 0)
min_x = min(min_x, TileX(tile));
max_x = max(max_x, TileX(tile));
min_y = min(min_y, TileY(tile));
max_y = max(max_y, TileY(tile));
}
}
+
+ free(span);
+ span = NULL;
+
if (_patches.modified_catchment) {
rad = FindCatchmentRadius(st);
} else {
@@ -546,7 +645,7 @@ static void UpdateStationAcceptance(Station *st, bool show_msg)
// And retrieve the acceptance.
if (max_x != 0) {
- GetAcceptanceAroundTiles(accepts, TILE_XY(min_x, min_y), max_x - min_x + 1, max_y-min_y+1,rad);
+ GetAcceptanceAroundTiles(accepts, TILE_XY(min_x, min_y), max_x - min_x + 1, max_y-min_y+1, rad);
} else {
memset(accepts, 0, sizeof(accepts));
}
@@ -1127,10 +1226,10 @@ ResolveStationSpriteGroup(struct SpriteGroup *spritegroup, struct Station *stat)
value = stat->airport_type;
break;
case 0x82:
- value = stat->truck_stop_status;
+ value = stat->truck_stops->status;
break;
case 0x83:
- value = stat->bus_stop_status;
+ value = stat->bus_stops->status;
break;
case 0x86:
value = stat->airport_flags & 0xFFFF;
@@ -1260,16 +1359,47 @@ int32 DoConvertStationRail(uint tile, uint totype, bool exec)
return _price.build_rail >> 1;
}
+void FindRoadStationSpot(bool truck_station, Station *st, RoadStop ***currstop, RoadStop **prev)
+{
+ RoadStop **primary_stop;
+
+ primary_stop = (truck_station) ? &st->truck_stops : &st->bus_stops;
+
+ if (*primary_stop == NULL) {
+ //we have no station of the type yet, so write a "primary station"
+ //(the one at st->foo_stops)
+ *currstop = primary_stop;
+ } else {
+ //there are stops already, so append to the end of the list
+ *prev = *primary_stop;
+ *currstop = &(*primary_stop)->next;
+ while (**currstop != NULL) {
+ *prev = (*prev)->next;
+ *currstop = &(**currstop)->next;
+ }
+ }
+}
+
/* Build a bus station
- * p1 - direction
- * p2 - unused
+ * direction - direction of the stop exit
+ * type - 0 for Bus stops, 1 for truck stops
*/
-int32 CmdBuildBusStation(int x, int y, uint32 flags, uint32 p1, uint32 p2)
+int32 CmdBuildRoadStop(int x, int y, uint32 flags, uint32 direction, uint32 type)
{
+ RoadStop *road_stop;
+ RoadStop **currstop;
+ RoadStop *prev = NULL;
uint tile;
int32 cost;
Station *st;
+ //Bus stops have a _map5 value of 0x47 + direction
+ //Truck stops have 0x43 + direction
+ byte gfxbase = (type) ? 0x43 : 0x47;
+
+ //saveguard the parameters
+ if (direction > 3 || type > 1)
+ return CMD_ERROR;
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
@@ -1278,7 +1408,8 @@ int32 CmdBuildBusStation(int x, int y, uint32 flags, uint32 p1, uint32 p2)
if (!(flags & DC_NO_TOWN_RATING) && !CheckIfAuthorityAllows(tile))
return CMD_ERROR;
- if ((cost=CheckFlatLandBelow(tile, 1, 1, flags, 1 << p1, NULL)) == CMD_ERROR)
+ cost = CheckFlatLandBelow(tile, 1, 1, flags, 1 << direction, NULL);
+ if (cost == CMD_ERROR)
return CMD_ERROR;
st = GetStationAround(tile, 1, 1, -1);
@@ -1291,6 +1422,14 @@ int32 CmdBuildBusStation(int x, int y, uint32 flags, uint32 p1, uint32 p2)
if (st!=NULL && st->facilities) st = NULL;
}
+ //give us a road stop in the list, and check if something went wrong
+ road_stop = GetFirstFreeRoadStop();
+ if (road_stop == NULL)
+ return_cmd_error( (type) ? STR_3008B_TOO_MANY_TRUCK_STOPS : STR_3008A_TOO_MANY_BUS_STOPS);
+
+ if ( st != NULL && (GetNumRoadStops(st, RS_BUS) + GetNumRoadStops(st, RS_TRUCK) >= ROAD_STOP_LIMIT))
+ return_cmd_error( (type) ? STR_3008B_TOO_MANY_TRUCK_STOPS : STR_3008A_TOO_MANY_BUS_STOPS);
+
if (st != NULL) {
if (st->owner != OWNER_NONE && st->owner != _current_player)
return_cmd_error(STR_3009_TOO_CLOSE_TO_ANOTHER_STATION);
@@ -1298,8 +1437,7 @@ int32 CmdBuildBusStation(int x, int y, uint32 flags, uint32 p1, uint32 p2)
if (!CheckStationSpreadOut(st, tile, 1, 1))
return CMD_ERROR;
- if (st->bus_tile != 0)
- return_cmd_error(STR_3044_TOO_CLOSE_TO_ANOTHER_BUS);
+ FindRoadStationSpot(type, st, &currstop, &prev);
} else {
Town *t;
@@ -1309,6 +1447,8 @@ int32 CmdBuildBusStation(int x, int y, uint32 flags, uint32 p1, uint32 p2)
st->town = t = ClosestTownFromTile(tile, (uint)-1);
+ FindRoadStationSpot(type, st, &currstop, &prev);
+
if (_current_player < MAX_PLAYERS && flags&DC_EXEC)
SETBIT(t->have_ratings, _current_player);
@@ -1321,13 +1461,17 @@ int32 CmdBuildBusStation(int x, int y, uint32 flags, uint32 p1, uint32 p2)
StationInitialize(st, tile);
}
- cost += _price.build_bus_station;
+ cost += (type) ? _price.build_truck_station : _price.build_bus_station;
if (flags & DC_EXEC) {
- st->bus_tile = tile;
+ //point to the correct item in the _busstops or _truckstops array
+ *currstop = road_stop;
+
+ //initialize an empty station
+ InitializeRoadStop(road_stop, prev, tile, st->index);
+ (*currstop)->type = type;
if (!st->facilities) st->xy = tile;
- st->facilities |= FACIL_BUS_STOP;
- st->bus_stop_status = 3;
+ st->facilities |= (type) ? FACIL_TRUCK_STOP : FACIL_BUS_STOP;
st->owner = _current_player;
st->build_date = _date;
@@ -1336,7 +1480,7 @@ int32 CmdBuildBusStation(int x, int y, uint32 flags, uint32 p1, uint32 p2)
MP_SETTYPE(MP_STATION) | MP_MAPOWNER_CURRENT |
MP_MAP2 | MP_MAP5 | MP_MAP3LO_CLEAR | MP_MAP3HI_CLEAR,
st->index, /* map2 parameter */
- p1 + 0x47 /* map5 parameter */
+ gfxbase + direction /* map5 parameter */
);
UpdateStationVirtCoordDirty(st);
@@ -1347,143 +1491,60 @@ int32 CmdBuildBusStation(int x, int y, uint32 flags, uint32 p1, uint32 p2)
}
// Remove a bus station
-static int32 RemoveBusStation(Station *st, uint32 flags)
+static int32 RemoveRoadStop(Station *st, uint32 flags, TileIndex tile)
{
- uint tile;
+ RoadStop **primary_stop;
+ RoadStop *cur_stop;
+ bool is_truck = _map5[tile] < 0x47;
if (_current_player != OWNER_WATER && !CheckOwnership(st->owner))
return CMD_ERROR;
- tile = st->bus_tile;
-
- if (!EnsureNoVehicle(tile))
- return CMD_ERROR;
-
- if (flags & DC_EXEC) {
- DoClearSquare(tile);
-
- st->bus_tile = 0;
- st->facilities &= ~FACIL_BUS_STOP;
-
- UpdateStationVirtCoordDirty(st);
- DeleteStationIfEmpty(st);
+ if (is_truck) { //truck stop
+ primary_stop = &st->truck_stops;
+ cur_stop = GetRoadStopByTile(tile, RS_TRUCK);
+ } else {
+ primary_stop = &st->bus_stops;
+ cur_stop = GetRoadStopByTile(tile, RS_BUS);
}
- return _price.remove_bus_station;
-}
-
-
-/* Build a truck station
- * p1 - direction
- * p2 - unused
- */
-int32 CmdBuildTruckStation(int x, int y, uint32 flags, uint32 p1, uint32 p2)
-{
- uint tile;
- int32 cost = 0;
- Station *st;
-
- SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
+ assert(cur_stop != NULL);
- tile = TILE_FROM_XY(x,y);
-
- if (!(flags & DC_NO_TOWN_RATING) && !CheckIfAuthorityAllows(tile))
- return CMD_ERROR;
-
- if ((cost=CheckFlatLandBelow(tile, 1, 1, flags, 1 << p1, NULL)) == CMD_ERROR)
- return CMD_ERROR;
-
- st = GetStationAround(tile, 1, 1, -1);
- if (st == CHECK_STATIONS_ERR)
+ if (!EnsureNoVehicle(tile))
return CMD_ERROR;
- /* Find a station close to us */
- if (st == NULL) {
- st = GetClosestStationFromTile(tile, 8, _current_player);
- if (st!=NULL && st->facilities) st = NULL;
- }
-
- if (st != NULL) {
- if (st->owner != OWNER_NONE && st->owner != _current_player)
- return_cmd_error(STR_3009_TOO_CLOSE_TO_ANOTHER_STATION);
-
- if (!CheckStationSpreadOut(st, tile, 1, 1))
- return CMD_ERROR;
-
- if (st->lorry_tile != 0)
- return_cmd_error(STR_3045_TOO_CLOSE_TO_ANOTHER_TRUCK);
- } else {
- Town *t;
-
- st = AllocateStation();
- if (st == NULL)
- return CMD_ERROR;
-
- st->town = t = ClosestTownFromTile(tile, (uint)-1);
-
- if (_current_player < MAX_PLAYERS && flags&DC_EXEC)
- SETBIT(t->have_ratings, _current_player);
-
- st->sign.width_1 = 0;
-
- if (!GenerateStationName(st, tile, 0))
- return CMD_ERROR;
-
- if (flags & DC_EXEC)
- StationInitialize(st, tile);
- }
-
- cost += _price.build_truck_station;
-
if (flags & DC_EXEC) {
- st->lorry_tile = tile;
- if (!st->facilities) st->xy = tile;
- st->facilities |= FACIL_TRUCK_STOP;
- st->truck_stop_status = 3;
- st->owner = _current_player;
-
- st->build_date = _date;
-
- ModifyTile(tile,
- MP_SETTYPE(MP_STATION) | MP_MAPOWNER_CURRENT |
- MP_MAP2 | MP_MAP3LO_CLEAR | MP_MAP3HI_CLEAR | MP_MAP5,
- st->index, /* map2 parameter */
- p1 + 0x43 /* map5 parameter */
- );
-
- UpdateStationVirtCoordDirty(st);
- UpdateStationAcceptance(st, false);
- InvalidateWindow(WC_STATION_LIST, st->owner);
- }
- return cost;
-}
+ DoClearSquare(tile);
-// Remove a truck station
-static int32 RemoveTruckStation(Station *st, uint32 flags)
-{
- uint tile;
+ cur_stop->used = false;
+ if (cur_stop->prev != NULL) //alter previous stop
+ cur_stop->prev->next = cur_stop->next;
- if (_current_player != OWNER_WATER && !CheckOwnership(st->owner))
- return CMD_ERROR;
+ if (cur_stop->next != NULL) //alter next stop
+ cur_stop->next->prev = cur_stop->prev;
- tile = st->lorry_tile;
+ //we only had one stop left
+ if (cur_stop->next == NULL && cur_stop->prev == NULL) {
- if (!EnsureNoVehicle(tile))
- return CMD_ERROR;
+ //so we remove ALL stops
+ *primary_stop = NULL;
+ st->facilities &= (is_truck) ? ~FACIL_TRUCK_STOP : ~FACIL_BUS_STOP;
- if (flags & DC_EXEC) {
- DoClearSquare(tile);
-
- st->lorry_tile = 0;
- st->facilities &= ~FACIL_TRUCK_STOP;
+ } else if (cur_stop == *primary_stop) {
+ //removed the first stop in the list
+ //need to set the primary element to the next stop
+ *primary_stop = (*primary_stop)->next;
+ }
UpdateStationVirtCoordDirty(st);
DeleteStationIfEmpty(st);
}
- return _price.remove_truck_station;
+ return (is_truck) ? _price.remove_truck_station : _price.remove_bus_station;
}
+
+
// FIXME -- need to move to its corresponding Airport variable
// Country Airfield (small)
static const byte _airport_map5_tiles_country[] = {
@@ -2215,7 +2276,7 @@ static const byte _enter_station_speedtable[12] = {
static uint32 VehicleEnter_Station(Vehicle *v, uint tile, int x, int y)
{
- uint16 station_id;
+ uint16 station_id; //XXX should be stationindex
byte dir;
uint16 spd;
@@ -2252,12 +2313,12 @@ static uint32 VehicleEnter_Station(Vehicle *v, uint tile, int x, int y)
}
} else if (v->type == VEH_Road) {
if (v->u.road.state < 16 && (v->u.road.state&4)==0 && v->u.road.frame==0) {
- Station *st = GetStation(_map2[tile]);
byte m5 = _map5[tile];
byte *b, bb,state;
if (IS_BYTE_INSIDE(m5, 0x43, 0x4B)) {
- b = (m5 >= 0x47) ? &st->bus_stop_status : &st->truck_stop_status;
+ RoadStop *rs = GetRoadStopByTile(tile, GetRoadStopType(tile));
+ b = &rs->status;
bb = *b;
@@ -2275,6 +2336,8 @@ static uint32 VehicleEnter_Station(Vehicle *v, uint tile, int x, int y)
bb &= ~2;
state += 2;
}
+
+ bb |= 0x80;
*b = bb;
v->u.road.state = state;
}
@@ -2625,7 +2688,8 @@ uint MoveGoodsToStation(uint tile, int w, int h, int type, uint amount)
/* several stations around, find the two with the highest rating */
st2 = st1 = NULL;
best_rating = best_rating2 = 0;
- for(i=0; i!=8 && around[i] != 0xFF; i++) {
+
+ for( i = 0; i != 8 && around[i] != 0xFF; i++) {
if (around_ptr[i]->goods[type].rating >= best_rating) {
best_rating2 = best_rating;
st2 = st1;
@@ -2686,8 +2750,8 @@ void BuildOilRig(uint tile)
st->airport_flags = 0;
st->airport_type = AT_OILRIG;
st->xy = tile;
- st->bus_tile = 0;
- st->lorry_tile = 0;
+ st->bus_stops = NULL;
+ st->truck_stops = NULL;
st->airport_tile = tile;
st->dock_tile = tile;
st->train_tile = 0;
@@ -2768,11 +2832,8 @@ static int32 ClearTile_Station(uint tile, byte flags) {
if (m5 < 0x43 || ( m5 >= 83 && m5 <= 114) )
return RemoveAirport(st, flags);
- if (m5 < 0x47)
- return RemoveTruckStation(st, flags);
-
if (m5 < 0x4B)
- return RemoveBusStation(st, flags);
+ return RemoveRoadStop(st, flags, tile);
if (m5 == 0x52)
return RemoveBuoy(st, flags);
@@ -2789,6 +2850,7 @@ void InitializeStations(void)
int i;
Station *s;
+ memset(_roadstops, 0, sizeof(_roadstops));
memset(_stations, 0, sizeof(_stations[0]) * _stations_size);
i = 0;
@@ -2820,14 +2882,27 @@ const TileTypeProcs _tile_type_station_procs = {
GetSlopeTileh_Station, /* get_slope_tileh_proc */
};
+static const byte _roadstop_desc[] = {
+ SLE_VAR(RoadStop,xy, SLE_UINT32),
+ SLE_VAR(RoadStop,used, SLE_UINT8),
+ SLE_VAR(RoadStop,status, SLE_UINT8),
+ SLE_VAR(RoadStop,index, SLE_UINT32),
+ SLE_VAR(RoadStop,station, SLE_UINT16),
+ SLE_VAR(RoadStop,type, SLE_UINT8),
+
+ SLE_REF(RoadStop,next, REF_ROADSTOPS),
+ SLE_REF(RoadStop,prev, REF_ROADSTOPS),
+
+ SLE_ARR(RoadStop,slot, SLE_UINT16, NUM_SLOTS),
+
+ SLE_END()
+};
static const byte _station_desc[] = {
SLE_CONDVAR(Station, xy, SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
SLE_CONDVAR(Station, xy, SLE_UINT32, 6, 255),
- SLE_CONDVAR(Station, bus_tile, SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
- SLE_CONDVAR(Station, bus_tile, SLE_UINT32, 6, 255),
- SLE_CONDVAR(Station, lorry_tile, SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
- SLE_CONDVAR(Station, lorry_tile, SLE_UINT32, 6, 255),
+ SLE_CONDVAR(Station, bus_tile_obsolete, SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
+ SLE_CONDVAR(Station, lorry_tile_obsolete, SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
SLE_CONDVAR(Station, train_tile, SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
SLE_CONDVAR(Station, train_tile, SLE_UINT32, 6, 255),
SLE_CONDVAR(Station, airport_tile, SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
@@ -2850,8 +2925,10 @@ static const byte _station_desc[] = {
SLE_VAR(Station,owner, SLE_UINT8),
SLE_VAR(Station,facilities, SLE_UINT8),
SLE_VAR(Station,airport_type, SLE_UINT8),
- SLE_VAR(Station,truck_stop_status, SLE_UINT8),
- SLE_VAR(Station,bus_stop_status, SLE_UINT8),
+
+ // truck/bus_stop_status was stored here in savegame format 0 - 6
+ SLE_CONDVAR(Station,truck_stop_status_obsolete, SLE_UINT8, 0, 5),
+ SLE_CONDVAR(Station,bus_stop_status_obsolete, SLE_UINT8, 0, 5),
// blocked_months was stored here in savegame format 0 - 4.0
SLE_CONDVAR(Station,blocked_months_obsolete, SLE_UINT8, 0, 4),
@@ -2865,7 +2942,10 @@ static const byte _station_desc[] = {
SLE_CONDVAR(Station,stat_id, SLE_UINT8, 3, 255),
SLE_CONDVAR(Station,build_date, SLE_UINT16, 3, 255),
- // reserve extra space in savegame here. (currently 32 bytes)
+ SLE_CONDREF(Station,bus_stops, REF_ROADSTOPS, 6, 255),
+ SLE_CONDREF(Station,truck_stops, REF_ROADSTOPS, 6, 255),
+
+ // reserve extra space in savegame here. (currently 28 bytes)
SLE_CONDARR(NullStruct,null,SLE_FILE_U8 | SLE_VAR_NULL, 32, 2, 255),
SLE_END()
@@ -2887,8 +2967,9 @@ static const byte _goods_desc[] = {
static void SaveLoad_STNS(Station *st)
{
int i;
+
SlObject(st, _station_desc);
- for(i=0; i!=NUM_CARGO; i++)
+ for (i = 0; i != NUM_CARGO; i++)
SlObject(&st->goods[i], _goods_desc);
}
@@ -2920,6 +3001,32 @@ static void Load_STNS(void)
st->trainst_w = w;
st->trainst_h = h;
}
+
+ if (_sl.full_version < 0x600) {
+ /* Convert old bus and truck tile to new-ones */
+ RoadStop **currstop;
+ RoadStop *prev = NULL;
+ RoadStop *road_stop;
+
+ if (st->bus_tile_obsolete != 0) {
+ road_stop = GetFirstFreeRoadStop();
+ if (road_stop == NULL)
+ error("Station: too many busstations in savegame");
+
+ FindRoadStationSpot(RS_BUS, st, &currstop, &prev);
+ *currstop = road_stop;
+ InitializeRoadStop(road_stop, prev, st->bus_tile_obsolete, st->index);
+ }
+ if (st->lorry_tile_obsolete != 0) {
+ road_stop = GetFirstFreeRoadStop();
+ if (road_stop == NULL)
+ error("Station: too many truckstations in savegame");
+
+ FindRoadStationSpot(RS_TRUCK, st, &currstop, &prev);
+ *currstop = road_stop;
+ InitializeRoadStop(road_stop, prev, st->lorry_tile_obsolete, st->index);
+ }
+ }
}
/* This is to ensure all pointers are within the limits of
@@ -2928,7 +3035,28 @@ static void Load_STNS(void)
_station_tick_ctr = 0;
}
+static void Save_ROADSTOP( void )
+{
+ uint i;
+
+ for (i = 0; i < lengthof(_roadstops); i++) {
+ if (_roadstops[i].used) {
+ SlSetArrayIndex(i);
+ SlObject(&_roadstops[i], _roadstop_desc);
+ }
+ }
+}
+
+static void Load_ROADSTOP( void )
+{
+ int index;
+
+ while ((index = SlIterateArray()) != -1)
+ SlObject(&_roadstops[index], _roadstop_desc);
+}
+
const ChunkHandler _station_chunk_handlers[] = {
- { 'STNS', Save_STNS, Load_STNS, CH_ARRAY | CH_LAST},
+ { 'STNS', Save_STNS, Load_STNS, CH_ARRAY },
+ { 'ROAD', Save_ROADSTOP, Load_ROADSTOP, CH_ARRAY | CH_LAST},
};