File diff r12404:d58b2d050240 → r12405:ba094e765533
src/economy.cpp
Show inline comments
 
@@ -788,130 +788,130 @@ void StartupIndustryDailyChanges(bool in
 

	
 
	if (init_counter) {
 
		/* A new game or a savegame from an older version will require the counter to be initialized */
 
		_economy.industry_daily_change_counter = 0;
 
	}
 
}
 

	
 
void StartupEconomy()
 
{
 
	int i;
 

	
 
	assert(sizeof(_price) == NUM_PRICES * sizeof(Money));
 

	
 
	for (i = 0; i != NUM_PRICES; i++) {
 
		Money price = _price_base[i];
 
		if (_price_category[i] != 0) {
 
			uint mod = _price_category[i] == 1 ? _settings_game.difficulty.vehicle_costs : _settings_game.difficulty.construction_cost;
 
			if (mod < 1) {
 
				price = price * 3 >> 2;
 
			} else if (mod > 1) {
 
				price = price * 9 >> 3;
 
			}
 
		}
 
		if (price_base_multiplier[i] > 8) {
 
			price <<= price_base_multiplier[i] - 8;
 
		} else {
 
			price >>= 8 - price_base_multiplier[i];
 
		}
 
		((Money*)&_price)[i] = price;
 
		_price_frac[i] = 0;
 
	}
 

	
 
	_economy.interest_rate = _settings_game.difficulty.initial_interest;
 
	_economy.infl_amount = _settings_game.difficulty.initial_interest;
 
	_economy.infl_amount_pr = max(0, _settings_game.difficulty.initial_interest - 1);
 
	_economy.max_loan_unround = _economy.max_loan = _settings_game.difficulty.max_loan;
 
	_economy.fluct = GB(Random(), 0, 8) + 168;
 

	
 
	StartupIndustryDailyChanges(true); // As we are starting a new game, initialize the counter too
 

	
 
}
 

	
 
void ResetEconomy()
 
{
 
	/* Test if resetting the economy is needed. */
 
	bool needed = false;
 

	
 
	for (CargoID c = 0; c < NUM_CARGO; c++) {
 
		const CargoSpec *cs = GetCargo(c);
 
		const CargoSpec *cs = CargoSpec::Get(c);
 
		if (!cs->IsValid()) continue;
 
		if (_cargo_payment_rates[c] == 0) {
 
			needed = true;
 
			break;
 
		}
 
	}
 

	
 
	if (!needed) return;
 

	
 
	/* Remember old unrounded maximum loan value. NewGRF has the ability
 
	 * to change all the other inflation affected base costs. */
 
	Money old_value = _economy.max_loan_unround;
 

	
 
	/* Reset the economy */
 
	StartupEconomy();
 
	InitializeLandscapeVariables(false);
 

	
 
	/* Reapply inflation, ignoring the year */
 
	while (old_value > _economy.max_loan_unround) {
 
		AddInflation(false);
 
	}
 
}
 

	
 
Money GetPriceByIndex(uint8 index)
 
{
 
	if (index > NUM_PRICES) return 0;
 

	
 
	return ((Money*)&_price)[index];
 
}
 

	
 
Money GetTransportedGoodsIncome(uint num_pieces, uint dist, byte transit_days, CargoID cargo_type)
 
{
 
	const CargoSpec *cs = GetCargo(cargo_type);
 
	const CargoSpec *cs = CargoSpec::Get(cargo_type);
 

	
 
	/* Use callback to calculate cargo profit, if available */
 
	if (HasBit(cs->callback_mask, CBM_CARGO_PROFIT_CALC)) {
 
		uint32 var18 = min(dist, 0xFFFF) | (min(num_pieces, 0xFF) << 16) | (transit_days << 24);
 
		uint16 callback = GetCargoCallback(CBID_CARGO_PROFIT_CALC, 0, var18, cs);
 
		if (callback != CALLBACK_FAILED) {
 
			int result = GB(callback, 0, 14);
 

	
 
			/* Simulate a 15 bit signed value */
 
			if (HasBit(callback, 14)) result = 0x4000 - result;
 

	
 
			/* "The result should be a signed multiplier that gets multiplied
 
			 * by the amount of cargo moved and the price factor, then gets
 
			 * divided by 8192." */
 
			return result * num_pieces * _cargo_payment_rates[cargo_type] / 8192;
 
		}
 
	}
 

	
 
	/* zero the distance (thus income) if it's the bank and very short transport. */
 
	if (_settings_game.game_creation.landscape == LT_TEMPERATE && cs->label == 'VALU' && dist < 10) return 0;
 

	
 

	
 
	static const int MIN_TIME_FACTOR = 31;
 
	static const int MAX_TIME_FACTOR = 255;
 

	
 
	const int days1 = cs->transit_days[0];
 
	const int days2 = cs->transit_days[1];
 
	const int days_over_days1 = max(   transit_days - days1, 0);
 
	const int days_over_days2 = max(days_over_days1 - days2, 0);
 

	
 
	/*
 
	 * The time factor is calculated based on the time it took
 
	 * (transit_days) compared two cargo-depending values. The
 
	 * range is divided into three parts:
 
	 *
 
	 *  - constant for fast transits
 
	 *  - linear decreasing with time with a slope of -1 for medium transports
 
	 *  - linear decreasing with time with a slope of -2 for slow transports
 
	 *
 
	 */
 
	const int time_factor = max(MAX_TIME_FACTOR - days_over_days1 - days_over_days2, MIN_TIME_FACTOR);
 

	
 
	return BigMulS(dist * time_factor * num_pieces, _cargo_payment_rates[cargo_type], 21);
 
}
 

	
 
