src/station_cmd.cpp
branchNewGRF_ports
changeset 6872 1c4a4a609f85
parent 6871 5a9dc001e1ad
child 6877 889301acc299
--- a/src/station_cmd.cpp	Mon Dec 03 23:39:38 2007 +0000
+++ b/src/station_cmd.cpp	Tue Jan 22 21:00:30 2008 +0000
@@ -8,24 +8,15 @@
 #include "bridge_map.h"
 #include "cmd_helper.h"
 #include "debug.h"
-#include "functions.h"
+#include "tile_cmd.h"
 #include "landscape.h"
 #include "station_map.h"
-#include "table/sprites.h"
-#include "table/strings.h"
-#include "map.h"
-#include "tile.h"
 #include "station.h"
-#include "gfx.h"
-#include "window.h"
-#include "viewport.h"
-#include "command.h"
+#include "viewport_func.h"
+#include "command_func.h"
 #include "town.h"
-#include "vehicle.h"
 #include "news.h"
 #include "saveload.h"
-#include "economy.h"
-#include "player.h"
 #include "airport.h"
 #include "sprite.h"
 #include "depot.h"
@@ -36,16 +27,26 @@
 #include "newgrf_callbacks.h"
 #include "newgrf_station.h"
 #include "yapf/yapf.h"
-#include "date.h"
-#include "helpers.hpp"
 #include "misc/autoptr.hpp"
-#include "road.h"
+#include "road_type.h"
+#include "road_internal.h" /* For drawing catenary/checking road removal */
 #include "cargotype.h"
-#include "strings.h"
+#include "variables.h"
 #include "autoslope.h"
 #include "newgrf_fsmports.h"
 #include "transparency.h"
 #include "water.h"
+#include "station_gui.h"
+#include "strings_func.h"
+#include "functions.h"
+#include "window_func.h"
+#include "date_func.h"
+#include "vehicle_func.h"
+#include "string_func.h"
+#include "signal_func.h"
+
+#include "table/sprites.h"
+#include "table/strings.h"
 
 DEFINE_OLD_POOL_GENERIC(Station, Station)
 DEFINE_OLD_POOL_GENERIC(RoadStop, RoadStop)
@@ -724,7 +725,7 @@
 	}
 
 	/* redraw the station view since acceptance changed */
-	InvalidateWindowWidget(WC_STATION_VIEW, st->index, 4);
+	InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_ACCEPTLIST);
 }
 
 static void UpdateStationSignCoord(Station *st)
@@ -768,7 +769,7 @@
  */
 CommandCost CheckFlatLandBelow(TileIndex tile, uint w, uint h, uint flags, uint32 invalid_dirs, StationID* station, const FSMportsSpec *fsmportspec, bool check_clear = true)
 {
-	CommandCost cost;
+	CommandCost cost(EXPENSES_CONSTRUCTION);
 	int allowed_z = -1;
 	byte layout_set = GB(invalid_dirs, 0, 3);
 	byte *b = NULL;
@@ -882,6 +883,15 @@
 		curh = max(TileY(st->train_tile) + curh, TileY(tile) + h) - y;
 		tile = TileXY(x, y);
 	} else {
+		/* do not allow modifying non-uniform stations,
+		 * the uniform-stations code wouldn't handle it well */
+		BEGIN_TILE_LOOP(t, st->trainst_w, st->trainst_h, st->train_tile)
+			if (!st->TileBelongsToRailStation(t)) { // there may be adjoined station
+				_error_message = STR_306D_NONUNIFORM_STATIONS_DISALLOWED;
+				return false;
+			}
+		END_TILE_LOOP(t, st->trainst_w, st->trainst_h, st->train_tile)
+
 		/* check so the orientation is the same */
 		if (GetRailStationAxis(st->train_tile) != axis) {
 			_error_message = STR_306D_NONUNIFORM_STATIONS_DISALLOWED;
@@ -983,11 +993,9 @@
 	int w_org, h_org;
 	CommandCost ret;
 
-	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
-
 	/* Does the authority allow this? */
 	if (!(flags & DC_NO_TOWN_RATING) && !CheckIfAuthorityAllows(tile_org)) return CMD_ERROR;
-	if (!ValParamRailtype(p2 & 0xF)) return CMD_ERROR;
+	if (!ValParamRailtype((RailType)(p2 & 0xF))) return CMD_ERROR;
 
 	/* unpack parameters */
 	Axis axis = Extract<Axis, 0>(p1);
@@ -1016,7 +1024,7 @@
 	 * https://sourceforge.net/tracker/index.php?func=detail&aid=1029064&group_id=103924&atid=636365 */
 	ret = CheckFlatLandBelow(tile_org, w_org, h_org, flags & ~DC_EXEC, 5 << axis, _patches.nonuniform_stations ? &est : NULL);
 	if (CmdFailed(ret)) return ret;
-	CommandCost cost(ret.GetCost() + (numtracks * _price.train_station_track + _price.train_station_length) * plat_len);
+	CommandCost cost(EXPENSES_CONSTRUCTION, ret.GetCost() + (numtracks * _price.train_station_track + _price.train_station_length) * plat_len);
 
 	Station *st = NULL;
 	bool check_surrounding = true;
@@ -1085,7 +1093,7 @@
 	}
 
 	/* Check if the given station class is valid */
-	if (GB(p2, 8, 8) >= STAT_CLASS_MAX) return CMD_ERROR;
+	if (GB(p2, 8, 8) >= GetNumStationClasses()) return CMD_ERROR;
 
 	/* Check if we can allocate a custom stationspec to this station */
 	const StationSpec *statspec = GetCustomStationSpec((StationClassID)GB(p2, 8, 8), GB(p2, 16, 8));
@@ -1154,7 +1162,7 @@
 
 				tile += tile_delta;
 			} while (--w);
