00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "stdafx.h"
00013 #include "company_func.h"
00014 #include "command_func.h"
00015 #include "industry.h"
00016 #include "town.h"
00017 #include "news_func.h"
00018 #include "network/network.h"
00019 #include "network/network_func.h"
00020 #include "ai/ai.hpp"
00021 #include "aircraft.h"
00022 #include "train.h"
00023 #include "newgrf_engine.h"
00024 #include "engine_base.h"
00025 #include "ground_vehicle.hpp"
00026 #include "newgrf_cargo.h"
00027 #include "newgrf_sound.h"
00028 #include "newgrf_industrytiles.h"
00029 #include "newgrf_station.h"
00030 #include "newgrf_airporttiles.h"
00031 #include "object.h"
00032 #include "strings_func.h"
00033 #include "date_func.h"
00034 #include "vehicle_func.h"
00035 #include "sound_func.h"
00036 #include "autoreplace_func.h"
00037 #include "company_gui.h"
00038 #include "signs_base.h"
00039 #include "subsidy_base.h"
00040 #include "subsidy_func.h"
00041 #include "station_base.h"
00042 #include "waypoint_base.h"
00043 #include "economy_base.h"
00044 #include "core/pool_func.hpp"
00045 #include "core/backup_type.hpp"
00046 #include "cargo_type.h"
00047 #include "water.h"
00048 #include "game/game.hpp"
00049 #include "cargomonitor.h"
00050 #include "goal_base.h"
00051 #include "story_base.h"
00052 #include "linkgraph/refresh.h"
00053
00054 #include "table/strings.h"
00055 #include "table/pricebase.h"
00056
00057
00058
00059 CargoPaymentPool _cargo_payment_pool("CargoPayment");
00060 INSTANTIATE_POOL_METHODS(CargoPayment)
00061
00062
00073 static inline int32 BigMulS(const int32 a, const int32 b, const uint8 shift)
00074 {
00075 return (int32)((int64)a * (int64)b >> shift);
00076 }
00077
00078 typedef SmallVector<Industry *, 16> SmallIndustryList;
00079
00083 const ScoreInfo _score_info[] = {
00084 { 120, 100},
00085 { 80, 100},
00086 { 10000, 100},
00087 { 50000, 50},
00088 { 100000, 100},
00089 { 40000, 400},
00090 { 8, 50},
00091 {10000000, 50},
00092 { 250000, 50},
00093 { 0, 0}
00094 };
00095
00096 int _score_part[MAX_COMPANIES][SCORE_END];
00097 Economy _economy;
00098 Prices _price;
00099 Money _additional_cash_required;
00100 static PriceMultipliers _price_base_multiplier;
00101
00111 Money CalculateCompanyValue(const Company *c, bool including_loan)
00112 {
00113 Owner owner = c->index;
00114
00115 Station *st;
00116 uint num = 0;
00117
00118 FOR_ALL_STATIONS(st) {
00119 if (st->owner == owner) num += CountBits((byte)st->facilities);
00120 }
00121
00122 Money value = num * _price[PR_STATION_VALUE] * 25;
00123
00124 Vehicle *v;
00125 FOR_ALL_VEHICLES(v) {
00126 if (v->owner != owner) continue;
00127
00128 if (v->type == VEH_TRAIN ||
00129 v->type == VEH_ROAD ||
00130 (v->type == VEH_AIRCRAFT && Aircraft::From(v)->IsNormalAircraft()) ||
00131 v->type == VEH_SHIP) {
00132 value += v->value * 3 >> 1;
00133 }
00134 }
00135
00136
00137 if (including_loan) value -= c->current_loan;
00138 value += c->money;
00139
00140 return max(value, (Money)1);
00141 }
00142
00151 int UpdateCompanyRatingAndValue(Company *c, bool update)
00152 {
00153 Owner owner = c->index;
00154 int score = 0;
00155
00156 memset(_score_part[owner], 0, sizeof(_score_part[owner]));
00157
00158
00159 {
00160 Vehicle *v;
00161 Money min_profit = 0;
00162 bool min_profit_first = true;
00163 uint num = 0;
00164
00165 FOR_ALL_VEHICLES(v) {
00166 if (v->owner != owner) continue;
00167 if (IsCompanyBuildableVehicleType(v->type) && v->IsPrimaryVehicle()) {
00168 if (v->profit_last_year > 0) num++;
00169 if (v->age > 730) {
00170
00171 if (min_profit_first || min_profit > v->profit_last_year) {
00172 min_profit = v->profit_last_year;
00173 min_profit_first = false;
00174 }
00175 }
00176 }
00177 }
00178
00179 min_profit >>= 8;
00180
00181 _score_part[owner][SCORE_VEHICLES] = num;
00182
00183 if (min_profit > 0) {
00184 _score_part[owner][SCORE_MIN_PROFIT] = ClampToI32(min_profit);
00185 }
00186 }
00187
00188
00189 {
00190 uint num = 0;
00191 const Station *st;
00192
00193 FOR_ALL_STATIONS(st) {
00194
00195 if (st->owner == owner && (st->time_since_load <= 20 || st->time_since_unload <= 20)) num += CountBits((byte)st->facilities);
00196 }
00197 _score_part[owner][SCORE_STATIONS] = num;
00198 }
00199
00200
00201 {
00202 int numec = min(c->num_valid_stat_ent, 12);
00203 if (numec != 0) {
00204 const CompanyEconomyEntry *cee = c->old_economy;
00205 Money min_income = cee->income + cee->expenses;
00206 Money max_income = cee->income + cee->expenses;
00207
00208 do {
00209 min_income = min(min_income, cee->income + cee->expenses);
00210 max_income = max(max_income, cee->income + cee->expenses);
00211 } while (++cee, --numec);
00212
00213 if (min_income > 0) {
00214 _score_part[owner][SCORE_MIN_INCOME] = ClampToI32(min_income);
00215 }
00216
00217 _score_part[owner][SCORE_MAX_INCOME] = ClampToI32(max_income);
00218 }
00219 }
00220
00221
00222 {
00223 int numec = min(c->num_valid_stat_ent, 4);
00224 if (numec != 0) {
00225 const CompanyEconomyEntry *cee = c->old_economy;
00226 OverflowSafeInt64 total_delivered = 0;
00227 do {
00228 total_delivered += cee->delivered_cargo.GetSum<OverflowSafeInt64>();
00229 } while (++cee, --numec);
00230
00231 _score_part[owner][SCORE_DELIVERED] = ClampToI32(total_delivered);
00232 }
00233 }
00234
00235
00236 {
00237 _score_part[owner][SCORE_CARGO] = c->old_economy->delivered_cargo.GetCount();
00238 }
00239
00240
00241 {
00242 if (c->money > 0) {
00243 _score_part[owner][SCORE_MONEY] = ClampToI32(c->money);
00244 }
00245 }
00246
00247
00248 {
00249 _score_part[owner][SCORE_LOAN] = ClampToI32(_score_info[SCORE_LOAN].needed - c->current_loan);
00250 }
00251
00252
00253 {
00254 int total_score = 0;
00255 int s;
00256 score = 0;
00257 for (ScoreID i = SCORE_BEGIN; i < SCORE_END; i++) {
00258
00259 if (i == SCORE_TOTAL) continue;
00260
00261 s = Clamp(_score_part[owner][i], 0, _score_info[i].needed) * _score_info[i].score / _score_info[i].needed;
00262 score += s;
00263 total_score += _score_info[i].score;
00264 }
00265
00266 _score_part[owner][SCORE_TOTAL] = score;
00267
00268
00269 if (total_score != SCORE_MAX) score = score * SCORE_MAX / total_score;
00270 }
00271
00272 if (update) {
00273 c->old_economy[0].performance_history = score;
00274 UpdateCompanyHQ(c->location_of_HQ, score);
00275 c->old_economy[0].company_value = CalculateCompanyValue(c);
00276 }
00277
00278 SetWindowDirty(WC_PERFORMANCE_DETAIL, 0);
00279 return score;
00280 }
00281
00287 void ChangeOwnershipOfCompanyItems(Owner old_owner, Owner new_owner)
00288 {
00289
00290
00291
00292 Backup<CompanyByte> cur_company(_current_company, old_owner, FILE_LINE);
00293 #ifdef ENABLE_NETWORK
00294
00295 if (_networking) NetworkClientsToSpectators(old_owner);
00296 #endif
00297 if (old_owner == _local_company) {
00298
00299
00300 assert(!_networking);
00301 Backup<CompanyByte> cur_company(_current_company, FILE_LINE);
00302 Company *c;
00303 FOR_ALL_COMPANIES(c) {
00304 if (c->index != old_owner) {
00305 SetLocalCompany(c->index);
00306 break;
00307 }
00308 }
00309 cur_company.Restore();
00310 assert(old_owner != _local_company);
00311 }
00312
00313 Town *t;
00314
00315 assert(old_owner != new_owner);
00316
00317 {
00318 Company *c;
00319 uint i;
00320
00321
00322 FOR_ALL_COMPANIES(c) {
00323 for (i = 0; i < 4; i++) {
00324 if (c->share_owners[i] == old_owner) {
00325
00326 CommandCost res = DoCommand(0, c->index, 0, DC_EXEC | DC_BANKRUPT, CMD_SELL_SHARE_IN_COMPANY);
00327
00328
00329 SubtractMoneyFromCompany(res);
00330 }
00331 }
00332 }
00333
00334
00335 Backup<CompanyByte> cur_company2(_current_company, FILE_LINE);
00336 c = Company::Get(old_owner);
00337 for (i = 0; i < 4; i++) {
00338 cur_company2.Change(c->share_owners[i]);
00339 if (_current_company != INVALID_OWNER) {
00340
00341 CommandCost res = DoCommand(0, old_owner, 0, DC_EXEC | DC_BANKRUPT, CMD_SELL_SHARE_IN_COMPANY);
00342
00343
00344 SubtractMoneyFromCompany(res);
00345 }
00346 }
00347 cur_company2.Restore();
00348 }
00349
00350
00351
00352
00353 if (new_owner == INVALID_OWNER) {
00354 Company::Get(old_owner)->money = UINT64_MAX >> 2;
00355 }
00356
00357 Subsidy *s;
00358 FOR_ALL_SUBSIDIES(s) {
00359 if (s->awarded == old_owner) {
00360 if (new_owner == INVALID_OWNER) {
00361 delete s;
00362 } else {
00363 s->awarded = new_owner;
00364 }
00365 }
00366 }
00367 if (new_owner == INVALID_OWNER) RebuildSubsidisedSourceAndDestinationCache();
00368
00369
00370 FOR_ALL_TOWNS(t) {
00371
00372 if (new_owner != INVALID_OWNER) {
00373 if (HasBit(t->have_ratings, old_owner)) {
00374 if (HasBit(t->have_ratings, new_owner)) {
00375
00376 t->ratings[new_owner] = max(t->ratings[new_owner], t->ratings[old_owner]);
00377 } else {
00378 SetBit(t->have_ratings, new_owner);
00379 t->ratings[new_owner] = t->ratings[old_owner];
00380 }
00381 }
00382 }
00383
00384
00385 t->ratings[old_owner] = RATING_INITIAL;
00386 ClrBit(t->have_ratings, old_owner);
00387
00388
00389 if (t->exclusive_counter > 0 && t->exclusivity == old_owner) {
00390 if (new_owner != INVALID_OWNER) {
00391 t->exclusivity = new_owner;
00392 } else {
00393 t->exclusive_counter = 0;
00394 t->exclusivity = INVALID_COMPANY;
00395 }
00396 }
00397 }
00398
00399 {
00400 Vehicle *v;
00401 FOR_ALL_VEHICLES(v) {
00402 if (v->owner == old_owner && IsCompanyBuildableVehicleType(v->type)) {
00403 if (new_owner == INVALID_OWNER) {
00404 if (v->Previous() == NULL) delete v;
00405 } else {
00406 if (v->IsEngineCountable()) GroupStatistics::CountEngine(v, -1);
00407 if (v->IsPrimaryVehicle()) GroupStatistics::CountVehicle(v, -1);
00408 }
00409 }
00410 }
00411 }
00412
00413
00414
00415 RemoveAllEngineReplacementForCompany(Company::Get(old_owner));
00416
00417 if (new_owner == INVALID_OWNER) {
00418 RemoveAllGroupsForCompany(old_owner);
00419 } else {
00420 Group *g;
00421 FOR_ALL_GROUPS(g) {
00422 if (g->owner == old_owner) g->owner = new_owner;
00423 }
00424 }
00425
00426 {
00427 FreeUnitIDGenerator unitidgen[] = {
00428 FreeUnitIDGenerator(VEH_TRAIN, new_owner), FreeUnitIDGenerator(VEH_ROAD, new_owner),
00429 FreeUnitIDGenerator(VEH_SHIP, new_owner), FreeUnitIDGenerator(VEH_AIRCRAFT, new_owner)
00430 };
00431
00432 Vehicle *v;
00433 FOR_ALL_VEHICLES(v) {
00434 if (v->owner == old_owner && IsCompanyBuildableVehicleType(v->type)) {
00435 assert(new_owner != INVALID_OWNER);
00436
00437 v->owner = new_owner;
00438
00439
00440 v->colourmap = PAL_NONE;
00441 v->InvalidateNewGRFCache();
00442
00443 if (v->IsEngineCountable()) {
00444 GroupStatistics::CountEngine(v, 1);
00445 }
00446 if (v->IsPrimaryVehicle()) {
00447 GroupStatistics::CountVehicle(v, 1);
00448 v->unitnumber = unitidgen[v->type].NextID();
00449 }
00450
00451
00452 if (v->cargo_payment != NULL) v->cargo_payment->owner = NULL;
00453 }
00454 }
00455
00456 if (new_owner != INVALID_OWNER) GroupStatistics::UpdateAutoreplace(new_owner);
00457 }
00458
00459
00460 {
00461 TileIndex tile = 0;
00462 do {
00463 ChangeTileOwner(tile, old_owner, new_owner);
00464 } while (++tile != MapSize());
00465
00466 if (new_owner != INVALID_OWNER) {
00467
00468
00469
00470
00471 tile = 0;
00472
00473 do {
00474 if (IsTileType(tile, MP_RAILWAY) && IsTileOwner(tile, new_owner) && HasSignals(tile)) {
00475 TrackBits tracks = GetTrackBits(tile);
00476 do {
00477 Track track = RemoveFirstTrack(&tracks);
00478 if (HasSignalOnTrack(tile, track)) AddTrackToSignalBuffer(tile, track, new_owner);
00479 } while (tracks != TRACK_BIT_NONE);
00480 } else if (IsLevelCrossingTile(tile) && IsTileOwner(tile, new_owner)) {
00481 UpdateLevelCrossing(tile);
00482 }
00483 } while (++tile != MapSize());
00484 }
00485
00486
00487 UpdateSignalsInBuffer();
00488 }
00489
00490
00491 if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.airport += Company::Get(old_owner)->infrastructure.airport;
00492
00493
00494 Station *st;
00495 FOR_ALL_STATIONS(st) {
00496 if (st->owner == old_owner) {
00497
00498
00499 st->owner = new_owner == INVALID_OWNER ? OWNER_NONE : new_owner;
00500 }
00501 }
00502
00503
00504 Waypoint *wp;
00505 FOR_ALL_WAYPOINTS(wp) {
00506 if (wp->owner == old_owner) {
00507 wp->owner = new_owner == INVALID_OWNER ? OWNER_NONE : new_owner;
00508 }
00509 }
00510
00511 Sign *si;
00512 FOR_ALL_SIGNS(si) {
00513 if (si->owner == old_owner) si->owner = new_owner == INVALID_OWNER ? OWNER_NONE : new_owner;
00514 }
00515
00516
00517 Goal *g;
00518 FOR_ALL_GOALS(g) {
00519 if (g->company == old_owner) delete g;
00520 }
00521
00522 ClearCargoPickupMonitoring(old_owner);
00523 ClearCargoDeliveryMonitoring(old_owner);
00524
00525 StoryPage *sp;
00526 FOR_ALL_STORY_PAGES(sp) {
00527 if (sp->company == old_owner) delete sp;
00528 }
00529
00530
00531 if (new_owner != INVALID_OWNER) ChangeWindowOwner(old_owner, new_owner);
00532
00533 cur_company.Restore();
00534
00535 MarkWholeScreenDirty();
00536 }
00537
00542 static void CompanyCheckBankrupt(Company *c)
00543 {
00544
00545 if (c->money - c->current_loan >= -_economy.max_loan) {
00546 c->months_of_bankruptcy = 0;
00547 c->bankrupt_asked = 0;
00548 return;
00549 }
00550
00551 c->months_of_bankruptcy++;
00552
00553 switch (c->months_of_bankruptcy) {
00554
00555 case 0:
00556 case 1:
00557 case 2:
00558 case 3:
00559
00560 case 5:
00561 case 6:
00562
00563 case 8:
00564 case 9:
00565 break;
00566
00567
00568 case 4: {
00569 CompanyNewsInformation *cni = MallocT<CompanyNewsInformation>(1);
00570 cni->FillData(c);
00571 SetDParam(0, STR_NEWS_COMPANY_IN_TROUBLE_TITLE);
00572 SetDParam(1, STR_NEWS_COMPANY_IN_TROUBLE_DESCRIPTION);
00573 SetDParamStr(2, cni->company_name);
00574 AddCompanyNewsItem(STR_MESSAGE_NEWS_FORMAT, cni);
00575 AI::BroadcastNewEvent(new ScriptEventCompanyInTrouble(c->index));
00576 Game::NewEvent(new ScriptEventCompanyInTrouble(c->index));
00577 break;
00578 }
00579
00580
00581 case 7: {
00582
00583 Money val = CalculateCompanyValue(c, false);
00584
00585 c->bankrupt_value = val;
00586 c->bankrupt_asked = 1 << c->index;
00587 c->bankrupt_timeout = 0;
00588
00589
00590 assert(c->bankrupt_value > 0);
00591 break;
00592 }
00593
00594
00595
00596 default:
00597 case 10: {
00598 if (!_networking && _local_company == c->index) {
00599
00600
00601
00602
00603 c->bankrupt_asked = MAX_UVALUE(CompanyMask);
00604 break;
00605 }
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616 if (!_networking || _network_server) DoCommandP(0, 2 | (c->index << 16), CRR_BANKRUPT, CMD_COMPANY_CTRL);
00617 break;
00618 }
00619 }
00620 }
00621
00626 static void CompaniesGenStatistics()
00627 {
00628 Station *st;
00629
00630 Backup<CompanyByte> cur_company(_current_company, FILE_LINE);
00631 Company *c;
00632
00633 if (!_settings_game.economy.infrastructure_maintenance) {
00634 FOR_ALL_STATIONS(st) {
00635 cur_company.Change(st->owner);
00636 CommandCost cost(EXPENSES_PROPERTY, _price[PR_STATION_VALUE] >> 1);
00637 SubtractMoneyFromCompany(cost);
00638 }
00639 } else {
00640
00641 FOR_ALL_COMPANIES(c) {
00642 cur_company.Change(c->index);
00643
00644 CommandCost cost(EXPENSES_PROPERTY);
00645 uint32 rail_total = c->infrastructure.GetRailTotal();
00646 for (RailType rt = RAILTYPE_BEGIN; rt < RAILTYPE_END; rt++) {
00647 if (c->infrastructure.rail[rt] != 0) cost.AddCost(RailMaintenanceCost(rt, c->infrastructure.rail[rt], rail_total));
00648 }
00649 cost.AddCost(SignalMaintenanceCost(c->infrastructure.signal));
00650 for (RoadType rt = ROADTYPE_BEGIN; rt < ROADTYPE_END; rt++) {
00651 if (c->infrastructure.road[rt] != 0) cost.AddCost(RoadMaintenanceCost(rt, c->infrastructure.road[rt]));
00652 }
00653 cost.AddCost(CanalMaintenanceCost(c->infrastructure.water));
00654 cost.AddCost(StationMaintenanceCost(c->infrastructure.station));
00655 cost.AddCost(AirportMaintenanceCost(c->index));
00656
00657 SubtractMoneyFromCompany(cost);
00658 }
00659 }
00660 cur_company.Restore();
00661
00662
00663 FOR_ALL_COMPANIES(c) {
00664 CompanyCheckBankrupt(c);
00665 }
00666
00667
00668 if (!HasBit(1 << 0 | 1 << 3 | 1 << 6 | 1 << 9, _cur_month)) return;
00669
00670 FOR_ALL_COMPANIES(c) {
00671 memmove(&c->old_economy[1], &c->old_economy[0], sizeof(c->old_economy) - sizeof(c->old_economy[0]));
00672 c->old_economy[0] = c->cur_economy;
00673 memset(&c->cur_economy, 0, sizeof(c->cur_economy));
00674
00675 if (c->num_valid_stat_ent != MAX_HISTORY_QUARTERS) c->num_valid_stat_ent++;
00676
00677 UpdateCompanyRatingAndValue(c, true);
00678 if (c->block_preview != 0) c->block_preview--;
00679 }
00680
00681 SetWindowDirty(WC_INCOME_GRAPH, 0);
00682 SetWindowDirty(WC_OPERATING_PROFIT, 0);
00683 SetWindowDirty(WC_DELIVERED_CARGO, 0);
00684 SetWindowDirty(WC_PERFORMANCE_HISTORY, 0);
00685 SetWindowDirty(WC_COMPANY_VALUE, 0);
00686 SetWindowDirty(WC_COMPANY_LEAGUE, 0);
00687 }
00688
00694 bool AddInflation(bool check_year)
00695 {
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711 if (check_year && (_cur_year - _settings_game.game_creation.starting_year) >= (ORIGINAL_MAX_YEAR - ORIGINAL_BASE_YEAR)) return true;
00712
00713 if (_economy.inflation_prices == MAX_INFLATION || _economy.inflation_payment == MAX_INFLATION) return true;
00714
00715
00716
00717
00718
00719
00720 _economy.inflation_prices += (_economy.inflation_prices * _economy.infl_amount * 54) >> 16;
00721 _economy.inflation_payment += (_economy.inflation_payment * _economy.infl_amount_pr * 54) >> 16;
00722
00723 if (_economy.inflation_prices > MAX_INFLATION) _economy.inflation_prices = MAX_INFLATION;
00724 if (_economy.inflation_payment > MAX_INFLATION) _economy.inflation_payment = MAX_INFLATION;
00725
00726 return false;
00727 }
00728
00732 void RecomputePrices()
00733 {
00734
00735 _economy.max_loan = (_settings_game.difficulty.max_loan * _economy.inflation_prices >> 16) / 50000 * 50000;
00736
00737
00738 for (Price i = PR_BEGIN; i < PR_END; i++) {
00739 Money price = _price_base_specs[i].start_price;
00740
00741
00742 uint mod = 1;
00743 switch (_price_base_specs[i].category) {
00744 case PCAT_RUNNING:
00745 mod = _settings_game.difficulty.vehicle_costs;
00746 break;
00747
00748 case PCAT_CONSTRUCTION:
00749 mod = _settings_game.difficulty.construction_cost;
00750 break;
00751
00752 default: break;
00753 }
00754 switch (mod) {
00755 case 0: price *= 6; break;
00756 case 1: price *= 8; break;
00757 case 2: price *= 9; break;
00758 default: NOT_REACHED();
00759 }
00760
00761
00762 price = (int64)price * _economy.inflation_prices;
00763
00764
00765 int shift = _price_base_multiplier[i] - 16 - 3;
00766 if (shift >= 0) {
00767 price <<= shift;
00768 } else {
00769 price >>= -shift;
00770 }
00771
00772
00773
00774
00775
00776
00777 if (price == 0) {
00778 price = Clamp(_price_base_specs[i].start_price, -1, 1);
00779
00780 assert(price != 0);
00781 }
00782
00783 _price[i] = price;
00784 }
00785
00786
00787 CargoSpec *cs;
00788 FOR_ALL_CARGOSPECS(cs) {
00789 cs->current_payment = ((int64)cs->initial_payment * _economy.inflation_payment) >> 16;
00790 }
00791
00792 SetWindowClassesDirty(WC_BUILD_VEHICLE);
00793 SetWindowClassesDirty(WC_REPLACE_VEHICLE);
00794 SetWindowClassesDirty(WC_VEHICLE_DETAILS);
00795 SetWindowClassesDirty(WC_COMPANY_INFRASTRUCTURE);
00796 InvalidateWindowData(WC_PAYMENT_RATES, 0);
00797 }
00798
00800 static void CompaniesPayInterest()
00801 {
00802 const Company *c;
00803
00804 Backup<CompanyByte> cur_company(_current_company, FILE_LINE);
00805 FOR_ALL_COMPANIES(c) {
00806 cur_company.Change(c->index);
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819 Money yearly_fee = c->current_loan * _economy.interest_rate / 100;
00820 if (c->money < 0) {
00821 yearly_fee += -c->money *_economy.interest_rate / 100;
00822 }
00823 Money up_to_previous_month = yearly_fee * _cur_month / 12;
00824 Money up_to_this_month = yearly_fee * (_cur_month + 1) / 12;
00825
00826 SubtractMoneyFromCompany(CommandCost(EXPENSES_LOAN_INT, up_to_this_month - up_to_previous_month));
00827
00828 SubtractMoneyFromCompany(CommandCost(EXPENSES_OTHER, _price[PR_STATION_VALUE] >> 2));
00829 }
00830 cur_company.Restore();
00831 }
00832
00833 static void HandleEconomyFluctuations()
00834 {
00835 if (_settings_game.difficulty.economy != 0) {
00836
00837 _economy.fluct--;
00838 } else if (EconomyIsInRecession()) {
00839
00840 _economy.fluct = -12;
00841 } else {
00842
00843 return;
00844 }
00845
00846 if (_economy.fluct == 0) {
00847 _economy.fluct = -(int)GB(Random(), 0, 2);
00848 AddNewsItem(STR_NEWS_BEGIN_OF_RECESSION, NT_ECONOMY, NF_NORMAL);
00849 } else if (_economy.fluct == -12) {
00850 _economy.fluct = GB(Random(), 0, 8) + 312;
00851 AddNewsItem(STR_NEWS_END_OF_RECESSION, NT_ECONOMY, NF_NORMAL);
00852 }
00853 }
00854
00855
00859 void ResetPriceBaseMultipliers()
00860 {
00861 memset(_price_base_multiplier, 0, sizeof(_price_base_multiplier));
00862 }
00863
00871 void SetPriceBaseMultiplier(Price price, int factor)
00872 {
00873 assert(price < PR_END);
00874 _price_base_multiplier[price] = Clamp(factor, MIN_PRICE_MODIFIER, MAX_PRICE_MODIFIER);
00875 }
00876
00881 void StartupIndustryDailyChanges(bool init_counter)
00882 {
00883 uint map_size = MapLogX() + MapLogY();
00884
00885
00886
00887
00888
00889
00890 _economy.industry_daily_increment = (1 << map_size) / 31;
00891
00892 if (init_counter) {
00893
00894 _economy.industry_daily_change_counter = 0;
00895 }
00896 }
00897
00898 void StartupEconomy()
00899 {
00900 _economy.interest_rate = _settings_game.difficulty.initial_interest;
00901 _economy.infl_amount = _settings_game.difficulty.initial_interest;
00902 _economy.infl_amount_pr = max(0, _settings_game.difficulty.initial_interest - 1);
00903 _economy.fluct = GB(Random(), 0, 8) + 168;
00904
00905
00906 RecomputePrices();
00907
00908 StartupIndustryDailyChanges(true);
00909
00910 }
00911
00915 void InitializeEconomy()
00916 {
00917 _economy.inflation_prices = _economy.inflation_payment = 1 << 16;
00918 ClearCargoPickupMonitoring();
00919 ClearCargoDeliveryMonitoring();
00920 }
00921
00930 Money GetPrice(Price index, uint cost_factor, const GRFFile *grf_file, int shift)
00931 {
00932 if (index >= PR_END) return 0;
00933
00934 Money cost = _price[index] * cost_factor;
00935 if (grf_file != NULL) shift += grf_file->price_base_multipliers[index];
00936
00937 if (shift >= 0) {
00938 cost <<= shift;
00939 } else {
00940 cost >>= -shift;
00941 }
00942
00943 return cost;
00944 }
00945
00946 Money GetTransportedGoodsIncome(uint num_pieces, uint dist, byte transit_days, CargoID cargo_type)
00947 {
00948 const CargoSpec *cs = CargoSpec::Get(cargo_type);
00949 if (!cs->IsValid()) {
00950
00951 return 0;
00952 }
00953
00954
00955 if (HasBit(cs->callback_mask, CBM_CARGO_PROFIT_CALC)) {
00956 uint32 var18 = min(dist, 0xFFFF) | (min(num_pieces, 0xFF) << 16) | (transit_days << 24);
00957 uint16 callback = GetCargoCallback(CBID_CARGO_PROFIT_CALC, 0, var18, cs);
00958 if (callback != CALLBACK_FAILED) {
00959 int result = GB(callback, 0, 14);
00960
00961
00962 if (HasBit(callback, 14)) result -= 0x4000;
00963
00964
00965
00966
00967 return result * num_pieces * cs->current_payment / 8192;
00968 }
00969 }
00970
00971 static const int MIN_TIME_FACTOR = 31;
00972 static const int MAX_TIME_FACTOR = 255;
00973
00974 const int days1 = cs->transit_days[0];
00975 const int days2 = cs->transit_days[1];
00976 const int days_over_days1 = max( transit_days - days1, 0);
00977 const int days_over_days2 = max(days_over_days1 - days2, 0);
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989 const int time_factor = max(MAX_TIME_FACTOR - days_over_days1 - days_over_days2, MIN_TIME_FACTOR);
00990
00991 return BigMulS(dist * time_factor * num_pieces, cs->current_payment, 21);
00992 }
00993
00995 static SmallIndustryList _cargo_delivery_destinations;
00996
01006 static uint DeliverGoodsToIndustry(const Station *st, CargoID cargo_type, uint num_pieces, IndustryID source)
01007 {
01008
01009
01010
01011
01012
01013
01014
01015 uint accepted = 0;
01016
01017 for (uint i = 0; i < st->industries_near.Length() && num_pieces != 0; i++) {
01018 Industry *ind = st->industries_near[i];
01019 if (ind->index == source) continue;
01020
01021 uint cargo_index;
01022 for (cargo_index = 0; cargo_index < lengthof(ind->accepts_cargo); cargo_index++) {
01023 if (cargo_type == ind->accepts_cargo[cargo_index]) break;
01024 }
01025
01026 if (cargo_index >= lengthof(ind->accepts_cargo)) continue;
01027
01028
01029 if (IndustryTemporarilyRefusesCargo(ind, cargo_type)) continue;
01030
01031
01032 _cargo_delivery_destinations.Include(ind);
01033
01034 uint amount = min(num_pieces, 0xFFFFU - ind->incoming_cargo_waiting[cargo_index]);
01035 ind->incoming_cargo_waiting[cargo_index] += amount;
01036 num_pieces -= amount;
01037 accepted += amount;
01038 }
01039
01040 return accepted;
01041 }
01042
01056 static Money DeliverGoods(int num_pieces, CargoID cargo_type, StationID dest, TileIndex source_tile, byte days_in_transit, Company *company, SourceType src_type, SourceID src)
01057 {
01058 assert(num_pieces > 0);
01059
01060 Station *st = Station::Get(dest);
01061
01062
01063 uint accepted = DeliverGoodsToIndustry(st, cargo_type, num_pieces, src_type == ST_INDUSTRY ? src : INVALID_INDUSTRY);
01064
01065
01066 if (HasBit(st->always_accepted, cargo_type)) accepted = num_pieces;
01067
01068
01069 if (accepted > 0) {
01070 SetBit(st->goods[cargo_type].status, GoodsEntry::GES_EVER_ACCEPTED);
01071 SetBit(st->goods[cargo_type].status, GoodsEntry::GES_CURRENT_MONTH);
01072 SetBit(st->goods[cargo_type].status, GoodsEntry::GES_ACCEPTED_BIGTICK);
01073 }
01074
01075
01076 company->cur_economy.delivered_cargo[cargo_type] += accepted;
01077
01078
01079 const CargoSpec *cs = CargoSpec::Get(cargo_type);
01080 st->town->received[cs->town_effect].new_act += accepted;
01081
01082
01083 Money profit = GetTransportedGoodsIncome(accepted, DistanceManhattan(source_tile, st->xy), days_in_transit, cargo_type);
01084
01085
01086 AddCargoDelivery(cargo_type, company->index, accepted, src_type, src, st);
01087
01088
01089 if (CheckSubsidised(cargo_type, company->index, src_type, src, st)) {
01090 switch (_settings_game.difficulty.subsidy_multiplier) {
01091 case 0: profit += profit >> 1; break;
01092 case 1: profit *= 2; break;
01093 case 2: profit *= 3; break;
01094 default: profit *= 4; break;
01095 }
01096 }
01097
01098 return profit;
01099 }
01100
01106 static void TriggerIndustryProduction(Industry *i)
01107 {
01108 const IndustrySpec *indspec = GetIndustrySpec(i->type);
01109 uint16 callback = indspec->callback_mask;
01110
01111 i->was_cargo_delivered = true;
01112 i->last_cargo_accepted_at = _date;
01113
01114 if (HasBit(callback, CBM_IND_PRODUCTION_CARGO_ARRIVAL) || HasBit(callback, CBM_IND_PRODUCTION_256_TICKS)) {
01115 if (HasBit(callback, CBM_IND_PRODUCTION_CARGO_ARRIVAL)) {
01116 IndustryProductionCallback(i, 0);
01117 } else {
01118 SetWindowDirty(WC_INDUSTRY_VIEW, i->index);
01119 }
01120 } else {
01121 for (uint cargo_index = 0; cargo_index < lengthof(i->incoming_cargo_waiting); cargo_index++) {
01122 uint cargo_waiting = i->incoming_cargo_waiting[cargo_index];
01123 if (cargo_waiting == 0) continue;
01124
01125 i->produced_cargo_waiting[0] = min(i->produced_cargo_waiting[0] + (cargo_waiting * indspec->input_cargo_multiplier[cargo_index][0] / 256), 0xFFFF);
01126 i->produced_cargo_waiting[1] = min(i->produced_cargo_waiting[1] + (cargo_waiting * indspec->input_cargo_multiplier[cargo_index][1] / 256), 0xFFFF);
01127
01128 i->incoming_cargo_waiting[cargo_index] = 0;
01129 }
01130 }
01131
01132 TriggerIndustry(i, INDUSTRY_TRIGGER_RECEIVED_CARGO);
01133 StartStopIndustryTileAnimation(i, IAT_INDUSTRY_RECEIVED_CARGO);
01134 }
01135
01140 CargoPayment::CargoPayment(Vehicle *front) :
01141 front(front),
01142 current_station(front->last_station_visited)
01143 {
01144 }
01145
01146 CargoPayment::~CargoPayment()
01147 {
01148 if (this->CleaningPool()) return;
01149
01150 this->front->cargo_payment = NULL;
01151
01152 if (this->visual_profit == 0 && this->visual_transfer == 0) return;
01153
01154 Backup<CompanyByte> cur_company(_current_company, this->front->owner, FILE_LINE);
01155
01156 SubtractMoneyFromCompany(CommandCost(this->front->GetExpenseType(true), -this->route_profit));
01157 this->front->profit_this_year += (this->visual_profit + this->visual_transfer) << 8;
01158
01159 if (this->route_profit != 0 && IsLocalCompany() && !PlayVehicleSound(this->front, VSE_LOAD_UNLOAD)) {
01160 SndPlayVehicleFx(SND_14_CASHTILL, this->front);
01161 }
01162
01163 if (this->visual_transfer != 0) {
01164 ShowFeederIncomeAnimation(this->front->x_pos, this->front->y_pos,
01165 this->front->z_pos, this->visual_transfer, -this->visual_profit);
01166 } else if (this->visual_profit != 0) {
01167 ShowCostOrIncomeAnimation(this->front->x_pos, this->front->y_pos,
01168 this->front->z_pos, -this->visual_profit);
01169 }
01170
01171 cur_company.Restore();
01172 }
01173
01179 void CargoPayment::PayFinalDelivery(const CargoPacket *cp, uint count)
01180 {
01181 if (this->owner == NULL) {
01182 this->owner = Company::Get(this->front->owner);
01183 }
01184
01185
01186 Money profit = DeliverGoods(count, this->ct, this->current_station, cp->SourceStationXY(), cp->DaysInTransit(), this->owner, cp->SourceSubsidyType(), cp->SourceSubsidyID());
01187 this->route_profit += profit;
01188
01189
01190 this->visual_profit += profit - cp->FeederShare(count);
01191 }
01192
01199 Money CargoPayment::PayTransfer(const CargoPacket *cp, uint count)
01200 {
01201 Money profit = GetTransportedGoodsIncome(
01202 count,
01203
01204 DistanceManhattan(cp->LoadedAtXY(), Station::Get(this->current_station)->xy),
01205 cp->DaysInTransit(),
01206 this->ct);
01207
01208 profit = profit * _settings_game.economy.feeder_payment_share / 100;
01209
01210 this->visual_transfer += profit;
01211 return profit;
01212 }
01213
01219 void PrepareUnload(Vehicle *front_v)
01220 {
01221 Station *curr_station = Station::Get(front_v->last_station_visited);
01222 curr_station->loading_vehicles.push_back(front_v);
01223
01224
01225 ClrBit(front_v->vehicle_flags, VF_LOADING_FINISHED);
01226
01227
01228 front_v->load_unload_ticks = 1;
01229
01230 assert(front_v->cargo_payment == NULL);
01231
01232
01233 assert_compile(CargoPaymentPool::MAX_SIZE == VehiclePool::MAX_SIZE);
01234 assert(CargoPayment::CanAllocateItem());
01235 front_v->cargo_payment = new CargoPayment(front_v);
01236
01237 StationIDStack next_station = front_v->GetNextStoppingStation();
01238 if (front_v->orders.list == NULL || (front_v->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0) {
01239 Station *st = Station::Get(front_v->last_station_visited);
01240 for (Vehicle *v = front_v; v != NULL; v = v->Next()) {
01241 const GoodsEntry *ge = &st->goods[v->cargo_type];
01242 if (v->cargo_cap > 0 && v->cargo.TotalCount() > 0) {
01243 v->cargo.Stage(
01244 HasBit(ge->status, GoodsEntry::GES_ACCEPTANCE),
01245 front_v->last_station_visited, next_station,
01246 front_v->current_order.GetUnloadType(), ge,
01247 front_v->cargo_payment);
01248 if (v->cargo.UnloadCount() > 0) SetBit(v->vehicle_flags, VF_CARGO_UNLOADING);
01249 }
01250 }
01251 }
01252 }
01253
01260 static uint GetLoadAmount(Vehicle *v)
01261 {
01262 const Engine *e = v->GetEngine();
01263 uint load_amount = e->info.load_amount;
01264
01265
01266 bool air_mail = v->type == VEH_AIRCRAFT && !Aircraft::From(v)->IsNormalAircraft();
01267 if (air_mail) load_amount = CeilDiv(load_amount, 4);
01268
01269 if (_settings_game.order.gradual_loading) {
01270 uint16 cb_load_amount = CALLBACK_FAILED;
01271 if (e->GetGRF() != NULL && e->GetGRF()->grf_version >= 8) {
01272
01273 cb_load_amount = GetVehicleProperty(v, PROP_VEHICLE_LOAD_AMOUNT, CALLBACK_FAILED);
01274 } else if (HasBit(e->info.callback_mask, CBM_VEHICLE_LOAD_AMOUNT)) {
01275
01276 cb_load_amount = GetVehicleCallback(CBID_VEHICLE_LOAD_AMOUNT, 0, 0, v->engine_type, v);
01277 }
01278 if (cb_load_amount != CALLBACK_FAILED) {
01279 if (e->GetGRF()->grf_version < 8) cb_load_amount = GB(cb_load_amount, 0, 8);
01280 if (cb_load_amount >= 0x100) {
01281 ErrorUnknownCallbackResult(e->GetGRFID(), CBID_VEHICLE_LOAD_AMOUNT, cb_load_amount);
01282 } else if (cb_load_amount != 0) {
01283 load_amount = cb_load_amount;
01284 }
01285 }
01286 }
01287
01288
01289 if (HasBit(e->info.misc_flags, EF_NO_DEFAULT_CARGO_MULTIPLIER) && !air_mail) load_amount = CeilDiv(load_amount * CargoSpec::Get(v->cargo_type)->multiplier, 0x100);
01290
01291 return load_amount;
01292 }
01293
01302 static void ReserveConsist(Station *st, Vehicle *u, CargoArray *consist_capleft, StationIDStack next_station)
01303 {
01304 Vehicle *next_cargo = u;
01305 uint32 seen_cargos = 0;
01306
01307 while (next_cargo != NULL) {
01308 if (next_cargo->cargo_cap == 0) {
01309
01310 next_cargo = next_cargo->Next();
01311 continue;
01312 }
01313
01314 CargoID current_cargo = next_cargo->cargo_type;
01315
01316 Vehicle *v = next_cargo;
01317 SetBit(seen_cargos, current_cargo);
01318 next_cargo = NULL;
01319 for (; v != NULL; v = v->Next()) {
01320 if (v->cargo_type != current_cargo) {
01321
01322 if (next_cargo == NULL && !HasBit(seen_cargos, v->cargo_type)) next_cargo = v;
01323 continue;
01324 }
01325
01326 assert(v->cargo_cap >= v->cargo.RemainingCount());
01327 uint cap = v->cargo_cap - v->cargo.RemainingCount();
01328
01329
01330 if (cap > 0) {
01331 cap -= st->goods[v->cargo_type].cargo.Reserve(cap, &v->cargo, st->xy, next_station);
01332 }
01333
01334 if (consist_capleft != NULL) {
01335 (*consist_capleft)[current_cargo] += cap;
01336 }
01337 }
01338 }
01339 }
01340
01350 template<class Taction>
01351 bool IterateVehicleParts(Vehicle *v, Taction action)
01352 {
01353 for (Vehicle *w = v; w != NULL;
01354 w = w->HasArticulatedPart() ? w->GetNextArticulatedPart() : NULL) {
01355 if (!action(w)) return false;
01356 if (w->type == VEH_TRAIN) {
01357 Train *train = Train::From(w);
01358 if (train->IsMultiheaded() && !action(train->other_multiheaded_part)) return false;
01359 }
01360 }
01361 if (v->type == VEH_AIRCRAFT && Aircraft::From(v)->IsNormalAircraft()) return action(v->Next());
01362 return true;
01363 }
01364
01368 struct IsEmptyAction
01369 {
01375 bool operator()(const Vehicle *v)
01376 {
01377 return v->cargo.StoredCount() == 0;
01378 }
01379 };
01380
01384 struct PrepareRefitAction
01385 {
01386 CargoArray &consist_capleft;
01387 uint32 &refit_mask;
01388
01394 PrepareRefitAction(CargoArray &consist_capleft, uint32 &refit_mask) :
01395 consist_capleft(consist_capleft), refit_mask(refit_mask) {}
01396
01403 bool operator()(const Vehicle *v)
01404 {
01405 this->consist_capleft[v->cargo_type] -= v->cargo_cap - v->cargo.ReservedCount();
01406 this->refit_mask |= EngInfo(v->engine_type)->refit_mask;
01407 return true;
01408 }
01409 };
01410
01414 struct ReturnCargoAction
01415 {
01416 Station *st;
01417 StationID next_hop;
01418
01424 ReturnCargoAction(Station *st, StationID next_one) : st(st), next_hop(next_one) {}
01425
01431 bool operator()(Vehicle *v)
01432 {
01433 v->cargo.Return(UINT_MAX, &this->st->goods[v->cargo_type].cargo, this->next_hop);
01434 return true;
01435 }
01436 };
01437
01441 struct FinalizeRefitAction
01442 {
01443 CargoArray &consist_capleft;
01444 Station *st;
01445 StationIDStack &next_station;
01446
01453 FinalizeRefitAction(CargoArray &consist_capleft, Station *st, StationIDStack &next_station) :
01454 consist_capleft(consist_capleft), st(st), next_station(next_station) {}
01455
01462 bool operator()(Vehicle *v)
01463 {
01464 this->st->goods[v->cargo_type].cargo.Reserve(v->cargo_cap - v->cargo.RemainingCount(),
01465 &v->cargo, st->xy, next_station);
01466 this->consist_capleft[v->cargo_type] += v->cargo_cap - v->cargo.RemainingCount();
01467 return true;
01468 }
01469 };
01470
01479 static void HandleStationRefit(Vehicle *v, CargoArray &consist_capleft, Station *st, StationIDStack next_station, CargoID new_cid)
01480 {
01481 Vehicle *v_start = v->GetFirstEnginePart();
01482 if (!IterateVehicleParts(v_start, IsEmptyAction())) return;
01483
01484 Backup<CompanyByte> cur_company(_current_company, v->owner, FILE_LINE);
01485
01486 uint32 refit_mask = v->GetEngine()->info.refit_mask;
01487
01488
01489 IterateVehicleParts(v_start, PrepareRefitAction(consist_capleft, refit_mask));
01490
01491 if (new_cid == CT_AUTO_REFIT) {
01492
01493 CargoID cid;
01494 new_cid = v_start->cargo_type;
01495 FOR_EACH_SET_CARGO_ID(cid, refit_mask) {
01496 if (st->goods[cid].cargo.HasCargoFor(next_station)) {
01497
01498
01499 DoCommand(v_start->tile, v_start->index, cid | 1U << 6 | 0xFF << 8 | 1U << 16, DC_QUERY_COST, GetCmdRefitVeh(v_start));
01500
01501
01502
01503
01504
01505
01506 if (_returned_refit_capacity > 0 && (consist_capleft[cid] < consist_capleft[new_cid] ||
01507 (consist_capleft[cid] == consist_capleft[new_cid] &&
01508 st->goods[cid].cargo.AvailableCount() > st->goods[new_cid].cargo.AvailableCount()))) {
01509 new_cid = cid;
01510 }
01511 }
01512 }
01513 }
01514
01515
01516 if (new_cid < NUM_CARGO && new_cid != v_start->cargo_type) {
01517 IterateVehicleParts(v_start, ReturnCargoAction(st, StationIDStack(next_station).Pop()));
01518 CommandCost cost = DoCommand(v_start->tile, v_start->index, new_cid | 1U << 6 | 0xFF << 8 | 1U << 16, DC_EXEC, GetCmdRefitVeh(v_start));
01519 if (cost.Succeeded()) v->First()->profit_this_year -= cost.GetCost() << 8;
01520 }
01521
01522
01523 IterateVehicleParts(v_start, FinalizeRefitAction(consist_capleft, st, next_station));
01524
01525 cur_company.Restore();
01526 }
01527
01532 static void LoadUnloadVehicle(Vehicle *front)
01533 {
01534 assert(front->current_order.IsType(OT_LOADING));
01535
01536 StationID last_visited = front->last_station_visited;
01537 Station *st = Station::Get(last_visited);
01538
01539 StationIDStack next_station = front->GetNextStoppingStation();
01540 bool use_autorefit = front->current_order.IsRefit() && front->current_order.GetRefitCargo() == CT_AUTO_REFIT;
01541 CargoArray consist_capleft;
01542 if (_settings_game.order.improved_load &&
01543 ((front->current_order.GetLoadType() & OLFB_FULL_LOAD) != 0 || use_autorefit)) {
01544 ReserveConsist(st, front,
01545 (use_autorefit && front->load_unload_ticks != 0) ? &consist_capleft : NULL,
01546 next_station);
01547 }
01548
01549
01550 if (front->load_unload_ticks != 0) return;
01551
01552 if (front->type == VEH_TRAIN && (!IsTileType(front->tile, MP_STATION) || GetStationIndex(front->tile) != st->index)) {
01553
01554
01555 SetBit(front->vehicle_flags, VF_LOADING_FINISHED);
01556 front->load_unload_ticks = 1;
01557 return;
01558 }
01559
01560 int unloading_time = 0;
01561 bool dirty_vehicle = false;
01562 bool dirty_station = false;
01563
01564 bool completely_emptied = true;
01565 bool anything_unloaded = false;
01566 bool anything_loaded = false;
01567 uint32 full_load_amount = 0;
01568 uint32 cargo_not_full = 0;
01569 uint32 cargo_full = 0;
01570 uint32 reservation_left = 0;
01571
01572 front->cur_speed = 0;
01573
01574 CargoPayment *payment = front->cargo_payment;
01575
01576 uint artic_part = 0;
01577 for (Vehicle *v = front; v != NULL; v = v->Next()) {
01578 if (v == front || !v->Previous()->HasArticulatedPart()) artic_part = 0;
01579 if (v->cargo_cap == 0) continue;
01580 artic_part++;
01581
01582 uint load_amount = GetLoadAmount(v);
01583
01584 GoodsEntry *ge = &st->goods[v->cargo_type];
01585
01586 if (HasBit(v->vehicle_flags, VF_CARGO_UNLOADING) && (front->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0) {
01587 uint cargo_count = v->cargo.UnloadCount();
01588 uint amount_unloaded = _settings_game.order.gradual_loading ? min(cargo_count, load_amount) : cargo_count;
01589 bool remaining = false;
01590
01591 payment->SetCargo(v->cargo_type);
01592
01593 if (!HasBit(ge->status, GoodsEntry::GES_ACCEPTANCE) && v->cargo.ActionCount(VehicleCargoList::MTA_DELIVER) > 0) {
01594
01595 if (front->current_order.GetUnloadType() & (OUFB_TRANSFER | OUFB_UNLOAD)) {
01596
01597 v->cargo.Reassign<VehicleCargoList::MTA_DELIVER, VehicleCargoList::MTA_TRANSFER>(
01598 v->cargo.ActionCount(VehicleCargoList::MTA_DELIVER), INVALID_STATION);
01599 } else {
01600 uint new_remaining = v->cargo.RemainingCount() + v->cargo.ActionCount(VehicleCargoList::MTA_DELIVER);
01601 if (v->cargo_cap < new_remaining) {
01602
01603 v->cargo.Return(new_remaining - v->cargo_cap, &ge->cargo, INVALID_STATION);
01604 }
01605
01606
01607 v->cargo.Reassign<VehicleCargoList::MTA_DELIVER, VehicleCargoList::MTA_KEEP>(
01608 v->cargo.ActionCount(VehicleCargoList::MTA_DELIVER));
01609
01610
01611
01612
01613
01614 anything_unloaded = true;
01615 }
01616 }
01617
01618 if (v->cargo.ActionCount(VehicleCargoList::MTA_TRANSFER) > 0) {
01619
01620 dirty_station = true;
01621
01622 if (!ge->HasRating()) {
01623
01624
01625 ge->time_since_pickup = 0;
01626 SetBit(ge->status, GoodsEntry::GES_RATING);
01627 }
01628 }
01629
01630 amount_unloaded = v->cargo.Unload(amount_unloaded, &ge->cargo, payment);
01631 remaining = v->cargo.UnloadCount() > 0;
01632 if (amount_unloaded > 0) {
01633 dirty_vehicle = true;
01634 anything_unloaded = true;
01635 unloading_time += amount_unloaded;
01636
01637
01638 st->time_since_unload = 0;
01639 }
01640
01641 if (_settings_game.order.gradual_loading && remaining) {
01642 completely_emptied = false;
01643 } else {
01644
01645 ClrBit(v->vehicle_flags, VF_CARGO_UNLOADING);
01646 }
01647
01648 continue;
01649 }
01650
01651
01652 if (front->current_order.GetLoadType() & OLFB_NO_LOAD || HasBit(front->vehicle_flags, VF_STOP_LOADING)) continue;
01653
01654
01655 if (front->current_order.IsRefit() && artic_part == 1) {
01656 HandleStationRefit(v, consist_capleft, st, next_station, front->current_order.GetRefitCargo());
01657 ge = &st->goods[v->cargo_type];
01658 }
01659
01660
01661 v->refit_cap = v->cargo_cap;
01662
01663
01664 int t;
01665 switch (front->type) {
01666 case VEH_TRAIN:
01667 case VEH_SHIP:
01668 t = front->vcache.cached_max_speed;
01669 break;
01670
01671 case VEH_ROAD:
01672 t = front->vcache.cached_max_speed / 2;
01673 break;
01674
01675 case VEH_AIRCRAFT:
01676 t = Aircraft::From(front)->GetSpeedOldUnits();
01677 break;
01678
01679 default: NOT_REACHED();
01680 }
01681
01682
01683 ge->last_speed = min(t, 255);
01684 ge->last_age = min(_cur_year - front->build_year, 255);
01685 ge->time_since_pickup = 0;
01686
01687 assert(v->cargo_cap >= v->cargo.StoredCount());
01688
01689
01690 uint cap_left = v->cargo_cap - v->cargo.StoredCount();
01691 if (cap_left > 0 && (v->cargo.ActionCount(VehicleCargoList::MTA_LOAD) > 0 || ge->cargo.AvailableCount() > 0)) {
01692 if (_settings_game.order.gradual_loading) cap_left = min(cap_left, load_amount);
01693 if (v->cargo.StoredCount() == 0) TriggerVehicle(v, VEHICLE_TRIGGER_NEW_CARGO);
01694
01695 uint loaded = ge->cargo.Load(cap_left, &v->cargo, st->xy, next_station);
01696 if (v->cargo.ActionCount(VehicleCargoList::MTA_LOAD) > 0) {
01697
01698
01699 SetBit(reservation_left, v->cargo_type);
01700 }
01701
01702
01703 if (loaded == cap_left) {
01704 SetBit(full_load_amount, v->cargo_type);
01705 } else {
01706 ClrBit(full_load_amount, v->cargo_type);
01707 }
01708
01709
01710
01711
01712
01713
01714
01715
01716 if (loaded > 0) {
01717 completely_emptied = false;
01718 anything_loaded = true;
01719
01720 st->time_since_load = 0;
01721 st->last_vehicle_type = v->type;
01722
01723 if (ge->cargo.TotalCount() == 0) {
01724 TriggerStationRandomisation(st, st->xy, SRT_CARGO_TAKEN, v->cargo_type);
01725 TriggerStationAnimation(st, st->xy, SAT_CARGO_TAKEN, v->cargo_type);
01726 AirportAnimationTrigger(st, AAT_STATION_CARGO_TAKEN, v->cargo_type);
01727 }
01728
01729 unloading_time += loaded;
01730
01731 dirty_vehicle = dirty_station = true;
01732 }
01733 }
01734
01735 if (v->cargo.StoredCount() >= v->cargo_cap) {
01736 SetBit(cargo_full, v->cargo_type);
01737 } else {
01738 SetBit(cargo_not_full, v->cargo_type);
01739 }
01740 }
01741
01742 if (anything_loaded || anything_unloaded) {
01743 if (front->type == VEH_TRAIN) {
01744 TriggerStationRandomisation(st, front->tile, SRT_TRAIN_LOADS);
01745 TriggerStationAnimation(st, front->tile, SAT_TRAIN_LOADS);
01746 }
01747 }
01748
01749
01750 completely_emptied &= anything_unloaded;
01751
01752 if (!anything_unloaded) delete payment;
01753
01754 ClrBit(front->vehicle_flags, VF_STOP_LOADING);
01755 if (anything_loaded || anything_unloaded) {
01756 if (_settings_game.order.gradual_loading) {
01757
01758
01759 const uint gradual_loading_wait_time[] = { 40, 20, 10, 20 };
01760
01761 unloading_time = gradual_loading_wait_time[front->type];
01762 }
01763
01764
01765 if (!anything_unloaded && full_load_amount == 0 && reservation_left == 0 && !(front->current_order.GetLoadType() & OLFB_FULL_LOAD) &&
01766 front->current_order_time >= (uint)max(front->current_order.wait_time - front->lateness_counter, 0)) {
01767 SetBit(front->vehicle_flags, VF_STOP_LOADING);
01768 }
01769 } else {
01770 bool finished_loading = true;
01771 if (front->current_order.GetLoadType() & OLFB_FULL_LOAD) {
01772 if (front->current_order.GetLoadType() == OLF_FULL_LOAD_ANY) {
01773
01774
01775 if ((front->type == VEH_AIRCRAFT && IsCargoInClass(front->cargo_type, CC_PASSENGERS) && front->cargo_cap > front->cargo.StoredCount()) ||
01776 (cargo_not_full && (cargo_full & ~cargo_not_full) == 0)) {
01777 finished_loading = false;
01778 }
01779 } else if (cargo_not_full != 0) {
01780 finished_loading = false;
01781 }
01782
01783
01784
01785
01786
01787
01788 if (!finished_loading) LinkRefresher::Run(front);
01789 }
01790 unloading_time = 20;
01791
01792 SB(front->vehicle_flags, VF_LOADING_FINISHED, 1, finished_loading);
01793 }
01794
01795 if (front->type == VEH_TRAIN) {
01796
01797 int overhang = front->GetGroundVehicleCache()->cached_total_length - st->GetPlatformLength(front->tile) * TILE_SIZE;
01798 if (overhang > 0) {
01799 unloading_time <<= 1;
01800 unloading_time += (overhang * unloading_time) / 8;
01801 }
01802 }
01803
01804
01805
01806
01807
01808
01809
01810 if (_game_mode != GM_MENU && (_settings_client.gui.loading_indicators > (uint)(front->owner != _local_company && _local_company != COMPANY_SPECTATOR))) {
01811 StringID percent_up_down = STR_NULL;
01812 int percent = CalcPercentVehicleFilled(front, &percent_up_down);
01813 if (front->fill_percent_te_id == INVALID_TE_ID) {
01814 front->fill_percent_te_id = ShowFillingPercent(front->x_pos, front->y_pos, front->z_pos + 20, percent, percent_up_down);
01815 } else {
01816 UpdateFillingPercent(front->fill_percent_te_id, percent, percent_up_down);
01817 }
01818 }
01819
01820
01821 front->load_unload_ticks = max(1, unloading_time);
01822
01823 if (completely_emptied) {
01824
01825
01826 dirty_vehicle = true;
01827 TriggerVehicle(front, VEHICLE_TRIGGER_EMPTY);
01828 }
01829
01830 if (dirty_vehicle) {
01831 SetWindowDirty(GetWindowClassForVehicleType(front->type), front->owner);
01832 SetWindowDirty(WC_VEHICLE_DETAILS, front->index);
01833 front->MarkDirty();
01834 }
01835 if (dirty_station) {
01836 st->MarkTilesDirty(true);
01837 SetWindowDirty(WC_STATION_VIEW, last_visited);
01838 InvalidateWindowData(WC_STATION_LIST, last_visited);
01839 }
01840 }
01841
01847 void LoadUnloadStation(Station *st)
01848 {
01849
01850 if (st->loading_vehicles.empty()) return;
01851
01852 Vehicle *last_loading = NULL;
01853 std::list<Vehicle *>::iterator iter;
01854
01855
01856 for (iter = st->loading_vehicles.begin(); iter != st->loading_vehicles.end(); ++iter) {
01857 Vehicle *v = *iter;
01858
01859 if ((v->vehstatus & (VS_STOPPED | VS_CRASHED))) continue;
01860
01861 assert(v->load_unload_ticks != 0);
01862 if (--v->load_unload_ticks == 0) last_loading = v;
01863 }
01864
01865
01866
01867
01868
01869
01870
01871
01872 if (last_loading == NULL) return;
01873
01874 for (iter = st->loading_vehicles.begin(); iter != st->loading_vehicles.end(); ++iter) {
01875 Vehicle *v = *iter;
01876 if (!(v->vehstatus & (VS_STOPPED | VS_CRASHED))) LoadUnloadVehicle(v);
01877 if (v == last_loading) break;
01878 }
01879
01880
01881 const Industry * const *isend = _cargo_delivery_destinations.End();
01882 for (Industry **iid = _cargo_delivery_destinations.Begin(); iid != isend; iid++) {
01883 TriggerIndustryProduction(*iid);
01884 }
01885 _cargo_delivery_destinations.Clear();
01886 }
01887
01891 void CompaniesMonthlyLoop()
01892 {
01893 CompaniesGenStatistics();
01894 if (_settings_game.economy.inflation) {
01895 AddInflation();
01896 RecomputePrices();
01897 }
01898 CompaniesPayInterest();
01899 HandleEconomyFluctuations();
01900 }
01901
01902 static void DoAcquireCompany(Company *c)
01903 {
01904 CompanyID ci = c->index;
01905
01906 CompanyNewsInformation *cni = MallocT<CompanyNewsInformation>(1);
01907 cni->FillData(c, Company::Get(_current_company));
01908
01909 SetDParam(0, STR_NEWS_COMPANY_MERGER_TITLE);
01910 SetDParam(1, c->bankrupt_value == 0 ? STR_NEWS_MERGER_TAKEOVER_TITLE : STR_NEWS_COMPANY_MERGER_DESCRIPTION);
01911 SetDParamStr(2, cni->company_name);
01912 SetDParamStr(3, cni->other_company_name);
01913 SetDParam(4, c->bankrupt_value);
01914 AddCompanyNewsItem(STR_MESSAGE_NEWS_FORMAT, cni);
01915 AI::BroadcastNewEvent(new ScriptEventCompanyMerger(ci, _current_company));
01916 Game::NewEvent(new ScriptEventCompanyMerger(ci, _current_company));
01917
01918 ChangeOwnershipOfCompanyItems(ci, _current_company);
01919
01920 if (c->bankrupt_value == 0) {
01921 Company *owner = Company::Get(_current_company);
01922 owner->current_loan += c->current_loan;
01923 }
01924
01925 if (c->is_ai) AI::Stop(c->index);
01926
01927 DeleteCompanyWindows(ci);
01928 InvalidateWindowClassesData(WC_TRAINS_LIST, 0);
01929 InvalidateWindowClassesData(WC_SHIPS_LIST, 0);
01930 InvalidateWindowClassesData(WC_ROADVEH_LIST, 0);
01931 InvalidateWindowClassesData(WC_AIRCRAFT_LIST, 0);
01932
01933 delete c;
01934 }
01935
01936 extern int GetAmountOwnedBy(const Company *c, Owner owner);
01937
01947 CommandCost CmdBuyShareInCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
01948 {
01949 CommandCost cost(EXPENSES_OTHER);
01950 CompanyID target_company = (CompanyID)p1;
01951 Company *c = Company::GetIfValid(target_company);
01952
01953
01954
01955 if (c == NULL || !_settings_game.economy.allow_shares || _current_company == target_company) return CMD_ERROR;
01956
01957
01958 if (_cur_year - c->inaugurated_year < 6) return_cmd_error(STR_ERROR_PROTECTED);
01959
01960
01961 if (GetAmountOwnedBy(c, COMPANY_SPECTATOR) == 0) return cost;
01962
01963 if (GetAmountOwnedBy(c, COMPANY_SPECTATOR) == 1) {
01964 if (!c->is_ai) return cost;
01965
01966 if (GetAmountOwnedBy(c, _current_company) == 3 && !MayCompanyTakeOver(_current_company, target_company)) return_cmd_error(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME);
01967 }
01968
01969
01970 cost.AddCost(CalculateCompanyValue(c) >> 2);
01971 if (flags & DC_EXEC) {
01972 OwnerByte *b = c->share_owners;
01973
01974 while (*b != COMPANY_SPECTATOR) b++;
01975 *b = _current_company;
01976
01977 for (int i = 0; c->share_owners[i] == _current_company;) {
01978 if (++i == 4) {
01979 c->bankrupt_value = 0;
01980 DoAcquireCompany(c);
01981 break;
01982 }
01983 }
01984 InvalidateWindowData(WC_COMPANY, target_company);
01985 CompanyAdminUpdate(c);
01986 }
01987 return cost;
01988 }
01989
01999 CommandCost CmdSellShareInCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
02000 {
02001 CompanyID target_company = (CompanyID)p1;
02002 Company *c = Company::GetIfValid(target_company);
02003
02004
02005 if (c == NULL || _current_company == target_company) return CMD_ERROR;
02006
02007
02008
02009 if (!_settings_game.economy.allow_shares && !(flags & DC_BANKRUPT)) return CMD_ERROR;
02010
02011
02012 if (GetAmountOwnedBy(c, _current_company) == 0) return CommandCost();
02013
02014
02015 Money cost = CalculateCompanyValue(c) >> 2;
02016 cost = -(cost - (cost >> 7));
02017
02018 if (flags & DC_EXEC) {
02019 OwnerByte *b = c->share_owners;
02020 while (*b != _current_company) b++;
02021 *b = COMPANY_SPECTATOR;
02022 InvalidateWindowData(WC_COMPANY, target_company);
02023 CompanyAdminUpdate(c);
02024 }
02025 return CommandCost(EXPENSES_OTHER, cost);
02026 }
02027
02040 CommandCost CmdBuyCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
02041 {
02042 CompanyID target_company = (CompanyID)p1;
02043 Company *c = Company::GetIfValid(target_company);
02044 if (c == NULL) return CMD_ERROR;
02045
02046
02047 if (!HasBit(c->bankrupt_asked, _current_company)) return CMD_ERROR;
02048
02049
02050 if (!_networking && _local_company == c->index) return CMD_ERROR;
02051
02052
02053 if (target_company == _current_company) return CMD_ERROR;
02054
02055
02056 if (!MayCompanyTakeOver(_current_company, target_company)) return CMD_ERROR;
02057
02058
02059 CommandCost cost(EXPENSES_OTHER, c->bankrupt_value);
02060
02061 if (flags & DC_EXEC) {
02062 DoAcquireCompany(c);
02063 }
02064 return cost;
02065 }