192
179
_score_part[owner][SCORE_STATIONS] = num;
195
/* Generate statistics depending on recent income statistics */
182
/* Generate statistics depending on recent income statistics */
197
int numec = min(p->num_valid_stat_ent, 12);
184
int numec = min(c->num_valid_stat_ent, 12);
198
185
if (numec != 0) {
199
const PlayerEconomyEntry *pee = p->old_economy;
200
Money min_income = pee->income + pee->expenses;
201
Money max_income = pee->income + pee->expenses;
186
const CompanyEconomyEntry *cee = c->old_economy;
187
Money min_income = cee->income + cee->expenses;
188
Money max_income = cee->income + cee->expenses;
204
min_income = min(min_income, pee->income + pee->expenses);
205
max_income = max(max_income, pee->income + pee->expenses);
206
} while (++pee,--numec);
191
min_income = min(min_income, cee->income + cee->expenses);
192
max_income = max(max_income, cee->income + cee->expenses);
193
} while (++cee, --numec);
195
if (min_income > 0) {
209
196
_score_part[owner][SCORE_MIN_INCOME] = ClampToI32(min_income);
211
199
_score_part[owner][SCORE_MAX_INCOME] = ClampToI32(max_income);
215
/* Generate score depending on amount of transported cargo */
203
/* Generate score depending on amount of transported cargo */
217
const PlayerEconomyEntry* pee;
205
const CompanyEconomyEntry *cee;
219
207
uint32 total_delivered;
221
numec = min(p->num_valid_stat_ent, 4);
209
numec = min(c->num_valid_stat_ent, 4);
222
210
if (numec != 0) {
223
pee = p->old_economy;
211
cee = c->old_economy;
224
212
total_delivered = 0;
226
total_delivered += pee->delivered_cargo;
227
} while (++pee,--numec);
214
total_delivered += cee->delivered_cargo;
215
} while (++cee, --numec);
229
217
_score_part[owner][SCORE_DELIVERED] = total_delivered;
233
/* Generate score for variety of cargo */
221
/* Generate score for variety of cargo */
235
uint num = CountBits(p->cargo_types);
223
uint num = CountBits(c->cargo_types);
236
224
_score_part[owner][SCORE_CARGO] = num;
237
if (update) p->cargo_types = 0;
225
if (update) c->cargo_types = 0;
240
/* Generate score for player money */
228
/* Generate score for company's money */
242
if (p->player_money > 0) {
243
_score_part[owner][SCORE_MONEY] = ClampToI32(p->player_money);
231
_score_part[owner][SCORE_MONEY] = ClampToI32(c->money);
247
/* Generate score for loan */
235
/* Generate score for loan */
249
_score_part[owner][SCORE_LOAN] = ClampToI32(_score_info[SCORE_LOAN].needed - p->current_loan);
237
_score_part[owner][SCORE_LOAN] = ClampToI32(_score_info[SCORE_LOAN].needed - c->current_loan);
252
240
/* Now we calculate the score for each item.. */
273
p->old_economy[0].performance_history = score;
274
UpdateCompanyHQ(p, score);
275
p->old_economy[0].company_value = CalculateCompanyValue(p);
261
c->old_economy[0].performance_history = score;
262
UpdateCompanyHQ(c, score);
263
c->old_economy[0].company_value = CalculateCompanyValue(c);
278
266
InvalidateWindow(WC_PERFORMANCE_DETAIL, 0);
282
/* use PLAYER_SPECTATOR as new_player to delete the player. */
283
void ChangeOwnershipOfPlayerItems(PlayerID old_player, PlayerID new_player)
270
/* use INVALID_OWNER as new_owner to delete the company. */
271
void ChangeOwnershipOfCompanyItems(Owner old_owner, Owner new_owner)
286
PlayerID old = _current_player;
274
CompanyID old = _current_company;
288
assert(old_player != new_player);
276
assert(old_owner != new_owner);
294
/* See if the old_player had shares in other companies */
295
_current_player = old_player;
297
if (!p->is_active) continue;
282
/* See if the old_owner had shares in other companies */
283
_current_company = old_owner;
284
FOR_ALL_COMPANIES(c) {
298
285
for (i = 0; i < 4; i++) {
299
if (p->share_owners[i] == old_player) {
286
if (c->share_owners[i] == old_owner) {
300
287
/* Sell his shares */
301
CommandCost res = DoCommand(0, p->index, 0, DC_EXEC, CMD_SELL_SHARE_IN_COMPANY);
288
CommandCost res = DoCommand(0, c->index, 0, DC_EXEC, CMD_SELL_SHARE_IN_COMPANY);
302
289
/* Because we are in a DoCommand, we can't just execute an other one and
303
290
* expect the money to be removed. We need to do it ourself! */
304
SubtractMoneyFromPlayer(res);
291
SubtractMoneyFromCompany(res);
309
296
/* Sell all the shares that people have on this company */
310
p = GetPlayer(old_player);
297
c = GetCompany(old_owner);
311
298
for (i = 0; i < 4; i++) {
312
_current_player = p->share_owners[i];
313
if (_current_player != PLAYER_SPECTATOR) {
299
_current_company = c->share_owners[i];
300
if (_current_company != INVALID_OWNER) {
314
301
/* Sell the shares */
315
CommandCost res = DoCommand(0, old_player, 0, DC_EXEC, CMD_SELL_SHARE_IN_COMPANY);
302
CommandCost res = DoCommand(0, old_owner, 0, DC_EXEC, CMD_SELL_SHARE_IN_COMPANY);
316
303
/* Because we are in a DoCommand, we can't just execute an other one and
317
304
* expect the money to be removed. We need to do it ourself! */
318
SubtractMoneyFromPlayer(res);
305
SubtractMoneyFromCompany(res);
323
_current_player = old_player;
310
_current_company = old_owner;
325
/* Temporarily increase the player's money, to be sure that
312
/* Temporarily increase the company's money, to be sure that
326
313
* removing his/her property doesn't fail because of lack of money.
327
314
* Not too drastically though, because it could overflow */
328
if (new_player == PLAYER_SPECTATOR) {
329
GetPlayer(old_player)->player_money = MAX_UVALUE(uint64) >> 2; // jackpot ;p
315
if (new_owner == INVALID_OWNER) {
316
GetCompany(old_owner)->money = UINT64_MAX >> 2; // jackpot ;p
332
if (new_player == PLAYER_SPECTATOR) {
319
if (new_owner == INVALID_OWNER) {
335
322
for (s = _subsidies; s != endof(_subsidies); s++) {
336
323
if (s->cargo_type != CT_INVALID && s->age >= 12) {
337
if (GetStation(s->to)->owner == old_player) s->cargo_type = CT_INVALID;
324
if (GetStation(s->to)->owner == old_owner) s->cargo_type = CT_INVALID;
342
329
/* Take care of rating in towns */
343
330
FOR_ALL_TOWNS(t) {
344
/* If a player takes over, give the ratings to that player. */
345
if (new_player != PLAYER_SPECTATOR) {
346
if (HasBit(t->have_ratings, old_player)) {
347
if (HasBit(t->have_ratings, new_player)) {
348
// use max of the two ratings.
349
t->ratings[new_player] = max(t->ratings[new_player], t->ratings[old_player]);
331
/* If a company takes over, give the ratings to that company. */
332
if (new_owner != INVALID_OWNER) {
333
if (HasBit(t->have_ratings, old_owner)) {
334
if (HasBit(t->have_ratings, new_owner)) {
335
/* use max of the two ratings. */
336
t->ratings[new_owner] = max(t->ratings[new_owner], t->ratings[old_owner]);
351
SetBit(t->have_ratings, new_player);
352
t->ratings[new_player] = t->ratings[old_player];
338
SetBit(t->have_ratings, new_owner);
339
t->ratings[new_owner] = t->ratings[old_owner];
357
/* Reset the ratings for the old player */
358
t->ratings[old_player] = 500;
359
ClrBit(t->have_ratings, old_player);
344
/* Reset the ratings for the old owner */
345
t->ratings[old_owner] = RATING_INITIAL;
346
ClrBit(t->have_ratings, old_owner);
366
int num_aircraft = 0;
350
FreeUnitIDGenerator unitidgen[] = {
351
FreeUnitIDGenerator(VEH_TRAIN, new_owner), FreeUnitIDGenerator(VEH_ROAD, new_owner),
352
FreeUnitIDGenerator(VEH_SHIP, new_owner), FreeUnitIDGenerator(VEH_AIRCRAFT, new_owner)
369
/* Determine Ids for the new vehicles */
370
FOR_ALL_VEHICLES(v) {
371
if (v->owner == new_player) {
373
case VEH_TRAIN: if (IsFrontEngine(v)) num_train++; break;
374
case VEH_ROAD: if (IsRoadVehFront(v)) num_road++; break;
375
case VEH_SHIP: num_ship++; break;
376
case VEH_AIRCRAFT: if (IsNormalAircraft(v)) num_aircraft++; break;
382
FOR_ALL_VEHICLES(v) {
383
if (v->owner == old_player && IsInsideMM(v->type, VEH_TRAIN, VEH_AIRCRAFT + 1)) {
384
if (new_player == PLAYER_SPECTATOR) {
385
DeleteWindowById(WC_VEHICLE_VIEW, v->index);
386
DeleteWindowById(WC_VEHICLE_DETAILS, v->index);
387
DeleteWindowById(WC_VEHICLE_ORDERS, v->index);
389
if (v->IsPrimaryVehicle() || (v->type == VEH_TRAIN && IsFreeWagon(v))) {
391
default: NOT_REACHED();
396
Vehicle *next = GetNextVehicle(u);
408
DeleteVehicleChain(v);
356
FOR_ALL_VEHICLES(v) {
357
if (v->owner == old_owner && IsCompanyBuildableVehicleType(v->type)) {
358
if (new_owner == INVALID_OWNER) {
359
if (v->Previous() == NULL) delete v;
413
v->owner = new_player;
414
v->colormap = PAL_NONE;
415
v->group_id = DEFAULT_GROUP;
416
if (IsEngineCountable(v)) GetPlayer(new_player)->num_engines[v->engine_type]++;
418
case VEH_TRAIN: if (IsFrontEngine(v)) v->unitnumber = ++num_train; break;
419
case VEH_ROAD: if (IsRoadVehFront(v)) v->unitnumber = ++num_road; break;
420
case VEH_SHIP: v->unitnumber = ++num_ship; break;
421
case VEH_AIRCRAFT: if (IsNormalAircraft(v)) v->unitnumber = ++num_aircraft; break;
422
default: NOT_REACHED();
361
v->owner = new_owner;
362
v->colourmap = PAL_NONE;
363
if (IsEngineCountable(v)) GetCompany(new_owner)->num_engines[v->engine_type]++;
364
if (v->IsPrimaryVehicle()) v->unitnumber = unitidgen[v->type].NextID();
457
398
UpdateSignalsInBuffer();
401
/* convert owner of stations (including deleted ones, but excluding buoys) */
403
FOR_ALL_STATIONS(st) {
404
if (st->owner == old_owner) {
405
/* if a company goes bankrupt, set owner to OWNER_NONE so the sign doesn't disappear immediately
406
* also, drawing station window would cause reading invalid company's colour */
407
st->owner = new_owner == INVALID_OWNER ? OWNER_NONE : new_owner;
411
/* do the same for waypoints (we need to do this here so deleted waypoints are converted too) */
413
FOR_ALL_WAYPOINTS(wp) {
414
if (wp->owner == old_owner) {
415
wp->owner = new_owner == INVALID_OWNER ? OWNER_NONE : new_owner;
460
419
/* In all cases clear replace engine rules.
461
420
* Even if it was copied, it could interfere with new owner's rules */
462
RemoveAllEngineReplacementForPlayer(GetPlayer(old_player));
421
RemoveAllEngineReplacementForCompany(GetCompany(old_owner));
464
if (new_player == PLAYER_SPECTATOR) {
465
RemoveAllGroupsForPlayer(old_player);
423
if (new_owner == INVALID_OWNER) {
424
RemoveAllGroupsForCompany(old_owner);
468
427
FOR_ALL_GROUPS(g) {
469
if (g->owner == old_player) g->owner = new_player;
428
if (g->owner == old_owner) g->owner = new_owner;
474
433
FOR_ALL_SIGNS(si) {
475
if (si->owner == old_player) si->owner = new_player == PLAYER_SPECTATOR ? OWNER_NONE : new_player;
434
if (si->owner == old_owner) si->owner = new_owner == INVALID_OWNER ? OWNER_NONE : new_owner;
478
/* Change color of existing windows */
479
if (new_player != PLAYER_SPECTATOR) ChangeWindowOwner(old_player, new_player);
437
/* Change colour of existing windows */
438
if (new_owner != INVALID_OWNER) ChangeWindowOwner(old_owner, new_owner);
481
_current_player = old;
440
_current_company = old;
483
442
MarkWholeScreenDirty();
486
static void ChangeNetworkOwner(PlayerID current_player, PlayerID new_player)
445
static void ChangeNetworkOwner(Owner current_owner, Owner new_owner)
488
447
#ifdef ENABLE_NETWORK
489
448
if (!_networking) return;
491
if (current_player == _local_player) {
492
_network_playas = new_player;
493
SetLocalPlayer(new_player);
450
if (current_owner == _local_company) {
451
_network_playas = new_owner;
452
SetLocalCompany(new_owner);
496
455
if (!_network_server) return;
498
/* The server has to handle all administrative issues, for example
499
* updating and notifying all clients of what has happened */
500
NetworkTCPSocketHandler *cs;
501
NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
503
/* The server has just changed from player */
504
if (current_player == ci->client_playas) {
505
ci->client_playas = new_player;
506
NetworkUpdateClientInfo(NETWORK_SERVER_INDEX);
509
/* Find all clients that were in control of this company, and mark them as new_player */
510
FOR_ALL_CLIENTS(cs) {
511
ci = DEREF_CLIENT_INFO(cs);
512
if (current_player == ci->client_playas) {
513
ci->client_playas = new_player;
514
NetworkUpdateClientInfo(ci->client_index);
457
NetworkServerChangeOwner(current_owner, new_owner);
517
458
#endif /* ENABLE_NETWORK */
520
static void PlayersCheckBankrupt(Player *p)
461
static void CompanyCheckBankrupt(Company *c)
524
/* If the player has money again, it does not go bankrupt */
525
if (p->player_money >= 0) {
526
p->quarters_of_bankrupcy = 0;
463
/* If the company has money again, it does not go bankrupt */
465
c->quarters_of_bankrupcy = 0;
530
p->quarters_of_bankrupcy++;
534
switch (p->quarters_of_bankrupcy) {
469
c->quarters_of_bankrupcy++;
471
CompanyNewsInformation *cni = MallocT<CompanyNewsInformation>(1);
474
switch (c->quarters_of_bankrupcy) {
536
AddNewsItem( (StringID)(owner | NB_BTROUBLE),
537
NEWS_FLAGS(NM_CALLBACK, 0, NT_COMPANY_INFO, DNC_BANKRUPCY),0,0);
481
SetDParam(0, STR_7056_TRANSPORT_COMPANY_IN_TROUBLE);
482
SetDParam(1, STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED);
483
SetDParamStr(2, cni->company_name);
484
AddNewsItem(STR_02B6, NS_COMPANY_TROUBLE, 0, 0, cni);
485
AI::BroadcastNewEvent(new AIEventCompanyInTrouble(c->index));
540
/* XXX - In multiplayer, should we ask other players if it wants to take
488
/* XXX - In multiplayer, should we ask other companies if it wants to take
541
489
over when it is a human company? -- TrueLight */
542
if (IsHumanPlayer(owner)) {
543
AddNewsItem( (StringID)(owner | NB_BTROUBLE),
544
NEWS_FLAGS(NM_CALLBACK, 0, NT_COMPANY_INFO, DNC_BANKRUPCY),0,0);
490
if (IsHumanCompany(c->index)) {
491
SetDParam(0, STR_7056_TRANSPORT_COMPANY_IN_TROUBLE);
492
SetDParam(1, STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED);
493
SetDParamStr(2, cni->company_name);
494
AddNewsItem(STR_02B6, NS_COMPANY_TROUBLE, 0, 0, cni);
548
498
/* Check if the company has any value.. if not, declare it bankrupt
550
Money val = CalculateCompanyValue(p);
500
Money val = CalculateCompanyValue(c);
552
p->bankrupt_value = val;
553
p->bankrupt_asked = 1 << owner; // Don't ask the owner
554
p->bankrupt_timeout = 0;
502
c->bankrupt_value = val;
503
c->bankrupt_asked = 1 << c->index; // Don't ask the owner
504
c->bankrupt_timeout = 0;
557
508
/* Else, falltrue to case 4... */
512
if (!_networking && _local_company == c->index) {
513
/* If we are in offline mode, leave the company playing. Eg. there
514
* is no THE-END, otherwise mark the client as spectator to make sure
515
* he/she is no long in control of this company. However... when you
516
* join another company (cheat) the "unowned" company can bankrupt. */
517
c->bankrupt_asked = MAX_UVALUE(CompanyMask);
518
c->bankrupt_timeout = 0x456;
560
522
/* Close everything the owner has open */
561
DeletePlayerWindows(owner);
523
DeleteCompanyWindows(c->index);
563
525
/* Show bankrupt news */
564
SetDParam(0, p->index);
565
AddNewsItem( (StringID)(owner | NB_BBANKRUPT), NEWS_FLAGS(NM_CALLBACK, 0, NT_COMPANY_INFO, DNC_BANKRUPCY),0,0);
567
if (IsHumanPlayer(owner)) {
568
/* XXX - If we are in offline mode, leave the player playing. Eg. there
569
* is no THE-END, otherwise mark the player as spectator to make sure
570
* he/she is no long in control of this company */
572
p->bankrupt_asked = 0xFF;
573
p->bankrupt_timeout = 0x456;
577
ChangeNetworkOwner(owner, PLAYER_SPECTATOR);
580
/* Remove the player */
581
ChangeOwnershipOfPlayerItems(owner, PLAYER_SPECTATOR);
582
/* Register the player as not-active */
583
p->is_active = false;
585
if (!IsHumanPlayer(owner) && (!_networking || _network_server) && _ai.enabled)
586
AI_PlayerDied(owner);
591
void DrawNewsBankrupcy(Window *w)
595
const NewsItem *ni = WP(w, news_d).ni;
596
Player *p = GetPlayer((PlayerID)GB(ni->string_id, 0, 4));
597
DrawPlayerFace(p->face, p->player_color, 2, 23);
598
GfxFillRect(3, 23, 3 + 91, 23 + 118, PALETTE_TO_STRUCT_GREY | (1 << USE_COLORTABLE));
600
SetDParam(0, p->index);
602
DrawStringMultiCenter(49, 148, STR_7058_PRESIDENT, 94);
604
switch (ni->string_id & 0xF0) {
606
DrawStringCentered(w->width >> 1, 1, STR_7056_TRANSPORT_COMPANY_IN_TROUBLE, TC_FROMSTRING);
608
SetDParam(0, p->index);
610
DrawStringMultiCenter(
611
((w->width - 101) >> 1) + 98,
613
STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED,
618
DrawStringCentered(w->width >> 1, 1, STR_7059_TRANSPORT_COMPANY_MERGER, TC_FROMSTRING);
619
SetDParam(0, ni->params[0]);
620
SetDParam(1, p->index);
621
SetDParam(2, ni->params[1]);
622
DrawStringMultiCenter(
623
((w->width - 101) >> 1) + 98,
625
ni->params[1] == 0 ? STR_707F_HAS_BEEN_TAKEN_OVER_BY : STR_705A_HAS_BEEN_SOLD_TO_FOR,
630
DrawStringCentered(w->width >> 1, 1, STR_705C_BANKRUPT, TC_FROMSTRING);
631
SetDParam(0, ni->params[0]);
632
DrawStringMultiCenter(
633
((w->width - 101) >> 1) + 98,
635
STR_705D_HAS_BEEN_CLOSED_DOWN_BY,
640
DrawStringCentered(w->width >> 1, 1, STR_705E_NEW_TRANSPORT_COMPANY_LAUNCHED, TC_FROMSTRING);
641
SetDParam(0, p->index);
642
SetDParam(1, ni->params[0]);
643
DrawStringMultiCenter(
644
((w->width - 101) >> 1) + 98,
646
STR_705F_STARTS_CONSTRUCTION_NEAR,
655
StringID GetNewsStringBankrupcy(const NewsItem *ni)
657
const Player *p = GetPlayer((PlayerID)GB(ni->string_id, 0, 4));
659
switch (ni->string_id & 0xF0) {
661
SetDParam(0, STR_7056_TRANSPORT_COMPANY_IN_TROUBLE);
662
SetDParam(1, STR_7057_WILL_BE_SOLD_OFF_OR_DECLARED);
663
SetDParam(2, p->index);
666
SetDParam(0, STR_7059_TRANSPORT_COMPANY_MERGER);
667
SetDParam(1, ni->params[1] == 0 ? STR_707F_HAS_BEEN_TAKEN_OVER_BY : STR_705A_HAS_BEEN_SOLD_TO_FOR);
668
SetDParam(2, ni->params[0]);
669
SetDParam(3, p->index);
670
SetDParam(4, ni->params[1]);
673
SetDParam(0, STR_705C_BANKRUPT);
674
SetDParam(1, STR_705D_HAS_BEEN_CLOSED_DOWN_BY);
675
SetDParam(2, ni->params[0]);
678
SetDParam(0, STR_705E_NEW_TRANSPORT_COMPANY_LAUNCHED);
679
SetDParam(1, STR_705F_STARTS_CONSTRUCTION_NEAR);
680
SetDParam(2, p->index);
681
SetDParam(3, ni->params[0]);
688
static void PlayersGenStatistics()
526
SetDParam(0, STR_705C_BANKRUPT);
527
SetDParam(1, STR_705D_HAS_BEEN_CLOSED_DOWN_BY);
528
SetDParamStr(2, cni->company_name);
529
AddNewsItem(STR_02B6, NS_COMPANY_BANKRUPT, 0, 0, cni);
531
/* Remove the company */
532
ChangeNetworkOwner(c->index, COMPANY_SPECTATOR);
533
ChangeOwnershipOfCompanyItems(c->index, INVALID_OWNER);
535
if (!IsHumanCompany(c->index)) AI::Stop(c->index);
537
CompanyID c_index = c->index;
539
AI::BroadcastNewEvent(new AIEventCompanyBankrupt(c_index));
543
static void CompaniesGenStatistics()
693
548
FOR_ALL_STATIONS(st) {
694
_current_player = st->owner;
549
_current_company = st->owner;
695
550
CommandCost cost(EXPENSES_PROPERTY, _price.station_value >> 1);
696
SubtractMoneyFromPlayer(cost);
551
SubtractMoneyFromCompany(cost);
699
if (!HasBit(1<<0|1<<3|1<<6|1<<9, _cur_month))
554
if (!HasBit(1 << 0 | 1 << 3 | 1 << 6 | 1 << 9, _cur_month))
704
memmove(&p->old_economy[1], &p->old_economy[0], sizeof(p->old_economy) - sizeof(p->old_economy[0]));
705
p->old_economy[0] = p->cur_economy;
706
memset(&p->cur_economy, 0, sizeof(p->cur_economy));
708
if (p->num_valid_stat_ent != 24) p->num_valid_stat_ent++;
710
UpdateCompanyRatingAndValue(p, true);
711
PlayersCheckBankrupt(p);
713
if (p->block_preview != 0) p->block_preview--;
557
FOR_ALL_COMPANIES(c) {
558
memmove(&c->old_economy[1], &c->old_economy[0], sizeof(c->old_economy) - sizeof(c->old_economy[0]));
559
c->old_economy[0] = c->cur_economy;
560
memset(&c->cur_economy, 0, sizeof(c->cur_economy));
562
if (c->num_valid_stat_ent != 24) c->num_valid_stat_ent++;
564
UpdateCompanyRatingAndValue(c, true);
565
CompanyCheckBankrupt(c);
567
if (c->block_preview != 0) c->block_preview--;
717
570
InvalidateWindow(WC_INCOME_GRAPH, 0);
784
637
InvalidateWindow(WC_PAYMENT_RATES, 0);
787
static void PlayersPayInterest()
640
static void CompaniesPayInterest()
790
int interest = _economy.interest_rate * 54;
793
if (!p->is_active) continue;
795
_current_player = p->index;
797
SubtractMoneyFromPlayer(CommandCost(EXPENSES_LOAN_INT, (Money)BigMulSU(p->current_loan, interest, 16)));
799
SubtractMoneyFromPlayer(CommandCost(EXPENSES_OTHER, _price.station_value >> 2));
644
FOR_ALL_COMPANIES(c) {
645
_current_company = c->index;
647
/* Over a year the paid interest should be "loan * interest percentage",
648
* but... as that number is likely not dividable by 12 (pay each month),
649
* one needs to account for that in the monthly fee calculations.
650
* To easily calculate what one should pay "this" month, you calculate
651
* what (total) should have been paid up to this month and you substract
652
* whatever has been paid in the previous months. This will mean one month
653
* it'll be a bit more and the other it'll be a bit less than the average
654
* monthly fee, but on average it will be exact. */
655
Money yearly_fee = c->current_loan * _economy.interest_rate / 100;
656
Money up_to_previous_month = yearly_fee * _cur_month / 12;
657
Money up_to_this_month = yearly_fee * (_cur_month + 1) / 12;
659
SubtractMoneyFromCompany(CommandCost(EXPENSES_LOAN_INT, up_to_this_month - up_to_previous_month));
661
SubtractMoneyFromCompany(CommandCost(EXPENSES_OTHER, _price.station_value >> 2));
803
665
static void HandleEconomyFluctuations()
805
if (_opt.diff.economy == 0) return;
667
if (_settings_game.difficulty.economy == 0) return;
807
669
if (--_economy.fluct == 0) {
808
670
_economy.fluct = -(int)GB(Random(), 0, 2);
809
AddNewsItem(STR_7073_WORLD_RECESSION_FINANCIAL, NEWS_FLAGS(NM_NORMAL,0,NT_ECONOMY,0), 0, 0);
671
AddNewsItem(STR_7073_WORLD_RECESSION_FINANCIAL, NS_ECONOMY, 0, 0);
810
672
} else if (_economy.fluct == -12) {
811
673
_economy.fluct = GB(Random(), 0, 8) + 312;
812
AddNewsItem(STR_7074_RECESSION_OVER_UPTURN_IN, NEWS_FLAGS(NM_NORMAL,0,NT_ECONOMY,0), 0, 0);
674
AddNewsItem(STR_7074_RECESSION_OVER_UPTURN_IN, NS_ECONOMY, 0, 0);
1280
1168
* - linear decreasing with time with a slope of -2 for slow transports
1284
if (days_over_days1 <= 0) {
1285
time_factor = MAX_TIME_FACTOR;
1286
} else if (days_over_days1 <= days2) {
1287
time_factor = MAX_TIME_FACTOR - days_over_days1;
1289
time_factor = MAX_TIME_FACTOR - 2 * days_over_days1 + days2;
1292
if (time_factor < MIN_TIME_FACTOR) time_factor = MIN_TIME_FACTOR;
1171
const int time_factor = max(MAX_TIME_FACTOR - days_over_days1 - days_over_days2, MIN_TIME_FACTOR);
1294
1173
return BigMulS(dist * time_factor * num_pieces, _cargo_payment_rates[cargo_type], 21);
1297
static void DeliverGoodsToIndustry(TileIndex xy, CargoID cargo_type, int num_pieces)
1299
Industry *best = NULL;
1301
const IndustrySpec *indspec;
1303
uint accepted_cargo_index = 0; ///< unlikely value, just for warning removing
1305
/* Check if there's an industry close to the station that accepts the cargo
1306
* XXX - Think of something better to
1307
* 1) Only deliver to industries which are withing the catchment radius
1308
* 2) Distribute between industries if more then one is present */
1309
best_dist = (_patches.station_spread + 8) * 2;
1310
FOR_ALL_INDUSTRIES(ind) {
1311
indspec = GetIndustrySpec(ind->type);
1314
for (i = 0; i < lengthof(ind->accepts_cargo); i++) {
1315
if (cargo_type == ind->accepts_cargo[i]) break;
1318
/* Check if matching cargo has been found */
1319
if (i == lengthof(ind->accepts_cargo)) continue;
1321
if (HasBit(indspec->callback_flags, CBM_IND_REFUSE_CARGO)) {
1322
uint16 res = GetIndustryCallback(CBID_INDUSTRY_REFUSE_CARGO, 0, GetReverseCargoTranslation(cargo_type, indspec->grf_prop.grffile), ind, ind->type, ind->xy);
1323
if (res == 0) continue;
1326
uint dist = DistanceManhattan(ind->xy, xy);
1328
if (dist < best_dist) {
1331
accepted_cargo_index = i;
1337
indspec = GetIndustrySpec(best->type);
1338
uint16 callback = indspec->callback_flags;
1340
best->was_cargo_delivered = true;
1341
best->last_cargo_accepted_at = _date;
1343
if (HasBit(callback, CBM_IND_PRODUCTION_CARGO_ARRIVAL) || HasBit(callback, CBM_IND_PRODUCTION_256_TICKS)) {
1344
best->incoming_cargo_waiting[accepted_cargo_index] = min(num_pieces + best->incoming_cargo_waiting[accepted_cargo_index], 0xFFFF);
1345
if (HasBit(callback, CBM_IND_PRODUCTION_CARGO_ARRIVAL)) {
1346
IndustryProductionCallback(best, 0);
1348
InvalidateWindow(WC_INDUSTRY_VIEW, best->index);
1351
best->produced_cargo_waiting[0] = min(best->produced_cargo_waiting[0] + (num_pieces * indspec->input_cargo_multiplier[accepted_cargo_index][0] / 256), 0xFFFF);
1352
best->produced_cargo_waiting[1] = min(best->produced_cargo_waiting[1] + (num_pieces * indspec->input_cargo_multiplier[accepted_cargo_index][1] / 256), 0xFFFF);
1355
TriggerIndustry(best, INDUSTRY_TRIGGER_RECEIVED_CARGO);
1356
StartStopIndustryTileAnimation(best, IAT_INDUSTRY_RECEIVED_CARGO);
1177
struct FindIndustryToDeliverData {
1178
const Rect *rect; ///< Station acceptance rectangle
1179
CargoID cargo_type; ///< Cargo type that was delivered
1181
Industry *ind; ///< Returns found industry
1182
const IndustrySpec *indspec; ///< Spec of ind
1183
uint cargo_index; ///< Index of cargo_type in acceptance list of ind
1186
static bool FindIndustryToDeliver(TileIndex ind_tile, void *user_data)
1188
FindIndustryToDeliverData *callback_data = (FindIndustryToDeliverData *)user_data;
1189
const Rect *rect = callback_data->rect;
1190
CargoID cargo_type = callback_data->cargo_type;
1192
/* Only process industry tiles */
1193
if (!IsTileType(ind_tile, MP_INDUSTRY)) return false;
1195
/* Only process tiles in the station acceptance rectangle */
1196
int x = TileX(ind_tile);
1197
int y = TileY(ind_tile);
1198
if (x < rect->left || x > rect->right || y < rect->top || y > rect->bottom) return false;
1200
Industry *ind = GetIndustryByTile(ind_tile);
1201
const IndustrySpec *indspec = GetIndustrySpec(ind->type);
1204
for (cargo_index = 0; cargo_index < lengthof(ind->accepts_cargo); cargo_index++) {
1205
if (cargo_type == ind->accepts_cargo[cargo_index]) break;
1207
/* Check if matching cargo has been found */
1208
if (cargo_index >= lengthof(ind->accepts_cargo)) return false;
1210
/* Check if industry temporarly refuses acceptance */
1211
if (HasBit(indspec->callback_flags, CBM_IND_REFUSE_CARGO)) {
1212
uint16 res = GetIndustryCallback(CBID_INDUSTRY_REFUSE_CARGO, 0, GetReverseCargoTranslation(cargo_type, indspec->grf_prop.grffile), ind, ind->type, ind->xy);
1213
if (res == 0) return false;
1216
/* Found industry accepting the cargo */
1217
callback_data->ind = ind;
1218
callback_data->indspec = indspec;
1219
callback_data->cargo_index = cargo_index;
1224
* Transfer goods from station to industry.
1225
* All cargo is delivered to the nearest (Manhattan) industry to the station sign, which is inside the acceptance rectangle and actually accepts the cargo.
1226
* @param st The station that accepted the cargo
1227
* @param cargo_type Type of cargo delivered
1228
* @param nun_pieces Amount of cargo delivered
1229
* @param industry_set The destination industry will be inserted into this set
1231
static void DeliverGoodsToIndustry(const Station *st, CargoID cargo_type, int num_pieces, SmallIndustryList *industry_set)
1233
if (st->rect.IsEmpty()) return;
1235
/* Compute acceptance rectangle */
1236
int catchment_radius = st->GetCatchmentRadius();
1238
max<int>(st->rect.left - catchment_radius, 0),
1239
max<int>(st->rect.top - catchment_radius, 0),
1240
min<int>(st->rect.right + catchment_radius, MapMaxX()),
1241
min<int>(st->rect.bottom + catchment_radius, MapMaxY())
1244
/* Compute maximum extent of acceptance rectangle wrt. station sign */
1245
TileIndex start_tile = st->xy;
1246
uint max_radius = max(
1247
max(DistanceManhattan(start_tile, TileXY(rect.left , rect.top)), DistanceManhattan(start_tile, TileXY(rect.left , rect.bottom))),
1248
max(DistanceManhattan(start_tile, TileXY(rect.right, rect.top)), DistanceManhattan(start_tile, TileXY(rect.right, rect.bottom)))
1251
FindIndustryToDeliverData callback_data;
1252
callback_data.rect = ▭
1253
callback_data.cargo_type = cargo_type;
1254
callback_data.ind = NULL;
1255
callback_data.indspec = NULL;
1256
callback_data.cargo_index = 0;
1258
/* Find the nearest industrytile to the station sign inside the catchment area, whose industry accepts the cargo.
1259
* This fails in three cases:
1260
* 1) The station accepts the cargo because there are enough houses around it accepting the cargo.
1261
* 2) The industries in the catchment area temporarily reject the cargo, and the daily station loop has not yet updated station acceptance.
1262
* 3) The results of callbacks CBID_INDUSTRY_REFUSE_CARGO and CBID_INDTILE_CARGO_ACCEPTANCE are inconsistent. (documented behaviour)
1264
if (CircularTileSearch(&start_tile, 2 * max_radius + 1, FindIndustryToDeliver, &callback_data)) {
1265
Industry *best = callback_data.ind;
1266
uint accepted_cargo_index = callback_data.cargo_index;
1267
assert(best != NULL);
1269
/* Insert the industry into industry_set, if not yet contained */
1270
if (industry_set != NULL) industry_set->Include(best);
1272
best->incoming_cargo_waiting[accepted_cargo_index] = min(num_pieces + best->incoming_cargo_waiting[accepted_cargo_index], 0xFFFF);
1615
1587
if (v->cargo_cap == 0) continue;
1617
1589
byte load_amount = EngInfo(v->engine_type)->load_amount;
1618
if (_patches.gradual_loading && HasBit(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_LOAD_AMOUNT)) {
1591
/* The default loadamount for mail is 1/4 of the load amount for passengers */
1592
if (v->type == VEH_AIRCRAFT && !IsNormalAircraft(v)) load_amount = (load_amount + 3) / 4;
1594
if (_settings_game.order.gradual_loading && HasBit(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_LOAD_AMOUNT)) {
1619
1595
uint16 cb_load_amount = GetVehicleCallback(CBID_VEHICLE_LOAD_AMOUNT, 0, 0, v->engine_type, v);
1620
1596
if (cb_load_amount != CALLBACK_FAILED && GB(cb_load_amount, 0, 8) != 0) load_amount = GB(cb_load_amount, 0, 8);
1623
1599
GoodsEntry *ge = &st->goods[v->cargo_type];
1625
if (HasBit(v->vehicle_flags, VF_CARGO_UNLOADING)) {
1601
if (HasBit(v->vehicle_flags, VF_CARGO_UNLOADING) && (u->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0) {
1626
1602
uint cargo_count = v->cargo.Count();
1627
uint amount_unloaded = _patches.gradual_loading ? min(cargo_count, load_amount) : cargo_count;
1628
bool remaining; // Are there cargo entities in this vehicle that can still be unloaded here?
1603
uint amount_unloaded = _settings_game.order.gradual_loading ? min(cargo_count, load_amount) : cargo_count;
1604
bool remaining = false; // Are there cargo entities in this vehicle that can still be unloaded here?
1605
bool accepted = false; // Is the cargo accepted by the station?
1630
if (HasBit(ge->acceptance_pickup, GoodsEntry::ACCEPTANCE) && !(u->current_order.flags & OFB_TRANSFER)) {
1607
if (HasBit(ge->acceptance_pickup, GoodsEntry::ACCEPTANCE) && !(u->current_order.GetUnloadType() & OUFB_TRANSFER)) {
1631
1608
/* The cargo has reached it's final destination, the packets may now be destroyed */
1632
1609
remaining = v->cargo.MoveTo(NULL, amount_unloaded, CargoList::MTA_FINAL_DELIVERY, last_visited);
1635
} else if (u->current_order.flags & (OFB_UNLOAD | OFB_TRANSFER)) {
1615
/* The !accepted || v->cargo.Count == cargo_count clause is there
1616
* to make it possible to force unload vehicles at the station where
1617
* they were loaded, but to not force unload the vehicle when the
1618
* station is still accepting the cargo in the vehicle. It doesn't
1619
* accept cargo that was loaded at the same station. */
1620
if (u->current_order.GetUnloadType() & (OUFB_UNLOAD | OUFB_TRANSFER) && (!accepted || v->cargo.Count() == cargo_count)) {
1636
1621
remaining = v->cargo.MoveTo(&ge->cargo, amount_unloaded);
1637
1622
SetBit(ge->acceptance_pickup, GoodsEntry::PICKUP);
1625
} else if (!accepted) {
1641
1626
/* The order changed while unloading (unset unload/transfer) or the
1642
1627
* station does not accept goods anymore. */
1643
1628
ClrBit(v->vehicle_flags, VF_CARGO_UNLOADING);
1832
void PlayersMonthlyLoop()
1821
void CompaniesMonthlyLoop()
1834
PlayersGenStatistics();
1835
if (_patches.inflation && _cur_year < MAX_YEAR)
1837
PlayersPayInterest();
1838
/* Reset the _current_player flag */
1839
_current_player = OWNER_NONE;
1823
CompaniesGenStatistics();
1824
if (_settings_game.economy.inflation) AddInflation();
1825
CompaniesPayInterest();
1826
/* Reset the _current_company flag */
1827
_current_company = OWNER_NONE;
1840
1828
HandleEconomyFluctuations();
1841
1829
SubsidyMonthlyHandler();
1844
static void DoAcquireCompany(Player *p)
1832
static void DoAcquireCompany(Company *c)
1850
SetDParam(0, p->index);
1851
SetDParam(1, p->bankrupt_value);
1852
AddNewsItem( (StringID)(_current_player | NB_BMERGER), NEWS_FLAGS(NM_CALLBACK, 0, NT_COMPANY_INFO, DNC_BANKRUPCY),0,0);
1837
CompanyID ci = c->index;
1839
CompanyNewsInformation *cni = MallocT<CompanyNewsInformation>(1);
1840
cni->FillData(c, GetCompany(_current_company));
1842
SetDParam(0, STR_7059_TRANSPORT_COMPANY_MERGER);
1843
SetDParam(1, c->bankrupt_value == 0 ? STR_707F_HAS_BEEN_TAKEN_OVER_BY : STR_705A_HAS_BEEN_SOLD_TO_FOR);
1844
SetDParamStr(2, cni->company_name);
1845
SetDParamStr(3, cni->other_company_name);
1846
SetDParam(4, c->bankrupt_value);
1847
AddNewsItem(STR_02B6, NS_COMPANY_MERGER, 0, 0, cni);
1848
AI::BroadcastNewEvent(new AIEventCompanyMerger(ci, _current_company));
1854
1850
/* original code does this a little bit differently */
1855
PlayerID pi = p->index;
1856
ChangeNetworkOwner(pi, _current_player);
1857
ChangeOwnershipOfPlayerItems(pi, _current_player);
1851
ChangeNetworkOwner(ci, _current_company);
1852
ChangeOwnershipOfCompanyItems(ci, _current_company);
1859
if (p->bankrupt_value == 0) {
1860
owner = GetPlayer(_current_player);
1861
owner->current_loan += p->current_loan;
1854
if (c->bankrupt_value == 0) {
1855
owner = GetCompany(_current_company);
1856
owner->current_loan += c->current_loan;
1864
value = CalculateCompanyValue(p) >> 2;
1865
PlayerID old_player = _current_player;
1859
value = CalculateCompanyValue(c) >> 2;
1860
CompanyID old_company = _current_company;
1866
1861
for (i = 0; i != 4; i++) {
1867
if (p->share_owners[i] != PLAYER_SPECTATOR) {
1868
_current_player = p->share_owners[i];
1869
SubtractMoneyFromPlayer(CommandCost(EXPENSES_OTHER, -value));
1862
if (c->share_owners[i] != COMPANY_SPECTATOR) {
1863
_current_company = c->share_owners[i];
1864
SubtractMoneyFromCompany(CommandCost(EXPENSES_OTHER, -value));
1872
_current_player = old_player;
1874
p->is_active = false;
1876
DeletePlayerWindows(pi);
1877
RebuildVehicleLists(); //Updates the open windows to add the newly acquired vehicles to the lists
1867
_current_company = old_company;
1869
if (!IsHumanCompany(c->index)) AI::Stop(c->index);
1871
DeleteCompanyWindows(ci);
1872
InvalidateWindowClassesData(WC_TRAINS_LIST, 0);
1873
InvalidateWindowClassesData(WC_SHIPS_LIST, 0);
1874
InvalidateWindowClassesData(WC_ROADVEH_LIST, 0);
1875
InvalidateWindowClassesData(WC_AIRCRAFT_LIST, 0);
1880
extern int GetAmountOwnedBy(const Player *p, PlayerID owner);
1880
extern int GetAmountOwnedBy(const Company *c, Owner owner);
1882
1882
/** Acquire shares in an opposing company.
1883
1883
* @param tile unused
1884
1884
* @param flags type of operation
1885
* @param p1 player to buy the shares from
1885
* @param p1 company to buy the shares from
1886
1886
* @param p2 unused
1888
CommandCost CmdBuyShareInCompany(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
1888
CommandCost CmdBuyShareInCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1891
1890
CommandCost cost(EXPENSES_OTHER);
1893
/* Check if buying shares is allowed (protection against modified clients) */
1894
/* Cannot buy own shares */
1895
if (!IsValidPlayer((PlayerID)p1) || !_patches.allow_shares || _current_player == (PlayerID)p1) return CMD_ERROR;
1897
p = GetPlayer((PlayerID)p1);
1899
/* Cannot buy shares of non-existent nor bankrupted company */
1900
if (!p->is_active) return CMD_ERROR;
1892
/* Check if buying shares is allowed (protection against modified clients)
1893
* Cannot buy own shares */
1894
if (!IsValidCompanyID((CompanyID)p1) || !_settings_game.economy.allow_shares || _current_company == (CompanyID)p1) return CMD_ERROR;
1896
Company *c = GetCompany((CompanyID)p1);
1902
1898
/* Protect new companies from hostile takeovers */
1903
if (_cur_year - p->inaugurated_year < 6) return_cmd_error(STR_PROTECTED);
1899
if (_cur_year - c->inaugurated_year < 6) return_cmd_error(STR_PROTECTED);
1905
1901
/* Those lines are here for network-protection (clients can be slow) */
1906
if (GetAmountOwnedBy(p, PLAYER_SPECTATOR) == 0) return cost;
1908
/* We can not buy out a real player (temporarily). TODO: well, enable it obviously */
1909
if (GetAmountOwnedBy(p, PLAYER_SPECTATOR) == 1 && !p->is_ai) return cost;
1911
cost.AddCost(CalculateCompanyValue(p) >> 2);
1902
if (GetAmountOwnedBy(c, COMPANY_SPECTATOR) == 0) return cost;
1904
/* We can not buy out a real company (temporarily). TODO: well, enable it obviously */
1905
if (GetAmountOwnedBy(c, COMPANY_SPECTATOR) == 1 && !c->is_ai) return cost;
1907
cost.AddCost(CalculateCompanyValue(c) >> 2);
1912
1908
if (flags & DC_EXEC) {
1913
PlayerByte* b = p->share_owners;
1909
OwnerByte *b = c->share_owners;
1916
while (*b != PLAYER_SPECTATOR) b++; /* share owners is guaranteed to contain at least one PLAYER_SPECTATOR */
1917
*b = _current_player;
1912
while (*b != COMPANY_SPECTATOR) b++; // share owners is guaranteed to contain at least one COMPANY_SPECTATOR
1913
*b = _current_company;
1919
for (i = 0; p->share_owners[i] == _current_player;) {
1915
for (i = 0; c->share_owners[i] == _current_company;) {
1920
1916
if (++i == 4) {
1921
p->bankrupt_value = 0;
1922
DoAcquireCompany(p);
1917
c->bankrupt_value = 0;
1918
DoAcquireCompany(c);
1967
1957
/** Buy up another company.
1968
1958
* When a competing company is gone bankrupt you get the chance to purchase
1969
1959
* that company.
1970
* @todo currently this only works for AI players
1960
* @todo currently this only works for AI companies
1971
1961
* @param tile unused
1972
1962
* @param flags type of operation
1973
* @param p1 player/company to buy up
1963
* @param p1 company to buy up
1974
1964
* @param p2 unused
1976
CommandCost CmdBuyCompany(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
1966
CommandCost CmdBuyCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1979
PlayerID pid = (PlayerID)p1;
1968
CompanyID cid = (CompanyID)p1;
1981
1970
/* Disable takeovers in multiplayer games */
1982
if (!IsValidPlayer(pid) || _networking) return CMD_ERROR;
1984
/* Do not allow players to take over themselves */
1985
if (pid == _current_player) return CMD_ERROR;
1989
if (!p->is_ai) return CMD_ERROR;
1971
if (!IsValidCompanyID(cid) || _networking) return CMD_ERROR;
1973
/* Do not allow companies to take over themselves */
1974
if (cid == _current_company) return CMD_ERROR;
1976
Company *c = GetCompany(cid);
1978
if (!c->is_ai) return CMD_ERROR;
1991
1980
if (flags & DC_EXEC) {
1992
DoAcquireCompany(p);
1981
DoAcquireCompany(c);
1994
return CommandCost(EXPENSES_OTHER, p->bankrupt_value);
1998
static void SaveLoad_PRIC()
2000
int vt = CheckSavegameVersion(65) ? (SLE_FILE_I32 | SLE_VAR_I64) : SLE_INT64;
2001
SlArray(&_price, NUM_PRICES, vt);
2002
SlArray(&_price_frac, NUM_PRICES, SLE_UINT16);
2005
/** Cargo payment rates */
2006
static void SaveLoad_CAPR()
2008
uint num_cargo = CheckSavegameVersion(55) ? 12 : NUM_CARGO;
2009
int vt = CheckSavegameVersion(65) ? (SLE_FILE_I32 | SLE_VAR_I64) : SLE_INT64;
2010
SlArray(&_cargo_payment_rates, num_cargo, vt);
2011
SlArray(&_cargo_payment_rates_frac, num_cargo, SLE_UINT16);
2014
static const SaveLoad _economy_desc[] = {
2015
SLE_CONDVAR(Economy, max_loan, SLE_FILE_I32 | SLE_VAR_I64, 0, 64),
2016
SLE_CONDVAR(Economy, max_loan, SLE_INT64, 65, SL_MAX_VERSION),
2017
SLE_CONDVAR(Economy, max_loan_unround, SLE_FILE_I32 | SLE_VAR_I64, 0, 64),
2018
SLE_CONDVAR(Economy, max_loan_unround, SLE_INT64, 65, SL_MAX_VERSION),
2019
SLE_CONDVAR(Economy, max_loan_unround_fract, SLE_UINT16, 70, SL_MAX_VERSION),
2020
SLE_VAR(Economy, fluct, SLE_INT16),
2021
SLE_VAR(Economy, interest_rate, SLE_UINT8),
2022
SLE_VAR(Economy, infl_amount, SLE_UINT8),
2023
SLE_VAR(Economy, infl_amount_pr, SLE_UINT8),
2027
/** Economy variables */
2028
static void SaveLoad_ECMY()
2030
SlObject(&_economy, _economy_desc);
2033
extern const ChunkHandler _economy_chunk_handlers[] = {
2034
{ 'PRIC', SaveLoad_PRIC, SaveLoad_PRIC, CH_RIFF | CH_AUTO_LENGTH},
2035
{ 'CAPR', SaveLoad_CAPR, SaveLoad_CAPR, CH_RIFF | CH_AUTO_LENGTH},
2036
{ 'SUBS', Save_SUBS, Load_SUBS, CH_ARRAY},
2037
{ 'ECMY', SaveLoad_ECMY, SaveLoad_ECMY, CH_RIFF | CH_LAST},
1983
return CommandCost(EXPENSES_OTHER, c->bankrupt_value);