Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- static bool CanMoveGoodsToStation(const Station *st, CargoID type) {
- if (st->owner != OWNER_NONE && st->town->exclusive_counter > 0 && st->town->exclusivity != st->owner) return false;
- if (st->goods[type].rating == 0) return false; // Lowest possible rating, better not to give cargo anymore
- if (_settings_game.order.selectgoods && !st->goods[type].HasVehicleEverTriedLoading()) return false; // Selectively servicing stations, and not this one
- if (IsCargoInClass(type, CC_PASSENGERS)) {
- if (st->facilities == FACIL_TRUCK_STOP) return false; // passengers are never served by just a truck stop
- } else {
- if (st->facilities == FACIL_BUS_STOP) return false; // non-passengers are never served by just a bus stop
- }
- return true;
- }
- /** The type of cargo to be compared. */
- static CargoID _cargo_type_comparator;
- static bool CompareCargoRatings(const Station *a, const Station *b)
- {
- return b->goods[_cargo_type_comparator].rating < a->goods[_cargo_type_comparator].rating;
- }
- uint MoveGoodsToStation(CargoID type, uint amount, SourceType source_type, SourceID source_id, const StationList *all_stations)
- {
- /* Return if nothing to do. Also the rounding below fails for 0. */
- if (amount == 0) return 0;
- uint company_best[MAX_COMPANIES + 1] = {}; // best rating for each company, including OWNER_NONE
- uint company_sum[MAX_COMPANIES + 1] = {}; // sum of ratings for each company
- uint best_rating = 0;
- uint best_sum = 0; // sum of best ratings for each company
- typedef std::vector<Station *> UsedStations;
- UsedStations used_stations;
- for (Station *st : *all_stations) {
- if (!CanMoveGoodsToStation(st, type)) continue;
- used_stations.emplace_back(st);
- uint st_owner = st->owner;
- if (st_owner == OWNER_NONE) st_owner = MAX_COMPANIES; // OWNER_NONE is remapped
- byte r = st->goods[type].rating;
- if (r > company_best[st_owner]) {
- best_sum += r - company_best[st_owner]; // it's usually faster than iterating companies later
- company_best[st_owner] = r;
- if (r > best_rating) {
- best_rating = r;
- }
- }
- company_sum[st_owner] += r;
- }
- /* no stations around at all? */
- if (best_rating == 0) return 0;
- /* From now we'll calculate with fractal cargo amounts.
- * First determine how much cargo we really have. */
- amount *= best_rating + 1;
- typedef std::map<int, int> StationCargoMoved;
- StationCargoMoved st_moved;
- uint moved_sum = 0;
- for (Station *st : used_stations) {
- uint st_owner = st->owner;
- if (st_owner == OWNER_NONE) st_owner = MAX_COMPANIES;
- uint station_amount = amount * company_best[st_owner] * st->goods[type].rating / best_sum / company_sum[st_owner];
- moved_sum += station_amount;
- st_moved.emplace(st->index, station_amount);
- }
- int remainder = amount - moved_sum;
- if (remainder > 0) {
- std::sort(used_stations.begin(), used_stations.end(), CompareCargoRatings);
- while (remainder > 0) {
- for (Station *st : used_stations) {
- if (remainder > 0) {
- st_moved[st->index]++;
- remainder--;
- } else {
- break;
- }
- }
- }
- }
- uint moving = 0;
- for (Station *st : used_stations) {
- moving += UpdateStationWaiting(st, type, st_moved[st->index], source_type, source_id);
- }
- return moving;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement