3 /** @file economy.cpp */ |
3 /** @file economy.cpp */ |
4 |
4 |
5 #include "stdafx.h" |
5 #include "stdafx.h" |
6 #include "openttd.h" |
6 #include "openttd.h" |
7 #include "currency.h" |
7 #include "currency.h" |
8 #include "functions.h" |
|
9 #include "landscape.h" |
8 #include "landscape.h" |
10 #include "strings.h" // XXX InjectDParam() |
|
11 #include "table/strings.h" |
9 #include "table/strings.h" |
12 #include "table/sprites.h" |
10 #include "table/sprites.h" |
13 #include "map.h" |
|
14 #include "news.h" |
11 #include "news.h" |
15 #include "player.h" |
12 #include "player.h" |
16 #include "station.h" |
13 #include "station.h" |
17 #include "vehicle.h" |
14 #include "command_func.h" |
18 #include "window.h" |
|
19 #include "gfx.h" |
|
20 #include "command.h" |
|
21 #include "saveload.h" |
15 #include "saveload.h" |
22 #include "economy.h" |
|
23 #include "industry.h" |
16 #include "industry.h" |
24 #include "town.h" |
17 #include "town.h" |
25 #include "network/network.h" |
18 #include "network/network.h" |
26 #include "sound.h" |
|
27 #include "engine.h" |
19 #include "engine.h" |
28 #include "network/network_data.h" |
20 #include "network/network_data.h" |
29 #include "variables.h" |
21 #include "variables.h" |
30 #include "vehicle_gui.h" |
22 #include "vehicle_gui.h" |
31 #include "ai/ai.h" |
23 #include "ai/ai.h" |
36 #include "newgrf_sound.h" |
28 #include "newgrf_sound.h" |
37 #include "newgrf_callbacks.h" |
29 #include "newgrf_callbacks.h" |
38 #include "newgrf_industries.h" |
30 #include "newgrf_industries.h" |
39 #include "newgrf_industrytiles.h" |
31 #include "newgrf_industrytiles.h" |
40 #include "unmovable.h" |
32 #include "unmovable.h" |
41 #include "date.h" |
|
42 #include "cargotype.h" |
33 #include "cargotype.h" |
43 #include "player_face.h" |
34 #include "player_face.h" |
44 #include "group.h" |
35 #include "group.h" |
|
36 #include "strings_func.h" |
|
37 #include "tile_cmd.h" |
|
38 #include "functions.h" |
|
39 #include "window_func.h" |
|
40 #include "date_func.h" |
|
41 #include "vehicle_func.h" |
|
42 #include "sound_func.h" |
|
43 #include "track_type.h" |
|
44 #include "track_func.h" |
|
45 #include "rail_map.h" |
|
46 #include "gfx_func.h" |
45 |
47 |
46 /** |
48 /** |
47 * Multiply two integer values and shift the results to right. |
49 * Multiply two integer values and shift the results to right. |
48 * |
50 * |
49 * This function multiplies two integer values. The result is |
51 * This function multiplies two integer values. The result is |
88 { SCORE_LOAN, 250000, 50 }, |
90 { SCORE_LOAN, 250000, 50 }, |
89 { SCORE_TOTAL, 0, 0 } |
91 { SCORE_TOTAL, 0, 0 } |
90 }; |
92 }; |
91 |
93 |
92 int _score_part[MAX_PLAYERS][SCORE_END]; |
94 int _score_part[MAX_PLAYERS][SCORE_END]; |
|
95 Economy _economy; |
|
96 Subsidy _subsidies[MAX_PLAYERS]; |
|
97 Prices _price; |
|
98 uint16 _price_frac[NUM_PRICES]; |
|
99 Money _cargo_payment_rates[NUM_CARGO]; |
|
100 uint16 _cargo_payment_rates_frac[NUM_CARGO]; |
|
101 Money _additional_cash_required; |
93 |
102 |
94 Money CalculateCompanyValue(const Player* p) |
103 Money CalculateCompanyValue(const Player* p) |
95 { |
104 { |
96 PlayerID owner = p->index; |
105 PlayerID owner = p->index; |
97 /* Do a little nasty by using CommandCost, so we can use the "overflow" protection of CommandCost */ |
|
98 Money value = 0; |
106 Money value = 0; |
99 |
107 |
100 Station *st; |
108 Station *st; |
101 uint num = 0; |
109 uint num = 0; |
102 |
110 |
278 uint i; |
286 uint i; |
279 |
287 |
280 /* See if the old_player had shares in other companies */ |
288 /* See if the old_player had shares in other companies */ |
281 _current_player = old_player; |
289 _current_player = old_player; |
282 FOR_ALL_PLAYERS(p) { |
290 FOR_ALL_PLAYERS(p) { |
|
291 if (!p->is_active) continue; |
283 for (i = 0; i < 4; i++) { |
292 for (i = 0; i < 4; i++) { |
284 if (p->share_owners[i] == old_player) { |
293 if (p->share_owners[i] == old_player) { |
285 /* Sell his shares */ |
294 /* Sell his shares */ |
286 CommandCost res = DoCommand(0, p->index, 0, DC_EXEC, CMD_SELL_SHARE_IN_COMPANY); |
295 CommandCost res = DoCommand(0, p->index, 0, DC_EXEC, CMD_SELL_SHARE_IN_COMPANY); |
287 /* Because we are in a DoCommand, we can't just execute an other one and |
296 /* Because we are in a DoCommand, we can't just execute an other one and |
363 } |
372 } |
364 } |
373 } |
365 } |
374 } |
366 |
375 |
367 FOR_ALL_VEHICLES(v) { |
376 FOR_ALL_VEHICLES(v) { |
368 if (v->owner == old_player && IS_BYTE_INSIDE(v->type, VEH_TRAIN, VEH_AIRCRAFT + 1)) { |
377 if (v->owner == old_player && IsInsideMM(v->type, VEH_TRAIN, VEH_AIRCRAFT + 1)) { |
369 if (new_player == PLAYER_SPECTATOR) { |
378 if (new_player == PLAYER_SPECTATOR) { |
370 DeleteWindowById(WC_VEHICLE_VIEW, v->index); |
379 DeleteWindowById(WC_VEHICLE_VIEW, v->index); |
371 DeleteWindowById(WC_VEHICLE_DETAILS, v->index); |
380 DeleteWindowById(WC_VEHICLE_DETAILS, v->index); |
372 DeleteWindowById(WC_VEHICLE_ORDERS, v->index); |
381 DeleteWindowById(WC_VEHICLE_ORDERS, v->index); |
373 |
382 |
394 break; |
403 break; |
395 } |
404 } |
396 } |
405 } |
397 } else { |
406 } else { |
398 v->owner = new_player; |
407 v->owner = new_player; |
|
408 v->colormap = PAL_NONE; |
399 v->group_id = DEFAULT_GROUP; |
409 v->group_id = DEFAULT_GROUP; |
400 if (IsEngineCountable(v)) GetPlayer(new_player)->num_engines[v->engine_type]++; |
410 if (IsEngineCountable(v)) GetPlayer(new_player)->num_engines[v->engine_type]++; |
401 switch (v->type) { |
411 switch (v->type) { |
402 case VEH_TRAIN: if (IsFrontEngine(v)) v->unitnumber = ++num_train; break; |
412 case VEH_TRAIN: if (IsFrontEngine(v)) v->unitnumber = ++num_train; break; |
403 case VEH_ROAD: if (IsRoadVehFront(v)) v->unitnumber = ++num_road; break; |
413 case VEH_ROAD: if (IsRoadVehFront(v)) v->unitnumber = ++num_road; break; |
414 { |
424 { |
415 TileIndex tile = 0; |
425 TileIndex tile = 0; |
416 do { |
426 do { |
417 ChangeTileOwner(tile, old_player, new_player); |
427 ChangeTileOwner(tile, old_player, new_player); |
418 } while (++tile != MapSize()); |
428 } while (++tile != MapSize()); |
|
429 |
|
430 if (new_player != PLAYER_SPECTATOR) { |
|
431 /* Update all signals because there can be new segment that was owned by two players |
|
432 * and signals were not propagated */ |
|
433 tile = 0; |
|
434 |
|
435 do { |
|
436 if (IsTileType(tile, MP_RAILWAY) && IsTileOwner(tile, new_player) && HasSignals(tile)) { |
|
437 TrackBits tracks = GetTrackBits(tile); |
|
438 do { // there may be two tracks with signals for TRACK_BIT_HORZ and TRACK_BIT_VERT |
|
439 Track track = RemoveFirstTrack(&tracks); |
|
440 if (HasSignalOnTrack(tile, track)) SetSignalsOnBothDir(tile, track); |
|
441 } while (tracks != TRACK_BIT_NONE); |
|
442 } |
|
443 } while (++tile != MapSize()); |
|
444 } |
419 } |
445 } |
420 |
446 |
421 /* Change color of existing windows */ |
447 /* Change color of existing windows */ |
422 if (new_player != PLAYER_SPECTATOR) ChangeWindowOwner(old_player, new_player); |
448 if (new_player != PLAYER_SPECTATOR) ChangeWindowOwner(old_player, new_player); |
423 |
449 |
632 Station *st; |
658 Station *st; |
633 Player *p; |
659 Player *p; |
634 |
660 |
635 FOR_ALL_STATIONS(st) { |
661 FOR_ALL_STATIONS(st) { |
636 _current_player = st->owner; |
662 _current_player = st->owner; |
637 SET_EXPENSES_TYPE(EXPENSES_PROPERTY); |
663 CommandCost cost(EXPENSES_PROPERTY, _price.station_value >> 1); |
638 SubtractMoneyFromPlayer(_price.station_value >> 1); |
664 SubtractMoneyFromPlayer(cost); |
639 } |
665 } |
640 |
666 |
641 if (!HasBit(1<<0|1<<3|1<<6|1<<9, _cur_month)) |
667 if (!HasBit(1<<0|1<<3|1<<6|1<<9, _cur_month)) |
642 return; |
668 return; |
643 |
669 |
733 |
759 |
734 FOR_ALL_PLAYERS(p) { |
760 FOR_ALL_PLAYERS(p) { |
735 if (!p->is_active) continue; |
761 if (!p->is_active) continue; |
736 |
762 |
737 _current_player = p->index; |
763 _current_player = p->index; |
738 SET_EXPENSES_TYPE(EXPENSES_LOAN_INT); |
764 |
739 |
765 SubtractMoneyFromPlayer(CommandCost(EXPENSES_LOAN_INT, (Money)BigMulSU(p->current_loan, interest, 16))); |
740 SubtractMoneyFromPlayer(CommandCost((Money)BigMulSU(p->current_loan, interest, 16))); |
766 |
741 |
767 SubtractMoneyFromPlayer(CommandCost(EXPENSES_OTHER, _price.station_value >> 2)); |
742 SET_EXPENSES_TYPE(EXPENSES_OTHER); |
|
743 SubtractMoneyFromPlayer(_price.station_value >> 2); |
|
744 } |
768 } |
745 } |
769 } |
746 |
770 |
747 static void HandleEconomyFluctuations() |
771 static void HandleEconomyFluctuations() |
748 { |
772 { |
788 700000, ///< aircraft_base |
812 700000, ///< aircraft_base |
789 14000, ///< roadveh_base |
813 14000, ///< roadveh_base |
790 65000, ///< ship_base |
814 65000, ///< ship_base |
791 20, ///< build_trees |
815 20, ///< build_trees |
792 250, ///< terraform |
816 250, ///< terraform |
793 20, ///< clear_1 |
817 20, ///< clear_grass |
794 40, ///< purchase_land |
818 40, ///< clear_roughland |
795 200, ///< clear_2 |
819 200, ///< clear_rocks |
796 500, ///< clear_3 |
820 500, ///< clear_fields |
797 20, ///< remove_trees |
821 20, ///< remove_trees |
798 -70, ///< remove_rail |
822 -70, ///< remove_rail |
799 10, ///< remove_signals |
823 10, ///< remove_signals |
800 50, ///< clear_bridge |
824 50, ///< clear_bridge |
801 80, ///< remove_train_depot |
825 80, ///< remove_train_depot |
1099 s->age++; |
1123 s->age++; |
1100 } |
1124 } |
1101 } |
1125 } |
1102 |
1126 |
1103 /* 25% chance to go on */ |
1127 /* 25% chance to go on */ |
1104 if (CHANCE16(1,4)) { |
1128 if (Chance16(1,4)) { |
1105 /* Find a free slot*/ |
1129 /* Find a free slot*/ |
1106 s = _subsidies; |
1130 s = _subsidies; |
1107 while (s->cargo_type != CT_INVALID) { |
1131 while (s->cargo_type != CT_INVALID) { |
1108 if (++s == endof(_subsidies)) |
1132 if (++s == endof(_subsidies)) |
1109 goto no_add; |
1133 goto no_add; |
1486 ShowFeederIncomeAnimation(front_v->x_pos, front_v->y_pos, front_v->z_pos, virtual_profit); |
1510 ShowFeederIncomeAnimation(front_v->x_pos, front_v->y_pos, front_v->z_pos, virtual_profit); |
1487 } |
1511 } |
1488 |
1512 |
1489 if (route_profit != 0) { |
1513 if (route_profit != 0) { |
1490 front_v->profit_this_year += vehicle_profit; |
1514 front_v->profit_this_year += vehicle_profit; |
1491 SubtractMoneyFromPlayer(-route_profit); |
1515 SubtractMoneyFromPlayer(CommandCost(front_v->GetExpenseType(true), -route_profit)); |
1492 |
1516 |
1493 if (IsLocalPlayer() && !PlayVehicleSound(front_v, VSE_LOAD_UNLOAD)) { |
1517 if (IsLocalPlayer() && !PlayVehicleSound(front_v, VSE_LOAD_UNLOAD)) { |
1494 SndPlayVehicleFx(SND_14_CASHTILL, front_v); |
1518 SndPlayVehicleFx(SND_14_CASHTILL, front_v); |
1495 } |
1519 } |
1496 |
1520 |
1521 } |
1545 } |
1522 } |
1546 } |
1523 return; |
1547 return; |
1524 } |
1548 } |
1525 |
1549 |
1526 if (v->type == VEH_TRAIN && !IsTileType(v->tile, MP_STATION)) { |
1550 StationID last_visited = v->last_station_visited; |
|
1551 Station *st = GetStation(last_visited); |
|
1552 |
|
1553 if (v->type == VEH_TRAIN && (!IsTileType(v->tile, MP_STATION) || GetStationIndex(v->tile) != st->index)) { |
1527 /* The train reversed in the station. Take the "easy" way |
1554 /* The train reversed in the station. Take the "easy" way |
1528 * out and let the train just leave as it always did. */ |
1555 * out and let the train just leave as it always did. */ |
1529 SetBit(v->vehicle_flags, VF_LOADING_FINISHED); |
1556 SetBit(v->vehicle_flags, VF_LOADING_FINISHED); |
1530 return; |
1557 return; |
1531 } |
1558 } |
1540 bool anything_loaded = false; |
1567 bool anything_loaded = false; |
1541 uint32 cargo_not_full = 0; |
1568 uint32 cargo_not_full = 0; |
1542 uint32 cargo_full = 0; |
1569 uint32 cargo_full = 0; |
1543 |
1570 |
1544 v->cur_speed = 0; |
1571 v->cur_speed = 0; |
1545 |
|
1546 StationID last_visited = v->last_station_visited; |
|
1547 Station *st = GetStation(last_visited); |
|
1548 |
1572 |
1549 for (; v != NULL; v = v->Next()) { |
1573 for (; v != NULL; v = v->Next()) { |
1550 if (v->cargo_cap == 0) continue; |
1574 if (v->cargo_cap == 0) continue; |
1551 |
1575 |
1552 byte load_amount = EngInfo(v->engine_type)->load_amount; |
1576 byte load_amount = EngInfo(v->engine_type)->load_amount; |
1795 |
1819 |
1796 value = CalculateCompanyValue(p) >> 2; |
1820 value = CalculateCompanyValue(p) >> 2; |
1797 PlayerID old_player = _current_player; |
1821 PlayerID old_player = _current_player; |
1798 for (i = 0; i != 4; i++) { |
1822 for (i = 0; i != 4; i++) { |
1799 if (p->share_owners[i] != PLAYER_SPECTATOR) { |
1823 if (p->share_owners[i] != PLAYER_SPECTATOR) { |
1800 SET_EXPENSES_TYPE(EXPENSES_OTHER); |
|
1801 _current_player = p->share_owners[i]; |
1824 _current_player = p->share_owners[i]; |
1802 SubtractMoneyFromPlayer(CommandCost(-value)); |
1825 SubtractMoneyFromPlayer(CommandCost(EXPENSES_OTHER, -value)); |
1803 } |
1826 } |
1804 } |
1827 } |
1805 _current_player = old_player; |
1828 _current_player = old_player; |
1806 |
1829 |
1807 p->is_active = false; |
1830 p->is_active = false; |
1819 * @param p2 unused |
1842 * @param p2 unused |
1820 */ |
1843 */ |
1821 CommandCost CmdBuyShareInCompany(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
1844 CommandCost CmdBuyShareInCompany(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
1822 { |
1845 { |
1823 Player *p; |
1846 Player *p; |
1824 CommandCost cost; |
1847 CommandCost cost(EXPENSES_OTHER); |
1825 |
1848 |
1826 /* Check if buying shares is allowed (protection against modified clients) */ |
1849 /* Check if buying shares is allowed (protection against modified clients) */ |
1827 /* Cannot buy own shares */ |
1850 /* Cannot buy own shares */ |
1828 if (!IsValidPlayer((PlayerID)p1) || !_patches.allow_shares || _current_player == (PlayerID)p1) return CMD_ERROR; |
1851 if (!IsValidPlayer((PlayerID)p1) || !_patches.allow_shares || _current_player == (PlayerID)p1) return CMD_ERROR; |
1829 |
1852 |
1830 p = GetPlayer((PlayerID)p1); |
1853 p = GetPlayer((PlayerID)p1); |
1831 |
1854 |
1832 /* Cannot buy shares of non-existent nor bankrupted company */ |
1855 /* Cannot buy shares of non-existent nor bankrupted company */ |
1833 if (!p->is_active) return CMD_ERROR; |
1856 if (!p->is_active) return CMD_ERROR; |
1834 |
|
1835 SET_EXPENSES_TYPE(EXPENSES_OTHER); |
|
1836 |
1857 |
1837 /* Protect new companies from hostile takeovers */ |
1858 /* Protect new companies from hostile takeovers */ |
1838 if (_cur_year - p->inaugurated_year < 6) return_cmd_error(STR_7080_PROTECTED); |
1859 if (_cur_year - p->inaugurated_year < 6) return_cmd_error(STR_7080_PROTECTED); |
1839 |
1860 |
1840 /* Those lines are here for network-protection (clients can be slow) */ |
1861 /* Those lines are here for network-protection (clients can be slow) */ |
1881 p = GetPlayer((PlayerID)p1); |
1902 p = GetPlayer((PlayerID)p1); |
1882 |
1903 |
1883 /* Cannot sell shares of non-existent nor bankrupted company */ |
1904 /* Cannot sell shares of non-existent nor bankrupted company */ |
1884 if (!p->is_active) return CMD_ERROR; |
1905 if (!p->is_active) return CMD_ERROR; |
1885 |
1906 |
1886 SET_EXPENSES_TYPE(EXPENSES_OTHER); |
|
1887 |
|
1888 /* Those lines are here for network-protection (clients can be slow) */ |
1907 /* Those lines are here for network-protection (clients can be slow) */ |
1889 if (GetAmountOwnedBy(p, _current_player) == 0) return CommandCost(); |
1908 if (GetAmountOwnedBy(p, _current_player) == 0) return CommandCost(); |
1890 |
1909 |
1891 /* adjust it a little to make it less profitable to sell and buy */ |
1910 /* adjust it a little to make it less profitable to sell and buy */ |
1892 cost = CalculateCompanyValue(p) >> 2; |
1911 cost = CalculateCompanyValue(p) >> 2; |
1896 PlayerByte* b = p->share_owners; |
1915 PlayerByte* b = p->share_owners; |
1897 while (*b != _current_player) b++; // share owners is guaranteed to contain player |
1916 while (*b != _current_player) b++; // share owners is guaranteed to contain player |
1898 *b = PLAYER_SPECTATOR; |
1917 *b = PLAYER_SPECTATOR; |
1899 InvalidateWindow(WC_COMPANY, p1); |
1918 InvalidateWindow(WC_COMPANY, p1); |
1900 } |
1919 } |
1901 return CommandCost(cost); |
1920 return CommandCost(EXPENSES_OTHER, cost); |
1902 } |
1921 } |
1903 |
1922 |
1904 /** Buy up another company. |
1923 /** Buy up another company. |
1905 * When a competing company is gone bankrupt you get the chance to purchase |
1924 * When a competing company is gone bankrupt you get the chance to purchase |
1906 * that company. |
1925 * that company. |
1919 if (!IsValidPlayer(pid) || _networking) return CMD_ERROR; |
1938 if (!IsValidPlayer(pid) || _networking) return CMD_ERROR; |
1920 |
1939 |
1921 /* Do not allow players to take over themselves */ |
1940 /* Do not allow players to take over themselves */ |
1922 if (pid == _current_player) return CMD_ERROR; |
1941 if (pid == _current_player) return CMD_ERROR; |
1923 |
1942 |
1924 SET_EXPENSES_TYPE(EXPENSES_OTHER); |
|
1925 p = GetPlayer(pid); |
1943 p = GetPlayer(pid); |
1926 |
1944 |
1927 if (!p->is_ai) return CMD_ERROR; |
1945 if (!p->is_ai) return CMD_ERROR; |
1928 |
1946 |
1929 if (flags & DC_EXEC) { |
1947 if (flags & DC_EXEC) { |
1930 DoAcquireCompany(p); |
1948 DoAcquireCompany(p); |
1931 } |
1949 } |
1932 return CommandCost(p->bankrupt_value); |
1950 return CommandCost(EXPENSES_OTHER, p->bankrupt_value); |
1933 } |
1951 } |
1934 |
1952 |
1935 /** Prices */ |
1953 /** Prices */ |
1936 static void SaveLoad_PRIC() |
1954 static void SaveLoad_PRIC() |
1937 { |
1955 { |