comparison src/station_cmd.cpp @ 7891:202a48f69a30 draft

(svn r11442) -Feature: make news messages related to the industry (production) changes better configurable; you can now disable news messages popping up for industries you are not servicing. Patch by Alberth.
author rubidium <rubidium@openttd.org>
date Thu, 15 Nov 2007 22:20:33 +0000
parents dee7f1c1a1e2
children ff1975ced735
comparison
equal deleted inserted replaced
7890:b6664cba0c67 7891:202a48f69a30
431 431
432 SetDParam(0, st->index); 432 SetDParam(0, st->index);
433 AddNewsItem(msg, NEWS_FLAGS(NM_SMALL, NF_VIEWPORT | NF_TILE, NT_ACCEPTANCE, 0), st->xy, 0); 433 AddNewsItem(msg, NEWS_FLAGS(NM_SMALL, NF_VIEWPORT | NF_TILE, NT_ACCEPTANCE, 0), st->xy, 0);
434 } 434 }
435 435
436 /** Get a list of the cargo types being produced around the tile.*/ 436 /**
437 * Get a list of the cargo types being produced around the tile (in a rectangle).
438 * @param produced: Destination array of produced cargo
439 * @param tile: Center of the search area
440 * @param w: Width of the center
441 * @param h: Height of the center
442 * @param rad: Radius of the search area
443 */
437 void GetProductionAroundTiles(AcceptedCargo produced, TileIndex tile, 444 void GetProductionAroundTiles(AcceptedCargo produced, TileIndex tile,
438 int w, int h, int rad) 445 int w, int h, int rad)
439 { 446 {
440 memset(produced, 0, sizeof(AcceptedCargo)); 447 memset(produced, 0, sizeof(AcceptedCargo));
441 448
475 } 482 }
476 } 483 }
477 } 484 }
478 } 485 }
479 486
480 /** Get a list of the cargo types that are accepted around the tile.*/ 487 /**
488 * Get a list of the cargo types that are accepted around the tile.
489 * @param accepts: Destination array of accepted cargo
490 * @param tile: Center of the search area
491 * @param w: Width of the center
492 * @param h: Height of the center
493 * @param rad: Radius of the rectangular search area
494 */
481 void GetAcceptanceAroundTiles(AcceptedCargo accepts, TileIndex tile, 495 void GetAcceptanceAroundTiles(AcceptedCargo accepts, TileIndex tile,
482 int w, int h, int rad) 496 int w, int h, int rad)
483 { 497 {
484 memset(accepts, 0, sizeof(AcceptedCargo)); 498 memset(accepts, 0, sizeof(AcceptedCargo));
485 499
2624 } 2638 }
2625 2639
2626 return CommandCost(); 2640 return CommandCost();
2627 } 2641 }
2628 2642
2629 2643 /**
2630 uint MoveGoodsToStation(TileIndex tile, int w, int h, CargoID type, uint amount) 2644 * Find all (non-buoy) stations around an industry tile
2631 { 2645 *
2632 Station* around[8]; 2646 * @param tile: Center tile to search from
2633 2647 * @param w: Width of the center
2634 for (uint i = 0; i < lengthof(around); i++) around[i] = NULL; 2648 * @param h: Height of the center
2635 2649 *
2636 int w_prod; //width and height of the "producer" of the cargo 2650 * @return: Set of found stations
2651 */
2652 StationSet FindStationsAroundIndustryTile(TileIndex tile, int w, int h)
2653 {
2654 StationSet station_set;
2655
2656 int w_prod; // width and height of the "producer" of the cargo
2637 int h_prod; 2657 int h_prod;
2638 int max_rad; 2658 int max_rad;
2639 if (_patches.modified_catchment) { 2659 if (_patches.modified_catchment) {
2640 w_prod = w; 2660 w_prod = w;
2641 h_prod = h; 2661 h_prod = h;
2654 cur_tile = TILE_MASK(cur_tile); 2674 cur_tile = TILE_MASK(cur_tile);
2655 if (!IsTileType(cur_tile, MP_STATION)) continue; 2675 if (!IsTileType(cur_tile, MP_STATION)) continue;
2656 2676
2657 Station *st = GetStationByTile(cur_tile); 2677 Station *st = GetStationByTile(cur_tile);
2658 2678
2659 for (uint i = 0; i != lengthof(around); i++) { 2679 if (st->IsBuoy()) continue; // bouys don't accept cargo
2660 if (around[i] == NULL) { 2680
2661 if (!st->IsBuoy() && 2681
2662 (st->town->exclusive_counter == 0 || st->town->exclusivity == st->owner) && // check exclusive transport rights 2682 if (_patches.modified_catchment) {
2663 st->goods[type].rating != 0 && // when you've got the lowest rating you can get, it's better not to give cargo anymore 2683 /* min and max coordinates of the producer relative */
2664 (!_patches.selectgoods || st->goods[type].last_speed != 0) && // we are servicing the station (or cargo is dumped on all stations) 2684 const int x_min_prod = max_rad + 1;
2665 ((st->facilities & ~FACIL_BUS_STOP) != 0 || IsCargoInClass(type, CC_PASSENGERS)) && // if we have other fac. than a bus stop, or the cargo is passengers 2685 const int x_max_prod = max_rad + w_prod;
2666 ((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 2686 const int y_min_prod = max_rad + 1;
2667 if (_patches.modified_catchment) { 2687 const int y_max_prod = max_rad + h_prod;
2668 /* min and max coordinates of the producer relative */ 2688
2669 const int x_min_prod = max_rad + 1; 2689 int rad = FindCatchmentRadius(st);
2670 const int x_max_prod = max_rad + w_prod; 2690
2671 const int y_min_prod = max_rad + 1; 2691 int x_dist = min(w_cur - x_min_prod, x_max_prod - w_cur);
2672 const int y_max_prod = max_rad + h_prod; 2692 if (w_cur < x_min_prod) {
2673 2693 x_dist = x_min_prod - w_cur;
2674 int rad = FindCatchmentRadius(st); 2694 } else if (w_cur > x_max_prod) {
2675 2695 x_dist = w_cur - x_max_prod;
2676 int x_dist = min(w_cur - x_min_prod, x_max_prod - w_cur); 2696 }
2677 if (w_cur < x_min_prod) { 2697
2678 x_dist = x_min_prod - w_cur; 2698 if (x_dist > rad) continue;
2679 } else if (w_cur > x_max_prod) { 2699
2680 x_dist = w_cur - x_max_prod; 2700 int y_dist = min(h_cur - y_min_prod, y_max_prod - h_cur);
2681 } 2701 if (h_cur < y_min_prod) {
2682 2702 y_dist = y_min_prod - h_cur;
2683 int y_dist = min(h_cur - y_min_prod, y_max_prod - h_cur); 2703 } else if (h_cur > y_max_prod) {
2684 if (h_cur < y_min_prod) { 2704 y_dist = h_cur - y_max_prod;
2685 y_dist = y_min_prod - h_cur; 2705 }
2686 } else if (h_cur > y_max_prod) { 2706
2687 y_dist = h_cur - y_max_prod; 2707 if (y_dist > rad) continue;
2688 } 2708 }
2689 2709
2690 if (x_dist > rad || y_dist > rad) break; 2710 /* Insert the station in the set. This will fail if it has
2691 } 2711 * already been added.
2692 2712 */
2693 around[i] = st; 2713 station_set.insert(st);
2694 } 2714
2695 break;
2696 } else if (around[i] == st) {
2697 break;
2698 }
2699 }
2700 END_TILE_LOOP(cur_tile, w, h, tile - TileDiffXY(max_rad, max_rad)) 2715 END_TILE_LOOP(cur_tile, w, h, tile - TileDiffXY(max_rad, max_rad))
2701 2716
2717 return station_set;
2718 }
2719
2720 uint MoveGoodsToStation(TileIndex tile, int w, int h, CargoID type, uint amount)
2721 {
2722 Station *st1 = NULL; // Station with best rating
2723 Station *st2 = NULL; // Second best station
2724 uint best_rating1 = 0; // rating of st1
2725 uint best_rating2 = 0; // rating of st2
2726
2727 StationSet all_stations = FindStationsAroundIndustryTile(tile, w, h);
2728 for (StationSet::iterator st_iter = all_stations.begin(); st_iter != all_stations.end(); ++st_iter) {
2729 Station *st = *st_iter;
2730
2731 /* Is the station reserved exclusively for somebody else? */
2732 if (st->town->exclusive_counter > 0 && st->town->exclusivity != st->owner) continue;
2733
2734 if (st->goods[type].rating == 0) continue; // Lowest possible rating, better not to give cargo anymore
2735
2736 if (_patches.selectgoods && st->goods[type].last_speed == 0) continue; // Selectively servicing stations, and not this one
2737
2738 if (IsCargoInClass(type, CC_PASSENGERS)) {
2739 if (st->facilities == FACIL_TRUCK_STOP) continue; // passengers are never served by just a truck stop
2740 } else {
2741 if (st->facilities == FACIL_BUS_STOP) continue; // non-passengers are never served by just a bus stop
2742 }
2743
2744 /* This station can be used, add it to st1/st2 */
2745 if (st1 == NULL || st->goods[type].rating >= best_rating1) {
2746 st2 = st1; best_rating2 = best_rating1; st1 = st; best_rating1 = st->goods[type].rating;
2747 } else if (st2 == NULL || st->goods[type].rating >= best_rating2) {
2748 st2 = st; best_rating2 = st->goods[type].rating;
2749 }
2750 }
2751
2702 /* no stations around at all? */ 2752 /* no stations around at all? */
2703 if (around[0] == NULL) return 0; 2753 if (st1 == NULL) return 0;
2704 2754
2705 if (around[1] == NULL) { 2755 if (st2 == NULL) {
2706 /* only one station around */ 2756 /* only one station around */
2707 uint moved = (amount * around[0]->goods[type].rating >> 8) + 1; 2757 uint moved = amount * best_rating1 / 256 + 1;
2708 UpdateStationWaiting(around[0], type, moved); 2758 UpdateStationWaiting(st1, type, moved);
2709 return moved; 2759 return moved;
2710 } 2760 }
2711 2761
2712 /* several stations around, find the two with the highest rating */ 2762 /* several stations around, the best two (highest rating) are in st1 and st2 */
2713 Station *st1 = NULL;
2714 Station *st2 = NULL;
2715 uint best_rating = 0;
2716 uint best_rating2 = 0;
2717
2718 for (uint i = 0; i != lengthof(around) && around[i] != NULL; i++) {
2719 if (around[i]->goods[type].rating >= best_rating) {
2720 best_rating2 = best_rating;
2721 st2 = st1;
2722
2723 best_rating = around[i]->goods[type].rating;
2724 st1 = around[i];
2725 } else if (around[i]->goods[type].rating >= best_rating2) {
2726 best_rating2 = around[i]->goods[type].rating;
2727 st2 = around[i];
2728 }
2729 }
2730
2731 assert(st1 != NULL); 2763 assert(st1 != NULL);
2732 assert(st2 != NULL); 2764 assert(st2 != NULL);
2733 assert(best_rating != 0 || best_rating2 != 0); 2765 assert(best_rating1 != 0 || best_rating2 != 0);
2734 2766
2735 /* the 2nd highest one gets a penalty */ 2767 /* the 2nd highest one gets a penalty */
2736 best_rating2 >>= 1; 2768 best_rating2 >>= 1;
2737 2769
2738 /* amount given to station 1 */ 2770 /* amount given to station 1 */
2739 uint t = (best_rating * (amount + 1)) / (best_rating + best_rating2); 2771 uint t = (best_rating1 * (amount + 1)) / (best_rating1 + best_rating2);
2740 2772
2741 uint moved = 0; 2773 uint moved = 0;
2742 if (t != 0) { 2774 if (t != 0) {
2743 moved = t * best_rating / 256 + 1; 2775 moved = t * best_rating1 / 256 + 1;
2744 amount -= t; 2776 amount -= t;
2745 UpdateStationWaiting(st1, type, moved); 2777 UpdateStationWaiting(st1, type, moved);
2746 } 2778 }
2747 2779
2748 if (amount != 0) { 2780 if (amount != 0) {