-			SetSignalsOnBothDir(tile_org, track);
+			AddTrackToSignalBuffer(tile_org, track, _current_player);
 			YapfNotifyTrackLayoutChange(tile_org, track);
 			tile_org += tile_delta ^ TileDiffXY(1, 1); // perpendicular to tile_delta
 		} while (--numtracks);
@@ -1164,6 +1172,7 @@
 		UpdateStationAcceptance(st, false);
 		RebuildStationLists();
 		InvalidateWindow(WC_STATION_LIST, st->owner);
+		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_TRAINS);
 		/* success, so don't delete the new station */
 		st_auto_delete.Detach();
 	}
@@ -1255,30 +1264,41 @@
 	int size_x = ex - sx + 1;
 	int size_y = ey - sy + 1;
 
-	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
-
 	/* Do the action for every tile into the area */
 	BEGIN_TILE_LOOP(tile2, size_x, size_y, tile) {
-		/* Make sure the specified tile belongs to the current player, and that it is a railroad station. */
-		if (!IsTileType(tile2, MP_STATION) || !IsRailwayStation(tile2) || !_patches.nonuniform_stations) {
+		/* Make sure the specified tile is a railroad station */
+		if (!IsTileType(tile2, MP_STATION) || !IsRailwayStation(tile2)) {
+			continue;
+		}
+
+		/* If there is a vehicle on ground, do not allow to remove (flood) the tile */
+		if (!EnsureNoVehicleOnGround(tile2)) {
 			continue;
 		}
 
 		/* Check ownership of station */
 		Station *st = GetStationByTile(tile2);
-		if (_current_player != OWNER_WATER && (!CheckOwnership(st->owner) || !EnsureNoVehicleOnGround(tile2))) {
+		if (_current_player != OWNER_WATER && !CheckOwnership(st->owner)) {
 			continue;
 		}
 
+		/* Do not allow removing from stations if non-uniform stations are not enabled
+		 * The check must be here to give correct error message
+ 		 */
+		if (!_patches.nonuniform_stations) return_cmd_error(STR_306D_NONUNIFORM_STATIONS_DISALLOWED);
+
 		/* If we reached here, the tile is valid so increase the quantity of tiles we will remove */
 		quantity++;
 
 		if (flags & DC_EXEC) {
+			/* read variables before the station tile is removed */
 			uint specindex = GetCustomStationSpecIndex(tile2);
 			Track track = GetRailStationTrack(tile2);
+			Owner owner = GetTileOwner(tile2);
+
 			DoClearSquare(tile2);
 			st->rect.AfterRemoveTile(st, tile2);
-			SetSignalsOnBothDir(tile2, track);
+			AddTrackToSignalBuffer(tile2, track, owner);
 			YapfNotifyTrackLayoutChange(tile2, track);
 
 			DeallocateSpecFromStation(st, specindex);
@@ -1293,6 +1313,7 @@
 			/* if we deleted the whole station, delete the train facility. */
 			if (st->train_tile == 0) {
 				st->facilities &= ~FACIL_TRAIN;
+				InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_TRAINS);
 				UpdateStationVirtCoordDirty(st);
 				DeleteStationIfEmpty(st);
 			}
@@ -1302,7 +1323,7 @@
 	/* If we've not removed any tiles, give an error */
 	if (quantity == 0) return CMD_ERROR;
 
-	return CommandCost(_price.remove_rail_station * quantity);
+	return CommandCost(EXPENSES_CONSTRUCTION, _price.remove_rail_station * quantity);
 }
 
 
@@ -1323,20 +1344,22 @@
 
 	assert(w != 0 && h != 0);
 
-	CommandCost cost;
+	CommandCost cost(EXPENSES_CONSTRUCTION);
 	/* clear all areas of the station */
 	do {
 		int w_bak = w;
 		do {
-			// for nonuniform stations, only remove tiles that are actually train station tiles
+			/* for nonuniform stations, only remove tiles that are actually train station tiles */
 			if (st->TileBelongsToRailStation(tile)) {
 				if (!EnsureNoVehicleOnGround(tile))
 					return CMD_ERROR;
 				cost.AddCost(_price.remove_rail_station);
 				if (flags & DC_EXEC) {
+					/* read variables before the station tile is removed */
 					Track track = GetRailStationTrack(tile);
+					Owner owner = GetTileOwner(tile); // _current_player can be OWNER_WATER
 					DoClearSquare(tile);
-					SetSignalsOnBothDir(tile, track);
+					AddTrackToSignalBuffer(tile, track, owner);
 					YapfNotifyTrackLayoutChange(tile, track);
 				}
 			}
@@ -1357,6 +1380,7 @@
 		st->num_specs = 0;
 		st->speclist  = NULL;
 
+		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_TRAINS);
 		UpdateStationVirtCoordDirty(st);
 		DeleteStationIfEmpty(st);
 	}
@@ -1365,29 +1389,6 @@
 }
 
 /**
- * Switches the rail type at a railway station tile.
- * @param tile        The tile on which the railtype is to be convert.
- * @param totype      The railtype we want to convert to
- * @param exec        Switches between test and execute mode
- * @return            The cost and state of the operation
- * @retval CMD_ERROR  An error occured during the operation.
- */
-CommandCost DoConvertStationRail(TileIndex tile, RailType totype, bool exec)
-{
-	/* Tile is not a railroad station? */
-	if (!IsRailwayStation(tile)) return CMD_ERROR;
-
-	if (exec) {
-		SetRailType(tile, totype);
-		MarkTileDirtyByTile(tile);
-		YapfNotifyTrackLayoutChange(tile, GetRailStationTrack(tile));
-		VehicleFromPos(tile, &tile, UpdateTrainPowerProc);
-	}
-
-	return CommandCost(RailBuildCost(totype) / 2);
-}
-
-/**
  * @param truck_station Determines whether a stop is RoadStop::BUS or RoadStop::TRUCK
  * @param st The Station to do the whole procedure for
  * @return a pointer to where to link a new RoadStop*
@@ -1436,8 +1437,6 @@
 	/* Road bits in the wrong direction */
 	if (build_over_road && (GetAllRoadBits(tile) & ((Axis)p1 == AXIS_X ? ROAD_Y : ROAD_X)) != 0) return_cmd_error(STR_DRIVE_THROUGH_ERROR_DIRECTION);
 
-	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
-
 	if (!(flags & DC_NO_TOWN_RATING) && !CheckIfAuthorityAllows(tile)) return CMD_ERROR;
 
 	CommandCost cost;
@@ -1447,13 +1446,23 @@
 		if (IsTileOwner(tile, OWNER_TOWN) && !_patches.road_stop_on_town_road) return_cmd_error(STR_DRIVE_THROUGH_ERROR_ON_TOWN_ROAD);
 		if (GetRoadTileType(tile) != ROAD_TILE_NORMAL) return CMD_ERROR;
 
+		RoadTypes cur_rts = GetRoadTypes(tile);
+
+		/* there is a road, check if we can build road+tram stop over it */
+		if (HasBit(cur_rts, ROADTYPE_ROAD)) {
+			Owner road_owner = GetRoadOwner(tile, ROADTYPE_ROAD);
+			if (road_owner != OWNER_TOWN && road_owner != OWNER_NONE && !CheckOwnership(road_owner)) return CMD_ERROR;
+		}
+
+		/* there is a tram, check if we can build road+tram stop over it */
+		if (HasBit(cur_rts, ROADTYPE_TRAM)) {
+			Owner tram_owner = GetRoadOwner(tile, ROADTYPE_TRAM);
+			if (tram_owner != OWNER_NONE && !CheckOwnership(tram_owner)) return CMD_ERROR;
+		}
+
 		/* Don't allow building the roadstop when vehicles are already driving on it */
 		if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
 
-		RoadTypes cur_rts = GetRoadTypes(tile);
-		if (GetRoadOwner(tile, ROADTYPE_ROAD) != OWNER_TOWN && HasBit(cur_rts, ROADTYPE_ROAD) && !CheckOwnership(GetRoadOwner(tile, ROADTYPE_ROAD))) return CMD_ERROR;
-		if (HasBit(cur_rts, ROADTYPE_TRAM) && !CheckOwnership(GetRoadOwner(tile, ROADTYPE_TRAM))) return CMD_ERROR;
-
 		/* Do not remove roadtypes! */
 		rts |= cur_rts;
 	}
