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 */ |