38 if (r & ROAD_NE) ++count; |
39 if (r & ROAD_NE) ++count; |
39 return count; |
40 return count; |
40 } |
41 } |
41 |
42 |
42 |
43 |
43 bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, bool *edge_road) |
44 bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, bool *edge_road, RoadType rt) |
44 { |
45 { |
45 RoadBits present; |
46 RoadBits present; |
46 RoadBits n; |
47 RoadBits n; |
47 *edge_road = true; |
48 *edge_road = true; |
48 |
49 |
49 if (_game_mode == GM_EDITOR) return true; |
50 if (_game_mode == GM_EDITOR || remove == ROAD_NONE) return true; |
50 |
51 |
51 /* Only do the special processing for actual players. */ |
52 /* Only do the special processing for actual players. */ |
52 if (!IsValidPlayer(_current_player)) return true; |
53 if (!IsValidPlayer(_current_player)) return true; |
53 |
54 |
54 /* Only do the special processing if the road is owned |
55 /* Only do the special processing if the road is owned |
57 |
58 |
58 if (_cheats.magic_bulldozer.value) return true; |
59 if (_cheats.magic_bulldozer.value) return true; |
59 |
60 |
60 /* Get a bitmask of which neighbouring roads has a tile */ |
61 /* Get a bitmask of which neighbouring roads has a tile */ |
61 n = ROAD_NONE; |
62 n = ROAD_NONE; |
62 present = GetAnyRoadBits(tile); |
63 present = GetAnyRoadBits(tile, rt); |
63 if (present & ROAD_NE && GetAnyRoadBits(TILE_ADDXY(tile, -1, 0)) & ROAD_SW) n |= ROAD_NE; |
64 if (present & ROAD_NE && GetAnyRoadBits(TILE_ADDXY(tile, -1, 0), rt) & ROAD_SW) n |= ROAD_NE; |
64 if (present & ROAD_SE && GetAnyRoadBits(TILE_ADDXY(tile, 0, 1)) & ROAD_NW) n |= ROAD_SE; |
65 if (present & ROAD_SE && GetAnyRoadBits(TILE_ADDXY(tile, 0, 1), rt) & ROAD_NW) n |= ROAD_SE; |
65 if (present & ROAD_SW && GetAnyRoadBits(TILE_ADDXY(tile, 1, 0)) & ROAD_NE) n |= ROAD_SW; |
66 if (present & ROAD_SW && GetAnyRoadBits(TILE_ADDXY(tile, 1, 0), rt) & ROAD_NE) n |= ROAD_SW; |
66 if (present & ROAD_NW && GetAnyRoadBits(TILE_ADDXY(tile, 0, -1)) & ROAD_SE) n |= ROAD_NW; |
67 if (present & ROAD_NW && GetAnyRoadBits(TILE_ADDXY(tile, 0, -1), rt) & ROAD_SE) n |= ROAD_NW; |
67 |
68 |
68 /* If 0 or 1 bits are set in n, or if no bits that match the bits to remove, |
69 /* If 0 or 1 bits are set in n, or if no bits that match the bits to remove, |
69 * then allow it */ |
70 * then allow it */ |
70 if ((n & (n - 1)) != 0 && (n & remove) != 0) { |
71 if ((n & (n - 1)) != 0 && (n & remove) != 0) { |
71 Town *t; |
72 Town *t; |
81 } |
82 } |
82 |
83 |
83 return true; |
84 return true; |
84 } |
85 } |
85 |
86 |
86 static bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, bool *edge_road) |
87 static bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, bool *edge_road, RoadType rt) |
87 { |
88 { |
88 return CheckAllowRemoveRoad(tile, remove, IsLevelCrossingTile(tile) ? GetCrossingRoadOwner(tile) : GetTileOwner(tile), edge_road); |
89 return CheckAllowRemoveRoad(tile, remove, GetRoadOwner(tile, rt), edge_road, rt); |
89 } |
90 } |
90 |
91 |
91 /** Delete a piece of road. |
92 /** Delete a piece of road. |
92 * @param tile tile where to remove road from |
93 * @param tile tile where to remove road from |
93 * @param flags operation to perform |
94 * @param flags operation to perform |
94 * @param p1 bit 0..3 road pieces to remove (RoadBits) |
95 * @param p1 bit 0..3 road pieces to remove (RoadBits) |
|
96 * bit 4..5 road type |
95 * @param p2 unused |
97 * @param p2 unused |
96 */ |
98 */ |
97 int32 CmdRemoveRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
99 int32 CmdRemoveRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
98 { |
100 { |
99 /* cost for removing inner/edge -roads */ |
101 /* cost for removing inner/edge -roads */ |
100 static const uint16 road_remove_cost[2] = {50, 18}; |
102 static const uint16 road_remove_cost[2] = {50, 18}; |
101 |
103 |
102 Owner owner; |
|
103 Town *t; |
104 Town *t; |
104 /* true if the roadpiece was always removeable, |
105 /* true if the roadpiece was always removeable, |
105 * false if it was a center piece. Affects town ratings drop */ |
106 * false if it was a center piece. Affects town ratings drop */ |
106 bool edge_road; |
107 bool edge_road; |
107 |
108 |
108 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
109 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
109 |
110 |
110 if (!IsTileType(tile, MP_STREET)) return CMD_ERROR; |
111 RoadType rt = (RoadType)GB(p1, 4, 2); |
111 |
112 if (!IsTileType(tile, MP_STREET) || !IsValidRoadType(rt)) return CMD_ERROR; |
112 owner = IsLevelCrossingTile(tile) ? GetCrossingRoadOwner(tile) : GetTileOwner(tile); |
113 |
|
114 Owner owner = GetRoadOwner(tile, rt); |
113 |
115 |
114 if (owner == OWNER_TOWN && _game_mode != GM_EDITOR) { |
116 if (owner == OWNER_TOWN && _game_mode != GM_EDITOR) { |
115 t = GetTownByTile(tile); |
117 t = GetTownByTile(tile); |
116 } else { |
118 } else { |
117 t = NULL; |
119 t = NULL; |
118 } |
120 } |
119 |
121 |
120 RoadBits pieces = Extract<RoadBits, 0>(p1); |
122 RoadBits pieces = Extract<RoadBits, 0>(p1); |
121 |
123 RoadTypes rts = GetRoadTypes(tile); |
122 if (!CheckAllowRemoveRoad(tile, pieces, &edge_road)) return CMD_ERROR; |
124 /* The tile doesn't have the given road type */ |
|
125 if (!HASBIT(rts, rt)) return CMD_ERROR; |
|
126 |
|
127 if (!CheckAllowRemoveRoad(tile, pieces, &edge_road, rt)) return CMD_ERROR; |
123 |
128 |
124 if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; |
129 if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; |
125 |
130 |
126 /* check if you're allowed to remove the street owned by a town |
131 /* check if you're allowed to remove the street owned by a town |
127 * removal allowance depends on difficulty setting */ |
132 * removal allowance depends on difficulty setting */ |
128 if (!CheckforTownRating(flags, t, ROAD_REMOVE)) return CMD_ERROR; |
133 if (!CheckforTownRating(flags, t, ROAD_REMOVE)) return CMD_ERROR; |
129 |
134 |
130 switch (GetRoadTileType(tile)) { |
135 switch (GetRoadTileType(tile)) { |
131 case ROAD_TILE_NORMAL: { |
136 case ROAD_TILE_NORMAL: { |
132 RoadBits present = GetRoadBits(tile); |
137 RoadBits present = GetRoadBits(tile, rt); |
133 RoadBits c = pieces; |
138 RoadBits c = pieces; |
134 |
139 |
135 if (HasRoadWorks(tile)) return_cmd_error(STR_ROAD_WORKS_IN_PROGRESS); |
140 if (HasRoadWorks(tile)) return_cmd_error(STR_ROAD_WORKS_IN_PROGRESS); |
136 |
141 |
137 if (GetTileSlope(tile, NULL) != SLOPE_FLAT && |
142 if (GetTileSlope(tile, NULL) != SLOPE_FLAT && |
140 c |= (RoadBits)((c & 0x3) << 2); |
145 c |= (RoadBits)((c & 0x3) << 2); |
141 } |
146 } |
142 |
147 |
143 /* limit the bits to delete to the existing bits. */ |
148 /* limit the bits to delete to the existing bits. */ |
144 c &= present; |
149 c &= present; |
145 if (c == 0) return CMD_ERROR; |
150 if (c == ROAD_NONE) return CMD_ERROR; |
146 |
151 |
147 present ^= c; |
152 present ^= c; |
148 if (flags & DC_EXEC) { |
153 if (flags & DC_EXEC) { |
149 ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM); |
154 ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM); |
150 |
155 |
151 if (present == 0) { |
156 if (present == ROAD_NONE) { |
152 DoClearSquare(tile); |
157 RoadTypes rts = GetRoadTypes(tile) & ComplementRoadTypes(RoadTypeToRoadTypes(rt)); |
|
158 if (rts == ROADTYPES_NONE) { |
|
159 DoClearSquare(tile); |
|
160 } else { |
|
161 SetRoadBits(tile, ROAD_NONE, rt); |
|
162 SetRoadTypes(tile, rts); |
|
163 } |
153 } else { |
164 } else { |
154 SetRoadBits(tile, present); |
165 SetRoadBits(tile, present, rt); |
155 MarkTileDirtyByTile(tile); |
166 MarkTileDirtyByTile(tile); |
156 } |
167 } |
157 } |
168 } |
158 return CountRoadBits(c) * _eco->GetPrice(CEconomy::REMOVE_ROAD, tile, (present == 0)); |
169 return CountRoadBits(c) * _eco->GetPrice(CEconomy::REMOVE_ROAD, tile, (present == 0)); |
159 } |
170 } |
162 if (pieces & ComplementRoadBits(GetCrossingRoadBits(tile))) { |
173 if (pieces & ComplementRoadBits(GetCrossingRoadBits(tile))) { |
163 return CMD_ERROR; |
174 return CMD_ERROR; |
164 } |
175 } |
165 |
176 |
166 if (flags & DC_EXEC) { |
177 if (flags & DC_EXEC) { |
167 ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM); |
178 if (rt == ROADTYPE_ROAD) { |
168 |
179 ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM); |
169 MakeRailNormal(tile, GetTileOwner(tile), GetCrossingRailBits(tile), GetRailType(tile)); |
180 } |
|
181 |
|
182 RoadTypes rts = GetRoadTypes(tile) & ComplementRoadTypes(RoadTypeToRoadTypes(rt)); |
|
183 if (rts == ROADTYPES_NONE) { |
|
184 MakeRailNormal(tile, GetTileOwner(tile), GetCrossingRailBits(tile), GetRailType(tile)); |
|
185 } else { |
|
186 SetRoadTypes(tile, rts); |
|
187 } |
170 MarkTileDirtyByTile(tile); |
188 MarkTileDirtyByTile(tile); |
171 YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetTrackBits(tile))); |
189 YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetTrackBits(tile))); |
172 } |
190 } |
173 return _eco->GetPrice(CEconomy::REMOVE_ROAD) * 2; |
191 return _eco->GetPrice(CEconomy::REMOVE_ROAD) * 2; |
174 } |
192 } |
268 /* Road pieces are max 4 bitset values (NE, NW, SE, SW) and town can only be non-zero |
287 /* Road pieces are max 4 bitset values (NE, NW, SE, SW) and town can only be non-zero |
269 * if a non-player is building the road */ |
288 * if a non-player is building the road */ |
270 if ((IsValidPlayer(_current_player) && p2 != 0) || (_current_player == OWNER_TOWN && !IsValidTownID(p2))) return CMD_ERROR; |
289 if ((IsValidPlayer(_current_player) && p2 != 0) || (_current_player == OWNER_TOWN && !IsValidTownID(p2))) return CMD_ERROR; |
271 |
290 |
272 RoadBits pieces = Extract<RoadBits, 0>(p1); |
291 RoadBits pieces = Extract<RoadBits, 0>(p1); |
|
292 |
|
293 RoadType rt = (RoadType)GB(p1, 4, 2); |
|
294 if (!IsValidRoadType(rt)) return CMD_ERROR; |
273 |
295 |
274 tileh = GetTileSlope(tile, NULL); |
296 tileh = GetTileSlope(tile, NULL); |
275 |
297 |
276 switch (GetTileType(tile)) { |
298 switch (GetTileType(tile)) { |
277 case MP_STREET: |
299 case MP_STREET: |
278 switch (GetRoadTileType(tile)) { |
300 switch (GetRoadTileType(tile)) { |
279 case ROAD_TILE_NORMAL: |
301 case ROAD_TILE_NORMAL: |
280 if (HasRoadWorks(tile)) return_cmd_error(STR_ROAD_WORKS_IN_PROGRESS); |
302 if (HasRoadWorks(tile)) return_cmd_error(STR_ROAD_WORKS_IN_PROGRESS); |
281 |
303 if (!HASBIT(GetRoadTypes(tile), rt)) break; |
282 existing = GetRoadBits(tile); |
304 |
|
305 existing = GetRoadBits(tile, rt); |
283 if ((existing & pieces) == pieces) { |
306 if ((existing & pieces) == pieces) { |
284 return_cmd_error(STR_1007_ALREADY_BUILT); |
307 return_cmd_error(STR_1007_ALREADY_BUILT); |
285 } |
308 } |
286 if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; |
309 if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; |
287 break; |
310 break; |
288 |
311 |
289 case ROAD_TILE_CROSSING: |
312 case ROAD_TILE_CROSSING: |
290 if (pieces != GetCrossingRoadBits(tile)) { // XXX is this correct? |
313 if (HASBIT(GetRoadTypes(tile), rt)) return_cmd_error(STR_1007_ALREADY_BUILT); |
291 return_cmd_error(STR_1007_ALREADY_BUILT); |
314 if (pieces & ComplementRoadBits(GetCrossingRoadBits(tile))) goto do_clear; |
292 } |
315 break; |
293 goto do_clear; |
|
294 |
316 |
295 default: |
317 default: |
296 case ROAD_TILE_DEPOT: |
318 case ROAD_TILE_DEPOT: |
297 goto do_clear; |
319 goto do_clear; |
298 } |
320 } |
329 |
351 |
330 if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; |
352 if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; |
331 |
353 |
332 if (flags & DC_EXEC) { |
354 if (flags & DC_EXEC) { |
333 YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetTrackBits(tile))); |
355 YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetTrackBits(tile))); |
334 MakeRoadCrossing(tile, _current_player, GetTileOwner(tile), roaddir, GetRailType(tile), p2); |
356 MakeRoadCrossing(tile, _current_player, _current_player, _current_player, GetTileOwner(tile), roaddir, GetRailType(tile), RoadTypeToRoadTypes(rt), p2); |
335 MarkTileDirtyByTile(tile); |
357 MarkTileDirtyByTile(tile); |
336 } |
358 } |
337 /** @todo should be more expensive */ |
359 /** @todo should be more expensive */ |
338 return _eco->GetPrice(CEconomy::BUILD_ROAD) * 2; |
360 return _eco->GetPrice(CEconomy::BUILD_ROAD) * 2; |
339 } |
361 } |
363 } |
385 } |
364 |
386 |
365 |
387 |
366 if (flags & DC_EXEC) { |
388 if (flags & DC_EXEC) { |
367 if (IsTileType(tile, MP_STREET)) { |
389 if (IsTileType(tile, MP_STREET)) { |
368 SetRoadBits(tile, existing | pieces); |
390 if (existing == ROAD_NONE) { |
|
391 SetRoadTypes(tile, GetRoadTypes(tile) | RoadTypeToRoadTypes(rt)); |
|
392 SetRoadOwner(tile, rt, _current_player); |
|
393 } |
|
394 SetRoadBits(tile, existing | pieces, rt); |
369 } else { |
395 } else { |
370 MakeRoadNormal(tile, _current_player, pieces, p2); |
396 MakeRoadNormal(tile, pieces, RoadTypeToRoadTypes(rt), p2, _current_player, _current_player, _current_player); |
371 } |
397 } |
372 |
398 |
373 MarkTileDirtyByTile(tile); |
399 MarkTileDirtyByTile(tile); |
374 } |
400 } |
375 return cost; |
401 return cost; |
412 * @param p1 start tile of drag |
438 * @param p1 start tile of drag |
413 * @param p2 various bitstuffed elements |
439 * @param p2 various bitstuffed elements |
414 * - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1) |
440 * - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1) |
415 * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2) |
441 * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2) |
416 * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4) |
442 * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4) |
|
443 * - p2 = (bit 3 + 4) - road type |
417 */ |
444 */ |
418 int32 CmdBuildLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2) |
445 int32 CmdBuildLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2) |
419 { |
446 { |
420 TileIndex start_tile, tile; |
447 TileIndex start_tile, tile; |
421 int32 cost, ret; |
448 int32 cost, ret; |
445 RoadBits bits = HASBIT(p2, 2) ? ROAD_Y : ROAD_X; |
474 RoadBits bits = HASBIT(p2, 2) ? ROAD_Y : ROAD_X; |
446 |
475 |
447 if (tile == end_tile && !HASBIT(p2, 1)) bits &= ROAD_NW | ROAD_NE; |
476 if (tile == end_tile && !HASBIT(p2, 1)) bits &= ROAD_NW | ROAD_NE; |
448 if (tile == start_tile && HASBIT(p2, 0)) bits &= ROAD_SE | ROAD_SW; |
477 if (tile == start_tile && HASBIT(p2, 0)) bits &= ROAD_SE | ROAD_SW; |
449 |
478 |
450 ret = DoCommand(tile, bits, 0, flags, CMD_BUILD_ROAD); |
479 ret = DoCommand(tile, rt << 4 | bits, 0, flags, CMD_BUILD_ROAD); |
451 if (CmdFailed(ret)) { |
480 if (CmdFailed(ret)) { |
452 if (_error_message != STR_1007_ALREADY_BUILT) return CMD_ERROR; |
481 if (_error_message != STR_1007_ALREADY_BUILT) return CMD_ERROR; |
453 _error_message = INVALID_STRING_ID; |
482 _error_message = INVALID_STRING_ID; |
454 } else { |
483 } else { |
455 cost += ret; |
484 cost += ret; |
469 * @param p1 start tile of drag |
498 * @param p1 start tile of drag |
470 * @param p2 various bitstuffed elements |
499 * @param p2 various bitstuffed elements |
471 * - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1) |
500 * - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1) |
472 * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2) |
501 * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2) |
473 * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4) |
502 * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4) |
|
503 * - p2 = (bit 3 + 4) - road type |
474 */ |
504 */ |
475 int32 CmdRemoveLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2) |
505 int32 CmdRemoveLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2) |
476 { |
506 { |
477 TileIndex start_tile, tile; |
507 TileIndex start_tile, tile; |
478 int32 cost, ret; |
508 int32 cost, ret; |
504 if (tile == end_tile && !HASBIT(p2, 1)) bits &= ROAD_NW | ROAD_NE; |
536 if (tile == end_tile && !HASBIT(p2, 1)) bits &= ROAD_NW | ROAD_NE; |
505 if (tile == start_tile && HASBIT(p2, 0)) bits &= ROAD_SE | ROAD_SW; |
537 if (tile == start_tile && HASBIT(p2, 0)) bits &= ROAD_SE | ROAD_SW; |
506 |
538 |
507 /* try to remove the halves. */ |
539 /* try to remove the halves. */ |
508 if (bits != 0) { |
540 if (bits != 0) { |
509 ret = DoCommand(tile, bits, 0, flags, CMD_REMOVE_ROAD); |
541 ret = DoCommand(tile, rt << 4 | bits, 0, flags, CMD_REMOVE_ROAD); |
510 if (!CmdFailed(ret)) cost += ret; |
542 if (!CmdFailed(ret)) cost += ret; |
511 } |
543 } |
512 |
544 |
513 if (tile == end_tile) break; |
545 if (tile == end_tile) break; |
514 |
546 |
580 |
616 |
581 static int32 ClearTile_Road(TileIndex tile, byte flags) |
617 static int32 ClearTile_Road(TileIndex tile, byte flags) |
582 { |
618 { |
583 switch (GetRoadTileType(tile)) { |
619 switch (GetRoadTileType(tile)) { |
584 case ROAD_TILE_NORMAL: { |
620 case ROAD_TILE_NORMAL: { |
585 RoadBits b = GetRoadBits(tile); |
621 RoadBits b = GetAllRoadBits(tile); |
586 |
622 |
587 #define M(x) (1 << (x)) |
623 #define M(x) (1 << (x)) |
588 /* Clear the road if only one piece is on the tile OR the AI tries |
624 /* Clear the road if only one piece is on the tile OR the AI tries |
589 * to clear town road OR we are not using the DC_AUTO flag */ |
625 * to clear town road OR we are not using the DC_AUTO flag */ |
590 if ((M(b) & (M(ROAD_NW) | M(ROAD_SW) | M(ROAD_SE) | M(ROAD_NE))) || |
626 if ((M(b) & (M(ROAD_NW) | M(ROAD_SW) | M(ROAD_SE) | M(ROAD_NE))) || |
666 3, 0, 0, 0, |
702 3, 0, 0, 0, |
667 0, 0 |
703 0, 0 |
668 }; |
704 }; |
669 |
705 |
670 /** |
706 /** |
|
707 * Whether to draw unpaved roads regardless of the town zone. |
|
708 * By default, OpenTTD always draws roads as unpaved if they are on a desert |
|
709 * tile or above the snowline. Newgrf files, however, can set a bit that allows |
|
710 * paved roads to be built on desert tiles as they would be on grassy tiles. |
|
711 * |
|
712 * @param tile The tile the road is on |
|
713 * @param roadside What sort of road this is |
|
714 * @return True if the road should be drawn unpaved regardless of the roadside. |
|
715 */ |
|
716 static bool AlwaysDrawUnpavedRoads(TileIndex tile, Roadside roadside) |
|
717 { |
|
718 return (IsOnSnow(tile) && |
|
719 !(_opt.landscape == LT_TROPIC && HasGrfMiscBit(GMB_DESERT_PAVED_ROADS) && |
|
720 roadside != ROADSIDE_BARREN && roadside != ROADSIDE_GRASS && roadside != ROADSIDE_GRASS_ROAD_WORKS)); |
|
721 } |
|
722 |
|
723 /** |
671 * Draw ground sprite and road pieces |
724 * Draw ground sprite and road pieces |
672 * @param ti TileInfo |
725 * @param ti TileInfo |
673 */ |
726 */ |
674 static void DrawRoadBits(TileInfo* ti) |
727 static void DrawRoadBits(TileInfo* ti) |
675 { |
728 { |
676 RoadBits road = GetRoadBits(ti->tile); |
729 RoadBits road = GetRoadBits(ti->tile, ROADTYPE_ROAD); |
677 const DrawRoadTileStruct *drts; |
730 const DrawRoadTileStruct *drts; |
678 SpriteID image = 0; |
731 SpriteID image = 0; |
679 SpriteID pal = PAL_NONE; |
732 SpriteID pal = PAL_NONE; |
680 Roadside roadside; |
733 Roadside roadside; |
681 |
734 |
711 DrawGroundSprite(road & ROAD_X ? SPR_EXCAVATION_X : SPR_EXCAVATION_Y, PAL_NONE); |
764 DrawGroundSprite(road & ROAD_X ? SPR_EXCAVATION_X : SPR_EXCAVATION_Y, PAL_NONE); |
712 return; |
765 return; |
713 } |
766 } |
714 |
767 |
715 /* Return if full detail is disabled, or we are zoomed fully out. */ |
768 /* Return if full detail is disabled, or we are zoomed fully out. */ |
716 if (!(_display_opt & DO_FULL_DETAIL) || _cur_dpi->zoom == 2) return; |
769 if (!HASBIT(_display_opt, DO_FULL_DETAIL) || _cur_dpi->zoom > ZOOM_LVL_DETAIL) return; |
717 |
770 |
718 /* Draw extra details. */ |
771 /* Draw extra details. */ |
719 for (drts = _road_display_table[roadside][road]; drts->image != 0; drts++) { |
772 for (drts = _road_display_table[roadside][road]; drts->image != 0; drts++) { |
720 int x = ti->x | drts->subcoord_x; |
773 int x = ti->x | drts->subcoord_x; |
721 int y = ti->y | drts->subcoord_y; |
774 int y = ti->y | drts->subcoord_y; |
733 break; |
786 break; |
734 |
787 |
735 case ROAD_TILE_CROSSING: { |
788 case ROAD_TILE_CROSSING: { |
736 SpriteID image; |
789 SpriteID image; |
737 SpriteID pal = PAL_NONE; |
790 SpriteID pal = PAL_NONE; |
|
791 Roadside roadside = GetRoadside(ti->tile); |
738 |
792 |
739 if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, ti->tileh); |
793 if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, ti->tileh); |
740 |
794 |
741 image = GetRailTypeInfo(GetRailType(ti->tile))->base_sprites.crossing; |
795 image = GetRailTypeInfo(GetRailType(ti->tile))->base_sprites.crossing; |
742 |
796 |
743 if (GetCrossingRoadAxis(ti->tile) == AXIS_X) image++; |
797 if (GetCrossingRoadAxis(ti->tile) == AXIS_X) image++; |
744 if (IsCrossingBarred(ti->tile)) image += 2; |
798 if (IsCrossingBarred(ti->tile)) image += 2; |
745 |
799 |
746 if (IsOnSnow(ti->tile)) { |
800 if (AlwaysDrawUnpavedRoads(ti->tile, roadside)) { |
747 image += 8; |
801 image += 8; |
748 } else { |
802 } else { |
749 switch (GetRoadside(ti->tile)) { |
803 switch (roadside) { |
750 case ROADSIDE_BARREN: pal = PALETTE_TO_BARE_LAND; break; |
804 case ROADSIDE_BARREN: pal = PALETTE_TO_BARE_LAND; break; |
751 case ROADSIDE_GRASS: break; |
805 case ROADSIDE_GRASS: break; |
752 default: image += 4; break; // Paved |
806 default: image += 4; break; // Paved |
753 } |
807 } |
754 } |
808 } |
841 |
895 |
842 static Slope GetSlopeTileh_Road(TileIndex tile, Slope tileh) |
896 static Slope GetSlopeTileh_Road(TileIndex tile, Slope tileh) |
843 { |
897 { |
844 if (tileh == SLOPE_FLAT) return SLOPE_FLAT; |
898 if (tileh == SLOPE_FLAT) return SLOPE_FLAT; |
845 if (GetRoadTileType(tile) == ROAD_TILE_NORMAL) { |
899 if (GetRoadTileType(tile) == ROAD_TILE_NORMAL) { |
846 uint f = GetRoadFoundation(tileh, GetRoadBits(tile)); |
900 uint f = GetRoadFoundation(tileh, GetAllRoadBits(tile)); |
847 |
901 |
848 if (f == 0) return tileh; |
902 if (f == 0) return tileh; |
849 if (f < 15) return SLOPE_FLAT; // leveled foundation |
903 if (f < 15) return SLOPE_FLAT; // leveled foundation |
850 return _inclined_tileh[f - 15]; // inclined foundation |
904 return _inclined_tileh[f - 15]; // inclined foundation |
851 } else { |
905 } else { |
909 grp = t->GetRadiusGroup(tile); |
963 grp = t->GetRadiusGroup(tile); |
910 |
964 |
911 /* Show an animation to indicate road work */ |
965 /* Show an animation to indicate road work */ |
912 if (t->road_build_months != 0 && |
966 if (t->road_build_months != 0 && |
913 (DistanceManhattan(t->xy, tile) < 8 || grp != 0) && |
967 (DistanceManhattan(t->xy, tile) < 8 || grp != 0) && |
914 GetRoadTileType(tile) == ROAD_TILE_NORMAL && (GetRoadBits(tile) == ROAD_X || GetRoadBits(tile) == ROAD_Y)) { |
968 GetRoadTileType(tile) == ROAD_TILE_NORMAL && (GetAllRoadBits(tile) == ROAD_X || GetAllRoadBits(tile) == ROAD_Y)) { |
915 if (GetTileSlope(tile, NULL) == SLOPE_FLAT && EnsureNoVehicleOnGround(tile) && CHANCE16(1, 20)) { |
969 if (GetTileSlope(tile, NULL) == SLOPE_FLAT && EnsureNoVehicleOnGround(tile) && CHANCE16(1, 20)) { |
916 StartRoadWorks(tile); |
970 StartRoadWorks(tile); |
917 |
971 |
918 SndPlayTileFx(SND_21_JACKHAMMER, tile); |
972 SndPlayTileFx(SND_21_JACKHAMMER, tile); |
919 CreateEffectVehicleAbove( |
973 CreateEffectVehicleAbove( |
963 0x0, 0x0, 0x0, 0x10, 0x0, 0x2, 0x8, 0x1A, 0x0, 0x4, 0x1, 0x15, 0x20, 0x26, 0x29, 0x3F, |
1017 0x0, 0x0, 0x0, 0x10, 0x0, 0x2, 0x8, 0x1A, 0x0, 0x4, 0x1, 0x15, 0x20, 0x26, 0x29, 0x3F, |
964 }; |
1018 }; |
965 |
1019 |
966 static uint32 GetTileTrackStatus_Road(TileIndex tile, TransportType mode) |
1020 static uint32 GetTileTrackStatus_Road(TileIndex tile, TransportType mode) |
967 { |
1021 { |
|
1022 RoadType rt = ROADTYPE_ROAD; |
|
1023 |
968 switch (mode) { |
1024 switch (mode) { |
969 case TRANSPORT_RAIL: |
1025 case TRANSPORT_RAIL: |
970 if (!IsLevelCrossing(tile)) return 0; |
1026 if (!IsLevelCrossing(tile)) return 0; |
971 return GetCrossingRailBits(tile) * 0x101; |
1027 return GetCrossingRailBits(tile) * 0x101; |
972 |
1028 |
973 case TRANSPORT_ROAD: |
1029 case TRANSPORT_ROAD: |
|
1030 if (!HASBIT(GetRoadTypes(tile), rt)) return 0; |
974 switch (GetRoadTileType(tile)) { |
1031 switch (GetRoadTileType(tile)) { |
975 case ROAD_TILE_NORMAL: |
1032 case ROAD_TILE_NORMAL: |
976 return HasRoadWorks(tile) ? 0 : _road_trackbits[GetRoadBits(tile)] * 0x101; |
1033 return HasRoadWorks(tile) ? 0 : _road_trackbits[GetRoadBits(tile, rt)] * 0x101; |
977 |
1034 |
978 case ROAD_TILE_CROSSING: { |
1035 case ROAD_TILE_CROSSING: { |
979 uint32 r = AxisToTrackBits(GetCrossingRoadAxis(tile)) * 0x101; |
1036 uint32 r = AxisToTrackBits(GetCrossingRoadAxis(tile)) * 0x101; |
980 |
1037 |
981 if (IsCrossingBarred(tile)) r *= 0x10001; |
1038 if (IsCrossingBarred(tile)) r *= 0x10001; |
1045 } |
1102 } |
1046 |
1103 |
1047 |
1104 |
1048 static void ChangeTileOwner_Road(TileIndex tile, PlayerID old_player, PlayerID new_player) |
1105 static void ChangeTileOwner_Road(TileIndex tile, PlayerID old_player, PlayerID new_player) |
1049 { |
1106 { |
1050 if (IsLevelCrossing(tile) && GetCrossingRoadOwner(tile) == old_player) { |
1107 if (GetRoadTileType(tile) == ROAD_TILE_DEPOT) { |
1051 SetCrossingRoadOwner(tile, new_player == PLAYER_SPECTATOR ? OWNER_NONE : new_player); |
1108 DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR); |
1052 } |
1109 return; |
1053 |
1110 } |
1054 if (!IsTileOwner(tile, old_player)) return; |
1111 |
1055 |
1112 for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) { |
1056 if (new_player != PLAYER_SPECTATOR) { |
1113 if (!HASBIT(GetRoadTypes(tile), rt)) continue; |
1057 SetTileOwner(tile, new_player); |
1114 |
1058 } else { |
1115 if (GetRoadOwner(tile, rt) == old_player) { |
1059 switch (GetRoadTileType(tile)) { |
1116 SetRoadOwner(tile, rt, new_player == PLAYER_SPECTATOR ? OWNER_NONE : new_player); |
1060 case ROAD_TILE_NORMAL: |
1117 |
1061 SetTileOwner(tile, OWNER_NONE); |
1118 if (rt == ROADTYPE_TRAM) { |
1062 break; |
1119 DoCommand(tile, ROADTYPE_TRAM << 4 | GetRoadBits(tile, ROADTYPE_ROAD), 0, DC_EXEC, CMD_REMOVE_ROAD); |
1063 |
1120 } |
1064 case ROAD_TILE_CROSSING: |
1121 } |
1065 MakeRoadNormal(tile, GetCrossingRoadOwner(tile), GetCrossingRoadBits(tile), GetTownIndex(tile)); |
1122 } |
1066 break; |
1123 |
1067 |
1124 if (IsLevelCrossing(tile)) { |
1068 default: |
1125 MakeRoadNormal(tile, GetCrossingRoadBits(tile), GetRoadTypes(tile), GetTownIndex(tile), GetRoadOwner(tile, ROADTYPE_ROAD), GetRoadOwner(tile, ROADTYPE_TRAM), GetRoadOwner(tile, ROADTYPE_HWAY)); |
1069 case ROAD_TILE_DEPOT: |
|
1070 DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR); |
|
1071 break; |
|
1072 } |
|
1073 } |
1126 } |
1074 } |
1127 } |
1075 |
1128 |
1076 |
1129 |
1077 extern const TileTypeProcs _tile_type_road_procs = { |
1130 extern const TileTypeProcs _tile_type_road_procs = { |