322 found = FindFirstBit(tmp); |
337 found = FindFirstBit(tmp); |
323 goto done; |
338 goto done; |
324 } |
339 } |
325 |
340 |
326 /* check mine? */ |
341 /* check mine? */ |
327 if (HASBIT(free_names, M(STR_SV_STNAME_MINES))) { |
342 if (HasBit(free_names, M(STR_SV_STNAME_MINES))) { |
328 if (CountMapSquareAround(tile, CMSAMine) >= 2) { |
343 if (CountMapSquareAround(tile, CMSAMine) >= 2) { |
329 found = M(STR_SV_STNAME_MINES); |
344 found = M(STR_SV_STNAME_MINES); |
330 goto done; |
345 goto done; |
331 } |
346 } |
332 } |
347 } |
333 |
348 |
334 /* check close enough to town to get central as name? */ |
349 /* check close enough to town to get central as name? */ |
335 if (DistanceMax(tile, t->xy) < 8) { |
350 if (DistanceMax(tile, t->xy) < 8) { |
336 found = M(STR_SV_STNAME); |
351 found = M(STR_SV_STNAME); |
337 if (HASBIT(free_names, M(STR_SV_STNAME))) goto done; |
352 if (HasBit(free_names, M(STR_SV_STNAME))) goto done; |
338 |
353 |
339 found = M(STR_SV_STNAME_CENTRAL); |
354 found = M(STR_SV_STNAME_CENTRAL); |
340 if (HASBIT(free_names, M(STR_SV_STNAME_CENTRAL))) goto done; |
355 if (HasBit(free_names, M(STR_SV_STNAME_CENTRAL))) goto done; |
341 } |
356 } |
342 |
357 |
343 /* Check lakeside */ |
358 /* Check lakeside */ |
344 if (HASBIT(free_names, M(STR_SV_STNAME_LAKESIDE)) && |
359 if (HasBit(free_names, M(STR_SV_STNAME_LAKESIDE)) && |
345 DistanceFromEdge(tile) < 20 && |
360 DistanceFromEdge(tile) < 20 && |
346 CountMapSquareAround(tile, CMSAWater) >= 5) { |
361 CountMapSquareAround(tile, CMSAWater) >= 5) { |
347 found = M(STR_SV_STNAME_LAKESIDE); |
362 found = M(STR_SV_STNAME_LAKESIDE); |
348 goto done; |
363 goto done; |
349 } |
364 } |
350 |
365 |
351 /* Check woods */ |
366 /* Check woods */ |
352 if (HASBIT(free_names, M(STR_SV_STNAME_WOODS)) && ( |
367 if (HasBit(free_names, M(STR_SV_STNAME_WOODS)) && ( |
353 CountMapSquareAround(tile, CMSATree) >= 8 || |
368 CountMapSquareAround(tile, CMSATree) >= 8 || |
354 CountMapSquareAround(tile, CMSAForest) >= 2) |
369 CountMapSquareAround(tile, CMSAForest) >= 2) |
355 ) { |
370 ) { |
356 found = _opt.landscape == LT_TROPIC ? |
371 found = _opt.landscape == LT_TROPIC ? |
357 M(STR_SV_STNAME_FOREST) : M(STR_SV_STNAME_WOODS); |
372 M(STR_SV_STNAME_FOREST) : M(STR_SV_STNAME_WOODS); |
451 st->MarkDirty(); |
467 st->MarkDirty(); |
452 UpdateStationVirtCoord(st); |
468 UpdateStationVirtCoord(st); |
453 st->MarkDirty(); |
469 st->MarkDirty(); |
454 } |
470 } |
455 |
471 |
456 // Get a mask of the cargo types that the station accepts. |
472 /** Get a mask of the cargo types that the station accepts. |
|
473 * @param st Station to query |
|
474 * @return the expected mask |
|
475 */ |
457 static uint GetAcceptanceMask(const Station *st) |
476 static uint GetAcceptanceMask(const Station *st) |
458 { |
477 { |
459 uint mask = 0; |
478 uint mask = 0; |
460 |
479 |
461 for (CargoID i = 0; i < NUM_CARGO; i++) { |
480 for (CargoID i = 0; i < NUM_CARGO; i++) { |
462 if (HASBIT(st->goods[i].acceptance_pickup, GoodsEntry::ACCEPTANCE)) mask |= 1 << i; |
481 if (HasBit(st->goods[i].acceptance_pickup, GoodsEntry::ACCEPTANCE)) mask |= 1 << i; |
463 } |
482 } |
464 return mask; |
483 return mask; |
465 } |
484 } |
466 |
485 |
467 // Items contains the two cargo names that are to be accepted or rejected. |
486 /** Items contains the two cargo names that are to be accepted or rejected. |
468 // msg is the string id of the message to display. |
487 * msg is the string id of the message to display. |
|
488 */ |
469 static void ShowRejectOrAcceptNews(const Station *st, uint num_items, CargoID *cargo, StringID msg) |
489 static void ShowRejectOrAcceptNews(const Station *st, uint num_items, CargoID *cargo, StringID msg) |
470 { |
490 { |
471 for (uint i = 0; i < num_items; i++) { |
491 for (uint i = 0; i < num_items; i++) { |
472 SetDParam(i + 1, GetCargo(cargo[i])->name); |
492 SetDParam(i + 1, GetCargo(cargo[i])->name); |
473 } |
493 } |
474 |
494 |
475 SetDParam(0, st->index); |
495 SetDParam(0, st->index); |
476 AddNewsItem(msg, NEWS_FLAGS(NM_SMALL, NF_VIEWPORT | NF_TILE, NT_ACCEPTANCE, 0), st->xy, 0); |
496 AddNewsItem(msg, NEWS_FLAGS(NM_SMALL, NF_VIEWPORT | NF_TILE, NT_ACCEPTANCE, 0), st->xy, 0); |
477 } |
497 } |
478 |
498 |
479 // Get a list of the cargo types being produced around the tile. |
499 /** |
|
500 * Get a list of the cargo types being produced around the tile (in a rectangle). |
|
501 * @param produced: Destination array of produced cargo |
|
502 * @param tile: Center of the search area |
|
503 * @param w: Width of the center |
|
504 * @param h: Height of the center |
|
505 * @param rad: Radius of the search area |
|
506 */ |
480 void GetProductionAroundTiles(AcceptedCargo produced, TileIndex tile, |
507 void GetProductionAroundTiles(AcceptedCargo produced, TileIndex tile, |
481 int w, int h, int rad) |
508 int w, int h, int rad) |
482 { |
509 { |
483 memset(produced, 0, sizeof(AcceptedCargo)); |
510 memset(produced, 0, sizeof(AcceptedCargo)); |
484 |
511 |
485 int x = TileX(tile); |
512 int x = TileX(tile); |
486 int y = TileY(tile); |
513 int y = TileY(tile); |
487 |
514 |
488 // expand the region by rad tiles on each side |
515 /* expand the region by rad tiles on each side |
489 // while making sure that we remain inside the board. |
516 * while making sure that we remain inside the board. */ |
490 int x2 = min(x + w + rad, MapSizeX()); |
517 int x2 = min(x + w + rad, MapSizeX()); |
491 int x1 = max(x - rad, 0); |
518 int x1 = max(x - rad, 0); |
492 |
519 |
493 int y2 = min(y + h + rad, MapSizeY()); |
520 int y2 = min(y + h + rad, MapSizeY()); |
494 int y1 = max(y - rad, 0); |
521 int y1 = max(y - rad, 0); |
518 } |
545 } |
519 } |
546 } |
520 } |
547 } |
521 } |
548 } |
522 |
549 |
523 // Get a list of the cargo types that are accepted around the tile. |
550 /** |
|
551 * Get a list of the cargo types that are accepted around the tile. |
|
552 * @param accepts: Destination array of accepted cargo |
|
553 * @param tile: Center of the search area |
|
554 * @param w: Width of the center |
|
555 * @param h: Height of the center |
|
556 * @param rad: Radius of the rectangular search area |
|
557 */ |
524 void GetAcceptanceAroundTiles(AcceptedCargo accepts, TileIndex tile, |
558 void GetAcceptanceAroundTiles(AcceptedCargo accepts, TileIndex tile, |
525 int w, int h, int rad) |
559 int w, int h, int rad) |
526 { |
560 { |
527 memset(accepts, 0, sizeof(AcceptedCargo)); |
561 memset(accepts, 0, sizeof(AcceptedCargo)); |
528 |
562 |
529 int x = TileX(tile); |
563 int x = TileX(tile); |
530 int y = TileY(tile); |
564 int y = TileY(tile); |
531 |
565 |
532 // expand the region by rad tiles on each side |
566 /* expand the region by rad tiles on each side |
533 // while making sure that we remain inside the board. |
567 * while making sure that we remain inside the board. */ |
534 int x2 = min(x + w + rad, MapSizeX()); |
568 int x2 = min(x + w + rad, MapSizeX()); |
535 int y2 = min(y + h + rad, MapSizeY()); |
569 int y2 = min(y + h + rad, MapSizeY()); |
536 int x1 = max(x - rad, 0); |
570 int x1 = max(x - rad, 0); |
537 int y1 = max(y - rad, 0); |
571 int y1 = max(y - rad, 0); |
538 |
572 |
628 ); |
664 ); |
629 } else { |
665 } else { |
630 memset(accepts, 0, sizeof(accepts)); |
666 memset(accepts, 0, sizeof(accepts)); |
631 } |
667 } |
632 |
668 |
633 // Adjust in case our station only accepts fewer kinds of goods |
669 /* Adjust in case our station only accepts fewer kinds of goods */ |
634 for (CargoID i = 0; i < NUM_CARGO; i++) { |
670 for (CargoID i = 0; i < NUM_CARGO; i++) { |
635 uint amt = min(accepts[i], 15); |
671 uint amt = min(accepts[i], 15); |
636 |
672 |
637 // Make sure the station can accept the goods type. |
673 /* Make sure the station can accept the goods type. */ |
638 bool is_passengers = IsCargoInClass(i, CC_PASSENGERS); |
674 bool is_passengers = IsCargoInClass(i, CC_PASSENGERS); |
639 if ((!is_passengers && !(st->facilities & (byte)~FACIL_BUS_STOP)) || |
675 if ((!is_passengers && !(st->facilities & (byte)~FACIL_BUS_STOP)) || |
640 (is_passengers && !(st->facilities & (byte)~FACIL_TRUCK_STOP))) |
676 (is_passengers && !(st->facilities & (byte)~FACIL_TRUCK_STOP))) |
641 amt = 0; |
677 amt = 0; |
642 |
678 |
643 SB(st->goods[i].acceptance_pickup, GoodsEntry::ACCEPTANCE, 1, amt >= 8); |
679 SB(st->goods[i].acceptance_pickup, GoodsEntry::ACCEPTANCE, 1, amt >= 8); |
644 } |
680 } |
645 |
681 |
646 // Only show a message in case the acceptance was actually changed. |
682 /* Only show a message in case the acceptance was actually changed. */ |
647 uint new_acc = GetAcceptanceMask(st); |
683 uint new_acc = GetAcceptanceMask(st); |
648 if (old_acc == new_acc) |
684 if (old_acc == new_acc) |
649 return; |
685 return; |
650 |
686 |
651 // show a message to report that the acceptance was changed? |
687 /* show a message to report that the acceptance was changed? */ |
652 if (show_msg && st->owner == _local_player && st->facilities) { |
688 if (show_msg && st->owner == _local_player && st->facilities) { |
653 /* List of accept and reject strings for different number of |
689 /* List of accept and reject strings for different number of |
654 * cargo types */ |
690 * cargo types */ |
655 static const StringID accept_msg[] = { |
691 static const StringID accept_msg[] = { |
656 STR_3040_NOW_ACCEPTS, |
692 STR_3040_NOW_ACCEPTS, |
685 /* Show news message if there are any changes */ |
721 /* Show news message if there are any changes */ |
686 if (num_acc > 0) ShowRejectOrAcceptNews(st, num_acc, accepts, accept_msg[num_acc - 1]); |
722 if (num_acc > 0) ShowRejectOrAcceptNews(st, num_acc, accepts, accept_msg[num_acc - 1]); |
687 if (num_rej > 0) ShowRejectOrAcceptNews(st, num_rej, rejects, reject_msg[num_rej - 1]); |
723 if (num_rej > 0) ShowRejectOrAcceptNews(st, num_rej, rejects, reject_msg[num_rej - 1]); |
688 } |
724 } |
689 |
725 |
690 // redraw the station view since acceptance changed |
726 /* redraw the station view since acceptance changed */ |
691 InvalidateWindowWidget(WC_STATION_VIEW, st->index, 4); |
727 InvalidateWindowWidget(WC_STATION_VIEW, st->index, 4); |
692 } |
728 } |
693 |
729 |
694 static void UpdateStationSignCoord(Station *st) |
730 static void UpdateStationSignCoord(Station *st) |
695 { |
731 { |
696 const StationRect *r = &st->rect; |
732 const StationRect *r = &st->rect; |
697 |
733 |
698 if (r->IsEmpty()) return; // no tiles belong to this station |
734 if (r->IsEmpty()) return; /* no tiles belong to this station */ |
699 |
735 |
700 // clamp sign coord to be inside the station rect |
736 /* clamp sign coord to be inside the station rect */ |
701 st->xy = TileXY(clampu(TileX(st->xy), r->left, r->right), clampu(TileY(st->xy), r->top, r->bottom)); |
737 st->xy = TileXY(ClampU(TileX(st->xy), r->left, r->right), ClampU(TileY(st->xy), r->top, r->bottom)); |
702 UpdateStationVirtCoordDirty(st); |
738 UpdateStationVirtCoordDirty(st); |
703 } |
739 } |
704 |
740 |
705 // This is called right after a station was deleted. |
741 /** This is called right after a station was deleted. |
706 // It checks if the whole station is free of substations, and if so, the station will be |
742 * It checks if the whole station is free of substations, and if so, the station will be |
707 // deleted after a little while. |
743 * deleted after a little while. |
708 static void DeleteStationIfEmpty(Station* st) |
744 * @param st Station |
|
745 */ |
|
746 static void DeleteStationIfEmpty(Station *st) |
709 { |
747 { |
710 if (st->facilities == 0) { |
748 if (st->facilities == 0) { |
711 st->delete_ctr = 0; |
749 st->delete_ctr = 0; |
712 RebuildStationLists(); |
750 RebuildStationLists(); |
713 InvalidateWindow(WC_STATION_LIST, st->owner); |
751 InvalidateWindow(WC_STATION_LIST, st->owner); |
716 UpdateStationSignCoord(st); |
754 UpdateStationSignCoord(st); |
717 } |
755 } |
718 |
756 |
719 static CommandCost ClearTile_Station(TileIndex tile, byte flags); |
757 static CommandCost ClearTile_Station(TileIndex tile, byte flags); |
720 |
758 |
721 // Tries to clear the given area. Returns the cost in case of success. |
759 /** Tries to clear the given area. |
722 // Or an error code if it failed. |
760 * @param tile TileIndex to start check |
|
761 * @param w width of search area |
|
762 * @param h height of search area |
|
763 * @param flags operation to perform |
|
764 * @param invalid_dirs prohibited directions |
|
765 * @param station StationID to be queried and returned if available |
|
766 * @param check_clear if clearing tile should be performed (in wich case, cost will be added) |
|
767 * @return the cost in case of success, or an error code if it failed. |
|
768 */ |
723 CommandCost CheckFlatLandBelow(TileIndex tile, uint w, uint h, uint flags, uint32 invalid_dirs, StationID* station, const FSMportsSpec *fsmportspec, bool check_clear = true) |
769 CommandCost CheckFlatLandBelow(TileIndex tile, uint w, uint h, uint flags, uint32 invalid_dirs, StationID* station, const FSMportsSpec *fsmportspec, bool check_clear = true) |
724 { |
770 { |
725 CommandCost cost; |
771 CommandCost cost; |
726 int allowed_z = -1; |
772 int allowed_z = -1; |
727 byte layout_set = GB(invalid_dirs, 0, 3); |
773 byte layout_set = GB(invalid_dirs, 0, 3); |
827 TileIndex tile = fin[0]; |
873 TileIndex tile = fin[0]; |
828 uint w = fin[1]; |
874 uint w = fin[1]; |
829 uint h = fin[2]; |
875 uint h = fin[2]; |
830 |
876 |
831 if (_patches.nonuniform_stations) { |
877 if (_patches.nonuniform_stations) { |
832 // determine new size of train station region.. |
878 /* determine new size of train station region.. */ |
833 int x = min(TileX(st->train_tile), TileX(tile)); |
879 int x = min(TileX(st->train_tile), TileX(tile)); |
834 int y = min(TileY(st->train_tile), TileY(tile)); |
880 int y = min(TileY(st->train_tile), TileY(tile)); |
835 curw = max(TileX(st->train_tile) + curw, TileX(tile) + w) - x; |
881 curw = max(TileX(st->train_tile) + curw, TileX(tile) + w) - x; |
836 curh = max(TileY(st->train_tile) + curh, TileY(tile) + h) - y; |
882 curh = max(TileY(st->train_tile) + curh, TileY(tile) + h) - y; |
837 tile = TileXY(x, y); |
883 tile = TileXY(x, y); |
838 } else { |
884 } else { |
839 // check so the orientation is the same |
885 /* check so the orientation is the same */ |
840 if (GetRailStationAxis(st->train_tile) != axis) { |
886 if (GetRailStationAxis(st->train_tile) != axis) { |
841 _error_message = STR_306D_NONUNIFORM_STATIONS_DISALLOWED; |
887 _error_message = STR_306D_NONUNIFORM_STATIONS_DISALLOWED; |
842 return false; |
888 return false; |
843 } |
889 } |
844 |
890 |
845 // check if the new station adjoins the old station in either direction |
891 /* check if the new station adjoins the old station in either direction */ |
846 if (curw == w && st->train_tile == tile + TileDiffXY(0, h)) { |
892 if (curw == w && st->train_tile == tile + TileDiffXY(0, h)) { |
847 // above |
893 /* above */ |
848 curh += h; |
894 curh += h; |
849 } else if (curw == w && st->train_tile == tile - TileDiffXY(0, curh)) { |
895 } else if (curw == w && st->train_tile == tile - TileDiffXY(0, curh)) { |
850 // below |
896 /* below */ |
851 tile -= TileDiffXY(0, curh); |
897 tile -= TileDiffXY(0, curh); |
852 curh += h; |
898 curh += h; |
853 } else if (curh == h && st->train_tile == tile + TileDiffXY(w, 0)) { |
899 } else if (curh == h && st->train_tile == tile + TileDiffXY(w, 0)) { |
854 // to the left |
900 /* to the left */ |
855 curw += w; |
901 curw += w; |
856 } else if (curh == h && st->train_tile == tile - TileDiffXY(curw, 0)) { |
902 } else if (curh == h && st->train_tile == tile - TileDiffXY(curw, 0)) { |
857 // to the right |
903 /* to the right */ |
858 tile -= TileDiffXY(curw, 0); |
904 tile -= TileDiffXY(curw, 0); |
859 curw += w; |
905 curw += w; |
860 } else { |
906 } else { |
861 _error_message = STR_306D_NONUNIFORM_STATIONS_DISALLOWED; |
907 _error_message = STR_306D_NONUNIFORM_STATIONS_DISALLOWED; |
862 return false; |
908 return false; |
863 } |
909 } |
864 } |
910 } |
865 // make sure the final size is not too big. |
911 /* make sure the final size is not too big. */ |
866 if (curw > _patches.station_spread || curh > _patches.station_spread) { |
912 if (curw > _patches.station_spread || curh > _patches.station_spread) { |
867 _error_message = STR_306C_STATION_TOO_SPREAD_OUT; |
913 _error_message = STR_306C_STATION_TOO_SPREAD_OUT; |
868 return false; |
914 return false; |
869 } |
915 } |
870 |
916 |
871 // now tile contains the new value for st->train_tile |
917 /* now tile contains the new value for st->train_tile |
872 // curw, curh contain the new value for width and height |
918 * curw, curh contain the new value for width and height */ |
873 fin[0] = tile; |
919 fin[0] = tile; |
874 fin[1] = curw; |
920 fin[1] = curw; |
875 fin[2] = curh; |
921 fin[2] = curh; |
876 return true; |
922 return true; |
877 } |
923 } |
955 w_org = numtracks; |
1001 w_org = numtracks; |
956 } |
1002 } |
957 |
1003 |
958 if (h_org > _patches.station_spread || w_org > _patches.station_spread) return CMD_ERROR; |
1004 if (h_org > _patches.station_spread || w_org > _patches.station_spread) return CMD_ERROR; |
959 |
1005 |
960 // these values are those that will be stored in train_tile and station_platforms |
1006 /* these values are those that will be stored in train_tile and station_platforms */ |
961 uint finalvalues[3]; |
1007 uint finalvalues[3]; |
962 finalvalues[0] = tile_org; |
1008 finalvalues[0] = tile_org; |
963 finalvalues[1] = w_org; |
1009 finalvalues[1] = w_org; |
964 finalvalues[2] = h_org; |
1010 finalvalues[2] = h_org; |
965 |
1011 |
966 // Make sure the area below consists of clear tiles. (OR tiles belonging to a certain rail station) |
1012 /* Make sure the area below consists of clear tiles. (OR tiles belonging to a certain rail station) */ |
967 StationID est = INVALID_STATION; |
1013 StationID est = INVALID_STATION; |
968 // If DC_EXEC is in flag, do not want to pass it to CheckFlatLandBelow, because of a nice bug |
1014 /* If DC_EXEC is in flag, do not want to pass it to CheckFlatLandBelow, because of a nice bug |
969 // for detail info, see: https://sourceforge.net/tracker/index.php?func=detail&aid=1029064&group_id=103924&atid=636365 |
1015 * for detail info, see: |
|
1016 * https://sourceforge.net/tracker/index.php?func=detail&aid=1029064&group_id=103924&atid=636365 */ |
970 ret = CheckFlatLandBelow(tile_org, w_org, h_org, flags & ~DC_EXEC, 5 << axis, _patches.nonuniform_stations ? &est : NULL); |
1017 ret = CheckFlatLandBelow(tile_org, w_org, h_org, flags & ~DC_EXEC, 5 << axis, _patches.nonuniform_stations ? &est : NULL); |
971 if (CmdFailed(ret)) return ret; |
1018 if (CmdFailed(ret)) return ret; |
972 CommandCost cost(ret.GetCost() + (numtracks * _price.train_station_track + _price.train_station_length) * plat_len); |
1019 CommandCost cost(ret.GetCost() + (numtracks * _price.train_station_track + _price.train_station_length) * plat_len); |
973 |
1020 |
974 Station *st = NULL; |
1021 Station *st = NULL; |
975 bool check_surrounding = true; |
1022 bool check_surrounding = true; |
976 |
1023 |
977 if (_patches.adjacent_stations) { |
1024 if (_patches.adjacent_stations) { |
978 if (est != INVALID_STATION) { |
1025 if (est != INVALID_STATION) { |
979 if (HASBIT(p1, 24)) { |
1026 if (HasBit(p1, 24)) { |
980 /* You can't build an adjacent station over the top of one that |
1027 /* You can't build an adjacent station over the top of one that |
981 * already exists. */ |
1028 * already exists. */ |
982 return_cmd_error(STR_MUST_REMOVE_RAILWAY_STATION_FIRST); |
1029 return_cmd_error(STR_MUST_REMOVE_RAILWAY_STATION_FIRST); |
983 } else { |
1030 } else { |
984 /* Extend the current station, and don't check whether it will |
1031 /* Extend the current station, and don't check whether it will |
987 check_surrounding = false; |
1034 check_surrounding = false; |
988 } |
1035 } |
989 } else { |
1036 } else { |
990 /* There's no station here. Don't check the tiles surrounding this |
1037 /* There's no station here. Don't check the tiles surrounding this |
991 * one if the player wanted to build an adjacent station. */ |
1038 * one if the player wanted to build an adjacent station. */ |
992 if (HASBIT(p1, 24)) check_surrounding = false; |
1039 if (HasBit(p1, 24)) check_surrounding = false; |
993 } |
1040 } |
994 } |
1041 } |
995 |
1042 |
996 if (check_surrounding) { |
1043 if (check_surrounding) { |
997 // Make sure there are no similar stations around us. |
1044 /* Make sure there are no similar stations around us. */ |
998 st = GetStationAround(tile_org, w_org, h_org, est); |
1045 st = GetStationAround(tile_org, w_org, h_org, est); |
999 if (st == CHECK_STATIONS_ERR) return CMD_ERROR; |
1046 if (st == CHECK_STATIONS_ERR) return CMD_ERROR; |
1000 } |
1047 } |
1001 |
1048 |
1002 // See if there is a deleted station close to us. |
1049 /* See if there is a deleted station close to us. */ |
1003 if (st == NULL) st = GetClosestStationFromTile(tile_org); |
1050 if (st == NULL) st = GetClosestStationFromTile(tile_org); |
1004 |
1051 |
1005 /* In case of new station if DC_EXEC is NOT set we still need to create the station |
1052 /* In case of new station if DC_EXEC is NOT set we still need to create the station |
1006 * to test if everything is OK. In this case we need to delete it before return. */ |
1053 * to test if everything is OK. In this case we need to delete it before return. */ |
1007 AutoPtrT<Station> st_auto_delete; |
1054 AutoPtrT<Station> st_auto_delete; |
1008 |
1055 |
1009 if (st != NULL) { |
1056 if (st != NULL) { |
1010 // Reuse an existing station. |
1057 /* Reuse an existing station. */ |
1011 if (st->owner != _current_player) |
1058 if (st->owner != _current_player) |
1012 return_cmd_error(STR_3009_TOO_CLOSE_TO_ANOTHER_STATION); |
1059 return_cmd_error(STR_3009_TOO_CLOSE_TO_ANOTHER_STATION); |
1013 |
1060 |
1014 if (st->train_tile != 0) { |
1061 if (st->train_tile != 0) { |
1015 // check if we want to expanding an already existing station? |
1062 /* check if we want to expanding an already existing station? */ |
1016 if (_is_old_ai_player || !_patches.join_stations) |
1063 if (_is_old_ai_player || !_patches.join_stations) |
1017 return_cmd_error(STR_3005_TOO_CLOSE_TO_ANOTHER_RAILROAD); |
1064 return_cmd_error(STR_3005_TOO_CLOSE_TO_ANOTHER_RAILROAD); |
1018 if (!CanExpandRailroadStation(st, finalvalues, axis)) |
1065 if (!CanExpandRailroadStation(st, finalvalues, axis)) |
1019 return CMD_ERROR; |
1066 return CMD_ERROR; |
1020 } |
1067 } |
1021 |
1068 |
1022 //XXX can't we pack this in the "else" part of the if above? |
1069 /* XXX can't we pack this in the "else" part of the if above? */ |
1023 if (!st->rect.BeforeAddRect(tile_org, w_org, h_org, StationRect::ADD_TEST)) return CMD_ERROR; |
1070 if (!st->rect.BeforeAddRect(tile_org, w_org, h_org, StationRect::ADD_TEST)) return CMD_ERROR; |
1024 } else { |
1071 } else { |
1025 /* allocate and initialize new station */ |
1072 /* allocate and initialize new station */ |
1026 st = new Station(tile_org); |
1073 st = new Station(tile_org); |
1027 if (st == NULL) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING); |
1074 if (st == NULL) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING); |
1028 |
1075 |
1029 /* ensure that in case of error (or no DC_EXEC) the station gets deleted upon return */ |
1076 /* ensure that in case of error (or no DC_EXEC) the station gets deleted upon return */ |
1030 st_auto_delete = st; |
1077 st_auto_delete = st; |
1031 |
1078 |
1032 st->town = ClosestTownFromTile(tile_org, (uint)-1); |
1079 st->town = ClosestTownFromTile(tile_org, (uint)-1); |
1033 if (!GenerateStationName(st, tile_org, 0)) return CMD_ERROR; |
1080 if (!GenerateStationName(st, tile_org, STATIONNAMING_RAIL)) return CMD_ERROR; |
1034 |
1081 |
1035 if (IsValidPlayer(_current_player) && (flags & DC_EXEC) != 0) { |
1082 if (IsValidPlayer(_current_player) && (flags & DC_EXEC) != 0) { |
1036 SETBIT(st->town->have_ratings, _current_player); |
1083 SetBit(st->town->have_ratings, _current_player); |
1037 } |
1084 } |
1038 } |
1085 } |
1039 |
1086 |
1040 /* Check if the given station class is valid */ |
1087 /* Check if the given station class is valid */ |
1041 if (GB(p2, 8, 8) >= STAT_CLASS_MAX) return CMD_ERROR; |
1088 if (GB(p2, 8, 8) >= STAT_CLASS_MAX) return CMD_ERROR; |
1047 |
1094 |
1048 if (statspec != NULL) { |
1095 if (statspec != NULL) { |
1049 /* Perform NewStation checks */ |
1096 /* Perform NewStation checks */ |
1050 |
1097 |
1051 /* Check if the station size is permitted */ |
1098 /* Check if the station size is permitted */ |
1052 if (HASBIT(statspec->disallowed_platforms, numtracks - 1) || HASBIT(statspec->disallowed_lengths, plat_len - 1)) { |
1099 if (HasBit(statspec->disallowed_platforms, numtracks - 1) || HasBit(statspec->disallowed_lengths, plat_len - 1)) { |
1053 return CMD_ERROR; |
1100 return CMD_ERROR; |
1054 } |
1101 } |
1055 |
1102 |
1056 /* Check if the station is buildable */ |
1103 /* Check if the station is buildable */ |
1057 if (HASBIT(statspec->callbackmask, CBM_STATION_AVAIL) && GetStationCallback(CBID_STATION_AVAILABILITY, 0, 0, statspec, NULL, INVALID_TILE) == 0) { |
1104 if (HasBit(statspec->callbackmask, CBM_STATION_AVAIL) && GetStationCallback(CBID_STATION_AVAILABILITY, 0, 0, statspec, NULL, INVALID_TILE) == 0) { |
1058 return CMD_ERROR; |
1105 return CMD_ERROR; |
1059 } |
1106 } |
1060 } |
1107 } |
1061 |
1108 |
1062 if (flags & DC_EXEC) { |
1109 if (flags & DC_EXEC) { |
1063 TileIndexDiff tile_delta; |
1110 TileIndexDiff tile_delta; |
1064 byte *layout_ptr; |
1111 byte *layout_ptr; |
1065 byte numtracks_orig; |
1112 byte numtracks_orig; |
1066 Track track; |
1113 Track track; |
1067 |
1114 |
1068 // Now really clear the land below the station |
1115 /* Now really clear the land below the station |
1069 // It should never return CMD_ERROR.. but you never know ;) |
1116 * It should never return CMD_ERROR.. but you never know ;) |
1070 // (a bit strange function name for it, but it really does clear the land, when DC_EXEC is in flags) |
1117 * (a bit strange function name for it, but it really does clear the land, when DC_EXEC is in flags) */ |
1071 ret = CheckFlatLandBelow(tile_org, w_org, h_org, flags, 5 << axis, _patches.nonuniform_stations ? &est : NULL); |
1118 ret = CheckFlatLandBelow(tile_org, w_org, h_org, flags, 5 << axis, _patches.nonuniform_stations ? &est : NULL); |
1072 if (CmdFailed(ret)) return ret; |
1119 if (CmdFailed(ret)) return ret; |
1073 |
1120 |
1074 st->train_tile = finalvalues[0]; |
1121 st->train_tile = finalvalues[0]; |
1075 st->AddFacility(FACIL_TRAIN, finalvalues[0]); |
1122 st->AddFacility(FACIL_TRAIN, finalvalues[0]); |
1097 SetStationTileRandomBits(tile, GB(Random(), 0, 4)); |
1144 SetStationTileRandomBits(tile, GB(Random(), 0, 4)); |
1098 |
1145 |
1099 if (statspec != NULL) { |
1146 if (statspec != NULL) { |
1100 /* Use a fixed axis for GetPlatformInfo as our platforms / numtracks are always the right way around */ |
1147 /* Use a fixed axis for GetPlatformInfo as our platforms / numtracks are always the right way around */ |
1101 uint32 platinfo = GetPlatformInfo(AXIS_X, 0, plat_len, numtracks_orig, plat_len - w, numtracks_orig - numtracks, false); |
1148 uint32 platinfo = GetPlatformInfo(AXIS_X, 0, plat_len, numtracks_orig, plat_len - w, numtracks_orig - numtracks, false); |
1102 uint16 callback = GetStationCallback(CBID_STATION_TILE_LAYOUT, platinfo, 0, statspec, st, tile); |
1149 |
|
1150 /* As the station is not yet completely finished, the station does not yet exist. */ |
|
1151 uint16 callback = GetStationCallback(CBID_STATION_TILE_LAYOUT, platinfo, 0, statspec, NULL, tile); |
1103 if (callback != CALLBACK_FAILED && callback < 8) SetStationGfx(tile, (callback & ~1) + axis); |
1152 if (callback != CALLBACK_FAILED && callback < 8) SetStationGfx(tile, (callback & ~1) + axis); |
1104 } |
1153 } |
1105 |
1154 |
1106 tile += tile_delta; |
1155 tile += tile_delta; |
1107 } while (--w); |
1156 } while (--w); |
1128 uint h = st->trainst_h; |
1177 uint h = st->trainst_h; |
1129 TileIndex tile = st->train_tile; |
1178 TileIndex tile = st->train_tile; |
1130 |
1179 |
1131 restart: |
1180 restart: |
1132 |
1181 |
1133 // too small? |
1182 /* too small? */ |
1134 if (w != 0 && h != 0) { |
1183 if (w != 0 && h != 0) { |
1135 // check the left side, x = constant, y changes |
1184 /* check the left side, x = constant, y changes */ |
1136 for (uint i = 0; !st->TileBelongsToRailStation(tile + TileDiffXY(0, i));) { |
1185 for (uint i = 0; !st->TileBelongsToRailStation(tile + TileDiffXY(0, i));) { |
1137 // the left side is unused? |
1186 /* the left side is unused? */ |
1138 if (++i == h) { |
1187 if (++i == h) { |
1139 tile += TileDiffXY(1, 0); |
1188 tile += TileDiffXY(1, 0); |
1140 w--; |
1189 w--; |
1141 goto restart; |
1190 goto restart; |
1142 } |
1191 } |
1143 } |
1192 } |
1144 |
1193 |
1145 // check the right side, x = constant, y changes |
1194 /* check the right side, x = constant, y changes */ |
1146 for (uint i = 0; !st->TileBelongsToRailStation(tile + TileDiffXY(w - 1, i));) { |
1195 for (uint i = 0; !st->TileBelongsToRailStation(tile + TileDiffXY(w - 1, i));) { |
1147 // the right side is unused? |
1196 /* the right side is unused? */ |
1148 if (++i == h) { |
1197 if (++i == h) { |
1149 w--; |
1198 w--; |
1150 goto restart; |
1199 goto restart; |
1151 } |
1200 } |
1152 } |
1201 } |
1153 |
1202 |
1154 // check the upper side, y = constant, x changes |
1203 /* check the upper side, y = constant, x changes */ |
1155 for (uint i = 0; !st->TileBelongsToRailStation(tile + TileDiffXY(i, 0));) { |
1204 for (uint i = 0; !st->TileBelongsToRailStation(tile + TileDiffXY(i, 0));) { |
1156 // the left side is unused? |
1205 /* the left side is unused? */ |
1157 if (++i == w) { |
1206 if (++i == w) { |
1158 tile += TileDiffXY(0, 1); |
1207 tile += TileDiffXY(0, 1); |
1159 h--; |
1208 h--; |
1160 goto restart; |
1209 goto restart; |
1161 } |
1210 } |
1162 } |
1211 } |
1163 |
1212 |
1164 // check the lower side, y = constant, x changes |
1213 /* check the lower side, y = constant, x changes */ |
1165 for (uint i = 0; !st->TileBelongsToRailStation(tile + TileDiffXY(i, h - 1));) { |
1214 for (uint i = 0; !st->TileBelongsToRailStation(tile + TileDiffXY(i, h - 1));) { |
1166 // the left side is unused? |
1215 /* the left side is unused? */ |
1167 if (++i == w) { |
1216 if (++i == w) { |
1168 h--; |
1217 h--; |
1169 goto restart; |
1218 goto restart; |
1170 } |
1219 } |
1171 } |
1220 } |
1232 SetSignalsOnBothDir(tile2, track); |
1281 SetSignalsOnBothDir(tile2, track); |
1233 YapfNotifyTrackLayoutChange(tile2, track); |
1282 YapfNotifyTrackLayoutChange(tile2, track); |
1234 |
1283 |
1235 DeallocateSpecFromStation(st, specindex); |
1284 DeallocateSpecFromStation(st, specindex); |
1236 |
1285 |
1237 // now we need to make the "spanned" area of the railway station smaller if we deleted something at the edges. |
1286 /* now we need to make the "spanned" area of the railway station smaller |
1238 // we also need to adjust train_tile. |
1287 * if we deleted something at the edges. |
|
1288 * we also need to adjust train_tile. */ |
1239 MakeRailwayStationAreaSmaller(st); |
1289 MakeRailwayStationAreaSmaller(st); |
1240 st->MarkTilesDirty(false); |
1290 st->MarkTilesDirty(false); |
1241 UpdateStationSignCoord(st); |
1291 UpdateStationSignCoord(st); |
1242 |
1292 |
1243 // if we deleted the whole station, delete the train facility. |
1293 /* if we deleted the whole station, delete the train facility. */ |
1244 if (st->train_tile == 0) { |
1294 if (st->train_tile == 0) { |
1245 st->facilities &= ~FACIL_TRAIN; |
1295 st->facilities &= ~FACIL_TRAIN; |
1246 UpdateStationVirtCoordDirty(st); |
1296 UpdateStationVirtCoordDirty(st); |
1247 DeleteStationIfEmpty(st); |
1297 DeleteStationIfEmpty(st); |
1248 } |
1298 } |
1366 * bit 2..4: the roadtypes |
1416 * bit 2..4: the roadtypes |
1367 * bit 5: allow stations directly adjacent to other stations. |
1417 * bit 5: allow stations directly adjacent to other stations. |
1368 */ |
1418 */ |
1369 CommandCost CmdBuildRoadStop(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
1419 CommandCost CmdBuildRoadStop(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
1370 { |
1420 { |
1371 bool type = HASBIT(p2, 0); |
1421 bool type = HasBit(p2, 0); |
1372 bool is_drive_through = HASBIT(p2, 1); |
1422 bool is_drive_through = HasBit(p2, 1); |
1373 bool build_over_road = is_drive_through && IsTileType(tile, MP_ROAD) && GetRoadTileType(tile) == ROAD_TILE_NORMAL; |
1423 bool build_over_road = is_drive_through && IsTileType(tile, MP_ROAD) && GetRoadTileType(tile) == ROAD_TILE_NORMAL; |
1374 bool town_owned_road = build_over_road && IsTileOwner(tile, OWNER_TOWN); |
1424 bool town_owned_road = build_over_road && IsTileOwner(tile, OWNER_TOWN); |
1375 RoadTypes rts = (RoadTypes)GB(p2, 2, 3); |
1425 RoadTypes rts = (RoadTypes)GB(p2, 2, 3); |
1376 |
1426 |
1377 if (rts == ROADTYPES_NONE || HASBIT(rts, ROADTYPE_HWAY)) return CMD_ERROR; |
1427 if (!AreValidRoadTypes(rts) || !HasRoadTypesAvail(_current_player, rts)) return CMD_ERROR; |
1378 |
1428 |
1379 /* Trams only have drive through stops */ |
1429 /* Trams only have drive through stops */ |
1380 if (!is_drive_through && HASBIT(rts, ROADTYPE_TRAM)) return CMD_ERROR; |
1430 if (!is_drive_through && HasBit(rts, ROADTYPE_TRAM)) return CMD_ERROR; |
1381 |
1431 |
1382 /* Saveguard the parameters */ |
1432 /* Saveguard the parameters */ |
1383 if (!IsValidDiagDirection((DiagDirection)p1)) return CMD_ERROR; |
1433 if (!IsValidDiagDirection((DiagDirection)p1)) return CMD_ERROR; |
1384 /* If it is a drive-through stop check for valid axis */ |
1434 /* If it is a drive-through stop check for valid axis */ |
1385 if (is_drive_through && !IsValidAxis((Axis)p1)) return CMD_ERROR; |
1435 if (is_drive_through && !IsValidAxis((Axis)p1)) return CMD_ERROR; |
1399 |
1449 |
1400 /* Don't allow building the roadstop when vehicles are already driving on it */ |
1450 /* Don't allow building the roadstop when vehicles are already driving on it */ |
1401 if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; |
1451 if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; |
1402 |
1452 |
1403 RoadTypes cur_rts = GetRoadTypes(tile); |
1453 RoadTypes cur_rts = GetRoadTypes(tile); |
1404 if (GetRoadOwner(tile, ROADTYPE_ROAD) != OWNER_TOWN && HASBIT(cur_rts, ROADTYPE_ROAD) && !CheckOwnership(GetRoadOwner(tile, ROADTYPE_ROAD))) return CMD_ERROR; |
1454 if (GetRoadOwner(tile, ROADTYPE_ROAD) != OWNER_TOWN && HasBit(cur_rts, ROADTYPE_ROAD) && !CheckOwnership(GetRoadOwner(tile, ROADTYPE_ROAD))) return CMD_ERROR; |
1405 if (HASBIT(cur_rts, ROADTYPE_TRAM) && !CheckOwnership(GetRoadOwner(tile, ROADTYPE_TRAM))) return CMD_ERROR; |
1455 if (HasBit(cur_rts, ROADTYPE_TRAM) && !CheckOwnership(GetRoadOwner(tile, ROADTYPE_TRAM))) return CMD_ERROR; |
1406 |
1456 |
1407 /* Do not remove roadtypes! */ |
1457 /* Do not remove roadtypes! */ |
1408 rts |= cur_rts; |
1458 rts |= cur_rts; |
1409 } |
1459 } |
1410 cost = CheckFlatLandBelow(tile, 1, 1, flags, is_drive_through ? 5 << p1 : 1 << p1, NULL, false, !build_over_road); |
1460 cost = CheckFlatLandBelow(tile, 1, 1, flags, is_drive_through ? 5 << p1 : 1 << p1, NULL, false, !build_over_road); |
1411 if (CmdFailed(cost)) return cost; |
1461 if (CmdFailed(cost)) return cost; |
1412 |
1462 |
1413 Station *st = NULL; |
1463 Station *st = NULL; |
1414 |
1464 |
1415 if (!_patches.adjacent_stations || !HASBIT(p2, 5)) { |
1465 if (!_patches.adjacent_stations || !HasBit(p2, 5)) { |
1416 st = GetStationAround(tile, 1, 1, INVALID_STATION); |
1466 st = GetStationAround(tile, 1, 1, INVALID_STATION); |
1417 if (st == CHECK_STATIONS_ERR) return CMD_ERROR; |
1467 if (st == CHECK_STATIONS_ERR) return CMD_ERROR; |
1418 } |
1468 } |
1419 |
1469 |
1420 /* Find a station close to us */ |
1470 /* Find a station close to us */ |
1421 if (st == NULL) st = GetClosestStationFromTile(tile); |
1471 if (st == NULL) st = GetClosestStationFromTile(tile); |
1422 |
1472 |
1423 //give us a road stop in the list, and check if something went wrong |
1473 /* give us a road stop in the list, and check if something went wrong */ |
1424 RoadStop *road_stop = new RoadStop(tile); |
1474 RoadStop *road_stop = new RoadStop(tile); |
1425 if (road_stop == NULL) { |
1475 if (road_stop == NULL) { |
1426 return_cmd_error(type ? STR_3008B_TOO_MANY_TRUCK_STOPS : STR_3008A_TOO_MANY_BUS_STOPS); |
1476 return_cmd_error(type ? STR_3008B_TOO_MANY_TRUCK_STOPS : STR_3008A_TOO_MANY_BUS_STOPS); |
1427 } |
1477 } |
1428 |
1478 |
1452 /* ensure that in case of error (or no DC_EXEC) the new station gets deleted upon return */ |
1502 /* ensure that in case of error (or no DC_EXEC) the new station gets deleted upon return */ |
1453 st_auto_delete = st; |
1503 st_auto_delete = st; |
1454 |
1504 |
1455 |
1505 |
1456 Town *t = st->town = ClosestTownFromTile(tile, (uint)-1); |
1506 Town *t = st->town = ClosestTownFromTile(tile, (uint)-1); |
1457 if (!GenerateStationName(st, tile, 0)) return CMD_ERROR; |
1507 if (!GenerateStationName(st, tile, STATIONNAMING_ROAD)) return CMD_ERROR; |
1458 |
1508 |
1459 if (IsValidPlayer(_current_player) && (flags & DC_EXEC) != 0) { |
1509 if (IsValidPlayer(_current_player) && (flags & DC_EXEC) != 0) { |
1460 SETBIT(t->have_ratings, _current_player); |
1510 SetBit(t->have_ratings, _current_player); |
1461 } |
1511 } |
1462 |
1512 |
1463 st->sign.width_1 = 0; |
1513 st->sign.width_1 = 0; |
1464 } |
1514 } |
1465 |
1515 |
1466 cost.AddCost((type) ? _price.build_truck_station : _price.build_bus_station); |
1516 cost.AddCost((type) ? _price.build_truck_station : _price.build_bus_station); |
1467 |
1517 |
1468 if (flags & DC_EXEC) { |
1518 if (flags & DC_EXEC) { |
1469 // Insert into linked list of RoadStops |
1519 /* Insert into linked list of RoadStops */ |
1470 RoadStop **currstop = FindRoadStopSpot(type, st); |
1520 RoadStop **currstop = FindRoadStopSpot(type, st); |
1471 *currstop = road_stop; |
1521 *currstop = road_stop; |
1472 |
1522 |
1473 //initialize an empty station |
1523 /*initialize an empty station */ |
1474 st->AddFacility((type) ? FACIL_TRUCK_STOP : FACIL_BUS_STOP, tile); |
1524 st->AddFacility((type) ? FACIL_TRUCK_STOP : FACIL_BUS_STOP, tile); |
1475 |
1525 |
1476 st->rect.BeforeAddTile(tile, StationRect::ADD_TRY); |
1526 st->rect.BeforeAddTile(tile, StationRect::ADD_TRY); |
1477 |
1527 |
1478 RoadStop::Type rs_type = type ? RoadStop::TRUCK : RoadStop::BUS; |
1528 RoadStop::Type rs_type = type ? RoadStop::TRUCK : RoadStop::BUS; |
1512 cur_stop = GetRoadStopByTile(tile, RoadStop::BUS); |
1567 cur_stop = GetRoadStopByTile(tile, RoadStop::BUS); |
1513 } |
1568 } |
1514 |
1569 |
1515 assert(cur_stop != NULL); |
1570 assert(cur_stop != NULL); |
1516 |
1571 |
1517 if (!EnsureNoVehicle(tile)) return CMD_ERROR; |
1572 if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; |
1518 |
1573 |
1519 if (flags & DC_EXEC) { |
1574 if (flags & DC_EXEC) { |
1520 if (*primary_stop == cur_stop) { |
1575 if (*primary_stop == cur_stop) { |
1521 // removed the first stop in the list |
1576 /* removed the first stop in the list */ |
1522 *primary_stop = cur_stop->next; |
1577 *primary_stop = cur_stop->next; |
1523 // removed the only stop? |
1578 /* removed the only stop? */ |
1524 if (*primary_stop == NULL) { |
1579 if (*primary_stop == NULL) { |
1525 st->facilities &= (is_truck ? ~FACIL_TRUCK_STOP : ~FACIL_BUS_STOP); |
1580 st->facilities &= (is_truck ? ~FACIL_TRUCK_STOP : ~FACIL_BUS_STOP); |
1526 } |
1581 } |
1527 } else { |
1582 } else { |
1528 // tell the predecessor in the list to skip this stop |
1583 /* tell the predecessor in the list to skip this stop */ |
1529 RoadStop *pred = *primary_stop; |
1584 RoadStop *pred = *primary_stop; |
1530 while (pred->next != cur_stop) pred = pred->next; |
1585 while (pred->next != cur_stop) pred = pred->next; |
1531 pred->next = cur_stop->next; |
1586 pred->next = cur_stop->next; |
1532 } |
1587 } |
1533 |
1588 |
1629 /* Perform NewStation checks */ |
1684 /* Perform NewStation checks */ |
1630 byte w = fsmportsspec->size_x[layout_set]; |
1685 byte w = fsmportsspec->size_x[layout_set]; |
1631 byte h = fsmportsspec->size_y[layout_set]; |
1686 byte h = fsmportsspec->size_y[layout_set]; |
1632 |
1687 |
1633 /* Check if the station is buildable */ |
1688 /* Check if the station is buildable */ |
1634 if (HASBIT(fsmportsspec->callbackmask, CBM_STATION_AVAIL) && GetFSMportsCallback(CBID_STATION_AVAILABILITY, 0, 0, fsmportsspec, NULL, INVALID_TILE) == 0) { |
1689 if (HasBit(fsmportsspec->callbackmask, CBM_STATION_AVAIL) && GetFSMportsCallback(CBID_STATION_AVAILABILITY, 0, 0, fsmportsspec, NULL, INVALID_TILE) == 0) { |
1635 return CMD_ERROR; |
1690 return CMD_ERROR; |
1636 } |
1691 } |
1637 |
1692 |
1638 if (!_patches.adjacent_stations || !HASBIT(p1, 24)) { |
1693 if (!_patches.adjacent_stations || !HasBit(p1, 24)) { |
1639 st = GetStationAround(tile, w, h, INVALID_STATION); |
1694 st = GetStationAround(tile, w, h, INVALID_STATION); |
1640 if (st == CHECK_STATIONS_ERR) return CMD_ERROR; |
1695 if (st == CHECK_STATIONS_ERR) return CMD_ERROR; |
1641 } |
1696 } |
1642 |
1697 |
1643 /* Find a station close to us */ |
1698 /* Find a station close to us */ |
1697 const byte *mask_ptr = fsmportsspec->layout_mask[layout_set] + 2; // width*length flagbytes. Also skip orientation and "filler" byte |
1752 const byte *mask_ptr = fsmportsspec->layout_mask[layout_set] + 2; // width*length flagbytes. Also skip orientation and "filler" byte |
1698 BEGIN_TILE_LOOP(tile_cur, w, h, tile) { |
1753 BEGIN_TILE_LOOP(tile_cur, w, h, tile) { |
1699 byte mask = *mask_ptr++; |
1754 byte mask = *mask_ptr++; |
1700 if (mask & 0x80) { |
1755 if (mask & 0x80) { |
1701 /* do water tests */ |
1756 /* do water tests */ |
1702 if (IsClearWaterTile(tile_cur)) { |
1757 if (IsWaterTile(tile_cur)) { |
1703 flags &= ~DC_NO_WATER; |
1758 flags &= ~DC_NO_WATER; |
1704 st->FSMport_flood_protected = true; |
1759 st->FSMport_flood_protected = true; |
1705 } else { |
1760 } else { |
1706 _error_message = STR_304B_SITE_UNSUITABLE; |
1761 _error_message = STR_304B_SITE_UNSUITABLE; |
1707 return CMD_ERROR; |
1762 return CMD_ERROR; |
1708 } |
1763 } |
1709 } else if (IsClearWaterTile(tile_cur)) { |
1764 } else if (IsWaterTile(tile_cur)) { |
1710 /* tile should be land, but is water */ |
1765 /* tile should be land, but is water */ |
1711 _error_message = STR_3807_CAN_T_BUILD_ON_WATER; |
1766 _error_message = STR_3807_CAN_T_BUILD_ON_WATER; |
1712 return CMD_ERROR; |
1767 return CMD_ERROR; |
1713 } |
1768 } |
1714 //TODO: add height comparison & validation code here |
1769 //TODO: add height comparison & validation code here |
1990 } |
2040 } |
1991 |
2041 |
1992 /* middle */ |
2042 /* middle */ |
1993 Station *st = NULL; |
2043 Station *st = NULL; |
1994 |
2044 |
1995 if (!_patches.adjacent_stations || !HASBIT(p1, 0)) { |
2045 if (!_patches.adjacent_stations || !HasBit(p1, 0)) { |
1996 st = GetStationAround( |
2046 st = GetStationAround( |
1997 tile + ToTileIndexDiff(_dock_tileoffs_chkaround[direction]), |
2047 tile + ToTileIndexDiff(_dock_tileoffs_chkaround[direction]), |
1998 _dock_w_chk[direction], _dock_h_chk[direction], INVALID_STATION); |
2048 _dock_w_chk[direction], _dock_h_chk[direction], INVALID_STATION); |
1999 if (st == CHECK_STATIONS_ERR) return CMD_ERROR; |
2049 if (st == CHECK_STATIONS_ERR) return CMD_ERROR; |
2000 } |
2050 } |
2001 |
2051 |
2002 /* Find a station close to us */ |
2052 /* Find a station close to us */ |
2003 if (st == NULL) st = GetClosestStationFromTile(tile); |
2053 if (st == NULL) st = GetClosestStationFromTile(tile); |
2004 |
2054 |
2005 /* In case of new station if DC_EXEC is NOT set we still need to create the station |
2055 /* In case of new station if DC_EXEC is NOT set we still need to create the station |
2006 * to test if everything is OK. In this case we need to delete it before return. */ |
2056 * to test if everything is OK. In this case we need to delete it before return. */ |
2007 AutoPtrT<Station> st_auto_delete; |
2057 AutoPtrT<Station> st_auto_delete; |
2008 |
2058 |
2009 if (st != NULL) { |
2059 if (st != NULL) { |
2010 if (st->owner != _current_player) |
2060 if (st->owner != _current_player) |
2011 return_cmd_error(STR_3009_TOO_CLOSE_TO_ANOTHER_STATION); |
2061 return_cmd_error(STR_3009_TOO_CLOSE_TO_ANOTHER_STATION); |
2111 |
2158 |
2112 SpriteID palette; |
2159 SpriteID palette; |
2113 if (IsValidPlayer(owner)) { |
2160 if (IsValidPlayer(owner)) { |
2114 palette = PLAYER_SPRITE_COLOR(owner); |
2161 palette = PLAYER_SPRITE_COLOR(owner); |
2115 } else { |
2162 } else { |
2116 // Some stations are not owner by a player, namely oil rigs |
2163 /* Some stations are not owner by a player, namely oil rigs */ |
2117 palette = PALETTE_TO_GREY; |
2164 palette = PALETTE_TO_GREY; |
2118 } |
2165 } |
2119 |
2166 |
2120 // don't show foundation for docks |
2167 /* don't show foundation for docks */ |
2121 if (ti->tileh != SLOPE_FLAT && !IsDock(ti->tile)) |
2168 if (ti->tileh != SLOPE_FLAT && !IsDock(ti->tile)) |
2122 DrawFoundation(ti, FOUNDATION_LEVELED); |
2169 DrawFoundation(ti, FOUNDATION_LEVELED); |
2123 |
2170 |
2124 if (IsCustomStationSpecIndex(ti->tile)) { |
2171 if (IsCustomStationSpecIndex(ti->tile)) { |
2125 // look for customization |
2172 /* look for customization */ |
2126 st = GetStationByTile(ti->tile); |
2173 st = GetStationByTile(ti->tile); |
2127 int specindex = GetCustomStationSpecIndex(ti->tile); |
2174 int specindex = GetCustomStationSpecIndex(ti->tile); |
2128 FSMport = IsCustomFSMportsSpecIndex(ti->tile); |
2175 FSMport = IsCustomFSMportsSpecIndex(ti->tile); |
2129 if (FSMport) { |
2176 if (FSMport) { |
2130 fsmportspec = st->fsmportsspeclist[specindex].spec; |
2177 fsmportspec = st->fsmportsspeclist[specindex].spec; |
2167 } |
2214 } |
2168 |
2215 |
2169 if (t == NULL || t->seq == NULL) t = &_station_display_datas[GetStationType(ti->tile)][GetStationGfx(ti->tile)]; |
2216 if (t == NULL || t->seq == NULL) t = &_station_display_datas[GetStationType(ti->tile)][GetStationGfx(ti->tile)]; |
2170 |
2217 |
2171 SpriteID image = t->ground_sprite; |
2218 SpriteID image = t->ground_sprite; |
2172 if (HASBIT(image, SPRITE_MODIFIER_USE_OFFSET)) { |
2219 if (HasBit(image, SPRITE_MODIFIER_USE_OFFSET)) { |
2173 image += (FSMport)? GetCustomFSMportsGroundRelocation(fsmportspec, st, ti->tile) : GetCustomStationGroundRelocation(statspec, st, ti->tile); |
2220 image += (FSMport)? GetCustomFSMportsGroundRelocation(fsmportspec, st, ti->tile) : GetCustomStationGroundRelocation(statspec, st, ti->tile); |
2174 image += rti->custom_ground_offset; |
2221 image += rti->custom_ground_offset; |
2175 } else { |
2222 } else { |
2176 image += rti->total_offset; |
2223 image += rti->total_offset; |
2177 } |
2224 } |
2178 |
2225 |
2179 // if ground tile 0x0F8D, but tile is desert/snow, then choose desert/snow graphic |
2226 // if ground tile 0x0F8D, but tile is desert/snow, then choose desert/snow graphic |
2180 if ((image == 0x0F8D) && (GetTropicZone(ti->tile) == TROPICZONE_DESERT)) |
2227 if ((image == 0x0F8D) && (GetTropicZone(ti->tile) == TROPICZONE_DESERT)) |
2181 image = 0x11C6; // snow tile (arctic) or desert tile (tropical) |
2228 image = 0x11C6; // snow tile (arctic) or desert tile (tropical) |
2182 |
2229 |
2183 // station_land array has been increased from 82 elements to 114 |
2230 /* station_land array has been increased from 82 elements to 114 |
2184 // but this is something else. If AI builds station with 114 it looks all weird |
2231 * but this is something else. If AI builds station with 114 it looks all weird */ |
2185 DrawGroundSprite(image, HASBIT(image, PALETTE_MODIFIER_COLOR) ? palette : PAL_NONE); |
2232 DrawGroundSprite(image, HasBit(image, PALETTE_MODIFIER_COLOR) ? palette : PAL_NONE); |
2186 |
2233 |
2187 if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC && IsStationTileElectrifiable(ti->tile)) DrawCatenary(ti); |
2234 if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC && IsStationTileElectrifiable(ti->tile)) DrawCatenary(ti); |
2188 |
2235 |
2189 if (HASBIT(roadtypes, ROADTYPE_TRAM)) { |
2236 if (HasBit(roadtypes, ROADTYPE_TRAM)) { |
2190 Axis axis = GetRoadStopDir(ti->tile) == DIAGDIR_NE ? AXIS_X : AXIS_Y; |
2237 Axis axis = GetRoadStopDir(ti->tile) == DIAGDIR_NE ? AXIS_X : AXIS_Y; |
2191 DrawGroundSprite((HASBIT(roadtypes, ROADTYPE_ROAD) ? SPR_TRAMWAY_OVERLAY : SPR_TRAMWAY_TRAM) + (axis ^ 1), PAL_NONE); |
2238 DrawGroundSprite((HasBit(roadtypes, ROADTYPE_ROAD) ? SPR_TRAMWAY_OVERLAY : SPR_TRAMWAY_TRAM) + (axis ^ 1), PAL_NONE); |
2192 DrawTramCatenary(ti, axis == AXIS_X ? ROAD_X : ROAD_Y); |
2239 DrawTramCatenary(ti, axis == AXIS_X ? ROAD_X : ROAD_Y); |
2193 } |
2240 } |
2194 |
2241 |
2195 if (IsBuoyTile(ti->tile) && (ti->z != 0 || !IsTileOwner(ti->tile, OWNER_WATER))) DrawCanalWater(ti->tile); |
2242 if (IsCanalBuoyTile(ti->tile)) DrawCanalWater(ti->tile); |
2196 |
2243 |
2197 const DrawTileSeqStruct *dtss; |
2244 const DrawTileSeqStruct *dtss; |
2198 foreach_draw_tile_seq(dtss, t->seq) { |
2245 foreach_draw_tile_seq(dtss, t->seq) { |
2199 image = dtss->image; |
2246 image = dtss->image; |
2200 if (relocation == 0 || HASBIT(image, SPRITE_MODIFIER_USE_OFFSET)) { |
2247 if (relocation == 0 || HasBit(image, SPRITE_MODIFIER_USE_OFFSET)) { |
2201 image += rti->total_offset; |
2248 image += rti->total_offset; |
2202 } else { |
2249 } else { |
2203 image += relocation; |
2250 image += relocation; |
2204 } |
2251 } |
2205 |
2252 |
2206 SpriteID pal; |
2253 SpriteID pal; |
2207 if (!HASBIT(_transparent_opt, TO_BUILDINGS) && HASBIT(image, PALETTE_MODIFIER_COLOR)) { |
2254 if (!IsTransparencySet(TO_BUILDINGS) && HasBit(image, PALETTE_MODIFIER_COLOR)) { |
2208 pal = palette; |
2255 pal = palette; |
2209 } else { |
2256 } else { |
2210 pal = dtss->pal; |
2257 pal = dtss->pal; |
2211 } |
2258 } |
2212 |
2259 |
2214 AddSortableSpriteToDraw( |
2261 AddSortableSpriteToDraw( |
2215 image, pal, |
2262 image, pal, |
2216 ti->x + dtss->delta_x, ti->y + dtss->delta_y, |
2263 ti->x + dtss->delta_x, ti->y + dtss->delta_y, |
2217 dtss->size_x, dtss->size_y, |
2264 dtss->size_x, dtss->size_y, |
2218 dtss->size_z, ti->z + dtss->delta_z, |
2265 dtss->size_z, ti->z + dtss->delta_z, |
2219 HASBIT(_transparent_opt, TO_BUILDINGS) |
2266 IsTransparencySet(TO_BUILDINGS) |
2220 ); |
2267 ); |
2221 } else { |
2268 } else { |
2222 AddChildSpriteScreen(image, pal, dtss->delta_x, dtss->delta_y, HASBIT(_transparent_opt, TO_BUILDINGS)); |
2269 AddChildSpriteScreen(image, pal, dtss->delta_x, dtss->delta_y, IsTransparencySet(TO_BUILDINGS)); |
2223 } |
2270 } |
2224 } |
2271 } |
2225 } |
2272 } |
2226 |
2273 |
2227 void StationPickerDrawSprite(int x, int y, StationType st, RailType railtype, RoadType roadtype, int image) |
2274 void StationPickerDrawSprite(int x, int y, StationType st, RailType railtype, RoadType roadtype, int image) |
2435 if (!rs->IsFreeBay(side)) return VETSB_CANNOT_ENTER; |
2482 if (!rs->IsFreeBay(side)) return VETSB_CANNOT_ENTER; |
2436 |
2483 |
2437 /* Check if the vehicle is stopping at this road stop */ |
2484 /* Check if the vehicle is stopping at this road stop */ |
2438 if (GetRoadStopType(tile) == (IsCargoInClass(v->cargo_type, CC_PASSENGERS) ? RoadStop::BUS : RoadStop::TRUCK) && |
2485 if (GetRoadStopType(tile) == (IsCargoInClass(v->cargo_type, CC_PASSENGERS) ? RoadStop::BUS : RoadStop::TRUCK) && |
2439 v->current_order.dest == GetStationIndex(tile)) { |
2486 v->current_order.dest == GetStationIndex(tile)) { |
2440 SETBIT(v->u.road.state, RVS_IS_STOPPING); |
2487 SetBit(v->u.road.state, RVS_IS_STOPPING); |
2441 rs->AllocateDriveThroughBay(side); |
2488 rs->AllocateDriveThroughBay(side); |
2442 } |
2489 } |
2443 |
2490 |
2444 /* Indicate if vehicle is using second bay. */ |
2491 /* Indicate if vehicle is using second bay. */ |
2445 if (side == 1) SETBIT(v->u.road.state, RVS_USING_SECOND_BAY); |
2492 if (side == 1) SetBit(v->u.road.state, RVS_USING_SECOND_BAY); |
2446 /* Indicate a drive-through stop */ |
2493 /* Indicate a drive-through stop */ |
2447 SETBIT(v->u.road.state, RVS_IN_DT_ROAD_STOP); |
2494 SetBit(v->u.road.state, RVS_IN_DT_ROAD_STOP); |
2448 return VETSB_CONTINUE; |
2495 return VETSB_CONTINUE; |
2449 } |
2496 } |
2450 |
2497 |
2451 /* For normal (non drive-through) road stops */ |
2498 /* For normal (non drive-through) road stops */ |
2452 /* Check if station is busy or if there are no free bays or whether it is a articulated vehicle. */ |
2499 /* Check if station is busy or if there are no free bays or whether it is a articulated vehicle. */ |
2453 if (rs->IsEntranceBusy() || !rs->HasFreeBay() || RoadVehHasArticPart(v)) return VETSB_CANNOT_ENTER; |
2500 if (rs->IsEntranceBusy() || !rs->HasFreeBay() || RoadVehHasArticPart(v)) return VETSB_CANNOT_ENTER; |
2454 |
2501 |
2455 SETBIT(v->u.road.state, RVS_IN_ROAD_STOP); |
2502 SetBit(v->u.road.state, RVS_IN_ROAD_STOP); |
2456 |
2503 |
2457 /* Allocate a bay and update the road state */ |
2504 /* Allocate a bay and update the road state */ |
2458 uint bay_nr = rs->AllocateBay(); |
2505 uint bay_nr = rs->AllocateBay(); |
2459 SB(v->u.road.state, RVS_USING_SECOND_BAY, 1, bay_nr); |
2506 SB(v->u.road.state, RVS_USING_SECOND_BAY, 1, bay_nr); |
2460 |
2507 |
2536 (rating += 10, true); |
2582 (rating += 10, true); |
2537 |
2583 |
2538 { |
2584 { |
2539 int or_ = ge->rating; // old rating |
2585 int or_ = ge->rating; // old rating |
2540 |
2586 |
2541 // only modify rating in steps of -2, -1, 0, 1 or 2 |
2587 /* only modify rating in steps of -2, -1, 0, 1 or 2 */ |
2542 ge->rating = rating = or_ + clamp(clamp(rating, 0, 255) - or_, -2, 2); |
2588 ge->rating = rating = or_ + Clamp(Clamp(rating, 0, 255) - or_, -2, 2); |
2543 |
2589 |
2544 // if rating is <= 64 and more than 200 items waiting, remove some random amount of goods from the station |
2590 /* if rating is <= 64 and more than 200 items waiting, |
|
2591 * remove some random amount of goods from the station */ |
2545 if (rating <= 64 && waiting >= 200) { |
2592 if (rating <= 64 && waiting >= 200) { |
2546 int dec = Random() & 0x1F; |
2593 int dec = Random() & 0x1F; |
2547 if (waiting < 400) dec &= 7; |
2594 if (waiting < 400) dec &= 7; |
2548 waiting -= dec + 1; |
2595 waiting -= dec + 1; |
2549 waiting_changed = true; |
2596 waiting_changed = true; |
2550 } |
2597 } |
2551 |
2598 |
2552 // if rating is <= 127 and there are any items waiting, maybe remove some goods. |
2599 /* if rating is <= 127 and there are any items waiting, maybe remove some goods. */ |
2553 if (rating <= 127 && waiting != 0) { |
2600 if (rating <= 127 && waiting != 0) { |
2554 uint32 r = Random(); |
2601 uint32 r = Random(); |
2555 if (rating <= (int)GB(r, 0, 7)) { |
2602 if (rating <= (int)GB(r, 0, 7)) { |
2556 /* Need to have int, otherwise it will just overflow etc. */ |
2603 /* Need to have int, otherwise it will just overflow etc. */ |
2557 waiting = max((int)waiting - (int)GB(r, 8, 2) - 1, 0); |
2604 waiting = max((int)waiting - (int)GB(r, 8, 2) - 1, 0); |
2719 cur_tile = TILE_MASK(cur_tile); |
2772 cur_tile = TILE_MASK(cur_tile); |
2720 if (!IsTileType(cur_tile, MP_STATION)) continue; |
2773 if (!IsTileType(cur_tile, MP_STATION)) continue; |
2721 |
2774 |
2722 Station *st = GetStationByTile(cur_tile); |
2775 Station *st = GetStationByTile(cur_tile); |
2723 |
2776 |
2724 for (uint i = 0; i != lengthof(around); i++) { |
2777 if (st->IsBuoy()) continue; // bouys don't accept cargo |
2725 if (around[i] == NULL) { |
2778 |
2726 if (!st->IsBuoy() && |
2779 |
2727 (st->town->exclusive_counter == 0 || st->town->exclusivity == st->owner) && // check exclusive transport rights |
2780 if (_patches.modified_catchment) { |
2728 st->goods[type].rating != 0 && // when you've got the lowest rating you can get, it's better not to give cargo anymore |
2781 /* min and max coordinates of the producer relative */ |
2729 (!_patches.selectgoods || st->goods[type].last_speed != 0) && // we are servicing the station (or cargo is dumped on all stations) |
2782 const int x_min_prod = max_rad + 1; |
2730 ((st->facilities & ~FACIL_BUS_STOP) != 0 || IsCargoInClass(type, CC_PASSENGERS)) && // if we have other fac. than a bus stop, or the cargo is passengers |
2783 const int x_max_prod = max_rad + w_prod; |
2731 ((st->facilities & ~FACIL_TRUCK_STOP) != 0 || !IsCargoInClass(type, CC_PASSENGERS))) { // if we have other fac. than a cargo bay or the cargo is not passengers |
2784 const int y_min_prod = max_rad + 1; |
2732 if (_patches.modified_catchment) { |
2785 const int y_max_prod = max_rad + h_prod; |
2733 // min and max coordinates of the producer relative |
2786 |
2734 const int x_min_prod = max_rad + 1; |
2787 int rad = FindCatchmentRadius(st); |
2735 const int x_max_prod = max_rad + w_prod; |
2788 |
2736 const int y_min_prod = max_rad + 1; |
2789 int x_dist = min(w_cur - x_min_prod, x_max_prod - w_cur); |
2737 const int y_max_prod = max_rad + h_prod; |
2790 if (w_cur < x_min_prod) { |
2738 |
2791 x_dist = x_min_prod - w_cur; |
2739 int rad = FindCatchmentRadius(st); |
2792 } else if (w_cur > x_max_prod) { |
2740 |
2793 x_dist = w_cur - x_max_prod; |
2741 int x_dist = min(w_cur - x_min_prod, x_max_prod - w_cur); |
2794 } |
2742 if (w_cur < x_min_prod) { |
2795 |
2743 x_dist = x_min_prod - w_cur; |
2796 if (x_dist > rad) continue; |
2744 } else if (w_cur > x_max_prod) { |
2797 |
2745 x_dist = w_cur - x_max_prod; |
2798 int y_dist = min(h_cur - y_min_prod, y_max_prod - h_cur); |
2746 } |
2799 if (h_cur < y_min_prod) { |
2747 |
2800 y_dist = y_min_prod - h_cur; |
2748 int y_dist = min(h_cur - y_min_prod, y_max_prod - h_cur); |
2801 } else if (h_cur > y_max_prod) { |
2749 if (h_cur < y_min_prod) { |
2802 y_dist = h_cur - y_max_prod; |
2750 y_dist = y_min_prod - h_cur; |
2803 } |
2751 } else if (h_cur > y_max_prod) { |
2804 |
2752 y_dist = h_cur - y_max_prod; |
2805 if (y_dist > rad) continue; |
2753 } |
2806 } |
2754 |
2807 |
2755 if (x_dist > rad || y_dist > rad) break; |
2808 /* Insert the station in the set. This will fail if it has |
2756 } |
2809 * already been added. |
2757 |
2810 */ |
2758 around[i] = st; |
2811 station_set.insert(st); |
2759 } |
2812 |
2760 break; |
|
2761 } else if (around[i] == st) { |
|
2762 break; |
|
2763 } |
|
2764 } |
|
2765 END_TILE_LOOP(cur_tile, w, h, tile - TileDiffXY(max_rad, max_rad)) |
2813 END_TILE_LOOP(cur_tile, w, h, tile - TileDiffXY(max_rad, max_rad)) |
2766 |
2814 |
|
2815 return station_set; |
|
2816 } |
|
2817 |
|
2818 uint MoveGoodsToStation(TileIndex tile, int w, int h, CargoID type, uint amount) |
|
2819 { |
|
2820 Station *st1 = NULL; // Station with best rating |
|
2821 Station *st2 = NULL; // Second best station |
|
2822 uint best_rating1 = 0; // rating of st1 |
|
2823 uint best_rating2 = 0; // rating of st2 |
|
2824 |
|
2825 StationSet all_stations = FindStationsAroundIndustryTile(tile, w, h); |
|
2826 for (StationSet::iterator st_iter = all_stations.begin(); st_iter != all_stations.end(); ++st_iter) { |
|
2827 Station *st = *st_iter; |
|
2828 |
|
2829 /* Is the station reserved exclusively for somebody else? */ |
|
2830 if (st->town->exclusive_counter > 0 && st->town->exclusivity != st->owner) continue; |
|
2831 |
|
2832 if (st->goods[type].rating == 0) continue; // Lowest possible rating, better not to give cargo anymore |
|
2833 |
|
2834 if (_patches.selectgoods && st->goods[type].last_speed == 0) continue; // Selectively servicing stations, and not this one |
|
2835 |
|
2836 if (IsCargoInClass(type, CC_PASSENGERS)) { |
|
2837 if (st->facilities == FACIL_TRUCK_STOP) continue; // passengers are never served by just a truck stop |
|
2838 } else { |
|
2839 if (st->facilities == FACIL_BUS_STOP) continue; // non-passengers are never served by just a bus stop |
|
2840 } |
|
2841 |
|
2842 /* This station can be used, add it to st1/st2 */ |
|
2843 if (st1 == NULL || st->goods[type].rating >= best_rating1) { |
|
2844 st2 = st1; best_rating2 = best_rating1; st1 = st; best_rating1 = st->goods[type].rating; |
|
2845 } else if (st2 == NULL || st->goods[type].rating >= best_rating2) { |
|
2846 st2 = st; best_rating2 = st->goods[type].rating; |
|
2847 } |
|
2848 } |
|
2849 |
2767 /* no stations around at all? */ |
2850 /* no stations around at all? */ |
2768 if (around[0] == NULL) return 0; |
2851 if (st1 == NULL) return 0; |
2769 |
2852 |
2770 if (around[1] == NULL) { |
2853 if (st2 == NULL) { |
2771 /* only one station around */ |
2854 /* only one station around */ |
2772 uint moved = (amount * around[0]->goods[type].rating >> 8) + 1; |
2855 uint moved = amount * best_rating1 / 256 + 1; |
2773 UpdateStationWaiting(around[0], type, moved); |
2856 UpdateStationWaiting(st1, type, moved); |
2774 return moved; |
2857 return moved; |
2775 } |
2858 } |
2776 |
2859 |
2777 /* several stations around, find the two with the highest rating */ |
2860 /* several stations around, the best two (highest rating) are in st1 and st2 */ |
2778 Station *st1 = NULL; |
|
2779 Station *st2 = NULL; |
|
2780 uint best_rating = 0; |
|
2781 uint best_rating2 = 0; |
|
2782 |
|
2783 for (uint i = 0; i != lengthof(around) && around[i] != NULL; i++) { |
|
2784 if (around[i]->goods[type].rating >= best_rating) { |
|
2785 best_rating2 = best_rating; |
|
2786 st2 = st1; |
|
2787 |
|
2788 best_rating = around[i]->goods[type].rating; |
|
2789 st1 = around[i]; |
|
2790 } else if (around[i]->goods[type].rating >= best_rating2) { |
|
2791 best_rating2 = around[i]->goods[type].rating; |
|
2792 st2 = around[i]; |
|
2793 } |
|
2794 } |
|
2795 |
|
2796 assert(st1 != NULL); |
2861 assert(st1 != NULL); |
2797 assert(st2 != NULL); |
2862 assert(st2 != NULL); |
2798 assert(best_rating != 0 || best_rating2 != 0); |
2863 assert(best_rating1 != 0 || best_rating2 != 0); |
2799 |
2864 |
2800 /* the 2nd highest one gets a penalty */ |
2865 /* the 2nd highest one gets a penalty */ |
2801 best_rating2 >>= 1; |
2866 best_rating2 >>= 1; |
2802 |
2867 |
2803 /* amount given to station 1 */ |
2868 /* amount given to station 1 */ |
2804 uint t = (best_rating * (amount + 1)) / (best_rating + best_rating2); |
2869 uint t = (best_rating1 * (amount + 1)) / (best_rating1 + best_rating2); |
2805 |
2870 |
2806 uint moved = 0; |
2871 uint moved = 0; |
2807 if (t != 0) { |
2872 if (t != 0) { |
2808 moved = t * best_rating / 256 + 1; |
2873 moved = t * best_rating1 / 256 + 1; |
2809 amount -= t; |
2874 amount -= t; |
2810 UpdateStationWaiting(st1, type, moved); |
2875 UpdateStationWaiting(st1, type, moved); |
2811 } |
2876 } |
2812 |
2877 |
2813 if (amount != 0) { |
2878 if (amount != 0) { |
2926 { |
2993 { |
2927 if (flags & DC_AUTO) { |
2994 if (flags & DC_AUTO) { |
2928 switch (GetStationType(tile)) { |
2995 switch (GetStationType(tile)) { |
2929 case STATION_RAIL: return_cmd_error(STR_300B_MUST_DEMOLISH_RAILROAD); |
2996 case STATION_RAIL: return_cmd_error(STR_300B_MUST_DEMOLISH_RAILROAD); |
2930 case STATION_AIRPORT: return_cmd_error(STR_300E_MUST_DEMOLISH_AIRPORT_FIRST); |
2997 case STATION_AIRPORT: return_cmd_error(STR_300E_MUST_DEMOLISH_AIRPORT_FIRST); |
2931 case STATION_TRUCK: return_cmd_error(HASBIT(GetRoadTypes(tile), ROADTYPE_TRAM) ? STR_3047_MUST_DEMOLISH_CARGO_TRAM_STATION : STR_3047_MUST_DEMOLISH_TRUCK_STATION); |
2998 case STATION_TRUCK: return_cmd_error(HasBit(GetRoadTypes(tile), ROADTYPE_TRAM) ? STR_3047_MUST_DEMOLISH_CARGO_TRAM_STATION : STR_3047_MUST_DEMOLISH_TRUCK_STATION); |
2932 case STATION_BUS: return_cmd_error(HASBIT(GetRoadTypes(tile), ROADTYPE_TRAM) ? STR_3046_MUST_DEMOLISH_PASSENGER_TRAM_STATION : STR_3046_MUST_DEMOLISH_BUS_STATION); |
2999 case STATION_BUS: return_cmd_error(HasBit(GetRoadTypes(tile), ROADTYPE_TRAM) ? STR_3046_MUST_DEMOLISH_PASSENGER_TRAM_STATION : STR_3046_MUST_DEMOLISH_BUS_STATION); |
2933 case STATION_BUOY: return_cmd_error(STR_306A_BUOY_IN_THE_WAY); |
3000 case STATION_BUOY: return_cmd_error(STR_306A_BUOY_IN_THE_WAY); |
2934 case STATION_DOCK: return_cmd_error(STR_304D_MUST_DEMOLISH_DOCK_FIRST); |
3001 case STATION_DOCK: return_cmd_error(STR_304D_MUST_DEMOLISH_DOCK_FIRST); |
2935 case STATION_OILRIG: |
3002 case STATION_OILRIG: |
2936 SetDParam(0, STR_4807_OIL_RIG); |
3003 SetDParam(0, STR_4807_OIL_RIG); |
2937 return_cmd_error(STR_4800_IN_THE_WAY); |
3004 return_cmd_error(STR_4800_IN_THE_WAY); |
3080 SLE_CONDVAR(Station, dock_tile, SLE_UINT32, 6, SL_MAX_VERSION), |
3147 SLE_CONDVAR(Station, dock_tile, SLE_UINT32, 6, SL_MAX_VERSION), |
3081 SLE_REF(Station, town, REF_TOWN), |
3148 SLE_REF(Station, town, REF_TOWN), |
3082 SLE_VAR(Station, trainst_w, SLE_UINT8), |
3149 SLE_VAR(Station, trainst_w, SLE_UINT8), |
3083 SLE_CONDVAR(Station, trainst_h, SLE_UINT8, 2, SL_MAX_VERSION), |
3150 SLE_CONDVAR(Station, trainst_h, SLE_UINT8, 2, SL_MAX_VERSION), |
3084 |
3151 |
3085 // alpha_order was stored here in savegame format 0 - 3 |
3152 /* alpha_order was stored here in savegame format 0 - 3 */ |
3086 SLE_CONDNULL(1, 0, 3), |
3153 SLE_CONDNULL(1, 0, 3), |
3087 |
3154 |
3088 SLE_VAR(Station, string_id, SLE_STRINGID), |
3155 SLE_VAR(Station, string_id, SLE_STRINGID), |
3089 SLE_VAR(Station, had_vehicle_of_type, SLE_UINT16), |
3156 SLE_VAR(Station, had_vehicle_of_type, SLE_UINT16), |
3090 |
3157 |
3104 SLE_CONDARR(Station, airport_flags, SLE_UINT64, 2, NEWGRF_AIRPORTS_SAVEGAME, SL_MAX_VERSION), |
3171 SLE_CONDARR(Station, airport_flags, SLE_UINT64, 2, NEWGRF_AIRPORTS_SAVEGAME, SL_MAX_VERSION), |
3105 |
3172 |
3106 SLE_CONDNULL(2, 0, 25), /* Ex last-vehicle */ |
3173 SLE_CONDNULL(2, 0, 25), /* Ex last-vehicle */ |
3107 SLE_CONDVAR(Station, last_vehicle_type, SLE_UINT8, 26, SL_MAX_VERSION), |
3174 SLE_CONDVAR(Station, last_vehicle_type, SLE_UINT8, 26, SL_MAX_VERSION), |
3108 |
3175 |
3109 // Was custom station class and id |
3176 /* Was custom station class and id */ |
3110 SLE_CONDNULL(2, 3, 25), |
3177 SLE_CONDNULL(2, 3, 25), |
3111 SLE_CONDVAR(Station, build_date, SLE_FILE_U16 | SLE_VAR_I32, 3, 30), |
3178 SLE_CONDVAR(Station, build_date, SLE_FILE_U16 | SLE_VAR_I32, 3, 30), |
3112 SLE_CONDVAR(Station, build_date, SLE_INT32, 31, SL_MAX_VERSION), |
3179 SLE_CONDVAR(Station, build_date, SLE_INT32, 31, SL_MAX_VERSION), |
3113 |
3180 |
3114 SLE_CONDREF(Station, bus_stops, REF_ROADSTOPS, 6, SL_MAX_VERSION), |
3181 SLE_CONDREF(Station, bus_stops, REF_ROADSTOPS, 6, SL_MAX_VERSION), |
3181 uint num_cargo = CheckSavegameVersion(55) ? 12 : NUM_CARGO; |
3248 uint num_cargo = CheckSavegameVersion(55) ? 12 : NUM_CARGO; |
3182 for (CargoID i = 0; i < num_cargo; i++) { |
3249 for (CargoID i = 0; i < num_cargo; i++) { |
3183 GoodsEntry *ge = &st->goods[i]; |
3250 GoodsEntry *ge = &st->goods[i]; |
3184 SlObject(ge, _goods_desc); |
3251 SlObject(ge, _goods_desc); |
3185 if (CheckSavegameVersion(68)) { |
3252 if (CheckSavegameVersion(68)) { |
3186 SB(ge->acceptance_pickup, GoodsEntry::ACCEPTANCE, 1, HASBIT(_waiting_acceptance, 15)); |
3253 SB(ge->acceptance_pickup, GoodsEntry::ACCEPTANCE, 1, HasBit(_waiting_acceptance, 15)); |
3187 if (GB(_waiting_acceptance, 0, 12) != 0) { |
3254 if (GB(_waiting_acceptance, 0, 12) != 0) { |
3188 /* Don't construct the packet with station here, because that'll fail with old savegames */ |
3255 /* Don't construct the packet with station here, because that'll fail with old savegames */ |
3189 CargoPacket *cp = new CargoPacket(); |
3256 CargoPacket *cp = new CargoPacket(); |
3190 /* In old versions, enroute_from used 0xFF as INVALID_STATION */ |
3257 /* In old versions, enroute_from used 0xFF as INVALID_STATION */ |
3191 cp->source = (CheckSavegameVersion(7) && _cargo_source == 0xFF) ? INVALID_STATION : _cargo_source; |
3258 cp->source = (CheckSavegameVersion(7) && _cargo_source == 0xFF) ? INVALID_STATION : _cargo_source; |