|
@@ -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);
|