@@ -1536,6 +1545,7 @@
 		UpdateStationAcceptance(st, false);
 		RebuildStationLists();
 		InvalidateWindow(WC_STATION_LIST, st->owner);
+		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_ROADVEHS);
 		/* success, so don't delete the new station and the new road stop */
 		st_auto_delete.Detach();
 		rs_auto_delete.Detach();
@@ -1586,6 +1596,7 @@
 			pred->next = cur_stop->next;
 		}
 
+		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_ROADVEHS);
 		delete cur_stop;
 		DoClearSquare(tile);
 		st->rect.AfterRemoveTile(st, tile);
@@ -1594,7 +1605,7 @@
 		DeleteStationIfEmpty(st);
 	}
 
-	return CommandCost((is_truck) ? _price.remove_truck_station : _price.remove_bus_station);
+	return CommandCost(EXPENSES_CONSTRUCTION, (is_truck) ? _price.remove_truck_station : _price.remove_bus_station);
 }
 
 /** Remove a bus or truck stop
@@ -1648,8 +1659,6 @@
 	byte layout_set = GB(p1, 0, 3);
 	const uint32 airport_type_for_flat_check = (GB(p2, 8, 8) << 3) | layout_set;
 
-	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
-
 	/* Check if a valid, buildable airport was chosen for construction */
 	//if (p1 > lengthof(_airport_sections) || !HasBit(GetValidAirports(), p1)) return CMD_ERROR;
 
