42 */ |
42 */ |
43 static void StationPoolNewBlock(uint start_item) |
43 static void StationPoolNewBlock(uint start_item) |
44 { |
44 { |
45 Station *st; |
45 Station *st; |
46 |
46 |
47 FOR_ALL_STATIONS_FROM(st, start_item) |
47 FOR_ALL_STATIONS_FROM(st, start_item) st->index = start_item++; |
48 st->index = start_item++; |
|
49 } |
48 } |
50 |
49 |
51 /** |
50 /** |
52 * Called if a new block is added to the roadstop-pool |
51 * Called if a new block is added to the roadstop-pool |
53 */ |
52 */ |
54 static void RoadStopPoolNewBlock(uint start_item) |
53 static void RoadStopPoolNewBlock(uint start_item) |
55 { |
54 { |
56 RoadStop *rs; |
55 RoadStop *rs; |
57 |
56 |
58 FOR_ALL_ROADSTOPS_FROM(rs, start_item) |
57 FOR_ALL_ROADSTOPS_FROM(rs, start_item) rs->index = start_item++; |
59 rs->index = start_item++; |
|
60 } |
58 } |
61 |
59 |
62 /* Initialize the station-pool and roadstop-pool */ |
60 /* Initialize the station-pool and roadstop-pool */ |
63 MemoryPool _station_pool = { "Stations", STATION_POOL_MAX_BLOCKS, STATION_POOL_BLOCK_SIZE_BITS, sizeof(Station), &StationPoolNewBlock, 0, 0, NULL }; |
61 MemoryPool _station_pool = { "Stations", STATION_POOL_MAX_BLOCKS, STATION_POOL_BLOCK_SIZE_BITS, sizeof(Station), &StationPoolNewBlock, 0, 0, NULL }; |
64 MemoryPool _roadstop_pool = { "RoadStop", ROADSTOP_POOL_MAX_BLOCKS, ROADSTOP_POOL_BLOCK_SIZE_BITS, sizeof(RoadStop), &RoadStopPoolNewBlock, 0, 0, NULL }; |
62 MemoryPool _roadstop_pool = { "RoadStop", ROADSTOP_POOL_MAX_BLOCKS, ROADSTOP_POOL_BLOCK_SIZE_BITS, sizeof(RoadStop), &RoadStopPoolNewBlock, 0, 0, NULL }; |
94 road_stop->next = NULL; |
92 road_stop->next = NULL; |
95 road_stop->prev = previous; |
93 road_stop->prev = previous; |
96 road_stop->station = index; |
94 road_stop->station = index; |
97 } |
95 } |
98 |
96 |
99 RoadStop * GetPrimaryRoadStop(const Station *st, RoadStopType type) |
97 RoadStop* GetPrimaryRoadStop(const Station* st, RoadStopType type) |
100 { |
98 { |
101 switch (type) { |
99 switch (type) { |
102 case RS_BUS: return st->bus_stops; |
100 case RS_BUS: return st->bus_stops; |
103 case RS_TRUCK: return st->truck_stops; |
101 case RS_TRUCK: return st->truck_stops; |
104 default: NOT_REACHED(); |
102 default: NOT_REACHED(); |
105 } |
103 } |
106 |
104 |
107 return NULL; |
105 return NULL; |
108 } |
106 } |
109 |
107 |
110 RoadStop * GetRoadStopByTile(TileIndex tile, RoadStopType type) |
108 RoadStop* GetRoadStopByTile(TileIndex tile, RoadStopType type) |
111 { |
109 { |
112 const Station *st = GetStation(_m[tile].m2); |
110 const Station* st = GetStation(_m[tile].m2); |
113 RoadStop *rs; |
111 RoadStop* rs; |
114 |
112 |
115 for ( rs = GetPrimaryRoadStop(st, type); rs->xy != tile; rs = rs->next) |
113 for (rs = GetPrimaryRoadStop(st, type); rs->xy != tile; rs = rs->next) { |
116 assert(rs->next != NULL); |
114 assert(rs->next != NULL); |
|
115 } |
117 |
116 |
118 return rs; |
117 return rs; |
119 } |
118 } |
120 |
119 |
121 uint GetNumRoadStops(const Station *st, RoadStopType type) |
120 uint GetNumRoadStops(const Station *st, RoadStopType type) |
478 } |
475 } |
479 |
476 |
480 // Update the virtual coords needed to draw the station sign for all stations. |
477 // Update the virtual coords needed to draw the station sign for all stations. |
481 void UpdateAllStationVirtCoord(void) |
478 void UpdateAllStationVirtCoord(void) |
482 { |
479 { |
483 Station *st; |
480 Station* st; |
|
481 |
484 FOR_ALL_STATIONS(st) { |
482 FOR_ALL_STATIONS(st) { |
485 if (st->xy != 0) |
483 if (st->xy != 0) UpdateStationVirtCoord(st); |
486 UpdateStationVirtCoord(st); |
|
487 } |
484 } |
488 } |
485 } |
489 |
486 |
490 // Update the station virt coords while making the modified parts dirty. |
487 // Update the station virt coords while making the modified parts dirty. |
491 static void UpdateStationVirtCoordDirty(Station *st) |
488 static void UpdateStationVirtCoordDirty(Station *st) |
640 |
636 |
641 rect.min_x = MapSizeX(); |
637 rect.min_x = MapSizeX(); |
642 rect.min_y = MapSizeY(); |
638 rect.min_y = MapSizeY(); |
643 rect.max_x = rect.max_y = 0; |
639 rect.max_x = rect.max_y = 0; |
644 // Don't update acceptance for a buoy |
640 // Don't update acceptance for a buoy |
645 if (IsBuoy(st)) |
641 if (IsBuoy(st)) return; |
646 return; |
|
647 |
642 |
648 /* old accepted goods types */ |
643 /* old accepted goods types */ |
649 old_acc = GetAcceptanceMask(st); |
644 old_acc = GetAcceptanceMask(st); |
650 |
645 |
651 // Put all the tiles that span an area in the table. |
646 // Put all the tiles that span an area in the table. |
730 } |
725 } |
731 |
726 |
732 // This is called right after a station was deleted. |
727 // This is called right after a station was deleted. |
733 // It checks if the whole station is free of substations, and if so, the station will be |
728 // It checks if the whole station is free of substations, and if so, the station will be |
734 // deleted after a little while. |
729 // deleted after a little while. |
735 static void DeleteStationIfEmpty(Station *st) { |
730 static void DeleteStationIfEmpty(Station* st) |
|
731 { |
736 if (st->facilities == 0) { |
732 if (st->facilities == 0) { |
737 st->delete_ctr = 0; |
733 st->delete_ctr = 0; |
738 InvalidateWindow(WC_STATION_LIST, st->owner); |
734 InvalidateWindow(WC_STATION_LIST, st->owner); |
739 } |
735 } |
740 } |
736 } |
751 uint z; |
747 uint z; |
752 int allowed_z = -1; |
748 int allowed_z = -1; |
753 int flat_z; |
749 int flat_z; |
754 |
750 |
755 BEGIN_TILE_LOOP(tile_cur, w, h, tile) |
751 BEGIN_TILE_LOOP(tile_cur, w, h, tile) |
756 if (!EnsureNoVehicle(tile_cur)) |
752 if (!EnsureNoVehicle(tile_cur)) return CMD_ERROR; |
757 return CMD_ERROR; |
|
758 |
753 |
759 tileh = GetTileSlope(tile_cur, &z); |
754 tileh = GetTileSlope(tile_cur, &z); |
760 |
755 |
761 /* Prohibit building if |
756 /* Prohibit building if |
762 1) The tile is "steep" (i.e. stretches two height levels) |
757 1) The tile is "steep" (i.e. stretches two height levels) |
765 a) the player building is an "old-school" AI |
760 a) the player building is an "old-school" AI |
766 -OR- |
761 -OR- |
767 b) the build_on_slopes switch is disabled |
762 b) the build_on_slopes switch is disabled |
768 */ |
763 */ |
769 if (IsSteepTileh(tileh) || |
764 if (IsSteepTileh(tileh) || |
770 ((_is_old_ai_player || !_patches.build_on_slopes) |
765 ((_is_old_ai_player || !_patches.build_on_slopes) && tileh != 0)) { |
771 && tileh != 0)) { |
|
772 |
|
773 _error_message = STR_0007_FLAT_LAND_REQUIRED; |
766 _error_message = STR_0007_FLAT_LAND_REQUIRED; |
774 return CMD_ERROR; |
767 return CMD_ERROR; |
775 } |
768 } |
776 |
769 |
777 flat_z = z; |
770 flat_z = z; |
895 layout[n-1-n] = 0; |
888 layout[n-1-n] = 0; |
896 } |
889 } |
897 return layout; |
890 return layout; |
898 } |
891 } |
899 |
892 |
900 // stolen from TTDPatch |
|
901 static void GetStationLayout(byte *layout, int numtracks, int plat_len, const StationSpec *spec) |
893 static void GetStationLayout(byte *layout, int numtracks, int plat_len, const StationSpec *spec) |
902 { |
894 { |
903 if (spec != NULL && spec->lengths >= plat_len && |
895 if (spec != NULL && spec->lengths >= plat_len && |
904 spec->platforms[plat_len - 1] >= numtracks && |
896 spec->platforms[plat_len - 1] >= numtracks && |
905 spec->layouts[plat_len - 1][numtracks - 1]) { |
897 spec->layouts[plat_len - 1][numtracks - 1]) { |
910 } |
902 } |
911 |
903 |
912 if (plat_len == 1) { |
904 if (plat_len == 1) { |
913 CreateSingle(layout, numtracks); |
905 CreateSingle(layout, numtracks); |
914 } else { |
906 } else { |
915 if (numtracks & 1) |
907 if (numtracks & 1) layout = CreateSingle(layout, plat_len); |
916 layout = CreateSingle(layout, plat_len); |
908 numtracks >>= 1; |
917 numtracks>>=1; |
|
918 |
909 |
919 while (--numtracks >= 0) { |
910 while (--numtracks >= 0) { |
920 layout = CreateMulti(layout, plat_len, 4); |
911 layout = CreateMulti(layout, plat_len, 4); |
921 layout = CreateMulti(layout, plat_len, 6); |
912 layout = CreateMulti(layout, plat_len, 6); |
922 } |
913 } |
1002 if (!CanExpandRailroadStation(st, finalvalues, direction)) |
993 if (!CanExpandRailroadStation(st, finalvalues, direction)) |
1003 return CMD_ERROR; |
994 return CMD_ERROR; |
1004 } |
995 } |
1005 |
996 |
1006 //XXX can't we pack this in the "else" part of the if above? |
997 //XXX can't we pack this in the "else" part of the if above? |
1007 if (!CheckStationSpreadOut(st, tile_org, w_org, h_org)) |
998 if (!CheckStationSpreadOut(st, tile_org, w_org, h_org)) return CMD_ERROR; |
1008 return CMD_ERROR; |
|
1009 |
|
1010 } else { |
999 } else { |
1011 // Create a new station |
1000 // Create a new station |
1012 st = AllocateStation(); |
1001 st = AllocateStation(); |
1013 if (st == NULL) |
1002 if (st == NULL) return CMD_ERROR; |
1014 return CMD_ERROR; |
|
1015 |
1003 |
1016 st->town = ClosestTownFromTile(tile_org, (uint)-1); |
1004 st->town = ClosestTownFromTile(tile_org, (uint)-1); |
1017 if (_current_player < MAX_PLAYERS && flags&DC_EXEC) |
1005 if (_current_player < MAX_PLAYERS && flags & DC_EXEC) |
1018 SETBIT(st->town->have_ratings, _current_player); |
1006 SETBIT(st->town->have_ratings, _current_player); |
1019 |
1007 |
1020 if (!GenerateStationName(st, tile_org, 0)) |
1008 if (!GenerateStationName(st, tile_org, 0)) return CMD_ERROR; |
1021 return CMD_ERROR; |
1009 |
1022 |
1010 if (flags & DC_EXEC) StationInitialize(st, tile_org); |
1023 if (flags & DC_EXEC) |
|
1024 StationInitialize(st, tile_org); |
|
1025 } |
1011 } |
1026 |
1012 |
1027 if (flags & DC_EXEC) { |
1013 if (flags & DC_EXEC) { |
1028 TileIndexDiff tile_delta; |
1014 TileIndexDiff tile_delta; |
1029 byte *layout_ptr; |
1015 byte *layout_ptr; |
1174 uint GetStationPlatforms(const Station *st, TileIndex tile) |
1160 uint GetStationPlatforms(const Station *st, TileIndex tile) |
1175 { |
1161 { |
1176 TileIndex t; |
1162 TileIndex t; |
1177 TileIndexDiff delta; |
1163 TileIndexDiff delta; |
1178 int dir; |
1164 int dir; |
1179 int len; |
1165 uint len; |
1180 assert(TileBelongsToRailStation(st, tile)); |
1166 assert(TileBelongsToRailStation(st, tile)); |
1181 |
1167 |
1182 len = 0; |
1168 len = 0; |
1183 dir = _m[tile].m5&1; |
1169 dir = _m[tile].m5 & 1; |
1184 delta = dir ? TileDiffXY(0, 1) : TileDiffXY(1, 0); |
1170 delta = dir ? TileDiffXY(0, 1) : TileDiffXY(1, 0); |
1185 |
1171 |
1186 // find starting tile.. |
1172 // find starting tile.. |
1187 t = tile; |
1173 t = tile; |
1188 do { t -= delta; len++; } while (TileBelongsToRailStation(st, t) && (_m[t].m5&1) == dir); |
1174 do { |
|
1175 t -= delta; |
|
1176 len++; |
|
1177 } while (TileBelongsToRailStation(st, t) && (_m[t].m5 & 1) == dir); |
1189 |
1178 |
1190 // find ending tile |
1179 // find ending tile |
1191 t = tile; |
1180 t = tile; |
1192 do { t += delta; len++; }while (TileBelongsToRailStation(st, t) && (_m[t].m5&1) == dir); |
1181 do { |
|
1182 t += delta; |
|
1183 len++; |
|
1184 } while (TileBelongsToRailStation(st, t) && (_m[t].m5 & 1) == dir); |
1193 |
1185 |
1194 return len - 1; |
1186 return len - 1; |
1195 } |
1187 } |
1196 |
1188 |
1197 static const RealSpriteGroup *ResolveStationSpriteGroup(const SpriteGroup *spg, const Station *st) |
1189 static const RealSpriteGroup *ResolveStationSpriteGroup(const SpriteGroup *spg, const Station *st) |
1394 |
1386 |
1395 if (!(flags & DC_NO_TOWN_RATING) && !CheckIfAuthorityAllows(tile)) |
1387 if (!(flags & DC_NO_TOWN_RATING) && !CheckIfAuthorityAllows(tile)) |
1396 return CMD_ERROR; |
1388 return CMD_ERROR; |
1397 |
1389 |
1398 cost = CheckFlatLandBelow(tile, 1, 1, flags, 1 << p1, NULL); |
1390 cost = CheckFlatLandBelow(tile, 1, 1, flags, 1 << p1, NULL); |
1399 if (cost == CMD_ERROR) |
1391 if (cost == CMD_ERROR) return CMD_ERROR; |
1400 return CMD_ERROR; |
|
1401 |
1392 |
1402 st = GetStationAround(tile, 1, 1, -1); |
1393 st = GetStationAround(tile, 1, 1, -1); |
1403 if (st == CHECK_STATIONS_ERR) |
1394 if (st == CHECK_STATIONS_ERR) return CMD_ERROR; |
1404 return CMD_ERROR; |
|
1405 |
1395 |
1406 /* Find a station close to us */ |
1396 /* Find a station close to us */ |
1407 if (st == NULL) { |
1397 if (st == NULL) { |
1408 st = GetClosestStationFromTile(tile, 8, _current_player); |
1398 st = GetClosestStationFromTile(tile, 8, _current_player); |
1409 if (st!=NULL && st->facilities) st = NULL; |
1399 if (st != NULL && st->facilities) st = NULL; |
1410 } |
1400 } |
1411 |
1401 |
1412 //give us a road stop in the list, and check if something went wrong |
1402 //give us a road stop in the list, and check if something went wrong |
1413 road_stop = AllocateRoadStop(); |
1403 road_stop = AllocateRoadStop(); |
1414 if (road_stop == NULL) |
1404 if (road_stop == NULL) |
1427 FindRoadStationSpot(type, st, &currstop, &prev); |
1417 FindRoadStationSpot(type, st, &currstop, &prev); |
1428 } else { |
1418 } else { |
1429 Town *t; |
1419 Town *t; |
1430 |
1420 |
1431 st = AllocateStation(); |
1421 st = AllocateStation(); |
1432 if (st == NULL) |
1422 if (st == NULL) return CMD_ERROR; |
1433 return CMD_ERROR; |
|
1434 |
1423 |
1435 st->town = t = ClosestTownFromTile(tile, (uint)-1); |
1424 st->town = t = ClosestTownFromTile(tile, (uint)-1); |
1436 |
1425 |
1437 FindRoadStationSpot(type, st, &currstop, &prev); |
1426 FindRoadStationSpot(type, st, &currstop, &prev); |
1438 |
1427 |
1439 if (_current_player < MAX_PLAYERS && flags&DC_EXEC) |
1428 if (_current_player < MAX_PLAYERS && flags&DC_EXEC) |
1440 SETBIT(t->have_ratings, _current_player); |
1429 SETBIT(t->have_ratings, _current_player); |
1441 |
1430 |
1442 st->sign.width_1 = 0; |
1431 st->sign.width_1 = 0; |
1443 |
1432 |
1444 if (!GenerateStationName(st, tile, 0)) |
1433 if (!GenerateStationName(st, tile, 0)) return CMD_ERROR; |
1445 return CMD_ERROR; |
1434 |
1446 |
1435 if (flags & DC_EXEC) StationInitialize(st, tile); |
1447 if (flags & DC_EXEC) |
|
1448 StationInitialize(st, tile); |
|
1449 } |
1436 } |
1450 |
1437 |
1451 cost += (type) ? _price.build_truck_station : _price.build_bus_station; |
1438 cost += (type) ? _price.build_truck_station : _price.build_bus_station; |
1452 |
1439 |
1453 if (flags & DC_EXEC) { |
1440 if (flags & DC_EXEC) { |
1487 bool is_truck = _m[tile].m5 < 0x47; |
1474 bool is_truck = _m[tile].m5 < 0x47; |
1488 |
1475 |
1489 if (_current_player != OWNER_WATER && !CheckOwnership(st->owner)) |
1476 if (_current_player != OWNER_WATER && !CheckOwnership(st->owner)) |
1490 return CMD_ERROR; |
1477 return CMD_ERROR; |
1491 |
1478 |
1492 if (is_truck) { //truck stop |
1479 if (is_truck) { // truck stop |
1493 primary_stop = &st->truck_stops; |
1480 primary_stop = &st->truck_stops; |
1494 cur_stop = GetRoadStopByTile(tile, RS_TRUCK); |
1481 cur_stop = GetRoadStopByTile(tile, RS_TRUCK); |
1495 } else { |
1482 } else { |
1496 primary_stop = &st->bus_stops; |
1483 primary_stop = &st->bus_stops; |
1497 cur_stop = GetRoadStopByTile(tile, RS_BUS); |
1484 cur_stop = GetRoadStopByTile(tile, RS_BUS); |
1501 |
1488 |
1502 if (!EnsureNoVehicle(tile)) |
1489 if (!EnsureNoVehicle(tile)) |
1503 return CMD_ERROR; |
1490 return CMD_ERROR; |
1504 |
1491 |
1505 if (flags & DC_EXEC) { |
1492 if (flags & DC_EXEC) { |
1506 int i; |
1493 uint i; |
1507 DoClearSquare(tile); |
1494 DoClearSquare(tile); |
1508 |
1495 |
1509 /* Clear all vehicles destined for this station */ |
1496 /* Clear all vehicles destined for this station */ |
1510 for (i = 0; i != NUM_SLOTS; i++) { |
1497 for (i = 0; i != NUM_SLOTS; i++) { |
1511 if (cur_stop->slot[i] != INVALID_SLOT) { |
1498 if (cur_stop->slot[i] != INVALID_SLOT) { |
1513 ClearSlot(v, v->u.road.slot); |
1500 ClearSlot(v, v->u.road.slot); |
1514 } |
1501 } |
1515 } |
1502 } |
1516 |
1503 |
1517 cur_stop->used = false; |
1504 cur_stop->used = false; |
1518 if (cur_stop->prev != NULL) //alter previous stop |
1505 if (cur_stop->prev != NULL) cur_stop->prev->next = cur_stop->next; |
1519 cur_stop->prev->next = cur_stop->next; |
1506 if (cur_stop->next != NULL) cur_stop->next->prev = cur_stop->prev; |
1520 |
|
1521 if (cur_stop->next != NULL) //alter next stop |
|
1522 cur_stop->next->prev = cur_stop->prev; |
|
1523 |
1507 |
1524 //we only had one stop left |
1508 //we only had one stop left |
1525 if (cur_stop->next == NULL && cur_stop->prev == NULL) { |
1509 if (cur_stop->next == NULL && cur_stop->prev == NULL) { |
1526 |
|
1527 //so we remove ALL stops |
1510 //so we remove ALL stops |
1528 *primary_stop = NULL; |
1511 *primary_stop = NULL; |
1529 st->facilities &= (is_truck) ? ~FACIL_TRUCK_STOP : ~FACIL_BUS_STOP; |
1512 st->facilities &= (is_truck) ? ~FACIL_TRUCK_STOP : ~FACIL_BUS_STOP; |
1530 |
|
1531 } else if (cur_stop == *primary_stop) { |
1513 } else if (cur_stop == *primary_stop) { |
1532 //removed the first stop in the list |
1514 //removed the first stop in the list |
1533 //need to set the primary element to the next stop |
1515 //need to set the primary element to the next stop |
1534 *primary_stop = (*primary_stop)->next; |
1516 *primary_stop = (*primary_stop)->next; |
1535 } |
1517 } |
1664 st = AllocateStation(); |
1646 st = AllocateStation(); |
1665 if (st == NULL) return CMD_ERROR; |
1647 if (st == NULL) return CMD_ERROR; |
1666 |
1648 |
1667 st->town = t; |
1649 st->town = t; |
1668 |
1650 |
1669 if (_current_player < MAX_PLAYERS && flags&DC_EXEC) |
1651 if (_current_player < MAX_PLAYERS && flags & DC_EXEC) |
1670 SETBIT(t->have_ratings, _current_player); |
1652 SETBIT(t->have_ratings, _current_player); |
1671 |
1653 |
1672 st->sign.width_1 = 0; |
1654 st->sign.width_1 = 0; |
1673 |
1655 |
1674 // if airport type equals Heliport then generate |
1656 // if airport type equals Heliport then generate |
1695 st->airport_type = (byte)p1; |
1677 st->airport_type = (byte)p1; |
1696 st->airport_flags = 0; |
1678 st->airport_flags = 0; |
1697 |
1679 |
1698 st->build_date = _date; |
1680 st->build_date = _date; |
1699 |
1681 |
1700 /* if airport was demolished while planes were en-route to it, the positions can no longer |
1682 /* if airport was demolished while planes were en-route to it, the |
1701 be the same (v->u.air.pos), since different airports have different indexes. So update |
1683 * positions can no longer be the same (v->u.air.pos), since different |
1702 all planes en-route to this airport. Only update if |
1684 * airports have different indexes. So update all planes en-route to this |
1703 1. airport is upgraded |
1685 * airport. Only update if |
1704 2. airport is added to existing station (unfortunately unavoideable) |
1686 * 1. airport is upgraded |
1705 */ |
1687 * 2. airport is added to existing station (unfortunately unavoideable) |
|
1688 */ |
1706 if (airport_upgrade) UpdateAirplanesOnNewStation(st); |
1689 if (airport_upgrade) UpdateAirplanesOnNewStation(st); |
1707 |
1690 |
1708 { |
1691 { |
1709 const byte *b = _airport_map5_tiles[p1]; |
1692 const byte *b = _airport_map5_tiles[p1]; |
1710 |
1693 |
1848 return_cmd_error(INVALID_STRING_ID); |
1831 return_cmd_error(INVALID_STRING_ID); |
1849 } |
1832 } |
1850 |
1833 |
1851 tile = st->dock_tile; |
1834 tile = st->dock_tile; |
1852 |
1835 |
1853 if (CheckShipsOnBuoy(st)) |
1836 if (CheckShipsOnBuoy(st)) return_cmd_error(STR_BUOY_IS_IN_USE); |
1854 return_cmd_error(STR_BUOY_IS_IN_USE); |
1837 if (!EnsureNoVehicle(tile)) return CMD_ERROR; |
1855 |
|
1856 if (!EnsureNoVehicle(tile)) |
|
1857 return CMD_ERROR; |
|
1858 |
1838 |
1859 if (flags & DC_EXEC) { |
1839 if (flags & DC_EXEC) { |
1860 st->dock_tile = 0; |
1840 st->dock_tile = 0; |
1861 /* Buoys are marked in the Station struct by this flag. Yes, it is this |
1841 /* Buoys are marked in the Station struct by this flag. Yes, it is this |
1862 * braindead.. */ |
1842 * braindead.. */ |
1961 |
1941 |
1962 st->sign.width_1 = 0; |
1942 st->sign.width_1 = 0; |
1963 |
1943 |
1964 if (!GenerateStationName(st, tile, 3)) return CMD_ERROR; |
1944 if (!GenerateStationName(st, tile, 3)) return CMD_ERROR; |
1965 |
1945 |
1966 if (flags & DC_EXEC) |
1946 if (flags & DC_EXEC) StationInitialize(st, tile); |
1967 StationInitialize(st, tile); |
|
1968 } |
1947 } |
1969 |
1948 |
1970 if (flags & DC_EXEC) { |
1949 if (flags & DC_EXEC) { |
1971 st->dock_tile = tile; |
1950 st->dock_tile = tile; |
1972 if (!st->facilities) st->xy = tile; |
1951 if (!st->facilities) st->xy = tile; |
1999 static int32 RemoveDock(Station *st, uint32 flags) |
1978 static int32 RemoveDock(Station *st, uint32 flags) |
2000 { |
1979 { |
2001 TileIndex tile1; |
1980 TileIndex tile1; |
2002 TileIndex tile2; |
1981 TileIndex tile2; |
2003 |
1982 |
2004 if (!CheckOwnership(st->owner)) |
1983 if (!CheckOwnership(st->owner)) return CMD_ERROR; |
2005 return CMD_ERROR; |
|
2006 |
1984 |
2007 tile1 = st->dock_tile; |
1985 tile1 = st->dock_tile; |
2008 tile2 = tile1 + TileOffsByDir(_m[tile1].m5 - 0x4C); |
1986 tile2 = tile1 + TileOffsByDir(_m[tile1].m5 - 0x4C); |
2009 |
1987 |
2010 if (!EnsureNoVehicle(tile1)) |
1988 if (!EnsureNoVehicle(tile1)) return CMD_ERROR; |
2011 return CMD_ERROR; |
1989 if (!EnsureNoVehicle(tile2)) return CMD_ERROR; |
2012 |
|
2013 if (!EnsureNoVehicle(tile2)) |
|
2014 return CMD_ERROR; |
|
2015 |
1990 |
2016 if (flags & DC_EXEC) { |
1991 if (flags & DC_EXEC) { |
2017 DoClearSquare(tile1); |
1992 DoClearSquare(tile1); |
2018 |
1993 |
2019 // convert the water tile to water. |
1994 // convert the water tile to water. |
2046 uint32 relocation = 0; |
2021 uint32 relocation = 0; |
2047 |
2022 |
2048 { |
2023 { |
2049 PlayerID owner = GetTileOwner(ti->tile); |
2024 PlayerID owner = GetTileOwner(ti->tile); |
2050 image_or_modificator = PALETTE_TO_GREY; /* NOTE: possible bug in ttd here? */ |
2025 image_or_modificator = PALETTE_TO_GREY; /* NOTE: possible bug in ttd here? */ |
2051 if (owner < MAX_PLAYERS) |
2026 if (owner < MAX_PLAYERS) image_or_modificator = PLAYER_SPRITE_COLOR(owner); |
2052 image_or_modificator = PLAYER_SPRITE_COLOR(owner); |
|
2053 } |
2027 } |
2054 |
2028 |
2055 // don't show foundation for docks (docks are between 76 (0x4C) and 81 (0x51)) |
2029 // don't show foundation for docks (docks are between 76 (0x4C) and 81 (0x51)) |
2056 if (ti->tileh != 0 && (ti->map5 < 0x4C || ti->map5 > 0x51)) |
2030 if (ti->tileh != 0 && (ti->map5 < 0x4C || ti->map5 > 0x51)) |
2057 DrawFoundation(ti, ti->tileh); |
2031 DrawFoundation(ti, ti->tileh); |
2072 } |
2046 } |
2073 |
2047 |
2074 if (t == NULL) t = &_station_display_datas[ti->map5]; |
2048 if (t == NULL) t = &_station_display_datas[ti->map5]; |
2075 |
2049 |
2076 image = t->ground_sprite; |
2050 image = t->ground_sprite; |
2077 if (image & PALETTE_MODIFIER_COLOR) |
2051 if (image & PALETTE_MODIFIER_COLOR) image |= image_or_modificator; |
2078 image |= image_or_modificator; |
|
2079 |
2052 |
2080 // For custom sprites, there's no railtype-based pitching. |
2053 // For custom sprites, there's no railtype-based pitching. |
2081 offset = (image & SPRITE_MASK) < _custom_sprites_base ? rti->total_offset : railtype; |
2054 offset = (image & SPRITE_MASK) < _custom_sprites_base ? rti->total_offset : railtype; |
2082 image += offset; |
2055 image += offset; |
2083 |
2056 |
2122 ormod = PLAYER_SPRITE_COLOR(_local_player); |
2095 ormod = PLAYER_SPRITE_COLOR(_local_player); |
2123 |
2096 |
2124 t = &_station_display_datas[image]; |
2097 t = &_station_display_datas[image]; |
2125 |
2098 |
2126 img = t->ground_sprite; |
2099 img = t->ground_sprite; |
2127 if (img & PALETTE_MODIFIER_COLOR) |
2100 if (img & PALETTE_MODIFIER_COLOR) img |= ormod; |
2128 img |= ormod; |
|
2129 DrawSprite(img + rti->total_offset, x, y); |
2101 DrawSprite(img + rti->total_offset, x, y); |
2130 |
2102 |
2131 foreach_draw_tile_seq(dtss, t->seq) { |
2103 foreach_draw_tile_seq(dtss, t->seq) { |
2132 Point pt = RemapCoords(dtss->delta_x, dtss->delta_y, dtss->delta_z); |
2104 Point pt = RemapCoords(dtss->delta_x, dtss->delta_y, dtss->delta_z); |
2133 DrawSprite((dtss->image | ormod) + rti->total_offset, x + pt.x, y + pt.y); |
2105 DrawSprite((dtss->image | ormod) + rti->total_offset, x + pt.x, y + pt.y); |
2278 |
2250 |
2279 static uint32 VehicleEnter_Station(Vehicle *v, TileIndex tile, int x, int y) |
2251 static uint32 VehicleEnter_Station(Vehicle *v, TileIndex tile, int x, int y) |
2280 { |
2252 { |
2281 StationID station_id; |
2253 StationID station_id; |
2282 byte dir; |
2254 byte dir; |
2283 uint16 spd; |
|
2284 |
2255 |
2285 if (v->type == VEH_Train) { |
2256 if (v->type == VEH_Train) { |
2286 if (IS_BYTE_INSIDE(_m[tile].m5, 0, 8) && v->subtype == TS_Front_Engine && |
2257 if (IS_BYTE_INSIDE(_m[tile].m5, 0, 8) && v->subtype == TS_Front_Engine && |
2287 !IsCompatibleTrainStationTile(tile + TileOffsByDir(v->direction >> 1), tile)) { |
2258 !IsCompatibleTrainStationTile(tile + TileOffsByDir(v->direction >> 1), tile)) { |
2288 |
2259 |
2289 station_id = _m[tile].m2; |
2260 station_id = _m[tile].m2; |
2290 if ((!(v->current_order.flags & OF_NON_STOP) && !_patches.new_nonstop) || |
2261 if ((!(v->current_order.flags & OF_NON_STOP) && !_patches.new_nonstop) || |
2291 (v->current_order.type == OT_GOTO_STATION && v->current_order.station == station_id)) { |
2262 (v->current_order.type == OT_GOTO_STATION && v->current_order.station == station_id)) { |
2292 |
|
2293 if (!(_patches.new_nonstop && v->current_order.flags & OF_NON_STOP) && |
2263 if (!(_patches.new_nonstop && v->current_order.flags & OF_NON_STOP) && |
2294 v->current_order.type != OT_LEAVESTATION && |
2264 v->current_order.type != OT_LEAVESTATION && |
2295 v->last_station_visited != station_id) { |
2265 v->last_station_visited != station_id) { |
2296 x &= 0xF; |
2266 x &= 0xF; |
2297 y &= 0xF; |
2267 y &= 0xF; |
2298 |
2268 |
2299 dir = v->direction & 6; |
2269 dir = v->direction & 6; |
2300 if (dir & 2) intswap(x,y); |
2270 if (dir & 2) intswap(x,y); |
2301 if (y == 8) { |
2271 if (y == 8) { |
2302 if (dir != 2 && dir != 4) { |
2272 if (dir != 2 && dir != 4) x = ~x & 0xF; |
2303 x = (~x)&0xF; |
|
2304 } |
|
2305 if (x == 12) return 2 | (station_id << 8); /* enter station */ |
2273 if (x == 12) return 2 | (station_id << 8); /* enter station */ |
2306 if (x < 12) { |
2274 if (x < 12) { |
|
2275 uint16 spd; |
|
2276 |
2307 v->vehstatus |= VS_TRAIN_SLOWING; |
2277 v->vehstatus |= VS_TRAIN_SLOWING; |
2308 spd = _enter_station_speedtable[x]; |
2278 spd = _enter_station_speedtable[x]; |
2309 if (spd < v->cur_speed) |
2279 if (spd < v->cur_speed) v->cur_speed = spd; |
2310 v->cur_speed = spd; |
|
2311 } |
2280 } |
2312 } |
2281 } |
2313 } |
2282 } |
2314 } |
2283 } |
2315 } |
2284 } |
2389 invalidate = true; |
2358 invalidate = true; |
2390 } |
2359 } |
2391 } |
2360 } |
2392 } |
2361 } |
2393 //Orders for the vehicle have been changed, invalidate the window |
2362 //Orders for the vehicle have been changed, invalidate the window |
2394 if (invalidate) |
2363 if (invalidate) InvalidateWindow(WC_VEHICLE_ORDERS, v->index); |
2395 InvalidateWindow(WC_VEHICLE_ORDERS, v->index); |
|
2396 } |
2364 } |
2397 |
2365 |
2398 //Subsidies need removal as well |
2366 //Subsidies need removal as well |
2399 DeleteSubsidyWithStation(index); |
2367 DeleteSubsidyWithStation(index); |
2400 } |
2368 } |
2433 /* this function is called for one station each tick */ |
2400 /* this function is called for one station each tick */ |
2434 static void StationHandleBigTick(Station *st) |
2401 static void StationHandleBigTick(Station *st) |
2435 { |
2402 { |
2436 UpdateStationAcceptance(st, true); |
2403 UpdateStationAcceptance(st, true); |
2437 |
2404 |
2438 if (st->facilities == 0) { |
2405 if (st->facilities == 0 && ++st->delete_ctr >= 8) DeleteStation(st); |
2439 if (++st->delete_ctr >= 8) |
|
2440 DeleteStation(st); |
|
2441 } |
|
2442 |
2406 |
2443 // Here we saveguard against orphaned slots |
2407 // Here we saveguard against orphaned slots |
2444 CheckOrphanedSlots(st, RS_BUS); |
2408 CheckOrphanedSlots(st, RS_BUS); |
2445 CheckOrphanedSlots(st, RS_TRUCK); |
2409 CheckOrphanedSlots(st, RS_TRUCK); |
2446 } |
2410 } |
2544 /* called for every station each tick */ |
2508 /* called for every station each tick */ |
2545 static void StationHandleSmallTick(Station *st) |
2509 static void StationHandleSmallTick(Station *st) |
2546 { |
2510 { |
2547 byte b; |
2511 byte b; |
2548 |
2512 |
2549 if (st->facilities == 0) |
2513 if (st->facilities == 0) return; |
2550 return; |
|
2551 |
2514 |
2552 b = st->delete_ctr + 1; |
2515 b = st->delete_ctr + 1; |
2553 if (b >= 185) b = 0; |
2516 if (b >= 185) b = 0; |
2554 st->delete_ctr = b; |
2517 st->delete_ctr = b; |
2555 |
2518 |
2556 if (b == 0) |
2519 if (b == 0) UpdateStationRating(st); |
2557 UpdateStationRating(st); |
|
2558 } |
2520 } |
2559 |
2521 |
2560 void OnTick_Station(void) |
2522 void OnTick_Station(void) |
2561 { |
2523 { |
2562 uint i; |
2524 uint i; |
2563 Station *st; |
2525 Station *st; |
2564 |
2526 |
2565 if (_game_mode == GM_EDITOR) |
2527 if (_game_mode == GM_EDITOR) return; |
2566 return; |
|
2567 |
2528 |
2568 i = _station_tick_ctr; |
2529 i = _station_tick_ctr; |
2569 if (++_station_tick_ctr == GetStationPoolSize()) |
2530 if (++_station_tick_ctr == GetStationPoolSize()) _station_tick_ctr = 0; |
2570 _station_tick_ctr = 0; |
|
2571 |
2531 |
2572 st = GetStation(i); |
2532 st = GetStation(i); |
2573 if (st->xy != 0) |
2533 if (st->xy != 0) StationHandleBigTick(st); |
2574 StationHandleBigTick(st); |
|
2575 |
2534 |
2576 FOR_ALL_STATIONS(st) { |
2535 FOR_ALL_STATIONS(st) { |
2577 if (st->xy != 0) |
2536 if (st->xy != INVALID_TILE) StationHandleSmallTick(st); |
2578 StationHandleSmallTick(st); |
2537 } |
2579 } |
|
2580 |
|
2581 } |
2538 } |
2582 |
2539 |
2583 void StationMonthlyLoop(void) |
2540 void StationMonthlyLoop(void) |
2584 { |
2541 { |
2585 } |
2542 } |
2621 * @param p1 station ID that is to be renamed |
2578 * @param p1 station ID that is to be renamed |
2622 * @param p2 unused |
2579 * @param p2 unused |
2623 */ |
2580 */ |
2624 int32 CmdRenameStation(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
2581 int32 CmdRenameStation(int x, int y, uint32 flags, uint32 p1, uint32 p2) |
2625 { |
2582 { |
2626 StringID str,old_str; |
2583 StringID str; |
2627 Station *st; |
2584 Station *st; |
2628 |
2585 |
2629 if (!IsStationIndex(p1) || _cmd_text[0] == '\0') return CMD_ERROR; |
2586 if (!IsStationIndex(p1) || _cmd_text[0] == '\0') return CMD_ERROR; |
2630 st = GetStation(p1); |
2587 st = GetStation(p1); |
2631 |
2588 |
2633 |
2590 |
2634 str = AllocateNameUnique(_cmd_text, 6); |
2591 str = AllocateNameUnique(_cmd_text, 6); |
2635 if (str == 0) return CMD_ERROR; |
2592 if (str == 0) return CMD_ERROR; |
2636 |
2593 |
2637 if (flags & DC_EXEC) { |
2594 if (flags & DC_EXEC) { |
2638 old_str = st->string_id; |
2595 StringID old_str = st->string_id; |
|
2596 |
2639 st->string_id = str; |
2597 st->string_id = str; |
2640 UpdateStationVirtCoord(st); |
2598 UpdateStationVirtCoord(st); |
2641 DeleteName(old_str); |
2599 DeleteName(old_str); |
2642 _station_sort_dirty[st->owner] = true; // rename a station |
2600 _station_sort_dirty[st->owner] = true; // rename a station |
2643 MarkWholeScreenDirty(); |
2601 MarkWholeScreenDirty(); |
2684 |
2642 |
2685 BEGIN_TILE_LOOP(cur_tile, w, h, tile - TileDiffXY(max_rad, max_rad)) |
2643 BEGIN_TILE_LOOP(cur_tile, w, h, tile - TileDiffXY(max_rad, max_rad)) |
2686 cur_tile = TILE_MASK(cur_tile); |
2644 cur_tile = TILE_MASK(cur_tile); |
2687 if (IsTileType(cur_tile, MP_STATION)) { |
2645 if (IsTileType(cur_tile, MP_STATION)) { |
2688 st_index = _m[cur_tile].m2; |
2646 st_index = _m[cur_tile].m2; |
2689 for(i=0; i!=8; i++) { |
2647 for (i = 0; i != 8; i++) { |
2690 if (around[i] == INVALID_STATION) { |
2648 if (around[i] == INVALID_STATION) { |
2691 st = GetStation(st_index); |
2649 st = GetStation(st_index); |
2692 if (!IsBuoy(st) && |
2650 if (!IsBuoy(st) && |
2693 ( !st->town->exclusive_counter || (st->town->exclusivity == st->owner) ) && // check exclusive transport rights |
2651 ( !st->town->exclusive_counter || (st->town->exclusivity == st->owner) ) && // check exclusive transport rights |
2694 st->goods[type].rating != 0 && |
2652 st->goods[type].rating != 0 && |
2802 |
2760 |
2803 st->town = ClosestTownFromTile(tile, (uint)-1); |
2761 st->town = ClosestTownFromTile(tile, (uint)-1); |
2804 st->sign.width_1 = 0; |
2762 st->sign.width_1 = 0; |
2805 |
2763 |
2806 SetTileType(tile, MP_STATION); |
2764 SetTileType(tile, MP_STATION); |
2807 _m[tile].m5 = 0x4B; |
|
2808 SetTileOwner(tile, OWNER_NONE); |
2765 SetTileOwner(tile, OWNER_NONE); |
|
2766 _m[tile].m2 = st->index; |
2809 _m[tile].m3 = 0; |
2767 _m[tile].m3 = 0; |
2810 _m[tile].m4 = 0; |
2768 _m[tile].m4 = 0; |
2811 _m[tile].m2 = st->index; |
2769 _m[tile].m5 = 0x4B; |
2812 |
2770 |
2813 st->owner = OWNER_NONE; |
2771 st->owner = OWNER_NONE; |
2814 st->airport_flags = 0; |
2772 st->airport_flags = 0; |
2815 st->airport_type = AT_OILRIG; |
2773 st->airport_type = AT_OILRIG; |
2816 st->xy = tile; |
2774 st->xy = tile; |
2885 return_cmd_error(STR_4800_IN_THE_WAY); |
2843 return_cmd_error(STR_4800_IN_THE_WAY); |
2886 } |
2844 } |
2887 |
2845 |
2888 st = GetStation(_m[tile].m2); |
2846 st = GetStation(_m[tile].m2); |
2889 |
2847 |
2890 if (m5 < 8) |
2848 if (m5 < 8) return RemoveRailroadStation(st, tile, flags); |
2891 return RemoveRailroadStation(st, tile, flags); |
|
2892 |
|
2893 // original airports < 67, new airports between 83 - 114 |
2849 // original airports < 67, new airports between 83 - 114 |
2894 if (m5 < 0x43 || ( m5 >= 83 && m5 <= 114) ) |
2850 if (m5 < 0x43 || (m5 >= 83 && m5 <= 114)) return RemoveAirport(st, flags); |
2895 return RemoveAirport(st, flags); |
2851 if (m5 < 0x4B) return RemoveRoadStop(st, flags, tile); |
2896 |
2852 if (m5 == 0x52) return RemoveBuoy(st, flags); |
2897 if (m5 < 0x4B) |
2853 if (m5 != 0x4B && m5 < 0x53) return RemoveDock(st, flags); |
2898 return RemoveRoadStop(st, flags, tile); |
|
2899 |
|
2900 if (m5 == 0x52) |
|
2901 return RemoveBuoy(st, flags); |
|
2902 |
|
2903 if (m5 != 0x4B && m5 < 0x53) |
|
2904 return RemoveDock(st, flags); |
|
2905 |
2854 |
2906 return CMD_ERROR; |
2855 return CMD_ERROR; |
2907 |
|
2908 } |
2856 } |
2909 |
2857 |
2910 void InitializeStations(void) |
2858 void InitializeStations(void) |
2911 { |
2859 { |
2912 /* Clean the station pool and create 1 block in it */ |
2860 /* Clean the station pool and create 1 block in it */ |
3034 SlObject(st, _station_desc); |
2982 SlObject(st, _station_desc); |
3035 for (i = 0; i != NUM_CARGO; i++) { |
2983 for (i = 0; i != NUM_CARGO; i++) { |
3036 SlObject(&st->goods[i], _goods_desc); |
2984 SlObject(&st->goods[i], _goods_desc); |
3037 |
2985 |
3038 /* In older versions, enroute_from had 0xFF as INVALID_STATION, is now 0xFFFF */ |
2986 /* In older versions, enroute_from had 0xFF as INVALID_STATION, is now 0xFFFF */ |
3039 if (_sl_full_version < 0x700 && st->goods[i].enroute_from == 0xFF) |
2987 if (_sl_full_version < 0x700 && st->goods[i].enroute_from == 0xFF) { |
3040 st->goods[i].enroute_from = INVALID_STATION; |
2988 st->goods[i].enroute_from = INVALID_STATION; |
|
2989 } |
3041 } |
2990 } |
3042 } |
2991 } |
3043 |
2992 |
3044 static void Save_STNS(void) |
2993 static void Save_STNS(void) |
3045 { |
2994 { |
3064 |
3013 |
3065 st = GetStation(index); |
3014 st = GetStation(index); |
3066 SaveLoad_STNS(st); |
3015 SaveLoad_STNS(st); |
3067 |
3016 |
3068 // this means it's an oldstyle savegame without support for nonuniform stations |
3017 // this means it's an oldstyle savegame without support for nonuniform stations |
3069 if (st->train_tile && st->trainst_h == 0) { |
3018 if (st->train_tile != 0 && st->trainst_h == 0) { |
3070 int w = st->trainst_w >> 4; |
3019 int w = st->trainst_w >> 4; |
3071 int h = st->trainst_w & 0xF; |
3020 int h = st->trainst_w & 0xF; |
3072 if (_m[st->train_tile].m5&1) intswap(w,h); |
3021 |
|
3022 if (_m[st->train_tile].m5 & 1) intswap(w, h); |
3073 st->trainst_w = w; |
3023 st->trainst_w = w; |
3074 st->trainst_h = h; |
3024 st->trainst_h = h; |
3075 } |
3025 } |
3076 |
3026 |
3077 if (_sl_full_version < 0x600) { |
3027 if (_sl_full_version < 0x600) { |