src/station_cmd.cpp
branchgamebalance
changeset 9911 0b8b245a2391
parent 9910 0b2aebc8283e
child 9912 1ac8aac92385
equal deleted inserted replaced
9910:0b2aebc8283e 9911:0b8b245a2391
   933 		do {
   933 		do {
   934 			TileIndex tile = tile_org;
   934 			TileIndex tile = tile_org;
   935 			int w = plat_len;
   935 			int w = plat_len;
   936 			do {
   936 			do {
   937 				byte layout = *layout_ptr++;
   937 				byte layout = *layout_ptr++;
   938 				MakeRailStation(tile, st->owner, st->index, axis, layout, (RailType)GB(p2, 0, 4));
   938 				MakeRailStation(tile, st->owner, st->index, axis, layout & ~1, (RailType)GB(p2, 0, 4));
   939 				SetCustomStationSpecIndex(tile, specindex);
   939 				SetCustomStationSpecIndex(tile, specindex);
   940 				SetStationTileRandomBits(tile, GB(Random(), 0, 4));
   940 				SetStationTileRandomBits(tile, GB(Random(), 0, 4));
   941 
   941 
   942 				if (statspec != NULL) {
   942 				if (statspec != NULL) {
   943 					/* Use a fixed axis for GetPlatformInfo as our platforms / numtracks are always the right way around */
   943 					/* Use a fixed axis for GetPlatformInfo as our platforms / numtracks are always the right way around */
   944 					uint32 platinfo = GetPlatformInfo(AXIS_X, 0, plat_len, numtracks_orig, plat_len - w, numtracks_orig - numtracks, false);
   944 					uint32 platinfo = GetPlatformInfo(AXIS_X, 0, plat_len, numtracks_orig, plat_len - w, numtracks_orig - numtracks, false);
   945 					uint16 callback = GetStationCallback(CBID_STATION_TILE_LAYOUT, platinfo, 0, statspec, st, tile);
   945 					uint16 callback = GetStationCallback(CBID_STATION_TILE_LAYOUT, platinfo, 0, statspec, st, tile);
   946 					if (callback != CALLBACK_FAILED && callback < 8) SetStationGfx(tile, callback + axis);
   946 					if (callback != CALLBACK_FAILED && callback < 8) SetStationGfx(tile, (callback & ~1) + axis);
   947 				}
   947 				}
   948 
   948 
   949 				tile += tile_delta;
   949 				tile += tile_delta;
   950 			} while (--w);
   950 			} while (--w);
   951 			SetSignalsOnBothDir(tile_org, track);
   951 			SetSignalsOnBothDir(tile_org, track);
  1023 
  1023 
  1024 /** Remove a single tile from a railroad station.
  1024 /** Remove a single tile from a railroad station.
  1025  * This allows for custom-built station with holes and weird layouts
  1025  * This allows for custom-built station with holes and weird layouts
  1026  * @param tile tile of station piece to remove
  1026  * @param tile tile of station piece to remove
  1027  * @param flags operation to perform
  1027  * @param flags operation to perform
  1028  * @param p1 unused
  1028  * @param p1 start_tile
  1029  * @param p2 unused
  1029  * @param p2 unused
  1030  */
  1030  */
  1031 int32 CmdRemoveFromRailroadStation(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1031 int32 CmdRemoveFromRailroadStation(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1032 {
  1032 {
       
  1033 	TileIndex start = p1 == 0 ? tile : p1;
       
  1034 
       
  1035 	/* Count of the number of tiles removed */
       
  1036 	int quantity = 0;
       
  1037 
       
  1038 	if (tile >= MapSize() || start >= MapSize()) return CMD_ERROR;
       
  1039 
       
  1040 	/* make sure sx,sy are smaller than ex,ey */
       
  1041 	int ex = TileX(tile);
       
  1042 	int ey = TileY(tile);
       
  1043 	int sx = TileX(start);
       
  1044 	int sy = TileY(start);
       
  1045 	if (ex < sx) Swap(ex, sx);
       
  1046 	if (ey < sy) Swap(ey, sy);
       
  1047 	tile = TileXY(sx, sy);
       
  1048 
       
  1049 	int size_x = ex - sx + 1;
       
  1050 	int size_y = ey - sy + 1;
       
  1051 
  1033 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
  1052 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
  1034 
  1053 
  1035 	// make sure the specified tile belongs to the current player, and that it is a railroad station.
  1054 	/* Do the action for every tile into the area */
  1036 	if (!IsTileType(tile, MP_STATION) || !IsRailwayStation(tile) || !_patches.nonuniform_stations) return CMD_ERROR;
  1055 	BEGIN_TILE_LOOP(tile2, size_x, size_y, tile) {
  1037 	Station *st = GetStationByTile(tile);
  1056 		/* Make sure the specified tile belongs to the current player, and that it is a railroad station. */
  1038 	if (_current_player != OWNER_WATER && (!CheckOwnership(st->owner) || !EnsureNoVehicle(tile))) return CMD_ERROR;
  1057 		if (!IsTileType(tile2, MP_STATION) || !IsRailwayStation(tile2) || !_patches.nonuniform_stations) {
  1039 
  1058 			continue;
  1040 	// if we reached here, it means we can actually delete it. do that.
  1059 		}
  1041 	if (flags & DC_EXEC) {
  1060 
  1042 		uint specindex = GetCustomStationSpecIndex(tile);
  1061 		/* Check ownership of station */
  1043 		Track track = GetRailStationTrack(tile);
  1062 		Station *st = GetStationByTile(tile2);
  1044 		DoClearSquare(tile);
  1063 		if (_current_player != OWNER_WATER && (!CheckOwnership(st->owner) || !EnsureNoVehicle(tile2))) {
  1045 		st->rect.AfterRemoveTile(st, tile);
  1064 			continue;
  1046 		SetSignalsOnBothDir(tile, track);
  1065 		}
  1047 		YapfNotifyTrackLayoutChange(tile, track);
  1066 
  1048 
  1067 		/* If we reached here, the tile is valid so increase the quantity of tiles we will remove */
  1049 		DeallocateSpecFromStation(st, specindex);
  1068 		quantity++;
  1050 
  1069 
  1051 		// now we need to make the "spanned" area of the railway station smaller if we deleted something at the edges.
  1070 		if (flags & DC_EXEC) {
  1052 		// we also need to adjust train_tile.
  1071 			uint specindex = GetCustomStationSpecIndex(tile2);
  1053 		MakeRailwayStationAreaSmaller(st);
  1072 			Track track = GetRailStationTrack(tile2);
  1054 		st->MarkTilesDirty();
  1073 			DoClearSquare(tile2);
  1055 		UpdateStationSignCoord(st);
  1074 			st->rect.AfterRemoveTile(st, tile2);
  1056 
  1075 			SetSignalsOnBothDir(tile2, track);
  1057 		// if we deleted the whole station, delete the train facility.
  1076 			YapfNotifyTrackLayoutChange(tile2, track);
  1058 		if (st->train_tile == 0) {
  1077 
  1059 			st->facilities &= ~FACIL_TRAIN;
  1078 			DeallocateSpecFromStation(st, specindex);
  1060 			UpdateStationVirtCoordDirty(st);
  1079 
  1061 			DeleteStationIfEmpty(st);
  1080 			// now we need to make the "spanned" area of the railway station smaller if we deleted something at the edges.
  1062 		}
  1081 			// we also need to adjust train_tile.
  1063 	}
  1082 			MakeRailwayStationAreaSmaller(st);
  1064 	return _eco->GetPrice(CEconomy::REMOVE_RAIL_STATION);
  1083 			st->MarkTilesDirty();
       
  1084 			UpdateStationSignCoord(st);
       
  1085 
       
  1086 			// if we deleted the whole station, delete the train facility.
       
  1087 			if (st->train_tile == 0) {
       
  1088 				st->facilities &= ~FACIL_TRAIN;
       
  1089 				UpdateStationVirtCoordDirty(st);
       
  1090 				DeleteStationIfEmpty(st);
       
  1091 			}
       
  1092 		}
       
  1093 	} END_TILE_LOOP(tile2, size_x, size_y, tile)
       
  1094 
       
  1095 	/* If we've not removed any tiles, give an error */
       
  1096 	if (quantity == 0) return CMD_ERROR;
       
  1097 
       
  1098 	return _eco->GetPrice(CEconomy::REMOVE_RAIL_STATION) * quantity;
  1065 }
  1099 }
  1066 
  1100 
  1067 
  1101 
  1068 static int32 RemoveRailroadStation(Station *st, TileIndex tile, uint32 flags)
  1102 static int32 RemoveRailroadStation(Station *st, TileIndex tile, uint32 flags)
  1069 {
  1103 {
  1178  * @param tile tile to build the stop at
  1212  * @param tile tile to build the stop at
  1179  * @param flags operation to perform
  1213  * @param flags operation to perform
  1180  * @param p1 entrance direction (DiagDirection)
  1214  * @param p1 entrance direction (DiagDirection)
  1181  * @param p2 bit 0: 0 for Bus stops, 1 for truck stops
  1215  * @param p2 bit 0: 0 for Bus stops, 1 for truck stops
  1182  *           bit 1: 0 for normal, 1 for drive-through
  1216  *           bit 1: 0 for normal, 1 for drive-through
       
  1217  *           bit 2..4: the roadtypes
  1183  */
  1218  */
  1184 int32 CmdBuildRoadStop(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1219 int32 CmdBuildRoadStop(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1185 {
  1220 {
  1186 	bool type = HASBIT(p2, 0);
  1221 	bool type = HASBIT(p2, 0);
  1187 	bool is_drive_through = HASBIT(p2, 1);
  1222 	bool is_drive_through = HASBIT(p2, 1);
  1188 	bool build_over_road  = is_drive_through && IsTileType(tile, MP_STREET) && GetRoadTileType(tile) == ROAD_TILE_NORMAL;
  1223 	bool build_over_road  = is_drive_through && IsTileType(tile, MP_STREET) && GetRoadTileType(tile) == ROAD_TILE_NORMAL;
  1189 	bool town_owned_road  = build_over_road && IsTileOwner(tile, OWNER_TOWN);
  1224 	bool town_owned_road  = build_over_road && IsTileOwner(tile, OWNER_TOWN);
  1190 	Owner cur_owner = _current_player;
  1225 	Owner cur_owner = _current_player;
       
  1226 	RoadTypes rts = (RoadTypes)GB(p2, 2, 3);
       
  1227 
       
  1228 	if (rts == ROADTYPES_NONE || HASBIT(rts, ROADTYPE_HWAY)) return CMD_ERROR;
  1191 
  1229 
  1192 	/* Saveguard the parameters */
  1230 	/* Saveguard the parameters */
  1193 	if (!IsValidDiagDirection((DiagDirection)p1)) return CMD_ERROR;
  1231 	if (!IsValidDiagDirection((DiagDirection)p1)) return CMD_ERROR;
  1194 	/* If it is a drive-through stop check for valid axis */
  1232 	/* If it is a drive-through stop check for valid axis */
  1195 	if (is_drive_through && !IsValidAxis((Axis)p1)) return CMD_ERROR;
  1233 	if (is_drive_through && !IsValidAxis((Axis)p1)) return CMD_ERROR;
  1196 	/* Road bits in the wrong direction */
  1234 	/* Road bits in the wrong direction */
  1197 	if (build_over_road && (GetRoadBits(tile) & ((Axis)p1 == AXIS_X ? ROAD_Y : ROAD_X)) != 0) return_cmd_error(STR_DRIVE_THROUGH_ERROR_DIRECTION);
  1235 	if (build_over_road && (GetAllRoadBits(tile) & ((Axis)p1 == AXIS_X ? ROAD_Y : ROAD_X)) != 0) return_cmd_error(STR_DRIVE_THROUGH_ERROR_DIRECTION);
  1198 	/* Not allowed to build over this road */
  1236 	/* Not allowed to build over this road */
  1199 	if (build_over_road) {
  1237 	if (build_over_road) {
  1200 		if (IsTileOwner(tile, OWNER_TOWN) && !_patches.road_stop_on_town_road) return_cmd_error(STR_DRIVE_THROUGH_ERROR_ON_TOWN_ROAD);
  1238 		if (IsTileOwner(tile, OWNER_TOWN) && !_patches.road_stop_on_town_road) return_cmd_error(STR_DRIVE_THROUGH_ERROR_ON_TOWN_ROAD);
  1201 		if (!IsTileOwner(tile, OWNER_TOWN) && !CheckOwnership(GetTileOwner(tile))) return CMD_ERROR;
  1239 		if (GetRoadTileType(tile) != ROAD_TILE_NORMAL) return CMD_ERROR;
       
  1240 		if (!IsTileOwner(tile, OWNER_TOWN) && !CheckOwnership(GetRoadOwner(tile, ROADTYPE_ROAD)) && !CheckOwnership(GetRoadOwner(tile, ROADTYPE_TRAM))) return CMD_ERROR;
       
  1241 		/* Do not remove roadtypes! */
       
  1242 		if (rts != GetRoadTypes(tile) && rts != ROADTYPES_ROADTRAM) return CMD_ERROR;
  1202 	}
  1243 	}
  1203 
  1244 
  1204 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
  1245 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
  1205 
  1246 
  1206 	if (!(flags & DC_NO_TOWN_RATING) && !CheckIfAuthorityAllows(tile))
  1247 	if (!(flags & DC_NO_TOWN_RATING) && !CheckIfAuthorityAllows(tile))
  1275 
  1316 
  1276 		st->rect.BeforeAddTile(tile, StationRect::ADD_TRY);
  1317 		st->rect.BeforeAddTile(tile, StationRect::ADD_TRY);
  1277 
  1318 
  1278 		RoadStop::Type rs_type = type ? RoadStop::TRUCK : RoadStop::BUS;
  1319 		RoadStop::Type rs_type = type ? RoadStop::TRUCK : RoadStop::BUS;
  1279 		if (is_drive_through) {
  1320 		if (is_drive_through) {
  1280 			MakeDriveThroughRoadStop(tile, st->owner, st->index, rs_type, (Axis)p1, town_owned_road);
  1321 			MakeDriveThroughRoadStop(tile, st->owner, st->index, rs_type, rts, (Axis)p1, town_owned_road);
  1281 		} else {
  1322 		} else {
  1282 			MakeRoadStop(tile, st->owner, st->index, rs_type, (DiagDirection)p1);
  1323 			MakeRoadStop(tile, st->owner, st->index, rs_type, rts, (DiagDirection)p1);
  1283 		}
  1324 		}
  1284 
  1325 
  1285 		UpdateStationVirtCoordDirty(st);
  1326 		UpdateStationVirtCoordDirty(st);
  1286 		UpdateStationAcceptance(st, false);
  1327 		UpdateStationAcceptance(st, false);
  1287 		RebuildStationLists();
  1328 		RebuildStationLists();
  1353 	/* Make sure the specified tile is a road stop of the correct type */
  1394 	/* Make sure the specified tile is a road stop of the correct type */
  1354 	if (!IsTileType(tile, MP_STATION) || !IsRoadStop(tile) || (uint32)GetRoadStopType(tile) != p2) return CMD_ERROR;
  1395 	if (!IsTileType(tile, MP_STATION) || !IsRoadStop(tile) || (uint32)GetRoadStopType(tile) != p2) return CMD_ERROR;
  1355 	Station *st = GetStationByTile(tile);
  1396 	Station *st = GetStationByTile(tile);
  1356 	/* Save the stop info before it is removed */
  1397 	/* Save the stop info before it is removed */
  1357 	bool is_drive_through = IsDriveThroughStopTile(tile);
  1398 	bool is_drive_through = IsDriveThroughStopTile(tile);
  1358 	RoadBits road_bits = GetAnyRoadBits(tile);
  1399 	RoadTypes rts = GetRoadTypes(tile);
       
  1400 	RoadBits road_bits = IsDriveThroughStopTile(tile) ?
       
  1401 			((GetRoadStopDir(tile) == DIAGDIR_NE) ? ROAD_X : ROAD_Y) :
       
  1402 			DiagDirToRoadBits(GetRoadStopDir(tile));
  1359 	bool is_towns_road = is_drive_through && GetStopBuiltOnTownRoad(tile);
  1403 	bool is_towns_road = is_drive_through && GetStopBuiltOnTownRoad(tile);
  1360 
  1404 
  1361 	int32 ret = RemoveRoadStop(st, flags, tile);
  1405 	int32 ret = RemoveRoadStop(st, flags, tile);
  1362 
  1406 
  1363 	/* If the stop was a drive-through stop replace the road */
  1407 	/* If the stop was a drive-through stop replace the road */
  1367 
  1411 
  1368 		if (is_towns_road) {
  1412 		if (is_towns_road) {
  1369 			index = ClosestTownFromTile(tile, (uint)-1)->index;
  1413 			index = ClosestTownFromTile(tile, (uint)-1)->index;
  1370 			_current_player = OWNER_TOWN;
  1414 			_current_player = OWNER_TOWN;
  1371 		}
  1415 		}
  1372 		DoCommand(tile, road_bits, index, DC_EXEC, CMD_BUILD_ROAD);
  1416 		if (HASBIT(rts, ROADTYPE_ROAD)) {
       
  1417 			DoCommand(tile, ROADTYPE_ROAD << 4 | road_bits, index, DC_EXEC, CMD_BUILD_ROAD);
       
  1418 		}
       
  1419 		if (HASBIT(rts, ROADTYPE_TRAM)) {
       
  1420 			DoCommand(tile, ROADTYPE_TRAM << 4 | road_bits, index, DC_EXEC, CMD_BUILD_ROAD);
       
  1421 		}
  1373 		_current_player = cur_owner;
  1422 		_current_player = cur_owner;
  1374 	}
  1423 	}
  1375 
  1424 
  1376 	return ret;
  1425 	return ret;
  1377 }
  1426 }
  2640 {
  2689 {
  2641 	/* The road can always be cleared if it was not a town-owned road */
  2690 	/* The road can always be cleared if it was not a town-owned road */
  2642 	if (!GetStopBuiltOnTownRoad(tile)) return true;
  2691 	if (!GetStopBuiltOnTownRoad(tile)) return true;
  2643 
  2692 
  2644 	bool edge_road;
  2693 	bool edge_road;
  2645 	return CheckAllowRemoveRoad(tile, GetAnyRoadBits(tile), OWNER_TOWN, &edge_road);
  2694 	return CheckAllowRemoveRoad(tile, GetAnyRoadBits(tile, ROADTYPE_ROAD), OWNER_TOWN, &edge_road, ROADTYPE_ROAD) &&
       
  2695 				CheckAllowRemoveRoad(tile, GetAnyRoadBits(tile, ROADTYPE_TRAM), OWNER_TOWN, &edge_road, ROADTYPE_TRAM);
  2646 }
  2696 }
  2647 
  2697 
  2648 static int32 ClearTile_Station(TileIndex tile, byte flags)
  2698 static int32 ClearTile_Station(TileIndex tile, byte flags)
  2649 {
  2699 {
  2650 	if (flags & DC_AUTO) {
  2700 	if (flags & DC_AUTO) {