src/station_cmd.cpp
branchgamebalance
changeset 9895 7bd07f43b0e3
parent 6527 f584ab6d87f8
child 9903 dc85aaa556ae
equal deleted inserted replaced
9894:70d78ac95d6c 9895:7bd07f43b0e3
   328 	SetDParam(1, st->facilities);
   328 	SetDParam(1, st->facilities);
   329 	UpdateViewportSignPos(&st->sign, pt.x, pt.y, STR_305C_0);
   329 	UpdateViewportSignPos(&st->sign, pt.x, pt.y, STR_305C_0);
   330 }
   330 }
   331 
   331 
   332 // Update the virtual coords needed to draw the station sign for all stations.
   332 // Update the virtual coords needed to draw the station sign for all stations.
   333 void UpdateAllStationVirtCoord(void)
   333 void UpdateAllStationVirtCoord()
   334 {
   334 {
   335 	Station* st;
   335 	Station* st;
   336 
   336 
   337 	FOR_ALL_STATIONS(st) {
   337 	FOR_ALL_STATIONS(st) {
   338 		UpdateStationVirtCoord(st);
   338 		UpdateStationVirtCoord(st);
   447 			}
   447 			}
   448 		}
   448 		}
   449 	}
   449 	}
   450 }
   450 }
   451 
   451 
   452 typedef struct ottd_Rectangle {
   452 struct ottd_Rectangle {
   453 	uint min_x;
   453 	uint min_x;
   454 	uint min_y;
   454 	uint min_y;
   455 	uint max_x;
   455 	uint max_x;
   456 	uint max_y;
   456 	uint max_y;
   457 } ottd_Rectangle;
   457 };
   458 
   458 
   459 static inline void MergePoint(ottd_Rectangle* rect, TileIndex tile)
   459 static inline void MergePoint(ottd_Rectangle* rect, TileIndex tile)
   460 {
   460 {
   461 	uint x = TileX(tile);
   461 	uint x = TileX(tile);
   462 	uint y = TileY(tile);
   462 	uint y = TileY(tile);
   527 	// Adjust in case our station only accepts fewer kinds of goods
   527 	// Adjust in case our station only accepts fewer kinds of goods
   528 	for (uint i = 0; i != NUM_CARGO; i++) {
   528 	for (uint i = 0; i != NUM_CARGO; i++) {
   529 		uint amt = min(accepts[i], 15);
   529 		uint amt = min(accepts[i], 15);
   530 
   530 
   531 		// Make sure the station can accept the goods type.
   531 		// Make sure the station can accept the goods type.
   532 		if ((i != CT_PASSENGERS && !(st->facilities & (byte)~FACIL_BUS_STOP)) ||
   532 		bool is_passengers = IsCargoInClass(i, CC_PASSENGERS);
   533 				(i == CT_PASSENGERS && !(st->facilities & (byte)~FACIL_TRUCK_STOP)))
   533 		if ((!is_passengers && !(st->facilities & (byte)~FACIL_BUS_STOP)) ||
       
   534 				(is_passengers && !(st->facilities & (byte)~FACIL_TRUCK_STOP)))
   534 			amt = 0;
   535 			amt = 0;
   535 
   536 
   536 		SB(st->goods[i].waiting_acceptance, 12, 4, amt);
   537 		SB(st->goods[i].waiting_acceptance, 12, 4, amt);
   537 	}
   538 	}
   538 
   539 
  1399 };
  1400 };
  1400 
  1401 
  1401 // Intercontinental Airport (vlarge) - 4 runways
  1402 // Intercontinental Airport (vlarge) - 4 runways
  1402 static const byte _airport_sections_intercontinental[] = {
  1403 static const byte _airport_sections_intercontinental[] = {
  1403 	102, 120,  89,  89,  89,  89,  89,  89, 118,
  1404 	102, 120,  89,  89,  89,  89,  89,  89, 118,
  1404 	120,  22,  22,  22,  22,  22,  22, 119, 117,
  1405 	120,  23,  23,  23,  23,  23,  23, 119, 117,
  1405 	 87,  54,  87,   8,   8,   8,   8,  51, 117,
  1406 	 87,  54,  87,   8,   8,   8,   8,  51, 117,
  1406 	 87, 162,  87,  85, 116, 116,   8,   9,  10,
  1407 	 87, 162,  87,  85, 116, 116,   8,   9,  10,
  1407 	 87,   8,   8,  11,  31,  11,   8, 160,  32,
  1408 	 87,   8,   8,  11,  31,  11,   8, 160,  32,
  1408 	 32, 160,   8,  11,  27,  11,   8,   8,  10,
  1409 	 32, 160,   8,  11,  27,  11,   8,   8,  10,
  1409 	 87,   8,   8,  11,  30,  11,   8,   8,  10,
  1410 	 87,   8,   8,  11,  30,  11,   8,   8,  10,
  1410 	 87, 142,   8,  11,  29,  11,  10, 163,  10,
  1411 	 87, 142,   8,  11,  29,  11,  10, 163,  10,
  1411 	 87, 164,  87,   8,   8,   8,  10,  37, 117,
  1412 	 87, 164,  87,   8,   8,   8,  10,  37, 117,
  1412 	 87, 120,  89,  89,  89,  89,  89,  89, 119,
  1413 	 87, 120,  89,  89,  89,  89,  89,  89, 119,
  1413 	121,  22,  22,  22,  22,  22,  22, 119,  37
  1414 	121,  23,  23,  23,  23,  23,  23, 119,  37
  1414 };
  1415 };
  1415 
  1416 
  1416 
  1417 
  1417 // Commuter Airfield (small)
  1418 // Commuter Airfield (small)
  1418 static const byte _airport_sections_commuter[] = {
  1419 static const byte _airport_sections_commuter[] = {
  1627 int32 CmdBuildBuoy(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1628 int32 CmdBuildBuoy(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1628 {
  1629 {
  1629 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
  1630 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
  1630 
  1631 
  1631 	if (!IsClearWaterTile(tile) || tile == 0) return_cmd_error(STR_304B_SITE_UNSUITABLE);
  1632 	if (!IsClearWaterTile(tile) || tile == 0) return_cmd_error(STR_304B_SITE_UNSUITABLE);
       
  1633 	if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
  1632 
  1634 
  1633 	/* allocate and initialize new station */
  1635 	/* allocate and initialize new station */
  1634 	Station *st = new Station(tile);
  1636 	Station *st = new Station(tile);
  1635 	if (st == NULL) return CMD_ERROR;
  1637 	if (st == NULL) return CMD_ERROR;
  1636 
  1638 
  1668 /* Checks if any ship is servicing the buoy specified. Returns yes or no */
  1670 /* Checks if any ship is servicing the buoy specified. Returns yes or no */
  1669 static bool CheckShipsOnBuoy(Station *st)
  1671 static bool CheckShipsOnBuoy(Station *st)
  1670 {
  1672 {
  1671 	const Vehicle *v;
  1673 	const Vehicle *v;
  1672 	FOR_ALL_VEHICLES(v) {
  1674 	FOR_ALL_VEHICLES(v) {
  1673 		if (v->type == VEH_Ship) {
  1675 		if (v->type == VEH_SHIP) {
  1674 			const Order *order;
  1676 			const Order *order;
  1675 			FOR_VEHICLE_ORDERS(v, order) {
  1677 			FOR_VEHICLE_ORDERS(v, order) {
  1676 				if (order->type == OT_GOTO_STATION && order->dest == st->index) {
  1678 				if (order->type == OT_GOTO_STATION && order->dest == st->index) {
  1677 					return true;
  1679 					return true;
  1678 				}
  1680 				}
  1746 		default: return_cmd_error(STR_304B_SITE_UNSUITABLE);
  1748 		default: return_cmd_error(STR_304B_SITE_UNSUITABLE);
  1747 	}
  1749 	}
  1748 
  1750 
  1749 	if (!(flags & DC_NO_TOWN_RATING) && !CheckIfAuthorityAllows(tile)) return CMD_ERROR;
  1751 	if (!(flags & DC_NO_TOWN_RATING) && !CheckIfAuthorityAllows(tile)) return CMD_ERROR;
  1750 
  1752 
       
  1753 	if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
       
  1754 
  1751 	cost = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
  1755 	cost = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
  1752 	if (CmdFailed(cost)) return CMD_ERROR;
  1756 	if (CmdFailed(cost)) return CMD_ERROR;
  1753 
  1757 
  1754 	TileIndex tile_cur = tile + TileOffsByDiagDir(direction);
  1758 	TileIndex tile_cur = tile + TileOffsByDiagDir(direction);
  1755 
  1759 
  1756 	if (!IsTileType(tile_cur, MP_WATER) || GetTileSlope(tile_cur, NULL) != SLOPE_FLAT) {
  1760 	if (!IsTileType(tile_cur, MP_WATER) || GetTileSlope(tile_cur, NULL) != SLOPE_FLAT) {
  1757 		return_cmd_error(STR_304B_SITE_UNSUITABLE);
  1761 		return_cmd_error(STR_304B_SITE_UNSUITABLE);
  1758 	}
  1762 	}
       
  1763 
       
  1764 	if (MayHaveBridgeAbove(tile_cur) && IsBridgeAbove(tile_cur)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
  1759 
  1765 
  1760 	cost = DoCommand(tile_cur, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
  1766 	cost = DoCommand(tile_cur, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
  1761 	if (CmdFailed(cost)) return CMD_ERROR;
  1767 	if (CmdFailed(cost)) return CMD_ERROR;
  1762 
  1768 
  1763 	tile_cur += TileOffsByDiagDir(direction);
  1769 	tile_cur += TileOffsByDiagDir(direction);
  2069 }
  2075 }
  2070 
  2076 
  2071 
  2077 
  2072 static void AnimateTile_Station(TileIndex tile)
  2078 static void AnimateTile_Station(TileIndex tile)
  2073 {
  2079 {
  2074 	typedef struct AnimData {
  2080 	struct AnimData {
  2075 		StationGfx from; // first sprite
  2081 		StationGfx from; // first sprite
  2076 		StationGfx to;   // last sprite
  2082 		StationGfx to;   // last sprite
  2077 		byte delay;
  2083 		byte delay;
  2078 	} AnimData;
  2084 	};
  2079 
  2085 
  2080 	static const AnimData data[] = {
  2086 	static const AnimData data[] = {
  2081 		{ GFX_RADAR_LARGE_FIRST,         GFX_RADAR_LARGE_LAST,         3 },
  2087 		{ GFX_RADAR_LARGE_FIRST,         GFX_RADAR_LARGE_LAST,         3 },
  2082 		{ GFX_WINDSACK_FIRST,            GFX_WINDSACK_LAST,            1 },
  2088 		{ GFX_WINDSACK_FIRST,            GFX_WINDSACK_LAST,            1 },
  2083 		{ GFX_RADAR_INTERNATIONAL_FIRST, GFX_RADAR_INTERNATIONAL_LAST, 3 },
  2089 		{ GFX_RADAR_INTERNATIONAL_FIRST, GFX_RADAR_INTERNATIONAL_LAST, 3 },
  2101 
  2107 
  2102 
  2108 
  2103 static void ClickTile_Station(TileIndex tile)
  2109 static void ClickTile_Station(TileIndex tile)
  2104 {
  2110 {
  2105 	if (IsHangar(tile)) {
  2111 	if (IsHangar(tile)) {
  2106 		ShowDepotWindow(tile, VEH_Aircraft);
  2112 		ShowDepotWindow(tile, VEH_AIRCRAFT);
  2107 	} else {
  2113 	} else {
  2108 		ShowStationViewWindow(GetStationIndex(tile));
  2114 		ShowStationViewWindow(GetStationIndex(tile));
  2109 	}
  2115 	}
  2110 }
  2116 }
  2111 
  2117 
  2113 	215, 195, 175, 155, 135, 115, 95, 75, 55, 35, 15, 0
  2119 	215, 195, 175, 155, 135, 115, 95, 75, 55, 35, 15, 0
  2114 };
  2120 };
  2115 
  2121 
  2116 static uint32 VehicleEnter_Station(Vehicle *v, TileIndex tile, int x, int y)
  2122 static uint32 VehicleEnter_Station(Vehicle *v, TileIndex tile, int x, int y)
  2117 {
  2123 {
  2118 	if (v->type == VEH_Train) {
  2124 	if (v->type == VEH_TRAIN) {
  2119 		if (IsRailwayStation(tile) && IsFrontEngine(v) &&
  2125 		if (IsRailwayStation(tile) && IsFrontEngine(v) &&
  2120 				!IsCompatibleTrainStationTile(tile + TileOffsByDiagDir(DirToDiagDir(v->direction)), tile)) {
  2126 				!IsCompatibleTrainStationTile(tile + TileOffsByDiagDir(DirToDiagDir(v->direction)), tile)) {
  2121 			StationID station_id = GetStationIndex(tile);
  2127 			StationID station_id = GetStationIndex(tile);
  2122 
  2128 
  2123 			if ((!(v->current_order.flags & OF_NON_STOP) && !_patches.new_nonstop) ||
  2129 			if ((!(v->current_order.flags & OF_NON_STOP) && !_patches.new_nonstop) ||
  2143 						}
  2149 						}
  2144 					}
  2150 					}
  2145 				}
  2151 				}
  2146 			}
  2152 			}
  2147 		}
  2153 		}
  2148 	} else if (v->type == VEH_Road) {
  2154 	} else if (v->type == VEH_ROAD) {
  2149 		if (v->u.road.state < RVSB_IN_ROAD_STOP && !IsReversingRoadTrackdir((Trackdir)v->u.road.state) && v->u.road.frame == 0) {
  2155 		if (v->u.road.state < RVSB_IN_ROAD_STOP && !IsReversingRoadTrackdir((Trackdir)v->u.road.state) && v->u.road.frame == 0) {
  2150 			if (IsRoadStop(tile)) {
  2156 			if (IsRoadStop(tile)) {
  2151 				/* Attempt to allocate a parking bay in a road stop */
  2157 				/* Attempt to allocate a parking bay in a road stop */
  2152 				RoadStop *rs = GetRoadStopByTile(tile, GetRoadStopType(tile));
  2158 				RoadStop *rs = GetRoadStopByTile(tile, GetRoadStopType(tile));
  2153 
  2159 
  2156 					byte side = ((DirToDiagDir(v->direction) == ReverseDiagDir(GetRoadStopDir(tile))) == (v->u.road.overtaking == 0)) ? 0 : 1;
  2162 					byte side = ((DirToDiagDir(v->direction) == ReverseDiagDir(GetRoadStopDir(tile))) == (v->u.road.overtaking == 0)) ? 0 : 1;
  2157 
  2163 
  2158 					if (!rs->IsFreeBay(side)) return VETSB_CANNOT_ENTER;
  2164 					if (!rs->IsFreeBay(side)) return VETSB_CANNOT_ENTER;
  2159 
  2165 
  2160 					/* Check if the vehicle is stopping at this road stop */
  2166 					/* Check if the vehicle is stopping at this road stop */
  2161 					if (GetRoadStopType(tile) == ((v->cargo_type == CT_PASSENGERS) ? RoadStop::BUS : RoadStop::TRUCK) &&
  2167 					if (GetRoadStopType(tile) == (IsCargoInClass(v->cargo_type, CC_PASSENGERS) ? RoadStop::BUS : RoadStop::TRUCK) &&
  2162 							v->current_order.dest == GetStationIndex(tile)) {
  2168 							v->current_order.dest == GetStationIndex(tile)) {
  2163 						SETBIT(v->u.road.state, RVS_IS_STOPPING);
  2169 						SETBIT(v->u.road.state, RVS_IS_STOPPING);
  2164 						rs->AllocateDriveThroughBay(side);
  2170 						rs->AllocateDriveThroughBay(side);
  2165 					}
  2171 					}
  2166 
  2172 
  2208 	byte_inc_sat(&st->time_since_load);
  2214 	byte_inc_sat(&st->time_since_load);
  2209 	byte_inc_sat(&st->time_since_unload);
  2215 	byte_inc_sat(&st->time_since_unload);
  2210 
  2216 
  2211 	GoodsEntry *ge = st->goods;
  2217 	GoodsEntry *ge = st->goods;
  2212 	do {
  2218 	do {
       
  2219 		/* Slowly increase the rating back to his original level in the case we
       
  2220 		 *  didn't deliver cargo yet to this station. This happens when a bribe
       
  2221 		 *  failed while you didn't moved that cargo yet to a station. */
       
  2222 		if (ge->enroute_from == INVALID_STATION && ge->rating < INITIAL_STATION_RATING)
       
  2223 			ge->rating++;
       
  2224 		/* Only change the rating if we are moving this cargo */
  2213 		if (ge->enroute_from != INVALID_STATION) {
  2225 		if (ge->enroute_from != INVALID_STATION) {
  2214 			byte_inc_sat(&ge->enroute_time);
  2226 			byte_inc_sat(&ge->enroute_time);
  2215 			byte_inc_sat(&ge->days_since_pickup);
  2227 			byte_inc_sat(&ge->days_since_pickup);
  2216 
  2228 
  2217 			int rating = 0;
  2229 			int rating = 0;
  2232 
  2244 
  2233 			if (IsValidPlayer(st->owner) && HASBIT(st->town->statues, st->owner)) rating += 26;
  2245 			if (IsValidPlayer(st->owner) && HASBIT(st->town->statues, st->owner)) rating += 26;
  2234 
  2246 
  2235 			{
  2247 			{
  2236 				byte days = ge->days_since_pickup;
  2248 				byte days = ge->days_since_pickup;
  2237 				if (st->last_vehicle_type == VEH_Ship)
  2249 				if (st->last_vehicle_type == VEH_SHIP)
  2238 							days >>= 2;
  2250 							days >>= 2;
  2239 				(days > 21) ||
  2251 				(days > 21) ||
  2240 				(rating += 25, days > 12) ||
  2252 				(rating += 25, days > 12) ||
  2241 				(rating += 25, days > 6) ||
  2253 				(rating += 25, days > 6) ||
  2242 				(rating += 45, days > 3) ||
  2254 				(rating += 45, days > 3) ||
  2297 	st->delete_ctr = b;
  2309 	st->delete_ctr = b;
  2298 
  2310 
  2299 	if (b == 0) UpdateStationRating(st);
  2311 	if (b == 0) UpdateStationRating(st);
  2300 }
  2312 }
  2301 
  2313 
  2302 void OnTick_Station(void)
  2314 void OnTick_Station()
  2303 {
  2315 {
  2304 	if (_game_mode == GM_EDITOR) return;
  2316 	if (_game_mode == GM_EDITOR) return;
  2305 
  2317 
  2306 	uint i = _station_tick_ctr;
  2318 	uint i = _station_tick_ctr;
  2307 	if (++_station_tick_ctr > GetMaxStationIndex()) _station_tick_ctr = 0;
  2319 	if (++_station_tick_ctr > GetMaxStationIndex()) _station_tick_ctr = 0;
  2310 
  2322 
  2311 	Station *st;
  2323 	Station *st;
  2312 	FOR_ALL_STATIONS(st) StationHandleSmallTick(st);
  2324 	FOR_ALL_STATIONS(st) StationHandleSmallTick(st);
  2313 }
  2325 }
  2314 
  2326 
  2315 void StationMonthlyLoop(void)
  2327 void StationMonthlyLoop()
  2316 {
  2328 {
  2317 }
  2329 }
  2318 
  2330 
  2319 
  2331 
  2320 void ModifyStationRatingAround(TileIndex tile, PlayerID owner, int amount, uint radius)
  2332 void ModifyStationRatingAround(TileIndex tile, PlayerID owner, int amount, uint radius)
  2412 			if (around[i] == NULL) {
  2424 			if (around[i] == NULL) {
  2413 				if (!st->IsBuoy() &&
  2425 				if (!st->IsBuoy() &&
  2414 						(st->town->exclusive_counter == 0 || st->town->exclusivity == st->owner) && // check exclusive transport rights
  2426 						(st->town->exclusive_counter == 0 || st->town->exclusivity == st->owner) && // check exclusive transport rights
  2415 						st->goods[type].rating != 0 &&
  2427 						st->goods[type].rating != 0 &&
  2416 						(!_patches.selectgoods || st->goods[type].last_speed > 0) && // if last_speed is 0, no vehicle has been there.
  2428 						(!_patches.selectgoods || st->goods[type].last_speed > 0) && // if last_speed is 0, no vehicle has been there.
  2417 						((st->facilities & ~FACIL_BUS_STOP)   != 0 || type == CT_PASSENGERS) && // if we have other fac. than a bus stop, or the cargo is passengers
  2429 						((st->facilities & ~FACIL_BUS_STOP)   != 0 || IsCargoInClass(type, CC_PASSENGERS)) && // if we have other fac. than a bus stop, or the cargo is passengers
  2418 						((st->facilities & ~FACIL_TRUCK_STOP) != 0 || type != CT_PASSENGERS)) { // if we have other fac. than a cargo bay or the cargo is not passengers
  2430 						((st->facilities & ~FACIL_TRUCK_STOP) != 0 || !IsCargoInClass(type, CC_PASSENGERS))) { // if we have other fac. than a cargo bay or the cargo is not passengers
  2419 					if (_patches.modified_catchment) {
  2431 					if (_patches.modified_catchment) {
  2420 						// min and max coordinates of the producer relative
  2432 						// min and max coordinates of the producer relative
  2421 						const int x_min_prod = 9;
  2433 						const int x_min_prod = 9;
  2422 						const int x_max_prod = 8 + w_prod;
  2434 						const int x_max_prod = 8 + w_prod;
  2423 						const int y_min_prod = 9;
  2435 						const int y_min_prod = 9;
  2535 	st->train_tile = 0;
  2547 	st->train_tile = 0;
  2536 	st->had_vehicle_of_type = 0;
  2548 	st->had_vehicle_of_type = 0;
  2537 	st->time_since_load = 255;
  2549 	st->time_since_load = 255;
  2538 	st->time_since_unload = 255;
  2550 	st->time_since_unload = 255;
  2539 	st->delete_ctr = 0;
  2551 	st->delete_ctr = 0;
  2540 	st->last_vehicle_type = VEH_Invalid;
  2552 	st->last_vehicle_type = VEH_INVALID;
  2541 	st->facilities = FACIL_AIRPORT | FACIL_DOCK;
  2553 	st->facilities = FACIL_AIRPORT | FACIL_DOCK;
  2542 	st->build_date = _date;
  2554 	st->build_date = _date;
  2543 
  2555 
  2544 	for (uint j = 0; j != NUM_CARGO; j++) {
  2556 	for (uint j = 0; j != NUM_CARGO; j++) {
  2545 		st->goods[j].waiting_acceptance = 0;
  2557 		st->goods[j].waiting_acceptance = 0;
  2546 		st->goods[j].days_since_pickup = 0;
  2558 		st->goods[j].days_since_pickup = 0;
  2547 		st->goods[j].enroute_from = INVALID_STATION;
  2559 		st->goods[j].enroute_from = INVALID_STATION;
  2548 		st->goods[j].enroute_from_xy = INVALID_TILE;
  2560 		st->goods[j].enroute_from_xy = INVALID_TILE;
  2549 		st->goods[j].rating = 175;
  2561 		st->goods[j].rating = INITIAL_STATION_RATING;
  2550 		st->goods[j].last_speed = 0;
  2562 		st->goods[j].last_speed = 0;
  2551 		st->goods[j].last_age = 255;
  2563 		st->goods[j].last_age = 255;
  2552 	}
  2564 	}
  2553 
  2565 
  2554 	UpdateStationVirtCoordDirty(st);
  2566 	UpdateStationVirtCoordDirty(st);
  2641 	}
  2653 	}
  2642 
  2654 
  2643 	return CMD_ERROR;
  2655 	return CMD_ERROR;
  2644 }
  2656 }
  2645 
  2657 
  2646 void InitializeStations(void)
  2658 void InitializeStations()
  2647 {
  2659 {
  2648 	/* Clean the station pool and create 1 block in it */
  2660 	/* Clean the station pool and create 1 block in it */
  2649 	CleanPool(&_Station_pool);
  2661 	CleanPool(&_Station_pool);
  2650 	AddBlockToPool(&_Station_pool);
  2662 	AddBlockToPool(&_Station_pool);
  2651 
  2663 
  2656 	_station_tick_ctr = 0;
  2668 	_station_tick_ctr = 0;
  2657 
  2669 
  2658 }
  2670 }
  2659 
  2671 
  2660 
  2672 
  2661 void AfterLoadStations(void)
  2673 void AfterLoadStations()
  2662 {
  2674 {
  2663 	/* Update the speclists of all stations to point to the currently loaded custom stations. */
  2675 	/* Update the speclists of all stations to point to the currently loaded custom stations. */
  2664 	Station *st;
  2676 	Station *st;
  2665 	FOR_ALL_STATIONS(st) {
  2677 	FOR_ALL_STATIONS(st) {
  2666 		for (uint i = 0; i < st->num_specs; i++) {
  2678 		for (uint i = 0; i < st->num_specs; i++) {
  2789 static void SaveLoad_STNS(Station *st)
  2801 static void SaveLoad_STNS(Station *st)
  2790 {
  2802 {
  2791 	SlObject(st, _station_desc);
  2803 	SlObject(st, _station_desc);
  2792 	for (uint i = 0; i != NUM_CARGO; i++) {
  2804 	for (uint i = 0; i != NUM_CARGO; i++) {
  2793 		SlObject(&st->goods[i], _goods_desc);
  2805 		SlObject(&st->goods[i], _goods_desc);
  2794 
       
  2795 		/* In older versions, enroute_from had 0xFF as INVALID_STATION, is now 0xFFFF */
       
  2796 		if (CheckSavegameVersion(7) && st->goods[i].enroute_from == 0xFF) {
       
  2797 			st->goods[i].enroute_from = INVALID_STATION;
       
  2798 		}
       
  2799 		if (CheckSavegameVersion(44)) {
       
  2800 			/* Store position of the station where the goods come from, so there are no
       
  2801 			 * very high payments when stations get removed. However, if the station
       
  2802 			 * where the goods came from is already removed, the source information is
       
  2803 			 * lost. In that case we set it to the position of this station */
       
  2804 			st->goods[i].enroute_from_xy = IsValidStationID(st->goods[i].enroute_from) ? GetStation(st->goods[i].enroute_from)->xy : st->xy;
       
  2805 		}
       
  2806 	}
  2806 	}
  2807 
  2807 
  2808 	if (st->num_specs != 0) {
  2808 	if (st->num_specs != 0) {
  2809 		/* Allocate speclist memory when loading a game */
  2809 		/* Allocate speclist memory when loading a game */
  2810 		if (st->speclist == NULL) st->speclist = CallocT<StationSpecList>(st->num_specs);
  2810 		if (st->speclist == NULL) st->speclist = CallocT<StationSpecList>(st->num_specs);
  2812 			SlObject(&st->speclist[i], _station_speclist_desc);
  2812 			SlObject(&st->speclist[i], _station_speclist_desc);
  2813 		}
  2813 		}
  2814 	}
  2814 	}
  2815 }
  2815 }
  2816 
  2816 
  2817 static void Save_STNS(void)
  2817 static void Save_STNS()
  2818 {
  2818 {
  2819 	Station *st;
  2819 	Station *st;
  2820 	// Write the stations
  2820 	// Write the stations
  2821 	FOR_ALL_STATIONS(st) {
  2821 	FOR_ALL_STATIONS(st) {
  2822 		SlSetArrayIndex(st->index);
  2822 		SlSetArrayIndex(st->index);
  2823 		SlAutolength((AutolengthProc*)SaveLoad_STNS, st);
  2823 		SlAutolength((AutolengthProc*)SaveLoad_STNS, st);
  2824 	}
  2824 	}
  2825 }
  2825 }
  2826 
  2826 
  2827 static void Load_STNS(void)
  2827 static void Load_STNS()
  2828 {
  2828 {
  2829 	int index;
  2829 	int index;
  2830 	while ((index = SlIterateArray()) != -1) {
  2830 	while ((index = SlIterateArray()) != -1) {
  2831 		Station *st = new (index) Station();
  2831 		Station *st = new (index) Station();
  2832 
  2832 
  2845 
  2845 
  2846 	/* This is to ensure all pointers are within the limits of _stations_size */
  2846 	/* This is to ensure all pointers are within the limits of _stations_size */
  2847 	if (_station_tick_ctr > GetMaxStationIndex()) _station_tick_ctr = 0;
  2847 	if (_station_tick_ctr > GetMaxStationIndex()) _station_tick_ctr = 0;
  2848 }
  2848 }
  2849 
  2849 
  2850 static void Save_ROADSTOP(void)
  2850 static void Save_ROADSTOP()
  2851 {
  2851 {
  2852 	RoadStop *rs;
  2852 	RoadStop *rs;
  2853 
  2853 
  2854 	FOR_ALL_ROADSTOPS(rs) {
  2854 	FOR_ALL_ROADSTOPS(rs) {
  2855 		SlSetArrayIndex(rs->index);
  2855 		SlSetArrayIndex(rs->index);
  2856 		SlObject(rs, _roadstop_desc);
  2856 		SlObject(rs, _roadstop_desc);
  2857 	}
  2857 	}
  2858 }
  2858 }
  2859 
  2859 
  2860 static void Load_ROADSTOP(void)
  2860 static void Load_ROADSTOP()
  2861 {
  2861 {
  2862 	int index;
  2862 	int index;
  2863 
  2863 
  2864 	while ((index = SlIterateArray()) != -1) {
  2864 	while ((index = SlIterateArray()) != -1) {
  2865 		RoadStop *rs = new (index) RoadStop(INVALID_TILE);
  2865 		RoadStop *rs = new (index) RoadStop(INVALID_TILE);