@@ -1819,6 +1828,7 @@
 		UpdateStationAcceptance(st, false);
 		RebuildStationLists();
 		InvalidateWindow(WC_STATION_LIST, st->owner);
+		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_PLANES);
 		/* success, so don't delete the new station */
 		st_auto_delete.Detach();
 	}
@@ -1837,7 +1847,7 @@
 	int w = fsmportsspec->size_x[layout_set];
 	int h = fsmportsspec->size_y[layout_set];
 
-	CommandCost cost(w * h * _price.remove_airport);
+	CommandCost cost(EXPENSES_CONSTRUCTION, w * h * _price.remove_airport);
 
 	Vehicle *v;
 	FOR_ALL_VEHICLES(v) {
@@ -1884,6 +1894,7 @@
 		st->airport_tile = 0;
 		st->facilities &= ~FACIL_AIRPORT;
 
+		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_PLANES);
 		UpdateStationVirtCoordDirty(st);
 		DeleteStationIfEmpty(st);
 	}
@@ -1899,8 +1910,6 @@
  */
 CommandCost CmdBuildBuoy(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 {
-	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
-
 	if (!IsWaterTile(tile) || tile == 0) return_cmd_error(STR_304B_SITE_UNSUITABLE);
 	if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
 
@@ -1932,22 +1941,28 @@
 		UpdateStationAcceptance(st, false);
 		RebuildStationLists();
 		InvalidateWindow(WC_STATION_LIST, st->owner);
+		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_SHIPS);
 		/* success, so don't delete the new station */
 		st_auto_delete.Detach();
 	}
 
