src/station_cmd.cpp
branchnoai
changeset 9724 b39bc69bb2f2
parent 9723 eee46cb39750
child 9732 f8eb3e208514
--- a/src/station_cmd.cpp	Wed Jan 09 18:11:12 2008 +0000
+++ b/src/station_cmd.cpp	Sun Feb 03 20:17:54 2008 +0000
@@ -11,15 +11,12 @@
 #include "tile_cmd.h"
 #include "landscape.h"
 #include "station_map.h"
-#include "table/sprites.h"
-#include "table/strings.h"
 #include "station.h"
 #include "viewport_func.h"
 #include "command_func.h"
 #include "town.h"
 #include "news.h"
 #include "saveload.h"
-#include "player.h"
 #include "airport.h"
 #include "sprite.h"
 #include "depot.h"
@@ -45,6 +42,10 @@
 #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)
@@ -699,7 +700,7 @@
  * @param w width of search area
  * @param h height of search area
  * @param flags operation to perform
- * @param invalid_dirs prohibited directions
+ * @param invalid_dirs prohibited directions (set of DiagDirections)
  * @param station StationID to be queried and returned if available
  * @param check_clear if clearing tile should be performed (in wich case, cost will be added)
  * @return the cost in case of success, or an error code if it failed.
@@ -734,11 +735,12 @@
 
 		int flat_z = z;
 		if (tileh != SLOPE_FLAT) {
-			/* need to check so the entrance to the station is not pointing at a slope. */
-			if ((invalid_dirs & 1 && !(tileh & SLOPE_NE) && (uint)w_cur == w) ||
-					(invalid_dirs & 2 && !(tileh & SLOPE_SE) && h_cur == 1) ||
-					(invalid_dirs & 4 && !(tileh & SLOPE_SW) && w_cur == 1) ||
-					(invalid_dirs & 8 && !(tileh & SLOPE_NW) && (uint)h_cur == h)) {
+			/* need to check so the entrance to the station is not pointing at a slope.
+			 * This must be valid for all station tiles, as the user can remove single station tiles. */
+			if ((HasBit(invalid_dirs, DIAGDIR_NE) && !(tileh & SLOPE_NE)) ||
+			    (HasBit(invalid_dirs, DIAGDIR_SE) && !(tileh & SLOPE_SE)) ||
+			    (HasBit(invalid_dirs, DIAGDIR_SW) && !(tileh & SLOPE_SW)) ||
+			    (HasBit(invalid_dirs, DIAGDIR_NW) && !(tileh & SLOPE_NW))) {
 				return_cmd_error(STR_0007_FLAT_LAND_REQUIRED);
 			}
 			cost.AddCost(_price.terraform);
@@ -797,14 +799,14 @@
 		 * 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;
+				_error_message = STR_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;
+			_error_message = STR_NONUNIFORM_STATIONS_DISALLOWED;
 			return false;
 		}
 
@@ -824,7 +826,7 @@
 			tile -= TileDiffXY(curw, 0);
 			curw += w;
 		} else {
-			_error_message = STR_306D_NONUNIFORM_STATIONS_DISALLOWED;
+			_error_message = STR_NONUNIFORM_STATIONS_DISALLOWED;
 			return false;
 		}
 	}
@@ -905,7 +907,7 @@
 
 	/* 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);
@@ -1003,7 +1005,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));
@@ -1072,7 +1074,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);
@@ -1195,17 +1197,20 @@
 		/* 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 (!_patches.nonuniform_stations) return_cmd_error(STR_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);
@@ -1256,15 +1261,17 @@
 	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);
 				}
 			}
@@ -1351,13 +1358,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;
 	}
@@ -1377,7 +1394,7 @@
 	/* give us a road stop in the list, and check if something went wrong */
 	RoadStop *road_stop = new RoadStop(tile);
 	if (road_stop == NULL) {
-		return_cmd_error(type ? STR_3008B_TOO_MANY_TRUCK_STOPS : STR_3008A_TOO_MANY_BUS_STOPS);
+		return_cmd_error(type ? STR_TOO_MANY_TRUCK_STOPS : STR_TOO_MANY_BUS_STOPS);
 	}
 
 	/* ensure that in case of error (or no DC_EXEC) the new road stop gets deleted upon return */
@@ -1385,7 +1402,7 @@
 
 	if (st != NULL &&
 			GetNumRoadStopsInStation(st, RoadStop::BUS) + GetNumRoadStopsInStation(st, RoadStop::TRUCK) >= RoadStop::LIMIT) {
-		return_cmd_error(type ? STR_3008B_TOO_MANY_TRUCK_STOPS : STR_3008A_TOO_MANY_BUS_STOPS);
+		return_cmd_error(type ? STR_TOO_MANY_TRUCK_STOPS : STR_TOO_MANY_BUS_STOPS);
 	}
 
 	/* In case of new station if DC_EXEC is NOT set we still need to create the station
@@ -1820,6 +1837,8 @@
 	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);
 
+	if (GetTileSlope(tile, NULL) != SLOPE_FLAT) return_cmd_error(STR_304B_SITE_UNSUITABLE);
+
 	/* allocate and initialize new station */
 	Station *st = new Station(tile);
 	if (st == NULL) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING);
@@ -1842,7 +1861,7 @@
 
 		st->build_date = _date;
 
-		MakeBuoy(tile, st->index);
+		MakeBuoy(tile, st->index, GetWaterClass(tile));
 
 		UpdateStationVirtCoordDirty(st);
 		UpdateStationAcceptance(st, false);
@@ -1900,7 +1919,7 @@
 		/* 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) */
