Changeset - r24430:e39e393df7ba
[Not reviewed]
master
0 8 0
Pavel Stupnikov - 3 years ago 2020-12-14 22:35:07
dp@dpointer.org
Add: new economy "frozen" that stops production changes and industry closures (#8282)
8 files changed with 54 insertions and 35 deletions:
0 comments (0 inline, 0 general)
src/economy_type.h
Show inline comments
 
@@ -12,12 +12,21 @@
 

	
 
#include "core/overflowsafe_type.hpp"
 
#include "core/enum_type.hpp"
 

	
 
typedef OverflowSafeInt64 Money;
 

	
 
/** Type of the game economy. */
 
enum EconomyType : uint8 {
 
	ET_BEGIN = 0,
 
	ET_ORIGINAL = 0,
 
	ET_SMOOTH = 1,
 
	ET_FROZEN = 2,
 
	ET_END = 3,
 
};
 

	
 
/** Data of the economy. */
 
struct Economy {
 
	Money max_loan;                       ///< NOSAVE: Maximum possible loan
 
	int16 fluct;                          ///< Economy fluctuation status
 
	byte interest_rate;                   ///< Interest
 
	byte infl_amount;                     ///< inflation amount
src/industry_cmd.cpp
Show inline comments
 
@@ -1733,14 +1733,14 @@ static void DoCreateNewIndustry(Industry
 
	MemSetT(i->this_month_transported,     0, lengthof(i->this_month_transported));
 
	MemSetT(i->last_month_pct_transported, 0, lengthof(i->last_month_pct_transported));
 
	MemSetT(i->last_month_transported,     0, lengthof(i->last_month_transported));
 
	MemSetT(i->incoming_cargo_waiting,     0, lengthof(i->incoming_cargo_waiting));
 
	MemSetT(i->last_cargo_accepted_at,     0, lengthof(i->last_cargo_accepted_at));
 

	
 
	/* don't use smooth economy for industries using production related callbacks */
 
	if (indspec->UsesSmoothEconomy()) {
 
	/* Randomize inital production if non-original economy is used and there are no production related callbacks. */
 
	if (!indspec->UsesOriginalEconomy()) {
 
		for (size_t ci = 0; ci < lengthof(i->production_rate); ci++) {
 
			i->production_rate[ci] = min((RandomRange(256) + 128) * i->production_rate[ci] >> 8, 255);
 
		}
 
	}
 

	
 
	i->town = t;
 
@@ -2301,13 +2301,13 @@ static void UpdateIndustryStatistics(Ind
 
 * Recompute #production_rate for current #prod_level.
 
 * This function is only valid when not using smooth economy.
 
 */
 
void Industry::RecomputeProductionMultipliers()
 
{
 
	const IndustrySpec *indspec = GetIndustrySpec(this->type);
 
	assert(!indspec->UsesSmoothEconomy());
 
	assert(indspec->UsesOriginalEconomy());
 

	
 
	/* Rates are rounded up, so e.g. oilrig always produces some passengers */
 
	for (size_t i = 0; i < lengthof(this->production_rate); i++) {
 
		this->production_rate[i] = min(CeilDiv(indspec->production_rate[i] * this->prod_level, PRODLEVEL_DEFAULT), 0xFF);
 
	}
 
}
 
@@ -2601,14 +2601,14 @@ static void ChangeIndustryProduction(Ind
 
	StringID str = STR_NULL;
 
	bool closeit = false;
 
	const IndustrySpec *indspec = GetIndustrySpec(i->type);
 
	bool standard = false;
 
	bool suppress_message = false;
 
	bool recalculate_multipliers = false; ///< reinitialize production_rate to match prod_level
 
	/* don't use smooth economy for industries using production related callbacks */
 
	bool smooth_economy = indspec->UsesSmoothEconomy();
 
	/* use original economy for industries using production related callbacks */
 
	bool original_economy = indspec->UsesOriginalEconomy();
 
	byte div = 0;
 
	byte mul = 0;
 
	int8 increment = 0;
 

	
 
	bool callback_enabled = HasBit(indspec->callback_mask, monthly ? CBM_IND_MONTHLYPROD_CHANGE : CBM_IND_PRODUCTION_CHANGE);
 
	if (callback_enabled) {
 
@@ -2637,21 +2637,31 @@ static void ChangeIndustryProduction(Ind
 
					i->prod_level = Clamp(GB(GetRegister(0x100), 16, 8), PRODLEVEL_MINIMUM, PRODLEVEL_MAXIMUM);
 
					recalculate_multipliers = true;
 
					break;
 
			}
 
		}
 
	} else {
 
		if (monthly != smooth_economy) return;
 
		if (monthly == original_economy) return;
 
		if (!original_economy && _settings_game.economy.type == ET_FROZEN) return;
 
		if (indspec->life_type == INDUSTRYLIFE_BLACK_HOLE) return;
 
	}
 

	
 
	if (standard || (!callback_enabled && (indspec->life_type & (INDUSTRYLIFE_ORGANIC | INDUSTRYLIFE_EXTRACTIVE)) != 0)) {
 
		/* decrease or increase */
 
		bool only_decrease = (indspec->behaviour & INDUSTRYBEH_DONT_INCR_PROD) && _settings_game.game_creation.landscape == LT_TEMPERATE;
 

	
 
		if (smooth_economy) {
 
		if (original_economy) {
 
			if (only_decrease || Chance16(1, 3)) {
 
				/* If more than 60% transported, 66% chance of increase, else 33% chance of increase */
 
				if (!only_decrease && (i->last_month_pct_transported[0] > PERCENT_TRANSPORTED_60) != Chance16(1, 3)) {
 
					mul = 1; // Increase production
 
				} else {
 
					div = 1; // Decrease production
 
				}
 
			}
 
		} else if (_settings_game.economy.type == ET_SMOOTH) {
 
			closeit = true;
 
			for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
 
				if (i->produced_cargo[j] == CT_INVALID) continue;
 
				uint32 r = Random();
 
				int old_prod, new_prod, percent;
 
				/* If over 60% is transported, mult is 1, else mult is -1. */
 
@@ -2695,26 +2705,17 @@ static void ChangeIndustryProduction(Ind
 
				if (new_prod > 1) closeit = false;
 

	
 
				if (abs(percent) >= 10) {
 
					ReportNewsProductionChangeIndustry(i, i->produced_cargo[j], percent);
 
				}
 
			}
 
		} else {
 
			if (only_decrease || Chance16(1, 3)) {
 
				/* If more than 60% transported, 66% chance of increase, else 33% chance of increase */
 
				if (!only_decrease && (i->last_month_pct_transported[0] > PERCENT_TRANSPORTED_60) != Chance16(1, 3)) {
 
					mul = 1; // Increase production
 
				} else {
 
					div = 1; // Decrease production
 
				}
 
			}
 
		}
 
	}
 

	
 
	if (!callback_enabled && (indspec->life_type & INDUSTRYLIFE_PROCESSING)) {
 
		if ( (byte)(_cur_year - i->last_prod_year) >= 5 && Chance16(1, smooth_economy ? 180 : 2)) {
 
		if ( (byte)(_cur_year - i->last_prod_year) >= 5 && Chance16(1, original_economy ? 2 : 180)) {
 
			closeit = true;
 
		}
 
	}
 

	
 
	/* Increase if needed */
 
	while (mul-- != 0 && i->prod_level < PRODLEVEL_MAXIMUM) {
 
@@ -2931,20 +2932,20 @@ Money IndustrySpec::GetConstructionCost(
 
Money IndustrySpec::GetRemovalCost() const
 
{
 
	return (_price[PR_CLEAR_INDUSTRY] * this->removal_cost_multiplier) >> 8;
 
}
 

	
 
/**
 
 * Determines whether this industrytype uses smooth economy or whether it uses standard/newgrf production changes.
 
 * @return true if smooth economy is used.
 
 * Determines whether this industrytype uses standard/newgrf production changes.
 
 * @return true if original economy is used.
 
 */
 
bool IndustrySpec::UsesSmoothEconomy() const
 
bool IndustrySpec::UsesOriginalEconomy() const
 
{
 
	return _settings_game.economy.smooth_economy &&
 
		!(HasBit(this->callback_mask, CBM_IND_PRODUCTION_256_TICKS) || HasBit(this->callback_mask, CBM_IND_PRODUCTION_CARGO_ARRIVAL)) && // production callbacks
 
		!(HasBit(this->callback_mask, CBM_IND_MONTHLYPROD_CHANGE) || HasBit(this->callback_mask, CBM_IND_PRODUCTION_CHANGE) || HasBit(this->callback_mask, CBM_IND_PROD_CHANGE_BUILD)); // production change callbacks
 
	return _settings_game.economy.type == ET_ORIGINAL ||
 
		HasBit(this->callback_mask, CBM_IND_PRODUCTION_256_TICKS) || HasBit(this->callback_mask, CBM_IND_PRODUCTION_CARGO_ARRIVAL) || // production callbacks
 
		HasBit(this->callback_mask, CBM_IND_MONTHLYPROD_CHANGE) || HasBit(this->callback_mask, CBM_IND_PRODUCTION_CHANGE) || HasBit(this->callback_mask, CBM_IND_PROD_CHANGE_BUILD); // production change callbacks
 
}
 

	
 
IndustrySpec::~IndustrySpec()
 
{
 
	if (HasBit(this->cleanup_flag, CLEAN_RANDOMSOUNDS)) {
 
		free(this->random_sounds);
src/industry_gui.cpp
Show inline comments
 
@@ -1077,13 +1077,13 @@ public:
 
	void OnInvalidateData(int data = 0, bool gui_scope = true) override
 
	{
 
		if (!gui_scope) return;
 
		const Industry *i = Industry::Get(this->window_number);
 
		if (IsProductionAlterable(i)) {
 
			const IndustrySpec *ind = GetIndustrySpec(i->type);
 
			this->editable = ind->UsesSmoothEconomy() ? EA_RATE : EA_MULTIPLIER;
 
			this->editable = ind->UsesOriginalEconomy() ? EA_MULTIPLIER : EA_RATE;
 
		} else {
 
			this->editable = EA_NONE;
 
		}
 
	}
 

	
 
	bool IsNewGRFInspectable() const override
 
@@ -1097,13 +1097,13 @@ public:
 
	}
 
};
 

	
 
static void UpdateIndustryProduction(Industry *i)
 
{
 
	const IndustrySpec *indspec = GetIndustrySpec(i->type);
 
	if (!indspec->UsesSmoothEconomy()) i->RecomputeProductionMultipliers();
 
	if (indspec->UsesOriginalEconomy()) i->RecomputeProductionMultipliers();
 

	
 
	for (byte j = 0; j < lengthof(i->produced_cargo); j++) {
 
		if (i->produced_cargo[j] != CT_INVALID) {
 
			i->last_month_production[j] = 8 * i->production_rate[j];
 
		}
 
	}
src/industrytype.h
Show inline comments
 
@@ -141,13 +141,13 @@ struct IndustrySpec {
 
	GRFFileProps grf_prop;                      ///< properties related to the grf file
 

	
 
	bool IsRawIndustry() const;
 
	bool IsProcessingIndustry() const;
 
	Money GetConstructionCost() const;
 
	Money GetRemovalCost() const;
 
	bool UsesSmoothEconomy() const;
 
	bool UsesOriginalEconomy() const;
 

	
 
	~IndustrySpec();
 
};
 

	
 
/**
 
 * Defines the data structure of each individual tile of an industry.
src/lang/english.txt
Show inline comments
 
@@ -1550,14 +1550,17 @@ STR_CONFIG_SETTING_COLOURED_NEWS_YEAR   
 
STR_CONFIG_SETTING_COLOURED_NEWS_YEAR_HELPTEXT                  :Year that the newspaper announcements get printed in colour. Before this year, it uses monochrome black/white
 
STR_CONFIG_SETTING_STARTING_YEAR                                :Starting year: {STRING2}
 
STR_CONFIG_SETTING_ENDING_YEAR                                  :Scoring end year: {STRING2}
 
STR_CONFIG_SETTING_ENDING_YEAR_HELPTEXT                         :Year the game ends for scoring purposes. At the end of this year, the company's score is recorded and the high-score screen is displayed, but the players can continue playing after that.{}If this is before the starting year, the high-score screen is never displayed.
 
STR_CONFIG_SETTING_ENDING_YEAR_VALUE                            :{NUM}
 
STR_CONFIG_SETTING_ENDING_YEAR_ZERO                             :Never
 
STR_CONFIG_SETTING_SMOOTH_ECONOMY                               :Enable smooth economy (more, smaller changes): {STRING2}
 
STR_CONFIG_SETTING_SMOOTH_ECONOMY_HELPTEXT                      :When enabled, industry production changes more often, and in smaller steps. This setting has usually no effect, if industry types are provided by a NewGRF
 
STR_CONFIG_SETTING_ECONOMY_TYPE                                 :Economy type: {STRING2}
 
STR_CONFIG_SETTING_ECONOMY_TYPE_HELPTEXT                        :Smooth economy makes production changes more often, and in smaller steps. Frozen economy stops production changes and industry closures. This setting may have no effect if industry types are provided by a NewGRF.
 
STR_CONFIG_SETTING_ECONOMY_TYPE_ORIGINAL                        :Original
 
STR_CONFIG_SETTING_ECONOMY_TYPE_SMOOTH                          :Smooth
 
STR_CONFIG_SETTING_ECONOMY_TYPE_FROZEN                          :Frozen
 
STR_CONFIG_SETTING_ALLOW_SHARES                                 :Allow buying shares from other companies: {STRING2}
 
STR_CONFIG_SETTING_ALLOW_SHARES_HELPTEXT                        :When enabled, allow buying and selling of company shares. Shares will only be available for companies reaching a certain age
 
STR_CONFIG_SETTING_MIN_YEARS_FOR_SHARES                         :Minimum company age to trade shares: {STRING2}
 
STR_CONFIG_SETTING_MIN_YEARS_FOR_SHARES_HELPTEXT                :Set the minimum age of a company for others to be able to buy and sell shares from them.
 
STR_CONFIG_SETTING_FEEDER_PAYMENT_SHARE                         :Percentage of leg profit to pay in feeder systems: {STRING2}
 
STR_CONFIG_SETTING_FEEDER_PAYMENT_SHARE_HELPTEXT                :Percentage of income given to the intermediate legs in feeder systems, giving more control over the income
src/settings_gui.cpp
Show inline comments
 
@@ -1726,13 +1726,13 @@ static SettingsContainer &GetSettingsTre
 
			SettingsPage *industries = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_INDUSTRIES));
 
			{
 
				industries->Add(new SettingEntry("construction.raw_industry_construction"));
 
				industries->Add(new SettingEntry("construction.industry_platform"));
 
				industries->Add(new SettingEntry("economy.multiple_industry_per_town"));
 
				industries->Add(new SettingEntry("game_creation.oil_refinery_limit"));
 
				industries->Add(new SettingEntry("economy.smooth_economy"));
 
				industries->Add(new SettingEntry("economy.type"));
 
				industries->Add(new SettingEntry("station.serve_neutral_industries"));
 
			}
 

	
 
			SettingsPage *cdist = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_CARGODIST));
 
			{
 
				cdist->Add(new SettingEntry("linkgraph.recalc_time"));
src/settings_type.h
Show inline comments
 
@@ -8,12 +8,13 @@
 
/** @file settings_type.h Types related to global configuration settings. */
 

	
 
#ifndef SETTINGS_TYPE_H
 
#define SETTINGS_TYPE_H
 

	
 
#include "date_type.h"
 
#include "economy_type.h"
 
#include "town_type.h"
 
#include "transport_type.h"
 
#include "network/core/config.h"
 
#include "company_type.h"
 
#include "cargotype.h"
 
#include "linkgraph/linkgraph_type.h"
 
@@ -467,13 +468,13 @@ struct VehicleSettings {
 
};
 

	
 
/** Settings related to the economy. */
 
struct EconomySettings {
 
	bool   inflation;                        ///< disable inflation
 
	bool   bribe;                            ///< enable bribing the local authority
 
	bool   smooth_economy;                   ///< smooth economy
 
	EconomyType type;                        ///< economy type (original/smooth/frozen)
 
	bool   allow_shares;                     ///< allow the buying/selling of shares
 
	uint8  min_years_for_shares;             ///< minimum age of a company for it to trade shares
 
	uint8  feeder_payment_share;             ///< percentage of leg payment to virtually pay in feeder systems
 
	byte   dist_local_authority;             ///< distance for town local authority, default 20
 
	bool   exclusive_rights;                 ///< allow buying exclusive rights
 
	bool   fund_buildings;                   ///< allow funding new buildings
src/table/settings.ini
Show inline comments
 
@@ -1426,18 +1426,23 @@ max      = MAX_YEAR
 
interval = 1
 
str      = STR_CONFIG_SETTING_ENDING_YEAR
 
strhelp  = STR_CONFIG_SETTING_ENDING_YEAR_HELPTEXT
 
strval   = STR_CONFIG_SETTING_ENDING_YEAR_VALUE
 
cat      = SC_ADVANCED
 

	
 
[SDT_BOOL]
 
[SDT_VAR]
 
base     = GameSettings
 
var      = economy.smooth_economy
 
def      = true
 
str      = STR_CONFIG_SETTING_SMOOTH_ECONOMY
 
strhelp  = STR_CONFIG_SETTING_SMOOTH_ECONOMY_HELPTEXT
 
var      = economy.type
 
type     = SLE_UINT8
 
guiflags = SGF_MULTISTRING
 
def      = ET_SMOOTH
 
min      = ET_BEGIN
 
max      = ET_END - 1
 
str      = STR_CONFIG_SETTING_ECONOMY_TYPE
 
strhelp  = STR_CONFIG_SETTING_ECONOMY_TYPE_HELPTEXT
 
strval   = STR_CONFIG_SETTING_ECONOMY_TYPE_ORIGINAL
 
proc     = InvalidateIndustryViewWindow
 
cat      = SC_BASIC
 

	
 
[SDT_BOOL]
 
base     = GameSettings
 
var      = economy.allow_shares
0 comments (0 inline, 0 general)