# economy.cpp

Go to the documentation of this file.

    00001 /* $Id: economy.cpp 17564 2009-09-18 07:00:35Z rubidium $ */
    00002
    00005 #include "stdafx.h"
    00006 #include "openttd.h"
    00007 #include "tile_cmd.h"
    00008 #include "company_func.h"
    00009 #include "command_func.h"
    00010 #include "industry_map.h"
    00011 #include "town.h"
    00012 #include "news_func.h"
    00013 #include "network/network.h"
    00014 #include "network/network_func.h"
    00015 #include "vehicle_gui.h"
    00016 #include "ai/ai.hpp"
    00017 #include "aircraft.h"
    00018 #include "newgrf_engine.h"
    00019 #include "newgrf_sound.h"
    00020 #include "newgrf_industries.h"
    00021 #include "newgrf_industrytiles.h"
    00022 #include "newgrf_station.h"
    00023 #include "unmovable.h"
    00024 #include "group.h"
    00025 #include "strings_func.h"
    00026 #include "functions.h"
    00027 #include "window_func.h"
    00028 #include "date_func.h"
    00029 #include "vehicle_func.h"
    00030 #include "sound_func.h"
    00031 #include "gfx_func.h"
    00032 #include "autoreplace_func.h"
    00033 #include "company_gui.h"
    00034 #include "signs_base.h"
    00035 #include "economy_base.h"
    00036 #include "oldpool_func.h"
    00037
    00038 #include "table/strings.h"
    00039 #include "table/sprites.h"
    00040
    00041
    00042 /* Initialize the cargo payment-pool */
    00043 DEFINE_OLD_POOL_GENERIC(CargoPayment, CargoPayment)
    00044
    00045
    00056 static inline int32 BigMulS(const int32 a, const int32 b, const uint8 shift)
    00057 {
    00058   return (int32)((int64)a * (int64)b >> shift);
    00059 }
    00060
    00072 static inline uint32 BigMulSU(const uint32 a, const uint32 b, const uint8 shift)
    00073 {
    00074   return (uint32)((uint64)a * (uint64)b >> shift);
    00075 }
    00076
    00077 typedef SmallVector<Industry *, 16> SmallIndustryList;
    00078
    00079 /* Score info */
    00080 const ScoreInfo _score_info[] = {
    00081   { SCORE_VEHICLES,        120, 100 },
    00082   { SCORE_STATIONS,         80, 100 },
    00083   { SCORE_MIN_PROFIT,    10000, 100 },
    00084   { SCORE_MIN_INCOME,    50000,  50 },
    00085   { SCORE_MAX_INCOME,   100000, 100 },
    00086   { SCORE_DELIVERED,     40000, 400 },
    00087   { SCORE_CARGO,             8,  50 },
    00088   { SCORE_MONEY,      10000000,  50 },
    00089   { SCORE_LOAN,         250000,  50 },
    00090   { SCORE_TOTAL,             0,   0 }
    00091 };
    00092
    00093 int _score_part[MAX_COMPANIES][SCORE_END];
    00094 Economy _economy;
    00095 Subsidy _subsidies[MAX_COMPANIES];
    00096 Prices _price;
    00097 uint16 _price_frac[NUM_PRICES];
    00098 Money  _cargo_payment_rates[NUM_CARGO];
    00099 uint16 _cargo_payment_rates_frac[NUM_CARGO];
    00100 Money _additional_cash_required;
    00101
    00102 Money CalculateCompanyValue(const Company *c)
    00103 {
    00104   Owner owner = c->index;
    00105   Money value = 0;
    00106
    00107   Station *st;
    00108   uint num = 0;
    00109
    00110   FOR_ALL_STATIONS(st) {
    00111     if (st->owner == owner) num += CountBits(st->facilities);
    00112   }
    00113
    00114   value += num * _price.station_value * 25;
    00115
    00116   Vehicle *v;
    00117   FOR_ALL_VEHICLES(v) {
    00118     if (v->owner != owner) continue;
    00119
    00120     if (v->type == VEH_TRAIN ||
    00121         v->type == VEH_ROAD ||
    00122         (v->type == VEH_AIRCRAFT && IsNormalAircraft(v)) ||
    00123         v->type == VEH_SHIP) {
    00124       value += v->value * 3 >> 1;
    00125     }
    00126   }
    00127
    00128   /* Add real money value */
    00129   value -= c->current_loan;
    00130   value += c->money;
    00131
    00132   return max(value, (Money)1);
    00133 }
    00134
    00141 int UpdateCompanyRatingAndValue(Company *c, bool update)
    00142 {
    00143   Owner owner = c->index;
    00144   int score = 0;
    00145
    00146   memset(_score_part[owner], 0, sizeof(_score_part[owner]));
    00147
    00148   /* Count vehicles */
    00149   {
    00150     Vehicle *v;
    00151     Money min_profit = 0;
    00152     bool min_profit_first = true;
    00153     uint num = 0;
    00154
    00155     FOR_ALL_VEHICLES(v) {
    00156       if (v->owner != owner) continue;
    00157       if (IsCompanyBuildableVehicleType(v->type) && v->IsPrimaryVehicle()) {
    00158         num++;
    00159         if (v->age > 730) {
    00160           /* Find the vehicle with the lowest amount of profit */
    00161           if (min_profit_first || min_profit > v->profit_last_year) {
    00162             min_profit = v->profit_last_year;
    00163             min_profit_first = false;
    00164           }
    00165         }
    00166       }
    00167     }
    00168
    00169     min_profit >>= 8; // remove the fract part
    00170
    00171     _score_part[owner][SCORE_VEHICLES] = num;
    00172     /* Don't allow negative min_profit to show */
    00173     if (min_profit > 0)
    00174       _score_part[owner][SCORE_MIN_PROFIT] = ClampToI32(min_profit);
    00175   }
    00176
    00177   /* Count stations */
    00178   {
    00179     uint num = 0;
    00180     const Station *st;
    00181
    00182     FOR_ALL_STATIONS(st) {
    00183       if (st->owner == owner) num += CountBits(st->facilities);
    00184     }
    00185     _score_part[owner][SCORE_STATIONS] = num;
    00186   }
    00187
    00188   /* Generate statistics depending on recent income statistics */
    00189   {
    00190     int numec = min(c->num_valid_stat_ent, 12);
    00191     if (numec != 0) {
    00192       const CompanyEconomyEntry *cee = c->old_economy;
    00193       Money min_income = cee->income + cee->expenses;
    00194       Money max_income = cee->income + cee->expenses;
    00195
    00196       do {
    00197         min_income = min(min_income, cee->income + cee->expenses);
    00198         max_income = max(max_income, cee->income + cee->expenses);
    00199       } while (++cee, --numec);
    00200
    00201       if (min_income > 0) {
    00202         _score_part[owner][SCORE_MIN_INCOME] = ClampToI32(min_income);
    00203       }
    00204
    00205       _score_part[owner][SCORE_MAX_INCOME] = ClampToI32(max_income);
    00206     }
    00207   }
    00208
    00209   /* Generate score depending on amount of transported cargo */
    00210   {
    00211     const CompanyEconomyEntry *cee;
    00212     int numec;
    00213     uint32 total_delivered;
    00214
    00215     numec = min(c->num_valid_stat_ent, 4);
    00216     if (numec != 0) {
    00217       cee = c->old_economy;
    00218       total_delivered = 0;
    00219       do {
    00220         total_delivered += cee->delivered_cargo;
    00221       } while (++cee, --numec);
    00222
    00223       _score_part[owner][SCORE_DELIVERED] = total_delivered;
    00224     }
    00225   }
    00226
    00227   /* Generate score for variety of cargo */
    00228   {
    00229     uint num = CountBits(c->cargo_types);
    00230     _score_part[owner][SCORE_CARGO] = num;
    00231     if (update) c->cargo_types = 0;
    00232   }
    00233
    00234   /* Generate score for company's money */
    00235   {
    00236     if (c->money > 0) {
    00237       _score_part[owner][SCORE_MONEY] = ClampToI32(c->money);
    00238     }
    00239   }
    00240
    00241   /* Generate score for loan */
    00242   {
    00243     _score_part[owner][SCORE_LOAN] = ClampToI32(_score_info[SCORE_LOAN].needed - c->current_loan);
    00244   }
    00245
    00246   /* Now we calculate the score for each item.. */
    00247   {
    00248     int total_score = 0;
    00249     int s;
    00250     score = 0;
    00251     for (ScoreID i = SCORE_BEGIN; i < SCORE_END; i++) {
    00252       /* Skip the total */
    00253       if (i == SCORE_TOTAL) continue;
    00254       /*  Check the score */
    00255       s = Clamp(_score_part[owner][i], 0, _score_info[i].needed) * _score_info[i].score / _score_info[i].needed;
    00256       score += s;
    00257       total_score += _score_info[i].score;
    00258     }
    00259
    00260     _score_part[owner][SCORE_TOTAL] = score;
    00261
    00262     /*  We always want the score scaled to SCORE_MAX (1000) */
    00263     if (total_score != SCORE_MAX) score = score * SCORE_MAX / total_score;
    00264   }
    00265
    00266   if (update) {
    00267     c->old_economy[0].performance_history = score;
    00268     UpdateCompanyHQ(c, score);
    00269     c->old_economy[0].company_value = CalculateCompanyValue(c);
    00270   }
    00271
    00272   InvalidateWindow(WC_PERFORMANCE_DETAIL, 0);
    00273   return score;
    00274 }
    00275
    00276 /*  use INVALID_OWNER as new_owner to delete the company. */
    00277 void ChangeOwnershipOfCompanyItems(Owner old_owner, Owner new_owner)
    00278 {
    00279   Town *t;
    00280   CompanyID old = _current_company;
    00281
    00282   assert(old_owner != new_owner);
    00283
    00284   {
    00285     Company *c;
    00286     uint i;
    00287
    00288     /* See if the old_owner had shares in other companies */
    00289     _current_company = old_owner;
    00290     FOR_ALL_COMPANIES(c) {
    00291       for (i = 0; i < 4; i++) {
    00292         if (c->share_owners[i] == old_owner) {
    00293           /* Sell his shares */
    00294           CommandCost res = DoCommand(0, c->index, 0, DC_EXEC, CMD_SELL_SHARE_IN_COMPANY);
    00295           /* Because we are in a DoCommand, we can't just execute an other one and
    00296            *  expect the money to be removed. We need to do it ourself! */
    00297           SubtractMoneyFromCompany(res);
    00298         }
    00299       }
    00300     }
    00301
    00302     /* Sell all the shares that people have on this company */
    00303     c = GetCompany(old_owner);
    00304     for (i = 0; i < 4; i++) {
    00305       _current_company = c->share_owners[i];
    00306       if (_current_company != INVALID_OWNER) {
    00307         /* Sell the shares */
    00308         CommandCost res = DoCommand(0, old_owner, 0, DC_EXEC, CMD_SELL_SHARE_IN_COMPANY);
    00309         /* Because we are in a DoCommand, we can't just execute an other one and
    00310          *  expect the money to be removed. We need to do it ourself! */
    00311         SubtractMoneyFromCompany(res);
    00312       }
    00313     }
    00314   }
    00315
    00316   _current_company = old_owner;
    00317
    00318   /* Temporarily increase the company's money, to be sure that
    00319    * removing his/her property doesn't fail because of lack of money.
    00320    * Not too drastically though, because it could overflow */
    00321   if (new_owner == INVALID_OWNER) {
    00322     GetCompany(old_owner)->money = UINT64_MAX >> 2; // jackpot ;p
    00323   }
    00324
    00325   if (new_owner == INVALID_OWNER) {
    00326     Subsidy *s;
    00327
    00328     for (s = _subsidies; s != endof(_subsidies); s++) {
    00329       if (s->cargo_type != CT_INVALID && s->age >= 12) {
    00330         if (GetStation(s->to)->owner == old_owner) s->cargo_type = CT_INVALID;
    00331       }
    00332     }
    00333   }
    00334
    00335   /* Take care of rating in towns */
    00336   FOR_ALL_TOWNS(t) {
    00337     /* If a company takes over, give the ratings to that company. */
    00338     if (new_owner != INVALID_OWNER) {
    00339       if (HasBit(t->have_ratings, old_owner)) {
    00340         if (HasBit(t->have_ratings, new_owner)) {
    00341           /* use max of the two ratings. */
    00342           t->ratings[new_owner] = max(t->ratings[new_owner], t->ratings[old_owner]);
    00343         } else {
    00344           SetBit(t->have_ratings, new_owner);
    00345           t->ratings[new_owner] = t->ratings[old_owner];
    00346         }
    00347       }
    00348     }
    00349
    00350     /* Reset the ratings for the old owner */
    00351     t->ratings[old_owner] = RATING_INITIAL;
    00352     ClrBit(t->have_ratings, old_owner);
    00353   }
    00354
    00355   {
    00356     FreeUnitIDGenerator unitidgen[] = {
    00357       FreeUnitIDGenerator(VEH_TRAIN, new_owner), FreeUnitIDGenerator(VEH_ROAD,     new_owner),
    00358       FreeUnitIDGenerator(VEH_SHIP,  new_owner), FreeUnitIDGenerator(VEH_AIRCRAFT, new_owner)
    00359     };
    00360
    00361     Vehicle *v;
    00362     FOR_ALL_VEHICLES(v) {
    00363       if (v->owner == old_owner && IsCompanyBuildableVehicleType(v->type)) {
    00364         if (new_owner == INVALID_OWNER) {
    00365           if (v->Previous() == NULL) delete v;
    00366         } else {
    00367           v->owner = new_owner;
    00368           v->colourmap = PAL_NONE;
    00369           if (IsEngineCountable(v)) GetCompany(new_owner)->num_engines[v->engine_type]++;
    00370           if (v->IsPrimaryVehicle()) v->unitnumber = unitidgen[v->type].NextID();
    00371         }
    00372       }
    00373     }
    00374   }
    00375
    00376   /*  Change ownership of tiles */
    00377   {
    00378     TileIndex tile = 0;
    00379     do {
    00380       ChangeTileOwner(tile, old_owner, new_owner);
    00381     } while (++tile != MapSize());
    00382
    00383     if (new_owner != INVALID_OWNER) {
    00384       /* Update all signals because there can be new segment that was owned by two companies
    00385        * and signals were not propagated
    00386        * Similiar with crossings - it is needed to bar crossings that weren't before
    00387        * because of different owner of crossing and approaching train */
    00388       tile = 0;
    00389
    00390       do {
    00391         if (IsTileType(tile, MP_RAILWAY) && IsTileOwner(tile, new_owner) && HasSignals(tile)) {
    00392           TrackBits tracks = GetTrackBits(tile);
    00393           do { // there may be two tracks with signals for TRACK_BIT_HORZ and TRACK_BIT_VERT
    00394             Track track = RemoveFirstTrack(&tracks);
    00395             if (HasSignalOnTrack(tile, track)) AddTrackToSignalBuffer(tile, track, new_owner);
    00396           } while (tracks != TRACK_BIT_NONE);
    00397         } else if (IsLevelCrossingTile(tile) && IsTileOwner(tile, new_owner)) {
    00398           UpdateLevelCrossing(tile);
    00399         }
    00400       } while (++tile != MapSize());
    00401     }
    00402
    00403     /* update signals in buffer */
    00404     UpdateSignalsInBuffer();
    00405   }
    00406
    00407   /* convert owner of stations (including deleted ones, but excluding buoys) */
    00408   Station *st;
    00409   FOR_ALL_STATIONS(st) {
    00410     if (st->owner == old_owner) {
    00411       /* if a company goes bankrupt, set owner to OWNER_NONE so the sign doesn't disappear immediately
    00412        * also, drawing station window would cause reading invalid company's colour */
    00413       st->owner = new_owner == INVALID_OWNER ? OWNER_NONE : new_owner;
    00414     }
    00415   }
    00416
    00417   /* do the same for waypoints (we need to do this here so deleted waypoints are converted too) */
    00418   Waypoint *wp;
    00419   FOR_ALL_WAYPOINTS(wp) {
    00420     if (wp->owner == old_owner) {
    00421       wp->owner = new_owner == INVALID_OWNER ? OWNER_NONE : new_owner;
    00422     }
    00423   }
    00424
    00425   /* In all cases clear replace engine rules.
    00426    * Even if it was copied, it could interfere with new owner's rules */
    00427   RemoveAllEngineReplacementForCompany(GetCompany(old_owner));
    00428
    00429   if (new_owner == INVALID_OWNER) {
    00430     RemoveAllGroupsForCompany(old_owner);
    00431   } else {
    00432     Group *g;
    00433     FOR_ALL_GROUPS(g) {
    00434       if (g->owner == old_owner) g->owner = new_owner;
    00435     }
    00436   }
    00437
    00438   Sign *si;
    00439   FOR_ALL_SIGNS(si) {
    00440     if (si->owner == old_owner) si->owner = new_owner == INVALID_OWNER ? OWNER_NONE : new_owner;
    00441   }
    00442
    00443   /* Change colour of existing windows */
    00444   if (new_owner != INVALID_OWNER) ChangeWindowOwner(old_owner, new_owner);
    00445
    00446   _current_company = old;
    00447
    00448   MarkWholeScreenDirty();
    00449 }
    00450
    00451 static void ChangeNetworkOwner(Owner current_owner, Owner new_owner)
    00452 {
    00453 #ifdef ENABLE_NETWORK
    00454   if (!_networking) return;
    00455
    00456   if (current_owner == _local_company) {
    00457     _network_playas = new_owner;
    00458     SetLocalCompany(new_owner);
    00459   }
    00460
    00461   if (!_network_server) return;
    00462
    00463   NetworkServerChangeOwner(current_owner, new_owner);
    00464 #endif /* ENABLE_NETWORK */
    00465 }
    00466
    00467 static void CompanyCheckBankrupt(Company *c)
    00468 {
    00469   /*  If the company has money again, it does not go bankrupt */
    00470   if (c->money >= 0) {
    00471     c->quarters_of_bankrupcy = 0;
    00472     c->bankrupt_asked = 0;
    00473     return;
    00474   }
    00475
    00476   c->quarters_of_bankrupcy++;
    00477
    00478   CompanyNewsInformation *cni = MallocT<CompanyNewsInformation>(1);
    00479   cni->FillData(c);
    00480
    00481   switch (c->quarters_of_bankrupcy) {
    00482     case 0:
    00483     case 1:
    00484       free(cni);
    00485       break;
    00486
    00487     case 2:
    00488       SetDParam(0, STR_7056_TRANSPORT_COMPANY_IN_TROUBLE);
    00489       SetDParam(1, STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED);
    00490       SetDParamStr(2, cni->company_name);
    00491       AddNewsItem(STR_02B6, NS_COMPANY_TROUBLE, 0, 0, cni);
    00492       AI::BroadcastNewEvent(new AIEventCompanyInTrouble(c->index));
    00493       break;
    00494     case 3: {
    00495       /* XXX - In multiplayer, should we ask other companies if it wants to take
    00496               over when it is a human company? -- TrueLight */
    00497       if (IsHumanCompany(c->index)) {
    00498         SetDParam(0, STR_7056_TRANSPORT_COMPANY_IN_TROUBLE);
    00499         SetDParam(1, STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED);
    00500         SetDParamStr(2, cni->company_name);
    00501         AddNewsItem(STR_02B6, NS_COMPANY_TROUBLE, 0, 0, cni);
    00502         break;
    00503       }
    00504
    00505       /* Check if the company has any value.. if not, declare it bankrupt
    00506        *  right now */
    00507       Money val = CalculateCompanyValue(c);
    00508       if (val > 0) {
    00509         c->bankrupt_value = val;
    00510         c->bankrupt_asked = 1 << c->index; // Don't ask the owner
    00511         c->bankrupt_timeout = 0;
    00512         free(cni);
    00513         break;
    00514       }
    00515       /* Else, falltrue to case 4... */
    00516     }
    00517     default:
    00518     case 4:
    00519       if (!_networking && _local_company == c->index) {
    00520         /* If we are in offline mode, leave the company playing. Eg. there
    00521          * is no THE-END, otherwise mark the client as spectator to make sure
    00522          * he/she is no long in control of this company. However... when you
    00523          * join another company (cheat) the "unowned" company can bankrupt. */
    00524         c->bankrupt_asked = MAX_UVALUE(CompanyMask);
    00525         free(cni);
    00526         break;
    00527       }
    00528
    00529       /* Close everything the owner has open */
    00530       DeleteCompanyWindows(c->index);
    00531
    00532       /* Show bankrupt news */
    00533       SetDParam(0, STR_705C_BANKRUPT);
    00534       SetDParam(1, STR_705D_HAS_BEEN_CLOSED_DOWN_BY);
    00535       SetDParamStr(2, cni->company_name);
    00536       AddNewsItem(STR_02B6, NS_COMPANY_BANKRUPT, 0, 0, cni);
    00537
    00538       /* Remove the company */
    00539       ChangeNetworkOwner(c->index, COMPANY_SPECTATOR);
    00540       ChangeOwnershipOfCompanyItems(c->index, INVALID_OWNER);
    00541
    00542       if (!IsHumanCompany(c->index)) AI::Stop(c->index);
    00543
    00544       CompanyID c_index = c->index;
    00545       delete c;
    00546       AI::BroadcastNewEvent(new AIEventCompanyBankrupt(c_index));
    00547   }
    00548 }
    00549
    00550 static void CompaniesGenStatistics()
    00551 {
    00552   Station *st;
    00553   Company *c;
    00554
    00555   FOR_ALL_STATIONS(st) {
    00556     _current_company = st->owner;
    00557     CommandCost cost(EXPENSES_PROPERTY, _price.station_value >> 1);
    00558     SubtractMoneyFromCompany(cost);
    00559   }
    00560
    00561   if (!HasBit(1 << 0 | 1 << 3 | 1 << 6 | 1 << 9, _cur_month))
    00562     return;
    00563
    00564   FOR_ALL_COMPANIES(c) {
    00565     memmove(&c->old_economy[1], &c->old_economy[0], sizeof(c->old_economy) - sizeof(c->old_economy[0]));
    00566     c->old_economy[0] = c->cur_economy;
    00567     memset(&c->cur_economy, 0, sizeof(c->cur_economy));
    00568
    00569     if (c->num_valid_stat_ent != 24) c->num_valid_stat_ent++;
    00570
    00571     UpdateCompanyRatingAndValue(c, true);
    00572     CompanyCheckBankrupt(c);
    00573
    00574     if (c->block_preview != 0) c->block_preview--;
    00575   }
    00576
    00577   InvalidateWindow(WC_INCOME_GRAPH, 0);
    00578   InvalidateWindow(WC_OPERATING_PROFIT, 0);
    00579   InvalidateWindow(WC_DELIVERED_CARGO, 0);
    00580   InvalidateWindow(WC_PERFORMANCE_HISTORY, 0);
    00581   InvalidateWindow(WC_COMPANY_VALUE, 0);
    00582   InvalidateWindow(WC_COMPANY_LEAGUE, 0);
    00583 }
    00584
    00585 static void AddSingleInflation(Money *value, uint16 *frac, int32 amt)
    00586 {
    00587   /* Is it safe to add inflation ? */
    00588   if ((INT64_MAX / amt) < (*value + 1)) {
    00589     *value = INT64_MAX / amt;
    00590     *frac = 0;
    00591   } else {
    00592     int64 tmp = (int64)*value * amt + *frac;
    00593     *frac   = GB(tmp, 0, 16);
    00594     *value += tmp >> 16;
    00595   }
    00596 }
    00597
    00598 static void AddInflation(bool check_year = true)
    00599 {
    00600   /* The cargo payment inflation differs from the normal inflation, so the
    00601    * relative amount of money you make with a transport decreases slowly over
    00602    * the 170 years. After a few hundred years we reach a level in which the
    00603    * games will become unplayable as the maximum income will be less than
    00604    * the minimum running cost.
    00605    *
    00606    * Furthermore there are a lot of inflation related overflows all over the
    00607    * place. Solving them is hardly possible because inflation will always
    00608    * reach the overflow threshold some day. So we'll just perform the
    00609    * inflation mechanism during the first 170 years (the amount of years that
    00610    * one had in the original TTD) and stop doing the inflation after that
    00611    * because it only causes problems that can't be solved nicely and the
    00612    * inflation doesn't add anything after that either; it even makes playing
    00613    * it impossible due to the diverging cost and income rates.
    00614    */
    00615   if (check_year && (_cur_year - _settings_game.game_creation.starting_year) >= (ORIGINAL_MAX_YEAR - ORIGINAL_BASE_YEAR)) return;
    00616
    00617   /* Approximation for (100 + infl_amount)% ** (1 / 12) - 100%
    00618    * scaled by 65536
    00619    * 12 -> months per year
    00620    * This is only a good approxiamtion for small values
    00621    */
    00622   int32 inf = _economy.infl_amount * 54;
    00623
    00624   for (uint i = 0; i != NUM_PRICES; i++) {
    00625     AddSingleInflation((Money*)&_price + i, _price_frac + i, inf);
    00626   }
    00627
    00628   AddSingleInflation(&_economy.max_loan_unround, &_economy.max_loan_unround_fract, inf);
    00629
    00630   if (_economy.max_loan + 50000 <= _economy.max_loan_unround) _economy.max_loan += 50000;
    00631
    00632   inf = _economy.infl_amount_pr * 54;
    00633   for (CargoID i = 0; i < NUM_CARGO; i++) {
    00634     AddSingleInflation(
    00635       (Money*)_cargo_payment_rates + i,
    00636       _cargo_payment_rates_frac + i,
    00637       inf
    00638     );
    00639   }
    00640
    00641   InvalidateWindowClasses(WC_BUILD_VEHICLE);
    00642   InvalidateWindowClasses(WC_REPLACE_VEHICLE);
    00643   InvalidateWindowClasses(WC_VEHICLE_DETAILS);
    00644   InvalidateWindow(WC_PAYMENT_RATES, 0);
    00645 }
    00646
    00647 static void CompaniesPayInterest()
    00648 {
    00649   const Company *c;
    00650
    00651   FOR_ALL_COMPANIES(c) {
    00652     _current_company = c->index;
    00653
    00654     /* Over a year the paid interest should be "loan * interest percentage",
    00655      * but... as that number is likely not dividable by 12 (pay each month),
    00656      * one needs to account for that in the monthly fee calculations.
    00657      * To easily calculate what one should pay "this" month, you calculate
    00658      * what (total) should have been paid up to this month and you substract
    00659      * whatever has been paid in the previous months. This will mean one month
    00660      * it'll be a bit more and the other it'll be a bit less than the average
    00661      * monthly fee, but on average it will be exact. */
    00662     Money yearly_fee = c->current_loan * _economy.interest_rate / 100;
    00663     Money up_to_previous_month = yearly_fee * _cur_month / 12;
    00664     Money up_to_this_month = yearly_fee * (_cur_month + 1) / 12;
    00665
    00666     SubtractMoneyFromCompany(CommandCost(EXPENSES_LOAN_INT, up_to_this_month - up_to_previous_month));
    00667
    00668     SubtractMoneyFromCompany(CommandCost(EXPENSES_OTHER, _price.station_value >> 2));
    00669   }
    00670 }
    00671
    00672 static void HandleEconomyFluctuations()
    00673 {
    00674   if (_settings_game.difficulty.economy != 0) {
    00675     /* When economy is Fluctuating, decrease counter */
    00676     _economy.fluct--;
    00677   } else if (_economy.fluct <= 0) {
    00678     /* When it's Steady and we are in recession, end it now */
    00679     _economy.fluct = -12;
    00680   } else {
    00681     /* No need to do anything else in other cases */
    00682     return;
    00683   }
    00684
    00685   if (_economy.fluct == 0) {
    00686     _economy.fluct = -(int)GB(Random(), 0, 2);
    00687     AddNewsItem(STR_7073_WORLD_RECESSION_FINANCIAL, NS_ECONOMY, 0, 0);
    00688   } else if (_economy.fluct == -12) {
    00689     _economy.fluct = GB(Random(), 0, 8) + 312;
    00690     AddNewsItem(STR_7074_RECESSION_OVER_UPTURN_IN, NS_ECONOMY, 0, 0);
    00691   }
    00692 }
    00693
    00694 static byte _price_category[NUM_PRICES] = {
    00695   0, 2, 2, 2, 2, 2, 2, 2,
    00696   2, 2, 2, 2, 2, 2, 2, 2,
    00697   2, 2, 2, 2, 2, 2, 2, 2,
    00698   2, 2, 2, 2, 2, 2, 2, 2,
    00699   2, 2, 2, 2, 2, 2, 2, 2,
    00700   2, 2, 1, 1, 1, 1, 1, 1,
    00701   2,
    00702 };
    00703
    00704 static const Money _price_base[NUM_PRICES] = {
    00705       100,
    00706       100,
    00707        95,
    00708        65,
    00709       275,
    00710       600,
    00711       500,
    00712       700,
    00713       450,
    00714       200,
    00715       180,
    00716       600,
    00717       200,
    00718       200,
    00719       350,
    00720    400000,
    00721      2000,
    00722    700000,
    00723     14000,
    00724     65000,
    00725        20,
    00726       250,
    00727        20,
    00728        40,
    00729       200,
    00730       500,
    00731        20,
    00732       -70,
    00733        10,
    00734        50,
    00735        80,
    00736        80,
    00737        90,
    00738        30,
    00739     10000,
    00740        50,
    00741        30,
    00742        50,
    00743        50,
    00744        55,
    00745      1600,
    00746        40,
    00747      5600,
    00748      5200,
    00749      4800,
    00750      9600,
    00751      1600,
    00752      5600,
    00753   1000000,
    00754 };
    00755
    00756 static byte price_base_multiplier[NUM_PRICES];
    00757
    00761 void ResetPriceBaseMultipliers()
    00762 {
    00763   uint i;
    00764
    00765   /* 8 means no multiplier. */
    00766   for (i = 0; i < NUM_PRICES; i++)
    00767     price_base_multiplier[i] = 8;
    00768 }
    00769
    00777 void SetPriceBaseMultiplier(uint price, byte factor)
    00778 {
    00779   assert(price < NUM_PRICES);
    00780   price_base_multiplier[price] = factor;
    00781 }
    00782
    00787 void StartupIndustryDailyChanges(bool init_counter)
    00788 {
    00789   uint map_size = MapLogX() + MapLogY();
    00790   /* After getting map size, it needs to be scaled appropriately and divided by 31,
    00791    * which stands for the days in a month.
    00792    * Using just 31 will make it so that a monthly reset (based on the real number of days of that month)
    00793    * would not be needed.
    00794    * Since it is based on "fractionnal parts", the leftover days will not make much of a difference
    00795    * on the overall total number of changes performed */
    00796   _economy.industry_daily_increment = (1 << map_size) / 31;
    00797
    00798   if (init_counter) {
    00799     /* A new game or a savegame from an older version will require the counter to be initialized */
    00800     _economy.industry_daily_change_counter = 0;
    00801   }
    00802 }
    00803
    00804 void StartupEconomy()
    00805 {
    00806   int i;
    00807
    00808   assert(sizeof(_price) == NUM_PRICES * sizeof(Money));
    00809
    00810   for (i = 0; i != NUM_PRICES; i++) {
    00811     Money price = _price_base[i];
    00812     if (_price_category[i] != 0) {
    00813       uint mod = _price_category[i] == 1 ? _settings_game.difficulty.vehicle_costs : _settings_game.difficulty.construction_cost;
    00814       if (mod < 1) {
    00815         price = price * 3 >> 2;
    00816       } else if (mod > 1) {
    00817         price = price * 9 >> 3;
    00818       }
    00819     }
    00820     if (price_base_multiplier[i] > 8) {
    00821       price <<= price_base_multiplier[i] - 8;
    00822     } else {
    00823       price >>= 8 - price_base_multiplier[i];
    00824     }
    00825     ((Money*)&_price)[i] = price;
    00826     _price_frac[i] = 0;
    00827   }
    00828
    00829   _economy.interest_rate = _settings_game.difficulty.initial_interest;
    00830   _economy.infl_amount = _settings_game.difficulty.initial_interest;
    00831   _economy.infl_amount_pr = max(0, _settings_game.difficulty.initial_interest - 1);
    00832   _economy.max_loan_unround = _economy.max_loan = _settings_game.difficulty.max_loan;
    00833   _economy.fluct = GB(Random(), 0, 8) + 168;
    00834
    00835   StartupIndustryDailyChanges(true); // As we are starting a new game, initialize the counter too
    00836
    00837 }
    00838
    00839 void ResetEconomy()
    00840 {
    00841   /* Test if resetting the economy is needed. */
    00842   bool needed = false;
    00843
    00844   for (CargoID c = 0; c < NUM_CARGO; c++) {
    00845     const CargoSpec *cs = GetCargo(c);
    00846     if (!cs->IsValid()) continue;
    00847     if (_cargo_payment_rates[c] == 0) {
    00848       needed = true;
    00849       break;
    00850     }
    00851   }
    00852
    00853   if (!needed) return;
    00854
    00855   /* Remember old unrounded maximum loan value. NewGRF has the ability
    00856    * to change all the other inflation affected base costs. */
    00857   Money old_value = _economy.max_loan_unround;
    00858
    00859   /* Reset the economy */
    00860   StartupEconomy();
    00861   InitializeLandscapeVariables(false);
    00862
    00863   /* Reapply inflation, ignoring the year */
    00864   while (old_value > _economy.max_loan_unround) {
    00865     AddInflation(false);
    00866   }
    00867 }
    00868
    00869 Money GetPriceByIndex(uint8 index)
    00870 {
    00871   if (index > NUM_PRICES) return 0;
    00872
    00873   return ((Money*)&_price)[index];
    00874 }
    00875
    00876
    00877 Pair SetupSubsidyDecodeParam(const Subsidy *s, bool mode)
    00878 {
    00879   TileIndex tile;
    00880   TileIndex tile2;
    00881   Pair tp;
    00882
    00883   /* if mode is false, use the singular form */
    00884   const CargoSpec *cs = GetCargo(s->cargo_type);
    00885   SetDParam(0, mode ? cs->name : cs->name_single);
    00886
    00887   if (s->age < 12) {
    00888     if (cs->town_effect != TE_PASSENGERS && cs->town_effect != TE_MAIL) {
    00889       SetDParam(1, STR_INDUSTRY);
    00890       SetDParam(2, s->from);
    00891       tile = GetIndustry(s->from)->xy;
    00892
    00893       if (cs->town_effect != TE_GOODS && cs->town_effect != TE_FOOD) {
    00894         SetDParam(4, STR_INDUSTRY);
    00895         SetDParam(5, s->to);
    00896         tile2 = GetIndustry(s->to)->xy;
    00897       } else {
    00898         SetDParam(4, STR_TOWN);
    00899         SetDParam(5, s->to);
    00900         tile2 = GetTown(s->to)->xy;
    00901       }
    00902     } else {
    00903       SetDParam(1, STR_TOWN);
    00904       SetDParam(2, s->from);
    00905       tile = GetTown(s->from)->xy;
    00906
    00907       SetDParam(4, STR_TOWN);
    00908       SetDParam(5, s->to);
    00909       tile2 = GetTown(s->to)->xy;
    00910     }
    00911   } else {
    00912     SetDParam(1, s->from);
    00913     tile = GetStation(s->from)->xy;
    00914
    00915     SetDParam(2, s->to);
    00916     tile2 = GetStation(s->to)->xy;
    00917   }
    00918
    00919   tp.a = tile;
    00920   tp.b = tile2;
    00921
    00922   return tp;
    00923 }
    00924
    00925 void DeleteSubsidyWithTown(TownID index)
    00926 {
    00927   Subsidy *s;
    00928
    00929   for (s = _subsidies; s != endof(_subsidies); s++) {
    00930     if (s->cargo_type != CT_INVALID && s->age < 12) {
    00931       const CargoSpec *cs = GetCargo(s->cargo_type);
    00932       if (((cs->town_effect == TE_PASSENGERS || cs->town_effect == TE_MAIL) && (index == s->from || index == s->to)) ||
    00933         ((cs->town_effect == TE_GOODS || cs->town_effect == TE_FOOD) && index == s->to)) {
    00934         s->cargo_type = CT_INVALID;
    00935       }
    00936     }
    00937   }
    00938 }
    00939
    00940 void DeleteSubsidyWithIndustry(IndustryID index)
    00941 {
    00942   Subsidy *s;
    00943
    00944   for (s = _subsidies; s != endof(_subsidies); s++) {
    00945     if (s->cargo_type != CT_INVALID && s->age < 12) {
    00946       const CargoSpec *cs = GetCargo(s->cargo_type);
    00947       if (cs->town_effect != TE_PASSENGERS && cs->town_effect != TE_MAIL &&
    00948         (index == s->from || (cs->town_effect != TE_GOODS && cs->town_effect != TE_FOOD && index == s->to))) {
    00949         s->cargo_type = CT_INVALID;
    00950       }
    00951     }
    00952   }
    00953 }
    00954
    00955 void DeleteSubsidyWithStation(StationID index)
    00956 {
    00957   Subsidy *s;
    00958   bool dirty = false;
    00959
    00960   for (s = _subsidies; s != endof(_subsidies); s++) {
    00961     if (s->cargo_type != CT_INVALID && s->age >= 12 &&
    00962         (s->from == index || s->to == index)) {
    00963       s->cargo_type = CT_INVALID;
    00964       dirty = true;
    00965     }
    00966   }
    00967
    00968   if (dirty)
    00969     InvalidateWindow(WC_SUBSIDIES_LIST, 0);
    00970 }
    00971
    00972 struct FoundRoute {
    00973   uint distance;
    00974   CargoID cargo;
    00975   void *from;
    00976   void *to;
    00977 };
    00978
    00979 static void FindSubsidyPassengerRoute(FoundRoute *fr)
    00980 {
    00981   Town *from, *to;
    00982
    00983   fr->distance = UINT_MAX;
    00984
    00985   fr->from = from = GetRandomTown();
    00986   if (from == NULL || from->population < 400) return;
    00987
    00988   fr->to = to = GetRandomTown();
    00989   if (from == to || to == NULL || to->population < 400 || to->pct_pass_transported > 42)
    00990     return;
    00991
    00992   fr->distance = DistanceManhattan(from->xy, to->xy);
    00993 }
    00994
    00995 static void FindSubsidyCargoRoute(FoundRoute *fr)
    00996 {
    00997   Industry *i;
    00998   int trans, total;
    00999   CargoID cargo;
    01000
    01001   fr->distance = UINT_MAX;
    01002
    01003   fr->from = i = GetRandomIndustry();
    01004   if (i == NULL) return;
    01005
    01006   /* Randomize cargo type */
    01007   if (HasBit(Random(), 0) && i->produced_cargo[1] != CT_INVALID) {
    01008     cargo = i->produced_cargo[1];
    01009     trans = i->last_month_pct_transported[1];
    01010     total = i->last_month_production[1];
    01011   } else {
    01012     cargo = i->produced_cargo[0];
    01013     trans = i->last_month_pct_transported[0];
    01014     total = i->last_month_production[0];
    01015   }
    01016
    01017   /* Quit if no production in this industry
    01018    * or if the cargo type is passengers
    01019    * or if the pct transported is already large enough */
    01020   if (total == 0 || trans > 42 || cargo == CT_INVALID) return;
    01021
    01022   const CargoSpec *cs = GetCargo(cargo);
    01023   if (cs->town_effect == TE_PASSENGERS) return;
    01024
    01025   fr->cargo = cargo;
    01026
    01027   if (cs->town_effect == TE_GOODS || cs->town_effect == TE_FOOD) {
    01028     /*  The destination is a town */
    01029     Town *t = GetRandomTown();
    01030
    01031     /* Only want big towns */
    01032     if (t == NULL || t->population < 900) return;
    01033
    01034     fr->distance = DistanceManhattan(i->xy, t->xy);
    01035     fr->to = t;
    01036   } else {
    01037     /* The destination is an industry */
    01038     Industry *i2 = GetRandomIndustry();
    01039
    01040     /* The industry must accept the cargo */
    01041     if (i2 == NULL || i == i2 ||
    01042         (cargo != i2->accepts_cargo[0] &&
    01043         cargo != i2->accepts_cargo[1] &&
    01044         cargo != i2->accepts_cargo[2])) {
    01045       return;
    01046     }
    01047     fr->distance = DistanceManhattan(i->xy, i2->xy);
    01048     fr->to = i2;
    01049   }
    01050 }
    01051
    01052 static bool CheckSubsidyDuplicate(Subsidy *s)
    01053 {
    01054   const Subsidy *ss;
    01055
    01056   for (ss = _subsidies; ss != endof(_subsidies); ss++) {
    01057     if (s != ss &&
    01058         ss->from == s->from &&
    01059         ss->to == s->to &&
    01060         ss->cargo_type == s->cargo_type) {
    01061       s->cargo_type = CT_INVALID;
    01062       return true;
    01063     }
    01064   }
    01065   return false;
    01066 }
    01067
    01068
    01069 static void SubsidyMonthlyHandler()
    01070 {
    01071   Subsidy *s;
    01072   Pair pair;
    01073   Station *st;
    01074   uint n;
    01075   FoundRoute fr;
    01076   bool modified = false;
    01077
    01078   for (s = _subsidies; s != endof(_subsidies); s++) {
    01079     if (s->cargo_type == CT_INVALID) continue;
    01080
    01081     if (s->age == 12 - 1) {
    01082       pair = SetupSubsidyDecodeParam(s, 1);
    01083       AddNewsItem(STR_202E_OFFER_OF_SUBSIDY_EXPIRED, NS_SUBSIDIES, pair.a, pair.b);
    01084       s->cargo_type = CT_INVALID;
    01085       modified = true;
    01086       AI::BroadcastNewEvent(new AIEventSubsidyOfferExpired(s - _subsidies));
    01087     } else if (s->age == 2 * 12 - 1) {
    01088       st = GetStation(s->to);
    01089       if (st->owner == _local_company) {
    01090         pair = SetupSubsidyDecodeParam(s, 1);
    01091         AddNewsItem(STR_202F_SUBSIDY_WITHDRAWN_SERVICE, NS_SUBSIDIES, pair.a, pair.b);
    01092       }
    01093       s->cargo_type = CT_INVALID;
    01094       modified = true;
    01095       AI::BroadcastNewEvent(new AIEventSubsidyExpired(s - _subsidies));
    01096     } else {
    01097       s->age++;
    01098     }
    01099   }
    01100
    01101   /* 25% chance to go on */
    01102   if (Chance16(1, 4)) {
    01103     /*  Find a free slot*/
    01104     s = _subsidies;
    01105     while (s->cargo_type != CT_INVALID) {
    01106       if (++s == endof(_subsidies))
    01107         goto no_add;
    01108     }
    01109
    01110     n = 1000;
    01111     do {
    01112       FindSubsidyPassengerRoute(&fr);
    01113       if (fr.distance <= 70) {
    01114         s->cargo_type = CT_PASSENGERS;
    01115         s->from = ((Town*)fr.from)->index;
    01116         s->to = ((Town*)fr.to)->index;
    01117         goto add_subsidy;
    01118       }
    01119       FindSubsidyCargoRoute(&fr);
    01120       if (fr.distance <= 70) {
    01121         s->cargo_type = fr.cargo;
    01122         s->from = ((Industry*)fr.from)->index;
    01123         {
    01124           const CargoSpec *cs = GetCargo(fr.cargo);
    01125           s->to = (cs->town_effect == TE_GOODS || cs->town_effect == TE_FOOD) ? ((Town*)fr.to)->index : ((Industry*)fr.to)->index;
    01126         }
    01127   add_subsidy:
    01128         if (!CheckSubsidyDuplicate(s)) {
    01129           s->age = 0;
    01130           pair = SetupSubsidyDecodeParam(s, 0);
    01131           AddNewsItem(STR_2030_SERVICE_SUBSIDY_OFFERED, NS_SUBSIDIES, pair.a, pair.b);
    01132           AI::BroadcastNewEvent(new AIEventSubsidyOffer(s - _subsidies));
    01133           modified = true;
    01134           break;
    01135         }
    01136       }
    01137     } while (n--);
    01138   }
    01139 no_add:;
    01140   if (modified)
    01141     InvalidateWindow(WC_SUBSIDIES_LIST, 0);
    01142 }
    01143
    01144 Money GetTransportedGoodsIncome(uint num_pieces, uint dist, byte transit_days, CargoID cargo_type)
    01145 {
    01146   const CargoSpec *cs = GetCargo(cargo_type);
    01147
    01148   /* Use callback to calculate cargo profit, if available */
    01149   if (HasBit(cs->callback_mask, CBM_CARGO_PROFIT_CALC)) {
    01150     uint32 var18 = min(dist, 0xFFFF) | (min(num_pieces, 0xFF) << 16) | (transit_days << 24);
    01151     uint16 callback = GetCargoCallback(CBID_CARGO_PROFIT_CALC, 0, var18, cs);
    01152     if (callback != CALLBACK_FAILED) {
    01153       int result = GB(callback, 0, 14);
    01154
    01155       /* Simulate a 15 bit signed value */
    01156       if (HasBit(callback, 14)) result -= 0x4000;
    01157
    01158       /* "The result should be a signed multiplier that gets multiplied
    01159        * by the amount of cargo moved and the price factor, then gets
    01160        * divided by 8192." */
    01161       return result * num_pieces * _cargo_payment_rates[cargo_type] / 8192;
    01162     }
    01163   }
    01164
    01165   /* zero the distance (thus income) if it's the bank and very short transport. */
    01166   if (_settings_game.game_creation.landscape == LT_TEMPERATE && cs->label == 'VALU' && dist < 10) return 0;
    01167
    01168
    01169   static const int MIN_TIME_FACTOR = 31;
    01170   static const int MAX_TIME_FACTOR = 255;
    01171
    01172   const int days1 = cs->transit_days[0];
    01173   const int days2 = cs->transit_days[1];
    01174   const int days_over_days1 = max(   transit_days - days1, 0);
    01175   const int days_over_days2 = max(days_over_days1 - days2, 0);
    01176
    01177   /*
    01178    * The time factor is calculated based on the time it took
    01179    * (transit_days) compared two cargo-depending values. The
    01180    * range is divided into three parts:
    01181    *
    01182    *  - constant for fast transits
    01183    *  - linear decreasing with time with a slope of -1 for medium transports
    01184    *  - linear decreasing with time with a slope of -2 for slow transports
    01185    *
    01186    */
    01187   const int time_factor = max(MAX_TIME_FACTOR - days_over_days1 - days_over_days2, MIN_TIME_FACTOR);
    01188
    01189   return BigMulS(dist * time_factor * num_pieces, _cargo_payment_rates[cargo_type], 21);
    01190 }
    01191
    01192
    01193 struct FindIndustryToDeliverData {
    01194   const Rect *rect;
    01195   CargoID cargo_type;
    01196
    01197   Industry *ind;
    01198   const IndustrySpec *indspec;
    01199   uint cargo_index;
    01200 };
    01201
    01202 static bool FindIndustryToDeliver(TileIndex ind_tile, void *user_data)
    01203 {
    01204   FindIndustryToDeliverData *callback_data = (FindIndustryToDeliverData *)user_data;
    01205   const Rect *rect = callback_data->rect;
    01206   CargoID cargo_type = callback_data->cargo_type;
    01207
    01208   /* Only process industry tiles */
    01209   if (!IsTileType(ind_tile, MP_INDUSTRY)) return false;
    01210
    01211   /* Only process tiles in the station acceptance rectangle */
    01212   int x = TileX(ind_tile);
    01213   int y = TileY(ind_tile);
    01214   if (x < rect->left || x > rect->right || y < rect->top || y > rect->bottom) return false;
    01215
    01216   Industry *ind = GetIndustryByTile(ind_tile);
    01217   const IndustrySpec *indspec = GetIndustrySpec(ind->type);
    01218
    01219   uint cargo_index;
    01220   for (cargo_index = 0; cargo_index < lengthof(ind->accepts_cargo); cargo_index++) {
    01221     if (cargo_type == ind->accepts_cargo[cargo_index]) break;
    01222   }
    01223   /* Check if matching cargo has been found */
    01224   if (cargo_index >= lengthof(ind->accepts_cargo)) return false;
    01225
    01226   /* Check if industry temporarly refuses acceptance */
    01227   if (HasBit(indspec->callback_flags, CBM_IND_REFUSE_CARGO)) {
    01228     uint16 res = GetIndustryCallback(CBID_INDUSTRY_REFUSE_CARGO, 0, GetReverseCargoTranslation(cargo_type, indspec->grf_prop.grffile), ind, ind->type, ind->xy);
    01229     if (res == 0) return false;
    01230   }
    01231
    01232   /* Found industry accepting the cargo */
    01233   callback_data->ind = ind;
    01234   callback_data->indspec = indspec;
    01235   callback_data->cargo_index = cargo_index;
    01236   return true;
    01237 }
    01238
    01240 static SmallIndustryList _cargo_delivery_destinations;
    01241
    01249 static void DeliverGoodsToIndustry(const Station *st, CargoID cargo_type, int num_pieces)
    01250 {
    01251   if (st->rect.IsEmpty()) return;
    01252
    01253   /* Compute acceptance rectangle */
    01254   int catchment_radius = st->GetCatchmentRadius();
    01255   Rect rect = {
    01256     max<int>(st->rect.left   - catchment_radius, 0),
    01257     max<int>(st->rect.top    - catchment_radius, 0),
    01258     min<int>(st->rect.right  + catchment_radius, MapMaxX()),
    01259     min<int>(st->rect.bottom + catchment_radius, MapMaxY())
    01260   };
    01261
    01262   /* Compute maximum extent of acceptance rectangle wrt. station sign */
    01263   TileIndex start_tile = st->xy;
    01264   uint max_radius = max(
    01265     max(DistanceManhattan(start_tile, TileXY(rect.left , rect.top)), DistanceManhattan(start_tile, TileXY(rect.left , rect.bottom))),
    01266     max(DistanceManhattan(start_tile, TileXY(rect.right, rect.top)), DistanceManhattan(start_tile, TileXY(rect.right, rect.bottom)))
    01267   );
    01268
    01269   FindIndustryToDeliverData callback_data;
    01270   callback_data.rect = &rect;
    01271   callback_data.cargo_type = cargo_type;
    01272   callback_data.ind = NULL;
    01273   callback_data.indspec = NULL;
    01274   callback_data.cargo_index = 0;
    01275
    01276   /* Find the nearest industrytile to the station sign inside the catchment area, whose industry accepts the cargo.
    01277    * This fails in three cases:
    01278    *  1) The station accepts the cargo because there are enough houses around it accepting the cargo.
    01279    *  2) The industries in the catchment area temporarily reject the cargo, and the daily station loop has not yet updated station acceptance.
    01280    *  3) The results of callbacks CBID_INDUSTRY_REFUSE_CARGO and CBID_INDTILE_CARGO_ACCEPTANCE are inconsistent. (documented behaviour)
    01281    */
    01282   if (CircularTileSearch(&start_tile, 2 * max_radius + 1, FindIndustryToDeliver, &callback_data)) {
    01283     Industry *best = callback_data.ind;
    01284     uint accepted_cargo_index = callback_data.cargo_index;
    01285     assert(best != NULL);
    01286
    01287     /* Insert the industry into industry_set, if not yet contained */
    01288     _cargo_delivery_destinations.Include(best);
    01289
    01290     best->incoming_cargo_waiting[accepted_cargo_index] = min(num_pieces + best->incoming_cargo_waiting[accepted_cargo_index], 0xFFFF);
    01291   }
    01292 }
    01293
    01294
    01295 static bool CheckSubsidised(Station *from, Station *to, CargoID cargo_type, CompanyID company)
    01296 {
    01297   Subsidy *s;
    01298   TileIndex xy;
    01299   Pair pair;
    01300
    01301   /* check if there is an already existing subsidy that applies to us */
    01302   for (s = _subsidies; s != endof(_subsidies); s++) {
    01303     if (s->cargo_type == cargo_type &&
    01304         s->age >= 12 &&
    01305         s->from == from->index &&
    01306         s->to == to->index) {
    01307       return true;
    01308     }
    01309   }
    01310
    01311   /* check if there's a new subsidy that applies.. */
    01312   for (s = _subsidies; s != endof(_subsidies); s++) {
    01313     if (s->cargo_type == cargo_type && s->age < 12) {
    01314       /* Check distance from source */
    01315       const CargoSpec *cs = GetCargo(cargo_type);
    01316       if (cs->town_effect == TE_PASSENGERS || cs->town_effect == TE_MAIL) {
    01317         xy = GetTown(s->from)->xy;
    01318       } else {
    01319         xy = GetIndustry(s->from)->xy;
    01320       }
    01321       if (DistanceMax(xy, from->xy) > 9) continue;
    01322
    01323       /* Check distance from dest */
    01324       switch (cs->town_effect) {
    01325         case TE_PASSENGERS:
    01326         case TE_MAIL:
    01327         case TE_GOODS:
    01328         case TE_FOOD:
    01329           xy = GetTown(s->to)->xy;
    01330           break;
    01331
    01332         default:
    01333           xy = GetIndustry(s->to)->xy;
    01334           break;
    01335       }
    01336       if (DistanceMax(xy, to->xy) > 9) continue;
    01337
    01338       /* Found a subsidy, change the values to indicate that it's in use */
    01339       s->age = 12;
    01340       s->from = from->index;
    01341       s->to = to->index;
    01342
    01343       /* Add a news item */
    01344       pair = SetupSubsidyDecodeParam(s, 0);
    01345       InjectDParam(1);
    01346
    01347       SetDParam(0, company);
    01348       AddNewsItem(
    01349         STR_2031_SERVICE_SUBSIDY_AWARDED + _settings_game.difficulty.subsidy_multiplier,
    01350         NS_SUBSIDIES,
    01351         pair.a, pair.b
    01352       );
    01353       AI::BroadcastNewEvent(new AIEventSubsidyAwarded(s - _subsidies));
    01354
    01355       InvalidateWindow(WC_SUBSIDIES_LIST, 0);
    01356       return true;
    01357     }
    01358   }
    01359   return false;
    01360 }
    01361
    01372 static Money DeliverGoods(int num_pieces, CargoID cargo_type, StationID source, StationID dest, TileIndex source_tile, byte days_in_transit, Company *company)
    01373 {
    01374   bool subsidised;
    01375   Station *s_from, *s_to;
    01376   Money profit;
    01377
    01378   assert(num_pieces > 0);
    01379
    01380   /* Update company statistics */
    01381   company->cur_economy.delivered_cargo += num_pieces;
    01382   SetBit(company->cargo_types, cargo_type);
    01383
    01384   /* Get station pointers. */
    01385   s_from = IsValidStationID(source) ? GetStation(source) : NULL;
    01386   s_to = GetStation(dest);
    01387
    01388   /* Check if a subsidy applies. */
    01389   subsidised = s_from != NULL && CheckSubsidised(s_from, s_to, cargo_type, company->index);
    01390
    01391   /* Increase town's counter for some special goods types */
    01392   const CargoSpec *cs = GetCargo(cargo_type);
    01393   if (cs->town_effect == TE_FOOD) s_to->town->new_act_food += num_pieces;
    01394   if (cs->town_effect == TE_WATER) s_to->town->new_act_water += num_pieces;
    01395
    01396   /* Give the goods to the industry. */
    01397   DeliverGoodsToIndustry(s_to, cargo_type, num_pieces);
    01398
    01399   /* Determine profit */
    01400   profit = GetTransportedGoodsIncome(num_pieces, DistanceManhattan(source_tile, s_to->xy), days_in_transit, cargo_type);
    01401
    01402   /* Modify profit if a subsidy is in effect */
    01403   if (subsidised) {
    01404     switch (_settings_game.difficulty.subsidy_multiplier) {
    01405       case 0:  profit += profit >> 1; break;
    01406       case 1:  profit *= 2; break;
    01407       case 2:  profit *= 3; break;
    01408       default: profit *= 4; break;
    01409     }
    01410   }
    01411
    01412   return profit;
    01413 }
    01414
    01420 static void TriggerIndustryProduction(Industry *i)
    01421 {
    01422   const IndustrySpec *indspec = GetIndustrySpec(i->type);
    01423   uint16 callback = indspec->callback_flags;
    01424
    01425   i->was_cargo_delivered = true;
    01426   i->last_cargo_accepted_at = _date;
    01427
    01428   if (HasBit(callback, CBM_IND_PRODUCTION_CARGO_ARRIVAL) || HasBit(callback, CBM_IND_PRODUCTION_256_TICKS)) {
    01429     if (HasBit(callback, CBM_IND_PRODUCTION_CARGO_ARRIVAL)) {
    01430       IndustryProductionCallback(i, 0);
    01431     } else {
    01432       InvalidateWindow(WC_INDUSTRY_VIEW, i->index);
    01433     }
    01434   } else {
    01435     for (uint cargo_index = 0; cargo_index < lengthof(i->incoming_cargo_waiting); cargo_index++) {
    01436       uint cargo_waiting = i->incoming_cargo_waiting[cargo_index];
    01437       if (cargo_waiting == 0) continue;
    01438
    01439       i->produced_cargo_waiting[0] = min(i->produced_cargo_waiting[0] + (cargo_waiting * indspec->input_cargo_multiplier[cargo_index][0] / 256), 0xFFFF);
    01440       i->produced_cargo_waiting[1] = min(i->produced_cargo_waiting[1] + (cargo_waiting * indspec->input_cargo_multiplier[cargo_index][1] / 256), 0xFFFF);
    01441
    01442       i->incoming_cargo_waiting[cargo_index] = 0;
    01443     }
    01444   }
    01445
    01446   TriggerIndustry(i, INDUSTRY_TRIGGER_RECEIVED_CARGO);
    01447   StartStopIndustryTileAnimation(i, IAT_INDUSTRY_RECEIVED_CARGO);
    01448 }
    01449
    01455 CargoPayment::CargoPayment(Vehicle *front) :
    01456   front(front),
    01457   current_station(front->last_station_visited)
    01458 {
    01459 }
    01460
    01461 CargoPayment::~CargoPayment()
    01462 {
    01463   if (this->CleaningPool()) return;
    01464
    01465   this->front->cargo_payment = NULL;
    01466
    01467   if (this->visual_profit == 0) {
    01468     this->front = NULL;
    01469     return;
    01470   }
    01471
    01472   CompanyID old_company = _current_company;
    01473   _current_company = this->front->owner;
    01474
    01475   SubtractMoneyFromCompany(CommandCost(this->front->GetExpenseType(true), -this->route_profit));
    01476   this->front->profit_this_year += this->visual_profit << 8;
    01477
    01478   if (this->route_profit != 0) {
    01479     if (IsLocalCompany() && !PlayVehicleSound(this->front, VSE_LOAD_UNLOAD)) {
    01480       SndPlayVehicleFx(SND_14_CASHTILL, this->front);
    01481     }
    01482
    01483     ShowCostOrIncomeAnimation(this->front->x_pos, this->front->y_pos, this->front->z_pos, -this->visual_profit);
    01484   } else {
    01485     ShowFeederIncomeAnimation(this->front->x_pos, this->front->y_pos, this->front->z_pos, this->visual_profit);
    01486   }
    01487
    01488   _current_company = old_company;
    01489
    01490   this->front = NULL;
    01491 }
    01492
    01498 void CargoPayment::PayFinalDelivery(CargoPacket *cp, uint count)
    01499 {
    01500   if (this->owner == NULL) {
    01501     this->owner = GetCompany(this->front->owner);
    01502   }
    01503
    01504   /* Handle end of route payment */
    01505   Money profit = DeliverGoods(count, this->ct, cp->source, this->current_station, cp->source_xy, cp->days_in_transit, this->owner);
    01506   this->route_profit += profit;
    01507
    01508   /* The vehicle's profit is whatever route profit there is minus feeder shares. */
    01509   this->visual_profit += profit - cp->feeder_share;
    01510 }
    01511
    01517 void CargoPayment::PayTransfer(CargoPacket *cp, uint count)
    01518 {
    01519   Money profit = GetTransportedGoodsIncome(
    01520     count,
    01521     /* pay transfer vehicle for only the part of transfer it has done: ie. cargo_loaded_at_xy to here */
    01522     DistanceManhattan(cp->loaded_at_xy, GetStation(this->current_station)->xy),
    01523     cp->days_in_transit,
    01524     this->ct);
    01525
    01526   this->visual_profit += profit; // accumulate transfer profits for whole vehicle
    01527   cp->feeder_share    += profit; // account for the (virtual) profit already made for the cargo packet
    01528 }
    01529
    01534 void PrepareUnload(Vehicle *front_v)
    01535 {
    01536   /* At this moment loading cannot be finished */
    01537   ClrBit(front_v->vehicle_flags, VF_LOADING_FINISHED);
    01538
    01539   /* Start unloading in at the first possible moment */
    01540   front_v->load_unload_time_rem = 1;
    01541
    01542   if ((front_v->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0) {
    01543     for (Vehicle *v = front_v; v != NULL; v = v->Next()) {
    01544       if (v->cargo_cap > 0 && !v->cargo.Empty()) {
    01545         SetBit(v->vehicle_flags, VF_CARGO_UNLOADING);
    01546       }
    01547     }
    01548   }
    01549
    01550   assert(front_v->cargo_payment == NULL);
    01551   front_v->cargo_payment = new CargoPayment(front_v);
    01552 }
    01553
    01562 static void LoadUnloadVehicle(Vehicle *v, int *cargo_left)
    01563 {
    01564   assert(v->current_order.IsType(OT_LOADING));
    01565
    01566   assert(v->load_unload_time_rem != 0);
    01567
    01568   /* We have not waited enough time till the next round of loading/unloading */
    01569   if (--v->load_unload_time_rem != 0) {
    01570     if (_settings_game.order.improved_load && (v->current_order.GetLoadType() & OLFB_FULL_LOAD)) {
    01571       /* 'Reserve' this cargo for this vehicle, because we were first. */
    01572       for (; v != NULL; v = v->Next()) {
    01573         int cap_left = v->cargo_cap - v->cargo.Count();
    01574         if (cap_left > 0) cargo_left[v->cargo_type] -= cap_left;
    01575       }
    01576     }
    01577     return;
    01578   }
    01579
    01580   StationID last_visited = v->last_station_visited;
    01581   Station *st = GetStation(last_visited);
    01582
    01583   if (v->type == VEH_TRAIN && (!IsTileType(v->tile, MP_STATION) || GetStationIndex(v->tile) != st->index)) {
    01584     /* The train reversed in the station. Take the "easy" way
    01585      * out and let the train just leave as it always did. */
    01586     SetBit(v->vehicle_flags, VF_LOADING_FINISHED);
    01587     v->load_unload_time_rem = 1;
    01588     return;
    01589   }
    01590
    01591   int unloading_time = 0;
    01592   Vehicle *u = v;
    01593   int result = 0;
    01594
    01595   bool completely_emptied = true;
    01596   bool anything_unloaded = false;
    01597   bool anything_loaded   = false;
    01598   uint32 cargo_not_full  = 0;
    01599   uint32 cargo_full      = 0;
    01600
    01601   v->cur_speed = 0;
    01602
    01603   CargoPayment *payment = v->cargo_payment;
    01604
    01605   for (; v != NULL; v = v->Next()) {
    01606     if (v->cargo_cap == 0) continue;
    01607
    01608     byte load_amount = EngInfo(v->engine_type)->load_amount;
    01609
    01610     /* The default loadamount for mail is 1/4 of the load amount for passengers */
    01611     if (v->type == VEH_AIRCRAFT && !IsNormalAircraft(v)) load_amount = (load_amount + 3) / 4;
    01612
    01613     if (_settings_game.order.gradual_loading && HasBit(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_LOAD_AMOUNT)) {
    01614       uint16 cb_load_amount = GetVehicleCallback(CBID_VEHICLE_LOAD_AMOUNT, 0, 0, v->engine_type, v);
    01615       if (cb_load_amount != CALLBACK_FAILED && GB(cb_load_amount, 0, 8) != 0) load_amount = GB(cb_load_amount, 0, 8);
    01616     }
    01617
    01618     GoodsEntry *ge = &st->goods[v->cargo_type];
    01619
    01620     if (HasBit(v->vehicle_flags, VF_CARGO_UNLOADING) && (u->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0) {
    01621       uint cargo_count = v->cargo.Count();
    01622       uint amount_unloaded = _settings_game.order.gradual_loading ? min(cargo_count, load_amount) : cargo_count;
    01623       bool remaining = false; // Are there cargo entities in this vehicle that can still be unloaded here?
    01624       bool accepted  = false; // Is the cargo accepted by the station?
    01625
    01626       payment->SetCargo(v->cargo_type);
    01627
    01628       if (HasBit(ge->acceptance_pickup, GoodsEntry::ACCEPTANCE) && !(u->current_order.GetUnloadType() & OUFB_TRANSFER)) {
    01629         /* The cargo has reached it's final destination, the packets may now be destroyed */
    01630         remaining = v->cargo.MoveTo(NULL, amount_unloaded, CargoList::MTA_FINAL_DELIVERY, payment, last_visited);
    01631
    01632         result |= 1;
    01633         accepted = true;
    01634       }
    01635
    01636       /* The !accepted || v->cargo.Count == cargo_count clause is there
    01637        * to make it possible to force unload vehicles at the station where
    01638        * they were loaded, but to not force unload the vehicle when the
    01639        * station is still accepting the cargo in the vehicle. It doesn't
    01640        * accept cargo that was loaded at the same station. */
    01641       if (u->current_order.GetUnloadType() & (OUFB_UNLOAD | OUFB_TRANSFER) && (!accepted || v->cargo.Count() == cargo_count)) {
    01642         remaining = v->cargo.MoveTo(&ge->cargo, amount_unloaded, u->current_order.GetUnloadType() & OUFB_TRANSFER ? CargoList::MTA_TRANSFER : CargoList::MTA_UNLOAD, payment);
    01643         SetBit(ge->acceptance_pickup, GoodsEntry::PICKUP);
    01644
    01645         result |= 2;
    01646       } else if (!accepted) {
    01647         /* The order changed while unloading (unset unload/transfer) or the
    01648          * station does not accept our goods. */
    01649         ClrBit(v->vehicle_flags, VF_CARGO_UNLOADING);
    01650
    01651         /* Say we loaded something, otherwise we'll think we didn't unload
    01652          * something and we didn't load something, so we must be finished
    01653          * at this station. Setting the unloaded means that we will get a
    01654          * retry for loading in the next cycle. */
    01655         anything_unloaded = true;
    01656         continue;
    01657       }
    01658
    01659       /* Deliver goods to the station */
    01660       st->time_since_unload = 0;
    01661
    01662       unloading_time += amount_unloaded;
    01663
    01664       anything_unloaded = true;
    01665       if (_settings_game.order.gradual_loading && remaining) {
    01666         completely_emptied = false;
    01667       } else {
    01668         /* We have finished unloading (cargo count == 0) */
    01669         ClrBit(v->vehicle_flags, VF_CARGO_UNLOADING);
    01670       }
    01671
    01672       continue;
    01673     }
    01674
    01675     /* Do not pick up goods when we have no-load set. */
    01676     if (u->current_order.GetLoadType() & OLFB_NO_LOAD) continue;
    01677
    01678     /* update stats */
    01679     int t;
    01680     switch (u->type) {
    01681       case VEH_TRAIN:    t = u->u.rail.cached_max_speed; break;
    01682       case VEH_ROAD:     t = u->max_speed / 2;           break;
    01683       case VEH_SHIP:     t = u->max_speed;               break;
    01684       case VEH_AIRCRAFT: t = u->max_speed * 10 / 129;    break; // convert to old units
    01685       default: NOT_REACHED();
    01686     }
    01687
    01688     /* if last speed is 0, we treat that as if no vehicle has ever visited the station. */
    01689     ge->last_speed = min(t, 255);
    01690     ge->last_age = _cur_year - u->build_year;
    01691     ge->days_since_pickup = 0;
    01692
    01693     /* If there's goods waiting at the station, and the vehicle
    01694      * has capacity for it, load it on the vehicle. */
    01695     int cap_left = v->cargo_cap - v->cargo.Count();
    01696     if (!ge->cargo.Empty() && cap_left > 0) {
    01697       uint cap = cap_left;
    01698       uint count = ge->cargo.Count();
    01699
    01700       /* Skip loading this vehicle if another train/vehicle is already handling
    01701        * the same cargo type at this station */
    01702       if (_settings_game.order.improved_load && cargo_left[v->cargo_type] <= 0) {
    01703         SetBit(cargo_not_full, v->cargo_type);
    01704         continue;
    01705       }
    01706
    01707       if (cap > count) cap = count;
    01708       if (_settings_game.order.gradual_loading) cap = min(cap, load_amount);
    01709       if (_settings_game.order.improved_load) {
    01710         /* Don't load stuff that is already 'reserved' for other vehicles */
    01711         cap = min((uint)cargo_left[v->cargo_type], cap);
    01712         cargo_left[v->cargo_type] -= cap;
    01713       }
    01714
    01715       if (v->cargo.Empty()) TriggerVehicle(v, VEHICLE_TRIGGER_NEW_CARGO);
    01716
    01717       /* TODO: Regarding this, when we do gradual loading, we
    01718        * should first unload all vehicles and then start
    01719        * loading them. Since this will cause
    01720        * VEHICLE_TRIGGER_EMPTY to be called at the time when
    01721        * the whole vehicle chain is really totally empty, the
    01722        * completely_emptied assignment can then be safely
    01723        * removed; that's how TTDPatch behaves too. --pasky */
    01724       completely_emptied = false;
    01725       anything_loaded = true;
    01726
    01727       ge->cargo.MoveTo(&v->cargo, cap, CargoList::MTA_CARGO_LOAD, NULL, st->xy);
    01728
    01729       st->time_since_load = 0;
    01730       st->last_vehicle_type = v->type;
    01731
    01732       StationAnimationTrigger(st, st->xy, STAT_ANIM_CARGO_TAKEN, v->cargo_type);
    01733
    01734       unloading_time += cap;
    01735
    01736       result |= 2;
    01737     }
    01738
    01739     if (v->cargo.Count() >= v->cargo_cap) {
    01740       SetBit(cargo_full, v->cargo_type);
    01741     } else {
    01742       SetBit(cargo_not_full, v->cargo_type);
    01743     }
    01744   }
    01745
    01746   /* Only set completly_emptied, if we just unloaded all remaining cargo */
    01747   completely_emptied &= anything_unloaded;
    01748
    01749   /* We update these variables here, so gradual loading still fills
    01750    * all wagons at the same time instead of using the same 'improved'
    01751    * loading algorithm for the wagons (only fill wagon when there is
    01752    * enough to fill the previous wagons) */
    01753   if (_settings_game.order.improved_load && (u->current_order.GetLoadType() & OLFB_FULL_LOAD)) {
    01754     /* Update left cargo */
    01755     for (v = u; v != NULL; v = v->Next()) {
    01756       int cap_left = v->cargo_cap - v->cargo.Count();
    01757       if (cap_left > 0) cargo_left[v->cargo_type] -= cap_left;
    01758     }
    01759   }
    01760
    01761   v = u;
    01762
    01763   if (!anything_unloaded) delete payment;
    01764
    01765   if (anything_loaded || anything_unloaded) {
    01766     if (_settings_game.order.gradual_loading) {
    01767       /* The time it takes to load one 'slice' of cargo or passengers depends
    01768        * on the vehicle type - the values here are those found in TTDPatch */
    01769       const uint gradual_loading_wait_time[] = { 40, 20, 10, 20 };
    01770
    01771       unloading_time = gradual_loading_wait_time[v->type];
    01772     }
    01773   } else {
    01774     bool finished_loading = true;
    01775     if (v->current_order.GetLoadType() & OLFB_FULL_LOAD) {
    01776       if (v->current_order.GetLoadType() == OLF_FULL_LOAD_ANY) {
    01777         /* if the aircraft carries passengers and is NOT full, then
    01778          * continue loading, no matter how much mail is in */
    01779         if ((v->type == VEH_AIRCRAFT && IsCargoInClass(v->cargo_type, CC_PASSENGERS) && v->cargo_cap > v->cargo.Count()) ||
    01780             (cargo_not_full && (cargo_full & ~cargo_not_full) == 0)) { // There are stull non-full cargos
    01781           finished_loading = false;
    01782         }
    01783       } else if (cargo_not_full != 0) {
    01784         finished_loading = false;
    01785       }
    01786     }
    01787     unloading_time = 20;
    01788
    01789     SB(v->vehicle_flags, VF_LOADING_FINISHED, 1, finished_loading);
    01790   }
    01791
    01792   if (v->type == VEH_TRAIN) {
    01793     /* Each platform tile is worth 2 rail vehicles. */
    01794     int overhang = v->u.rail.cached_total_length - st->GetPlatformLength(v->tile) * TILE_SIZE;
    01795     if (overhang > 0) {
    01796       unloading_time <<= 1;
    01797       unloading_time += (overhang * unloading_time) / 8;
    01798     }
    01799   }
    01800
    01801   /* Calculate the loading indicator fill percent and display
    01802    * In the Game Menu do not display indicators
    01803    * If _settings_client.gui.loading_indicators == 2, show indicators (bool can be promoted to int as 0 or 1 - results in 2 > 0,1 )
    01804    * if _settings_client.gui.loading_indicators == 1, _local_company must be the owner or must be a spectator to show ind., so 1 > 0
    01805    * if _settings_client.gui.loading_indicators == 0, do not display indicators ... 0 is never greater than anything
    01806    */
    01807   if (_game_mode != GM_MENU && (_settings_client.gui.loading_indicators > (uint)(v->owner != _local_company && _local_company != COMPANY_SPECTATOR))) {
    01808     StringID percent_up_down = STR_NULL;
    01809     int percent = CalcPercentVehicleFilled(v, &percent_up_down);
    01810     if (v->fill_percent_te_id == INVALID_TE_ID) {
    01811       v->fill_percent_te_id = ShowFillingPercent(v->x_pos, v->y_pos, v->z_pos + 20, percent, percent_up_down);
    01812     } else {
    01813       UpdateFillingPercent(v->fill_percent_te_id, percent, percent_up_down);
    01814     }
    01815   }
    01816
    01817   /* Always wait at least 1, otherwise we'll wait 'infinitively' long. */
    01818   v->load_unload_time_rem = max(1, unloading_time);
    01819
    01820   if (completely_emptied) {
    01821     TriggerVehicle(v, VEHICLE_TRIGGER_EMPTY);
    01822   }
    01823
    01824   if (result != 0) {
    01825     InvalidateWindow(GetWindowClassForVehicleType(v->type), v->owner);
    01826     InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
    01827
    01828     st->MarkTilesDirty(true);
    01829     v->MarkDirty();
    01830
    01831     if (result & 2) InvalidateWindow(WC_STATION_VIEW, last_visited);
    01832   }
    01833 }
    01834
    01840 void LoadUnloadStation(Station *st)
    01841 {
    01842   /* No vehicle is here... */
    01843   if (st->loading_vehicles.empty()) return;
    01844
    01845   int cargo_left[NUM_CARGO];
    01846
    01847   for (uint i = 0; i < NUM_CARGO; i++) cargo_left[i] = st->goods[i].cargo.Count();
    01848
    01849   std::list<Vehicle *>::iterator iter;
    01850   for (iter = st->loading_vehicles.begin(); iter != st->loading_vehicles.end(); ++iter) {
    01851     Vehicle *v = *iter;
    01852     if (!(v->vehstatus & (VS_STOPPED | VS_CRASHED))) LoadUnloadVehicle(v, cargo_left);
    01853   }
    01854
    01855   /* Call the production machinery of industries */
    01856   const Industry * const *isend = _cargo_delivery_destinations.End();
    01857   for (Industry **iid = _cargo_delivery_destinations.Begin(); iid != isend; iid++) {
    01858     TriggerIndustryProduction(*iid);
    01859   }
    01860   _cargo_delivery_destinations.Clear();
    01861 }
    01862
    01863 void CompaniesMonthlyLoop()
    01864 {
    01865   CompaniesGenStatistics();
    01866   if (_settings_game.economy.inflation) AddInflation();
    01867   CompaniesPayInterest();
    01868   /* Reset the _current_company flag */
    01869   _current_company = OWNER_NONE;
    01870   HandleEconomyFluctuations();
    01871   SubsidyMonthlyHandler();
    01872 }
    01873
    01874 static void DoAcquireCompany(Company *c)
    01875 {
    01876   Company *owner;
    01877   int i;
    01878   Money value;
    01879   CompanyID ci = c->index;
    01880
    01881   CompanyNewsInformation *cni = MallocT<CompanyNewsInformation>(1);
    01882   cni->FillData(c, GetCompany(_current_company));
    01883
    01884   SetDParam(0, STR_7059_TRANSPORT_COMPANY_MERGER);
    01885   SetDParam(1, c->bankrupt_value == 0 ? STR_707F_HAS_BEEN_TAKEN_OVER_BY : STR_705A_HAS_BEEN_SOLD_TO_FOR);
    01886   SetDParamStr(2, cni->company_name);
    01887   SetDParamStr(3, cni->other_company_name);
    01888   SetDParam(4, c->bankrupt_value);
    01889   AddNewsItem(STR_02B6, NS_COMPANY_MERGER, 0, 0, cni);
    01890   AI::BroadcastNewEvent(new AIEventCompanyMerger(ci, _current_company));
    01891
    01892   /* original code does this a little bit differently */
    01893   ChangeNetworkOwner(ci, _current_company);
    01894   ChangeOwnershipOfCompanyItems(ci, _current_company);
    01895
    01896   if (c->bankrupt_value == 0) {
    01897     owner = GetCompany(_current_company);
    01898     owner->current_loan += c->current_loan;
    01899   }
    01900
    01901   value = CalculateCompanyValue(c) >> 2;
    01902   CompanyID old_company = _current_company;
    01903   for (i = 0; i != 4; i++) {
    01904     if (c->share_owners[i] != COMPANY_SPECTATOR) {
    01905       _current_company = c->share_owners[i];
    01906       SubtractMoneyFromCompany(CommandCost(EXPENSES_OTHER, -value));
    01907     }
    01908   }
    01909   _current_company = old_company;
    01910
    01911   if (!IsHumanCompany(c->index)) AI::Stop(c->index);
    01912
    01913   DeleteCompanyWindows(ci);
    01914   InvalidateWindowClassesData(WC_TRAINS_LIST, 0);
    01915   InvalidateWindowClassesData(WC_SHIPS_LIST, 0);
    01916   InvalidateWindowClassesData(WC_ROADVEH_LIST, 0);
    01917   InvalidateWindowClassesData(WC_AIRCRAFT_LIST, 0);
    01918
    01919   delete c;
    01920 }
    01921
    01922 extern int GetAmountOwnedBy(const Company *c, Owner owner);
    01923
    01930 CommandCost CmdBuyShareInCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
    01931 {
    01932   CommandCost cost(EXPENSES_OTHER);
    01933
    01934   /* Check if buying shares is allowed (protection against modified clients)
    01935    * Cannot buy own shares */
    01936   if (!IsValidCompanyID((CompanyID)p1) || !_settings_game.economy.allow_shares || _current_company == (CompanyID)p1) return CMD_ERROR;
    01937
    01938   Company *c = GetCompany((CompanyID)p1);
    01939
    01940   /* Protect new companies from hostile takeovers */
    01941   if (_cur_year - c->inaugurated_year < 6) return_cmd_error(STR_PROTECTED);
    01942
    01943   /* Those lines are here for network-protection (clients can be slow) */
    01944   if (GetAmountOwnedBy(c, COMPANY_SPECTATOR) == 0) return cost;
    01945
    01946   /* We can not buy out a real company (temporarily). TODO: well, enable it obviously */
    01947   if (GetAmountOwnedBy(c, COMPANY_SPECTATOR) == 1 && !c->is_ai) return cost;
    01948
    01949   cost.AddCost(CalculateCompanyValue(c) >> 2);
    01950   if (flags & DC_EXEC) {
    01951     OwnerByte *b = c->share_owners;
    01952     int i;
    01953
    01954     while (*b != COMPANY_SPECTATOR) b++; // share owners is guaranteed to contain at least one COMPANY_SPECTATOR
    01955     *b = _current_company;
    01956
    01957     for (i = 0; c->share_owners[i] == _current_company;) {
    01958       if (++i == 4) {
    01959         c->bankrupt_value = 0;
    01960         DoAcquireCompany(c);
    01961         break;
    01962       }
    01963     }
    01964     InvalidateWindow(WC_COMPANY, p1);
    01965   }
    01966   return cost;
    01967 }
    01968
    01975 CommandCost CmdSellShareInCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
    01976 {
    01977   /* Check if selling shares is allowed (protection against modified clients)
    01978    * Cannot sell own shares */
    01979   if (!IsValidCompanyID((CompanyID)p1) || !_settings_game.economy.allow_shares || _current_company == (CompanyID)p1) return CMD_ERROR;
    01980
    01981   Company *c = GetCompany((CompanyID)p1);
    01982
    01983   /* Those lines are here for network-protection (clients can be slow) */
    01984   if (GetAmountOwnedBy(c, _current_company) == 0) return CommandCost();
    01985
    01986   /* adjust it a little to make it less profitable to sell and buy */
    01987   Money cost = CalculateCompanyValue(c) >> 2;
    01988   cost = -(cost - (cost >> 7));
    01989
    01990   if (flags & DC_EXEC) {
    01991     OwnerByte *b = c->share_owners;
    01992     while (*b != _current_company) b++; // share owners is guaranteed to contain company
    01993     *b = COMPANY_SPECTATOR;
    01994     InvalidateWindow(WC_COMPANY, p1);
    01995   }
    01996   return CommandCost(EXPENSES_OTHER, cost);
    01997 }
    01998
    02008 CommandCost CmdBuyCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
    02009 {
    02010   CompanyID cid = (CompanyID)p1;
    02011
    02012   /* Disable takeovers in multiplayer games */
    02013   if (!IsValidCompanyID(cid) || _networking) return CMD_ERROR;
    02014
    02015   /* Do not allow companies to take over themselves */
    02016   if (cid == _current_company) return CMD_ERROR;
    02017
    02018   Company *c = GetCompany(cid);
    02019
    02020   if (!c->is_ai) return CMD_ERROR;
    02021
    02022   if (flags & DC_EXEC) {
    02023     DoAcquireCompany(c);
    02024   }
    02025   return CommandCost(EXPENSES_OTHER, c->bankrupt_value);
    02026 }