-	return CommandCost(_price.build_dock);
+	return CommandCost(EXPENSES_CONSTRUCTION, _price.build_dock);
 }
 
-/* Checks if any ship is servicing the buoy specified. Returns yes or no */
-static bool CheckShipsOnBuoy(Station *st)
+/**
+ * Tests whether the player's vehicles have this station in orders
+ * When player == INVALID_PLAYER, then check all vehicles
+ * @param station station ID
+ * @param player player ID, INVALID_PLAYER to disable the check
+ */
+bool HasStationInUse(StationID station, PlayerID player)
 {
 	const Vehicle *v;
 	FOR_ALL_VEHICLES(v) {
-		if (v->type == VEH_SHIP) {
+		if (player == INVALID_PLAYER || v->owner == player) {
 			const Order *order;
 			FOR_VEHICLE_ORDERS(v, order) {
-				if (order->type == OT_GOTO_STATION && order->dest == st->index) {
+				if (order->type == OT_GOTO_STATION && order->dest == station) {
 					return true;
 				}
 			}
@@ -1963,7 +1978,7 @@
 
 	TileIndex tile = st->dock_tile;
 
-	if (CheckShipsOnBuoy(st))   return_cmd_error(STR_BUOY_IS_IN_USE);
+	if (HasStationInUse(st->index, INVALID_PLAYER)) return_cmd_error(STR_BUOY_IS_IN_USE);
 	if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
 
 	if (flags & DC_EXEC) {
@@ -1973,17 +1988,19 @@
 		st->facilities &= ~FACIL_DOCK;
 		st->had_vehicle_of_type &= ~HVOT_BUOY;
 
+		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_SHIPS);
+
 		/* We have to set the water tile's state to the same state as before the
 		 * buoy was placed. Otherwise one could plant a buoy on a canal edge,
 		 * remove it and flood the land (if the canal edge is at level 0) */
-		MakeWaterOrCanalDependingOnSurroundings(tile, GetTileOwner(tile));
+		MakeWaterOrCanalDependingOnOwner(tile, GetTileOwner(tile));
 		MarkTileDirtyByTile(tile);
 
 		UpdateStationVirtCoordDirty(st);
 		DeleteStationIfEmpty(st);
 	}
 
-	return CommandCost(_price.remove_truck_station);
+	return CommandCost(EXPENSES_CONSTRUCTION, _price.remove_truck_station);
 }
 
 static const TileIndexDiffC _dock_tileoffs_chkaround[] = {
@@ -2005,8 +2022,6 @@
 {
 	CommandCost cost;
 
-	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
-
 	DiagDirection direction;
 	switch (GetTileSlope(tile, NULL)) {
 		case SLOPE_SW: direction = DIAGDIR_NE; break;
@@ -2094,10 +2109,11 @@
 		UpdateStationAcceptance(st, false);
 		RebuildStationLists();
 		InvalidateWindow(WC_STATION_LIST, st->owner);
+		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_SHIPS);
 		/* success, so don't delete the new station */
 		st_auto_delete.Detach();
 	}
-	return CommandCost(_price.build_dock);
+	return CommandCost(EXPENSES_CONSTRUCTION, _price.build_dock);
 }
 
 static CommandCost RemoveDock(Station *st, uint32 flags)
@@ -2122,11 +2138,12 @@
 		st->dock_tile = 0;
 		st->facilities &= ~FACIL_DOCK;
 
+		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_SHIPS);
 		UpdateStationVirtCoordDirty(st);
 		DeleteStationIfEmpty(st);
 	}
 
-	return CommandCost(_price.remove_dock);
+	return CommandCost(EXPENSES_CONSTRUCTION, _price.remove_dock);
 }
 
 #include "table/station_land.h"