/**
 
 * @note THIS STRUCTURE WILL BE REMOVED SOON!
 
 */
 
@@ -1044,97 +1044,97 @@ static void DeliverGoodsToIndustry(const
 
		if (HasBit(indspec->callback_flags, CBM_IND_REFUSE_CARGO)) {
 
			uint16 res = GetIndustryCallback(CBID_INDUSTRY_REFUSE_CARGO, 0, GetReverseCargoTranslation(cargo_type, indspec->grf_prop.grffile), ind, ind->type, ind->xy);
 
			if (res == 0) continue;
 
		}
 

	
 
		/* Insert the industry into _cargo_delivery_destinations, if not yet contained */
 
		_cargo_delivery_destinations.Include(ind);
 

	
 
		assert(DeliverGoodsToIndustryCheckOldStyle(st, cargo_type, num_pieces) == ind); // safety check, will be removed soon
 

	
 
		ind->incoming_cargo_waiting[cargo_index] = min(num_pieces + ind->incoming_cargo_waiting[cargo_index], 0xFFFF);
 

	
 
		return;
 
	}
 

	
 
	assert(DeliverGoodsToIndustryCheckOldStyle(st, cargo_type, num_pieces) == NULL); // safety check, will be removed soon
 
}
 

	
 
/**
 
 * Delivers goods to industries/towns and calculates the payment
 
 * @param num_pieces amount of cargo delivered
 
 * @param source Originstation of the cargo
 
 * @param dest Station the cargo has been unloaded
 
 * @param source_tile The origin of the cargo for distance calculation
 
 * @param days_in_transit Travel time
 
 * @param company The company delivering the cargo
 
 * The cargo is just added to the stockpile of the industry. It is due to the caller to trigger the industry's production machinery
 
 */
 
static Money DeliverGoods(int num_pieces, CargoID cargo_type, StationID source, StationID dest, TileIndex source_tile, byte days_in_transit, Company *company)
 
{
 
	bool subsidised = false;
 

	
 
	assert(num_pieces > 0);
 

	
 
	/* Update company statistics */
 
	company->cur_economy.delivered_cargo += num_pieces;
 
	SetBit(company->cargo_types, cargo_type);
 

	
 
	const Station *s_to = Station::Get(dest);
 

	
 
	if (source != INVALID_STATION) {
 
		const Station *s_from = Station::Get(source);
 

	
 
		/* Check if a subsidy applies. */
 
		subsidised = CheckSubsidised(s_from, s_to, cargo_type, company->index);
 
	}
 

	
 
	/* Increase town's counter for some special goods types */
 
	const CargoSpec *cs = GetCargo(cargo_type);
 
	const CargoSpec *cs = CargoSpec::Get(cargo_type);
 
	if (cs->town_effect == TE_FOOD) s_to->town->new_act_food += num_pieces;
 
	if (cs->town_effect == TE_WATER) s_to->town->new_act_water += num_pieces;
 

	
 
	/* Give the goods to the industry. */
 
	DeliverGoodsToIndustry(s_to, cargo_type, num_pieces);
 

	
 
	/* Determine profit */
 
	Money profit = GetTransportedGoodsIncome(num_pieces, DistanceManhattan(source_tile, s_to->xy), days_in_transit, cargo_type);
 

	
 
	/* Modify profit if a subsidy is in effect */
 
	if (subsidised) {
 
		switch (_settings_game.difficulty.subsidy_multiplier) {
 
			case 0:  profit += profit >> 1; break;
 
			case 1:  profit *= 2; break;
 
			case 2:  profit *= 3; break;
 
			default: profit *= 4; break;
 
		}
 
	}
 

	
 
	return profit;
 
}
 

	
 
/**
 
 * Inform the industry about just delivered cargo
 
 * DeliverGoodsToIndustry() silently incremented incoming_cargo_waiting, now it is time to do something with the new cargo.
 
 * @param i The industry to process
 
 */
 
static void TriggerIndustryProduction(Industry *i)
 
{
 
	const IndustrySpec *indspec = GetIndustrySpec(i->type);
 
	uint16 callback = indspec->callback_flags;
 

	
 
	i->was_cargo_delivered = true;
 
	i->last_cargo_accepted_at = _date;
 

	
 
	if (HasBit(callback, CBM_IND_PRODUCTION_CARGO_ARRIVAL) || HasBit(callback, CBM_IND_PRODUCTION_256_TICKS)) {
 
		if (HasBit(callback, CBM_IND_PRODUCTION_CARGO_ARRIVAL)) {
 
			IndustryProductionCallback(i, 0);
 
		} else {
 
			InvalidateWindow(WC_INDUSTRY_VIEW, i->index);
 
		}
 
	} else {
 
		for (uint cargo_index = 0; cargo_index < lengthof(i->incoming_cargo_waiting); cargo_index++) {
 
			uint cargo_waiting = i->incoming_cargo_waiting[cargo_index];
 
			if (cargo_waiting == 0) continue;
 

	
 
			i->produced_cargo_waiting[0] = min(i->produced_cargo_waiting[0] + (cargo_waiting * indspec->input_cargo_multiplier[cargo_index][0] / 256), 0xFFFF);
 
			i->produced_cargo_waiting[1] = min(i->produced_cargo_waiting[1] + (cargo_waiting * indspec->input_cargo_multiplier[cargo_index][1] / 256), 0xFFFF);