src/economy.cpp
branchgamebalance
changeset 9895 7bd07f43b0e3
parent 6525 52bebe2b485e
child 9901 a922f277ebfd
equal deleted inserted replaced
9894:70d78ac95d6c 9895:7bd07f43b0e3
    77 		Vehicle *v;
    77 		Vehicle *v;
    78 
    78 
    79 		FOR_ALL_VEHICLES(v) {
    79 		FOR_ALL_VEHICLES(v) {
    80 			if (v->owner != owner) continue;
    80 			if (v->owner != owner) continue;
    81 
    81 
    82 			if (v->type == VEH_Train ||
    82 			if (v->type == VEH_TRAIN ||
    83 					v->type == VEH_Road ||
    83 					v->type == VEH_ROAD ||
    84 					(v->type == VEH_Aircraft && IsNormalAircraft(v)) ||
    84 					(v->type == VEH_AIRCRAFT && IsNormalAircraft(v)) ||
    85 					v->type == VEH_Ship) {
    85 					v->type == VEH_SHIP) {
    86 				value += v->value * 3 >> 1;
    86 				value += v->value * 3 >> 1;
    87 			}
    87 			}
    88 		}
    88 		}
    89 	}
    89 	}
    90 
    90 
   113 		bool min_profit_first = true;
   113 		bool min_profit_first = true;
   114 		uint num = 0;
   114 		uint num = 0;
   115 
   115 
   116 		FOR_ALL_VEHICLES(v) {
   116 		FOR_ALL_VEHICLES(v) {
   117 			if (v->owner != owner) continue;
   117 			if (v->owner != owner) continue;
   118 			if ((v->type == VEH_Train && IsFrontEngine(v)) ||
   118 			if ((v->type == VEH_TRAIN && IsFrontEngine(v)) ||
   119 					 v->type == VEH_Road ||
   119 					 v->type == VEH_ROAD ||
   120 					(v->type == VEH_Aircraft && IsNormalAircraft(v)) ||
   120 					(v->type == VEH_AIRCRAFT && IsNormalAircraft(v)) ||
   121 					 v->type == VEH_Ship) {
   121 					 v->type == VEH_SHIP) {
   122 				num++;
   122 				num++;
   123 				if (v->age > 730) {
   123 				if (v->age > 730) {
   124 					/* Find the vehicle with the lowest amount of profit */
   124 					/* Find the vehicle with the lowest amount of profit */
   125 					if (min_profit_first == true) {
   125 					if (min_profit_first == true) {
   126 						min_profit = v->profit_last_year;
   126 						min_profit = v->profit_last_year;
   303 
   303 
   304 		/*  Determine Ids for the new vehicles */
   304 		/*  Determine Ids for the new vehicles */
   305 		FOR_ALL_VEHICLES(v) {
   305 		FOR_ALL_VEHICLES(v) {
   306 			if (v->owner == new_player) {
   306 			if (v->owner == new_player) {
   307 				switch (v->type) {
   307 				switch (v->type) {
   308 					case VEH_Train:    if (IsFrontEngine(v)) num_train++; break;
   308 					case VEH_TRAIN:    if (IsFrontEngine(v)) num_train++; break;
   309 					case VEH_Road:     num_road++; break;
   309 					case VEH_ROAD:     num_road++; break;
   310 					case VEH_Ship:     num_ship++; break;
   310 					case VEH_SHIP:     num_ship++; break;
   311 					case VEH_Aircraft: if (IsNormalAircraft(v)) num_aircraft++; break;
   311 					case VEH_AIRCRAFT: if (IsNormalAircraft(v)) num_aircraft++; break;
   312 					default: break;
   312 					default: break;
   313 				}
   313 				}
   314 			}
   314 			}
   315 		}
   315 		}
   316 
   316 
   317 		FOR_ALL_VEHICLES(v) {
   317 		FOR_ALL_VEHICLES(v) {
   318 			if (v->owner == old_player && IS_BYTE_INSIDE(v->type, VEH_Train, VEH_Aircraft + 1)) {
   318 			if (v->owner == old_player && IS_BYTE_INSIDE(v->type, VEH_TRAIN, VEH_AIRCRAFT + 1)) {
   319 				if (new_player == PLAYER_SPECTATOR) {
   319 				if (new_player == PLAYER_SPECTATOR) {
   320 					DeleteWindowById(WC_VEHICLE_VIEW, v->index);
   320 					DeleteWindowById(WC_VEHICLE_VIEW, v->index);
   321 					DeleteWindowById(WC_VEHICLE_DETAILS, v->index);
   321 					DeleteWindowById(WC_VEHICLE_DETAILS, v->index);
   322 					DeleteWindowById(WC_VEHICLE_ORDERS, v->index);
   322 					DeleteWindowById(WC_VEHICLE_ORDERS, v->index);
   323 					DeleteVehicle(v);
   323 					DeleteVehicle(v);
   324 				} else {
   324 				} else {
   325 					v->owner = new_player;
   325 					v->owner = new_player;
   326 					if (IsEngineCountable(v)) GetPlayer(new_player)->num_engines[v->engine_type]++;
   326 					if (IsEngineCountable(v)) GetPlayer(new_player)->num_engines[v->engine_type]++;
   327 					switch (v->type) {
   327 					switch (v->type) {
   328 						case VEH_Train:    if (IsFrontEngine(v)) v->unitnumber = ++num_train; break;
   328 						case VEH_TRAIN:    if (IsFrontEngine(v)) v->unitnumber = ++num_train; break;
   329 						case VEH_Road:     v->unitnumber = ++num_road; break;
   329 						case VEH_ROAD:     v->unitnumber = ++num_road; break;
   330 						case VEH_Ship:     v->unitnumber = ++num_ship; break;
   330 						case VEH_SHIP:     v->unitnumber = ++num_ship; break;
   331 						case VEH_Aircraft: if (IsNormalAircraft(v)) v->unitnumber = ++num_aircraft; break;
   331 						case VEH_AIRCRAFT: if (IsNormalAircraft(v)) v->unitnumber = ++num_aircraft; break;
   332 					}
   332 					}
   333 				}
   333 				}
   334 			}
   334 			}
   335 		}
   335 		}
   336 	}
   336 	}
   366 	}
   366 	}
   367 
   367 
   368 	_current_player = old;
   368 	_current_player = old;
   369 
   369 
   370 	MarkWholeScreenDirty();
   370 	MarkWholeScreenDirty();
       
   371 }
       
   372 
       
   373 static void ChangeNetworkOwner(PlayerID current_player, PlayerID new_player)
       
   374 {
       
   375 #ifdef ENABLE_NETWORK
       
   376 	if (!_networking) return;
       
   377 
       
   378 	if (current_player == _local_player) {
       
   379 		_network_playas = new_player;
       
   380 		SetLocalPlayer(new_player);
       
   381 	}
       
   382 
       
   383 	if (!_network_server) return;
       
   384 
       
   385 	/* The server has to handle all administrative issues, for example
       
   386 	* updating and notifying all clients of what has happened */
       
   387 	NetworkTCPSocketHandler *cs;
       
   388 	NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
       
   389 
       
   390 	/* The server has just changed from player */
       
   391 	if (current_player == ci->client_playas) {
       
   392 		ci->client_playas = new_player;
       
   393 		NetworkUpdateClientInfo(NETWORK_SERVER_INDEX);
       
   394 	}
       
   395 
       
   396 	/* Find all clients that were in control of this company, and mark them as new_player */
       
   397 	FOR_ALL_CLIENTS(cs) {
       
   398 		ci = DEREF_CLIENT_INFO(cs);
       
   399 		if (current_player == ci->client_playas) {
       
   400 			ci->client_playas = new_player;
       
   401 			NetworkUpdateClientInfo(ci->client_index);
       
   402 		}
       
   403 	}
       
   404 #endif /* ENABLE_NETWORK */
   371 }
   405 }
   372 
   406 
   373 static void PlayersCheckBankrupt(Player *p)
   407 static void PlayersCheckBankrupt(Player *p)
   374 {
   408 {
   375 	PlayerID owner;
   409 	PlayerID owner;
   425 				 * he/she is no long in control of this company */
   459 				 * he/she is no long in control of this company */
   426 				if (!_networking) {
   460 				if (!_networking) {
   427 					p->bankrupt_asked = 0xFF;
   461 					p->bankrupt_asked = 0xFF;
   428 					p->bankrupt_timeout = 0x456;
   462 					p->bankrupt_timeout = 0x456;
   429 					break;
   463 					break;
   430 				} else if (owner == _local_player) {
       
   431 					_network_playas = PLAYER_SPECTATOR;
       
   432 					SetLocalPlayer(PLAYER_SPECTATOR);
       
   433 				}
   464 				}
   434 
   465 
   435 #ifdef ENABLE_NETWORK
   466 				ChangeNetworkOwner(owner, PLAYER_SPECTATOR);
   436 				/* The server has to handle all administrative issues, for example
       
   437 				 * updating and notifying all clients of what has happened */
       
   438 				if (_network_server) {
       
   439 					NetworkTCPSocketHandler *cs;
       
   440 					NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
       
   441 
       
   442 					/* The server has just gone belly-up, mark it as spectator */
       
   443 					if (owner == ci->client_playas) {
       
   444 						ci->client_playas = PLAYER_SPECTATOR;
       
   445 						NetworkUpdateClientInfo(NETWORK_SERVER_INDEX);
       
   446 					}
       
   447 
       
   448 					/* Find all clients that were in control of this company,
       
   449 					 * and mark them as spectator; broadcast this message to everyone */
       
   450 					FOR_ALL_CLIENTS(cs) {
       
   451 						ci = DEREF_CLIENT_INFO(cs);
       
   452 						if (ci->client_playas == owner) {
       
   453 							ci->client_playas = PLAYER_SPECTATOR;
       
   454 							NetworkUpdateClientInfo(ci->client_index);
       
   455 						}
       
   456 					}
       
   457 				}
       
   458 #endif /* ENABLE_NETWORK */
       
   459 			}
   467 			}
   460 
   468 
   461 			/* Remove the player */
   469 			/* Remove the player */
   462 			ChangeOwnershipOfPlayerItems(owner, PLAYER_SPECTATOR);
   470 			ChangeOwnershipOfPlayerItems(owner, PLAYER_SPECTATOR);
   463 			/* Register the player as not-active */
   471 			/* Register the player as not-active */
   579 
   587 
   580 	/* useless, but avoids compiler warning this way */
   588 	/* useless, but avoids compiler warning this way */
   581 	return 0;
   589 	return 0;
   582 }
   590 }
   583 
   591 
   584 static void PlayersGenStatistics(void)
   592 static void PlayersGenStatistics()
   585 {
   593 {
   586 	Station *st;
   594 	Station *st;
   587 	Player *p;
   595 	Player *p;
   588 
   596 
   589 	FOR_ALL_STATIONS(st) {
   597 	FOR_ALL_STATIONS(st) {
   623 	int64 tmp = (int64)*value * amt + *frac;
   631 	int64 tmp = (int64)*value * amt + *frac;
   624 	*frac   = GB(tmp, 0, 16);
   632 	*frac   = GB(tmp, 0, 16);
   625 	*value += tmp >> 16;
   633 	*value += tmp >> 16;
   626 }
   634 }
   627 
   635 
   628 static void AddInflation(void)
   636 static void AddInflation()
   629 {
   637 {
   630 	/* Approximation for (100 + infl_amount)% ** (1 / 12) - 100%
   638 	/* Approximation for (100 + infl_amount)% ** (1 / 12) - 100%
   631 	 * scaled by 65536
   639 	 * scaled by 65536
   632 	 * 12 -> months per year
   640 	 * 12 -> months per year
   633 	 * This is only a good approxiamtion for small values
   641 	 * This is only a good approxiamtion for small values
   656 	InvalidateWindowClasses(WC_REPLACE_VEHICLE);
   664 	InvalidateWindowClasses(WC_REPLACE_VEHICLE);
   657 	InvalidateWindowClasses(WC_VEHICLE_DETAILS);
   665 	InvalidateWindowClasses(WC_VEHICLE_DETAILS);
   658 	InvalidateWindow(WC_PAYMENT_RATES, 0);
   666 	InvalidateWindow(WC_PAYMENT_RATES, 0);
   659 }
   667 }
   660 
   668 
   661 static void PlayersPayInterest(void)
   669 static void PlayersPayInterest()
   662 {
   670 {
   663 	const Player* p;
   671 	const Player* p;
   664 	int interest = _economy.interest_rate * 54;
   672 	int interest = _economy.interest_rate * 54;
   665 
   673 
   666 	FOR_ALL_PLAYERS(p) {
   674 	FOR_ALL_PLAYERS(p) {
   674 		SET_EXPENSES_TYPE(EXPENSES_OTHER);
   682 		SET_EXPENSES_TYPE(EXPENSES_OTHER);
   675 		SubtractMoneyFromPlayer(_price.station_value >> 2);
   683 		SubtractMoneyFromPlayer(_price.station_value >> 2);
   676 	}
   684 	}
   677 }
   685 }
   678 
   686 
   679 static void HandleEconomyFluctuations(void)
   687 static void HandleEconomyFluctuations()
   680 {
   688 {
   681 	if (_opt.diff.economy == 0) return;
   689 	if (_opt.diff.economy == 0) return;
   682 
   690 
   683 	if (--_economy.fluct == 0) {
   691 	if (--_economy.fluct == 0) {
   684 		_economy.fluct = -(int)GB(Random(), 0, 2);
   692 		_economy.fluct = -(int)GB(Random(), 0, 2);
   754 static byte price_base_multiplier[NUM_PRICES];
   762 static byte price_base_multiplier[NUM_PRICES];
   755 
   763 
   756 /**
   764 /**
   757  * Reset changes to the price base multipliers.
   765  * Reset changes to the price base multipliers.
   758  */
   766  */
   759 void ResetPriceBaseMultipliers(void)
   767 void ResetPriceBaseMultipliers()
   760 {
   768 {
   761 	uint i;
   769 	uint i;
   762 
   770 
   763 	/* 8 means no multiplier. */
   771 	/* 8 means no multiplier. */
   764 	for (i = 0; i < NUM_PRICES; i++)
   772 	for (i = 0; i < NUM_PRICES; i++)
   776 {
   784 {
   777 	assert(price < NUM_PRICES);
   785 	assert(price < NUM_PRICES);
   778 	price_base_multiplier[price] = factor;
   786 	price_base_multiplier[price] = factor;
   779 }
   787 }
   780 
   788 
   781 void StartupEconomy(void)
   789 void StartupEconomy()
   782 {
   790 {
   783 	int i;
   791 	int i;
   784 
   792 
   785 	assert(sizeof(_price) == NUM_PRICES * sizeof(int32));
   793 	assert(sizeof(_price) == NUM_PRICES * sizeof(int32));
   786 
   794 
   819 	/* if mode is false, use the singular form */
   827 	/* if mode is false, use the singular form */
   820 	const CargoSpec *cs = GetCargo(s->cargo_type);
   828 	const CargoSpec *cs = GetCargo(s->cargo_type);
   821 	SetDParam(0, mode ? cs->name_plural : cs->name);
   829 	SetDParam(0, mode ? cs->name_plural : cs->name);
   822 
   830 
   823 	if (s->age < 12) {
   831 	if (s->age < 12) {
   824 		if (s->cargo_type != CT_PASSENGERS && s->cargo_type != CT_MAIL) {
   832 		if (cs->town_effect != TE_PASSENGERS && cs->town_effect != TE_MAIL) {
   825 			SetDParam(1, STR_INDUSTRY);
   833 			SetDParam(1, STR_INDUSTRY);
   826 			SetDParam(2, s->from);
   834 			SetDParam(2, s->from);
   827 			tile = GetIndustry(s->from)->xy;
   835 			tile = GetIndustry(s->from)->xy;
   828 
   836 
   829 			if (s->cargo_type != CT_GOODS && s->cargo_type != CT_FOOD) {
   837 			if (cs->town_effect != TE_GOODS && cs->town_effect != TE_FOOD) {
   830 				SetDParam(4, STR_INDUSTRY);
   838 				SetDParam(4, STR_INDUSTRY);
   831 				SetDParam(5, s->to);
   839 				SetDParam(5, s->to);
   832 				tile2 = GetIndustry(s->to)->xy;
   840 				tile2 = GetIndustry(s->to)->xy;
   833 			} else {
   841 			} else {
   834 				SetDParam(4, STR_TOWN);
   842 				SetDParam(4, STR_TOWN);
   861 void DeleteSubsidyWithTown(TownID index)
   869 void DeleteSubsidyWithTown(TownID index)
   862 {
   870 {
   863 	Subsidy *s;
   871 	Subsidy *s;
   864 
   872 
   865 	for (s = _subsidies; s != endof(_subsidies); s++) {
   873 	for (s = _subsidies; s != endof(_subsidies); s++) {
   866 		if (s->cargo_type != CT_INVALID && s->age < 12 &&
   874 		if (s->cargo_type != CT_INVALID && s->age < 12) {
   867 				(((s->cargo_type == CT_PASSENGERS || s->cargo_type == CT_MAIL) && (index == s->from || index == s->to)) ||
   875 			const CargoSpec *cs = GetCargo(s->cargo_type);
   868 				((s->cargo_type == CT_GOODS || s->cargo_type == CT_FOOD) && index == s->to))) {
   876 			if (((cs->town_effect == TE_PASSENGERS || cs->town_effect == TE_MAIL) && (index == s->from || index == s->to)) ||
   869 			s->cargo_type = CT_INVALID;
   877 				((cs->town_effect == TE_GOODS || cs->town_effect == TE_FOOD) && index == s->to)) {
       
   878 				s->cargo_type = CT_INVALID;
       
   879 			}
   870 		}
   880 		}
   871 	}
   881 	}
   872 }
   882 }
   873 
   883 
   874 void DeleteSubsidyWithIndustry(IndustryID index)
   884 void DeleteSubsidyWithIndustry(IndustryID index)
   875 {
   885 {
   876 	Subsidy *s;
   886 	Subsidy *s;
   877 
   887 
   878 	for (s = _subsidies; s != endof(_subsidies); s++) {
   888 	for (s = _subsidies; s != endof(_subsidies); s++) {
   879 		if (s->cargo_type != CT_INVALID && s->age < 12 &&
   889 		if (s->cargo_type != CT_INVALID && s->age < 12) {
   880 				s->cargo_type != CT_PASSENGERS && s->cargo_type != CT_MAIL &&
   890 			const CargoSpec *cs = GetCargo(s->cargo_type);
   881 				(index == s->from || (s->cargo_type != CT_GOODS && s->cargo_type != CT_FOOD && index == s->to))) {
   891 			if (cs->town_effect != TE_PASSENGERS && cs->town_effect != TE_MAIL &&
   882 			s->cargo_type = CT_INVALID;
   892 				(index == s->from || (cs->town_effect != TE_GOODS && cs->town_effect != TE_FOOD && index == s->to))) {
       
   893 				s->cargo_type = CT_INVALID;
       
   894 			}
   883 		}
   895 		}
   884 	}
   896 	}
   885 }
   897 }
   886 
   898 
   887 void DeleteSubsidyWithStation(StationID index)
   899 void DeleteSubsidyWithStation(StationID index)
   899 
   911 
   900 	if (dirty)
   912 	if (dirty)
   901 		InvalidateWindow(WC_SUBSIDIES_LIST, 0);
   913 		InvalidateWindow(WC_SUBSIDIES_LIST, 0);
   902 }
   914 }
   903 
   915 
   904 typedef struct FoundRoute {
   916 struct FoundRoute {
   905 	uint distance;
   917 	uint distance;
   906 	CargoID cargo;
   918 	CargoID cargo;
   907 	void *from;
   919 	void *from;
   908 	void *to;
   920 	void *to;
   909 } FoundRoute;
   921 };
   910 
   922 
   911 static void FindSubsidyPassengerRoute(FoundRoute *fr)
   923 static void FindSubsidyPassengerRoute(FoundRoute *fr)
   912 {
   924 {
   913 	Town *from,*to;
   925 	Town *from,*to;
   914 
   926 
   947 	}
   959 	}
   948 
   960 
   949 	/* Quit if no production in this industry
   961 	/* Quit if no production in this industry
   950 	 * or if the cargo type is passengers
   962 	 * or if the cargo type is passengers
   951 	 * or if the pct transported is already large enough */
   963 	 * or if the pct transported is already large enough */
   952 	if (total == 0 || trans > 42 || cargo == CT_INVALID || cargo == CT_PASSENGERS)
   964 	if (total == 0 || trans > 42 || cargo == CT_INVALID) return;
   953 		return;
   965 
       
   966 	const CargoSpec *cs = GetCargo(cargo);
       
   967 	if (cs->town_effect == TE_PASSENGERS) return;
   954 
   968 
   955 	fr->cargo = cargo;
   969 	fr->cargo = cargo;
   956 
   970 
   957 	if (cargo == CT_GOODS || cargo == CT_FOOD) {
   971 	if (cs->town_effect == TE_GOODS || cs->town_effect == TE_FOOD) {
   958 		/*  The destination is a town */
   972 		/*  The destination is a town */
   959 		Town *t = GetRandomTown();
   973 		Town *t = GetRandomTown();
   960 
   974 
   961 		/* Only want big towns */
   975 		/* Only want big towns */
   962 		if (t == NULL || t->population < 900) return;
   976 		if (t == NULL || t->population < 900) return;
   993 	}
  1007 	}
   994 	return false;
  1008 	return false;
   995 }
  1009 }
   996 
  1010 
   997 
  1011 
   998 static void SubsidyMonthlyHandler(void)
  1012 static void SubsidyMonthlyHandler()
   999 {
  1013 {
  1000 	Subsidy *s;
  1014 	Subsidy *s;
  1001 	Pair pair;
  1015 	Pair pair;
  1002 	Station *st;
  1016 	Station *st;
  1003 	uint n;
  1017 	uint n;
  1045 			}
  1059 			}
  1046 			FindSubsidyCargoRoute(&fr);
  1060 			FindSubsidyCargoRoute(&fr);
  1047 			if (fr.distance <= 70) {
  1061 			if (fr.distance <= 70) {
  1048 				s->cargo_type = fr.cargo;
  1062 				s->cargo_type = fr.cargo;
  1049 				s->from = ((Industry*)fr.from)->index;
  1063 				s->from = ((Industry*)fr.from)->index;
  1050 				s->to = (fr.cargo == CT_GOODS || fr.cargo == CT_FOOD) ? ((Town*)fr.to)->index : ((Industry*)fr.to)->index;
  1064 				{
       
  1065 					const CargoSpec *cs = GetCargo(fr.cargo);
       
  1066 					s->to = (cs->town_effect == TE_GOODS || cs->town_effect == TE_FOOD) ? ((Town*)fr.to)->index : ((Industry*)fr.to)->index;
       
  1067 				}
  1051 	add_subsidy:
  1068 	add_subsidy:
  1052 				if (!CheckSubsidyDuplicate(s)) {
  1069 				if (!CheckSubsidyDuplicate(s)) {
  1053 					s->age = 0;
  1070 					s->age = 0;
  1054 					pair = SetupSubsidyDecodeParam(s, 0);
  1071 					pair = SetupSubsidyDecodeParam(s, 0);
  1055 					AddNewsItem(STR_2030_SERVICE_SUBSIDY_OFFERED, NEWS_FLAGS(NM_NORMAL, NF_TILE, NT_SUBSIDIES, 0), pair.a, pair.b);
  1072 					AddNewsItem(STR_2030_SERVICE_SUBSIDY_OFFERED, NEWS_FLAGS(NM_NORMAL, NF_TILE, NT_SUBSIDIES, 0), pair.a, pair.b);
  1072 	SLE_CONDVAR(Subsidy, to,         SLE_FILE_U8 | SLE_VAR_U16, 0, 4),
  1089 	SLE_CONDVAR(Subsidy, to,         SLE_FILE_U8 | SLE_VAR_U16, 0, 4),
  1073 	SLE_CONDVAR(Subsidy, to,         SLE_UINT16,                5, SL_MAX_VERSION),
  1090 	SLE_CONDVAR(Subsidy, to,         SLE_UINT16,                5, SL_MAX_VERSION),
  1074 	SLE_END()
  1091 	SLE_END()
  1075 };
  1092 };
  1076 
  1093 
  1077 static void Save_SUBS(void)
  1094 static void Save_SUBS()
  1078 {
  1095 {
  1079 	int i;
  1096 	int i;
  1080 	Subsidy *s;
  1097 	Subsidy *s;
  1081 
  1098 
  1082 	for (i = 0; i != lengthof(_subsidies); i++) {
  1099 	for (i = 0; i != lengthof(_subsidies); i++) {
  1086 			SlObject(s, _subsidies_desc);
  1103 			SlObject(s, _subsidies_desc);
  1087 		}
  1104 		}
  1088 	}
  1105 	}
  1089 }
  1106 }
  1090 
  1107 
  1091 static void Load_SUBS(void)
  1108 static void Load_SUBS()
  1092 {
  1109 {
  1093 	int index;
  1110 	int index;
  1094 	while ((index = SlIterateArray()) != -1)
  1111 	while ((index = SlIterateArray()) != -1)
  1095 		SlObject(&_subsidies[index], _subsidies_desc);
  1112 		SlObject(&_subsidies[index], _subsidies_desc);
  1096 }
  1113 }
  1100 	CargoID cargo = cargo_type;
  1117 	CargoID cargo = cargo_type;
  1101 	const CargoSpec *cs = GetCargo(cargo_type);
  1118 	const CargoSpec *cs = GetCargo(cargo_type);
  1102 	byte f;
  1119 	byte f;
  1103 
  1120 
  1104 	/* zero the distance if it's the bank and very short transport. */
  1121 	/* zero the distance if it's the bank and very short transport. */
  1105 	if (_opt.landscape == LT_NORMAL && cargo == CT_VALUABLES && dist < 10)
  1122 	if (_opt.landscape == LT_NORMAL && cs->label == 'VALU' && dist < 10)
  1106 		dist = 0;
  1123 		dist = 0;
  1107 
  1124 
  1108 	f = 255;
  1125 	f = 255;
  1109 	if (transit_days > cs->transit_days[0]) {
  1126 	if (transit_days > cs->transit_days[0]) {
  1110 		transit_days -= cs->transit_days[0];
  1127 		transit_days -= cs->transit_days[0];
  1177 
  1194 
  1178 	/* check if there's a new subsidy that applies.. */
  1195 	/* check if there's a new subsidy that applies.. */
  1179 	for (s = _subsidies; s != endof(_subsidies); s++) {
  1196 	for (s = _subsidies; s != endof(_subsidies); s++) {
  1180 		if (s->cargo_type == cargo_type && s->age < 12) {
  1197 		if (s->cargo_type == cargo_type && s->age < 12) {
  1181 			/* Check distance from source */
  1198 			/* Check distance from source */
  1182 			if (cargo_type == CT_PASSENGERS || cargo_type == CT_MAIL) {
  1199 			const CargoSpec *cs = GetCargo(cargo_type);
       
  1200 			if (cs->town_effect == TE_PASSENGERS || cs->town_effect == TE_MAIL) {
  1183 				xy = GetTown(s->from)->xy;
  1201 				xy = GetTown(s->from)->xy;
  1184 			} else {
  1202 			} else {
  1185 				xy = (GetIndustry(s->from))->xy;
  1203 				xy = (GetIndustry(s->from))->xy;
  1186 			}
  1204 			}
  1187 			if (DistanceMax(xy, from->xy) > 9) continue;
  1205 			if (DistanceMax(xy, from->xy) > 9) continue;
  1188 
  1206 
  1189 			/* Check distance from dest */
  1207 			/* Check distance from dest */
  1190 			switch (cargo_type) {
  1208 			switch (cs->town_effect) {
  1191 				case CT_PASSENGERS:
  1209 				case TE_PASSENGERS:
  1192 				case CT_MAIL:
  1210 				case TE_MAIL:
  1193 				case CT_GOODS:
  1211 				case TE_GOODS:
  1194 				case CT_FOOD:
  1212 				case TE_FOOD:
  1195 					xy = GetTown(s->to)->xy;
  1213 					xy = GetTown(s->to)->xy;
  1196 					break;
  1214 					break;
  1197 
  1215 
  1198 				default:
  1216 				default:
  1199 					xy = GetIndustry(s->to)->xy;
  1217 					xy = GetIndustry(s->to)->xy;
  1247 
  1265 
  1248 	/* Check if a subsidy applies. */
  1266 	/* Check if a subsidy applies. */
  1249 	subsidised = CheckSubsidised(s_from, s_to, cargo_type);
  1267 	subsidised = CheckSubsidised(s_from, s_to, cargo_type);
  1250 
  1268 
  1251 	/* Increase town's counter for some special goods types */
  1269 	/* Increase town's counter for some special goods types */
  1252 	if (cargo_type == CT_FOOD) s_to->town->new_act_food += num_pieces;
  1270 	const CargoSpec *cs = GetCargo(cargo_type);
  1253 	if (cargo_type == CT_WATER)  s_to->town->new_act_water += num_pieces;
  1271 	if (cs->town_effect == TE_FOOD) s_to->town->new_act_food += num_pieces;
       
  1272 	if (cs->town_effect == TE_WATER) s_to->town->new_act_water += num_pieces;
  1254 
  1273 
  1255 	/* Give the goods to the industry. */
  1274 	/* Give the goods to the industry. */
  1256 	DeliverGoodsToIndustry(s_to->xy, cargo_type, num_pieces);
  1275 	DeliverGoodsToIndustry(s_to->xy, cargo_type, num_pieces);
  1257 
  1276 
  1258 	/* Determine profit */
  1277 	/* Determine profit */
  1293 			has_any_cargo = true;
  1312 			has_any_cargo = true;
  1294 		}
  1313 		}
  1295 	}
  1314 	}
  1296 
  1315 
  1297 	FOR_ALL_VEHICLES(x) {
  1316 	FOR_ALL_VEHICLES(x) {
  1298 		if ((x->type != VEH_Train || IsFrontEngine(x)) && // for all locs
  1317 		if ((x->type != VEH_TRAIN || IsFrontEngine(x)) && // for all locs
  1299 				u->last_station_visited == x->last_station_visited && // at the same station
  1318 				u->last_station_visited == x->last_station_visited && // at the same station
  1300 				!(x->vehstatus & (VS_STOPPED | VS_CRASHED)) && // not stopped or crashed
  1319 				!(x->vehstatus & (VS_STOPPED | VS_CRASHED)) && // not stopped or crashed
  1301 				x->current_order.type == OT_LOADING && // loading
  1320 				x->current_order.type == OT_LOADING && // loading
  1302 				u != x) { // not itself
  1321 				u != x) { // not itself
  1303 			bool other_has_any_cargo = false;
  1322 			bool other_has_any_cargo = false;
  1366 	int all_vehicles_cargo_feeder_share = v->cargo_feeder_share; // used to hold transfer value of complete vehicle chain - used by trains
  1385 	int all_vehicles_cargo_feeder_share = v->cargo_feeder_share; // used to hold transfer value of complete vehicle chain - used by trains
  1367 
  1386 
  1368 	for (; v != NULL; v = v->next) {
  1387 	for (; v != NULL; v = v->next) {
  1369 		GoodsEntry* ge;
  1388 		GoodsEntry* ge;
  1370 		load_amount = EngInfo(v->engine_type)->load_amount;
  1389 		load_amount = EngInfo(v->engine_type)->load_amount;
  1371 		if (_patches.gradual_loading) {
  1390 		if (_patches.gradual_loading && HASBIT(EngInfo(v->engine_type)->callbackmask, CBM_LOAD_AMOUNT)) {
  1372 			uint16 cb_load_amount = GetVehicleCallback(CBID_VEHICLE_LOAD_AMOUNT, 0, 0, v->engine_type, v);
  1391 			uint16 cb_load_amount = GetVehicleCallback(CBID_VEHICLE_LOAD_AMOUNT, 0, 0, v->engine_type, v);
  1373 			if (cb_load_amount != CALLBACK_FAILED) load_amount = cb_load_amount & 0xFF;
  1392 			if (cb_load_amount != CALLBACK_FAILED) load_amount = cb_load_amount & 0xFF;
  1374 		}
  1393 		}
  1375 
  1394 
  1376 		if (v->cargo_cap == 0) continue;
  1395 		if (v->cargo_cap == 0) continue;
  1479 		if (u->current_order.flags & OF_UNLOAD) continue;
  1498 		if (u->current_order.flags & OF_UNLOAD) continue;
  1480 
  1499 
  1481 		/* update stats */
  1500 		/* update stats */
  1482 		ge->days_since_pickup = 0;
  1501 		ge->days_since_pickup = 0;
  1483 		switch (u->type) {
  1502 		switch (u->type) {
  1484 			case VEH_Train: t = u->u.rail.cached_max_speed; break;
  1503 			case VEH_TRAIN: t = u->u.rail.cached_max_speed; break;
  1485 			case VEH_Road:  t = u->max_speed / 2;           break;
  1504 			case VEH_ROAD:  t = u->max_speed / 2;           break;
  1486 			default:        t = u->max_speed;               break;
  1505 			default:        t = u->max_speed;               break;
  1487 		}
  1506 		}
  1488 
  1507 
  1489 		/* if last speed is 0, we treat that as if no vehicle has ever visited the station. */
  1508 		/* if last speed is 0, we treat that as if no vehicle has ever visited the station. */
  1490 		ge->last_speed = min(t, 255);
  1509 		ge->last_speed = min(t, 255);
  1564 
  1583 
  1565 	if (virtual_profit_total > 0) {
  1584 	if (virtual_profit_total > 0) {
  1566 		ShowFeederIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, virtual_profit_total);
  1585 		ShowFeederIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, virtual_profit_total);
  1567 	}
  1586 	}
  1568 
  1587 
  1569 	if (v->type == VEH_Train) {
  1588 	if (v->type == VEH_TRAIN) {
  1570 		/* Each platform tile is worth 2 rail vehicles. */
  1589 		/* Each platform tile is worth 2 rail vehicles. */
  1571 		int overhang = v->u.rail.cached_total_length - st->GetPlatformLength(v->tile) * TILE_SIZE;
  1590 		int overhang = v->u.rail.cached_total_length - st->GetPlatformLength(v->tile) * TILE_SIZE;
  1572 		if (overhang > 0) {
  1591 		if (overhang > 0) {
  1573 			unloading_time <<= 1;
  1592 			unloading_time <<= 1;
  1574 			unloading_time += (overhang * unloading_time) / 8;
  1593 			unloading_time += (overhang * unloading_time) / 8;
  1601 
  1620 
  1602 	_current_player = old_player;
  1621 	_current_player = old_player;
  1603 	return result;
  1622 	return result;
  1604 }
  1623 }
  1605 
  1624 
  1606 void PlayersMonthlyLoop(void)
  1625 void PlayersMonthlyLoop()
  1607 {
  1626 {
  1608 	PlayersGenStatistics();
  1627 	PlayersGenStatistics();
  1609 	if (_patches.inflation && _cur_year < MAX_YEAR)
  1628 	if (_patches.inflation && _cur_year < MAX_YEAR)
  1610 		AddInflation();
  1629 		AddInflation();
  1611 	PlayersPayInterest();
  1630 	PlayersPayInterest();
  1626 	SetDParam(2, p->bankrupt_value);
  1645 	SetDParam(2, p->bankrupt_value);
  1627 	AddNewsItem( (StringID)(_current_player | NB_BMERGER), NEWS_FLAGS(NM_CALLBACK, 0, NT_COMPANY_INFO, DNC_BANKRUPCY),0,0);
  1646 	AddNewsItem( (StringID)(_current_player | NB_BMERGER), NEWS_FLAGS(NM_CALLBACK, 0, NT_COMPANY_INFO, DNC_BANKRUPCY),0,0);
  1628 
  1647 
  1629 	/* original code does this a little bit differently */
  1648 	/* original code does this a little bit differently */
  1630 	PlayerID pi = p->index;
  1649 	PlayerID pi = p->index;
       
  1650 	ChangeNetworkOwner(pi, _current_player);
  1631 	ChangeOwnershipOfPlayerItems(pi, _current_player);
  1651 	ChangeOwnershipOfPlayerItems(pi, _current_player);
  1632 
  1652 
  1633 	if (p->bankrupt_value == 0) {
  1653 	if (p->bankrupt_value == 0) {
  1634 		owner = GetPlayer(_current_player);
  1654 		owner = GetPlayer(_current_player);
  1635 		owner->current_loan += p->current_loan;
  1655 		owner->current_loan += p->current_loan;
  1755 	}
  1775 	}
  1756 	return p->bankrupt_value;
  1776 	return p->bankrupt_value;
  1757 }
  1777 }
  1758 
  1778 
  1759 /** Prices */
  1779 /** Prices */
  1760 static void SaveLoad_PRIC(void)
  1780 static void SaveLoad_PRIC()
  1761 {
  1781 {
  1762 	SlArray(&_price,      NUM_PRICES, SLE_INT32);
  1782 	SlArray(&_price,      NUM_PRICES, SLE_INT32);
  1763 	SlArray(&_price_frac, NUM_PRICES, SLE_UINT16);
  1783 	SlArray(&_price_frac, NUM_PRICES, SLE_UINT16);
  1764 }
  1784 }
  1765 
  1785 
  1766 /** Cargo payment rates */
  1786 /** Cargo payment rates */
  1767 static void SaveLoad_CAPR(void)
  1787 static void SaveLoad_CAPR()
  1768 {
  1788 {
  1769 	SlArray(&_cargo_payment_rates,      NUM_CARGO, SLE_INT32);
  1789 	SlArray(&_cargo_payment_rates,      NUM_CARGO, SLE_INT32);
  1770 	SlArray(&_cargo_payment_rates_frac, NUM_CARGO, SLE_UINT16);
  1790 	SlArray(&_cargo_payment_rates_frac, NUM_CARGO, SLE_UINT16);
  1771 }
  1791 }
  1772 
  1792 
  1779 	SLE_VAR(Economy, infl_amount_pr,   SLE_UINT8),
  1799 	SLE_VAR(Economy, infl_amount_pr,   SLE_UINT8),
  1780 	SLE_END()
  1800 	SLE_END()
  1781 };
  1801 };
  1782 
  1802 
  1783 /** Economy variables */
  1803 /** Economy variables */
  1784 static void SaveLoad_ECMY(void)
  1804 static void SaveLoad_ECMY()
  1785 {
  1805 {
  1786 	SlObject(&_economy, _economy_desc);
  1806 	SlObject(&_economy, _economy_desc);
  1787 }
  1807 }
  1788 
  1808 
  1789 extern const ChunkHandler _economy_chunk_handlers[] = {
  1809 extern const ChunkHandler _economy_chunk_handlers[] = {