# economy.cpp

Go to the documentation of this file.

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