45 |
45 |
46 Foundation GetRoadFoundation(Slope tileh, RoadBits bits); |
46 Foundation GetRoadFoundation(Slope tileh, RoadBits bits); |
47 |
47 |
48 bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, bool *edge_road, RoadType rt) |
48 bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, bool *edge_road, RoadType rt) |
49 { |
49 { |
50 RoadBits present; |
|
51 RoadBits n; |
|
52 *edge_road = true; |
50 *edge_road = true; |
53 |
51 |
54 if (_game_mode == GM_EDITOR || remove == ROAD_NONE) return true; |
52 if (_game_mode == GM_EDITOR || remove == ROAD_NONE) return true; |
55 |
53 |
56 /* Water can always flood and towns can always remove "normal" road pieces. |
54 /* Water can always flood and towns can always remove "normal" road pieces. |
64 if (owner != OWNER_TOWN) return (owner == OWNER_NONE) || CheckOwnership(owner); |
62 if (owner != OWNER_TOWN) return (owner == OWNER_NONE) || CheckOwnership(owner); |
65 |
63 |
66 if (_cheats.magic_bulldozer.value) return true; |
64 if (_cheats.magic_bulldozer.value) return true; |
67 |
65 |
68 /* Get a bitmask of which neighbouring roads has a tile */ |
66 /* Get a bitmask of which neighbouring roads has a tile */ |
69 n = ROAD_NONE; |
67 RoadBits n = ROAD_NONE; |
70 present = GetAnyRoadBits(tile, rt); |
68 RoadBits present = GetAnyRoadBits(tile, rt); |
71 if (present & ROAD_NE && GetAnyRoadBits(TILE_ADDXY(tile, -1, 0), rt) & ROAD_SW) n |= ROAD_NE; |
69 if (present & ROAD_NE && GetAnyRoadBits(TILE_ADDXY(tile, -1, 0), rt) & ROAD_SW) n |= ROAD_NE; |
72 if (present & ROAD_SE && GetAnyRoadBits(TILE_ADDXY(tile, 0, 1), rt) & ROAD_NW) n |= ROAD_SE; |
70 if (present & ROAD_SE && GetAnyRoadBits(TILE_ADDXY(tile, 0, 1), rt) & ROAD_NW) n |= ROAD_SE; |
73 if (present & ROAD_SW && GetAnyRoadBits(TILE_ADDXY(tile, 1, 0), rt) & ROAD_NE) n |= ROAD_SW; |
71 if (present & ROAD_SW && GetAnyRoadBits(TILE_ADDXY(tile, 1, 0), rt) & ROAD_NE) n |= ROAD_SW; |
74 if (present & ROAD_NW && GetAnyRoadBits(TILE_ADDXY(tile, 0, -1), rt) & ROAD_SE) n |= ROAD_NW; |
72 if (present & ROAD_NW && GetAnyRoadBits(TILE_ADDXY(tile, 0, -1), rt) & ROAD_SE) n |= ROAD_NW; |
75 |
73 |
76 /* If 0 or 1 bits are set in n, or if no bits that match the bits to remove, |
74 /* If 0 or 1 bits are set in n, or if no bits that match the bits to remove, |
77 * then allow it */ |
75 * then allow it */ |
78 if ((n & (n - 1)) != 0 && (n & remove) != 0) { |
76 if (KillFirstBit(n) != ROAD_NONE && (n & remove) != ROAD_NONE) { |
79 Town *t; |
|
80 *edge_road = false; |
77 *edge_road = false; |
81 /* you can remove all kind of roads with extra dynamite */ |
78 /* you can remove all kind of roads with extra dynamite */ |
82 if (_patches.extra_dynamite) return true; |
79 if (_patches.extra_dynamite) return true; |
83 |
80 |
84 t = ClosestTownFromTile(tile, (uint)-1); |
81 const Town *t = ClosestTownFromTile(tile, (uint)-1); |
85 |
82 |
86 SetDParam(0, t->index); |
83 SetDParam(0, t->index); |
87 _error_message = STR_2009_LOCAL_AUTHORITY_REFUSES; |
84 _error_message = STR_2009_LOCAL_AUTHORITY_REFUSES; |
88 return false; |
85 return false; |
89 } |
86 } |
177 } |
174 } |
178 |
175 |
179 switch (GetRoadTileType(tile)) { |
176 switch (GetRoadTileType(tile)) { |
180 case ROAD_TILE_NORMAL: { |
177 case ROAD_TILE_NORMAL: { |
181 RoadBits present = GetRoadBits(tile, rt); |
178 RoadBits present = GetRoadBits(tile, rt); |
182 RoadBits c = pieces; |
|
183 |
179 |
184 if (HasRoadWorks(tile)) return_cmd_error(STR_ROAD_WORKS_IN_PROGRESS); |
180 if (HasRoadWorks(tile)) return_cmd_error(STR_ROAD_WORKS_IN_PROGRESS); |
185 |
181 |
186 if (GetTileSlope(tile, NULL) != SLOPE_FLAT && |
182 if (GetTileSlope(tile, NULL) != SLOPE_FLAT && IsStraightRoad(present)) { |
187 (present == ROAD_Y || present == ROAD_X)) { |
183 pieces |= MirrorRoadBits(pieces); |
188 c |= (RoadBits)((c & 0xC) >> 2); |
|
189 c |= (RoadBits)((c & 0x3) << 2); |
|
190 } |
184 } |
191 |
185 |
192 /* limit the bits to delete to the existing bits. */ |
186 /* limit the bits to delete to the existing bits. */ |
193 c &= present; |
187 pieces &= present; |
194 if (c == ROAD_NONE) return CMD_ERROR; |
188 if (pieces == ROAD_NONE) return CMD_ERROR; |
195 |
189 |
196 ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM); |
190 ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM); |
197 if (flags & DC_EXEC) { |
191 if (flags & DC_EXEC) { |
198 present ^= c; |
192 present ^= pieces; |
199 if (present == ROAD_NONE) { |
193 if (present == ROAD_NONE) { |
200 RoadTypes rts = GetRoadTypes(tile) & ComplementRoadTypes(RoadTypeToRoadTypes(rt)); |
194 RoadTypes rts = GetRoadTypes(tile) & ComplementRoadTypes(RoadTypeToRoadTypes(rt)); |
201 if (rts == ROADTYPES_NONE) { |
195 if (rts == ROADTYPES_NONE) { |
202 /* Includes MarkTileDirtyByTile() */ |
196 /* Includes MarkTileDirtyByTile() */ |
203 DoClearSquare(tile); |
197 DoClearSquare(tile); |
213 if (rt != ROADTYPE_TRAM) SetDisallowedRoadDirections(tile, DRD_NONE); |
207 if (rt != ROADTYPE_TRAM) SetDisallowedRoadDirections(tile, DRD_NONE); |
214 SetRoadBits(tile, present, rt); |
208 SetRoadBits(tile, present, rt); |
215 MarkTileDirtyByTile(tile); |
209 MarkTileDirtyByTile(tile); |
216 } |
210 } |
217 } |
211 } |
218 return CommandCost(EXPENSES_CONSTRUCTION, CountBits(c) * _price.remove_road); |
212 return CommandCost(EXPENSES_CONSTRUCTION, CountBits(pieces) * _price.remove_road); |
219 } |
213 } |
220 |
214 |
221 case ROAD_TILE_CROSSING: { |
215 case ROAD_TILE_CROSSING: { |
222 if (pieces & ComplementRoadBits(GetCrossingRoadBits(tile))) { |
216 if (pieces & ComplementRoadBits(GetCrossingRoadBits(tile))) { |
223 return CMD_ERROR; |
217 return CMD_ERROR; |
348 * @param existing The existent RoadBits |
342 * @param existing The existent RoadBits |
349 * @return The costs for these RoadBits on this slope |
343 * @return The costs for these RoadBits on this slope |
350 */ |
344 */ |
351 static CommandCost CheckRoadSlope(Slope tileh, RoadBits* pieces, RoadBits existing) |
345 static CommandCost CheckRoadSlope(Slope tileh, RoadBits* pieces, RoadBits existing) |
352 { |
346 { |
|
347 /* Proceed steep Slopes first to reduce lookup table size */ |
353 if (IsSteepSlope(tileh)) { |
348 if (IsSteepSlope(tileh)) { |
354 /* Force straight roads. */ |
349 /* Force straight roads. */ |
355 *pieces |= MirrorRoadBits(*pieces); |
350 *pieces |= MirrorRoadBits(*pieces); |
356 |
351 |
357 if (existing == ROAD_NONE || existing == *pieces) { |
352 if (existing == ROAD_NONE || existing == *pieces) { |
404 { |
399 { |
405 CommandCost cost(EXPENSES_CONSTRUCTION); |
400 CommandCost cost(EXPENSES_CONSTRUCTION); |
406 CommandCost ret; |
401 CommandCost ret; |
407 RoadBits existing = ROAD_NONE; |
402 RoadBits existing = ROAD_NONE; |
408 RoadBits all_bits = ROAD_NONE; |
403 RoadBits all_bits = ROAD_NONE; |
409 Slope tileh; |
|
410 |
404 |
411 /* Road pieces are max 4 bitset values (NE, NW, SE, SW) and town can only be non-zero |
405 /* Road pieces are max 4 bitset values (NE, NW, SE, SW) and town can only be non-zero |
412 * if a non-player is building the road */ |
406 * if a non-player is building the road */ |
413 if ((IsValidPlayer(_current_player) && p2 != 0) || (_current_player == OWNER_TOWN && !IsValidTownID(p2))) return CMD_ERROR; |
407 if ((IsValidPlayer(_current_player) && p2 != 0) || (_current_player == OWNER_TOWN && !IsValidTownID(p2))) return CMD_ERROR; |
414 |
408 |
420 RoadType rt = (RoadType)GB(p1, 4, 2); |
414 RoadType rt = (RoadType)GB(p1, 4, 2); |
421 if (!IsValidRoadType(rt) || !ValParamRoadType(rt)) return CMD_ERROR; |
415 if (!IsValidRoadType(rt) || !ValParamRoadType(rt)) return CMD_ERROR; |
422 |
416 |
423 DisallowedRoadDirections toggle_drd = (DisallowedRoadDirections)GB(p1, 6, 2); |
417 DisallowedRoadDirections toggle_drd = (DisallowedRoadDirections)GB(p1, 6, 2); |
424 |
418 |
425 tileh = GetTileSlope(tile, NULL); |
419 Slope tileh = GetTileSlope(tile, NULL); |
426 |
420 |
427 switch (GetTileType(tile)) { |
421 switch (GetTileType(tile)) { |
428 case MP_ROAD: |
422 case MP_ROAD: |
429 switch (GetRoadTileType(tile)) { |
423 switch (GetRoadTileType(tile)) { |
430 case ROAD_TILE_NORMAL: { |
424 case ROAD_TILE_NORMAL: { |
432 |
426 |
433 all_bits = GetAllRoadBits(tile); |
427 all_bits = GetAllRoadBits(tile); |
434 if (!HasTileRoadType(tile, rt)) break; |
428 if (!HasTileRoadType(tile, rt)) break; |
435 |
429 |
436 existing = GetRoadBits(tile, rt); |
430 existing = GetRoadBits(tile, rt); |
437 RoadBits merged = existing | pieces; |
431 bool crossing = !IsStraightRoad(existing | pieces); |
438 bool crossing = (merged != ROAD_X && merged != ROAD_Y); |
|
439 if (rt != ROADTYPE_TRAM && (GetDisallowedRoadDirections(tile) != DRD_NONE || toggle_drd != DRD_NONE) && crossing) { |
432 if (rt != ROADTYPE_TRAM && (GetDisallowedRoadDirections(tile) != DRD_NONE || toggle_drd != DRD_NONE) && crossing) { |
440 /* Junctions cannot be one-way */ |
433 /* Junctions cannot be one-way */ |
441 return_cmd_error(STR_ERR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION); |
434 return_cmd_error(STR_ERR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION); |
442 } |
435 } |
443 if ((existing & pieces) == pieces) { |
436 if ((existing & pieces) == pieces) { |
446 if (crossing) return_cmd_error(STR_ERR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION); |
439 if (crossing) return_cmd_error(STR_ERR_ONEWAY_ROADS_CAN_T_HAVE_JUNCTION); |
447 |
440 |
448 if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; |
441 if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; |
449 |
442 |
450 /* Ignore half built tiles */ |
443 /* Ignore half built tiles */ |
451 if (flags & DC_EXEC && rt != ROADTYPE_TRAM && (existing == ROAD_X || existing == ROAD_Y)) { |
444 if (flags & DC_EXEC && rt != ROADTYPE_TRAM && IsStraightRoad(existing)) { |
452 SetDisallowedRoadDirections(tile, GetDisallowedRoadDirections(tile) ^ toggle_drd); |
445 SetDisallowedRoadDirections(tile, GetDisallowedRoadDirections(tile) ^ toggle_drd); |
453 MarkTileDirtyByTile(tile); |
446 MarkTileDirtyByTile(tile); |
454 } |
447 } |
455 return CommandCost(); |
448 return CommandCost(); |
456 } |
449 } |
898 byte subcoord_y; |
891 byte subcoord_y; |
899 }; |
892 }; |
900 |
893 |
901 #include "table/road_land.h" |
894 #include "table/road_land.h" |
902 |
895 |
903 |
896 /** |
|
897 * Get the foundationtype of a RoadBits Slope combination |
|
898 * |
|
899 * @param tileh The Slope part |
|
900 * @param bits The RoadBits part |
|
901 * @return The resulting Foundation |
|
902 */ |
904 Foundation GetRoadFoundation(Slope tileh, RoadBits bits) |
903 Foundation GetRoadFoundation(Slope tileh, RoadBits bits) |
905 { |
904 { |
|
905 /* Flat land and land without a road doesn't require a foundation */ |
|
906 if (tileh == SLOPE_FLAT || bits == ROAD_NONE) return FOUNDATION_NONE; |
|
907 |
906 if (!IsSteepSlope(tileh)) { |
908 if (!IsSteepSlope(tileh)) { |
907 if ((~_valid_tileh_slopes_road[0][tileh] & bits) == 0) { |
909 if ((~_valid_tileh_slopes_road[0][tileh] & bits) == ROAD_NONE) { |
908 /* As one can remove a single road piece when in a corner on a foundation as |
910 /* As one can remove a single road piece when in a corner on a foundation as |
909 * it is on a sloped piece of landscape, one creates a state that cannot be |
911 * it is on a sloped piece of landscape, one creates a state that cannot be |
910 * created directly, but the state itself is still perfectly drawable. |
912 * created directly, but the state itself is still perfectly drawable. |
911 * However, as we do not want this to be build directly, we need to check |
913 * However, as we do not want this to be build directly, we need to check |
912 * for that situation in here. */ |
914 * for that situation in here. */ |
913 return (tileh != 0 && CountBits(bits) == 1) ? FOUNDATION_LEVELED : FOUNDATION_NONE; |
915 return (CountBits(bits) == 1) ? FOUNDATION_LEVELED : FOUNDATION_NONE; |
914 } |
916 } |
915 if ((~_valid_tileh_slopes_road[1][tileh] & bits) == 0) return FOUNDATION_LEVELED; |
917 if ((~_valid_tileh_slopes_road[1][tileh] & bits) == ROAD_NONE) return FOUNDATION_LEVELED; |
916 } |
918 } |
917 |
919 |
918 return (bits == ROAD_X ? FOUNDATION_INCLINED_X : FOUNDATION_INCLINED_Y); |
920 return (bits == ROAD_X ? FOUNDATION_INCLINED_X : FOUNDATION_INCLINED_Y); |
919 } |
921 } |
920 |
922 |