mirror of https://github.com/OpenTTD/OpenTTD
(svn r17345) -Fix [FS#2769]: one wasn't offered to take over bankrupt companies anymore; caused by the introduction NoAI, although NewAI had the same problem too.
parent
4abf4602e7
commit
4c84db1636
|
@ -186,6 +186,7 @@ void AIInstance::RegisterAPI()
|
||||||
SQAIEngineList_Register(this->engine);
|
SQAIEngineList_Register(this->engine);
|
||||||
SQAIError_Register(this->engine);
|
SQAIError_Register(this->engine);
|
||||||
SQAIEvent_Register(this->engine);
|
SQAIEvent_Register(this->engine);
|
||||||
|
SQAIEventCompanyAskMerger_Register(this->engine);
|
||||||
SQAIEventCompanyBankrupt_Register(this->engine);
|
SQAIEventCompanyBankrupt_Register(this->engine);
|
||||||
SQAIEventCompanyInTrouble_Register(this->engine);
|
SQAIEventCompanyInTrouble_Register(this->engine);
|
||||||
SQAIEventCompanyMerger_Register(this->engine);
|
SQAIEventCompanyMerger_Register(this->engine);
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
* API additions:
|
* API additions:
|
||||||
* \li AIBaseStation
|
* \li AIBaseStation
|
||||||
* \li AIBuoyList
|
* \li AIBuoyList
|
||||||
|
* \li AIEventCompanyAskMerger
|
||||||
* \li AIRail::RemoveRailWaypointTileRect
|
* \li AIRail::RemoveRailWaypointTileRect
|
||||||
* \li AISubsidy::SubsidyParticipantType
|
* \li AISubsidy::SubsidyParticipantType
|
||||||
* \li AISubsidy::GetSourceType
|
* \li AISubsidy::GetSourceType
|
||||||
|
|
|
@ -36,6 +36,7 @@ public:
|
||||||
AI_ET_ENGINE_PREVIEW,
|
AI_ET_ENGINE_PREVIEW,
|
||||||
AI_ET_COMPANY_NEW,
|
AI_ET_COMPANY_NEW,
|
||||||
AI_ET_COMPANY_IN_TROUBLE,
|
AI_ET_COMPANY_IN_TROUBLE,
|
||||||
|
AI_ET_COMPANY_ASK_MERGER,
|
||||||
AI_ET_COMPANY_MERGER,
|
AI_ET_COMPANY_MERGER,
|
||||||
AI_ET_COMPANY_BANKRUPT,
|
AI_ET_COMPANY_BANKRUPT,
|
||||||
AI_ET_VEHICLE_CRASHED,
|
AI_ET_VEHICLE_CRASHED,
|
||||||
|
|
|
@ -38,6 +38,7 @@ void SQAIEvent_Register(Squirrel *engine) {
|
||||||
SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_ENGINE_PREVIEW, "AI_ET_ENGINE_PREVIEW");
|
SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_ENGINE_PREVIEW, "AI_ET_ENGINE_PREVIEW");
|
||||||
SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_COMPANY_NEW, "AI_ET_COMPANY_NEW");
|
SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_COMPANY_NEW, "AI_ET_COMPANY_NEW");
|
||||||
SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_COMPANY_IN_TROUBLE, "AI_ET_COMPANY_IN_TROUBLE");
|
SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_COMPANY_IN_TROUBLE, "AI_ET_COMPANY_IN_TROUBLE");
|
||||||
|
SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_COMPANY_ASK_MERGER, "AI_ET_COMPANY_ASK_MERGER");
|
||||||
SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_COMPANY_MERGER, "AI_ET_COMPANY_MERGER");
|
SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_COMPANY_MERGER, "AI_ET_COMPANY_MERGER");
|
||||||
SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_COMPANY_BANKRUPT, "AI_ET_COMPANY_BANKRUPT");
|
SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_COMPANY_BANKRUPT, "AI_ET_COMPANY_BANKRUPT");
|
||||||
SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_VEHICLE_CRASHED, "AI_ET_VEHICLE_CRASHED");
|
SQAIEvent.DefSQConst(engine, AIEvent::AI_ET_VEHICLE_CRASHED, "AI_ET_VEHICLE_CRASHED");
|
||||||
|
|
|
@ -92,3 +92,8 @@ bool AIEventEnginePreview::AcceptPreview()
|
||||||
{
|
{
|
||||||
return AIObject::DoCommand(0, this->engine, 0, CMD_WANT_ENGINE_PREVIEW);
|
return AIObject::DoCommand(0, this->engine, 0, CMD_WANT_ENGINE_PREVIEW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AIEventCompanyAskMerger::AcceptMerger()
|
||||||
|
{
|
||||||
|
return AIObject::DoCommand(0, this->owner, 0, CMD_BUY_COMPANY);
|
||||||
|
}
|
||||||
|
|
|
@ -358,6 +358,54 @@ private:
|
||||||
AICompany::CompanyID owner;
|
AICompany::CompanyID owner;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event Company Ask Merger, indicating a company can be bought (cheaply) by you.
|
||||||
|
*/
|
||||||
|
class AIEventCompanyAskMerger : public AIEvent {
|
||||||
|
public:
|
||||||
|
static const char *GetClassName() { return "AIEventCompanyAskMerger"; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param owner The company that can be bough.
|
||||||
|
* @param value The value/costs of buying the company.
|
||||||
|
*/
|
||||||
|
AIEventCompanyAskMerger(Owner owner, int32 value) :
|
||||||
|
AIEvent(AI_ET_COMPANY_MERGER),
|
||||||
|
owner((AICompany::CompanyID)owner),
|
||||||
|
value(value)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert an AIEvent to the real instance.
|
||||||
|
* @param instance The instance to convert.
|
||||||
|
* @return The converted instance.
|
||||||
|
*/
|
||||||
|
static AIEventCompanyAskMerger *Convert(AIEvent *instance) { return (AIEventCompanyAskMerger *)instance; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the CompanyID of the company that can be bought.
|
||||||
|
* @return The CompanyID of the company that can be bought.
|
||||||
|
* @note If the company is bought this will become invalid.
|
||||||
|
*/
|
||||||
|
AICompany::CompanyID GetCompanyID() { return this->owner; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of the new company.
|
||||||
|
* @return The value of the new company.
|
||||||
|
*/
|
||||||
|
int32 GetValue() { return this->value; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Take over the company for this merger.
|
||||||
|
* @return true if the merger was a success.
|
||||||
|
*/
|
||||||
|
bool AcceptMerger();
|
||||||
|
|
||||||
|
private:
|
||||||
|
AICompany::CompanyID owner;
|
||||||
|
int32 value;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event Company Merger, indicating a company has been bought by another
|
* Event Company Merger, indicating a company has been bought by another
|
||||||
* company.
|
* company.
|
||||||
|
|
|
@ -191,6 +191,28 @@ void SQAIEventCompanyInTrouble_Register(Squirrel *engine) {
|
||||||
SQAIEventCompanyInTrouble.PostRegister(engine);
|
SQAIEventCompanyInTrouble.PostRegister(engine);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace SQConvert {
|
||||||
|
/* Allow AIEventCompanyAskMerger to be used as Squirrel parameter */
|
||||||
|
template <> AIEventCompanyAskMerger *GetParam(ForceType<AIEventCompanyAskMerger *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventCompanyAskMerger *)instance; }
|
||||||
|
template <> AIEventCompanyAskMerger &GetParam(ForceType<AIEventCompanyAskMerger &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventCompanyAskMerger *)instance; }
|
||||||
|
template <> const AIEventCompanyAskMerger *GetParam(ForceType<const AIEventCompanyAskMerger *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventCompanyAskMerger *)instance; }
|
||||||
|
template <> const AIEventCompanyAskMerger &GetParam(ForceType<const AIEventCompanyAskMerger &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(AIEventCompanyAskMerger *)instance; }
|
||||||
|
template <> int Return<AIEventCompanyAskMerger *>(HSQUIRRELVM vm, AIEventCompanyAskMerger *res) { if (res == NULL) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "AIEventCompanyAskMerger", res, NULL, DefSQDestructorCallback<AIEventCompanyAskMerger>); return 1; }
|
||||||
|
}; // namespace SQConvert
|
||||||
|
|
||||||
|
void SQAIEventCompanyAskMerger_Register(Squirrel *engine) {
|
||||||
|
DefSQClass <AIEventCompanyAskMerger> SQAIEventCompanyAskMerger("AIEventCompanyAskMerger");
|
||||||
|
SQAIEventCompanyAskMerger.PreRegister(engine, "AIEvent");
|
||||||
|
|
||||||
|
SQAIEventCompanyAskMerger.DefSQStaticMethod(engine, &AIEventCompanyAskMerger::Convert, "Convert", 2, ".x");
|
||||||
|
|
||||||
|
SQAIEventCompanyAskMerger.DefSQMethod(engine, &AIEventCompanyAskMerger::GetCompanyID, "GetCompanyID", 1, "x");
|
||||||
|
SQAIEventCompanyAskMerger.DefSQMethod(engine, &AIEventCompanyAskMerger::GetValue, "GetValue", 1, "x");
|
||||||
|
SQAIEventCompanyAskMerger.DefSQMethod(engine, &AIEventCompanyAskMerger::AcceptMerger, "AcceptMerger", 1, "x");
|
||||||
|
|
||||||
|
SQAIEventCompanyAskMerger.PostRegister(engine);
|
||||||
|
}
|
||||||
|
|
||||||
namespace SQConvert {
|
namespace SQConvert {
|
||||||
/* Allow AIEventCompanyMerger to be used as Squirrel parameter */
|
/* Allow AIEventCompanyMerger to be used as Squirrel parameter */
|
||||||
template <> AIEventCompanyMerger *GetParam(ForceType<AIEventCompanyMerger *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventCompanyMerger *)instance; }
|
template <> AIEventCompanyMerger *GetParam(ForceType<AIEventCompanyMerger *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIEventCompanyMerger *)instance; }
|
||||||
|
|
|
@ -492,13 +492,78 @@ void InitializeCompanies()
|
||||||
_cur_company_tick_index = 0;
|
_cur_company_tick_index = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the bankruptcy take over of a company.
|
||||||
|
* Companies going bankrupt will ask the other companies in order of their
|
||||||
|
* performance rating, so better performing companies get the 'do you want to
|
||||||
|
* merge with Y' question earlier. The question will then stay till either the
|
||||||
|
* company has gone bankrupt or got merged with a company.
|
||||||
|
*
|
||||||
|
* @param c the company that is going bankrupt.
|
||||||
|
*/
|
||||||
|
static void HandleBankruptcyTakeover(Company *c)
|
||||||
|
{
|
||||||
|
/* Amount of time out for each company to take over a company;
|
||||||
|
* Timeout is a quarter (3 months of 30 days) divided over the
|
||||||
|
* number of companies. The minimum number of days in a quarter
|
||||||
|
* is 90: 31 in January, 28 in February and 31 in March.
|
||||||
|
* Note that the company going bankrupt can't buy itself. */
|
||||||
|
static const int TAKE_OVER_TIMEOUT = 3 * 30 * DAY_TICKS / (MAX_COMPANIES - 1);
|
||||||
|
|
||||||
|
assert(c->bankrupt_asked != 0);
|
||||||
|
|
||||||
|
/* We're currently asking some company to buy 'us' */
|
||||||
|
if (c->bankrupt_timeout != 0) {
|
||||||
|
c->bankrupt_timeout -= MAX_COMPANIES;
|
||||||
|
if (c->bankrupt_timeout > 0) return;
|
||||||
|
c->bankrupt_timeout = 0;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Did we ask everyone for bankruptcy? If so, bail out. */
|
||||||
|
if (c->bankrupt_asked == MAX_UVALUE(CompanyMask)) return;
|
||||||
|
|
||||||
|
Company *c2, *best = NULL;
|
||||||
|
int32 best_performance = -1;
|
||||||
|
|
||||||
|
/* Ask the company with the highest performance history first */
|
||||||
|
FOR_ALL_COMPANIES(c2) {
|
||||||
|
if (c2->bankrupt_asked == 0 && // Don't ask companies going bankrupt themselves
|
||||||
|
!HasBit(c->bankrupt_asked, c2->index) &&
|
||||||
|
best_performance < c2->old_economy[1].performance_history) {
|
||||||
|
best_performance = c2->old_economy[1].performance_history;
|
||||||
|
best = c2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Asked all companies? */
|
||||||
|
if (best_performance == -1) {
|
||||||
|
c->bankrupt_asked = MAX_UVALUE(CompanyMask);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetBit(c->bankrupt_asked, best->index);
|
||||||
|
|
||||||
|
if (IsInteractiveCompany(best->index)) {
|
||||||
|
c->bankrupt_timeout = TAKE_OVER_TIMEOUT;
|
||||||
|
ShowBuyCompanyDialog(c->index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (best->is_ai) {
|
||||||
|
AI::NewEvent(best->index, new AIEventCompanyAskMerger(c->index, ClampToI32(c->bankrupt_value)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void OnTick_Companies()
|
void OnTick_Companies()
|
||||||
{
|
{
|
||||||
if (_game_mode == GM_EDITOR) return;
|
if (_game_mode == GM_EDITOR) return;
|
||||||
|
|
||||||
Company *c = Company::GetIfValid(_cur_company_tick_index);
|
Company *c = Company::GetIfValid(_cur_company_tick_index);
|
||||||
if (c != NULL && c->name_1 != 0) {
|
if (c != NULL) {
|
||||||
GenerateCompanyName(c);
|
if (c->name_1 != 0) GenerateCompanyName(c);
|
||||||
|
if (c->bankrupt_asked != 0) HandleBankruptcyTakeover(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_next_competitor_start == 0) {
|
if (_next_competitor_start == 0) {
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
void ChangeOwnershipOfCompanyItems(Owner old_owner, Owner new_owner);
|
void ChangeOwnershipOfCompanyItems(Owner old_owner, Owner new_owner);
|
||||||
void GetNameOfOwner(Owner owner, TileIndex tile);
|
void GetNameOfOwner(Owner owner, TileIndex tile);
|
||||||
void SetLocalCompany(CompanyID new_company);
|
void SetLocalCompany(CompanyID new_company);
|
||||||
|
void ShowBuyCompanyDialog(CompanyID company);
|
||||||
|
|
||||||
extern CompanyByte _local_company;
|
extern CompanyByte _local_company;
|
||||||
extern CompanyByte _current_company;
|
extern CompanyByte _current_company;
|
||||||
|
|
|
@ -506,16 +506,6 @@ static void CompanyCheckBankrupt(Company *c)
|
||||||
AI::BroadcastNewEvent(new AIEventCompanyInTrouble(c->index));
|
AI::BroadcastNewEvent(new AIEventCompanyInTrouble(c->index));
|
||||||
break;
|
break;
|
||||||
case 3: {
|
case 3: {
|
||||||
/* XXX - In multiplayer, should we ask other companies if it wants to take
|
|
||||||
over when it is a human company? -- TrueLight */
|
|
||||||
if (!c->is_ai) {
|
|
||||||
SetDParam(0, STR_NEWS_COMPANY_IN_TROUBLE_TITLE);
|
|
||||||
SetDParam(1, STR_NEWS_COMPANY_IN_TROUBLE_DESCRIPTION);
|
|
||||||
SetDParamStr(2, cni->company_name);
|
|
||||||
AddCompanyNewsItem(STR_MESSAGE_NEWS_FORMAT, NS_COMPANY_TROUBLE, cni);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if the company has any value.. if not, declare it bankrupt
|
/* Check if the company has any value.. if not, declare it bankrupt
|
||||||
* right now */
|
* right now */
|
||||||
Money val = CalculateCompanyValue(c);
|
Money val = CalculateCompanyValue(c);
|
||||||
|
@ -1560,15 +1550,17 @@ CommandCost CmdSellShareInCompany(TileIndex tile, DoCommandFlag flags, uint32 p1
|
||||||
CommandCost CmdBuyCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
|
CommandCost CmdBuyCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
|
||||||
{
|
{
|
||||||
Company *c = Company::GetIfValid(p1);
|
Company *c = Company::GetIfValid(p1);
|
||||||
|
if (c == NULL) return CMD_ERROR;
|
||||||
|
|
||||||
/* Disable takeovers in multiplayer games */
|
/* Disable takeovers when not asked */
|
||||||
if (c == NULL || _networking) return CMD_ERROR;
|
if (!HasBit(c->bankrupt_asked, _current_company)) return CMD_ERROR;
|
||||||
|
|
||||||
|
/* Disable taking over the local company in single player */
|
||||||
|
if (!_networking && _local_company == c->index) return CMD_ERROR;
|
||||||
|
|
||||||
/* Do not allow companies to take over themselves */
|
/* Do not allow companies to take over themselves */
|
||||||
if ((CompanyID)p1 == _current_company) return CMD_ERROR;
|
if ((CompanyID)p1 == _current_company) return CMD_ERROR;
|
||||||
|
|
||||||
if (!c->is_ai) return CMD_ERROR;
|
|
||||||
|
|
||||||
if (flags & DC_EXEC) {
|
if (flags & DC_EXEC) {
|
||||||
DoAcquireCompany(c);
|
DoAcquireCompany(c);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue