mirror of https://github.com/OpenTTD/OpenTTD.git
Add: [GS] Allow to set max loan for each company separately (#11224)
This commit is contained in:
parent
b370ae1212
commit
897b59c158
|
@ -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
|
||||
|
|
|
@ -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, CompanyPool::PoolItem<&_company_pool> {
|
|||
|
||||
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.
|
||||
|
|
|
@ -95,6 +95,16 @@ void Company::PostDestructor(size_t index)
|
|||
InvalidateWindowData(WC_ERRMSG, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
|
||||
|
|
|
@ -572,7 +572,7 @@ static void CompanyCheckBankrupt(Company *c)
|
|||
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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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(DoCommandFlag flags, LoanCommand cmd, Money amount)
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -118,6 +118,32 @@ CommandCost CmdDecreaseLoan(DoCommandFlag flags, LoanCommand cmd, Money amount)
|
|||
return CommandCost();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
|
|
@ -25,12 +25,14 @@ CommandCost CmdMoneyCheat(DoCommandFlag flags, Money amount);
|
|||
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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -217,12 +217,38 @@ 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.
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue