Changeset - r28615:854bbcf6faa2
[Not reviewed]
master
0 15 0
dP - 10 months ago 2024-01-30 18:15:19
dp@dpointer.org
Add: [GS] Allow to set max loan for each company separately (#11224)
15 files changed with 129 insertions and 20 deletions:
0 comments (0 inline, 0 general)
src/command_type.h
Show inline comments
 
@@ -253,6 +253,7 @@ enum Commands : uint16_t {
 

	
 
	CMD_INCREASE_LOAN,                ///< increase the loan from the bank
 
	CMD_DECREASE_LOAN,                ///< decrease the loan from the bank
 
	CMD_SET_COMPANY_MAX_LOAN,         ///< sets the max loan for the company
 

	
 
	CMD_WANT_ENGINE_PREVIEW,          ///< confirm the preview of an engine
 
	CMD_ENGINE_CTRL,                  ///< control availability of the engine for companies
src/company_base.h
Show inline comments
 
@@ -18,6 +18,8 @@
 
#include "settings_type.h"
 
#include "group.h"
 

	
 
static const Money COMPANY_MAX_LOAN_DEFAULT = INT64_MIN;
 

	
 
/** Statistics about the economy. */
 
struct CompanyEconomyEntry {
 
	Money income;               ///< The amount of income.
 
@@ -50,7 +52,6 @@ struct CompanyInfrastructure {
 
typedef Pool<Company, CompanyID, 1, MAX_COMPANIES> CompanyPool;
 
extern CompanyPool _company_pool;
 

	
 

	
 
/** Statically loadable part of Company pool item */
 
struct CompanyProperties {
 
	uint32_t name_2;                   ///< Parameter of #name_1.
 
@@ -66,6 +67,7 @@ struct CompanyProperties {
 
	Money money;                     ///< Money owned by the company.
 
	byte money_fraction;             ///< Fraction of money of the company, too small to represent in #money.
 
	Money current_loan;              ///< Amount of money borrowed from the bank.
 
	Money max_loan;                  ///< Max allowed amount of the loan or COMPANY_MAX_LOAN_DEFAULT.
 

	
 
	Colours colour;                  ///< Company colour.
 

	
 
@@ -105,8 +107,8 @@ struct CompanyProperties {
 
	// TODO: Change some of these member variables to use relevant INVALID_xxx constants
 
	CompanyProperties()
 
		: name_2(0), name_1(0), president_name_1(0), president_name_2(0),
 
		  face(0), money(0), money_fraction(0), current_loan(0), colour(COLOUR_BEGIN), block_preview(0),
 
		  location_of_HQ(0), last_build_coordinate(0), inaugurated_year(0),
 
		  face(0), money(0), money_fraction(0), current_loan(0), max_loan(COMPANY_MAX_LOAN_DEFAULT),
 
		  colour(COLOUR_BEGIN), block_preview(0), location_of_HQ(0), last_build_coordinate(0), inaugurated_year(0),
 
		  months_of_bankruptcy(0), bankrupt_asked(0), bankrupt_timeout(0), bankrupt_value(0),
 
		  terraform_limit(0), clear_limit(0), tree_limit(0), build_object_limit(0), is_ai(false), engine_renew_list(nullptr) {}
 
};
 
@@ -126,6 +128,8 @@ struct Company : CompanyProperties, Comp
 

	
 
	CompanyInfrastructure infrastructure; ///< NOSAVE: Counts of company owned infrastructure.
 

	
 
	Money GetMaxLoan() const;
 

	
 
	/**
 
	 * Is this company a valid company, controlled by the computer (a NoAI program)?
 
	 * @param index Index in the pool.
src/company_cmd.cpp
Show inline comments
 
@@ -96,6 +96,16 @@ void Company::PostDestructor(size_t inde
 
}
 

	
 
/**
 
 * Calculate the max allowed loan for this company.
 
 * @return the max loan amount.
 
 */
 
Money Company::GetMaxLoan() const
 
{
 
	if (this->max_loan == COMPANY_MAX_LOAN_DEFAULT) return _economy.max_loan;
 
	return this->max_loan;
 
}
 

	
 
/**
 
 * Sets the local company and updates the settings that are set on a
 
 * per-company basis to reflect the core's state in the GUI.
 
 * @param new_company the new company
src/company_gui.cpp
Show inline comments
 
@@ -374,9 +374,11 @@ struct CompanyFinancesWindow : Window {
 
				SetDParam(0, _settings_game.difficulty.initial_interest);
 
				break;
 

	
 
			case WID_CF_MAXLOAN_VALUE:
 
				SetDParam(0, _economy.max_loan);
 
			case WID_CF_MAXLOAN_VALUE: {
 
				const Company *c = Company::Get((CompanyID)this->window_number);
 
				SetDParam(0, c->GetMaxLoan());
 
				break;
 
			}
 

	
 
			case WID_CF_INCREASE_LOAN:
 
			case WID_CF_REPAY_LOAN:
 
@@ -474,7 +476,7 @@ struct CompanyFinancesWindow : Window {
 
			}
 

	
 
			const Company *c = Company::Get(company);
 
			this->SetWidgetDisabledState(WID_CF_INCREASE_LOAN, c->current_loan == _economy.max_loan); // Borrow button only shows when there is any more money to loan.
 
			this->SetWidgetDisabledState(WID_CF_INCREASE_LOAN, c->current_loan >= c->GetMaxLoan()); // Borrow button only shows when there is any more money to loan.
 
			this->SetWidgetDisabledState(WID_CF_REPAY_LOAN, company != _local_company || c->current_loan == 0); // Repay button only shows when there is any more money to repay.
 
		}
 

	
src/economy.cpp
Show inline comments
 
@@ -572,7 +572,7 @@ static void CompanyCheckBankrupt(Company
 
	if (_settings_game.difficulty.infinite_money) return;
 

	
 
	/*  If the company has money again, it does not go bankrupt */
 
	if (c->money - c->current_loan >= -_economy.max_loan) {
 
	if (c->money - c->current_loan >= -c->GetMaxLoan()) {
 
		int previous_months_of_bankruptcy = CeilDiv(c->months_of_bankruptcy, 3);
 
		c->months_of_bankruptcy = 0;
 
		c->bankrupt_asked = 0;
src/economy_type.h
Show inline comments
 
@@ -200,6 +200,8 @@ struct PriceBaseSpec {
 
static const int LOAN_INTERVAL = 10000;
 
/** The size of loan for a new company, in British Pounds! */
 
static const int64_t INITIAL_LOAN = 100000;
 
/** The max amount possible to configure for a max loan of a company. */
 
static const int64_t MAX_LOAN_LIMIT = 2000000000;
 

	
 
/**
 
 * Maximum inflation (including fractional part) without causing overflows in int64_t price computations.
src/misc_cmd.cpp
Show inline comments
 
@@ -39,9 +39,9 @@
 
CommandCost CmdIncreaseLoan(DoCommandFlag flags, LoanCommand cmd, Money amount)
 
{
 
	Company *c = Company::Get(_current_company);
 

	
 
	if (c->current_loan >= _economy.max_loan) {
 
		SetDParam(0, _economy.max_loan);
 
	Money max_loan = c->GetMaxLoan();
 
	if (c->current_loan >= max_loan) {
 
		SetDParam(0, max_loan);
 
		return_cmd_error(STR_ERROR_MAXIMUM_PERMITTED_LOAN);
 
	}
 

	
 
@@ -52,11 +52,11 @@ CommandCost CmdIncreaseLoan(DoCommandFla
 
			loan = LOAN_INTERVAL;
 
			break;
 
		case LoanCommand::Max: // Take a loan as big as possible
 
			loan = _economy.max_loan - c->current_loan;
 
			loan = max_loan - c->current_loan;
 
			break;
 
		case LoanCommand::Amount: // Take the given amount of loan
 
			loan = amount;
 
			if (loan < LOAN_INTERVAL || c->current_loan + loan > _economy.max_loan || loan % LOAN_INTERVAL != 0) return CMD_ERROR;
 
			if (loan < LOAN_INTERVAL || c->current_loan + loan > max_loan || loan % LOAN_INTERVAL != 0) return CMD_ERROR;
 
			break;
 
	}
 

	
 
@@ -119,6 +119,32 @@ CommandCost CmdDecreaseLoan(DoCommandFla
 
}
 

	
 
/**
 
 * Sets the max loan amount of your company. Does not respect the global loan setting.
 
 * @param company the company ID.
 
 * @param amount the new max loan amount, will be rounded down to the multitude of LOAN_INTERVAL. If set to COMPANY_MAX_LOAN_DEFAULT reset the max loan to default(global) value.
 
 * @return zero cost or an error
 
 */
 
CommandCost CmdSetCompanyMaxLoan(DoCommandFlag flags, CompanyID company, Money amount)
 
{
 
	if (_current_company != OWNER_DEITY) return CMD_ERROR;
 
	if (amount != COMPANY_MAX_LOAN_DEFAULT) {
 
		if (amount < 0 || amount > (Money)MAX_LOAN_LIMIT) return CMD_ERROR;
 
	}
 

	
 
	Company *c = Company::GetIfValid(company);
 
	if (c == nullptr) return CMD_ERROR;
 

	
 
	if (flags & DC_EXEC) {
 
		/* Round the amount down to a multiple of LOAN_INTERVAL. */
 
		if (amount != COMPANY_MAX_LOAN_DEFAULT) amount -= (int64_t)amount % LOAN_INTERVAL;
 

	
 
		c->max_loan = amount;
 
		InvalidateCompanyWindows(c);
 
	}
 
	return CommandCost();
 
}
 

	
 
/**
 
 * In case of an unsafe unpause, we want the
 
 * user to confirm that it might crash.
 
 * @param confirmed whether the user confirmed their action
src/misc_cmd.h
Show inline comments
 
@@ -25,12 +25,14 @@ CommandCost CmdMoneyCheat(DoCommandFlag 
 
CommandCost CmdChangeBankBalance(DoCommandFlag flags, TileIndex tile, Money delta, CompanyID company, ExpensesType expenses_type);
 
CommandCost CmdIncreaseLoan(DoCommandFlag flags, LoanCommand cmd, Money amount);
 
CommandCost CmdDecreaseLoan(DoCommandFlag flags, LoanCommand cmd, Money amount);
 
CommandCost CmdSetCompanyMaxLoan(DoCommandFlag flags, CompanyID company, Money amount);
 
CommandCost CmdPause(DoCommandFlag flags, PauseMode mode, bool pause);
 

	
 
DEF_CMD_TRAIT(CMD_MONEY_CHEAT,         CmdMoneyCheat,        CMD_OFFLINE,             CMDT_CHEAT)
 
DEF_CMD_TRAIT(CMD_CHANGE_BANK_BALANCE, CmdChangeBankBalance, CMD_DEITY,               CMDT_MONEY_MANAGEMENT)
 
DEF_CMD_TRAIT(CMD_INCREASE_LOAN,       CmdIncreaseLoan,      0,                       CMDT_MONEY_MANAGEMENT)
 
DEF_CMD_TRAIT(CMD_DECREASE_LOAN,       CmdDecreaseLoan,      0,                       CMDT_MONEY_MANAGEMENT)
 
DEF_CMD_TRAIT(CMD_PAUSE,               CmdPause,             CMD_SERVER | CMD_NO_EST, CMDT_SERVER_SETTING)
 
DEF_CMD_TRAIT(CMD_MONEY_CHEAT,          CmdMoneyCheat,        CMD_OFFLINE,             CMDT_CHEAT)
 
DEF_CMD_TRAIT(CMD_CHANGE_BANK_BALANCE,  CmdChangeBankBalance, CMD_DEITY,               CMDT_MONEY_MANAGEMENT)
 
DEF_CMD_TRAIT(CMD_INCREASE_LOAN,        CmdIncreaseLoan,      0,                       CMDT_MONEY_MANAGEMENT)
 
DEF_CMD_TRAIT(CMD_DECREASE_LOAN,        CmdDecreaseLoan,      0,                       CMDT_MONEY_MANAGEMENT)
 
DEF_CMD_TRAIT(CMD_SET_COMPANY_MAX_LOAN, CmdSetCompanyMaxLoan, CMD_DEITY,               CMDT_MONEY_MANAGEMENT)
 
DEF_CMD_TRAIT(CMD_PAUSE,                CmdPause,             CMD_SERVER | CMD_NO_EST, CMDT_SERVER_SETTING)
 

	
 
#endif /* MISC_CMD_H */
src/saveload/afterload.cpp
Show inline comments
 
@@ -3280,6 +3280,12 @@ bool AfterLoadGame()
 
		}
 
	}
 

	
 
	if (IsSavegameVersionBefore(SLV_MAX_LOAN_FOR_COMPANY)) {
 
		for (Company *c : Company::Iterate()) {
 
			c->max_loan = COMPANY_MAX_LOAN_DEFAULT;
 
		}
 
	}
 

	
 
	for (Company *c : Company::Iterate()) {
 
		UpdateCompanyLiveries(c);
 
	}
src/saveload/company_sl.cpp
Show inline comments
 
@@ -458,6 +458,7 @@ static const SaveLoad _company_desc[] = 
 

	
 
	SLE_CONDVAR(CompanyProperties, current_loan,          SLE_VAR_I64 | SLE_FILE_I32,  SL_MIN_VERSION, SLV_65),
 
	SLE_CONDVAR(CompanyProperties, current_loan,          SLE_INT64,                  SLV_65, SL_MAX_VERSION),
 
	SLE_CONDVAR(CompanyProperties, max_loan,              SLE_INT64, SLV_MAX_LOAN_FOR_COMPANY, SL_MAX_VERSION),
 

	
 
	    SLE_VAR(CompanyProperties, colour,                SLE_UINT8),
 
	    SLE_VAR(CompanyProperties, money_fraction,        SLE_UINT8),
src/saveload/saveload.h
Show inline comments
 
@@ -373,6 +373,8 @@ enum SaveLoadVersion : uint16_t {
 
	SLV_CALENDAR_SUB_DATE_FRACT,            ///< 328  PR#11428 Add sub_date_fract to measure calendar days.
 
	SLV_SHIP_ACCELERATION,                  ///< 329  PR#10734 Start using Vehicle's acceleration field for ships too.
 

	
 
	SLV_MAX_LOAN_FOR_COMPANY,               ///< 330  PR#11224 Separate max loan for each company.
 

	
 
	SL_MAX_VERSION,                         ///< Highest possible saveload version
 
};
 

	
src/script/api/game_changelog.hpp
Show inline comments
 
@@ -47,6 +47,8 @@
 
 * \li GSCompany::SetAutoRenewStatus
 
 * \li GSCompany::SetAutoRenewMonths
 
 * \li GSCompany::SetAutoRenewMoney
 
 * \li GSCompany::SetMaxLoanAmountForCompany
 
 * \li GSCompany::ResetMaxLoanAmountForCompany
 
 * \li GSGameSettings::IsDisabledVehicleType
 
 * \li GSGroup::GroupID
 
 * \li GSGroup::IsValidGroup
src/script/api/script_company.cpp
Show inline comments
 
@@ -192,7 +192,32 @@
 

	
 
/* static */ Money ScriptCompany::GetMaxLoanAmount()
 
{
 
	return _economy.max_loan;
 
	if (ScriptCompanyMode::IsDeity()) return _economy.max_loan;
 

	
 
	ScriptCompany::CompanyID company = ResolveCompanyID(COMPANY_SELF);
 
	if (company == COMPANY_INVALID) return -1;
 

	
 
	return ::Company::Get(company)->GetMaxLoan();
 
}
 

	
 
/* static */ bool ScriptCompany::SetMaxLoanAmountForCompany(CompanyID company, Money amount)
 
{
 
	EnforceDeityMode(false);
 
	EnforcePrecondition(false, amount >= 0 && amount <= (Money)MAX_LOAN_LIMIT);
 

	
 
	company = ResolveCompanyID(company);
 
	EnforcePrecondition(false, company != COMPANY_INVALID);
 
	return ScriptObject::Command<CMD_SET_COMPANY_MAX_LOAN>::Do((::CompanyID)company, amount);
 
}
 

	
 
/* static */ bool ScriptCompany::ResetMaxLoanAmountForCompany(CompanyID company)
 
{
 
	EnforceDeityMode(false);
 

	
 
	company = ResolveCompanyID(company);
 
	EnforcePrecondition(false, company != COMPANY_INVALID);
 

	
 
	return ScriptObject::Command<CMD_SET_COMPANY_MAX_LOAN>::Do((::CompanyID)company, COMPANY_MAX_LOAN_DEFAULT);
 
}
 

	
 
/* static */ Money ScriptCompany::GetLoanInterval()
src/script/api/script_company.hpp
Show inline comments
 
@@ -217,13 +217,39 @@ public:
 
	static Money GetLoanAmount();
 

	
 
	/**
 
	 * Gets the maximum amount your company can loan.
 
	 * Gets the maximum amount your company can loan. In deity mode returns the global max loan.
 
	 * @return The maximum amount your company can loan.
 
	 * @post GetLoanInterval() is always a multiplier of the return value.
 
	 */
 
	static Money GetMaxLoanAmount();
 

	
 
	/**
 
	 * Sets the max amount of money company can loan.
 
	 * @param company The company ID.
 
	 * @param amount Max loan amount. Will be rounded down to a multiple of GetLoanInterval().
 
	 * @return True, if the max loan was changed.
 
	 * @pre ScriptCompanyMode::IsDeity().
 
	 * @pre amount >= 0.
 
	 * @pre ResolveCompanyID(company) != COMPANY_INVALID.
 
	 * @note You need to create your own news message to inform about max loan change.
 
	 * @note Max loan value set with this method is not affected by inflation.
 
	 * @api -ai
 
	 */
 
	static bool SetMaxLoanAmountForCompany(CompanyID company, Money amount);
 

	
 
	/**
 
	 * Makes the max amount of money company can loan follow the global max loan setting.
 
	 * @param company The company ID.
 
	 * @return True, if the max loan was reset.
 
	 * @pre ScriptCompanyMode::IsDeity().
 
	 * @pre amount >= 0 && amount <= MAX_LOAN_LIMIT.
 
	 * @pre ResolveCompanyID(company) != COMPANY_INVALID.
 
	 * @note You need to create your own news message to inform about max loan change.
 
	 * @api -ai
 
	 */
 
	static bool ResetMaxLoanAmountForCompany(CompanyID company);
 

	
 
	/**
 
	 * Gets the interval/loan step.
 
	 * @return The loan step.
 
	 * @post Return value is always positive.
src/table/settings/difficulty_settings.ini
Show inline comments
 
@@ -111,7 +111,7 @@ from     = SLV_97
 
flags    = SF_NEWGAME_ONLY | SF_SCENEDIT_TOO | SF_GUI_CURRENCY | SF_GUI_0_IS_SPECIAL
 
def      = 300000
 
min      = LOAN_INTERVAL
 
max      = 2000000000
 
max      = MAX_LOAN_LIMIT
 
pre_cb   = [](auto &new_value) { new_value = (new_value + LOAN_INTERVAL / 2) / LOAN_INTERVAL * LOAN_INTERVAL; return true; }
 
interval = LOAN_INTERVAL
 
str      = STR_CONFIG_SETTING_MAXIMUM_INITIAL_LOAN
0 comments (0 inline, 0 general)