-		MakeWaterOrCanalDependingOnOwner(tile, GetTileOwner(tile));
+		MakeWaterKeepingClass(tile, GetTileOwner(tile));
 		MarkTileDirtyByTile(tile);
 
 		UpdateStationVirtCoordDirty(st);
@@ -1929,14 +1948,12 @@
 {
 	CommandCost cost;
 
-	DiagDirection direction;
-	switch (GetTileSlope(tile, NULL)) {
-		case SLOPE_SW: direction = DIAGDIR_NE; break;
-		case SLOPE_SE: direction = DIAGDIR_NW; break;
-		case SLOPE_NW: direction = DIAGDIR_SE; break;
-		case SLOPE_NE: direction = DIAGDIR_SW; break;
-		default: return_cmd_error(STR_304B_SITE_UNSUITABLE);
-	}
+	DiagDirection direction = GetInclinedSlopeDirection(GetTileSlope(tile, NULL));
+	if (direction == INVALID_DIAGDIR) return_cmd_error(STR_304B_SITE_UNSUITABLE);
+	direction = ReverseDiagDir(direction);
+
+	/* Docks cannot be placed on rapids */
+	if (IsWaterTile(tile)) return_cmd_error(STR_304B_SITE_UNSUITABLE);
 
 	if (!(flags & DC_NO_TOWN_RATING) && !CheckIfAuthorityAllows(tile)) return CMD_ERROR;
 
@@ -1953,6 +1970,9 @@
 
 	if (MayHaveBridgeAbove(tile_cur) && IsBridgeAbove(tile_cur)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
 
+	/* Get the water class of the water tile before it is cleared.*/
+	WaterClass wc = GetWaterClass(tile_cur);
+
 	cost = DoCommand(tile_cur, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 	if (CmdFailed(cost)) return CMD_ERROR;
 
@@ -2010,7 +2030,7 @@
 
 		st->rect.BeforeAddRect(tile, _dock_w_chk[direction], _dock_h_chk[direction], StationRect::ADD_TRY);
 
-		MakeDock(tile, st->owner, st->index, direction);
+		MakeDock(tile, st->owner, st->index, direction, wc);
 
 		UpdateStationVirtCoordDirty(st);
 		UpdateStationAcceptance(st, false);
@@ -2035,7 +2055,7 @@
 
 	if (flags & DC_EXEC) {
 		DoClearSquare(tile1);
-		MakeWaterOrCanalDependingOnSurroundings(tile2, st->owner);
+		MakeWaterKeepingClass(tile2, st->owner);
 
 		st->rect.AfterRemoveTile(st, tile1);
 		st->rect.AfterRemoveTile(st, tile2);
@@ -2073,7 +2093,7 @@
 		total_offset = rti->total_offset;
 		custom_ground_offset = rti->custom_ground_offset;
 	} else {
-		roadtypes = GetRoadTypes(ti->tile);
+		roadtypes = IsRoadStop(ti->tile) ? GetRoadTypes(ti->tile) : ROADTYPES_NONE;
 		total_offset = 0;
 		custom_ground_offset = 0;
 	}
@@ -2140,7 +2160,14 @@
 		DrawTramCatenary(ti, axis == AXIS_X ? ROAD_X : ROAD_Y);
 	}
 
-	if (IsCanalBuoyTile(ti->tile)) DrawCanalWater(ti->tile);
+	if (IsBuoy(ti->tile)) {
+		/* Draw appropriate water edges */
+		switch (GetWaterClass(ti->tile)) {
+			case WATER_CLASS_SEA: break;
+			case WATER_CLASS_CANAL: DrawCanalWater(ti->tile, false); break;
+			case WATER_CLASS_RIVER: DrawRiverWater(ti, false); break;
+		}
+	}
 
 	const DrawTileSeqStruct *dtss;
 	foreach_draw_tile_seq(dtss, t->seq) {
@@ -2348,9 +2375,9 @@
 				!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);
@@ -2624,19 +2651,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();
@@ -2895,8 +2916,8 @@
 		switch (GetStationType(tile)) {
 			case STATION_RAIL:    return_cmd_error(STR_300B_MUST_DEMOLISH_RAILROAD);
 			case STATION_AIRPORT: return_cmd_error(STR_300E_MUST_DEMOLISH_AIRPORT_FIRST);
-			case STATION_TRUCK:   return_cmd_error(HasBit(GetRoadTypes(tile), ROADTYPE_TRAM) ? STR_3047_MUST_DEMOLISH_CARGO_TRAM_STATION : STR_3047_MUST_DEMOLISH_TRUCK_STATION);
-			case STATION_BUS:     return_cmd_error(HasBit(GetRoadTypes(tile), ROADTYPE_TRAM) ? STR_3046_MUST_DEMOLISH_PASSENGER_TRAM_STATION : STR_3046_MUST_DEMOLISH_BUS_STATION);
+			case STATION_TRUCK:   return_cmd_error(HasBit(GetRoadTypes(tile), ROADTYPE_TRAM) ? STR_MUST_DEMOLISH_CARGO_TRAM_STATION : STR_3047_MUST_DEMOLISH_TRUCK_STATION);
+			case STATION_BUS:     return_cmd_error(HasBit(GetRoadTypes(tile), ROADTYPE_TRAM) ? STR_MUST_DEMOLISH_PASSENGER_TRAM_STATION : STR_3046_MUST_DEMOLISH_BUS_STATION);
 			case STATION_BUOY:    return_cmd_error(STR_306A_BUOY_IN_THE_WAY);
 			case STATION_DOCK:    return_cmd_error(STR_304D_MUST_DEMOLISH_DOCK_FIRST);
 			case STATION_OILRIG:
@@ -3045,6 +3066,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),