41 #include "date.h" |
41 #include "date.h" |
42 #include "cargotype.h" |
42 #include "cargotype.h" |
43 #include "player_face.h" |
43 #include "player_face.h" |
44 #include "group.h" |
44 #include "group.h" |
45 |
45 |
|
46 /** |
|
47 * Multiply two integer values and shift the results to right. |
|
48 * |
|
49 * This function multiplies two integer values. The result is |
|
50 * shifted by the amount of shift to right. |
|
51 * |
|
52 * @param a The first integer |
|
53 * @param b The second integer |
|
54 * @param shift The amount to shift the value to right. |
|
55 * @return The shifted result |
|
56 */ |
|
57 static inline int32 BigMulS(const int32 a, const int32 b, const uint8 shift) |
|
58 { |
|
59 return (int32)((int64)a * (int64)b >> shift); |
|
60 } |
|
61 |
|
62 /** |
|
63 * Multiply two unsigned integers and shift the results to right. |
|
64 * |
|
65 * This function multiplies two unsigned integers. The result is |
|
66 * shifted by the amount of shift to right. |
|
67 * |
|
68 * @param a The first unsigned integer |
|
69 * @param b The second unsigned integer |
|
70 * @param shift The amount to shift the value to right. |
|
71 * @return The shifted result |
|
72 */ |
|
73 static inline uint32 BigMulSU(const uint32 a, const uint32 b, const uint8 shift) |
|
74 { |
|
75 return (uint32)((uint64)a * (uint64)b >> shift); |
|
76 } |
|
77 |
46 /* Score info */ |
78 /* Score info */ |
47 const ScoreInfo _score_info[] = { |
79 const ScoreInfo _score_info[] = { |
48 { SCORE_VEHICLES, 120, 100 }, |
80 { SCORE_VEHICLES, 120, 100 }, |
49 { SCORE_STATIONS, 80, 100 }, |
81 { SCORE_STATIONS, 80, 100 }, |
50 { SCORE_MIN_PROFIT, 10000, 100 }, |
82 { SCORE_MIN_PROFIT, 10000, 100 }, |
61 |
93 |
62 Money CalculateCompanyValue(const Player* p) |
94 Money CalculateCompanyValue(const Player* p) |
63 { |
95 { |
64 PlayerID owner = p->index; |
96 PlayerID owner = p->index; |
65 /* Do a little nasty by using CommandCost, so we can use the "overflow" protection of CommandCost */ |
97 /* Do a little nasty by using CommandCost, so we can use the "overflow" protection of CommandCost */ |
66 CommandCost value; |
98 Money value = 0; |
67 |
99 |
68 { |
100 Station *st; |
69 Station *st; |
101 uint num = 0; |
70 uint num = 0; |
102 |
71 |
103 FOR_ALL_STATIONS(st) { |
72 FOR_ALL_STATIONS(st) { |
104 if (st->owner == owner) num += CountBits(st->facilities); |
73 if (st->owner == owner) num += COUNTBITS(st->facilities); |
105 } |
74 } |
106 |
75 |
107 value += num * _price.station_value * 25; |
76 value.AddCost(num * _price.station_value * 25); |
108 |
77 } |
109 Vehicle *v; |
78 |
110 FOR_ALL_VEHICLES(v) { |
79 { |
111 if (v->owner != owner) continue; |
80 Vehicle *v; |
112 |
81 |
113 if (v->type == VEH_TRAIN || |
82 FOR_ALL_VEHICLES(v) { |
114 v->type == VEH_ROAD || |
83 if (v->owner != owner) continue; |
115 (v->type == VEH_AIRCRAFT && IsNormalAircraft(v)) || |
84 |
116 v->type == VEH_SHIP) { |
85 if (v->type == VEH_TRAIN || |
117 value += v->value * 3 >> 1; |
86 v->type == VEH_ROAD || |
|
87 (v->type == VEH_AIRCRAFT && IsNormalAircraft(v)) || |
|
88 v->type == VEH_SHIP) { |
|
89 value.AddCost(v->value * 3 >> 1); |
|
90 } |
|
91 } |
118 } |
92 } |
119 } |
93 |
120 |
94 /* Add real money value */ |
121 /* Add real money value */ |
95 value.AddCost(-p->current_loan); |
122 value -= p->current_loan; |
96 value.AddCost(p->player_money); |
123 value += p->player_money; |
97 |
124 |
98 return max(value.GetCost(), 1LL); |
125 return max(value, (Money)1); |
99 } |
126 } |
100 |
127 |
101 /** if update is set to true, the economy is updated with this score |
128 /** if update is set to true, the economy is updated with this score |
102 * (also the house is updated, should only be true in the on-tick event) |
129 * (also the house is updated, should only be true in the on-tick event) |
103 * @param update the economy with calculated score |
130 * @param update the economy with calculated score |
215 score = 0; |
242 score = 0; |
216 for (ScoreID i = SCORE_BEGIN; i < SCORE_END; i++) { |
243 for (ScoreID i = SCORE_BEGIN; i < SCORE_END; i++) { |
217 /* Skip the total */ |
244 /* Skip the total */ |
218 if (i == SCORE_TOTAL) continue; |
245 if (i == SCORE_TOTAL) continue; |
219 /* Check the score */ |
246 /* Check the score */ |
220 s = clamp(_score_part[owner][i], 0, _score_info[i].needed) * _score_info[i].score / _score_info[i].needed; |
247 s = Clamp(_score_part[owner][i], 0, _score_info[i].needed) * _score_info[i].score / _score_info[i].needed; |
221 score += s; |
248 score += s; |
222 total_score += _score_info[i].score; |
249 total_score += _score_info[i].score; |
223 } |
250 } |
224 |
251 |
225 _score_part[owner][SCORE_TOTAL] = score; |
252 _score_part[owner][SCORE_TOTAL] = score; |
299 |
326 |
300 /* Take care of rating in towns */ |
327 /* Take care of rating in towns */ |
301 FOR_ALL_TOWNS(t) { |
328 FOR_ALL_TOWNS(t) { |
302 /* If a player takes over, give the ratings to that player. */ |
329 /* If a player takes over, give the ratings to that player. */ |
303 if (new_player != PLAYER_SPECTATOR) { |
330 if (new_player != PLAYER_SPECTATOR) { |
304 if (HASBIT(t->have_ratings, old_player)) { |
331 if (HasBit(t->have_ratings, old_player)) { |
305 if (HASBIT(t->have_ratings, new_player)) { |
332 if (HasBit(t->have_ratings, new_player)) { |
306 // use max of the two ratings. |
333 // use max of the two ratings. |
307 t->ratings[new_player] = max(t->ratings[new_player], t->ratings[old_player]); |
334 t->ratings[new_player] = max(t->ratings[new_player], t->ratings[old_player]); |
308 } else { |
335 } else { |
309 SETBIT(t->have_ratings, new_player); |
336 SetBit(t->have_ratings, new_player); |
310 t->ratings[new_player] = t->ratings[old_player]; |
337 t->ratings[new_player] = t->ratings[old_player]; |
311 } |
338 } |
312 } |
339 } |
313 } |
340 } |
314 |
341 |
315 /* Reset the ratings for the old player */ |
342 /* Reset the ratings for the old player */ |
316 t->ratings[old_player] = 500; |
343 t->ratings[old_player] = 500; |
317 CLRBIT(t->have_ratings, old_player); |
344 ClrBit(t->have_ratings, old_player); |
318 } |
345 } |
319 |
346 |
320 { |
347 { |
321 int num_train = 0; |
348 int num_train = 0; |
322 int num_road = 0; |
349 int num_road = 0; |
336 } |
363 } |
337 } |
364 } |
338 } |
365 } |
339 |
366 |
340 FOR_ALL_VEHICLES(v) { |
367 FOR_ALL_VEHICLES(v) { |
341 if (v->owner == old_player && IS_BYTE_INSIDE(v->type, VEH_TRAIN, VEH_AIRCRAFT + 1)) { |
368 if (v->owner == old_player && IsInsideMM(v->type, VEH_TRAIN, VEH_AIRCRAFT + 1)) { |
342 if (new_player == PLAYER_SPECTATOR) { |
369 if (new_player == PLAYER_SPECTATOR) { |
343 DeleteWindowById(WC_VEHICLE_VIEW, v->index); |
370 DeleteWindowById(WC_VEHICLE_VIEW, v->index); |
344 DeleteWindowById(WC_VEHICLE_DETAILS, v->index); |
371 DeleteWindowById(WC_VEHICLE_DETAILS, v->index); |
345 DeleteWindowById(WC_VEHICLE_ORDERS, v->index); |
372 DeleteWindowById(WC_VEHICLE_ORDERS, v->index); |
346 |
373 |
517 |
544 |
518 DrawStringMultiCenter(49, 148, STR_7058_PRESIDENT, 94); |
545 DrawStringMultiCenter(49, 148, STR_7058_PRESIDENT, 94); |
519 |
546 |
520 switch (ni->string_id & 0xF0) { |
547 switch (ni->string_id & 0xF0) { |
521 case NB_BTROUBLE: |
548 case NB_BTROUBLE: |
522 DrawStringCentered(w->width >> 1, 1, STR_7056_TRANSPORT_COMPANY_IN_TROUBLE, 0); |
549 DrawStringCentered(w->width >> 1, 1, STR_7056_TRANSPORT_COMPANY_IN_TROUBLE, TC_FROMSTRING); |
523 |
550 |
524 SetDParam(0, p->index); |
551 SetDParam(0, p->index); |
525 |
552 |
526 DrawStringMultiCenter( |
553 DrawStringMultiCenter( |
527 ((w->width - 101) >> 1) + 98, |
554 ((w->width - 101) >> 1) + 98, |
529 STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED, |
556 STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED, |
530 w->width - 101); |
557 w->width - 101); |
531 break; |
558 break; |
532 |
559 |
533 case NB_BMERGER: |
560 case NB_BMERGER: |
534 DrawStringCentered(w->width >> 1, 1, STR_7059_TRANSPORT_COMPANY_MERGER, 0); |
561 DrawStringCentered(w->width >> 1, 1, STR_7059_TRANSPORT_COMPANY_MERGER, TC_FROMSTRING); |
535 SetDParam(0, ni->params[0]); |
562 SetDParam(0, ni->params[0]); |
536 SetDParam(1, p->index); |
563 SetDParam(1, p->index); |
537 SetDParam(2, ni->params[1]); |
564 SetDParam(2, ni->params[1]); |
538 DrawStringMultiCenter( |
565 DrawStringMultiCenter( |
539 ((w->width - 101) >> 1) + 98, |
566 ((w->width - 101) >> 1) + 98, |
541 ni->params[1] == 0 ? STR_707F_HAS_BEEN_TAKEN_OVER_BY : STR_705A_HAS_BEEN_SOLD_TO_FOR, |
568 ni->params[1] == 0 ? STR_707F_HAS_BEEN_TAKEN_OVER_BY : STR_705A_HAS_BEEN_SOLD_TO_FOR, |
542 w->width - 101); |
569 w->width - 101); |
543 break; |
570 break; |
544 |
571 |
545 case NB_BBANKRUPT: |
572 case NB_BBANKRUPT: |
546 DrawStringCentered(w->width >> 1, 1, STR_705C_BANKRUPT, 0); |
573 DrawStringCentered(w->width >> 1, 1, STR_705C_BANKRUPT, TC_FROMSTRING); |
547 SetDParam(0, ni->params[0]); |
574 SetDParam(0, ni->params[0]); |
548 DrawStringMultiCenter( |
575 DrawStringMultiCenter( |
549 ((w->width - 101) >> 1) + 98, |
576 ((w->width - 101) >> 1) + 98, |
550 90, |
577 90, |
551 STR_705D_HAS_BEEN_CLOSED_DOWN_BY, |
578 STR_705D_HAS_BEEN_CLOSED_DOWN_BY, |
552 w->width - 101); |
579 w->width - 101); |
553 break; |
580 break; |
554 |
581 |
555 case NB_BNEWCOMPANY: |
582 case NB_BNEWCOMPANY: |
556 DrawStringCentered(w->width >> 1, 1, STR_705E_NEW_TRANSPORT_COMPANY_LAUNCHED, 0); |
583 DrawStringCentered(w->width >> 1, 1, STR_705E_NEW_TRANSPORT_COMPANY_LAUNCHED, TC_FROMSTRING); |
557 SetDParam(0, p->index); |
584 SetDParam(0, p->index); |
558 SetDParam(1, ni->params[0]); |
585 SetDParam(1, ni->params[0]); |
559 DrawStringMultiCenter( |
586 DrawStringMultiCenter( |
560 ((w->width - 101) >> 1) + 98, |
587 ((w->width - 101) >> 1) + 98, |
561 90, |
588 90, |
610 _current_player = st->owner; |
637 _current_player = st->owner; |
611 SET_EXPENSES_TYPE(EXPENSES_PROPERTY); |
638 SET_EXPENSES_TYPE(EXPENSES_PROPERTY); |
612 SubtractMoneyFromPlayer(_price.station_value >> 1); |
639 SubtractMoneyFromPlayer(_price.station_value >> 1); |
613 } |
640 } |
614 |
641 |
615 if (!HASBIT(1<<0|1<<3|1<<6|1<<9, _cur_month)) |
642 if (!HasBit(1<<0|1<<3|1<<6|1<<9, _cur_month)) |
616 return; |
643 return; |
617 |
644 |
618 FOR_ALL_PLAYERS(p) { |
645 FOR_ALL_PLAYERS(p) { |
619 if (p->is_active) { |
646 if (p->is_active) { |
620 memmove(&p->old_economy[1], &p->old_economy[0], sizeof(p->old_economy) - sizeof(p->old_economy[0])); |
647 memmove(&p->old_economy[1], &p->old_economy[0], sizeof(p->old_economy) - sizeof(p->old_economy[0])); |
709 if (!p->is_active) continue; |
736 if (!p->is_active) continue; |
710 |
737 |
711 _current_player = p->index; |
738 _current_player = p->index; |
712 SET_EXPENSES_TYPE(EXPENSES_LOAN_INT); |
739 SET_EXPENSES_TYPE(EXPENSES_LOAN_INT); |
713 |
740 |
714 SubtractMoneyFromPlayer(CommandCost((Money)BIGMULUS(p->current_loan, interest, 16))); |
741 SubtractMoneyFromPlayer(CommandCost((Money)BigMulSU(p->current_loan, interest, 16))); |
715 |
742 |
716 SET_EXPENSES_TYPE(EXPENSES_OTHER); |
743 SET_EXPENSES_TYPE(EXPENSES_OTHER); |
717 SubtractMoneyFromPlayer(_price.station_value >> 2); |
744 SubtractMoneyFromPlayer(_price.station_value >> 2); |
718 } |
745 } |
719 } |
746 } |
762 700000, ///< aircraft_base |
789 700000, ///< aircraft_base |
763 14000, ///< roadveh_base |
790 14000, ///< roadveh_base |
764 65000, ///< ship_base |
791 65000, ///< ship_base |
765 20, ///< build_trees |
792 20, ///< build_trees |
766 250, ///< terraform |
793 250, ///< terraform |
767 20, ///< clear_1 |
794 20, ///< clear_grass |
768 40, ///< purchase_land |
795 40, ///< clear_roughland |
769 200, ///< clear_2 |
796 200, ///< clear_rocks |
770 500, ///< clear_3 |
797 500, ///< clear_fields |
771 20, ///< remove_trees |
798 20, ///< remove_trees |
772 -70, ///< remove_rail |
799 -70, ///< remove_rail |
773 10, ///< remove_signals |
800 10, ///< remove_signals |
774 50, ///< clear_bridge |
801 50, ///< clear_bridge |
775 80, ///< remove_train_depot |
802 80, ///< remove_train_depot |
980 |
1007 |
981 fr->from = i = GetRandomIndustry(); |
1008 fr->from = i = GetRandomIndustry(); |
982 if (i == NULL) return; |
1009 if (i == NULL) return; |
983 |
1010 |
984 /* Randomize cargo type */ |
1011 /* Randomize cargo type */ |
985 if (HASBIT(Random(), 0) && i->produced_cargo[1] != CT_INVALID) { |
1012 if (HasBit(Random(), 0) && i->produced_cargo[1] != CT_INVALID) { |
986 cargo = i->produced_cargo[1]; |
1013 cargo = i->produced_cargo[1]; |
987 trans = i->last_month_pct_transported[1]; |
1014 trans = i->last_month_pct_transported[1]; |
988 total = i->last_month_production[1]; |
1015 total = i->last_month_production[1]; |
989 } else { |
1016 } else { |
990 cargo = i->produced_cargo[0]; |
1017 cargo = i->produced_cargo[0]; |
1150 Money GetTransportedGoodsIncome(uint num_pieces, uint dist, byte transit_days, CargoID cargo_type) |
1177 Money GetTransportedGoodsIncome(uint num_pieces, uint dist, byte transit_days, CargoID cargo_type) |
1151 { |
1178 { |
1152 const CargoSpec *cs = GetCargo(cargo_type); |
1179 const CargoSpec *cs = GetCargo(cargo_type); |
1153 |
1180 |
1154 /* Use callback to calculate cargo profit, if available */ |
1181 /* Use callback to calculate cargo profit, if available */ |
1155 if (HASBIT(cs->callback_mask, CBM_CARGO_PROFIT_CALC)) { |
1182 if (HasBit(cs->callback_mask, CBM_CARGO_PROFIT_CALC)) { |
1156 uint32 var18 = min(dist, 0xFFFF) | (min(num_pieces, 0xFF) << 16) | (transit_days << 24); |
1183 uint32 var18 = min(dist, 0xFFFF) | (min(num_pieces, 0xFF) << 16) | (transit_days << 24); |
1157 uint16 callback = GetCargoCallback(CBID_CARGO_PROFIT_CALC, 0, var18, cs); |
1184 uint16 callback = GetCargoCallback(CBID_CARGO_PROFIT_CALC, 0, var18, cs); |
1158 if (callback != CALLBACK_FAILED) { |
1185 if (callback != CALLBACK_FAILED) { |
1159 int result = GB(callback, 0, 14); |
1186 int result = GB(callback, 0, 14); |
1160 |
1187 |
1161 /* Simulate a 15 bit signed value */ |
1188 /* Simulate a 15 bit signed value */ |
1162 if (HASBIT(callback, 14)) result = 0x4000 - result; |
1189 if (HasBit(callback, 14)) result = 0x4000 - result; |
1163 |
1190 |
1164 /* "The result should be a signed multiplier that gets multiplied |
1191 /* "The result should be a signed multiplier that gets multiplied |
1165 * by the amount of cargo moved and the price factor, then gets |
1192 * by the amount of cargo moved and the price factor, then gets |
1166 * divided by 8192." */ |
1193 * divided by 8192." */ |
1167 return result * num_pieces * _cargo_payment_rates[cargo_type] / 8192; |
1194 return result * num_pieces * _cargo_payment_rates[cargo_type] / 8192; |
1198 time_factor = MAX_TIME_FACTOR - 2 * days_over_days1 + days2; |
1225 time_factor = MAX_TIME_FACTOR - 2 * days_over_days1 + days2; |
1199 } |
1226 } |
1200 |
1227 |
1201 if (time_factor < MIN_TIME_FACTOR) time_factor = MIN_TIME_FACTOR; |
1228 if (time_factor < MIN_TIME_FACTOR) time_factor = MIN_TIME_FACTOR; |
1202 |
1229 |
1203 return BIGMULSS(dist * time_factor * num_pieces, _cargo_payment_rates[cargo_type], 21); |
1230 return BigMulS(dist * time_factor * num_pieces, _cargo_payment_rates[cargo_type], 21); |
1204 } |
1231 } |
1205 |
1232 |
1206 static void DeliverGoodsToIndustry(TileIndex xy, CargoID cargo_type, int num_pieces) |
1233 static void DeliverGoodsToIndustry(TileIndex xy, CargoID cargo_type, int num_pieces) |
1207 { |
1234 { |
1208 Industry *best = NULL; |
1235 Industry *best = NULL; |
1225 } |
1252 } |
1226 |
1253 |
1227 /* Check if matching cargo has been found */ |
1254 /* Check if matching cargo has been found */ |
1228 if (i == lengthof(ind->accepts_cargo)) continue; |
1255 if (i == lengthof(ind->accepts_cargo)) continue; |
1229 |
1256 |
1230 if (HASBIT(indspec->callback_flags, CBM_IND_REFUSE_CARGO)) { |
1257 if (HasBit(indspec->callback_flags, CBM_IND_REFUSE_CARGO)) { |
1231 uint16 res = GetIndustryCallback(CBID_INDUSTRY_REFUSE_CARGO, 0, GetReverseCargoTranslation(cargo_type, indspec->grf_prop.grffile), ind, ind->type, ind->xy); |
1258 uint16 res = GetIndustryCallback(CBID_INDUSTRY_REFUSE_CARGO, 0, GetReverseCargoTranslation(cargo_type, indspec->grf_prop.grffile), ind, ind->type, ind->xy); |
1232 if (res == 0) continue; |
1259 if (res == 0) continue; |
1233 } |
1260 } |
1234 |
1261 |
1235 uint dist = DistanceManhattan(ind->xy, xy); |
1262 uint dist = DistanceManhattan(ind->xy, xy); |
1247 uint16 callback = indspec->callback_flags; |
1274 uint16 callback = indspec->callback_flags; |
1248 |
1275 |
1249 best->was_cargo_delivered = true; |
1276 best->was_cargo_delivered = true; |
1250 best->last_cargo_accepted_at = _date; |
1277 best->last_cargo_accepted_at = _date; |
1251 |
1278 |
1252 if (HASBIT(callback, CBM_IND_PRODUCTION_CARGO_ARRIVAL) || HASBIT(callback, CBM_IND_PRODUCTION_256_TICKS)) { |
1279 if (HasBit(callback, CBM_IND_PRODUCTION_CARGO_ARRIVAL) || HasBit(callback, CBM_IND_PRODUCTION_256_TICKS)) { |
1253 best->incoming_cargo_waiting[accepted_cargo_index] = min(num_pieces + best->incoming_cargo_waiting[accepted_cargo_index], 0xFFFF); |
1280 best->incoming_cargo_waiting[accepted_cargo_index] = min(num_pieces + best->incoming_cargo_waiting[accepted_cargo_index], 0xFFFF); |
1254 if (HASBIT(callback, CBM_IND_PRODUCTION_CARGO_ARRIVAL)) { |
1281 if (HasBit(callback, CBM_IND_PRODUCTION_CARGO_ARRIVAL)) { |
1255 IndustryProductionCallback(best, 0); |
1282 IndustryProductionCallback(best, 0); |
1256 } else { |
1283 } else { |
1257 InvalidateWindow(WC_INDUSTRY_VIEW, best->index); |
1284 InvalidateWindow(WC_INDUSTRY_VIEW, best->index); |
1258 } |
1285 } |
1259 } else { |
1286 } else { |
1260 best->produced_cargo_waiting[0] = min(best->produced_cargo_waiting[0] + (num_pieces * indspec->input_cargo_multiplier[accepted_cargo_index][0] / 256), 0xFFFF); |
1287 best->produced_cargo_waiting[0] = min(best->produced_cargo_waiting[0] + (num_pieces * indspec->input_cargo_multiplier[accepted_cargo_index][0] / 256), 0xFFFF); |
1261 best->produced_cargo_waiting[1] = min(best->produced_cargo_waiting[1] + (num_pieces * indspec->input_cargo_multiplier[accepted_cargo_index][1] / 256), 0xFFFF); |
1288 best->produced_cargo_waiting[1] = min(best->produced_cargo_waiting[1] + (num_pieces * indspec->input_cargo_multiplier[accepted_cargo_index][1] / 256), 0xFFFF); |
1262 } |
1289 } |
1263 |
1290 |
|
1291 TriggerIndustry(best, INDUSTRY_TRIGGER_RECEIVED_CARGO); |
1264 StartStopIndustryTileAnimation(best, IAT_INDUSTRY_RECEIVED_CARGO); |
1292 StartStopIndustryTileAnimation(best, IAT_INDUSTRY_RECEIVED_CARGO); |
1265 } |
1293 } |
1266 } |
1294 } |
1267 |
1295 |
1268 static bool CheckSubsidised(Station *from, Station *to, CargoID cargo_type) |
1296 static bool CheckSubsidised(Station *from, Station *to, CargoID cargo_type) |
1341 |
1369 |
1342 /* Update player statistics */ |
1370 /* Update player statistics */ |
1343 { |
1371 { |
1344 Player *p = GetPlayer(_current_player); |
1372 Player *p = GetPlayer(_current_player); |
1345 p->cur_economy.delivered_cargo += num_pieces; |
1373 p->cur_economy.delivered_cargo += num_pieces; |
1346 SETBIT(p->cargo_types, cargo_type); |
1374 SetBit(p->cargo_types, cargo_type); |
1347 } |
1375 } |
1348 |
1376 |
1349 /* Get station pointers. */ |
1377 /* Get station pointers. */ |
1350 s_from = GetStation(source); |
1378 s_from = GetStation(source); |
1351 s_to = GetStation(dest); |
1379 s_to = GetStation(dest); |
1395 /* The owner of the train wants to be paid */ |
1423 /* The owner of the train wants to be paid */ |
1396 PlayerID old_player = _current_player; |
1424 PlayerID old_player = _current_player; |
1397 _current_player = front_v->owner; |
1425 _current_player = front_v->owner; |
1398 |
1426 |
1399 /* At this moment loading cannot be finished */ |
1427 /* At this moment loading cannot be finished */ |
1400 CLRBIT(front_v->vehicle_flags, VF_LOADING_FINISHED); |
1428 ClrBit(front_v->vehicle_flags, VF_LOADING_FINISHED); |
1401 |
1429 |
1402 /* Start unloading in at the first possible moment */ |
1430 /* Start unloading in at the first possible moment */ |
1403 front_v->load_unload_time_rem = 1; |
1431 front_v->load_unload_time_rem = 1; |
1404 |
1432 |
1405 for (Vehicle *v = front_v; v != NULL; v = v->Next()) { |
1433 for (Vehicle *v = front_v; v != NULL; v = v->Next()) { |
1406 /* No cargo to unload */ |
1434 /* No cargo to unload */ |
1407 if (v->cargo_cap == 0 || v->cargo.Empty()) continue; |
1435 if (v->cargo_cap == 0 || v->cargo.Empty()) continue; |
1408 |
1436 |
1409 /* All cargo has already been paid for, no need to pay again */ |
1437 /* All cargo has already been paid for, no need to pay again */ |
1410 if (!v->cargo.UnpaidCargo()) { |
1438 if (!v->cargo.UnpaidCargo()) { |
1411 SETBIT(v->vehicle_flags, VF_CARGO_UNLOADING); |
1439 SetBit(v->vehicle_flags, VF_CARGO_UNLOADING); |
1412 continue; |
1440 continue; |
1413 } |
1441 } |
1414 |
1442 |
1415 GoodsEntry *ge = &st->goods[v->cargo_type]; |
1443 GoodsEntry *ge = &st->goods[v->cargo_type]; |
1416 const CargoList::List *cargos = v->cargo.Packets(); |
1444 const CargoList::List *cargos = v->cargo.Packets(); |
1417 |
1445 |
1418 for (CargoList::List::const_iterator it = cargos->begin(); it != cargos->end(); it++) { |
1446 for (CargoList::List::const_iterator it = cargos->begin(); it != cargos->end(); it++) { |
1419 CargoPacket *cp = *it; |
1447 CargoPacket *cp = *it; |
1420 if (!cp->paid_for && |
1448 if (!cp->paid_for && |
1421 cp->source != last_visited && |
1449 cp->source != last_visited && |
1422 HASBIT(ge->acceptance_pickup, GoodsEntry::ACCEPTANCE) && |
1450 HasBit(ge->acceptance_pickup, GoodsEntry::ACCEPTANCE) && |
1423 (front_v->current_order.flags & OF_TRANSFER) == 0) { |
1451 (front_v->current_order.flags & OF_TRANSFER) == 0) { |
1424 /* Deliver goods to the station */ |
1452 /* Deliver goods to the station */ |
1425 st->time_since_unload = 0; |
1453 st->time_since_unload = 0; |
1426 |
1454 |
1427 /* handle end of route payment */ |
1455 /* handle end of route payment */ |
1430 route_profit += profit; // display amount paid for final route delivery, A-D of a chain A-B-C-D |
1458 route_profit += profit; // display amount paid for final route delivery, A-D of a chain A-B-C-D |
1431 vehicle_profit += profit - cp->feeder_share; // whole vehicle is not payed for transfers picked up earlier |
1459 vehicle_profit += profit - cp->feeder_share; // whole vehicle is not payed for transfers picked up earlier |
1432 |
1460 |
1433 result |= 1; |
1461 result |= 1; |
1434 |
1462 |
1435 SETBIT(v->vehicle_flags, VF_CARGO_UNLOADING); |
1463 SetBit(v->vehicle_flags, VF_CARGO_UNLOADING); |
1436 } else if (front_v->current_order.flags & (OF_UNLOAD | OF_TRANSFER)) { |
1464 } else if (front_v->current_order.flags & (OF_UNLOAD | OF_TRANSFER)) { |
1437 if (!cp->paid_for && (front_v->current_order.flags & OF_TRANSFER) != 0) { |
1465 if (!cp->paid_for && (front_v->current_order.flags & OF_TRANSFER) != 0) { |
1438 Money profit = GetTransportedGoodsIncome( |
1466 Money profit = GetTransportedGoodsIncome( |
1439 cp->count, |
1467 cp->count, |
1440 /* pay transfer vehicle for only the part of transfer it has done: ie. cargo_loaded_at_xy to here */ |
1468 /* pay transfer vehicle for only the part of transfer it has done: ie. cargo_loaded_at_xy to here */ |
1485 { |
1513 { |
1486 assert(v->current_order.type == OT_LOADING); |
1514 assert(v->current_order.type == OT_LOADING); |
1487 |
1515 |
1488 /* We have not waited enough time till the next round of loading/unloading */ |
1516 /* We have not waited enough time till the next round of loading/unloading */ |
1489 if (--v->load_unload_time_rem != 0) { |
1517 if (--v->load_unload_time_rem != 0) { |
1490 if (_patches.improved_load && HASBIT(v->current_order.flags, OFB_FULL_LOAD)) { |
1518 if (_patches.improved_load && HasBit(v->current_order.flags, OFB_FULL_LOAD)) { |
1491 /* 'Reserve' this cargo for this vehicle, because we were first. */ |
1519 /* 'Reserve' this cargo for this vehicle, because we were first. */ |
1492 for (; v != NULL; v = v->Next()) { |
1520 for (; v != NULL; v = v->Next()) { |
1493 if (v->cargo_cap != 0) cargo_left[v->cargo_type] -= v->cargo_cap - v->cargo.Count(); |
1521 if (v->cargo_cap != 0) cargo_left[v->cargo_type] -= v->cargo_cap - v->cargo.Count(); |
1494 } |
1522 } |
1495 } |
1523 } |
1521 |
1549 |
1522 for (; v != NULL; v = v->Next()) { |
1550 for (; v != NULL; v = v->Next()) { |
1523 if (v->cargo_cap == 0) continue; |
1551 if (v->cargo_cap == 0) continue; |
1524 |
1552 |
1525 byte load_amount = EngInfo(v->engine_type)->load_amount; |
1553 byte load_amount = EngInfo(v->engine_type)->load_amount; |
1526 if (_patches.gradual_loading && HASBIT(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_LOAD_AMOUNT)) { |
1554 if (_patches.gradual_loading && HasBit(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_LOAD_AMOUNT)) { |
1527 uint16 cb_load_amount = GetVehicleCallback(CBID_VEHICLE_LOAD_AMOUNT, 0, 0, v->engine_type, v); |
1555 uint16 cb_load_amount = GetVehicleCallback(CBID_VEHICLE_LOAD_AMOUNT, 0, 0, v->engine_type, v); |
1528 if (cb_load_amount != CALLBACK_FAILED) load_amount = cb_load_amount & 0xFF; |
1556 if (cb_load_amount != CALLBACK_FAILED && cb_load_amount != 0) load_amount = cb_load_amount & 0xFF; |
1529 } |
1557 } |
1530 |
1558 |
1531 GoodsEntry *ge = &st->goods[v->cargo_type]; |
1559 GoodsEntry *ge = &st->goods[v->cargo_type]; |
1532 |
1560 |
1533 if (HASBIT(v->vehicle_flags, VF_CARGO_UNLOADING)) { |
1561 if (HasBit(v->vehicle_flags, VF_CARGO_UNLOADING)) { |
1534 uint cargo_count = v->cargo.Count(); |
1562 uint cargo_count = v->cargo.Count(); |
1535 uint amount_unloaded = _patches.gradual_loading ? min(cargo_count, load_amount) : cargo_count; |
1563 uint amount_unloaded = _patches.gradual_loading ? min(cargo_count, load_amount) : cargo_count; |
1536 bool remaining; // Are there cargo entities in this vehicle that can still be unloaded here? |
1564 bool remaining; // Are there cargo entities in this vehicle that can still be unloaded here? |
1537 |
1565 |
1538 if (HASBIT(ge->acceptance_pickup, GoodsEntry::ACCEPTANCE) && !(u->current_order.flags & OF_TRANSFER)) { |
1566 if (HasBit(ge->acceptance_pickup, GoodsEntry::ACCEPTANCE) && !(u->current_order.flags & OF_TRANSFER)) { |
1539 /* The cargo has reached it's final destination, the packets may now be destroyed */ |
1567 /* The cargo has reached it's final destination, the packets may now be destroyed */ |
1540 remaining = v->cargo.MoveTo(NULL, amount_unloaded, CargoList::MTA_FINAL_DELIVERY, last_visited); |
1568 remaining = v->cargo.MoveTo(NULL, amount_unloaded, CargoList::MTA_FINAL_DELIVERY, last_visited); |
1541 |
1569 |
1542 result |= 1; |
1570 result |= 1; |
1543 } else if (u->current_order.flags & (OF_UNLOAD | OF_TRANSFER)) { |
1571 } else if (u->current_order.flags & (OF_UNLOAD | OF_TRANSFER)) { |
1544 remaining = v->cargo.MoveTo(&ge->cargo, amount_unloaded); |
1572 remaining = v->cargo.MoveTo(&ge->cargo, amount_unloaded); |
1545 SETBIT(ge->acceptance_pickup, GoodsEntry::PICKUP); |
1573 SetBit(ge->acceptance_pickup, GoodsEntry::PICKUP); |
1546 |
1574 |
1547 result |= 2; |
1575 result |= 2; |
1548 } else { |
1576 } else { |
1549 /* The order changed while unloading (unset unload/transfer) or the |
1577 /* The order changed while unloading (unset unload/transfer) or the |
1550 * station does not accept goods anymore. */ |
1578 * station does not accept goods anymore. */ |
1551 CLRBIT(v->vehicle_flags, VF_CARGO_UNLOADING); |
1579 ClrBit(v->vehicle_flags, VF_CARGO_UNLOADING); |
1552 continue; |
1580 continue; |
1553 } |
1581 } |
1554 |
1582 |
1555 /* Deliver goods to the station */ |
1583 /* Deliver goods to the station */ |
1556 st->time_since_unload = 0; |
1584 st->time_since_unload = 0; |
1591 uint count = ge->cargo.Count(); |
1619 uint count = ge->cargo.Count(); |
1592 |
1620 |
1593 /* Skip loading this vehicle if another train/vehicle is already handling |
1621 /* Skip loading this vehicle if another train/vehicle is already handling |
1594 * the same cargo type at this station */ |
1622 * the same cargo type at this station */ |
1595 if (_patches.improved_load && cargo_left[v->cargo_type] <= 0) { |
1623 if (_patches.improved_load && cargo_left[v->cargo_type] <= 0) { |
1596 SETBIT(cargo_not_full, v->cargo_type); |
1624 SetBit(cargo_not_full, v->cargo_type); |
1597 continue; |
1625 continue; |
1598 } |
1626 } |
1599 |
1627 |
1600 if (cap > count) cap = count; |
1628 if (cap > count) cap = count; |
1601 if (_patches.gradual_loading) cap = min(cap, load_amount); |
1629 if (_patches.gradual_loading) cap = min(cap, load_amount); |
1626 |
1654 |
1627 result |= 2; |
1655 result |= 2; |
1628 } |
1656 } |
1629 |
1657 |
1630 if (v->cargo.Count() == v->cargo_cap) { |
1658 if (v->cargo.Count() == v->cargo_cap) { |
1631 SETBIT(cargo_full, v->cargo_type); |
1659 SetBit(cargo_full, v->cargo_type); |
1632 } else { |
1660 } else { |
1633 SETBIT(cargo_not_full, v->cargo_type); |
1661 SetBit(cargo_not_full, v->cargo_type); |
1634 } |
1662 } |
1635 } |
1663 } |
1636 |
1664 |
1637 /* We update these variables here, so gradual loading still fills |
1665 /* We update these variables here, so gradual loading still fills |
1638 * all wagons at the same time instead of using the same 'improved' |
1666 * all wagons at the same time instead of using the same 'improved' |
1639 * loading algorithm for the wagons (only fill wagon when there is |
1667 * loading algorithm for the wagons (only fill wagon when there is |
1640 * enough to fill the previous wagons) */ |
1668 * enough to fill the previous wagons) */ |
1641 if (_patches.improved_load && HASBIT(u->current_order.flags, OFB_FULL_LOAD)) { |
1669 if (_patches.improved_load && HasBit(u->current_order.flags, OFB_FULL_LOAD)) { |
1642 /* Update left cargo */ |
1670 /* Update left cargo */ |
1643 for (v = u; v != NULL; v = v->Next()) { |
1671 for (v = u; v != NULL; v = v->Next()) { |
1644 if (v->cargo_cap != 0) cargo_left[v->cargo_type] -= v->cargo_cap - v->cargo.Count(); |
1672 if (v->cargo_cap != 0) cargo_left[v->cargo_type] -= v->cargo_cap - v->cargo.Count(); |
1645 } |
1673 } |
1646 } |
1674 } |
1655 |
1683 |
1656 unloading_time = gradual_loading_wait_time[v->type]; |
1684 unloading_time = gradual_loading_wait_time[v->type]; |
1657 } |
1685 } |
1658 } else { |
1686 } else { |
1659 bool finished_loading = true; |
1687 bool finished_loading = true; |
1660 if (HASBIT(v->current_order.flags, OFB_FULL_LOAD)) { |
1688 if (HasBit(v->current_order.flags, OFB_FULL_LOAD)) { |
1661 if (_patches.full_load_any) { |
1689 if (_patches.full_load_any) { |
1662 /* if the aircraft carries passengers and is NOT full, then |
1690 /* if the aircraft carries passengers and is NOT full, then |
1663 * continue loading, no matter how much mail is in */ |
1691 * continue loading, no matter how much mail is in */ |
1664 if ((v->type == VEH_AIRCRAFT && IsCargoInClass(v->cargo_type, CC_PASSENGERS) && v->cargo_cap != v->cargo.Count()) || |
1692 if ((v->type == VEH_AIRCRAFT && IsCargoInClass(v->cargo_type, CC_PASSENGERS) && v->cargo_cap != v->cargo.Count()) || |
1665 (cargo_not_full && (cargo_full & ~cargo_not_full) == 0)) { // There are stull non-full cargos |
1693 (cargo_not_full && (cargo_full & ~cargo_not_full) == 0)) { // There are stull non-full cargos |