Improve handling of company sales

Avoid conflicts between bankruptcy and manual company sale paths
pull/428/head
Jonathan G Rennison 2 years ago
parent 142a5a95ec
commit 23fa7cd239

@ -49,6 +49,13 @@ struct CompanyInfrastructure {
char *Dump(char *buffer, const char *last) const;
};
enum CompanyBankruptcyFlags : byte {
CBRF_NONE = 0x0,
CBRF_SALE = 0x1, ///< the company has been marked for sale
CBRF_SALE_ONLY = 0x2, ///< the company has been marked for sale without being in a bankruptcy state first
};
DECLARE_ENUM_AS_BIT_SET(CompanyBankruptcyFlags)
typedef Pool<Company, CompanyID, 1, MAX_COMPANIES> CompanyPool;
extern CompanyPool _company_pool;
@ -82,6 +89,7 @@ struct CompanyProperties {
byte months_of_bankruptcy; ///< Number of months that the company is unable to pay its debts
CompanyID bankrupt_last_asked; ///< Which company was most recently asked about buying it?
CompanyBankruptcyFlags bankrupt_flags; ///< bankruptcy flags
CompanyMask bankrupt_asked; ///< which companies were asked about buying it?
int16 bankrupt_timeout; ///< If bigger than \c 0, amount of time to wait for an answer on an offer to buy this company.
Money bankrupt_value;
@ -113,7 +121,7 @@ struct 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(0), block_preview(0),
location_of_HQ(0), last_build_coordinate(0), share_owners(), inaugurated_year(0),
months_of_bankruptcy(0), bankrupt_last_asked(INVALID_COMPANY), bankrupt_asked(0), bankrupt_timeout(0), bankrupt_value(0),
months_of_bankruptcy(0), bankrupt_last_asked(INVALID_COMPANY), bankrupt_flags(CBRF_NONE), bankrupt_asked(0), bankrupt_timeout(0), bankrupt_value(0),
terraform_limit(0), clear_limit(0), tree_limit(0), purchase_land_limit(0), build_object_limit(0), is_ai(false), engine_renew_list(nullptr) {}
};

@ -681,6 +681,7 @@ static void HandleBankruptcyTakeover(Company *c)
assert(c->bankrupt_asked != 0);
/* We're currently asking some company to buy 'us' */
if (c->bankrupt_timeout != 0) {
c->bankrupt_timeout -= MAX_COMPANIES;
@ -698,7 +699,7 @@ static void HandleBankruptcyTakeover(Company *c)
/* Ask the company with the highest performance history first */
for (Company *c2 : Company::Iterate()) {
if (c2->bankrupt_asked == 0 && // Don't ask companies going bankrupt themselves
if ((c2->bankrupt_asked == 0 || (c2->bankrupt_flags & CBRF_SALE_ONLY)) && // Don't ask companies going bankrupt themselves
!HasBit(c->bankrupt_asked, c2->index) &&
best_performance < c2->old_economy[1].performance_history &&
MayCompanyTakeOver(c2->index, c->index)) {
@ -709,7 +710,13 @@ static void HandleBankruptcyTakeover(Company *c)
/* Asked all companies? */
if (best_performance == -1) {
c->bankrupt_asked = MAX_UVALUE(CompanyMask);
if (c->bankrupt_flags & CBRF_SALE_ONLY) {
c->bankrupt_asked = 0;
DeleteWindowById(WC_BUY_COMPANY, c->index);
} else {
c->bankrupt_asked = MAX_UVALUE(CompanyMask);
}
c->bankrupt_flags = CBRF_NONE;
return;
}
@ -962,9 +969,12 @@ CommandCost CmdCompanyCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
if (!(flags & DC_EXEC)) return CommandCost();
c->bankrupt_flags |= CBRF_SALE;
if (c->bankrupt_asked == 0) c->bankrupt_flags |= CBRF_SALE_ONLY;
c->bankrupt_value = CalculateCompanyValue(c, false);
c->bankrupt_asked = 1 << c->index; // Don't ask the owner
c->bankrupt_timeout = 0;
DeleteWindowById(WC_BUY_COMPANY, c->index);
break;
}

@ -2885,12 +2885,13 @@ struct BuyCompanyWindow : Window {
BuyCompanyWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc)
{
this->InitNested(window_number);
this->owner = _local_company;
}
~BuyCompanyWindow()
{
const Company *c = Company::GetIfValid((CompanyID)this->window_number);
if (c != nullptr && HasBit(c->bankrupt_asked, _current_company)) {
if (c != nullptr && HasBit(c->bankrupt_asked, this->owner)) {
DoCommandP(0, this->window_number, 0, CMD_DECLINE_BUY_COMPANY);
}
}

@ -628,10 +628,12 @@ void ChangeOwnershipOfCompanyItems(Owner old_owner, Owner new_owner)
static void CompanyCheckBankrupt(Company *c)
{
/* If the company has money again, it does not go bankrupt */
if (c->bankrupt_flags & CBRF_SALE) return;
if (c->money - c->current_loan >= -_economy.max_loan) {
int previous_months_of_bankruptcy = CeilDiv(c->months_of_bankruptcy, 3);
c->months_of_bankruptcy = 0;
c->bankrupt_asked = 0;
DeleteWindowById(WC_BUY_COMPANY, c->index);
if (previous_months_of_bankruptcy != 0) CompanyAdminUpdate(c);
return;
}

@ -283,6 +283,7 @@ static const SaveLoad _company_desc[] = {
SLE_VAR(CompanyProperties, months_of_bankruptcy, SLE_UINT8),
SLE_CONDVAR_X(CompanyProperties, bankrupt_last_asked, SLE_UINT8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_BANKRUPTCY_EXTRA)),
SLE_CONDVAR_X(CompanyProperties, bankrupt_flags, SLE_UINT8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_BANKRUPTCY_EXTRA, 2)),
SLE_CONDVAR(CompanyProperties, bankrupt_asked, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SLV_104),
SLE_CONDVAR(CompanyProperties, bankrupt_asked, SLE_UINT16, SLV_104, SL_MAX_VERSION),
SLE_VAR(CompanyProperties, bankrupt_timeout, SLE_INT16),

@ -161,7 +161,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
{ XSLFI_EXTRA_STATION_NAMES, XSCF_NULL, 1, 1, "extra_station_names", nullptr, nullptr, nullptr },
{ XSLFI_DEPOT_ORDER_EXTRA_FLAGS,XSCF_IGNORABLE_UNKNOWN, 1, 1, "depot_order_extra_flags", nullptr, nullptr, nullptr },
{ XSLFI_EXTRA_SIGNAL_TYPES, XSCF_NULL, 1, 1, "extra_signal_types", nullptr, nullptr, nullptr },
{ XSLFI_BANKRUPTCY_EXTRA, XSCF_NULL, 1, 1, "bankruptcy_extra", nullptr, nullptr, nullptr },
{ XSLFI_BANKRUPTCY_EXTRA, XSCF_NULL, 2, 2, "bankruptcy_extra", nullptr, nullptr, nullptr },
{ XSLFI_OBJECT_GROUND_TYPES, XSCF_NULL, 3, 3, "object_ground_types", nullptr, nullptr, nullptr },
{ XSLFI_LINKGRAPH_AIRCRAFT, XSCF_NULL, 1, 1, "linkgraph_aircraft", nullptr, nullptr, nullptr },
{ XSLFI_COMPANY_PW, XSCF_IGNORABLE_ALL, 1, 1, "company_password", nullptr, nullptr, "PLYP" },

Loading…
Cancel
Save