Feature: allow to do a hostile takeover of an AI company (in singleplayer) (#10914)

With the removal of the share-system, you could no longer make an
AI disappear in a single player game. At least, not without going
into the console.
This commit is contained in:
Patric Stout
2023-06-05 19:32:22 +02:00
committed by GitHub
parent f814c86389
commit 3b1407d240
9 changed files with 136 additions and 36 deletions

View File

@@ -105,15 +105,12 @@ Prices _price;
static PriceMultipliers _price_base_multiplier;
/**
* Calculate the value of the company. That is the value of all
* assets (vehicles, stations) and money minus the loan,
* except when including_loan is \c false which is useful when
* we want to calculate the value for bankruptcy.
* @param c the company to get the value of.
* @param including_loan include the loan in the company value.
* @return the value of the company.
* Calculate the value of the assets of a company.
*
* @param c The company to calculate the value of.
* @return The value of the assets of the company.
*/
Money CalculateCompanyValue(const Company *c, bool including_loan)
static Money CalculateCompanyAssetValue(const Company *c)
{
Owner owner = c->index;
@@ -136,6 +133,22 @@ Money CalculateCompanyValue(const Company *c, bool including_loan)
}
}
return value;
}
/**
* Calculate the value of the company. That is the value of all
* assets (vehicles, stations) and money (including loan),
* except when including_loan is \c false which is useful when
* we want to calculate the value for bankruptcy.
* @param c the company to get the value of.
* @param including_loan include the loan in the company value.
* @return the value of the company.
*/
Money CalculateCompanyValue(const Company *c, bool including_loan)
{
Money value = CalculateCompanyAssetValue(c);
/* Add real money value */
if (including_loan) value -= c->current_loan;
value += c->money;
@@ -143,6 +156,39 @@ Money CalculateCompanyValue(const Company *c, bool including_loan)
return std::max<Money>(value, 1);
}
/**
* Calculate what you have to pay to take over a company.
*
* This is different from bankruptcy and company value, and involves a few
* more parameters to make it more realistic.
*
* You have to pay for:
* - The value of all the assets in the company.
* - The loan the company has (the investors really want their money back).
* - The profit for the next two years (if positive) based on the last four quarters.
*
* And on top of that, they walk away with all the money they have in the bank.
*
* @param c the company to get the value of.
* @return The value of the company.
*/
Money CalculateHostileTakeoverValue(const Company *c)
{
Money value = CalculateCompanyAssetValue(c);
value += c->current_loan;
/* Negative balance is basically a loan. */
if (c->money < 0) {
value += -c->money;
}
for (int quarter = 0; quarter < 4; quarter++) {
value += std::max<Money>(c->old_economy[quarter].income - c->old_economy[quarter].expenses, 0) * 2;
}
return std::max<Money>(value, 1);
}
/**
* if update is set to true, the economy is updated with this score
* (also the house is updated, should only be true in the on-tick event)
@@ -1940,14 +1986,14 @@ static IntervalTimer<TimerGameCalendar> _companies_monthly({TimerGameCalendar::M
HandleEconomyFluctuations();
});
static void DoAcquireCompany(Company *c)
static void DoAcquireCompany(Company *c, bool hostile_takeover)
{
CompanyID ci = c->index;
CompanyNewsInformation *cni = new CompanyNewsInformation(c, Company::Get(_current_company));
SetDParam(0, STR_NEWS_COMPANY_MERGER_TITLE);
SetDParam(1, c->bankrupt_value == 0 ? STR_NEWS_MERGER_TAKEOVER_TITLE : STR_NEWS_COMPANY_MERGER_DESCRIPTION);
SetDParam(1, hostile_takeover ? STR_NEWS_MERGER_TAKEOVER_TITLE : STR_NEWS_COMPANY_MERGER_DESCRIPTION);
SetDParamStr(2, cni->company_name);
SetDParamStr(3, cni->other_company_name);
SetDParam(4, c->bankrupt_value);
@@ -1957,14 +2003,6 @@ static void DoAcquireCompany(Company *c)
ChangeOwnershipOfCompanyItems(ci, _current_company);
if (c->bankrupt_value == 0) {
Company *owner = Company::Get(_current_company);
/* Get both the balance and the loan of the company you just bought. */
SubtractMoneyFromCompany(CommandCost(EXPENSES_OTHER, -c->money));
owner->current_loan += c->current_loan;
}
if (c->is_ai) AI::Stop(c->index);
CloseCompanyWindows(ci);
@@ -1983,15 +2021,23 @@ static void DoAcquireCompany(Company *c)
* @todo currently this only works for AI companies
* @param flags type of operation
* @param target_company company to buy up
* @param hostile_takeover whether to buy up the company even if it is not bankrupt
* @return the cost of this operation or an error
*/
CommandCost CmdBuyCompany(DoCommandFlag flags, CompanyID target_company)
CommandCost CmdBuyCompany(DoCommandFlag flags, CompanyID target_company, bool hostile_takeover)
{
Company *c = Company::GetIfValid(target_company);
if (c == nullptr) return CMD_ERROR;
/* If you do a hostile takeover but the company went bankrupt, buy it via bankruptcy rules. */
if (hostile_takeover && HasBit(c->bankrupt_asked, _current_company)) hostile_takeover = false;
/* Disable takeovers when not asked */
if (!HasBit(c->bankrupt_asked, _current_company)) return CMD_ERROR;
if (!hostile_takeover && !HasBit(c->bankrupt_asked, _current_company)) return CMD_ERROR;
/* Only allow hostile takeover of AI companies and when in single player */
if (hostile_takeover && !c->is_ai) return CMD_ERROR;
if (hostile_takeover && _networking) return CMD_ERROR;
/* Disable taking over the local company in singleplayer mode */
if (!_networking && _local_company == c->index) return CMD_ERROR;
@@ -2002,11 +2048,13 @@ CommandCost CmdBuyCompany(DoCommandFlag flags, CompanyID target_company)
/* Disable taking over when not allowed. */
if (!MayCompanyTakeOver(_current_company, target_company)) return CMD_ERROR;
/* Get the cost here as the company is deleted in DoAcquireCompany. */
CommandCost cost(EXPENSES_OTHER, c->bankrupt_value);
/* Get the cost here as the company is deleted in DoAcquireCompany.
* For bankruptcy this amount is calculated when the offer was made;
* for hostile takeover you pay the current price. */
CommandCost cost(EXPENSES_OTHER, hostile_takeover ? CalculateHostileTakeoverValue(c) : c->bankrupt_value);
if (flags & DC_EXEC) {
DoAcquireCompany(c);
DoAcquireCompany(c, hostile_takeover);
}
return cost;
}