@@ -2139,16 +2156,20 @@
 static void DrawTile_Station(TileInfo *ti)
 {
 	const DrawTileSprites *t = NULL;
-	RailType railtype;
 	RoadTypes roadtypes;
+	int32 total_offset;
+	int32 custom_ground_offset;
+
 	if (IsRailwayStation(ti->tile)) {
-		railtype = GetRailType(ti->tile);
+		const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
 		roadtypes = ROADTYPES_NONE;
+		total_offset = rti->total_offset;
+		custom_ground_offset = rti->custom_ground_offset;
 	} else {
 		roadtypes = GetRoadTypes(ti->tile);
-		railtype = RAILTYPE_BEGIN;
+		total_offset = 0;
+		custom_ground_offset = 0;
 	}
-	const RailtypeInfo *rti = GetRailTypeInfo(railtype);
 	uint32 relocation = 0;
 	const Station *st = NULL;
 	const StationSpec *statspec = NULL;
@@ -2218,9 +2239,9 @@
 	SpriteID image = t->ground_sprite;
 	if (HasBit(image, SPRITE_MODIFIER_USE_OFFSET)) {
 		image += (FSMport)? GetCustomFSMportsGroundRelocation(fsmportspec, st, ti->tile) : GetCustomStationGroundRelocation(statspec, st, ti->tile);
-		image += rti->custom_ground_offset;
+		image += custom_ground_offset;
 	} else {
-		image += rti->total_offset;
+		image += total_offset;
 	}
 
 	// if ground tile 0x0F8D, but tile is desert/snow, then choose desert/snow graphic
@@ -2245,13 +2266,13 @@
 	foreach_draw_tile_seq(dtss, t->seq) {
 		image = dtss->image;
 		if (relocation == 0 || HasBit(image, SPRITE_MODIFIER_USE_OFFSET)) {
-			image += rti->total_offset;
+			image += total_offset;
 		} else {
 			image += relocation;
 		}
 
 		SpriteID pal;
-		if (!IsTransparencySet(TO_BUILDINGS) && HasBit(image, PALETTE_MODIFIER_COLOR)) {
+		if (!(!HasBit(image, SPRITE_MODIFIER_OPAQUE) && IsTransparencySet(TO_BUILDINGS)) && HasBit(image, PALETTE_MODIFIER_COLOR)) {
 			pal = palette;
 		} else {
 			pal = dtss->pal;
@@ -2263,7 +2284,7 @@
 				ti->x + dtss->delta_x, ti->y + dtss->delta_y,
 				dtss->size_x, dtss->size_y,
 				dtss->size_z, ti->z + dtss->delta_z,
-				IsTransparencySet(TO_BUILDINGS)
+				!HasBit(image, SPRITE_MODIFIER_OPAQUE) && IsTransparencySet(TO_BUILDINGS)
 			);
 		} else {
 			AddChildSpriteScreen(image, pal, dtss->delta_x, dtss->delta_y, IsTransparencySet(TO_BUILDINGS));
@@ -2273,12 +2294,17 @@
 
 void StationPickerDrawSprite(int x, int y, StationType st, RailType railtype, RoadType roadtype, int image)
 {
-	const RailtypeInfo *rti = GetRailTypeInfo(railtype);
+	int32 total_offset = 0;
 	SpriteID pal = PLAYER_SPRITE_COLOR(_local_player);
 	const DrawTileSprites *t = &_station_display_datas[st][image];
 
+	if (railtype != INVALID_RAILTYPE) {
+		const RailtypeInfo *rti = GetRailTypeInfo(railtype);
+		total_offset = rti->total_offset;
+	}
+
 	SpriteID img = t->ground_sprite;
-	DrawSprite(img + rti->total_offset, HasBit(img, PALETTE_MODIFIER_COLOR) ? pal : PAL_NONE, x, y);
+	DrawSprite(img + total_offset, HasBit(img, PALETTE_MODIFIER_COLOR) ? pal : PAL_NONE, x, y);
 
 	if (roadtype == ROADTYPE_TRAM) {
 		DrawSprite(SPR_TRAMWAY_TRAM + (t->ground_sprite == SPR_ROAD_PAVED_STRAIGHT_X ? 1 : 0), PAL_NONE, x, y);
@@ -2287,7 +2313,7 @@
 	const DrawTileSeqStruct *dtss;
 	foreach_draw_tile_seq(dtss, t->seq) {
 		Point pt = RemapCoords(dtss->delta_x, dtss->delta_y, dtss->delta_z);
-		DrawSprite(dtss->image + rti->total_offset, pal, x + pt.x, y + pt.y);
+		DrawSprite(dtss->image + total_offset, pal, x + pt.x, y + pt.y);
 	}
 }
 
@@ -2437,16 +2463,16 @@
 	215, 195, 175, 155, 135, 115, 95, 75, 55, 35, 15, 0
 };
 
-static uint32 VehicleEnter_Station(Vehicle *v, TileIndex tile, int x, int y)
+static VehicleEnterTileStatus VehicleEnter_Station(Vehicle *v, TileIndex tile, int x, int y)
 {
 	if (v->type == VEH_TRAIN) {
 		if (IsRailwayStation(tile) && IsFrontEngine(v) &&
 				!IsCompatibleTrainStationTile(tile + TileOffsByDiagDir(DirToDiagDir(v->direction)), tile)) {
 			StationID station_id = GetStationIndex(tile);
 
-			if ((!(v->current_order.flags & OF_NON_STOP) && !_patches.new_nonstop) ||
+			if ((!(v->current_order.flags & OFB_NON_STOP) && !_patches.new_nonstop) ||
 					(v->current_order.type == OT_GOTO_STATION && v->current_order.dest == station_id)) {
-				if (!(_patches.new_nonstop && v->current_order.flags & OF_NON_STOP) &&
+				if (!(_patches.new_nonstop && v->current_order.flags & OFB_NON_STOP) &&
 						v->current_order.type != OT_LEAVESTATION &&
 						v->last_station_visited != station_id) {
 					DiagDirection dir = DirToDiagDir(v->direction);
@@ -2457,7 +2483,7 @@
 					if (DiagDirToAxis(dir) != AXIS_X) Swap(x, y);
 					if (y == TILE_SIZE / 2) {
 						if (dir != DIAGDIR_SE && dir != DIAGDIR_SW) x = TILE_SIZE - 1 - x;
-						if (x == 12) return VETSB_ENTERED_STATION | (station_id << VETS_STATION_ID_OFFSET); /* enter station */
+						if (x == 12) return VETSB_ENTERED_STATION | (VehicleEnterTileStatus)(station_id << VETS_STATION_ID_OFFSET); /* enter station */
 						if (x < 12) {
 							uint16 spd;
 
@@ -2628,9 +2654,9 @@
 
 	StationID index = st->index;
 	if (waiting_changed) {
-		InvalidateWindow(WC_STATION_VIEW, index);
+		InvalidateWindow(WC_STATION_VIEW, index); // update whole window
 	} else {
-		InvalidateWindowWidget(WC_STATION_VIEW, index, 5);
+		InvalidateWindowWidget(WC_STATION_VIEW, index, SVW_RATINGLIST); // update only ratings list
 	}
 }
 
@@ -2720,19 +2746,13 @@
 
 	if (!IsUniqueStationName(_cmd_text)) return_cmd_error(STR_NAME_MUST_BE_UNIQUE);
 
-	StringID str = AllocateName(_cmd_text, 6);
-	if (str == 0) return CMD_ERROR;
-
 	if (flags & DC_EXEC) {
-		StringID old_str = st->string_id;
-
-		st->string_id = str;
+		free(st->name);
+		st->name = strdup(_cmd_text);
+
 		UpdateStationVirtCoord(st);
-		DeleteName(old_str);
 		ResortStationLists();
 		MarkWholeScreenDirty();
-	} else {
-		DeleteName(str);
 	}
 
 	return CommandCost();
@@ -3076,11 +3096,11 @@
 					DiagDirection direction = AxisToDiagDir(GetRailStationAxis(tile));
 					if (!AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, direction)) break;
 					if (!AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, ReverseDiagDir(direction))) break;
-					return _price.terraform;
+					return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform);
 				}
 
 				case STATION_AIRPORT:
-					return _price.terraform;
+					return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform);
 
 				case STATION_TRUCK:
 				case STATION_BUS: {
@@ -3089,7 +3109,7 @@
 					if (IsDriveThroughStopTile(tile)) {
 						if (!AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, ReverseDiagDir(direction))) break;
 					}
-					return _price.terraform;
+					return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform);
 				}
 
 				default: break;
@@ -3153,6 +3173,7 @@
 	SLE_CONDNULL(1, 0, 3),
 
 	    SLE_VAR(Station, string_id,                  SLE_STRINGID),
+	SLE_CONDSTR(Station, name,                       SLE_STR, 0,                 84, SL_MAX_VERSION),
 	    SLE_VAR(Station, had_vehicle_of_type,        SLE_UINT16),
 
 	    SLE_VAR(Station, time_since_load,            SLE_UINT8),