diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index 136029f523..7a12cf7268 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -1198,3 +1198,31 @@ CommandCost CmdGiveMoney(DoCommandFlag flags, uint32 money, CompanyID dest_compa /* Subtract money from local-company */ return amount; } + +/** + * Get the index of the first available company. It attempts, + * from first to last, and as soon as the attempt succeeds, + * to get the index of the company: + * 1st - get the first existing human company. + * 2nd - get the first non-existing company. + * 3rd - get COMPANY_FIRST. + * @return the index of the first available company. + */ +CompanyID GetFirstPlayableCompanyID() +{ + for (Company *c : Company::Iterate()) { + if (Company::IsHumanID(c->index)) { + return c->index; + } + } + + if (Company::CanAllocateItem()) { + for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) { + if (!Company::IsValidID(c)) { + return c; + } + } + } + + return COMPANY_FIRST; +} diff --git a/src/company_func.h b/src/company_func.h index 97e1e6e828..5c58ee8da4 100644 --- a/src/company_func.h +++ b/src/company_func.h @@ -56,5 +56,6 @@ static inline bool IsInteractiveCompany(CompanyID company) } int CompanyServiceInterval(const Company *c, VehicleType type); +CompanyID GetFirstPlayableCompanyID(); #endif /* COMPANY_FUNC_H */ diff --git a/src/openttd.cpp b/src/openttd.cpp index 230529a786..2e11380d8c 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -835,9 +835,9 @@ void HandleExitGameRequest() */ static void OnStartGame(bool dedicated_server) { - /* Update the local company for a loaded game. It is either always - * company #1 (eg 0) or in the case of a dedicated server a spectator */ - SetLocalCompany(dedicated_server ? COMPANY_SPECTATOR : COMPANY_FIRST); + /* Update the local company for a loaded game. It is either the first available company + * or in the case of a dedicated server, a spectator */ + SetLocalCompany(dedicated_server ? COMPANY_SPECTATOR : GetFirstPlayableCompanyID()); /* Update the static game info to set the values from the new game. */ NetworkServerUpdateGameInfo(); diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 4751ff6c43..acc16a1781 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -823,10 +823,12 @@ bool AfterLoadGame() * a company does not exist yet. So create one here. * 1 exception: network-games. Those can have 0 companies * But this exception is not true for non-dedicated network servers! */ - if (!Company::IsValidID(COMPANY_FIRST) && (!_networking || (_networking && _network_server && !_network_dedicated))) { - DoStartupNewCompany(false); - Company *c = Company::Get(COMPANY_FIRST); - c->settings = _settings_client.company; + if (!_networking || (_networking && _network_server && !_network_dedicated)) { + CompanyID first_human_company = GetFirstPlayableCompanyID(); + if (!Company::IsValidID(first_human_company)) { + Company *c = DoStartupNewCompany(false, first_human_company); + c->settings = _settings_client.company; + } } /* Fix the cache for cargo payments. */ @@ -1006,10 +1008,10 @@ bool AfterLoadGame() /* When loading a game, _local_company is not yet set to the correct value. * However, in a dedicated server we are a spectator, so nothing needs to * happen. In case we are not a dedicated server, the local company always - * becomes company 0, unless we are in the scenario editor where all the - * companies are 'invalid'. + * becomes the first available company, unless we are in the scenario editor + * where all the companies are 'invalid'. */ - Company *c = Company::GetIfValid(COMPANY_FIRST); + Company *c = Company::GetIfValid(GetFirstPlayableCompanyID()); if (!_network_dedicated && c != nullptr) { c->settings = _settings_client.company; }